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