简体   繁体   English

是什么导致片段着色器 output 缺少颜色?

[英]What is causing the lack of color from fragment shader output?

I have a "Hello Triangle" program I'm working on and can't for the life of me figure out why there is no color coming from the fragment shader.我有一个正在开发的“Hello Triangle”程序,但我一生都无法弄清楚为什么片段着色器没有颜色。 What is causing all fragments to output as white?是什么导致 output 的所有片段为白色? I'm on Visual Studio 2019, program compiles just fine, and stepping through the debugger yields no results.我在 Visual Studio 2019 上,程序编译得很好,单步调试调试器不会产生任何结果。 I'm assuming the error is either in GLSL or my vertex attribute plumbing.我假设错误是在 GLSL 或我的顶点属性管道中。 Vertex Shader:顶点着色器:

#version 450 core
layout (location = 0) in vec4 vPosition;
layout (location = 1) in vec4 color;
out vec4 fColor;
void main() {
    fColor = color;
    gl_Position = vPosition;
}

Fragment Shader:片段着色器:

#version 450 core
in vec4 fColor;
out vec4 fragColor;
void main() {
    //fColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
    fragColor = fColor;
}

Main:主要的:

#include <Windows.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <cstdlib>
#include <string>
#include <GL/gl3w.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
std::string readFile(const char* filePath) {
    std::string content;
    std::ifstream fileStream(filePath, std::ios::in);
    if (!fileStream.is_open()) {
        std::cerr << "Could not read file " << filePath << ". File does not exist." << std::endl;
        return "";
    }
    std::string line = "";
    while (!fileStream.eof()) {
        std::getline(fileStream, line);
        content.append(line + "\n");
    }
    fileStream.close();
    return content;
}
void loadShaders(std::string filedir, GLenum type, GLuint &prog) {
    GLenum errorVal;
    std::string vertexSource = readFile("./vert.vert");
    std::string fragmentSource = readFile("./frag.frag");
    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    const GLchar* source = (const GLchar*)vertexSource.c_str();
    glShaderSource(vertexShader, 1, &source, 0);
    glCompileShader(vertexShader);
    GLint isCompiled = 0;
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &isCompiled);
    if (isCompiled == GL_FALSE)
    {
        GLint maxLength = 0;
        glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &maxLength);
        // The maxLength includes the NULL character
        std::vector<GLchar> infoLog(maxLength);
        glGetShaderInfoLog(vertexShader, maxLength, &maxLength, &infoLog[0]);
        // We don't need the shader anymore.
        glDeleteShader(vertexShader);
        // Use the infoLog as you see fit.
        // In this simple program, we'll just leave
        return;
    }
    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    source = (const GLchar*)fragmentSource.c_str();
    glShaderSource(fragmentShader, 1, &source, 0);
    glCompileShader(fragmentShader);
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &isCompiled);
    if (isCompiled == GL_FALSE)
    {
        GLint maxLength = 0;
        glGetShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &maxLength);
        // The maxLength includes the NULL character
        std::vector<GLchar> infoLog(maxLength);
        glGetShaderInfoLog(fragmentShader, maxLength, &maxLength, &infoLog[0]);
        // We don't need the shader anymore.
        glDeleteShader(fragmentShader);
        // Either of them. Don't leak shaders.
        glDeleteShader(vertexShader);
        // Use the infoLog as you see fit.
        // In this simple program, we'll just leave
        return;
    }

    // Vertex and fragment shaders are successfully compiled.
    // Now time to link them together into a program.
    // Get a program object.
    GLuint program = glCreateProgram();
    glAttachShader(program, vertexShader);
    glAttachShader(program, fragmentShader);
    glLinkProgram(program);
    GLint isLinked = 0;
    glGetProgramiv(program, GL_LINK_STATUS, (int*)&isLinked);
    if (isLinked == GL_FALSE)
    {
        GLint maxLength = 0;
        glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
        // The maxLength includes the NULL character
        std::vector<GLchar> infoLog(maxLength);
        glGetProgramInfoLog(program, maxLength, &maxLength, &infoLog[0]);
        // We don't need the program anymore.
        glDeleteProgram(program);
        // Don't leak shaders either.
        glDeleteShader(vertexShader);
        glDeleteShader(fragmentShader);
        // Use the infoLog as you see fit.
        // In this simple program, we'll just leave
        return;
    }
    // Always detach shaders after a successful link.
    glDetachShader(program, vertexShader);
    glDetachShader(program, fragmentShader);
}
int main(int argc, char** argv) {
    GLenum errorVal;
    //glfw and gl3w initialization and window creation
    glfwInit();
    GLFWwindow* window = glfwCreateWindow(1920, 1080, "openGL bullshit", NULL, NULL);
    glfwMakeContextCurrent(window);
    gl3wInit();
    //do shit here
    GLuint VAOs[1];
    GLuint bufferNames[1];
    //vertices gets copied into the GPU, can be modified GPU-side using glMapData, glBufferSubData, or glNamedBufferStorage
    GLfloat vertices[12][4] = {
        { -1.0f, 1.0f, 0.0f, 1.0f }, // Triangle 1
        { -1.0f, -1.0f, 0.0f, 1.0f },
        { 1.0f, -1.0f, 0.0f, 1.0f },
        { 1.0f, -1.0f, 0.0f, 1.0f }, //Traingle 2
        { 1.0f, 1.0f, 0.0f, 1.0f },
        { -1.0f, 1.0f, 0.0f, 1.0f },
        {1.0f, 0.0f, 0.0f, 1.0f}, //colors
        {1.0f, 0.0f, 0.0f, 1.0f},
        {1.0f, 0.0f, 0.0f, 1.0f},
        {1.0f, 0.0f, 0.0f, 1.0f},
        {1.0f, 0.0f, 0.0f, 1.0f},
        {1.0f, 0.0f, 0.0f, 1.0f}
    };
    glCreateVertexArrays(1, VAOs);
    glCreateBuffers(1, bufferNames);
    glNamedBufferStorage(bufferNames[0], sizeof(vertices), vertices, GL_DYNAMIC_STORAGE_BIT + GL_MAP_WRITE_BIT);
    //glNamedBufferSubData(bufferNames[0], sizeof(GLfloat) * 12, sizeof(GLfloat)*24, colors);
    //insert shader shit here
    GLuint program = glCreateProgram();
    loadShaders("./vert.vert", GL_VERTEX_SHADER, program); //ignore the inputs, they aren't used. This one command loads both vertex and fragment shaders
    glUseProgram(program);
    //binding and plumbing
    glBindVertexArray(VAOs[0]);
    glBindBuffer(GL_ARRAY_BUFFER, bufferNames[0]);
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), (void*)0);
    glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (void*)(sizeof(GLfloat) * 24));
    //glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (void*)(sizeof(GLfloat) * 2));
    
    
    //main loop
    GLfloat debugArr[6][2];
    while (!glfwWindowShouldClose(window)) {
        static const float black[] = { 0.0f, 0.0f, 0.0f, 0.0f };
        vertices[0][0] += 0.0001f;
        void *pointer = glMapNamedBuffer(bufferNames[0], GL_WRITE_ONLY);
        memcpy(pointer, vertices, sizeof(vertices) / 12);
        glUnmapNamedBuffer(bufferNames[0]);
        glClearBufferfv(GL_COLOR, 0, black);
        glDrawArrays(GL_TRIANGLES, 0, 6);
        glfwSwapBuffers(window);
        glfwPollEvents();
    }
    //shutdown if main loop stops
    glfwDestroyWindow(window);
    glfwTerminate();
}

