【问题标题】:Fragment shader compiles and links but doesn't have any effect片段着色器编译和链接但没有任何效果
【发布时间】:2021-08-18 21:55:37
【问题描述】:

我刚开始通过https://learnopengl.com/Getting-started/Hello-Triangle 学习 OpenGL,按照教程我根据我的理解编写了代码,该代码编译并确实给了我一个输出,但它不是一个橙色的三角形,而是一个白色的三角形。如果我用https://learnopengl.com/code_viewer_gh.php?code=src/1.getting_started/2.1.hello_triangle/hello_triangle.cpp 中的代码替换shaderProgram() 它可以工作(显示橙色三角形),所以我认为我将问题缩小到着色器程序编译,我只是找不到它有什么问题,以下是我的代码.

// Local Headers
#include "glitter.hpp"

// System Headers
#include <glad/glad.h>
#include <GLFW/glfw3.h>

// Standard Headers
#include <cstdio>
#include <cstdlib>

#include <stdexcept>
#include <iostream>
#include <memory>

void _delete_shader(const GLuint *shader)
{
    if (!shader) return;
    glDeleteShader(*shader);
    delete shader;
}

using shader_t = std::unique_ptr<GLuint, decltype(&_delete_shader)>;

// window resize callback
void framebuffer_size_callback(GLFWwindow* , int width, int height)
{
    glViewport(0, 0, width, height);
}

void processInput(GLFWwindow *window)
{
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
    {
        glfwSetWindowShouldClose(window, true);
    }
}

shader_t compileShader(const char *source, GLenum shaderType)
{
    auto shader = glCreateShader(shaderType);
    glShaderSource(shader, 1, &source, nullptr);
    glCompileShader(shader);

    int success;
    char log[512];
    glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(shader, sizeof(log), nullptr, log);
        throw std::runtime_error(log);
    }

    return shader_t(new GLuint {shader}, &_delete_shader);
}

shader_t vertexshader() try
{
    static const char *source = R"(
        #version 330 core
        layout (location = 0) in vec3 aPos;
        void main()
        {
            gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
        }
    )";

    return compileShader(source, GL_VERTEX_SHADER);
}
catch(const std::exception& e)
{
    printf("error in vertex shader, %s\n", e.what());
    exit(-1);
}


shader_t fragmentShader() try
{
    static const char *source = R"(
        #version 330 core
        out vec4 FragColor;
        void main()
        {
            FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
        }
    )";

    return compileShader(source, GL_FRAGMENT_SHADER);
}
catch(const std::exception &e)
{
    printf("error in fragment shader, %s\n", e.what());
    exit(-1);
}

uint32_t shaderProgram() try
{
    uint32_t program = glCreateProgram();

    const auto vertexShader = ::vertexshader();
    glAttachShader(program, *vertexShader);

    const auto fragmentShader = ::fragmentShader();
    glAttachShader(program, *fragmentShader);

    glLinkProgram(program);

    int success;
    glGetProgramiv(program, GL_LINK_STATUS, &success);
    if (!success)
    {
        char log[512];
        glGetProgramInfoLog(program, 512, nullptr, log);
        throw std::runtime_error(log);
    }
}
catch(const std::exception &e)
{
    printf("error in shader program, %s\n", e.what());
    exit(-1);
}


int main(int , char * [])
{
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    GLFWwindow *window = glfwCreateWindow(800, 600, "LearnOpenGL", nullptr, nullptr);
    if (window == nullptr)
    {
        printf("Failed to create window\n");
        glfwTerminate();
        return -1;
    }

    glfwMakeContextCurrent(window);
    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        puts("Failed to initialize GLAD\n");
        glfwTerminate();
        return -1;
    }

    glViewport(0, 0, 800, 600);

    float vertices[] =
    {
        -0.5f, -0.5f, 0.0f,
        0.5f, -0.5f, 0.0f,
        0.0f,  0.5f, 0.0f
    };

    const auto shaderProgram = ::shaderProgram();

    unsigned int VAO, VBO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);

    // bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
    glBindVertexArray(VAO);

    // copy vertices into gpu memory
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    // how data should be interpretted
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)0);
    glEnableVertexAttribArray(0);

    // note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind
    glBindBuffer(GL_ARRAY_BUFFER, 0);

     // You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other
    // VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary.
    glBindVertexArray(0);

    while (!glfwWindowShouldClose(window))
    {
        // inputs
        processInput(window);

        // paint color
        glClearColor(.2f, .3f, .3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        // draw triangle
        glUseProgram(shaderProgram);
        glBindVertexArray(VAO);
        glDrawArrays(GL_TRIANGLES, 0, 3);

        // final rendering step
        glfwSwapBuffers(window);

        // check for events
        glfwPollEvents();
    }

    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteProgram(shaderProgram);

    glfwTerminate();
    return 0;
}

【问题讨论】:

    标签: c++ windows opengl


    【解决方案1】:

    shaderProgram() 从来没有 returns 任何东西,所以你的 GL 程序对象的名称只是丢失了,你的 shaderProgram 局部变量只包含一些 undefined 值,因此你永远不会使用它程序。

    请注意,几乎所有体面的编译器都会发现此类错误,只需启用(并阅读)警告...

    【讨论】:

    • 浪费了一整天?‍♂️...谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-01
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多