소스 검색

Merge pull request #1094 from jayfella/master

Add support for fog in materials.
James Khan 6 년 전
부모
커밋
a8f5ac0589

+ 38 - 0
jme3-core/src/main/resources/Common/MatDefs/Light/Lighting.frag

@@ -6,6 +6,26 @@
     #import "Common/ShaderLib/Lighting.glsllib"
 #endif
 
+// fog - jayfella
+#ifdef USE_FOG
+#import "Common/ShaderLib/MaterialFog.glsllib"
+varying float fog_distance;
+uniform vec4 m_FogColor;
+
+#ifdef FOG_LINEAR
+uniform vec2 m_LinearFog;
+#endif
+
+#ifdef FOG_EXP
+uniform float m_ExpFog;
+#endif
+
+#ifdef FOG_EXPSQ
+uniform float m_ExpSqFog;
+#endif
+
+#endif // end fog
+
 varying vec2 texCoord;
 #ifdef SEPARATE_TEXCOORD
   varying vec2 texCoord2;
@@ -115,6 +135,7 @@ void main(){
     #endif
 
 
+
     // ***********************
     // Read from textures
     // ***********************
@@ -207,5 +228,22 @@ void main(){
                            DiffuseSum.rgb   * diffuseColor.rgb  * vec3(light.x) +
                            SpecularSum2.rgb * specularColor.rgb * vec3(light.y);
     #endif
+
+
+    // add fog after the lighting because shadows will cause the fog to darken
+    // which just results in the geometry looking like it's changed color
+    #ifdef USE_FOG
+        #ifdef FOG_LINEAR
+            gl_FragColor = getFogLinear(gl_FragColor, m_FogColor, m_LinearFog.x, m_LinearFog.y, fog_distance);
+        #endif
+        #ifdef FOG_EXP
+            gl_FragColor = getFogExp(gl_FragColor, m_FogColor, m_ExpFog, fog_distance);
+        #endif
+        #ifdef FOG_EXPSQ
+            gl_FragColor = getFogExpSquare(gl_FragColor, m_FogColor, m_ExpSqFog, fog_distance);
+        #endif
+    #endif // end fog
+
+
     gl_FragColor.a = alpha;
 }

+ 20 - 0
jme3-core/src/main/resources/Common/MatDefs/Light/Lighting.j3md

@@ -120,6 +120,14 @@ MaterialDef Phong Lighting {
         Boolean UseInstancing
 
         Boolean BackfaceShadows : false
+
+        // fog - jayfella
+        Boolean UseFog
+        Color FogColor
+        Vector2 LinearFog
+        Float ExpFog
+        Float ExpSqFog
+
     }
 
     Technique {
@@ -159,6 +167,12 @@ MaterialDef Phong Lighting {
             INSTANCING : UseInstancing
             NUM_MORPH_TARGETS: NumberOfMorphTargets
             NUM_TARGETS_BUFFERS: NumberOfTargetsBuffers
+
+            // fog - jayfella
+            USE_FOG : UseFog
+            FOG_LINEAR : LinearFog
+            FOG_EXP : ExpFog
+            FOG_EXPSQ : ExpSqFog
         }
     }
 
@@ -200,6 +214,12 @@ MaterialDef Phong Lighting {
             INSTANCING : UseInstancing
             NUM_MORPH_TARGETS: NumberOfMorphTargets
             NUM_TARGETS_BUFFERS: NumberOfTargetsBuffers
+
+            // fog - jayfella
+            USE_FOG : UseFog
+            FOG_LINEAR : LinearFog
+            FOG_EXP : ExpFog
+            FOG_EXPSQ : ExpSqFog
         }
     }
 

+ 10 - 1
jme3-core/src/main/resources/Common/MatDefs/Light/Lighting.vert

@@ -8,6 +8,11 @@
     #import "Common/ShaderLib/BlinnPhongLighting.glsllib"    
 #endif
 
