Exemple #1
0
void QuadRenderer::initializeGraphicsResources()
{
    LOOM_PROFILE_SCOPE(quadInit);

    lmLogInfo(gGFXQuadRendererLogGroup, "Initializing Graphics Resources");

    GL_Context* ctx = Graphics::context();

    // create the single initial vertex buffer
    ctx->glGenBuffers(1, &vertexBufferId);
    ctx->glBindBuffer(GL_ARRAY_BUFFER, vertexBufferId);
    ctx->glBufferData(GL_ARRAY_BUFFER, MAXBATCHQUADS * 4 * sizeof(VertexPosColorTex), 0, GL_STREAM_DRAW);
    ctx->glBindBuffer(GL_ARRAY_BUFFER, 0);

    // create the single, reused index buffer
    ctx->glGenBuffers(1, &indexBufferId);
    ctx->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferId);
    uint16_t *pIndex = (uint16_t*)lmAlloc(gQuadMemoryAllocator, sizeof(unsigned short) * 6 * MAXBATCHQUADS);
    uint16_t *pStart = pIndex;

    int j = 0;
    for (int i = 0; i < 6 * MAXBATCHQUADS; i += 6, j += 4, pIndex += 6)
    {
        pIndex[0] = j;
        pIndex[1] = j + 2;
        pIndex[2] = j + 1;
        pIndex[3] = j + 1;
        pIndex[4] = j + 2;
        pIndex[5] = j + 3;
    }

    ctx->glBufferData(GL_ELEMENT_ARRAY_BUFFER, MAXBATCHQUADS * 6 * sizeof(uint16_t), pStart, GL_STREAM_DRAW);
    ctx->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

    lmFree(gQuadMemoryAllocator, pStart);

    // Create the system memory buffer for quads.
    batchedVertices = static_cast<VertexPosColorTex*>(lmAlloc(gQuadMemoryAllocator, MAXBATCHQUADS * 4 * sizeof(VertexPosColorTex)));
}
Exemple #2
0
void QuadRenderer::submit()
{
    LOOM_PROFILE_SCOPE(quadSubmit);

    if (batchedVertexCount <= 0)
    {
        return;
    }

    numFrameSubmit++;

    TextureInfo &tinfo = *Texture::getTextureInfo(currentTexture);

    if (tinfo.handle != -1)
    {
        if (tinfo.visible) {

            GL_Context* ctx = Graphics::context();

            // On iPad 1, the PosColorTex shader, which multiplies texture color with
            // vertex color, is 5x slower than PosTex, which just draws the texture
            // unmodified. So we select the shader to use appropriately.

            //lmLogInfo(gGFXQuadRendererLogGroup, "Handle > %u", tinfo.handle);

            if (!Graphics_IsGLStateValid(GFX_OPENGL_STATE_QUAD))
            {
                sShaderStateValid = false;
                sTextureStateValid = false;
                sBlendStateValid = false;
            }
            
            ctx->glBindBuffer(GL_ARRAY_BUFFER, vertexBufferId);
            
            if (!sShaderStateValid)
            {
                Loom2D::Matrix mvp;
                mvp.copyFromMatrix4(Graphics::getMVP());
                sCurrentShader->setMVP(mvp);
                sCurrentShader->setTextureId(0);
                sCurrentShader->bind();

                sShaderStateValid = true;
            }
            
            if (!sTextureStateValid)
            {
                // Set up texture state.
                ctx->glActiveTexture(GL_TEXTURE0);
                ctx->glBindTexture(GL_TEXTURE_2D, tinfo.handle);

                if (tinfo.clampOnly) {
                    tinfo.wrapU = TEXTUREINFO_WRAP_CLAMP;
                    tinfo.wrapV = TEXTUREINFO_WRAP_CLAMP;
                }

                switch (tinfo.wrapU)
                {
                    case TEXTUREINFO_WRAP_CLAMP:
                        ctx->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
                        break;
                    case TEXTUREINFO_WRAP_MIRROR:
                        ctx->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
                        break;
                    case TEXTUREINFO_WRAP_REPEAT:
                        ctx->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
                        break;
                    default:
                        lmAssert(false, "Unsupported wrapU: %d", tinfo.wrapU);
                }
                switch (tinfo.wrapV)
                {
                    case TEXTUREINFO_WRAP_CLAMP:
                        ctx->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
                        break;
                    case TEXTUREINFO_WRAP_MIRROR:
                        ctx->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
                        break;
                    case TEXTUREINFO_WRAP_REPEAT:
                        ctx->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
                        break;
                    default:
                        lmAssert(false, "Unsupported wrapV: %d", tinfo.wrapV);
                }
                //*/

                switch (tinfo.smoothing)
                {
                    case TEXTUREINFO_SMOOTHING_NONE:
                        ctx->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, tinfo.mipmaps ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST);
                        ctx->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
                        break;
                    case TEXTUREINFO_SMOOTHING_BILINEAR:
                        ctx->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, tinfo.mipmaps ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR);
                        ctx->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
                        break;
                    default:
                        lmAssert(false, "Unsupported smoothing: %d", tinfo.smoothing);
                }
                
                sTextureStateValid = true;
            }

            if (!sBlendStateValid)
            {
                if (sBlendEnabled)
                {
                    ctx->glEnable(GL_BLEND);
                    ctx->glBlendFuncSeparate(sSrcBlend, sDstBlend, sSrcBlend, sDstBlend);
                }
                else
                {
                    ctx->glDisable(GL_BLEND);
                }

                sBlendStateValid = true;
            }
            
            Graphics_SetCurrentGLState(GFX_OPENGL_STATE_QUAD);
            
            // Setting the buffer to null supposedly enables better performance because it enables the driver to do some optimizations.
            ctx->glBufferData(GL_ARRAY_BUFFER, batchedVertexCount*sizeof(VertexPosColorTex), NULL, GL_STREAM_DRAW);
            ctx->glBufferData(GL_ARRAY_BUFFER, batchedVertexCount*sizeof(VertexPosColorTex), batchedVertices, GL_STREAM_DRAW);

            // And bind indices and draw.
            ctx->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferId);
            ctx->glDrawElements(GL_TRIANGLES,
                                                (GLsizei)(batchedVertexCount / 4 * 6), GL_UNSIGNED_SHORT,
                                                nullptr);
        }
    }
    
    batchedVertexCount = 0;
}