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
3.0
rem..om 14 years ago
parent d67adb8266
commit 9e5f9be5ec
  1. 12
      engine/src/core-data/Common/MatDefs/Light/Lighting.frag
  2. 14
      engine/src/core-data/Common/MatDefs/Light/Lighting.vert
  3. 26
      engine/src/core/com/jme3/material/Material.java
  4. 14
      engine/src/core/com/jme3/util/TempVars.java

@ -2,6 +2,7 @@
#define ATTENUATION #define ATTENUATION
//#define HQ_ATTENUATION //#define HQ_ATTENUATION
uniform vec4 g_LightDirection;
varying vec2 texCoord; varying vec2 texCoord;
#ifdef SEPARATE_TEXCOORD #ifdef SEPARATE_TEXCOORD
varying vec2 texCoord2; varying vec2 texCoord2;
@ -50,8 +51,7 @@ varying vec3 SpecularSum;
#endif #endif
uniform float m_AlphaDiscardThreshold; uniform float m_AlphaDiscardThreshold;
varying vec4 lightVec; varying vec3 lightVec;
varying vec4 spotVec;
#ifndef VERTEX_LIGHTING #ifndef VERTEX_LIGHTING
uniform float m_Shininess; uniform float m_Shininess;
@ -162,12 +162,12 @@ void main(){
#ifndef VERTEX_LIGHTING #ifndef VERTEX_LIGHTING
float spotFallOff = 1.0; float spotFallOff = 1.0;
if(spotVec.w != 0.0){ if(g_LightDirection.w != 0.0){
vec3 L = normalize(lightVec.xyz); vec3 L = normalize(lightVec.xyz);
vec3 spotdir = normalize(spotVec.xyz); vec3 spotdir = normalize(g_LightDirection.xyz);
float curAngleCos = dot(-L, spotdir); float curAngleCos = dot(-L, spotdir);
float innerAngleCos = spotVec.w; float innerAngleCos = floor(g_LightDirection.w) * 0.001;
float outerAngleCos = lightVec.w; float outerAngleCos = fract(g_LightDirection.w);
float innerMinusOuter = innerAngleCos - outerAngleCos; float innerMinusOuter = innerAngleCos - outerAngleCos;
spotFallOff = clamp((curAngleCos - outerAngleCos) / innerMinusOuter, 0.0, 1.0); spotFallOff = clamp((curAngleCos - outerAngleCos) / innerMinusOuter, 0.0, 1.0);
if(spotFallOff <= 0.0){ if(spotFallOff <= 0.0){

@ -13,7 +13,7 @@ uniform float m_Shininess;
uniform vec4 g_LightColor; uniform vec4 g_LightColor;
uniform vec4 g_LightPosition; uniform vec4 g_LightPosition;
uniform vec4 g_LightDirection; //uniform vec4 g_LightDirection;
uniform vec4 g_AmbientLightColor; uniform vec4 g_AmbientLightColor;
varying vec2 texCoord; varying vec2 texCoord;
@ -30,8 +30,8 @@ attribute vec3 inPosition;
attribute vec2 inTexCoord; attribute vec2 inTexCoord;
attribute vec3 inNormal; attribute vec3 inNormal;
varying vec4 lightVec; varying vec3 lightVec;
varying vec4 spotVec; //varying vec4 spotVec;
#ifdef VERTEX_COLOR #ifdef VERTEX_COLOR
attribute vec4 inColor; attribute vec4 inColor;
@ -83,7 +83,7 @@ varying vec4 spotVec;
void lightComputeDir(in vec3 worldPos, in vec4 color, in vec4 position, out vec4 lightDir){ void lightComputeDir(in vec3 worldPos, in vec4 color, in vec4 position, out vec4 lightDir){
float posLight = step(0.5, color.w); float posLight = step(0.5, color.w);
vec3 tempVec = position.xyz * sign(posLight - 0.5) - (worldPos * posLight); vec3 tempVec = position.xyz * sign(posLight - 0.5) - (worldPos * posLight);
lightVec.xyz = tempVec; lightVec = tempVec;
#ifdef ATTENUATION #ifdef ATTENUATION
float dist = length(tempVec); float dist = length(tempVec);
lightDir.w = clamp(1.0 - position.w * dist * posLight, 0.0, 1.0); lightDir.w = clamp(1.0 - position.w * dist * posLight, 0.0, 1.0);
@ -176,9 +176,9 @@ void main(){
#endif #endif
//computing spot direction in view space and unpacking spotlight cos //computing spot direction in view space and unpacking spotlight cos
spotVec = (g_ViewMatrix * vec4(g_LightDirection.xyz, 0.0) ); // spotVec = (g_ViewMatrix * vec4(g_LightDirection.xyz, 0.0) );
spotVec.w = floor(g_LightDirection.w) * 0.001; // spotVec.w = floor(g_LightDirection.w) * 0.001;
lightVec.w = fract(g_LightDirection.w); // lightVec.w = fract(g_LightDirection.w);
lightColor.w = 1.0; lightColor.w = 1.0;
#ifdef MATERIAL_COLORS #ifdef MATERIAL_COLORS

@ -47,7 +47,6 @@ import com.jme3.light.LightList;
import com.jme3.light.PointLight; import com.jme3.light.PointLight;
import com.jme3.light.SpotLight; import com.jme3.light.SpotLight;
import com.jme3.material.TechniqueDef.LightMode; import com.jme3.material.TechniqueDef.LightMode;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion; import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f; import com.jme3.math.Vector3f;
import com.jme3.math.Vector4f; import com.jme3.math.Vector4f;
@ -98,7 +97,6 @@ public class Material implements Asset, Cloneable, Savable, Comparable<Material>
additiveLight.setBlendMode(RenderState.BlendMode.AlphaAdditive); additiveLight.setBlendMode(RenderState.BlendMode.AlphaAdditive);
additiveLight.setDepthWrite(false); additiveLight.setDepthWrite(false);
} }
private AssetKey key; private AssetKey key;
private MaterialDef def; private MaterialDef def;
private ListMap<String, MatParam> paramValues = new ListMap<String, MatParam>(); private ListMap<String, MatParam> paramValues = new ListMap<String, MatParam>();
@ -141,11 +139,11 @@ public class Material implements Asset, Cloneable, Savable, Comparable<Material>
return key != null ? key.getName() : null; return key != null ? key.getName() : null;
} }
public void setKey(AssetKey key){ public void setKey(AssetKey key) {
this.key = key; this.key = key;
} }
public AssetKey getKey(){ public AssetKey getKey() {
return key; return key;
} }
@ -698,7 +696,9 @@ public class Material implements Asset, Cloneable, Savable, Comparable<Material>
} }
} }
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(); LightList lightList = g.getWorldLightList();
Uniform lightDir = shader.getUniform("g_LightDirection"); Uniform lightDir = shader.getUniform("g_LightDirection");
Uniform lightColor = shader.getUniform("g_LightColor"); Uniform lightColor = shader.getUniform("g_LightColor");
@ -729,6 +729,7 @@ public class Material implements Asset, Cloneable, Savable, Comparable<Material>
Quaternion tmpLightDirection = vars.quat1; Quaternion tmpLightDirection = vars.quat1;
Quaternion tmpLightPosition = vars.quat2; Quaternion tmpLightPosition = vars.quat2;
ColorRGBA tmpLightColor = vars.color; ColorRGBA tmpLightColor = vars.color;
Vector4f tmpVec = vars.vect4f;
ColorRGBA color = l.getColor(); ColorRGBA color = l.getColor();
tmpLightColor.set(color); tmpLightColor.set(color);
@ -742,7 +743,7 @@ public class Material implements Asset, Cloneable, Savable, Comparable<Material>
tmpLightPosition.set(dir.getX(), dir.getY(), dir.getZ(), -1); tmpLightPosition.set(dir.getX(), dir.getY(), dir.getZ(), -1);
lightPos.setValue(VarType.Vector4, tmpLightPosition); lightPos.setValue(VarType.Vector4, tmpLightPosition);
tmpLightDirection.set(0,0,0,0); tmpLightDirection.set(0, 0, 0, 0);
lightDir.setValue(VarType.Vector4, tmpLightDirection); lightDir.setValue(VarType.Vector4, tmpLightDirection);
break; break;
case Point: case Point:
@ -752,7 +753,7 @@ public class Material implements Asset, Cloneable, Savable, Comparable<Material>
tmpLightPosition.set(pos.getX(), pos.getY(), pos.getZ(), invRadius); tmpLightPosition.set(pos.getX(), pos.getY(), pos.getZ(), invRadius);
lightPos.setValue(VarType.Vector4, tmpLightPosition); lightPos.setValue(VarType.Vector4, tmpLightPosition);
tmpLightDirection.set(0,0,0,0); tmpLightDirection.set(0, 0, 0, 0);
lightDir.setValue(VarType.Vector4, tmpLightDirection); lightDir.setValue(VarType.Vector4, tmpLightDirection);
break; break;
case Spot: case Spot:
@ -765,7 +766,13 @@ public class Material implements Asset, Cloneable, Savable, Comparable<Material>
tmpLightPosition.set(pos2.getX(), pos2.getY(), pos2.getZ(), invRange); tmpLightPosition.set(pos2.getX(), pos2.getY(), pos2.getZ(), invRange);
lightPos.setValue(VarType.Vector4, tmpLightPosition); 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); lightDir.setValue(VarType.Vector4, tmpLightDirection);
break; break;
@ -951,6 +958,7 @@ public class Material implements Asset, Cloneable, Savable, Comparable<Material>
autoSelectTechnique(rm); autoSelectTechnique(rm);
Renderer r = rm.getRenderer(); Renderer r = rm.getRenderer();
TechniqueDef techDef = technique.getDef(); TechniqueDef techDef = technique.getDef();
if (techDef.getLightMode() == LightMode.MultiPass if (techDef.getLightMode() == LightMode.MultiPass
@ -999,7 +1007,7 @@ public class Material implements Asset, Cloneable, Savable, Comparable<Material>
case MultiPass: case MultiPass:
// NOTE: Special case! // NOTE: Special case!
resetUniformsNotSetByCurrent(shader); resetUniformsNotSetByCurrent(shader);
renderMultipassLighting(shader, geom, r); renderMultipassLighting(shader, geom, rm);
// very important, notice the return statement! // very important, notice the return statement!
return; return;
} }

