clustering terrain draw calls
This commit is contained in:
parent
44ae9909ee
commit
7d04008197
Binary file not shown.
@ -1972,6 +1972,7 @@ Performance improvements
|
||||
- AI does not simulate for low-lod server entities
|
||||
- Nearby entity lookup caching per frame
|
||||
- Far-away entities do not spawn physics by default
|
||||
- Clustering terrain draw calls
|
||||
Lod emitter service checker function
|
||||
Mesh profiling
|
||||
|
||||
|
||||
@ -47,6 +47,7 @@ public class EntityDataStrings {
|
||||
Terrain Entity
|
||||
*/
|
||||
public static final String TERRAIN_IS_TERRAIN = "terrainEntity";
|
||||
public static final String BLOCK_ENTITY = "blockEntity";
|
||||
public static final String CORRESPONDING_DRAW_CELL = "correspondingDrawCell";
|
||||
|
||||
/*
|
||||
|
||||
@ -113,6 +113,7 @@ public class BlockChunkEntity {
|
||||
}
|
||||
}
|
||||
solidsEnt.putData(EntityDataStrings.TERRAIN_IS_TERRAIN, true);
|
||||
solidsEnt.putData(EntityDataStrings.BLOCK_ENTITY, true);
|
||||
rVal.add(solidsEnt);
|
||||
|
||||
//
|
||||
@ -165,6 +166,7 @@ public class BlockChunkEntity {
|
||||
}
|
||||
}
|
||||
transparentEnt.putData(EntityDataStrings.TERRAIN_IS_TERRAIN, true);
|
||||
transparentEnt.putData(EntityDataStrings.BLOCK_ENTITY, true);
|
||||
rVal.add(transparentEnt);
|
||||
|
||||
|
||||
@ -189,6 +191,7 @@ public class BlockChunkEntity {
|
||||
Quaterniond entityRot = EntityUtils.getRotation(entity);
|
||||
PhysicsUtils.setGeomTransform(realm.getCollisionEngine(), entityPos, entityRot, terrainCollider);
|
||||
entity.putData(EntityDataStrings.TERRAIN_IS_TERRAIN, true);
|
||||
entity.putData(EntityDataStrings.BLOCK_ENTITY, true);
|
||||
CommonEntityUtils.setEntityType(entity, EntityType.ENGINE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -163,4 +163,13 @@ public class TerrainChunk {
|
||||
return entity.containsKey(EntityDataStrings.TERRAIN_IS_TERRAIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this is a block entity
|
||||
* @param entity The entity
|
||||
* @return True if it is a block entity, false otherwise
|
||||
*/
|
||||
public static boolean isBlockEntity(Entity entity){
|
||||
return entity.containsKey(EntityDataStrings.BLOCK_ENTITY);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -139,6 +139,52 @@ public class MainContentPipeline implements RenderPipeline {
|
||||
}
|
||||
}
|
||||
}
|
||||
for(Entity currentEntity : this.drawTargetAccumulator.getTerrainEntities()){
|
||||
Vector3d position = EntityUtils.getPosition(currentEntity);
|
||||
if(
|
||||
currentEntity.getData(EntityDataStrings.DATA_STRING_DRAW)!=null
|
||||
){
|
||||
//fetch actor
|
||||
Actor currentActor = EntityUtils.getActor(currentEntity);
|
||||
//calculate camera-modified vector3d
|
||||
Vector3d cameraCenter = scaleVec.set(cameraCenterVec);
|
||||
Vector3d cameraModifiedPosition = positionVec.set(position).sub(cameraCenter);
|
||||
//calculate and apply model transform
|
||||
modelTransformMatrix = modelTransformMatrix.identity();
|
||||
modelTransformMatrix.translate(cameraModifiedPosition);
|
||||
modelTransformMatrix.rotate(EntityUtils.getRotation(currentEntity));
|
||||
modelTransformMatrix.scale(scaleVec.set(EntityUtils.getScale(currentEntity)));
|
||||
currentActor.applySpatialData(new Matrix4d(modelTransformMatrix),new Vector3d(position));
|
||||
//draw
|
||||
currentActor.draw(renderPipelineState,openGLState);
|
||||
|
||||
//tracking
|
||||
this.terrainChunks++;
|
||||
}
|
||||
}
|
||||
for(Entity currentEntity : this.drawTargetAccumulator.getBlockEntities()){
|
||||
Vector3d position = EntityUtils.getPosition(currentEntity);
|
||||
if(
|
||||
currentEntity.getData(EntityDataStrings.DATA_STRING_DRAW)!=null
|
||||
){
|
||||
//fetch actor
|
||||
Actor currentActor = EntityUtils.getActor(currentEntity);
|
||||
//calculate camera-modified vector3d
|
||||
Vector3d cameraCenter = scaleVec.set(cameraCenterVec);
|
||||
Vector3d cameraModifiedPosition = positionVec.set(position).sub(cameraCenter);
|
||||
//calculate and apply model transform
|
||||
modelTransformMatrix = modelTransformMatrix.identity();
|
||||
modelTransformMatrix.translate(cameraModifiedPosition);
|
||||
modelTransformMatrix.rotate(EntityUtils.getRotation(currentEntity));
|
||||
modelTransformMatrix.scale(scaleVec.set(EntityUtils.getScale(currentEntity)));
|
||||
currentActor.applySpatialData(new Matrix4d(modelTransformMatrix),new Vector3d(position));
|
||||
//draw
|
||||
currentActor.draw(renderPipelineState,openGLState);
|
||||
|
||||
//tracking
|
||||
this.terrainChunks++;
|
||||
}
|
||||
}
|
||||
renderPipelineState.setUseBones(true);
|
||||
Globals.profiler.endCpuSample();
|
||||
Globals.profiler.beginCpuSample("MainContentPipeline.render - Solids Foliage");
|
||||
|
||||
@ -164,6 +164,46 @@ public class ShadowMapPipeline implements RenderPipeline {
|
||||
}
|
||||
}
|
||||
}
|
||||
for(Entity currentEntity : this.drawTargetAccumulator.getTerrainEntities()){
|
||||
Vector3d position = EntityUtils.getPosition(currentEntity);
|
||||
if(
|
||||
currentEntity.getData(EntityDataStrings.DATA_STRING_DRAW)!=null
|
||||
){
|
||||
//fetch actor
|
||||
Actor currentActor = EntityUtils.getActor(currentEntity);
|
||||
//calculate camera-modified vector3d
|
||||
Vector3d cameraCenter = scaleVec.set(CameraEntityUtils.getCameraCenter(Globals.clientState.playerCamera));
|
||||
Vector3d cameraModifiedPosition = posVec.set(position).sub(cameraCenter);
|
||||
//calculate and apply model transform
|
||||
modelTransformMatrix = modelTransformMatrix.identity();
|
||||
modelTransformMatrix.translate(cameraModifiedPosition);
|
||||
modelTransformMatrix.rotate(EntityUtils.getRotation(currentEntity));
|
||||
modelTransformMatrix.scale(scaleVec.set(EntityUtils.getScale(currentEntity)));
|
||||
currentActor.applySpatialData(new Matrix4d(modelTransformMatrix),new Vector3d(position));
|
||||
//draw
|
||||
currentActor.draw(renderPipelineState,openGLState);
|
||||
}
|
||||
}
|
||||
for(Entity currentEntity : this.drawTargetAccumulator.getBlockEntities()){
|
||||
Vector3d position = EntityUtils.getPosition(currentEntity);
|
||||
if(
|
||||
currentEntity.getData(EntityDataStrings.DATA_STRING_DRAW)!=null
|
||||
){
|
||||
//fetch actor
|
||||
Actor currentActor = EntityUtils.getActor(currentEntity);
|
||||
//calculate camera-modified vector3d
|
||||
Vector3d cameraCenter = scaleVec.set(CameraEntityUtils.getCameraCenter(Globals.clientState.playerCamera));
|
||||
Vector3d cameraModifiedPosition = posVec.set(position).sub(cameraCenter);
|
||||
//calculate and apply model transform
|
||||
modelTransformMatrix = modelTransformMatrix.identity();
|
||||
modelTransformMatrix.translate(cameraModifiedPosition);
|
||||
modelTransformMatrix.rotate(EntityUtils.getRotation(currentEntity));
|
||||
modelTransformMatrix.scale(scaleVec.set(EntityUtils.getScale(currentEntity)));
|
||||
currentActor.applySpatialData(new Matrix4d(modelTransformMatrix),new Vector3d(position));
|
||||
//draw
|
||||
currentActor.draw(renderPipelineState,openGLState);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -3,12 +3,15 @@ package electrosphere.renderer.target;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.joml.Matrix4d;
|
||||
import org.joml.Vector3d;
|
||||
|
||||
import electrosphere.entity.Entity;
|
||||
|
||||
/**
|
||||
* Accumulates non-spatially identical draw calls to batch to gpu
|
||||
*/
|
||||
@ -19,6 +22,16 @@ public class DrawTargetAccumulator {
|
||||
*/
|
||||
private Map<String,ModelAccumulatorData> modelPathAccumulatorMap = new HashMap<String,ModelAccumulatorData>();
|
||||
|
||||
/**
|
||||
* Groups terrain entities
|
||||
*/
|
||||
private List<Entity> terrainEntities = new LinkedList<Entity>();
|
||||
|
||||
/**
|
||||
* Groups block entities
|
||||
*/
|
||||
private List<Entity> blockEntities = new LinkedList<Entity>();
|
||||
|
||||
|
||||
/**
|
||||
* Adds a call to draw a given model
|
||||
@ -37,6 +50,22 @@ public class DrawTargetAccumulator {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a terrain entity
|
||||
* @param entity The entity
|
||||
*/
|
||||
public void addTerrainCall(Entity entity){
|
||||
this.terrainEntities.add(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a block entity
|
||||
* @param entity The entity
|
||||
*/
|
||||
public void addBlockCall(Entity entity){
|
||||
this.blockEntities.add(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the calls to make
|
||||
* @return The calls to make
|
||||
@ -52,6 +81,24 @@ public class DrawTargetAccumulator {
|
||||
for(ModelAccumulatorData data : modelPathAccumulatorMap.values()){
|
||||
data.count = 0;
|
||||
}
|
||||
this.terrainEntities.clear();
|
||||
this.blockEntities.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of terrain entities
|
||||
* @return The list of terrain entities
|
||||
*/
|
||||
public List<Entity> getTerrainEntities(){
|
||||
return this.terrainEntities;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of block entities
|
||||
* @return The list of block entities
|
||||
*/
|
||||
public List<Entity> getBlockEntities(){
|
||||
return this.blockEntities;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -12,6 +12,7 @@ import electrosphere.entity.DrawableUtils;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityTags;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.entity.types.terrain.TerrainChunk;
|
||||
import electrosphere.renderer.actor.Actor;
|
||||
import electrosphere.renderer.pipelines.MainContentPipeline;
|
||||
import electrosphere.renderer.pipelines.NormalsForOutlinePipeline;
|
||||
@ -112,6 +113,26 @@ public class DrawTargetEvaluator {
|
||||
normalAccumulator.addCall(currentActor.getModelPath(), position, modelTransformMatrix);
|
||||
}
|
||||
}
|
||||
} else if(TerrainChunk.isBlockEntity(currentEntity)){
|
||||
if(MainContentPipeline.shouldDrawSolidPass(currentEntity)){
|
||||
mainAccumulator.addBlockCall(currentEntity);
|
||||
}
|
||||
if(dist < ShadowMapPipeline.DRAW_CUTOFF_DIST && shadowList.contains(currentEntity)){
|
||||
shadowAccumulator.addBlockCall(currentEntity);
|
||||
}
|
||||
if(dist < NormalsForOutlinePipeline.DRAW_CUTOFF_DIST && NormalsForOutlinePipeline.shouldDraw(currentEntity)){
|
||||
normalAccumulator.addBlockCall(currentEntity);
|
||||
}
|
||||
} else if(TerrainChunk.isTerrainEntity(currentEntity)) {
|
||||
if(MainContentPipeline.shouldDrawSolidPass(currentEntity)){
|
||||
mainAccumulator.addTerrainCall(currentEntity);
|
||||
}
|
||||
if(dist < ShadowMapPipeline.DRAW_CUTOFF_DIST && shadowList.contains(currentEntity)){
|
||||
shadowAccumulator.addTerrainCall(currentEntity);
|
||||
}
|
||||
if(dist < NormalsForOutlinePipeline.DRAW_CUTOFF_DIST && NormalsForOutlinePipeline.shouldDraw(currentEntity)){
|
||||
normalAccumulator.addTerrainCall(currentEntity);
|
||||
}
|
||||
} else {
|
||||
if(MainContentPipeline.shouldDrawSolidPass(currentEntity)){
|
||||
mainQueue.add(currentEntity);
|
||||
|
||||
@ -103,6 +103,7 @@ public class PhysicsDataCell {
|
||||
this.blockData = BlockMeshgen.rasterize(this.blockChunk);
|
||||
BlockChunkEntity.serverCreateBlockChunkEntity(localBlockPhysicsEntity, this.blockData);
|
||||
localBlockPhysicsEntity.putData(EntityDataStrings.TERRAIN_IS_TERRAIN, true);
|
||||
localBlockPhysicsEntity.putData(EntityDataStrings.BLOCK_ENTITY, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Loading…
Reference in New Issue
Block a user