- Reverted previous uniform change, it was causing changes in constants, when user was assigning a constant to a uniform (like mat.setColor("Color",ColorRGBA.White)).

- Changed Material's renderMultipassLighting method to not reuse Shader's values instance, and to use temporary allocated variables in the material instance instead

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7901 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
rem..om 14 years ago
parent 1bbbc3b0bb
commit c172b2e455
  1. 80
      engine/src/core/com/jme3/material/Material.java
  2. 192
      engine/src/core/com/jme3/shader/Uniform.java

@ -637,7 +637,7 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
Uniform lightPos = shader.getUniform("g_LightPosition"); Uniform lightPos = shader.getUniform("g_LightPosition");
Uniform lightDir = shader.getUniform("g_LightDirection"); Uniform lightDir = shader.getUniform("g_LightDirection");
lightColor.setVector4Length(numLights); lightColor.setVector4Length(numLights);
lightPos.setVector4Length(numLights); lightPos.setVector4Length(numLights);
lightDir.setVector4Length(numLights); lightDir.setVector4Length(numLights);
Uniform ambientColor = shader.getUniform("g_AmbientLightColor"); Uniform ambientColor = shader.getUniform("g_AmbientLightColor");
@ -667,16 +667,16 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
case Point: case Point:
PointLight pl = (PointLight) l; PointLight pl = (PointLight) l;
Vector3f pos = pl.getPosition(); Vector3f pos = pl.getPosition();
float invRadius = pl.getInvRadius(); float invRadius = pl.getInvRadius();
lightPos.setVector4InArray(pos.getX(), pos.getY(), pos.getZ(), invRadius, lightIndex); lightPos.setVector4InArray(pos.getX(), pos.getY(), pos.getZ(), invRadius, lightIndex);
break; break;
case Spot: case Spot:
SpotLight sl = (SpotLight) l; SpotLight sl = (SpotLight) l;
Vector3f pos2 = sl.getPosition(); Vector3f pos2 = sl.getPosition();
Vector3f dir2 = sl.getDirection(); Vector3f dir2 = sl.getDirection();
float invRange = sl.getInvSpotRange(); float invRange = sl.getInvSpotRange();
float spotAngleCos = sl.getPackedAngleCos(); float spotAngleCos = sl.getPackedAngleCos();
lightPos.setVector4InArray(pos2.getX(), pos2.getY(), pos2.getZ(), invRange, lightIndex); lightPos.setVector4InArray(pos2.getX(), pos2.getY(), pos2.getZ(), invRange, lightIndex);
lightDir.setVector4InArray(dir2.getX(), dir2.getY(), dir2.getZ(), spotAngleCos, lightIndex); lightDir.setVector4InArray(dir2.getX(), dir2.getY(), dir2.getZ(), spotAngleCos, lightIndex);
break; break;
@ -698,6 +698,9 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
lightIndex++; lightIndex++;
} }
} }
Quaternion tmpLightDirection = new Quaternion();
Quaternion tmpLightPosition = new Quaternion();
ColorRGBA tmpLightColor = new ColorRGBA();
protected void renderMultipassLighting(Shader shader, Geometry g, Renderer r) { protected void renderMultipassLighting(Shader shader, Geometry g, Renderer r) {
LightList lightList = g.getWorldLightList(); LightList lightList = g.getWorldLightList();
@ -727,66 +730,39 @@ public class Material implements Cloneable, Savable, Comparable<Material> {
} }
ColorRGBA color = l.getColor(); ColorRGBA color = l.getColor();
ColorRGBA color2; tmpLightColor.set(color);
if (lightColor.getValue() != null) { tmpLightColor.a = l.getType().getId();
color2 = (ColorRGBA) lightColor.getValue(); lightColor.setValue(VarType.Vector4, tmpLightColor);
} else {
color2 = new ColorRGBA();
}
color2.set(color);
color2.a = l.getType().getId();
lightColor.setValue(VarType.Vector4, color2);
switch (l.getType()) { switch (l.getType()) {
case Directional: case Directional:
DirectionalLight dl = (DirectionalLight) l; DirectionalLight dl = (DirectionalLight) l;
Vector3f dir = dl.getDirection(); Vector3f dir = dl.getDirection();
Quaternion q1;
if (lightPos.getValue() != null) { tmpLightPosition.set(dir.getX(), dir.getY(), dir.getZ(), -1);
q1 = (Quaternion) lightPos.getValue(); lightPos.setValue(VarType.Vector4, tmpLightPosition);
} else {
q1 = new Quaternion();
}
q1.set(dir.getX(), dir.getY(), dir.getZ(), -1);
lightPos.setValue(VarType.Vector4, q1);
break; break;
case Point: case Point:
PointLight pl = (PointLight) l; PointLight pl = (PointLight) l;
Vector3f pos = pl.getPosition(); Vector3f pos = pl.getPosition();
float invRadius = pl.getInvRadius(); float invRadius = pl.getInvRadius();
Quaternion q2;
if (lightPos.getValue() != null) { tmpLightPosition.set(pos.getX(), pos.getY(), pos.getZ(), invRadius);
q2 = (Quaternion) lightPos.getValue(); lightPos.setValue(VarType.Vector4, tmpLightPosition);
} else {
q2 = new Quaternion();
}
q2.set(pos.getX(), pos.getY(), pos.getZ(), invRadius);
lightPos.setValue(VarType.Vector4, q2);
break; break;
case Spot: case Spot:
SpotLight sl = (SpotLight) l; SpotLight sl = (SpotLight) l;
Vector3f pos2 = sl.getPosition(); Vector3f pos2 = sl.getPosition();
Vector3f dir2 = sl.getDirection(); Vector3f dir2 = sl.getDirection();
float invRange = sl.getInvSpotRange(); float invRange = sl.getInvSpotRange();
float spotAngleCos = sl.getPackedAngleCos(); float spotAngleCos = sl.getPackedAngleCos();
Quaternion q3,q4; tmpLightPosition.set(pos2.getX(), pos2.getY(), pos2.getZ(), invRange);
if (lightPos.getValue() != null) { lightPos.setValue(VarType.Vector4, tmpLightPosition);
q3 = (Quaternion) lightPos.getValue();
} else { tmpLightDirection.set(dir2.getX(), dir2.getY(), dir2.getZ(), spotAngleCos);
q3 = new Quaternion(); lightDir.setValue(VarType.Vector4, tmpLightDirection);
}
q3.set(pos2.getX(), pos2.getY(), pos2.getZ(), invRange);
lightPos.setValue(VarType.Vector4, q3);
if (lightDir.getValue() != null) {
q4 = (Quaternion) lightDir.getValue();
} else {
q4 = new Quaternion();
}
q4.set(dir2.getX(), dir2.getY(), dir2.getZ(), spotAngleCos);
lightDir.setValue(VarType.Vector4, q4);
break; break;
default: default:
throw new UnsupportedOperationException("Unknown type of light: " + l.getType()); throw new UnsupportedOperationException("Unknown type of light: " + l.getType());

@ -29,6 +29,7 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package com.jme3.shader; package com.jme3.shader;
import com.jme3.export.JmeExporter; import com.jme3.export.JmeExporter;
@ -41,7 +42,6 @@ import com.jme3.math.Matrix4f;
import com.jme3.math.Quaternion; import com.jme3.math.Quaternion;
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.util.BufferUtils; import com.jme3.util.BufferUtils;
import java.io.IOException; import java.io.IOException;
import java.nio.FloatBuffer; import java.nio.FloatBuffer;
@ -50,77 +50,81 @@ public class Uniform extends ShaderVariable {
private static final Integer ZERO_INT = Integer.valueOf(0); private static final Integer ZERO_INT = Integer.valueOf(0);
private static final Float ZERO_FLT = Float.valueOf(0); private static final Float ZERO_FLT = Float.valueOf(0);
private static final FloatBuffer ZERO_BUF = BufferUtils.createFloatBuffer(4 * 4); private static final FloatBuffer ZERO_BUF = BufferUtils.createFloatBuffer(4*4);
/** /**
* Currently set value of the uniform. * Currently set value of the uniform.
*/ */
protected Object value = null; protected Object value = null;
protected FloatBuffer multiData = null; protected FloatBuffer multiData = null;
/** /**
* Type of uniform * Type of uniform
*/ */
protected VarType varType; protected VarType varType;
/** /**
* Binding to a renderer value, or null if user-defined uniform * Binding to a renderer value, or null if user-defined uniform
*/ */
protected UniformBinding binding; protected UniformBinding binding;
protected boolean setByCurrentMaterial = false; protected boolean setByCurrentMaterial = false;
// protected Object lastChanger = null; // protected Object lastChanger = null;
@Override @Override
public void write(JmeExporter ex) throws IOException { public void write(JmeExporter ex) throws IOException{
super.write(ex); super.write(ex);
OutputCapsule oc = ex.getCapsule(this); OutputCapsule oc = ex.getCapsule(this);
oc.write(varType, "varType", null); oc.write(varType, "varType", null);
oc.write(binding, "binding", null); oc.write(binding, "binding", null);
switch (varType) { switch (varType){
case Boolean: case Boolean:
oc.write(((Boolean) value).booleanValue(), "valueBoolean", false); oc.write( ((Boolean)value).booleanValue(), "valueBoolean", false );
break; break;
case Float: case Float:
oc.write(((Float) value).floatValue(), "valueFloat", 0); oc.write( ((Float)value).floatValue(), "valueFloat", 0);
break; break;
case FloatArray: case FloatArray:
oc.write((FloatBuffer) value, "valueFloatArray", null); oc.write( (FloatBuffer)value, "valueFloatArray", null);
break; break;
case Int: case Int:
oc.write(((Integer) value).intValue(), "valueInt", 0); oc.write( ((Integer)value).intValue(), "valueInt", 0);
break; break;
case Matrix3: case Matrix3:
oc.write((Matrix3f) value, "valueMatrix3", null); oc.write( (Matrix3f)value, "valueMatrix3", null);
break; break;
case Matrix3Array: case Matrix3Array:
case Matrix4Array: case Matrix4Array:
case Vector2Array: case Vector2Array:
throw new UnsupportedOperationException("Come again?"); throw new UnsupportedOperationException("Come again?");
case Matrix4: case Matrix4:
oc.write((Matrix4f) value, "valueMatrix4", null); oc.write( (Matrix4f)value, "valueMatrix4", null);
break; break;
case Vector2: case Vector2:
oc.write((Vector2f) value, "valueVector2", null); oc.write( (Vector2f)value, "valueVector2", null);
break; break;
case Vector3: case Vector3:
oc.write((Vector3f) value, "valueVector3", null); oc.write( (Vector3f)value, "valueVector3", null);
break; break;
case Vector3Array: case Vector3Array:
oc.write((FloatBuffer) value, "valueVector3Array", null); oc.write( (FloatBuffer)value, "valueVector3Array", null);
break; break;
case Vector4: case Vector4:
oc.write((ColorRGBA) value, "valueVector4", null); oc.write( (ColorRGBA)value, "valueVector4", null);
break; break;
case Vector4Array: case Vector4Array:
oc.write((FloatBuffer) value, "valueVector4Array", null); oc.write( (FloatBuffer)value, "valueVector4Array", null);
break; break;
} }
} }
@Override @Override
public void read(JmeImporter im) throws IOException { public void read(JmeImporter im) throws IOException{
super.read(im); super.read(im);
InputCapsule ic = im.getCapsule(this); InputCapsule ic = im.getCapsule(this);
varType = ic.readEnum("varType", VarType.class, null); varType = ic.readEnum("varType", VarType.class, null);
binding = ic.readEnum("binding", UniformBinding.class, null); binding = ic.readEnum("binding", UniformBinding.class, null);
switch (varType) { switch (varType){
case Boolean: case Boolean:
value = ic.readBoolean("valueBoolean", false); value = ic.readBoolean("valueBoolean", false);
break; break;
@ -160,17 +164,17 @@ public class Uniform extends ShaderVariable {
} }
@Override @Override
public String toString() { public String toString(){
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
if (name != null) { if (name != null){
sb.append("Uniform[name="); sb.append("Uniform[name=");
sb.append(name); sb.append(name);
if (varType != null) { if (varType != null){
sb.append(", type="); sb.append(", type=");
sb.append(varType); sb.append(varType);
sb.append(", value="); sb.append(", value=");
sb.append(value); sb.append(value);
} else { }else{
sb.append(", value=<not set>"); sb.append(", value=<not set>");
} }
} }
@ -178,11 +182,11 @@ public class Uniform extends ShaderVariable {
return sb.toString(); return sb.toString();
} }
public void setBinding(UniformBinding binding) { public void setBinding(UniformBinding binding){
this.binding = binding; this.binding = binding;
} }
public UniformBinding getBinding() { public UniformBinding getBinding(){
return binding; return binding;
} }
@ -190,7 +194,7 @@ public class Uniform extends ShaderVariable {
return varType; return varType;
} }
public Object getValue() { public Object getValue(){
return value; return value;
} }
@ -198,7 +202,7 @@ public class Uniform extends ShaderVariable {
return setByCurrentMaterial; return setByCurrentMaterial;
} }
public void clearSetByCurrentMaterial() { public void clearSetByCurrentMaterial(){
setByCurrentMaterial = false; setByCurrentMaterial = false;
} }
@ -209,15 +213,16 @@ public class Uniform extends ShaderVariable {
// public Object getLastChanger(){ // public Object getLastChanger(){
// return lastChanger; // return lastChanger;
// } // }
public void clearValue() {
public void clearValue(){
updateNeeded = true; updateNeeded = true;
if (multiData != null) { if (multiData != null){
ZERO_BUF.clear(); ZERO_BUF.clear();
multiData.clear(); multiData.clear();
while (multiData.remaining() > 0) { while (multiData.remaining() > 0){
ZERO_BUF.limit(Math.min(multiData.remaining(), 16)); ZERO_BUF.limit( Math.min(multiData.remaining(), 16) );
multiData.put(ZERO_BUF); multiData.put(ZERO_BUF);
} }
@ -226,11 +231,10 @@ public class Uniform extends ShaderVariable {
return; return;
} }
if (varType == null) { if (varType == null)
return; return;
}
switch (varType) { switch (varType){
case Int: case Int:
this.value = ZERO_INT; this.value = ZERO_INT;
break; break;
@ -238,153 +242,140 @@ public class Uniform extends ShaderVariable {
this.value = Boolean.FALSE; this.value = Boolean.FALSE;
break; break;
case Float: case Float:
this.value = ZERO_FLT; this.value = ZERO_FLT;
break; break;
case Vector2: case Vector2:
((Vector2f) this.value).set(Vector2f.ZERO); this.value = Vector2f.ZERO;
break; break;
case Vector3: case Vector3:
((Vector3f) this.value).set(Vector3f.ZERO); this.value = Vector3f.ZERO;
break; break;
case Vector4: case Vector4:
if (this.value instanceof ColorRGBA) { if (this.value instanceof ColorRGBA){
((ColorRGBA) this.value).set(ColorRGBA.BlackNoAlpha); this.value = ColorRGBA.BlackNoAlpha;
} else if (this.value instanceof Quaternion) { }else{
((Quaternion) this.value).set(Quaternion.ZERO); this.value = Quaternion.ZERO;
} else {
((Vector4f) this.value).set(Vector4f.ZERO);
} }
break; break;
default: default:
break; // won't happen because those are either textures break; // won't happen because those are either textures
// or multidata types // or multidata types
} }
} }
public void setValue(VarType type, Object value) { public void setValue(VarType type, Object value){
if (location == -1) { if (location == -1)
return; return;
}
if (varType != null && varType != type) { if (varType != null && varType != type)
throw new IllegalArgumentException("Expected a " + varType.name() + " value!"); throw new IllegalArgumentException("Expected a "+varType.name()+" value!");
}
if (value == null) { if (value == null)
throw new NullPointerException(); throw new NullPointerException();
}
setByCurrentMaterial = true; setByCurrentMaterial = true;
switch (type) { switch (type){
case Matrix3: case Matrix3:
Matrix3f m3 = (Matrix3f) value; Matrix3f m3 = (Matrix3f) value;
if (multiData == null) { if (multiData == null)
multiData = BufferUtils.createFloatBuffer(9); multiData = BufferUtils.createFloatBuffer(9);
}
m3.fillFloatBuffer(multiData, true); m3.fillFloatBuffer(multiData, true);
multiData.clear(); multiData.clear();
break; break;
case Matrix4: case Matrix4:
Matrix4f m4 = (Matrix4f) value; Matrix4f m4 = (Matrix4f) value;
if (multiData == null) { if (multiData == null)
multiData = BufferUtils.createFloatBuffer(16); multiData = BufferUtils.createFloatBuffer(16);
}
m4.fillFloatBuffer(multiData, true); m4.fillFloatBuffer(multiData, true);
multiData.clear(); multiData.clear();
break; break;
case FloatArray: case FloatArray:
float[] fa = (float[]) value; float[] fa = (float[]) value;
if (multiData == null) { if (multiData == null){
multiData = BufferUtils.createFloatBuffer(fa); multiData = BufferUtils.createFloatBuffer(fa);
} else { }else{
multiData = BufferUtils.ensureLargeEnough(multiData, fa.length); multiData = BufferUtils.ensureLargeEnough(multiData, fa.length);
} }
multiData.put(fa); multiData.put(fa);
multiData.clear(); multiData.clear();
break; break;
case Vector2Array: case Vector2Array:
Vector2f[] v2a = (Vector2f[]) value; Vector2f[] v2a = (Vector2f[]) value;
if (multiData == null) { if (multiData == null){
multiData = BufferUtils.createFloatBuffer(v2a); multiData = BufferUtils.createFloatBuffer(v2a);
} else { } else {
multiData = BufferUtils.ensureLargeEnough(multiData, v2a.length * 2); multiData = BufferUtils.ensureLargeEnough(multiData, v2a.length * 2);
} }
for (int i = 0; i < v2a.length; i++) { for (int i = 0; i < v2a.length; i++)
BufferUtils.setInBuffer(v2a[i], multiData, i); BufferUtils.setInBuffer(v2a[i], multiData, i);
}
multiData.clear(); multiData.clear();
break; break;
case Vector3Array: case Vector3Array:
Vector3f[] v3a = (Vector3f[]) value; Vector3f[] v3a = (Vector3f[]) value;
if (multiData == null) { if (multiData == null){
multiData = BufferUtils.createFloatBuffer(v3a); multiData = BufferUtils.createFloatBuffer(v3a);
} else { } else{
multiData = BufferUtils.ensureLargeEnough(multiData, v3a.length * 3); multiData = BufferUtils.ensureLargeEnough(multiData, v3a.length * 3);
} }
for (int i = 0; i < v3a.length; i++) { for (int i = 0; i < v3a.length; i++)
BufferUtils.setInBuffer(v3a[i], multiData, i); BufferUtils.setInBuffer(v3a[i], multiData, i);
}
multiData.clear(); multiData.clear();
break; break;
case Vector4Array: case Vector4Array:
Quaternion[] v4a = (Quaternion[]) value; Quaternion[] v4a = (Quaternion[]) value;
if (multiData == null) { if (multiData == null){
multiData = BufferUtils.createFloatBuffer(v4a); multiData = BufferUtils.createFloatBuffer(v4a);
} else { } else {
multiData = BufferUtils.ensureLargeEnough(multiData, v4a.length * 4); multiData = BufferUtils.ensureLargeEnough(multiData, v4a.length * 4);
} }
for (int i = 0; i < v4a.length; i++) { for (int i = 0; i < v4a.length; i++)
BufferUtils.setInBuffer(v4a[i], multiData, i); BufferUtils.setInBuffer(v4a[i], multiData, i);
}
multiData.clear(); multiData.clear();
break; break;
case Matrix3Array: case Matrix3Array:
Matrix3f[] m3a = (Matrix3f[]) value; Matrix3f[] m3a = (Matrix3f[]) value;
if (multiData == null) { if (multiData == null)
multiData = BufferUtils.createFloatBuffer(m3a.length * 9); multiData = BufferUtils.createFloatBuffer(m3a.length * 9);
} else { else{
multiData = BufferUtils.ensureLargeEnough(multiData, m3a.length * 9); multiData = BufferUtils.ensureLargeEnough(multiData, m3a.length * 9);
} }
for (int i = 0; i < m3a.length; i++) { for (int i = 0; i < m3a.length; i++)
m3a[i].fillFloatBuffer(multiData, true); m3a[i].fillFloatBuffer(multiData, true);
}
multiData.clear(); multiData.clear();
break; break;
case Matrix4Array: case Matrix4Array:
Matrix4f[] m4a = (Matrix4f[]) value; Matrix4f[] m4a = (Matrix4f[]) value;
if (multiData == null) { if (multiData == null)
multiData = BufferUtils.createFloatBuffer(m4a.length * 16); multiData = BufferUtils.createFloatBuffer(m4a.length * 16);
} else { else{
multiData = BufferUtils.ensureLargeEnough(multiData, m4a.length * 16); multiData = BufferUtils.ensureLargeEnough(multiData, m4a.length * 16);
} }
for (int i = 0; i < m4a.length; i++) { for (int i = 0; i < m4a.length; i++)
m4a[i].fillFloatBuffer(multiData, true); m4a[i].fillFloatBuffer(multiData, true);
}
multiData.clear(); multiData.clear();
break; break;
// Only use check if equals optimization for primitive values // Only use check if equals optimization for primitive values
case Int: case Int:
case Float: case Float:
case Boolean: case Boolean:
if (this.value != null && this.value.equals(value)) { if (this.value != null && this.value.equals(value))
return; return;
}
this.value = value; this.value = value;
break; break;
@ -393,21 +384,19 @@ public class Uniform extends ShaderVariable {
break; break;
} }
if (multiData != null) { if (multiData != null)
this.value = multiData; this.value = multiData;
}
varType = type; varType = type;
updateNeeded = true; updateNeeded = true;
} }
public void setVector4Length(int length) { public void setVector4Length(int length){
if (location == -1) { if (location == -1)
return; return;
}
FloatBuffer fb = (FloatBuffer) value; FloatBuffer fb = (FloatBuffer) value;
if (fb == null || fb.capacity() < length) { if (fb == null || fb.capacity() < length){
value = BufferUtils.createFloatBuffer(length * 4); value = BufferUtils.createFloatBuffer(length * 4);
} }
@ -416,14 +405,12 @@ public class Uniform extends ShaderVariable {
setByCurrentMaterial = true; setByCurrentMaterial = true;
} }
public void setVector4InArray(float x, float y, float z, float w, int index) { public void setVector4InArray(float x, float y, float z, float w, int index){
if (location == -1) { if (location == -1)
return; return;
}
if (varType != null && varType != VarType.Vector4Array) { if (varType != null && varType != VarType.Vector4Array)
throw new IllegalArgumentException("Expected a " + varType.name() + " value!"); throw new IllegalArgumentException("Expected a "+varType.name()+" value!");
}
FloatBuffer fb = (FloatBuffer) value; FloatBuffer fb = (FloatBuffer) value;
fb.position(index * 4); fb.position(index * 4);
@ -432,18 +419,19 @@ public class Uniform extends ShaderVariable {
updateNeeded = true; updateNeeded = true;
setByCurrentMaterial = true; setByCurrentMaterial = true;
} }
public boolean isUpdateNeeded() { public boolean isUpdateNeeded(){
return updateNeeded; return updateNeeded;
} }
public void clearUpdateNeeded() { public void clearUpdateNeeded(){
updateNeeded = false; updateNeeded = false;
} }
public void reset() { public void reset(){
setByCurrentMaterial = false; setByCurrentMaterial = false;
location = -2; location = -2;
updateNeeded = true; updateNeeded = true;
} }
} }

Loading…
Cancel
Save