有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

我使用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_Positionin_Colorin_TextureCoord是什么,但前两个似乎工作得很好。它是in_TextureCoord,最终被传递到片段着色器,似乎有一个恒定值(0,0)-我已经确定,通过设置片段着色器的输出颜色,使其中一个通道等于纹理坐标的X坐标。它在整个广场上保持着纯色,这表明纹理坐标没有变化

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

This是我用来完成上述任务的教程

另外,我知道Java代码片段正在使用deprecated立即模式,但我不知道如何使用glDrawArrays或任何其他常用的建议方法来实现同样的功能。你能帮我换一下吗


共 (1) 个答案

  1. # 1 楼答案

    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;
    

    或者在着色器程序中指定属性索引,在链接着色器程序(glLinkProgram)之前,右

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


    如果要绘制对象,只需绑定顶点数组对象即可:

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

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