c++ - GLSL 4.10 纹理映射

标签 c++ opengl glsl shader fragment-shader

我正在尝试弄清楚如何使用 GLSL 版本 4.10 进行纹理映射。我对 GLSL 还很陌生,很高兴今天能使用着色器根据 sin(time) 进行颜色渐变的三角形渲染。现在我对使用具有单个纹理的着色器感兴趣。

很多教程甚至 Stack Overflow 的答案都建议使用 gl_MultiTexCoord0。但是,自 GLSL 1.30 以来,此功能已被弃用,最新版本现在是 4.20。我的显卡不支持 4.20,这就是我尝试使用 4.10 的原因。

我知道我正在适本地生成和绑定(bind)我的纹理,并且我有正确的顶点坐标和纹理坐标,因为当我使用固定功能管道时,我的高度图渲染得很好,并且它用颜色而不是纹理渲染得很好。

这是我的 GLSL 着色器和一些 C++ 绘制代码:

---heightmap.vert (GLSL)---

in vec3 position;
in vec2 texcoord;

out vec2 p_texcoord;

uniform mat4 projection;
uniform mat4 modelview;

void main(void)
{
    gl_Position = projection * modelview * vec4(position, 1.0);
    p_texcoord = texcoord;
}


---heightmap.frag (GLSL)---

in vec2 p_texcoord;

out vec4 color;

uniform sampler2D texture;

void main(void)
{
    color = texture2D(texture, p_texcoord);
}


---Heightmap::Draw() (C++)---

// Bind Shader
// Bind VBO + IBO
// Enable Vertex and Texcoord client state

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureId);

// glVertexPointer(...)
// glTexCoordPointer(...)

glUniform4fv(projLoc, projection);
glUniform4fv(modelviewLoc, modelview);
glUniform1i(textureId, 0);

// glDrawElements(...)

// glDisable/unbind everything

我还怀疑的是,我是否必须将纹理坐标内容作为变量传递给片段着色器,因为我没有在顶点着色器中接触它。另外,我不知道如何从中获得插值的纹理坐标。看起来它只会得到 0.f 或 1.f,而不是插值坐标。我对着色器了解不够,无法理解它是如何工作的。如果有人能启发我,我会很高兴!

编辑1:

@Bahbar:很抱歉,这是一个错字。我在一台机器上输入代码,同时从另一台机器上读取代码。就像我说的,这一切都与固定功能管道一起工作。尽管 glEnableClientState 和 gl[Vertex|TexCoord]Pointer 已弃用,但它们仍然应该与着色器一起使用,不是吗? glVertexPointer 而不是 glVertexAttribPointer 使用颜色而不是纹理。另外,我正在使用 glBindAttribLocation(位置为 0,texcoord 为 1)。

我仍然使用 glVertexPointer 的原因是我试图一次取消弃用一件事。

最佳答案

glBindTexture 将纹理对象作为第二个参数。

// Enable Vertex and Texcoord client state

我假设您指的是通用顶点属性?您的 positiontexcoord 属性在哪里设置?为此,您需要调用一些 glEnableVertexAttrib 和 glVertexAttribPointer,而不是 glEnableClientState 和 glVertex/TexCoordPointer(所有这些都已被弃用,就像 glsl 中的 gl_MultiTexCoord 一样)。

当然,要确定属性的绑定(bind)位置,您需要调用 glGetAttribLocation 来确定 GL 选择放置 attrib 的位置,或者使用 glBindAttribLocation 自行定义(在链接程序之前)。

添加后进行编辑:

好吧,0 可能最终会从 glVertexPointer 中提取数据(出于您不应该依赖的原因。attrib 0 很特殊,大多数 IHV 使其像 Vertex 一样工作),但 1 很可能不会从 glTexCoord 中提取数据。

理论上,通用属性(如你的 texcoord,它从 glVertexAttribPointer(1,XXX) 获取数据,此处 1 是你选择的位置)和内置属性(如 gl_MultiTexCoord[0 ] 从 glTexCoordPointer 获取数据)。

现在,众所周知,nvidia 不遵循规范,并且确实别名属性(据我所知,这来自 Cg 模型),并且甚至会说使用 glTexCoord 的特定属性位置( Cg spec 建议它对 TexCoord0 使用位置 8 - 位置 1 是属性 blendweight - 请参阅表 39,p242),但实际上您应该硬着头皮将 TexCoordPointer 切换到 VertexAttribPointer 调用。

关于c++ - GLSL 4.10 纹理映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8317242/

相关文章:

c++ 派生函数未被调用

C++ VS17 给出与 Linux 子系统中相同代码不同的输出

c++ - Qt 未解析的外部符号 LNK2019

c++ - 在 X11 上设置 OpenGL

objective-c - 2个着色器使用相同的顶点数据

c++ - 将大型体素数据传输到 GLSL 着色器

c++ - Dlib 在 kurento opencv 过滤器中没有检测到人脸

java - 光线转换以避免绘制看不见的面孔

c++ - OpenGL4.5 - 绑定(bind)多个纹理和采样器

opengl - 查明 GL_TEXTURE_2D 是否在着色器中处于事件状态