在OpenGL中向着色器传递纹理

3
我是一名有用的助手,可以为您翻译文本。

我正在处理一些示例,尝试将纹理传递给着色器。

为了构建VAO,我有以下代码:

void PlaneShaderProgram::BuildVAO()
{
    // Generate and bind the vertex array object
    glGenVertexArrays(1, &_vao);
    glBindVertexArray(_vao);

    // Generate and bind the vertex buffer object
    glGenBuffers(1, &_vbo);
    glBindBuffer(GL_ARRAY_BUFFER, _vbo);
    glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(GLfloat), _coordinates, GL_STATIC_DRAW);

    // Generate and bind the index buffer object
    glGenBuffers(1, &_ibo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ibo);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(GLuint), _indexes, GL_STATIC_DRAW);

    // Generate and bind texture
    _texture = LoadTexture("floor.bmp");

    LoadAttributeVariables();

    glBindVertexArray(0);
}

这是我如何加载着色器属性的代码:
void PlaneShaderProgram::LoadAttributeVariables()
{
    GLuint VertexPosition_location = glGetAttribLocation(GetProgramID(), "vPosition");
    glEnableVertexAttribArray(VertexPosition_location);

    glVertexAttribPointer(VertexPosition_location, 3, GL_FLOAT, GL_FALSE, 0, 0);
}

void PlaneShaderProgram::LoadUniformVariables()
{
    // OpenGL Matrices
    GLuint ModelViewProjection_location = glGetUniformLocation(GetProgramID(), "mvpMatrix");
    glUniformMatrix4fv(ModelViewProjection_location, 1, GL_FALSE, glm::value_ptr(_ModelViewProjection));

    // Floor texture
    // glActiveTexture(GL_TEXTURE0);
    // glBindTexture(GL_TEXTURE_2D, _texture);
    // GLint Texture_location = glGetUniformLocation(GetProgramID(), "texture");
    // glUniform1i(Texture_location, 0);
}

我想谈一下我的LoatTexture

GLuint ProgramManager::LoadTexture(const char* imagepath)
{
    unsigned char * data = LoadBMP(imagepath, &width, &height);

    GLuint textureID;
    glGenTextures(1, &textureID);
    glBindTexture(GL_TEXTURE_2D, textureID);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, data);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

    return textureID;
}

最后,我的绘图函数在OpenGL主循环中调用,代码如下:

void PlaneShaderProgram::DrawPlane(const glm::mat4 &Projection, const glm::mat4 &ModelView)
{
    _ModelViewProjection = Projection * ModelView;
    _ModelView = ModelView;

    Bind();

    glBindVertexArray(_vao);
    LoadUniformVariables();
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    glBindVertexArray(0);

    UnBind();
}

我不理解的是,即使我没有设置着色器使用的均匀纹理(在代码中已注释),平面仍然使用纹理绘制。对我来说这毫无意义。一旦着色器需要一个sample2D,我认为这应该不能工作并返回一些错误。

顶点着色器:

uniform mat4 mvpMatrix;
in vec4 vPosition;

smooth out vec2 uvCoord;

void main() 
{
   uvCoord = vPosition.xz;
   gl_Position = mvpMatrix * vPosition;
}

片段着色器:

uniform sampler2D texture;
in vec2 uvCoord;

out vec4 fragColor;
void main()
{ 
    fragColor.rgb = texture(texture, uvCoord).rgb;
};

我有点不明白,但这个东西确实可行。为什么它能够工作我不是很清楚,但我真的很喜欢它。

1个回答

3
GLSL中的sampler数据类型引用纹理单元,而不是纹理对象。默认情况下,uniform变量将被初始化为0,因此如果您没有设置sampler uniform变量,则它们将从纹理单元0进行采样(这也是默认单元)。在您的ProgramManager::LoadTexture()方法中,您绑定了新创建的纹理,并且很可能仍在使用GL_TEXTURE0作为当前活动的纹理单元。您似乎从未解除绑定,因此在绘制调用时它仍然处于绑定状态,着色器可以访问它。

谢谢你,@derhass。现在完全明白了。 :) - pceccon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接