OpenGL 着色器问题
我有一个正在运行的程序,它使用 glVertexPointer、glNormalPointer 等来绘制大量元素。其运行速度约为 30 FPS。现在我已经达到了这样的程度:集成着色器将是一个可行的选择(每个顶点需要有一个基于特定类计算的颜色)。 1. 现在我的第一个问题是使用着色器会对我的 FPS 产生多大影响?我当前的实现(我认为 99.99% 至少在某些方面存在缺陷,将在下面发布代码)将 FPS 大幅降至 3 FPS。如果这种 FPS 下降是正常的,那么就没有必要为此烦恼。
现在来看一些代码。我的着色器看起来像:
vertexsource = """
attribute vec3 position;
attribute vec3 normal;
varying vec3 norm;
varying vec3 color_out;
uniform vec3 color_in;
void main()
{
gl_Position = gl_ModelViewProjectionMatrix * vec4( position,1);
color_out = color_in;
norm = normal;
}"""
fragmentsource = """
varying vec3 norm;
varying vec3 color_out;
void main()
{
gl_FragColor = vec4( color_out, 1.0);
}"""
vshader = compileShader( vertexsource, GL_VERTEX_SHADER )
fshader = compileShader( fragmentsource, GL_FRAGMENT_SHADER )
program = compileProgram( vshader, fshader )
color = glGetUniformLocation( program, "color_in")
normal = glGetAttribLocation( program, "normal" )
position = glGetAttribLocation( program, "position" )
glUseProgram( program )
glUniform3fv( color, 3, (0,0,1) )
return position, normal
所以我返回位置和法线,因为稍后我将使用它们来传递实际的顶点和法线。从这里我有一个问题。如果没有着色器,我只需使用 VertexPointer 和 NormalPointer 传递法线和顶点数组,然后 OpenGL 处理其余部分。 2. 我读到着色器内置了 gl_Vertex 和 gl_Normal 属性。如何将值从我的 VBO 传递给这些属性?正如您所看到的,目前我正在将顶点位置传递给属性位置,并将法线传递给法线,但我没有对法线做任何事情,因为我不知道做什么。
绘图是这样完成的:
glEnableVertexAttribArray( self.position )
glEnableVertexAttribArray( self.normal )
glBindBufferARB(GL_ARRAY_BUFFER_ARB, self.bufferVertices)
glVertexAttribPointer( self.position, 3, GL_FLOAT, GL_FALSE, 0, None )
glEnableClientState(GL_NORMAL_ARRAY);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, self.bufferNormals)
glVertexAttribPointer( self.normal, 3, GL_FLOAT, GL_FALSE, 0, None )
glDrawElements(GL_TRIANGLES, len(self.triangles) , GL_UNSIGNED_SHORT, ADT.voidDataPointer(self.triangles))
这里 self.bufferVertices、self.bufferNormals 是包含我的顶点和法线的 VBO。 self.triangles 索引数组。到目前为止,它绘制了正确的索引,但如上所述,我的 FPS 非常低。
- 这个绘图顺序正确吗?还有其他启用时可能与着色器冲突的东西吗? (
GL_LIGHTNING
、GL_DEPTH_TEST
等)
I have a running program that uses glVertexPointer, glNormalPointer etc to draw a large number of elements. This works around 30 FPS. Now I've reach a point where integrating shaders would be a viable option (each vertex need to have a color calculated based on a specific class).
1. Now my first question is how much would using shaders affect my FPS ? My current implementation (which I'm 99.99% is flawed in at least some way, will post code below) drops the FPS drastically to 3 FPS. If this kind of drop in FPS is normal there is no point to struggle with this.
Now for some code. My shaders look like:
vertexsource = """
attribute vec3 position;
attribute vec3 normal;
varying vec3 norm;
varying vec3 color_out;
uniform vec3 color_in;
void main()
{
gl_Position = gl_ModelViewProjectionMatrix * vec4( position,1);
color_out = color_in;
norm = normal;
}"""
fragmentsource = """
varying vec3 norm;
varying vec3 color_out;
void main()
{
gl_FragColor = vec4( color_out, 1.0);
}"""
vshader = compileShader( vertexsource, GL_VERTEX_SHADER )
fshader = compileShader( fragmentsource, GL_FRAGMENT_SHADER )
program = compileProgram( vshader, fshader )
color = glGetUniformLocation( program, "color_in")
normal = glGetAttribLocation( program, "normal" )
position = glGetAttribLocation( program, "position" )
glUseProgram( program )
glUniform3fv( color, 3, (0,0,1) )
return position, normal
So I return position and normal because I will use them later to pass the actual vertices and normals. Right from here I have a question. Without shaders I just pass the normals and vertices arrays using VertexPointer and NormalPointer and OpenGL handles the rest.
2. I've read that shaders have gl_Vertex and gl_Normal attributes build in. How do I pass the values from my VBO's to these ? As you can see currently I'm passing my vertexes position to the attribute position and my normals to normal, but I'm not doing anything with the normals as I don't know what.
The drawing is done like this:
glEnableVertexAttribArray( self.position )
glEnableVertexAttribArray( self.normal )
glBindBufferARB(GL_ARRAY_BUFFER_ARB, self.bufferVertices)
glVertexAttribPointer( self.position, 3, GL_FLOAT, GL_FALSE, 0, None )
glEnableClientState(GL_NORMAL_ARRAY);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, self.bufferNormals)
glVertexAttribPointer( self.normal, 3, GL_FLOAT, GL_FALSE, 0, None )
glDrawElements(GL_TRIANGLES, len(self.triangles) , GL_UNSIGNED_SHORT, ADT.voidDataPointer(self.triangles))
Here self.bufferVertices, self.bufferNormals are VBO's containg my vertices and normals. self.triangles indices array. It draws the correct indices so far but my FPS is very low as mentioned.
- Is this drawing sequence correct? Also are there other things that when enabled could conflict with the shader? (
GL_LIGHTNING
,GL_DEPTH_TEST
and so on)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
每次调用该函数(第一个代码)时是否都会编译着色器?
Are you compiling your shader each time you call that function (the first code)?