glPolygonMode 未以正确模式呈现
Posted
技术标签:
【中文标题】glPolygonMode 未以正确模式呈现【英文标题】:glPolygonMode not rendering in correct mode 【发布时间】:2018-07-20 14:15:36 【问题描述】:我最近开始学习曲面细分,今天我试图在曲面细分之后绘制一个三角形,这样我就可以使用glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
看到所有经过细分的较小三角形。但由于某种原因,输出只是一个彩色背景,其中没有任何三角形。
对于镶嵌,我制作了control shader
和evaluation shader
,然后将它们链接到program
。(下面的代码)
// Source code for Tesselation Control Shader
static const GLchar * tesselation_control_shader[] =
"#version 450 core \n"
" \n"
"layout(vertices = 3) out; \n"
" \n"
"void main(void) \n"
" \n"
" //Only if I am invocation 0 \n"
" if (gl_InvocationID == 0) \n"
" \n"
" gl_TessLevelInner[0] = 5.0; \n"
" gl_TessLevelOuter[0] = 5.0; \n"
" gl_TessLevelOuter[1] = 5.0; \n"
" gl_TessLevelOuter[2] = 5.0; \n"
" \n"
" \n"
" // Everybody copies their input to their input \n"
" gl_out[gl_InvocationID].gl_Position = \n"
" gl_in[gl_InvocationID].gl_Position; \n"
" \n"
;
// Source code for tesselation evaluation shader
static const GLchar * tesselation_evaluation_shader[] =
"#version 450 core \n"
" \n"
"layout(triangles, equal_spacing, cw) in; \n"
" \n"
"void main(void) \n"
" \n"
" gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position + \n"
" gl_TessCoord.y * gl_in[1].gl_Position + \n"
" gl_TessCoord.z * gl_in[2].gl_Position); \n"
" \n"
;
然后我在使用glDrawArrays(GL_TRIANGLE, 0, 3)
绘制三角形之前在我的render
函数中调用glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
。
我最初认为glPolygonMode
默认为GL_FILL
,但我认为这不是问题,因为我只是在读一本书(OpenGL Superbible 7th Edition)。
我该如何解决这个问题?
编辑: 我在下面添加了整个程序的代码:
GLuint compile_shaders(void)
GLuint vertex_shader;
GLuint fragment_shader;
GLuint control_shader;
GLuint evaluation_shader;
GLuint program;
// Source code for Vertex Shader
static const GLchar * vertex_shader_source[] =
"#version 450 core \n"
" \n"
"// offset and color are input vertex attribute \n"
"layout (location = 0) in vec4 offset; \n"
"layout (location = 1) in vec4 color; \n"
" \n"
"//Declare VS_OUT as an output interface block \n"
"out VS_OUT \n"
" \n"
" vec4 color; //Send color to next stage \n"
"vs_out; \n"
" \n"
"void main(void) \n"
" \n"
" //Decalre a hardcoded array of positions \n"
" const vec4 vertices[3] = vec4[3](vec4(0.25, -0.25, 0.5, 1.0), \n"
" vec4(-0.25, -0.25, 0.5, 1.0), \n"
" vec4(0.25, 0.25, 0.5, 1.0)); \n"
" \n"
" //Index into our array using gl_VertexID \n"
" gl_Position = vertices[gl_VertexID] + offset; \n"
" \n"
"//color = vec4(1.0, 0.0, 0.0, 1.0); \n"
"//Output fixed value for vs_color \n"
"vs_out.color = color; \n"
" \n"
;
// Source code for Fragment Shader
static const GLchar * fragment_shader_source[] =
"#version 450 core \n"
" \n"
"//Declare VS_OUT as an input interface block \n"
"in VS_OUT \n"
" \n"
" vec4 color; //Send color to next stage \n"
"fs_in; \n"
" \n"
"//Ouput to the framebuffer \n"
"out vec4 color; \n"
" \n"
"void main(void) \n"
" \n"
"// Simply assign the color we were given by the vertex shader to our output \n"
" color = fs_in.color; \n"
" \n"
;
// Source code for Tesselation Control Shader
static const GLchar * tesselation_control_shader[] =
"#version 450 core \n"
" \n"
"layout(vertices = 3) out; \n"
" \n"
"void main(void) \n"
" \n"
" //Only if I am invocation 0 \n"
" if (gl_InvocationID == 0) \n"
" \n"
" gl_TessLevelInner[0] = 5.0; \n"
" gl_TessLevelOuter[0] = 5.0; \n"
" gl_TessLevelOuter[1] = 5.0; \n"
" gl_TessLevelOuter[2] = 5.0; \n"
" \n"
" \n"
" // Everybody copies their input to their input \n"
" gl_out[gl_InvocationID].gl_Position = \n"
" gl_in[gl_InvocationID].gl_Position; \n"
" \n"
;
// Source code for tesselation evaluation shader
static const GLchar * tesselation_evaluation_shader[] =
"#version 450 core \n"
" \n"
"layout(triangles, equal_spacing, cw) in; \n"
" \n"
"void main(void) \n"
" \n"
" gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position + \n"
" gl_TessCoord.y * gl_in[1].gl_Position + \n"
" gl_TessCoord.z * gl_in[2].gl_Position); \n"
" \n"
;
// Create and compiler Vertex Shader
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, vertex_shader_source, NULL);
glCompileShader(vertex_shader);
// Create and compiler Fragment Shader
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, fragment_shader_source, NULL);
glCompileShader(fragment_shader);
// Create and compile tesselation control shader
control_shader = glCreateShader(GL_TESS_CONTROL_SHADER);
glShaderSource(control_shader, 1, tesselation_control_shader, NULL);
glCompileShader(control_shader);
// Create and compile tesselation evaluation shader
evaluation_shader = glCreateShader(GL_TESS_CONTROL_SHADER);
glShaderSource(evaluation_shader, 1, tesselation_control_shader, NULL);
glCompileShader(evaluation_shader);
// Create program, attach shaders to it, and link it
program = glCreateProgram();
glAttachShader(program, vertex_shader);
glAttachShader(program, fragment_shader);
glAttachShader(program, control_shader);
glAttachShader(program, evaluation_shader);
glLinkProgram(program);
// Delete shaders as program has them now
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);
glDeleteShader(control_shader);
glDeleteShader(evaluation_shader);
return program;
;
class TesselationCSOne : public sb7::application
public:
void startup()
rendering_program = compile_shaders();
glCreateVertexArrays(1, &vertex_array_object);
glBindVertexArray(vertex_array_object);
void shutdown()
glDeleteVertexArrays(1, &vertex_array_object);
glDeleteProgram(rendering_program);
glDeleteVertexArrays(1, &vertex_array_object);
// Our rendering function
void render(double currentTime)
// Sets colour
static const GLfloat color[] = (float)sin(currentTime) * 0.5f + 0.5f, (float)sin(currentTime) * 0.5f + 0.5f, 0.0f, 1.0f ;
glClearBufferfv(GL_COLOR, 0, color);
//Tell OpenGL to draw only the outlines of the resulting triangle
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
// Use program object we created for rendering
glUseProgram(rendering_program);
GLfloat attrib[] = 1.0, 0.0, 0.0, 0.0 ;/* (float)sin(currentTime) * 0.5f, (float)sin(currentTime) * 0.6f, 0.0f, 0.0f ;*/
// Update value of input attribute 0
glVertexAttrib4fv(0, attrib);
// Draw pathes for tesselation shaders
glPatchParameteri(GL_PATCH_VERTICES, 3);
// Draw one triangle
glDrawArrays(GL_PATCHES, 0, 3);
private:
GLuint rendering_program;
GLuint vertex_array_object;
;
// Only instance of DECLARE_MAIN to state entry point
DECLARE_MAIN(TesselationCSOne);
【问题讨论】:
如果你使用曲面细分着色器,那么你必须绘制Patches (GL_PATCHES
)。
与您的问题无关,但可能值得研究raw string literals,而不是用引号将您的 GLSL 源代码的每一行括起来。
@Rabbid76 我认为如果您使用 Tessellation 着色器,补丁会自动(隐式)完成?我需要的每个补丁的控制点数是 3。这不是默认值吗?而如果是默认值,那我就不用调用了吧?
@Fibbles 我会调查一下,谢谢你的建议
@Varun.R 您必须通过glPatchParameteri( GL_PATCH_VERTICES, ...)
设置补丁的大小,并且原始类型必须为GL_PATCHES
【参考方案1】:
如果您使用曲面细分着色器,则必须绘制补丁。您必须通过glPatchParameteri( GL_PATCH_VERTICES, ...)
设置补丁的大小,原始类型必须是GL_PATCHES
。
如果一个patch中的顶点数是3,那么你必须这样做:
glPatchParameteri(GL_PATCH_VERTICES, 3);
glDrawArrays(GL_PATCHES, 0, 3)
见OpenGL 4.6 API Core Profile Specification; 10.1.15 Separate Patches; page 342:
使用模式
PATCHES
指定单独的补丁。补丁是用于原始曲面细分的有序顶点集合(第 11.2 节)。组成面片的顶点没有隐含的几何顺序。曲面细分着色器和固定功能曲面细分器使用补丁的顶点来生成新的点、线或三角形图元。void PatchParameteri( enum pname, int value );
将 pname 设置为
PATCH_VERTICES
您的着色器程序甚至没有链接,因为片段着色器试图从输入接口块读取, 未声明为前一个着色器阶段的输出。 您必须通过曲面细分控制和评估着色器将顶点属性传递给片段着色器:
镶嵌控制着色器:
#version 450 core
layout(vertices = 3) out;
in VS_OUT
vec4 color;
tesc_in[];
out TESC_OUT
vec4 color;
tesc_out[];
void main(void)
if (gl_InvocationID == 0)
gl_TessLevelInner[0] = 5.0;
gl_TessLevelOuter[0] = 5.0;
gl_TessLevelOuter[1] = 5.0;
gl_TessLevelOuter[2] = 5.0;
tesc_out[gl_InvocationID].color = tesc_in[gl_InvocationID].color;
gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
曲面细分评估着色器:
#version 450 core
layout(triangles, equal_spacing, cw) in;
in TESC_OUT
vec4 color;
tese_in[];
out TESE_OUT
vec4 color;
tese_out;
void main(void)
tese_out.color = ( gl_TessCoord.x * tese_in[0].color +
gl_TessCoord.y * tese_in[1].color +
gl_TessCoord.z * tese_in[2].color ) / 3.0;
gl_Position = ( gl_TessCoord.x * gl_in[0].gl_Position +
gl_TessCoord.y * gl_in[1].gl_Position +
gl_TessCoord.z * gl_in[2].gl_Position ) / 3.0;
片段着色器:
#version 450 core
in TESE_OUT
vec4 color;
fs_in;
out vec4 color;
void main(void)
color = fs_in.color;
此外,我建议检查着色器对象是否已成功编译:
GLuint shaderObj = .... ;
glCompileShader( shaderObj );
GLint status = GL_TRUE;
glGetShaderiv( shaderObj, GL_COMPILE_STATUS, &status );
if ( status == GL_FALSE )
GLint logLen;
glGetShaderiv( shaderObj, GL_INFO_LOG_LENGTH, &logLen );
std::vector< char >log( logLen );
GLsizei written;
glGetShaderInfoLog( shaderObj, logLen, &written, log.data() );
std::cout << "compile error:" << std::endl << log.data() << std::endl;
并且一个着色器程序对象已成功链接:
GLuint progObj = ....;
glLinkProgram( progObj );
GLint status = GL_TRUE;
glGetProgramiv( progObj, GL_LINK_STATUS, &status );
if ( status == GL_FALSE )
GLint logLen;
glGetProgramiv( progObj, GL_INFO_LOG_LENGTH, &logLen );
std::vector< char >log( logLen );
GLsizei written;
glGetProgramInfoLog( progObj, logLen, &written, log.data() );
std::cout << "link error:" << std::endl << log.data() << std::endl;
顺便阅读一下Raw string literals,它简化了着色器源代码字符串的声明:
例如
std::string fragment_shader_source = R"(
#version 450 core
in TESE_OUT
vec4 color;
fs_in;
out vec4 color;
void main(void)
color = fs_in.color;
)";
进一步注意,offset
可能会将三角形移出视口。在属性初始化中更改offset
的值:
GLfloat attrib[] = 0.0, 0.0, 0.0, 0.0 ;
或者出于调试原因去掉顶点着色器中的offest
gl_Position = vertices[gl_VertexID];
您必须确保也设置了颜色属性:
GLfloat attrib1[] = 1.0, 1.0, 0.0, 1.0 ;
glVertexAttrib4fv(1, attrib1);
结果可能如下所示:
【讨论】:
我在哪里打电话给glPatchParametri and glDrawArrays
?我在render()
中绘制三角形之前调用它,但输出相同,并且曲面细分仍然不存在
@Varun.R 在您的问题中,您只发布了曲面细分着色器。所以很难找到问题。您问题中的代码不是Minimal, Complete, and Verifiable example
我编辑了问题并添加了整个程序的代码。这有帮助吗?
我修复了错误并链接了着色器程序,就像您在您放置的代码 sn-ps 中所做的那样,但输出仍然是黄色屏幕并且没有三角形
@Varun.R 我扩展了答案。【参考方案2】:
所以在检查了很多来源和 Superbible 的代码存储库后,我意识到我有很多不必要的代码(例如,着色器中的 interface blocks
),甚至还有不少错误(例如,我有两个 @987654322 @ 变量)。
但是,在修复了所有生成所需输出(镶嵌三角形)的代码之后:
/**
Program to draw a triangle with tesselation.
**/
#include <sb7.h>
class TesselatedTriangle : public sb7::application
void init()
static const char title[] = "Tessellated Triangle";
sb7::application::init();
memcpy(info.title, title, sizeof(title));
virtual void startup()
static const char * vertex_shader_source[] =
"#version 450 core \n"
" \n"
"void main(void) \n"
" \n"
" const vec4 vertices[] = vec4[](vec4( 0.25, -0.25, 0.5, 1.0), \n"
" vec4(-0.25, -0.25, 0.5, 1.0), \n"
" vec4( 0.25, 0.25, 0.5, 1.0)); \n"
" \n"
" gl_Position = vertices[gl_VertexID]; \n"
" \n"
;
static const char * tesselation_control_shader_source[] =
"#version 450 core \n"
" \n"
"layout (vertices = 3) out; \n"
" \n"
"void main(void) \n"
" \n"
" if (gl_InvocationID == 0) \n"
" \n"
" gl_TessLevelInner[0] = 5.0; \n"
" gl_TessLevelOuter[0] = 5.0; \n"
" gl_TessLevelOuter[1] = 5.0; \n"
" gl_TessLevelOuter[2] = 5.0; \n"
" \n"
" gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; \n"
" \n"
;
static const char * tesselation_evaluation_shader_source[] =
"#version 450 core \n"
" \n"
"layout (triangles, equal_spacing, cw) in; \n"
" \n"
"void main(void) \n"
" \n"
" gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position) + \n"
" (gl_TessCoord.y * gl_in[1].gl_Position) + \n"
" (gl_TessCoord.z * gl_in[2].gl_Position); \n"
" \n"
;
static const char * fragment_shader_source[] =
"#version 450 core \n"
" \n"
"out vec4 color; \n"
" \n"
"void main(void) \n"
" \n"
" color = vec4(0.0, 0.8, 1.0, 1.0); \n"
" \n"
;
rendering_program = glCreateProgram();
// Compile shaders
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, vertex_shader_source, NULL);
glCompileShader(vs);
GLuint tcs = glCreateShader(GL_TESS_CONTROL_SHADER);
glShaderSource(tcs, 1, tesselation_control_shader_source, NULL);
glCompileShader(tcs);
GLuint tes = glCreateShader(GL_TESS_EVALUATION_SHADER);
glShaderSource(tes, 1, tesselation_evaluation_shader_source, NULL);
glCompileShader(tes);
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, fragment_shader_source, NULL);
glCompileShader(fs);
// Attach shaders to the program
glAttachShader(rendering_program, vs);
glAttachShader(rendering_program, tcs);
glAttachShader(rendering_program, tes);
glAttachShader(rendering_program, fs);
// Link the program
glLinkProgram(rendering_program);
// Generate vertex arrays
glGenVertexArrays(1, &vertex_array_object);
glBindVertexArray(vertex_array_object);
// Declare the drawing mode for the polygons
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
virtual void render(double currentTime)
static const GLfloat green[] = 0.0f, 0.25f, 0.0f, 1.0f ;
glClearBufferfv(GL_COLOR, 0, green);
glUseProgram(rendering_program);
glDrawArrays(GL_PATCHES, 0, 3);
virtual void shutdown()
glDeleteVertexArrays(1, &vertex_array_object);
glDeleteProgram(rendering_program);
private:
GLuint rendering_program;
GLuint vertex_array_object;
;
// One and only instance of DECLARE_MAIN
DECLARE_MAIN(TesselatedTriangle)
希望这可以帮助遇到同样问题的其他人。
【讨论】:
以上是关于glPolygonMode 未以正确模式呈现的主要内容,如果未能解决你的问题,请参考以下文章