diff --git a/assets/DMonkey/AmbientLight.j3md b/assets/DMonkey/AmbientLight.j3md index b56287a..316f638 100644 --- a/assets/DMonkey/AmbientLight.j3md +++ b/assets/DMonkey/AmbientLight.j3md @@ -5,8 +5,12 @@ MaterialDef AmbientLight { Texture2D DepthBuffer Texture2D NormalBuffer Texture2D DiffuseBuffer - Vector3 LightPosition + + Vector4Array DirectionalColors + Vector3Array Directions + Float LightIntensity + Int DirectionalLights } @@ -15,7 +19,10 @@ MaterialDef AmbientLight { FragmentShader GLSL100: DMonkey/Shaders/AmbientLight.frag WorldParameters { - Resolution + ViewMatrix + ProjectionMatrixInverse + WorldViewProjectionMatrix + Resolution } } diff --git a/assets/DMonkey/GBuffer.j3md b/assets/DMonkey/GBuffer.j3md index 88ea391..608845e 100644 --- a/assets/DMonkey/GBuffer.j3md +++ b/assets/DMonkey/GBuffer.j3md @@ -14,14 +14,9 @@ MaterialDef GBuffer { FragmentShader GLSL100: DMonkey/Shaders/GBuffer.frag WorldParameters { - ProjectionMatrixInverse WorldViewProjectionMatrix - WorldViewNatrix - ViewMatrix - ViewMatrixInverse - NormalMatrix - WorldMatrixInverse - WorldMatrix + ViewMatrix + NormalMatrix FrustumNearFar Time } @@ -41,14 +36,9 @@ MaterialDef GBuffer { FragmentShader GLSL100: DMonkey/Shaders/GBuffer.frag WorldParameters { - ProjectionMatrixInverse WorldViewProjectionMatrix - WorldViewNatrix - ViewMatrix - ViewMatrixInverse - NormalMatrix - WorldMatrixInverse - WorldMatrix + ViewMatrix + NormalMatrix FrustumNearFar Time } diff --git a/assets/DMonkey/PointLight.j3md b/assets/DMonkey/PointLight.j3md index e87d35c..8c80b90 100644 --- a/assets/DMonkey/PointLight.j3md +++ b/assets/DMonkey/PointLight.j3md @@ -1,16 +1,17 @@ MaterialDef PointLight { MaterialParameters { - Vector4 LightColor Texture2D DepthBuffer Texture2D NormalBuffer Texture2D DiffuseBuffer + + Vector4 LightColor Vector3 LightPosition - Float LightIntensity Float LightRadius - Boolean fullscreen - Vector3 FrustumCorner - Vector2 FrustumNearFar + + Float LightIntensity + + Boolean fullscreen Boolean specular : true } @@ -20,22 +21,15 @@ MaterialDef PointLight { WorldParameters { ViewMatrix - ProjectionMatrixInverse - ViewProjectionMatrixInverse + ProjectionMatrixInverse WorldViewProjectionMatrix - WorldViewProjectionMatrixInverse - ViewProjectionMatrixInverse Resolution - CameraDirection } Defines { - NORMAL_BUFFER : NormalBuffer - DIFFUSE_BUFFER : DiffuseBuffer - DEPTH_BUFFER : DepthBuffer - FULLSCREEN : fullscreen SPECULAR : specular } } + Technique DeferredLight{ VertexShader GLSL100: Shaders/PointLight.vert FragmentShader GLSL100: Shaders/PointLight.frag diff --git a/assets/DMonkey/Shaders/AmbientLight.frag b/assets/DMonkey/Shaders/AmbientLight.frag index e14d642..2bcc5df 100644 --- a/assets/DMonkey/Shaders/AmbientLight.frag +++ b/assets/DMonkey/Shaders/AmbientLight.frag @@ -1,26 +1,33 @@ -#import "DMonkey/Shaders/GBuffer.glsllib" -#import "DMonkey/Shaders/Gamma.glsllib" +#import "DMonkey/Shaders/DM_Light.glsllib" uniform vec4 m_Color; -uniform vec3 g_CameraDirection; -uniform vec2 g_Resolution; -uniform mat4 g_WorldViewProjectionMatrixInverse; - -uniform vec3 m_LightPosition; uniform float m_LightIntensity; +uniform int m_DirectionalLights; +uniform vec4 m_DirectionalColors[12]; +uniform vec3 m_Directions[12]; #define EXTRACT_DEPTH(cc)((cc).b + (cc).g / 256.0 + (cc).r / (256.0 * 256.0) + (cc).a / (256.0 * 256.0 * 256.0)) void main() { - // Compute GBuffer sample position - vec2 TexCoord = gl_FragCoord.xy / g_Resolution; - dm_decode(TexCoord); + + // Prepare + prepare(); vec3 albedo = gamma(GBuffer.albedo, 2.2); - //gl_FragColor.rgb = 0.05 * albedo; - float mixValue = dot(GBuffer.normal, vec3(0.0,1.0,0.0))*0.5 + 0.5; - gl_FragColor.rgb = mix(vec3(0.3,0.3,0.8)*0.5, vec3(0.7,0.7,1), mixValue) * albedo * 0.2; + vec4 dirColors; + + for(int i = 0; i < 3; i++) { + vec3 dir = -(g_ViewMatrix * vec4(m_Directions[i], 0)).xyz; + + Light light = Light(m_DirectionalColors[i], dir, dir); + vec4 color = light.color * vec4(gamma(ComputeLighting(light).rgb, 2.2), 1); + + dirColors += color; + } + + vec4 ambient = m_Color; + gl_FragColor.rgb = ambient.rgb * albedo + dirColors.rgb * albedo; } diff --git a/assets/DMonkey/Shaders/DM_Light.glsllib b/assets/DMonkey/Shaders/DM_Light.glsllib new file mode 100644 index 0000000..8ba3d0c --- /dev/null +++ b/assets/DMonkey/Shaders/DM_Light.glsllib @@ -0,0 +1,48 @@ +#import "DMonkey/Shaders/GBuffer.glsllib" + +vec3 gamma(vec3 color, float gamma){ + color.r = pow(color.r, gamma); + color.g = pow(color.g, gamma); + color.b = pow(color.b, gamma); + return color; +} + +struct Light { + vec4 color; + vec3 position; + + vec3 direction; +}; + +vec4 ComputeLighting(Light light) { + + float lambert = clamp(dot(GBuffer.normal, light.direction), 0.0, 1.0); + + vec4 DiffuseColor = vec4(0, 0, 0, 0); + vec4 SpecularColor = vec4(0, 0, 0, 0); + + if (lambert > 0.0) { + DiffuseColor = light.color * lambert; + + #ifdef SPECULAR + vec3 vsCameraDir = normalize(GBuffer.position); + vec3 reflection = reflect(light.direction, GBuffer.normal); + float specular = clamp(dot(normalize(vsCameraDir), normalize(reflection)), 0.0, 1.0); + specular = pow(specular, 120.0); + + if (specular > 0.0) { + SpecularColor = vec4(light.color.rgb, 1.0) * GBuffer.specular * specular; + } + #else + float specular = 0.0; + #endif + } + + return DiffuseColor + SpecularColor; +} + +// Other uses.. later on +void prepare() { + // Do it here + dm_decode(); +} diff --git a/assets/DMonkey/Shaders/GBuffer.glsllib b/assets/DMonkey/Shaders/GBuffer.glsllib index 2ee741e..e307ddc 100644 --- a/assets/DMonkey/Shaders/GBuffer.glsllib +++ b/assets/DMonkey/Shaders/GBuffer.glsllib @@ -1,18 +1,14 @@ -#define DM_NORMAL_BUFFER m_NormalBuffer -#define DM_DIFFUSE_BUFFER m_DiffuseBuffer -#define DM_DEPTH_BUFFER m_DepthBuffer - -uniform sampler2D DM_NORMAL_BUFFER; -uniform sampler2D DM_DIFFUSE_BUFFER; -uniform sampler2D DM_DEPTH_BUFFER; - - -/** - * These uniform should be passed in from JME; - */ -uniform mat4 g_ViewProjectionMatrixInverse; +// Global uniforms from JME uniform mat4 g_ProjectionMatrixInverse; uniform mat4 g_ViewMatrix; +uniform vec2 g_Resolution; + +// MRT Textures +uniform sampler2D m_NormalBuffer; +uniform sampler2D m_DiffuseBuffer; +uniform sampler2D m_DepthBuffer; + +// Material uniform vec3 m_FrustumCorner; uniform vec2 m_FrustumNearFar; @@ -26,7 +22,7 @@ struct DM_GBuffer{ } GBuffer; float dm_depth(vec2 tc){ - return texture2D(DM_DEPTH_BUFFER, tc).r; + return texture2D(m_DepthBuffer, tc).r; } vec3 dm_position(vec2 tc, float projectiveDepth){ @@ -36,7 +32,7 @@ vec3 dm_position(vec2 tc, float projectiveDepth){ } vec3 dm_normal(vec2 tc){ - return normalize((texture2D(DM_NORMAL_BUFFER, tc) * 2.0 - 1.0).rgb); + return normalize((texture2D(m_NormalBuffer, tc) * 2.0 - 1.0).rgb); } /** @@ -48,19 +44,21 @@ float dm_non_linear_2_linear_depth(float w){ return (w - wnear) * (wfar / (wfar - wnear)); } -void dm_decode(vec2 tc){ +void dm_decode() { + vec2 tc = gl_FragCoord.xy/g_Resolution; + GBuffer.depth = dm_depth(tc); GBuffer.linear_depth = dm_non_linear_2_linear_depth(GBuffer.depth); // Decode normal and specular - vec4 normalAndSpecluar = texture2D(DM_NORMAL_BUFFER, tc); + vec4 normalAndSpecluar = texture2D(m_NormalBuffer, tc); GBuffer.normal = normalAndSpecluar.rgb * 2.0 - 1.0; GBuffer.specular = normalAndSpecluar.a; - // Decode position - GBuffer.position = dm_position(tc, GBuffer.depth); + // Decode position + GBuffer.position = dm_position(tc, GBuffer.depth); - // Recover albedo - GBuffer.albedo = texture2D(DM_DIFFUSE_BUFFER, tc).rgb; + // Recover albedo + GBuffer.albedo = texture2D(m_DiffuseBuffer, tc).rgb; } diff --git a/assets/DMonkey/Shaders/PointLight.frag b/assets/DMonkey/Shaders/PointLight.frag index ae0530c..3c5a59a 100644 --- a/assets/DMonkey/Shaders/PointLight.frag +++ b/assets/DMonkey/Shaders/PointLight.frag @@ -1,12 +1,6 @@ -#import "DMonkey/Shaders/GBuffer.glsllib" -#import "DMonkey/Shaders/Gamma.glsllib" +#import "DMonkey/Shaders/DM_Light.glsllib" -// Global uniforms from JME -uniform mat4 g_WorldViewProjectionMatrixInverse; -uniform vec3 g_CameraDirection; -uniform vec2 g_Resolution; - -// Light parameters +// Point Light parameters uniform vec3 m_LightPosition; uniform float m_LightIntensity; uniform float m_LightRadius; @@ -22,58 +16,27 @@ float quad_fallof(float D, float r, float kq){ float fallof(float D, float r, float kl, float kq){ return linear_fallof(D, r, kl) * quad_fallof(D, r, kq); } -vec4 perform_lighting(vec3 Position, vec3 LightPos, vec3 Normal, vec3 Albedo, vec4 LightColor, float LightRadius){ - vec4 color = vec4(0); - vec3 LightVector = LightPos - Position; - vec3 LightDir = normalize(LightVector); - - float lambert = clamp(dot(GBuffer.normal, LightDir), 0.0, 1.0); - - #ifdef SPECULAR - vec3 vsCameraDir = normalize(GBuffer.position); - vec3 reflection = reflect(LightDir, GBuffer.normal); - float specular = clamp(dot(normalize(Position), normalize(reflection)), 0.0, 1.0); - specular = pow(specular, 120.0)*GBuffer.specular; - #else - float specular = 0.0; - #endif +void main() { + + // Decode gbuffer + prepare(); - - // Compute distance to light - float Dist = length(LightVector); - float fallof = fallof(LightRadius, Dist, 0.0, 1.0); - fallof *= LightColor.a; + vec3 LightVector = m_LightPosition - GBuffer.position; + vec3 LightDir = normalize(LightVector); - color = LightColor*(lambert + specular) * fallof; - return color; -} + Light light = Light(m_LightColor, m_LightPosition, LightDir); + vec4 color = light.color * ComputeLighting(light); -void main() { - vec2 TexCoord = gl_FragCoord.xy/g_Resolution; - - // Decode gbuffer - dm_decode(TexCoord); - - - - // Get view space camera direction - //vec3 vsCameraDir = normalize(GBuffer.position); + float Dist = length(LightVector); + float fallof = fallof(m_LightRadius, Dist, 0.0, 1.0); - vec4 albedo = vec4(GBuffer.albedo, 1.0); - - // GammaCorrect textures - albedo.rgb = gamma(albedo.rgb, 2.2); - - - - gl_FragColor = perform_lighting(GBuffer.position, m_LightPosition, GBuffer.normal, albedo.rgb, m_LightColor, m_LightRadius); + gl_FragColor = color * fallof * light.color.a; - //gl_FragColor += 0.03; - gl_FragColor *= albedo; - - return; + // GammaCorrect textures + vec3 albedo = gamma(GBuffer.albedo, 2.2); + gl_FragColor *= vec4(albedo, 1); } diff --git a/assets/DMonkey/Shaders/Resolve.frag b/assets/DMonkey/Shaders/Resolve.frag index f108d15..64c3e37 100644 --- a/assets/DMonkey/Shaders/Resolve.frag +++ b/assets/DMonkey/Shaders/Resolve.frag @@ -9,7 +9,7 @@ uniform mat4 m_ProjectionMatrix; varying vec2 TexCoord; vec3 FilmicMain(vec3 texColor){ - float range = 0.5; + float range = 0.2; texColor *= range; vec3 x = max(vec3(0.0),texColor-0.004); // Filmic Curve vec3 retColor = (x*(6.2*x+0.5))/(x*(6.2*x+1.7)+0.06); @@ -21,5 +21,5 @@ void main() { gl_FragColor.rgb = LBuffer.rgb; //gl_FragColor.rgb = gl_FragColor.rgb / (1.0 + gl_FragColor.rgb); //gl_FragColor.rgb = gamma(gl_FragColor.rgb, 1.0/2.2); - gl_FragColor.rgb = FilmicMain(gl_FragColor.rgb); + //gl_FragColor.rgb = FilmicMain(gl_FragColor.rgb); } diff --git a/assets/DMonkey/Shaders/SpotLight.frag b/assets/DMonkey/Shaders/SpotLight.frag index ab06ae6..de0056a 100644 --- a/assets/DMonkey/Shaders/SpotLight.frag +++ b/assets/DMonkey/Shaders/SpotLight.frag @@ -1,94 +1,52 @@ -#import "DMonkey/Shaders/GBuffer.glsllib" -#import "DMonkey/Shaders/Gamma.glsllib" - -// Global uniforms from JME -uniform mat4 g_WorldViewProjectionMatrixInverse; -uniform vec3 g_CameraDirection; -uniform vec2 g_Resolution; +#import "DMonkey/Shaders/DM_Light.glsllib" // Light parameters uniform vec3 m_LightPosition; uniform float m_LightIntensity; uniform float m_CutoffAngle; +uniform float m_LightRange; uniform vec3 m_LightDirection; uniform vec4 m_LightColor; -const int num_lights = 1; + varying vec3 vsPosition; float linear_fallof(float D, float r, float kl){ return D / (D + kl * r); } + float quad_fallof(float D, float r, float kq){ float D2 = D*D; return D2 / (D2 + kq * r * r); } + float fallof(float D, float r, float kl, float kq){ return linear_fallof(D, r, kl) * quad_fallof(D, r, kq); } -vec4 perform_lighting(vec3 Position, vec3 LightPos, vec3 Normal, vec3 Albedo, vec4 LightColor, float LightRadius){ - vec4 color = vec4(0); - - vec3 LightVector = LightPos - Position; - vec3 LightDir = normalize(LightVector); - - float lambert = clamp(dot(GBuffer.normal, LightDir), 0.0, 1.0); - - #ifdef SPECULAR - vec3 vsCameraDir = normalize(GBuffer.position); - vec3 reflection = reflect(LightDir, GBuffer.normal); - float specular = clamp(dot(normalize(Position), normalize(reflection)), 0.0, 1.0); - specular = pow(specular, 120.0)*GBuffer.specular; - #else - float specular = 0.0; - #endif - - - - // Compute distance to light - float Dist = length(LightVector); - float fallof = fallof(LightRadius, Dist, 0.0, 1.0); - fallof *= LightColor.a; - - color = LightColor*(lambert + specular) * fallof; - return color; -} - void main() { - vec2 TexCoord = gl_FragCoord.xy/g_Resolution; - - // Decode gbuffer - dm_decode(TexCoord); + + prepare(); - vec3 LightPos = (g_ViewMatrix * vec4(m_LightPosition, 1.0)).xyz; + vec3 LightDir = normalize((g_ViewMatrix * vec4(m_LightDirection, 0.0)).xyz); - vec4 albedo = vec4(GBuffer.albedo, 1.0); - - // GammaCorrect textures - albedo.rgb = gamma(albedo.rgb, 2.2); + Light light = Light(m_LightColor, m_LightPosition, LightDir); + vec4 color = light.color + ComputeLighting(light); - vec3 LightDir = normalize((g_ViewMatrix * vec4(m_LightDirection, 0.0)).xyz); + // GammaCorrect textures + vec4 albedo = vec4(gamma(GBuffer.albedo, 2.2), 1.0); - float fallof = clamp(dot(normalize(GBuffer.position-LightPos), LightDir), 0.0, 1.0); + vec3 LightVector = GBuffer.position - light.position; + float fallof = clamp(dot(normalize(LightVector), LightDir), 0.0, 1.0); - float modifier = 1.0; if(cos(m_CutoffAngle/2.0) > fallof || dot(LightDir, GBuffer.normal) > 0.0){ - modifier = 0.0; - discard; + discard; } - float lambert = clamp(-dot(GBuffer.normal, LightDir), 0.0, 1.0); - - - // Range fallof - fallof = clamp(5.0-length(GBuffer.position - LightPos),0.0, 5.0)/5.0; + // Calculate range fallof + fallof = dot(LightVector, LightVector) / (m_LightRange * m_LightRange); + fallof = 1.0 - clamp(fallof, 0.0, 1.0); - fallof = fallof*fallof; - float outerAngleCos = cos(m_CutoffAngle/2.0); - float currAngleCos = dot(-LightDir, normalize(LightPos-GBuffer.position)); - float innerAngleCos = 0.99939082701*1.07; - float diff = clamp((currAngleCos-outerAngleCos)/(innerAngleCos-outerAngleCos), 0.0, 1.0); - gl_FragColor.rgb = vec3(outerAngleCos)*albedo.rgb*diff*m_LightColor.rgb; + gl_FragColor = color * fallof * albedo; } diff --git a/assets/DMonkey/Terrain/Terrain.frag b/assets/DMonkey/Terrain/Terrain.frag new file mode 100644 index 0000000..b3d37d2 --- /dev/null +++ b/assets/DMonkey/Terrain/Terrain.frag @@ -0,0 +1,576 @@ +uniform mat4 g_ViewMatrix; +uniform float m_Shininess; + +varying vec3 vNormal; +varying vec2 texCoord; + +varying vec3 wvTangent; +varying vec3 wvBinormal; + +#ifdef DIFFUSEMAP + uniform sampler2D m_DiffuseMap; +#endif +#ifdef DIFFUSEMAP_1 + uniform sampler2D m_DiffuseMap_1; +#endif +#ifdef DIFFUSEMAP_2 + uniform sampler2D m_DiffuseMap_2; +#endif +#ifdef DIFFUSEMAP_3 + uniform sampler2D m_DiffuseMap_3; +#endif +#ifdef DIFFUSEMAP_4 + uniform sampler2D m_DiffuseMap_4; +#endif +#ifdef DIFFUSEMAP_5 + uniform sampler2D m_DiffuseMap_5; +#endif +#ifdef DIFFUSEMAP_6 + uniform sampler2D m_DiffuseMap_6; +#endif +#ifdef DIFFUSEMAP_7 + uniform sampler2D m_DiffuseMap_7; +#endif +#ifdef DIFFUSEMAP_8 + uniform sampler2D m_DiffuseMap_8; +#endif +#ifdef DIFFUSEMAP_9 + uniform sampler2D m_DiffuseMap_9; +#endif +#ifdef DIFFUSEMAP_10 + uniform sampler2D m_DiffuseMap_10; +#endif +#ifdef DIFFUSEMAP_11 + uniform sampler2D m_DiffuseMap_11; +#endif + + +#ifdef DIFFUSEMAP_0_SCALE + uniform float m_DiffuseMap_0_scale; +#endif +#ifdef DIFFUSEMAP_1_SCALE + uniform float m_DiffuseMap_1_scale; +#endif +#ifdef DIFFUSEMAP_2_SCALE + uniform float m_DiffuseMap_2_scale; +#endif +#ifdef DIFFUSEMAP_3_SCALE + uniform float m_DiffuseMap_3_scale; +#endif +#ifdef DIFFUSEMAP_4_SCALE + uniform float m_DiffuseMap_4_scale; +#endif +#ifdef DIFFUSEMAP_5_SCALE + uniform float m_DiffuseMap_5_scale; +#endif +#ifdef DIFFUSEMAP_6_SCALE + uniform float m_DiffuseMap_6_scale; +#endif +#ifdef DIFFUSEMAP_7_SCALE + uniform float m_DiffuseMap_7_scale; +#endif +#ifdef DIFFUSEMAP_8_SCALE + uniform float m_DiffuseMap_8_scale; +#endif +#ifdef DIFFUSEMAP_9_SCALE + uniform float m_DiffuseMap_9_scale; +#endif +#ifdef DIFFUSEMAP_10_SCALE + uniform float m_DiffuseMap_10_scale; +#endif +#ifdef DIFFUSEMAP_11_SCALE + uniform float m_DiffuseMap_11_scale; +#endif + + +#ifdef ALPHAMAP + uniform sampler2D m_AlphaMap; +#endif +#ifdef ALPHAMAP_1 + uniform sampler2D m_AlphaMap_1; +#endif +#ifdef ALPHAMAP_2 + uniform sampler2D m_AlphaMap_2; +#endif + +#ifdef NORMALMAP + uniform sampler2D m_NormalMap; +#endif +#ifdef NORMALMAP_1 + uniform sampler2D m_NormalMap_1; +#endif +#ifdef NORMALMAP_2 + uniform sampler2D m_NormalMap_2; +#endif +#ifdef NORMALMAP_3 + uniform sampler2D m_NormalMap_3; +#endif +#ifdef NORMALMAP_4 + uniform sampler2D m_NormalMap_4; +#endif +#ifdef NORMALMAP_5 + uniform sampler2D m_NormalMap_5; +#endif +#ifdef NORMALMAP_6 + uniform sampler2D m_NormalMap_6; +#endif +#ifdef NORMALMAP_7 + uniform sampler2D m_NormalMap_7; +#endif +#ifdef NORMALMAP_8 + uniform sampler2D m_NormalMap_8; +#endif +#ifdef NORMALMAP_9 + uniform sampler2D m_NormalMap_9; +#endif +#ifdef NORMALMAP_10 + uniform sampler2D m_NormalMap_10; +#endif +#ifdef NORMALMAP_11 + uniform sampler2D m_NormalMap_11; +#endif + + +#ifdef TRI_PLANAR_MAPPING + varying vec4 wVertex; + varying vec3 wNormal; +#endif + +#ifdef ALPHAMAP + + vec4 calculateDiffuseBlend(in vec2 texCoord) { + vec4 alphaBlend = texture2D( m_AlphaMap, texCoord.xy ); + + #ifdef ALPHAMAP_1 + vec4 alphaBlend1 = texture2D( m_AlphaMap_1, texCoord.xy ); + #endif + #ifdef ALPHAMAP_2 + vec4 alphaBlend2 = texture2D( m_AlphaMap_2, texCoord.xy ); + #endif + + vec4 diffuseColor = texture2D(m_DiffuseMap, texCoord * m_DiffuseMap_0_scale); + diffuseColor *= alphaBlend.r; + #ifdef DIFFUSEMAP_1 + vec4 diffuseColor1 = texture2D(m_DiffuseMap_1, texCoord * m_DiffuseMap_1_scale); + diffuseColor = mix( diffuseColor, diffuseColor1, alphaBlend.g ); + #ifdef DIFFUSEMAP_2 + vec4 diffuseColor2 = texture2D(m_DiffuseMap_2, texCoord * m_DiffuseMap_2_scale); + diffuseColor = mix( diffuseColor, diffuseColor2, alphaBlend.b ); + #ifdef DIFFUSEMAP_3 + vec4 diffuseColor3 = texture2D(m_DiffuseMap_3, texCoord * m_DiffuseMap_3_scale); + diffuseColor = mix( diffuseColor, diffuseColor3, alphaBlend.a ); + #ifdef ALPHAMAP_1 + #ifdef DIFFUSEMAP_4 + vec4 diffuseColor4 = texture2D(m_DiffuseMap_4, texCoord * m_DiffuseMap_4_scale); + diffuseColor = mix( diffuseColor, diffuseColor4, alphaBlend1.r ); + #ifdef DIFFUSEMAP_5 + vec4 diffuseColor5 = texture2D(m_DiffuseMap_5, texCoord * m_DiffuseMap_5_scale); + diffuseColor = mix( diffuseColor, diffuseColor5, alphaBlend1.g ); + #ifdef DIFFUSEMAP_6 + vec4 diffuseColor6 = texture2D(m_DiffuseMap_6, texCoord * m_DiffuseMap_6_scale); + diffuseColor = mix( diffuseColor, diffuseColor6, alphaBlend1.b ); + #ifdef DIFFUSEMAP_7 + vec4 diffuseColor7 = texture2D(m_DiffuseMap_7, texCoord * m_DiffuseMap_7_scale); + diffuseColor = mix( diffuseColor, diffuseColor7, alphaBlend1.a ); + #ifdef ALPHAMAP_2 + #ifdef DIFFUSEMAP_8 + vec4 diffuseColor8 = texture2D(m_DiffuseMap_8, texCoord * m_DiffuseMap_8_scale); + diffuseColor = mix( diffuseColor, diffuseColor8, alphaBlend2.r ); + #ifdef DIFFUSEMAP_9 + vec4 diffuseColor9 = texture2D(m_DiffuseMap_9, texCoord * m_DiffuseMap_9_scale); + diffuseColor = mix( diffuseColor, diffuseColor9, alphaBlend2.g ); + #ifdef DIFFUSEMAP_10 + vec4 diffuseColor10 = texture2D(m_DiffuseMap_10, texCoord * m_DiffuseMap_10_scale); + diffuseColor = mix( diffuseColor, diffuseColor10, alphaBlend2.b ); + #ifdef DIFFUSEMAP_11 + vec4 diffuseColor11 = texture2D(m_DiffuseMap_11, texCoord * m_DiffuseMap_11_scale); + diffuseColor = mix( diffuseColor, diffuseColor11, alphaBlend2.a ); + #endif + #endif + #endif + #endif + #endif + #endif + #endif + #endif + #endif + #endif + #endif + #endif + #endif + return diffuseColor; + } + + vec3 calculateNormal(vec2 texCoord) { + vec3 normal = vec3(0,0,1); + vec3 n = vec3(0,0,0); + + vec4 alphaBlend = texture2D( m_AlphaMap, texCoord.xy ); + + #ifdef ALPHAMAP_1 + vec4 alphaBlend1 = texture2D( m_AlphaMap_1, texCoord.xy ); + #endif + #ifdef ALPHAMAP_2 + vec4 alphaBlend2 = texture2D( m_AlphaMap_2, texCoord.xy ); + #endif + + #ifdef NORMALMAP + n = texture2D(m_NormalMap, texCoord * m_DiffuseMap_0_scale).xyz; + normal += n * alphaBlend.r; + #else + normal += vec3(0.5,0.5,1) * alphaBlend.r; + #endif + + #ifdef NORMALMAP_1 + n = texture2D(m_NormalMap_1, texCoord * m_DiffuseMap_1_scale).xyz; + normal += n * alphaBlend.g; + #else + normal += vec3(0.5,0.5,1) * alphaBlend.g; + #endif + + #ifdef NORMALMAP_2 + n = texture2D(m_NormalMap_2, texCoord * m_DiffuseMap_2_scale).xyz; + normal += n * alphaBlend.b; + #else + normal += vec3(0.5,0.5,1) * alphaBlend.b; + #endif + + #ifdef NORMALMAP_3 + n = texture2D(m_NormalMap_3, texCoord * m_DiffuseMap_3_scale).xyz; + normal += n * alphaBlend.a; + #else + normal += vec3(0.5,0.5,1) * alphaBlend.a; + #endif + + #ifdef ALPHAMAP_1 + #ifdef NORMALMAP_4 + n = texture2D(m_NormalMap_4, texCoord * m_DiffuseMap_4_scale).xyz; + normal += n * alphaBlend1.r; + #endif + + #ifdef NORMALMAP_5 + n = texture2D(m_NormalMap_5, texCoord * m_DiffuseMap_5_scale).xyz; + normal += n * alphaBlend1.g; + #endif + + #ifdef NORMALMAP_6 + n = texture2D(m_NormalMap_6, texCoord * m_DiffuseMap_6_scale).xyz; + normal += n * alphaBlend1.b; + #endif + + #ifdef NORMALMAP_7 + n = texture2D(m_NormalMap_7, texCoord * m_DiffuseMap_7_scale).xyz; + normal += n * alphaBlend1.a; + #endif + #endif + + #ifdef ALPHAMAP_2 + #ifdef NORMALMAP_8 + n = texture2D(m_NormalMap_8, texCoord * m_DiffuseMap_8_scale).xyz; + normal += n * alphaBlend2.r; + #endif + + #ifdef NORMALMAP_9 + n = texture2D(m_NormalMap_9, texCoord * m_DiffuseMap_9_scale); + normal += n * alphaBlend2.g; + #endif + + #ifdef NORMALMAP_10 + n = texture2D(m_NormalMap_10, texCoord * m_DiffuseMap_10_scale); + normal += n * alphaBlend2.b; + #endif + + #ifdef NORMALMAP_11 + n = texture2D(m_NormalMap_11, texCoord * m_DiffuseMap_11_scale); + normal += n * alphaBlend2.a; + #endif + #endif + + normal = (normal.xyz * vec3(2.0) - vec3(1.0)); + normal = normalize(wvTangent * normal.x + wvBinormal * normal.y + vNormal * normal.z); + return normal; + } + + #ifdef TRI_PLANAR_MAPPING + + vec4 getTriPlanarBlend(in vec4 coords, in vec3 blending, in sampler2D map, in float scale) { + vec4 col1 = texture2D( map, coords.yz * scale); + vec4 col2 = texture2D( map, coords.xz * scale); + vec4 col3 = texture2D( map, coords.xy * scale); + // blend the results of the 3 planar projections. + vec4 tex = col1 * blending.x + col2 * blending.y + col3 * blending.z; + return tex; + } + + vec4 calculateTriPlanarDiffuseBlend(in vec3 wNorm, in vec4 wVert, in vec2 texCoord) { + // tri-planar texture bending factor for this fragment's normal + vec3 blending = abs( wNorm ); + blending = (blending -0.2) * 0.7; + blending = normalize(max(blending, 0.00001)); // Force weights to sum to 1.0 (very important!) + float b = (blending.x + blending.y + blending.z); + blending /= vec3(b, b, b); + + // texture coords + vec4 coords = wVert; + + // blend the results of the 3 planar projections. + vec4 tex0 = getTriPlanarBlend(coords, blending, m_DiffuseMap, m_DiffuseMap_0_scale); + + #ifdef DIFFUSEMAP_1 + // blend the results of the 3 planar projections. + vec4 tex1 = getTriPlanarBlend(coords, blending, m_DiffuseMap_1, m_DiffuseMap_1_scale); + #endif + #ifdef DIFFUSEMAP_2 + // blend the results of the 3 planar projections. + vec4 tex2 = getTriPlanarBlend(coords, blending, m_DiffuseMap_2, m_DiffuseMap_2_scale); + #endif + #ifdef DIFFUSEMAP_3 + // blend the results of the 3 planar projections. + vec4 tex3 = getTriPlanarBlend(coords, blending, m_DiffuseMap_3, m_DiffuseMap_3_scale); + #endif + #ifdef DIFFUSEMAP_4 + // blend the results of the 3 planar projections. + vec4 tex4 = getTriPlanarBlend(coords, blending, m_DiffuseMap_4, m_DiffuseMap_4_scale); + #endif + #ifdef DIFFUSEMAP_5 + // blend the results of the 3 planar projections. + vec4 tex5 = getTriPlanarBlend(coords, blending, m_DiffuseMap_5, m_DiffuseMap_5_scale); + #endif + #ifdef DIFFUSEMAP_6 + // blend the results of the 3 planar projections. + vec4 tex6 = getTriPlanarBlend(coords, blending, m_DiffuseMap_6, m_DiffuseMap_6_scale); + #endif + #ifdef DIFFUSEMAP_7 + // blend the results of the 3 planar projections. + vec4 tex7 = getTriPlanarBlend(coords, blending, m_DiffuseMap_7, m_DiffuseMap_7_scale); + #endif + #ifdef DIFFUSEMAP_8 + // blend the results of the 3 planar projections. + vec4 tex8 = getTriPlanarBlend(coords, blending, m_DiffuseMap_8, m_DiffuseMap_8_scale); + #endif + #ifdef DIFFUSEMAP_9 + // blend the results of the 3 planar projections. + vec4 tex9 = getTriPlanarBlend(coords, blending, m_DiffuseMap_9, m_DiffuseMap_9_scale); + #endif + #ifdef DIFFUSEMAP_10 + // blend the results of the 3 planar projections. + vec4 tex10 = getTriPlanarBlend(coords, blending, m_DiffuseMap_10, m_DiffuseMap_10_scale); + #endif + #ifdef DIFFUSEMAP_11 + // blend the results of the 3 planar projections. + vec4 tex11 = getTriPlanarBlend(coords, blending, m_DiffuseMap_11, m_DiffuseMap_11_scale); + #endif + + vec4 alphaBlend = texture2D( m_AlphaMap, texCoord.xy ); + + #ifdef ALPHAMAP_1 + vec4 alphaBlend1 = texture2D( m_AlphaMap_1, texCoord.xy ); + #endif + #ifdef ALPHAMAP_2 + vec4 alphaBlend2 = texture2D( m_AlphaMap_2, texCoord.xy ); + #endif + + vec4 diffuseColor = tex0 * alphaBlend.r; + #ifdef DIFFUSEMAP_1 + diffuseColor = mix( diffuseColor, tex1, alphaBlend.g ); + #ifdef DIFFUSEMAP_2 + diffuseColor = mix( diffuseColor, tex2, alphaBlend.b ); + #ifdef DIFFUSEMAP_3 + diffuseColor = mix( diffuseColor, tex3, alphaBlend.a ); + #ifdef ALPHAMAP_1 + #ifdef DIFFUSEMAP_4 + diffuseColor = mix( diffuseColor, tex4, alphaBlend1.r ); + #ifdef DIFFUSEMAP_5 + diffuseColor = mix( diffuseColor, tex5, alphaBlend1.g ); + #ifdef DIFFUSEMAP_6 + diffuseColor = mix( diffuseColor, tex6, alphaBlend1.b ); + #ifdef DIFFUSEMAP_7 + diffuseColor = mix( diffuseColor, tex7, alphaBlend1.a ); + #ifdef ALPHAMAP_2 + #ifdef DIFFUSEMAP_8 + diffuseColor = mix( diffuseColor, tex8, alphaBlend2.r ); + #ifdef DIFFUSEMAP_9 + diffuseColor = mix( diffuseColor, tex9, alphaBlend2.g ); + #ifdef DIFFUSEMAP_10 + diffuseColor = mix( diffuseColor, tex10, alphaBlend2.b ); + #ifdef DIFFUSEMAP_11 + diffuseColor = mix( diffuseColor, tex11, alphaBlend2.a ); + #endif + #endif + #endif + #endif + #endif + #endif + #endif + #endif + #endif + #endif + #endif + #endif + #endif + + return diffuseColor; + } + + vec3 calculateNormalTriPlanar(in vec3 wNorm, in vec4 wVert,in vec2 texCoord) { + // tri-planar texture bending factor for this fragment's world-space normal + vec3 blending = abs( wNorm ); + blending = (blending -0.2) * 0.7; + blending = normalize(max(blending, 0.00001)); // Force weights to sum to 1.0 (very important!) + float b = (blending.x + blending.y + blending.z); + blending /= vec3(b, b, b); + + // texture coords + vec4 coords = wVert; + vec4 alphaBlend = texture2D( m_AlphaMap, texCoord.xy ); + + #ifdef ALPHAMAP_1 + vec4 alphaBlend1 = texture2D( m_AlphaMap_1, texCoord.xy ); + #endif + #ifdef ALPHAMAP_2 + vec4 alphaBlend2 = texture2D( m_AlphaMap_2, texCoord.xy ); + #endif + + vec3 normal = vec3(0,0,1); + vec3 n = vec3(0,0,0); + + #ifdef NORMALMAP + n = getTriPlanarBlend(coords, blending, m_NormalMap, m_DiffuseMap_0_scale).xyz; + normal += n * alphaBlend.r; + #else + normal += vec3(0.5,0.5,1) * alphaBlend.r; + #endif + + #ifdef NORMALMAP_1 + n = getTriPlanarBlend(coords, blending, m_NormalMap_1, m_DiffuseMap_1_scale).xyz; + normal += n * alphaBlend.g; + #else + normal += vec3(0.5,0.5,1) * alphaBlend.g; + #endif + + #ifdef NORMALMAP_2 + n = getTriPlanarBlend(coords, blending, m_NormalMap_2, m_DiffuseMap_2_scale).xyz; + normal += n * alphaBlend.b; + #else + normal += vec3(0.5,0.5,1) * alphaBlend.b; + #endif + + #ifdef NORMALMAP_3 + n = getTriPlanarBlend(coords, blending, m_NormalMap_3, m_DiffuseMap_3_scale).xyz; + normal += n * alphaBlend.a; + #else + normal += vec3(0.5,0.5,1) * alphaBlend.a; + #endif + + #ifdef ALPHAMAP_1 + #ifdef NORMALMAP_4 + n = getTriPlanarBlend(coords, blending, m_NormalMap_4, m_DiffuseMap_4_scale).xyz; + normal += n * alphaBlend1.r; + #else + normal += vec3(0.5,0.5,1) * alphaBlend.r; + #endif + + #ifdef NORMALMAP_5 + n = getTriPlanarBlend(coords, blending, m_NormalMap_5, m_DiffuseMap_5_scale).xyz; + normal += n * alphaBlend1.g; + #else + normal += vec3(0.5,0.5,1) * alphaBlend.g; + #endif + + #ifdef NORMALMAP_6 + n = getTriPlanarBlend(coords, blending, m_NormalMap_6, m_DiffuseMap_6_scale).xyz; + normal += n * alphaBlend1.b; + #else + normal += vec3(0.5,0.5,1) * alphaBlend.b; + #endif + + #ifdef NORMALMAP_7 + n = getTriPlanarBlend(coords, blending, m_NormalMap_7, m_DiffuseMap_7_scale).xyz; + normal += n * alphaBlend1.a; + #else + normal += vec3(0.5,0.5,1) * alphaBlend.a; + #endif + #endif + + #ifdef ALPHAMAP_2 + #ifdef NORMALMAP_8 + n = getTriPlanarBlend(coords, blending, m_NormalMap_8, m_DiffuseMap_8_scale).xyz; + normal += n * alphaBlend2.r; + #else + normal += vec3(0.5,0.5,1) * alphaBlend.r; + #endif + + #ifdef NORMALMAP_9 + n = getTriPlanarBlend(coords, blending, m_NormalMap_9, m_DiffuseMap_9_scale).xyz; + normal += n * alphaBlend2.g; + #else + normal += vec3(0.5,0.5,1) * alphaBlend.g; + #endif + + #ifdef NORMALMAP_10 + n = getTriPlanarBlend(coords, blending, m_NormalMap_10, m_DiffuseMap_10_scale).xyz; + normal += n * alphaBlend2.b; + #else + normal += vec3(0.5,0.5,1) * alphaBlend.b; + #endif + + #ifdef NORMALMAP_11 + n = getTriPlanarBlend(coords, blending, m_NormalMap_11, m_DiffuseMap_11_scale).xyz; + normal += n * alphaBlend2.a; + #else + normal += vec3(0.5,0.5,1) * alphaBlend.a; + #endif + #endif + + normal = (normal.xyz * vec3(2.0) - vec3(1.0)); + normal = normalize(wvTangent * normal.x + wvBinormal * normal.y + vNormal * normal.z); + return normal; + } + #endif + +#endif + + + +void main(){ + + //---------------------- + // diffuse calculations + //---------------------- + #ifdef DIFFUSEMAP + #ifdef ALPHAMAP + #ifdef TRI_PLANAR_MAPPING + vec4 diffuseColor = calculateTriPlanarDiffuseBlend(wNormal, wVertex, texCoord); + #else + vec4 diffuseColor = calculateDiffuseBlend(texCoord); + #endif + #else + vec4 diffuseColor = texture2D(m_DiffuseMap, texCoord); + #endif + #else + vec4 diffuseColor = vec4(1.0); + #endif + + //--------------------- + // normal calculations + //--------------------- + #if defined(NORMALMAP) || defined(NORMALMAP_1) || defined(NORMALMAP_2) || defined(NORMALMAP_3) || defined(NORMALMAP_4) || defined(NORMALMAP_5) || defined(NORMALMAP_6) || defined(NORMALMAP_7) || defined(NORMALMAP_8) || defined(NORMALMAP_9) || defined(NORMALMAP_10) || defined(NORMALMAP_11) + #ifdef TRI_PLANAR_MAPPING + vec3 normal = calculateNormalTriPlanar(wNormal, wVertex, texCoord); + #else + vec3 normal = calculateNormal(texCoord); + #endif + + #else + vec3 normal = vNormal; + #endif + + + //-------------------------- + // final color calculations + //-------------------------- + gl_FragData[0] = vec4(normal *0.5+0.5, m_Shininess); + gl_FragData[1] = diffuseColor; + + //gl_FragColor.a = alpha; +} \ No newline at end of file diff --git a/assets/DMonkey/Terrain/Terrain.j3md b/assets/DMonkey/Terrain/Terrain.j3md new file mode 100644 index 0000000..3e2de50 --- /dev/null +++ b/assets/DMonkey/Terrain/Terrain.j3md @@ -0,0 +1,290 @@ +// NOTE: Doesn't support OpenGL1 +MaterialDef Terrain { + + MaterialParameters { + + // use tri-planar mapping + Boolean useTriPlanarMapping + + // Use ward specular instead of phong + Boolean WardIso + + // Are we rendering TerrainGrid + Boolean isTerrainGrid + + // Ambient color + Color Ambient + + // Diffuse color + Color Diffuse + + // Specular color + Color Specular + + // Specular power/shininess + Float Shininess : 0 + + // Texture map #0 + Texture2D DiffuseMap + Float DiffuseMap_0_scale + Texture2D NormalMap + + // Texture map #1 + Texture2D DiffuseMap_1 + Float DiffuseMap_1_scale + Texture2D NormalMap_1 + + // Texture map #2 + Texture2D DiffuseMap_2 + Float DiffuseMap_2_scale + Texture2D NormalMap_2 + + // Texture map #3 + Texture2D DiffuseMap_3 + Float DiffuseMap_3_scale + Texture2D NormalMap_3 + + // Texture map #4 + Texture2D DiffuseMap_4 + Float DiffuseMap_4_scale + Texture2D NormalMap_4 + + // Texture map #5 + Texture2D DiffuseMap_5 + Float DiffuseMap_5_scale + Texture2D NormalMap_5 + + // Texture map #6 + Texture2D DiffuseMap_6 + Float DiffuseMap_6_scale + Texture2D NormalMap_6 + + // Texture map #7 + Texture2D DiffuseMap_7 + Float DiffuseMap_7_scale + Texture2D NormalMap_7 + + // Texture map #8 + Texture2D DiffuseMap_8 + Float DiffuseMap_8_scale + Texture2D NormalMap_8 + + // Texture map #9 + Texture2D DiffuseMap_9 + Float DiffuseMap_9_scale + Texture2D NormalMap_9 + + // Texture map #10 + Texture2D DiffuseMap_10 + Float DiffuseMap_10_scale + Texture2D NormalMap_10 + + // Texture map #11 + Texture2D DiffuseMap_11 + Float DiffuseMap_11_scale + Texture2D NormalMap_11 + + + // Specular/gloss map + Texture2D SpecularMap + + + // Texture that specifies alpha values + Texture2D AlphaMap + Texture2D AlphaMap_1 + Texture2D AlphaMap_2 + + // Texture of the glowing parts of the material + Texture2D GlowMap + + // The glow color of the object + Color GlowColor + } + + Technique { + + LightMode MultiPass + + VertexShader GLSL100: Common/MatDefs/Terrain/TerrainLighting.vert + FragmentShader GLSL100: Common/MatDefs/Terrain/TerrainLighting.frag + + WorldParameters { + WorldViewProjectionMatrix + NormalMatrix + WorldViewMatrix + ViewMatrix + } + + Defines { + TRI_PLANAR_MAPPING : useTriPlanarMapping + TERRAIN_GRID : isTerrainGrid + WARDISO : WardIso + + DIFFUSEMAP : DiffuseMap + DIFFUSEMAP_1 : DiffuseMap_1 + DIFFUSEMAP_2 : DiffuseMap_2 + DIFFUSEMAP_3 : DiffuseMap_3 + DIFFUSEMAP_4 : DiffuseMap_4 + DIFFUSEMAP_5 : DiffuseMap_5 + DIFFUSEMAP_6 : DiffuseMap_6 + DIFFUSEMAP_7 : DiffuseMap_7 + DIFFUSEMAP_8 : DiffuseMap_8 + DIFFUSEMAP_9 : DiffuseMap_9 + DIFFUSEMAP_10 : DiffuseMap_10 + DIFFUSEMAP_11 : DiffuseMap_11 + NORMALMAP : NormalMap + NORMALMAP_1 : NormalMap_1 + NORMALMAP_2 : NormalMap_2 + NORMALMAP_3 : NormalMap_3 + NORMALMAP_4 : NormalMap_4 + NORMALMAP_5 : NormalMap_5 + NORMALMAP_6 : NormalMap_6 + NORMALMAP_7 : NormalMap_7 + NORMALMAP_8 : NormalMap_8 + NORMALMAP_9 : NormalMap_9 + NORMALMAP_10 : NormalMap_10 + NORMALMAP_11 : NormalMap_11 + SPECULARMAP : SpecularMap + ALPHAMAP : AlphaMap + ALPHAMAP_1 : AlphaMap_1 + ALPHAMAP_2 : AlphaMap_2 + DIFFUSEMAP_0_SCALE : DiffuseMap_0_scale + DIFFUSEMAP_1_SCALE : DiffuseMap_1_scale + DIFFUSEMAP_2_SCALE : DiffuseMap_2_scale + DIFFUSEMAP_3_SCALE : DiffuseMap_3_scale + DIFFUSEMAP_4_SCALE : DiffuseMap_4_scale + DIFFUSEMAP_5_SCALE : DiffuseMap_5_scale + DIFFUSEMAP_6_SCALE : DiffuseMap_6_scale + DIFFUSEMAP_7_SCALE : DiffuseMap_7_scale + DIFFUSEMAP_8_SCALE : DiffuseMap_8_scale + DIFFUSEMAP_9_SCALE : DiffuseMap_9_scale + DIFFUSEMAP_10_SCALE : DiffuseMap_10_scale + DIFFUSEMAP_11_SCALE : DiffuseMap_11_scale + } + } + + Technique PreShadow { + + VertexShader GLSL100 : Common/MatDefs/Shadow/PreShadow.vert + FragmentShader GLSL100 : Common/MatDefs/Shadow/PreShadow.frag + + WorldParameters { + WorldViewProjectionMatrix + WorldViewMatrix + } + + Defines { + DIFFUSEMAP_ALPHA : DiffuseMap + } + + RenderState { + FaceCull Off + DepthTest On + DepthWrite On + PolyOffset 5 0 + ColorWrite Off + } + + } + + Technique PreNormalPass { + + VertexShader GLSL100 : Common/MatDefs/SSAO/normal.vert + FragmentShader GLSL100 : Common/MatDefs/SSAO/normal.frag + + WorldParameters { + WorldViewProjectionMatrix + WorldViewMatrix + NormalMatrix + } + + Defines { + DIFFUSEMAP_ALPHA : DiffuseMap + } + + RenderState { + + } + + } + + Technique GBuffer { + + VertexShader GLSL100: DMonkey/Terrain/Terrain.vert + FragmentShader GLSL100: DMonkey/Terrain/Terrain.frag + + WorldParameters { + WorldViewProjectionMatrix + NormalMatrix + WorldViewMatrix + ViewMatrix + } + + Defines { + TRI_PLANAR_MAPPING : useTriPlanarMapping + TERRAIN_GRID : isTerrainGrid + WARDISO : WardIso + + DIFFUSEMAP : DiffuseMap + DIFFUSEMAP_1 : DiffuseMap_1 + DIFFUSEMAP_2 : DiffuseMap_2 + DIFFUSEMAP_3 : DiffuseMap_3 + DIFFUSEMAP_4 : DiffuseMap_4 + DIFFUSEMAP_5 : DiffuseMap_5 + DIFFUSEMAP_6 : DiffuseMap_6 + DIFFUSEMAP_7 : DiffuseMap_7 + DIFFUSEMAP_8 : DiffuseMap_8 + DIFFUSEMAP_9 : DiffuseMap_9 + DIFFUSEMAP_10 : DiffuseMap_10 + DIFFUSEMAP_11 : DiffuseMap_11 + NORMALMAP : NormalMap + NORMALMAP_1 : NormalMap_1 + NORMALMAP_2 : NormalMap_2 + NORMALMAP_3 : NormalMap_3 + NORMALMAP_4 : NormalMap_4 + NORMALMAP_5 : NormalMap_5 + NORMALMAP_6 : NormalMap_6 + NORMALMAP_7 : NormalMap_7 + NORMALMAP_8 : NormalMap_8 + NORMALMAP_9 : NormalMap_9 + NORMALMAP_10 : NormalMap_10 + NORMALMAP_11 : NormalMap_11 + SPECULARMAP : SpecularMap + ALPHAMAP : AlphaMap + ALPHAMAP_1 : AlphaMap_1 + ALPHAMAP_2 : AlphaMap_2 + DIFFUSEMAP_0_SCALE : DiffuseMap_0_scale + DIFFUSEMAP_1_SCALE : DiffuseMap_1_scale + DIFFUSEMAP_2_SCALE : DiffuseMap_2_scale + DIFFUSEMAP_3_SCALE : DiffuseMap_3_scale + DIFFUSEMAP_4_SCALE : DiffuseMap_4_scale + DIFFUSEMAP_5_SCALE : DiffuseMap_5_scale + DIFFUSEMAP_6_SCALE : DiffuseMap_6_scale + DIFFUSEMAP_7_SCALE : DiffuseMap_7_scale + DIFFUSEMAP_8_SCALE : DiffuseMap_8_scale + DIFFUSEMAP_9_SCALE : DiffuseMap_9_scale + DIFFUSEMAP_10_SCALE : DiffuseMap_10_scale + DIFFUSEMAP_11_SCALE : DiffuseMap_11_scale + } + } + + Technique { + LightMode FixedPipeline + } + + Technique Glow { + + VertexShader GLSL100: Common/MatDefs/Misc/Unshaded.vert + FragmentShader GLSL100: Common/MatDefs/Light/Glow.frag + + WorldParameters { + WorldViewProjectionMatrix + } + + Defines { + HAS_GLOWMAP : GlowMap + HAS_GLOWCOLOR : GlowColor + } + } + +} \ No newline at end of file diff --git a/assets/DMonkey/Terrain/Terrain.vert b/assets/DMonkey/Terrain/Terrain.vert new file mode 100644 index 0000000..3af9899 --- /dev/null +++ b/assets/DMonkey/Terrain/Terrain.vert @@ -0,0 +1,56 @@ +uniform mat4 g_WorldViewProjectionMatrix; +uniform mat4 g_WorldViewMatrix; +uniform mat3 g_NormalMatrix; +uniform mat4 g_ViewMatrix; + +uniform float m_Shininess; + +attribute vec3 inPosition; +attribute vec3 inNormal; +attribute vec2 inTexCoord; +attribute vec4 inTangent; + +varying vec3 vNormal; +varying vec2 texCoord; + +varying vec3 wvTangent; +varying vec3 wvBinormal; + +#ifdef TRI_PLANAR_MAPPING + varying vec4 wVertex; + varying vec3 wNormal; +#endif + +void main(){ + vec4 pos = vec4(inPosition, 1.0); + gl_Position = g_WorldViewProjectionMatrix * pos; + + #ifdef TERRAIN_GRID + texCoord = inTexCoord * 2.0; + #else + texCoord = inTexCoord; + #endif + + vec3 wvNormal = g_NormalMatrix * inNormal; + + //-------------------------- + // specific to normal maps: + //-------------------------- + #if defined(NORMALMAP) || defined(NORMALMAP_1) || defined(NORMALMAP_2) || defined(NORMALMAP_3) || defined(NORMALMAP_4) || defined(NORMALMAP_5) || defined(NORMALMAP_6) || defined(NORMALMAP_7) || defined(NORMALMAP_8) || defined(NORMALMAP_9) || defined(NORMALMAP_10) || defined(NORMALMAP_11) + wvTangent = normalize(g_NormalMatrix * inTangent.xyz); + wvBinormal = cross(wvTangent, wvNormal); + #else + + //------------------------- + // general to all lighting + //------------------------- + vNormal = wvNormal; + + #endif + + #ifdef TRI_PLANAR_MAPPING + wVertex = vec4(inPosition,0.0); + wNormal = inNormal; + #endif + +} \ No newline at end of file diff --git a/src/me/merciless/dmonkey/DeferredSceneProcessor.java b/src/me/merciless/dmonkey/DeferredSceneProcessor.java index dd84c2d..ce39cbe 100644 --- a/src/me/merciless/dmonkey/DeferredSceneProcessor.java +++ b/src/me/merciless/dmonkey/DeferredSceneProcessor.java @@ -4,13 +4,13 @@ */ package me.merciless.dmonkey; -import me.merciless.dmonkey.lights.Ambient; import me.merciless.dmonkey.lights.DLight; import com.jme3.app.Application; import com.jme3.asset.AssetManager; -import com.jme3.light.AmbientLight; import com.jme3.light.Light; +import com.jme3.light.PointLight; +import com.jme3.light.SpotLight; import com.jme3.material.Material; import com.jme3.math.ColorRGBA; import com.jme3.post.SceneProcessor; @@ -26,6 +26,10 @@ import com.jme3.texture.FrameBuffer; import com.jme3.texture.Image; import com.jme3.texture.Texture2D; +import java.util.HashMap; +import me.merciless.dmonkey.lights.Ambient; +import me.merciless.dmonkey.lights.DPointLight; +import me.merciless.dmonkey.lights.DSpotLight; /** * @@ -33,39 +37,43 @@ */ public class DeferredSceneProcessor implements SceneProcessor { + private Application app; private ViewPort vp; private RenderManager rm; private Renderer renderer; private ViewPort lightVp; private float tpf; - private AssetManager assets; + public AssetManager assets; private Node lightNode; - private GBuffer gbuffer; + public GBuffer gbuffer; private boolean debugLights = false; private Geometry resolveQuad; private FrameBuffer lightBuffer; private Texture2D lightTexture; + + private HashMaplights; private final Ambient ambient; public DeferredSceneProcessor(Application app) { this.assets = app.getAssetManager(); this.lightNode = new Node("BoundingVolumes"); - ambient = new Ambient(); + this.lights = new HashMap(); + ambient = new Ambient(this); + this.app = app; } public void initialize(RenderManager rm, ViewPort vp) { this.vp = vp; this.rm = rm; this.renderer = rm.getRenderer(); + Camera cam = vp.getCamera(); lightVp = new ViewPort("Lights", cam); lightVp.attachScene(lightNode); lightVp.setClearFlags(true, false, false); reshape(vp, cam.getWidth(), cam.getHeight()); - - ambient.initialize(this, gbuffer, assets); - scanRootNode(); + DeferredShadingUtils.showDebug(this, app, true); resolveQuad = new Geometry("ResolveQuad", new Quad(1, 1)); Material resolveMat = new Material(assets, "DMonkey/Resolve.j3md"); @@ -79,32 +87,53 @@ public void initialize(RenderManager rm, ViewPort vp) { resolveMat.setTexture("LightBuffer", lightTexture); resolveQuad.setQueueBucket(RenderQueue.Bucket.Opaque); - } - - public void scanRootNode() { - // It's always the rootNode right? - Node rootNode = (Node) vp.getScenes().get(0); - DeferredShadingUtils.scanNode(this, rootNode); - } - - public DLight addLight(Light light) { - return DeferredShadingUtils.addLight(this, light, true); - } - - public DLight getDLight(Light light) { - return DeferredShadingUtils.getLight(this, light); + lightNode.updateGeometricState(); } public void removeLight(Light light) { - if(light instanceof AmbientLight) - ambient.removeAmbientLight(light); - else { - DLight l = DeferredShadingUtils.getLight(this, light); - - if(l != null) - l.clean(); - } + DLight dlight = lights.remove(light); + if(dlight != null){ + dlight.removeFromParent(); + } } + + public DLight addLight(Light light, boolean check) { + + DeferredSceneProcessor dsp = this; + if (check) { + DLight l = lights.get(light); + + if (l != null) + return l; + } + + switch (light.getType()) { + case Ambient: + case Directional: + ambient.addLight(light); + return ambient; + case Point: { + DPointLight l = new DPointLight((PointLight)light, this); + lights.put(light, l); + dsp.lightNode.attachChild(l); + return l; + } + case Spot: { + DSpotLight l = new DSpotLight((SpotLight)light, this); + lights.put(light, l); + dsp.lightNode.attachChild(l); + return l; + } + default: + System.out.println("Unsuported light type: " + light.getType() + " - " + light.getName()); + break; + } + + return null; + } + public DLight getLight(Light light) { + return lights.get(light); + } public void reshape(ViewPort vp, int w, int h) { gbuffer = new GBuffer(w, h); @@ -123,6 +152,7 @@ public boolean isInitialized() { public void preFrame(float tpf) { this.tpf = tpf; lightNode.updateLogicalState(tpf); + ambient.updateLogicalState(tpf); } public void postQueue(RenderQueue rq) { @@ -142,9 +172,12 @@ public void postQueue(RenderQueue rq) { public void postFrame(FrameBuffer out) { rm.setForcedTechnique(null); rm.renderViewPort(lightVp, tpf); - rm.renderGeometry(ambient); + + ambient.updateGeometricState(); + ambient.render(rm, vp); if (debugLights) { + lightNode.updateGeometricState(); rm.setForcedMaterial(assets.loadMaterial("DMonkey/DebugMaterial.j3m")); rm.renderViewPortRaw(lightVp); rm.setForcedMaterial(null); @@ -157,30 +190,7 @@ public void cleanup() { rm = null; } - /** - * @return the assets - */ - public AssetManager getAssetManager() { - return assets; - } - - public Ambient getAmbient() { - return ambient; - } - - protected GBuffer getGBuffer() { - return gbuffer; - } - - protected ViewPort getLightViewport() { - return lightVp; - } - - protected ViewPort getMainViewPort() { - return vp; - } - - protected Node getLightNode() { - return lightNode; - } + public Camera getCamera() { + return lightVp.getCamera(); + } } diff --git a/src/me/merciless/dmonkey/DeferredShadingUtils.java b/src/me/merciless/dmonkey/DeferredShadingUtils.java index 903ba53..e8efd38 100644 --- a/src/me/merciless/dmonkey/DeferredShadingUtils.java +++ b/src/me/merciless/dmonkey/DeferredShadingUtils.java @@ -4,11 +4,16 @@ import me.merciless.dmonkey.lights.DLight; import me.merciless.dmonkey.lights.DPointLight; +import me.merciless.dmonkey.lights.DSpotLight; +import com.jme3.app.Application; import com.jme3.light.Light; import com.jme3.light.LightList; +import com.jme3.material.Material; import com.jme3.scene.Node; import com.jme3.scene.Spatial; +import com.jme3.texture.Texture2D; +import com.jme3.ui.Picture; /** * @author Seth @@ -27,13 +32,13 @@ protected static void scanNode(DeferredSceneProcessor dsp, Spatial root) { for (Light light : lights) { - if (getLight(dsp, light) != null) { + if (dsp.getLight(light) != null) { processed.add(light); continue; } // TADA - addLight(dsp, light, false); + dsp.addLight(light, false); } for (Light light : processed) { @@ -49,36 +54,33 @@ protected static void scanNode(DeferredSceneProcessor dsp, Spatial root) { } } } + + public static void showDebug(DeferredSceneProcessor dsp, Application app, boolean show) { + + Node guiNode = ((Node) app.getGuiViewPort().getScenes().get(0)); + + if(show) { + + Texture2D[] textures = { dsp.gbuffer.getNormals(), dsp.gbuffer.getDepth(), dsp.gbuffer.getDiffuse() }; + + int vpHeight = app.getGuiViewPort().getCamera().getHeight(); + int vpWidth = app.getGuiViewPort().getCamera().getWidth(); + float scale = 4f; + for (int i = 0; i < textures.length; i++) { + Material material = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md"); + material.setTexture("ColorMap", textures[i]); + Picture pic = new Picture("Normals"); + pic.setWidth(vpWidth / scale); + pic.setHeight(vpHeight / scale); + pic.move(vpWidth - (vpWidth / scale), vpHeight - (vpHeight / scale) * (i + 1), -1); + pic.setMaterial(material); + guiNode.attachChild(pic); + } + } + else + guiNode.detachChildNamed("Normals"); - protected static DLight addLight(DeferredSceneProcessor dsp, Light light, boolean check) { - - if (check) { - DLight l = getLight(dsp, light); - if (l != null) - return l; - } - - switch (light.getType()) { - case Ambient: - dsp.getAmbient().addAmbientLight(light); - return dsp.getAmbient(); - case Point: { - DPointLight l = new DPointLight(light); - l.initialize(dsp, dsp.getGBuffer(), dsp.getAssetManager()); - l.addControl(new LightQualityControl(l.getMaterial(), dsp.getLightViewport().getCamera())); - dsp.getLightNode().attachChild(l); - return l; - } - default: - System.out.println("Unsuported light type: " + light.getType() + " - " + light.getName()); - break; - } - - return null; + guiNode.updateGeometricState(); } - protected static DLight getLight(DeferredSceneProcessor dsp, Light light) { - String id = "DPS-" + light.getType() + "-[" + light.getName() + "/" + light.hashCode() + "]"; - return (DLight) dsp.getLightNode().getChild(id); - } } diff --git a/src/me/merciless/dmonkey/Main.java b/src/me/merciless/dmonkey/Main.java index 2e70d7b..d24bb6f 100644 --- a/src/me/merciless/dmonkey/Main.java +++ b/src/me/merciless/dmonkey/Main.java @@ -3,6 +3,7 @@ import java.util.ArrayList; import com.jme3.app.SimpleApplication; +import com.jme3.app.state.ScreenshotAppState; import com.jme3.input.KeyInput; import com.jme3.input.RawInputListener; import com.jme3.input.event.JoyAxisEvent; @@ -11,7 +12,11 @@ import com.jme3.input.event.MouseButtonEvent; import com.jme3.input.event.MouseMotionEvent; import com.jme3.input.event.TouchEvent; +import com.jme3.light.AmbientLight; +import com.jme3.light.DirectionalLight; +import com.jme3.light.Light; import com.jme3.light.PointLight; +import com.jme3.light.SpotLight; import com.jme3.material.Material; import com.jme3.math.ColorRGBA; import com.jme3.math.FastMath; @@ -23,7 +28,16 @@ import com.jme3.scene.BatchNode; import com.jme3.scene.Spatial; import com.jme3.system.AppSettings; +import com.jme3.terrain.geomipmap.TerrainLodControl; +import com.jme3.terrain.geomipmap.TerrainQuad; +import com.jme3.terrain.geomipmap.lodcalc.DistanceLodCalculator; +import com.jme3.terrain.heightmap.AbstractHeightMap; +import com.jme3.terrain.heightmap.ImageBasedHeightMap; +import com.jme3.texture.Texture; +import com.jme3.texture.Texture.WrapMode; import com.jme3.util.TangentBinormalGenerator; +import java.util.logging.Level; +import java.util.logging.Logger; /** * test @@ -32,9 +46,13 @@ */ public class Main extends SimpleApplication { - private ArrayList someLights = new ArrayList(); - + private ArrayList someLights = new ArrayList(); + private float grassScale = 64; + private float dirtScale = 16; + private float rockScale = 128; + public static void main(String[] args) { + Logger.getLogger("").setLevel(Level.WARNING); Main app = new Main(); AppSettings settings = new AppSettings(true); settings.setWidth(1280); @@ -43,10 +61,11 @@ public static void main(String[] args) { //settings.setDepthBits(16); app.setSettings(settings); - //app.setShowSettings(false); + app.setShowSettings(false); app.start(); } DeferredSceneProcessor dsp; + SpotLight sp = new SpotLight(); @Override public void simpleInitApp() { viewPort.addProcessor(dsp = new DeferredSceneProcessor(this)); @@ -56,9 +75,80 @@ public void simpleInitApp() { fpp.addFilter(new FXAAFilter()); viewPort.addProcessor(fpp); - flyCam.setMoveSpeed(10); + flyCam.setMoveSpeed(60); + + sp.setColor(ColorRGBA.Red); + sp.setPosition(new Vector3f(0, 3.9f, 0)); + sp.setDirection(new Vector3f(1, -1, 0).normalizeLocal()); + //sp.setDirection(new Vector3f(0.0077216243f, -0.14402537f, 0.98954386f).normalizeLocal()); + sp.setSpotOuterAngle(20f * FastMath.DEG_TO_RAD); + sp.setSpotRange(15f); + rootNode.addLight(sp); + + Material matTerrain = new Material(assetManager, "DMonkey/Terrain/Terrain.j3md"); + matTerrain.setBoolean("useTriPlanarMapping", false); + matTerrain.setBoolean("WardIso", false); + matTerrain.setFloat("Shininess", 20); + + // ALPHA map (for splat textures) + matTerrain.setTexture("AlphaMap", assetManager.loadTexture("Textures/Terrain/splat/alphamap.png")); + + // GRASS texture + Texture grass = assetManager.loadTexture("Textures/Terrain/splat/grass.jpg"); + grass.setWrap(WrapMode.Repeat); + matTerrain.setTexture("DiffuseMap", grass); + matTerrain.setFloat("DiffuseMap_0_scale", grassScale); + // DIRT texture + Texture dirt = assetManager.loadTexture("Textures/Terrain/splat/dirt.jpg"); + dirt.setWrap(WrapMode.Repeat); + matTerrain.setTexture("DiffuseMap_1", dirt); + matTerrain.setFloat("DiffuseMap_1_scale", dirtScale); + // ROCK texture + Texture rock = assetManager.loadTexture("Textures/Terrain/splat/road.jpg"); + rock.setWrap(WrapMode.Repeat); + matTerrain.setTexture("DiffuseMap_2", rock); + matTerrain.setFloat("DiffuseMap_2_scale", rockScale); + +// matTerrain.setFloat("DiffuseMap_0_scale", 1f / (float) (512f / grassScale)); +// matTerrain.setFloat("DiffuseMap_1_scale", 1f / (float) (512f / dirtScale)); +// matTerrain.setFloat("DiffuseMap_2_scale", 1f / (float) (512f / rockScale)); +// matTerrain.setFloat("DiffuseMap_3_scale", 1f / (float) (512f / rockScale)); +// matTerrain.setFloat("DiffuseMap_4_scale", 1f / (float) (512f / rockScale)); + + Texture normalMap0 = assetManager.loadTexture("Textures/Terrain/splat/grass_normal.jpg"); + normalMap0.setWrap(WrapMode.Repeat); + Texture normalMap1 = assetManager.loadTexture("Textures/Terrain/splat/dirt_normal.png"); + normalMap1.setWrap(WrapMode.Repeat); + Texture normalMap2 = assetManager.loadTexture("Textures/Terrain/splat/road_normal.png"); + normalMap2.setWrap(WrapMode.Repeat); + matTerrain.setTexture("NormalMap", normalMap0); + matTerrain.setTexture("NormalMap_1", normalMap1); + matTerrain.setTexture("NormalMap_2", normalMap2); + + // HEIGHTMAP image (for the terrain heightmap) + Texture heightMapImage = assetManager.loadTexture("Textures/Terrain/splat/mountains512.png"); + AbstractHeightMap heightmap = null; + try { + heightmap = new ImageBasedHeightMap(heightMapImage.getImage(), 1.5f); + heightmap.load(); + heightmap.smooth(0.9f, 1); + + } catch (Exception e) { + e.printStackTrace(); + } + + // CREATE THE TERRAIN + TerrainQuad terrain = new TerrainQuad("terrain", 65, 513, heightmap.getHeightMap()); + TerrainLodControl control = new TerrainLodControl(terrain, getCamera()); + control.setLodCalculator( new DistanceLodCalculator(65, 2.7f) ); // patch size, and a multiplier + terrain.addControl(control); + terrain.setMaterial(matTerrain); + terrain.setLocalTranslation(0, -100, 0); + terrain.setLocalScale(2.5f, 0.5f, 2.5f); + rootNode.attachChild(terrain); + Material mat = assetManager.loadMaterial("DMonkey/TestMaterial.j3m"); Spatial geom = assetManager.loadModel("Models/brokenCube.j3o"); geom.setMaterial(mat); @@ -87,7 +177,32 @@ public void simpleInitApp() { } rootNode.attachChild(cubes); + + AmbientLight al = new AmbientLight(); + al.setColor(ColorRGBA.DarkGray); + rootNode.addLight(al); + + DirectionalLight dl = new DirectionalLight(); + dl.setColor(ColorRGBA.LightGray.addLocal(ColorRGBA.White)); + dl.setDirection(new Vector3f(0, -1, 0).normalizeLocal()); + someLights.add(dl); + rootNode.addLight(dl); + + dl = new DirectionalLight(); + dl.setColor(ColorRGBA.Green); + dl.setDirection(new Vector3f(1,0,0).normalize()); + //someLights.add(dl); + //rootNode.addLight(dl); + dl = new DirectionalLight(); + dl.setColor(ColorRGBA.Blue); + dl.setDirection(new Vector3f(0,0,1).normalize()); + //someLights.add(dl); + //rootNode.addLight(dl); + + DeferredShadingUtils.scanNode(dsp, rootNode); + + stateManager.attach(new ScreenshotAppState("E:/Game-Development/Workbench/dmonkey2/")); inputManager.addRawInputListener(new RawInputListener() { @Override @@ -106,12 +221,33 @@ public void onKeyEvent(KeyInputEvent evt) { if(!isPressed) { switch (evt.getKeyCode()) { case KeyInput.KEY_1: - PointLight light = someLights.remove(someLights.size() - 1); + if(someLights.isEmpty()) { + System.out.println("No more lights to remove"); + return; + } + Light light = someLights.remove(someLights.size() - 1); if(light != null) dsp.removeLight(light); break; + case KeyInput.KEY_2: { + Vector3f pos = sp.getPosition(); + pos.y -= 0.1f; + sp.setPosition(pos); + break; + } + case KeyInput.KEY_3: { + Vector3f pos = sp.getPosition(); + pos.y += 0.1f; + sp.setPosition(pos); + break; + } + case KeyInput.KEY_4: { + sp.setPosition(cam.getLocation()); + sp.setDirection(cam.getDirection()); + break; + } default: break; } @@ -142,9 +278,11 @@ public void simpleUpdate(float tpf) { time -= period; } - for (PointLight slight : someLights) { - Vector3f origin = slight.getPosition(); - slight.setPosition(new Vector3f(origin.x, FastMath.sin(time / period * FastMath.TWO_PI) * 1 + 1.2f, origin.z)); + for (Light slight : someLights) { + if(slight instanceof PointLight) { + Vector3f origin = ((PointLight) slight).getPosition(); + ((PointLight) slight).setPosition(new Vector3f(origin.x, FastMath.sin(time / period * FastMath.TWO_PI) * 1 + 1.2f, origin.z)); + } } } diff --git a/src/me/merciless/dmonkey/lights/Ambient.java b/src/me/merciless/dmonkey/lights/Ambient.java index faf594c..324fd44 100644 --- a/src/me/merciless/dmonkey/lights/Ambient.java +++ b/src/me/merciless/dmonkey/lights/Ambient.java @@ -5,13 +5,19 @@ import com.jme3.asset.AssetManager; import com.jme3.light.AmbientLight; +import com.jme3.light.DirectionalLight; import com.jme3.light.Light; import com.jme3.material.Material; import com.jme3.material.RenderState; +import com.jme3.material.RenderState.FaceCullMode; import com.jme3.math.ColorRGBA; +import com.jme3.math.Matrix4f; +import com.jme3.math.Vector3f; +import com.jme3.math.Vector4f; import com.jme3.renderer.RenderManager; import com.jme3.renderer.ViewPort; import com.jme3.scene.shape.Quad; +import com.jme3.shader.VarType; import com.jme3.util.SafeArrayList; /** @@ -20,12 +26,13 @@ public final class Ambient extends DLight { // The reason this is here is to get the colors - private final SafeArrayList lights = new SafeArrayList(AmbientLight.class); + private final SafeArrayList lights = new SafeArrayList(Light.class); + private int dLightSize; private final ColorRGBA ambientColor = new ColorRGBA(0,0,0,0); - public Ambient() { - super(null); // Nothing that needs to be keept track of + public Ambient(DeferredSceneProcessor dsp) { + super(null, dsp); // Nothing that needs to be keept track of mesh = new Quad(1, 1); mesh.setStatic(); @@ -42,6 +49,7 @@ public void initialize(DeferredSceneProcessor dsp, GBuffer buff, AssetManager as RenderState rs = material.getAdditionalRenderState(); rs.setBlendMode(RenderState.BlendMode.Additive); + rs.setFaceCullMode(FaceCullMode.Back); rs.setDepthTest(false); rs.setDepthWrite(false); } @@ -50,27 +58,60 @@ public void initialize(DeferredSceneProcessor dsp, GBuffer buff, AssetManager as public void render(RenderManager rm, ViewPort vp) { ambientColor.set(0, 0, 0, 0); - for (AmbientLight light : lights) { - ambientColor.addLocal(light.getColor()); + Vector4f[] dlcs = new Vector4f[dLightSize]; + Vector3f[] dlds = new Vector3f[dLightSize]; + + int position = 0; + for (Light light : lights) { + if(light instanceof AmbientLight) + ambientColor.addLocal(light.getColor()); + else { // lights here can be only 2 types, ambient and directional + DirectionalLight dl = (DirectionalLight)light; + + if(position >= dlcs.length) { + System.out.println("Way too many direct lights!"); + break; + } + + int pos = position++; + dlcs[pos] = dl.getColor().toVector4f(); + + //Matrix4f viewMatrix = vp.getCamera().getViewMatrix(); + dlds[pos] = dl.getDirection();//viewMatrix.mult(dl.getDirection()); + } } if(ambientColor.a > 1.0f) ambientColor.a = 1.0f; material.setColor("Color", ambientColor); + + material.setInt("DirectionalLights", dLightSize); + material.setParam("DirectionalColors", VarType.Vector4Array, dlcs); + material.setParam("Directions", VarType.Vector3Array, dlds); + + // and done + rm.renderGeometry(this); } @Override public void update(float tpf) { } - public void addAmbientLight(Light light) { - if(!lights.contains(light)) - lights.add((AmbientLight) light); + @Override + public void addLight(Light light) { + if(!lights.contains(light)) { + lights.add(light); + + if(light instanceof DirectionalLight) + dLightSize++; + } } - public void removeAmbientLight(Light light) { - lights.remove(light); + @Override + public void removeLight(Light light) { + if(lights.remove(light) && light instanceof DirectionalLight) + dLightSize--; } @Override diff --git a/src/me/merciless/dmonkey/lights/ConeMesh.java b/src/me/merciless/dmonkey/lights/ConeMesh.java new file mode 100644 index 0000000..607d627 --- /dev/null +++ b/src/me/merciless/dmonkey/lights/ConeMesh.java @@ -0,0 +1,136 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package me.merciless.dmonkey.lights; + +import com.jme3.math.FastMath; +import com.jme3.math.Vector3f; +import com.jme3.scene.Mesh; +import com.jme3.scene.VertexBuffer.Type; +import com.jme3.util.BufferUtils; +import java.nio.FloatBuffer; +import java.nio.IntBuffer; + +/** + * @author kwando + */ +public class ConeMesh extends Mesh { + + private ConeMesh() { + } + + private static float radiusAtHeight(float height, float cutoff) { + return height * FastMath.tan(cutoff / 2); + } + + public static Mesh volumeFromRangeAndCutoff(float range, float cutoff) { + if (cutoff < 0 || cutoff > 80) { + throw new IllegalArgumentException("cutoff should be between 0 and 80"); + } + cutoff *= FastMath.DEG_TO_RAD; + + + + ConeMesh cm = new ConeMesh(); + int radialSamples = 24; + int heightSegments = 4; + float heightStep = range / (heightSegments - 1); + + + float stepSize = FastMath.TWO_PI / radialSamples; + FloatBuffer positionBuffer = BufferUtils.createFloatBuffer(radialSamples * heightSegments * 3); + FloatBuffer normalBuffer = BufferUtils.createFloatBuffer(radialSamples * heightSegments * 3); + Vector3f tmp = new Vector3f(); + for (int h = 0; h < heightSegments; h++) { + float radius = radiusAtHeight(heightStep * h, cutoff); + float height = h * heightStep; + + for (int i = 0; i < radialSamples; i++) { + float cos = FastMath.cos(stepSize * i); + float sin = FastMath.sin(stepSize * i); + + + tmp.x = cos * radius; + tmp.z = sin * radius; + tmp.y = -height; + + positionBuffer.put(tmp.x); + positionBuffer.put(tmp.y); + positionBuffer.put(tmp.z); + + tmp.set(cos, cutoff / 2, sin); + tmp.normalizeLocal(); + normalBuffer.put(tmp.x); + normalBuffer.put(tmp.y); + normalBuffer.put(tmp.z); + } + } + IntBuffer indexBuffer = BufferUtils.createIntBuffer(radialSamples * (heightSegments - 1) * 6); + for (int h = 0; h < heightSegments - 1; h++) { + int offset = h * radialSamples; + for (int i = 0; i < radialSamples; i++) { + int a = offset + i; + int b = offset + (i + 1) % radialSamples; + int c = offset + radialSamples + i; + int d = offset + radialSamples + (i + 1) % radialSamples; + + indexBuffer.put(a); + indexBuffer.put(b); + indexBuffer.put(c); + + indexBuffer.put(d); + indexBuffer.put(c); + indexBuffer.put(b); + } + } + + cm.setBuffer(Type.Position, 3, positionBuffer); + cm.setBuffer(Type.Index, 3, indexBuffer); + cm.setBuffer(Type.Normal, 3, normalBuffer); + + cm.setMode(Mode.Triangles); + cm.updateBound(); + return cm; + } + + public static ConeMesh fromRangeAndCutoff(float range, float cutoff) { + if (cutoff < 0 || cutoff > 80) { + throw new IllegalArgumentException("cutoff should be between 0 and 80"); + } + cutoff *= FastMath.DEG_TO_RAD; + + float radius = range * FastMath.tan(cutoff / 2); + + ConeMesh cm = new ConeMesh(); + int samples = 32; + float stepSize = FastMath.TWO_PI / samples; + Vector3f[] positions = new Vector3f[samples + 2]; + for (int i = 0; i < samples; i++) { + positions[i] = new Vector3f(FastMath.cos(stepSize * i) * radius, -range, FastMath.sin(stepSize * i) * radius); + } + positions[samples] = Vector3f.ZERO.add(0, 0, 0); + positions[samples + 1] = Vector3f.ZERO.add(0, -range, 0); + int[] index = new int[samples * 3 * 2]; + for (int i = 0; i < samples; i++) { + int n = 0; + index[6 * i + n++] = (i + 1) % samples; + index[6 * i + n++] = i; + index[6 * i + n++] = samples; + + + index[6 * i + n++] = i; + index[6 * i + n++] = (i + 1) % samples; + index[6 * i + n++] = samples + 1; + } + + cm.setBuffer(Type.Position, 3, BufferUtils.createFloatBuffer(positions)); + cm.setBuffer(Type.Index, 3, BufferUtils.createIntBuffer(index)); + + + cm.setPointSize(3); + cm.setMode(Mode.Triangles); + cm.updateBound(); + return cm; + } +} diff --git a/src/me/merciless/dmonkey/lights/DLight.java b/src/me/merciless/dmonkey/lights/DLight.java index fc9781b..7b19965 100644 --- a/src/me/merciless/dmonkey/lights/DLight.java +++ b/src/me/merciless/dmonkey/lights/DLight.java @@ -12,27 +12,24 @@ /** * @author Seth */ -public abstract class DLight extends Geometry { +public abstract class DLight extends Geometry { - private final Light light; + private final T light; + private boolean isInitialized = false; + private DeferredSceneProcessor dsp; - public DLight(Light light) { + public DLight(T light, DeferredSceneProcessor dsp) { this.light = light; + this.dsp = dsp; } - - public abstract void initialize(DeferredSceneProcessor dsp, GBuffer buff, AssetManager assetManager); + + protected abstract void initialize(DeferredSceneProcessor dsp, GBuffer buff, AssetManager assetManager); public abstract void render(RenderManager rm, ViewPort vp); public abstract void update(float tpf); public abstract void clean(); - @SuppressWarnings("unchecked") - public T getLight() { - return (T)light; - } - - @SuppressWarnings("unchecked") - public T getLight(Class type) { - return (T)light; + public T getLight() { + return light; } @Override @@ -48,10 +45,12 @@ public void runControlRender(RenderManager rm, ViewPort vp) { @Override public void updateLogicalState(float tpf) { + if(!isInitialized){ + initialize(dsp, dsp.gbuffer, dsp.assets); + isInitialized = true; + } update(tpf); super.updateLogicalState(tpf); } - - } diff --git a/src/me/merciless/dmonkey/lights/DPointLight.java b/src/me/merciless/dmonkey/lights/DPointLight.java index 6326ebd..59d219f 100644 --- a/src/me/merciless/dmonkey/lights/DPointLight.java +++ b/src/me/merciless/dmonkey/lights/DPointLight.java @@ -12,14 +12,15 @@ import com.jme3.renderer.RenderManager; import com.jme3.renderer.ViewPort; import com.jme3.scene.shape.Sphere; +import me.merciless.dmonkey.LightQualityControl; /** * @author Seth */ -public final class DPointLight extends DLight { +public final class DPointLight extends DLight { - public DPointLight(Light light) { - super(light); + public DPointLight(PointLight light, DeferredSceneProcessor dsp) { + super(light, dsp); // Better option? lol setName("DPS-"+light.getType()+"-["+light.getName()+"/"+light.hashCode()+"]"); @@ -40,6 +41,7 @@ public void initialize(DeferredSceneProcessor dsp, GBuffer buff, AssetManager as material.getAdditionalRenderState().setDepthTest(true); material.getAdditionalRenderState().setDepthWrite(false); material.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Additive); + addControl(new LightQualityControl(material, dsp.getCamera())); } @Override diff --git a/src/me/merciless/dmonkey/lights/DSpotLight.java b/src/me/merciless/dmonkey/lights/DSpotLight.java new file mode 100644 index 0000000..9c94ad1 --- /dev/null +++ b/src/me/merciless/dmonkey/lights/DSpotLight.java @@ -0,0 +1,70 @@ +package me.merciless.dmonkey.lights; + +import me.merciless.dmonkey.DeferredSceneProcessor; +import me.merciless.dmonkey.GBuffer; + +import com.jme3.asset.AssetManager; +import com.jme3.light.Light; +import com.jme3.light.SpotLight; +import com.jme3.material.Material; +import com.jme3.material.RenderState; +import com.jme3.material.RenderState.FaceCullMode; +import com.jme3.math.FastMath; +import com.jme3.math.Matrix4f; +import com.jme3.math.Vector3f; +import com.jme3.renderer.RenderManager; +import com.jme3.renderer.ViewPort; + +/** + * @author Seth + */ +public final class DSpotLight extends DLight { + + public DSpotLight(SpotLight light, DeferredSceneProcessor dsp) { + super(light, dsp); + + SpotLight sp = getLight(); + mesh = ConeMesh.fromRangeAndCutoff(sp.getSpotRange(), sp.getSpotOuterAngle() * FastMath.RAD_TO_DEG); + mesh.setStatic(); + setBoundRefresh(); + } + + @Override + public void initialize(DeferredSceneProcessor dsp, GBuffer buff, AssetManager assetManager) { + material = new Material(assetManager, "DMonkey/SpotLight.j3md"); + material.setTexture("DiffuseBuffer", buff.getDiffuse()); + material.setTexture("DepthBuffer", buff.getDepth()); + material.setTexture("NormalBuffer", buff.getNormals()); + material.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Additive); + material.getAdditionalRenderState().setDepthTest(false); + material.getAdditionalRenderState().setDepthWrite(false); + material.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Front); + } + + @Override + public void render(RenderManager rm, ViewPort vp) { + SpotLight light = getLight(); + Matrix4f viewMatrix = vp.getCamera().getViewMatrix(); + material.setVector3("LightPosition", viewMatrix.mult(light.getPosition())); + material.setColor("LightColor", light.getColor()); + material.setFloat("CutoffAngle", light.getSpotOuterAngle()); + material.setFloat("LightRange", light.getSpotRange()); + material.setVector3("LightDirection", light.getDirection()); + } + + @Override + public void update(float tpf) { + SpotLight light = getLight(); + + setLocalTranslation(light.getPosition()); + getLocalRotation().lookAt(light.getDirection(), Vector3f.UNIT_Y); + rotate(80,0,0); + } + + @Override + public void clean() { + removeFromParent(); + } + + +} diff --git a/src/me/merciless/dmonkey/lights/PyramidMesh.java b/src/me/merciless/dmonkey/lights/PyramidMesh.java new file mode 100644 index 0000000..d97d797 --- /dev/null +++ b/src/me/merciless/dmonkey/lights/PyramidMesh.java @@ -0,0 +1,83 @@ +package me.merciless.dmonkey.lights; + +import com.jme3.math.FastMath; +import com.jme3.scene.Mesh; +import com.jme3.scene.VertexBuffer; +import com.jme3.scene.VertexBuffer.Type; +import com.jme3.util.BufferUtils; +import java.nio.FloatBuffer; +import java.nio.IntBuffer; + +/** + * + * @author kwando + */ +public class PyramidMesh extends Mesh { + + private float outerAngleInrad; + private float range; + + public PyramidMesh(float outerAngleInrad, float range) { + this.outerAngleInrad = outerAngleInrad; + this.range = range; + createMesh(); + } + + private void createMesh() { + float halfSide = FastMath.atan(outerAngleInrad / 1.8f) * range; + + FloatBuffer pos = BufferUtils.createFloatBuffer(5 * 3); + IntBuffer index = BufferUtils.createIntBuffer(6 * 3); + pos.put(0); + pos.put(0); + pos.put(0); + + pos.put(-halfSide); + pos.put(-range); + pos.put(-halfSide); + + pos.put(-halfSide); + pos.put(-range); + pos.put(+halfSide); + + pos.put(+halfSide); + pos.put(-range); + pos.put(+halfSide); + + pos.put(+halfSide); + pos.put(-range); + pos.put(-halfSide); + + + index.put(0); + index.put(1); + index.put(2); + + index.put(0); + index.put(2); + index.put(3); + + index.put(0); + index.put(3); + index.put(4); + + index.put(0); + index.put(4); + index.put(1); + + index.put(2); + index.put(1); + index.put(3); + + index.put(3); + index.put(1); + index.put(4); + + + + setBuffer(Type.Position, 3, pos); + setBuffer(Type.Index, 3, index); + setMode(Mode.Triangles); + updateBound(); + } +}