1

サンドボックス (ボクセル) のオープンワールド ゲームを作ろうとしています。私のゲームでは、チャンクと呼ばれる 32x32x32 のブロック セットを使用してブロック データを格納します。これらにはそれぞれ、頂点、プライマリ カラー、セカンダリ カラー、テクスチャ 座標の 4 つの VBO があります。これらの VBO は、次のクラスに格納されます。

import game.vc3d.util.ArrayUtils;

import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;

import org.lwjgl.BufferUtils;

import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL14.*;

public class VBORenderer extends ImmediateModeRenderer {


FloatBuffer vertexData;
FloatBuffer primColorData;
FloatBuffer secColorData;
DoubleBuffer texCoordData;

FloatBuffer allData;

int fullVBOID;

int vboVertexID;
int vboPrimColorID;
int vboSecColorID;
int vboTexCoordID;
int amountOfVertexes = 0;
boolean fin1ed = false;

int texIndex = 0;

static final int DRAW_METHOD = GL_STATIC_DRAW;

static boolean ted = false;

int vertexEnd;
int primCStart;
int primCEnd;
int secCStart;
int secCEnd;




@Override
public void setTexture(int texture) {
    texEnabled = true;
    texIndex = texture;
}

/* (non-Javadoc)
 * @see game.vc3d.rendering.Renderer#disableTexture()
 */
@Override
public void disableTexture() {
    texEnabled = false;

}

/* (non-Javadoc)
 * @see game.vc3d.rendering.Renderer#finalize()
 */
@Override
public void finalize() {
    amountOfVertexes = vertexes.size() / 3;

    if(amountOfVertexes < 1) return;




    float tempVD[] = ArrayUtils.toPrimatives(vertexes.toArray(new Float[vertexes.size()]));
    vertexData = BufferUtils.createFloatBuffer(tempVD.length);
    vertexData.put(tempVD);

    float tempPCD[] = ArrayUtils.toPrimatives(primaryColors.toArray(new Float[vertexes.size()]));
    primColorData = BufferUtils.createFloatBuffer(tempPCD.length);
    primColorData.put(tempPCD);
    float tempSCD[] = ArrayUtils.toPrimatives(secondaryColors.toArray(new Float[vertexes.size()]));
    secColorData = BufferUtils.createFloatBuffer(tempSCD.length);
    secColorData.put(tempSCD);
    double tempTCD[] = ArrayUtils.toPrimatives(texCoords.toArray(new Double[vertexes.size()]));
    texCoordData = BufferUtils.createDoubleBuffer(tempTCD.length);
    texCoordData.put(tempTCD);

    vertexData.flip();
    primColorData.flip();
    secColorData.flip();
    texCoordData.flip();


    if(!fin1ed)vboVertexID = glGenBuffers();
    glBindBuffer(GL_ARRAY_BUFFER, vboVertexID);
    glBufferData(GL_ARRAY_BUFFER, vertexData, DRAW_METHOD);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    if(!fin1ed)vboPrimColorID = glGenBuffers();
    glBindBuffer(GL_ARRAY_BUFFER, vboPrimColorID);
    glBufferData(GL_ARRAY_BUFFER, primColorData, DRAW_METHOD);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    if(!fin1ed)vboSecColorID = glGenBuffers();
    glBindBuffer(GL_ARRAY_BUFFER, vboSecColorID);
    glBufferData(GL_ARRAY_BUFFER, secColorData, DRAW_METHOD);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    if(!fin1ed)vboTexCoordID = glGenBuffers();
    glBindBuffer(GL_ARRAY_BUFFER, vboTexCoordID);
    glBufferData(GL_ARRAY_BUFFER, texCoordData, DRAW_METHOD);
    glBindBuffer(GL_ARRAY_BUFFER, 0);




    fin1ed = true;

}


/* (non-Javadoc)
 * @see game.vc3d.rendering.Renderer#clear()
 */
@Override
public void clear() {
    super.clear();
    texIndex = 0;
}

/* (non-Javadoc)
 * @see game.vc3d.rendering.Renderer#render()
 */
@Override
public void render() {

    if(amountOfVertexes < 1) return;


    glBindBuffer(GL_ARRAY_BUFFER, vboVertexID);
    glVertexPointer(3, GL_FLOAT, 0, 0L);

    glBindBuffer(GL_ARRAY_BUFFER, vboPrimColorID);
    glColorPointer(4, GL_FLOAT, 0, 0L);

    glBindBuffer(GL_ARRAY_BUFFER, vboSecColorID);
    glSecondaryColorPointer(3, GL_FLOAT, 0, 0L);

    glBindBuffer(GL_ARRAY_BUFFER, vboTexCoordID);
    glTexCoordPointer(2, GL_DOUBLE, 0, 0L);

    glDrawArrays(GL_QUADS, 0, amountOfVertexes);

    glBindBuffer(GL_ARRAY_BUFFER, 0);




}
public static void prepareForRendering(Object...objects){
    if(objects.length > 0){
        glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D, (Integer)objects[0]);
        ted = true;
    } else {
        glDisable(GL_TEXTURE_2D);
    }

