2017-01-17 4 views
1

J'essaye d'écrire un shader de géométrie qui prend une seule position vec4, et crée un triangle. Le programme lie correctement, mais quand l'appel de tirage arrive, rien n'est affiché sur l'écran. J'ai une version de travail où je donne les sommets à OpenGL après avoir moi-même calculé le triangle, mais j'espère que le shader fonctionnera pour que le triangle (et éventuellement d'autres formes) puisse être créé sur le gpu à la place. Voici mon code:OpenGL Geomentry Shader triangle ne dessine pas sans erreurs

void TriSprite::v_InitShader(void) 
{ 
    if(_shaderProgram != NULL) return; 

    //=====Vertex Shaders===== 
    //This is used when only colors, not textures are used to render 
    //a pirmitive 
    static const GLchar* _vertexShaderSource[] = 
    { 
     "#version 430 core                \n" 
     "                    \n" 
     "layout (location = 0) in vec4 position;          \n" 
     "layout (location = 1) in vec4 color;           \n" 
     "layout (location = 2) in float width;           \n" 
     "layout (location = 3) in float height;           \n"     
     "uniform mat4 transform_mat;             \n" 
     "                    \n" 
     "out vec4 vs_color;                \n" 
     "out vec4 vs_dimnsions;               \n" 
     "                    \n" 
     "void main(void)                \n" 
     "{                    \n" 
     //=====Top===== 
     " gl_Position = transform_mat * position;          \n" 
     " vs_color = color;               \n" 
     " vs_dimnsions = vec4(width, height, 0.0, 0.0);        \n" 
     "}                    \n" 
    }; 

    //=====Geomtry Shader===== 
    static const GLchar* _geometryShaderSource[] = 
    { 
     "#version 430 core                \n" 
     "                    \n" 
     "layout(points) in;                \n" 
     "layout(triangle_strip, max_vertices = 2) out;         \n" 
     "                    \n" 
     "in vec4 vs_color[1];               \n" 
     "in vec4 vs_dimnsions[1];              \n" 
     "                    \n" 
     "out vec4 gs_color;                \n" 
     "                    \n" 
     "void main()                 \n" 
     "{                    \n" 
     //Bottom Right 
     " gl_Position = gl_in[0].gl_Position + vec4(vs_dimnsions[0].x, -vs_dimnsions[0].y, 0, 0);   \n" 
     " EmitVertex();                     \n" 
     //Top 
     " gl_Position = gl_in[0].gl_Position + vec4(0.0, vs_dimnsions[0].y, 0.0, 0.0);     \n" 
     " EmitVertex();                     \n" 
     //Bottom Left 
     " gl_Position = gl_in[0].gl_Position + vec4(-vs_dimnsions[0].x, -vs_dimnsions[0].y, 0.0, 0.0); \n" 
     " EmitVertex();                     \n" 
     "                    \n" 
     " EndPrimitive();                \n" 
     " gs_color = vs_color[0];              \n" 
     "}                    \n" 
    }; 


    //=====Fragment Shaders===== 
    //This is used when only colors, not textures are used to render 
    //a pirmitive 
    static const GLchar* _fragmentShaderSource[] = 
    { 
     "#version 430 core                \n" 
     "                    \n" 
     "in vec4 gs_color;                \n" 
     "out vec4 color;                \n" 
     "                    \n" 
     "void main(void)                \n" 
     "{                    \n" 
     " color = gs_color;               \n" 
     "}                    \n" 
    }; 

    //=====Compile Shaders===== 
    GLuint vertextShaderProgram; 
    GLuint geometryShaderProgram; 
    GLuint fragmentShaderProgram; 

    vertextShaderProgram = glCreateShader(GL_VERTEX_SHADER); 
    glShaderSource(vertextShaderProgram, 1, _vertexShaderSource, NULL); 
    glCompileShader(vertextShaderProgram); 

    geometryShaderProgram = glCreateShader(GL_GEOMETRY_SHADER); 
    glShaderSource(geometryShaderProgram, 1, _geometryShaderSource, NULL); 
    glCompileShader(geometryShaderProgram); 

    fragmentShaderProgram = glCreateShader(GL_FRAGMENT_SHADER); 
    glShaderSource(fragmentShaderProgram, 1, _fragmentShaderSource, NULL); 
    glCompileShader(fragmentShaderProgram); 

    _shaderProgram = glCreateProgram(); 
    glAttachShader(_shaderProgram, vertextShaderProgram); 
    glAttachShader(_shaderProgram, geometryShaderProgram); 
    glAttachShader(_shaderProgram, fragmentShaderProgram); 
    glLinkProgram(_shaderProgram); 

    GLint isLinked = 0; 
    glGetProgramiv(_shaderProgram, GL_LINK_STATUS, &isLinked); 

    //=====Error Checking===== 
    if(isLinked == GL_FALSE) 
    { 
     GLint maxLength = 0; 
     glGetProgramiv(_shaderProgram, GL_INFO_LOG_LENGTH, &maxLength); 

     //The maxLength includes the NULL character 
     std::vector<GLchar> infoLog(maxLength); 
     glGetProgramInfoLog(_shaderProgram, maxLength, &maxLength, &infoLog[0]); 

     for(auto i = infoLog.begin(); i != infoLog.end(); ++i) 
     { 
      std::cout << *i ; 
     } 

     std::cout << "\n"; 

     //The program is useless now. So delete it. 
     glDeleteProgram(_shaderProgram); 

    } 

    //=====Clean up===== 
    glDeleteShader(vertextShaderProgram); 
    glDeleteShader(geometryShaderProgram); 
    glDeleteShader(vertextShaderProgram); 
} 

