OpenGL ES 2.0如何在iOS中使用不同的着色器程序绘制多个VBO

OpenGL ES 2.0如何在iOS中使用不同的着色器程序绘制多个VBO,ios,ios5,opengl-es,opengl-es-2.0,Ios,Ios5,Opengl Es,Opengl Es 2.0,我正在尝试破解通用的Xcode iOS OpenGL游戏模板,以绘制两个顶点缓冲区对象,并使用不同的GLSL着色器渲染它们。 我“认为”我正确地渲染了两个VBO?(因为我在通过第一个着色器程序运行两个VBO时都能看到它们)但是,我的第二个着色器似乎根本没有渲染我的第二个对象 以下是两个正方形的顶点数据: GLfloat gCubeVertexData[36] = { // Data layout for each line below is: // positionX, pos

我正在尝试破解通用的Xcode iOS OpenGL游戏模板,以绘制两个顶点缓冲区对象,并使用不同的GLSL着色器渲染它们。 我“认为”我正确地渲染了两个VBO?(因为我在通过第一个着色器程序运行两个VBO时都能看到它们)但是,我的第二个着色器似乎根本没有渲染我的第二个对象

以下是两个正方形的顶点数据:

GLfloat gCubeVertexData[36] = 
{
    // Data layout for each line below is:
    // positionX, positionY, positionZ,     normalX, normalY, normalZ,

    0.5f, 0.5f, 0.5f,          0.0f, 0.0f, 1.0f,
    -0.5f, 0.5f, 0.5f,         0.0f, 0.0f, 1.0f,
    0.5f, -0.5f, 0.5f,         0.0f, 0.0f, 1.0f,
    0.5f, -0.5f, 0.5f,         0.0f, 0.0f, 1.0f,
    -0.5f, 0.5f, 0.5f,         0.0f, 0.0f, 1.0f,
    -0.5f, -0.5f, 0.5f,        0.0f, 0.0f, 1.0f

};

GLfloat fooVertexData[36] = 
{
    // Data layout for each line below is:
    // positionX, positionY, positionZ,     normalX, normalY, normalZ

    0.5f, 0.5f, 0.5f,          0.0f, 0.0f, 1.0f,
    -0.5f, 0.5f, 0.5f,         0.0f, 0.0f, 1.0f,
    0.5f, -0.5f, 0.5f,         0.0f, 0.0f, 1.0f,
    0.5f, -0.5f, 0.5f,         0.0f, 0.0f, 1.0f,
    -0.5f, 0.5f, 0.5f,         0.0f, 0.0f, 1.0f,
    -0.5f, -0.5f, 0.5f,        0.0f, 0.0f, 1.0f
};
这里是我试图生成两个VBO并将它们绑定到数据的地方。但不确定“glBindVertexArrayOES(0)”的最终目的是什么

- (void)setupGL
{
    [EAGLContext setCurrentContext:self.context];

    [self loadShaders];

    //---- First Vertex Array Object --------
    glGenVertexArraysOES(1, &_vertexArray1);
    glGenBuffers(1, &_vertexBuffer1);   

    glBindVertexArrayOES(_vertexArray1);

    glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer1);
    glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW);

    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0));
    glEnableVertexAttribArray(GLKVertexAttribNormal);
    glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12));

    //----- Second Vertex Array Object ----------
    glGenVertexArraysOES(1, &_vertexArray2);
    glGenBuffers(1, &_vertexBuffer2);

    glBindVertexArrayOES(_vertexArray2);

    glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer2);
    glBufferData(GL_ARRAY_BUFFER, sizeof(fooVertexData), fooVertexData, GL_STATIC_DRAW);

    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0));
    glEnableVertexAttribArray(GLKVertexAttribNormal);
    glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12));

    glBindBuffer(GL_ARRAY_BUFFER,0);
    glBindVertexArrayOES(0);
}
我正在使用此更新代码设置模型视图投影矩阵的动画:

