代码之家  ›  专栏  ›  技术社区  ›  Acorn

OpenGL纹理未渲染

  •  1
  • Acorn  · 技术社区  · 7 年前

    我目前正在尝试学习OpenGL。我已经成功地将彩虹三角形渲染到屏幕上,并成功地在屏幕上移动了它们。 然而,我似乎无法正确地将纹理渲染为两个三角形。

    每当我运行这个程序时,我都会看到一个黑屏,没有任何渲染。我已经检查过了,图像文件肯定在正确的目录中(否则它不会运行!)

    define STB_IMAGE_IMPLEMENTATION
    
    #include <GL/glew.h>
    #include <GLFW/glfw3.h>
    #include <iostream>
    #include <stb/stb_image.h>
    
    int main()
    {
        //Initialize glfw
        if (!glfwInit())
        {
            fprintf(stderr, "ERROR: Could not start GLFW3.\n");
            return 1;
        }
    
        //Create the rendering context
        GLFWwindow* window = glfwCreateWindow(480, 600, "Hello Rendering",
                                              nullptr, nullptr);
    
        if(!window)
        {
            fprintf(stderr, "ERROR: Could not create a rendering context with "
                "GLFW3.\n");
            return 1;
        }
    
        glfwMakeContextCurrent(window);
    
        //Start GLEW
        glewExperimental=GL_TRUE;
        GLenum err=glewInit();
        if(err!=GLEW_OK)
        {
            //Problem: glewInit failed, something is seriously wrong.
            std::cout<<"glewInit failed, aborting."<<std::endl;
        }
    
    
    
        ////////////////////////
        //Loading PNG
        ////////////////////////
        int x = 0;
        int y = 0;
        int n = 0;
        int force_channels = 4;
        unsigned char* image_data = stbi_load("spooky.png", &x, &y, &n,
                                              force_channels);
        if(!image_data)
        {
            fprintf(stderr, "ERROR: Could not load spooky.png\n.");
            return 1;
        }
    
        //NPOT Check
        if((x & (x - 1)) != 0 || (y & (y - 1)) != 0)
        {
            fprintf(stderr, "ERROR: Image is not a power of 2.\n");
            fprintf(stderr, "h: %d w: %d", y, x);
            return 1;
        }
    
        //Flip the image
        int width_in_bytes = x * 4;
        unsigned char* top = nullptr;
        unsigned char* bottom = nullptr;
        unsigned char temp = 0;
        int half_height = y / 2;
    
        for(int row = 0; row < half_height; row++)
        {
            top = image_data + row * width_in_bytes;
            bottom = image_data + (y - row - 1) * width_in_bytes;
            for(int col = 0; col < width_in_bytes; col++)
            {
                temp = *top;
                *top = *bottom;
                *bottom = temp;
                top++;
                bottom++;
            }
        }
    
    
        GLuint tex = 0;
        glGenTextures(1, &tex);
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, tex);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA,
                     GL_UNSIGNED_BYTE, image_data);
    
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    
    
        //////////////////////////////////
        //Vertex shader
        //////////////////////////////////
        const char* vertShader =
            "#version 330 core"
            "layout(location = 0) in vec3 vertexPosition_modelspace;"
            "layout(location = 1) in vec2 vt;"
            "out vec2 texture_coordinates;"
            "void main() {"
            "   texture_coordinates = vt;"
            "   gl_Position.xyz = vertexPosition_modelspace;"
            "   gl_Position.w = 1.0;"
            "}";
    
        ///////////////////////////////////
        //Frag shader
        ///////////////////////////////////
        const char* fragShader =
            "#version 330 core"
            "uniform sampler2D basic_texture;"
            "out vec4 frag_color;"
            "void main() {"
            "   vec4 texel = texture(basic_texture, texture_coordinates);"
            "   frag_color = texel;"
            "}";
    
    
        ////////////////////////////////////
        //Create shader program
        ///////////////////////////////////
        GLuint vsp = glCreateShader(GL_VERTEX_SHADER);
        glShaderSource(vsp, 1, &vertShader,  nullptr);
        glCompileShader(vsp);
    
        GLuint fsp = glCreateShader(GL_FRAGMENT_SHADER);
        glShaderSource(fsp, 1, &fragShader, nullptr);
        glCompileShader(fsp);
    
        GLuint shader_program = glCreateProgram();
        glAttachShader(shader_program, fsp);
        glAttachShader(shader_program, vsp);
        glLinkProgram(shader_program);
    
        glUseProgram(shader_program);
    
    
    
        ////////////////////////////////////
        //Texture coordinates
        ////////////////////////////////////
        GLfloat texcoords[] = {
            0.0f, 1.0f,
            0.0f, 0.0f,
            1.0f, 0.0f,
            1.0f, 0.0f,
            1.0f, 1.0f,
            0.0f, 1.0f
        };
    
        GLuint vt_vbo;
        glGenBuffers(1, &vt_vbo);
        glBindBuffer(GL_ARRAY_BUFFER, vt_vbo);
        glBufferData(GL_ARRAY_BUFFER, sizeof( texcoords), texcoords,
                     GL_STATIC_DRAW);
    
        GLuint vao;;
        glGenVertexArrays(1, &vao);
        glBindVertexArray(vao);
        glBindBuffer(GL_ARRAY_BUFFER, vt_vbo);
        int dimensions = 2;
        glVertexAttribPointer(1, dimensions, GL_FLOAT, GL_FALSE, 0, nullptr);
        glEnableVertexAttribArray(1);
    
        while(!glfwWindowShouldClose(window))
        {
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
            //Use the shader
            glUseProgram(shader_program);
            //Draw the two triangles (6 points)
            glDrawArrays(GL_TRIANGLES, 0, 6);
            glfwPollEvents();
            glfwSwapBuffers(window);
            if(GLFW_PRESS == glfwGetKey(window, GLFW_KEY_ESCAPE))
            {
                glfwSetWindowShouldClose(window, 1);
            }
        }
    
        std::cout << "Hello, World!" << std::endl;
        return 0;
    }
    
    1 回复  |  直到 7 年前
        1
  •  1
  •   Rabbid76    7 年前

    首先,在编译和链接着色器时,应检索错误消息:

    GLint status = GL_TRUE;
    char error_msg[1024];
    GLsizei read;
    
    GLuint vsp = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vsp, 1, &vertShader,  nullptr);
    glCompileShader(vsp);
    glGetShaderiv( vsp, GL_COMPILE_STATUS, &status );
    if ( status != GL_TRUE )
    {
        glGetShaderInfoLog( vsp, 1024, &read, error_msg );
        std::cout << "compile error:" << std::endl << error_msg << std::endl;
    }
    
    GLuint fsp = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fsp, 1, &fragShader, nullptr);
    glCompileShader(fsp);
    glGetShaderiv( fsp, GL_COMPILE_STATUS, &status );
    if ( status != GL_TRUE )
    {
        glGetShaderInfoLog( fsp, 1024, &read, error_msg );
        std::cout << "compile error:" << std::endl << error_msg << std::endl;
    }
    
    GLuint shader_program = glCreateProgram();
    glAttachShader(shader_program, fsp);
    glAttachShader(shader_program, vsp);
    glLinkProgram(shader_program);
    glGetProgramiv( shader_program, GL_LINK_STATUS, &status );
    if ( status != GL_TRUE )
    {
        glGetProgramInfoLog( shader_program, 1024, &read, error_msg );
        std::cout << "compile error:" << std::endl << error_msg << std::endl;
    }
    

    您将收到的第一条错误消息是这样的:

    0(1):错误C0205:配置文件“corelayout”无效
    0(1):错误C0206:版本行中的令牌“”无效

    这是因为你没有写这行的结尾 "\n" 在着色器代码的第一行之后( "#version 330 core" ).

    解决此问题后,您会收到下一条错误消息:

    0(2):错误C1008:未定义变量“texture\u坐标”

    您必须添加 in 变量 texture_coordinates 到片段着色器。

    in vec2 texture_coordinates;
    

    最终代码如下所示:

    const char* vertShader =
        "#version 330 core\n"
        "layout(location = 0) in vec3 vertexPosition_modelspace;"
        "layout(location = 1) in vec2 vt;"
        "out vec2 texture_coordinates;"
        "void main() {"
        "   texture_coordinates = vt;"
        "   gl_Position.xyz = vertexPosition_modelspace;"
        "   gl_Position.w = 1.0;"
        "}";
    
    const char* fragShader =
        "#version 330 core\n"
        "uniform sampler2D basic_texture;"
        "out vec4 frag_color;"
        "in vec2 texture_coordinates;"
        "void main() {"
        "   vec4 texel = texture(basic_texture, texture_coordinates);"
        "   frag_color = texel;"
        "}";
    


    当然,您必须为顶点属性提供顶点数据 vertexPosition_modelspace :

    GLfloat texcoords[] = {
        0.0f, 1.0f,
        0.0f, 0.0f,
        1.0f, 0.0f,
        1.0f, 0.0f,
        1.0f, 1.0f,
        0.0f, 1.0f
    };
    
    GLfloat vertex[] = {
        -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
    };
    
    GLuint vert_vbo;
    glGenBuffers(1, &vert_vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vert_vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof( vertex ), vertex, GL_STATIC_DRAW);
    
    GLuint vt_vbo;
    glGenBuffers(1, &vt_vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vt_vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof( texcoords ), texcoords, GL_STATIC_DRAW);
    
    GLuint vao;
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);
    glBindBuffer(GL_ARRAY_BUFFER, vert_vbo);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, vt_vbo);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
    glEnableVertexAttribArray(1);
    


    最后,当纹理绑定到时,应将纹理单元的索引设置为纹理采样器均匀变量 basic_texture :

    int texture_unit_index = 0;
    GLuint tex = 0;
    glGenTextures(1, &tex);
    glActiveTexture(GL_TEXTURE0 + texture_unit_index );
    glBindTexture(GL_TEXTURE_2D, tex);
    
    .....
    
    // to do after    glLinkProgram(shader_program);
    int tex_sampler_loc = glGetUniformLocation( shader_program, "basic_texture" );
    
    .....
    
    // to do after    glUseProgram(shader_program);
    glUniform1i( tex_sampler_loc, texture_unit_index );  
    
    推荐文章