+// fog - jayfella
+#ifdef USE_FOG
+varying float fog_distance;
+uniform vec3 g_CameraPosition;
+#endif
 
 uniform vec4 m_Ambient;
 uniform vec4 m_Diffuse;
@@ -178,5 +183,9 @@ void main(){
 
     #ifdef USE_REFLECTION 
         computeRef(modelSpacePos);
-    #endif 
+    #endif
+
+    #ifdef USE_FOG
+    fog_distance = distance(g_CameraPosition, (g_WorldMatrix * modelSpacePos).xyz);
+    #endif
 }

+ 35 - 0
jme3-core/src/main/resources/Common/MatDefs/Light/SPLighting.frag

@@ -6,6 +6,26 @@
     #import "Common/ShaderLib/Lighting.glsllib"
 #endif
 
+// fog - jayfella
+#ifdef USE_FOG
+#import "Common/ShaderLib/MaterialFog.glsllib"
+varying float fog_distance;
+uniform vec4 m_FogColor;
+
+#ifdef FOG_LINEAR
+uniform vec2 m_LinearFog;
+#endif
+
+#ifdef FOG_EXP
+uniform float m_ExpFog;
+#endif
+
+#ifdef FOG_EXPSQ
+uniform float m_ExpSqFog;
+#endif
+
+#endif // end fog
+
 varying vec2 texCoord;
 #ifdef SEPARATE_TEXCOORD
   varying vec2 texCoord2;
@@ -226,5 +246,20 @@ void main(){
         }
            
      #endif
+
+    // add fog after the lighting because shadows will cause the fog to darken
+    // which just results in the geometry looking like it's changed color
+    #ifdef USE_FOG
+        #ifdef FOG_LINEAR
+            gl_FragColor = getFogLinear(gl_FragColor, m_FogColor, m_LinearFog.x, m_LinearFog.y, fog_distance);
+        #endif
+        #ifdef FOG_EXP
+            gl_FragColor = getFogExp(gl_FragColor, m_FogColor, m_ExpFog, fog_distance);
+        #endif
+        #ifdef FOG_EXPSQ
+            gl_FragColor = getFogExpSquare(gl_FragColor, m_FogColor, m_ExpSqFog, fog_distance);
+        #endif
+    #endif // end fog
+
     gl_FragColor.a = alpha;
 }

+ 10 - 1
jme3-core/src/main/resources/Common/MatDefs/Light/SPLighting.vert

@@ -8,6 +8,11 @@
     #import "Common/ShaderLib/BlinnPhongLighting.glsllib"
 #endif
 
+// fog - jayfella
+#ifdef USE_FOG
+varying float fog_distance;
+uniform vec3 g_CameraPosition;
+#endif
 
 uniform vec4 m_Ambient;
 uniform vec4 m_Diffuse;
@@ -187,5 +192,9 @@ void main(){
 
     #ifdef USE_REFLECTION
         computeRef(modelSpacePos);
-    #endif 
+    #endif
+
+    #ifdef USE_FOG
+    fog_distance = distance(g_CameraPosition, (g_WorldMatrix * modelSpacePos).xyz);
+    #endif
 }

+ 25 - 0
jme3-core/src/main/resources/Common/ShaderLib/MaterialFog.glsllib

@@ -0,0 +1,25 @@
+
+vec4 getFogLinear(in vec4 diffuseColor, in vec4 fogColor, in float start, in float end, in float distance) {
+
+    float fogFactor = (end - distance) / (end - start);
+    fogFactor = clamp(fogFactor, 0.0, 1.0);
+
+    return mix(fogColor, diffuseColor, fogFactor);
+}
+
+vec4 getFogExp(in vec4 diffuseColor, in vec4 fogColor, in float fogDensity, in float distance) {
+
+    float fogFactor = 1.0 / exp(distance * fogDensity);
+    fogFactor = clamp( fogFactor, 0.0, 1.0 );
+
+    return mix(fogColor, diffuseColor, fogFactor);
+}
+
+vec4 getFogExpSquare(in vec4 diffuseColor, in vec4 fogColor, in float fogDensity, in float distance) {
+
+    float fogFactor = 1.0 / exp( (distance * fogDensity) * (distance * fogDensity));
+    fogFactor = clamp( fogFactor, 0.0, 1.0 );
+
+    vec4 finalColor = mix(fogColor, diffuseColor, fogFactor);
+    return finalColor;
+}

