我正在使用LWJGL在屏幕上绘制“图块”或纹理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_Position
,in_Color
或in_TextureCoord
是什么,但前两个似乎工作正常。它是in_TextureCoord
,最终传递给片段着色器,它似乎具有常量值(0,0) - 我已经确定通过将片段着色器的输出颜色设置为具有其中一个通道等于纹理坐标的X坐标。它在整个方块中保持纯色,表明纹理坐标没有变化。
使用上面的代码生成的正方形应该是纹理的,而是涂成纯色 - 给定纹理的第一个像素。如何更改代码以使纹理坐标相应更改?如果我似乎对这一切如何融合有一些误解,请纠正我。
This是我过去尝试完成上述内容的教程。
P.S。我知道Java片段正在使用deprecated立即模式,但我不知道如何使用glDrawArrays或任何其他常用的方法来实现相同的目的。你能帮我改变一下吗?
答案 0 :(得分:1)
我知道Java片段正在使用不推荐的立即模式,但我不知道如何使用glDrawArrays或任何其他常用的方法来实现相同的目的。你能帮我改变一下吗?
由于您不再需要属性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_Position
和in_TextureCoord
的属性索引。
您可以在顶点着色器中使用显式布局规范:
layout (location = 0) in vec4 in_Position;
layout (location = 1) in vec2 in_TextureCoord;
或者您在着色器程序中指定属性索引,在之前链接着色器程序(glLinkProgram
)。
glBindAttribLocation(shaderProgramID, 0, "in_Position");
glBindAttribLocation(shaderProgramID, 1, "in_TextureCoord");
如果要绘制对象,则绑定vertexArrayObject:
glBindVertexArray(vaoObj);
glDrawArrays(GL_QUADS, 0, 4); // 4 = number of vertices
glBindVertexArray(0);
注意,如果缓冲区对象或顶点数组对象不再使用,则必须将其删除,以防止内存泄漏。由glDeleteBuffers
和顶点数组对象删除的缓冲区对象被glDeleteVertexArrays
删除。
缓冲区对象不是“在”顶点数组对象下创建的,仅仅删除顶点数组对象是不够的(见OpenGL Vertex Array/Buffer Objects)
答案 1 :(得分:0)
如果使用“需要使用框”来显示一些适合整个框区域的纹理图像,则可以使用两个三角形,并在-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