- (void)update
{
    _rotation += self.timeSinceLastUpdate * 0.2f;

    float aspect = fabsf(self.view.bounds.size.width / self.view.bounds.size.height);

    GLKMatrix4 projectionMatrix = GLKMatrix4MakeOrtho(-1.0f, 1.0f, -1.0f / aspect, 1.0f / aspect, -10.0f, 10.0f);
    GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.5f, 0.0f, 0.0f);
    modelViewMatrix = GLKMatrix4Multiply(modelViewMatrix, GLKMatrix4MakeZRotation(0.0 - _rotation));
    _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix);

    GLKMatrix4 modelViewMatrix2 = GLKMatrix4MakeTranslation(-0.5f, 0.0f, 0.0f);
    modelViewMatrix2 = GLKMatrix4Multiply(modelViewMatrix2, GLKMatrix4MakeZRotation(_rotation));
    _modelViewProjectionMatrix2 = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix2);
}
调用“_program2”着色器时,我看不到第二个正方形:

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
    glClearColor(0.65f, 0.65f, 0.65f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    glBindVertexArrayOES(_vertexArray1);
    glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer1);

    glUseProgram(_program);
    glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m);
    glDrawArrays(GL_TRIANGLES, 0, 6);

    ///////// second object and shader program:
    glBindVertexArrayOES(_vertexArray2);
    glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer2);

    glUseProgram(_program2);
    glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX2], 1, 0, _modelViewProjectionMatrix2.m);
    glDrawArrays(GL_TRIANGLES, 0, 6);

}
我基本上已经尝试复制加载第一个着色器的代码,加载第二个着色器。我怀疑我在这里可能做错了什么。。但我不确定是什么:

- (BOOL)loadShaders
{
    GLuint vertShader, fragShader, vertShader2, fragShader2;
    NSString *vertShaderPathname, *fragShaderPathname, *vertShaderPathname2, *fragShaderPathname2;

    // Create shader program.
    _program = glCreateProgram();


    // Create and compile vertex shader.
    vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"];
    if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) {
        NSLog(@"Failed to compile vertex shader");
        return NO;
    }

    // Create and compile fragment shader.
    fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"];
    if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) {
        NSLog(@"Failed to compile fragment shader");
        return NO;
    }

    // Attach vertex shader to program.
    glAttachShader(_program, vertShader);

    // Attach fragment shader to program.
    glAttachShader(_program, fragShader);

    // Bind attribute locations.
    // This needs to be done prior to linking.
    glBindAttribLocation(_program, ATTRIB_VERTEX, "position");

    // Link program.
    if (![self linkProgram:_program]) {
        NSLog(@"Failed to link program: %d", _program);

        if (vertShader) {
            glDeleteShader(vertShader);
            vertShader = 0;
        }
        if (fragShader) {
            glDeleteShader(fragShader);
            fragShader = 0;
        }
        if (_program) {
            glDeleteProgram(_program);
            _program = 0;
        }

        return NO;
    }

    // Get uniform locations.
    uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix");

    // Release vertex and fragment shaders.
    if (vertShader) {
        glDetachShader(_program, vertShader);
        glDeleteShader(vertShader);
    }
    if (fragShader) {
        glDetachShader(_program, fragShader);
        glDeleteShader(fragShader);
    }


    ///////////////// the second shader:

    _program2 = glCreateProgram();

    vertShaderPathname2 = [[NSBundle mainBundle] pathForResource:@"Shader2" ofType:@"vsh"];
    if (![self compileShader:&vertShader2 type:GL_VERTEX_SHADER file:vertShaderPathname2]) {
        NSLog(@"Failed to compile vertex shader2");
        return NO;
    }

    fragShaderPathname2 = [[NSBundle mainBundle] pathForResource:@"Shader2" ofType:@"fsh"];
    if (![self compileShader:&fragShader2 type:GL_FRAGMENT_SHADER file:fragShaderPathname2]) {
        NSLog(@"Failed to compile fragment shader2");
        return NO;
    }

        glAttachShader(_program2, vertShader2);
        glAttachShader(_program2, fragShader2);

        glBindAttribLocation(_program2, ATTRIB_VERTEX2, "position2");

    if (![self linkProgram:_program2]) {
        NSLog(@"Failed to link program: %d", _program2);

        if (vertShader2) {
            glDeleteShader(vertShader2);
            vertShader2 = 0;
        }
        if (fragShader2) {
            glDeleteShader(fragShader2);
            fragShader2 = 0;
        }
        if (_program2) {
            glDeleteProgram(_program2);
            _program2 = 0;
        }

        return NO;
    }

        uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX2] = glGetUniformLocation(_program2, "modelViewProjectionMatrix2");
    if (vertShader2) {
        glDetachShader(_program2, vertShader2);
        glDeleteShader(vertShader2);
    }
    if (fragShader2) {
        glDetachShader(_program2, fragShader2);
        glDeleteShader(fragShader2);
    }    



    return YES;
}

- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file
{
    GLint status;
    const GLchar *source;

    source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String];
    if (!source) {
        NSLog(@"Failed to load vertex shader");
        return NO;
    }

    *shader = glCreateShader(type);
    glShaderSource(*shader, 1, &source, NULL);
    glCompileShader(*shader);

#if defined(DEBUG)
    GLint logLength;
    glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength);
    if (logLength > 0) {
        GLchar *log = (GLchar *)malloc(logLength);
        glGetShaderInfoLog(*shader, logLength, &logLength, log);
        NSLog(@"Shader compile log:\n%s", log);
        free(log);
    }
#endif

    glGetShaderiv(*shader, GL_COMPILE_STATUS, &status);
    if (status == 0) {
        glDeleteShader(*shader);
        return NO;
    }

    return YES;
}

- (BOOL)linkProgram:(GLuint)prog
{
    GLint status;
    glLinkProgram(prog);

#if defined(DEBUG)
    GLint logLength;
    glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength);
    if (logLength > 0) {
        GLchar *log = (GLchar *)malloc(logLength);
        glGetProgramInfoLog(prog, logLength, &logLength, log);
        NSLog(@"Program link log:\n%s", log);
        free(log);
    }
#endif

    glGetProgramiv(prog, GL_LINK_STATUS, &status);
    if (status == 0) {
        return NO;
    }

    return YES;
}

- (BOOL)validateProgram:(GLuint)prog
{
    GLint logLength, status;

    glValidateProgram(prog);
    glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength);
    if (logLength > 0) {
        GLchar *log = (GLchar *)malloc(logLength);
        glGetProgramInfoLog(prog, logLength, &logLength, log);
        NSLog(@"Program validate log:\n%s", log);
        free(log);
    }

    glGetProgramiv(prog, GL_VALIDATE_STATUS, &status);
    if (status == 0) {
        return NO;
    }

    return YES;
}
我的垂直着色器和片段着色器很简单:

// vert shader1:
attribute vec4 position;
uniform mat4 modelViewProjectionMatrix;

void main()
{
    gl_Position = modelViewProjectionMatrix * position;
}


// vert shader2:
attribute vec4 position2;
uniform mat4 modelViewProjectionMatrix2;

void main()
{
    gl_Position = modelViewProjectionMatrix2 * position2;
}


// frag shader(s):
void main()
{
    gl_FragColor = vec4(0.12,0.32,0.54,1.0);
}

使用OpenGL ES需要记住的最重要的一点是,您正在OOP语言中使用过程语言

一次只能将一个顶点数组绑定到顶点缓冲区

将两个顶点数组逐个绑定到VBO,然后应用变换,只会变换附加到VBO的最后一个顶点数组


在主循环中,必须遍历顶点数组列表。对于每个顶点数组,将其绑定到VBO,然后执行任何转换。

主要问题是我在哪里绑定了第二个顶点着色器的“位置”属性位置。我在枚举中使用了一个“单独的”ATTRIB_VERTEX2。一旦我将“位置”属性位置绑定到ATTRIB_顶点,我就能够在应用其他着色器程序的情况下看到第二个VBO。。。以下是为有相同问题的人整理的代码:

// Uniform index.
enum
{
    UNIFORM_MODELVIEWPROJECTION_MATRIX,
    UNIFORM_MODELVIEWPROJECTION_MATRIX2,    
    NUM_UNIFORMS
};
GLint uniforms[NUM_UNIFORMS];

