带有着色器程序且没有错误的现代 OpenGL 黑屏

Posted

技术标签:

【中文标题】带有着色器程序且没有错误的现代 OpenGL 黑屏【英文标题】:Modern OpenGL Black Screen with shader program and no errors 【发布时间】:2020-07-03 01:14:17 【问题描述】:

我没有错误,但是当我运行程序时,我只有一个黑屏,我应该有两个三角形:

#include <iostream> //includes C++ i/o stream
#include <GL/glew.h> //includes glew header
#include <GL/freeglut.h> //includes freeglut header

using namespace std; //Uses the standard namespace

#define WINDOW_TITLE "3-1 Assignment" //Macro for window title

//Vertex and Fragment shader source macro
#ifndef GLSL
#define GLSL(Version, Source) "#version " #Version "\n" #Source
#endif

//Windows Variables for height and width
int WindowWidth=800, WindowHeight=600;

/*User-defined function prototypes to: initialize the program, set the window size, redraw graphics on the window when resized and render graphics on the screen*/
void UInitalize(int, char*[]);
void UInitWindow(int, char*[]);
void UResizeWindow(int, int);
void URenderGraphics(void);
void UCreateShaders(void);
void UCreateVBO();

//Vertex and Shader program source code
const GLchar * VertexShader = GLSL(440,
    //Receive Vertex coordinates from attribute
    in layout(location=0) vec4 vertex_Position;
//for attribute 1 expect vec(4) floats passed into the vertex shader
in layout(location=1) vec4 colorFromVBO;
//Declare a vec4 variable that will reference the vertex colors passed into the vertex shader from the buffer
out vec4 colorFromVShader;
    void main()
        //Sends vertex positions
        gl_Position= vertex_Position;

        //References vertex colors sent from the buffer
        colorFromVShader= colorFromVBO;
    
);

const GLchar * FragmentShader = GLSL(440,
        //vertex colors from the shader
        in vec4 colorFromVShader;

        //vec 4 variable that will reference vertex colors passed into the fragment shader from the vertex shader
        out vec4 vertex_color;
    void main()
        //gl_FragCOlor= vec4(0.0, 1.0, 0.0, 1.0);
        vertex_Color= colorFromVShader;
    
);

//Main Function
int main(int argc, char* argv[])

    UInitalize(argc, argv); //Initialize openGL program
    glutMainLoop(); //Starts openGL loop in background
    exit(EXIT_SUCCESS); //Ends the program


//Implements createVBO function
void UCreateVBO(void)

    // Specifies Coordinates
    GLfloat verts[]=
    
        /*index 0*/
        -1.0f, 1.0f, // top-center of the screen
        1.0f, 0.0f, 0.0f, 1.0f, // Red vertex

        /*index 1*/
        -1.0f, 0.0f, // bottom-left of the screen
        0.0f, 0.0f, 1.0f, 1.0f, // Blue vertex

        /*index 2*/
        -0.5f, 0.0f, // bottom-right of the screen
        0.0f, 1.0f, 0.0f, 1.0f, // Green vertex

        /*index 3*/
        0.0f, 0.0f, // bottom-left of the screen
        1.0f, 0.0f, 0.0f, 1.0f, // Red vertex

        /*index 4*/
        0.0f, -1.0f, // bottom-right of the screen
        0.0f, 1.0f, 0.0f, 1.0f, // Green vertex
    ;

    //Stores the size of the verts array
    float numVertices= sizeof(verts);

    //Variable for the vertex buffer object id
    GLuint myBufferID;

    //creates 1 buffer
    glGenBuffers(1, &myBufferID);

    //Activates the buffer
    glBindBuffer(GL_ARRAY_BUFFER, myBufferID);

    //Sends vertex data to the GPU
    glBufferData(GL_ARRAY_BUFFER, numVertices, verts, GL_STATIC_DRAW);

    //Creates vertex attribute pointer
    //Number of coordinates per vertex
    GLuint floatsPerVertex= 2;

    //Specifies the initial position of the coordinates in the buffer
    glEnableVertexAttribArray(0);

    //Strides between vertex coordinates is 6 (x, y ,r, g, b, a)
    //the number of floats before each vertex position

    GLint vertexStride= sizeof(float)*6;

    //Instructs GPU on how to handle the vertex buffer object
    //parameters: atrribPointerPosition | coordinates per vertex|data type| deactivate normalizations | 0 strides | 0 offset
    glVertexAttribPointer(0, floatsPerVertex, GL_FLOAT, GL_FALSE, vertexStride, 0);

    //Sets an attribute pointer for the vertex colors
    glEnableVertexAttribArray(1);
    GLint colorStride= sizeof(float)*6;

    //Parameters: attribPointerPosition 1 | floats per color is 4 | data type | deactivate normalization | 6 strides until the next color | 2 floats until the beginning of each color
    glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, colorStride, (char*)(sizeof(float)*2));

    //Creates a buffer object for the indexes
    GLushort indicies[]= 0,1,2,2,3,4;
    float numIndicies= sizeof(indicies);
    GLuint indexBufferID;
    glGenBuffers(1, &indexBufferID);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, numIndicies, indicies, GL_STATIC_DRAW);