Et le rendu appel:

void Renderer::AddToBatch(GLuint shader, Vec2& pos, U32 w, U32 h, Col& c) 
{ 
    if(_currentShader != shader) 
    { 
     Draw(); 
     _currentShader = shader; 

     glUseProgram(_currentShader); 
    } 

    if(_currentBatchSize + 1 >= _maxBatchSize) { Draw(); } 

    _vertices.push_back(pos.GetX()); 
    _vertices.push_back(pos.GetY()); 
    _vertices.push_back(pos.GetZ()); 
    _vertices.push_back(pos.GetW()); 

    _xDimensions.push_back((F32)w); 
    _yDimensions.push_back((F32)h); 


    _colors.push_back(c.GetRed()); 
    _colors.push_back(c.GetGreen()); 
    _colors.push_back(c.GetBlue()); 
    _colors.push_back(c.GetAlpha()); 

    ++_currentBatchSize; 
} 

    void Renderer::Draw(void) 
{ 
    if(_currentBatchSize == 0) return; 

    GLuint buffers[4]; 
    glGenBuffers(4, buffers); 

    glBindBuffer(GL_ARRAY_BUFFER, buffers[0]); 
    glBufferData(GL_ARRAY_BUFFER, (sizeof(F32) * _vertices.size()), &_vertices[0], GL_STATIC_DRAW); 
    glEnableVertexAttribArray(0); 
    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL); 

    glBindBuffer(GL_ARRAY_BUFFER, buffers[1]); 
    glBufferData(GL_ARRAY_BUFFER, (sizeof(F32) * _colors.size()), &_colors[0], GL_STATIC_DRAW); 
    glEnableVertexAttribArray(1); 
    glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, NULL); 


    glBindBuffer(GL_ARRAY_BUFFER, buffers[2]); 
    glBufferData(GL_ARRAY_BUFFER, (sizeof(U32) * _xDimensions.size()), &_xDimensions[0], GL_STATIC_DRAW); 
    glEnableVertexAttribArray(2); 
    glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, 0, NULL); 


    glBindBuffer(GL_ARRAY_BUFFER, buffers[3]); 
    glBufferData(GL_ARRAY_BUFFER, (sizeof(U32) * _yDimensions.size()), &_yDimensions[0], GL_STATIC_DRAW); 
    glEnableVertexAttribArray(3); 
    glVertexAttribPointer(3, 1, GL_FLOAT, GL_FALSE, 0, NULL); 


    glDrawArrays(GL_TRIANGLES, 0, _currentBatchSize); 

    _currentBatchSize = 0; 
} 

Toute idée ou de l'aide sera grandement appréciée. Vous remarquerez que dans cet exemple, je charge directement le shader des sommets, et je les transforme simplement. Cette version fonctionne. Voici une version mise à jour basée sur les commentaires. Ce ne fonctionne toujours pas:

static const GLchar* _vertexShaderSource[] = 
    { 
     "#version 430 core                \n" 
     "                    \n" 
     "layout (location = 0) in vec4 position;          \n" 
     "layout (location = 1) in vec4 color;           \n" 
     "layout (location = 2) in float width;           \n" 
     "layout (location = 3) in float height;           \n"     
     "uniform mat4 transform_mat;             \n" 
     "                    \n" 
     "out vec4 vs_color;                \n" 
     "out vec4 vs_dimensions;              \n" 
     "                    \n" 
     "void main(void)                \n" 
     "{                    \n" 
     " gl_Position = transform_mat * position;          \n" 
     " vs_color = color;               \n" 
     " vs_dimensions = transform_mat * vec4(width, height, 0.0, 0.0);    \n" 
     "}                    \n" 
    }; 