// Attribute index.
enum
{
    ATTRIB_VERTEX,
    NUM_ATTRIBUTES
};

GLfloat square1Data[18] = 
{
    // Data layout for each line below is:
    // positionX, positionY, positionZ
    
    0.5f, 0.5f, 0.5f,  
    -0.5f, 0.5f, 0.5f, 
    0.5f, -0.5f, 0.5f, 
    0.5f, -0.5f, 0.5f, 
    -0.5f, 0.5f, 0.5f, 
    -0.5f, -0.5f, 0.5f
    
};

GLfloat square2Data[18] = 
{
    // Data layout for each line below is:
    // positionX, positionY, positionZ
    
    0.5f, 0.5f, 0.5f,   
    -0.5f, 0.5f, 0.5f,  
    0.5f, -0.5f, 0.5f,  
    0.5f, -0.5f, 0.5f,  
    -0.5f, 0.5f, 0.5f,  
    -0.5f, -0.5f, 0.5f
};

- (void)setupGL
{
    [EAGLContext setCurrentContext:self.context];
    
    [self loadShaders];
    
    //---- First Vertex Array Object --------
    glGenVertexArraysOES(1, &_vertexArray1);
    glGenBuffers(1, &_vertexBuffer1);   
    
    glBindVertexArrayOES(_vertexArray1);
    
    glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer1);
    glBufferData(GL_ARRAY_BUFFER, sizeof(square1Data), square1Data, GL_STATIC_DRAW);
    
    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 12, BUFFER_OFFSET(0));
//    glEnableVertexAttribArray(GLKVertexAttribNormal);
//    glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12));
    
    //----- Second Vertex Array Object ----------
    glGenBuffers(1, &_vertexBuffer2);
        
    glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer2);
    glBufferData(GL_ARRAY_BUFFER, sizeof(square2Data), square2Data, GL_STATIC_DRAW);
    
    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 12, BUFFER_OFFSET(0));
//    glEnableVertexAttribArray(GLKVertexAttribNormal);
//    glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12));
    
    glBindBuffer(GL_ARRAY_BUFFER,0);
    glBindVertexArrayOES(0);
}

- (void)update
{
    _rotation += self.timeSinceLastUpdate * 0.2f;
    
    float aspect = fabsf(self.view.bounds.size.width / self.view.bounds.size.height);
    
    GLKMatrix4 projectionMatrix = GLKMatrix4MakeOrtho(-1.0f, 1.0f, -1.0f / aspect, 1.0f / aspect, -10.0f, 10.0f);
            
    GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.5f, 0.0f, 0.0f);
    modelViewMatrix = GLKMatrix4Multiply(modelViewMatrix, GLKMatrix4MakeZRotation(0.0 - _rotation));
    _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix);
            
    GLKMatrix4 modelViewMatrix2 = GLKMatrix4MakeTranslation(-0.5f, 0.0f, 0.0f);
    modelViewMatrix2 = GLKMatrix4Multiply(modelViewMatrix2, GLKMatrix4MakeZRotation(_rotation));
    _modelViewProjectionMatrix2 = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix2);
    
}

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
    glClearColor(0.65f, 0.65f, 0.65f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    
    glBindVertexArrayOES(_vertexArray1);
        
    glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer1);
    glUseProgram(_program);
    glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m);
    glDrawArrays(GL_TRIANGLES, 0, 6);
    
    ///////// second VBO and shader program:
    glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer2);
    glUseProgram(_program2);
    glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX2], 1, 0, _modelViewProjectionMatrix2.m);
    glDrawArrays(GL_TRIANGLES, 0, 6); 
}

