OpenGL ES 3.0 glEnableVertexAttribArray的作用

本文檔討論glEnableVertexAttribArray的作用及調(diào)用位置問題。

對于OpenGL ES 3.0,可使用至少16個頂點屬性,可查詢具體實現(xiàn)的支持數(shù)量。

GLint maxVertexAttribs;
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);

默認情況下,出于性能考慮,所有頂點著色器的屬性(Attribute)變量都是關(guān)閉的,意味著數(shù)據(jù)在著色器端是不可見的,哪怕數(shù)據(jù)已經(jīng)上傳到GPU,由glEnableVertexAttribArray啟用指定屬性,才可在頂點著色器中訪問逐頂點的屬性數(shù)據(jù)。glVertexAttribPointer或VBO只是建立CPU和GPU之間的邏輯連接,從而實現(xiàn)了CPU數(shù)據(jù)上傳至GPU。但是,數(shù)據(jù)在GPU端是否可見,即,著色器能否讀取到數(shù)據(jù),由是否啟用了對應(yīng)的屬性決定,這就是glEnableVertexAttribArray的功能,允許頂點著色器讀取GPU(服務(wù)器端)數(shù)據(jù)。

那么,glEnableVertexAttribArray應(yīng)該在glVertexAttribPointer之前還是之后調(diào)用?答案是都可以,只要在繪圖調(diào)用(glDraw*系列函數(shù))前調(diào)用即可。

下面示例代碼驗證了不用glEnableVertexAttribArray對應(yīng)屬性時繪制內(nèi)容為清除緩沖區(qū)顏色。在取消glEnableVertexAttribArray(0);注釋后,得到正常的繪制結(jié)果。

正常情況
#import <UIKit/UIKit.h>
#import <OpenGLES/ES3/gl.h>

@interface MyGLView : UIView

@end

@implementation MyGLView

+ (Class)layerClass {
    return [CAEAGLLayer class];
}

- (void)layoutSubviews {
    [super layoutSubviews];
    
    EAGLContext *context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
    [EAGLContext setCurrentContext:context];
    
    GLuint renderbuffer;
    glGenRenderbuffers(1, &renderbuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
    [context renderbufferStorage:GL_RENDERBUFFER fromDrawable:self.layer];
    
    GLuint framebuffer;
    glGenFramebuffers(1, &framebuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
    
    NSString *vertexShaderString = @"#version 300 es  \n"
    "layout (location = 0) in vec4 a_position;  \n"
    "void main() {  \n"
    "gl_Position = a_position;  \n"
    "gl_PointSize = 20.0;}";
    NSString *fragmentShaderString = @"#version 300 es  \n"
    "precision lowp float;  \n"
    "out vec4 o_color;  \n"
    "void main() {  \n"
    "o_color = vec4(1.0, 0, 1.0, 1.0);}";
    
    GLint vertexShader = [self compileShaderWithString:vertexShaderString withType:GL_VERTEX_SHADER];
    GLint fragmentShader = [self compileShaderWithString:fragmentShaderString withType:GL_FRAGMENT_SHADER];
    
    GLint program = glCreateProgram();
    glAttachShader(program, vertexShader);
    glAttachShader(program, fragmentShader);
    glLinkProgram(program);
    GLint linkStatus;
    glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
    if (linkStatus == GL_FALSE) {
        GLint length;
        glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
        if (length > 0) {
            GLchar *infolog = (GLchar *)malloc(sizeof(GLchar) * length);
            glGetProgramInfoLog(program, length, NULL, infolog);
            fprintf(stderr, "link error = %s", infolog);
            if (infolog) {
                free(infolog);
            }
        }
    }
    glValidateProgram(program);
    glUseProgram(program);
    
    glClearColor(1.0, 1.0, 1.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT);
    CGRect frame = [UIScreen mainScreen].bounds;
    glViewport(0, 0, frame.size.width * self.layer.contentsScale, frame.size.height * self.layer.contentsScale);
    
    GLfloat vertexs[] = {
        -0.5f,  0.5f, 0.0f,  // Position 0
        -0.5f, -0.5f, 0.0f,  // Position 1
    };
    
    glLineWidth(20);
    
    //glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertexs);
    
    glDrawArrays(GL_LINES, 0, 2/* 1 line = 2 points */);

    [context presentRenderbuffer:GL_RENDERBUFFER];
}

- (GLuint)compileShaderWithString:(NSString *)content withType:(GLenum)type {
    GLuint shader;
    const char *shaderString = content.UTF8String;
    shader = glCreateShader(type);
    glShaderSource(shader, 1, &shaderString, NULL);
    glCompileShader(shader);
    GLint status;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
    if (status == GL_FALSE) {
        GLint length;
        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
        if (length > 0) {
            GLchar *infolog = (GLchar *)malloc(sizeof(GLchar) * length);
            glGetShaderInfoLog(shader, length, NULL, infolog);
            fprintf(stderr, "%s -> compile error = %s", type == GL_VERTEX_SHADER ? "vertex shader" : "fragment shader", infolog);
            if (infolog) {
                free(infolog);
            }
        }
    }
    return shader;
}

@end
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容