package electrosphere.renderer.pipelines; import org.joml.Matrix4d; import org.joml.Matrix4f; 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.actor.Actor; /** * Shadow map pipeline */ public class ShadowMapPipeline implements RenderPipeline { @Override public void render(OpenGLState openGLState, RenderPipelineState renderPipelineState) { Globals.profiler.beginCpuSample("ShadowMapPipeline.render"); Matrix4d modelTransformMatrix = new Matrix4d(); //set the viewport to shadow map size openGLState.glViewport(4096, 4096); openGLState.glDepthTest(true); openGLState.glDepthFunc(GL40.GL_ALWAYS); openGLState.setActiveShader(renderPipelineState, RenderingEngine.lightDepthShaderProgram); RenderingEngine.lightDepthBuffer.bind(openGLState); GL40.glClear(GL40.GL_DEPTH_BUFFER_BIT); openGLState.glActiveTexture(GL40.GL_TEXTURE0); float eyeX = -1.0f; float eyeY = 10.0f; float eyeZ = -5.5f; float nearPlane = 0.01f; float eyeDist = (float)Math.sqrt(eyeX * eyeX + eyeY * eyeY + eyeZ * eyeZ); float farPlane = eyeDist + 10.0f; float sidesMagnitude = (float)Math.sqrt(eyeDist); //set matrices for light render Matrix4f lightProjection = new Matrix4f().setOrtho(-sidesMagnitude, sidesMagnitude, -sidesMagnitude, sidesMagnitude, nearPlane, farPlane);//glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, near_plane, far_plane); Matrix4f lightView = new Matrix4f().setLookAt( new Vector3f(eyeX, eyeY, eyeZ), new Vector3f( 0.0f, 0.0f, 0.0f), new Vector3f( 0.0f, 1.0f, 0.0f) ); Globals.lightDepthMatrix = new Matrix4f(lightProjection).mul(lightView); GL40.glUniformMatrix4fv(GL40.glGetUniformLocation(openGLState.getActiveShader().getShaderId(), "lightSpaceMatrix"), false, Globals.lightDepthMatrix.get(new float[16])); // glCullFace(GL_FRONT); // // Set render pipeline state // renderPipelineState.setUseMeshShader(false); renderPipelineState.setBufferStandardUniforms(true); renderPipelineState.setBufferNonStandardUniforms(true); renderPipelineState.setUseMaterial(false); renderPipelineState.setUseShadowMap(false); renderPipelineState.setUseBones(true); renderPipelineState.setUseLight(false); // // D R A W A L L E N T I T I E S // modelTransformMatrix = new Matrix4d(); for(Entity currentEntity : Globals.clientScene.getEntitiesWithTag(EntityTags.DRAWABLE)){ Vector3d position = EntityUtils.getPosition(currentEntity); if( currentEntity.getData(EntityDataStrings.DATA_STRING_DRAW)!=null && currentEntity.containsKey(EntityDataStrings.DRAW_CAST_SHADOW) ){ //fetch actor Actor currentActor = EntityUtils.getActor(currentEntity); //calculate camera-modified vector3f Vector3f cameraCenter = CameraEntityUtils.getCameraCenter(Globals.playerCamera); Vector3f cameraModifiedPosition = new Vector3f((float)position.x,(float)position.y,(float)position.z).sub(cameraCenter); //calculate and apply model transform modelTransformMatrix = modelTransformMatrix.identity(); modelTransformMatrix.translate(cameraModifiedPosition); modelTransformMatrix.rotate(EntityUtils.getRotation(currentEntity)); modelTransformMatrix.scale(new Vector3d(EntityUtils.getScale(currentEntity))); currentActor.applySpatialData(modelTransformMatrix,position); //draw currentActor.draw(renderPipelineState,openGLState); } } //reset texture openGLState.glActiveTexture(GL40.GL_TEXTURE0); openGLState.glBindTexture(GL40.GL_TEXTURE_2D, 0); //bind default framebuffer openGLState.glBindFramebuffer(GL40.GL_FRAMEBUFFER,0); //reset the viewport to screen size openGLState.glViewport(Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT); //resume culling backface // glCullFace(GL_BACK); Globals.profiler.endCpuSample(); } }