Well in all honesty the code has gotten to the stage where it's about as pretty as dog vomit. I will release the source (or parts of it) regardless, though I'm sure I will feel great shame having everyone look at it :P and I doubt most of it will be of much use for learning given how untidy it is.
I will not go out of my way too clean up the code as most of the ugly stuff is abstracted away from and I can't afford to sink time into it.
Seeing as you are interested here is the C++ section of my rendering code:
Code: Select all
/*
* Renderer.h
* core
*
* Created by Samuel Zeid on 16/02/10.
* Copyright 2010 *. All rights reserved.
*
*/
#ifndef _RENDERER_H
#define _RENDERER_H
#import <QuartzCore/QuartzCore.h>
#include <OpenGLES/EAGL.h>
#include <OpenGLES/ES1/gl.h>
#include <OpenGLES/ES1/glext.h>
#include "Singleton.h"
#include "TextureManager.h"
#include "AnimationManager.h"
#include "StateManager.h"
#include "SpriteManager.h"
#include "Entity.h"
#include <map.h>
#include <list.h>
class Renderer : public Singleton<Renderer>
{
friend class Singleton<Renderer>;
public:
void initialise(EAGLContext* context, GLuint renderBuffer, GLuint frameBuffer)
{
textureManager=TextureManager::instance();
stateManager=StateManager::instance();
animationManager=AnimationManager::instance();
spriteManager=SpriteManager::instance();
m_context=context;
m_renderBuffer=renderBuffer;
m_frameBuffer=frameBuffer;
glEnable(GL_TEXTURE_2D);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);
vertices[0]=-0.5f;
vertices[1]=0.5f;
vertices[2]=0.5f;
vertices[3]=0.5f;
vertices[4]=-0.5f;
vertices[5]=-0.5f;
vertices[6]=0.5f;
vertices[7]=-0.5f;
texCoords[0]=0.0f;
texCoords[1]=0.0f;
texCoords[2]=1.0f;
texCoords[3]=0.0f;
texCoords[4]=0.0f;
texCoords[5]=1.0f;
texCoords[6]=1.0f;
texCoords[7]=1.0f;
[EAGLContext setCurrentContext:m_context];
glBindBuffer(GL_FRAMEBUFFER_OES, m_frameBuffer);
glViewport(0,0,320,480);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrthof(0.0f, 320.0f, 0.0f, 480.0f, 0.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
glClearColor(0.5f, 0.55f, 0.65f, 1.0f);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
//Make them pixels nice and crisp...
//glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
//glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
}
void render()
{
glClear(GL_COLOR_BUFFER_BIT);
glColor4f(0.0f,0.0f,0.0f,1.0f);
renderCycle();
glBindRenderbufferOES(GL_RENDERBUFFER_OES, m_renderBuffer);
[m_context presentRenderbuffer:GL_RENDERBUFFER_OES];
}
private:
Renderer(){}
~Renderer()
{
textureManager->release();
NSLog(@"Cleanup");
}
void renderCycle()
{
glVertexPointer(2, GL_FLOAT, 0, vertices);
glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
State* drawState;
GLuint previousTexture;
for(int i=0;i<stateManager->size();i++)
{
drawState=stateManager->states[i]->state;
if(drawState->visible)
{
glPushMatrix();
glTranslatef(drawState->camera.x, drawState->camera.y, 0);
list<Entity*>* layer=drawState->entityManager->getLayer(0);
int layerCount=drawState->entityManager->layerCount()+1;
for(int i=0; i<layerCount;i++)
{
for(list<Entity*>::iterator iter=layer->begin();iter!=layer->end();++iter)
{
Entity* e=*iter;
if(e->y>(-drawState->camera.y)-(e->sizeY/2)&&e->y<(-drawState->camera.y)+480+(e->sizeY/2))
{
e->onScreen=true;
Animation *a=animationManager->getAnimation(e->currentAnimation);
if(!e->textureDetail())
{
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
else
{
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
}
if(a->spriteSheet!=previousTexture)
textureManager->bindTexture(previousTexture=a->spriteSheet);
float cellDiff=(a->getDiff(e->currentSubframe))*spriteManager->getCellDiff(a->spriteSheet);
texCoords[4]=texCoords[0]=cellDiff;
texCoords[6]=texCoords[2]=cellDiff+spriteManager->getCellDiff(a->spriteSheet);
glPushMatrix();
glColor4f(drawState->screenRed*e->red, drawState->screenGreen*e->green, drawState->screenBlue*e->blue, 1.0f);
glTranslatef(e->x, e->y, 0);
glScalef(e->sizeX, e->sizeY, 0);
glRotatef(e->rotation, 0, 0, 1);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glPopMatrix();
}
else
{
e->onScreen=false;
}
}
layer=drawState->entityManager->getLayer(i);//stateManager->getLayer(i);
}
glPopMatrix();
}
}
}
EAGLContext *m_context;
GLuint m_renderBuffer, m_frameBuffer;
float vertices[8],texCoords[8];
list<Entity*>* layer;
TextureManager *textureManager;
StateManager *stateManager;
AnimationManager *animationManager;
SpriteManager* spriteManager;
};
#endif
I never bothered implementing VBO's for it (which is recommended) and there are a number of other things I would change if I were to spend more time on it:
* Obviously clean up the code a bit.
* Use dynamic VBO's and adjust their data using my own matrix class rather then the inbuilt openGL functions for translation, rotation and scaling.
* Use the batch rendering classes I had originally intended to use (dividing the objects to be drawn into groups based on their texture).
Instead of that I ended up using a cheap trick to improve rendering which took 3 minutes to implement. Whenever a texture is bound I store it's id value then whenever an object is to be drawn I check if it has the same texture value, if it does I don't bind the texture, otherwise I do. This mightn't seem like much of a boost, but because I sort objects based on the layer they are in when drawing (they get drawn from back to front on top of one another) most objects of the same type are in the same layer, and hence all are drawn one after another.