//Implements UInitalize function
void UInitalize(int argc, char* argv[])

    //glew status variable
    GLenum GlewInitResult;

    UInitWindow(argc, argv);

    //Check glew status
    GlewInitResult= glewInit();

    if (GLEW_OK != GlewInitResult)
    
        fprintf(stderr,"ERROR: %s\n", glewGetErrorString(GlewInitResult));
        exit(EXIT_FAILURE);
    

    //Display GPU OpenGl version
    fprintf(stdout, "INFO: OpenGL Version: %s\n", glGetString(GL_VERSION));

    //Makes the screen black
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);


//Implements the UInitWindow function
void UInitWindow(int argc, char* argv[])

    //Initialize freeglut
    glutInit(&argc, argv);

    //Set window size
    glutInitWindowSize(WindowWidth, WindowHeight);

    //Memory buffer setup for display
    glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);

    //Creates a window with the macro placeholder title
    glutCreateWindow(WINDOW_TITLE);

    //Called when window is resized
    glutReshapeFunc(UResizeWindow);

    //Renders graphics on the screen
    glutDisplayFunc(URenderGraphics);


//Implements the UResizeWindow function
void UResizeWindow(int Width, int Height)

    glViewport(0, 0, Width, Height);


//Implements the URenderGraphics
void URenderGraphics(void)

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

    //Create the triangle
    //Specifies the number of vertexes
    GLuint totalVertices = 6;

    //Draw the triangles
    //glDrawArrays(GL_TRIANGLES, 0, totalVertices);
    glDrawElements(GL_TRIANGLES, totalVertices, GL_UNSIGNED_SHORT, NULL);

    //Flips the back buffer with the front buffer every frame, akin to GL Flush
    glutSwapBuffers();


//Initialize the UCreateShaders function
void UCreateShaders(void)

    //Create a shader program object
    GLuint ProgramId = glCreateProgram();

    //Create the vertex shader
    GLuint vertexShaderId = glCreateShader(GL_VERTEX_SHADER);

    //Create the fragment shader
    GLuint fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER);

    //Get the source for the vertex shader
    glShaderSource(vertexShaderId, 1, &VertexShader, NULL);

    //Get the source for the fragment shader
    glShaderSource(fragmentShaderId, 1, &FragmentShader, NULL);

    //Complies the vertex shader
    glCompileShader(vertexShaderId);

    //Compiles the fragment shader
    glCompileShader(fragmentShaderId);

    //Attach shaders
    glAttachShader(ProgramId, vertexShaderId);
    glAttachShader(ProgramId, fragmentShaderId);

    //Link the shader program
    glLinkProgram(ProgramId);

    //Utilizes the shader program
    glUseProgram(ProgramId);

【问题讨论】:

【参考方案1】:

几个问题:

UCreateShaders()UCreateVBO() 永远不会被调用。

没有着色器或几何体绑定 glDrawElements() 无法做任何有用的事情。

片段着色器大小写不匹配导致链接失败:vertex_color != vertex_Color:

