我正在尝试制作沙盒(Voxel),开放世界的游戏。我的游戏使用称为块的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中使用双打,使用浮点数!
答案 0 :(得分:4)
考虑实现交错的VBO而不是单独存储数据。这应该会改善性能。