aboutsummaryrefslogtreecommitdiff
path: root/engine/src/core/com/jme3/shader/Uniform.java
diff options
context:
space:
mode:
Diffstat (limited to 'engine/src/core/com/jme3/shader/Uniform.java')
-rw-r--r--engine/src/core/com/jme3/shader/Uniform.java432
1 files changed, 432 insertions, 0 deletions
diff --git a/engine/src/core/com/jme3/shader/Uniform.java b/engine/src/core/com/jme3/shader/Uniform.java
new file mode 100644
index 0000000..228e097
--- /dev/null
+++ b/engine/src/core/com/jme3/shader/Uniform.java
@@ -0,0 +1,432 @@
+/*
+ * 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.shader;
+
+import com.jme3.export.InputCapsule;
+import com.jme3.export.JmeExporter;
+import com.jme3.export.JmeImporter;
+import com.jme3.export.OutputCapsule;
+import com.jme3.math.*;
+import com.jme3.util.BufferUtils;
+import java.io.IOException;
+import java.nio.FloatBuffer;
+
+public class Uniform extends ShaderVariable {
+
+ private static final Integer ZERO_INT = Integer.valueOf(0);
+ private static final Float ZERO_FLT = Float.valueOf(0);
+ private static final FloatBuffer ZERO_BUF = BufferUtils.createFloatBuffer(4*4);
+
+ /**
+ * Currently set value of the uniform.
+ */
+ protected Object value = null;
+ protected FloatBuffer multiData = null;
+
+ /**
+ * Type of uniform
+ */
+ protected VarType varType;
+
+ /**
+ * Binding to a renderer value, or null if user-defined uniform
+ */
+ protected UniformBinding binding;
+
+ protected boolean setByCurrentMaterial = false;
+// protected Object lastChanger = null;
+
+ @Override
+ public void write(JmeExporter ex) throws IOException{
+ super.write(ex);
+ OutputCapsule oc = ex.getCapsule(this);
+ oc.write(varType, "varType", null);
+ oc.write(binding, "binding", null);
+ switch (varType){
+ case Boolean:
+ oc.write( ((Boolean)value).booleanValue(), "valueBoolean", false );
+ break;
+ case Float:
+ oc.write( ((Float)value).floatValue(), "valueFloat", 0);
+ break;
+ case FloatArray:
+ oc.write( (FloatBuffer)value, "valueFloatArray", null);
+ break;
+ case Int:
+ oc.write( ((Integer)value).intValue(), "valueInt", 0);
+ break;
+ case Matrix3:
+ oc.write( (Matrix3f)value, "valueMatrix3", null);
+ break;
+ case Matrix3Array:
+ case Matrix4Array:
+ case Vector2Array:
+ throw new UnsupportedOperationException("Come again?");
+ case Matrix4:
+ oc.write( (Matrix4f)value, "valueMatrix4", null);
+ break;
+ case Vector2:
+ oc.write( (Vector2f)value, "valueVector2", null);
+ break;
+ case Vector3:
+ oc.write( (Vector3f)value, "valueVector3", null);
+ break;
+ case Vector3Array:
+ oc.write( (FloatBuffer)value, "valueVector3Array", null);
+ break;
+ case Vector4:
+ oc.write( (ColorRGBA)value, "valueVector4", null);
+ break;
+ case Vector4Array:
+ oc.write( (FloatBuffer)value, "valueVector4Array", null);
+ break;
+ }
+ }
+
+ @Override
+ public void read(JmeImporter im) throws IOException{
+ super.read(im);
+ InputCapsule ic = im.getCapsule(this);
+ varType = ic.readEnum("varType", VarType.class, null);
+ binding = ic.readEnum("binding", UniformBinding.class, null);
+ switch (varType){
+ case Boolean:
+ value = ic.readBoolean("valueBoolean", false);
+ break;
+ case Float:
+ value = ic.readFloat("valueFloat", 0);
+ break;
+ case FloatArray:
+ value = ic.readFloatBuffer("valueFloatArray", null);
+ break;
+ case Int:
+ value = ic.readInt("valueInt", 0);
+ break;
+ case Matrix3:
+ multiData = ic.readFloatBuffer("valueMatrix3", null);
+ value = multiData;
+ break;
+ case Matrix4:
+ multiData = ic.readFloatBuffer("valueMatrix4", null);
+ value = multiData;
+ break;
+ case Vector2:
+ value = ic.readSavable("valueVector2", null);
+ break;
+ case Vector3:
+ value = ic.readSavable("valueVector3", null);
+ break;
+ case Vector3Array:
+ value = ic.readFloatBuffer("valueVector3Array", null);
+ break;
+ case Vector4:
+ value = ic.readSavable("valueVector4", null);
+ break;
+ case Vector4Array:
+ value = ic.readFloatBuffer("valueVector4Array", null);
+ break;
+ }
+ }
+
+ @Override
+ public String toString(){
+ StringBuilder sb = new StringBuilder();
+ if (name != null){
+ sb.append("Uniform[name=");
+ sb.append(name);
+ if (varType != null){
+ sb.append(", type=");
+ sb.append(varType);
+ sb.append(", value=");
+ sb.append(value);
+ }else{
+ sb.append(", value=<not set>");
+ }
+ }
+ sb.append("]");
+ return sb.toString();
+ }
+
+ public void setBinding(UniformBinding binding){
+ this.binding = binding;
+ }
+
+ public UniformBinding getBinding(){
+ return binding;
+ }
+
+ public VarType getVarType() {
+ return varType;
+ }
+
+ public Object getValue(){
+ return value;
+ }
+
+ public boolean isSetByCurrentMaterial() {
+ return setByCurrentMaterial;
+ }
+
+ public void clearSetByCurrentMaterial(){
+ setByCurrentMaterial = false;
+ }
+
+// public void setLastChanger(Object lastChanger){
+// this.lastChanger = lastChanger;
+// }
+//
+// public Object getLastChanger(){
+// return lastChanger;
+// }
+
+ public void clearValue(){
+ updateNeeded = true;
+
+ if (multiData != null){
+ ZERO_BUF.clear();
+ multiData.clear();
+
+ while (multiData.remaining() > 0){
+ ZERO_BUF.limit( Math.min(multiData.remaining(), 16) );
+ multiData.put(ZERO_BUF);
+ }
+
+ multiData.clear();
+
+ return;
+ }
+
+ if (varType == null)
+ return;
+
+ switch (varType){
+ case Int:
+ this.value = ZERO_INT;
+ break;
+ case Boolean:
+ this.value = Boolean.FALSE;
+ break;
+ case Float:
+ this.value = ZERO_FLT;
+ break;
+ case Vector2:
+ this.value = Vector2f.ZERO;
+ break;
+ case Vector3:
+ this.value = Vector3f.ZERO;
+ break;
+ case Vector4:
+ if (this.value instanceof ColorRGBA){
+ this.value = ColorRGBA.BlackNoAlpha;
+ }else{
+ this.value = Quaternion.ZERO;
+ }
+ break;
+ default:
+ break; // won't happen because those are either textures
+ // or multidata types
+ }
+ }
+
+ public void setValue(VarType type, Object value){
+ if (location == -1)
+ return;
+
+ if (varType != null && varType != type)
+ throw new IllegalArgumentException("Expected a "+varType.name()+" value!");
+
+ if (value == null)
+ throw new NullPointerException();
+
+ setByCurrentMaterial = true;
+
+ switch (type){
+ case Matrix3:
+ Matrix3f m3 = (Matrix3f) value;
+ if (multiData == null)
+ multiData = BufferUtils.createFloatBuffer(9);
+
+ m3.fillFloatBuffer(multiData, true);
+ multiData.clear();
+ break;
+ case Matrix4:
+ Matrix4f m4 = (Matrix4f) value;
+ if (multiData == null)
+ multiData = BufferUtils.createFloatBuffer(16);
+
+ m4.fillFloatBuffer(multiData, true);
+ multiData.clear();
+ break;
+ case FloatArray:
+ float[] fa = (float[]) value;
+ if (multiData == null){
+ multiData = BufferUtils.createFloatBuffer(fa);
+ }else{
+ multiData = BufferUtils.ensureLargeEnough(multiData, fa.length);
+ }
+
+ multiData.put(fa);
+ multiData.clear();
+ break;
+ case Vector2Array:
+ Vector2f[] v2a = (Vector2f[]) value;
+ if (multiData == null){
+ multiData = BufferUtils.createFloatBuffer(v2a);
+ } else {
+ multiData = BufferUtils.ensureLargeEnough(multiData, v2a.length * 2);
+ }
+
+ for (int i = 0; i < v2a.length; i++)
+ BufferUtils.setInBuffer(v2a[i], multiData, i);
+
+ multiData.clear();
+ break;
+ case Vector3Array:
+ Vector3f[] v3a = (Vector3f[]) value;
+ if (multiData == null){
+ multiData = BufferUtils.createFloatBuffer(v3a);
+ } else{
+ multiData = BufferUtils.ensureLargeEnough(multiData, v3a.length * 3);
+ }
+
+ for (int i = 0; i < v3a.length; i++)
+ BufferUtils.setInBuffer(v3a[i], multiData, i);
+
+ multiData.clear();
+ break;
+ case Vector4Array:
+ Quaternion[] v4a = (Quaternion[]) value;
+ if (multiData == null){
+ multiData = BufferUtils.createFloatBuffer(v4a);
+ } else {
+ multiData = BufferUtils.ensureLargeEnough(multiData, v4a.length * 4);
+ }
+
+ for (int i = 0; i < v4a.length; i++)
+ BufferUtils.setInBuffer(v4a[i], multiData, i);
+
+ multiData.clear();
+ break;
+ case Matrix3Array:
+ Matrix3f[] m3a = (Matrix3f[]) value;
+
+ if (multiData == null)
+ multiData = BufferUtils.createFloatBuffer(m3a.length * 9);
+ else{
+ multiData = BufferUtils.ensureLargeEnough(multiData, m3a.length * 9);
+ }
+
+ for (int i = 0; i < m3a.length; i++)
+ m3a[i].fillFloatBuffer(multiData, true);
+
+ multiData.clear();
+ break;
+ case Matrix4Array:
+ Matrix4f[] m4a = (Matrix4f[]) value;
+
+ if (multiData == null)
+ multiData = BufferUtils.createFloatBuffer(m4a.length * 16);
+ else{
+ multiData = BufferUtils.ensureLargeEnough(multiData, m4a.length * 16);
+ }
+
+ for (int i = 0; i < m4a.length; i++)
+ m4a[i].fillFloatBuffer(multiData, true);
+
+ multiData.clear();
+ break;
+ // Only use check if equals optimization for primitive values
+ case Int:
+ case Float:
+ case Boolean:
+ if (this.value != null && this.value.equals(value))
+ return;
+
+ this.value = value;
+ break;
+ default:
+ this.value = value;
+ break;
+ }
+
+ if (multiData != null)
+ this.value = multiData;
+
+ varType = type;
+ updateNeeded = true;
+ }
+
+ public void setVector4Length(int length){
+ if (location == -1)
+ return;
+
+ FloatBuffer fb = (FloatBuffer) value;
+ if (fb == null || fb.capacity() < length){
+ value = BufferUtils.createFloatBuffer(length * 4);
+ }
+
+ varType = VarType.Vector4Array;
+ updateNeeded = true;
+ setByCurrentMaterial = true;
+ }
+
+ public void setVector4InArray(float x, float y, float z, float w, int index){
+ if (location == -1)
+ return;
+
+ if (varType != null && varType != VarType.Vector4Array)
+ throw new IllegalArgumentException("Expected a "+varType.name()+" value!");
+
+ FloatBuffer fb = (FloatBuffer) value;
+ fb.position(index * 4);
+ fb.put(x).put(y).put(z).put(w);
+ fb.rewind();
+ updateNeeded = true;
+ setByCurrentMaterial = true;
+ }
+
+ public boolean isUpdateNeeded(){
+ return updateNeeded;
+ }
+
+ public void clearUpdateNeeded(){
+ updateNeeded = false;
+ }
+
+ public void reset(){
+ setByCurrentMaterial = false;
+ location = -2;
+ updateNeeded = true;
+ }
+
+}