首页 > 解决方案 > 纹理不绘制 OpenGL

问题描述

尝试在 OpenGL 中绘制纹理时,我遇到了一些奇怪的行为。目前,这个程序对我所做的只是绘制背景颜色,而没有指示正在绘制纹理。我刚刚从 Visual Studio(此代码产生正确的输出)转移到在命令提示符下进行编译。此代码应为背景着色并在屏幕中央绘制一个纹理。

我担心我可能提供了不正确的库进行编译,因为就我而言,我所做的一切都是一样的。然而,不同的库总是说它们不兼容。

主要代码:

#define GLEW_STATIC
#include <GL/glew.h> // window management library
#include <GL/glfw3.h>
#include <GL/glm.hpp>
#include <GL/gtc/matrix_transform.hpp> //

#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

int main(int argc, char** argv){

    //Initialize GLFW and GLEW...
    //Setup and combine shaders...

    GLint vertex_att = glGetAttribLocation(program, "vertex");
    glVertexAttribPointer(vertex_att, 2, GL_FLOAT, GL_FALSE, 7*sizeof(GLfloat), 0);
    glEnableVertexAttribArray(vertex_att);

    GLint color_att = glGetAttribLocation(program, "color");
    glVertexAttribPointer(color_att, 3, GL_FLOAT, GL_FALSE, 7*sizeof(GLfloat), (void *) (2 *sizeof(GLfloat)));
    glEnableVertexAttribArray(color_att);

    GLint tex_att = glGetAttribLocation(program, "uv");
    glVertexAttribPointer(tex_att, 2, GL_FLOAT, GL_FALSE, 7*sizeof(GLfloat), (void *) (5 *sizeof(GLfloat)));
    glEnableVertexAttribArray(tex_att);

    glUseProgram(program);

    GLuint texture;
    glGenTextures(1, &texture);
    setthisTexture(texture, "./black.png");

    // Create geometry of the square
    int size = CreateSquare();

    while (!glfwWindowShouldClose(window)){
        // Clear background
        glClearColor(viewport_background_color_g[0], 
                     viewport_background_color_g[1],
                     viewport_background_color_g[2], 0.0);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        //set displacement - 'program' being the shader program
        int matrixLocation = glGetUniformLocation(program, "x");

        glm::mat4 translate = glm::mat4();
        translate = glm::translate(translate, glm::vec3(0.0f, 0.0f, 0.0f));

        glUniformMatrix4fv(matrixLocation, 1, GL_FALSE, &translate[0][0]);
        glBindTexture(GL_TEXTURE_2D, texture);
        glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_INT, 0);

        glfwPollEvents();

        glfwSwapBuffers(window);
    }
}

顶点着色器:

#version 130

in vec2 vertex;
in vec3 color;
in vec2 uv;
out vec2 uv_interp;

// Uniform (global) buffer
uniform mat4 x;

// Attributes forwarded to the fragment shader
out vec4 color_interp;

void main(){
    vec4 t;
    t = vec4(vertex, 0.0, 1.0);
    gl_Position = x*t;

    color_interp = vec4(color, 1.0);
    uv_interp = uv;
}

片段着色器:

#version 130

in vec4 color_interp;
in vec2 uv_interp;

uniform sampler2D onetex;

void main(){
    vec4 color = texture2D(onetex, uv_interp);
    gl_FragColor = vec4(color.r,color.g,color.b,color.a);
    if(gl_FragColor.a < 0.9){
        discard;
    }
}

设置此纹理:

void setthisTexture(GLuint w, const char *fname)
{
    glBindTexture(GL_TEXTURE_2D, w);

    int width, height, nrChannels;
    unsigned char* image = stbi_load(fname, &width, &height, &nrChannels, 0);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
    stbi_image_free(image);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}

创建广场:

int CreateSquare(void) {

    // The face of the square is defined by four vertices and two triangles

    // Number of attributes for vertices and faces
    //  const int vertex_att = 7;  // 7 attributes per vertex: 2D (or 3D) position (2), RGB color (3), 2D texture coordinates (2)
    //  const int face_att = 3; // Vertex indices (3)

    GLfloat vertex[]  = {
        //  square (two triangles)
        //  Position     Color                  Texcoords
        -0.5f, 0.5f,     1.0f, 0.0f, 0.0f,      0.0f, 0.0f, // Top-left
        0.5f, 0.5f,      0.0f, 1.0f, 0.0f,      1.0f, 0.0f, // Top-right
        0.5f, -0.5f,     0.0f, 0.0f, 1.0f,      1.0f, 1.0f, // Bottom-right
        -0.5f, -0.5f,    1.0f, 1.0f, 1.0f,      0.0f, 1.0f  // Bottom-left
    };

    GLuint face[] = {
        0, 1, 2, // t1
        2, 3, 0  //t2
    };

    GLuint vbo, ebo;

    // Create buffer for vertices
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertex), vertex, GL_STATIC_DRAW);

    // Create buffer for faces (index buffer)
    glGenBuffers(1, &ebo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(face), face, GL_STATIC_DRAW);

    // Return number of elements in array buffer
    return sizeof(face);
}

标签: c++openglglfwglewstb-image

解决方案


为了使用glVertexAttribPointer命名GL_ARRAY_BUFFER缓冲区对象,必须绑定或传递指向顶点数据的指针。

在您的情况下,这意味着

int size = CreateSquare();

必须在之前完成

GLint vertex_att = glGetAttribLocation(program, "vertex");
glVertexAttribPointer(vertex_att, 2, GL_FLOAT, GL_FALSE, 7*sizeof(GLfloat), 0);
glEnableVertexAttribArray(vertex_att);

.....


注意在函数CreateSquare中,命名的缓冲区对象vbo是绑定的:

glBindBuffer(GL_ARRAY_BUFFER, vbo);

glVertexAttribPointer调用使用。


请参阅OpenGL 4.6 API 兼容性配置文件规范;10.3.9 缓冲区对象中的顶点数组;第 409 页

缓冲区对象绑定点被添加到与每个顶点数组类型和索引关联的客户端状态。指定顶点数组的位置和组织的命令将绑定到 ARRAY_BUFFER 的缓冲区对象名称复制到与指定的顶点数组类型或索引对应的绑定点。例如,VertexAttribPointer 命令将 ARRAY_BUFFER_BINDING 的值(与目标 ARRAY_BUFFER 对应的缓冲区绑定的可查询名称)复制到指定索引的客户端状态变量 VERTEX_ATTRIB_-ARRAY_BUFFER_BINDING。


推荐阅读