+ 79 - 0
jme3-examples/src/main/java/jme3test/light/TestLightingFog.java

@@ -0,0 +1,79 @@
+package jme3test.light;
+
+import com.jme3.app.SimpleApplication;
+import com.jme3.input.KeyInput;
+import com.jme3.input.controls.ActionListener;
+import com.jme3.input.controls.KeyTrigger;
+import com.jme3.light.DirectionalLight;
+import com.jme3.material.Material;
+import com.jme3.material.Materials;
+import com.jme3.math.ColorRGBA;
+import com.jme3.math.FastMath;
+import com.jme3.math.Vector2f;
+import com.jme3.math.Vector3f;
+import com.jme3.scene.Geometry;
+import com.jme3.scene.shape.Sphere;
+
+public class TestLightingFog extends SimpleApplication implements ActionListener {
+
+    private Material material;
+    private Vector2f linear = new Vector2f(25, 120);
+    private float exp = 0.015f;
+    private float expsq = 0.02f;
+
+    public static void main(String[] args) {
+        TestLightingFog testLightingFog = new TestLightingFog();
+        testLightingFog.start();
+    }
+
+    @Override
+    public void simpleInitApp() {
+
+        ColorRGBA skyColor = new ColorRGBA(0.5f, 0.6f, 0.7f, 0.0f);
+
+        flyCam.setMoveSpeed(20);
+        viewPort.setBackgroundColor(skyColor.mult(0.9f));
+
+        DirectionalLight directionalLight = new DirectionalLight(new Vector3f(-1, -1, -1).normalizeLocal());
+        rootNode.addLight(directionalLight);
+
+        material = new Material(assetManager, Materials.LIGHTING);
+        material.setBoolean("UseFog", true);
+        material.setColor("FogColor", skyColor);
+        material.setVector2("LinearFog", linear);
+
+        int distance = -3;
+
+        for (int i = 0; i < 100; i++) {
+            Geometry geometry = new Geometry("Sphere", new Sphere(32, 32, 2));
+            geometry.setMaterial(material);
+
+            geometry.setLocalTranslation((FastMath.nextRandomFloat() - 0.5f) * 45, 0, i * distance);
+            rootNode.attachChild(geometry);
+        }
+
+        inputManager.addMapping("Linear",  new KeyTrigger(KeyInput.KEY_1));
+        inputManager.addMapping("Exponential",  new KeyTrigger(KeyInput.KEY_2));
+        inputManager.addMapping("ExponentialSquared",  new KeyTrigger(KeyInput.KEY_3));
+        inputManager.addListener(this, "Linear", "Exponential", "ExponentialSquared");
+    }
+
+    @Override
+    public void onAction(String name, boolean isPressed, float tpf) {
+        if (name.equals("Linear") && !isPressed) {
+            material.setVector2("LinearFog", linear);
+            material.clearParam("ExpFog");
+            material.clearParam("ExpSqFog");
+        }
+        else if (name.equals("Exponential") && !isPressed) {
+            material.clearParam("LinearFog");
+            material.setFloat("ExpFog", exp);
+            material.clearParam("ExpSqFog");
+        }
+        else if (name.equals("ExponentialSquared") && !isPressed) {
+            material.clearParam("LinearFog");
+            material.clearParam("ExpFog");
+            material.setFloat("ExpSqFog", expsq);
+        }
+    }
+}