Renderer/src/main/java/electrosphere/renderer/pipelines/MainContentPipeline.java

220 lines
10 KiB
Java

package electrosphere.renderer.pipelines;
import org.joml.Matrix4d;
import org.joml.Matrix4f;
import org.joml.Quaterniond;
import org.joml.Quaternionf;
import org.joml.Vector3d;
import org.joml.Vector3f;
import org.lwjgl.opengl.GL40;
import electrosphere.engine.Globals;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityTags;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.types.camera.CameraEntityUtils;
import electrosphere.renderer.OpenGLState;
import electrosphere.renderer.RenderPipelineState;
import electrosphere.renderer.RenderingEngine;
import electrosphere.renderer.RenderPipelineState.SelectedShaderEnum;
import electrosphere.renderer.actor.Actor;
import electrosphere.renderer.actor.instance.InstancedActor;
import electrosphere.renderer.buffer.ShaderAttribute;
/**
* The main render pipeline with OIT pass
*/
public class MainContentPipeline implements RenderPipeline {
@Override
public void render(OpenGLState openGLState, RenderPipelineState renderPipelineState) {
Matrix4d modelTransformMatrix = new Matrix4d();
//bind screen fbo
RenderingEngine.screenFramebuffer.bind();
openGLState.glDepthTest(true);
openGLState.glDepthFunc(GL40.GL_LESS);
GL40.glDepthMask(true);
openGLState.glViewport(Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY());
///
/// R E N D E R I N G S T U F F
///
//Sets the background color.
GL40.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
GL40.glClear(GL40.GL_COLOR_BUFFER_BIT | GL40.GL_DEPTH_BUFFER_BIT);
//
// Set render pipeline state
//
renderPipelineState.setSelectedShader(SelectedShaderEnum.PRIMARY);
renderPipelineState.setUseMeshShader(true);
renderPipelineState.setBufferStandardUniforms(true);
renderPipelineState.setBufferNonStandardUniforms(false);
renderPipelineState.setUseMaterial(true);
renderPipelineState.setUseShadowMap(true);
renderPipelineState.setUseBones(true);
renderPipelineState.setUseLight(true);
//
// Pass One: Solids
//
//
// D R A W A L L E N T I T I E S
//
for(Entity currentEntity : Globals.clientScene.getEntitiesWithTag(EntityTags.DRAWABLE)){
Vector3d position = EntityUtils.getPosition(currentEntity);
if(
(boolean)currentEntity.getData(EntityDataStrings.DATA_STRING_DRAW) &&
currentEntity.getData(EntityDataStrings.DRAW_SOLID_PASS) != null
){
//fetch actor
Actor currentActor = EntityUtils.getActor(currentEntity);
//calculate camera-modified vector3f
Vector3f cameraModifiedPosition = new Vector3f((float)position.x,(float)position.y,(float)position.z).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera));
//calculate and apply model transform
modelTransformMatrix.identity();
modelTransformMatrix.translate(cameraModifiedPosition);
modelTransformMatrix.rotate(EntityUtils.getRotation(currentEntity));
modelTransformMatrix.scale(new Vector3d(EntityUtils.getScale(currentEntity)));
currentActor.applyModelMatrix(modelTransformMatrix);
//draw
currentActor.draw(renderPipelineState,openGLState);
}
}
Globals.clientFoliageManager.draw();
for(Entity currentEntity : Globals.clientScene.getEntitiesWithTag(EntityTags.DRAW_INSTANCED)){
Vector3d position = EntityUtils.getPosition(currentEntity);
if(
currentEntity.getData(EntityDataStrings.DATA_STRING_DRAW) != null &&
currentEntity.getData(EntityDataStrings.DRAW_SOLID_PASS) != null
){
//fetch actor
InstancedActor currentActor = InstancedActor.getInstancedActor(currentEntity);
//if the shader attribute for model matrix exists, calculate the model matrix and apply
if(InstancedActor.getInstanceModelAttribute(currentEntity) != null){
ShaderAttribute modelAttribute = InstancedActor.getInstanceModelAttribute(currentEntity);
//calculate model matrix
Vector3f cameraModifiedPosition = new Vector3f((float)position.x,(float)position.y,(float)position.z).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera));
Quaterniond rotation = EntityUtils.getRotation(currentEntity);
// modelTransformMatrix.identity();
modelTransformMatrix.identity().translationRotateScale(
cameraModifiedPosition,
new Quaternionf((float)rotation.x,(float)rotation.y,(float)rotation.z,(float)rotation.w),
new Vector3f(EntityUtils.getScale(currentEntity))
);
//set actor value
currentActor.setAttribute(modelAttribute, new Matrix4f(modelTransformMatrix));
//draw
currentActor.draw(renderPipelineState, new Vector3d(cameraModifiedPosition));
} else {
currentActor.draw(renderPipelineState);
}
}
}
//draw all instanced models
Globals.clientInstanceManager.draw(renderPipelineState,openGLState);
//
// Pass Two: Transparency Accumulator + Revealage
//
// glDisable(GL_DEPTH_TEST);
GL40.glDepthMask(false);
GL40.glEnable(GL40.GL_BLEND);
GL40.glBlendFunci(0, GL40.GL_ONE, GL40.GL_ONE);
GL40.glBlendFunci(1, GL40.GL_ZERO, GL40.GL_ONE_MINUS_SRC_COLOR);
GL40.glBlendEquation(GL40.GL_FUNC_ADD);
RenderingEngine.transparencyBuffer.bind();
GL40.glClearBufferfv(GL40.GL_COLOR,0,RenderingEngine.transparencyAccumulatorClear);
GL40.glClearBufferfv(GL40.GL_COLOR,1,RenderingEngine.transparencyRevealageClear);
//
// Set render pipeline state
//
renderPipelineState.setUseMeshShader(true);
renderPipelineState.setSelectedShader(SelectedShaderEnum.OIT);
openGLState.glDepthFunc(GL40.GL_LEQUAL);
//
//!!!WARNING!!!
//Comments on function:
//If you're going "gee wilikers I don't know why the back planes of my transparent-labeled aren't showing through the transparency", this is for you
//The transparent pass receives the depth buffer of the opaque pass and IS DEPTH MASK CULLED
//This means if you draw the transparent object in the depth pass, it will not draw in the transparent pass as it is culled
//
//!!!WARNING!!!
//TLDR OF ABOVE: DO NOT DRAW TRANSPARENT OBJECTS IN OPAQUE PASS
//
for(Entity currentEntity : Globals.clientScene.getEntitiesWithTag(EntityTags.DRAWABLE)){
Vector3d position = EntityUtils.getPosition(currentEntity);
if(
(boolean)currentEntity.getData(EntityDataStrings.DATA_STRING_DRAW) &&
currentEntity.getData(EntityDataStrings.DRAW_TRANSPARENT_PASS) != null
){
//fetch actor
Actor currentActor = EntityUtils.getActor(currentEntity);
//calculate camera-modified vector3f
Vector3f cameraModifiedPosition = new Vector3f((float)position.x,(float)position.y,(float)position.z).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera));
//calculate and apply model transform
modelTransformMatrix.identity();
modelTransformMatrix.translate(cameraModifiedPosition);
modelTransformMatrix.rotate(EntityUtils.getRotation(currentEntity));
modelTransformMatrix.scale(new Vector3d(EntityUtils.getScale(currentEntity)));
currentActor.applyModelMatrix(modelTransformMatrix);
//draw
currentActor.draw(renderPipelineState,openGLState);
}
}
for(Entity currentEntity : Globals.clientScene.getEntitiesWithTag(EntityTags.DRAW_INSTANCED)){
Vector3d position = EntityUtils.getPosition(currentEntity);
if(
currentEntity.getData(EntityDataStrings.DATA_STRING_DRAW) != null &&
currentEntity.getData(EntityDataStrings.DRAW_TRANSPARENT_PASS) != null
){
//fetch actor
InstancedActor currentActor = InstancedActor.getInstancedActor(currentEntity);
//if the shader attribute for model matrix exists, calculate the model matrix and apply
if(InstancedActor.getInstanceModelAttribute(currentEntity) != null){
ShaderAttribute modelAttribute = InstancedActor.getInstanceModelAttribute(currentEntity);
//calculate model matrix
Vector3f cameraModifiedPosition = new Vector3f((float)position.x,(float)position.y,(float)position.z).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera));
Quaterniond rotation = EntityUtils.getRotation(currentEntity);
// modelTransformMatrix.identity();
modelTransformMatrix.identity().translationRotateScale(
cameraModifiedPosition,
new Quaternionf((float)rotation.x,(float)rotation.y,(float)rotation.z,(float)rotation.w),
new Vector3f(EntityUtils.getScale(currentEntity))
);
//set actor value
currentActor.setAttribute(modelAttribute, new Matrix4f(modelTransformMatrix));
//draw
currentActor.draw(renderPipelineState, new Vector3d(cameraModifiedPosition));
} else {
currentActor.draw(renderPipelineState);
}
}
}
//draw all instanced models
Globals.clientInstanceManager.draw(renderPipelineState,openGLState);
//
// Set render pipeline state
//
renderPipelineState.setSelectedShader(SelectedShaderEnum.PRIMARY);
// glBindVertexArray(0);
}
}