OpenGL纹理不呈现

OpenGL Texture not rendering

本文关键字:纹理 OpenGL      更新时间:2023-10-16

我目前正在尝试学习OpenGL。我已经成功地将Rainbow Triangles渲染到了屏幕上,并且成功地将它们移到了屏幕上。但是,我似乎无法正确地呈现两个三角形的纹理。

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

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.pngn.");
        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;
}

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

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:无效令牌"版本行

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

修复此操作时,您将获得下一个错误消息:

0(2):错误c1008:未定义的变量" texture_coordinates"

您必须将in变量texture_coordinates的声明添加到片段着色器中。

in vec2 texture_coordinates;

最终代码看起来像这样:

const char* vertShader =
    "#version 330 coren"
    "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 coren"
    "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 );