Rendering multiple textures at different points on screen without using point sprites

后端 未结 2 1333
后悔当初
后悔当初 2020-12-20 07:55

I\'m building an ios drawing app and am having a hard time how to draw paint textures on the screen at different points. Most tutorials online refer to rendering a single te

相关标签:
2条回答
  • 2020-12-20 08:41

    I finally got this to work. I drew each point where the user touches as a TRIANGLE_STRIP primitive, two of which together result in a square.

        GLfloat *tBuffer = malloc(4 * 2 * sizeof(GLfloat));
        tBuffer[0] = 0.0;
        tBuffer[1] = 1.0;
        tBuffer[2] = 1.0;
        tBuffer[3] = 1.0;
        tBuffer[4] = 0.0;
        tBuffer[5] = 0.0;
        tBuffer[6] = 1.0;
        tBuffer[7] = 0.0;
        glTexCoordPointer(2, GL_FLOAT, 0, tBuffer);
    
        CGFloat padding = 16;
        vBuffer[0] = xCenter - padding;
        vBuffer[1] = yCenter - padding;
    
        vBuffer[2] = xCenter + padding;
        vBuffer[3] = yCenter - padding;
    
        vBuffer[4] = xCenter - padding;
        vBuffer[5] = yCenter + padding;
    
        vBuffer[6] = xCenter + padding;
        vBuffer[7] = yCenter + padding;
    
        CGFloat degrees = atan2(end.y - start.y, end.x - start.x) * 180 / M_PI;
    
        // rotate the texture in the direction of the stroke.
        glMatrixMode(GL_TEXTURE);
        glPushMatrix();
        glTranslatef(0.5, 0.5, 0);
        glRotatef(degrees, 0, 0, 1);
        glTranslatef(-0.5, -0.5, 0);
        glVertexPointer(2, GL_FLOAT, 0, vBuffer);
        glDrawArrays(GL_TRIANGLE_STRIP, 0, count);
        glPopMatrix();
        glMatrixMode(GL_MODELVIEW);
    

    xCenter, yCenter is where the user touches. Padding determines the size of the primitive.

    I also rotate the texture, but translate it to the center before rotating since rotation happens with the pivot at the origin otherwise.

    Hope this helps!

    UPDATE:

    I was able to reduce the number of openGL calls by 1 by running the following set of commands for rotation instead:

    Note that I was able to reduce the number of OpenGL calls by 1, by running the following set of commands for the rotation (removing push/pop matrix)

        glMatrixMode(GL_TEXTURE);
        glLoadIdentity();
        glTranslatef(0.5, 0.5, 0);
        [GLManager rotateBrush:degrees];
        glTranslatef(-0.5, -0.5, 0);
        [GLManager drawVertexBuffer:vBuffer withVertexNumber:4];
        glMatrixMode(GL_MODELVIEW);`
    
    0 讨论(0)
  • 2020-12-20 08:56

    If i understand correct you want to draw many textures (same image) at points that the user touched the screen . For my particle system i use this:

    float squarevData[12]={
            -1,1,
            1,1,
            -1,-1,
            1,1,
            1,-1,
            -1,-1,
        };
    float squarevData2[12]={
            -1,1,
            1,1,
            -1,-1,
            1,1,
            1,-1,
            -1,-1,
        };
    class BatchRenderer
    {
    public:
        float* partVdata;
        float* partCdata;
        float* partTdata;
    
        int counter1,counter2,counter3;
        int count;
        bool isz;
        BatchRenderer(int maxTextures,bool iszi)
        {
            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);
        }
    
        void Draw(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);
            }
    
            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++]=0;
            partTdata[counter3++]=1;
    
    
            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++]=1;
            partTdata[counter3++]=1;
    
            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++]=0;
            partTdata[counter3++]=0;
    
            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++]=1;
            partTdata[counter3++]=1;
    
            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++]=1;
            partTdata[counter3++]=0;
    
            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++]=0;
            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);
    
        }
    };
    

    How to use it?

    BatchRenderer* br=new BatchRenderer(500,false)//the max number of textures that can be drawn , and if you want z axis
    
    void Render()
    {
          br->RenderStart();
          for(int c=0;c<POINTS;c++)
          {                          
        br->Draw(p[c].x,p[c].y,0,p[c].scalex,p[c].scaly,p[c].angle,p[c].r,p[c].g,p[c].b,p[c].a);
          }
          br->RenderStop(yourtextureid);
    
    }
    

    You can draw more than 500 textures in 60 fps with a mid device and you can have unique scale,rotation and color for each

    0 讨论(0)
提交回复
热议问题