Attempted performance tweaks (caching, etc)
This commit is contained in:
parent
4ced329a47
commit
716ed65f70
@ -1,6 +1,7 @@
|
||||
package electrosphere.game.cell;
|
||||
|
||||
import electrosphere.game.terrain.TerrainManager;
|
||||
import electrosphere.renderer.ShaderProgram;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
@ -26,11 +27,13 @@ public class CellManager {
|
||||
boolean[][] updateable;
|
||||
|
||||
|
||||
ShaderProgram program;
|
||||
|
||||
|
||||
int drawRadius = 5;
|
||||
|
||||
int drawRadius = 1;
|
||||
int drawStepdownInterval = 2;
|
||||
int drawStepdownValue = 10;
|
||||
int drawStepdownValue = 20;
|
||||
|
||||
public CellManager(TerrainManager terrainManager, float realX, float realY){
|
||||
this.terrainManager = terrainManager;
|
||||
@ -48,6 +51,8 @@ public class CellManager {
|
||||
}
|
||||
cellX = transformRealSpaceToCellSpace(realX);
|
||||
cellY = transformRealSpaceToCellSpace(realY);
|
||||
|
||||
program = ShaderProgram.smart_assemble_shader(false, true);
|
||||
}
|
||||
|
||||
public int getCellX(){
|
||||
@ -98,7 +103,8 @@ public class CellManager {
|
||||
terrainManager.getAugmentedChunkWidth(),
|
||||
currentCellX,
|
||||
currentCellY,
|
||||
terrainManager.getChunkWidth()
|
||||
terrainManager.getChunkWidth(),
|
||||
program
|
||||
);
|
||||
}
|
||||
valid[targetX][targetY] = true;
|
||||
@ -135,7 +141,10 @@ public class CellManager {
|
||||
currentCellY < terrainManager.getWorldDiscreteSize()
|
||||
){
|
||||
int dist = Math.abs(targetX - drawRadius) * Math.abs(targetY - drawRadius);
|
||||
int stride = 20;//Math.max(100, dist / drawStepdownInterval * drawStepdownValue);
|
||||
int stride = Math.min(100, Math.max(3, dist / drawStepdownInterval * drawStepdownValue));
|
||||
while(terrainManager.getChunkWidth() % stride != 0){
|
||||
stride = stride + 1;
|
||||
}
|
||||
cells[targetX][targetY].generateDrawableEntity(stride);
|
||||
}
|
||||
drawable[targetX][targetY] = true;
|
||||
@ -170,7 +179,10 @@ public class CellManager {
|
||||
currentCellY < terrainManager.getWorldDiscreteSize()
|
||||
){
|
||||
int dist = Math.abs(targetX - drawRadius) * Math.abs(targetY - drawRadius);
|
||||
int stride = 20;//Math.max(100, dist / drawStepdownInterval * drawStepdownValue);
|
||||
int stride = Math.min(100, Math.max(1, dist / drawStepdownInterval * drawStepdownValue));
|
||||
while(terrainManager.getChunkWidth() % stride != 0){
|
||||
stride = stride + 1;
|
||||
}
|
||||
cells[targetX][targetY].generateDrawableEntity(stride);
|
||||
}
|
||||
updateable[targetX][targetY] = false;
|
||||
|
||||
@ -5,6 +5,7 @@ import electrosphere.entity.EntityUtil;
|
||||
import electrosphere.main.Globals;
|
||||
import electrosphere.renderer.Model;
|
||||
import electrosphere.renderer.ModelUtils;
|
||||
import electrosphere.renderer.ShaderProgram;
|
||||
import electrosphere.util.Utilities;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
@ -23,12 +24,15 @@ public class DrawCell {
|
||||
|
||||
Entity modelEntity;
|
||||
|
||||
public DrawCell(float[][] drawArray, int drawWidth, int cellX, int cellY, int cellWidth){
|
||||
ShaderProgram program;
|
||||
|
||||
public DrawCell(float[][] drawArray, int drawWidth, int cellX, int cellY, int cellWidth, ShaderProgram program){
|
||||
this.drawArray = drawArray;
|
||||
this.drawWidth = drawWidth;
|
||||
this.cellX = cellX;
|
||||
this.cellY = cellY;
|
||||
this.cellWidth = cellWidth;
|
||||
this.program = program;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -39,7 +43,7 @@ public class DrawCell {
|
||||
if(modelEntity != null){
|
||||
Globals.entityManager.deregisterEntity(modelEntity);
|
||||
}
|
||||
Model terrainModel = ModelUtils.createTerrainModel(drawArray, stride);
|
||||
Model terrainModel = ModelUtils.createTerrainModelPrecomputedShader(drawArray, program, stride);
|
||||
modelEntity = EntityUtil.spawnDrawableEntity(terrainModel);
|
||||
// System.out.println("New cell @ " + cellX * cellWidth + "," + cellY * cellWidth);
|
||||
EntityUtil.getEntityPosition(modelEntity).set(new Vector3f(cellX * cellWidth, 0, cellY * cellWidth));
|
||||
|
||||
@ -8,6 +8,8 @@ import electrosphere.util.Utilities;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -27,11 +29,21 @@ public class TerrainManager {
|
||||
TerrainModel model;
|
||||
|
||||
|
||||
//Basic idea is we associate string that contains chunk x&y with elevation
|
||||
//While we incur a penalty with converting ints -> string, think this will
|
||||
//offset regenerating the array every time we want a new one
|
||||
int cacheSize = 50;
|
||||
HashMap<String, float[][]> elevationMapCache;
|
||||
ArrayList<String> elevationMapCacheContents;
|
||||
|
||||
|
||||
|
||||
public TerrainManager(int worldSizeDiscrete, int verticalInterpolationRatio, int dynamicInterpolationRatio){
|
||||
this.worldSizeDiscrete = worldSizeDiscrete;
|
||||
this.verticalInterpolationRatio = verticalInterpolationRatio;
|
||||
this.dynamicInterpolationRatio = dynamicInterpolationRatio;
|
||||
this.elevationMapCache = new HashMap();
|
||||
this.elevationMapCacheContents = new ArrayList();
|
||||
}
|
||||
|
||||
public void generate(){
|
||||
@ -63,7 +75,21 @@ public class TerrainManager {
|
||||
}
|
||||
|
||||
public float[][] getAugmentedTerrainAtChunk(int x, int y){
|
||||
return model.getAugmentedElevationForChunk(x, y);
|
||||
String targetChunkName = x + "-" + y;
|
||||
if(elevationMapCache.containsKey(targetChunkName)){
|
||||
elevationMapCacheContents.remove(targetChunkName);
|
||||
elevationMapCacheContents.add(0, targetChunkName);
|
||||
return elevationMapCache.get(targetChunkName);
|
||||
} else {
|
||||
float[][] targetChunk = model.getAugmentedElevationForChunk(x, y);
|
||||
if(elevationMapCacheContents.size() > cacheSize){
|
||||
String oldChunk = elevationMapCacheContents.remove(elevationMapCacheContents.size() - 1);
|
||||
elevationMapCache.remove(oldChunk);
|
||||
}
|
||||
elevationMapCache.put(targetChunkName, targetChunk);
|
||||
elevationMapCacheContents.add(targetChunkName);
|
||||
return targetChunk;
|
||||
}
|
||||
}
|
||||
|
||||
public float getHeightAtPosition(float x, float y){
|
||||
|
||||
@ -364,7 +364,7 @@ public class Main {
|
||||
|
||||
static void initPlayer(){
|
||||
Globals.player = new Entity();
|
||||
Globals.player.putData("position", new Vector3f(playerStartRealX,1900f,playerStartRealY));
|
||||
Globals.player.putData("position", new Vector3f(playerStartRealX,2200f,playerStartRealY));
|
||||
|
||||
Globals.cellManager.setCellX(GL_S);
|
||||
}
|
||||
|
||||
@ -162,6 +162,171 @@ public class ModelUtils {
|
||||
return rVal;
|
||||
}
|
||||
|
||||
|
||||
public static Model createTerrainModelPrecomputedShader(float[][] heightfield, ShaderProgram program, int stride){
|
||||
Model rVal = new Model();
|
||||
rVal.meshes = new ArrayList();
|
||||
Mesh m = new Mesh();
|
||||
int width = heightfield.length;
|
||||
int height = heightfield[0].length;
|
||||
|
||||
int actualWidth = (int)Math.ceil(1.0f * width / (1.0f * stride));
|
||||
int actualHeight = (int)Math.ceil(1.0f * height / (1.0f * stride));
|
||||
|
||||
// System.out.println(actualWidth + " " + actualHeight);
|
||||
|
||||
// System.out.println((actualWidth - 1) * (actualHeight - 1));
|
||||
|
||||
FloatBuffer vertices;
|
||||
FloatBuffer normals;
|
||||
IntBuffer faces;
|
||||
FloatBuffer texture_coords;
|
||||
if(stride * actualWidth > width){
|
||||
int drawWidth = actualWidth + 1;
|
||||
int drawHeight = actualHeight + 1;
|
||||
vertices = BufferUtils.createFloatBuffer(drawWidth * drawHeight * 3);
|
||||
normals = BufferUtils.createFloatBuffer(drawWidth * drawHeight * 3);
|
||||
faces = BufferUtils.createIntBuffer((drawWidth - 1) * (drawHeight - 1) * 2 * 3);
|
||||
texture_coords = BufferUtils.createFloatBuffer(drawWidth * drawHeight * 2);
|
||||
} else {
|
||||
vertices = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 3);
|
||||
normals = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 3);
|
||||
faces = BufferUtils.createIntBuffer((actualWidth - 1) * (actualHeight - 1) * 2 * 3);
|
||||
texture_coords = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 2);
|
||||
}
|
||||
|
||||
for(int x = 0; x < width; x = x + stride){
|
||||
for(int y = 0; y < height; y = y + stride){
|
||||
//deal with vertex
|
||||
vertices.put(x);
|
||||
vertices.put(heightfield[x][y]);
|
||||
vertices.put(y);
|
||||
//deal with normal
|
||||
if(x / stride < actualWidth - 1){
|
||||
if(y / stride < actualHeight - 1){
|
||||
float hL;
|
||||
if(x > 0){
|
||||
hL = heightfield[x-1][y];
|
||||
} else {
|
||||
hL = heightfield[x][y];
|
||||
}
|
||||
float hR = heightfield[x+1][y];
|
||||
float hD = heightfield[x][y+1];
|
||||
float hU;
|
||||
if(y > 0){
|
||||
hU = heightfield[x][y-1];
|
||||
} else {
|
||||
hU = heightfield[x][y];
|
||||
}
|
||||
Vector3f Normal = new Vector3f(hL - hR, 2.0f, hD - hU);
|
||||
Normal.normalize();
|
||||
normals.put(Normal.x);
|
||||
normals.put(Normal.y);
|
||||
normals.put(Normal.z);
|
||||
} else {
|
||||
float hL;
|
||||
if(x > 0){
|
||||
hL = heightfield[x-1][y];
|
||||
} else {
|
||||
hL = heightfield[x][y];
|
||||
}
|
||||
float hR = heightfield[x+1][y];
|
||||
float hD = heightfield[x][y];
|
||||
float hU = heightfield[x][y-1];
|
||||
Vector3f Normal = new Vector3f(hL - hR, 2.0f, hD - hU);
|
||||
Normal.normalize();
|
||||
normals.put(Normal.x);
|
||||
normals.put(Normal.y);
|
||||
normals.put(Normal.z);
|
||||
}
|
||||
} else {
|
||||
if(y / stride < actualHeight - 1){
|
||||
float hL = heightfield[x-1][y];
|
||||
float hR = heightfield[x][y];
|
||||
float hD = heightfield[x][y+1];
|
||||
float hU;
|
||||
if(y > 0){
|
||||
hU = heightfield[x][y-1];
|
||||
} else {
|
||||
hU = heightfield[x][y];
|
||||
}
|
||||
Vector3f Normal = new Vector3f(hL - hR, 2.0f, hD - hU);
|
||||
Normal.normalize();
|
||||
normals.put(Normal.x);
|
||||
normals.put(Normal.y);
|
||||
normals.put(Normal.z);
|
||||
} else {
|
||||
float hL = heightfield[x-1][y];
|
||||
float hR = heightfield[x][y];
|
||||
float hD = heightfield[x][y];
|
||||
float hU = heightfield[x][y-1];
|
||||
Vector3f Normal = new Vector3f(hL - hR, 2.0f, hD - hU);
|
||||
Normal.normalize();
|
||||
normals.put(Normal.x);
|
||||
normals.put(Normal.y);
|
||||
normals.put(Normal.z);
|
||||
}
|
||||
}
|
||||
//deal with texture coordinates
|
||||
if(x / stride % 2 == 0){
|
||||
if(y / stride % 2 == 0){
|
||||
texture_coords.put(0);
|
||||
texture_coords.put(0);
|
||||
} else {
|
||||
texture_coords.put(0);
|
||||
texture_coords.put(1);
|
||||
}
|
||||
} else {
|
||||
if(y / stride % 2 == 0){
|
||||
texture_coords.put(1);
|
||||
texture_coords.put(0);
|
||||
} else {
|
||||
texture_coords.put(1);
|
||||
texture_coords.put(1);
|
||||
}
|
||||
}
|
||||
//deal with faces
|
||||
if(1.0f * x / stride < actualWidth - 1 && 1.0f * y / stride < actualHeight - 1){
|
||||
faces.put((x / stride + 0) * actualHeight + (y / stride + 0));
|
||||
faces.put((x / stride + 0) * actualHeight + (y / stride + 1));
|
||||
faces.put((x / stride + 1) * actualHeight + (y / stride + 0));
|
||||
faces.put((x / stride + 1) * actualHeight + (y / stride + 0));
|
||||
faces.put((x / stride + 0) * actualHeight + (y / stride + 1));
|
||||
faces.put((x / stride + 1) * actualHeight + (y / stride + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vertices.flip();
|
||||
normals.flip();
|
||||
faces.flip();
|
||||
texture_coords.flip();
|
||||
|
||||
m.vertexArrayObject = glGenVertexArrays();
|
||||
glBindVertexArray(m.vertexArrayObject);
|
||||
//buffer vertices
|
||||
m.buffer_vertices(vertices);
|
||||
//buffer normals
|
||||
m.buffer_normals(normals);
|
||||
//buffer faces
|
||||
m.buffer_faces(faces);
|
||||
//buffer texture coords
|
||||
m.buffer_texture_coords(texture_coords);
|
||||
m.shader = program;
|
||||
glBindVertexArray(0);
|
||||
m.parent = rVal;
|
||||
|
||||
Material groundMat = new Material();
|
||||
Texture groundTex = new Texture("Textures/Ground/Dirt1.png");
|
||||
groundMat.set_diffuse(groundTex);
|
||||
groundMat.set_specular(groundTex);
|
||||
m.set_material(groundMat);
|
||||
|
||||
rVal.meshes.add(m);
|
||||
return rVal;
|
||||
}
|
||||
|
||||
|
||||
public static Model createUnitCube(){
|
||||
Model rVal = new Model();
|
||||
rVal.meshes = new ArrayList();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user