- (BOOL)loadShaders
{
    GLuint vertShader, fragShader, vertShader2, fragShader2;
    NSString *vertShaderPathname, *fragShaderPathname, *vertShaderPathname2, *fragShaderPathname2;
    
    // Create shader program.
    _program = glCreateProgram();
    _program2 = glCreateProgram(); 

    
    // Create and compile vertex shader.
    vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"];
    if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) {
        NSLog(@"Failed to compile vertex shader");
        return NO;
    }
    
    // Create and compile fragment shader.
    fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"];
    if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) {
        NSLog(@"Failed to compile fragment shader");
        return NO;
    }
    
    // Create and compile vertex shader.
    vertShaderPathname2 = [[NSBundle mainBundle] pathForResource:@"Shader2" ofType:@"vsh"];
    if (![self compileShader:&vertShader2 type:GL_VERTEX_SHADER file:vertShaderPathname2]) {
        NSLog(@"Failed to compile vertex shader");
        return NO;
    }
    
    // Create and compile fragment shader.
    fragShaderPathname2 = [[NSBundle mainBundle] pathForResource:@"Shader2" ofType:@"fsh"];
    if (![self compileShader:&fragShader2 type:GL_FRAGMENT_SHADER file:fragShaderPathname2]) {
        NSLog(@"Failed to compile fragment shader");
        return NO;
    }

    // Attach vertex shader to program.
    glAttachShader(_program, vertShader);
    glAttachShader(_program2, vertShader2);

    
    // Attach fragment shader to program.
    glAttachShader(_program, fragShader);
    glAttachShader(_program2, fragShader2);
    
    // Bind attribute locations.
    // This needs to be done prior to linking.
    glBindAttribLocation(_program, ATTRIB_VERTEX, "position");
    glBindAttribLocation(_program2, ATTRIB_VERTEX, "position");

    
    // Link program.
    if (![self linkProgram:_program]) {
        NSLog(@"Failed to link program: %d", _program);
        
        if (vertShader) {
            glDeleteShader(vertShader);
            vertShader = 0;
        }
        if (fragShader) {
            glDeleteShader(fragShader);
            fragShader = 0;
        }
        if (_program) {
            glDeleteProgram(_program);
            _program = 0;
        }
        
        return NO;
    }
    if (![self linkProgram:_program2]) {
        NSLog(@"Failed to link program: %d", _program2);
        
        if (vertShader2) {
            glDeleteShader(vertShader2);
            vertShader2 = 0;
        }
        if (fragShader2) {
            glDeleteShader(fragShader2);
            fragShader2 = 0;
        }
        if (_program2) {
            glDeleteProgram(_program2);
            _program2 = 0;
        }
        
        return NO;
    }    
    
    // Get uniform locations.
    uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix");
    uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX2] = glGetUniformLocation(_program2, "modelViewProjectionMatrix2");
    
    // Release vertex and fragment shaders.
    if (vertShader) {
        glDetachShader(_program, vertShader);
        glDeleteShader(vertShader);
    }
    if (fragShader) {
        glDetachShader(_program, fragShader);
        glDeleteShader(fragShader);
    }
    
    if (vertShader2) {
        glDetachShader(_program2, vertShader2);
        glDeleteShader(vertShader2);
    }
    if (fragShader2) {
        glDetachShader(_program2, fragShader2);
        glDeleteShader(fragShader2);
    }    
    
    return YES;
}

OES后缀未在OpenGL ES 2中使用。0@MatisseVerDuyn这是误导。这些函数不在基本OpenGL ES 2规范中,因此它们在默认情况下没有定义,但它们作为扩展提供(由支持的设备提供)。感谢这些指针。不幸的是,我还是被卡住了。我是否可以将两个顶点缓冲区对象绑定到单独的顶点阵列,以便使用不同的片段着色器程序渲染它们?首先,您应该尝试更改方法,使其仅使用一个VBO。其次,运行不同的着色器程序不需要不同的VBO。编译两个单独的程序(需要顶点和片段着色器对),然后调用
glUseProgram(…)当你需要在程序之间切换时。我看到两个正方形通过第一个着色器程序完美地动画,但通过第二个着色器程序没有动画。编译第二个着色器程序时,我没有收到任何错误,第二个着色器程序采用的格式与第一个几乎完全相同(只是片段程序中应用了不同的颜色)。有没有办法在两个不同的着色器中使用相同的一致性,就像属性ATTRIB_VERTEX一样?@rraallvv我不能肯定,我不知道。但我的猜测是属性在着色器程序之间失去了上下文(即超出范围)。