That is just undefined behavoir:那只是未定义的行为:

 glNamedBufferStorage(bufferNames[0], sizeof(vertices) + sizeof(colors), vertices, GL_DYNAMIC_STORAGE_BIT + GL_MAP_WRITE_BIT);

You tell the GL to read sizeof(vertices) + sizeof(colors) bytes beginning from the vertex array, but the memory after that array is completely unspecified.您告诉 GL 从vertex数组开始读取sizeof(vertices) + sizeof(colors)字节,但该数组之后的 memory 完全未指定。 This might crash your program, or put random data into your buffer.这可能会使您的程序崩溃,或将随机数据放入您的缓冲区。

 glBufferSubData(bufferNames[0], sizeof(GLfloat) * 12, sizeof(GLfloat)*24, colors);

This will just generate a GL_INVALID_ENUM error as glBufferSubData 's first parameter is the binding target (like GL_ARRAY_BUFFER ).这只会产生GL_INVALID_ENUM错误,因为glBufferSubData的第一个参数是绑定目标(如GL_ARRAY_BUFFER )。 So you never transfer the color data into the buffer.因此,您永远不会将颜色数据传输到缓冲区中。 You need to use the DSA variant glNamedBufferSubData here.您需要在此处使用 DSA 变体glNamedBufferSubData

Turns out the issue was with the program, when shaders were loaded it used a program variable that was baked into the load routine from the tutorial I used for that part, and I completely forgot about the program variable that passed as reference into the loadShaders function.原来问题出在程序上,当加载着色器时,它使用了一个程序变量,该变量从我用于该部分的教程中烘焙到加载例程中,我完全忘记了作为引用传递给 loadShaders function 的程序变量. Once the code was corrected to use the prog reference instead, all of the color came in!一旦代码被更正为使用 prog 参考,所有的颜色都进来了!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM