Reutilización textura y vértices en OpenGL

Oscar Sjöstedt:

Estoy tratando de hacer un simple juego en 2D, y almaceno el mundo en una matriz 2D del bloque (una enumeración, con cada valor que tiene su textura).

Dado que estos son todos los azulejos opacos simples, al visualizarse en cierto modo me ellas por la textura y luego los hacen mediante la traducción a su coordenadas. Sin embargo, también necesito para especificar las coordenadas de textura y el vértice de cada baldosa que dibujo, a pesar de que estos también son los mismos.

Esto es lo que tengo actualmente:

public static void render() {
    // Sorting...
    for(SolidBlock block : xValues.keySet()) {
        block.getTexture().bind();
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

        for(int coordinateIndex = 0; coordinateIndex < xValues.get(block).size(); coordinateIndex++) {
            int x = xValues.get(block).get(coordinateIndex);
            int y = yValues.get(block).get(coordinateIndex);
            glTranslatef(x, y, Integer.MIN_VALUE);
            // Here I use MIN_VALUE because I'll later have to do z sorting with other tiles
            glBegin(GL_QUADS);
            loadModel();
            glEnd();
            glLoadIdentity();
        }

        xValues.get(block).clear();
        yValues.get(block).clear();
    }
}

private static void loadModel() {
    glTexCoord2f(0, 0);
    glVertex2f(0, 0);
    glTexCoord2f(1, 0);
    glVertex2f(1, 0);
    glTexCoord2f(1, 1);
    glVertex2f(1, 1);
    glTexCoord2f(0, 1);
    glVertex2f(0, 1);
}

Me gustaría saber si es posible poner loadModel () antes de que el bucle principal, para no tener que cargar el modelo miles de veces con los mismos datos, y también qué otra cosa podía ser movido para que sea lo más rápido posible!

magma:

Algunas optimizaciones rápidas:

  • glTexParameterisolo necesita ser llamada una vez por parámetro por la textura. Usted debe poner en la parte de su código donde se cargan las texturas.
  • Puede dibujar varios quads en uno glBegin/ glEndpar simplemente añadiendo más vértices. Sin embargo, no se puede hacer ninguna coordinar cambios entre glBeginy glEnd(como glTranslatefo glLoadIdentityo glPushMatrix) por lo que tendrá que pasar xy yque su loadModelfunción (que en realidad debería llamarse addQuadde precisión). Asimismo, no está permitido volver a enlazar entre texturas glBegin/ glEnd, por lo que tendrá que utilizar un conjunto de glBegin/ glEndpor la textura.
  • Menor, pero en lugar de llamar xValues.get(block)a un montón de veces, sólo decir List<Integer> blockXValues = xValues.get(block)al comienzo de su lazo externo y luego utilizar blockXValuesa partir de ahí.

Algunas optimizaciones más involucrados:

  • Legado OpenGL tiene listas de sorteo, que son básicamente macros para OpenGL. Usted puede hacer todo el registro de OpenGL OpenGL llama que está haciendo entre glNewListy glEndList(con algunas excepciones), y almacenarlos de alguna manera. La próxima vez que desee ejecutar esas llamadas exactas OpenGL, se puede utilizar glCallListpara hacer OpenGL hacer eso para usted. Algunas optimizaciones se hará sobre la lista de sorteo con el fin de acelerar los sorteos posteriores.
  • Textura de conmutación es relativamente caro, que ya se encuentra probablemente ha dado cuenta desde la ordenó su quads por la textura, pero no hay una solución mejor que las texturas de clasificación: Ponga todos sus texturas en un único atlas de textura . Usted querrá guardar las coordenadas subtexture de cada bloque dentro de sus SolidBlocks, y luego pasa blocka addQuadasí para que pueda pasar las coordenadas apropiadas para subtexture glTexCoord2f. Una vez que hayas hecho esto, no es necesario para ordenar por la textura más y sólo puede iterar sobre coordenadas X e Y.

Buenas practicas:

  • Utilice sólo glLoadIdentityuna vez por cuadro, al comienzo de su proceso de sorteo. A continuación, utilice glPushMatrixemparejado con glPopMatrixguardar y restaurar el estado de las matrices. De esta manera las partes internas de su código no necesita saber acerca de las transformaciones de matriz las partes exteriores pueden o no pueden haber hecho de antemano.
  • No utilice Integer.MIN_VALUEcomo un vértice de coordenadas. Utilizar una constante de su propia elección, de preferencia uno que no hará que su rango de profundidad enorme (los dos últimos argumentos a glOrthoque supongo que está utilizando). Precisión buffer de profundidad está limitada, se encontrará con problemas de extinción de Z si intenta coordenadas uso Z de 1 o 2 o así después de establecer su rango de Z Integer.MIN_VALUEa Integer.MAX_VALUE. Además, se está utilizando floatcoordenadas, por lo que intlas constantes no tienen sentido aquí de todos modos.

Aquí está el código después de un pase rápido (sin la textura del atlas de cambios):

private static final float BLOCK_Z_DEPTH = -1; // change to whatever works for you
private int blockCallList;
private boolean regenerateBlockCallList; // set to true whenever you need to update some blocks

public static void init() {
    blockCallList = glGenLists(1);
    regenerateBlockCallList = true;
}

public static void render() {
    if (regenerateBlockCallList) {
        glNewList(blockCallList, GL_COMPILE_AND_EXECUTE);
        drawBlocks();
        glEndList();

        regenerateBlockCallList = false;
    } else {
        glCallList(blockCallList);
    }
}

private static void drawBlocks() {
    // Sorting...

    glPushMatrix();
    glTranslatef(0, 0, BLOCK_Z_DEPTH);

    for (SolidBlock block : xValues.keySet()) {
        List<Integer> blockXValues = xValues.get(block);
        List<Integer> blockYValues = yValues.get(block);

        block.getTexture().bind();
        glBegin(GL_QUADS);
        for(int coordinateIndex = 0; coordinateIndex < blockXValues.size(); coordinateIndex++) {
            int x = blockXValues.get(coordinateIndex);
            int y = blockYValues.get(coordinateIndex);
            addQuad(x,y);
        }
        glEnd();

        blockXValues.clear();
        blockYValues.clear();
    }

    glPopMatrix();

}

private static void addQuad(float x, float y) {
    glTexCoord2f(0, 0);
    glVertex2f(x, y);
    glTexCoord2f(1, 0);
    glVertex2f(x+1, y);
    glTexCoord2f(1, 1);
    glVertex2f(x+1, y+1);
    glTexCoord2f(0, 1);
    glVertex2f(x, y+1);
}

Con OpenGL moderna (buffers de vértices, shaders y la creación de instancias en lugar de las listas de visualización, transformaciones de matriz y pasando vértices uno por uno) que le acerque a este problema de manera muy diferente, pero lo tendré más allá del alcance de mi respuesta.

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=334522&siteId=1
Recomendado
Clasificación