From 90aa9fb963428552dee132c882876a3f1aac1ebc Mon Sep 17 00:00:00 2001 From: austin Date: Tue, 1 Mar 2022 23:24:46 -0500 Subject: [PATCH] Volumetric rendering --- assets/Shaders/backup/FragmentShader.fs | 165 ------------ assets/Shaders/backup/NewVertexShader.vs | 97 ------- assets/Shaders/flame2/flame.fs | 255 ++++++++++++++++++ assets/Shaders/flame2/flame.vs | 43 +++ assets/Shaders/old/LampShader.fs | 13 - assets/Shaders/old/VertexShader.vs | 68 ----- assets/Shaders/old/old shader code | 61 ----- assets/Shaders/old/oldFragShader.fs | 34 --- assets/Shaders/volumeBuffer/volumetric.fs | 37 +++ assets/Shaders/volumeBuffer/volumetric.vs | 40 +++ .../controls/ControlHandler.java | 9 +- .../electrosphere/engine/LoadingThread.java | 46 ++-- .../entity/EntityDataStrings.java | 1 + .../game/client/cells/DrawCell.java | 21 +- .../java/electrosphere/renderer/Mesh.java | 19 +- .../java/electrosphere/renderer/Model.java | 15 ++ .../renderer/RenderingEngine.java | 213 ++++++++++++++- .../electrosphere/renderer/actor/Actor.java | 12 + .../renderer/actor/ActorTextureMask.java | 31 +++ .../framebuffer/FramebufferUtils.java | 46 ++++ .../renderer/texture/Texture.java | 7 + 21 files changed, 745 insertions(+), 488 deletions(-) delete mode 100644 assets/Shaders/backup/FragmentShader.fs delete mode 100644 assets/Shaders/backup/NewVertexShader.vs create mode 100644 assets/Shaders/flame2/flame.fs create mode 100644 assets/Shaders/flame2/flame.vs delete mode 100644 assets/Shaders/old/LampShader.fs delete mode 100644 assets/Shaders/old/VertexShader.vs delete mode 100644 assets/Shaders/old/old shader code delete mode 100644 assets/Shaders/old/oldFragShader.fs create mode 100644 assets/Shaders/volumeBuffer/volumetric.fs create mode 100644 assets/Shaders/volumeBuffer/volumetric.vs create mode 100644 src/main/java/electrosphere/renderer/actor/ActorTextureMask.java diff --git a/assets/Shaders/backup/FragmentShader.fs b/assets/Shaders/backup/FragmentShader.fs deleted file mode 100644 index b9c17f24..00000000 --- a/assets/Shaders/backup/FragmentShader.fs +++ /dev/null @@ -1,165 +0,0 @@ - - -#version 430 core -out vec4 FragColor; - -struct Material { - sampler2D diffuse; - sampler2D specular; - float shininess; -}; - -struct DirLight { - vec3 direction; - - vec3 ambient; - vec3 diffuse; - vec3 specular; -}; - -struct PointLight { - vec3 position; - - float constant; - float linear; - float quadratic; - - vec3 ambient; - vec3 diffuse; - vec3 specular; -}; - -struct SpotLight { - vec3 position; - vec3 direction; - float cutOff; - float outerCutOff; - - float constant; - float linear; - float quadratic; - - vec3 ambient; - vec3 diffuse; - vec3 specular; -}; - -#define NR_POINT_LIGHTS 4 - -in vec3 FragPos; -in vec3 Normal; -in vec2 TexCoords; - - -uniform int fragHasTexture; - -uniform vec3 viewPos; -uniform DirLight dirLight; -uniform PointLight pointLights[NR_POINT_LIGHTS]; -uniform SpotLight spotLight; -uniform Material material; - -// function prototypes -vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir); -vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir); -vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir); - -void main() -{ - // properties - vec3 norm = normalize(Normal); - vec3 viewDir = normalize(viewPos - FragPos); - - // == ===================================================== - // Our lighting is set up in 3 phases: directional, point lights and an optional flashlight - // For each phase, a calculate function is defined that calculates the corresponding color - // per lamp. In the main() function we take all the calculated colors and sum them up for - // this fragment's final color. - // == ===================================================== - // phase 1: directional lighting - vec3 result = CalcDirLight(dirLight, norm, viewDir); - // phase 2: point lights - //for(int i = 0; i < NR_POINT_LIGHTS; i++) - // result += CalcPointLight(pointLights[i], norm, FragPos, viewDir); - // phase 3: spot light - //result += CalcSpotLight(spotLight, norm, FragPos, viewDir); - - FragColor = vec4(result, 1.0); -} - -// calculates the color when using a directional light. -vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir) -{ - vec3 lightDir = normalize(-light.direction); - // diffuse shading - float diff = max(dot(normal, lightDir), 0.0); - // specular shading - vec3 reflectDir = reflect(-lightDir, normal); - float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); - // combine results - vec3 ambient = vec3(1.0,1.0,1.0); - vec3 diffuse = vec3(1.0,1.0,1.0); - vec3 specular = vec3(1.0,1.0,1.0); - if(fragHasTexture == 1){ - ambient = light.ambient;// * vec3(texture(material.diffuse, TexCoords)); - diffuse = light.diffuse * diff;// * vec3(texture(material.diffuse, TexCoords)); - specular = light.specular * spec;// * vec3(texture(material.specular, TexCoords)); - } else { - ambient = light.ambient;// * vec3(texture(material.diffuse, TexCoords)); - diffuse = light.diffuse * diff;// * vec3(texture(material.diffuse, TexCoords)); - specular = light.specular * spec;// * vec3(texture(material.specular, TexCoords)); - } - //vec3 ambient = light.ambient;// * vec3(texture(material.diffuse, TexCoords)); - //vec3 diffuse = light.diffuse * diff;// * vec3(texture(material.diffuse, TexCoords)); - //vec3 specular = light.specular * spec;// * vec3(texture(material.specular, TexCoords)); - return (ambient + diffuse);// + specular); -} - -// calculates the color when using a point light. -vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir) -{ - vec3 lightDir = normalize(light.position - fragPos); - // diffuse shading - float diff = max(dot(normal, lightDir), 0.0); - // specular shading - vec3 reflectDir = reflect(-lightDir, normal); - float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); - // attenuation - float distance = length(light.position - fragPos); - float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance)); - // combine results - vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords)); - vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords)); - vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords)); - ambient *= attenuation; - diffuse *= attenuation; - specular *= attenuation; - return (ambient + diffuse + specular); -} - -// calculates the color when using a spot light. -vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir) -{ - vec3 lightDir = normalize(light.position - fragPos); - // diffuse shading - float diff = max(dot(normal, lightDir), 0.0); - // specular shading - vec3 reflectDir = reflect(-lightDir, normal); - float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); - // attenuation - float distance = length(light.position - fragPos); - float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance)); - // spotlight intensity - float theta = dot(lightDir, normalize(-light.direction)); - float epsilon = light.cutOff - light.outerCutOff; - float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0); - // combine results - vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords)); - vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords)); - vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords)); - ambient *= attenuation * intensity; - diffuse *= attenuation * intensity; - specular *= attenuation * intensity; - return (ambient + diffuse + specular); -} - diff --git a/assets/Shaders/backup/NewVertexShader.vs b/assets/Shaders/backup/NewVertexShader.vs deleted file mode 100644 index 01885edb..00000000 --- a/assets/Shaders/backup/NewVertexShader.vs +++ /dev/null @@ -1,97 +0,0 @@ -//Vertex Shader -#version 430 core - - - - -layout (location = 0) in vec3 aPos; -layout (location = 1) in vec3 aNormal; -layout (location = 2) in vec4 aWeights; -layout (location = 3) in vec4 aIndex; -layout (location = 4) in vec2 aText; - - - -uniform mat4 transform; -uniform mat4 model; -uniform mat4 view; -uniform mat4 projection; - - -const int MAX_BONES = 100; -uniform mat4 bones[MAX_BONES]; -uniform int hasBones; -uniform int numBones; - -uniform int hasTexture; - - - -out vec3 Normal; -out vec3 FragPos; -out vec2 TexCoords; - - - - -void main() -{ - vec4 FinalVertex = vec4(aPos, 1.0); - vec4 FinalNormal = vec4(aNormal, 0.0); - if(hasBones == 1){ - //mat4 BoneTransform; - //for(int i = 0; i < MAX_BONES; i++){ - // if(i < numBones){ - // BoneTransform += bones[i] * aWeights[i]; - // } - //} - //vec4 FinalVertex = vec4(aPos, 1.0); - //vec4 FinalNormal = vec4(aNormal, 1.0); - //mat4 BoneTransform; - //BoneTransform = mat4( - // 1.0,0.0,0.0,0.0, - // 0.0,1.0,0.0,0.0, - // 0.0,0.0,1.0,0.0, - // 0.0,0.0,0.0,1.0); - //BoneTransform = BoneTransform * mat4( - // 1.0,0.0,0.0,0.0, - // 0.0,1.0,0.0,0.0, - // 0.0,0.0,2.0,0.0, - // 0.0,0.0,0.0,1.0); - //BoneTransform = BoneTransform * bones[aIndex[0]] * aWeights[0]; - //BoneTransform += bones[aIndex[0]] * 1.0; - //BoneTransform += bones[aIndex[1]] * aWeights[1]; - //BoneTransform += bones[aIndex[2]] * aWeights[2]; - //BoneTransform += bones[aIndex[3]] * aWeights[3]; - //FinalVertex = BoneTransform * FinalVertex; - vec4 inputVertex = FinalVertex; - vec4 inputNormal = FinalNormal; - //mat4 BoneTransform; - //BoneTransform = bones[int(aIndex[0])] * aWeights[0]; - //BoneTransform += bones[int(aIndex[1])] * aWeights[1]; - //BoneTransform += bones[int(aIndex[2])] * aWeights[2]; - //BoneTransform += bones[int(aIndex[3])] * aWeights[3]; - //FinalVertex = BoneTransform * inputVertex; - //FinalNormal = BoneTransform * inputNormal; - FinalVertex = (bones[int(aIndex[0])] * inputVertex) * aWeights[0]; - FinalVertex = (bones[int(aIndex[1])] * inputVertex) * aWeights[1] + FinalVertex; - FinalVertex = (bones[int(aIndex[2])] * inputVertex) * aWeights[2] + FinalVertex; - FinalVertex = (bones[int(aIndex[3])] * inputVertex) * aWeights[3] + FinalVertex; - FinalNormal = (bones[int(aIndex[0])] * inputNormal) * aWeights[0]; - FinalNormal = (bones[int(aIndex[1])] * inputNormal) * aWeights[1] + FinalNormal; - FinalNormal = (bones[int(aIndex[2])] * inputNormal) * aWeights[2] + FinalNormal; - FinalNormal = (bones[int(aIndex[3])] * inputNormal) * aWeights[3] + FinalNormal; - } else { - //gl_Position = projection * view * model * vec4(aPos, 1.0); - } - - vec2 FinalTexture = vec2(1.0,1.0); - if(hasTexture == 1){ - FinalTexture = aText; - } - TexCoords = FinalTexture; - - FragPos = vec3(model * FinalVertex); - Normal = vec3(transpose(inverse(model)) * FinalNormal); - gl_Position = projection * view * model * FinalVertex; -} \ No newline at end of file diff --git a/assets/Shaders/flame2/flame.fs b/assets/Shaders/flame2/flame.fs new file mode 100644 index 00000000..382b4725 --- /dev/null +++ b/assets/Shaders/flame2/flame.fs @@ -0,0 +1,255 @@ +/* +MIT License + +Copyright (c) 2022 railgunSR + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +/* +THIS MAKES USE OF OPENSIMPLEX2, A NOISE ALGORITHM CREATED BY THE FINE FOLKS +OVER AT https://github.com/KdotJPG/OpenSimplex2 +PLEASE GIVE THEM SOME LOVE. + +THE FLAME FUNCTION IS ONE CREATED BY ME BLENDING A LOG2 INTO A EXPONENTIAL. +*/ + +//version +#version 330 core + +//macros +#extension GL_ARB_explicit_uniform_location : enable + +//output +out vec4 fragColor; + +//input +in vec3 FragPos; +in vec3 Normal; +in vec2 TexCoord; +in vec4 projCoord; + +//uniforms +uniform float time; + +//layout uniforms +layout (location = 5) uniform sampler2D volumeDepthFrontface; +layout (location = 6) uniform sampler2D volumeDepthBackface; + +//function declarations +vec4 openSimplex2_ImproveXY(vec3 X); +float flameTex(float x, float y); + +/* +Main method +*/ +void main(){ + + float timeS = time * 0.003; + + // Normalized pixel coordinates (from 0 to 1) + // vec2 uv = vec2(TexCoord.x,TexCoord.y); + + vec3 projCoordNorm = projCoord.xyz / projCoord.w / 2.0 + 0.5; + + // vec2 finalProd = vec2((projCoord.x + 1.0)/2.0, (projCoord.y + 1.0)/2.0); + vec2 finalProd = projCoordNorm.xy; + + // float closeDepth = texture(volumeDepthFrontface, projCoordNorm.xy).r; + // float farDepth = texture(volumeDepthBackface, projCoordNorm.xy).r; + + float closeDepth = texture(volumeDepthFrontface, finalProd.xy).r; + float farDepth = texture(volumeDepthBackface, finalProd.xy).r; + + // float closeDepth = texture(volumeDepthFrontface, uv).r; + // float farDepth = texture(volumeDepthBackface, uv).r; + + + float dist = farDepth - closeDepth; + + float red = 0; + float green = 0; + float blue = 0; + + // if(projCoordNorm.x > -0.4 && projCoordNorm.x < 0.6 && projCoordNorm.y > -0.4 && projCoordNorm.y < 0.1){ + // dist = 0.1; + // green = 1; + // blue = closeDepth; + // } + + // if(closeDepth != 1){ + // blue = 1; + // } + // val = dist; + + // red = projCoordNorm.x; + // green = projCoordNorm.y; + // blue = 0; + + // if(mod(TexCoord.x,0.01) < 0.005){ + // red = 1; + // } + // if(mod(TexCoord.y,0.01) < 0.005){ + // green = 1; + // } + + // if(dist != 0){ + // red = 1; + // green = 1; + // blue = 1; + // } + + red = dist; + green = dist; + blue = dist; + + vec4 color = vec4( + red, + green, + blue, + 1.0 + ); + + // if(val < 0.3){ + // discard; + // } + + // Output to screen + fragColor = color; +} + +// +//custom flame function +/// + +float flameTex(float x, float y){ + //flip y + float t = 1.0 - y; + //calculate vertical component + float verticalFlameValue = pow(log(t+1.0),1.4) - step(0.5,t) * (pow((2.0 * (t - 0.5)),3.0) / pow(log(2.0),1.4)); + //calculate dist along horizontal from vertical component + float dist = abs(x-0.5); + //want to fade to nothing at dist >= vertical flame value + //use exponent to get there + //clamp range with min + float v = max(2.0 * (verticalFlameValue - dist),0.0); + //apply exponent to get value + float rVal = pow(v,1.4); + return rVal; +} + + + +//////////////// K.jpg's Re-oriented 4-Point BCC Noise (OpenSimplex2) //////////////// +////////////////////// Output: vec4(dF/dx, dF/dy, dF/dz, value) ////////////////////// + +// Inspired by Stefan Gustavson's noise +vec4 permute(vec4 t) { + return t * (t * 34.0 + 133.0); +} + +// Gradient set is a normalized expanded rhombic dodecahedron +vec3 grad(float hash) { + + // Random vertex of a cube, +/- 1 each + vec3 cube = mod(floor(hash / vec3(1.0, 2.0, 4.0)), 2.0) * 2.0 - 1.0; + + // Random edge of the three edges connected to that vertex + // Also a cuboctahedral vertex + // And corresponds to the face of its dual, the rhombic dodecahedron + vec3 cuboct = cube; + cuboct[int(hash / 16.0)] = 0.0; + + // In a funky way, pick one of the four points on the rhombic face + float type = mod(floor(hash / 8.0), 2.0); + vec3 rhomb = (1.0 - type) * cube + type * (cuboct + cross(cube, cuboct)); + + // Expand it so that the new edges are the same length + // as the existing ones + vec3 grad = cuboct * 1.22474487139 + rhomb; + + // To make all gradients the same length, we only need to shorten the + // second type of vector. We also put in the whole noise scale constant. + // The compiler should reduce it into the existing floats. I think. + grad *= (1.0 - 0.042942436724648037 * type) * 32.80201376986577; + + return grad; +} + +// BCC lattice split up into 2 cube lattices +vec4 openSimplex2Base(vec3 X) { + + // First half-lattice, closest edge + vec3 v1 = round(X); + vec3 d1 = X - v1; + vec3 score1 = abs(d1); + vec3 dir1 = step(max(score1.yzx, score1.zxy), score1); + vec3 v2 = v1 + dir1 * sign(d1); + vec3 d2 = X - v2; + + // Second half-lattice, closest edge + vec3 X2 = X + 144.5; + vec3 v3 = round(X2); + vec3 d3 = X2 - v3; + vec3 score2 = abs(d3); + vec3 dir2 = step(max(score2.yzx, score2.zxy), score2); + vec3 v4 = v3 + dir2 * sign(d3); + vec3 d4 = X2 - v4; + + // Gradient hashes for the four points, two from each half-lattice + vec4 hashes = permute(mod(vec4(v1.x, v2.x, v3.x, v4.x), 289.0)); + hashes = permute(mod(hashes + vec4(v1.y, v2.y, v3.y, v4.y), 289.0)); + hashes = mod(permute(mod(hashes + vec4(v1.z, v2.z, v3.z, v4.z), 289.0)), 48.0); + + // Gradient extrapolations & kernel function + vec4 a = max(0.5 - vec4(dot(d1, d1), dot(d2, d2), dot(d3, d3), dot(d4, d4)), 0.0); + vec4 aa = a * a; vec4 aaaa = aa * aa; + vec3 g1 = grad(hashes.x); vec3 g2 = grad(hashes.y); + vec3 g3 = grad(hashes.z); vec3 g4 = grad(hashes.w); + vec4 extrapolations = vec4(dot(d1, g1), dot(d2, g2), dot(d3, g3), dot(d4, g4)); + + // Derivatives of the noise + vec3 derivative = -8.0 * mat4x3(d1, d2, d3, d4) * (aa * a * extrapolations) + + mat4x3(g1, g2, g3, g4) * aaaa; + + // Return it all as a vec4 + return vec4(derivative, dot(aaaa, extrapolations)); +} + +// Use this if you don't want Z to look different from X and Y +vec4 openSimplex2_Conventional(vec3 X) { + + // Rotate around the main diagonal. Not a skew transform. + vec4 result = openSimplex2Base(dot(X, vec3(2.0/3.0)) - X); + return vec4(dot(result.xyz, vec3(2.0/3.0)) - result.xyz, result.w); +} + +// Use this if you want to show X and Y in a plane, then use Z for time, vertical, etc. +vec4 openSimplex2_ImproveXY(vec3 X) { + + // Rotate so Z points down the main diagonal. Not a skew transform. + mat3 orthonormalMap = mat3( + 0.788675134594813, -0.211324865405187, -0.577350269189626, + -0.211324865405187, 0.788675134594813, -0.577350269189626, + 0.577350269189626, 0.577350269189626, 0.577350269189626); + + vec4 result = openSimplex2Base(orthonormalMap * X); + return vec4(result.xyz * orthonormalMap, result.w); +} + +//////////////////////////////// End noise code //////////////////////////////// \ No newline at end of file diff --git a/assets/Shaders/flame2/flame.vs b/assets/Shaders/flame2/flame.vs new file mode 100644 index 00000000..36deec99 --- /dev/null +++ b/assets/Shaders/flame2/flame.vs @@ -0,0 +1,43 @@ +//Vertex Shader +#version 330 core + + + +//input buffers +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; +layout (location = 4) in vec2 aTex; + + +//coordinate space transformation matrices +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; +uniform float time; + + + +//output buffers +out vec3 FragPos; +out vec3 Normal; +out vec2 TexCoord; +out vec4 projCoord; + + + +void main() { + //normalize posiiton and normal + vec4 FinalVertex = vec4(aPos, 1.0); + vec4 FinalNormal = vec4(aNormal, 1.0); + + + //push frag, normal, and texture positions to fragment shader + FragPos = vec3(model * FinalVertex); + Normal = mat3(transpose(inverse(model))) * aNormal; + TexCoord = aTex; + projCoord = projection * view * model * FinalVertex; + + + //set final position with opengl space + gl_Position = projection * view * model * FinalVertex; +} diff --git a/assets/Shaders/old/LampShader.fs b/assets/Shaders/old/LampShader.fs deleted file mode 100644 index 34b7eeca..00000000 --- a/assets/Shaders/old/LampShader.fs +++ /dev/null @@ -1,13 +0,0 @@ -//Fragment Shader -#version 330 core - - -out vec4 FragColor; - -uniform vec3 objectColor; -uniform vec3 lightColor; - -void main() -{ -FragColor = vec4(1.0); -} diff --git a/assets/Shaders/old/VertexShader.vs b/assets/Shaders/old/VertexShader.vs deleted file mode 100644 index b1013f2a..00000000 --- a/assets/Shaders/old/VertexShader.vs +++ /dev/null @@ -1,68 +0,0 @@ -//Vertex Shader -#version 430 core - - - - -layout (location = 0) in vec3 aPos; -layout (location = 1) in vec3 aNormal; -layout (location = 2) in vec4 aWeights; -layout (location = 3) in ivec4 aIndex; - - - -uniform mat4 transform; -uniform mat4 model; -uniform mat4 view; -uniform mat4 projection; - - -const int MAX_BONES = 100; -uniform mat4 bones[MAX_BONES]; -uniform int hasBones; -uniform int numBones; - - - -out vec3 Normal; -out vec3 FragPos; -out vec2 TexCoords; - - - -void main() -{ - if(hasBones == 1){ - //mat4 BoneTransform; - //for(int i = 0; i < MAX_BONES; i++){ - // if(i < numBones){ - // BoneTransform += bones[i] * aWeights[i]; - // } - //} - mat4 BoneTransform; - BoneTransform = mat4( - 1.0,0.0,0.0,0.0, - 0.0,1.0,0.0,0.0, - 0.0,0.0,1.0,0.0, - 0.0,0.0,0.0,1.0); - //BoneTransform = BoneTransform * mat4( - // 1.0,0.0,0.0,0.0, - // 0.0,1.0,0.0,0.0, - // 0.0,0.0,2.0,0.0, - // 0.0,0.0,0.0,1.0); - BoneTransform = BoneTransform * bones[aIndex[0]] * aWeights[0]; - BoneTransform += BoneTransform * bones[aIndex[1]] * aWeights[1]; - BoneTransform += BoneTransform * bones[aIndex[2]] * aWeights[2]; - BoneTransform += BoneTransform * bones[aIndex[3]] * aWeights[3]; - //BoneTransform += bones[aIndex[0]] * 1.0; - //BoneTransform += bones[aIndex[1]] * aWeights[1]; - //BoneTransform += bones[aIndex[2]] * aWeights[2]; - //BoneTransform += bones[aIndex[3]] * aWeights[3]; - gl_Position = projection * view * model * BoneTransform * vec4(aPos, 1.0); - } else { - gl_Position = projection * view * model * vec4(aPos, 1.0); - } - FragPos = vec3(model * vec4(aPos, 1.0)); - Normal = vec3(vec4(aNormal, 1.0)); - TexCoords = vec2(0.5, 0.5); -} \ No newline at end of file diff --git a/assets/Shaders/old/old shader code b/assets/Shaders/old/old shader code deleted file mode 100644 index ebace10c..00000000 --- a/assets/Shaders/old/old shader code +++ /dev/null @@ -1,61 +0,0 @@ -//Vertex Shader -#version 330 core -layout (location = 0) in vec3 aPos; -//layout (location = 1) in vec3 aColor; -//layout (location = 1) in vec2 aTexCoord; -//layout (location = 2) in vec3 aNormal; - -//out vec3 ourColor; - -//uniform vec3 offset; - -uniform mat4 transform; -uniform mat4 model; -uniform mat4 view; -uniform mat4 projection; - -//out vec3 ourPos; -//out vec2 TexCoord; -//out vec3 FragPos; -//out vec3 Normal; -void main() -{ -//gl_Position = vec4(aPos, 1.0); -gl_Position = projection * view * model * vec4(aPos, 1.0); -//ourColor = aColor; -//FragPos = vec3(model * vec4(aPos, 1.0)); -//TexCoord = aTexCoord; -//Normal = mat3(transpose(inverse(model))) * aNormal; -} - - - - - -//Fragment Shader -#version 330 core - - -out vec4 FragColor; - -//in vec3 ourColor; - -//in vec2 TexCoord; -//uniform sampler2D ourTexture1; -//uniform sampler2D ourTexture2; -//in vec3 Normal; -//uniform vec3 lightPos; -//in vec3 FragPos; - - -void main() -{ -//vec3 lightColor = vec3(1.0, 1.0, 1.0); -//vec3 norm = normalize(Normal); -//vec3 lightDir = normalize(lightPos - FragPos); -//float diff = max(dot(Normal, lightDir), 0.0); -//vec3 diffuse = diff * lightColor; -//vec3 result = diffuse * objectColor; -//FragColor = mix(texture(ourTexture1, TexCoord), texture(ourTexture2, TexCoord), 0.2);// - (vec4(diffuse, 1.0)*0.2);// * vec4(ourColor, 1.0); -FragColor = vec4(0.5, 0.5, 0.5, 1.0); -} diff --git a/assets/Shaders/old/oldFragShader.fs b/assets/Shaders/old/oldFragShader.fs deleted file mode 100644 index e429040f..00000000 --- a/assets/Shaders/old/oldFragShader.fs +++ /dev/null @@ -1,34 +0,0 @@ -//Fragment Shader -#version 330 core - -in vec3 FragPos; -in vec3 Normal; - -uniform vec3 objectColor; -uniform vec3 lightColor; -uniform vec3 lightPos; -uniform vec3 viewPos; - -out vec4 FragColor; - -void main() -{ -//Diffuse calculations.. -vec3 norm = normalize(Normal); -vec3 lightDir = normalize(lightPos - FragPos); -float diff = max(dot(norm, lightDir), 0.0); -vec3 diffuse = diff * lightColor; -//Ambient Light -float ambientStrength = 0.5; -vec3 ambient = ambientStrength * lightColor; -//Specular calculations.. -float specularStrength = 0.5; -vec3 viewDir = normalize(viewPos - FragPos); -vec3 reflectDir = reflect(-lightDir, norm); -float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32); -vec3 specular = specularStrength * spec * lightColor; -//result color -vec3 result = (ambient + diffuse + specular) * objectColor; -//push output color -FragColor = vec4(result, 1.0); -} diff --git a/assets/Shaders/volumeBuffer/volumetric.fs b/assets/Shaders/volumeBuffer/volumetric.fs new file mode 100644 index 00000000..d017dd20 --- /dev/null +++ b/assets/Shaders/volumeBuffer/volumetric.fs @@ -0,0 +1,37 @@ +#version 330 core + +uniform float linearCoef; +uniform float quadCoef; + +uniform float near; +uniform float far; + +float LinearizeDepth(float depth); + +void main(){ + // float coord = gl_FragCoord.x; + // if(coord != 1){ + // gl_FragDepth = 0; + // } else { + // gl_FragDepth = 1; + // } + + float depthRaw = gl_FragCoord.z; + + // if(depthRaw != 1){ + // depthRaw = 0; + // } + + float finalValue = LinearizeDepth(depthRaw) / sqrt(far);//min(depthRaw * linearCoef + depthRaw * depthRaw * quadCoef,1); + + gl_FragDepth = finalValue; +} + + +// +//Util +// +float LinearizeDepth(float depth){ + float z = depth * 2.0 - 1.0; // back to NDC + return (2.0 * near * far) / (far + near - z * (far - near)); +} \ No newline at end of file diff --git a/assets/Shaders/volumeBuffer/volumetric.vs b/assets/Shaders/volumeBuffer/volumetric.vs new file mode 100644 index 00000000..9d8f828b --- /dev/null +++ b/assets/Shaders/volumeBuffer/volumetric.vs @@ -0,0 +1,40 @@ +#version 330 core + +layout (location = 0) in vec3 aPos; +layout (location = 2) in vec4 aWeights; +layout (location = 3) in vec4 aIndex; + +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; + +//bone related variables +const int MAX_WEIGHTS = 4; +const int MAX_BONES = 100; +uniform mat4 bones[MAX_BONES]; +uniform int numBones; +uniform int hasBones; + +void main() +{ + //calculate bone transform + mat4 BoneTransform = (bones[int(aIndex[0])] * aWeights[0]); + BoneTransform = BoneTransform + (bones[int(aIndex[1])] * aWeights[1]); + BoneTransform = BoneTransform + (bones[int(aIndex[2])] * aWeights[2]); + BoneTransform = BoneTransform + (bones[int(aIndex[3])] * aWeights[3]); + + + //apply bone transform to position vectors + vec4 FinalVertex = BoneTransform * vec4(aPos, 1.0); + + + //make sure the W component is 1.0 + FinalVertex = vec4(FinalVertex.xyz, 1.0); + + //have to account for if dont have bones + if(hasBones == 0){ + FinalVertex = vec4(aPos, 1.0); + } + + gl_Position = projection * view * model * FinalVertex; +} \ No newline at end of file diff --git a/src/main/java/electrosphere/controls/ControlHandler.java b/src/main/java/electrosphere/controls/ControlHandler.java index 70867ff5..829087b5 100644 --- a/src/main/java/electrosphere/controls/ControlHandler.java +++ b/src/main/java/electrosphere/controls/ControlHandler.java @@ -24,6 +24,7 @@ import electrosphere.menu.WindowStrings; import electrosphere.menu.WindowUtils; import electrosphere.menu.MenuCallbacks; import electrosphere.menu.MenuGenerators; +import electrosphere.renderer.RenderingEngine; import electrosphere.renderer.ui.DrawableElement; import electrosphere.renderer.ui.Element; import electrosphere.renderer.ui.Window; @@ -765,10 +766,12 @@ public class ControlHandler { void setInGameDebugControls(){ mainGameDebugControlList.add(controls.get(DATA_STRING_INPUT_CODE_DEBUG_SPAWN_ITEM)); controls.get(DATA_STRING_INPUT_CODE_DEBUG_SPAWN_ITEM).setOnPress(new ControlMethod(){public void execute(){ - Entity bow = ItemUtils.spawnBasicItem("shorts1"); - EntityUtils.getPosition(bow).set(1, 5, 2); - CollisionObjUtils.positionCharacter(bow, new Vector3f(1, 5, 2)); + RenderingEngine.incrementOutputFramebuffer(); + // Entity bow = ItemUtils.spawnBasicItem("shorts1"); + // EntityUtils.getPosition(bow).set(1, 5, 2); + // CollisionObjUtils.positionCharacter(bow, new Vector3f(1, 5, 2)); }}); + // RenderingEngine.incrementOutputFramebuffer(); } void setMenuNavigationControls(){ diff --git a/src/main/java/electrosphere/engine/LoadingThread.java b/src/main/java/electrosphere/engine/LoadingThread.java index e978443f..8be62372 100644 --- a/src/main/java/electrosphere/engine/LoadingThread.java +++ b/src/main/java/electrosphere/engine/LoadingThread.java @@ -3,6 +3,7 @@ package electrosphere.engine; import electrosphere.collision.dispatch.CollisionObject; import electrosphere.controls.ControlHandler; import electrosphere.entity.Entity; +import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityUtils; import electrosphere.entity.state.ApplyRotationTree; import electrosphere.game.collision.CollisionEngine; @@ -40,10 +41,13 @@ import electrosphere.menu.WindowUtils; import electrosphere.net.NetUtils; import electrosphere.net.client.ClientNetworking; import electrosphere.net.server.Server; +import electrosphere.renderer.Mesh; import electrosphere.renderer.Model; import electrosphere.renderer.RenderUtils; import electrosphere.renderer.actor.Actor; +import electrosphere.renderer.actor.ActorTextureMask; import electrosphere.renderer.actor.ActorUtils; +import electrosphere.renderer.texture.Texture; import electrosphere.engine.assetmanager.AssetDataStrings; import electrosphere.game.client.targeting.crosshair.Crosshair; import electrosphere.game.server.ai.creature.OpportunisticAttacker; @@ -55,6 +59,8 @@ import electrosphere.renderer.ui.DrawableElement; import electrosphere.renderer.ui.WidgetUtils; import electrosphere.renderer.ui.Window; +import java.util.LinkedList; +import java.util.List; import java.util.Random; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; @@ -679,36 +685,28 @@ public class LoadingThread extends Thread { Actor fireActor = EntityUtils.getActor(fire); fireActor.maskShader("particleBillboard", "Shaders/flame1/flame.vs", "Shaders/flame1/flame.fs"); Globals.assetManager.addShaderToQueue("Shaders/flame1/flame.vs", "Shaders/flame1/flame.fs"); - //corner flame 1 - fire = ParticleUtils.spawnStaticBillboardParticle(); - EntityUtils.getPosition(fire).set(new Vector3f(1.05f,0.1f,0.95f)); - EntityUtils.getScale(fire).set(0.4f); - fireActor = EntityUtils.getActor(fire); - fireActor.maskShader("particleBillboard", "Shaders/flame1/flame.vs", "Shaders/flame1/flame.fs"); - //corner flame 2 - fire = ParticleUtils.spawnStaticBillboardParticle(); - EntityUtils.getPosition(fire).set(new Vector3f(1.05f,0.1f,1.05f)); - EntityUtils.getScale(fire).set(0.4f); - fireActor = EntityUtils.getActor(fire); - fireActor.maskShader("particleBillboard", "Shaders/flame1/flame.vs", "Shaders/flame1/flame.fs"); - //corner flame 3 - fire = ParticleUtils.spawnStaticBillboardParticle(); - EntityUtils.getPosition(fire).set(new Vector3f(0.95f,0.1f,0.95f)); - EntityUtils.getScale(fire).set(0.4f); - fireActor = EntityUtils.getActor(fire); - fireActor.maskShader("particleBillboard", "Shaders/flame1/flame.vs", "Shaders/flame1/flame.fs"); - //corner flame 4 - fire = ParticleUtils.spawnStaticBillboardParticle(); - EntityUtils.getPosition(fire).set(new Vector3f(0.95f,0.1f,1.05f)); - EntityUtils.getScale(fire).set(0.4f); - fireActor = EntityUtils.getActor(fire); - fireActor.maskShader("particleBillboard", "Shaders/flame1/flame.vs", "Shaders/flame1/flame.fs"); //campfire Entity campfire = EntityUtils.spawnDrawableEntity("Models/campfire1.fbx"); EntityUtils.getPosition(campfire).set(1,0,1); EntityUtils.getRotation(campfire).rotationX(-(float)Math.PI/2.0f); + Entity cube = EntityUtils.spawnDrawableEntity("Models/unitcube.fbx"); + //shader mask + EntityUtils.getActor(cube).maskShader("Cube", "Shaders/flame2/flame.vs", "Shaders/flame2/flame.fs"); + Globals.assetManager.addShaderToQueue("Shaders/flame2/flame.vs", "Shaders/flame2/flame.fs"); + //texture mask + List textureList = new LinkedList(); + textureList.add(Globals.renderingEngine.getVolumeFrontfaceTexture()); + textureList.add(Globals.renderingEngine.getVolumeBackfaceTexture()); + List uniformList = new LinkedList(); + uniformList.add("volumeDepthFrontface"); + uniformList.add("volumeDepthBackface"); + ActorTextureMask textureMask = new ActorTextureMask("Cube",textureList,uniformList); + EntityUtils.getActor(cube).addTextureMask(textureMask); + //set draw volumetric + cube.putData(EntityDataStrings.DRAW_VOLUMETRIC, true); + // goblin = CreatureUtils.spawnBasicCreature("Goblin"); // CollisionObjUtils.positionCharacter(goblin, new Vector3f(3, 0, 4)); // EntityUtils.getScale(goblin).set(0.005f); diff --git a/src/main/java/electrosphere/entity/EntityDataStrings.java b/src/main/java/electrosphere/entity/EntityDataStrings.java index 091fabc6..9c5c0991 100644 --- a/src/main/java/electrosphere/entity/EntityDataStrings.java +++ b/src/main/java/electrosphere/entity/EntityDataStrings.java @@ -17,6 +17,7 @@ public class EntityDataStrings { public static final String DATA_STRING_ACTOR = "actor"; public static final String DATA_STRING_DRAW = "drawFlag"; public static final String DRAW_CAST_SHADOW = "castShadow"; + public static final String DRAW_VOLUMETRIC = "drawVolumetric"; /* diff --git a/src/main/java/electrosphere/game/client/cells/DrawCell.java b/src/main/java/electrosphere/game/client/cells/DrawCell.java index 490dff9b..3c33b484 100644 --- a/src/main/java/electrosphere/game/client/cells/DrawCell.java +++ b/src/main/java/electrosphere/game/client/cells/DrawCell.java @@ -15,8 +15,13 @@ import electrosphere.renderer.Model; import electrosphere.renderer.ModelUtils; import electrosphere.renderer.RenderUtils; import electrosphere.renderer.ShaderProgram; +import electrosphere.renderer.actor.ActorTextureMask; import electrosphere.renderer.texture.Texture; import electrosphere.util.Utilities; + +import java.util.LinkedList; +import java.util.List; + import org.joml.Quaternionf; import org.joml.Vector3f; @@ -96,13 +101,19 @@ public class DrawCell { } Model terrainModel = RenderUtils.createMinimizedTerrainModelPrecomputedShader(heightmap, texturemap, program, stride); Mesh terrainMesh = terrainModel.meshes.get(0); - terrainMesh.useTextureList = true; - terrainMesh.textureList.add(groundTextureOne); - terrainMesh.textureList.add(groundTextureTwo); - terrainMesh.textureList.add(groundTextureThree); - terrainMesh.textureList.add(groundTextureFour); + List textureList = new LinkedList(); + textureList.add(groundTextureOne); + textureList.add(groundTextureTwo); + textureList.add(groundTextureThree); + textureList.add(groundTextureFour); + List uniformList = new LinkedList(); + uniformList.add("groundTextures[0]"); + uniformList.add("groundTextures[1]"); + uniformList.add("groundTextures[2]"); + uniformList.add("groundTextures[3]"); String terrainModelPath = Globals.assetManager.registerModel(terrainModel); modelEntity = EntityUtils.spawnDrawableEntity(terrainModelPath); + EntityUtils.getActor(modelEntity).addTextureMask(new ActorTextureMask("terrain",textureList,uniformList)); modelEntity.putData(EntityDataStrings.TERRAIN_IS_TERRAIN, true); modelEntity.putData(EntityDataStrings.DRAW_CAST_SHADOW, true); LoggerInterface.loggerRenderer.INFO("New cell @ " + cellX * dynamicInterpolationRatio + "," + cellY * dynamicInterpolationRatio); diff --git a/src/main/java/electrosphere/renderer/Mesh.java b/src/main/java/electrosphere/renderer/Mesh.java index 32931df7..4d703681 100644 --- a/src/main/java/electrosphere/renderer/Mesh.java +++ b/src/main/java/electrosphere/renderer/Mesh.java @@ -4,6 +4,7 @@ import electrosphere.entity.types.camera.CameraEntityUtils; import electrosphere.logger.LoggerInterface; import electrosphere.main.Globals; import electrosphere.main.Main; +import electrosphere.renderer.actor.ActorTextureMask; import electrosphere.renderer.light.LightManager; import electrosphere.renderer.texture.Texture; import java.nio.FloatBuffer; @@ -81,9 +82,7 @@ public class Mesh { boolean hasBones = true; public boolean hasTextureCoords = true; - public List textureList = new ArrayList(); - public boolean useTextureList; - public String textureListArrayUniformName; + public ActorTextureMask textureMask; public float vertexMinX; public float vertexMaxX; @@ -609,10 +608,8 @@ public class Mesh { glEnableVertexAttribArray(attribIndex); } - public void setTextureList(List textureList, String uniformName){ - this.textureList = textureList; - useTextureList = true; - textureListArrayUniformName = uniformName; + public void setTextureMask(ActorTextureMask textureMask){ + this.textureMask = textureMask; } public void setMaterial(Material input){ @@ -774,7 +771,7 @@ public class Mesh { } } - if(useMaterial && !useTextureList){ + if(useMaterial && textureMask == null){ if(material == null){ Globals.materialDefault.apply_material(0,1); GL20.glUniform1i(glGetUniformLocation(Globals.renderingEngine.getActiveShader().shaderProgram, "hasTransparency"), 0); @@ -796,18 +793,18 @@ public class Mesh { - if(useTextureList){ + if(textureMask != null){ int i = 0; // glUniform1i(glGetUniformLocation(Globals.renderingEngine.getActiveShader().shaderProgram, "groundTextures"), 5); // for(int j = 1; j < 15; j++){ // textureList.get(0).bind(j); // } - for(Texture texture : textureList){ + for(Texture texture : textureMask.getTextures()){ // System.out.println(texture.getPath() + " => groundTextures[" + i + "]" + "=>" + (i)); if(texture != null){ texture.bind(5+i); } - glUniform1i(glGetUniformLocation(Globals.renderingEngine.getActiveShader().shaderProgram, "groundTextures[" + i + "]"),5+i); + glUniform1i(glGetUniformLocation(Globals.renderingEngine.getActiveShader().shaderProgram, textureMask.getUniformNames().get(i)),5+i); i++; } // for(int j = i; j < 10; j++){ diff --git a/src/main/java/electrosphere/renderer/Model.java b/src/main/java/electrosphere/renderer/Model.java index d5f5297f..2d2af607 100644 --- a/src/main/java/electrosphere/renderer/Model.java +++ b/src/main/java/electrosphere/renderer/Model.java @@ -3,6 +3,7 @@ package electrosphere.renderer; import electrosphere.renderer.actor.ActorAnimationMask; import electrosphere.renderer.actor.ActorMeshMask; import electrosphere.renderer.actor.ActorShaderMask; +import electrosphere.renderer.actor.ActorTextureMask; import electrosphere.renderer.anim.AnimChannel; import electrosphere.renderer.anim.Animation; import electrosphere.renderer.anim.AnimNode; @@ -61,6 +62,7 @@ public class Model { AnimNode root_anim_node; ActorMeshMask meshMask; Map shaderMask = new HashMap(); + Map textureMap = null; public static Model createModelFromAiscene(AIScene s){ Model rVal = new Model(); @@ -203,10 +205,19 @@ public class Model { while(mesh_Iterator.hasNext()){ Mesh currentMesh = mesh_Iterator.next(); if(!meshMask.isBlockedMesh(currentMesh.nodeID)){ + //set shader ShaderProgram original = currentMesh.shader; ShaderProgram shader = getCorrectShader(shaderMask, currentMesh, currentMesh.shader); currentMesh.shader = shader; + //set texture mask + if(this.textureMap != null && textureMap.containsKey(currentMesh.nodeID)){ + currentMesh.setTextureMask(textureMap.get(currentMesh.nodeID)); + } + //draw currentMesh.complexDraw(setShader, bufferStandardUniforms, bufferNonStandardUniforms, useMaterial, useShadowMap, setBones, useLight); + //reset texture mask + currentMesh.setTextureMask(null); + //reset shader currentMesh.shader = original; } } @@ -483,4 +494,8 @@ public class Model { public void setMeshMask(ActorMeshMask meshMask){ this.meshMask = meshMask; } + + public void setTextureMask(Map textureMask){ + this.textureMap = textureMask; + } } diff --git a/src/main/java/electrosphere/renderer/RenderingEngine.java b/src/main/java/electrosphere/renderer/RenderingEngine.java index 4f1b68e2..ab470e8b 100644 --- a/src/main/java/electrosphere/renderer/RenderingEngine.java +++ b/src/main/java/electrosphere/renderer/RenderingEngine.java @@ -57,6 +57,9 @@ import static org.lwjgl.glfw.GLFW.glfwWindowHint; import org.lwjgl.glfw.GLFWWindowSizeCallbackI; import org.lwjgl.opengl.GL; import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL15; +import org.lwjgl.opengl.GL20; + import static org.lwjgl.opengl.GL11.GL_BLEND; import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT; import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT; @@ -112,6 +115,17 @@ public class RenderingEngine { static ShaderProgram lightDepthShaderProgram; static Framebuffer lightDepthBuffer; + + static Matrix4f nearVolumeProjectionMatrix = new Matrix4f(); + static Matrix4f midVolumeProjectionMatrix = new Matrix4f(); + static Matrix4f farVolumeProjectionMatrix = new Matrix4f(); + static ShaderProgram volumeDepthShaderProgram; + static Framebuffer volumeDepthBackfaceFramebuffer; + static Texture volumeDepthBackfaceTexture; + static Framebuffer volumeDepthFrontfaceFramebuffer; + static Texture volumeDepthFrontfaceTexture; + static float volumeDepthLinearCoef = 0.1f; + static float volumeDepthQuadCoef = 0.01f; // public static boolean renderHitboxes = false; // public static boolean renderPhysics = false; @@ -121,6 +135,8 @@ public class RenderingEngine { static float currentViewPlanarAngle; ShaderProgram activeProgram; + + static int outputFramebuffer = 0; public void createOpenglContext(){ @@ -210,13 +226,28 @@ public class RenderingEngine { screenFramebuffer = FramebufferUtils.generateScreensizeTextureFramebuffer(); glBindFramebuffer(GL_FRAMEBUFFER, GL_DEFAULT_FRAMEBUFFER); glBindRenderbuffer(GL_RENDERBUFFER, GL_DEFAULT_RENDERBUFFER); - + + // + //create light depth framebuffer/shader for shadowmapping + // lightDepthShaderProgram = ShaderProgram.loadSpecificShader("/Shaders/lightDepth/lightDepth.vs", "/Shaders/lightDepth/lightDepth.fs"); Globals.depthMapShaderProgramLoc = lightDepthShaderProgram.shaderProgram; lightDepthBuffer = FramebufferUtils.generateDepthBuffer(); Globals.shadowMapTextureLoc = lightDepthBuffer.getTexturePointer(); // glEnable(GL_CULL_FACE); // enabled for shadow mapping + // + //create volume depth framebuffer/shader for volumetric rendering + // + volumeDepthShaderProgram = ShaderProgram.loadSpecificShader("/Shaders/volumeBuffer/volumetric.vs", "/Shaders/volumeBuffer/volumetric.fs"); + volumeDepthBackfaceTexture = FramebufferUtils.generateDepthBufferTexture(Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT); + 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); + //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 @@ -302,17 +333,26 @@ public class RenderingEngine { if(Globals.RENDER_FLAG_RENDER_SHADOW_MAP){ renderShadowMapContent(); } + + /* + render volume buffer + */ + if(Globals.RENDER_FLAG_RENDER_SCREEN_FRAMEBUFFER_CONTENT){ + updateVolumeBuffer(); + } /* Update light buffer */ lightManager.updateData(); + /* Render content to the game framebuffer */ if(Globals.RENDER_FLAG_RENDER_SCREEN_FRAMEBUFFER_CONTENT){ renderGameContent(); + renderDebugContent(); } @@ -500,6 +540,13 @@ public class RenderingEngine { } } + + +// glBindVertexArray(0); + } + + static void renderDebugContent(){ + Matrix4f modelTransformMatrix = new Matrix4f(); if(Globals.userSettings.graphicsDebugDrawCollisionSpheres()){ for(Entity currentHitbox : Globals.hitboxManager.getAllHitboxes()){ if((boolean)currentHitbox.getData(EntityDataStrings.DATA_STRING_DRAW)){ @@ -645,10 +692,6 @@ public class RenderingEngine { } } } - - - -// glBindVertexArray(0); } static void renderScreenFramebuffer(){ @@ -681,8 +724,15 @@ public class RenderingEngine { Globals.renderingEngine.setActiveShader(screenTextureShaders); glBindVertexArray(screenTextureVAO); //aaa - glBindTexture(GL_TEXTURE_2D, screenFramebuffer.getTexturePointer()); -// glBindTexture(GL_TEXTURE_2D, lightDepthBuffer.getTexturePointer()); + if(outputFramebuffer == 0){ + glBindTexture(GL_TEXTURE_2D, screenFramebuffer.getTexturePointer()); + } else if(outputFramebuffer == 1){ + glBindTexture(GL_TEXTURE_2D, lightDepthBuffer.getTexturePointer()); + } else if(outputFramebuffer == 2){ + glBindTexture(GL_TEXTURE_2D, volumeDepthBackfaceTexture.getTexturePointer()); + } else if(outputFramebuffer == 3){ + glBindTexture(GL_TEXTURE_2D, volumeDepthFrontfaceTexture.getTexturePointer()); + } glDrawArrays(GL_TRIANGLES, 0, 6); glBindVertexArray(0); } @@ -709,6 +759,140 @@ public class RenderingEngine { // uiActor.drawUI(); // } } + + static void updateVolumeBuffer(){ + Matrix4f modelTransformMatrix = new Matrix4f(); + + //set the viewport to shadow map size + glViewport(0, 0, Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT); + glEnable(GL_DEPTH_TEST); + + //stop rendering front faces + GL15.glEnable(GL15.GL_CULL_FACE); + GL15.glCullFace(GL15.GL_FRONT); + + Globals.renderingEngine.setActiveShader(volumeDepthShaderProgram); + + volumeDepthBackfaceFramebuffer.bind(); + glClear(GL_DEPTH_BUFFER_BIT); + glActiveTexture(GL_TEXTURE0); +// glBindTexture(GL_TEXTURE_2D, woodTexture); +// renderScene(simpleDepthShader); + + glUniformMatrix4fv(glGetUniformLocation(Globals.renderingEngine.getActiveShader().shaderProgram, "view"), false, Globals.viewMatrix.get(new float[16])); + // glUniformMatrix4fv(glGetUniformLocation(Globals.renderingEngine.getActiveShader().shaderProgram, "projection"), false, Globals.projectionMatrix.get(new float[16])); + + + + GL20.glUniform1f(glGetUniformLocation(Globals.renderingEngine.getActiveShader().shaderProgram, "linearCoef"), volumeDepthLinearCoef); + GL20.glUniform1f(glGetUniformLocation(Globals.renderingEngine.getActiveShader().shaderProgram, "quadCoef"), volumeDepthQuadCoef); + + GL20.glUniform1f(glGetUniformLocation(Globals.renderingEngine.getActiveShader().shaderProgram, "near"), 0.1f); + GL20.glUniform1f(glGetUniformLocation(Globals.renderingEngine.getActiveShader().shaderProgram, "far"), 100f); + +// glCullFace(GL_FRONT); + + // + // D R A W A L L E N T I T I E S + // + Vector3f cameraPos = CameraEntityUtils.getCameraCenter(Globals.playerCamera); + 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)) && + currentEntity.getDataKeys().contains(EntityDataStrings.DRAW_VOLUMETRIC) + ){ + //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)); + //set projection matrix + // if(cameraModifiedPosition.length() > 2f){ + // glUniformMatrix4fv(glGetUniformLocation(Globals.renderingEngine.getActiveShader().shaderProgram, "projection"), false, farVolumeProjectionMatrix.get(new float[16])); + // } else if(cameraModifiedPosition.length() > 0.5f){ + // glUniformMatrix4fv(glGetUniformLocation(Globals.renderingEngine.getActiveShader().shaderProgram, "projection"), false, midVolumeProjectionMatrix.get(new float[16])); + // } else { + glUniformMatrix4fv(glGetUniformLocation(Globals.renderingEngine.getActiveShader().shaderProgram, "projection"), false, nearVolumeProjectionMatrix.get(new float[16])); + // } + // glUniformMatrix4fv(glGetUniformLocation(Globals.renderingEngine.getActiveShader().shaderProgram, "projection"), false, Globals.projectionMatrix.get(new float[16])); + //calculate and apply model transform + modelTransformMatrix = modelTransformMatrix.identity(); + modelTransformMatrix.translate(cameraModifiedPosition); + modelTransformMatrix.rotate(EntityUtils.getRotation(currentEntity)); + modelTransformMatrix.scale(EntityUtils.getScale(currentEntity)); + currentActor.applyModelMatrix(modelTransformMatrix); + //draw +// if(!currentEntity.getDataKeys().contains(EntityDataStrings.TERRAIN_IS_TERRAIN) && !currentEntity.getDataKeys().contains(EntityDataStrings.DATA_STRING_CREATURE_IS_CREATURE)){ + currentActor.drawForDepthBuffer(); +// System.out.println(currentActor.modelPath); +// } + } + } + + + + //stop rendering front faces + GL15.glEnable(GL15.GL_CULL_FACE); + GL15.glCullFace(GL15.GL_BACK); + + Globals.renderingEngine.setActiveShader(volumeDepthShaderProgram); + + volumeDepthFrontfaceFramebuffer.bind(); + glClear(GL_DEPTH_BUFFER_BIT); + glActiveTexture(GL_TEXTURE0); +// glBindTexture(GL_TEXTURE_2D, woodTexture); +// renderScene(simpleDepthShader); + + // glUniformMatrix4fv(glGetUniformLocation(Globals.renderingEngine.getActiveShader().shaderProgram, "view"), false, Globals.viewMatrix.get(new float[16])); + // glUniformMatrix4fv(glGetUniformLocation(Globals.renderingEngine.getActiveShader().shaderProgram, "projection"), false, Globals.projectionMatrix.get(new float[16])); + + + + // GL20.glUniform1f(glGetUniformLocation(Globals.renderingEngine.getActiveShader().shaderProgram, "linearCoef"), volumeDepthLinearCoef); + // GL20.glUniform1f(glGetUniformLocation(Globals.renderingEngine.getActiveShader().shaderProgram, "quadCoef"), volumeDepthQuadCoef); + +// glCullFace(GL_FRONT); + + // + // D R A W A L L E N T I T I E S + // + 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)) && + currentEntity.getDataKeys().contains(EntityDataStrings.DRAW_VOLUMETRIC) + ){ + //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 = modelTransformMatrix.identity(); + modelTransformMatrix.translate(cameraModifiedPosition); + modelTransformMatrix.rotate(EntityUtils.getRotation(currentEntity)); + modelTransformMatrix.scale(EntityUtils.getScale(currentEntity)); + currentActor.applyModelMatrix(modelTransformMatrix); + //draw +// if(!currentEntity.getDataKeys().contains(EntityDataStrings.TERRAIN_IS_TERRAIN) && !currentEntity.getDataKeys().contains(EntityDataStrings.DATA_STRING_CREATURE_IS_CREATURE)){ + currentActor.drawForDepthBuffer(); +// System.out.println(currentActor.modelPath); +// } + } + } + + GL15.glCullFace(GL15.GL_BACK); + //now cull back faces + + //reset texture + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, 0); + //bind default framebuffer + glBindFramebuffer(GL_FRAMEBUFFER,0); + //resume culling backface + GL15.glDisable(GL15.GL_CULL_FACE); + } static void renderBlackBackground(){ //render full screen quad @@ -768,8 +952,23 @@ public class RenderingEngine { // System.out.println(tLeft.get() + " " + tTop.get() + " " + tRight.get() + " " + tBottom.get()); } + public Texture getVolumeBackfaceTexture(){ + return volumeDepthBackfaceTexture; + } + + public Texture getVolumeFrontfaceTexture(){ + return volumeDepthFrontfaceTexture; + } + public LightManager getLightManager(){ return lightManager; } + + public static void incrementOutputFramebuffer(){ + outputFramebuffer++; + if(outputFramebuffer > 3){ + outputFramebuffer = 0; + } + } } diff --git a/src/main/java/electrosphere/renderer/actor/Actor.java b/src/main/java/electrosphere/renderer/actor/Actor.java index e9c63212..a801c632 100644 --- a/src/main/java/electrosphere/renderer/actor/Actor.java +++ b/src/main/java/electrosphere/renderer/actor/Actor.java @@ -5,8 +5,10 @@ import electrosphere.renderer.Bone; import electrosphere.renderer.Model; import electrosphere.renderer.texture.Texture; +import java.util.HashMap; import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.PriorityQueue; import org.joml.AxisAngle4f; @@ -26,6 +28,7 @@ public class Actor { PriorityQueue animationQueue = new PriorityQueue(); ActorMeshMask meshMask = new ActorMeshMask(); List shaderMasks = new LinkedList(); + Map textureMap = null; public Actor(String modelPath){ this.modelPath = modelPath; @@ -183,6 +186,7 @@ public class Actor { applyAnimationMasks(model); meshMask.processMeshMaskQueue(); model.setMeshMask(meshMask); + model.setTextureMask(textureMap); // if(!meshMask.isEmpty()){ // } // if(animation != null){ @@ -210,6 +214,7 @@ public class Actor { model.draw(true, true, false, true, true, true, true); } model.getShaderMask().clear(); + model.setTextureMask(null); } } @@ -328,5 +333,12 @@ public class Actor { throw new UnsupportedOperationException("Not implemented yet"); } + public void addTextureMask(ActorTextureMask textureMask){ + if(textureMap == null){ + textureMap = new HashMap(); + } + textureMap.put(textureMask.getMeshName(),textureMask); + } + } diff --git a/src/main/java/electrosphere/renderer/actor/ActorTextureMask.java b/src/main/java/electrosphere/renderer/actor/ActorTextureMask.java new file mode 100644 index 00000000..42701571 --- /dev/null +++ b/src/main/java/electrosphere/renderer/actor/ActorTextureMask.java @@ -0,0 +1,31 @@ +package electrosphere.renderer.actor; + +import java.util.List; + +import electrosphere.renderer.texture.Texture; + +public class ActorTextureMask { + + String meshName; + List textures; + List uniformNames; + + public ActorTextureMask(String meshName, List textures, List uniformNames){ + this.meshName = meshName; + this.textures = textures; + this.uniformNames = uniformNames; + } + + public String getMeshName(){ + return meshName; + } + + public List getTextures(){ + return textures; + } + + public List getUniformNames(){ + return uniformNames; + } + +} diff --git a/src/main/java/electrosphere/renderer/framebuffer/FramebufferUtils.java b/src/main/java/electrosphere/renderer/framebuffer/FramebufferUtils.java index 64b69e18..a4b888bd 100644 --- a/src/main/java/electrosphere/renderer/framebuffer/FramebufferUtils.java +++ b/src/main/java/electrosphere/renderer/framebuffer/FramebufferUtils.java @@ -2,6 +2,8 @@ package electrosphere.renderer.framebuffer; import electrosphere.logger.LoggerInterface; import electrosphere.main.Globals; +import electrosphere.renderer.texture.Texture; + import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; @@ -157,4 +159,48 @@ public class FramebufferUtils { } return buffer; } + + + public static Texture generateDepthBufferTexture(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); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + float borderColor[] = { 1.0f, 1.0f, 1.0f, 1.0f }; + glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); + + Texture texture = new Texture(texturePtr); + + return texture; + } + + public static Framebuffer generateDepthBuffer(int width, int height, Texture texture){ + Framebuffer buffer = new Framebuffer(); + buffer.bind(); + + + //texture + buffer.setTexturePointer(texture.getTexturePointer()); + + + + //bind texture to fbo + int mipMapLevel = 0; + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, texture.getTexturePointer(), mipMapLevel); + glDrawBuffer(GL_NONE); + glReadBuffer(GL_NONE); + + + + //check make sure compiled + if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE){ + System.out.println("Framebuffer is not complete!"); + } + return buffer; + } + + } diff --git a/src/main/java/electrosphere/renderer/texture/Texture.java b/src/main/java/electrosphere/renderer/texture/Texture.java index 0d0a0463..7db44c14 100644 --- a/src/main/java/electrosphere/renderer/texture/Texture.java +++ b/src/main/java/electrosphere/renderer/texture/Texture.java @@ -30,9 +30,16 @@ public class Texture { int height; boolean hasTransparency; String path = ""; + + public Texture(){ } + + public Texture(int pointer){ + this.texturePointer = pointer; + } + public Texture(String path){ this.path = path; //generate the texture object on gpu