我是OpenGL ES 1.1的新手,我试图通过创建一组函数来缓慢启动,这些函数将从我的iPhone上的单个纹理渲染多个精灵。我的工作正如我所期望的那样(但如果我犯了任何明显的错误,请告诉我),但我现在正在寻找优化我的代码。因此,我有两个问题:
1)如何加快下面的代码?据我了解,我应该能够从同一个OpenGL纹理批处理多个绘制调用,以加快渲染速度。我该怎么做呢,我应该注意哪些好的代码示例?
2)使用glOrthof我已经将坐标系从0,0改为我的设备宽度和高度。在传递允许我传入像素值的glTexCoordPointer纹理坐标时,是否有类似的处理方法?
供参考,这是我的代码:
- (void)drawGLView
{
[EAGLContext setCurrentContext:context];
glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
glClearColor( 0, 0, 0, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D, spriteTexture);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
for(Sprite *sprite in self.sprites)
{
[self drawAtPoint:sprite.location];
}
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
[context presentRenderbuffer:GL_RENDERBUFFER_OES];
}
- (void)drawAtPoint:(CGPoint)point
{
GLfloat x = point.x, y = point.y;
GLfloat w = self.spritesheet.size.width;
GLfloat h = self.spritesheet.size.height;
GLfloat box[] = {
x, y + h, 0,
x, y, 0,
x + w, y + h, 0,
x + w, y , 0
};
GLfloat tex[] = {
0, 1,
0, 0,
1, 1,
1, 0
};
glVertexPointer(3, GL_FLOAT, 0, box);
glTexCoordPointer(2, GL_FLOAT, 0, tex);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
答案 0 :(得分:0)
1)这是我用于我的粒子系统的东西(用c ++编写,但你会明白这一点)。你可以把纹理连成一排(水平,都是相同的大小),并绘制它正确的id,0-first tex,1-second等等;
class gltAtlasRenderer
{
public:
float* partVdata;
float* partCdata;
float* partTdata;
int counter1,counter2,counter3;
int count;
bool isz;
int tilesize;
float tilesx;
gltAtlasRenderer(int maxTextures,bool iszi,int numberoftiles)
{
isz=iszi;
if(isz)partVdata=(float*)malloc(maxTextures*18*4);
else partVdata=(float*)malloc(maxTextures*12*4);
partCdata=(float*)malloc(maxTextures*24*4);
partTdata=(float*)malloc(maxTextures*12*4);
tilesize=numberoftiles;
tilesx=(float)(1.0f/numberoftiles);
}
void Draw(int id,float x,float y,float z,float scalex,float scaley,float angle,float r,float g,float b,float a)
{
angle*=0.017453f;
for(int c2=0;c2<12;c2+=2)
{
float x=squarevData[c2]*scalex;
float y=squarevData[c2+1]*scaley;
float cos1=cos(angle);
float sin1=sin(angle);
squarevData2[c2] = (cos1*x) - ( sin1*y);
squarevData2[c2+1] = (sin1*x) + ( cos1*y);
}
//up left
partVdata[counter1++]=x+squarevData2[0];
partVdata[counter1++]=y+squarevData2[1];
if(isz)partVdata[counter1++]=z;
partCdata[counter2++]=r;
partCdata[counter2++]=g;
partCdata[counter2++]=b;
partCdata[counter2++]=a;
partTdata[counter3++]=tilesx*id;
partTdata[counter3++]=1;
//up right
partVdata[counter1++]=x+squarevData2[2];
partVdata[counter1++]=y+squarevData2[3];
if(isz)partVdata[counter1++]=z;
partCdata[counter2++]=r;
partCdata[counter2++]=g;
partCdata[counter2++]=b;
partCdata[counter2++]=a;
partTdata[counter3++]=tilesx*id+tilesx;
partTdata[counter3++]=1;
//down left
partVdata[counter1++]=x+squarevData2[4];
partVdata[counter1++]=y+squarevData2[5];
if(isz)partVdata[counter1++]=z;
partCdata[counter2++]=r;
partCdata[counter2++]=g;
partCdata[counter2++]=b;
partCdata[counter2++]=a;
partTdata[counter3++]=tilesx*id;
partTdata[counter3++]=0;
//up right
partVdata[counter1++]=x+squarevData2[6];
partVdata[counter1++]=y+squarevData2[7];
if(isz)partVdata[counter1++]=z;
partCdata[counter2++]=r;
partCdata[counter2++]=g;
partCdata[counter2++]=b;
partCdata[counter2++]=a;
partTdata[counter3++]=tilesx*id+tilesx;
partTdata[counter3++]=1;
//down right
partVdata[counter1++]=x+squarevData2[8];
partVdata[counter1++]=y+squarevData2[9];
if(isz)partVdata[counter1++]=z;
partCdata[counter2++]=r;
partCdata[counter2++]=g;
partCdata[counter2++]=b;
partCdata[counter2++]=a;
partTdata[counter3++]=tilesx*id+tilesx;
partTdata[counter3++]=0;
//down left
partVdata[counter1++]=x+squarevData2[10];
partVdata[counter1++]=y+squarevData2[11];
if(isz)partVdata[counter1++]=z;
partCdata[counter2++]=r;
partCdata[counter2++]=g;
partCdata[counter2++]=b;
partCdata[counter2++]=a;
partTdata[counter3++]=tilesx*id;
partTdata[counter3++]=0;
count++;
}
void RenderStart()
{
counter1=counter2=count=counter3=0;
}
void RenderStop(int textureid)
{
glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,GL_MODULATE);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glBindTexture(GL_TEXTURE_2D, textureid);
glTexCoordPointer(2, GL_FLOAT, 0, partTdata);
glColorPointer(4, GL_FLOAT, 0,partCdata );
if(isz)glVertexPointer(3, GL_FLOAT, 0, partVdata);
else glVertexPointer(2, GL_FLOAT, 0, partVdata);
glDrawArrays(GL_TRIANGLES, 0, count*6);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
}
};
gltAtlasRenderer ar=new gltAtlasRenderer(100,false,5);//max textures, is there z,max textures in texture
ar.RenderStart();
void Render()
{
for(int c=0;c<100;c++)ar.Draw(0,x,y,z,scalex,scaley,rotation,r,g,b,a);
}
ar.RenderStop(textureid);
2)如果我理解正确你想要使用纹理坐标与纹理的大小(而不是0到1的比例)
例如,在纹理512x512中,纹理坐标将是
float cv(float maxsize,float num)
{
return (num/maxsize);
}
cv(0),cv(0)//bot,left
cv(512),cv(0)//bot,right
cv(512),cv(512)//top,right
cv(0),cv(512)//bot,left