0:6(2): error: `vertex_Color' undeclared
0:6(2): error: value of type vec4 cannot be assigned to variable of type error

确保在加载着色器时检查 GL_COMPILE_STATUSGL_LINK_STATUS 并获取相应的信息日志 (glGetShaderInfoLog()/glGetProgramInfoLog()),以帮助在未来发现此类问题。

大家一起:

#include <GL/glew.h>
#include <GL/freeglut.h>
#include <cstdio>
#include <cstdlib>
#include <iostream>

void CheckStatus( GLuint obj, bool isShader )

    GLint status = GL_FALSE, log[ 1 << 11 ] =  0 ;
    ( isShader ? glGetShaderiv : glGetProgramiv )( obj, isShader ? GL_COMPILE_STATUS : GL_LINK_STATUS, &status );
    if( status == GL_TRUE ) return;
    ( isShader ? glGetShaderInfoLog : glGetProgramInfoLog )( obj, sizeof( log ), NULL, (GLchar*)log );
    std::cerr << (GLchar*)log << "\n";
    std::exit( EXIT_FAILURE );


void AttachShader( GLuint program, GLenum type, const char* src )

    GLuint shader = glCreateShader( type );
    glShaderSource( shader, 1, &src, NULL );
    glCompileShader( shader );
    CheckStatus( shader, true );
    glAttachShader( program, shader );
    glDeleteShader( shader );


const char* const vert = R"GLSL(
#version 440
in layout(location=0) vec4 vertex_Position;
in layout(location=1) vec4 colorFromVBO;
out vec4 colorFromVShader;
void main()

    gl_Position = vertex_Position;
    colorFromVShader = colorFromVBO;

)GLSL";

const char* const frag = R"GLSL(
#version 440
in vec4 colorFromVShader;
out vec4 vertex_color;
void main()

    vertex_color = colorFromVShader;

)GLSL";

void UCreateShaders()

    GLuint prog = glCreateProgram();
    AttachShader( prog, GL_VERTEX_SHADER, vert );
    AttachShader( prog, GL_FRAGMENT_SHADER, frag );
    glLinkProgram( prog );
    CheckStatus( prog, false );
    glUseProgram( prog );    


void UCreateVBO()

    // Specifies Coordinates
    GLfloat verts[]=
    
        /*index 0*/
        -1.0f, 1.0f, // top-center of the screen
        1.0f, 0.0f, 0.0f, 1.0f, // Red vertex

        /*index 1*/
        -1.0f, 0.0f, // bottom-left of the screen
        0.0f, 0.0f, 1.0f, 1.0f, // Blue vertex

        /*index 2*/
        -0.5f, 0.0f, // bottom-right of the screen
        0.0f, 1.0f, 0.0f, 1.0f, // Green vertex

        /*index 3*/
        0.0f, 0.0f, // bottom-left of the screen
        1.0f, 0.0f, 0.0f, 1.0f, // Red vertex

        /*index 4*/
        0.0f, -1.0f, // bottom-right of the screen
        0.0f, 1.0f, 0.0f, 1.0f, // Green vertex
    ;

    //Variable for the vertex buffer object id
    GLuint myBufferID;
    glGenBuffers(1, &myBufferID);
    glBindBuffer(GL_ARRAY_BUFFER, myBufferID);
    glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float)*6, 0);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(float)*6, (char*)(sizeof(float)*2));
    glEnableVertexAttribArray(1);

    //Creates a buffer object for the indexes
    GLushort indicies[]= 0,1,2,2,3,4;
    GLuint indexBufferID;
    glGenBuffers(1, &indexBufferID);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indicies), indicies, GL_STATIC_DRAW);


void URenderGraphics(void)

    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);    
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    GLuint totalVertices = 6;
    glDrawElements(GL_TRIANGLES, totalVertices, GL_UNSIGNED_SHORT, NULL);
    glutSwapBuffers();


int main(int argc, char* argv[])

    glutInit(&argc, argv);
    glutInitWindowSize(640, 480);
    glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
    glutCreateWindow("GLUT");
    glutDisplayFunc(URenderGraphics);    

    GLenum GlewInitResult = glewInit();
    if (GLEW_OK != GlewInitResult)
    
        fprintf(stderr,"ERROR: %s\n", glewGetErrorString(GlewInitResult));
        exit(EXIT_FAILURE);
    

    fprintf(stdout, "INFO: OpenGL Version: %s\n", glGetString(GL_VERSION));    

    UCreateVBO();
    UCreateShaders();
    
    glutMainLoop();
    return 0;

【讨论】:

以上是关于带有着色器程序且没有错误的现代 OpenGL 黑屏的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL纹理无法正常工作-黑屏[关闭]

OpenGL着色器程序在使用时导致屏幕变黑

现代硬件上的 OpenGL 可分离着色器程序和管道性能

现代opengl渲染管道

OpenGL代码适用于GLFW,但不适用于Qt OpenGL

使用着色器渲染“顶点彩色”三角形时的OpenGL“黑屏”