Рисуването на триъгълник не работи: виждам само черен екран и мишката си

Използвам 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;
}

person Casper    schedule 23.05.2014    source източник


Отговори (2)


"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 );
    }
};
person genpfault    schedule 23.05.2014
comment
Уау, не мога да повярвам, че това е проблемът.. ти. - person Casper; 23.05.2014

не е необходимо да използвате glBindFragDataLocation, вместо това пишете на gl_FragColor във фрагментния шейдър:

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

в противен случай трябва да посочите в кой буфер се записва с glDrawBuffers

person ratchet freak    schedule 23.05.2014
comment
Постерът използва основния профил, където gl_FragColor е отхвърлен. Но обаждането glBindFragDataLocation така или иначе не е необходимо. Ако даден фрагментен шейдър има само един out, той автоматично се записва в първия буфер за изтегляне (който по подразбиране е GL_BACK за буфера на рамката по подразбиране и GL_COLOR_ATTACHMENT0 за FBO). - person Reto Koradi; 24.05.2014
comment
@RetoKoradi: Всъщност никога не можах да намеря такава гаранция в спецификацията. Всичко, което се казва в спецификацията, е, че GL автоматично ще присвои всички изходи, където местоположението не е присвоено ръчно на някакъв неизползван номер на цвят. Всяка реализация в реалния свят започва присвояването с 0 по очевидни причини, но разчитането на това все още е недефинирано поведение, що се отнася до спецификацията. - person derhass; 24.05.2014
comment
@derhass: Уточнено е. Спецификация на GLSL 4.4: Ако изходна променлива без местоположение или индекс, присвоени в текста на шейдъра, има местоположение, указано чрез OpenGL API, ще се използва присвоеното от API местоположение. В противен случай на такива променливи ще бъде присвоено местоположение от линкера. Всички такива присвоявания ще имат цветен индекс нула. Спецификация на ES 3.0 GLSLS: Ако има само един изход, местоположението не е необходимо да се посочва, в който случай то по подразбиране е нула. - person Reto Koradi; 24.05.2014
comment
@RetoKoradi: всъщност не е така. Направих същата грешка сам по-рано: има разлика между числото на цвета и индекса на цвета. Цветното номер е съответната част тук. Индекс е само за смесване с множество входове. Обърнете внимание, че също би било странно, ако спецификацията изисква всички изходи (ако се използват повече от един) да бъдат обвързани с едно и също число 0... Спецификацията на ES 3.0 обаче е различно нещо. - person derhass; 24.05.2014
comment
@derhass: Добре, да, разбирам какво казваш. Наистина не е изрично посочено, че линкерът ще присвои местоположенията, започващи от 0. Има много софтуер, който би се счупил, ако драйвер не се справи по този начин, но теоретично сте прав. Справката за ES има значение, защото те се опитват много да запазят спецификациите на ES да бъдат подмножество на пълния OpenGL. Така че, ако поведението е гарантирано в ES, но не и в OpenGL, това би било много нежелателно. - person Reto Koradi; 24.05.2014