【问题标题】:Rendering multiple sprites from a single OpenGL ES texture从单个 OpenGL ES 纹理渲染多个精灵
【发布时间】:2012-08-11 19:49:04
【问题描述】:

我是 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);
}

【问题讨论】:

    标签: ios opengl-es


    【解决方案1】:

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多