我正在尝试编写一个采用单个 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"
};
您会注意到,在此示例中,我直接向着色器提供顶点,基本上只是转换它们。此版本有效。这是基于评论的更新版本。这仍然不起作用:
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;
}
在逐步完成代码并花一些时间查看几何着色器的进出内容后,我发现了我的问题。这是语法错误、普遍缺乏理解和一些逻辑错误的结合。以下是所有有效的最终代码:
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;
}