static const GLchar* _geometryShaderSource[] = 
    { 
     "#version 430 core                \n" 
     "                    \n" 
     "layout(points) in;                \n" 
     "layout(triangle_strip, max_vertices = 3) out;         \n" 
     "                    \n" 
     "in vec4 vs_color[1];               \n" 
     "in vec4 vs_dimensions[1];              \n" 
     "                    \n" 
     "out vec4 gs_color;                \n" 
     "                    \n" 
     "void main()                 \n" 
     "{                    \n" 
     " gs_color = vs_color[0];              \n" 
     //Top 
     " gl_Position = gl_in[0].gl_Position + vec4(0.0, vs_dimensions[0].y, 0.0, 0.0);     \n" 
     " EmitVertex();                     \n" 
     //Bottom Right 
     " gl_Position = gl_in[0].gl_Position + vec4(vs_dimensions[0].x, -vs_dimensions[0].y, 0, 0);  \n" 
     " EmitVertex();                     \n" 
     //Bottom Left 
     " gl_Position = gl_in[0].gl_Position + vec4(-vs_dimensions[0].x, -vs_dimensions[0].y, 0.0, 0.0); \n" 
     " EmitVertex();                     \n" 
     "                    \n" 
     " EndPrimitive();                \n" 
     "} 

static const GLchar* _fragmentShaderSource[] = 
    { 
     "#version 430 core                \n" 
     "                    \n" 
     "in vec4 gs_color;                \n" 
     "out vec4 color;                \n" 
     "                    \n" 
     "void main(void)                \n" 
     "{                    \n" 
     " color = gs_color;               \n" 
     "}                    \n" 
    }; 


void Renderer::Draw(void) 
{ 
    if(_currentBatchSize == 0) return; 

    GLuint buffers[4]; 
    glGenBuffers(4, buffers); 

    glBindBuffer(GL_ARRAY_BUFFER, buffers[0]); 
    glBufferData(GL_ARRAY_BUFFER, (sizeof(F32) * _vertices.size()), &_vertices[0], GL_STATIC_DRAW); 
    glEnableVertexAttribArray(0); 
    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL); 

    glBindBuffer(GL_ARRAY_BUFFER, buffers[1]); 
    glBufferData(GL_ARRAY_BUFFER, (sizeof(F32) * _colors.size()), &_colors[0], GL_STATIC_DRAW); 
    glEnableVertexAttribArray(1); 
    glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, NULL); 


    glBindBuffer(GL_ARRAY_BUFFER, buffers[2]); 
    glBufferData(GL_ARRAY_BUFFER, (sizeof(U32) * _xDimensions.size()), &_xDimensions[0], GL_STATIC_DRAW); 
    glEnableVertexAttribArray(2); 
    glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, 0, NULL); 


    glBindBuffer(GL_ARRAY_BUFFER, buffers[3]); 
    glBufferData(GL_ARRAY_BUFFER, (sizeof(U32) * _yDimensions.size()), &_yDimensions[0], GL_STATIC_DRAW); 
    glEnableVertexAttribArray(3); 
    glVertexAttribPointer(3, 1, GL_FLOAT, GL_FALSE, 0, NULL); 


    glDrawArrays(GL_TRIANGLES, 0, _currentBatchSize); 

    _currentBatchSize = 0; 
} 
+0

Quel type de matrice de transformation avez-vous? Est-ce une transformation de perspective? Êtes-vous sûr que la largeur et la hauteur sont passées correctement? –

+0

Il s'agit d'une projection orthographique, et autant que je sache, ils sont passés. Les valeurs sont définies correctement dans l'appel AddToBatch. Pour ce test, w = 200 et h = 200. –

Répondre

0

Après avoir quitté dans le code, et passer du temps à examiner ce qui se passe dans et hors d'un geometry shader, j'ai trouvé mes questions. C'était une combinaison d'erreurs de syntaxe, de manque général de compréhension et de quelques erreurs logiques. Voici tout le code final qui fonctionne:

