我在这里发现了类似的帖子,但没有人帮我解决我的问题。我只是使用基本的OpenGL,并试图绘制一个应用了纹理的三角形。但由于某种原因,三角形是一种纯色。此颜色恰好与纹理背景颜色相同。
这是我尝试绘制的纹理
这是我运行程序时的结果
我通过编辑纹理在左下角(原点)有一些蓝色进行了实验,它就像这样出现了
我的猜测是它插入红色和蓝色给我紫色。但是我不知道它为什么要首先插入颜色而不是像我想要的那样只绘制纹理。
这是我的代码的相关部分的一些部分:
在主循环之前启用东西
glClearColor(0, 0, 0, 1);
glEnable(GL_BLEND);
glEnable(GL_TEXTURE);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
加载着色器
auto vertString = getSource("test.vert");
auto vertSource = vertString.c_str();
GLint vertLength = vertString.length();
auto fragString= getSource("test.frag");
auto fragSource = fragString.c_str();
GLint fragLength = fragString.length();
auto vertShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertShader, 1, &vertSource, &vertLength);
auto fragShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragShader, 1, &fragSource, &fragLength);
//compile shaders
glCompileShader(vertShader);
checkShaderCompilation(vertShader, "vertex shader");
glCompileShader(fragShader);
checkShaderCompilation(fragShader, "fragment shader");
auto program = glCreateProgram();
glAttachShader(program, vertShader);
glAttachShader(program, fragShader);
glBindAttribLocation(program, 0, "i_position");
glBindAttribLocation(program, 1, "i_texCoord");
//link program
glLinkProgram(program);
checkProgramLinkage(program, "vertex shader", "fragment shader");
glDetachShader(program, vertShader);
glDetachShader(program, fragShader);
glDeleteShader(vertShader);
glDeleteShader(fragShader);
加载纹理
SDL_Surface* surface = IMG_Load("Numel.png");
if (!surface)
{
std::cout << "Unable to load texture." << std::endl;
return 0;
}
auto width = surface->w;
auto height = surface->h;
GLuint texture = 0;
//generate the id
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
auto mode = surface->format->BytesPerPixel == 4 ? GL_RGBA : GL_RGB;
glTexImage2D(GL_TEXTURE_2D, 0, mode, surface->w, surface->h, false, mode, GL_UNSIGNED_BYTE, surface->pixels);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
SDL_FreeSurface(surface);
glBindTexture(GL_TEXTURE_2D, 0);
顶点结构
struct Vertex
{
Vector2 position;
Vector2 texCoord;
};
生成顶点数组
Vertex data[] = {
-0.5, -0.5, 0, 0,
0.5, -0.5, 1, 0,
0.5, 0.5, 1, 1
};
GLuint vertexBuffer = 0, vertexArray = 0;
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex)*3, data, GL_STATIC_DRAW);
glGenVertexArrays(1, &vertexArray);
glBindVertexArray(vertexArray);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, 0, sizeof(Vertex), (char*)offsetof(Vertex, position));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, 0, sizeof(Vertex), (char*)offsetof(Vertex, texCoord));
在主循环中绑定/绘制所有内容
glClear(GL_COLOR_BUFFER_BIT);
//texture
glBindTexture(GL_TEXTURE_2D, texture);
//shader
auto colorLoc = glGetUniformLocation(program, "u_color");
glUniform3f(colorLoc, 0, 0, 1);
auto useTextureLoc = glGetUniformLocation(program, "u_usingTexture");
glUniform1i(useTextureLoc, 1);
auto textureLoc = glGetUniformLocation(program, "u_sampler");
glUniform1i(textureLoc, 0);
glUseProgram(program);
//vertex array
glBindVertexArray(vertexArray);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glDrawArrays(GL_TRIANGLES, 0, 3);
SDL_GL_SwapWindow(window);
这是我的顶点着色器
#version 420
in vec2 i_position;
in vec2 i_texCoord;
out vec2 o_texCoord;
void main()
{
o_texCoord=i_texCoord;
gl_Position=vec4(i_position, 0, 1);
}
我的片段着色器
#version 420
uniform vec3 u_color;
uniform sampler2D u_sampler;
uniform bool u_usingTexture;
in vec2 i_texCoord;
out vec4 o_color;
void main()
{
if(u_usingTexture)
o_color=texture(u_sampler, i_texCoord);
else
o_color=vec4(u_color, 1);
}
我真的试图解决这个问题好几天,我不知道。如果有人能够弄清楚它为什么用一种颜色而不是纹理进行渲染,那么我们将非常感激。
答案 0 :(得分:2)
您没有使用texcoords:
这是我的顶点着色器
[...] out vec2 o_texCoord;
我的片段着色器
[...] in vec2 i_texCoord;
顶点着色器输出的名称必须与片段着色器输入的名称相匹配。由于它们没有,因此您的片段着色器会根据规范看到一个输入值 undefined 。
在链接期间没有收到错误的唯一原因是您以某种条件方式在“片段着色器”中使用i_texCoord
(“动态使用”)。如果您在片段着色器中静态使用i_texCoord
,实际上会出现链接错误。但是,由于comipler / linker不能排除您永远不会访问该变量,因此根据规范允许使用此代码,并且不得导致编译错误。但是,如果您实际访问这些值,则它们是未定义的。