OpenGL-ES(iOS) - 在渲染过程中在着色器程序对象之间切换

时间:2014-11-03 05:32:23

标签: ios opengl-es

拜托,请耐心等待。对不起,我很抱歉。

我的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()成功切换着色器?我认为它必须是非常简单的事情,但我无法弄明白。

非常感谢你的帮助。

0 个答案:

没有答案