为什么我的片段着色器中的纹理坐标总是 (0, 0)?

Why is the texture coordinate in my fragment shader always (0, 0)?

我正在使用 LWJGL 在屏幕上绘制 "tiles" 或带纹理的 2D 正方形。但是,纹理坐标始终为 (0, 0),因此纹理正方形仅使用第一个像素颜色来填充它。

这是我的顶点着色器:

#version 330 core

in vec4 in_Position;
in vec4 in_Color;
in vec2 in_TextureCoord;

out vec4 pass_Color;
out vec2 pass_TextureCoord;

void main(void) {
    gl_Position = in_Position;

    pass_Color = in_Color;
    pass_TextureCoord = in_TextureCoord;
} 

这是我的片段着色器:

#version 330 core

uniform sampler2D texture_diffuse;

in vec4 pass_Color;
in vec2 pass_TextureCoord;

out vec4 out_Color;

void main(void) {
    out_Color = pass_Color;
    // Override out_Color with our texture pixel
    out_Color = texture(texture_diffuse, pass_TextureCoord);
} 

这实际上是我用来绘制正方形的代码:

ARBShaderObjects.glUseProgramObjectARB(shaderProgram);  

glBindTexture(GL_TEXTURE_2D, sprite.getId());

glBegin(GL11.GL_QUADS); 
glVertex2d(screenMinX, screenMinY);
glTexCoord2d(0.0, 0.0);
glVertex2d(screenMaxX, screenMinY);
glTexCoord2d(1.0, 0.0);
glVertex2d(screenMaxX, screenMaxY);
glTexCoord2d(1.0, 1.0);
glVertex2d(screenMinX, screenMaxY);
glTexCoord2d(0.0, 1.0);
glEnd();

// release the shader
ARBShaderObjects.glUseProgramObjectARB(0);

我无法修复它,因为我一开始就不知道上面的代码是如何工作的。我没有告诉着色器 in_Positionin_Colorin_TextureCoord 是什么,但前两个似乎工作得很好。它是 in_TextureCoord,它最终被传递给片段着色器,似乎有一个常量值 (0, 0) - 我已经确定通过将片段着色器的输出颜色设置为具有通道之一等于纹理坐标的 X 坐标。整个方块都是纯色,说明纹理坐标没有变化。

用上面的代码生成的正方形应该是带纹理的,而是涂成纯色 - 给定纹理的第一个像素。如何更改代码以使纹理坐标相应变化?如果我似乎对这一切如何组合在一起有一些误解,请纠正我。

This 是我用来尝试完成上述操作的教程。

p.s。我知道 Java 片段正在使用 deprecated 即时模式,但我不知道如何使用 glDrawArrays 或任何其他通常建议的方法来完成相同的操作。你能帮我改一下吗?

I am aware that the Java snippet is using deprecated immediate-mode, but I don't know how to use glDrawArrays or any other commonly suggested method to accomplish the same. Could you help me to change this?

由于您不再需要 in_Color 属性,因此必须从顶点着色器中删除该属性(当然还有 pass_Color 从顶点着色器和片段着色器中删除)。
否则,你必须通过颜色属性逻辑扩展我的解决方案。

为顶点位置和纹理坐标设置数组:

float[] posData = {
    screenMinX, screenMinY, 0.0, 1.0,
    screenMaxX, screenMinY, 0.0, 1.0,
    screenMaxX, screenMaxY, 0.0, 1.0,
    screenMinX, screenMaxY, 0.0, 1.0 };

float[] texData = { 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0 };

生成顶点数组对象:

int  vaoObj = glGenVertexArrays();
glBindVertexArray(vaoObj);

为顶点和纹理坐标生成数组缓冲区,启用属性索引并将它们的缓冲区关联到属性索引:

FloatBuffer posBuffer = MemoryUtil.memAllocFloat(posData.length);
posBuffer.put(posData).flip();
FloatBuffer texBuffer = MemoryUtil.memAllocFloat(texData.length);
texBuffer.put(texData).flip();

int vboPosObj = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vboPosObj);
glBufferData(GL_ARRAY_BUFFER, posBuffer, GL_STATIC_DRAW);

// index 0 to associate with "in_Position"            
glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, 0); 
glEnableVertexAttribArray(0); // 0 = attribute index of "in_Position"

int vboTexObj = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vboTexObj);
glBufferData(GL_ARRAY_BUFFER, texBuffer, GL_STATIC_DRAW);

// index 0 to associate with "in_TextureCoord"
glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, 0);
glEnableVertexAttribArray(1); // 1 = attribute index of "in_TextureCoord"

释放顶点数组对象:

glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);


您必须指定属性 in_Positionin_TextureCoord 的属性索引。

要么在顶点着色器中使用明确的布局规范:

layout (location = 0) in vec4 in_Position;
layout (location = 1) in vec2 in_TextureCoord;

或者您在着色器程序中指定属性索引,在之前您link着色器程序(glLinkProgram)。

glBindAttribLocation(shaderProgramID, 0, "in_Position");
glBindAttribLocation(shaderProgramID, 1, "in_TextureCoord");


如果要绘制对象,绑定Vertex Array Object即可:

glBindVertexArray(vaoObj);
glDrawArrays(GL_QUADS, 0, 4); // 4 = number of vertices 
glBindVertexArray(0);

请注意,如果不再使用缓冲区对象或顶点数组对象,则必须将其删除,以防止内存泄漏。 glDeleteBuffers 删除缓冲区对象,glDeleteVertexArrays 删除顶点数组对象。 缓冲区对象不是 "created under" 顶点数组对象,仅删除顶点数组对象是不够的(参见 OpenGL Vertex Array/Buffer Objects

如果您需要使用方框来显示一些适合整个方框区域的纹理图像,您可以为它使用两个三角形,并为 -1、-1 到 1,1 区域使用以下参数(可以是与适当的着色器一起使用以显示)。

顶点(两个三角形坐标):

-1.0f, 1.0f, 0.0f,
-1.0f, -1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f

然后可以使用以下纹理坐标获得全尺寸:

0.0f, 1.0f,
0.0f, 0.0f,
1.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f