4

一般的な Xcode iOS OpenGL ゲーム テンプレートをハックして、2 つの頂点バッファー オブジェクトを描画し、異なる GLSL シェーダーでレンダリングしようとしています。2 つの VBO を正しくレンダリングしていると思いますか? (最初のシェーダー プログラムで両方の VBO を実行すると両方が表示されるため)ただし、2 番目のシェーダーは 2 番目のオブジェクトをまったくレンダリングしていないようです。

2 つの正方形の頂点データは次のとおりです。

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
};

ここでは、2 つの 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」シェーダーを呼び出すと、2 番目の正方形が表示されません。

- (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);

}

基本的に、最初のシェーダーをロードするコードを複製して、2 番目のシェーダーをロードしようとしました。私はここで何か間違ったことをしているかもしれないと思う..しかし、何がわからない:

- (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);
}
4

2 に答える 2

2

OpenGL ES で覚えておくべき最も重要なことは、OOP 言語内で手続き型言語を使用していることです。

一度に1 つの頂点配列のみを頂点バッファーにバインドできます。

2 つの頂点配列を VBO に順番にバインドしてから変換を適用すると、VBO にアタッチされた最後の頂点配列のみが変換されます。

メイン ループでは、頂点配列のリストを反復処理する必要があります。各頂点配列を VBO にバインドし、変換を実行します。

于 2012-04-10T18:10:19.723 に答える
2

主な問題は、2 番目の頂点シェーダーの「位置」属性の場所をバインドする場所でした。列挙型で「別の」ATTRIB_VERTEX2を使用していました。「位置」属性の場所を ATTRIB_VERTEX にバインドすると、他のシェーダー プログラムが適用された 2 番目の 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;
}
于 2012-04-11T16:25:40.410 に答える