为啥我的扁平着色器(来自 Lighthouse3d 教程)不起作用?
Posted
技术标签:
【中文标题】为啥我的扁平着色器(来自 Lighthouse3d 教程)不起作用?【英文标题】:Why My Flatten Shader (from Lighthouse3d Tutorial) Is Not Working?为什么我的扁平着色器(来自 Lighthouse3d 教程)不起作用? 【发布时间】:2011-06-16 16:37:19 【问题描述】:tutorial 有一个名为 Flatten Shader 的示例,它将 GLUT 茶壶显示为扁平茶壶。 Here is the link to the Flatten Shader.
我已经按照教程中提到的步骤完成了所有操作,但是我的茶壶不像教程中的茶壶那样扁平。它看起来就像一个普通的茶壶。
这是顶点着色器的代码:
void main()
vec4 v = vec4(gl_Vertex);
v.z = 0.0;
gl_Position = gl_ModelViewProjectionMatrix * v;
这是我的片段着色器:
void main()
gl_FragColor = gl_Color;
这是我画茶壶的方法:
void display ( void )
glClearDepth(1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
gluLookAt( 0.0, 0.0, 2.0,
0.0, 0.0, 0.0,
0.0, 1.0, 0.0
);
glMultMatrixd(trackball->getRotation());
const GLfloat diffuseIntensity[] = 0.8, 0.4, 0.4, 1.0 ;
const GLfloat specularIntensity[] = 0.5, 0.5, 0.5, 1.0 ;
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, diffuseIntensity);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specularIntensity);
glMaterialf( GL_FRONT_AND_BACK, GL_SHININESS, 5.0 );
glutSolidTeapot(1.0);
glutSwapBuffers();
虽然它应该是“平的”,但显示的茶壶就像一个普通的茶壶。如果您认为我错过了一些初始配置/设置步骤,请不要这样做,因为我已经完成了:
GLuint createShader ( const GLchar* const source, GLenum type )
GLuint shader = glCreateShader( type );
glShaderSource( shader, 1, const_cast<const GLchar**>(&source), 0 );
glCompileShader( shader );
return shader;
和:
GLuint createProgram ( const GLuint shader )
GLuint program = glCreateProgram();
glAttachShader(program, shader);
glLinkProgram(program);
return program;
这里是所有东西聚集在一起的地方:
GLuint vertexShader = createShader(vertexShaderSource, GL_VERTEX_SHADER);
GLuint fragmentShader = createShader(fragmentShaderSource, GL_FRAGMENT_SHADER);
GLuint vertexShaderProgram = createProgram(vertexShader);
GLuint fragmentShaderProgram = createProgram(fragmentShader);
glUseProgram(vertexShaderProgram);
glUseProgram(fragmentShaderProgram);
我哪里错了?
【问题讨论】:
【参考方案1】:一些事情:
您没有正确绑定着色器。您的 createProgram 函数需要将片段着色器和顶点着色器绑定在一起。您应该将其替换为如下所示的代码:
GLuint createProgram ( const GLuint fshader, const GLuint vshader )
GLuint program = glCreateProgram();
glAttachShader(program, fshader);
glAttachShader(program, vshader);
glLinkProgram(program);
return program;
相应地,您应该将最后一个 sn-p 修改为如下所示:
GLuint vertexShader = createShader(vertexShaderSource, GL_VERTEX_SHADER);
GLuint fragmentShader = createShader(fragmentShaderSource, GL_FRAGMENT_SHADER);
GLuint shaderProgram = createProgram(fragmentShader, vertexShader);
glUseProgram(shaderProgram);
此外,可能还有其他问题。您应该使用 glGet(Shader|Program)InfoLog 来帮助调试着色器,并调用 glGetError 来帮助诊断程序失败的位置。
最后,我不能保证这个堆栈交换答案的可信度,但显然在一些较旧的 ATi 实现中,gl_Color 是 vec3,而不是 vec4,因此您需要在分配之前对其进行转换。请参阅以下讨论:GLSL fragment shader syntax error
【讨论】:
【参考方案2】:作为对 Mikola 回答的补充,您无需每次都查看信息日志;您可以检查您的着色器是否正确编译以及您的程序是否正确链接,如果发生错误,则仅调用 glGetShaderInfoLog
和 glGetProgramInfoLog
。
这里有一些代码可以做到这一点(在 Python 中,但翻译成 C++ 很简单):
# create your vertex shader, attach its source, etc.
glCompileShader(vertex_shader)
rc_compile = GLint()
glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, rc_compile)
if rc_compile.value == GL_FALSE: # shader compilation failed
info = create_string_buffer(1024)
glGetShaderInfoLog(vertex_shader, 1024, None, info)
glDeleteShader(vertex_shader)
raise Exception(info.value)
# do the same thing for a fragment shader and create a program to link the two
glAttachShader(program, vertex_shader)
glAttachShader(program, fragment_shader)
rc_link = GLint()
glGetProgramiv(program, GL_LINK_STATUS, rc_link)
if rc_link.value == GL_FALSE: # program link failed
info = create_string_buffer(1024)
glGetProgramInfoLog(program, 1024, None, info)
glDeleteProgram(program)
raise Exception(info.value)
【讨论】:
以上是关于为啥我的扁平着色器(来自 Lighthouse3d 教程)不起作用?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 OSX Mavericks 不能编译我的 GLSL 着色器?