绘制三角形不起作用:我只看到黑屏和鼠标

Posted

技术标签:

【中文标题】绘制三角形不起作用:我只看到黑屏和鼠标【英文标题】:Drawing triangle doesn't work: I just see a black screen and my mouse 【发布时间】:2014-05-23 15:26:10 【问题描述】:

我将 GLEW 用于现代 OpenGL 函数,将 GLFW 用于窗口。我正在尝试绘制一个三角形,但它编译并运行但不绘制三角形有问题,我只看到一个黑屏和我的鼠标。 这是我的代码:

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <glew.h>
#include <GLFW\glfw3.h>
#include <glm\glm.hpp>

const GLchar* vertexSource =
"#version 150 core\n"
"in ver2 position;"
"void main()"
"   gl_Position = vec4(position, 0.0, 1.0);"
"";

const GLchar* fragmentSource =
"#version 150 core\n"
"out vec4 outColor;"
"void main()"
"   outColor = vec4(1.0, 1.0, 1.0, 1.0);"
"";

int main()

    //GLFW init:
    if (!glfwInit())
        fprintf(stderr, "Failed to init GLFW");
        glfwTerminate();
    

    //Hints:
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

    //Creating window:
    GLFWwindow* window = glfwCreateWindow(800, 600, "Engine", glfwGetPrimaryMonitor(), nullptr);
    glfwMakeContextCurrent(window);

    //Glew initialize:
    glewExperimental = GL_TRUE;
    glewInit();

    //Create vertex array object:
    GLuint vao;
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);

    //Create vertex buffer object:
    GLuint vbo;
    glGenBuffers(1, &vbo);

    //Our triangle data:
    GLfloat vertices[] = 
         0.0f,  0.5f, //Vertex 1 (X, Y)
         0.5f, -0.5f, //Vertex 2 (X, Y)
        -0.5f, -0.5f  //Vertex 3 (X, Y)
    ;

    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    //Create and compile the vertex shader:
    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexSource, NULL);
    glCompileShader(vertexShader);

    //Create and compile the fragment shader:
    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentSource, NULL);
    glCompileShader(fragmentShader);

    //Creating shaders program:
    GLuint shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glBindFragDataLocation(shaderProgram, 0, "outColor");
    glLinkProgram(shaderProgram);
    glUseProgram(shaderProgram);

    GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
    glEnableVertexAttribArray(posAttrib);
    glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0);



    //The loop:
    while (!glfwWindowShouldClose(window))

        //Escape key:
        if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
            glfwSetWindowShouldClose(window, GL_TRUE);
        

        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);
        glDrawArrays(GL_TRIANGLES, 0, 3);

        glfwSwapBuffers(window);
        glfwPollEvents();
    



    return 0;

【问题讨论】:

【参考方案1】:
"in ver2 position;"
    ^^^^

ver2 是什么?我怀疑你的 GLSL 编译器也知道。

尝试vec2 并检查您的着色器编译/链接状态/日志:

struct Program

    static GLuint Load( const char* vert, const char* geom, const char* frag )
    
        GLuint prog = glCreateProgram();
        if( vert ) AttachShader( prog, GL_VERTEX_SHADER, vert );
        if( geom ) AttachShader( prog, GL_GEOMETRY_SHADER, geom );
        if( frag ) AttachShader( prog, GL_FRAGMENT_SHADER, frag );
        glLinkProgram( prog );
        CheckStatus( prog );
        return prog;
    

private:
    static void CheckStatus( GLuint obj )
    
        GLint status = GL_FALSE;
        if( glIsShader(obj) ) glGetShaderiv( obj, GL_COMPILE_STATUS, &status );
        if( glIsProgram(obj) ) glGetProgramiv( obj, GL_LINK_STATUS, &status );
        if( status == GL_TRUE ) return;
        GLchar log[ 1 << 15 ] =  0 ;
        if( glIsShader(obj) ) glGetShaderInfoLog( obj, sizeof(log), NULL, log );
        if( glIsProgram(obj) ) glGetProgramInfoLog( obj, sizeof(log), NULL, log );
        std::cerr << log << std::endl;
        exit( -1 );
    

    static void AttachShader( GLuint program, GLenum type, const char* src )
    
        GLuint shader = glCreateShader( type );
        glShaderSource( shader, 1, &src, NULL );
        glCompileShader( shader );
        CheckStatus( shader );
        glAttachShader( program, shader );
        glDeleteShader( shader );
    
;

【讨论】:

哇,我不敢相信这是问题所在.. ty.【参考方案2】:

您不需要使用glBindFragDataLocation,而是在片段着色器中写入gl_FragColor

const GLchar* fragmentSource =
"#version 150 core\n"
"void main()"
"   gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);"
"";

否则你需要用glDrawBuffers指定写入哪个缓冲区

【讨论】:

发帖者使用的是核心配置文件,其中 gl_FragColor 已弃用。但是无论如何都不需要glBindFragDataLocation 调用。如果片段着色器只有一个out,它会自动写入第一个绘制缓冲区(默认帧缓冲区默认为GL_BACK,FBO 为GL_COLOR_ATTACHMENT0)。 @RetoKoradi:实际上,我从未在规范中找到这样的保证。规范中的所有内容是 GL 将自动分配任何未手动分配位置的输出到某些未使用的颜色编号。出于显而易见的原因,每个现实世界的实现都从 0 开始赋值,但就规范而言,依赖它仍然是未定义的行为。 @derhass:已指定。 GLSL 4.4 规范:“如果在着色器文本中未分配位置或索引的输出变量具有通过 OpenGL API 指定的位置,则将使用 API 分配的位置。否则,链接器将为此类变量分配位置。所有此类分配的颜色索引都将为零。” ES 3.0 GLSLS 规范:“如果只有一个输出,则不需要指定位置,在这种情况下它默认为零。” @RetoKoradi:实际上并非如此。之前我自己也犯过同样的错误:颜色number和颜色index是有区别的。颜色 number 是这里的相关部分。 index 仅用于多输入混合。请注意,如果规范要求所有输出(如果使用多个输出)都绑定到相同的数字 0,那也会很奇怪......不过,ES 3.0 规范是另一回事。 @derhass:好的,是的,我明白你在说什么。确实没有明确指定链接器将从 0 开始分配位置。如果驱动程序不以这种方式处理它,很多软件都会中断,但理论上你是对的。 ES 参考很重要,因为他们非常努力地将 ES 规范保持为完整 OpenGL 的子集。因此,如果在 ES 中保证行为,但在 OpenGL 中不保证,那将是非常不可取的。

以上是关于绘制三角形不起作用:我只看到黑屏和鼠标的主要内容,如果未能解决你的问题,请参考以下文章

简单的 OpenTK 着色器不起作用

iOS startMonitoringForRegion 在睡眠模式下不起作用(黑屏)

windowbackground 在深色和浅色主题中不起作用

使用 avkit 流式传输视频时出现黑屏

为啥鼠标滚动条不起作用?

OpenGL 与 GLUT - 黑屏