Open GL - ES 2.0 : Multiple Vertex Buffer Object - iphone

I had a quick question on openGL ES 2.0 I am trying to create some drawings on the screen which will require multiple geometries. This is how I am creating the geometries.
(void)setupBoxGeometry{
GLuint vertexBuffer;
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(BoxVertices), BoxVertices, GL_STATIC_DRAW);
GLuint indexBuffer;
glGenBuffers(1, &indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(BoxIndices), BoxIndices, GL_STATIC_DRAW);
}
- (void)setupLineGeometry{
GLuint vertexBuffer;
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(LineVertices), LineVertices, GL_STATIC_DRAW);
GLuint indexBuffer;
glGenBuffers(1, &indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(LineIndices), LineIndices, GL_STATIC_DRAW);
}
This is my render function
- (void)render:(CADisplayLink*)displayLink {
glClearColor(0.0/255.0, 0.0/255.0, 0.0/255.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
float h = 4.0f * self.frame.size.height / self.frame.size.width;
glViewport(0, 0, self.frame.size.width, self.frame.size.height);
glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, GL_FALSE,
sizeof(Vertex), 0);
glVertexAttribPointer(_colorSlot, 4, GL_FLOAT, GL_FALSE,
sizeof(Vertex), (GLvoid*) (sizeof(float) * 3));
// Do some thing to the projection
CC3GLMatrix *projection = [CC3GLMatrix matrix];
[projection populateFromFrustumLeft:-2 andRight:2 andBottom:-h/2 andTop:h/2 andNear:4 andFar:10];
glUniformMatrix4fv(_projectionUniform, 1, 0, projection.glMatrix);
// Create the base for the square to be drawn on the screen
_baseMatrix = [CC3GLMatrix matrix];
[_baseMatrix populateFromTranslation:CC3VectorMake(-3.0, -5.2 + _yIncrease, -10)];
[_baseMatrix scaleByX:0.5];
[_baseMatrix scaleByY:_yIncrease];
[_baseMatrix rotateBy:CC3VectorMake(0, _rotationAngle, 0)];
glUniformMatrix4fv(_modelViewUniform, 1, 0, _baseMatrix.glMatrix);
glDrawElements(GL_TRIANGLES, sizeof(BoxIndices)/sizeof(BoxIndices[0]),
GL_UNSIGNED_BYTE, 0);
}
I call the box geometry function before I call the line geometry function. The problem is now my render function only draws lines. It does not draw any boxes. What am I doing wrong. If the question is not clear I can give more clarifications/

Where are you binding buffers before drawing?
Call
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
before
glVertexAttribPointer(...);
And call
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
before
glDrawElements(...);
Also you need to enable vertex pointers you are using:
glEnableVertexAttribArray(_positionSlot);
glEnableVertexAttribArray(_colorSlot);

Related

OpenGl ES 2.0 and GLKit : From GLKBaseEffect shaders to OpenGl

