From 9e5f9be5ec578bded98490f29e0c5ddd4ed1d39c Mon Sep 17 00:00:00 2001 From: "rem..om" Date: Fri, 5 Aug 2011 17:03:46 +0000 Subject: [PATCH] SpotLight : reduced the number of float varying by 5 in the shaders : - computed the spotDirection in view space on the java side in Material and pass it as a uniform -> vec4 spotVec disapear - this implies to decode the cos values for falloff in the frag shader instead of the vert shader, but allows to reduce light vec from vec4 to vec3 All in all it shouldn't be that much of a performance hit, since the matrix multiplication of spotVec occur once per geometry instead of once per vertex, we could go further and compute it once per frame. On the other hand decoding of the cos values happens once for each pixel instead of once for each vertex ( a floor a mult and a fract). I guess this should be balanced in a rich scene. git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7978 75d07b2b-3a1a-0410-a2c5-0572b91ccdca --- .../Common/MatDefs/Light/Lighting.frag | 12 +++--- .../Common/MatDefs/Light/Lighting.vert | 14 +++---- .../src/core/com/jme3/material/Material.java | 30 ++++++++----- engine/src/core/com/jme3/util/TempVars.java | 42 +++++++++---------- 4 files changed, 53 insertions(+), 45 deletions(-) diff --git a/engine/src/core-data/Common/MatDefs/Light/Lighting.frag b/engine/src/core-data/Common/MatDefs/Light/Lighting.frag index 1dfe0e0f9..0c50b072c 100644 --- a/engine/src/core-data/Common/MatDefs/Light/Lighting.frag +++ b/engine/src/core-data/Common/MatDefs/Light/Lighting.frag @@ -2,6 +2,7 @@ #define ATTENUATION //#define HQ_ATTENUATION +uniform vec4 g_LightDirection; varying vec2 texCoord; #ifdef SEPARATE_TEXCOORD varying vec2 texCoord2; @@ -50,8 +51,7 @@ varying vec3 SpecularSum; #endif uniform float m_AlphaDiscardThreshold; -varying vec4 lightVec; -varying vec4 spotVec; +varying vec3 lightVec; #ifndef VERTEX_LIGHTING uniform float m_Shininess; @@ -162,12 +162,12 @@ void main(){ #ifndef VERTEX_LIGHTING float spotFallOff = 1.0; - if(spotVec.w != 0.0){ + if(g_LightDirection.w != 0.0){ vec3 L = normalize(lightVec.xyz); - vec3 spotdir = normalize(spotVec.xyz); + vec3 spotdir = normalize(g_LightDirection.xyz); float curAngleCos = dot(-L, spotdir); - float innerAngleCos = spotVec.w; - float outerAngleCos = lightVec.w; + float innerAngleCos = floor(g_LightDirection.w) * 0.001; + float outerAngleCos = fract(g_LightDirection.w); float innerMinusOuter = innerAngleCos - outerAngleCos; spotFallOff = clamp((curAngleCos - outerAngleCos) / innerMinusOuter, 0.0, 1.0); if(spotFallOff <= 0.0){ diff --git a/engine/src/core-data/Common/MatDefs/Light/Lighting.vert b/engine/src/core-data/Common/MatDefs/Light/Lighting.vert index 7f880c10f..031633efe 100644 --- a/engine/src/core-data/Common/MatDefs/Light/Lighting.vert +++ b/engine/src/core-data/Common/MatDefs/Light/Lighting.vert @@ -13,7 +13,7 @@ uniform float m_Shininess; uniform vec4 g_LightColor; uniform vec4 g_LightPosition; -uniform vec4 g_LightDirection; +//uniform vec4 g_LightDirection; uniform vec4 g_AmbientLightColor; varying vec2 texCoord; @@ -30,8 +30,8 @@ attribute vec3 inPosition; attribute vec2 inTexCoord; attribute vec3 inNormal; -varying vec4 lightVec; -varying vec4 spotVec; +varying vec3 lightVec; +//varying vec4 spotVec; #ifdef VERTEX_COLOR attribute vec4 inColor; @@ -83,7 +83,7 @@ varying vec4 spotVec; void lightComputeDir(in vec3 worldPos, in vec4 color, in vec4 position, out vec4 lightDir){ float posLight = step(0.5, color.w); vec3 tempVec = position.xyz * sign(posLight - 0.5) - (worldPos * posLight); - lightVec.xyz = tempVec; + lightVec = tempVec; #ifdef ATTENUATION float dist = length(tempVec); lightDir.w = clamp(1.0 - position.w * dist * posLight, 0.0, 1.0); @@ -176,9 +176,9 @@ void main(){ #endif //computing spot direction in view space and unpacking spotlight cos - spotVec = (g_ViewMatrix * vec4(g_LightDirection.xyz, 0.0) ); - spotVec.w = floor(g_LightDirection.w) * 0.001; - lightVec.w = fract(g_LightDirection.w); +// spotVec = (g_ViewMatrix * vec4(g_LightDirection.xyz, 0.0) ); +// spotVec.w = floor(g_LightDirection.w) * 0.001; +// lightVec.w = fract(g_LightDirection.w); lightColor.w = 1.0; #ifdef MATERIAL_COLORS diff --git a/engine/src/core/com/jme3/material/Material.java b/engine/src/core/com/jme3/material/Material.java index 369b64681..fa14f0d12 100644 --- a/engine/src/core/com/jme3/material/Material.java +++ b/engine/src/core/com/jme3/material/Material.java @@ -47,7 +47,6 @@ import com.jme3.light.LightList; import com.jme3.light.PointLight; import com.jme3.light.SpotLight; import com.jme3.material.TechniqueDef.LightMode; -import com.jme3.math.FastMath; import com.jme3.math.Quaternion; import com.jme3.math.Vector3f; import com.jme3.math.Vector4f; @@ -98,7 +97,6 @@ public class Material implements Asset, Cloneable, Savable, Comparable additiveLight.setBlendMode(RenderState.BlendMode.AlphaAdditive); additiveLight.setDepthWrite(false); } - private AssetKey key; private MaterialDef def; private ListMap paramValues = new ListMap(); @@ -141,14 +139,14 @@ public class Material implements Asset, Cloneable, Savable, Comparable return key != null ? key.getName() : null; } - public void setKey(AssetKey key){ + public void setKey(AssetKey key) { this.key = key; } - - public AssetKey getKey(){ + + public AssetKey getKey() { return key; } - + /** * Returns the sorting ID or sorting index for this material. * @@ -698,7 +696,9 @@ public class Material implements Asset, Cloneable, Savable, Comparable } } - protected void renderMultipassLighting(Shader shader, Geometry g, Renderer r) { + protected void renderMultipassLighting(Shader shader, Geometry g, RenderManager rm) { + + Renderer r = rm.getRenderer(); LightList lightList = g.getWorldLightList(); Uniform lightDir = shader.getUniform("g_LightDirection"); Uniform lightColor = shader.getUniform("g_LightColor"); @@ -729,6 +729,7 @@ public class Material implements Asset, Cloneable, Savable, Comparable Quaternion tmpLightDirection = vars.quat1; Quaternion tmpLightPosition = vars.quat2; ColorRGBA tmpLightColor = vars.color; + Vector4f tmpVec = vars.vect4f; ColorRGBA color = l.getColor(); tmpLightColor.set(color); @@ -742,7 +743,7 @@ public class Material implements Asset, Cloneable, Savable, Comparable tmpLightPosition.set(dir.getX(), dir.getY(), dir.getZ(), -1); lightPos.setValue(VarType.Vector4, tmpLightPosition); - tmpLightDirection.set(0,0,0,0); + tmpLightDirection.set(0, 0, 0, 0); lightDir.setValue(VarType.Vector4, tmpLightDirection); break; case Point: @@ -752,7 +753,7 @@ public class Material implements Asset, Cloneable, Savable, Comparable tmpLightPosition.set(pos.getX(), pos.getY(), pos.getZ(), invRadius); lightPos.setValue(VarType.Vector4, tmpLightPosition); - tmpLightDirection.set(0,0,0,0); + tmpLightDirection.set(0, 0, 0, 0); lightDir.setValue(VarType.Vector4, tmpLightDirection); break; case Spot: @@ -765,7 +766,13 @@ public class Material implements Asset, Cloneable, Savable, Comparable tmpLightPosition.set(pos2.getX(), pos2.getY(), pos2.getZ(), invRange); lightPos.setValue(VarType.Vector4, tmpLightPosition); - tmpLightDirection.set(dir2.getX(), dir2.getY(), dir2.getZ(), spotAngleCos); + //We transform the spot directoin in view space here to save 5 varying later in the lighting shader + //one vec4 less and a vec4 that becomes a vec3 + //the downside is that spotAngleCos decoding happen now in the frag shader. + tmpVec.set(dir2.getX(), dir2.getY(), dir2.getZ(),0); + rm.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec); + tmpLightDirection.set(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), spotAngleCos); + lightDir.setValue(VarType.Vector4, tmpLightDirection); break; @@ -951,6 +958,7 @@ public class Material implements Asset, Cloneable, Savable, Comparable autoSelectTechnique(rm); Renderer r = rm.getRenderer(); + TechniqueDef techDef = technique.getDef(); if (techDef.getLightMode() == LightMode.MultiPass @@ -999,7 +1007,7 @@ public class Material implements Asset, Cloneable, Savable, Comparable case MultiPass: // NOTE: Special case! resetUniformsNotSetByCurrent(shader); - renderMultipassLighting(shader, geom, r); + renderMultipassLighting(shader, geom, rm); // very important, notice the return statement! return; } diff --git a/engine/src/core/com/jme3/util/TempVars.java b/engine/src/core/com/jme3/util/TempVars.java index f51ab8313..5b361e952 100644 --- a/engine/src/core/com/jme3/util/TempVars.java +++ b/engine/src/core/com/jme3/util/TempVars.java @@ -41,6 +41,7 @@ import com.jme3.math.Quaternion; import com.jme3.math.Triangle; import com.jme3.math.Vector2f; import com.jme3.math.Vector3f; +import com.jme3.math.Vector4f; import com.jme3.scene.Spatial; import java.nio.FloatBuffer; import java.nio.IntBuffer; @@ -53,13 +54,13 @@ import java.util.ArrayList; * This returns an available instance of the TempVar class ensuring this * particular instance is never used elsewhere in the mean time. */ -public class TempVars { +public class TempVars { /** * Allow X instances of TempVars in a single thread. */ private static final int STACK_SIZE = 5; - + /** * TempVarsStack contains a stack of TempVars. * Every time TempVars.get() is called, a new entry is added to the stack, @@ -68,30 +69,30 @@ public class TempVars { * the current instance and then the index is decremented. */ private static class TempVarsStack { + int index = 0; TempVars[] tempVars = new TempVars[STACK_SIZE]; } - /** * ThreadLocal to store a TempVarsStack for each thread. * This ensures each thread has a single TempVarsStack that is * used only in method calls in that thread. */ private static final ThreadLocal varsLocal = new ThreadLocal() { + @Override public TempVarsStack initialValue() { return new TempVarsStack(); } }; - /** * This instance of TempVars has been retrieved but not released yet. */ private boolean isUsed = false; - + private TempVars() { } - + /** * Acquire an instance of the TempVar class. * You have to release the instance after use by calling the @@ -103,21 +104,21 @@ public class TempVars { */ public static TempVars get() { TempVarsStack stack = varsLocal.get(); - + TempVars instance = stack.tempVars[stack.index]; - - if (instance == null){ + + if (instance == null) { // Create new instance = new TempVars(); - + // Put it in there stack.tempVars[stack.index] = instance; } - + stack.index++; - + instance.isUsed = true; - + return instance; } @@ -129,23 +130,22 @@ public class TempVars { * first otherwise an exception will be thrown. */ public void release() { - if (!isUsed){ + if (!isUsed) { throw new IllegalStateException("This instance of TempVars was already released!"); } - + isUsed = false; - + TempVarsStack stack = varsLocal.get(); - + // Return it to the stack stack.index--; - + // Check if it is actually there - if (stack.tempVars[stack.index] != this){ + if (stack.tempVars[stack.index] != this) { throw new IllegalStateException("An instance of TempVars has not been released in a called method!"); } } - /** * For interfacing with OpenGL in Renderer. */ @@ -161,7 +161,6 @@ public class TempVars { * Fetching triangle from mesh */ public final Triangle triangle = new Triangle(); - /** * Color */ @@ -180,6 +179,7 @@ public class TempVars { public final Vector3f vect8 = new Vector3f(); public final Vector3f vect9 = new Vector3f(); public final Vector3f vect10 = new Vector3f(); + public final Vector4f vect4f = new Vector4f(); public final Vector3f[] tri = {new Vector3f(), new Vector3f(), new Vector3f()};