OpenGL几何着色器三角形不会没有错误地绘制
Posted
技术标签:
【中文标题】OpenGL几何着色器三角形不会没有错误地绘制【英文标题】:OpenGL Geomentry Shader triangle wont draw with no errors 【发布时间】:2017-01-17 05:35:08 【问题描述】:我正在尝试编写一个几何着色器,它采用单个 vec4 位置并创建一个三角形。程序链接正确,但是当绘制调用发生时,屏幕上没有显示任何内容。
我有一个工作版本,在我自己计算三角形后将顶点提供给 OpenGL,但我希望让着色器工作,以便可以在 gpu 上创建三角形(以及最终其他形状)反而。这是我的代码:
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);
以及渲染调用:
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;
任何见解或帮助将不胜感激。
static const GLchar* _vertexShaderSource[] =
"#version 430 core \n"
" \n"
"layout (location = 0) in vec4 position; \n"
"layout (location = 1) in vec4 color; \n"
"uniform mat4 transform_mat; \n"
" \n"
"out vec4 vs_color; \n"
" \n"
"void main(void) \n"
" \n"
" gl_Position = transform_mat * position; \n"
" vs_color = color; \n"
" \n"
;
static const GLchar* _fragmentShaderSource[] =
"#version 430 core \n"
" \n"
"in vec4 vs_color; \n"
"out vec4 color; \n"
" \n"
"void main(void) \n"
" \n"
" color = vs_color; \n"
" \n"
;
您会注意到,在此示例中,我直接为着色器提供顶点,并且基本上只是转换它们。这个版本有效。这是基于 cmets 的更新版本。这仍然不起作用:
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;
【问题讨论】:
你有什么样的变换矩阵?是透视变换吗?你确定宽度和高度传递正确吗? 这是一个正交投影,据我所知,它们正在被传入。在 AddToBatch 调用中正确设置了这些值。对于此测试,w = 200,h = 200。 【参考方案1】:在单步执行代码并花一些时间查看进出几何着色器的内容后,我发现了我的问题。这是语法错误、普遍缺乏理解和一些逻辑错误的组合。这是所有工作的最终代码:
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"
;
下面是 draw 和 AddToBatch 函数的样子:
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;
【讨论】:
以上是关于OpenGL几何着色器三角形不会没有错误地绘制的主要内容,如果未能解决你的问题,请参考以下文章
无法获得简单的 2D 着色器以在 C++ openGL 中绘制红色三角形(无编译器错误)