【问题标题】:Need assistance with simple OpenGL ES 2.0 code需要简单 OpenGL ES 2.0 代码的帮助
【发布时间】:2012-03-16 00:31:33
【问题描述】:

我完全是 OpenGL 的白痴,我不知道为什么我的代码不工作,只有清晰的颜色显示。我正在尝试在 iOS 上设置一些简单的渲染。请问有人可以帮我吗?

我的主要场景代码是:

//
//  Scene.m

#import "Scene.h"

GLfloat vertices[] = {
    0.0, 0.0,
    1.0, 0.0,
    0.0, 1.0,
    1.0, 1.0
};

@implementation Scene
+(Class)layerClass {
    return [CAEAGLLayer class];
}
- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        CAEAGLLayer *glLayer = (CAEAGLLayer *)self.layer;
        glLayer.opaque = YES;
        glLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:FALSE], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];

        context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
        if (!context) {
            NSLog(@"Failed to create 2.0 context");
            exit(1);
        }

        [EAGLContext setCurrentContext:context];


        GLuint framebuffer, colorRenderbuffer;
        glGenFramebuffers(1, &framebuffer);
        glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
        glGenRenderbuffers(1, &colorRenderbuffer);
        glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
        [context renderbufferStorage:GL_RENDERBUFFER fromDrawable:glLayer];
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRenderbuffer);

        GLuint vbo;
        glGenBuffers(1, &vbo);
        glBindBuffer(GL_ARRAY_BUFFER, vbo);
        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

        GLuint program = [self loadShaders:@"Test.vp" frag:@"Test.fp"];
        positionIndex = glGetAttribLocation(program, "position");
        mvpIndex = glGetUniformLocation(program, "mvp");
        glLinkProgram(program); //added this
        GLint param;
        glGetProgramiv(program, GL_LINK_STATUS, &param);
        if (param == GL_FALSE) {
            NSLog(@"Failed to link the program");
            exit(1);
        }
        glUseProgram(program);

        CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(render:)];
        [displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
    }
    return self;
}
-(void)render:(CADisplayLink *)_displayLink {
    glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    glEnableVertexAttribArray(positionIndex);
    glVertexAttribPointer(positionIndex, 2, GL_FLOAT, GL_FALSE, 0, (GLvoid *)0);
    GLfloat mvp[] = {
        1, 0, 0, 0,
        0, 1, 0, 0,
        0, 0, 1, 0,
        0, 0, 0, 1
    };
    glUniformMatrix4fv(mvpIndex, 1, GL_FALSE, mvp);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    [context presentRenderbuffer:GL_RENDERBUFFER];

    glDisableVertexAttribArray(positionIndex);
}
-(GLuint)loadShaders:(NSString *)vertShader frag:(NSString *)fragShader {
    NSString *vertPath = [[NSBundle mainBundle] pathForResource:[vertShader stringByDeletingPathExtension] ofType:@"vp"];
    NSString *fragPath = [[NSBundle mainBundle] pathForResource:[fragShader stringByDeletingPathExtension] ofType:@"fp"];

    if (!vertPath || !fragPath) {
        NSLog(@"Failed to find paths of shaders");
        exit(1);
    }

    NSError *error;
    const GLchar* vertSource = [[NSString stringWithContentsOfFile:vertPath encoding:NSUTF8StringEncoding error:&error] UTF8String];
    const GLchar* fragSource = [[NSString stringWithContentsOfFile:fragPath encoding:NSUTF8StringEncoding error:&error] UTF8String];

    if (!vertSource || !fragSource) {
        NSLog(@"Faild to load shader sources\n%@", [error localizedDescription]);
        exit(1);
    }

    GLuint vert, frag;
    vert = glCreateShader(GL_VERTEX_SHADER);
    frag = glCreateShader(GL_FRAGMENT_SHADER);

    GLint length = strlen(vertSource);
    glShaderSource(vert, 1, &vertSource, &length);
    length = strlen(fragSource);
    glShaderSource(frag, 1, &fragSource, &length);

    glCompileShader(vert);
    glCompileShader(frag);

    GLint success;
    glGetShaderiv(vert, GL_COMPILE_STATUS, &success);
    if (success == GL_FALSE) {
        GLchar messages[256];
        glGetShaderInfoLog(vert, sizeof(messages), 0, &messages[0]);
        NSLog(@"Failed to compile vertex shader\n%@", [NSString stringWithUTF8String:messages]);
        exit(1);
    }

    glGetShaderiv(frag, GL_COMPILE_STATUS, &success);
    if (success == GL_FALSE) {
        GLchar messages[256];
        glGetShaderInfoLog(frag, sizeof(messages), 0, &messages[0]);
        NSLog(@"Failed to compile fragment shader\n%@", [NSString stringWithUTF8String:messages]);
        exit(1);
    }

    GLuint prog = glCreateProgram();
    glAttachShader(prog, vert);
    glAttachShader(prog, frag);

    //Removed glLinkProgram()

    return prog;
}
@end

