From 2f0af2f096f1a3d4b690a83a0f2a112e5b6d15e1 Mon Sep 17 00:00:00 2001 From: austin Date: Fri, 18 Mar 2022 17:19:45 -0400 Subject: [PATCH] OIT start --- assets/Shaders/oit/composite.fs | 55 ++++++ assets/Shaders/oit/composite.vs | 9 + .../screentexture/drawChannel/drawChannel.fs | 30 ++++ .../screentexture/drawChannel/drawChannel.vs | 10 ++ .../screentexture/drawDepth/drawDepth.fs | 9 + .../screentexture/drawDepth/drawDepth.vs | 10 ++ assets/Shaders/water1/water.fs | 25 ++- assets/Shaders/water1/water.vs | 7 +- .../electrosphere/engine/LoadingThread.java | 2 + .../entity/EntityDataStrings.java | 2 + .../electrosphere/entity/EntityUtils.java | 2 + .../renderer/RenderingEngine.java | 170 +++++++++++++++--- .../renderer/framebuffer/Framebuffer.java | 1 + .../framebuffer/FramebufferUtils.java | 117 ++++++++++++ 14 files changed, 420 insertions(+), 29 deletions(-) create mode 100644 assets/Shaders/oit/composite.fs create mode 100644 assets/Shaders/oit/composite.vs create mode 100644 assets/Shaders/screentexture/drawChannel/drawChannel.fs create mode 100644 assets/Shaders/screentexture/drawChannel/drawChannel.vs create mode 100644 assets/Shaders/screentexture/drawDepth/drawDepth.fs create mode 100644 assets/Shaders/screentexture/drawDepth/drawDepth.vs diff --git a/assets/Shaders/oit/composite.fs b/assets/Shaders/oit/composite.fs new file mode 100644 index 00000000..4c367042 --- /dev/null +++ b/assets/Shaders/oit/composite.fs @@ -0,0 +1,55 @@ +#version 420 core + +// shader outputs +layout (location = 0) out vec4 frag; + +// color accumulation buffer +layout (binding = 0) uniform sampler2D accum; + +// revealage threshold buffer +layout (binding = 1) uniform sampler2D reveal; + +// epsilon number +const float EPSILON = 0.00001f; + +// caluclate floating point numbers equality accurately +bool isApproximatelyEqual(float a, float b) +{ + return abs(a - b) <= (abs(a) < abs(b) ? abs(b) : abs(a)) * EPSILON; +} + +// get the max value between three values +float max3(vec3 v) +{ + return max(max(v.x, v.y), v.z); +} + +void main() +{ + // fragment coordination + ivec2 coords = ivec2(gl_FragCoord.xy); + + // fragment revealage + float revealage = texelFetch(reveal, coords, 0).r; + + // save the blending and color texture fetch cost if there is not a transparent fragment + if (isApproximatelyEqual(revealage, 1.0f)){ + discard; + } + + // fragment color + vec4 accumulation = texelFetch(accum, coords, 0); + + // suppress overflow + if (isinf(max3(abs(accumulation.rgb)))){ + accumulation.rgb = vec3(accumulation.a); + } + + // prevent floating point precision bug + vec3 average_color = accumulation.rgb / max(accumulation.a, EPSILON); + + // blend pixels + frag = vec4(average_color, 1.0f - revealage); + // frag = vec4(accumulation.rgb, 1.0f - revealage); + // frag = vec4(0,0,0,0); +} \ No newline at end of file diff --git a/assets/Shaders/oit/composite.vs b/assets/Shaders/oit/composite.vs new file mode 100644 index 00000000..fa50aa04 --- /dev/null +++ b/assets/Shaders/oit/composite.vs @@ -0,0 +1,9 @@ +#version 420 core + +// shader inputs +layout (location = 0) in vec3 position; + +void main() +{ + gl_Position = vec4(position, 1.0f); +} \ No newline at end of file diff --git a/assets/Shaders/screentexture/drawChannel/drawChannel.fs b/assets/Shaders/screentexture/drawChannel/drawChannel.fs new file mode 100644 index 00000000..f0b4988b --- /dev/null +++ b/assets/Shaders/screentexture/drawChannel/drawChannel.fs @@ -0,0 +1,30 @@ +#version 330 core +out vec4 FragColor; + +in vec2 TexCoords; + +uniform sampler2D screenTexture; + +uniform float channel; + +void main(){ + switch(int(channel)){ + case 0: + FragColor = vec4(texture(screenTexture, TexCoords).r,0,0,1); + break; + case 1: + FragColor = vec4(0,texture(screenTexture, TexCoords).g,0,1); + break; + case 2: + FragColor = vec4(0,0,texture(screenTexture, TexCoords).b,1); + break; + case 3: + FragColor = vec4(texture(screenTexture, TexCoords).a,texture(screenTexture, TexCoords).a,texture(screenTexture, TexCoords).a,1); + break; + case 4: + FragColor = vec4(vec3(texture(screenTexture, TexCoords)),1.0); + default: + FragColor = vec4(1,1,1,1); + break; + } +} \ No newline at end of file diff --git a/assets/Shaders/screentexture/drawChannel/drawChannel.vs b/assets/Shaders/screentexture/drawChannel/drawChannel.vs new file mode 100644 index 00000000..addab705 --- /dev/null +++ b/assets/Shaders/screentexture/drawChannel/drawChannel.vs @@ -0,0 +1,10 @@ +#version 330 core +layout (location = 0) in vec2 aPos; +layout (location = 1) in vec2 aTexCoords; + +out vec2 TexCoords; + +void main(){ + gl_Position = vec4(aPos.x, aPos.y, 0.0, 1.0); + TexCoords = aTexCoords; +} \ No newline at end of file diff --git a/assets/Shaders/screentexture/drawDepth/drawDepth.fs b/assets/Shaders/screentexture/drawDepth/drawDepth.fs new file mode 100644 index 00000000..6485d80c --- /dev/null +++ b/assets/Shaders/screentexture/drawDepth/drawDepth.fs @@ -0,0 +1,9 @@ +#version 330 core +out vec4 FragColor; + +in vec2 TexCoords; + + +void main(){ + vec4(vec3(gl_FragCoord.z), 1.0); +} \ No newline at end of file diff --git a/assets/Shaders/screentexture/drawDepth/drawDepth.vs b/assets/Shaders/screentexture/drawDepth/drawDepth.vs new file mode 100644 index 00000000..addab705 --- /dev/null +++ b/assets/Shaders/screentexture/drawDepth/drawDepth.vs @@ -0,0 +1,10 @@ +#version 330 core +layout (location = 0) in vec2 aPos; +layout (location = 1) in vec2 aTexCoords; + +out vec2 TexCoords; + +void main(){ + gl_Position = vec4(aPos.x, aPos.y, 0.0, 1.0); + TexCoords = aTexCoords; +} \ No newline at end of file diff --git a/assets/Shaders/water1/water.fs b/assets/Shaders/water1/water.fs index 96172dcb..260820fe 100644 --- a/assets/Shaders/water1/water.fs +++ b/assets/Shaders/water1/water.fs @@ -30,13 +30,16 @@ THE FLAME FUNCTION IS ONE CREATED BY ME BLENDING A LOG2 INTO A EXPONENTIAL. */ //version -#version 330 core +#version 420 core //macros #extension GL_ARB_explicit_uniform_location : enable //output -out vec4 fragColor; +// out vec4 fragColor; + +layout (location = 0) out vec4 accum; +layout (location = 1) out float reveal; //input in vec3 FragPos; @@ -49,6 +52,7 @@ in vec4 modelCoord; uniform float time; //layout uniforms +layout (location = 3) uniform sampler2D shadowMap; layout (location = 5) uniform sampler2D volumeDepthFrontface; layout (location = 6) uniform sampler2D volumeDepthBackface; @@ -104,6 +108,8 @@ void main(){ float blue = 0.7366; float alpha = volume * 10.0; + // alpha = 0.5; + // float red = volume * 10.0; // float green = volume * 10.0; // float blue = volume * 10.0; @@ -115,13 +121,26 @@ void main(){ blue, alpha ); + + + // weight function + float weight = clamp(pow(min(1.0, color.a * 10.0) + 0.01, 3.0) * 1e8 * pow(1.0 - gl_FragCoord.z * 0.9, 3.0), 1e-2, 3e3); + + // weight = 1.0; + + // store pixel color accumulation + accum = vec4(color.rgb * color.a, color.a) * weight; + + // store pixel revealage threshold + reveal = color.a; + // reveal = 1.0; // if(val < 0.3){ // discard; // } // Output to screen - fragColor = color; + // fragColor = color; } diff --git a/assets/Shaders/water1/water.vs b/assets/Shaders/water1/water.vs index 1bf83e85..71738328 100644 --- a/assets/Shaders/water1/water.vs +++ b/assets/Shaders/water1/water.vs @@ -1,5 +1,5 @@ //Vertex Shader -#version 330 core +#version 420 core @@ -40,5 +40,8 @@ void main() { modelCoord = FinalVertex; //set final position with opengl space - gl_Position = projection * view * model * FinalVertex; + vec4 outVec = projection * view * model * FinalVertex; + // outVec.z = outVec.z - 0.1f; + // outVec.z = -0.9; + gl_Position = outVec; } diff --git a/src/main/java/electrosphere/engine/LoadingThread.java b/src/main/java/electrosphere/engine/LoadingThread.java index 4b42ba7d..4b4708bb 100644 --- a/src/main/java/electrosphere/engine/LoadingThread.java +++ b/src/main/java/electrosphere/engine/LoadingThread.java @@ -732,6 +732,8 @@ public class LoadingThread extends Thread { EntityUtils.getActor(water).addTextureMask(RenderUtils.generateVolumetricTextureMask("Cube")); //set draw volumetric water.putData(EntityDataStrings.DRAW_VOLUMETRIC, true); + water.removeData(EntityDataStrings.DRAW_SOLID_PASS); + water.putData(EntityDataStrings.DRAW_TRANSPARENT_PASS, true); // goblin = CreatureUtils.spawnBasicCreature("Goblin"); diff --git a/src/main/java/electrosphere/entity/EntityDataStrings.java b/src/main/java/electrosphere/entity/EntityDataStrings.java index 9edcf192..a732c8f7 100644 --- a/src/main/java/electrosphere/entity/EntityDataStrings.java +++ b/src/main/java/electrosphere/entity/EntityDataStrings.java @@ -16,6 +16,8 @@ public class EntityDataStrings { public static final String DATA_STRING_MODEL_PATH = "modelPath"; public static final String DATA_STRING_ACTOR = "actor"; public static final String DATA_STRING_DRAW = "drawFlag"; + public static final String DRAW_SOLID_PASS = "drawSolidPass"; + public static final String DRAW_TRANSPARENT_PASS = "drawTransparentPass"; public static final String DRAW_CAST_SHADOW = "castShadow"; public static final String DRAW_VOLUMETRIC = "drawVolumetric"; diff --git a/src/main/java/electrosphere/entity/EntityUtils.java b/src/main/java/electrosphere/entity/EntityUtils.java index b73c4b6c..b59671b5 100644 --- a/src/main/java/electrosphere/entity/EntityUtils.java +++ b/src/main/java/electrosphere/entity/EntityUtils.java @@ -48,6 +48,7 @@ public class EntityUtils { rVal.putData(EntityDataStrings.DATA_STRING_ROTATION, new Quaternionf().identity()); rVal.putData(EntityDataStrings.DATA_STRING_SCALE, new Vector3f(1,1,1)); rVal.putData(EntityDataStrings.DATA_STRING_DRAW, true); + rVal.putData(EntityDataStrings.DRAW_SOLID_PASS, true); Globals.entityManager.registerEntity(rVal); Globals.entityManager.registerDrawableEntity(rVal); return rVal; @@ -60,6 +61,7 @@ public class EntityUtils { rVal.putData(EntityDataStrings.DATA_STRING_ROTATION, new Quaternionf().rotateAxis((float)0, new Vector3f(1,0,0))); rVal.putData(EntityDataStrings.DATA_STRING_SCALE, new Vector3f(1,1,1)); rVal.putData(EntityDataStrings.DATA_STRING_DRAW, true); + rVal.putData(EntityDataStrings.DRAW_SOLID_PASS, true); Globals.entityManager.registerEntity(rVal); Globals.entityManager.registerDrawableEntity(rVal); return rVal; diff --git a/src/main/java/electrosphere/renderer/RenderingEngine.java b/src/main/java/electrosphere/renderer/RenderingEngine.java index ab470e8b..93b3eea0 100644 --- a/src/main/java/electrosphere/renderer/RenderingEngine.java +++ b/src/main/java/electrosphere/renderer/RenderingEngine.java @@ -73,10 +73,22 @@ import static org.lwjgl.opengl.GL11.GL_FOG_MODE; import static org.lwjgl.opengl.GL11.GL_FOG_START; import static org.lwjgl.opengl.GL11.GL_LINEAR; import static org.lwjgl.opengl.GL11.GL_NEAREST; +import static org.lwjgl.opengl.GL11.GL_LESS; +import static org.lwjgl.opengl.GL11.GL_LEQUAL; +import static org.lwjgl.opengl.GL11.GL_EQUAL; +import static org.lwjgl.opengl.GL11.GL_GREATER; import static org.lwjgl.opengl.GL11.GL_ONE_MINUS_SRC_ALPHA; import static org.lwjgl.opengl.GL11.GL_SRC_ALPHA; import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D; import static org.lwjgl.opengl.GL11.GL_TRIANGLES; +import static org.lwjgl.opengl.GL11.GL_FALSE; +import static org.lwjgl.opengl.GL11.GL_ONE; +import static org.lwjgl.opengl.GL11.GL_ZERO; +import static org.lwjgl.opengl.GL11.GL_COLOR; +import static org.lwjgl.opengl.GL11.GL_ONE_MINUS_SRC_COLOR; +import static org.lwjgl.opengl.GL11.GL_ALWAYS; +import static org.lwjgl.opengl.GL11.glDepthFunc; +import static org.lwjgl.opengl.GL11.glDepthMask; import static org.lwjgl.opengl.GL11.glBindTexture; import static org.lwjgl.opengl.GL11.glBlendFunc; import static org.lwjgl.opengl.GL11.glClear; @@ -91,15 +103,22 @@ import static org.lwjgl.opengl.GL13.GL_TEXTURE1; import static org.lwjgl.opengl.GL13.GL_TEXTURE2; import static org.lwjgl.opengl.GL13.GL_TEXTURE3; import static org.lwjgl.opengl.GL13.glActiveTexture; +import static org.lwjgl.opengl.GL14.GL_FUNC_ADD; import static org.lwjgl.opengl.GL20.glGetUniformLocation; import static org.lwjgl.opengl.GL20.glUniformMatrix4fv; import static org.lwjgl.opengl.GL20.glUseProgram; +import static org.lwjgl.opengl.GL20.glUniform1f; import static org.lwjgl.opengl.GL30.GL_FRAMEBUFFER; import static org.lwjgl.opengl.GL30.GL_RENDERBUFFER; +import static org.lwjgl.opengl.GL30.GL_COLOR_ATTACHMENT0; +import static org.lwjgl.opengl.GL30.GL_COLOR_ATTACHMENT1; import static org.lwjgl.opengl.GL30.glBindFramebuffer; import static org.lwjgl.opengl.GL30.glBindRenderbuffer; import static org.lwjgl.opengl.GL30.glBindVertexArray; import static org.lwjgl.opengl.GL30.glBlitFramebuffer; +import static org.lwjgl.opengl.GL30.glClearBufferfv; +import static org.lwjgl.opengl.GL40.glBlendFunci; +import static org.lwjgl.opengl.GL40.glBlendEquation; import static org.lwjgl.system.MemoryUtil.NULL; public class RenderingEngine { @@ -108,14 +127,27 @@ public class RenderingEngine { public static final int GL_DEFAULT_FRAMEBUFFER = 0; public static final int GL_DEFAULT_RENDERBUFFER = 0; + static Texture screenTextureColor; + static Texture screenTextureDepth; static Framebuffer screenFramebuffer; static Renderbuffer screenRenderbuffer; static int screenTextureVAO; static ShaderProgram screenTextureShaders; + + static ShaderProgram drawChannel; + //depth framebuffer/shader for shadow mapping static ShaderProgram lightDepthShaderProgram; static Framebuffer lightDepthBuffer; + //framebuffers for transparent textures + static float[] transparencyAccumulatorClear; + static Texture transparencyAccumulatorTexture; + static float[] transparencyRevealageClear; + static Texture transparencyRevealageTexture; + static Framebuffer transparencyBuffer; + static ShaderProgram oitCompositeProgram; + static Matrix4f nearVolumeProjectionMatrix = new Matrix4f(); static Matrix4f midVolumeProjectionMatrix = new Matrix4f(); static Matrix4f farVolumeProjectionMatrix = new Matrix4f(); @@ -223,10 +255,17 @@ public class RenderingEngine { // screenTextureShaders = ShaderProgram.loadSpecificShader("/Shaders/screentexture/drawDepthBuffer/drawDepthBuffer.vs", "/Shaders/screentexture/drawDepthBuffer/drawDepthBuffer.fs"); //generate framebuffers - screenFramebuffer = FramebufferUtils.generateScreensizeTextureFramebuffer(); + screenTextureColor = FramebufferUtils.generateScreenTextureColor(Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT); + screenTextureDepth = FramebufferUtils.generateScreenTextureDepth(Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT); + screenFramebuffer = FramebufferUtils.generateScreenTextureFramebuffer(Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT, screenTextureColor, screenTextureDepth); glBindFramebuffer(GL_FRAMEBUFFER, GL_DEFAULT_FRAMEBUFFER); glBindRenderbuffer(GL_RENDERBUFFER, GL_DEFAULT_RENDERBUFFER); + // + //Channel debug program + // + drawChannel = ShaderProgram.loadSpecificShader("/Shaders/screentexture/drawChannel/drawChannel.vs", "/Shaders/screentexture/drawChannel/drawChannel.fs"); + // //create light depth framebuffer/shader for shadowmapping // @@ -244,10 +283,19 @@ public class RenderingEngine { volumeDepthBackfaceFramebuffer = FramebufferUtils.generateDepthBuffer(Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT, volumeDepthBackfaceTexture); volumeDepthFrontfaceTexture = FramebufferUtils.generateDepthBufferTexture(Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT); volumeDepthFrontfaceFramebuffer = FramebufferUtils.generateDepthBuffer(Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT, volumeDepthFrontfaceTexture); + + // + //Transparency framebuffers + // + transparencyAccumulatorClear = new float[]{0.0f, 0.0f, 0.0f, 0.0f}; + transparencyAccumulatorTexture = FramebufferUtils.generateOITAccumulatorTexture(Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT); + transparencyRevealageClear = new float[]{1.0f, 0.0f, 0.0f, 0.0f}; + transparencyRevealageTexture = FramebufferUtils.generateOITRevealageTexture(Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT); + transparencyBuffer = FramebufferUtils.generateOITFramebuffer(Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT, transparencyAccumulatorTexture, transparencyRevealageTexture, screenTextureDepth); + oitCompositeProgram = ShaderProgram.loadSpecificShader("Shaders/oit/composite.vs", "Shaders/oit/composite.fs"); + //projection matrices nearVolumeProjectionMatrix.setPerspective((float)(Globals.verticalFOV * Math.PI /180.0f), (float)Globals.WINDOW_WIDTH / (float)Globals.WINDOW_HEIGHT, 0.1f, 100); - // midVolumeProjectionMatrix.setPerspective((float)(Globals.verticalFOV * Math.PI /180.0f), (float)Globals.WINDOW_WIDTH / (float)Globals.WINDOW_HEIGHT, 0.01f, 7); - // farVolumeProjectionMatrix.setPerspective((float)(Globals.verticalFOV * Math.PI /180.0f), (float)Globals.WINDOW_WIDTH / (float)Globals.WINDOW_HEIGHT, 0.1f, 50); //instantiate light manager @@ -489,16 +537,22 @@ public class RenderingEngine { //bind screen fbo screenFramebuffer.bind(); glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + glDepthMask(true); glViewport(0, 0, Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT); /// /// R E N D E R I N G S T U F F /// //Sets the background color. - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + // + // Pass One: Solids + // + // // D R A W A L L E N T I T I E S // @@ -506,15 +560,14 @@ public class RenderingEngine { modelTransformMatrix = new Matrix4f(); for(Entity currentEntity : Globals.entityManager.getDrawable()){ Vector3d position = EntityUtils.getPosition(currentEntity); - if((boolean)currentEntity.getData(EntityDataStrings.DATA_STRING_DRAW) && drawPoint(cameraPos,new Vector3f((float)position.x,(float)position.y,(float)position.z))){ + if( + (boolean)currentEntity.getData(EntityDataStrings.DATA_STRING_DRAW) && + currentEntity.getData(EntityDataStrings.DRAW_SOLID_PASS) != null && + drawPoint(cameraPos,new Vector3f((float)position.x,(float)position.y,(float)position.z)) + ){ //fetch actor Actor currentActor = EntityUtils.getActor(currentEntity); currentActor.incrementAnimationTime(0.001); - //increment animations - //this is incremented in the shadow calculations - // if(currentActor.getCurrentAnimation() != null){ - // currentActor.incrementAnimationTime(deltaTime * 500); - // } //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 @@ -525,22 +578,77 @@ public class RenderingEngine { currentActor.applyModelMatrix(modelTransformMatrix); //draw currentActor.draw(); - - // Model currentModel = Globals.assetManager.fetchModel(EntityUtils.getEntityModelPath(currentEntity)); - // if(currentModel != null){ - // if(currentModel.currentAnimation != null){ - // currentModel.incrementTime(deltaTime * 500); - // } - // currentModel.modelMatrix = new Matrix4f(); - // currentModel.modelMatrix.translate(new Vector3f(EntityUtils.getEntityPosition(currentEntity)).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera)).sub(new Vector3f(0,1,0))); - // currentModel.modelMatrix.rotate(EntityUtils.getEntityRotation(currentEntity)); - // currentModel.modelMatrix.scale(EntityUtils.getEntityScale(currentEntity)); - // currentModel.draw(); - // } } } + + // + // Pass Two: Transparency Accumulator + Revealage + // + glDepthMask(false); + glDepthFunc(GL_LESS); + // glDepthFunc(GL_GREATER); + // glDepthFunc(GL_ALWAYS); + glEnable(GL_BLEND); + glBlendFunci(0, GL_ONE, GL_ONE); + glBlendFunci(1, GL_ZERO, GL_ONE_MINUS_SRC_COLOR); + glBlendEquation(GL_FUNC_ADD); + + transparencyBuffer.bind(); + glClearBufferfv(GL_COLOR,0,transparencyAccumulatorClear); + glClearBufferfv(GL_COLOR,1,transparencyRevealageClear); + + + for(Entity currentEntity : Globals.entityManager.getDrawable()){ + Vector3d position = EntityUtils.getPosition(currentEntity); + if( + (boolean)currentEntity.getData(EntityDataStrings.DATA_STRING_DRAW) && + currentEntity.getData(EntityDataStrings.DRAW_TRANSPARENT_PASS) != null && + drawPoint(cameraPos,new Vector3f((float)position.x,(float)position.y,(float)position.z)) + ){ + //fetch actor + Actor currentActor = EntityUtils.getActor(currentEntity); + currentActor.incrementAnimationTime(0.001); + //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(EntityUtils.getScale(currentEntity)); + currentActor.applyModelMatrix(modelTransformMatrix); + //draw + currentActor.draw(); + } + } + + // + // Pass Three: Composite transparency on top of solids + // + glDepthFunc(GL_ALWAYS); + // glDepthMask(false); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - + screenFramebuffer.bind(); + Globals.renderingEngine.setActiveShader(oitCompositeProgram); + + glBindVertexArray(screenTextureVAO); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, 0); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, 0); + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, 0); + glActiveTexture(GL_TEXTURE3); + glBindTexture(GL_TEXTURE_2D, 0); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, transparencyAccumulatorTexture.getTexturePointer()); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, transparencyRevealageTexture.getTexturePointer()); + + glDrawArrays(GL_TRIANGLES, 0, 6); + glBindVertexArray(0); // glBindVertexArray(0); } @@ -732,6 +840,18 @@ public class RenderingEngine { glBindTexture(GL_TEXTURE_2D, volumeDepthBackfaceTexture.getTexturePointer()); } else if(outputFramebuffer == 3){ glBindTexture(GL_TEXTURE_2D, volumeDepthFrontfaceTexture.getTexturePointer()); + } else if(outputFramebuffer == 4){ + glBindTexture(GL_TEXTURE_2D, transparencyAccumulatorTexture.getTexturePointer()); + } else if(outputFramebuffer == 5){ + glBindTexture(GL_TEXTURE_2D, transparencyRevealageTexture.getTexturePointer()); + } else if(outputFramebuffer == 6){ + Globals.renderingEngine.setActiveShader(drawChannel); + glUniform1f(glGetUniformLocation(Globals.renderingEngine.getActiveShader().shaderProgram, "channel"),0); + glBindTexture(GL_TEXTURE_2D, transparencyRevealageTexture.getTexturePointer()); + } else if(outputFramebuffer == 7){ + Globals.renderingEngine.setActiveShader(drawChannel); + glUniform1f(glGetUniformLocation(Globals.renderingEngine.getActiveShader().shaderProgram, "channel"),4); + glBindTexture(GL_TEXTURE_2D, screenTextureDepth.getTexturePointer()); } glDrawArrays(GL_TRIANGLES, 0, 6); glBindVertexArray(0); @@ -766,6 +886,8 @@ public class RenderingEngine { //set the viewport to shadow map size glViewport(0, 0, Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT); glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + glDepthMask(true); //stop rendering front faces GL15.glEnable(GL15.GL_CULL_FACE); @@ -966,7 +1088,7 @@ public class RenderingEngine { public static void incrementOutputFramebuffer(){ outputFramebuffer++; - if(outputFramebuffer > 3){ + if(outputFramebuffer > 7){ outputFramebuffer = 0; } } diff --git a/src/main/java/electrosphere/renderer/framebuffer/Framebuffer.java b/src/main/java/electrosphere/renderer/framebuffer/Framebuffer.java index 0c0aeb6a..1ef0c871 100644 --- a/src/main/java/electrosphere/renderer/framebuffer/Framebuffer.java +++ b/src/main/java/electrosphere/renderer/framebuffer/Framebuffer.java @@ -4,6 +4,7 @@ import electrosphere.logger.LoggerInterface; import java.util.concurrent.TimeUnit; import org.lwjgl.opengl.GL30; import static org.lwjgl.opengl.GL30.GL_FRAMEBUFFER; +import static org.lwjgl.opengl.GL30.GL_DRAW_FRAMEBUFFER; import static org.lwjgl.opengl.GL30.GL_FRAMEBUFFER_COMPLETE; import static org.lwjgl.opengl.GL30.glBindFramebuffer; import static org.lwjgl.opengl.GL30.glCheckFramebufferStatus; diff --git a/src/main/java/electrosphere/renderer/framebuffer/FramebufferUtils.java b/src/main/java/electrosphere/renderer/framebuffer/FramebufferUtils.java index a4b888bd..490a7682 100644 --- a/src/main/java/electrosphere/renderer/framebuffer/FramebufferUtils.java +++ b/src/main/java/electrosphere/renderer/framebuffer/FramebufferUtils.java @@ -4,9 +4,13 @@ import electrosphere.logger.LoggerInterface; import electrosphere.main.Globals; import electrosphere.renderer.texture.Texture; +import java.nio.IntBuffer; import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; + +import org.lwjgl.BufferUtils; + import static org.lwjgl.opengl.GL11.GL_DEPTH_COMPONENT; import static org.lwjgl.opengl.GL11.GL_FLOAT; import static org.lwjgl.opengl.GL11.GL_LINEAR; @@ -31,13 +35,20 @@ import static org.lwjgl.opengl.GL11.glTexParameterfv; import static org.lwjgl.opengl.GL11.glTexParameteri; import static org.lwjgl.opengl.GL12.GL_CLAMP_TO_EDGE; import static org.lwjgl.opengl.GL13.GL_CLAMP_TO_BORDER; +import static org.lwjgl.opengl.GL20.glDrawBuffers; import static org.lwjgl.opengl.GL30.GL_COLOR_ATTACHMENT0; +import static org.lwjgl.opengl.GL30.GL_COLOR_ATTACHMENT1; import static org.lwjgl.opengl.GL30.GL_DEPTH24_STENCIL8; import static org.lwjgl.opengl.GL30.GL_DEPTH_ATTACHMENT; import static org.lwjgl.opengl.GL30.GL_DEPTH_STENCIL_ATTACHMENT; import static org.lwjgl.opengl.GL30.GL_FRAMEBUFFER; import static org.lwjgl.opengl.GL30.GL_FRAMEBUFFER_COMPLETE; import static org.lwjgl.opengl.GL30.GL_RENDERBUFFER; +import static org.lwjgl.opengl.GL30.GL_RGBA16F; +import static org.lwjgl.opengl.GL30.GL_HALF_FLOAT; +import static org.lwjgl.opengl.GL30.GL_R8; +import static org.lwjgl.opengl.GL30.GL_RED; +import static org.lwjgl.opengl.GL30.glBindFramebuffer; import static org.lwjgl.opengl.GL30.glBindRenderbuffer; import static org.lwjgl.opengl.GL30.glCheckFramebufferStatus; import static org.lwjgl.opengl.GL30.glFramebufferRenderbuffer; @@ -51,8 +62,58 @@ import static org.lwjgl.system.MemoryUtil.NULL; * @author amaterasu */ public class FramebufferUtils { + + public static Texture generateScreenTextureColor(int width, int height){ + int texturePtr = glGenTextures(); + glBindTexture(GL_TEXTURE_2D,texturePtr); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + //these make sure the texture actually clamps to the borders of the quad + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + Texture texture = new Texture(texturePtr); + + return texture; + } + + public static Texture generateScreenTextureDepth(int width, int height){ + int texturePtr = glGenTextures(); + glBindTexture(GL_TEXTURE_2D,texturePtr); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL); + + Texture texture = new Texture(texturePtr); + + return texture; + } + public static Framebuffer generateScreenTextureFramebuffer(int width, int height, Texture colorTexture, Texture depthTexture){ + Framebuffer buffer = new Framebuffer(); + buffer.bind(); + //texture + // int texture = glGenTextures(); + // glBindTexture(GL_TEXTURE_2D,texture); + // glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); + // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + // //these make sure the texture actually clamps to the borders of the quad + // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + buffer.setTexturePointer(colorTexture.getTexturePointer()); + //bind texture to fbo + int mipMapLevel = 0; + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture.getTexturePointer(), mipMapLevel); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture.getTexturePointer(), mipMapLevel); + //check make sure compiled + if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE){ + System.out.println("Framebuffer is not complete!"); + } + glBindFramebuffer(GL_FRAMEBUFFER, 0); + return buffer; + } + public static Framebuffer generateScreensizeTextureFramebuffer(){ Framebuffer buffer = new Framebuffer(); buffer.bind(); @@ -202,5 +263,61 @@ public class FramebufferUtils { return buffer; } + public static Texture generateOITAccumulatorTexture(int width, int height){ + int texturePtr = glGenTextures(); + glBindTexture(GL_TEXTURE_2D,texturePtr); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_HALF_FLOAT, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glBindTexture(GL_TEXTURE_2D, 0); + + Texture texture = new Texture(texturePtr); + + return texture; + } + + public static Texture generateOITRevealageTexture(int width, int height){ + int texturePtr = glGenTextures(); + glBindTexture(GL_TEXTURE_2D,texturePtr); + glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, width, height, 0, GL_RED, GL_FLOAT, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glBindTexture(GL_TEXTURE_2D, 0); + + Texture texture = new Texture(texturePtr); + + return texture; + } + + public static Framebuffer generateOITFramebuffer(int width, int height, Texture accumulatorTex, Texture revealageTex, Texture depthTexture){ + Framebuffer buffer = new Framebuffer(); + buffer.bind(); + + + //texture + buffer.setTexturePointer(accumulatorTex.getTexturePointer()); + + //bind texture to fbo + int mipMapLevel = 0; + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, accumulatorTex.getTexturePointer(), mipMapLevel); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, revealageTex.getTexturePointer(), mipMapLevel); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture.getTexturePointer(), mipMapLevel); + + // const GLenum transparentDrawBuffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 }; + // glDrawBuffers(2, transparentDrawBuffers); + IntBuffer drawBuffers = BufferUtils.createIntBuffer(2); + drawBuffers.put(GL_COLOR_ATTACHMENT0); + drawBuffers.put(GL_COLOR_ATTACHMENT1); + drawBuffers.flip(); + glDrawBuffers(drawBuffers); + + //check make sure compiled + if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE){ + System.out.println("Framebuffer is not complete!"); + } + glBindFramebuffer(GL_FRAMEBUFFER, 0); + return buffer; + } + }