拜托,请耐心等待。对不起,我很抱歉。
我的iPad上有一个立方体,球体和圆柱体的3D场景。我想将纹理应用于立方体,将颜色应用于球体,以及将纹理和颜色应用于圆柱体。
所以,我的解决方案是有3个不同的着色器程序来处理这3个案例,然后在渲染过程中,我使用glUseProgram()在渲染我的立方体/球体/柱面之前切换到适当的着色器程序。
然而,问题是glUseProgram()在渲染过程中似乎不起作用。
在下面的renderScene()函数中,如果我对所有3个对象使用相同的着色器句柄,那么所有3个对象都将按预期呈现,没问题。但是,当我将它们混合起来时,只会渲染使用与最后一个对象相同的着色器句柄的对象。
例如:
draw(cube, m_programHandleTexture); // showing
draw(sphere, m_programHandleColor); // not showing
draw(cylinder, m_programHandleTexture); // showing - NOTE: last object rendered
另一个例子:
draw(cube, m_programHandleTexture); // not showing
draw(sphere, m_programHandleColor); // showing
draw(cylinder, m_programHandleColor); // showing - NOTE: last object rendered
所以,我认为在调用glUseProgram()来切换着色器程序之前,我必须遗漏一些非常简单的东西。我一直在谷歌上搜索,并尝试移动函数调用,但到目前为止我还没有成功。
我错过了什么?
请参阅下面的我的代码段。再次,我很抱歉这篇长篇文章。我尽量使信息尽可能简洁。
首先,init函数:
-(id) initWithFrame:
{
...
// See below for compileShader() and createProgramHandle() definitions
m_vertexShader = [self compileShader:@"SimpleVertex" withType:GL_VERTEX_SHADER];
m_fragmentShader = [self compileShader:@"SimpleFragment" withType:GL_FRAGMENT_SHADER];
m_fragmentShaderColor = [self compileShader:@"SimpleFragmentColorOnly" withType:GL_FRAGMENT_SHADER];
m_fragmentShaderTexture = [self compileShader:@"SimpleFragmentTexOnly" withType:GL_FRAGMENT_SHADER];
m_programHandle = [self createProgramHandle :m_vertexShader :m_fragmentShader];
m_programHandleColor = [self createProgramHandle :m_vertexShader :m_fragmentShaderColor];
m_programHandleTexture = [self createProgramHandle :m_vertexShader :m_fragmentShaderTexture];
...
}
现在,渲染功能:(这是发生问题的地方)
-(void) renderScene
{
glClearColor(0, 0, 1, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
...
[self draw :Cube :m_programHandleTexture]; // Not showing
[self draw :Sphere :m_programHandleColor]; // Not showing
[self draw :Cylinder :m_programHandle]; // Showing
...
}
draw()函数:
-(void) draw :(object)obj :(GLuint)programHandle
{
...
glUseProgram(programHandle);
//Apply texture on object
glVertexAttribPointer(m_texCoordSlot, 2, GL_FLOAT, GL_FALSE, stride, (GLvoid*) (sizeof(float) * 7));
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, bufferedTexture);
glUniform1i(m_textureUniform, 0);
...
glDrawArrays();
}
compileShader()函数:
- (GLuint)compileShader :(NSString*)shaderSource withType:(GLenum)shaderType
{
...
GLuint shaderHandle = glCreateShader(shaderType);
glShaderSource(shaderHandle, 1, &shaderStringUTF8, &shaderStringLength);
glCompileShader(shaderHandle);
...
return shaderHandle;
}
createProgramHandle()函数:
- (GLuint) createProgramHandle :(GLuint)vertexShader :(GLuint)fragmentShader;
{
GLuint programHandle = glCreateProgram();
glAttachShader(programHandle, vertexShader);
glAttachShader(programHandle, fragmentShader);
glLinkProgram(programHandle);
...
glDetachShader(programHandle, fragmentShader); // Doesn't really make any difference
glDetachShader(programHandle, vertexShader); // Same as above
glUseProgram(programHandle);
...
return programHandle;
}
以下是我的片段着色器来源:
SimpleFragment.glsl
void main(void)
{
gl_FragColor = texture2D(Texture, TexCoordOut) * (DestinationColor + vec4(1.0, 1.0, 1.0, 1.0));
}
SimpleFragmentColorOnly.glsl
void main(void)
{
gl_FragColor = DestinationColor;
}
SimpleFragmentTextureOnly.glsl
void main(void)
{
gl_FragColor = texture2D(Texture, TexCoordOut);
}
那么,我错过了什么?我是否需要做任何其他事情(清除缓冲区,分离着色器等)才能使用glUseProgram()成功切换着色器?我认为它必须是非常简单的事情,但我无法弄明白。
非常感谢你的帮助。