From b0ada38d21f6bd7303642ae2bf81382b3f96f636 Mon Sep 17 00:00:00 2001 From: "nor..67" Date: Fri, 24 Feb 2012 12:16:43 +0000 Subject: [PATCH] - move effects and networking to separate jar files git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9190 75d07b2b-3a1a-0410-a2c5-0572b91ccdca --- engine/build.xml | 36 +- engine/nbproject/build-impl.xml | 19 +- engine/nbproject/genfiles.properties | 4 +- engine/nbproject/project.properties | 249 ++-- engine/nbproject/project.xml | 1 + .../Common/MatDefs/Post/BloomExtract.j3md | 43 + .../Common/MatDefs/Post/BloomFinal.j3md | 36 + .../Common/MatDefs/Post/CartoonEdge.frag | 55 + .../Common/MatDefs/Post/CartoonEdge.j3md | 48 + .../Common/MatDefs/Post/CartoonEdge15.frag | 57 + .../Common/MatDefs/Post/CrossHatch.frag | 51 + .../Common/MatDefs/Post/CrossHatch.j3md | 41 + .../Common/MatDefs/Post/CrossHatch15.frag | 53 + .../Common/MatDefs/Post/DepthOfField.frag | 89 ++ .../Common/MatDefs/Post/DepthOfField.j3md | 25 + .../Common/MatDefs/Post/FXAA.frag | 88 ++ .../Common/MatDefs/Post/FXAA.j3md | 20 + .../Common/MatDefs/Post/FXAA.vert | 18 + .../Common/MatDefs/Post/Fade.frag | 11 + .../Common/MatDefs/Post/Fade.j3md | 34 + .../Common/MatDefs/Post/Fade15.frag | 11 + .../core-effects/Common/MatDefs/Post/Fog.frag | 21 + .../core-effects/Common/MatDefs/Post/Fog.j3md | 39 + .../Common/MatDefs/Post/Fog15.frag | 24 + .../Common/MatDefs/Post/GammaCorrection.frag | 23 + .../Common/MatDefs/Post/GammaCorrection.j3md | 39 + .../MatDefs/Post/GammaCorrection15.frag | 26 + .../Common/MatDefs/Post/LightScattering.frag | 36 + .../Common/MatDefs/Post/LightScattering.j3md | 41 + .../Common/MatDefs/Post/LightScattering.vert | 14 + .../MatDefs/Post/LightScattering15.frag | 39 + .../MatDefs/Post/LightScattering15.vert | 14 + .../Common/MatDefs/Post/Overlay.frag | 9 + .../Common/MatDefs/Post/Overlay.j3md | 36 + .../Common/MatDefs/Post/Overlay15.frag | 11 + .../Common/MatDefs/Post/Post.vert | 10 + .../Common/MatDefs/Post/Post15.vert | 12 + .../Common/MatDefs/Post/Posterization.frag | 18 + .../Common/MatDefs/Post/Posterization.j3md | 32 + .../Common/MatDefs/Post/Posterization15.frag | 20 + .../Common/MatDefs/Post/bloomExtract.frag | 29 + .../Common/MatDefs/Post/bloomExtract15.frag | 33 + .../Common/MatDefs/Post/bloomFinal.frag | 12 + .../Common/MatDefs/Post/bloomFinal15.frag | 15 + .../Common/MatDefs/SSAO/Textures/random.png | Bin 0 -> 42993 bytes .../Common/MatDefs/SSAO/normal.frag | 21 + .../Common/MatDefs/SSAO/normal.vert | 16 + .../Common/MatDefs/SSAO/ssao.frag | 104 ++ .../Common/MatDefs/SSAO/ssao.j3md | 51 + .../Common/MatDefs/SSAO/ssao15.frag | 96 ++ .../Common/MatDefs/SSAO/ssaoBlur.frag | 159 +++ .../Common/MatDefs/SSAO/ssaoBlur.j3md | 57 + .../Common/MatDefs/SSAO/ssaoBlur15.frag | 160 +++ .../Common/MatDefs/Water/SimpleWater.j3md | 34 + .../MatDefs/Water/Textures/caustics.jpg | Bin 0 -> 57225 bytes .../MatDefs/Water/Textures/dudv_map.jpg | Bin 0 -> 39633 bytes .../Common/MatDefs/Water/Textures/foam.jpg | Bin 0 -> 65823 bytes .../Common/MatDefs/Water/Textures/foam2.jpg | Bin 0 -> 80871 bytes .../Common/MatDefs/Water/Textures/foam3.jpg | Bin 0 -> 100447 bytes .../MatDefs/Water/Textures/heightmap.jpg | Bin 0 -> 24995 bytes .../Water/Textures/water_normalmap.dds | Bin 0 -> 32896 bytes .../Common/MatDefs/Water/Water.frag | 402 +++++++ .../Common/MatDefs/Water/Water.j3md | 90 ++ .../Common/MatDefs/Water/Water15.frag | 419 +++++++ .../Common/MatDefs/Water/simple_water.frag | 126 ++ .../Common/MatDefs/Water/simple_water.vert | 87 ++ .../com/jme3/post/filters/BloomFilter.java | 309 +++++ .../jme3/post/filters/CartoonEdgeFilter.java | 245 ++++ .../jme3/post/filters/ColorOverlayFilter.java | 111 ++ .../jme3/post/filters/CrossHatchFilter.java | 305 +++++ .../jme3/post/filters/DepthOfFieldFilter.java | 158 +++ .../com/jme3/post/filters/FXAAFilter.java | 95 ++ .../com/jme3/post/filters/FadeFilter.java | 177 +++ .../com/jme3/post/filters/FogFilter.java | 172 +++ .../post/filters/GammaCorrectionFilter.java | 78 ++ .../post/filters/LightScatteringFilter.java | 243 ++++ .../post/filters/PosterizationFilter.java | 147 +++ .../jme3/post/filters/RadialBlurFilter.java | 156 +++ .../post/filters/TranslucentBucketFilter.java | 80 ++ .../com/jme3/post/ssao/SSAOFilter.java | 324 +++++ .../com/jme3/water/ReflectionProcessor.java | 125 ++ .../com/jme3/water/SimpleWaterProcessor.java | 589 +++++++++ .../com/jme3/water/WaterFilter.java | 1050 +++++++++++++++++ 83 files changed, 7596 insertions(+), 132 deletions(-) create mode 100644 engine/src/core-effects/Common/MatDefs/Post/BloomExtract.j3md create mode 100644 engine/src/core-effects/Common/MatDefs/Post/BloomFinal.j3md create mode 100644 engine/src/core-effects/Common/MatDefs/Post/CartoonEdge.frag create mode 100644 engine/src/core-effects/Common/MatDefs/Post/CartoonEdge.j3md create mode 100644 engine/src/core-effects/Common/MatDefs/Post/CartoonEdge15.frag create mode 100644 engine/src/core-effects/Common/MatDefs/Post/CrossHatch.frag create mode 100644 engine/src/core-effects/Common/MatDefs/Post/CrossHatch.j3md create mode 100644 engine/src/core-effects/Common/MatDefs/Post/CrossHatch15.frag create mode 100644 engine/src/core-effects/Common/MatDefs/Post/DepthOfField.frag create mode 100644 engine/src/core-effects/Common/MatDefs/Post/DepthOfField.j3md create mode 100644 engine/src/core-effects/Common/MatDefs/Post/FXAA.frag create mode 100644 engine/src/core-effects/Common/MatDefs/Post/FXAA.j3md create mode 100644 engine/src/core-effects/Common/MatDefs/Post/FXAA.vert create mode 100644 engine/src/core-effects/Common/MatDefs/Post/Fade.frag create mode 100644 engine/src/core-effects/Common/MatDefs/Post/Fade.j3md create mode 100644 engine/src/core-effects/Common/MatDefs/Post/Fade15.frag create mode 100644 engine/src/core-effects/Common/MatDefs/Post/Fog.frag create mode 100644 engine/src/core-effects/Common/MatDefs/Post/Fog.j3md create mode 100644 engine/src/core-effects/Common/MatDefs/Post/Fog15.frag create mode 100644 engine/src/core-effects/Common/MatDefs/Post/GammaCorrection.frag create mode 100644 engine/src/core-effects/Common/MatDefs/Post/GammaCorrection.j3md create mode 100644 engine/src/core-effects/Common/MatDefs/Post/GammaCorrection15.frag create mode 100644 engine/src/core-effects/Common/MatDefs/Post/LightScattering.frag create mode 100644 engine/src/core-effects/Common/MatDefs/Post/LightScattering.j3md create mode 100644 engine/src/core-effects/Common/MatDefs/Post/LightScattering.vert create mode 100644 engine/src/core-effects/Common/MatDefs/Post/LightScattering15.frag create mode 100644 engine/src/core-effects/Common/MatDefs/Post/LightScattering15.vert create mode 100644 engine/src/core-effects/Common/MatDefs/Post/Overlay.frag create mode 100644 engine/src/core-effects/Common/MatDefs/Post/Overlay.j3md create mode 100644 engine/src/core-effects/Common/MatDefs/Post/Overlay15.frag create mode 100644 engine/src/core-effects/Common/MatDefs/Post/Post.vert create mode 100644 engine/src/core-effects/Common/MatDefs/Post/Post15.vert create mode 100644 engine/src/core-effects/Common/MatDefs/Post/Posterization.frag create mode 100644 engine/src/core-effects/Common/MatDefs/Post/Posterization.j3md create mode 100644 engine/src/core-effects/Common/MatDefs/Post/Posterization15.frag create mode 100644 engine/src/core-effects/Common/MatDefs/Post/bloomExtract.frag create mode 100644 engine/src/core-effects/Common/MatDefs/Post/bloomExtract15.frag create mode 100644 engine/src/core-effects/Common/MatDefs/Post/bloomFinal.frag create mode 100644 engine/src/core-effects/Common/MatDefs/Post/bloomFinal15.frag create mode 100644 engine/src/core-effects/Common/MatDefs/SSAO/Textures/random.png create mode 100644 engine/src/core-effects/Common/MatDefs/SSAO/normal.frag create mode 100644 engine/src/core-effects/Common/MatDefs/SSAO/normal.vert create mode 100644 engine/src/core-effects/Common/MatDefs/SSAO/ssao.frag create mode 100644 engine/src/core-effects/Common/MatDefs/SSAO/ssao.j3md create mode 100644 engine/src/core-effects/Common/MatDefs/SSAO/ssao15.frag create mode 100644 engine/src/core-effects/Common/MatDefs/SSAO/ssaoBlur.frag create mode 100644 engine/src/core-effects/Common/MatDefs/SSAO/ssaoBlur.j3md create mode 100644 engine/src/core-effects/Common/MatDefs/SSAO/ssaoBlur15.frag create mode 100644 engine/src/core-effects/Common/MatDefs/Water/SimpleWater.j3md create mode 100644 engine/src/core-effects/Common/MatDefs/Water/Textures/caustics.jpg create mode 100644 engine/src/core-effects/Common/MatDefs/Water/Textures/dudv_map.jpg create mode 100644 engine/src/core-effects/Common/MatDefs/Water/Textures/foam.jpg create mode 100644 engine/src/core-effects/Common/MatDefs/Water/Textures/foam2.jpg create mode 100644 engine/src/core-effects/Common/MatDefs/Water/Textures/foam3.jpg create mode 100644 engine/src/core-effects/Common/MatDefs/Water/Textures/heightmap.jpg create mode 100644 engine/src/core-effects/Common/MatDefs/Water/Textures/water_normalmap.dds create mode 100644 engine/src/core-effects/Common/MatDefs/Water/Water.frag create mode 100644 engine/src/core-effects/Common/MatDefs/Water/Water.j3md create mode 100644 engine/src/core-effects/Common/MatDefs/Water/Water15.frag create mode 100644 engine/src/core-effects/Common/MatDefs/Water/simple_water.frag create mode 100644 engine/src/core-effects/Common/MatDefs/Water/simple_water.vert create mode 100644 engine/src/core-effects/com/jme3/post/filters/BloomFilter.java create mode 100644 engine/src/core-effects/com/jme3/post/filters/CartoonEdgeFilter.java create mode 100644 engine/src/core-effects/com/jme3/post/filters/ColorOverlayFilter.java create mode 100644 engine/src/core-effects/com/jme3/post/filters/CrossHatchFilter.java create mode 100644 engine/src/core-effects/com/jme3/post/filters/DepthOfFieldFilter.java create mode 100644 engine/src/core-effects/com/jme3/post/filters/FXAAFilter.java create mode 100644 engine/src/core-effects/com/jme3/post/filters/FadeFilter.java create mode 100644 engine/src/core-effects/com/jme3/post/filters/FogFilter.java create mode 100644 engine/src/core-effects/com/jme3/post/filters/GammaCorrectionFilter.java create mode 100644 engine/src/core-effects/com/jme3/post/filters/LightScatteringFilter.java create mode 100644 engine/src/core-effects/com/jme3/post/filters/PosterizationFilter.java create mode 100644 engine/src/core-effects/com/jme3/post/filters/RadialBlurFilter.java create mode 100644 engine/src/core-effects/com/jme3/post/filters/TranslucentBucketFilter.java create mode 100644 engine/src/core-effects/com/jme3/post/ssao/SSAOFilter.java create mode 100644 engine/src/core-effects/com/jme3/water/ReflectionProcessor.java create mode 100644 engine/src/core-effects/com/jme3/water/SimpleWaterProcessor.java create mode 100644 engine/src/core-effects/com/jme3/water/WaterFilter.java diff --git a/engine/build.xml b/engine/build.xml index 0fa3c4604..69adcc6be 100644 --- a/engine/build.xml +++ b/engine/build.xml @@ -21,6 +21,8 @@ + + @@ -35,7 +37,7 @@ Compile Core @@ -44,6 +46,26 @@ + Compile Effects + + + + + + Compile Networking + + + + + Compile Plugins (Ogre, XML) @@ -163,6 +185,8 @@ Building Engine JAR files.. + + @@ -183,6 +207,8 @@ + + @@ -199,6 +225,8 @@ + + @@ -214,6 +242,8 @@ + + @@ -328,6 +358,7 @@ + @@ -385,6 +416,7 @@ + diff --git a/engine/nbproject/build-impl.xml b/engine/nbproject/build-impl.xml index b97ff9d66..ce1f28951 100644 --- a/engine/nbproject/build-impl.xml +++ b/engine/nbproject/build-impl.xml @@ -168,6 +168,7 @@ is divided into following sections: + @@ -251,6 +252,7 @@ is divided into following sections: Must set src.core.dir Must set src.core-data.dir + Must set src.core-effects.dir Must set src.core-plugins.dir Must set src.desktop.dir Must set src.terrain.dir @@ -289,7 +291,7 @@ is divided into following sections: - + @@ -329,7 +331,7 @@ is divided into following sections: - + @@ -361,7 +363,7 @@ is divided into following sections: - + @@ -659,13 +661,14 @@ is divided into following sections: - + + @@ -703,7 +706,7 @@ is divided into following sections: Must select some files in the IDE or set javac.includes - + @@ -929,6 +932,9 @@ is divided into following sections: + + + @@ -992,6 +998,9 @@ is divided into following sections: + + + diff --git a/engine/nbproject/genfiles.properties b/engine/nbproject/genfiles.properties index a8c608d9b..65b246953 100644 --- a/engine/nbproject/genfiles.properties +++ b/engine/nbproject/genfiles.properties @@ -3,8 +3,8 @@ build.xml.script.CRC32=34d4c2f2 build.xml.stylesheet.CRC32=958a1d3e # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=5d760efd -nbproject/build-impl.xml.script.CRC32=a73ff29f +nbproject/build-impl.xml.data.CRC32=ba8f4e88 +nbproject/build-impl.xml.script.CRC32=9dc03a5e nbproject/build-impl.xml.stylesheet.CRC32=0ae3a408@1.44.1.45 nbproject/profiler-build-impl.xml.data.CRC32=aff514c1 nbproject/profiler-build-impl.xml.script.CRC32=abda56ed diff --git a/engine/nbproject/project.properties b/engine/nbproject/project.properties index ea78bae08..2d3b36445 100644 --- a/engine/nbproject/project.properties +++ b/engine/nbproject/project.properties @@ -1,123 +1,126 @@ -annotation.processing.enabled=false -annotation.processing.enabled.in.editor=false -annotation.processing.run.all.processors=true -ant.customtasks.libs=JWSAntTasks -application.homepage=http://www.jmonkeyengine.com/ -application.title=jMonkeyEngine 3.0 -application.vendor=jMonkeyEngine -build.classes.dir=${build.dir}/classes -build.classes.excludes=**/*.java,**/*.form -# This directory is removed when the project is cleaned: -build.dir=build -build.generated.dir=${build.dir}/generated -build.generated.sources.dir=${build.dir}/generated-sources -# Only compile against the classpath explicitly listed here: -build.sysclasspath=ignore -build.test.classes.dir=${build.dir}/test/classes -build.test.results.dir=${build.dir}/test/results -# Uncomment to specify the preferred debugger connection transport: -#debug.transport=dt_socket -debug.classpath=\ - ${run.classpath} -debug.test.classpath=\ - ${run.test.classpath} -# This directory is removed when the project is cleaned: -dist.dir=dist -dist.jar=${dist.dir}/jMonkeyEngine3.jar -dist.javadoc.dir=${dist.dir}/javadoc -endorsed.classpath= -excludes= -file.reference.src-test-data=src/test-data -includes=** -jar.archive.disabled=${jnlp.enabled} -jar.compress=true -jar.index=${jnlp.enabled} -javac.classpath=\ - ${libs.jogg.classpath}:\ - ${libs.jbullet.classpath}:\ - ${libs.lwjgl.classpath}:\ - ${libs.niftygui1.3.classpath}:\ - ${libs.jme3-test-data.classpath}:\ - ${libs.android.classpath}:\ - ${libs.bullet.classpath} -# Space-separated list of extra javac options -javac.compilerargs= -javac.deprecation=false -javac.processorpath=\ - ${javac.classpath} -javac.source=1.5 -javac.target=1.5 -javac.test.classpath=\ - ${javac.classpath}:\ - ${build.classes.dir}:\ - ${libs.junit_4.classpath} -javadoc.additionalparam=-public -javadoc.author=false -javadoc.encoding=${source.encoding} -javadoc.noindex=false -javadoc.nonavbar=false -javadoc.notree=false -javadoc.private=false -javadoc.splitindex=true -javadoc.use=true -javadoc.version=false -javadoc.windowtitle=jMonkeyEngine3 -jaxbwiz.endorsed.dirs="${netbeans.home}/../ide12/modules/ext/jaxb/api" -jnlp.applet.class=jme3test.awt.AppHarness -jnlp.applet.height=300 -jnlp.applet.width=300 -jnlp.codebase.type=user -jnlp.codebase.user=http://jmonkeyengine.com/javawebstart/ -jnlp.descriptor=application -jnlp.enabled=false -jnlp.icon=/Users/normenhansen/Pictures/jme/icons/jme-logo48.png -jnlp.mixed.code=default -jnlp.offline-allowed=true -jnlp.signed=true -jnlp.signing=generated -jnlp.signing.alias= -jnlp.signing.keystore= -main.class=jme3test.TestChooser -manifest.file=MANIFEST.MF -meta.inf.dir=${src.dir}/META-INF -mkdist.disabled=false -platform.active=default_platform -run.classpath=\ - ${javac.classpath}:\ - ${build.classes.dir}:\ - ${build.dir}/core:\ - ${build.dir}/plugins:\ - ${build.dir}/jogg:\ - ${build.dir}/desktop:\ - ${build.dir}/blender:\ - ${build.dir}/terrain:\ - ${build.dir}/jbullet:\ - ${build.dir}/bullet:\ - ${build.dir}/niftygui:\ - ${build.dir}/lwjgl:\ - ${build.dir}/android -run.jvmargs=-Xms128m -Xmx128m -XX:MaxDirectMemorySize=256M -run.test.classpath=\ - ${javac.test.classpath}:\ - ${build.test.classes.dir} -source.encoding=UTF-8 -src.android.dir=src/android -src.blender.dir=src/blender -src.bullet-common.dir=src/bullet-common -src.bullet-native.dir=src/bullet-native -src.bullet.dir=src/bullet -src.core-data.dir=src/core-data -src.core-plugins.dir=src/core-plugins -src.core.dir=src/core -src.desktop.dir=src/desktop -src.jbullet.dir=src/jbullet -src.jogg.dir=src/jogg -src.lwjgl.dir=src/lwjgl -src.networking.dir=src\\networking -src.niftygui.dir=src/niftygui -src.ogre.dir=src/ogre -src.terrain.dir=src/terrain -src.test.dir=src/test -src.tools.dir=src/tools -src.xml.dir=src/xml -test.test.dir=test +annotation.processing.enabled=false +annotation.processing.enabled.in.editor=false +annotation.processing.run.all.processors=true +ant.customtasks.libs=JWSAntTasks +application.homepage=http://www.jmonkeyengine.com/ +application.title=jMonkeyEngine 3.0 +application.vendor=jMonkeyEngine +build.classes.dir=${build.dir}/classes +build.classes.excludes=**/*.java,**/*.form +# This directory is removed when the project is cleaned: +build.dir=build +build.generated.dir=${build.dir}/generated +build.generated.sources.dir=${build.dir}/generated-sources +# Only compile against the classpath explicitly listed here: +build.sysclasspath=ignore +build.test.classes.dir=${build.dir}/test/classes +build.test.results.dir=${build.dir}/test/results +# Uncomment to specify the preferred debugger connection transport: +#debug.transport=dt_socket +debug.classpath=\ + ${run.classpath} +debug.test.classpath=\ + ${run.test.classpath} +# This directory is removed when the project is cleaned: +dist.dir=dist +dist.jar=${dist.dir}/jMonkeyEngine3.jar +dist.javadoc.dir=${dist.dir}/javadoc +endorsed.classpath= +excludes= +file.reference.src-test-data=src/test-data +includes=** +jar.archive.disabled=${jnlp.enabled} +jar.compress=true +jar.index=${jnlp.enabled} +javac.classpath=\ + ${libs.jogg.classpath}:\ + ${libs.jbullet.classpath}:\ + ${libs.lwjgl.classpath}:\ + ${libs.niftygui1.3.classpath}:\ + ${libs.jme3-test-data.classpath}:\ + ${libs.android.classpath}:\ + ${libs.bullet.classpath} +# Space-separated list of extra javac options +javac.compilerargs= +javac.deprecation=false +javac.processorpath=\ + ${javac.classpath} +javac.source=1.5 +javac.target=1.5 +javac.test.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir}:\ + ${libs.junit_4.classpath} +javadoc.additionalparam=-public +javadoc.author=false +javadoc.encoding=${source.encoding} +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle=jMonkeyEngine3 +jaxbwiz.endorsed.dirs="${netbeans.home}/../ide12/modules/ext/jaxb/api" +jnlp.applet.class=jme3test.awt.AppHarness +jnlp.applet.height=300 +jnlp.applet.width=300 +jnlp.codebase.type=user +jnlp.codebase.user=http://jmonkeyengine.com/javawebstart/ +jnlp.descriptor=application +jnlp.enabled=false +jnlp.icon=/Users/normenhansen/Pictures/jme/icons/jme-logo48.png +jnlp.mixed.code=default +jnlp.offline-allowed=true +jnlp.signed=true +jnlp.signing=generated +jnlp.signing.alias= +jnlp.signing.keystore= +main.class=jme3test.TestChooser +manifest.file=MANIFEST.MF +meta.inf.dir=${src.dir}/META-INF +mkdist.disabled=false +platform.active=default_platform +run.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir}:\ + ${build.dir}/core:\ + ${build.dir}/effects:\ + ${build.dir}/networking:\ + ${build.dir}/plugins:\ + ${build.dir}/jogg:\ + ${build.dir}/desktop:\ + ${build.dir}/blender:\ + ${build.dir}/terrain:\ + ${build.dir}/jbullet:\ + ${build.dir}/bullet:\ + ${build.dir}/niftygui:\ + ${build.dir}/lwjgl:\ + ${build.dir}/android +run.jvmargs=-Xms128m -Xmx128m -XX:MaxDirectMemorySize=256M +run.test.classpath=\ + ${javac.test.classpath}:\ + ${build.test.classes.dir} +source.encoding=UTF-8 +src.android.dir=src/android +src.blender.dir=src/blender +src.bullet-common.dir=src/bullet-common +src.bullet-native.dir=src/bullet-native +src.bullet.dir=src/bullet +src.core-data.dir=src/core-data +src.core-effects.dir=src/core-effects +src.core-plugins.dir=src/core-plugins +src.core.dir=src/core +src.desktop.dir=src/desktop +src.jbullet.dir=src/jbullet +src.jogg.dir=src/jogg +src.lwjgl.dir=src/lwjgl +src.networking.dir=src/networking +src.niftygui.dir=src/niftygui +src.ogre.dir=src/ogre +src.terrain.dir=src/terrain +src.test.dir=src/test +src.tools.dir=src/tools +src.xml.dir=src/xml +test.test.dir=test diff --git a/engine/nbproject/project.xml b/engine/nbproject/project.xml index 29a6f2402..51772cf9c 100644 --- a/engine/nbproject/project.xml +++ b/engine/nbproject/project.xml @@ -13,6 +13,7 @@ + diff --git a/engine/src/core-effects/Common/MatDefs/Post/BloomExtract.j3md b/engine/src/core-effects/Common/MatDefs/Post/BloomExtract.j3md new file mode 100644 index 000000000..76614ccc7 --- /dev/null +++ b/engine/src/core-effects/Common/MatDefs/Post/BloomExtract.j3md @@ -0,0 +1,43 @@ +MaterialDef Bloom { + + MaterialParameters { + Int NumSamples + Texture2D Texture + Float ExposurePow + Float ExposureCutoff + Boolean Extract + Texture2D GlowMap + } + + Technique { + VertexShader GLSL150: Common/MatDefs/Post/Post15.vert + FragmentShader GLSL150: Common/MatDefs/Post/bloomExtract15.frag + + WorldParameters { + WorldViewProjectionMatrix + } + + Defines { + HAS_GLOWMAP : GlowMap + DO_EXTRACT : Extract + RESOLVE_MS : NumSamples + } + } + + Technique { + VertexShader GLSL100: Common/MatDefs/Post/Post.vert + FragmentShader GLSL100: Common/MatDefs/Post/bloomExtract.frag + + WorldParameters { + WorldViewProjectionMatrix + } + + Defines { + HAS_GLOWMAP : GlowMap + DO_EXTRACT : Extract + } + } + + Technique FixedFunc { + } +} \ No newline at end of file diff --git a/engine/src/core-effects/Common/MatDefs/Post/BloomFinal.j3md b/engine/src/core-effects/Common/MatDefs/Post/BloomFinal.j3md new file mode 100644 index 000000000..68f8c287d --- /dev/null +++ b/engine/src/core-effects/Common/MatDefs/Post/BloomFinal.j3md @@ -0,0 +1,36 @@ +MaterialDef Bloom Final { + + MaterialParameters { + Int NumSamples + Texture2D Texture + Texture2D BloomTex + Float BloomIntensity + } + + Technique { + VertexShader GLSL100: Common/MatDefs/Post/Post15.vert + FragmentShader GLSL150: Common/MatDefs/Post/bloomFinal15.frag + + WorldParameters { + WorldViewProjectionMatrix + } + + Defines { + RESOLVE_MS : NumSamples + } + } + + Technique { + VertexShader GLSL100: Common/MatDefs/Post/Post.vert + FragmentShader GLSL100: Common/MatDefs/Post/bloomFinal.frag + + WorldParameters { + WorldViewProjectionMatrix + } + } + + + + Technique FixedFunc { + } +} \ No newline at end of file diff --git a/engine/src/core-effects/Common/MatDefs/Post/CartoonEdge.frag b/engine/src/core-effects/Common/MatDefs/Post/CartoonEdge.frag new file mode 100644 index 000000000..7ee7f789f --- /dev/null +++ b/engine/src/core-effects/Common/MatDefs/Post/CartoonEdge.frag @@ -0,0 +1,55 @@ +uniform vec4 m_EdgeColor; + +uniform float m_EdgeWidth; +uniform float m_EdgeIntensity; + +uniform float m_NormalThreshold; +uniform float m_DepthThreshold; + +uniform float m_NormalSensitivity; +uniform float m_DepthSensitivity; + +varying vec2 texCoord; + +uniform sampler2D m_Texture; +uniform sampler2D m_NormalsTexture; +uniform sampler2D m_DepthTexture; + +uniform vec2 g_Resolution; + +vec4 fetchNormalDepth(vec2 tc){ + vec4 nd; + nd.xyz = texture2D(m_NormalsTexture, tc).rgb; + nd.w = texture2D(m_DepthTexture, tc).r; + return nd; +} + +void main(){ + vec3 color = texture2D(m_Texture, texCoord).rgb; + + vec2 edgeOffset = vec2(m_EdgeWidth) / g_Resolution; + + vec4 n1 = fetchNormalDepth(texCoord + vec2(-1.0, -1.0) * edgeOffset); + vec4 n2 = fetchNormalDepth(texCoord + vec2( 1.0, 1.0) * edgeOffset); + vec4 n3 = fetchNormalDepth(texCoord + vec2(-1.0, 1.0) * edgeOffset); + vec4 n4 = fetchNormalDepth(texCoord + vec2( 1.0, -1.0) * edgeOffset); + + // Work out how much the normal and depth values are changing. + vec4 diagonalDelta = abs(n1 - n2) + abs(n3 - n4); + + float normalDelta = dot(diagonalDelta.xyz, vec3(1.0)); + float depthDelta = diagonalDelta.w; + + // Filter out very small changes, in order to produce nice clean results. + normalDelta = clamp((normalDelta - m_NormalThreshold) * m_NormalSensitivity, 0.0, 1.0); + depthDelta = clamp((depthDelta - m_DepthThreshold) * m_DepthSensitivity, 0.0, 1.0); + + // Does this pixel lie on an edge? + float edgeAmount = clamp(normalDelta + depthDelta, 0.0, 1.0) * m_EdgeIntensity; + + // Apply the edge detection result to the main scene color. + //color *= (1.0 - edgeAmount); + color = mix (color,m_EdgeColor.rgb,edgeAmount); + + gl_FragColor = vec4(color, 1.0); +} \ No newline at end of file diff --git a/engine/src/core-effects/Common/MatDefs/Post/CartoonEdge.j3md b/engine/src/core-effects/Common/MatDefs/Post/CartoonEdge.j3md new file mode 100644 index 000000000..687193e8e --- /dev/null +++ b/engine/src/core-effects/Common/MatDefs/Post/CartoonEdge.j3md @@ -0,0 +1,48 @@ +MaterialDef Cartoon Edge { + + MaterialParameters { + Int NumSamples + Int NumSamplesDepth + Texture2D Texture + Texture2D NormalsTexture + Texture2D DepthTexture + Color EdgeColor + Float EdgeWidth + Float EdgeIntensity + Float NormalThreshold + Float DepthThreshold + Float NormalSensitivity + Float DepthSensitivity + } + + Technique { + VertexShader GLSL150: Common/MatDefs/Post/Post15.vert + FragmentShader GLSL150: Common/MatDefs/Post/CartoonEdge15.frag + + WorldParameters { + WorldViewProjectionMatrix + WorldViewMatrix + Resolution + } + + Defines { + RESOLVE_MS : NumSamples + RESOLVE_DEPTH_MS : NumSamplesDepth + } + } + + + Technique { + VertexShader GLSL100: Common/MatDefs/Post/Post.vert + FragmentShader GLSL100: Common/MatDefs/Post/CartoonEdge.frag + + WorldParameters { + WorldViewProjectionMatrix + WorldViewMatrix + Resolution + } + } + + Technique FixedFunc { + } +} \ No newline at end of file diff --git a/engine/src/core-effects/Common/MatDefs/Post/CartoonEdge15.frag b/engine/src/core-effects/Common/MatDefs/Post/CartoonEdge15.frag new file mode 100644 index 000000000..3c3921a98 --- /dev/null +++ b/engine/src/core-effects/Common/MatDefs/Post/CartoonEdge15.frag @@ -0,0 +1,57 @@ +#import "Common/ShaderLib/MultiSample.glsllib" + +uniform COLORTEXTURE m_Texture; +uniform DEPTHTEXTURE m_DepthTexture; + +uniform sampler2D m_NormalsTexture; +uniform vec2 g_Resolution; + +uniform vec4 m_EdgeColor; + +uniform float m_EdgeWidth; +uniform float m_EdgeIntensity; + +uniform float m_NormalThreshold; +uniform float m_DepthThreshold; + +uniform float m_NormalSensitivity; +uniform float m_DepthSensitivity; + +in vec2 texCoord; +out vec4 outFragColor; + +vec4 fetchNormalDepth(vec2 tc){ + vec4 nd; + nd.xyz = texture2D(m_NormalsTexture, tc).rgb; + nd.w = fetchTextureSample(m_DepthTexture, tc,0).r; + return nd; +} + +void main(){ + vec3 color = getColor(m_Texture, texCoord).rgb; + + vec2 edgeOffset = vec2(m_EdgeWidth) / textureSize(m_NormalsTexture, 0); + vec4 n1 = fetchNormalDepth(texCoord + vec2(-1.0, -1.0) * edgeOffset); + vec4 n2 = fetchNormalDepth(texCoord + vec2( 1.0, 1.0) * edgeOffset); + vec4 n3 = fetchNormalDepth(texCoord + vec2(-1.0, 1.0) * edgeOffset); + vec4 n4 = fetchNormalDepth(texCoord + vec2( 1.0, -1.0) * edgeOffset); + + // Work out how much the normal and depth values are changing. + vec4 diagonalDelta = abs(n1 - n2) + abs(n3 - n4); + + float normalDelta = dot(diagonalDelta.xyz, vec3(1.0)); + float depthDelta = diagonalDelta.w; + + // Filter out very small changes, in order to produce nice clean results. + normalDelta = clamp((normalDelta - m_NormalThreshold) * m_NormalSensitivity, 0.0, 1.0); + depthDelta = clamp((depthDelta - m_DepthThreshold) * m_DepthSensitivity, 0.0, 1.0); + + // Does this pixel lie on an edge? + float edgeAmount = clamp(normalDelta + depthDelta, 0.0, 1.0) * m_EdgeIntensity; + + // Apply the edge detection result to the main scene color. + //color *= (1.0 - edgeAmount); + color = mix (color,m_EdgeColor.rgb,edgeAmount); + + outFragColor = vec4(color, 1.0); +} diff --git a/engine/src/core-effects/Common/MatDefs/Post/CrossHatch.frag b/engine/src/core-effects/Common/MatDefs/Post/CrossHatch.frag new file mode 100644 index 000000000..fc700f883 --- /dev/null +++ b/engine/src/core-effects/Common/MatDefs/Post/CrossHatch.frag @@ -0,0 +1,51 @@ +uniform sampler2D m_Texture; +varying vec2 texCoord; + +uniform vec4 m_LineColor; +uniform vec4 m_PaperColor; +uniform float m_ColorInfluenceLine; +uniform float m_ColorInfluencePaper; + +uniform float m_FillValue; +uniform float m_Luminance1; +uniform float m_Luminance2; +uniform float m_Luminance3; +uniform float m_Luminance4; +uniform float m_Luminance5; + +uniform float m_LineDistance; +uniform float m_LineThickness; + +void main() { + vec4 texVal = texture2D(m_Texture, texCoord); + float linePixel = 0.0; + + float lum = texVal.r*0.2126 + texVal.g*0.7152 + texVal.b*0.0722; + + if (lum < m_Luminance1){ + if (mod(gl_FragCoord.x + gl_FragCoord.y, m_LineDistance * 2.0) < m_LineThickness) + linePixel = 1.0; + } + if (lum < m_Luminance2){ + if (mod(gl_FragCoord.x - gl_FragCoord.y, m_LineDistance * 2.0) < m_LineThickness) + linePixel = 1.0; + } + if (lum < m_Luminance3){ + if (mod(gl_FragCoord.x + gl_FragCoord.y - m_LineDistance, m_LineDistance) < m_LineThickness) + linePixel = 1.0; + } + if (lum < m_Luminance4){ + if (mod(gl_FragCoord.x - gl_FragCoord.y - m_LineDistance, m_LineDistance) < m_LineThickness) + linePixel = 1.0; + } + if (lum < m_Luminance5){ // No line, make a blob instead + linePixel = m_FillValue; + } + + // Mix line color with existing color information + vec4 lineColor = mix(m_LineColor, texVal, m_ColorInfluenceLine); + // Mix paper color with existing color information + vec4 paperColor = mix(m_PaperColor, texVal, m_ColorInfluencePaper); + + gl_FragColor = mix(paperColor, lineColor, linePixel); +} \ No newline at end of file diff --git a/engine/src/core-effects/Common/MatDefs/Post/CrossHatch.j3md b/engine/src/core-effects/Common/MatDefs/Post/CrossHatch.j3md new file mode 100644 index 000000000..bf850dc9f --- /dev/null +++ b/engine/src/core-effects/Common/MatDefs/Post/CrossHatch.j3md @@ -0,0 +1,41 @@ +MaterialDef CrossHatch { + + MaterialParameters { + Int NumSamples + Texture2D Texture; + Vector4 LineColor; + Vector4 PaperColor; + Float ColorInfluenceLine; + Float ColorInfluencePaper; + Float FillValue; + Float Luminance1; + Float Luminance2; + Float Luminance3; + Float Luminance4; + Float Luminance5; + Float LineThickness; + Float LineDistance; + } + + Technique { + VertexShader GLSL150: Common/MatDefs/Post/Post15.vert + FragmentShader GLSL150: Common/MatDefs/Post/CrossHatch15.frag + + WorldParameters { + WorldViewProjectionMatrix + } + } + + Technique { + VertexShader GLSL100: Common/MatDefs/Post/Post.vert + FragmentShader GLSL100: Common/MatDefs/Post/CrossHatch.frag + + WorldParameters { + WorldViewProjectionMatrix + } + } + + Technique FixedFunc { + } + +} \ No newline at end of file diff --git a/engine/src/core-effects/Common/MatDefs/Post/CrossHatch15.frag b/engine/src/core-effects/Common/MatDefs/Post/CrossHatch15.frag new file mode 100644 index 000000000..8daa4f7fd --- /dev/null +++ b/engine/src/core-effects/Common/MatDefs/Post/CrossHatch15.frag @@ -0,0 +1,53 @@ +#import "Common/ShaderLib/MultiSample.glsllib" + +uniform COLORTEXTURE m_Texture; +in vec2 texCoord; + +uniform vec4 m_LineColor; +uniform vec4 m_PaperColor; +uniform float m_ColorInfluenceLine; +uniform float m_ColorInfluencePaper; + +uniform float m_FillValue; +uniform float m_Luminance1; +uniform float m_Luminance2; +uniform float m_Luminance3; +uniform float m_Luminance4; +uniform float m_Luminance5; + +uniform float m_LineDistance; +uniform float m_LineThickness; + +void main() { + vec4 texVal = getColor(m_Texture, texCoord); + float linePixel = 0; + + float lum = texVal.r*0.2126 + texVal.g*0.7152 + texVal.b*0.0722; + + if (lum < m_Luminance1){ + if (mod(gl_FragCoord.x + gl_FragCoord.y, m_LineDistance * 2.0) < m_LineThickness) + linePixel = 1; + } + if (lum < m_Luminance2){ + if (mod(gl_FragCoord.x - gl_FragCoord.y, m_LineDistance * 2.0) < m_LineThickness) + linePixel = 1; + } + if (lum < m_Luminance3){ + if (mod(gl_FragCoord.x + gl_FragCoord.y - m_LineDistance, m_LineDistance) < m_LineThickness) + linePixel = 1; + } + if (lum < m_Luminance4){ + if (mod(gl_FragCoord.x - gl_FragCoord.y - m_LineDistance, m_LineDistance) < m_LineThickness) + linePixel = 1; + } + if (lum < m_Luminance5){ // No line, make a blob instead + linePixel = m_FillValue; + } + + // Mix line color with existing color information + vec4 lineColor = mix(m_LineColor, texVal, m_ColorInfluenceLine); + // Mix paper color with existing color information + vec4 paperColor = mix(m_PaperColor, texVal, m_ColorInfluencePaper); + + gl_FragColor = mix(paperColor, lineColor, linePixel); +} \ No newline at end of file diff --git a/engine/src/core-effects/Common/MatDefs/Post/DepthOfField.frag b/engine/src/core-effects/Common/MatDefs/Post/DepthOfField.frag new file mode 100644 index 000000000..658da546f --- /dev/null +++ b/engine/src/core-effects/Common/MatDefs/Post/DepthOfField.frag @@ -0,0 +1,89 @@ +uniform sampler2D m_Texture; +uniform sampler2D m_DepthTexture; +varying vec2 texCoord; + +uniform float m_FocusRange; +uniform float m_FocusDistance; +uniform float m_XScale; +uniform float m_YScale; + +vec2 m_NearFar = vec2( 0.1, 1000.0 ); + +void main() { + + vec4 texVal = texture2D( m_Texture, texCoord ); + + float zBuffer = texture2D( m_DepthTexture, texCoord ).r; + + // + // z_buffer_value = a + b / z; + // + // Where: + // a = zFar / ( zFar - zNear ) + // b = zFar * zNear / ( zNear - zFar ) + // z = distance from the eye to the object + // + // Which means: + // zb - a = b / z; + // z * (zb - a) = b + // z = b / (zb - a) + // + float a = m_NearFar.y / (m_NearFar.y - m_NearFar.x); + float b = m_NearFar.y * m_NearFar.x / (m_NearFar.x - m_NearFar.y); + float z = b / (zBuffer - a); + + // Above could be the same for any depth-based filter + + // We want to be purely focused right at + // m_FocusDistance and be purely unfocused + // at +/- m_FocusRange to either side of that. + float unfocus = min( 1.0, abs( z - m_FocusDistance ) / m_FocusRange ); + + if( unfocus < 0.2 ) { + // If we are mostly in focus then don't bother with the + // convolution filter + gl_FragColor = texVal; + } else { + // Perform a wide convolution filter and we scatter it + // a bit to avoid some texture look-ups. Instead of + // a full 5x5 (25-1 lookups) we'll skip every other one + // to only perform 12. + // 1 0 1 0 1 + // 0 1 0 1 0 + // 1 0 x 0 1 + // 0 1 0 1 0 + // 1 0 1 0 1 + // + // You can get away with 8 just around the outside but + // it looks more jittery to me. + + vec4 sum = vec4(0.0); + + float x = texCoord.x; + float y = texCoord.y; + + float xScale = m_XScale; + float yScale = m_YScale; + + // In order from lower left to right, depending on how you look at it + sum += texture2D( m_Texture, vec2(x - 2.0 * xScale, y - 2.0 * yScale) ); + sum += texture2D( m_Texture, vec2(x - 0.0 * xScale, y - 2.0 * yScale) ); + sum += texture2D( m_Texture, vec2(x + 2.0 * xScale, y - 2.0 * yScale) ); + sum += texture2D( m_Texture, vec2(x - 1.0 * xScale, y - 1.0 * yScale) ); + sum += texture2D( m_Texture, vec2(x + 1.0 * xScale, y - 1.0 * yScale) ); + sum += texture2D( m_Texture, vec2(x - 2.0 * xScale, y - 0.0 * yScale) ); + sum += texture2D( m_Texture, vec2(x + 2.0 * xScale, y - 0.0 * yScale) ); + sum += texture2D( m_Texture, vec2(x - 1.0 * xScale, y + 1.0 * yScale) ); + sum += texture2D( m_Texture, vec2(x + 1.0 * xScale, y + 1.0 * yScale) ); + sum += texture2D( m_Texture, vec2(x - 2.0 * xScale, y + 2.0 * yScale) ); + sum += texture2D( m_Texture, vec2(x - 0.0 * xScale, y + 2.0 * yScale) ); + sum += texture2D( m_Texture, vec2(x + 2.0 * xScale, y + 2.0 * yScale) ); + + sum = sum / 12.0; + + gl_FragColor = mix( texVal, sum, unfocus ); + + // I used this for debugging the range + // gl_FragColor.r = unfocus; +} +} \ No newline at end of file diff --git a/engine/src/core-effects/Common/MatDefs/Post/DepthOfField.j3md b/engine/src/core-effects/Common/MatDefs/Post/DepthOfField.j3md new file mode 100644 index 000000000..db30a0975 --- /dev/null +++ b/engine/src/core-effects/Common/MatDefs/Post/DepthOfField.j3md @@ -0,0 +1,25 @@ +MaterialDef Depth Of Field { + + MaterialParameters { + Int NumSamples + Int NumSamplesDepth + Texture2D Texture + Texture2D DepthTexture + Float FocusRange; + Float FocusDistance; + Float XScale; + Float YScale; + } + + Technique { + VertexShader GLSL100: Common/MatDefs/Post/Post.vert + FragmentShader GLSL100: Common/MatDefs/Post/DepthOfField.frag + + WorldParameters { + WorldViewProjectionMatrix + } + } + + Technique FixedFunc { + } +} \ No newline at end of file diff --git a/engine/src/core-effects/Common/MatDefs/Post/FXAA.frag b/engine/src/core-effects/Common/MatDefs/Post/FXAA.frag new file mode 100644 index 000000000..d630b3595 --- /dev/null +++ b/engine/src/core-effects/Common/MatDefs/Post/FXAA.frag @@ -0,0 +1,88 @@ +#extension GL_EXT_gpu_shader4 : enable + +uniform sampler2D m_Texture; +uniform vec2 g_Resolution; + +uniform float m_VxOffset; +uniform float m_SpanMax; +uniform float m_ReduceMul; + +varying vec2 texCoord; +varying vec4 posPos; + +#define FxaaTex(t, p) texture2D(t, p) + +#if __VERSION__ >= 130 + #define OffsetVec(a, b) ivec2(a, b) + #define FxaaTexOff(t, p, o, r) textureOffset(t, p, o) +#elif defined(GL_EXT_gpu_shader4) + #define OffsetVec(a, b) ivec2(a, b) + #define FxaaTexOff(t, p, o, r) texture2DLodOffset(t, p, 0.0, o) +#else + #define OffsetVec(a, b) vec2(a, b) + #define FxaaTexOff(t, p, o, r) texture2D(t, p + o * r) +#endif + +vec3 FxaaPixelShader( + vec4 posPos, // Output of FxaaVertexShader interpolated across screen. + sampler2D tex, // Input texture. + vec2 rcpFrame) // Constant {1.0/frameWidth, 1.0/frameHeight}. +{ + + #define FXAA_REDUCE_MIN (1.0/128.0) + //#define FXAA_REDUCE_MUL (1.0/8.0) + //#define FXAA_SPAN_MAX 8.0 + + vec3 rgbNW = FxaaTex(tex, posPos.zw).xyz; + vec3 rgbNE = FxaaTexOff(tex, posPos.zw, OffsetVec(1,0), rcpFrame.xy).xyz; + vec3 rgbSW = FxaaTexOff(tex, posPos.zw, OffsetVec(0,1), rcpFrame.xy).xyz; + vec3 rgbSE = FxaaTexOff(tex, posPos.zw, OffsetVec(1,1), rcpFrame.xy).xyz; + + vec3 rgbM = FxaaTex(tex, posPos.xy).xyz; + + vec3 luma = vec3(0.299, 0.587, 0.114); + float lumaNW = dot(rgbNW, luma); + float lumaNE = dot(rgbNE, luma); + float lumaSW = dot(rgbSW, luma); + float lumaSE = dot(rgbSE, luma); + float lumaM = dot(rgbM, luma); + + float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE))); + float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE))); + + vec2 dir; + dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE)); + dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE)); + + float dirReduce = max( + (lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * m_ReduceMul), + FXAA_REDUCE_MIN); + float rcpDirMin = 1.0/(min(abs(dir.x), abs(dir.y)) + dirReduce); + dir = min(vec2( m_SpanMax, m_SpanMax), + max(vec2(-m_SpanMax, -m_SpanMax), + dir * rcpDirMin)) * rcpFrame.xy; + + vec3 rgbA = (1.0/2.0) * ( + FxaaTex(tex, posPos.xy + dir * vec2(1.0/3.0 - 0.5)).xyz + + FxaaTex(tex, posPos.xy + dir * vec2(2.0/3.0 - 0.5)).xyz); + vec3 rgbB = rgbA * (1.0/2.0) + (1.0/4.0) * ( + FxaaTex(tex, posPos.xy + dir * vec2(0.0/3.0 - 0.5)).xyz + + FxaaTex(tex, posPos.xy + dir * vec2(3.0/3.0 - 0.5)).xyz); + + float lumaB = dot(rgbB, luma); + + if ((lumaB < lumaMin) || (lumaB > lumaMax)) + { + return rgbA; + } + else + { + return rgbB; + } +} + +void main() +{ + vec2 rcpFrame = vec2(1.0) / g_Resolution; + gl_FragColor = vec4(FxaaPixelShader(posPos, m_Texture, rcpFrame), 1.0); +} \ No newline at end of file diff --git a/engine/src/core-effects/Common/MatDefs/Post/FXAA.j3md b/engine/src/core-effects/Common/MatDefs/Post/FXAA.j3md new file mode 100644 index 000000000..66855850c --- /dev/null +++ b/engine/src/core-effects/Common/MatDefs/Post/FXAA.j3md @@ -0,0 +1,20 @@ +MaterialDef FXAA { + MaterialParameters { + Int NumSamples + Texture2D Texture + Float SubPixelShift + Float VxOffset + Float SpanMax + Float ReduceMul + } + Technique { + VertexShader GLSL100: Common/MatDefs/Post/FXAA.vert + FragmentShader GLSL100: Common/MatDefs/Post/FXAA.frag + WorldParameters { + WorldViewProjectionMatrix + Resolution + } + } + Technique FixedFunc { + } +} \ No newline at end of file diff --git a/engine/src/core-effects/Common/MatDefs/Post/FXAA.vert b/engine/src/core-effects/Common/MatDefs/Post/FXAA.vert new file mode 100644 index 000000000..2390384a7 --- /dev/null +++ b/engine/src/core-effects/Common/MatDefs/Post/FXAA.vert @@ -0,0 +1,18 @@ +uniform mat4 g_WorldViewProjectionMatrix; +uniform vec2 g_Resolution; + +uniform float m_SubPixelShift; + +attribute vec4 inPosition; +attribute vec2 inTexCoord; + +varying vec2 texCoord; +varying vec4 posPos; + +void main() { + gl_Position = inPosition * 2.0 - 1.0; //vec4(pos, 0.0, 1.0); + texCoord = inTexCoord; + vec2 rcpFrame = vec2(1.0) / g_Resolution; + posPos.xy = inTexCoord.xy; + posPos.zw = inTexCoord.xy - (rcpFrame * vec2(0.5 + m_SubPixelShift)); +} \ No newline at end of file diff --git a/engine/src/core-effects/Common/MatDefs/Post/Fade.frag b/engine/src/core-effects/Common/MatDefs/Post/Fade.frag new file mode 100644 index 000000000..b616239d0 --- /dev/null +++ b/engine/src/core-effects/Common/MatDefs/Post/Fade.frag @@ -0,0 +1,11 @@ +uniform sampler2D m_Texture; +varying vec2 texCoord; + +uniform float m_Value; + +void main() { + vec4 texVal = texture2D(m_Texture, texCoord); + + gl_FragColor = texVal * m_Value; + +} \ No newline at end of file diff --git a/engine/src/core-effects/Common/MatDefs/Post/Fade.j3md b/engine/src/core-effects/Common/MatDefs/Post/Fade.j3md new file mode 100644 index 000000000..e93b276b9 --- /dev/null +++ b/engine/src/core-effects/Common/MatDefs/Post/Fade.j3md @@ -0,0 +1,34 @@ +MaterialDef Fade { + + MaterialParameters { + Int NumSamples + Texture2D Texture + Float Value + } + + Technique { + VertexShader GLSL150: Common/MatDefs/Post/Post15.vert + FragmentShader GLSL150: Common/MatDefs/Post/Fade15.frag + + WorldParameters { + WorldViewProjectionMatrix + } + + Defines { + RESOLVE_MS : NumSamples + } + } + + Technique { + VertexShader GLSL100: Common/MatDefs/Post/Post.vert + FragmentShader GLSL100: Common/MatDefs/Post/Fade.frag + + WorldParameters { + WorldViewProjectionMatrix + } + } + + Technique FixedFunc { + } + +} \ No newline at end of file diff --git a/engine/src/core-effects/Common/MatDefs/Post/Fade15.frag b/engine/src/core-effects/Common/MatDefs/Post/Fade15.frag new file mode 100644 index 000000000..c99de34ad --- /dev/null +++ b/engine/src/core-effects/Common/MatDefs/Post/Fade15.frag @@ -0,0 +1,11 @@ +#import "Common/ShaderLib/MultiSample.glsllib" + +uniform COLORTEXTURE m_Texture; +uniform float m_Value; + +in vec2 texCoord; + +void main() { + vec4 texVal = getColor(m_Texture, texCoord); + gl_FragColor = texVal * m_Value; +} \ No newline at end of file diff --git a/engine/src/core-effects/Common/MatDefs/Post/Fog.frag b/engine/src/core-effects/Common/MatDefs/Post/Fog.frag new file mode 100644 index 000000000..7321b1516 --- /dev/null +++ b/engine/src/core-effects/Common/MatDefs/Post/Fog.frag @@ -0,0 +1,21 @@ +uniform sampler2D m_Texture; +uniform sampler2D m_DepthTexture; +varying vec2 texCoord; + +uniform vec4 m_FogColor; +uniform float m_FogDensity; +uniform float m_FogDistance; + +vec2 m_FrustumNearFar=vec2(1.0,m_FogDistance); +const float LOG2 = 1.442695; + +void main() { + vec4 texVal = texture2D(m_Texture, texCoord); + float fogVal =texture2D(m_DepthTexture,texCoord).r; + float depth= (2.0 * m_FrustumNearFar.x) / (m_FrustumNearFar.y + m_FrustumNearFar.x - fogVal* (m_FrustumNearFar.y-m_FrustumNearFar.x)); + + float fogFactor = exp2( -m_FogDensity * m_FogDensity * depth * depth * LOG2 ); + fogFactor = clamp(fogFactor, 0.0, 1.0); + gl_FragColor =mix(m_FogColor,texVal,fogFactor); + +} \ No newline at end of file diff --git a/engine/src/core-effects/Common/MatDefs/Post/Fog.j3md b/engine/src/core-effects/Common/MatDefs/Post/Fog.j3md new file mode 100644 index 000000000..e5d6c8db7 --- /dev/null +++ b/engine/src/core-effects/Common/MatDefs/Post/Fog.j3md @@ -0,0 +1,39 @@ +MaterialDef Fade { + + MaterialParameters { + Int NumSamples + Int NumSamplesDepth + Texture2D Texture + Texture2D DepthTexture + Vector4 FogColor; + Float FogDensity; + Float FogDistance; + } + + Technique { + VertexShader GLSL150: Common/MatDefs/Post/Post15.vert + FragmentShader GLSL150: Common/MatDefs/Post/Fog15.frag + + WorldParameters { + WorldViewProjectionMatrix + } + + Defines { + RESOLVE_MS : NumSamples + RESOLVE_DEPTH_MS : NumSamplesDepth + } + } + + Technique { + VertexShader GLSL100: Common/MatDefs/Post/Post.vert + FragmentShader GLSL100: Common/MatDefs/Post/Fog.frag + + WorldParameters { + WorldViewProjectionMatrix + } + } + + Technique FixedFunc { + } + +} \ No newline at end of file diff --git a/engine/src/core-effects/Common/MatDefs/Post/Fog15.frag b/engine/src/core-effects/Common/MatDefs/Post/Fog15.frag new file mode 100644 index 000000000..65a340723 --- /dev/null +++ b/engine/src/core-effects/Common/MatDefs/Post/Fog15.frag @@ -0,0 +1,24 @@ +#import "Common/ShaderLib/MultiSample.glsllib" + +uniform COLORTEXTURE m_Texture; +uniform DEPTHTEXTURE m_DepthTexture; + +uniform vec4 m_FogColor; +uniform float m_FogDensity; +uniform float m_FogDistance; + +in vec2 texCoord; + +vec2 m_FrustumNearFar=vec2(1.0,m_FogDistance); +const float LOG2 = 1.442695; + +void main() { + vec4 texVal = getColor(m_Texture, texCoord); + float fogVal = getDepth(m_DepthTexture,texCoord).r; + float depth= (2.0 * m_FrustumNearFar.x) / (m_FrustumNearFar.y + m_FrustumNearFar.x - fogVal* (m_FrustumNearFar.y-m_FrustumNearFar.x)); + + float fogFactor = exp2( -m_FogDensity * m_FogDensity * depth * depth * LOG2 ); + fogFactor = clamp(fogFactor, 0.0, 1.0); + gl_FragColor =mix(m_FogColor,texVal,fogFactor); + +} \ No newline at end of file diff --git a/engine/src/core-effects/Common/MatDefs/Post/GammaCorrection.frag b/engine/src/core-effects/Common/MatDefs/Post/GammaCorrection.frag new file mode 100644 index 000000000..90b2adedc --- /dev/null +++ b/engine/src/core-effects/Common/MatDefs/Post/GammaCorrection.frag @@ -0,0 +1,23 @@ +uniform sampler2D m_Texture; +varying vec2 texCoord; + +uniform float m_gamma; + +vec3 gamma(vec3 L,float gamma) +{ + return pow(L, vec3(1.0 / gamma)); +} + +void main() { + vec4 texVal = texture2D(m_Texture, texCoord); + + if(m_gamma > 0.0) + { + texVal.rgb = gamma(texVal.rgb , m_gamma); + } + #ifdef COMPUTE_LUMA + texVal.a = dot(texVal.rgb, vec3(0.299, 0.587, 0.114)); + #endif + + gl_FragColor = texVal; +} \ No newline at end of file diff --git a/engine/src/core-effects/Common/MatDefs/Post/GammaCorrection.j3md b/engine/src/core-effects/Common/MatDefs/Post/GammaCorrection.j3md new file mode 100644 index 000000000..b9c94c042 --- /dev/null +++ b/engine/src/core-effects/Common/MatDefs/Post/GammaCorrection.j3md @@ -0,0 +1,39 @@ +MaterialDef GammaCorrection { + + MaterialParameters { + Int NumSamples + Texture2D Texture + Float gamma + Boolean computeLuma + } + + Technique { + VertexShader GLSL150: Common/MatDefs/Post/Post15.vert + FragmentShader GLSL150: Common/MatDefs/Post/GammaCorrection15.frag + + WorldParameters { + WorldViewProjectionMatrix + } + + Defines { + COMPUTE_LUMA : computeLuma + } + } + + Technique { + VertexShader GLSL100: Common/MatDefs/Post/Post.vert + FragmentShader GLSL100: Common/MatDefs/Post/GammaCorrection.frag + + WorldParameters { + WorldViewProjectionMatrix + } + + Defines { + COMPUTE_LUMA : computeLuma + } + } + + Technique FixedFunc { + } + +} \ No newline at end of file diff --git a/engine/src/core-effects/Common/MatDefs/Post/GammaCorrection15.frag b/engine/src/core-effects/Common/MatDefs/Post/GammaCorrection15.frag new file mode 100644 index 000000000..b7861908a --- /dev/null +++ b/engine/src/core-effects/Common/MatDefs/Post/GammaCorrection15.frag @@ -0,0 +1,26 @@ +#import "Common/ShaderLib/MultiSample.glsllib" + +uniform COLORTEXTURE m_Texture; +in vec2 texCoord; + +uniform float m_gamma; + +vec3 gamma(vec3 L,float gamma) +{ + return pow(L, vec3(1.0 / gamma)); +} + +void main() { + vec4 texVal = texture2D(m_Texture, texCoord); + + if(m_gamma > 0.0) + { + texVal.rgb = gamma(texVal.rgb , m_gamma); + } + + #ifdef COMPUTE_LUMA + texVal.a = dot(texVal.rgb, vec3(0.299, 0.587, 0.114)); + #endif + + gl_FragColor = texVal; +} \ No newline at end of file diff --git a/engine/src/core-effects/Common/MatDefs/Post/LightScattering.frag b/engine/src/core-effects/Common/MatDefs/Post/LightScattering.frag new file mode 100644 index 000000000..683bbeaa7 --- /dev/null +++ b/engine/src/core-effects/Common/MatDefs/Post/LightScattering.frag @@ -0,0 +1,36 @@ +uniform sampler2D m_Texture; +uniform sampler2D m_DepthTexture; +uniform int m_NbSamples; +uniform float m_BlurStart; +uniform float m_BlurWidth; +uniform float m_LightDensity; +uniform bool m_Display; + +varying vec2 lightPos; +varying vec2 texCoord; + +void main(void) +{ + if(m_Display){ + + vec4 colorRes= texture2D(m_Texture,texCoord); + float factor=(m_BlurWidth/float(m_NbSamples-1.0)); + float scale; + vec2 texCoo=texCoord-lightPos; + vec2 scaledCoord; + vec4 res = vec4(0.0); + for(int i=0; i= m_ExposureCutoff ) { + color = pow(color, vec4(m_ExposurePow)); + }else{ + color = vec4(0.0); + } + #endif + + #ifdef HAS_GLOWMAP + vec4 glowColor = texture2D( m_GlowMap, texCoord ); + glowColor = pow(glowColor, vec4(m_ExposurePow)); + color += glowColor; + #endif + + outFragColor = color; +} diff --git a/engine/src/core-effects/Common/MatDefs/Post/bloomFinal.frag b/engine/src/core-effects/Common/MatDefs/Post/bloomFinal.frag new file mode 100644 index 000000000..9499e589c --- /dev/null +++ b/engine/src/core-effects/Common/MatDefs/Post/bloomFinal.frag @@ -0,0 +1,12 @@ +uniform sampler2D m_Texture; +uniform sampler2D m_BloomTex; +uniform float m_BloomIntensity; + +varying vec2 texCoord; + +void main(){ + vec4 colorRes = texture2D(m_Texture, texCoord); + vec4 bloom = texture2D(m_BloomTex, texCoord); + gl_FragColor = bloom * m_BloomIntensity + colorRes; +} + diff --git a/engine/src/core-effects/Common/MatDefs/Post/bloomFinal15.frag b/engine/src/core-effects/Common/MatDefs/Post/bloomFinal15.frag new file mode 100644 index 000000000..34268c565 --- /dev/null +++ b/engine/src/core-effects/Common/MatDefs/Post/bloomFinal15.frag @@ -0,0 +1,15 @@ +#import "Common/ShaderLib/MultiSample.glsllib" + +uniform COLORTEXTURE m_Texture; + +uniform sampler2D m_BloomTex; +uniform float m_BloomIntensity; + +in vec2 texCoord; + +void main(){ + vec4 colorRes = getColor(m_Texture,texCoord); + vec4 bloom = texture2D(m_BloomTex, texCoord); + gl_FragColor = bloom * m_BloomIntensity + colorRes; +} + diff --git a/engine/src/core-effects/Common/MatDefs/SSAO/Textures/random.png b/engine/src/core-effects/Common/MatDefs/SSAO/Textures/random.png new file mode 100644 index 0000000000000000000000000000000000000000..e19b7f5945eb0604e3cba80fb7e730fa67536a7e GIT binary patch literal 42993 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≪&aYB6xTC+2Vesn(hr8%4vr|IznMCH$kte87hQGO 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 literal 0 HcmV?d00001 diff --git a/engine/src/core-effects/Common/MatDefs/Water/Textures/dudv_map.jpg b/engine/src/core-effects/Common/MatDefs/Water/Textures/dudv_map.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a2734bbdf2b9c5e8d91e61b016dfdf4a450b4628 GIT binary patch literal 39633 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 Z$4;N6X~V50%9x{!m(K+B^{Q3_|Jm?L3oZZv literal 0 HcmV?d00001 diff --git a/engine/src/core-effects/Common/MatDefs/Water/Textures/foam2.jpg b/engine/src/core-effects/Common/MatDefs/Water/Textures/foam2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ef19b87088e15aa66b0fc836a7510fa0fe1cc6d2 GIT binary patch literal 80871 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 BMH2u3 literal 0 HcmV?d00001 diff --git a/engine/src/core-effects/Common/MatDefs/Water/Textures/water_normalmap.dds b/engine/src/core-effects/Common/MatDefs/Water/Textures/water_normalmap.dds new file mode 100644 index 0000000000000000000000000000000000000000..13582e148ce932a4b748ecf0759844cd440b5f18 GIT binary patch literal 32896 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 literal 0 HcmV?d00001 diff --git a/engine/src/core-effects/Common/MatDefs/Water/Water.frag b/engine/src/core-effects/Common/MatDefs/Water/Water.frag new file mode 100644 index 000000000..928ee2275 --- /dev/null +++ b/engine/src/core-effects/Common/MatDefs/Water/Water.frag @@ -0,0 +1,402 @@ +// Water pixel shader +// Copyright (C) JMonkeyEngine 3.0 +// by Remy Bouquet (nehon) for JMonkeyEngine 3.0 +// original HLSL version by Wojciech Toman 2009 + +uniform sampler2D m_HeightMap; +uniform sampler2D m_Texture; +uniform sampler2D m_DepthTexture; +uniform sampler2D m_NormalMap; +uniform sampler2D m_FoamMap; +uniform sampler2D m_CausticsMap; +uniform sampler2D m_ReflectionMap; + +uniform mat4 m_ViewProjectionMatrixInverse; +uniform mat4 m_TextureProjMatrix; +uniform vec3 m_CameraPosition; + +uniform float m_WaterHeight; +uniform float m_Time; +uniform float m_WaterTransparency; +uniform float m_NormalScale; +uniform float m_R0; +uniform float m_MaxAmplitude; +uniform vec3 m_LightDir; +uniform vec4 m_LightColor; +uniform float m_ShoreHardness; +uniform float m_FoamHardness; +uniform float m_RefractionStrength; +uniform vec3 m_FoamExistence; +uniform vec3 m_ColorExtinction; +uniform float m_Shininess; +uniform vec4 m_WaterColor; +uniform vec4 m_DeepWaterColor; +uniform vec2 m_WindDirection; +uniform float m_SunScale; +uniform float m_WaveScale; +uniform float m_UnderWaterFogDistance; +uniform float m_CausticsIntensity; + +vec2 scale = vec2(m_WaveScale, m_WaveScale); +float refractionScale = m_WaveScale; + +// Modifies 4 sampled normals. Increase first values to have more +// smaller "waves" or last to have more bigger "waves" +const vec4 normalModifier = vec4(3.0, 2.0, 4.0, 10.0); +// Strength of displacement along normal. +// Strength of displacement along normal. +uniform float m_ReflectionDisplace; +// Water transparency along eye vector. +const float visibility = 3.0; +// foam intensity +uniform float m_FoamIntensity ; + +varying vec2 texCoord; + +mat3 MatrixInverse(in mat3 inMatrix){ + float det = dot(cross(inMatrix[0], inMatrix[1]), inMatrix[2]); + mat3 T = transpose(inMatrix); + return mat3(cross(T[1], T[2]), + cross(T[2], T[0]), + cross(T[0], T[1])) / det; +} + + +mat3 computeTangentFrame(in vec3 N, in vec3 P, in vec2 UV) { + vec3 dp1 = dFdx(P); + vec3 dp2 = dFdy(P); + vec2 duv1 = dFdx(UV); + vec2 duv2 = dFdy(UV); + + // solve the linear system + mat3 M = mat3(dp1, dp2, cross(dp1, dp2)); + //vec3 dp1xdp2 = cross(dp1, dp2); + mat3 inverseM = MatrixInverse(M); + //mat2x3 inverseM = mat2x3(cross(dp2, dp1xdp2), cross(dp1xdp2, dp1)); + + vec3 T = inverseM * vec3(duv1.x, duv2.x, 0.0); + vec3 B = inverseM * vec3(duv1.y, duv2.y, 0.0); + + //vec3 T = inverseM * vec2(duv1.x, duv2.x); + //vec3 B = inverseM * vec2(duv1.y, duv2.y); + + // construct tangent frame + float maxLength = max(length(T), length(B)); + T = T / maxLength; + B = B / maxLength; + + //vec3 tangent = normalize(T); + //vec3 binormal = normalize(B); + + return mat3(T, B, N); +} + +float saturate(in float val){ + return clamp(val,0.0,1.0); +} + +vec3 saturate(in vec3 val){ + return clamp(val,vec3(0.0),vec3(1.0)); +} + + +vec3 getPosition(in float depth, in vec2 uv){ + vec4 pos = vec4(uv, depth, 1.0) * 2.0 - 1.0; + pos = m_ViewProjectionMatrixInverse * pos; + return pos.xyz / pos.w; +} + +// Function calculating fresnel term. +// - normal - normalized normal vector +// - eyeVec - normalized eye vector +float fresnelTerm(in vec3 normal,in vec3 eyeVec){ + float angle = 1.0 - saturate(dot(normal, eyeVec)); + float fresnel = angle * angle; + fresnel = fresnel * fresnel; + fresnel = fresnel * angle; + return saturate(fresnel * (1.0 - saturate(m_R0)) + m_R0 - m_RefractionStrength); +} + +vec2 m_FrustumNearFar=vec2(1.0,m_UnderWaterFogDistance); +const float LOG2 = 1.442695; + +vec4 underWater(){ + + + float sceneDepth = texture2D(m_DepthTexture, texCoord).r; + vec3 color2 = texture2D(m_Texture, texCoord).rgb; + + vec3 position = getPosition(sceneDepth, texCoord); + float level = m_WaterHeight; + + vec3 eyeVec = position - m_CameraPosition; + + // Find intersection with water surface + vec3 eyeVecNorm = normalize(eyeVec); + float t = (level - m_CameraPosition.y) / eyeVecNorm.y; + vec3 surfacePoint = m_CameraPosition + eyeVecNorm * t; + + vec2 texC = vec2(0.0); + + float cameraDepth = length(m_CameraPosition - surfacePoint); + texC = (surfacePoint.xz + eyeVecNorm.xz) * scale + m_Time * 0.03 * m_WindDirection; + float bias = texture2D(m_HeightMap, texC).r; + level += bias * m_MaxAmplitude; + t = (level - m_CameraPosition.y) / eyeVecNorm.y; + surfacePoint = m_CameraPosition + eyeVecNorm * t; + eyeVecNorm = normalize(m_CameraPosition - surfacePoint); + + // Find normal of water surface + float normal1 = texture2D(m_HeightMap, (texC + vec2(-1.0, 0.0) / 256.0)).r; + float normal2 = texture2D(m_HeightMap, (texC + vec2(1.0, 0.0) / 256.0)).r; + float normal3 = texture2D(m_HeightMap, (texC + vec2(0.0, -1.0) / 256.0)).r; + float normal4 = texture2D(m_HeightMap, (texC + vec2(0.0, 1.0) / 256.0)).r; + + vec3 myNormal = normalize(vec3((normal1 - normal2) * m_MaxAmplitude,m_NormalScale,(normal3 - normal4) * m_MaxAmplitude)); + vec3 normal = myNormal*-1.0; + float fresnel = fresnelTerm(normal, eyeVecNorm); + + vec3 refraction = color2; + #ifdef ENABLE_REFRACTION + texC = texCoord.xy *sin (fresnel+1.0); + refraction = texture2D(m_Texture, texC).rgb; + #endif + + float waterCol = saturate(length(m_LightColor.rgb) / m_SunScale); + refraction = mix(mix(refraction, m_DeepWaterColor.rgb * waterCol, m_WaterTransparency), m_WaterColor.rgb* waterCol,m_WaterTransparency); + + vec3 foam = vec3(0.0); + #ifdef ENABLE_FOAM + texC = (surfacePoint.xz + eyeVecNorm.xz * 0.1) * 0.05 + m_Time * 0.05 * m_WindDirection + sin(m_Time * 0.001 + position.x) * 0.005; + vec2 texCoord2 = (surfacePoint.xz + eyeVecNorm.xz * 0.1) * 0.05 + m_Time * 0.1 * m_WindDirection + sin(m_Time * 0.001 + position.z) * 0.005; + + if(m_MaxAmplitude - m_FoamExistence.z> 0.0001){ + foam += ((texture2D(m_FoamMap, texC) + texture2D(m_FoamMap, texCoord2)) * m_FoamIntensity * m_FoamIntensity * 0.3 * + saturate((level - (m_WaterHeight + m_FoamExistence.z)) / (m_MaxAmplitude - m_FoamExistence.z))).rgb; + } + foam *= m_LightColor.rgb; + #endif + + + + vec3 specular = vec3(0.0); + vec3 color ; + float fogFactor; + + if(position.y>level){ + #ifdef ENABLE_SPECULAR + if(step(0.9999,sceneDepth)==1.0){ + vec3 lightDir=normalize(m_LightDir); + vec3 mirrorEye = (2.0 * dot(eyeVecNorm, normal) * normal - eyeVecNorm); + float dotSpec = saturate(dot(mirrorEye.xyz, -lightDir) * 0.5 + 0.5); + specular = vec3((1.0 - fresnel) * saturate(-lightDir.y) * ((pow(dotSpec, 512.0)) * (m_Shininess * 1.8 + 0.2))); + specular += specular * 25.0 * saturate(m_Shininess - 0.05); + specular=specular * m_LightColor.rgb * 100.0; + } + #endif + float fogIntensity= 8.0 * m_WaterTransparency; + fogFactor = exp2( -fogIntensity * fogIntensity * cameraDepth * 0.03 * LOG2 ); + fogFactor = clamp(fogFactor, 0.0, 1.0); + color =mix(m_DeepWaterColor.rgb,refraction,fogFactor); + specular=specular*fogFactor; + color = saturate(color + max(specular, foam )); + }else{ + vec3 caustics = vec3(0.0); + #ifdef ENABLE_CAUSTICS + vec2 windDirection=m_WindDirection; + texC = (position.xz + eyeVecNorm.xz * 0.1) * 0.05 + m_Time * 0.05 * windDirection + sin(m_Time + position.x) * 0.01; + vec2 texCoord2 = (position.xz + eyeVecNorm.xz * 0.1) * 0.05 + m_Time * 0.05 * windDirection + sin(m_Time + position.z) * 0.01; + caustics += (texture2D(m_CausticsMap, texC)+ texture2D(m_CausticsMap, texCoord2)).rgb; + caustics=saturate(mix(m_WaterColor.rgb,caustics,m_CausticsIntensity)); + color=mix(color2,caustics,m_CausticsIntensity); + #else + color=color2; + #endif + + float fogDepth= (2.0 * m_FrustumNearFar.x) / (m_FrustumNearFar.y + m_FrustumNearFar.x - sceneDepth* (m_FrustumNearFar.y-m_FrustumNearFar.x)); + float fogIntensity= 18 * m_WaterTransparency; + fogFactor = exp2( -fogIntensity * fogIntensity * fogDepth * fogDepth * LOG2 ); + fogFactor = clamp(fogFactor, 0.0, 1.0); + color =mix(m_DeepWaterColor.rgb,color,fogFactor); + } + + return vec4(color, 1.0); +} + +void main(){ + float sceneDepth = texture2D(m_DepthTexture, texCoord).r; + float isAtFarPlane = step(0.99998, sceneDepth); + + vec3 color2 = texture2D(m_Texture, texCoord).rgb; + vec3 color = color2; + + vec3 position = getPosition(sceneDepth,texCoord); + + float level = m_WaterHeight; + + // If we are underwater let's go to under water function + if(level >= m_CameraPosition.y){ + gl_FragColor = underWater(); + return ; + } + + //#ifndef ENABLE_RIPPLES + // This optimization won't work on NVIDIA cards if ripples are enabled + if(position.y > level + m_MaxAmplitude + isAtFarPlane * 100.0){ + gl_FragColor = vec4(color2, 1.0); + return; + } + //#endif + + vec3 eyeVec = position - m_CameraPosition; + float diff = level - position.y; + float cameraDepth = m_CameraPosition.y - position.y; + + // Find intersection with water surface + vec3 eyeVecNorm = normalize(eyeVec); + float t = (level - m_CameraPosition.y) / eyeVecNorm.y; + vec3 surfacePoint = m_CameraPosition + eyeVecNorm * t; + + vec2 texC; + int samples = 1; + #ifdef ENABLE_HQ_SHORELINE + samples = 10; + #endif + float biasFactor = 1.0/samples; + for (int i = 0; i < samples; i++){ + texC = (surfacePoint.xz + eyeVecNorm.xz * biasFactor) * scale + m_Time * 0.03 * m_WindDirection; + + float bias = texture2D(m_HeightMap, texC).r; + + bias *= biasFactor; + level += bias * m_MaxAmplitude; + t = (level - m_CameraPosition.y) / eyeVecNorm.y; + surfacePoint = m_CameraPosition + eyeVecNorm * t; + } + + float depth = length(position - surfacePoint); + float depth2 = surfacePoint.y - position.y; + + // XXX: HACK ALERT: Increase water depth to infinity if at far plane + // Prevents "foam on horizon" issue + // For best results, replace the "100.0" below with the + // highest value in the m_ColorExtinction vec3 + depth += isAtFarPlane * 100.0; + depth2 += isAtFarPlane * 100.0; + + eyeVecNorm = normalize(m_CameraPosition - surfacePoint); + + // Find normal of water surface + float normal1 = texture2D(m_HeightMap, (texC + vec2(-1.0, 0.0) / 256.0)).r; + float normal2 = texture2D(m_HeightMap, (texC + vec2(1.0, 0.0) / 256.0)).r; + float normal3 = texture2D(m_HeightMap, (texC + vec2(0.0, -1.0) / 256.0)).r; + float normal4 = texture2D(m_HeightMap, (texC + vec2(0.0, 1.0) / 256.0)).r; + + vec3 myNormal = normalize(vec3((normal1 - normal2) * m_MaxAmplitude,m_NormalScale,(normal3 - normal4) * m_MaxAmplitude)); + vec3 normal = vec3(0.0); + + #ifdef ENABLE_RIPPLES + texC = surfacePoint.xz * 0.8 + m_WindDirection * m_Time* 1.6; + mat3 tangentFrame = computeTangentFrame(myNormal, eyeVecNorm, texC); + vec3 normal0a = normalize(tangentFrame*(2.0 * texture2D(m_NormalMap, texC).xyz - 1.0)); + + texC = surfacePoint.xz * 0.4 + m_WindDirection * m_Time* 0.8; + tangentFrame = computeTangentFrame(myNormal, eyeVecNorm, texC); + vec3 normal1a = normalize(tangentFrame*(2.0 * texture2D(m_NormalMap, texC).xyz - 1.0)); + + texC = surfacePoint.xz * 0.2 + m_WindDirection * m_Time * 0.4; + tangentFrame = computeTangentFrame(myNormal, eyeVecNorm, texC); + vec3 normal2a = normalize(tangentFrame*(2.0 * texture2D(m_NormalMap, texC).xyz - 1.0)); + + texC = surfacePoint.xz * 0.1 + m_WindDirection * m_Time * 0.2; + tangentFrame = computeTangentFrame(myNormal, eyeVecNorm, texC); + vec3 normal3a = normalize(tangentFrame*(2.0 * texture2D(m_NormalMap, texC).xyz - 1.0)); + + normal = normalize(normal0a * normalModifier.x + normal1a * normalModifier.y +normal2a * normalModifier.z + normal3a * normalModifier.w); + // XXX: Here's another way to fix the terrain edge issue, + // But it requires GLSL 1.3 and still looks kinda incorrect + // around edges + // To make the shader 1.2 compatible we use a trick : + // we clamp the x value of the normal and compare it to it's former value instead of using isnan. + normal = clamp(normal.x,0.0,1.0)!=normal.x ? myNormal : normal; + //if (position.y > level){ + // gl_FragColor = vec4(color2 + normal*0.0001, 1.0); + // return; + //} + #else + normal = myNormal; + #endif + + vec3 refraction = color2; + #ifdef ENABLE_REFRACTION + texC = texCoord.xy; + texC += sin(m_Time*1.8 + 3.0 * abs(position.y)) * (refractionScale * min(depth2, 1.0)); + refraction = texture2D(m_Texture, texC).rgb; + #endif + + vec3 waterPosition = surfacePoint.xyz; + waterPosition.y -= (level - m_WaterHeight); + vec4 texCoordProj = m_TextureProjMatrix * vec4(waterPosition, 1.0); + + texCoordProj.x = texCoordProj.x + m_ReflectionDisplace * normal.x; + texCoordProj.z = texCoordProj.z + m_ReflectionDisplace * normal.z; + texCoordProj /= texCoordProj.w; + texCoordProj.y = 1.0 - texCoordProj.y; + + vec3 reflection = texture2D(m_ReflectionMap, texCoordProj.xy).rgb; + + float fresnel = fresnelTerm(normal, eyeVecNorm); + + float depthN = depth * m_WaterTransparency; + float waterCol = saturate(length(m_LightColor.rgb) / m_SunScale); + refraction = mix(mix(refraction, m_WaterColor.rgb * waterCol, saturate(depthN / visibility)), + m_DeepWaterColor.rgb * waterCol, saturate(depth2 / m_ColorExtinction)); + + vec3 foam = vec3(0.0); + #ifdef ENABLE_FOAM + texC = (surfacePoint.xz + eyeVecNorm.xz * 0.1) * 0.05 + m_Time * 0.05 * m_WindDirection + sin(m_Time * 0.001 + position.x) * 0.005; + vec2 texCoord2 = (surfacePoint.xz + eyeVecNorm.xz * 0.1) * 0.05 + m_Time * 0.1 * m_WindDirection + sin(m_Time * 0.001 + position.z) * 0.005; + + if(depth2 < m_FoamExistence.x){ + foam = (texture2D(m_FoamMap, texC).r + texture2D(m_FoamMap, texCoord2)).rgb * m_FoamIntensity; + }else if(depth2 < m_FoamExistence.y){ + foam = mix((texture2D(m_FoamMap, texC) + texture2D(m_FoamMap, texCoord2)) * m_FoamIntensity, vec4(0.0), + (depth2 - m_FoamExistence.x) / (m_FoamExistence.y - m_FoamExistence.x)).rgb; + } + + if(m_MaxAmplitude - m_FoamExistence.z > 0.0001){ + foam += ((texture2D(m_FoamMap, texC) + texture2D(m_FoamMap, texCoord2)) * m_FoamIntensity * m_FoamIntensity * 0.3 * + saturate((level - (m_WaterHeight + m_FoamExistence.z)) / (m_MaxAmplitude - m_FoamExistence.z))).rgb; + } + foam *= m_LightColor.rgb; + #endif + + vec3 specular =vec3(0.0); + #ifdef ENABLE_SPECULAR + vec3 lightDir=normalize(m_LightDir); + vec3 mirrorEye = (2.0 * dot(eyeVecNorm, normal) * normal - eyeVecNorm); + float dotSpec = saturate(dot(mirrorEye.xyz, -lightDir) * 0.5 + 0.5); + specular = vec3((1.0 - fresnel) * saturate(-lightDir.y) * ((pow(dotSpec, 512.0)) * (m_Shininess * 1.8 + 0.2))); + specular += specular * 25.0 * saturate(m_Shininess - 0.05); + //foam does not shine + specular=specular * m_LightColor.rgb - (5.0 * foam); + #endif + + color = mix(refraction, reflection, fresnel); + color = mix(refraction, color, saturate(depth * m_ShoreHardness)); + color = saturate(color + max(specular, foam )); + color = mix(refraction, color, saturate(depth* m_FoamHardness)); + + + // XXX: HACK ALERT: + // We trick the GeForces to think they have + // to calculate the derivatives for all these pixels by using step()! + // That way we won't get pixels around the edges of the terrain, + // Where the derivatives are undefined + if(position.y > level){ + color = color2; + } + + gl_FragColor = vec4(color,1.0); + +} \ No newline at end of file diff --git a/engine/src/core-effects/Common/MatDefs/Water/Water.j3md b/engine/src/core-effects/Common/MatDefs/Water/Water.j3md new file mode 100644 index 000000000..160cadb98 --- /dev/null +++ b/engine/src/core-effects/Common/MatDefs/Water/Water.j3md @@ -0,0 +1,90 @@ +MaterialDef Advanced Water { + + MaterialParameters { + Int NumSamples + Int NumSamplesDepth + Texture2D FoamMap + Texture2D CausticsMap + Texture2D NormalMap + Texture2D ReflectionMap + Texture2D HeightMap + Texture2D Texture + Texture2D DepthTexture + Vector3 CameraPosition + Float Time + Vector3 frustumCorner + Matrix4 TextureProjMatrix + Matrix4 ViewProjectionMatrixInverse + Float WaterHeight + Vector3 LightDir + Float WaterTransparency + Float NormalScale + Float R0 + Float MaxAmplitude + Color LightColor + Float ShoreHardness + Float FoamHardness + Float RefractionStrength + Float WaveScale + Vector3 FoamExistence + Float SunScale + Vector3 ColorExtinction + Float Shininess + Color WaterColor + Color DeepWaterColor + Vector2 WindDirection + Float ReflectionDisplace + Float FoamIntensity + Float CausticsIntensity + Float UnderWaterFogDistance + + Boolean UseRipples + Boolean UseHQShoreline + Boolean UseSpecular + Boolean UseFoam + Boolean UseCaustics + Boolean UseRefraction + + } + + Technique { + VertexShader GLSL150 : Common/MatDefs/Post/Post15.vert + FragmentShader GLSL150 : Common/MatDefs/Water/Water15.frag + + WorldParameters { + WorldViewProjectionMatrix + } + + Defines { + RESOLVE_MS : NumSamples + RESOLVE_DEPTH_MS : NumSamplesDepth + ENABLE_RIPPLES : UseRipples + ENABLE_HQ_SHORELINE : UseHQShoreline + ENABLE_SPECULAR : UseSpecular + ENABLE_FOAM : UseFoam + ENABLE_CAUSTICS : UseCaustics + ENABLE_REFRACTION : UseRefraction + } + } + + Technique { + VertexShader GLSL100 : Common/MatDefs/Post/Post.vert + FragmentShader GLSL120 : Common/MatDefs/Water/Water.frag + + WorldParameters { + WorldViewProjectionMatrix + } + Defines { + ENABLE_RIPPLES : UseRipples + ENABLE_HQ_SHORELINE : UseHQShoreline + ENABLE_SPECULAR : UseSpecular + ENABLE_FOAM : UseFoam + ENABLE_CAUSTICS : UseCaustics + ENABLE_REFRACTION : UseRefraction + + } + } + + Technique FixedFunc { + } +} \ No newline at end of file diff --git a/engine/src/core-effects/Common/MatDefs/Water/Water15.frag b/engine/src/core-effects/Common/MatDefs/Water/Water15.frag new file mode 100644 index 000000000..64cf280de --- /dev/null +++ b/engine/src/core-effects/Common/MatDefs/Water/Water15.frag @@ -0,0 +1,419 @@ +#import "Common/ShaderLib/MultiSample.glsllib" + +// Water pixel shader +// Copyright (C) JMonkeyEngine 3.0 +// by Remy Bouquet (nehon) for JMonkeyEngine 3.0 +// original HLSL version by Wojciech Toman 2009 + +uniform COLORTEXTURE m_Texture; +uniform DEPTHTEXTURE m_DepthTexture; + + +uniform sampler2D m_HeightMap; +uniform sampler2D m_NormalMap; +uniform sampler2D m_FoamMap; +uniform sampler2D m_CausticsMap; +uniform sampler2D m_ReflectionMap; + +uniform mat4 m_ViewProjectionMatrixInverse; +uniform mat4 m_TextureProjMatrix; +uniform vec3 m_CameraPosition; + +uniform float m_WaterHeight; +uniform float m_Time; +uniform float m_WaterTransparency; +uniform float m_NormalScale; +uniform float m_R0; +uniform float m_MaxAmplitude; +uniform vec3 m_LightDir; +uniform vec4 m_LightColor; +uniform float m_ShoreHardness; +uniform float m_FoamHardness; +uniform float m_RefractionStrength; +uniform vec3 m_FoamExistence; +uniform vec3 m_ColorExtinction; +uniform float m_Shininess; +uniform vec4 m_WaterColor; +uniform vec4 m_DeepWaterColor; +uniform vec2 m_WindDirection; +uniform float m_SunScale; +uniform float m_WaveScale; +uniform float m_UnderWaterFogDistance; +uniform float m_CausticsIntensity; + + +vec2 scale = vec2(m_WaveScale, m_WaveScale); +float refractionScale = m_WaveScale; + +// Modifies 4 sampled normals. Increase first values to have more +// smaller "waves" or last to have more bigger "waves" +const vec4 normalModifier = vec4(3.0, 2.0, 4.0, 10.0); +// Strength of displacement along normal. +uniform float m_ReflectionDisplace; +// Water transparency along eye vector. +const float visibility = 3.0; +// foam intensity +uniform float m_FoamIntensity ; + +in vec2 texCoord; +out vec4 outFragColor; + +mat3 MatrixInverse(in mat3 inMatrix){ + float det = dot(cross(inMatrix[0], inMatrix[1]), inMatrix[2]); + mat3 T = transpose(inMatrix); + return mat3(cross(T[1], T[2]), + cross(T[2], T[0]), + cross(T[0], T[1])) / det; +} + + +mat3 computeTangentFrame(in vec3 N, in vec3 P, in vec2 UV) { + vec3 dp1 = dFdx(P); + vec3 dp2 = dFdy(P); + vec2 duv1 = dFdx(UV); + vec2 duv2 = dFdy(UV); + + // solve the linear system + vec3 dp1xdp2 = cross(dp1, dp2); + mat2x3 inverseM = mat2x3(cross(dp2, dp1xdp2), cross(dp1xdp2, dp1)); + + vec3 T = inverseM * vec2(duv1.x, duv2.x); + vec3 B = inverseM * vec2(duv1.y, duv2.y); + + // construct tangent frame + float maxLength = max(length(T), length(B)); + T = T / maxLength; + B = B / maxLength; + + return mat3(T, B, N); +} + +float saturate(in float val){ + return clamp(val,0.0,1.0); +} + +vec3 saturate(in vec3 val){ + return clamp(val,vec3(0.0),vec3(1.0)); +} + +vec3 getPosition(in float depth, in vec2 uv){ + vec4 pos = vec4(uv, depth, 1.0) * 2.0 - 1.0; + pos = m_ViewProjectionMatrixInverse * pos; + return pos.xyz / pos.w; +} + +// Function calculating fresnel term. +// - normal - normalized normal vector +// - eyeVec - normalized eye vector +float fresnelTerm(in vec3 normal,in vec3 eyeVec){ + float angle = 1.0 - max(0.0, dot(normal, eyeVec)); + float fresnel = angle * angle; + fresnel = fresnel * fresnel; + fresnel = fresnel * angle; + return saturate(fresnel * (1.0 - saturate(m_R0)) + m_R0 - m_RefractionStrength); +} + +vec2 m_FrustumNearFar=vec2(1.0,m_UnderWaterFogDistance); +const float LOG2 = 1.442695; + +vec4 underWater(int sampleNum){ + + + float sceneDepth = fetchTextureSample(m_DepthTexture, texCoord, sampleNum).r; + vec3 color2 = fetchTextureSample(m_Texture, texCoord, sampleNum).rgb; + + vec3 position = getPosition(sceneDepth, texCoord); + float level = m_WaterHeight; + + vec3 eyeVec = position - m_CameraPosition; + + // Find intersection with water surface + vec3 eyeVecNorm = normalize(eyeVec); + float t = (level - m_CameraPosition.y) / eyeVecNorm.y; + vec3 surfacePoint = m_CameraPosition + eyeVecNorm * t; + + vec2 texC = vec2(0.0); + + float cameraDepth = length(m_CameraPosition - surfacePoint); + texC = (surfacePoint.xz + eyeVecNorm.xz) * scale + m_Time * 0.03 * m_WindDirection; + float bias = texture(m_HeightMap, texC).r; + level += bias * m_MaxAmplitude; + t = (level - m_CameraPosition.y) / eyeVecNorm.y; + surfacePoint = m_CameraPosition + eyeVecNorm * t; + eyeVecNorm = normalize(m_CameraPosition - surfacePoint); + + // Find normal of water surface + float normal1 = textureOffset(m_HeightMap, texC, ivec2(-1.0, 0.0)).r; + float normal2 = textureOffset(m_HeightMap, texC, ivec2( 1.0, 0.0)).r; + float normal3 = textureOffset(m_HeightMap, texC, ivec2( 0.0, -1.0)).r; + float normal4 = textureOffset(m_HeightMap, texC, ivec2( 0.0, 1.0)).r; + + vec3 myNormal = normalize(vec3((normal1 - normal2) * m_MaxAmplitude,m_NormalScale,(normal3 - normal4) * m_MaxAmplitude)); + vec3 normal = myNormal*-1.0; + float fresnel = fresnelTerm(normal, eyeVecNorm); + + vec3 refraction = color2; + #ifdef ENABLE_REFRACTION + texC = texCoord.xy *sin (fresnel+1.0); + #ifdef RESOLVE_MS + ivec2 iTexC = ivec2(texC * textureSize(m_Texture)); + refraction = texelFetch(m_Texture, iTexC, sampleNum).rgb; + #else + ivec2 iTexC = ivec2(texC * textureSize(m_Texture, 0)); + refraction = texelFetch(m_Texture, iTexC, 0).rgb; + #endif + #endif + + float waterCol = saturate(length(m_LightColor.rgb) / m_SunScale); + refraction = mix(mix(refraction, m_DeepWaterColor.rgb * waterCol, m_WaterTransparency), m_WaterColor.rgb* waterCol,m_WaterTransparency); + + vec3 foam = vec3(0.0); + #ifdef ENABLE_FOAM + texC = (surfacePoint.xz + eyeVecNorm.xz * 0.1) * 0.05 + m_Time * 0.05 * m_WindDirection + sin(m_Time * 0.001 + position.x) * 0.005; + vec2 texCoord2 = (surfacePoint.xz + eyeVecNorm.xz * 0.1) * 0.05 + m_Time * 0.1 * m_WindDirection + sin(m_Time * 0.001 + position.z) * 0.005; + + if(m_MaxAmplitude - m_FoamExistence.z> 0.0001){ + foam += ((texture2D(m_FoamMap, texC) + texture2D(m_FoamMap, texCoord2)) * m_FoamIntensity * m_FoamIntensity * 0.3 * + saturate((level - (m_WaterHeight + m_FoamExistence.z)) / (m_MaxAmplitude - m_FoamExistence.z))).rgb; + } + foam *= m_LightColor.rgb; + #endif + + + + vec3 specular = vec3(0.0); + vec3 color ; + float fogFactor; + + if(position.y>level){ + #ifdef ENABLE_SPECULAR + if(step(0.9999,sceneDepth)==1.0){ + vec3 lightDir=normalize(m_LightDir); + vec3 mirrorEye = (2.0 * dot(eyeVecNorm, normal) * normal - eyeVecNorm); + float dotSpec = saturate(dot(mirrorEye.xyz, -lightDir) * 0.5 + 0.5); + specular = vec3((1.0 - fresnel) * saturate(-lightDir.y) * ((pow(dotSpec, 512.0)) * (m_Shininess * 1.8 + 0.2))); + specular += specular * 25.0 * saturate(m_Shininess - 0.05); + specular=specular * m_LightColor.rgb * 100.0; + } + #endif + float fogIntensity= 8.0 * m_WaterTransparency; + fogFactor = exp2( -fogIntensity * fogIntensity * cameraDepth * 0.03 * LOG2 ); + fogFactor = clamp(fogFactor, 0.0, 1.0); + color =mix(m_DeepWaterColor.rgb,refraction,fogFactor); + specular=specular*fogFactor; + color = saturate(color + max(specular, foam )); + }else{ + vec3 caustics = vec3(0.0); + #ifdef ENABLE_CAUSTICS + vec2 windDirection=m_WindDirection; + texC = (position.xz + eyeVecNorm.xz * 0.1) * 0.05 + m_Time * 0.05 * windDirection + sin(m_Time + position.x) * 0.01; + vec2 texCoord2 = (position.xz + eyeVecNorm.xz * 0.1) * 0.05 + m_Time * 0.05 * windDirection + sin(m_Time + position.z) * 0.01; + caustics += (texture2D(m_CausticsMap, texC)+ texture2D(m_CausticsMap, texCoord2)).rgb; + caustics=saturate(mix(m_WaterColor.rgb,caustics,m_CausticsIntensity)); + color=mix(color2,caustics,m_CausticsIntensity); + #else + color=color2; + #endif + + float fogDepth= (2.0 * m_FrustumNearFar.x) / (m_FrustumNearFar.y + m_FrustumNearFar.x - sceneDepth* (m_FrustumNearFar.y-m_FrustumNearFar.x)); + float fogIntensity= 18 * m_WaterTransparency; + fogFactor = exp2( -fogIntensity * fogIntensity * fogDepth * fogDepth * LOG2 ); + fogFactor = clamp(fogFactor, 0.0, 1.0); + color =mix(m_DeepWaterColor.rgb,color,fogFactor); + } + + return vec4(color, 1.0); +} +// NOTE: This will be called even for single-sampling +vec4 main_multiSample(int sampleNum){ + // If we are underwater let's call the underwater function + if(m_WaterHeight >= m_CameraPosition.y){ + + return underWater(sampleNum); + } + + float sceneDepth = fetchTextureSample(m_DepthTexture, texCoord, sampleNum).r; + vec3 color2 = fetchTextureSample(m_Texture, texCoord, sampleNum).rgb; + + vec3 color = color2; + vec3 position = getPosition(sceneDepth, texCoord); + + float level = m_WaterHeight; + + float isAtFarPlane = step(0.99998, sceneDepth); + //#ifndef ENABLE_RIPPLES + // This optimization won't work on NVIDIA cards if ripples are enabled + if(position.y > level + m_MaxAmplitude + isAtFarPlane * 100.0){ + + return vec4(color2, 1.0); + } + //#endif + + vec3 eyeVec = position - m_CameraPosition; + float cameraDepth = m_CameraPosition.y - position.y; + + // Find intersection with water surface + vec3 eyeVecNorm = normalize(eyeVec); + float t = (level - m_CameraPosition.y) / eyeVecNorm.y; + vec3 surfacePoint = m_CameraPosition + eyeVecNorm * t; + + vec2 texC = vec2(0.0); + int samples = 1; + #ifdef ENABLE_HQ_SHORELINE + samples = 10; + #endif + + float biasFactor = 1.0 / samples; + for (int i = 0; i < samples; i++){ + texC = (surfacePoint.xz + eyeVecNorm.xz * biasFactor) * scale + m_Time * 0.03 * m_WindDirection; + + float bias = texture(m_HeightMap, texC).r; + + bias *= biasFactor; + level += bias * m_MaxAmplitude; + t = (level - m_CameraPosition.y) / eyeVecNorm.y; + surfacePoint = m_CameraPosition + eyeVecNorm * t; + } + + float depth = length(position - surfacePoint); + float depth2 = surfacePoint.y - position.y; + + // XXX: HACK ALERT: Increase water depth to infinity if at far plane + // Prevents "foam on horizon" issue + // For best results, replace the "100.0" below with the + // highest value in the m_ColorExtinction vec3 + depth += isAtFarPlane * 100.0; + depth2 += isAtFarPlane * 100.0; + + eyeVecNorm = normalize(m_CameraPosition - surfacePoint); + + // Find normal of water surface + float normal1 = textureOffset(m_HeightMap, texC, ivec2(-1.0, 0.0)).r; + float normal2 = textureOffset(m_HeightMap, texC, ivec2( 1.0, 0.0)).r; + float normal3 = textureOffset(m_HeightMap, texC, ivec2( 0.0, -1.0)).r; + float normal4 = textureOffset(m_HeightMap, texC, ivec2( 0.0, 1.0)).r; + + vec3 myNormal = normalize(vec3((normal1 - normal2) * m_MaxAmplitude,m_NormalScale,(normal3 - normal4) * m_MaxAmplitude)); + vec3 normal = vec3(0.0); + + #ifdef ENABLE_RIPPLES + texC = surfacePoint.xz * 0.8 + m_WindDirection * m_Time* 1.6; + mat3 tangentFrame = computeTangentFrame(myNormal, eyeVecNorm, texC); + vec3 normal0a = normalize(tangentFrame*(2.0 * texture(m_NormalMap, texC).xyz - 1.0)); + + texC = surfacePoint.xz * 0.4 + m_WindDirection * m_Time* 0.8; + tangentFrame = computeTangentFrame(myNormal, eyeVecNorm, texC); + vec3 normal1a = normalize(tangentFrame*(2.0 * texture(m_NormalMap, texC).xyz - 1.0)); + + texC = surfacePoint.xz * 0.2 + m_WindDirection * m_Time * 0.4; + tangentFrame = computeTangentFrame(myNormal, eyeVecNorm, texC); + vec3 normal2a = normalize(tangentFrame*(2.0 * texture(m_NormalMap, texC).xyz - 1.0)); + + texC = surfacePoint.xz * 0.1 + m_WindDirection * m_Time * 0.2; + tangentFrame = computeTangentFrame(myNormal, eyeVecNorm, texC); + vec3 normal3a = normalize(tangentFrame*(2.0 * texture(m_NormalMap, texC).xyz - 1.0)); + + normal = normalize(normal0a * normalModifier.x + normal1a * normalModifier.y +normal2a * normalModifier.z + normal3a * normalModifier.w); + // XXX: Here's another way to fix the terrain edge issue, + // But it requires GLSL 1.3 and still looks kinda incorrect + // around edges + normal = isnan(normal.x) ? myNormal : normal; + //if (position.y > level){ + // gl_FragColor = vec4(color2 + normal*0.0001, 1.0); + // return; + //} + #else + normal = myNormal; + #endif + + vec3 refraction = color2; + #ifdef ENABLE_REFRACTION + // texC = texCoord.xy+ m_ReflectionDisplace * normal.x; + texC = texCoord.xy; + texC += sin(m_Time*1.8 + 3.0 * abs(position.y)) * (refractionScale * min(depth2, 1.0)); + #ifdef RESOLVE_MS + ivec2 iTexC = ivec2(texC * textureSize(m_Texture)); + refraction = texelFetch(m_Texture, iTexC, sampleNum).rgb; + #else + ivec2 iTexC = ivec2(texC * textureSize(m_Texture, 0)); + refraction = texelFetch(m_Texture, iTexC, 0).rgb; + #endif + #endif + + vec3 waterPosition = surfacePoint.xyz; + waterPosition.y -= (level - m_WaterHeight); + vec4 texCoordProj = m_TextureProjMatrix * vec4(waterPosition, 1.0); + + texCoordProj.x = texCoordProj.x + m_ReflectionDisplace * normal.x; + texCoordProj.z = texCoordProj.z + m_ReflectionDisplace * normal.z; + texCoordProj /= texCoordProj.w; + texCoordProj.y = 1.0 - texCoordProj.y; + + vec3 reflection = texture(m_ReflectionMap, texCoordProj.xy).rgb; + + float fresnel = fresnelTerm(normal, eyeVecNorm); + + float depthN = depth * m_WaterTransparency; + float waterCol = saturate(length(m_LightColor.rgb) / m_SunScale); + refraction = mix(mix(refraction, m_WaterColor.rgb * waterCol, saturate(depthN / visibility)), + m_DeepWaterColor.rgb * waterCol, saturate(depth2 / m_ColorExtinction)); + + + + + vec3 foam = vec3(0.0); + #ifdef ENABLE_FOAM + texC = (surfacePoint.xz + eyeVecNorm.xz * 0.1) * 0.05 + m_Time * 0.05 * m_WindDirection + sin(m_Time * 0.001 + position.x) * 0.005; + vec2 texCoord2 = (surfacePoint.xz + eyeVecNorm.xz * 0.1) * 0.05 + m_Time * 0.1 * m_WindDirection + sin(m_Time * 0.001 + position.z) * 0.005; + + if(depth2 < m_FoamExistence.x){ + foam = (texture2D(m_FoamMap, texC).r + texture2D(m_FoamMap, texCoord2)).rgb * vec3(m_FoamIntensity); + }else if(depth2 < m_FoamExistence.y){ + foam = mix((texture2D(m_FoamMap, texC) + texture2D(m_FoamMap, texCoord2)) * m_FoamIntensity , vec4(0.0), + (depth2 - m_FoamExistence.x) / (m_FoamExistence.y - m_FoamExistence.x)).rgb; + } + + + if(m_MaxAmplitude - m_FoamExistence.z> 0.0001){ + foam += ((texture2D(m_FoamMap, texC) + texture2D(m_FoamMap, texCoord2)) * m_FoamIntensity * m_FoamIntensity * 0.3 * + saturate((level - (m_WaterHeight + m_FoamExistence.z)) / (m_MaxAmplitude - m_FoamExistence.z))).rgb; + } + foam *= m_LightColor.rgb; + #endif + + vec3 specular = vec3(0.0); + #ifdef ENABLE_SPECULAR + vec3 lightDir=normalize(m_LightDir); + vec3 mirrorEye = (2.0 * dot(eyeVecNorm, normal) * normal - eyeVecNorm); + float dotSpec = saturate(dot(mirrorEye.xyz, -lightDir) * 0.5 + 0.5); + specular = vec3((1.0 - fresnel) * saturate(-lightDir.y) * ((pow(dotSpec, 512.0)) * (m_Shininess * 1.8 + 0.2))); + specular += specular * 25.0 * saturate(m_Shininess - 0.05); + //foam does not shine + specular=specular * m_LightColor.rgb - (5.0 * foam); + #endif + + color = mix(refraction, reflection, fresnel); + color = mix(refraction, color, saturate(depth * m_ShoreHardness)); + color = saturate(color + max(specular, foam )); + color = mix(refraction, color, saturate(depth* m_FoamHardness)); + + + // XXX: HACK ALERT: + // We trick the GeForces to think they have + // to calculate the derivatives for all these pixels by using step()! + // That way we won't get pixels around the edges of the terrain, + // Where the derivatives are undefined + return vec4(mix(color, color2, step(level, position.y)), 1.0); +} + +void main(){ + #ifdef RESOLVE_MS + vec4 color = vec4(0.0); + for (int i = 0; i < m_NumSamples; i++){ + color += main_multiSample(i); + } + outFragColor = color / m_NumSamples; + #else + outFragColor = main_multiSample(0); + #endif +} \ No newline at end of file diff --git a/engine/src/core-effects/Common/MatDefs/Water/simple_water.frag b/engine/src/core-effects/Common/MatDefs/Water/simple_water.frag new file mode 100644 index 000000000..65a9c991c --- /dev/null +++ b/engine/src/core-effects/Common/MatDefs/Water/simple_water.frag @@ -0,0 +1,126 @@ +/* +GLSL conversion of Michael Horsch water demo +http://www.bonzaisoftware.com/wfs.html +Converted by Mars_999 +8/20/2005 +*/ + +uniform sampler2D m_water_normalmap; +uniform sampler2D m_water_reflection; +uniform sampler2D m_water_refraction; +uniform sampler2D m_water_dudvmap; +uniform sampler2D m_water_depthmap; +uniform vec4 m_waterColor; +uniform float m_waterDepth; +uniform vec4 m_distortionScale; +uniform vec4 m_distortionMix; +uniform vec4 m_texScale; +uniform vec2 m_FrustumNearFar; +uniform float m_waterTransparency; + + + +varying vec4 lightDir; //lightpos +varying vec4 waterTex1; //moving texcoords +varying vec4 waterTex2; //moving texcoords +varying vec4 position; //for projection +varying vec4 viewDir; //viewts +varying vec4 viewLightDir; +varying vec4 viewCamDir; + +//unit 0 = m_water_reflection +//unit 1 = m_water_refraction +//unit 2 = m_water_normalmap +//unit 3 = m_water_dudvmap +//unit 4 = m_water_depthmap + + const vec4 two = vec4(2.0, 2.0, 2.0, 1.0); + const vec4 mone = vec4(-1.0, -1.0, -1.0, 1.0); + + const vec4 ofive = vec4(0.5,0.5,0.5,1.0); + + const float exponent = 64.0; + +float tangDot(in vec3 v1, in vec3 v2){ + float d = dot(v1,v2); + #ifdef V_TANGENT + d = 1.0 - d*d; + return step(0.0, d) * sqrt(d); + #else + return d; + #endif +} + +vec4 readDepth(vec2 uv){ + float depth= (2.0 * m_FrustumNearFar.x) / (m_FrustumNearFar.y + m_FrustumNearFar.x - texture2D(m_water_depthmap, uv).r* (m_FrustumNearFar.y-m_FrustumNearFar.x)); + return vec4( depth); +} + +void main(void) +{ + + + vec4 lightTS = normalize(lightDir); + vec4 viewt = normalize(viewDir); + vec4 disdis = texture2D(m_water_dudvmap, vec2(waterTex2 * m_texScale)); + vec4 fdist = texture2D(m_water_dudvmap, vec2(waterTex1 + disdis*m_distortionMix)); + fdist =normalize( fdist * 2.0 - 1.0)* m_distortionScale; + + + //load normalmap + vec4 nmap = texture2D(m_water_normalmap, vec2(waterTex1 + disdis*m_distortionMix)); + nmap = (nmap-ofive) * two; + // nmap = nmap*2.0-1.0; + vec4 vNorm = normalize(nmap); + + + vec4 projCoord = position / position.w; + projCoord =(projCoord+1.0)*0.5 + fdist; + projCoord = clamp(projCoord, 0.001, 0.999); + + //load reflection,refraction and depth texture + vec4 refl = texture2D(m_water_reflection, vec2(projCoord.x,1.0-projCoord.y)); + vec4 refr = texture2D(m_water_refraction, vec2(projCoord)); + vec4 wdepth =readDepth(vec2(projCoord)); + + wdepth = vec4(pow(wdepth.x, m_waterDepth)); + vec4 invdepth = 1.0 - wdepth; + + + // Blinn - Phong + // vec4 H = (viewt - lightTS); + // vec4 specular =vec4(pow(max(dot(H, vNorm), 0.0), exponent)); + +// Standard Phong + + // vec4 R =reflect(-L, vNorm); + // vec4 specular =vec4( pow(max(dot(R, E), 0.0),exponent)); + + + //calculate specular highlight + vec4 L=normalize(viewLightDir); + vec4 E=normalize(viewCamDir); + vec4 vRef = normalize(reflect(-L,vNorm)); + float stemp =max(0.0, dot( vRef,E) ); + //initializing to 0 to avoid artifacts on old intel cards + vec4 specular = vec4(0.0,0.0,0.0,0.0); + if(stemp>0.0){ + stemp = pow(stemp, exponent); + specular = vec4(stemp); + } + + + + vec4 fresnelTerm = vec4(0.02+0.97*pow((1.0-dot(normalize(viewt), vNorm)),5.0)); + + + + fresnelTerm=fresnelTerm*invdepth*m_waterTransparency; + fresnelTerm=clamp(fresnelTerm,0.0,1.0); + + refr*=(fresnelTerm); + refr *= invdepth; + refr= refr+ m_waterColor*wdepth*fresnelTerm; + + gl_FragColor =(refr+ refl*(1.0-fresnelTerm))+specular; +} diff --git a/engine/src/core-effects/Common/MatDefs/Water/simple_water.vert b/engine/src/core-effects/Common/MatDefs/Water/simple_water.vert new file mode 100644 index 000000000..e6052d8d5 --- /dev/null +++ b/engine/src/core-effects/Common/MatDefs/Water/simple_water.vert @@ -0,0 +1,87 @@ +/* +GLSL conversion of Michael Horsch water demo +http://www.bonzaisoftware.com/wfs.html +Converted by Mars_999 +8/20/2005 +*/ +uniform vec3 m_lightPos; +uniform float m_time; + +uniform mat4 g_WorldViewProjectionMatrix; +uniform mat4 g_WorldViewMatrix; +uniform mat4 g_ViewMatrix; +uniform vec3 g_CameraPosition; +uniform mat3 g_NormalMatrix; + +attribute vec4 inPosition; +attribute vec2 inTexCoord; +attribute vec3 inTangent; +attribute vec3 inNormal; + +varying vec4 lightDir; +varying vec4 waterTex1; +varying vec4 waterTex2; +varying vec4 position; +varying vec4 viewDir; +varying vec4 viewpos; +varying vec4 viewLightDir; +varying vec4 viewCamDir; + + +//unit 0 = water_reflection +//unit 1 = water_refraction +//unit 2 = water_normalmap +//unit 3 = water_dudvmap +//unit 4 = water_depthmap + +void main(void) +{ + viewpos.x = g_CameraPosition.x; + viewpos.y = g_CameraPosition.y; + viewpos.z = g_CameraPosition.z; + viewpos.w = 1.0; + + vec4 temp; + vec4 tangent = vec4(1.0, 0.0, 0.0, 0.0); + vec4 norm = vec4(0.0, 1.0, 0.0, 0.0); + vec4 binormal = vec4(0.0, 0.0, 1.0, 0.0); + + + temp = viewpos - inPosition; + + viewDir.x = dot(temp, tangent); + viewDir.y = dot(temp, binormal); + viewDir.z = dot(temp, norm); + viewDir.w = 0.0; + + temp = vec4(m_lightPos,1.0)- inPosition; + lightDir.x = dot(temp, tangent); + lightDir.y = dot(temp, binormal); + lightDir.z = dot(temp, norm); + lightDir.w = 0.0; + + vec4 viewSpaceLightPos=g_ViewMatrix*vec4(m_lightPos,1.0); + vec4 viewSpacePos=g_WorldViewMatrix*inPosition; + vec3 wvNormal = normalize(g_NormalMatrix * inNormal); + vec3 wvTangent = normalize(g_NormalMatrix * inTangent); + vec3 wvBinormal = cross(wvNormal, wvTangent); + mat3 tbnMat = mat3(wvTangent, wvBinormal, wvNormal); + + temp = viewSpaceLightPos - viewSpacePos; + viewLightDir.xyz=temp.xyz*tbnMat; + viewLightDir.w = 0.0; + + temp = -viewSpacePos; + viewCamDir.xyz =temp.xyz*tbnMat; + viewCamDir.w = 0.0; + + + vec4 t1 = vec4(0.0, -m_time, 0.0,0.0); + vec4 t2 = vec4(0.0, m_time, 0.0,0.0); + + waterTex1 =vec4(inTexCoord,0.0,0.0) + t1; + waterTex2 =vec4(inTexCoord ,0.0,0.0)+ t2; + + position = g_WorldViewProjectionMatrix * inPosition; + gl_Position = position; +} diff --git a/engine/src/core-effects/com/jme3/post/filters/BloomFilter.java b/engine/src/core-effects/com/jme3/post/filters/BloomFilter.java new file mode 100644 index 000000000..770e7f448 --- /dev/null +++ b/engine/src/core-effects/com/jme3/post/filters/BloomFilter.java @@ -0,0 +1,309 @@ +/* + * Copyright (c) 2009-2010 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 com.jme3.post.filters; + +import com.jme3.asset.AssetManager; +import com.jme3.export.InputCapsule; +import com.jme3.export.JmeExporter; +import com.jme3.export.JmeImporter; +import com.jme3.export.OutputCapsule; +import com.jme3.material.Material; +import com.jme3.math.ColorRGBA; +import com.jme3.post.Filter; +import com.jme3.renderer.RenderManager; +import com.jme3.renderer.ViewPort; +import com.jme3.texture.Image.Format; +import java.io.IOException; +import java.util.ArrayList; + +/** + * BloomFilter is used to make objects in the scene have a glow effect.
+ * There are 2 mode : Scene and Objects.
+ * Scene mode extracts the bright parts of the scene to make them glow
+ * Object mode make objects glow according to their material's glowMap or their GlowColor
+ * @see
advanced:bloom_and_glow for more details + * + * @author Rémy Bouquet aka Nehon + */ +public class BloomFilter extends Filter { + + /** + * GlowMode specifies if the glow will be applied to the whole scene,or to objects that have aglow color or a glow map + */ + public enum GlowMode { + + /** + * Apply bloom filter to bright areas in the scene. + */ + Scene, + /** + * Apply bloom only to objects that have a glow map or a glow color. + */ + Objects, + /** + * Apply bloom to both bright parts of the scene and objects with glow map. + */ + SceneAndObjects; + } + + private GlowMode glowMode = GlowMode.Scene; + //Bloom parameters + private float blurScale = 1.5f; + private float exposurePower = 5.0f; + private float exposureCutOff = 0.0f; + private float bloomIntensity = 2.0f; + private float downSamplingFactor = 1; + private Pass preGlowPass; + private Pass extractPass; + private Pass horizontalBlur = new Pass(); + private Pass verticalalBlur = new Pass(); + private Material extractMat; + private Material vBlurMat; + private Material hBlurMat; + private int screenWidth; + private int screenHeight; + + /** + * Creates a Bloom filter + */ + public BloomFilter() { + super("BloomFilter"); + } + + /** + * Creates the bloom filter with the specific glow mode + * @param glowMode + */ + public BloomFilter(GlowMode glowMode) { + this(); + this.glowMode = glowMode; + } + + @Override + protected void initFilter(AssetManager manager, RenderManager renderManager, ViewPort vp, int w, int h) { + screenWidth = (int) Math.max(1, (w / downSamplingFactor)); + screenHeight = (int) Math.max(1, (h / downSamplingFactor)); + // System.out.println(screenWidth + " " + screenHeight); + if (glowMode != GlowMode.Scene) { + preGlowPass = new Pass(); + preGlowPass.init(renderManager.getRenderer(), screenWidth, screenHeight, Format.RGBA8, Format.Depth); + } + + postRenderPasses = new ArrayList(); + //configuring extractPass + extractMat = new Material(manager, "Common/MatDefs/Post/BloomExtract.j3md"); + extractPass = new Pass() { + + @Override + public boolean requiresSceneAsTexture() { + return true; + } + + @Override + public void beforeRender() { + extractMat.setFloat("ExposurePow", exposurePower); + extractMat.setFloat("ExposureCutoff", exposureCutOff); + if (glowMode != GlowMode.Scene) { + extractMat.setTexture("GlowMap", preGlowPass.getRenderedTexture()); + } + extractMat.setBoolean("Extract", glowMode != GlowMode.Objects); + } + }; + + extractPass.init(renderManager.getRenderer(), screenWidth, screenHeight, Format.RGBA8, Format.Depth, 1, extractMat); + postRenderPasses.add(extractPass); + + //configuring horizontal blur pass + hBlurMat = new Material(manager, "Common/MatDefs/Blur/HGaussianBlur.j3md"); + horizontalBlur = new Pass() { + + @Override + public void beforeRender() { + hBlurMat.setTexture("Texture", extractPass.getRenderedTexture()); + hBlurMat.setFloat("Size", screenWidth); + hBlurMat.setFloat("Scale", blurScale); + } + }; + + horizontalBlur.init(renderManager.getRenderer(), screenWidth, screenHeight, Format.RGBA8, Format.Depth, 1, hBlurMat); + postRenderPasses.add(horizontalBlur); + + //configuring vertical blur pass + vBlurMat = new Material(manager, "Common/MatDefs/Blur/VGaussianBlur.j3md"); + verticalalBlur = new Pass() { + + @Override + public void beforeRender() { + vBlurMat.setTexture("Texture", horizontalBlur.getRenderedTexture()); + vBlurMat.setFloat("Size", screenHeight); + vBlurMat.setFloat("Scale", blurScale); + } + }; + + verticalalBlur.init(renderManager.getRenderer(), screenWidth, screenHeight, Format.RGBA8, Format.Depth, 1, vBlurMat); + postRenderPasses.add(verticalalBlur); + + + //final material + material = new Material(manager, "Common/MatDefs/Post/BloomFinal.j3md"); + material.setTexture("BloomTex", verticalalBlur.getRenderedTexture()); + } + + + @Override + protected Material getMaterial() { + material.setFloat("BloomIntensity", bloomIntensity); + return material; + } + + @Override + protected void postQueue(RenderManager renderManager, ViewPort viewPort) { + if (glowMode != GlowMode.Scene) { + renderManager.getRenderer().setBackgroundColor(ColorRGBA.BlackNoAlpha); + renderManager.getRenderer().setFrameBuffer(preGlowPass.getRenderFrameBuffer()); + renderManager.getRenderer().clearBuffers(true, true, true); + renderManager.setForcedTechnique("Glow"); + renderManager.renderViewPortQueues(viewPort, false); + renderManager.setForcedTechnique(null); + renderManager.getRenderer().setFrameBuffer(viewPort.getOutputFrameBuffer()); + } + } + + /** + * returns the bloom intensity + * @return + */ + public float getBloomIntensity() { + return bloomIntensity; + } + + /** + * intensity of the bloom effect default is 2.0 + * @param bloomIntensity + */ + public void setBloomIntensity(float bloomIntensity) { + this.bloomIntensity = bloomIntensity; + } + + /** + * returns the blur scale + * @return + */ + public float getBlurScale() { + return blurScale; + } + + /** + * sets The spread of the bloom default is 1.5f + * @param blurScale + */ + public void setBlurScale(float blurScale) { + this.blurScale = blurScale; + } + + /** + * returns the exposure cutoff
+ * for more details see {@link setExposureCutOff(float exposureCutOff)} + * @return + */ + public float getExposureCutOff() { + return exposureCutOff; + } + + /** + * Define the color threshold on which the bloom will be applied (0.0 to 1.0) + * @param exposureCutOff + */ + public void setExposureCutOff(float exposureCutOff) { + this.exposureCutOff = exposureCutOff; + } + + /** + * returns the exposure power
+ * form more details see {@link setExposurePower(float exposurePower)} + * @return + */ + public float getExposurePower() { + return exposurePower; + } + + /** + * defines how many time the bloom extracted color will be multiplied by itself. default id 5.0
+ * a high value will reduce rough edges in the bloom and somhow the range of the bloom area * + * @param exposurePower + */ + public void setExposurePower(float exposurePower) { + this.exposurePower = exposurePower; + } + + /** + * returns the downSampling factor
+ * form more details see {@link setDownSamplingFactor(float downSamplingFactor)} + * @return + */ + public float getDownSamplingFactor() { + return downSamplingFactor; + } + + /** + * Sets the downSampling factor : the size of the computed texture will be divided by this factor. default is 1 for no downsampling + * A 2 value is a good way of widening the blur + * @param downSamplingFactor + */ + public void setDownSamplingFactor(float downSamplingFactor) { + this.downSamplingFactor = downSamplingFactor; + } + + @Override + public void write(JmeExporter ex) throws IOException { + super.write(ex); + OutputCapsule oc = ex.getCapsule(this); + oc.write(glowMode, "glowMode", GlowMode.Scene); + oc.write(blurScale, "blurScale", 1.5f); + oc.write(exposurePower, "exposurePower", 5.0f); + oc.write(exposureCutOff, "exposureCutOff", 0.0f); + oc.write(bloomIntensity, "bloomIntensity", 2.0f); + oc.write(downSamplingFactor, "downSamplingFactor", 1); + } + + @Override + public void read(JmeImporter im) throws IOException { + super.read(im); + InputCapsule ic = im.getCapsule(this); + glowMode = ic.readEnum("glowMode", GlowMode.class, GlowMode.Scene); + blurScale = ic.readFloat("blurScale", 1.5f); + exposurePower = ic.readFloat("exposurePower", 5.0f); + exposureCutOff = ic.readFloat("exposureCutOff", 0.0f); + bloomIntensity = ic.readFloat("bloomIntensity", 2.0f); + downSamplingFactor = ic.readFloat("downSamplingFactor", 1); + } +} diff --git a/engine/src/core-effects/com/jme3/post/filters/CartoonEdgeFilter.java b/engine/src/core-effects/com/jme3/post/filters/CartoonEdgeFilter.java new file mode 100644 index 000000000..3e9998ba7 --- /dev/null +++ b/engine/src/core-effects/com/jme3/post/filters/CartoonEdgeFilter.java @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2009-2010 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 com.jme3.post.filters; + +import com.jme3.asset.AssetManager; +import com.jme3.material.Material; +import com.jme3.math.ColorRGBA; +import com.jme3.post.Filter; +import com.jme3.post.Filter.Pass; +import com.jme3.renderer.RenderManager; +import com.jme3.renderer.Renderer; +import com.jme3.renderer.ViewPort; +import com.jme3.texture.Image.Format; + +/** + * Applies a cartoon-style edge detection filter to all objects in the scene. + * + * @author Kirill Vainer + */ +public class CartoonEdgeFilter extends Filter { + + private Pass normalPass; + private float edgeWidth = 1.0f; + private float edgeIntensity = 1.0f; + private float normalThreshold = 0.5f; + private float depthThreshold = 0.1f; + private float normalSensitivity = 1.0f; + private float depthSensitivity = 10.0f; + private ColorRGBA edgeColor = new ColorRGBA(0, 0, 0, 1); + + /** + * Creates a CartoonEdgeFilter + */ + public CartoonEdgeFilter() { + super("CartoonEdgeFilter"); + } + + @Override + protected boolean isRequiresDepthTexture() { + return true; + } + + @Override + protected void postQueue(RenderManager renderManager, ViewPort viewPort) { + Renderer r = renderManager.getRenderer(); + r.setFrameBuffer(normalPass.getRenderFrameBuffer()); + renderManager.getRenderer().clearBuffers(true, true, true); + renderManager.setForcedTechnique("PreNormalPass"); + renderManager.renderViewPortQueues(viewPort, false); + renderManager.setForcedTechnique(null); + renderManager.getRenderer().setFrameBuffer(viewPort.getOutputFrameBuffer()); + } + + @Override + protected Material getMaterial() { + material.setTexture("NormalsTexture", normalPass.getRenderedTexture()); + return material; + } + + @Override + protected void initFilter(AssetManager manager, RenderManager renderManager, ViewPort vp, int w, int h) { + normalPass = new Pass(); + normalPass.init(renderManager.getRenderer(), w, h, Format.RGBA8, Format.Depth); + material = new Material(manager, "Common/MatDefs/Post/CartoonEdge.j3md"); + material.setFloat("EdgeWidth", edgeWidth); + material.setFloat("EdgeIntensity", edgeIntensity); + material.setFloat("NormalThreshold", normalThreshold); + material.setFloat("DepthThreshold", depthThreshold); + material.setFloat("NormalSensitivity", normalSensitivity); + material.setFloat("DepthSensitivity", depthSensitivity); + material.setColor("EdgeColor", edgeColor); + } + + /** + * Return the depth sensitivity
+ * for more details see {@link setDepthSensitivity(float depthSensitivity)} + * @return + */ + public float getDepthSensitivity() { + return depthSensitivity; + } + + /** + * sets the depth sensitivity
+ * defines how much depth will influence edges, default is 10 + * @param depthSensitivity + */ + public void setDepthSensitivity(float depthSensitivity) { + this.depthSensitivity = depthSensitivity; + if (material != null) { + material.setFloat("DepthSensitivity", depthSensitivity); + } + } + + /** + * returns the depth threshold
+ * for more details see {@link setDepthThreshold(float depthThreshold)} + * @return + */ + public float getDepthThreshold() { + return depthThreshold; + } + + /** + * sets the depth threshold
+ * Defines at what threshold of difference of depth an edge is outlined default is 0.1f + * @param depthThreshold + */ + public void setDepthThreshold(float depthThreshold) { + this.depthThreshold = depthThreshold; + if (material != null) { + material.setFloat("DepthThreshold", depthThreshold); + } + } + + /** + * returns the edge intensity
+ * for more details see {@link setEdgeIntensity(float edgeIntensity) } + * @return + */ + public float getEdgeIntensity() { + return edgeIntensity; + } + + /** + * sets the edge intensity
+ * Defineshow visilble will be the outlined edges + * @param edgeIntensity + */ + public void setEdgeIntensity(float edgeIntensity) { + this.edgeIntensity = edgeIntensity; + if (material != null) { + material.setFloat("EdgeIntensity", edgeIntensity); + } + } + + /** + * returns the width of the edges + * @return + */ + public float getEdgeWidth() { + return edgeWidth; + } + + /** + * sets the witdh of the edge in pixels default is 1 + * @param edgeWidth + */ + public void setEdgeWidth(float edgeWidth) { + this.edgeWidth = edgeWidth; + if (material != null) { + material.setFloat("EdgeWidth", edgeWidth); + } + + } + + /** + * returns the normals sensitivity
+ * form more details see {@link setNormalSensitivity(float normalSensitivity)} + * @return + */ + public float getNormalSensitivity() { + return normalSensitivity; + } + + /** + * sets the normals sensitivity default is 1 + * @param normalSensitivity + */ + public void setNormalSensitivity(float normalSensitivity) { + this.normalSensitivity = normalSensitivity; + if (material != null) { + material.setFloat("NormalSensitivity", normalSensitivity); + } + } + + /** + * returns the normal threshold
+ * for more details see {@link setNormalThreshold(float normalThreshold)} + * + * @return + */ + public float getNormalThreshold() { + return normalThreshold; + } + + /** + * sets the normal threshold default is 0.5 + * @param normalThreshold + */ + public void setNormalThreshold(float normalThreshold) { + this.normalThreshold = normalThreshold; + if (material != null) { + material.setFloat("NormalThreshold", normalThreshold); + } + } + + /** + * returns the edge color + * @return + */ + public ColorRGBA getEdgeColor() { + return edgeColor; + } + + /** + * Sets the edge color, default is black + * @param edgeColor + */ + public void setEdgeColor(ColorRGBA edgeColor) { + this.edgeColor = edgeColor; + if (material != null) { + material.setColor("EdgeColor", edgeColor); + } + } +} diff --git a/engine/src/core-effects/com/jme3/post/filters/ColorOverlayFilter.java b/engine/src/core-effects/com/jme3/post/filters/ColorOverlayFilter.java new file mode 100644 index 000000000..a7f30f884 --- /dev/null +++ b/engine/src/core-effects/com/jme3/post/filters/ColorOverlayFilter.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2009-2010 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 com.jme3.post.filters; + +import com.jme3.asset.AssetManager; +import com.jme3.export.InputCapsule; +import com.jme3.export.JmeExporter; +import com.jme3.export.JmeImporter; +import com.jme3.export.OutputCapsule; +import com.jme3.material.Material; +import com.jme3.math.ColorRGBA; +import com.jme3.post.Filter; +import com.jme3.renderer.RenderManager; +import com.jme3.renderer.ViewPort; +import java.io.IOException; + +/** + * This filter simply multiply the whole scene by a color + * @author Rémy Bouquet aka Nehon + */ +public class ColorOverlayFilter extends Filter { + + private ColorRGBA color = ColorRGBA.White; + + /** + * creates a colorOverlayFilter with a white coor (transparent) + */ + public ColorOverlayFilter() { + super("Color Overlay"); + } + + /** + * creates a colorOverlayFilter with the given color + * @param color + */ + public ColorOverlayFilter(ColorRGBA color) { + this(); + this.color = color; + } + + @Override + protected Material getMaterial() { + + material.setColor("Color", color); + return material; + } + + /** + * returns the color + * @return color + */ + public ColorRGBA getColor() { + return color; + } + + /** + * sets the color + * @param color + */ + public void setColor(ColorRGBA color) { + this.color = color; + } + + @Override + protected void initFilter(AssetManager manager, RenderManager renderManager, ViewPort vp, int w, int h) { + material = new Material(manager, "Common/MatDefs/Post/Overlay.j3md"); + } + + @Override + public void write(JmeExporter ex) throws IOException { + super.write(ex); + OutputCapsule oc = ex.getCapsule(this); + oc.write(color, "color", ColorRGBA.White); + } + + @Override + public void read(JmeImporter im) throws IOException { + super.read(im); + InputCapsule ic = im.getCapsule(this); + color = (ColorRGBA) ic.readSavable("color", ColorRGBA.White); + } +} diff --git a/engine/src/core-effects/com/jme3/post/filters/CrossHatchFilter.java b/engine/src/core-effects/com/jme3/post/filters/CrossHatchFilter.java new file mode 100644 index 000000000..699a252cd --- /dev/null +++ b/engine/src/core-effects/com/jme3/post/filters/CrossHatchFilter.java @@ -0,0 +1,305 @@ +/* + * 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 com.jme3.post.filters; + +import com.jme3.asset.AssetManager; +import com.jme3.material.Material; +import com.jme3.math.ColorRGBA; +import com.jme3.post.Filter; +import com.jme3.renderer.RenderManager; +import com.jme3.renderer.ViewPort; + +/** + * A Post Processing filter that makes the screen look like it was drawn as + * diagonal lines with a pen. + * Try combining this with a cartoon edge filter to obtain manga style visuals. + * + * Based on an article from Geeks3D: + * http://www.geeks3d.com/20110219/shader-library-crosshatching-glsl-filter/ + * + * @author Roy Straver a.k.a. Baal Garnaal + */ +public class CrossHatchFilter extends Filter { + + private ColorRGBA lineColor = ColorRGBA.Black.clone(); + private ColorRGBA paperColor = ColorRGBA.White.clone(); + private float colorInfluenceLine = 0.8f; + private float colorInfluencePaper = 0.1f; + private float fillValue = 0.9f; + private float luminance1 = 0.9f; + private float luminance2 = 0.7f; + private float luminance3 = 0.5f; + private float luminance4 = 0.3f; + private float luminance5 = 0.0f; + private float lineThickness = 1.0f; + private float lineDistance = 4.0f; + + /** + * Creates a crossHatch filter + */ + public CrossHatchFilter() { + super("CrossHatchFilter"); + } + + /** + * Creates a crossHatch filter + * @param lineColor the colors of the lines + * @param paperColor the paper color + */ + public CrossHatchFilter(ColorRGBA lineColor, ColorRGBA paperColor) { + this(); + this.lineColor = lineColor; + this.paperColor = paperColor; + } + + @Override + protected boolean isRequiresDepthTexture() { + return false; + } + + @Override + protected void initFilter(AssetManager manager, RenderManager renderManager, ViewPort vp, int w, int h) { + material = new Material(manager, "Common/MatDefs/Post/CrossHatch.j3md"); + material.setColor("LineColor", lineColor); + material.setColor("PaperColor", paperColor); + + material.setFloat("ColorInfluenceLine", colorInfluenceLine); + material.setFloat("ColorInfluencePaper", colorInfluencePaper); + + material.setFloat("FillValue", fillValue); + + material.setFloat("Luminance1", luminance1); + material.setFloat("Luminance2", luminance2); + material.setFloat("Luminance3", luminance3); + material.setFloat("Luminance4", luminance4); + material.setFloat("Luminance5", luminance5); + + material.setFloat("LineThickness", lineThickness); + material.setFloat("LineDistance", lineDistance); + } + + @Override + protected Material getMaterial() { + return material; + } + + /** + * Sets color used to draw lines + * @param lineColor + */ + public void setLineColor(ColorRGBA lineColor) { + this.lineColor = lineColor; + if (material != null) { + material.setColor("LineColor", lineColor); + } + } + + /** + * Sets color used as background + * @param paperColor + */ + public void setPaperColor(ColorRGBA paperColor) { + this.paperColor = paperColor; + if (material != null) { + material.setColor("PaperColor", paperColor); + } + } + + /** + * Sets color influence of original image on lines drawn + * @param colorInfluenceLine + */ + public void setColorInfluenceLine(float colorInfluenceLine) { + this.colorInfluenceLine = colorInfluenceLine; + if (material != null) { + material.setFloat("ColorInfluenceLine", colorInfluenceLine); + } + } + + /** + * Sets color influence of original image on non-line areas + * @param colorInfluencePaper + */ + public void setColorInfluencePaper(float colorInfluencePaper) { + this.colorInfluencePaper = colorInfluencePaper; + if (material != null) { + material.setFloat("ColorInfluencePaper", colorInfluencePaper); + } + } + + /** + * Sets line/paper color ratio for areas with values < luminance5, + * really dark areas get no lines but a filled blob instead + * @param fillValue + */ + public void setFillValue(float fillValue) { + this.fillValue = fillValue; + if (material != null) { + material.setFloat("FillValue", fillValue); + } + } + + /** + * + * Sets minimum luminance levels for lines drawn + * @param luminance1 Top-left to down right 1 + * @param luminance2 Top-right to bottom left 1 + * @param luminance3 Top-left to down right 2 + * @param luminance4 Top-right to bottom left 2 + * @param luminance5 Blobs + */ + public void setLuminanceLevels(float luminance1, float luminance2, float luminance3, float luminance4, float luminance5) { + this.luminance1 = luminance1; + this.luminance2 = luminance2; + this.luminance3 = luminance3; + this.luminance4 = luminance4; + this.luminance5 = luminance5; + + if (material != null) { + material.setFloat("Luminance1", luminance1); + material.setFloat("Luminance2", luminance2); + material.setFloat("Luminance3", luminance3); + material.setFloat("Luminance4", luminance4); + material.setFloat("Luminance5", luminance5); + } + } + + /** + * Sets the thickness of lines drawn + * @param lineThickness + */ + public void setLineThickness(float lineThickness) { + this.lineThickness = lineThickness; + if (material != null) { + material.setFloat("LineThickness", lineThickness); + } + } + + /** + * Sets minimum distance between lines drawn + * Primary lines are drawn at 2*lineDistance + * Secondary lines are drawn at lineDistance + * @param lineDistance + */ + public void setLineDistance(float lineDistance) { + this.lineDistance = lineDistance; + if (material != null) { + material.setFloat("LineDistance", lineDistance); + } + } + + /** + * Returns line color + * @return + */ + public ColorRGBA getLineColor() { + return lineColor; + } + + /** + * Returns paper background color + * @return + */ + public ColorRGBA getPaperColor() { + return paperColor; + } + + /** + * Returns current influence of image colors on lines + */ + public float getColorInfluenceLine() { + return colorInfluenceLine; + } + + /** + * Returns current influence of image colors on paper background + */ + public float getColorInfluencePaper() { + return colorInfluencePaper; + } + + /** + * Returns line/paper color ratio for blobs + */ + public float getFillValue() { + return fillValue; + } + + /** + * Returns the thickness of the lines drawn + */ + public float getLineThickness() { + return lineThickness; + } + + /** + * Returns minimum distance between lines + */ + public float getLineDistance() { + return lineDistance; + } + + /** + * Returns treshold for lines 1 + */ + public float getLuminance1() { + return luminance1; + } + + /** + * Returns treshold for lines 2 + */ + public float getLuminance2() { + return luminance2; + } + + /** + * Returns treshold for lines 3 + */ + public float getLuminance3() { + return luminance3; + } + + /** + * Returns treshold for lines 4 + */ + public float getLuminance4() { + return luminance4; + } + + /** + * Returns treshold for blobs + */ + public float getLuminance5() { + return luminance5; + } +} \ No newline at end of file diff --git a/engine/src/core-effects/com/jme3/post/filters/DepthOfFieldFilter.java b/engine/src/core-effects/com/jme3/post/filters/DepthOfFieldFilter.java new file mode 100644 index 000000000..55591c988 --- /dev/null +++ b/engine/src/core-effects/com/jme3/post/filters/DepthOfFieldFilter.java @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2009-2010 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 com.jme3.post.filters; + +import com.jme3.asset.AssetManager; +import com.jme3.material.Material; +import com.jme3.post.Filter; +import com.jme3.renderer.RenderManager; +import com.jme3.renderer.ViewPort; + +/** + * A post-processing filter that performs a depth range + * blur using a scaled convolution filter. + * + * @version $Revision: 779 $ + * @author Paul Speed + */ +public class DepthOfFieldFilter extends Filter { + + private float focusDistance = 50f; + private float focusRange = 10f; + private float blurScale = 1f; + // These values are set internally based on the + // viewport size. + private float xScale; + private float yScale; + + /** + * Creates a DepthOfField filter + */ + public DepthOfFieldFilter() { + super("Depth Of Field"); + } + + @Override + protected boolean isRequiresDepthTexture() { + return true; + } + + @Override + protected Material getMaterial() { + + return material; + } + + @Override + protected void initFilter(AssetManager assets, RenderManager renderManager, + ViewPort vp, int w, int h) { + material = new Material(assets, "Common/MatDefs/Post/DepthOfField.j3md"); + material.setFloat("FocusDistance", focusDistance); + material.setFloat("FocusRange", focusRange); + + + xScale = 1.0f / w; + yScale = 1.0f / h; + + material.setFloat("XScale", blurScale * xScale); + material.setFloat("YScale", blurScale * yScale); + } + + /** + * Sets the distance at which objects are purely in focus. + */ + public void setFocusDistance(float f) { + + this.focusDistance = f; + if (material != null) { + material.setFloat("FocusDistance", focusDistance); + } + + } + + /** + * returns the focus distance + * @return + */ + public float getFocusDistance() { + return focusDistance; + } + + /** + * Sets the range to either side of focusDistance where the + * objects go gradually out of focus. Less than focusDistance - focusRange + * and greater than focusDistance + focusRange, objects are maximally "blurred". + */ + public void setFocusRange(float f) { + this.focusRange = f; + if (material != null) { + material.setFloat("FocusRange", focusRange); + } + + } + + /** + * returns the focus range + * @return + */ + public float getFocusRange() { + return focusRange; + } + + /** + * Sets the blur amount by scaling the convolution filter up or + * down. A value of 1 (the default) performs a sparse 5x5 evenly + * distribubted convolution at pixel level accuracy. Higher values skip + * more pixels, and so on until you are no longer blurring the image + * but simply hashing it. + * + * The sparse convolution is as follows: + *%MINIFYHTMLc3d0cd9fab65de6875a381fd3f83e1b338%* + * Where 'x' is the texel being modified. Setting blur scale higher + * than 1 spaces the samples out. + */ + public void setBlurScale(float f) { + this.blurScale = f; + if (material != null) { + material.setFloat("XScale", blurScale * xScale); + material.setFloat("YScale", blurScale * yScale); + } + } + + /** + * returns the blur scale + * @return + */ + public float getBlurScale() { + return blurScale; + } +} diff --git a/engine/src/core-effects/com/jme3/post/filters/FXAAFilter.java b/engine/src/core-effects/com/jme3/post/filters/FXAAFilter.java new file mode 100644 index 000000000..8ba3c16bb --- /dev/null +++ b/engine/src/core-effects/com/jme3/post/filters/FXAAFilter.java @@ -0,0 +1,95 @@ +package com.jme3.post.filters; + +import com.jme3.asset.AssetManager; +import com.jme3.material.Material; +import com.jme3.post.Filter; +import com.jme3.renderer.RenderManager; +import com.jme3.renderer.ViewPort; + +/** + * http://www.geeks3d.com/20110405/fxaa-fast-approximate-anti-aliasing-demo-glsl-opengl-test-radeon-geforce/3/ + * http://developer.download.nvidia.com/assets/gamedev/files/sdk/11/FXAA_WhitePaper.pdf + * + * @author Phate666 (adapted to jme3) + * + */ +public class FXAAFilter extends Filter { + + private float subPixelShift = 1.0f / 4.0f; + private float vxOffset = 0.0f; + private float spanMax = 8.0f; + private float reduceMul = 1.0f / 8.0f; + + public FXAAFilter() { + super("FXAAFilter"); + } + + @Override + protected void initFilter(AssetManager manager, + RenderManager renderManager, ViewPort vp, int w, int h) { + material = new Material(manager, "Common/MatDefs/Post/FXAA.j3md"); + material.setFloat("SubPixelShift", subPixelShift); + material.setFloat("VxOffset", vxOffset); + material.setFloat("SpanMax", spanMax); + material.setFloat("ReduceMul", reduceMul); + } + + @Override + protected Material getMaterial() { + return material; + } + + public void setSpanMax(float spanMax) { + this.spanMax = spanMax; + if (material != null) { + material.setFloat("SpanMax", this.spanMax); + } + } + + /** + * set to 0.0f for higher quality + * + * @param subPixelShift + */ + public void setSubPixelShift(float subPixelShift) { + this.subPixelShift = subPixelShift; + if (material != null) { + material.setFloat("SubPixelShif", this.subPixelShift); + } + } + + /** + * set to 0.0f for higher quality + * + * @param reduceMul + */ + public void setReduceMul(float reduceMul) { + this.reduceMul = reduceMul; + if (material != null) { + material.setFloat("ReduceMul", this.reduceMul); + } + } + + public void setVxOffset(float vxOffset) { + this.vxOffset = vxOffset; + if (material != null) { + material.setFloat("VxOffset", this.vxOffset); + } + } + + public float getReduceMul() { + return reduceMul; + } + + public float getSpanMax() { + return spanMax; + } + + public float getSubPixelShift() { + return subPixelShift; + } + + public float getVxOffset() { + return vxOffset; + } +} \ No newline at end of file diff --git a/engine/src/core-effects/com/jme3/post/filters/FadeFilter.java b/engine/src/core-effects/com/jme3/post/filters/FadeFilter.java new file mode 100644 index 000000000..1fb234074 --- /dev/null +++ b/engine/src/core-effects/com/jme3/post/filters/FadeFilter.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2009-2010 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 com.jme3.post.filters; + +import com.jme3.asset.AssetManager; +import com.jme3.export.InputCapsule; +import com.jme3.export.JmeExporter; +import com.jme3.export.JmeImporter; +import com.jme3.export.OutputCapsule; +import com.jme3.material.Material; +import com.jme3.post.Filter; +import com.jme3.renderer.RenderManager; +import com.jme3.renderer.ViewPort; +import java.io.IOException; + +/** + * + * Fade Filter allows you to make an animated fade effect on a scene. + * @author Rémy Bouquet aka Nehon + * implemented from boxjar implementation + * @see http://jmonkeyengine.org/groups/graphics/forum/topic/newbie-question-general-fade-inout-effect/#post-105559 + */ +public class FadeFilter extends Filter { + + private float value = 1; + private boolean playing = false; + private float direction = 1; + private float duration = 1; + + /** + * Creates a FadeFilter + */ + public FadeFilter() { + super("Fade In/Out"); + } + + /** + * Creates a FadeFilter with the given duration + * @param duration + */ + public FadeFilter(float duration) { + this(); + this.duration = duration; + } + + @Override + protected Material getMaterial() { + material.setFloat("Value", value); + return material; + } + + @Override + protected void initFilter(AssetManager manager, RenderManager renderManager, ViewPort vp, int w, int h) { + material = new Material(manager, "Common/MatDefs/Post/Fade.j3md"); + } + + @Override + protected void preFrame(float tpf) { + if (playing) { + value += tpf * direction / duration; + + if (direction > 0 && value > 1) { + value = 1; + playing = false; + setEnabled(false); + } + if (direction < 0 && value < 0) { + value = 0; + playing = false; + setEnabled(false); + } + } + } + + /** + * returns the duration of the effect + * @return + */ + public float getDuration() { + return duration; + } + + /** + * Sets the duration of the filter default is 1 second + * @param duration + */ + public void setDuration(float duration) { + this.duration = duration; + } + + /** + * fades the scene in (black to scene) + */ + public void fadeIn() { + setEnabled(true); + direction = 1; + playing = true; + } + + /** + * fades the scene out (scene to black) + */ + public void fadeOut() { + setEnabled(true); + direction = -1; + playing = true; + + } + + public void pause() { + playing = false; + } + + @Override + public void write(JmeExporter ex) throws IOException { + super.write(ex); + OutputCapsule oc = ex.getCapsule(this); + oc.write(duration, "duration", 1); + } + + @Override + public void read(JmeImporter im) throws IOException { + super.read(im); + InputCapsule ic = im.getCapsule(this); + duration = ic.readFloat("duration", 1); + } + + /** + * return the current value of the fading + * can be used to chack if fade is complete (eg value=1) + * @return + */ + public float getValue() { + return value; + } + + /** + * sets the fade value + * can be used to force complete black or compete scene + * @param value + */ + public void setValue(float value) { + this.value = value; + if (material != null) { + material.setFloat("Value", value); + } + } +} diff --git a/engine/src/core-effects/com/jme3/post/filters/FogFilter.java b/engine/src/core-effects/com/jme3/post/filters/FogFilter.java new file mode 100644 index 000000000..c1df3b761 --- /dev/null +++ b/engine/src/core-effects/com/jme3/post/filters/FogFilter.java @@ -0,0 +1,172 @@ +/* + * 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 com.jme3.post.filters; + +import com.jme3.asset.AssetManager; +import com.jme3.export.InputCapsule; +import com.jme3.export.JmeExporter; +import com.jme3.export.JmeImporter; +import com.jme3.export.OutputCapsule; +import com.jme3.material.Material; +import com.jme3.math.ColorRGBA; +import com.jme3.post.Filter; +import com.jme3.renderer.RenderManager; +import com.jme3.renderer.ViewPort; +import java.io.IOException; + +/** + * A filter to render a fog effect + * @author Rémy Bouquet aka Nehon + */ +public class FogFilter extends Filter { + + private ColorRGBA fogColor = ColorRGBA.White.clone(); + private float fogDensity = 0.7f; + private float fogDistance = 1000; + + /** + * Creates a FogFilter + */ + public FogFilter() { + super("FogFilter"); + } + + /** + * Create a fog filter + * @param fogColor the color of the fog (default is white) + * @param fogDensity the density of the fog (default is 0.7) + * @param fogDistance the distance of the fog (default is 1000) + */ + public FogFilter(ColorRGBA fogColor, float fogDensity, float fogDistance) { + this(); + this.fogColor = fogColor; + this.fogDensity = fogDensity; + this.fogDistance = fogDistance; + } + + @Override + protected boolean isRequiresDepthTexture() { + return true; + } + + @Override + protected void initFilter(AssetManager manager, RenderManager renderManager, ViewPort vp, int w, int h) { + material = new Material(manager, "Common/MatDefs/Post/Fog.j3md"); + material.setColor("FogColor", fogColor); + material.setFloat("FogDensity", fogDensity); + material.setFloat("FogDistance", fogDistance); + } + + @Override + protected Material getMaterial() { + + return material; + } + + + /** + * returns the fog color + * @return + */ + public ColorRGBA getFogColor() { + return fogColor; + } + + /** + * Sets the color of the fog + * @param fogColor + */ + public void setFogColor(ColorRGBA fogColor) { + if (material != null) { + material.setColor("FogColor", fogColor); + } + this.fogColor = fogColor; + } + + /** + * returns the fog density + * @return + */ + public float getFogDensity() { + return fogDensity; + } + + /** + * Sets the density of the fog, a high value gives a thick fog + * @param fogDensity + */ + public void setFogDensity(float fogDensity) { + if (material != null) { + material.setFloat("FogDensity", fogDensity); + } + this.fogDensity = fogDensity; + } + + /** + * returns the fog distance + * @return + */ + public float getFogDistance() { + return fogDistance; + } + + /** + * the distance of the fog. the higer the value the distant the fog looks + * @param fogDistance + */ + public void setFogDistance(float fogDistance) { + if (material != null) { + material.setFloat("FogDistance", fogDistance); + } + this.fogDistance = fogDistance; + } + + @Override + public void write(JmeExporter ex) throws IOException { + super.write(ex); + OutputCapsule oc = ex.getCapsule(this); + oc.write(fogColor, "fogColor", ColorRGBA.White.clone()); + oc.write(fogDensity, "fogDensity", 0.7f); + oc.write(fogDistance, "fogDistance", 1000); + } + + @Override + public void read(JmeImporter im) throws IOException { + super.read(im); + InputCapsule ic = im.getCapsule(this); + fogColor = (ColorRGBA) ic.readSavable("fogColor", ColorRGBA.White.clone()); + fogDensity = ic.readFloat("fogDensity", 0.7f); + fogDistance = ic.readFloat("fogDistance", 1000); + } + + +} diff --git a/engine/src/core-effects/com/jme3/post/filters/GammaCorrectionFilter.java b/engine/src/core-effects/com/jme3/post/filters/GammaCorrectionFilter.java new file mode 100644 index 000000000..9e283ca13 --- /dev/null +++ b/engine/src/core-effects/com/jme3/post/filters/GammaCorrectionFilter.java @@ -0,0 +1,78 @@ +package com.jme3.post.filters; + +import com.jme3.asset.AssetManager; +import com.jme3.material.Material; +import com.jme3.post.Filter; +import com.jme3.renderer.RenderManager; +import com.jme3.renderer.ViewPort; + +/** + * + * @author Phate666 + * @version 1.0 initial version + * @version 1.1 added luma + */ +public class GammaCorrectionFilter extends Filter +{ + private float gamma = 2.0f; + private boolean computeLuma = false; + + public GammaCorrectionFilter() + { + super("GammaCorrectionFilter"); + } + + public GammaCorrectionFilter(float gamma) + { + this(); + this.setGamma(gamma); + } + + @Override + protected Material getMaterial() + { + return material; + } + + @Override + protected void initFilter(AssetManager manager, + RenderManager renderManager, ViewPort vp, int w, int h) + { + material = new Material(manager, + "Common/MatDefs/Post/GammaCorrection.j3md"); + material.setFloat("gamma", gamma); + material.setBoolean("computeLuma", computeLuma); + } + + public float getGamma() + { + return gamma; + } + + /** + * set to 0.0 to disable gamma correction + * @param gamma + */ + public void setGamma(float gamma) + { + if (material != null) + { + material.setFloat("gamma", gamma); + } + this.gamma = gamma; + } + + public boolean isComputeLuma() + { + return computeLuma; + } + + public void setComputeLuma(boolean computeLuma) + { + if (material != null) + { + material.setBoolean("computeLuma", computeLuma); + } + this.computeLuma = computeLuma; + } +} diff --git a/engine/src/core-effects/com/jme3/post/filters/LightScatteringFilter.java b/engine/src/core-effects/com/jme3/post/filters/LightScatteringFilter.java new file mode 100644 index 000000000..953f10a66 --- /dev/null +++ b/engine/src/core-effects/com/jme3/post/filters/LightScatteringFilter.java @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2009-2010 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 com.jme3.post.filters; + +import com.jme3.asset.AssetManager; +import com.jme3.export.InputCapsule; +import com.jme3.export.JmeExporter; +import com.jme3.export.JmeImporter; +import com.jme3.export.OutputCapsule; +import com.jme3.material.Material; +import com.jme3.math.Vector3f; +import com.jme3.post.Filter; +import com.jme3.renderer.Camera; +import com.jme3.renderer.RenderManager; +import com.jme3.renderer.ViewPort; +import java.io.IOException; + +/** + * LightScattering filters creates rays comming from a light sources + * This is often reffered as god rays. + * + * @author Rémy Bouquet aka Nehon + */ +public class LightScatteringFilter extends Filter { + + private Vector3f lightPosition; + private Vector3f screenLightPos = new Vector3f(); + private int nbSamples = 50; + private float blurStart = 0.02f; + private float blurWidth = 0.9f; + private float lightDensity = 1.4f; + private boolean adaptative = true; + Vector3f viewLightPos = new Vector3f(); + private boolean display = true; + private float innerLightDensity; + + /** + * creates a lightScaterring filter + */ + public LightScatteringFilter() { + super("Light Scattering"); + } + + /** + * Creates a lightScatteringFilter + * @param lightPosition + */ + public LightScatteringFilter(Vector3f lightPosition) { + this(); + this.lightPosition = lightPosition; + } + + @Override + protected boolean isRequiresDepthTexture() { + return true; + } + + @Override + protected Material getMaterial() { + material.setVector3("LightPosition", screenLightPos); + material.setInt("NbSamples", nbSamples); + material.setFloat("BlurStart", blurStart); + material.setFloat("BlurWidth", blurWidth); + material.setFloat("LightDensity", innerLightDensity); + material.setBoolean("Display", display); + return material; + } + + @Override + protected void postQueue(RenderManager renderManager, ViewPort viewPort) { + getClipCoordinates(lightPosition, screenLightPos, viewPort.getCamera()); + // screenLightPos.x = screenLightPos.x / viewPort.getCamera().getWidth(); + // screenLightPos.y = screenLightPos.y / viewPort.getCamera().getHeight(); + + viewPort.getCamera().getViewMatrix().mult(lightPosition, viewLightPos); + //System.err.println("viewLightPos "+viewLightPos); + display = screenLightPos.x < 1.6f && screenLightPos.x > -0.6f && screenLightPos.y < 1.6f && screenLightPos.y > -0.6f && viewLightPos.z < 0; +//System.err.println("camdir "+viewPort.getCamera().getDirection()); +//System.err.println("lightPos "+lightPosition); +//System.err.println("screenLightPos "+screenLightPos); + if (adaptative) { + innerLightDensity = Math.max(lightDensity - Math.max(screenLightPos.x, screenLightPos.y), 0.0f); + } else { + innerLightDensity = lightDensity; + } + } + + private Vector3f getClipCoordinates(Vector3f worldPosition, Vector3f store, Camera cam) { + + float w = cam.getViewProjectionMatrix().multProj(worldPosition, store); + store.divideLocal(w); + + store.x = ((store.x + 1f) * (cam.getViewPortRight() - cam.getViewPortLeft()) / 2f + cam.getViewPortLeft()); + store.y = ((store.y + 1f) * (cam.getViewPortTop() - cam.getViewPortBottom()) / 2f + cam.getViewPortBottom()); + store.z = (store.z + 1f) / 2f; + + return store; + } + + @Override + protected void initFilter(AssetManager manager, RenderManager renderManager, ViewPort vp, int w, int h) { + material = new Material(manager, "Common/MatDefs/Post/LightScattering.j3md"); + } + + /** + * returns the blur start of the scattering + * see {@link setBlurStart(float blurStart)} + * @return + */ + public float getBlurStart() { + return blurStart; + } + + /** + * sets the blur start
+ * at which distance from the light source the effect starts default is 0.02 + * @param blurStart + */ + public void setBlurStart(float blurStart) { + this.blurStart = blurStart; + } + + /** + * returns the blur width
+ * see {@link setBlurWidth(float blurWidth)} + * @return + */ + public float getBlurWidth() { + return blurWidth; + } + + /** + * sets the blur width default is 0.9 + * @param blurWidth + */ + public void setBlurWidth(float blurWidth) { + this.blurWidth = blurWidth; + } + + /** + * retiurns the light density
+ * see {@link setLightDensity(float lightDensity)} + * + * @return + */ + public float getLightDensity() { + return lightDensity; + } + + /** + * sets how much the effect is visible over the rendered scene default is 1.4 + * @param lightDensity + */ + public void setLightDensity(float lightDensity) { + this.lightDensity = lightDensity; + } + + /** + * returns the light position + * @return + */ + public Vector3f getLightPosition() { + return lightPosition; + } + + /** + * sets the light position + * @param lightPosition + */ + public void setLightPosition(Vector3f lightPosition) { + this.lightPosition = lightPosition; + } + + /** + * returns the nmber of samples for the radial blur + * @return + */ + public int getNbSamples() { + return nbSamples; + } + + /** + * sets the number of samples for the radial blur default is 50 + * the higher the value the higher the quality, but the slower the performances. + * @param nbSamples + */ + public void setNbSamples(int nbSamples) { + this.nbSamples = nbSamples; + } + + @Override + public void write(JmeExporter ex) throws IOException { + super.write(ex); + OutputCapsule oc = ex.getCapsule(this); + oc.write(lightPosition, "lightPosition", Vector3f.ZERO); + oc.write(nbSamples, "nbSamples", 50); + oc.write(blurStart, "blurStart", 0.02f); + oc.write(blurWidth, "blurWidth", 0.9f); + oc.write(lightDensity, "lightDensity", 1.4f); + oc.write(adaptative, "adaptative", true); + } + + @Override + public void read(JmeImporter im) throws IOException { + super.read(im); + InputCapsule ic = im.getCapsule(this); + lightPosition = (Vector3f) ic.readSavable("lightPosition", Vector3f.ZERO); + nbSamples = ic.readInt("nbSamples", 50); + blurStart = ic.readFloat("blurStart", 0.02f); + blurWidth = ic.readFloat("blurWidth", 0.9f); + lightDensity = ic.readFloat("lightDensity", 1.4f); + adaptative = ic.readBoolean("adaptative", true); + } +} diff --git a/engine/src/core-effects/com/jme3/post/filters/PosterizationFilter.java b/engine/src/core-effects/com/jme3/post/filters/PosterizationFilter.java new file mode 100644 index 000000000..c980edaee --- /dev/null +++ b/engine/src/core-effects/com/jme3/post/filters/PosterizationFilter.java @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2009-2010 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 com.jme3.post.filters; + +import com.jme3.asset.AssetManager; +import com.jme3.material.Material; +import com.jme3.post.Filter; +import com.jme3.renderer.RenderManager; +import com.jme3.renderer.ViewPort; + +/** + * A Post Processing filter to change colors appear with sharp edges as if the + * available amount of colors available was not enough to draw the true image. + * Possibly useful in cartoon styled games. Use the strength variable to lessen + * influence of this filter on the total result. Values from 0.2 to 0.7 appear + * to give nice results. + * + * Based on an article from Geeks3D: + * http://www.geeks3d.com/20091027/shader-library-posterization-post-processing-effect-glsl/ + * + * @author: Roy Straver a.k.a. Baal Garnaal + */ +public class PosterizationFilter extends Filter { + + private int numColors = 8; + private float gamma = 0.6f; + private float strength = 1.0f; + + /** + * Creates a posterization Filter + */ + public PosterizationFilter() { + super("PosterizationFilter"); + } + + /** + * Creates a posterization Filter with the given number of colors + * @param numColors + */ + public PosterizationFilter(int numColors) { + this(); + this.numColors = numColors; + } + + /** + * Creates a posterization Filter with the given number of colors and gamma + * @param numColors + * @param gamma + */ + public PosterizationFilter(int numColors, float gamma) { + this(numColors); + this.gamma = gamma; + } + + @Override + protected void initFilter(AssetManager manager, RenderManager renderManager, ViewPort vp, int w, int h) { + material = new Material(manager, "Common/MatDefs/Post/Posterization.j3md"); + material.setInt("NumColors", numColors); + material.setFloat("Gamma", gamma); + material.setFloat("Strength", strength); + } + + @Override + protected Material getMaterial() { + return material; + } + + /** + * Sets number of color levels used to draw the screen + */ + public void setNumColors(int numColors) { + this.numColors = numColors; + if (material != null) { + material.setInt("NumColors", numColors); + } + } + + /** + * Sets gamma level used to enhange visual quality + */ + public void setGamma(float gamma) { + this.gamma = gamma; + if (material != null) { + material.setFloat("Gamma", gamma); + } + } + + /** + * Sets urrent strength value, i.e. influence on final image + */ + public void setStrength(float strength) { + this.strength = strength; + if (material != null) { + material.setFloat("Strength", strength); + } + } + + /** + * Returns number of color levels used + */ + public int getNumColors() { + return numColors; + } + + /** + * Returns current gamma value + */ + public float getGamma() { + return gamma; + } + + /** + * Returns current strength value, i.e. influence on final image + */ + public float getStrength() { + return strength; + } +} \ No newline at end of file diff --git a/engine/src/core-effects/com/jme3/post/filters/RadialBlurFilter.java b/engine/src/core-effects/com/jme3/post/filters/RadialBlurFilter.java new file mode 100644 index 000000000..0bcae5fe6 --- /dev/null +++ b/engine/src/core-effects/com/jme3/post/filters/RadialBlurFilter.java @@ -0,0 +1,156 @@ +/* + * 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 com.jme3.post.filters; + +import com.jme3.asset.AssetManager; +import com.jme3.export.InputCapsule; +import com.jme3.export.JmeExporter; +import com.jme3.export.JmeImporter; +import com.jme3.export.OutputCapsule; +import com.jme3.material.Material; +import com.jme3.post.Filter; +import com.jme3.renderer.RenderManager; +import com.jme3.renderer.ViewPort; +import com.jme3.shader.VarType; +import java.io.IOException; + +/** + * Radially blurs the scene from the center of it + * @author Rémy Bouquet aka Nehon + */ +public class RadialBlurFilter extends Filter { + + private float sampleDist = 1.0f; + private float sampleStrength = 2.2f; + private float[] samples = {-0.08f, -0.05f, -0.03f, -0.02f, -0.01f, 0.01f, 0.02f, 0.03f, 0.05f, 0.08f}; + + /** + * Creates a RadialBlurFilter + */ + public RadialBlurFilter() { + super("Radial blur"); + } + + /** + * Creates a RadialBlurFilter + * @param sampleDist the distance between samples + * @param sampleStrength the strenght of each sample + */ + public RadialBlurFilter(float sampleDist, float sampleStrength) { + this(); + this.sampleDist = sampleDist; + this.sampleStrength = sampleStrength; + } + + @Override + protected Material getMaterial() { + + material.setFloat("SampleDist", sampleDist); + material.setFloat("SampleStrength", sampleStrength); + material.setParam("Samples", VarType.FloatArray, samples); + + return material; + } + + /** + * return the sample distance + * @return + */ + public float getSampleDistance() { + return sampleDist; + } + + /** + * sets the samples distances default is 1 + * @param sampleDist + */ + public void setSampleDistance(float sampleDist) { + this.sampleDist = sampleDist; + } + + /** + * + * @return + * @deprecated use {@link #getSampleDistance()} + */ + @Deprecated + public float getSampleDist() { + return sampleDist; + } + + /** + * + * @param sampleDist + * @deprecated use {@link #setSampleDistance(float sampleDist)} + */ + @Deprecated + public void setSampleDist(float sampleDist) { + this.sampleDist = sampleDist; + } + + /** + * Returns the sample Strength + * @return + */ + public float getSampleStrength() { + return sampleStrength; + } + + /** + * sets the sample streanght default is 2.2 + * @param sampleStrength + */ + public void setSampleStrength(float sampleStrength) { + this.sampleStrength = sampleStrength; + } + + @Override + protected void initFilter(AssetManager manager, RenderManager renderManager, ViewPort vp, int w, int h) { + material = new Material(manager, "Common/MatDefs/Blur/RadialBlur.j3md"); + } + + @Override + public void write(JmeExporter ex) throws IOException { + super.write(ex); + OutputCapsule oc = ex.getCapsule(this); + oc.write(sampleDist, "sampleDist", 1.0f); + oc.write(sampleStrength, "sampleStrength", 2.2f); + } + + @Override + public void read(JmeImporter im) throws IOException { + super.read(im); + InputCapsule ic = im.getCapsule(this); + sampleDist = ic.readFloat("sampleDist", 1.0f); + sampleStrength = ic.readFloat("sampleStrength", 2.2f); + } +} diff --git a/engine/src/core-effects/com/jme3/post/filters/TranslucentBucketFilter.java b/engine/src/core-effects/com/jme3/post/filters/TranslucentBucketFilter.java new file mode 100644 index 000000000..47be41382 --- /dev/null +++ b/engine/src/core-effects/com/jme3/post/filters/TranslucentBucketFilter.java @@ -0,0 +1,80 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.post.filters; + +import com.jme3.asset.AssetManager; +import com.jme3.material.Material; +import com.jme3.math.ColorRGBA; +import com.jme3.post.Filter; +import com.jme3.renderer.RenderManager; +import com.jme3.renderer.Renderer; +import com.jme3.renderer.ViewPort; +import com.jme3.renderer.queue.RenderQueue; +import com.jme3.texture.FrameBuffer; +import com.jme3.texture.Texture2D; + +/** + * A filter to handle translucent objects when rendering a scene with filters that uses depth like WaterFilter and SSAOFilter + * just create a TranslucentBucketFilter and add it to the Filter list of a FilterPostPorcessor + * @author Nehon + */ +public final class TranslucentBucketFilter extends Filter { + + private RenderManager renderManager; + + @Override + protected void initFilter(AssetManager manager, RenderManager rm, ViewPort vp, int w, int h) { + this.renderManager = rm; + material = new Material(manager, "Common/MatDefs/Post/Overlay.j3md"); + material.setColor("Color", ColorRGBA.White); + Texture2D tex = processor.getFilterTexture(); + material.setTexture("Texture", tex); + if (tex.getImage().getMultiSamples() > 1) { + material.setInt("NumSamples", tex.getImage().getMultiSamples()); + } else { + material.clearParam("NumSamples"); + } + renderManager.setHandleTranslucentBucket(false); + } + + /** + * Override this method and return false if your Filter does not need the scene texture + * @return + */ + @Override + protected boolean isRequiresSceneTexture() { + return false; + } + + @Override + protected void postFrame(RenderManager renderManager, ViewPort viewPort, FrameBuffer prevFilterBuffer, FrameBuffer sceneBuffer) { + renderManager.setCamera(viewPort.getCamera(), false); + if (prevFilterBuffer != sceneBuffer) { + renderManager.getRenderer().copyFrameBuffer(prevFilterBuffer, sceneBuffer, false); + } + renderManager.getRenderer().setFrameBuffer(sceneBuffer); + viewPort.getQueue().renderQueue(RenderQueue.Bucket.Translucent, renderManager, viewPort.getCamera()); + } + + @Override + protected void cleanUpFilter(Renderer r) { + if (renderManager != null) { + renderManager.setHandleTranslucentBucket(true); + } + } + + @Override + protected Material getMaterial() { + return material; + } + + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + if (renderManager != null) { + renderManager.setHandleTranslucentBucket(!enabled); + } + } +} diff --git a/engine/src/core-effects/com/jme3/post/ssao/SSAOFilter.java b/engine/src/core-effects/com/jme3/post/ssao/SSAOFilter.java new file mode 100644 index 000000000..cb0c037b7 --- /dev/null +++ b/engine/src/core-effects/com/jme3/post/ssao/SSAOFilter.java @@ -0,0 +1,324 @@ +/* + * 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 com.jme3.post.ssao; + +import com.jme3.asset.AssetManager; +import com.jme3.export.InputCapsule; +import com.jme3.export.JmeExporter; +import com.jme3.export.JmeImporter; +import com.jme3.export.OutputCapsule; +import com.jme3.material.Material; +import com.jme3.math.Vector2f; +import com.jme3.math.Vector3f; +import com.jme3.post.Filter; +import com.jme3.post.Filter.Pass; +import com.jme3.renderer.RenderManager; +import com.jme3.renderer.Renderer; +import com.jme3.renderer.ViewPort; +import com.jme3.shader.VarType; +import com.jme3.texture.Image.Format; +import com.jme3.texture.Texture; +import java.io.IOException; +import java.util.ArrayList; + +/** + * SSAO stands for screen space ambient occlusion + * It's a technique that fake ambient lighting by computing shadows that near by objects would casts on each others + * under the effect of an ambient light + * more info on this in this blog post http://jmonkeyengine.org/2010/08/16/screen-space-ambient-occlusion-for-jmonkeyengine-3-0/ + * + * @author Rémy Bouquet aka Nehon + */ +public class SSAOFilter extends Filter { + + private Pass normalPass; + private Vector3f frustumCorner; + private Vector2f frustumNearFar; + private Vector2f[] samples = {new Vector2f(1.0f, 0.0f), new Vector2f(-1.0f, 0.0f), new Vector2f(0.0f, 1.0f), new Vector2f(0.0f, -1.0f)}; + private float sampleRadius = 5.1f; + private float intensity = 1.5f; + private float scale = 0.2f; + private float bias = 0.1f; + private boolean useOnlyAo = false; + private boolean useAo = true; + private Material ssaoMat; + private Pass ssaoPass; +// private Material downSampleMat; +// private Pass downSamplePass; + private float downSampleFactor = 1f; + + /** + * Create a Screen Space Ambient Occlusion Filter + */ + public SSAOFilter() { + super("SSAOFilter"); + } + + /** + * Create a Screen Space Ambient Occlusion Filter + * @param sampleRadius The radius of the area where random samples will be picked. default 5.1f + * @param intensity intensity of the resulting AO. default 1.2f + * @param scale distance between occluders and occludee. default 0.2f + * @param bias the width of the occlusion cone considered by the occludee. default 0.1f + */ + public SSAOFilter(float sampleRadius, float intensity, float scale, float bias) { + this(); + this.sampleRadius = sampleRadius; + this.intensity = intensity; + this.scale = scale; + this.bias = bias; + } + + @Override + protected boolean isRequiresDepthTexture() { + return true; + } + + @Override + protected void postQueue(RenderManager renderManager, ViewPort viewPort) { + Renderer r = renderManager.getRenderer(); + r.setFrameBuffer(normalPass.getRenderFrameBuffer()); + renderManager.getRenderer().clearBuffers(true, true, true); + renderManager.setForcedTechnique("PreNormalPass"); + renderManager.renderViewPortQueues(viewPort, false); + renderManager.setForcedTechnique(null); + renderManager.getRenderer().setFrameBuffer(viewPort.getOutputFrameBuffer()); + } + + @Override + protected Material getMaterial() { + return material; + } + + @Override + protected void initFilter(AssetManager manager, RenderManager renderManager, ViewPort vp, int w, int h) { + int screenWidth = w; + int screenHeight = h; + postRenderPasses = new ArrayList(); + + normalPass = new Pass(); + normalPass.init(renderManager.getRenderer(), (int) (screenWidth / downSampleFactor), (int) (screenHeight / downSampleFactor), Format.RGBA8, Format.Depth); + + + frustumNearFar = new Vector2f(); + + float farY = (vp.getCamera().getFrustumTop() / vp.getCamera().getFrustumNear()) * vp.getCamera().getFrustumFar(); + float farX = farY * ((float) screenWidth / (float) screenHeight); + frustumCorner = new Vector3f(farX, farY, vp.getCamera().getFrustumFar()); + frustumNearFar.x = vp.getCamera().getFrustumNear(); + frustumNearFar.y = vp.getCamera().getFrustumFar(); + + + + + + //ssao Pass + ssaoMat = new Material(manager, "Common/MatDefs/SSAO/ssao.j3md"); + ssaoMat.setTexture("Normals", normalPass.getRenderedTexture()); + Texture random = manager.loadTexture("Common/MatDefs/SSAO/Textures/random.png"); + random.setWrap(Texture.WrapMode.Repeat); + ssaoMat.setTexture("RandomMap", random); + + ssaoPass = new Pass() { + + @Override + public boolean requiresDepthAsTexture() { + return true; + } + }; + + ssaoPass.init(renderManager.getRenderer(), (int) (screenWidth / downSampleFactor), (int) (screenHeight / downSampleFactor), Format.RGBA8, Format.Depth, 1, ssaoMat); + ssaoPass.getRenderedTexture().setMinFilter(Texture.MinFilter.Trilinear); + ssaoPass.getRenderedTexture().setMagFilter(Texture.MagFilter.Bilinear); + postRenderPasses.add(ssaoPass); + material = new Material(manager, "Common/MatDefs/SSAO/ssaoBlur.j3md"); + material.setTexture("SSAOMap", ssaoPass.getRenderedTexture()); + + ssaoMat.setVector3("FrustumCorner", frustumCorner); + ssaoMat.setFloat("SampleRadius", sampleRadius); + ssaoMat.setFloat("Intensity", intensity); + ssaoMat.setFloat("Scale", scale); + ssaoMat.setFloat("Bias", bias); + material.setBoolean("UseAo", useAo); + material.setBoolean("UseOnlyAo", useOnlyAo); + ssaoMat.setVector2("FrustumNearFar", frustumNearFar); + material.setVector2("FrustumNearFar", frustumNearFar); + ssaoMat.setParam("Samples", VarType.Vector2Array, samples); + + float xScale = 1.0f / w; + float yScale = 1.0f / h; + + float blurScale = 2f; + material.setFloat("XScale", blurScale * xScale); + material.setFloat("YScale", blurScale * yScale); + + } + + /** + * Return the bias
+ * see {@link #setBias(float bias)} + * @return + */ + public float getBias() { + return bias; + } + + /** + * Sets the the width of the occlusion cone considered by the occludee default is 0.1f + * @param bias + */ + public void setBias(float bias) { + this.bias = bias; + if (ssaoMat != null) { + ssaoMat.setFloat("Bias", bias); + } + } + + /** + * returns the ambient occlusion intensity + * @return + */ + public float getIntensity() { + return intensity; + } + + /** + * Sets the Ambient occlusion intensity default is 1.2f + * @param intensity + */ + public void setIntensity(float intensity) { + this.intensity = intensity; + if (ssaoMat != null) { + ssaoMat.setFloat("Intensity", intensity); + } + + } + + /** + * returns the sample radius
+ * see {link setSampleRadius(float sampleRadius)} + * @return + */ + public float getSampleRadius() { + return sampleRadius; + } + + /** + * Sets the radius of the area where random samples will be picked dafault 5.1f + * @param sampleRadius + */ + public void setSampleRadius(float sampleRadius) { + this.sampleRadius = sampleRadius; + if (ssaoMat != null) { + ssaoMat.setFloat("SampleRadius", sampleRadius); + } + + } + + /** + * returns the scale
+ * see {@link #setScale(float scale)} + * @return + */ + public float getScale() { + return scale; + } + + /** + * + * Returns the distance between occluders and occludee. default 0.2f + * @param scale + */ + public void setScale(float scale) { + this.scale = scale; + if (ssaoMat != null) { + ssaoMat.setFloat("Scale", scale); + } + } + + /** + * debugging only , will be removed + * @return + */ + public boolean isUseAo() { + return useAo; + } + + /** + * debugging only , will be removed + */ + public void setUseAo(boolean useAo) { + this.useAo = useAo; + if (material != null) { + material.setBoolean("UseAo", useAo); + } + + } + + /** + * debugging only , will be removed + * @return + */ + public boolean isUseOnlyAo() { + return useOnlyAo; + } + + /** + * debugging only , will be removed + */ + public void setUseOnlyAo(boolean useOnlyAo) { + this.useOnlyAo = useOnlyAo; + if (material != null) { + material.setBoolean("UseOnlyAo", useOnlyAo); + } + } + + @Override + public void write(JmeExporter ex) throws IOException { + super.write(ex); + OutputCapsule oc = ex.getCapsule(this); + oc.write(sampleRadius, "sampleRadius", 5.1f); + oc.write(intensity, "intensity", 1.5f); + oc.write(scale, "scale", 0.2f); + oc.write(bias, "bias", 0.1f); + } + + @Override + public void read(JmeImporter im) throws IOException { + super.read(im); + InputCapsule ic = im.getCapsule(this); + sampleRadius = ic.readFloat("sampleRadius", 5.1f); + intensity = ic.readFloat("intensity", 1.5f); + scale = ic.readFloat("scale", 0.2f); + bias = ic.readFloat("bias", 0.1f); + } +} diff --git a/engine/src/core-effects/com/jme3/water/ReflectionProcessor.java b/engine/src/core-effects/com/jme3/water/ReflectionProcessor.java new file mode 100644 index 000000000..9a14df82f --- /dev/null +++ b/engine/src/core-effects/com/jme3/water/ReflectionProcessor.java @@ -0,0 +1,125 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.water; + +import com.jme3.math.Plane; +import com.jme3.post.SceneProcessor; +import com.jme3.renderer.Camera; +import com.jme3.renderer.RenderManager; +import com.jme3.renderer.ViewPort; +import com.jme3.renderer.queue.RenderQueue; +import com.jme3.texture.FrameBuffer; + +/** + * Reflection Processor + * Used to render the reflected scene in an off view port + */ +public class ReflectionProcessor implements SceneProcessor { + + private RenderManager rm; + private ViewPort vp; + private Camera reflectionCam; + private FrameBuffer reflectionBuffer; + private Plane reflectionClipPlane; + + /** + * Creates a ReflectionProcessor + * @param reflectionCam the cam to use for reflection + * @param reflectionBuffer the FrameBuffer to render to + * @param reflectionClipPlane the clipping plane + */ + public ReflectionProcessor(Camera reflectionCam, FrameBuffer reflectionBuffer, Plane reflectionClipPlane) { + this.reflectionCam = reflectionCam; + this.reflectionBuffer = reflectionBuffer; + this.reflectionClipPlane = reflectionClipPlane; + } + + public void initialize(RenderManager rm, ViewPort vp) { + this.rm = rm; + this.vp = vp; + } + + public void reshape(ViewPort vp, int w, int h) { + } + + public boolean isInitialized() { + return rm != null; + } + + public void preFrame(float tpf) { + } + + public void postQueue(RenderQueue rq) { + //we need special treatement for the sky because it must not be clipped + rm.getRenderer().setFrameBuffer(reflectionBuffer); + reflectionCam.setProjectionMatrix(null); + rm.setCamera(reflectionCam, false); + rm.getRenderer().clearBuffers(true, true, true); + //Rendering the sky whithout clipping + rm.getRenderer().setDepthRange(1, 1); + vp.getQueue().renderQueue(RenderQueue.Bucket.Sky, rm, reflectionCam, true); + rm.getRenderer().setDepthRange(0, 1); + //setting the clip plane to the cam + reflectionCam.setClipPlane(reflectionClipPlane, Plane.Side.Positive);//,1 + rm.setCamera(reflectionCam, false); + + } + + public void postFrame(FrameBuffer out) { + } + + public void cleanup() { + } + + /** + * Internal use only
+ * returns the frame buffer + * @return + */ + public FrameBuffer getReflectionBuffer() { + return reflectionBuffer; + } + + /** + * Internal use only
+ * sets the frame buffer + * @param reflectionBuffer + */ + public void setReflectionBuffer(FrameBuffer reflectionBuffer) { + this.reflectionBuffer = reflectionBuffer; + } + + /** + * returns the reflection cam + * @return + */ + public Camera getReflectionCam() { + return reflectionCam; + } + + /** + * sets the reflection cam + * @param reflectionCam + */ + public void setReflectionCam(Camera reflectionCam) { + this.reflectionCam = reflectionCam; + } + + /** + * returns the reflection clip plane + * @return + */ + public Plane getReflectionClipPlane() { + return reflectionClipPlane; + } + + /** + * Sets the reflection clip plane + * @param reflectionClipPlane + */ + public void setReflectionClipPlane(Plane reflectionClipPlane) { + this.reflectionClipPlane = reflectionClipPlane; + } +} diff --git a/engine/src/core-effects/com/jme3/water/SimpleWaterProcessor.java b/engine/src/core-effects/com/jme3/water/SimpleWaterProcessor.java new file mode 100644 index 000000000..70ccd1130 --- /dev/null +++ b/engine/src/core-effects/com/jme3/water/SimpleWaterProcessor.java @@ -0,0 +1,589 @@ +/* + * Copyright (c) 2009-2010 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 com.jme3.water; + +import com.jme3.asset.AssetManager; +import com.jme3.material.Material; +import com.jme3.math.*; +import com.jme3.post.SceneProcessor; +import com.jme3.renderer.Camera; +import com.jme3.renderer.RenderManager; +import com.jme3.renderer.Renderer; +import com.jme3.renderer.ViewPort; +import com.jme3.renderer.queue.RenderQueue; +import com.jme3.scene.Geometry; +import com.jme3.scene.Spatial; +import com.jme3.scene.shape.Quad; +import com.jme3.texture.FrameBuffer; +import com.jme3.texture.Image.Format; +import com.jme3.texture.Texture.WrapMode; +import com.jme3.texture.Texture2D; +import com.jme3.ui.Picture; + +/** + * + * Simple Water renders a simple plane that use reflection and refraction to look like water. + * It's pretty basic, but much faster than the WaterFilter + * It's useful if you aim low specs hardware and still want a good looking water. + * Usage is : + * + * SimpleWaterProcessor waterProcessor = new SimpleWaterProcessor(assetManager); + * //setting the scene to use for reflection + * waterProcessor.setReflectionScene(mainScene); + * //setting the light position + * waterProcessor.setLightPosition(lightPos); + * + * //setting the water plane + * Vector3f waterLocation=new Vector3f(0,-20,0); + * waterProcessor.setPlane(new Plane(Vector3f.UNIT_Y, waterLocation.dot(Vector3f.UNIT_Y))); + * //setting the water color + * waterProcessor.setWaterColor(ColorRGBA.Brown); + * + * //creating a quad to render water to + * Quad quad = new Quad(400,400); + * + * //the texture coordinates define the general size of the waves + * quad.scaleTextureCoordinates(new Vector2f(6f,6f)); + * + * //creating a geom to attach the water material + * Geometry water=new Geometry("water", quad); + * water.setLocalTranslation(-200, -20, 250); + * water.setLocalRotation(new Quaternion().fromAngleAxis(-FastMath.HALF_PI, Vector3f.UNIT_X)); + * //finally setting the material + * water.setMaterial(waterProcessor.getMaterial()); + * + * //attaching the water to the root node + * rootNode.attachChild(water); + * + * @author Normen Hansen & Rémy Bouquet + */ +public class SimpleWaterProcessor implements SceneProcessor { + + protected RenderManager rm; + protected ViewPort vp; + protected Spatial reflectionScene; + protected ViewPort reflectionView; + protected ViewPort refractionView; + protected FrameBuffer reflectionBuffer; + protected FrameBuffer refractionBuffer; + protected Camera reflectionCam; + protected Camera refractionCam; + protected Texture2D reflectionTexture; + protected Texture2D refractionTexture; + protected Texture2D depthTexture; + protected Texture2D normalTexture; + protected Texture2D dudvTexture; + protected int renderWidth = 512; + protected int renderHeight = 512; + protected Plane plane = new Plane(Vector3f.UNIT_Y, Vector3f.ZERO.dot(Vector3f.UNIT_Y)); + protected float speed = 0.05f; + protected Ray ray = new Ray(); + protected Vector3f targetLocation = new Vector3f(); + protected AssetManager manager; + protected Material material; + protected float waterDepth = 1; + protected float waterTransparency = 0.4f; + protected boolean debug = false; + private Picture dispRefraction; + private Picture dispReflection; + private Picture dispDepth; + private Plane reflectionClipPlane; + private Plane refractionClipPlane; + private float refractionClippingOffset = 0.3f; + private float reflectionClippingOffset = -5f; + private Vector3f vect1 = new Vector3f(); + private Vector3f vect2 = new Vector3f(); + private Vector3f vect3 = new Vector3f(); + + /** + * Creates a SimpleWaterProcessor + * @param manager the asset manager + */ + public SimpleWaterProcessor(AssetManager manager) { + this.manager = manager; + material = new Material(manager, "Common/MatDefs/Water/SimpleWater.j3md"); + material.setFloat("waterDepth", waterDepth); + material.setFloat("waterTransparency", waterTransparency / 10); + material.setColor("waterColor", ColorRGBA.White); + material.setVector3("lightPos", new Vector3f(1, -1, 1)); + + material.setColor("distortionScale", new ColorRGBA(0.2f, 0.2f, 0.2f, 0.2f)); + material.setColor("distortionMix", new ColorRGBA(0.5f, 0.5f, 0.5f, 0.5f)); + material.setColor("texScale", new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f)); + updateClipPlanes(); + + } + + public void initialize(RenderManager rm, ViewPort vp) { + this.rm = rm; + this.vp = vp; + + loadTextures(manager); + createTextures(); + applyTextures(material); + + createPreViews(); + + material.setVector2("FrustumNearFar", new Vector2f(vp.getCamera().getFrustumNear(), vp.getCamera().getFrustumFar())); + + if (debug) { + dispRefraction = new Picture("dispRefraction"); + dispRefraction.setTexture(manager, refractionTexture, false); + dispReflection = new Picture("dispRefraction"); + dispReflection.setTexture(manager, reflectionTexture, false); + dispDepth = new Picture("depthTexture"); + dispDepth.setTexture(manager, depthTexture, false); + } + } + + public void reshape(ViewPort vp, int w, int h) { + } + + public boolean isInitialized() { + return rm != null; + } + float time = 0; + float savedTpf = 0; + + public void preFrame(float tpf) { + time = time + (tpf * speed); + if (time > 1f) { + time = 0; + } + material.setFloat("time", time); + savedTpf = tpf; + } + + public void postQueue(RenderQueue rq) { + Camera sceneCam = rm.getCurrentCamera(); + + //update ray + ray.setOrigin(sceneCam.getLocation()); + ray.setDirection(sceneCam.getDirection()); + + //update refraction cam + refractionCam.setLocation(sceneCam.getLocation()); + refractionCam.setRotation(sceneCam.getRotation()); + refractionCam.setFrustum(sceneCam.getFrustumNear(), + sceneCam.getFrustumFar(), + sceneCam.getFrustumLeft(), + sceneCam.getFrustumRight(), + sceneCam.getFrustumTop(), + sceneCam.getFrustumBottom()); + + //update reflection cam + boolean inv = false; + if (!ray.intersectsWherePlane(plane, targetLocation)) { + ray.setDirection(ray.getDirection().negateLocal()); + ray.intersectsWherePlane(plane, targetLocation); + inv = true; + } + Vector3f loc = plane.reflect(sceneCam.getLocation(), new Vector3f()); + reflectionCam.setLocation(loc); + reflectionCam.setFrustum(sceneCam.getFrustumNear(), + sceneCam.getFrustumFar(), + sceneCam.getFrustumLeft(), + sceneCam.getFrustumRight(), + sceneCam.getFrustumTop(), + sceneCam.getFrustumBottom()); + // tempVec and calcVect are just temporary vector3f objects + vect1.set(sceneCam.getLocation()).addLocal(sceneCam.getUp()); + float planeDistance = plane.pseudoDistance(vect1); + vect2.set(plane.getNormal()).multLocal(planeDistance * 2.0f); + vect3.set(vect1.subtractLocal(vect2)).subtractLocal(loc).normalizeLocal().negateLocal(); + // now set the up vector + reflectionCam.lookAt(targetLocation, vect3); + if (inv) { + reflectionCam.setAxes(reflectionCam.getLeft().negateLocal(), reflectionCam.getUp(), reflectionCam.getDirection().negateLocal()); + } + + //Rendering reflection and refraction + rm.renderViewPort(reflectionView, savedTpf); + rm.renderViewPort(refractionView, savedTpf); + rm.getRenderer().setFrameBuffer(vp.getOutputFrameBuffer()); + rm.setCamera(sceneCam, false); + + } + + public void postFrame(FrameBuffer out) { + if (debug) { + displayMap(rm.getRenderer(), dispRefraction, 64); + displayMap(rm.getRenderer(), dispReflection, 256); + displayMap(rm.getRenderer(), dispDepth, 448); + } + } + + public void cleanup() { + } + + //debug only : displays maps + protected void displayMap(Renderer r, Picture pic, int left) { + Camera cam = vp.getCamera(); + rm.setCamera(cam, true); + int h = cam.getHeight(); + + pic.setPosition(left, h / 20f); + + pic.setWidth(128); + pic.setHeight(128); + pic.updateGeometricState(); + rm.renderGeometry(pic); + rm.setCamera(cam, false); + } + + protected void loadTextures(AssetManager manager) { + normalTexture = (Texture2D) manager.loadTexture("Common/MatDefs/Water/Textures/water_normalmap.dds"); + dudvTexture = (Texture2D) manager.loadTexture("Common/MatDefs/Water/Textures/dudv_map.jpg"); + normalTexture.setWrap(WrapMode.Repeat); + dudvTexture.setWrap(WrapMode.Repeat); + } + + protected void createTextures() { + reflectionTexture = new Texture2D(renderWidth, renderHeight, Format.RGBA8); + refractionTexture = new Texture2D(renderWidth, renderHeight, Format.RGBA8); + depthTexture = new Texture2D(renderWidth, renderHeight, Format.Depth); + } + + protected void applyTextures(Material mat) { + mat.setTexture("water_reflection", reflectionTexture); + mat.setTexture("water_refraction", refractionTexture); + mat.setTexture("water_depthmap", depthTexture); + mat.setTexture("water_normalmap", normalTexture); + mat.setTexture("water_dudvmap", dudvTexture); + } + + protected void createPreViews() { + reflectionCam = new Camera(renderWidth, renderHeight); + refractionCam = new Camera(renderWidth, renderHeight); + + // create a pre-view. a view that is rendered before the main view + reflectionView = new ViewPort("Reflection View", reflectionCam); + reflectionView.setClearFlags(true, true, true); + reflectionView.setBackgroundColor(ColorRGBA.Black); + // create offscreen framebuffer + reflectionBuffer = new FrameBuffer(renderWidth, renderHeight, 1); + //setup framebuffer to use texture + reflectionBuffer.setDepthBuffer(Format.Depth); + reflectionBuffer.setColorTexture(reflectionTexture); + + //set viewport to render to offscreen framebuffer + reflectionView.setOutputFrameBuffer(reflectionBuffer); + reflectionView.addProcessor(new ReflectionProcessor(reflectionCam, reflectionBuffer, reflectionClipPlane)); + // attach the scene to the viewport to be rendered + reflectionView.attachScene(reflectionScene); + + // create a pre-view. a view that is rendered before the main view + refractionView = new ViewPort("Refraction View", refractionCam); + refractionView.setClearFlags(true, true, true); + refractionView.setBackgroundColor(ColorRGBA.Black); + // create offscreen framebuffer + refractionBuffer = new FrameBuffer(renderWidth, renderHeight, 1); + //setup framebuffer to use texture + refractionBuffer.setDepthBuffer(Format.Depth); + refractionBuffer.setColorTexture(refractionTexture); + refractionBuffer.setDepthTexture(depthTexture); + //set viewport to render to offscreen framebuffer + refractionView.setOutputFrameBuffer(refractionBuffer); + refractionView.addProcessor(new RefractionProcessor()); + // attach the scene to the viewport to be rendered + refractionView.attachScene(reflectionScene); + } + + protected void destroyViews() { + // rm.removePreView(reflectionView); + rm.removePreView(refractionView); + } + + /** + * Get the water material from this processor, apply this to your water quad. + * @return + */ + public Material getMaterial() { + return material; + } + + /** + * Sets the reflected scene, should not include the water quad! + * Set before adding processor. + * @param spat + */ + public void setReflectionScene(Spatial spat) { + reflectionScene = spat; + } + + /** + * returns the width of the reflection and refraction textures + * @return + */ + public int getRenderWidth() { + return renderWidth; + } + + /** + * returns the height of the reflection and refraction textures + * @return + */ + public int getRenderHeight() { + return renderHeight; + } + + /** + * Set the reflection Texture render size, + * set before adding the processor! + * @param with + * @param height + */ + public void setRenderSize(int width, int height) { + renderWidth = width; + renderHeight = height; + } + + /** + * returns the water plane + * @return + */ + public Plane getPlane() { + return plane; + } + + /** + * Set the water plane for this processor. + * @param plane + */ + public void setPlane(Plane plane) { + this.plane.setConstant(plane.getConstant()); + this.plane.setNormal(plane.getNormal()); + updateClipPlanes(); + } + + /** + * Set the water plane using an origin (location) and a normal (reflection direction). + * @param origin Set to 0,-6,0 if your water quad is at that location for correct reflection + * @param normal Set to 0,1,0 (Vector3f.UNIT_Y) for normal planar water + */ + public void setPlane(Vector3f origin, Vector3f normal) { + this.plane.setOriginNormal(origin, normal); + updateClipPlanes(); + } + + private void updateClipPlanes() { + reflectionClipPlane = plane.clone(); + reflectionClipPlane.setConstant(reflectionClipPlane.getConstant() + reflectionClippingOffset); + refractionClipPlane = plane.clone(); + refractionClipPlane.setConstant(refractionClipPlane.getConstant() + refractionClippingOffset); + + } + + /** + * Set the light Position for the processor + * @param position + */ + //TODO maybe we should provide a convenient method to compute position from direction + public void setLightPosition(Vector3f position) { + material.setVector3("lightPos", position); + } + + /** + * Set the color that will be added to the refraction texture. + * @param color + */ + public void setWaterColor(ColorRGBA color) { + material.setColor("waterColor", color); + } + + /** + * Higher values make the refraction texture shine through earlier. + * Default is 4 + * @param depth + */ + public void setWaterDepth(float depth) { + waterDepth = depth; + material.setFloat("waterDepth", depth); + } + + /** + * return the water depth + * @return + */ + public float getWaterDepth() { + return waterDepth; + } + + /** + * returns water transparency + * @return + */ + public float getWaterTransparency() { + return waterTransparency; + } + + /** + * sets the water transparency default os 0.1f + * @param waterTransparency + */ + public void setWaterTransparency(float waterTransparency) { + this.waterTransparency = Math.max(0, waterTransparency); + material.setFloat("waterTransparency", waterTransparency / 10); + } + + /** + * Sets the speed of the wave animation, default = 0.05f. + * @param speed + */ + public void setWaveSpeed(float speed) { + this.speed = speed; + } + + /** + * Sets the scale of distortion by the normal map, default = 0.2 + */ + public void setDistortionScale(float value) { + material.setColor("distortionScale", new ColorRGBA(value, value, value, value)); + } + + /** + * Sets how the normal and dudv map are mixed to create the wave effect, default = 0.5 + */ + public void setDistortionMix(float value) { + material.setColor("distortionMix", new ColorRGBA(value, value, value, value)); + } + + /** + * Sets the scale of the normal/dudv texture, default = 1. + * Note that the waves should be scaled by the texture coordinates of the quad to avoid animation artifacts, + * use mesh.scaleTextureCoordinates(Vector2f) for that. + */ + public void setTexScale(float value) { + material.setColor("texScale", new ColorRGBA(value, value, value, value)); + } + + /** + * retruns true if the waterprocessor is in debug mode + * @return + */ + public boolean isDebug() { + return debug; + } + + /** + * set to true to display reflection and refraction textures in the GUI for debug purpose + * @param debug + */ + public void setDebug(boolean debug) { + this.debug = debug; + } + + /** + * Creates a quad with the water material applied to it. + * @param width + * @param height + * @return + */ + public Geometry createWaterGeometry(float width, float height) { + Quad quad = new Quad(width, height); + Geometry geom = new Geometry("WaterGeometry", quad); + geom.setLocalRotation(new Quaternion().fromAngleAxis(-FastMath.HALF_PI, Vector3f.UNIT_X)); + geom.setMaterial(material); + return geom; + } + + /** + * returns the reflection clipping plane offset + * @return + */ + public float getReflectionClippingOffset() { + return reflectionClippingOffset; + } + + /** + * sets the reflection clipping plane offset + * set a nagetive value to lower the clipping plane for relection texture rendering. + * @param reflectionClippingOffset + */ + public void setReflectionClippingOffset(float reflectionClippingOffset) { + this.reflectionClippingOffset = reflectionClippingOffset; + updateClipPlanes(); + } + + /** + * returns the refraction clipping plane offset + * @return + */ + public float getRefractionClippingOffset() { + return refractionClippingOffset; + } + + /** + * Sets the refraction clipping plane offset + * set a positive value to raise the clipping plane for refraction texture rendering + * @param refractionClippingOffset + */ + public void setRefractionClippingOffset(float refractionClippingOffset) { + this.refractionClippingOffset = refractionClippingOffset; + updateClipPlanes(); + } + + /** + * Refraction Processor + */ + public class RefractionProcessor implements SceneProcessor { + + RenderManager rm; + ViewPort vp; + + public void initialize(RenderManager rm, ViewPort vp) { + this.rm = rm; + this.vp = vp; + } + + public void reshape(ViewPort vp, int w, int h) { + } + + public boolean isInitialized() { + return rm != null; + } + + public void preFrame(float tpf) { + refractionCam.setClipPlane(refractionClipPlane, Plane.Side.Negative);//,-1 + + } + + public void postQueue(RenderQueue rq) { + } + + public void postFrame(FrameBuffer out) { + } + + public void cleanup() { + } + } +} diff --git a/engine/src/core-effects/com/jme3/water/WaterFilter.java b/engine/src/core-effects/com/jme3/water/WaterFilter.java new file mode 100644 index 000000000..2943dce51 --- /dev/null +++ b/engine/src/core-effects/com/jme3/water/WaterFilter.java @@ -0,0 +1,1050 @@ +/* + * 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 com.jme3.water; + +import com.jme3.asset.AssetManager; +import com.jme3.export.InputCapsule; +import com.jme3.export.JmeExporter; +import com.jme3.export.JmeImporter; +import com.jme3.export.OutputCapsule; +import com.jme3.light.DirectionalLight; +import com.jme3.light.Light; +import com.jme3.material.Material; +import com.jme3.math.*; +import com.jme3.post.Filter; +import com.jme3.post.Filter.Pass; +import com.jme3.renderer.Camera; +import com.jme3.renderer.RenderManager; +import com.jme3.renderer.ViewPort; +import com.jme3.scene.Node; +import com.jme3.scene.Spatial; +import com.jme3.texture.Image.Format; +import com.jme3.texture.Texture.WrapMode; +import com.jme3.texture.Texture2D; +import com.jme3.util.TempVars; +import java.io.IOException; + +/** + * The WaterFilter is a 2D post process that simulate water. + * It renders water above and under water. + * See this blog post for more info http://jmonkeyengine.org/2011/01/15/new-advanced-water-effect-for-jmonkeyengine-3/ + * + * + * @author Rémy Bouquet aka Nehon + */ +public class WaterFilter extends Filter { + + private Pass reflectionPass; + protected Spatial reflectionScene; + protected ViewPort reflectionView; + private Texture2D normalTexture; + private Texture2D foamTexture; + private Texture2D causticsTexture; + private Texture2D heightTexture; + private Plane plane; + private Camera reflectionCam; + protected Ray ray = new Ray(); + private Vector3f targetLocation = new Vector3f(); + private ReflectionProcessor reflectionProcessor; + private Matrix4f biasMatrix = new Matrix4f(0.5f, 0.0f, 0.0f, 0.5f, + 0.0f, 0.5f, 0.0f, 0.5f, + 0.0f, 0.0f, 0.0f, 0.5f, + 0.0f, 0.0f, 0.0f, 1.0f); + private Matrix4f textureProjMatrix = new Matrix4f(); + private boolean underWater; + private RenderManager renderManager; + private ViewPort viewPort; + private float time = 0; + //properties + private float speed = 1; + private Vector3f lightDirection = new Vector3f(0, -1, 0); + private ColorRGBA lightColor = ColorRGBA.White; + private float waterHeight = 0.0f; + private ColorRGBA waterColor = new ColorRGBA(0.0078f, 0.3176f, 0.5f, 1.0f); + private ColorRGBA deepWaterColor = new ColorRGBA(0.0039f, 0.00196f, 0.145f, 1.0f); + private Vector3f colorExtinction = new Vector3f(5.0f, 20.0f, 30.0f); + private float waterTransparency = 0.1f; + private float maxAmplitude = 1.5f; + private float shoreHardness = 0.1f; + private boolean useFoam = true; + private float foamIntensity = 0.5f; + private float foamHardness = 1.0f; + private Vector3f foamExistence = new Vector3f(0.45f, 4.35f, 1.5f); + private float waveScale = 0.005f; + private float sunScale = 3.0f; + private float shininess = 0.7f; + private Vector2f windDirection = new Vector2f(0.0f, -1.0f); + private int reflectionMapSize = 512; + private boolean useRipples = true; + private float normalScale = 3.0f; + private boolean useHQShoreline = true; + private boolean useSpecular = true; + private boolean useRefraction = true; + private float refractionStrength = 0.0f; + private float refractionConstant = 0.5f; + private float reflectionDisplace = 30; + private float underWaterFogDistance = 120; + private boolean useCaustics = true; + private float causticsIntensity = 0.5f; + + /** + * Create a Water Filter + */ + public WaterFilter() { + super("WaterFilter"); + } + + public WaterFilter(Node reflectionScene, Vector3f lightDirection) { + super("WaterFilter"); + this.reflectionScene = reflectionScene; + this.lightDirection = lightDirection; + } + + @Override + protected boolean isRequiresDepthTexture() { + return true; + } + + @Override + protected void preFrame(float tpf) { + time = time + (tpf * speed); + material.setFloat("Time", time); + Camera sceneCam = viewPort.getCamera(); + biasMatrix.mult(sceneCam.getViewProjectionMatrix(), textureProjMatrix); + material.setMatrix4("TextureProjMatrix", textureProjMatrix); + material.setVector3("CameraPosition", sceneCam.getLocation()); + material.setMatrix4("ViewProjectionMatrixInverse", sceneCam.getViewProjectionMatrix().invert()); + + material.setFloat("WaterHeight", waterHeight); + + //update reflection cam + ray.setOrigin(sceneCam.getLocation()); + ray.setDirection(sceneCam.getDirection()); + plane = new Plane(Vector3f.UNIT_Y, new Vector3f(0, waterHeight, 0).dot(Vector3f.UNIT_Y)); + reflectionProcessor.setReflectionClipPlane(plane); + boolean inv = false; + if (!ray.intersectsWherePlane(plane, targetLocation)) { + ray.setDirection(ray.getDirection().negateLocal()); + ray.intersectsWherePlane(plane, targetLocation); + inv = true; + } + Vector3f loc = plane.reflect(sceneCam.getLocation(), new Vector3f()); + reflectionCam.setLocation(loc); + reflectionCam.setFrustum(sceneCam.getFrustumNear(), + sceneCam.getFrustumFar(), + sceneCam.getFrustumLeft(), + sceneCam.getFrustumRight(), + sceneCam.getFrustumTop(), + sceneCam.getFrustumBottom()); + TempVars vars = TempVars.get(); + + + vars.vect1.set(sceneCam.getLocation()).addLocal(sceneCam.getUp()); + float planeDistance = plane.pseudoDistance(vars.vect1); + vars.vect2.set(plane.getNormal()).multLocal(planeDistance * 2.0f); + vars.vect3.set(vars.vect1.subtractLocal(vars.vect2)).subtractLocal(loc).normalizeLocal().negateLocal(); + + reflectionCam.lookAt(targetLocation, vars.vect3); + vars.release(); + + if (inv) { + reflectionCam.setAxes(reflectionCam.getLeft().negateLocal(), reflectionCam.getUp(), reflectionCam.getDirection().negateLocal()); + } + + //if we're under water no need to compute reflection + if (sceneCam.getLocation().y >= waterHeight) { + boolean rtb = true; + if (!renderManager.isHandleTranslucentBucket()) { + renderManager.setHandleTranslucentBucket(true); + rtb = false; + } + renderManager.renderViewPort(reflectionView, tpf); + if (!rtb) { + renderManager.setHandleTranslucentBucket(false); + } + renderManager.setCamera(sceneCam, false); + renderManager.getRenderer().setFrameBuffer(viewPort.getOutputFrameBuffer()); + + + underWater = false; + } else { + underWater = true; + } + } + + @Override + protected Material getMaterial() { + return material; + } + + private DirectionalLight findLight(Node node) { + for (Light light : node.getWorldLightList()) { + if (light instanceof DirectionalLight) { + return (DirectionalLight) light; + } + } + for (Spatial child : node.getChildren()) { + if (child instanceof Node) { + return findLight((Node) child); + } + } + + return null; + } + + @Override + protected void initFilter(AssetManager manager, RenderManager renderManager, ViewPort vp, int w, int h) { + + if (reflectionScene == null) { + reflectionScene = vp.getScenes().get(0); + DirectionalLight l = findLight((Node) reflectionScene); + if (l != null) { + lightDirection = l.getDirection(); + } + + } + + this.renderManager = renderManager; + this.viewPort = vp; + reflectionPass = new Pass(); + reflectionPass.init(renderManager.getRenderer(), reflectionMapSize, reflectionMapSize, Format.RGBA8, Format.Depth); + reflectionCam = new Camera(reflectionMapSize, reflectionMapSize); + reflectionView = new ViewPort("reflectionView", reflectionCam); + reflectionView.setClearFlags(true, true, true); + reflectionView.attachScene(reflectionScene); + reflectionView.setOutputFrameBuffer(reflectionPass.getRenderFrameBuffer()); + plane = new Plane(Vector3f.UNIT_Y, new Vector3f(0, waterHeight, 0).dot(Vector3f.UNIT_Y)); + reflectionProcessor = new ReflectionProcessor(reflectionCam, reflectionPass.getRenderFrameBuffer(), plane); + reflectionView.addProcessor(reflectionProcessor); + + normalTexture = (Texture2D) manager.loadTexture("Common/MatDefs/Water/Textures/water_normalmap.dds"); + if (foamTexture == null) { + foamTexture = (Texture2D) manager.loadTexture("Common/MatDefs/Water/Textures/foam.jpg"); + } + if (causticsTexture == null) { + causticsTexture = (Texture2D) manager.loadTexture("Common/MatDefs/Water/Textures/caustics.jpg"); + } + heightTexture = (Texture2D) manager.loadTexture("Common/MatDefs/Water/Textures/heightmap.jpg"); + + normalTexture.setWrap(WrapMode.Repeat); + foamTexture.setWrap(WrapMode.Repeat); + causticsTexture.setWrap(WrapMode.Repeat); + heightTexture.setWrap(WrapMode.Repeat); + + material = new Material(manager, "Common/MatDefs/Water/Water.j3md"); + material.setTexture("HeightMap", heightTexture); + material.setTexture("CausticsMap", causticsTexture); + material.setTexture("FoamMap", foamTexture); + material.setTexture("NormalMap", normalTexture); + material.setTexture("ReflectionMap", reflectionPass.getRenderedTexture()); + + material.setFloat("WaterTransparency", waterTransparency); + material.setFloat("NormalScale", normalScale); + material.setFloat("R0", refractionConstant); + material.setFloat("MaxAmplitude", maxAmplitude); + material.setVector3("LightDir", lightDirection); + material.setColor("LightColor", lightColor); + material.setFloat("ShoreHardness", shoreHardness); + material.setFloat("RefractionStrength", refractionStrength); + material.setFloat("WaveScale", waveScale); + material.setVector3("FoamExistence", foamExistence); + material.setFloat("SunScale", sunScale); + material.setVector3("ColorExtinction", colorExtinction); + material.setFloat("Shininess", shininess); + material.setColor("WaterColor", waterColor); + material.setColor("DeepWaterColor", deepWaterColor); + material.setVector2("WindDirection", windDirection); + material.setFloat("FoamHardness", foamHardness); + material.setBoolean("UseRipples", useRipples); + material.setBoolean("UseHQShoreline", useHQShoreline); + material.setBoolean("UseSpecular", useSpecular); + material.setBoolean("UseFoam", useFoam); + material.setBoolean("UseCaustics", useCaustics); + material.setBoolean("UseRefraction", useRefraction); + material.setFloat("ReflectionDisplace", reflectionDisplace); + material.setFloat("FoamIntensity", foamIntensity); + material.setFloat("UnderWaterFogDistance", underWaterFogDistance); + material.setFloat("CausticsIntensity", causticsIntensity); + + + } + + @Override + public void write(JmeExporter ex) throws IOException { + super.write(ex); + OutputCapsule oc = ex.getCapsule(this); + + oc.write(speed, "speed", 1f); + oc.write(lightDirection, "lightDirection", new Vector3f(0, -1, 0)); + oc.write(lightColor, "lightColor", ColorRGBA.White); + oc.write(waterHeight, "waterHeight", 0.0f); + oc.write(waterColor, "waterColor", new ColorRGBA(0.0078f, 0.3176f, 0.5f, 1.0f)); + oc.write(deepWaterColor, "deepWaterColor", new ColorRGBA(0.0039f, 0.00196f, 0.145f, 1.0f)); + + oc.write(colorExtinction, "colorExtinction", new Vector3f(5.0f, 20.0f, 30.0f)); + oc.write(waterTransparency, "waterTransparency", 0.1f); + oc.write(maxAmplitude, "maxAmplitude", 1.5f); + oc.write(shoreHardness, "shoreHardness", 0.1f); + oc.write(useFoam, "useFoam", true); + + oc.write(foamIntensity, "foamIntensity", 0.5f); + oc.write(foamHardness, "foamHardness", 1.0f); + + oc.write(foamExistence, "foamExistence", new Vector3f(0.45f, 4.35f, 1.5f)); + oc.write(waveScale, "waveScale", 0.005f); + + oc.write(sunScale, "sunScale", 3.0f); + oc.write(shininess, "shininess", 0.7f); + oc.write(windDirection, "windDirection", new Vector2f(0.0f, -1.0f)); + oc.write(reflectionMapSize, "reflectionMapSize", 512); + oc.write(useRipples, "useRipples", true); + + oc.write(normalScale, "normalScale", 3.0f); + oc.write(useHQShoreline, "useHQShoreline", true); + + oc.write(useSpecular, "useSpecular", true); + + oc.write(useRefraction, "useRefraction", true); + oc.write(refractionStrength, "refractionStrength", 0.0f); + oc.write(refractionConstant, "refractionConstant", 0.5f); + oc.write(reflectionDisplace, "reflectionDisplace", 30f); + oc.write(underWaterFogDistance, "underWaterFogDistance", 120f); + oc.write(causticsIntensity, "causticsIntensity", 0.5f); + + oc.write(useCaustics, "useCaustics", true); + } + + @Override + public void read(JmeImporter im) throws IOException { + super.read(im); + InputCapsule ic = im.getCapsule(this); + speed = ic.readFloat("speed", 1f); + lightDirection = (Vector3f) ic.readSavable("lightDirection", new Vector3f(0, -1, 0)); + lightColor = (ColorRGBA) ic.readSavable("lightColor", ColorRGBA.White); + waterHeight = ic.readFloat("waterHeight", 0.0f); + waterColor = (ColorRGBA) ic.readSavable("waterColor", new ColorRGBA(0.0078f, 0.3176f, 0.5f, 1.0f)); + deepWaterColor = (ColorRGBA) ic.readSavable("deepWaterColor", new ColorRGBA(0.0039f, 0.00196f, 0.145f, 1.0f)); + + colorExtinction = (Vector3f) ic.readSavable("colorExtinction", new Vector3f(5.0f, 20.0f, 30.0f)); + waterTransparency = ic.readFloat("waterTransparency", 0.1f); + maxAmplitude = ic.readFloat("maxAmplitude", 1.5f); + shoreHardness = ic.readFloat("shoreHardness", 0.1f); + useFoam = ic.readBoolean("useFoam", true); + + foamIntensity = ic.readFloat("foamIntensity", 0.5f); + foamHardness = ic.readFloat("foamHardness", 1.0f); + + foamExistence = (Vector3f) ic.readSavable("foamExistence", new Vector3f(0.45f, 4.35f, 1.5f)); + waveScale = ic.readFloat("waveScale", 0.005f); + + sunScale = ic.readFloat("sunScale", 3.0f); + shininess = ic.readFloat("shininess", 0.7f); + windDirection = (Vector2f) ic.readSavable("windDirection", new Vector2f(0.0f, -1.0f)); + reflectionMapSize = ic.readInt("reflectionMapSize", 512); + useRipples = ic.readBoolean("useRipples", true); + + normalScale = ic.readFloat("normalScale", 3.0f); + useHQShoreline = ic.readBoolean("useHQShoreline", true); + + useSpecular = ic.readBoolean("useSpecular", true); + + useRefraction = ic.readBoolean("useRefraction", true); + refractionStrength = ic.readFloat("refractionStrength", 0.0f); + refractionConstant = ic.readFloat("refractionConstant", 0.5f); + reflectionDisplace = ic.readFloat("reflectionDisplace", 30f); + underWaterFogDistance = ic.readFloat("underWaterFogDistance", 120f); + causticsIntensity = ic.readFloat("causticsIntensity", 0.5f); + + useCaustics = ic.readBoolean("useCaustics", true); + + } + + /** + * gets the height of the water plane + * @return + */ + public float getWaterHeight() { + return waterHeight; + } + + /** + * Sets the height of the water plane + * default is 0.0 + * @param waterHeight + */ + public void setWaterHeight(float waterHeight) { + this.waterHeight = waterHeight; + } + + /** + * sets the scene to render in the reflection map + * @param reflectionScene + */ + public void setReflectionScene(Spatial reflectionScene) { + this.reflectionScene = reflectionScene; + } + + /** + * returns the waterTransparency value + * @return + */ + public float getWaterTransparency() { + return waterTransparency; + } + + /** + * Sets how fast will colours fade out. You can also think about this + * values as how clear water is. Therefore use smaller values (eg. 0.05) + * to have crystal clear water and bigger to achieve "muddy" water. + * default is 0.1f + * @param waterTransparency + */ + public void setWaterTransparency(float waterTransparency) { + this.waterTransparency = waterTransparency; + if (material != null) { + material.setFloat("WaterTransparency", waterTransparency); + } + } + + /** + * Returns the normal scales applied to the normal map + * @return + */ + public float getNormalScale() { + return normalScale; + } + + /** + * Sets the normal scaling factors to apply to the normal map. + * the higher the value the more small ripples will be visible on the waves. + * default is 1.0 + * @param normalScale + */ + public void setNormalScale(float normalScale) { + this.normalScale = normalScale; + if (material != null) { + material.setFloat("NormalScale", normalScale); + } + } + + /** + * returns the refractoin constant + * @return + */ + public float getRefractionConstant() { + return refractionConstant; + } + + /** + * This is a constant related to the index of refraction (IOR) used to compute the fresnel term. + * F = R0 + (1-R0)( 1 - N.V)^5 + * where F is the fresnel term, R0 the constant, N the normal vector and V tne view vector. + * It usually depend on the material you are lookinh through (here water). + * Default value is 0.3f + * In practice, the lowest the value and the less the reflection can be seen on water + * @param refractionConstant + */ + public void setRefractionConstant(float refractionConstant) { + this.refractionConstant = refractionConstant; + if (material != null) { + material.setFloat("R0", refractionConstant); + } + } + + /** + * return the maximum wave amplitude + * @return + */ + public float getMaxAmplitude() { + return maxAmplitude; + } + + /** + * Sets the maximum waves amplitude + * default is 1.0 + * @param maxAmplitude + */ + public void setMaxAmplitude(float maxAmplitude) { + this.maxAmplitude = maxAmplitude; + if (material != null) { + material.setFloat("MaxAmplitude", maxAmplitude); + } + } + + /** + * gets the light direction + * @return + */ + public Vector3f getLightDirection() { + return lightDirection; + } + + /** + * Sets the light direction + * @param lightDirection + */ + public void setLightDirection(Vector3f lightDirection) { + this.lightDirection = lightDirection; + if (material != null) { + material.setVector3("LightDir", lightDirection); + } + } + + /** + * returns the light color + * @return + */ + public ColorRGBA getLightColor() { + return lightColor; + } + + /** + * Sets the light color to use + * default is white + * @param lightColor + */ + public void setLightColor(ColorRGBA lightColor) { + this.lightColor = lightColor; + if (material != null) { + material.setColor("LightColor", lightColor); + } + } + + /** + * Return the shoreHardeness + * @return + */ + public float getShoreHardness() { + return shoreHardness; + } + + /** + * The smaller this value is, the softer the transition between + * shore and water. If you want hard edges use very big value. + * Default is 0.1f. + * @param shoreHardness + */ + public void setShoreHardness(float shoreHardness) { + this.shoreHardness = shoreHardness; + if (material != null) { + material.setFloat("ShoreHardness", shoreHardness); + } + } + + /** + * returns the foam hardness + * @return + */ + public float getFoamHardness() { + return foamHardness; + } + + /** + * Sets the foam hardness : How much the foam will blend with the shore to avoid hard edged water plane. + * Default is 1.0 + * @param foamHardness + */ + public void setFoamHardness(float foamHardness) { + this.foamHardness = foamHardness; + if (material != null) { + material.setFloat("FoamHardness", foamHardness); + } + } + + /** + * returns the refractionStrenght + * @return + */ + public float getRefractionStrength() { + return refractionStrength; + } + + /** + * This value modifies current fresnel term. If you want to weaken + * reflections use bigger value. If you want to empasize them use + * value smaller then 0. Default is 0.0f. + * @param refractionStrength + */ + public void setRefractionStrength(float refractionStrength) { + this.refractionStrength = refractionStrength; + if (material != null) { + material.setFloat("RefractionStrength", refractionStrength); + } + } + + /** + * returns the scale factor of the waves height map + * @return + */ + public float getWaveScale() { + return waveScale; + } + + /** + * Sets the scale factor of the waves height map + * the smaller the value the bigger the waves + * default is 0.005f + * @param waveScale + */ + public void setWaveScale(float waveScale) { + this.waveScale = waveScale; + if (material != null) { + material.setFloat("WaveScale", waveScale); + } + } + + /** + * returns the foam existance vector + * @return + */ + public Vector3f getFoamExistence() { + return foamExistence; + } + + /** + * Describes at what depth foam starts to fade out and + * at what it is completely invisible. The third value is at + * what height foam for waves appear (+ waterHeight). + * default is (0.45, 4.35, 1.0); + * @param foamExistence + */ + public void setFoamExistence(Vector3f foamExistence) { + this.foamExistence = foamExistence; + if (material != null) { + material.setVector3("FoamExistence", foamExistence); + } + } + + /** + * gets the scale of the sun + * @return + */ + public float getSunScale() { + return sunScale; + } + + /** + * Sets the scale of the sun for specular effect + * @param sunScale + */ + public void setSunScale(float sunScale) { + this.sunScale = sunScale; + if (material != null) { + material.setFloat("SunScale", sunScale); + } + } + + /** + * Returns the color exctinction vector of the water + * @return + */ + public Vector3f getColorExtinction() { + return colorExtinction; + } + + /** + * Return at what depth the refraction color extinct + * the first value is for red + * the second is for green + * the third is for blue + * Play with thos parameters to "trouble" the water + * default is (5.0, 20.0, 30.0f); + * @param colorExtinction + */ + public void setColorExtinction(Vector3f colorExtinction) { + this.colorExtinction = colorExtinction; + if (material != null) { + material.setVector3("ColorExtinction", colorExtinction); + } + } + + /** + * Sets the foam texture + * @param foamTexture + */ + public void setFoamTexture(Texture2D foamTexture) { + this.foamTexture = foamTexture; + foamTexture.setWrap(WrapMode.Repeat); + if (material != null) { + material.setTexture("FoamMap", foamTexture); + } + } + + /** + * Sets the height texture + * @param heightTexture + */ + public void setHeightTexture(Texture2D heightTexture) { + this.heightTexture = heightTexture; + heightTexture.setWrap(WrapMode.Repeat); + } + + /** + * Sets the normal Texture + * @param normalTexture + */ + public void setNormalTexture(Texture2D normalTexture) { + this.normalTexture = normalTexture; + normalTexture.setWrap(WrapMode.Repeat); + } + + /** + * return the shininess factor of the water + * @return + */ + public float getShininess() { + return shininess; + } + + /** + * Sets the shinines factor of the water + * default is 0.7f + * @param shininess + */ + public void setShininess(float shininess) { + this.shininess = shininess; + if (material != null) { + material.setFloat("Shininess", shininess); + } + } + + /** + * retruns the speed of the waves + * @return + */ + public float getSpeed() { + return speed; + } + + /** + * Set the speed of the waves (0.0 is still) default is 1.0 + * @param speed + */ + public void setSpeed(float speed) { + this.speed = speed; + } + + /** + * returns the color of the water + * + * @return + */ + public ColorRGBA getWaterColor() { + return waterColor; + } + + /** + * Sets the color of the water + * see setDeepWaterColor for deep water color + * default is (0.0078f, 0.5176f, 0.5f,1.0f) (greenish blue) + * @param waterColor + */ + public void setWaterColor(ColorRGBA waterColor) { + this.waterColor = waterColor; + if (material != null) { + material.setColor("WaterColor", waterColor); + } + } + + /** + * returns the deep water color + * @return + */ + public ColorRGBA getDeepWaterColor() { + return deepWaterColor; + } + + /** + * sets the deep water color + * see setWaterColor for general color + * default is (0.0039f, 0.00196f, 0.145f,1.0f) (very dark blue) + * @param deepWaterColor + */ + public void setDeepWaterColor(ColorRGBA deepWaterColor) { + this.deepWaterColor = deepWaterColor; + if (material != null) { + material.setColor("DeepWaterColor", deepWaterColor); + } + } + + /** + * returns the wind direction + * @return + */ + public Vector2f getWindDirection() { + return windDirection; + } + + /** + * sets the wind direction + * the direction where the waves move + * default is (0.0f, -1.0f) + * @param windDirection + */ + public void setWindDirection(Vector2f windDirection) { + this.windDirection = windDirection; + if (material != null) { + material.setVector2("WindDirection", windDirection); + } + } + + /** + * returns the size of the reflection map + * @return + */ + public int getReflectionMapSize() { + return reflectionMapSize; + } + + /** + * Sets the size of the reflection map + * default is 512, the higher, the better quality, but the slower the effect. + * @param reflectionMapSize + */ + public void setReflectionMapSize(int reflectionMapSize) { + this.reflectionMapSize = reflectionMapSize; + } + + /** + * returns true if the water uses foam + * @return + */ + public boolean isUseFoam() { + return useFoam; + } + + /** + * set to true to use foam with water + * default true + * @param useFoam + */ + public void setUseFoam(boolean useFoam) { + this.useFoam = useFoam; + if (material != null) { + material.setBoolean("UseFoam", useFoam); + } + + } + + /** + * sets the texture to use to render caustics on the ground underwater + * @param causticsTexture + */ + public void setCausticsTexture(Texture2D causticsTexture) { + this.causticsTexture = causticsTexture; + if (material != null) { + material.setTexture("causticsMap", causticsTexture); + } + } + + /** + * returns true if caustics are rendered + * @return + */ + public boolean isUseCaustics() { + return useCaustics; + } + + /** + * set to true if you want caustics to be rendered on the ground underwater, false otherwise + * @param useCaustics + */ + public void setUseCaustics(boolean useCaustics) { + this.useCaustics = useCaustics; + if (material != null) { + material.setBoolean("UseCaustics", useCaustics); + } + } + + /** + * return true + * @return + */ + public boolean isUseHQShoreline() { + return useHQShoreline; + } + + public void setUseHQShoreline(boolean useHQShoreline) { + this.useHQShoreline = useHQShoreline; + if (material != null) { + material.setBoolean("UseHQShoreline", useHQShoreline); + } + + } + + /** + * returns true if the water use the refraction + * @return + */ + public boolean isUseRefraction() { + return useRefraction; + } + + /** + * set to true to use refraction (default is true) + * @param useRefraction + */ + public void setUseRefraction(boolean useRefraction) { + this.useRefraction = useRefraction; + if (material != null) { + material.setBoolean("UseRefraction", useRefraction); + } + + } + + /** + * returns true if the ater use ripples + * @return + */ + public boolean isUseRipples() { + return useRipples; + } + + /** + * + * Set to true tu use ripples + * @param useRipples + */ + public void setUseRipples(boolean useRipples) { + this.useRipples = useRipples; + if (material != null) { + material.setBoolean("UseRipples", useRipples); + } + + } + + /** + * returns true if the water use specular + * @return + */ + public boolean isUseSpecular() { + return useSpecular; + } + + /** + * Set to true to use specular lightings on the water + * @param useSpecular + */ + public void setUseSpecular(boolean useSpecular) { + this.useSpecular = useSpecular; + if (material != null) { + material.setBoolean("UseSpecular", useSpecular); + } + } + + /** + * returns the foam intensity + * @return + */ + public float getFoamIntensity() { + return foamIntensity; + } + + /** + * sets the foam intensity default is 0.5f + * @param foamIntensity + */ + public void setFoamIntensity(float foamIntensity) { + this.foamIntensity = foamIntensity; + if (material != null) { + material.setFloat("FoamIntensity", foamIntensity); + + } + } + + /** + * returns the reflection displace + * see {@link setReflectionDisplace(float reflectionDisplace)} + * @return + */ + public float getReflectionDisplace() { + return reflectionDisplace; + } + + /** + * Sets the reflection displace. define how troubled will look the reflection in the water. default is 30 + * @param reflectionDisplace + */ + public void setReflectionDisplace(float reflectionDisplace) { + this.reflectionDisplace = reflectionDisplace; + if (material != null) { + material.setFloat("m_ReflectionDisplace", reflectionDisplace); + } + } + + /** + * returns true if the camera is under the water level + * @return + */ + public boolean isUnderWater() { + return underWater; + } + + /** + * returns the distance of the fog when under water + * @return + */ + public float getUnderWaterFogDistance() { + return underWaterFogDistance; + } + + /** + * sets the distance of the fog when under water. + * default is 120 (120 world units) use a high value to raise the view range under water + * @param underWaterFogDistance + */ + public void setUnderWaterFogDistance(float underWaterFogDistance) { + this.underWaterFogDistance = underWaterFogDistance; + if (material != null) { + material.setFloat("UnderWaterFogDistance", underWaterFogDistance); + } + } + + /** + * get the intensity of caustics under water + * @return + */ + public float getCausticsIntensity() { + return causticsIntensity; + } + + /** + * sets the intensity of caustics under water. goes from 0 to 1, default is 0.5f + * @param causticsIntensity + */ + public void setCausticsIntensity(float causticsIntensity) { + this.causticsIntensity = causticsIntensity; + if (material != null) { + material.setFloat("CausticsIntensity", causticsIntensity); + } + } +}