From 01ed6db77c60772c167919687584f1540a4f4134 Mon Sep 17 00:00:00 2001 From: Nehon Date: Sat, 21 Mar 2015 10:36:00 +0100 Subject: [PATCH] Introduced a LightSpace attribute in the TechniqueDef to define in what space LightData should be sent to the shader. Used it for the multipass lighting --- .../main/java/com/jme3/material/Material.java | 33 ++++++++++++---- .../java/com/jme3/material/TechniqueDef.java | 38 ++++++++++++++++++- 2 files changed, 62 insertions(+), 9 deletions(-) diff --git a/jme3-core/src/main/java/com/jme3/material/Material.java b/jme3-core/src/main/java/com/jme3/material/Material.java index 5f0ab8f91..2e388ebf5 100644 --- a/jme3-core/src/main/java/com/jme3/material/Material.java +++ b/jme3-core/src/main/java/com/jme3/material/Material.java @@ -874,7 +874,7 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable { TempVars vars = TempVars.get(); Quaternion tmpLightDirection = vars.quat1; - Quaternion tmpLightPosition = vars.quat2; + Vector4f tmpLightPosition = vars.vect4f2; ColorRGBA tmpLightColor = vars.color; Vector4f tmpVec = vars.vect4f1; @@ -892,7 +892,8 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable { //The directional light direction is passed in the //LightPosition uniform. The lighting shader needs to be //reworked though in order to fix this. - tmpLightPosition.set(dir.getX(), dir.getY(), dir.getZ(), -1); + tmpLightPosition.set(dir.getX(), dir.getY(), dir.getZ(), -1); + transposeLightDataToSpace(technique.getDef().getLightSpace(), rm, tmpLightPosition); lightPos.setValue(VarType.Vector4, tmpLightPosition); tmpLightDirection.set(0, 0, 0, 0); lightDir.setValue(VarType.Vector4, tmpLightDirection); @@ -903,6 +904,7 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable { float invRadius = pl.getInvRadius(); tmpLightPosition.set(pos.getX(), pos.getY(), pos.getZ(), invRadius); + transposeLightDataToSpace(technique.getDef().getLightSpace(), rm, tmpLightPosition); lightPos.setValue(VarType.Vector4, tmpLightPosition); tmpLightDirection.set(0, 0, 0, 0); lightDir.setValue(VarType.Vector4, tmpLightDirection); @@ -913,15 +915,21 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable { Vector3f dir2 = sl.getDirection(); float invRange = sl.getInvSpotRange(); float spotAngleCos = sl.getPackedAngleCos(); - + tmpLightPosition.set(pos2.getX(), pos2.getY(), pos2.getZ(), invRange); + transposeLightDataToSpace(technique.getDef().getLightSpace(), rm, tmpLightPosition); lightPos.setValue(VarType.Vector4, tmpLightPosition); - //We transform the spot direction 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 happens now in the frag shader. tmpVec.set(dir2.getX(), dir2.getY(), dir2.getZ(), 0); - rm.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec); + if (technique.getDef().getLightSpace() == TechniqueDef.LightSpace.Legacy) { + //Legacy kept for backward compatibility. + //We transform the spot direction 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 happens now in the frag shader. + transposeLightDataToSpace(TechniqueDef.LightSpace.View, rm, tmpVec); + } else { + transposeLightDataToSpace(technique.getDef().getLightSpace(), rm, tmpVec); + } tmpLightDirection.set(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), spotAngleCos); lightDir.setValue(VarType.Vector4, tmpLightDirection); @@ -945,6 +953,12 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable { renderMeshFromGeometry(r, g); } } + + private void transposeLightDataToSpace(TechniqueDef.LightSpace space, RenderManager rm, Vector4f store){ + if(space == TechniqueDef.LightSpace.View){ + rm.getCurrentCamera().getViewMatrix().mult(store, store); + } + }; /** * Select the technique to use for rendering this material. @@ -1179,15 +1193,17 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable { Shader shader = technique.getShader(); + // send lighting information, if needed switch (techDef.getLightMode()) { case Disable: break; case SinglePass: + assert technique.getDef().getLightSpace()!= null; int nbRenderedLights = 0; resetUniformsNotSetByCurrent(shader); if (lights.size() == 0) { - nbRenderedLights = updateLightListUniforms(shader, geom, lights, rm.getSinglePassLightBatchSize(), rm, 0); + updateLightListUniforms(shader, geom, lights, rm.getSinglePassLightBatchSize(), rm, 0); r.setShader(shader); renderMeshFromGeometry(r, geom); } else { @@ -1201,6 +1217,7 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable { case FixedPipeline: throw new IllegalArgumentException("OpenGL1 is not supported"); case MultiPass: + assert technique.getDef().getLightSpace()!= null; // NOTE: Special case! resetUniformsNotSetByCurrent(shader); renderMultipassLighting(shader, geom, lights, rm); diff --git a/jme3-core/src/main/java/com/jme3/material/TechniqueDef.java b/jme3-core/src/main/java/com/jme3/material/TechniqueDef.java index e618a046c..6f129c958 100644 --- a/jme3-core/src/main/java/com/jme3/material/TechniqueDef.java +++ b/jme3-core/src/main/java/com/jme3/material/TechniqueDef.java @@ -90,6 +90,15 @@ public class TechniqueDef implements Savable { InPass, PostPass, } + + /** + * Define in what space the light data should be sent to the shader. + */ + public enum LightSpace { + World, + View, + Legacy + } private EnumSet requiredCaps = EnumSet.noneOf(Caps.class); private String name; @@ -111,6 +120,8 @@ public class TechniqueDef implements Savable { private HashMap defineParams; private ArrayList worldBinds; + //The space in which the light should be transposed before sending to the shader. + private LightSpace lightSpace; /** * Creates a new technique definition. @@ -161,6 +172,14 @@ public class TechniqueDef implements Savable { */ public void setLightMode(LightMode lightMode) { this.lightMode = lightMode; + //if light space is not specified we set it to Legacy + if(lightSpace == null){ + if(lightMode== LightMode.MultiPass){ + lightSpace = LightSpace.Legacy; + }else if(lightMode== LightMode.SinglePass){ + lightSpace = LightSpace.View; + } + } } /** @@ -530,5 +549,22 @@ public class TechniqueDef implements Savable { @Override public String toString() { return "TechniqueDef{" + "requiredCaps=" + requiredCaps + ", name=" + name /*+ ", vertName=" + vertName + ", fragName=" + fragName + ", vertLanguage=" + vertLanguage + ", fragLanguage=" + fragLanguage */+ ", presetDefines=" + presetDefines + ", usesShaders=" + usesShaders + ", usesNodes=" + usesNodes + ", shaderNodes=" + shaderNodes + ", shaderGenerationInfo=" + shaderGenerationInfo + ", renderState=" + renderState + ", forcedRenderState=" + forcedRenderState + ", lightMode=" + lightMode + ", shadowMode=" + shadowMode + ", defineParams=" + defineParams + ", worldBinds=" + worldBinds + '}'; - } + } + + /** + * Returns the space in which the light data should be passed to the shader. + * @return the light space + */ + public LightSpace getLightSpace() { + return lightSpace; + } + + /** + * Sets the space in which the light data should be passed to the shader. + * @param lightSpace the light space + */ + public void setLightSpace(LightSpace lightSpace) { + this.lightSpace = lightSpace; + } + }