Hye,
I have encountered serious problem to draw a simple cube. Now I can’t understand why the depth buffer doesn’t work.
I probably have a lot of mistakes but where.
Any clues :
EAGLView.m
#import "EAGLView.h"
#import "ES1Renderer.h"
#import "ES2Renderer.h"
@implementation EAGLView
@synthesize animating;
@dynamic animationFrameInterval;
// You must implement this method
+ (Class)layerClass
{
return [CAEAGLLayer class];
}
//The EAGL view is stored in the nib file. When it's unarchived it's sent -initWithCoder:
- (id)initWithCoder:(NSCoder*)coder
{
if ((self = [super initWithCoder:coder]))
{
// Get the layer
CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
eaglLayer.opaque = TRUE;
eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:FALSE], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
renderer = [[ES2Renderer alloc] init];
if (!renderer)
{
renderer = [[ES1Renderer alloc] init];
if (!renderer)
{
[self release];
return nil;
}
}
animating = FALSE;
displayLinkSupported = FALSE;
animationFrameInterval = 1;
displayLink = nil;
animationTimer = nil;
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
// A system version of 3.1 or greater is required to use CADisplayLink. The NSTimer
// class is used as fallback when it isn't available.
NSString *reqSysVer = @"3.1";
NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
if ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending)
displayLinkSupported = TRUE;
}
return self;
}
- (void)drawView:(id)sender
{
[renderer render];
}
- (void)layoutSubviews
{
[renderer resizeFromLayer:(CAEAGLLayer*)self.layer];
[self drawView:nil];
}
- (NSInteger)animationFrameInterval
{
return animationFrameInterval;
}
- (void)setAnimationFrameInterval:(NSInteger)frameInterval
{
// Frame interval defines how many display frames must pass between each time the
// display link fires. The display link will only fire 30 times a second when the
// frame internal is two on a display that refreshes 60 times a second. The default
// frame interval setting of one will fire 60 times a second when the display refreshes
// at 60 times a second. A frame interval setting of less than one results in undefined
// behavior.
if (frameInterval >= 1)
{
animationFrameInterval = frameInterval;
if (animating)
{
[self stopAnimation];
[self startAnimation];
}
}
}
- (void)startAnimation
{
if (!animating)
{
if (displayLinkSupported)
{
// CADisplayLink is API new to iPhone SDK 3.1. Compiling against earlier versions will result in a warning, but can be dismissed
// if the system version runtime check for CADisplayLink exists in -initWithCoder:. The runtime check ensures this code will
// not be called in system versions earlier than 3.1.
displayLink = [NSClassFromString(@"CADisplayLink") displayLinkWithTarget:self selector:@selector(drawView:)];
[displayLink setFrameInterval:animationFrameInterval];
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}
else
animationTimer = [NSTimer scheduledTimerWithTimeInterval:(NSTimeInterval)((1.0 / 60.0) * animationFrameInterval) target:self selector:@selector(drawView:) userInfo:nil repeats:TRUE];
animating = TRUE;
}
}
- (void)stopAnimation
{
if (animating)
{
if (displayLinkSupported)
{
[displayLink invalidate];
displayLink = nil;
}
else
{
[animationTimer invalidate];
animationTimer = nil;
}
animating = FALSE;
}
}
- (void)dealloc
{
[renderer release];
[super dealloc];
}
@end
ES2Rendered.m
#import "ES2Renderer.h"
#define USE_DEPTH_BUFFER 1
@implementation ES2Renderer
// Create an OpenGL ES 2.0 context
- (id)init
{
if ((self = [super init]))
{
context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
if (!context || ![EAGLContext setCurrentContext:context]/* || ![self loadShaders]*/)
{
[self release];
return nil;
}
if (USE_DEPTH_BUFFER) {
glGenRenderbuffers(1, &depthRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, backingWidth, backingHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderbuffer);
}
// Create default framebuffer object. The backing will be allocated for the current layer in -resizeFromLayer
glGenFramebuffers(1, &defaultFramebuffer);
glGenRenderbuffers(1, &colorRenderbuffer);
glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebuffer);
glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRenderbuffer);
mainScene = [[Scene alloc] init];
[mainScene addCube:[[Cube alloc]initWithDim:big atX:0.0f andY:0.0f andZ:0.0f]];
}
return self;
}
- (void)render{
[mainScene update];
// Replace the implementation of this method to do your own custom drawing
// This application only creates a single context which is already set current at this point.
// This call is redundant, but needed if dealing with multiple contexts.
[EAGLContext setCurrentContext:context];
// This application only creates a single default framebuffer which is already bound at this point.
// This call is redundant, but needed if dealing with multiple framebuffers.
glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebuffer);
glViewport(0, 0, backingWidth, backingHeight);
/*************** Debut du nouveau code ******************/
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
// Validate program before drawing. This is a good check, but only really necessary in a debug build.
// DEBUG macro must be defined in your debug configurations if that's not already the case
[mainScene render];
// This application only creates a single color renderbuffer which is already bound at this point.
// This call is redundant, but needed if dealing with multiple renderbuffers.
glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
[context presentRenderbuffer:GL_RENDERBUFFER];
}
- (BOOL)resizeFromLayer:(CAEAGLLayer *)layer{
// Allocate color buffer backing based on the current layer size
glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
[context renderbufferStorage:GL_RENDERBUFFER fromDrawable:layer];
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &backingWidth);
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &backingHeight);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
NSLog(@"Failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER));
return NO;
}
return YES;
}
- (void)dealloc
{
// Tear down GL
if (defaultFramebuffer){
glDeleteFramebuffers(1, &defaultFramebuffer);
defaultFramebuffer = 0;
}
if (colorRenderbuffer){
glDeleteRenderbuffers(1, &colorRenderbuffer);
colorRenderbuffer = 0;
}
if (program){
glDeleteProgram(program);
program = 0;
}
if(depthRenderbuffer) {
glDeleteRenderbuffers(1, &depthRenderbuffer);
depthRenderbuffer = 0;
}
// Tear down context
if ([EAGLContext currentContext] == context)
[EAGLContext setCurrentContext:nil];
[context release];
context = nil;
[mainScene release];
mainScene = nil;
[super dealloc];
}
@end
Cube.m
#import "Cube.h"
@implementation Cube
const GLfloat cubeVertices[] = {
// face de devant
-0.5, 0.5, 0.5,
-0.5, -0.5, 0.5,
0.5, -0.5, 0.5,
0.5, 0.5, 0.5,
// haut
-0.5, 0.5, -0.5,
-0.5, 0.5, 0.5,
0.5, 0.5, 0.5,
0.5, 0.5, -0.5,
// arrière
0.5, 0.5, -0.5,
0.5, -0.5, -0.5,
-0.5, -0.5, -0.5,
-0.5, 0.5, -0.5,
// dessous
-0.5, -0.5, 0.5,
-0.5, -0.5, -0.5,
0.5, -0.5, -0.5,
0.5, -0.5, 0.5,
// gauche
-0.5, 0.5, -0.5,
-0.5, 0.5, 0.5,
-0.5, -0.5, 0.5,
-0.5, -0.5, -0.5,
// droit
0.5, 0.5, 0.5,
0.5, 0.5, -0.5,
0.5, -0.5, -0.5,
0.5, -0.5, 0.5
};
static const GLubyte squareColors[] = {
0, 0, 204, 255,
0, 204, 0, 255,
204, 0, 0, 255,
204, 0, 204, 255,
0, 0, 204, 255,
0, 204, 0, 255,
204, 0, 0, 255,
204, 0, 204, 255,
0, 0, 204, 255,
0, 204, 0, 255,
204, 0, 0, 255,
204, 0, 204, 255,
0, 0, 204, 255,
0, 204, 0, 255,
204, 0, 0, 255,
204, 0, 204, 255,
0, 0, 204, 255,
0, 204, 0, 255,
204, 0, 0, 255,
204, 0, 204, 255,
0, 0, 204, 255,
0, 204, 0, 255,
204, 0, 0, 255,
204, 0, 204, 255,
};
-(id)initWithDim:(cubeCategory)cat atX:(CGFloat)_x andY:(CGFloat)_y andZ:(CGFloat)_z{
if(self = [super initAtX:_x andY:_y andZ:_z]){
cubeType = cat;
s_loader = [[ShaderLoader alloc] init];
[s_loader setProgramShader:@"rotationShader"];
if((s_loader != nil) && ([s_loader getProgramIdentifier] != 0)){
attribPositionOnShader = glGetAttribLocation([s_loader getProgramIdentifier], "position");
attribColorOnShader = glGetAttribLocation([s_loader getProgramIdentifier], "color");
uniformTranslateOnShader = glGetUniformLocation([s_loader getProgramIdentifier], "translate");
projMatOnShader = glGetUniformLocation([s_loader getProgramIdentifier], "orthoMat");
}
}
return self;
}
-(void)render{
Mat4x4 proj;
Mat4x4::setOrtho(proj, -2.0f, 2.0f, -3.0f, 3.0f, -2.0f, 2.0f);
r_angle += 0.02f;
Mat4x4 rot;
rot.rotY(r_angle);
Mat4x4 mvp = rot * proj;
//Matrix4x4 mvp;
//Matrix4x4Utils::Mul(mvp, rot, proj);
glUseProgram([s_loader getProgramIdentifier]);
glUniform1f(uniformTranslateOnShader, (GLfloat)center->getY());
glVertexAttribPointer(attribPositionOnShader, 3, GL_FLOAT, 0, 0, cubeVertices);
glEnableVertexAttribArray(attribPositionOnShader);
glVertexAttribPointer(attribColorOnShader, 4, GL_UNSIGNED_BYTE, 1, 0, squareColors);
glEnableVertexAttribArray(attribColorOnShader);
glUniformMatrix4fv(projMatOnShader, 16, GL_FALSE, mvp.toArray()/*proj.toArray()*/);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glDrawArrays(GL_TRIANGLE_FAN, 4, 4);
glDrawArrays(GL_TRIANGLE_FAN, 8, 4);
glDrawArrays(GL_TRIANGLE_FAN, 12, 4);
glDrawArrays(GL_TRIANGLE_FAN, 16, 4);
glDrawArrays(GL_TRIANGLE_FAN, 20, 4);
glDrawArrays(GL_TRIANGLE_FAN, 24, 4);
glUseProgram(0);
}
-(void)update{
}
-(void)dealloc{
[s_loader release];
[super dealloc];
}
@end
I have to say that the difference between openGL ES1.0 and openGL ES 2.0 was a little confusing for me …
Thanks for any help