瀏覽代碼

Fixed Parallax for PBR lighting

Nehon 10 年之前
父節點
當前提交
719a683c2c

+ 11 - 18
jme3-core/src/main/resources/Common/MatDefs/Light/PBRLighting.frag

@@ -62,7 +62,7 @@ varying vec3 wPosition;
   uniform sampler2D m_LightMap;
 #endif
   
-#ifdef NORMALMAP
+#if defined(NORMALMAP) || defined(PARALLAXMAP)
   uniform sampler2D m_NormalMap;   
   varying vec3 wTangent;
   varying vec3 wBinormal;
@@ -75,9 +75,14 @@ uniform float m_AlphaDiscardThreshold;
 
 void main(){
     vec2 newTexCoord;
-     
+    vec3 viewDir = normalize(g_CameraPosition - wPosition);
+
+    #if defined(NORMALMAP) || defined(PARALLAXMAP)
+        mat3 tbnMat = mat3(normalize(wTangent.xyz) , normalize(wBinormal.xyz) , normalize(wNormal.xyz));       
+    #endif
+
     #if (defined(PARALLAXMAP) || (defined(NORMALMAP_PARALLAX) && defined(NORMALMAP)))
-     
+       vec3 vViewDir =  viewDir * tbnMat;  
        #ifdef STEEP_PARALLAX
            #ifdef NORMALMAP_PARALLAX
                //parallax map is stored in the alpha channel of the normal map         
@@ -114,9 +119,7 @@ void main(){
     #else
         float Metallic =  max(m_Metallic,0.00);
     #endif
-
- //Roughness =  max(m_Roughness,1e-8);
- //Metallic =  max(m_Metallic,0.00);
+ 
     float alpha = Color.a * albedo.a;
 
     #ifdef DISCARD_ALPHA
@@ -135,6 +138,8 @@ void main(){
       //see http://hub.jmonkeyengine.org/forum/topic/parallax-mapping-fundamental-bug/#post-256898
       //for more explanation.
       vec3 normal = normalize((normalHeight.xyz * vec3(2.0,-2.0,2.0) - vec3(1.0,-1.0,1.0)));
+      normal = tbnMat * normal;
+      //normal = normalize(normal * inverse(tbnMat));
     #else
       vec3 normal = normalize(wNormal);            
     #endif
@@ -151,19 +156,7 @@ void main(){
        albedo.rgb  *= lightMapColor;
     #endif
 
-    int i = 0;
-
-
-    #ifdef NORMALMAP   
-        mat3 tbnMat = mat3(normalize(wTangent.xyz) , normalize(wBinormal.xyz) , normalize(wNormal.xyz));
-        normal = normalize(tbnMat * normal);
-//        normal = normalize(normal * inverse(tbnMat));
-    #endif
-    vec3 viewDir = normalize(g_CameraPosition - wPosition);
-    
-   
     float specular = 0.5;
-
     #ifdef SPECGLOSSPIPELINE
           vec4 specularColor = texture2D(m_SpecularMap, newTexCoord);
           vec4 diffuseColor = albedo;

+ 4 - 4
jme3-core/src/main/resources/Common/MatDefs/Light/PBRLighting.vert

@@ -23,7 +23,7 @@ attribute vec3 inNormal;
 
 varying vec3 wNormal;
 varying vec3 wPosition;
-#ifdef NORMALMAP
+#if defined(NORMALMAP) || defined(PARALLAXMAP)
     attribute vec4 inTangent;
     varying vec3 wTangent;
     varying vec3 wBinormal;
@@ -33,7 +33,7 @@ void main(){
     vec4 modelSpacePos = vec4(inPosition, 1.0);
     vec3 modelSpaceNorm = inNormal;
 
-    #if  defined(NORMALMAP) && !defined(VERTEX_LIGHTING)
+    #if  ( defined(NORMALMAP) || defined(PARALLAXMAP)) && !defined(VERTEX_LIGHTING)
          vec3 modelSpaceTan  = inTangent.xyz;
     #endif
 
@@ -53,8 +53,8 @@ void main(){
 
     wPosition = TransformWorld(modelSpacePos).xyz;
     wNormal  = TransformWorld(vec4(modelSpaceNorm,0.0)).xyz;
-       
-    #if defined(NORMALMAP) 
+
+    #if defined(NORMALMAP) || defined(PARALLAXMAP)
       wTangent = TransformWorld(vec4(modelSpaceTan,0.0)).xyz;
       wBinormal = cross(wNormal, wTangent)* inTangent.w;            
     #endif

+ 157 - 0
jme3-examples/src/main/java/jme3test/material/TestParallaxPBR.java

@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2009-2012 jMonkeyEngine
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *   may be used to endorse or promote products derived from this software
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package jme3test.material;
+
+import com.jme3.app.SimpleApplication;
+import com.jme3.input.KeyInput;
+import com.jme3.input.controls.ActionListener;
+import com.jme3.input.controls.AnalogListener;
+import com.jme3.input.controls.KeyTrigger;
+import com.jme3.light.DirectionalLight;
+import com.jme3.material.Material;
+import com.jme3.math.*;
+import com.jme3.renderer.queue.RenderQueue.ShadowMode;
+import com.jme3.scene.Geometry;
+import com.jme3.scene.Node;
+import com.jme3.scene.Spatial;
+import com.jme3.scene.shape.Quad;
+import com.jme3.util.SkyFactory;
+import com.jme3.util.TangentBinormalGenerator;
+
+public class TestParallaxPBR extends SimpleApplication {
+
+    private Vector3f lightDir = new Vector3f(-1, -1, .5f).normalizeLocal();
+
+    public static void main(String[] args) {
+        TestParallaxPBR app = new TestParallaxPBR();
+        app.start();
+    }
+
+    public void setupSkyBox() {
+        rootNode.attachChild(SkyFactory.createSky(assetManager, "Scenes/Beach/FullskiesSunset0068.dds", false));
+    }
+    DirectionalLight dl;
+
+    public void setupLighting() {
+
+        dl = new DirectionalLight();
+        dl.setDirection(lightDir);
+        dl.setColor(new ColorRGBA(.9f, .9f, .9f, 1));
+        rootNode.addLight(dl);
+    }
+    Material mat;
+
+    public void setupFloor() {
+        mat = assetManager.loadMaterial("Textures/Terrain/BrickWall/BrickWallPBR.j3m");
+        //mat = assetManager.loadMaterial("Textures/Terrain/BrickWall/BrickWallPBR2.j3m");
+                
+        Node floorGeom = new Node("floorGeom");
+        Quad q = new Quad(100, 100);
+        q.scaleTextureCoordinates(new Vector2f(10, 10));
+        Geometry g = new Geometry("geom", q);
+        g.setLocalRotation(new Quaternion().fromAngleAxis(-FastMath.HALF_PI, Vector3f.UNIT_X));
+        floorGeom.attachChild(g);
+        
+        
+        TangentBinormalGenerator.generate(floorGeom);
+        floorGeom.setLocalTranslation(-50, 22, 60);
+        //floorGeom.setLocalScale(100);
+
+        floorGeom.setMaterial(mat);        
+        rootNode.attachChild(floorGeom);
+    }
+
+    public void setupSignpost() {
+        Spatial signpost = assetManager.loadModel("Models/Sign Post/Sign Post.mesh.xml");
+        Material mat = assetManager.loadMaterial("Models/Sign Post/Sign Post.j3m");
+        TangentBinormalGenerator.generate(signpost);
+        signpost.setMaterial(mat);
+        signpost.rotate(0, FastMath.HALF_PI, 0);
+        signpost.setLocalTranslation(12, 23.5f, 30);
+        signpost.setLocalScale(4);
+        signpost.setShadowMode(ShadowMode.CastAndReceive);
+        rootNode.attachChild(signpost);
+    }
+
+    @Override
+    public void simpleInitApp() {
+        cam.setLocation(new Vector3f(-15.445636f, 30.162927f, 60.252777f));
+        cam.setRotation(new Quaternion(0.05173137f, 0.92363626f, -0.13454558f, 0.35513034f));
+        flyCam.setMoveSpeed(30);
+
+
+        setupLighting();
+        setupSkyBox();
+        setupFloor();
+        setupSignpost();
+
+        inputManager.addListener(new AnalogListener() {
+
+            public void onAnalog(String name, float value, float tpf) {
+                if ("heightUP".equals(name)) {
+                    parallaxHeigh += 0.01;
+                    mat.setFloat("ParallaxHeight", parallaxHeigh);
+                }
+                if ("heightDown".equals(name)) {
+                    parallaxHeigh -= 0.01;
+                    parallaxHeigh = Math.max(parallaxHeigh, 0);
+                    mat.setFloat("ParallaxHeight", parallaxHeigh);
+                }
+
+            }
+        }, "heightUP", "heightDown");
+        inputManager.addMapping("heightUP", new KeyTrigger(KeyInput.KEY_I));
+        inputManager.addMapping("heightDown", new KeyTrigger(KeyInput.KEY_K));
+
+        inputManager.addListener(new ActionListener() {
+
+            public void onAction(String name, boolean isPressed, float tpf) {
+                if (isPressed && "toggleSteep".equals(name)) {
+                    steep = !steep;
+                    mat.setBoolean("SteepParallax", steep);
+                }
+            }
+        }, "toggleSteep");
+        inputManager.addMapping("toggleSteep", new KeyTrigger(KeyInput.KEY_SPACE));
+    }
+    float parallaxHeigh = 0.05f;
+    float time = 0;
+    boolean steep = false;
+
+    @Override
+    public void simpleUpdate(float tpf) {
+//        time+=tpf;
+//        lightDir.set(FastMath.sin(time), -1, FastMath.cos(time));
+//        bsr.setDirection(lightDir);
+//        dl.setDirection(lightDir);
+    }
+}

+ 9 - 0
jme3-testdata/src/main/resources/Textures/Terrain/BrickWall/BrickWallPBR.j3m

@@ -0,0 +1,9 @@
+Material Pong Rock PBR : Common/MatDefs/Light/PBRLighting.j3md {
+     MaterialParameters {
+         Roughness : 1.0
+         Metallic : 0.0
+         BaseColorMap : Repeat Textures/Terrain/BrickWall/BrickWall.jpg
+         NormalMap : Repeat Textures/Terrain/BrickWall/BrickWall_normal_parallax.dds
+         PackedNormalParallax: true
+     }
+}

+ 8 - 0
jme3-testdata/src/main/resources/Textures/Terrain/BrickWall/BrickWallPBR2.j3m

@@ -0,0 +1,8 @@
+Material Pong Rock PBR : Common/MatDefs/Light/PBRLighting.j3md {
+     MaterialParameters {
+         Roughness : 1.0
+         Metallic : 0.0
+         BaseColorMap : Repeat Textures/Terrain/BrickWall/BrickWall.jpg
+         ParallaxMap : Repeat Textures/Terrain/BrickWall/BrickWall_height.jpg         
+     }
+}