ios - OpenGL ES 2.0 如何在iOS中用不同的Shader程序绘制多个VBO

标签 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, 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 并将它们绑定(bind)到数据的地方。不确定最后“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);
}

我正在使用此更新代码来制作模型- View -投影矩阵的动画:

- (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”着色器时,我没有看到第二个方 block :

- (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 语言中使用过程语言。

您一次只能将一个顶点数组绑定(bind)到顶点缓冲区。

将两个顶点数组一个接一个地绑定(bind)到 VBO,然后应用变换,只会变换附加到 VBO 的最后一个顶点数组。

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

关于ios - OpenGL ES 2.0 如何在iOS中用不同的Shader程序绘制多个VBO,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10067447/

相关文章:

ios - 多个 UNUserNotifications 未触发

ios5 - 如何在 xcode 4.3 中使用 GDataXML 更改 xml 标记的值?

iphone - iOS 5 是否以不同方式处理低内存情况?

java - 房间内的光源出乎意料地起作用

ios - 为什么 View 中的所有 View 都将 userInteractionEnabled 设置为 NO

javascript - 如何使用 monaca 触发对输入的关注?

ios - Flickr照片管理器中的JSON警告

iphone - 如何在 iPhone 上生成良好的、不变的 UDID

javascript - WebGL2 texelFetch'ing 纹理意外结果

Android queueEvent(new Runnable()) 如果我有多个线程托管渲染器怎么办?