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!
Related
I am using Blender to create a 3D cow and obtain the correct vertices (optimized afterwards to remove duplicates). I have created a Cow Class to be able to draw multiple instances of this cow on screen.
Cow 1 is drawn at (-2,0,-10) and Cow 2 is drawn at (2,0,-10). When I render cow 1 only I see Cow 1 at (-2,0,-10). When I render either both cows or only cow 2 (comment render cow 1 out), I only get cow 2 (do not see cow 1) at (2,0,-10). I am making a game where I will have many enemies running around and I need to be able to draw multiple instances of these objects and render them independently at different locations. Can anyone tell me what I am doing wrong? Thanks
//
// Cow.m
//
#import "Cow.h"
#import "cow_verts.h"
#implementation Cow
- (id)initWithContext:(EAGLContext *)aContext {
context = aContext;
effect = [[GLKBaseEffect alloc] init];
[EAGLContext setCurrentContext:context];
sharedResourceManager = [ResourceManager sharedResourceManager];
UIImage *textureImage = [UIImage imageNamed:#"cowUV.png"];
texture = [sharedResourceManager addTexture:textureImage];
position = GLKVector3Make(0,0,0);
rotation = GLKVector3Make(0,0,0);
scale = GLKVector3Make(1,1,1);
[self setupGL];
return self;
}
- (void)setupGL {
glGenVertexArraysOES(1, &_vao);
glBindVertexArrayOES(_vao);
glGenBuffers(1, &_dynamicVBO);
glBindBuffer(GL_ARRAY_BUFFER, _dynamicVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(CowDynamicVertexData), CowDynamicVertexData, GL_DYNAMIC_DRAW);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(dynamicVertexData), (void *)offsetof(dynamicVertexData, position));
glEnableVertexAttribArray(GLKVertexAttribPosition);
glGenBuffers(1, &_staticVBO);
glBindBuffer(GL_ARRAY_BUFFER, _staticVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(CowStaticVertexData), CowStaticVertexData, GL_STATIC_DRAW);
glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(staticVertexData), (void *)offsetof(staticVertexData, texCoord));
glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
glGenBuffers(1, &_indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(CowIndices), CowIndices, GL_STATIC_DRAW);
glBindVertexArrayOES(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
- (void)updateWithDelta:(float)aDelta {
float aspect = fabsf([[UIScreen mainScreen] bounds].size.width/ [[UIScreen mainScreen] bounds].size.height);
GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 4.0f, 20.0f);
effect.transform.projectionMatrix = projectionMatrix;
rotation.y += 90 * aDelta;
}
- (void)render {
[EAGLContext setCurrentContext:context];
glClearColor(0, 1, 1, 1);
glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
GLKMatrix4 xRotationMatrix = GLKMatrix4MakeXRotation(GLKMathDegreesToRadians(rotation.x));
GLKMatrix4 yRotationMatrix = GLKMatrix4MakeYRotation(GLKMathDegreesToRadians(rotation.y));
GLKMatrix4 zRotationMatrix = GLKMatrix4MakeZRotation(GLKMathDegreesToRadians(rotation.z));
GLKMatrix4 scaleMatrix = GLKMatrix4MakeScale(scale.x, scale.y, scale.z);
GLKMatrix4 translateMatrix = GLKMatrix4MakeTranslation(position.x, position.y, position.z);
GLKMatrix4 modelMatrix = GLKMatrix4Multiply(translateMatrix,
GLKMatrix4Multiply(scaleMatrix,
GLKMatrix4Multiply(zRotationMatrix,
GLKMatrix4Multiply(yRotationMatrix,
xRotationMatrix))));
effect.transform.modelviewMatrix = modelMatrix;
//GLKMatrix4 viewMatrix = GLKMatrix4MakeLookAt(0, 0, 3, 0, 0, 0, 0, 1, 0);
//effect.transform.modelviewMatrix = GLKMatrix4Multiply(viewMatrix, modelMatrix);
effect.texture2d0.name = texture.name;
effect.texture2d0.target = texture.target;
effect.texture2d0.envMode = GLKTextureEnvModeReplace;
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
glBindVertexArrayOES(_vao);
[effect prepareToDraw];
glDrawElements(GL_TRIANGLES, sizeof(CowIndices)/sizeof(CowIndices[0]), GL_UNSIGNED_INT, (void *)0);
glBindVertexArrayOES(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
}
#end
//
// Cow.h
//
#interface Cow : NSObject {
EAGLContext *context;
GLuint _vao;
GLuint _staticVBO;
GLuint _dynamicVBO;
GLuint _indexBuffer;
GLKTextureInfo *texture;
GLKBaseEffect *effect;
GLKVector3 position;
GLKVector3 rotation;
GLKVector3 scale;
ResourceManager *sharedResourceManager;
}
- (id)initWithContext:(EAGLContext *)aContext;
- (void)updateWithDelta:(float)aDelta;
- (void)render;
#end
//
// Scene which creates these objects and calls the functions
//
#import "Cow.h"
#implementation GameScene {
NSMutableArray *cows;
}
- (id)init {
if(self = [super init]) {
sharedDirector = [Director sharedDirector];
[EAGLContext setCurrentContext:[sharedDirector context]];
cows = [[NSMutableArray alloc] init];
AbstractEnemy *cow1 = [[Cow alloc] initWithContext:[sharedDirector context]];
cow1.position = GLKVector3Make(-2, 0, -10);
[cows addObject:cow1];
AbstractEnemy *cow2 = [[Cow alloc] initWithContext:[sharedDirector context]];
cow2.position = GLKVector3Make(2, 0, -10);
[cows addObject:cow2];
AbstractEnemy *cow3 = [[Cow alloc] initWithContext:[sharedDirector context]];
cow3.position = GLKVector3Make(0, 0, -15);
[cows addObject:cow3];
}
return self;
}
- (void)updateWithDelta:(GLfloat)aDelta {
for (int i = 0; i < cows.count; i++)
{
[cows[i] updateWithDelta:aDelta];
}
}
- (void)render {
for (int i = 0; i < cows.count; i++)
{
[cows[i] render];
}
}
#end
From the code you gave, you are calling a glClear() every time before you draw the cow. With all those clear calls, only the last cow you draw will be visible.
Move this call into the scene's render function so you only clear the scene once at the start of each frame.
Am working in a simple iPhone game application using OpenGLES framework. I facing an "EXC Bad Access" error while draw a line on the images. Here i will explain you what i did and what i tried in my project.
Step:1 I draw a Background Image used GL_TRIANGLE_STRIP. Here is my sample code,
- (void)viewDidLoad
{
[super viewDidLoad];
self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
Test = NO;
Test1 = NO;
if (!self.context)
{
NSLog(#"Failed to create ES context");
}
GLKView *view = (GLKView *)self.view;
view.context = self.context;
[EAGLContext setCurrentContext:self.context];
self.effect = [[GLKBaseEffect alloc] init];
GLKMatrix4 projectionMatrix = GLKMatrix4MakeOrtho(0, 480, 0, 320, -1024, 1024);
self.effect.transform.projectionMatrix = projectionMatrix;
self.player = [[SGGSprite alloc] initWithFile:#"bg.png" effect:self.effect];
self.player.position = GLKVector2Make(self.player.contentSize.width, 460);
self.children = [NSMutableArray array];
[self.children addObject:self.player];
}
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
// glClearColor(1, 1, 1, 1);
// glClear(GL_COLOR_BUFFER_BIT);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
// Condition satisfied to draw a line code given below, otherwise the background and fish image draw in else part.
if(Test1 == YES)
{
GLKView *view = (GLKView *)self.view;
view.context = self.context;
view.drawableDepthFormat = GLKViewDrawableDepthFormat24;
self.effect = [[GLKBaseEffect alloc] init];
[self.effect prepareToDraw];
const GLfloat line[] =
{
0.0f, 0.5f,
-3.0f,-1.0f,
};
GLuint bufferObjectNameArray;
glGenBuffers(1, &bufferObjectNameArray);
glBindBuffer(GL_ARRAY_BUFFER, bufferObjectNameArray);
glBufferData(
GL_ARRAY_BUFFER, // the target buffer
sizeof(line), // the number of bytes to put into the buffer
line, // a pointer to the data being copied
GL_STATIC_DRAW); // the usage pattern of the data
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(
GLKVertexAttribPosition,
2, // number of coordinates per vertex
GL_FLOAT, // the data type of each component
GL_FALSE, // can the data be scaled
2*4,
NULL);
glDrawArrays(GL_LINES, 0, 2);
}
else
{
//SGGSprite is another class and self.children is mutable array.
for (SGGSprite * sprite in self.children)
{
[sprite render];
}
}
}
//render method in SGGSprite class to draw a fish and background image
- (void)render
{
self.effect.texture2d0.name = self.textureInfo.name;
self.effect.texture2d0.enabled = YES;
self.effect.transform.modelviewMatrix = self.modelMatrix;
[self.effect prepareToDraw];
long offset = (long)&_quad;
glEnableVertexAttribArray(GLKVertexAttribPosition);
glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
NSLog(#"TexturedVertex:%ld",offset);
glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedVertex), (void *) (offset + offsetof(TexturedVertex, geometryVertex)));
glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedVertex), (void *) (offset + offsetof(TexturedVertex, textureVertex)));
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
Step:2 After i draw a background image for my view am going to draw a fish images in the screen by using GL_TRIANGLE_STRIP. The fish images are always in moving. Here is my sample code,
(void)update
{
if(Test == NO)
{
self.timeSinceLastSpawn += self.timeSinceLastUpdate;
if (self.timeSinceLastSpawn > 2.0)
{
self.timeSinceLastSpawn = 0;
[self target]; // add fish image
}
for (SGGSprite * sprite in self.children)
{
[sprite update:self.timeSinceLastUpdate];
}
}
}
(void)target
{
SGGSprite * target = [[SGGSprite alloc] initWithFile:#"img2.png" effect:self.effect];
[self.children addObject:target]; // Add fish image in NSMutable array
int minY = target.contentSize.height/2;
int maxY = 320 - target.contentSize.height/2;
int rangeY = maxY - minY;
int actualY = (arc4random() % rangeY) + minY;
if(actualY <= 100)
{
actualY = 215;
}
target.position = GLKVector2Make(480 + (target.contentSize.width), actualY);
int minVelocity = 480.0/12.0;
int maxVelocity = 480.0/6.0;
int rangeVelocity = maxVelocity - minVelocity;
int actualVelocity = (arc4random() % rangeVelocity) + minVelocity;
target.moveVelocity = GLKVector2Make(-actualVelocity, 0);
}
(void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
// glClearColor(1, 1, 1, 1);
// glClear(GL_COLOR_BUFFER_BIT);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
// Condition satisfied to draw a line code given below, otherwise the background and fish image draw in else part.
if(Test1 == YES)
{
GLKView *view = (GLKView *)self.view;
view.context = self.context;
view.drawableDepthFormat = GLKViewDrawableDepthFormat24;
self.effect = [[GLKBaseEffect alloc] init];
[self.effect prepareToDraw];
const GLfloat line[] =
{
0.0f, 0.5f,
-3.0f,-1.0f,
};
GLuint bufferObjectNameArray;
glGenBuffers(1, &bufferObjectNameArray);
glBindBuffer(GL_ARRAY_BUFFER, bufferObjectNameArray);
glBufferData(
GL_ARRAY_BUFFER, // the target buffer
sizeof(line), // the number of bytes to put into the buffer
line, // a pointer to the data being copied
GL_STATIC_DRAW); // the usage pattern of the data
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(
GLKVertexAttribPosition,
2, // number of coordinates per vertex
GL_FLOAT, // the data type of each component
GL_FALSE, // can the data be scaled
2*4,
NULL);
glDrawArrays(GL_LINES, 0, 2);
}
else
{
//SGGSprite is another class and self.children is mutable array.
for (SGGSprite * sprite in self.children)
{
[sprite render];
}
}
}
Step:3 Now i draw a Background Image and fish images in my screen. It works perfect. Now am going to draw a white line (using GL_LINE) in the screen above the fish images and background image. When i draw a line by using below code,
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
Test = YES;
Test1 = YES;
}
- (void)update
{
if(Test == NO)
{
self.timeSinceLastSpawn += self.timeSinceLastUpdate;
NSLog(#"timeSinceLastUpdate:%f",self.timeSinceLastUpdate);
if (self.timeSinceLastSpawn > 2.0)
{
self.timeSinceLastSpawn = 0;
[self target];
}
NSLog(#"Children count:%d",[self.children count]);
for (SGGSprite * sprite in self.children)
{
[sprite update:self.timeSinceLastUpdate];
}
}
}
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
// glClearColor(1, 1, 1, 1);
// glClear(GL_COLOR_BUFFER_BIT);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
// Condition satisfied to draw a line code given below, otherwise the background and fish image draw in else part.
if(Test1 == YES)
{
GLKView *view = (GLKView *)self.view;
view.context = self.context;
view.drawableDepthFormat = GLKViewDrawableDepthFormat24;
self.effect = [[GLKBaseEffect alloc] init];
[self.effect prepareToDraw];
const GLfloat line[] =
{
0.0f, 0.5f,
-3.0f,-1.0f,
};
GLuint bufferObjectNameArray;
glGenBuffers(1, &bufferObjectNameArray);
glBindBuffer(GL_ARRAY_BUFFER, bufferObjectNameArray);
glBufferData(
GL_ARRAY_BUFFER, // the target buffer
sizeof(line), // the number of bytes to put into the buffer
line, // a pointer to the data being copied
GL_STATIC_DRAW); // the usage pattern of the data
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(
GLKVertexAttribPosition,
2, // number of coordinates per vertex
GL_FLOAT, // the data type of each component
GL_FALSE, // can the data be scaled
2*4,
NULL);
glDrawArrays(GL_LINES, 0, 2);
}
else
{
//SGGSprite is another class and self.children is mutable array, Draw a fish and background image
for (SGGSprite * sprite in self.children)
{
[sprite render];
}
}
}
The app getting crash in the line "glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); // ERROR -Bad excess happened here when i touch the screen"
(void)render
{
self.effect.texture2d0.name = self.textureInfo.name;
self.effect.texture2d0.enabled = YES;
self.effect.transform.modelviewMatrix = self.modelMatrix;
[self.effect prepareToDraw];
long offset = (long)&_quad;
glEnableVertexAttribArray(GLKVertexAttribPosition);
glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
NSLog(#"TexturedVertex:%ld",offset);
glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedVertex), (void *) (offset + offsetof(TexturedVertex, geometryVertex)));
glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedVertex), (void *) (offset + offsetof(TexturedVertex, textureVertex)));
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); // ERROR comes from this line, when i touch the screen.
}
Can you please refer these code and tell what is wrong with my code? What i should do to fix this problem? Please help me. Thanks in advance.
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);
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.
I'm trying to render a simple quad with a texture using a vertex buffer object and an index buffer object. I haven't seen any solutions for how to do this with an IBO using glDrawElements. In any case, all that appears to happen is that the quad is textured using only the upper left hand pixel of the texture image.
This is how initialize an entity that will be rendered:
void Entity::init(){
// create triangle verticies
numVerticies = 20;
verticies = new GLfloat[numVerticies];
// 3 verts, 2 tex coords
verticies[0] = -1.0f; verticies[1] = -1.0f; verticies[2] = 0.0f; verticies[3] = 0.0f; verticies[4] = 0.0f;
verticies[5] = 1.0f; verticies[6] = 1.0f; verticies[7] = 0.0f; verticies[8] = 1.0f; verticies[9] = 1.0f;
verticies[10] = -1.0f; verticies[11] = 1.0f; verticies[12] = 0.0f; verticies[13] = 0.0f; verticies[14] = 1.0f;
verticies[15] = 1.0f; verticies[16] = -1.0f; verticies[17] = 0.0f; verticies[18] = 1.0f; verticies[19] = 0.0f;
// create face indicies
numIndicies = 6;
indicies = new GLushort[numIndicies];
indicies[0] = 0; indicies[1] = 1; indicies[2] = 2;
indicies[3] = 0; indicies[4] = 3; indicies[5] = 1;
// generate buffers for geometry
glGenBuffers(2, geometryBuffer);
// buffer the data to the vertex buffer
glBindBuffer(GL_ARRAY_BUFFER, geometryBuffer[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(verticies) * numVerticies, verticies, GL_STATIC_DRAW);
// buffer the data to the index buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, geometryBuffer[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indicies) * numIndicies, indicies, GL_STATIC_DRAW);
rotation = 0.0f;
// load a texure object
std::string path = [[[NSBundle mainBundle] bundlePath] UTF8String];
path += "/test.png";
NSString *fileName = [NSString stringWithUTF8String:path.c_str()];
NSError *error;
GLKTextureInfo *texture = [GLKTextureLoader textureWithContentsOfFile:fileName options:nil error:&error];
if(error || texture == nil){
NSLog(#"Error loading texture %#\n", error);
}
// get the texture id
tex = [texture name];
}
And this is how I render the object ( I should mention that I call glUseProgram before calling this method):
void Entity::render(GLint uniformPos, GLint uniformTex, GLKMatrix4 projection){
GLKMatrix4 modelViewProjection = GLKMatrix4Multiply(projection, modelView);
// bind and enable enable verticies
glBindBuffer(GL_ARRAY_BUFFER, geometryBuffer[0]);
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), BUFFER_OFFSET(0));
// enable tex coords
glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), BUFFER_OFFSET(12));
// bind the index buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, geometryBuffer[1]);
// bind the texture
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex);
// render with uniforms
glUniform1i(uniformTex, 0);
glUniformMatrix4fv(uniformPos, 1, 0, modelViewProjection.m);
glDrawElements(GL_TRIANGLES, numIndicies, GL_UNSIGNED_SHORT, 0);
// disable attributes and buffers
glDisableVertexAttribArray(GLKVertexAttribPosition);
glDisableVertexAttribArray(GLKVertexAttribTexCoord0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
So I figured this out.
This:
// enable tex coords
glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), BUFFER_OFFSET(12));
Needs to be this:
GLint texCoordLoc = glGetAttributeLocation(program, texCoordAttributeName);
glEnableVertexAttribArray(texCoordLoc);
glVertexAttribPointer(texCoordLoc, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), BUFFER_OFFSET(12));