OpenGL 纹理不通过 GLSL 渲染
OpenGL texture not rendering through GLSL
所以我有一个非常简单的 glsl 着色器,可以渲染具有纹理和定向光的对象。
现在我很难尝试显示纹理,除此之外其他一切正常。
当我禁用着色器 ( glUseProgram(0) ) 时,纹理呈现为黑白,但是当我启用它时,整个网格都是单一颜色且没有纹理,并且当我尝试不同的纹理时它会改变颜色。
这就是我加载纹理的方式
data = CImg<unsigned char>(src);
glGenTextures(1, &m_textureObj);
glBindTexture(GL_TEXTURE_2D, m_textureObj);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, data.width(), data.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
这就是我绑定纹理的方式
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_textureObj);
这是我的顶点着色器
#version 330
layout (location = 0) in vec3 Position;
layout (location = 1) in vec2 TexCoord;
layout (location = 2) in vec3 Normal;
uniform mat4 gWVP;
uniform mat4 gWorld;
out vec2 TexCoord0;
out vec3 Normal0;
void main()
{
gl_Position = (gWVP * gWorld) * vec4(Position, 1.0);
TexCoord0 = TexCoord;
Normal0 = (gWorld * vec4(Normal, 0.0)).xyz;
}
这是我的片段着色器
#version 330
in vec2 TexCoord0;
in vec3 Normal0;
out vec4 FragColor;
struct DirectionalLight
{
vec3 Color;
float AmbientIntensity;
float DiffuseIntensity;
vec3 Direction;
};
uniform DirectionalLight gDirectionalLight;
uniform sampler2D gSampler;
void main()
{
vec4 AmbientColor = vec4(gDirectionalLight.Color, 1.0f) *
gDirectionalLight.AmbientIntensity;
float DiffuseFactor = dot(normalize(Normal0), -gDirectionalLight.Direction);
vec4 DiffuseColor;
if (DiffuseFactor > 0) {
DiffuseColor = vec4(gDirectionalLight.Color, 1.0f) *
gDirectionalLight.DiffuseIntensity *
DiffuseFactor;
}
else {
DiffuseColor = vec4(0, 0, 0, 0);
}
FragColor = texture2D(gSampler, TexCoord0.xy) *
(AmbientColor + DiffuseColor);
}
最后但同样重要的是,我告诉我的着色器使用正确的纹理
glUniform1i(GetUniformLocation("gSampler"), 0);
我已经在网上阅读了大量关于如何正确完成这个简单任务的内容,运行它在一堆不同的配置中只会变得沮丧。
如果有人能指出我做错了什么,我会很高兴,我确信我遗漏了一个愚蠢的细节,但我似乎找不到它。请不要推荐我 https://www.opengl.org/wiki/Common_Mistakes#Creating_a_complete_texture 感谢阅读。
这就是我创建网格并将其上传到 GPU 的方式。
这是顶点构造函数 Vertex(x, y, z, u, v)
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
unsigned int Indices[] = {
0, 3, 1,
1, 3, 2,
2, 3, 0,
1, 2, 0
};
Vertex Vertices[4] = {
Vertex(-1.0f, -1.0f, 0.5773f, 0.0f, 0.0f),
Vertex(0.0f, -1.0f, -1.15475f, 0.5f, 0.0f),
Vertex(1.0f, -1.0f, 0.5773f, 1.0f, 0.0f),
Vertex(0.0f, 1.0f, 0.0f, 0.5f, 1.0f)
};
Mesh *data = new Mesh(Vertices, 4, Indices, 12);
glGenBuffers(1, &vbo);
glGenBuffers(1, &ibo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(0));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(12));
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(24));
glBufferData(GL_ARRAY_BUFFER, data->count*Vertex::Size(), data->verts, GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, data->indsCount*sizeof(unsigned int), data->inds, GL_STATIC_DRAW);
unsigned int Vertex::Size() {
return 32;
}
/*In the update function*/
glDrawElements(GL_TRIANGLES, data->indsCount, GL_UNSIGNED_INT, 0);
这是我的顶点classhttp://pastebin.com/iYwjEdTQ
编辑
我已经解决了!我以旧方式绑定顶点,然后在 ratchet freak 向我展示如何正确绑定它之后,我注意到我将纹理坐标绑定到位置 2,但在着色器中我正在寻找位置 1。
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(24));
(片段着色器)
layout (location = 1) in vec2 TexCoord;
所以我将片段着色器更改为
layout (location = 2) in vec2 TexCoord;
现在效果很好。感谢 ratchet freak 和 birdypme 的帮助,我将接受 ratchet freak 的回答,因为它引导我找到解决方案,但你们都引导我朝着正确的方向前进。
这是你的问题:
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, Vertex::Size(), BUFFER_OFFSET(0));
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, Vertex::Size(), BUFFER_OFFSET(12));
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, Vertex::Size(), BUFFER_OFFSET(24));
这使用旧的和已弃用的固定功能样式规范,而不是您想要使用 glVertexAttribPointer:
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, Vertex::Size(), BUFFER_OFFSET(0));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, Vertex::Size(), BUFFER_OFFSET(12));
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, Vertex::Size(), BUFFER_OFFSET(24));
我看到的另一个问题是您的 Vertex class 没有在构造函数中采用法线。 Vertex::Size()
应该等于 sizeof(Vertex)
一般来说,您应该使用 sizeof() 而不是硬编码偏移量,以避免出现意外情况。
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, Vertex::Size(), BUFFER_OFFSET(0));
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, Vertex::Size(), BUFFER_OFFSET(3*sizeof(float)));
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, Vertex::Size(), BUFFER_OFFSET(6*sizeof(float)));
并在 vertex.h
static unsigned int Size() {
return 8*sizeof(float);
}
但是,这不太可能正确回答您的问题。我不会删除我的答案以保留下面的 vertex.h pastebin,这可能很重要,但一旦发布有效答案,我可能会删除它。
所以我有一个非常简单的 glsl 着色器,可以渲染具有纹理和定向光的对象。
现在我很难尝试显示纹理,除此之外其他一切正常。
当我禁用着色器 ( glUseProgram(0) ) 时,纹理呈现为黑白,但是当我启用它时,整个网格都是单一颜色且没有纹理,并且当我尝试不同的纹理时它会改变颜色。
这就是我加载纹理的方式
data = CImg<unsigned char>(src);
glGenTextures(1, &m_textureObj);
glBindTexture(GL_TEXTURE_2D, m_textureObj);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, data.width(), data.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
这就是我绑定纹理的方式
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_textureObj);
这是我的顶点着色器
#version 330
layout (location = 0) in vec3 Position;
layout (location = 1) in vec2 TexCoord;
layout (location = 2) in vec3 Normal;
uniform mat4 gWVP;
uniform mat4 gWorld;
out vec2 TexCoord0;
out vec3 Normal0;
void main()
{
gl_Position = (gWVP * gWorld) * vec4(Position, 1.0);
TexCoord0 = TexCoord;
Normal0 = (gWorld * vec4(Normal, 0.0)).xyz;
}
这是我的片段着色器
#version 330
in vec2 TexCoord0;
in vec3 Normal0;
out vec4 FragColor;
struct DirectionalLight
{
vec3 Color;
float AmbientIntensity;
float DiffuseIntensity;
vec3 Direction;
};
uniform DirectionalLight gDirectionalLight;
uniform sampler2D gSampler;
void main()
{
vec4 AmbientColor = vec4(gDirectionalLight.Color, 1.0f) *
gDirectionalLight.AmbientIntensity;
float DiffuseFactor = dot(normalize(Normal0), -gDirectionalLight.Direction);
vec4 DiffuseColor;
if (DiffuseFactor > 0) {
DiffuseColor = vec4(gDirectionalLight.Color, 1.0f) *
gDirectionalLight.DiffuseIntensity *
DiffuseFactor;
}
else {
DiffuseColor = vec4(0, 0, 0, 0);
}
FragColor = texture2D(gSampler, TexCoord0.xy) *
(AmbientColor + DiffuseColor);
}
最后但同样重要的是,我告诉我的着色器使用正确的纹理
glUniform1i(GetUniformLocation("gSampler"), 0);
我已经在网上阅读了大量关于如何正确完成这个简单任务的内容,运行它在一堆不同的配置中只会变得沮丧。
如果有人能指出我做错了什么,我会很高兴,我确信我遗漏了一个愚蠢的细节,但我似乎找不到它。请不要推荐我 https://www.opengl.org/wiki/Common_Mistakes#Creating_a_complete_texture 感谢阅读。
这就是我创建网格并将其上传到 GPU 的方式。 这是顶点构造函数 Vertex(x, y, z, u, v)
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
unsigned int Indices[] = {
0, 3, 1,
1, 3, 2,
2, 3, 0,
1, 2, 0
};
Vertex Vertices[4] = {
Vertex(-1.0f, -1.0f, 0.5773f, 0.0f, 0.0f),
Vertex(0.0f, -1.0f, -1.15475f, 0.5f, 0.0f),
Vertex(1.0f, -1.0f, 0.5773f, 1.0f, 0.0f),
Vertex(0.0f, 1.0f, 0.0f, 0.5f, 1.0f)
};
Mesh *data = new Mesh(Vertices, 4, Indices, 12);
glGenBuffers(1, &vbo);
glGenBuffers(1, &ibo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(0));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(12));
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(24));
glBufferData(GL_ARRAY_BUFFER, data->count*Vertex::Size(), data->verts, GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, data->indsCount*sizeof(unsigned int), data->inds, GL_STATIC_DRAW);
unsigned int Vertex::Size() {
return 32;
}
/*In the update function*/
glDrawElements(GL_TRIANGLES, data->indsCount, GL_UNSIGNED_INT, 0);
这是我的顶点classhttp://pastebin.com/iYwjEdTQ
编辑
我已经解决了!我以旧方式绑定顶点,然后在 ratchet freak 向我展示如何正确绑定它之后,我注意到我将纹理坐标绑定到位置 2,但在着色器中我正在寻找位置 1。
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(24));
(片段着色器)
layout (location = 1) in vec2 TexCoord;
所以我将片段着色器更改为
layout (location = 2) in vec2 TexCoord;
现在效果很好。感谢 ratchet freak 和 birdypme 的帮助,我将接受 ratchet freak 的回答,因为它引导我找到解决方案,但你们都引导我朝着正确的方向前进。
这是你的问题:
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, Vertex::Size(), BUFFER_OFFSET(0));
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, Vertex::Size(), BUFFER_OFFSET(12));
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, Vertex::Size(), BUFFER_OFFSET(24));
这使用旧的和已弃用的固定功能样式规范,而不是您想要使用 glVertexAttribPointer:
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, Vertex::Size(), BUFFER_OFFSET(0));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, Vertex::Size(), BUFFER_OFFSET(12));
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, Vertex::Size(), BUFFER_OFFSET(24));
我看到的另一个问题是您的 Vertex class 没有在构造函数中采用法线。 Vertex::Size()
应该等于 sizeof(Vertex)
一般来说,您应该使用 sizeof() 而不是硬编码偏移量,以避免出现意外情况。
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, Vertex::Size(), BUFFER_OFFSET(0));
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, Vertex::Size(), BUFFER_OFFSET(3*sizeof(float)));
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, Vertex::Size(), BUFFER_OFFSET(6*sizeof(float)));
并在 vertex.h
static unsigned int Size() {
return 8*sizeof(float);
}
但是,这不太可能正确回答您的问题。我不会删除我的答案以保留下面的 vertex.h pastebin,这可能很重要,但一旦发布有效答案,我可能会删除它。