无法使用简单的盒子创建纹理

时间:2019-10-25 13:47:07

标签: c++ opengl glfw glm-math

我正在尝试为纹理渲染一个简单的蓝色框,以便可以将纹理传递给ImGui以将其渲染为图像。但是由于某种原因,我只能得到纯白色的纹理,而且我不知道为什么。我将课程简化为可以的简单情况,但我仍然只能获得纯白色的纹理,而不是占据屏幕大部分位置的蓝色框。

main.cpp

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <stdlib.h>
#include <cstdio>
#include <iostream>
#include <string>
#include <vector>

GLFWwindow * window;
GLuint solid_texture;

GLuint loadShaders(const char * vertex_file_source, const char * fragment_file_source)
{
    // Create the shaders
    GLuint vertex_shader_id = glCreateShader(GL_VERTEX_SHADER);
    GLuint framgent_shader_id = glCreateShader(GL_FRAGMENT_SHADER);

    GLint Result = GL_FALSE;
    int InfoLogLength;

    glShaderSource(vertex_shader_id, 1, &vertex_file_source, NULL);
    glCompileShader(vertex_shader_id);

    // Check Vertex Shader
    glGetShaderiv(vertex_shader_id, GL_COMPILE_STATUS, &Result);
    glGetShaderiv(vertex_shader_id, GL_INFO_LOG_LENGTH, &InfoLogLength);
    if (InfoLogLength > 0) {
        std::vector<char> VertexShaderErrorMessage(InfoLogLength + 1);
        glGetShaderInfoLog(vertex_shader_id, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
        std::cerr << VertexShaderErrorMessage[0] << std::endl;
    }

    glShaderSource(framgent_shader_id, 1, &fragment_file_source, NULL);
    glCompileShader(framgent_shader_id);

    // Check Fragment Shader
    glGetShaderiv(framgent_shader_id, GL_COMPILE_STATUS, &Result);
    glGetShaderiv(framgent_shader_id, GL_INFO_LOG_LENGTH, &InfoLogLength);
    if (InfoLogLength > 0) {
        std::vector<char> FragmentShaderErrorMessage(InfoLogLength + 1);
        glGetShaderInfoLog(framgent_shader_id, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
        std::cerr << FragmentShaderErrorMessage[0] << std::endl;
    }

    GLuint ProgramID = glCreateProgram();
    glAttachShader(ProgramID, vertex_shader_id);
    glAttachShader(ProgramID, framgent_shader_id);
    glLinkProgram(ProgramID);

    // Check the program
    glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
    glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    if (InfoLogLength > 0) {
        std::vector<char> ProgramErrorMessage(InfoLogLength + 1);
        glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
        std::cerr << ProgramErrorMessage[0] << std::endl;
    }

    glDetachShader(ProgramID, vertex_shader_id);
    glDetachShader(ProgramID, framgent_shader_id);

    glDeleteShader(vertex_shader_id);
    glDeleteShader(framgent_shader_id);

    return ProgramID;
}

void generate_solid_texture()
{
    glGenTextures(1, &solid_texture);

    // Solid texture
    unsigned char solidTexturePixels[4];
    solidTexturePixels[0] = ~0;
    solidTexturePixels[1] = ~0;
    solidTexturePixels[2] = ~0;
    solidTexturePixels[3] = ~0;

    glBindTexture(GL_TEXTURE_2D, solid_texture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, solidTexturePixels);

    glBindTexture(GL_TEXTURE_2D, 0);
}

int main(void)
{
    // Initialise GLFW
    if (!glfwInit()) {
        std::cerr << "Failed to initialize GLFW" << std::endl;
        return -1;
    }

    glfwWindowHint(GLFW_SAMPLES, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);  // To make MacOS happy; should not be needed
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    // Open a window and create its OpenGL context
    window = glfwCreateWindow(1024, 768, "Tutorial 14 - Render To Texture", NULL, NULL);
    if (window == NULL) {
        fprintf(stderr,
                "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 "
                "version of the tutorials.\n");
        getchar();
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);

    // We would expect width and height to be 1024 and 768
    int windowWidth = 1024;
    int windowHeight = 768;
    // But on MacOS X with a retina screen it'll be 1024*2 and 768*2, so we get the actual framebuffer size:
    glfwGetFramebufferSize(window, &windowWidth, &windowHeight);

    // Initialize GLEW
    glewExperimental = true;  // Needed for core profile
    if (glewInit() != GLEW_OK) {
        fprintf(stderr, "Failed to initialize GLEW\n");
        getchar();
        glfwTerminate();
        return -1;
    }

    // Ensure we can capture the escape key being pressed below
    glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
    // Hide the mouse and enable unlimited mouvement
    glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);

    // Set the mouse at the center of the screen
    glfwPollEvents();
    glfwSetCursorPos(window, 1024 / 2, 768 / 2);

    // Dark blue background
    glClearColor(0.0f, 0.0f, 0.4f, 0.0f);

    // Enable depth test
    glEnable(GL_DEPTH_TEST);

    // Setup OpenGL shaders
    std::string vertex_shader_source =
        R""(
#version 330 core

layout (location = 0) in vec3 position;
layout (location = 1) in vec2 uv;
layout (location = 2) in vec3 color;
uniform mat4 mv_matrix;
uniform mat4 proj_matrix;

out vec2 frag_uv;
out vec4 frag_color;

void main()
{
    frag_uv = uv;
    frag_color = vec4(color, 1.0f);
    gl_Position = proj_matrix * mv_matrix * vec4(position.xyz, 1);
}
)"";

    std::string fragment_shader_source =
        R""(
#version 330 core

uniform sampler2D Texture;
in vec2 frag_uv;
in vec4 frag_color;

layout (location = 0) out vec4 color;

void main()
{
    // color = frag_color * texture(Texture, frag_uv.st);
    // color = vec4((frag_color * texture(Texture, frag_uv)).xyz, 1);
    color = frag_color * texture(Texture, frag_uv.st);
}
)"";

    GLuint program_id = loadShaders(vertex_shader_source.c_str(), fragment_shader_source.c_str());
    generate_solid_texture();

    // Heatmap objects
    GLuint m_vao, m_vbo, m_uvbo, m_cbo;
    glGenVertexArrays(1, &m_vao);
    glBindVertexArray(m_vao);
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    glEnableVertexAttribArray(2);

    glGenBuffers(1, &m_vbo);
    glGenBuffers(1, &m_uvbo);
    glGenBuffers(1, &m_cbo);
    glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void *)0);
    glBindBuffer(GL_ARRAY_BUFFER, m_uvbo);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void *)0);
    glBindBuffer(GL_ARRAY_BUFFER, m_cbo);
    glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void *)0);

    // Create the FBO for later
    GLuint fbo, map_texture;
    glGenFramebuffers(1, &fbo);
    glGenTextures(1, &map_texture);
    glBindVertexArray(0);

    GLsizei heat_map_width = 600;
    GLsizei heat_map_height = 600;

    std::vector<float> map_vertices, map_vertex_uvs, map_vertex_colors;

    std::vector<float> solid_uv = {0.0f, 0.0f};
    std::vector<float> bl = {0, 0}, br = {1.0f, 0}, tl = {0, 1.0f}, tr = {1.0f, 1.0f};
    map_vertices = {bl[0], bl[1], 1.0f, tr[0], tr[1], 1.0f, tl[0], tl[1], 1.0f,
                    bl[0], bl[1], 1.0f, br[0], br[1], 1.0f, tr[0], tr[1], 1.0f};
    map_vertex_uvs = {solid_uv[0], solid_uv[1], solid_uv[0], solid_uv[1], solid_uv[0], solid_uv[1],
                      solid_uv[0], solid_uv[1], solid_uv[0], solid_uv[1], solid_uv[0], solid_uv[1]};
    map_vertex_colors = {0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
                         0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f};

    glUseProgram(program_id);

    glBindTexture(GL_TEXTURE_2D, map_texture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, heat_map_width, heat_map_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glBindTexture(GL_TEXTURE_2D, 0);

    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, map_texture, 0);

    // glViewport(0, 0, heat_map_width, heat_map_height);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_MULTISAMPLE);

    glClearColor(0.0f, 0.0f, 0.0f, 1.00f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glBindVertexArray(m_vao);
    // Vertex buffer
    glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
    glBufferData(GL_ARRAY_BUFFER, map_vertices.size() * sizeof(map_vertices[0]), map_vertices.data(), GL_STATIC_DRAW);
    // UV buffer
    glBindBuffer(GL_ARRAY_BUFFER, m_uvbo);
    glBufferData(GL_ARRAY_BUFFER, map_vertex_uvs.size() * sizeof(map_vertex_uvs[0]), map_vertex_uvs.data(),
                 GL_STATIC_DRAW);
    // Color buffer
    glBindBuffer(GL_ARRAY_BUFFER, m_cbo);
    glBufferData(GL_ARRAY_BUFFER, map_vertex_colors.size() * sizeof(map_vertex_colors[0]), map_vertex_colors.data(),
                 GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    static const GLfloat identity_matrix[16] = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
                                                0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};

    GLuint move_matrix_location = glGetUniformLocation(program_id, "mv_matrix");
    GLuint projection_matrix_location = glGetUniformLocation(program_id, "proj_matrix");
    GLuint texture_location = glGetUniformLocation(program_id, "Texture");

    glUniformMatrix4fv(move_matrix_location, 1, GL_FALSE, identity_matrix);
    glUniformMatrix4fv(projection_matrix_location, 1, GL_FALSE, identity_matrix);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, solid_texture);
    glUniform1i(texture_location, 0);
    glDrawArrays(GL_TRIANGLES, 0, map_vertices.size() / 3);

    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glBindTexture(GL_TEXTURE_2D, 0);
    glBindVertexArray(0);

    // Framebuffer to texture
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    // Always check that our framebuffer is ok
    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
        return false;

    // The fullscreen quad's FBO
    static const GLfloat g_quad_vertex_buffer_data[] = {
        -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,
    };
    static const GLfloat g_quad_vertex_uv_data[] = {
        -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f,
    };
    static const GLfloat g_quad_vertex_color_data[] = {
        1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
    };

    GLuint quad_vao;
    glGenVertexArrays(1, &quad_vao);
    glBindVertexArray(quad_vao);

    GLuint quad_vertexbuffer;
    glGenBuffers(1, &quad_vertexbuffer);
    glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(g_quad_vertex_buffer_data), g_quad_vertex_buffer_data, GL_STATIC_DRAW);

    GLuint quad_uvbuffer;
    glGenBuffers(1, &quad_uvbuffer);
    glBindBuffer(GL_ARRAY_BUFFER, quad_uvbuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(g_quad_vertex_uv_data), g_quad_vertex_uv_data, GL_STATIC_DRAW);

    GLuint quad_colorbuffer;
    glGenBuffers(1, &quad_colorbuffer);
    glBindBuffer(GL_ARRAY_BUFFER, quad_colorbuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(g_quad_vertex_color_data), g_quad_vertex_color_data, GL_STATIC_DRAW);

    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    glEnableVertexAttribArray(2);

    glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void *)0);
    glBindBuffer(GL_ARRAY_BUFFER, quad_uvbuffer);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void *)0);
    glBindBuffer(GL_ARRAY_BUFFER, quad_colorbuffer);
    glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void *)0);

    glBindVertexArray(0);

    do {
        // Render to our framebuffer
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
        glViewport(
            0, 0, windowWidth,
            windowHeight);  // Render on the whole framebuffer, complete from the lower left corner to the upper right

        // Clear the screen
        glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // Use our shader
        glUseProgram(program_id);

        // Render to the screen
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
        // Render on the whole framebuffer, complete from the lower left corner to the upper right
        glViewport(0, 0, windowWidth, windowHeight);

        // Clear the screen
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // Use our shader
        glUseProgram(program_id);

        // Bind our texture in Texture Unit 0
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, map_texture);
        // Set our "renderedTexture" sampler to use Texture Unit 0
        glUniform1i(texture_location, 0);

        glBindVertexArray(quad_vao);

        // Draw the triangles !
        glDrawArrays(GL_TRIANGLES, 0, 6);  // 2*3 indices starting at 0 -> 2 triangles

        glBindVertexArray(0);

        glDisableVertexAttribArray(0);

        // Swap buffers
        glfwSwapBuffers(window);
        glfwPollEvents();

    }  // Check if the ESC key was pressed or the window was closed
    while (glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS && glfwWindowShouldClose(window) == 0);

    // Close OpenGL window and terminate GLFW
    glfwTerminate();

    return 0;
}

我相当确定问题不在于顶点着色器或片段着色器,因为我在另一个渲染器类中使用了它们,并且效果很好。请让我知道是否可以提供其他有用的东西。

主要修改:我为我的问题创建了一个最小的可复制示例。

Edit2:我相信我已经对其进行了更新,但是现在显示的是黑屏,而不是白屏。我运行了generate_solid_texture函数,为quad_vao启用了veratt atttrib数组,并在主循环中将帧缓冲区设置为默认值。

0 个答案:

没有答案