我是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, ¶m);
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);
}
提前谢谢
答案 0 :(得分:3)
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
。见下面的评论。至于你的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);