着色器代码为:

attribute vec2 position;
uniform mat4 mvp;

void main(void) {
    gl_Position = mvp * vec4(position.xy, -1.0, 1.0);
}

void main() {
    gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
}

提前谢谢你

【问题讨论】:

  • 在调用 gl 函数后尝试使用glGetError。首先你应该在glUseProgramglDrawArrays 之后尝试一下。等待结果。

标签: objective-c c ios opengl-es opengl-es-2.0


【解决方案1】:
glEnableVertexAttribArray(positionIndex);
glVertexAttribPointer(positionIndex, 2, GL_FLOAT, GL_FALSE, 0, vertices);

此行不正确:

glDisableVertexAttribArray(positionIndex);

在使用之前不要禁用它,否则你会丢失它

另外,由于您使用 vbo 作为顶点,您不需要这样做:

glVertexAttribPointer(positionIndex, 2, GL_FLOAT, GL_FALSE, 0, vertices);

只需切换到这个:

glVertexAttribPointer(positionIndex, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);

您有一个绑定到 GPU 的 vbo,它将使用该缓冲区进行绘制。使用glVertexAttribPointer 定义到 vbo 的偏移量,它将找到给定属性的第一个元素。

@kibab 我对 vbo 的建议是正确的。

由于他的属性没有绑定到他的着色器,他收到了EXC_BAD_ACCESS。请参见下面的 cmets。至于mvp,你又是不正确的。 mvp 旨在将点转换为-1.0, -1.0 的坐标系,到1.0, 1.0。这意味着他的顶点应该根据它们的值显示。

http://flylib.com/books/2/789/1/html/2/images/03fig02.jpg

同样改变 z 坐标对你没有任何作用。将您的顶点更改为从 -1.0,-1.0 开始,然后转到 1.0,1.0 一个全屏框,这样我们就可以在屏幕上看到一些东西。

假设你没有使用任何苹果提供的 gl 类,你的 glViewPort 没有被设置。

尝试使用视图的边界大小

glViewport(0, 0, bouds.width, bounds.height);

另外请把你的顶点放在 0.0 z 而不是 -1.0

也让我们试试这个,只是为了弄清楚出了什么问题! 尽量不要使用顶点缓冲区对象并像这样直接传递它。 现在也不要担心禁用你的属性,让我们先在屏幕上显示一些东西。

GLfloat     vertices[] = {  
            -1.0f,  -1.0f,  0.0f,
            1.0f,   -1.0f , 0.0f,
            -1.0f,  1.0f ,  0.0f,
            1.0f,   1.0f ,  0.0f,};

        glVertexAttribPointer(positionIndex,3,GL_FLOAT,0,0,vertices);
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

【讨论】:

  • 谢谢,但我还是遇到了一些问题。如果我按照您的建议更改 glVertexAttribPointer,我仍然会得到红屏,但如果我只更改 glDisableVertexAttribArray,glDrawArrays 会恢复 EXC_BAD_ACCESS。
  • 突然决定不要再在glDrawArrays上崩溃了,但是还是红屏。
  • 好吧,最后一点是错误的,就是你如何获取属性。您必须在链接之前获取属性。所以在 glLinkProgram(prog); 之前映射你的属性
  • 再次感谢(我喜欢总是有一个好心人愿意帮助我度过我的白痴),我改变了 glLinkProgram 的位置(这里是新代码cl.ly/2i0D2T0g2X2q3Z3Y2a1l),但它仍然不是不工作。
  • 关于以下内容的小提示:“另外,由于您正在为您的顶点使用 vbo,因此您不需要这样做” - 不仅您“不需要”,而且您不能使用它方式,当绑定 VBO 时,此指针用作绑定 VBO link 的起始偏移量 - 这是 EXC_BAD_ACCESS 的一个很好的理由
猜你喜欢
  • 2011-08-13
  • 2014-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多