    glEnable(GL_COLOR_SUM);

    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);
    glEnableClientState(GL_SECONDARY_COLOR_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}
public static void finishRendering(){

    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_COLOR_ARRAY);
    glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);

    if(ted){
        glDisable(GL_TEXTURE_2D);
        ted = false;
    }


}

}

ImmediateModeRenderer を拡張するもの:

import java.util.ArrayList;

import org.lwjgl.opengl.GL14;
import org.lwjgl.util.vector.Vector3f;
import org.lwjgl.util.vector.Vector4f;

import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL14.glSecondaryColor3f;

public class ImmediateModeRenderer extends Renderer {

private boolean canInput = true;

public ArrayList<Float> vertexes = new ArrayList<Float>();
public ArrayList<Boolean> textures = new ArrayList<Boolean>();
public ArrayList<Float> primaryColors = new ArrayList<Float>();
public ArrayList<Float> secondaryColors = new ArrayList<Float>();
public ArrayList<Double> texCoords = new ArrayList<Double>();
public ArrayList<Integer> currentTextures = new ArrayList<Integer>();
boolean texEnabled = false;
Vector4f primColor = new Vector4f(1, 1, 1, 1);
Vector4f secColor = new Vector4f(0, 0, 0, 0);
double texX = 0;
double texY = 0;
int currentTex = 0;
Vector3f _trans = new Vector3f(0, 0, 0);
Vector3f _scale = new Vector3f(1, 1, 1);


/* (non-Javadoc)
 * @see game.vc3d.rendering.Renderer#addVertex(float, float, float)
 */
@Override
public void addVertex(float x, float y, float z) {
    if(!canInput) throw new IllegalStateException("this.canInput() must be true");
    vertexes.add((x + _trans.x) * _scale.x);
    vertexes.add((y + _trans.y) * _scale.y);
    vertexes.add((z + _trans.z) * _scale.z);
    textures.add(texEnabled);
    if(texEnabled){
        texCoords.add(texX);
        texCoords.add(texY);
        currentTextures.add(currentTex);
    }
    primaryColors.add(primColor.x);
    primaryColors.add(primColor.y);
    primaryColors.add(primColor.z);
    primaryColors.add(primColor.w);
    secondaryColors.add(secColor.x);
    secondaryColors.add(secColor.y);
    secondaryColors.add(secColor.z);
    //secondaryColors.add(secColor.w);

}

/* (non-Javadoc)
 * @see game.vc3d.rendering.Renderer#primaryColor(float, float, float, float)
 */
@Override
public void primaryColor(float r, float g, float b, float a) {
    primColor = new Vector4f(r, g, b, a);

}

/* (non-Javadoc)
 * @see game.vc3d.rendering.Renderer#setTexture(int)
 */
@Override
public void setTexture(int texture) {
    texEnabled = true;
    currentTex = texture;

}

/* (non-Javadoc)
 * @see game.vc3d.rendering.Renderer#texture(float, float)
 */
@Override
public void texture(double x, double y) {
    texX = x;
    texY = y;

}

/* (non-Javadoc)
 * @see game.vc3d.rendering.Renderer#secondaryColor(float, float, float, float)
 */
@Override
public void secondaryColor(float r, float g, float b, float a) {
    secColor = new Vector4f(r, g, b, a);

}

/* (non-Javadoc)
 * @see game.vc3d.rendering.Renderer#disableTexture()
 */
@Override
public void disableTexture() {
    texEnabled = true;

}

/* (non-Javadoc)
 * @see game.vc3d.rendering.Renderer#clear()
 */
@Override
public void clear() {
    vertexes = new ArrayList<Float>();
    textures = new ArrayList<Boolean>();
    primaryColors = new ArrayList<Float>();
    secondaryColors = new ArrayList<Float>();
    texCoords = new ArrayList<Double>();
    currentTextures = new ArrayList<Integer>();
    texEnabled = false;
    primColor = new Vector4f(1, 1, 1, 1);
    secColor = new Vector4f(0, 0, 0, 0);
    texX = 0;
    texY = 0;
    currentTex = 0;

    _trans = new Vector3f(0, 0, 0);
    _scale = new Vector3f(1, 1, 1);

    canInput = true;

}

/* (non-Javadoc)
 * @see game.vc3d.rendering.Renderer#render()
 */
@Override
public void render() {
    int amountOfVertexs = vertexes.size() / 3;
    int currentV = -1;
    int currentPC = -1;
    int currentSC = -1;
    int currentTex = -1; //Current Tex Coords
    int texInd = -1; //Current Texture No.
    int texNoInd = -1; //Curent vert
    int oldBoundTexture = 0; //Old texture
    boolean oldTex = false;
    glDisable(GL_TEXTURE_2D);
    glEnable(GL14.GL_COLOR_SUM);
    glBegin(GL_QUADS);
    for(int vert = 0; vert < amountOfVertexs; vert++){
        if(textures.get(++texNoInd)){
            if(!oldTex){
                glEnd();
                glEnable(GL_TEXTURE_2D);
                glBegin(GL_QUADS);
            }
            if(currentTextures.get(++texInd) != oldBoundTexture){
                glEnd();
                oldBoundTexture = currentTextures.get(texInd);
                glBindTexture(GL_TEXTURE_2D, oldBoundTexture);
                glBegin(GL_QUADS);
            }

            glTexCoord2d(texCoords.get(++currentTex), texCoords.get(++currentTex));


        } else {
            if(oldTex){
                glEnd();
                glDisable(GL_TEXTURE_2D);
                glBegin(GL_QUADS);
            }
        }
        oldTex = textures.get(texNoInd);

        //Do Colors
        glColor4f(primaryColors.get(++currentPC), primaryColors.get(++currentPC), primaryColors.get(++currentPC), primaryColors.get(++currentPC));
        glSecondaryColor3f(secondaryColors.get(++currentSC), secondaryColors.get(++currentSC), secondaryColors.get(++currentSC));
        //Finalize the vertex
        glVertex3f(vertexes.get(++currentV), vertexes.get(++currentV), vertexes.get(++currentV));
    }
    glEnd();
    glDisable(GL14.GL_COLOR_SUM);
}

/* (non-Javadoc)
 * @see game.vc3d.rendering.Renderer#finalize()
 */
@Override
public void finalize() {
    canInput = false;

}

/* (non-Javadoc)
 * @see game.vc3d.rendering.Renderer#canInput()
 */
@Override
public boolean canInput() {
    return canInput;
}

/* (non-Javadoc)
 * @see game.vc3d.rendering.Renderer#scale(float, float, float)
 */
@Override
public void scale(float x, float y, float z) {
    _scale = new Vector3f(x, y, z);

}

/* (non-Javadoc)
 * @see game.vc3d.rendering.Renderer#translate(float, float, float)
 */
@Override
public void translate(float x, float y, float z) {
    _trans = new Vector3f(x, y, z);

}

}

開始および停止する静的メソッドは、ワールド クラスから呼び出され、チャンクの描画を準備し、チャンクの描画を終了します。

編集:問題は修正されました!VBO の内容に double を使用しないでください。float を使用してください。

4

1 に答える 1

4

データを個別に保存する代わりに、インターリーブされた VBO を実装することを検討してください。これにより、パフォーマンスが少し向上するはずです。

于 2012-06-29T15:42:19.707 に答える