static const GLchar* _vertexShaderSource[] = 
    { 
     "#version 430 core                \n" 

     "layout (location = 0) in vec4 position;          \n" 
     "layout (location = 1) in vec4 color;           \n" 
     "layout (location = 2) in vec2 dimensions;          \n" 

     "uniform mat4 transform_mat;             \n" 

     "out vec4 gs_color;                \n" 
     "out vec4 gs_dimensions;              \n" 

     "void main(void)                \n" 
     "{                    \n" 
     " gl_Position = transform_mat * position;          \n" 
     " gs_color = color;               \n" 
     " gs_dimensions = transform_mat * vec4(dimensions.x, dimensions.y, 0.0, 0.0);         \n" 
     "}                    \n" 
    }; 

//=====Geomtry Shader===== 
    static const GLchar* _geometryShaderSource[] = 
    { 
     "#version 430 core                \n" 

     "layout(points) in;                \n" 
     "layout(triangle_strip, max_vertices = 3) out;         \n" 

     "in vec4 gs_color[];               \n" 
     "in vec4 gs_dimensions[];              \n" 

     "out vec4 fs_color;                \n" 

     "void main()                 \n" 
     "{                    \n" 
     " fs_color = gs_color[0];              \n" 
     //Top 
     " gl_Position = gl_in[0].gl_Position + vec4(0.0, gs_dimensions[0].y, 0.0, 0.0);     \n" 
     " EmitVertex();                     \n" 
     //Bottom Right 
     " gl_Position = gl_in[0].gl_Position + vec4(-gs_dimensions[0].x, -gs_dimensions[0].y, 0, 0);  \n" 
     " EmitVertex();                     \n" 
     //Bottom Left 
     " gl_Position = gl_in[0].gl_Position + vec4(gs_dimensions[0].x, -gs_dimensions[0].y, 0.0, 0.0); \n" 
     " EmitVertex();                     \n" 

     " EndPrimitive();                \n" 
     "}                    \n" 
    }; 


    //=====Fragment Shaders===== 
    //This is used when only colors, not textures are used to render 
    //a pirmitive 
    static const GLchar* _fragmentShaderSource[] = 
    { 
     "#version 430 core                \n" 

     "in vec4 fs_color;                \n" 
     "out vec4 color;                \n" 

     "void main(void)                \n" 
     "{                    \n" 
     " color = fs_color;               \n" 
     "}                    \n" 
    }; 

Et voici ce que le tirage au sort et les fonctions AddToBatch ressemblent:

void Renderer::AddToBatch(GLuint shader, Vec2& pos, U32 w, U32 h, Col& c) 
{ 
    if(_currentShader != shader) 
    { 
     Draw(); 
     _currentShader = shader; 

     glUseProgram(_currentShader); 

     _SetOrthoProjection(); 
    } 

    if(_currentBatchSize + 1 >= _maxBatchSize) { Draw(); } 

    _vertices.push_back(pos.GetX()); 
    _vertices.push_back(pos.GetY()); 
    _vertices.push_back(pos.GetZ()); 
    _vertices.push_back(pos.GetW()); 

    _dimensions.push_back((F32)w); 
    _dimensions.push_back((F32)h); 

    _colors.push_back(c.GetRed()); 
    _colors.push_back(c.GetGreen()); 
    _colors.push_back(c.GetBlue()); 
    _colors.push_back(c.GetAlpha()); 

    ++_currentBatchSize; 
} 


void Renderer::Draw(void) 
{ 
    if(_currentBatchSize == 0) return; 

    GLuint buffers[4]; 
    glGenBuffers(4, buffers); 

    glBindBuffer(GL_ARRAY_BUFFER, buffers[0]); 
    glBufferData(GL_ARRAY_BUFFER, (sizeof(F32) * _vertices.size()), &_vertices[0], GL_STATIC_DRAW); 
    glEnableVertexAttribArray(0); 
    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL); 

    glBindBuffer(GL_ARRAY_BUFFER, buffers[1]); 
    glBufferData(GL_ARRAY_BUFFER, (sizeof(F32) * _colors.size()), &_colors[0], GL_STATIC_DRAW); 
    glEnableVertexAttribArray(1); 
    glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, NULL); 


    glBindBuffer(GL_ARRAY_BUFFER, buffers[2]); 
    glBufferData(GL_ARRAY_BUFFER, (sizeof(F32) * _dimensions.size()), &_dimensions[0], GL_STATIC_DRAW); 
    glEnableVertexAttribArray(2); 
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, NULL); 

    glDrawArrays(GL_POINTS, 0, _currentBatchSize); 

    //=====Reset All Containers and Counters===== 
    _vertices.clear(); 
    _dimensions.clear(); 
    _colors.clear(); 
    _uvs.clear(); 
    _currentBatchSize = 0; 
}