I'm coding a 2D game with OpenGL ES 2.0 and GLKit. My architecture is based on the Games by Ian Terrel tutorials.
I discover recently that the GLKBaseEffect (provide simple shaders mgmt) leaks and makes sometimes my app crash. I'm now using my own shaders files (based on the Ray Wenderlich tutorial) but, at this time, I've just succeed to display openGl background color. My shapes colors and textures aren't displayed anymore.
IMPORTANT : I was setting the current context badly, now openGL says invalid Drawable.
Here is a part of my shape.m code :
#implementation P3Shape
const GLushort indices[] = {
0,1,2,3
};
typedef struct {
float Position[2];
float Color[4];
float TexCoord[2];
} Vertex;
//testing
const Vertex Vertices[] = {
// Front
{{10, -15}, {1, 0, 0, 1}, {1, 0}},
{{10, 15}, {0, 1, 0, 1}, {1, 0}},
{{-10, 10}, {0, 0, 1, 1}, {0, 0}},
{{-10, -1}, {0, 0, 0, 1}, {0, 1}},
};
- (id)initWithLayer:(CAEAGLLayer *)layer {
self = [super init];
if (self) {
[...]
_currentContext = [P3SessionState currentContext];
_eaglLayer = layer;
_eaglLayer.opaque = YES;
[self setupRenderBuffer];
[self setupFrameBuffer];
[self addToProgram];
[self createBuffers];
}
return self;
}
- (int)numVertices {
return 0;
}
- (void) addToProgram {
// setted before in the gamemanager
GLuint programHandle = [P3SessionState programHandle];
_positionSlot = glGetAttribLocation(programHandle, "Position");
_colorSlot = glGetAttribLocation(programHandle, "SourceColor");
_projectionUniform = glGetUniformLocation(programHandle, "Projection");
_modelViewUniform = glGetUniformLocation(programHandle, "Modelview");
_texCoordSlot = glGetAttribLocation(programHandle, "TexCoordIn");
_textureUniform = glGetUniformLocation(programHandle, "Texture");
}
- (void)setupRenderBuffer {
glGenRenderbuffers(1, &_colorRenderBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, _colorRenderBuffer);
[_currentContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:_eaglLayer];
}
- (void)setupFrameBuffer {
GLuint framebuffer;
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _colorRenderBuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthRenderBuffer);
}
- (void)createBuffers {
// Static index data
glGenBuffers(1, &indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
}
// initialize the vertex data
- (GLKVector2 *)vertices {
if (vertexData == nil) {
vertexData = [NSMutableData dataWithLength:sizeof(GLKVector2)*self.numVertices];
}
return [vertexData mutableBytes];
}
// set a textureImage, allocate a glname and enable the GL_TEXTURE_2D and all
- (void)setTextureImage:(UIImage *)image {
CGImageRef spriteImage = image.CGImage;
if (!spriteImage) {
NSLog(#"Failed to load image %#", image);
exit(1);
}
size_t width = CGImageGetWidth(spriteImage);
size_t height = CGImageGetHeight(spriteImage);
GLubyte * spriteData = (GLubyte *) calloc(width*height*4, sizeof(GLubyte));
CGContextRef spriteContext = CGBitmapContextCreate(spriteData, width, height, 8, width*4, CGImageGetColorSpace(spriteImage), kCGImageAlphaPremultipliedLast);
CGContextDrawImage(spriteContext, CGRectMake(0, 0, width, height), spriteImage);
CGContextRelease(spriteContext);
GLuint texName;
glGenTextures(1, &texName);
glBindTexture(GL_TEXTURE_2D, texName);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, spriteData);
free(spriteData);
_imageTexture = texName;
}
- (GLKVector2 *)textureCoordinates {
if (textureCoordinateData == nil)
textureCoordinateData = [NSMutableData dataWithLength:sizeof(GLKVector2)*self.numVertices];
return [textureCoordinateData mutableBytes];
}
- (void)render {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glClearColor(0, 104.0/255.0, 55.0/255.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUniformMatrix4fv(_modelViewUniform, 1, 0, modelview.m);
glUniformMatrix4fv(_projectionUniform, 1, 0, projectionMatrix.m);
glEnableVertexAttribArray(_positionSlot);
glEnableVertexAttribArray(_colorSlot);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glVertexAttribPointer(_positionSlot, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
glVertexAttribPointer(_colorSlot, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) (sizeof(float) * 3));
if(texture != nil) {
glEnableVertexAttribArray(_texCoordSlot);
glActiveTexture(GL_TEXTURE0); // unneccc in practice
glBindTexture(GL_TEXTURE_2D, _imageTexture);
glUniform1i(_textureUniform, 0); // unnecc in practice
glVertexAttribPointer(_texCoordSlot, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) (sizeof(float) * 7));
}
glDrawElements(GL_TRIANGLE_FAN, sizeof(indices)/sizeof(GLushort), GL_UNSIGNED_SHORT, (void*)0);
}
//is cleanup code that tells the shader that we’re done using vertex position data.
glDisableVertexAttribArray(GLKVertexAttribPosition);
if (texture != nil)
glDisableVertexAttribArray(GLKVertexAttribTexCoord0);
[_currentContext presentRenderbuffer:GL_RENDERBUFFER];
glDisable(GL_BLEND);
}
// draw the shape in the selected scene
- (void)renderInScene:(P3Scene *)theScene {
projectionMatrix = [theScene projectionMatrix];
modelview = GLKMatrix4Multiply(GLKMatrix4MakeTranslation(0, 0, 0), GLKMatrix4MakeRotation(0, 0, 0, 1));
modelview = GLKMatrix4Multiply(modelview, GLKMatrix4MakeScale(scale.x, scale.y, 1));
[self render];
}
-(void)update:(NSTimeInterval)dt {
if(self.toDraw)
[spriteAnimation update:dt];
}
#end
As you can see, I'm testing with a Vertices array and a basic color but it makes no differences. OpenGl seems to be set correctly because my view is green thanks to the glClearColor(0, 104.0/255.0, 55.0/255.0, 1.0); in the render function.
Here the files on pastebin :
P3Shape.m on pastebin
And a manager who create the ogl program
P3GameManager.m on pastebin
Any ideas ?
EDIT : maybe a problem with my shaders ?
vertex :
attribute vec4 Position;
attribute vec4 SourceColor;
varying vec4 DestinationColor;
uniform mat4 Projection;
uniform mat4 Modelview;
attribute vec2 TexCoordIn; // New
varying vec2 TexCoordOut; // New
void main(void) {
DestinationColor = SourceColor;
gl_Position = Projection * Modelview * Position;
TexCoordOut = TexCoordIn; // New
}
and fragment :
varying lowp vec4 DestinationColor;
varying lowp vec2 TexCoordOut; // New
uniform sampler2D Texture; // New
void main(void) {
gl_FragColor = DestinationColor * texture2D(Texture, TexCoordOut); // New
}
I recommend using GLKViewController and GLKView to simplify your setup. Similarly, replace your texture loading with GLKTextureLoader.
I haven't seen any issues with GLKBaseEffect leaking memory and causing crashes. I would suggest posting a new question about this particular problem, and returning to using GLKBaseEffect if you don't need custom shaders (it looks like you don't). Will make your code a lot easier to manage and debug.

OpenGL ES 2.0 GLKit GL_LINE_SMOOTH error

I'm using drawing a glDrawArrays to draw a GL_LINE_STRIP and want to make them smooth. I've seen on a couple questions here people recommend using glEnable(GL_LINE_SMOOTH) and glHint(GL_LINE_SMOOTH_HINT, GL_NICEST), but when I do so, I'm getting an error. Here's my code:
- (void)setupGL
{
[EAGLContext setCurrentContext:self.context];
self.effect = [[[GLKBaseEffect alloc] init] autorelease];
self.effect.light0.enabled = GL_FALSE;
self.effect.light1.enabled = GL_FALSE;
self.effect.light2.enabled = GL_FALSE;
self.effect.lightModelAmbientColor = GLKVector4Make(0.0f, 0.0f, 0.0f, 1.0f);
glDisable(GL_DEPTH_TEST);
// glEnable(GL_LINE_SMOOTH);
// glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glGenVertexArraysOES(1, &_vertexArray);
glBindVertexArrayOES(_vertexArray);
glGenBuffers(1, &_vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, VERTEX_POS_DATA_SIZE, GL_FLOAT, GL_FALSE, VERTEX_DATA_SIZE * sizeof(GLfloat), BUFFER_OFFSET(0));
glEnableVertexAttribArray(GLKVertexAttribColor);
glVertexAttribPointer(GLKVertexAttribColor, VERTEX_COLOR_DATA_SIZE, GL_FLOAT, GL_FLOAT, VERTEX_DATA_SIZE * sizeof(GLfloat), BUFFER_OFFSET(VERTEX_POS_DATA_SIZE * sizeof(GLfloat)));
glLineWidth(10.0);
}
If I uncomment either (or both) of those lines, I get a GL ERROR. Any thoughts?
I had that working (well!) with an ES1.1 context, i.e.
self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
I'm writing new code and trying to ride the wave of the future (or at least, the now-recent past) and jump to ES2.0. In the 2.0 universe, I have had moderate success with
view.drawableMultisample = GLKViewDrawableMultisample4X;
set in my GLKViewController's -viewDidLoad override, set on my GLKView. YMMV.

making an iphone cube class

I followed this tutorial and I'm currently trying to create a class to draw cubes. The class populates the buffers in a function called setup and draws them in a function called draw.
There are no errors however nothing is displayed on the screen.
My question is basicly how do I go about making a class from which I can render cubes.
Using Xcode 4.2, Opengl and Objective-C.
[edit]
-(void)SetShader:(GLuint)InShader
{
glUseProgram(InShader);
_positionSlot = glGetAttribLocation(InShader, "Position");
_colorSlot = glGetAttribLocation(InShader, "SourceColor");
glEnableVertexAttribArray(_positionSlot);
glEnableVertexAttribArray(_colorSlot);
_projectionUniform = glGetUniformLocation(InShader, "Projection");
_modelViewUniform = glGetUniformLocation(InShader, "Modelview");
_texCoordSlot = glGetAttribLocation(InShader, "TexCoordIn");
glEnableVertexAttribArray(_texCoordSlot);
_textureUniform = glGetUniformLocation(InShader, "Texture");
}
-(void)SetupVBO
{
GLuint vertexBuffer;
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(CubeVertices), CubeVertices, GL_STATIC_DRAW);
GLuint indexBuffer;
glGenBuffers(1, &indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(CubeIndices), CubeIndices, GL_STATIC_DRAW);
}
-(void)draw
{
glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
glVertexAttribPointer(_colorSlot, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) (sizeof(float) * 3));
glVertexAttribPointer(_texCoordSlot, 2, GL_FLOAT, GL_FALSE,
sizeof(Vertex), (GLvoid*) (sizeof(float) * 7));
glDrawElements(GL_TRIANGLES, sizeof(CubeIndices)/sizeof(CubeIndices[0]), GL_UNSIGNED_BYTE, 0);
}
-(void)render:(CADisplayLink*)displayLink
{
glClearColor(0, 0, 0.2, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
CC3GLMatrix *projection = [CC3GLMatrix matrix];
float h = 4.0f * self.frame.size.height / self.frame.size.width;
[projection populateFromFrustumLeft:-2 andRight:2 andBottom:-h/2 andTop:h/2 andNear:4 andFar:10];
glUniformMatrix4fv(_projectionUniform, 1, 0, projection.glMatrix);
CC3GLMatrix *modelView = [CC3GLMatrix matrix];
[modelView populateFromTranslation:CC3VectorMake(0, 0, -7)];
[modelView translateBy:CC3VectorMake(0,5,0)];
glUniformMatrix4fv(_modelViewUniform, 1, 0, modelView.glMatrix);
glViewport(0, 0, self.frame.size.width, self.frame.size.height);
[m_cube draw];
[_context presentRenderbuffer:GL_RENDERBUFFER];
}
It was as mentioned a problem with the arrangement of my viewport and perspective setups.

How to change the perspective on a 3D cube in OpenGL ES?

I draw a cube with OpenGL ES and I want to have an above perspective on it.But I don't know what should I modify...Maybe you can help.
- (void)render:(CADisplayLink*)displayLink {
//-(void) render{
glClearColor(255.0, 255.0/255.0, 255.0/255.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
//projection
CC3GLMatrix *projection = [CC3GLMatrix matrix];
float h = 4.0f * self.frame.size.height / self.frame.size.width;
[projection populateFromFrustumLeft:-2 andRight:2 andBottom:-h/2 andTop:h/2 andNear:4 andFar:8];
glUniformMatrix4fv(_projectionUniform, 1, 0, projection.glMatrix);
CC3GLMatrix *modelView = [CC3GLMatrix matrix];
// _currentScaling += displayLink.duration * 1.0;
[modelView populateFromTranslation:CC3VectorMake(sin(30), _currentScaling , -7)];
[modelView rotateBy:CC3VectorMake(0, -15, 0)];
// [modelView scaleByY:_currentScaling];
if(_currentScaling > 2 ){
[displayLink invalidate];
_running = 1;
// scale = 0;
}
glUniformMatrix4fv(_modelViewUniform, 1, 0, modelView.glMatrix);
// 1
glViewport(0, 0, self.frame.size.width, self.frame.size.height);
// 2
glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, GL_FALSE,
sizeof(Vertex), 0);
glVertexAttribPointer(_colorSlot, 4, GL_FLOAT, GL_FALSE,
sizeof(Vertex), (GLvoid*) (sizeof(float) * 3));
// 3
glDrawElements(GL_TRIANGLES, sizeof(Indices)/sizeof(Indices[0]),
GL_UNSIGNED_BYTE, 0);
[_context presentRenderbuffer:GL_RENDERBUFFER];
}
I recently started looking into OpenGL myself and found this same example. I believe what you are looking for is to change this line to change the perspective:
[modelView rotateBy:CC3VectorMake(0, -15, 0)];
and specify the degrees of rotation you want for the x,y,z axes.

exc_bad_access when using VBO's in Cocos2d

In my iPhone application I am creating a vertex buffer as shown below:
-(id)initWithPoints:(NSArray *)polygonPoints andTexture: (CCTexture2D *) fillTexture{
self = [super init];
if(self){
int vertexCount = [polygonPoints count];
CGPoint *vertices = (CGPoint*)malloc(sizeof(CGPoint)*vertexCount);
GLushort *indices = (GLushort*)malloc(sizeof(GLushort)*2*vertexCount);
int i = 0;
for(NSValue *value in polygonPoints){
CGPoint p = [value CGPointValue];
vertices[i] = ccp(p.x, p.y);
i++;
}
for (int k = 0; k<vertexCount; k++) {
indices[k] = (GLushort)k;
}
NSLog(#"count: %i", vertexCount);
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, vertexCount*sizeof(CGPoint), &vertices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGenBuffers(1, &indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (vertexCount)*2*sizeof(GLushort), &indices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
self.text = fillTexture;
}
return self;
}
And I draw it using:
-(void)draw{
glBindTexture(GL_TEXTURE_2D, self.text.name);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexPointer(2, GL_FLOAT, sizeof(CGPoint), 0);
glEnableClientState(GL_VERTEX_ARRAY);
glDrawElements(GL_TRIANGLES, 1024, GL_UNSIGNED_SHORT, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
However, I can only call glDrawElements with 1024 elements (out of ~20,000) and they render ok.
If I set it to (for example) 1025, the application crashes with EXC_BAD_ACCESS.
Obviously there's a reason the app crashes at 1024 elements, but I can't understand what it is. Any ideas would be much appreciated!