@ -41,6 +41,7 @@ import com.jme3.math.Quaternion;
import com.jme3.math.Triangle; import com.jme3.math.Triangle;
import com.jme3.math.Vector2f; import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f; import com.jme3.math.Vector3f;
import com.jme3.math.Vector4f;
import com.jme3.scene.Spatial; import com.jme3.scene.Spatial;
import java.nio.FloatBuffer; import java.nio.FloatBuffer;
import java.nio.IntBuffer; import java.nio.IntBuffer;
@ -68,22 +69,22 @@ public class TempVars {
* the current instance and then the index is decremented. * the current instance and then the index is decremented.
*/ */
private static class TempVarsStack { private static class TempVarsStack {
int index = 0; int index = 0;
TempVars[] tempVars = new TempVars[STACK_SIZE]; TempVars[] tempVars = new TempVars[STACK_SIZE];
} }
/** /**
* ThreadLocal to store a TempVarsStack for each thread. * ThreadLocal to store a TempVarsStack for each thread.
* This ensures each thread has a single TempVarsStack that is * This ensures each thread has a single TempVarsStack that is
* used only in method calls in that thread. * used only in method calls in that thread.
*/ */
private static final ThreadLocal<TempVarsStack> varsLocal = new ThreadLocal<TempVarsStack>() { private static final ThreadLocal<TempVarsStack> varsLocal = new ThreadLocal<TempVarsStack>() {
@Override @Override
public TempVarsStack initialValue() { public TempVarsStack initialValue() {
return new TempVarsStack(); return new TempVarsStack();
} }
}; };
/** /**
* This instance of TempVars has been retrieved but not released yet. * This instance of TempVars has been retrieved but not released yet.
*/ */
@ -106,7 +107,7 @@ public class TempVars {
TempVars instance = stack.tempVars[stack.index]; TempVars instance = stack.tempVars[stack.index];
if (instance == null){ if (instance == null) {
// Create new // Create new
instance = new TempVars(); instance = new TempVars();
@ -129,7 +130,7 @@ public class TempVars {
* first otherwise an exception will be thrown. * first otherwise an exception will be thrown.
*/ */
public void release() { public void release() {
if (!isUsed){ if (!isUsed) {
throw new IllegalStateException("This instance of TempVars was already released!"); throw new IllegalStateException("This instance of TempVars was already released!");
} }
@ -141,11 +142,10 @@ public class TempVars {
stack.index--; stack.index--;
// Check if it is actually there // 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!"); throw new IllegalStateException("An instance of TempVars has not been released in a called method!");
} }
} }
/** /**
* For interfacing with OpenGL in Renderer. * For interfacing with OpenGL in Renderer.
*/ */
@ -161,7 +161,6 @@ public class TempVars {
* Fetching triangle from mesh * Fetching triangle from mesh
*/ */
public final Triangle triangle = new Triangle(); public final Triangle triangle = new Triangle();
/** /**
* Color * Color
*/ */
@ -180,6 +179,7 @@ public class TempVars {
public final Vector3f vect8 = new Vector3f(); public final Vector3f vect8 = new Vector3f();
public final Vector3f vect9 = new Vector3f(); public final Vector3f vect9 = new Vector3f();
public final Vector3f vect10 = new Vector3f(); public final Vector3f vect10 = new Vector3f();
public final Vector4f vect4f = new Vector4f();
public final Vector3f[] tri = {new Vector3f(), public final Vector3f[] tri = {new Vector3f(),
new Vector3f(), new Vector3f(),
new Vector3f()}; new Vector3f()};

Loading…
Cancel
Save