shader-nodes-enhancement
parent
302e746a94
commit
266d8b0828
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,828 @@ |
|||||||
|
package com.jme3.shader; |
||||||
|
|
||||||
|
import com.jme3.math.*; |
||||||
|
import com.jme3.renderer.Caps; |
||||||
|
import com.jme3.renderer.Renderer; |
||||||
|
import com.jme3.util.BufferUtils; |
||||||
|
import com.jme3.util.NativeObject; |
||||||
|
import com.jme3.util.SafeArrayList; |
||||||
|
|
||||||
|
import java.nio.ByteBuffer; |
||||||
|
import java.util.Collection; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
/** |
||||||
|
* The base implementation of BO. |
||||||
|
* |
||||||
|
* @author JavaSaBr |
||||||
|
*/ |
||||||
|
public class BufferObject extends NativeObject { |
||||||
|
|
||||||
|
private static final Map<Class<?>, VarType> CLASS_TO_VAR_TYPE = new HashMap<>(); |
||||||
|
|
||||||
|
static { |
||||||
|
CLASS_TO_VAR_TYPE.put(Float.class, VarType.Float); |
||||||
|
CLASS_TO_VAR_TYPE.put(Integer.class, VarType.Int); |
||||||
|
CLASS_TO_VAR_TYPE.put(Boolean.class, VarType.Boolean); |
||||||
|
CLASS_TO_VAR_TYPE.put(Vector2f.class, VarType.Vector2); |
||||||
|
CLASS_TO_VAR_TYPE.put(Vector3f.class, VarType.Vector3); |
||||||
|
CLASS_TO_VAR_TYPE.put(ColorRGBA.class, VarType.Vector4); |
||||||
|
CLASS_TO_VAR_TYPE.put(Quaternion.class, VarType.Vector4); |
||||||
|
CLASS_TO_VAR_TYPE.put(Vector4f.class, VarType.Vector4); |
||||||
|
|
||||||
|
CLASS_TO_VAR_TYPE.put(Vector2f[].class, VarType.Vector2Array); |
||||||
|
CLASS_TO_VAR_TYPE.put(Vector3f[].class, VarType.Vector3Array); |
||||||
|
CLASS_TO_VAR_TYPE.put(Vector4f[].class, VarType.Vector4Array); |
||||||
|
CLASS_TO_VAR_TYPE.put(ColorRGBA[].class, VarType.Vector4Array); |
||||||
|
CLASS_TO_VAR_TYPE.put(Quaternion[].class, VarType.Vector4Array); |
||||||
|
|
||||||
|
CLASS_TO_VAR_TYPE.put(Matrix3f.class, VarType.Matrix3); |
||||||
|
CLASS_TO_VAR_TYPE.put(Matrix4f.class, VarType.Matrix4); |
||||||
|
CLASS_TO_VAR_TYPE.put(Matrix3f[].class, VarType.Matrix3Array); |
||||||
|
CLASS_TO_VAR_TYPE.put(Matrix4f[].class, VarType.Matrix4Array); |
||||||
|
} |
||||||
|
|
||||||
|
protected static VarType getVarTypeByValue(final Object value) { |
||||||
|
|
||||||
|
final VarType varType = CLASS_TO_VAR_TYPE.get(value.getClass()); |
||||||
|
if (varType != null) { |
||||||
|
return varType; |
||||||
|
} else if (value instanceof Collection<?> && ((Collection) value).isEmpty()) { |
||||||
|
throw new IllegalArgumentException("Can't calculate a var type for the empty collection value[" + value + "]."); |
||||||
|
} else if (value instanceof List<?>) { |
||||||
|
return getVarTypeByValue(((List) value).get(0)); |
||||||
|
} else if (value instanceof Collection<?>) { |
||||||
|
return getVarTypeByValue(((Collection) value).iterator().next()); |
||||||
|
} |
||||||
|
|
||||||
|
throw new IllegalArgumentException("Can't calculate a var type for the value " + value); |
||||||
|
} |
||||||
|
|
||||||
|
public enum Layout { |
||||||
|
std140, |
||||||
|
/** unsupported yet */ |
||||||
|
@Deprecated |
||||||
|
std430, |
||||||
|
} |
||||||
|
|
||||||
|
public enum BufferType { |
||||||
|
ShaderStorageBufferObject(Caps.ShaderStorageBufferObject), |
||||||
|
UniformBufferObject(Caps.UniformBufferObject), |
||||||
|
; |
||||||
|
|
||||||
|
private final Caps requiredCaps; |
||||||
|
|
||||||
|
BufferType(final Caps requiredCaps) { |
||||||
|
this.requiredCaps = requiredCaps; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get the required caps. |
||||||
|
* |
||||||
|
* @return the required caps. |
||||||
|
*/ |
||||||
|
public Caps getRequiredCaps() { |
||||||
|
return requiredCaps; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* The fields of this BO. |
||||||
|
*/ |
||||||
|
private final Map<String, BufferObjectField> fields; |
||||||
|
|
||||||
|
/** |
||||||
|
* The field's array. |
||||||
|
*/ |
||||||
|
private final SafeArrayList<BufferObjectField> fieldArray; |
||||||
|
|
||||||
|
/** |
||||||
|
* The buffer's data layout. |
||||||
|
*/ |
||||||
|
private final Layout layout; |
||||||
|
|
||||||
|
/** |
||||||
|
* The binding number. |
||||||
|
*/ |
||||||
|
private final int binding; |
||||||
|
|
||||||
|
/** |
||||||
|
* The buffer's type. |
||||||
|
*/ |
||||||
|
private BufferType bufferType; |
||||||
|
|
||||||
|
/** |
||||||
|
* The previous data buffer. |
||||||
|
*/ |
||||||
|
private ByteBuffer previousData; |
||||||
|
|
||||||
|
public BufferObject(final int binding, final Layout layout, final BufferType bufferType) { |
||||||
|
this.handleRef = new Object(); |
||||||
|
this.bufferType = bufferType; |
||||||
|
this.binding = binding; |
||||||
|
this.layout = layout; |
||||||
|
this.fields = new HashMap<>(); |
||||||
|
this.fieldArray = new SafeArrayList<>(BufferObjectField.class); |
||||||
|
} |
||||||
|
|
||||||
|
public BufferObject(final int binding, final Layout layout) { |
||||||
|
this(binding, layout, BufferType.UniformBufferObject); |
||||||
|
} |
||||||
|
|
||||||
|
public BufferObject(final int binding, final BufferType bufferType) { |
||||||
|
this(binding, Layout.std140, bufferType); |
||||||
|
} |
||||||
|
|
||||||
|
public BufferObject(final BufferType bufferType) { |
||||||
|
this(1, Layout.std140, bufferType); |
||||||
|
} |
||||||
|
|
||||||
|
public BufferObject(final Layout layout) { |
||||||
|
this(1, layout, BufferType.UniformBufferObject); |
||||||
|
} |
||||||
|
|
||||||
|
public BufferObject(final int binding) { |
||||||
|
this(binding, Layout.std140, BufferType.UniformBufferObject); |
||||||
|
} |
||||||
|
|
||||||
|
public BufferObject() { |
||||||
|
this(1, Layout.std140, BufferType.UniformBufferObject); |
||||||
|
} |
||||||
|
|
||||||
|
private BufferObject(final Void unused, final int id) { |
||||||
|
super(id); |
||||||
|
this.fieldArray = null; |
||||||
|
this.fields = null; |
||||||
|
this.layout = null; |
||||||
|
this.binding = 0; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Declares a filed in this BO. |
||||||
|
* |
||||||
|
* @param name the field's name. |
||||||
|
* @param varType the field's type. |
||||||
|
*/ |
||||||
|
public void declareField(final String name, final VarType varType) { |
||||||
|
|
||||||
|
if (fields.containsKey(name)) { |
||||||
|
throw new IllegalArgumentException("The field " + name + " is already declared."); |
||||||
|
} |
||||||
|
|
||||||
|
final BufferObjectField field = new BufferObjectField(name, varType); |
||||||
|
|
||||||
|
fields.put(name, field); |
||||||
|
fieldArray.add(field); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Gets the buffer's type. |
||||||
|
* |
||||||
|
* @return the buffer's type. |
||||||
|
*/ |
||||||
|
public BufferType getBufferType() { |
||||||
|
return bufferType; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Sets the buffer's type. |
||||||
|
* |
||||||
|
* @param bufferType the buffer's type. |
||||||
|
*/ |
||||||
|
public void setBufferType(final BufferType bufferType) { |
||||||
|
|
||||||
|
if (getId() != -1) { |
||||||
|
throw new IllegalStateException("Can't change buffer's type when this buffer is already initialized."); |
||||||
|
} |
||||||
|
|
||||||
|
this.bufferType = bufferType; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Sets the value to the filed by the field's name. |
||||||
|
* |
||||||
|
* @param name the field's name. |
||||||
|
* @param value the value. |
||||||
|
*/ |
||||||
|
public void setFieldValue(final String name, final Object value) { |
||||||
|
|
||||||
|
BufferObjectField field = fields.get(name); |
||||||
|
|
||||||
|
if (field == null) { |
||||||
|
declareField(name, getVarTypeByValue(value)); |
||||||
|
field = fields.get(name); |
||||||
|
} |
||||||
|
|
||||||
|
field.setValue(value); |
||||||
|
setUpdateNeeded(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Gets the current value of the field by the name. |
||||||
|
* |
||||||
|
* @param name the field name. |
||||||
|
* @param <T> the value's type. |
||||||
|
* @return the current value. |
||||||
|
*/ |
||||||
|
public <T> T getFieldValue(final String name) { |
||||||
|
|
||||||
|
final BufferObjectField field = fields.get(name); |
||||||
|
if (field == null) { |
||||||
|
throw new IllegalArgumentException("Unknown a field with the name " + name); |
||||||
|
} |
||||||
|
|
||||||
|
return (T) field.getValue(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get the binding number. |
||||||
|
* |
||||||
|
* @return the binding number. |
||||||
|
*/ |
||||||
|
public int getBinding() { |
||||||
|
return binding; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void resetObject() { |
||||||
|
this.id = -1; |
||||||
|
setUpdateNeeded(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Computes the current binary data of this BO. |
||||||
|
* |
||||||
|
* @param maxSize the max data size. |
||||||
|
* @return the current binary data of this BO. |
||||||
|
*/ |
||||||
|
public ByteBuffer computeData(final int maxSize) { |
||||||
|
|
||||||
|
int estimateSize = 0; |
||||||
|
|
||||||
|
for (final BufferObjectField field : fieldArray) { |
||||||
|
estimateSize += estimateSize(field); |
||||||
|
} |
||||||
|
|
||||||
|
if(maxSize < estimateSize) { |
||||||
|
throw new IllegalStateException("The estimated size(" + estimateSize + ") of this BO is bigger than " + |
||||||
|
"maximum available size " + maxSize); |
||||||
|
} |
||||||
|
|
||||||
|
if (previousData != null) { |
||||||
|
if (previousData.capacity() < estimateSize) { |
||||||
|
BufferUtils.destroyDirectBuffer(previousData); |
||||||
|
previousData = null; |
||||||
|
} else { |
||||||
|
previousData.clear(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
final ByteBuffer data = previousData == null ? BufferUtils.createByteBuffer(estimateSize) : previousData; |
||||||
|
|
||||||
|
for (final BufferObjectField field : fieldArray) { |
||||||
|
writeField(field, data); |
||||||
|
} |
||||||
|
|
||||||
|
data.flip(); |
||||||
|
|
||||||
|
this.previousData = data; |
||||||
|
|
||||||
|
return data; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Estimates size of the field. |
||||||
|
* |
||||||
|
* @param field the field. |
||||||
|
* @return the estimated size. |
||||||
|
*/ |
||||||
|
protected int estimateSize(final BufferObjectField field) { |
||||||
|
|
||||||
|
switch (field.getType()) { |
||||||
|
case Float: |
||||||
|
case Int: { |
||||||
|
if (layout == Layout.std140) { |
||||||
|
return 16; |
||||||
|
} |
||||||
|
return 4; |
||||||
|
} |
||||||
|
case Boolean: { |
||||||
|
if (layout == Layout.std140) { |
||||||
|
return 16; |
||||||
|
} |
||||||
|
return 1; |
||||||
|
} |
||||||
|
case Vector2: { |
||||||
|
return 4 * 2; |
||||||
|
} |
||||||
|
case Vector3: { |
||||||
|
final int multiplier = layout == Layout.std140 ? 4 : 3; |
||||||
|
return 4 * multiplier; |
||||||
|
} |
||||||
|
case Vector4: |
||||||
|
return 16; |
||||||
|
case IntArray: { |
||||||
|
return estimate((int[]) field.getValue()); |
||||||
|
} |
||||||
|
case FloatArray: { |
||||||
|
return estimate((float[]) field.getValue()); |
||||||
|
} |
||||||
|
case Vector2Array: { |
||||||
|
return estimateArray(field.getValue(), 8); |
||||||
|
} |
||||||
|
case Vector3Array: { |
||||||
|
final int multiplier = layout == Layout.std140 ? 16 : 12; |
||||||
|
return estimateArray(field.getValue(), multiplier); |
||||||
|
} |
||||||
|
case Vector4Array: { |
||||||
|
return estimateArray(field.getValue(), 16); |
||||||
|
} |
||||||
|
case Matrix3: { |
||||||
|
final int multiplier = layout == Layout.std140 ? 16 : 12; |
||||||
|
return 3 * 3 * multiplier; |
||||||
|
} |
||||||
|
case Matrix4: { |
||||||
|
return 4 * 4 * 4; |
||||||
|
} |
||||||
|
case Matrix3Array: { |
||||||
|
int multiplier = layout == Layout.std140 ? 16 : 12; |
||||||
|
multiplier = 3 * 3 * multiplier; |
||||||
|
return estimateArray(field.getValue(), multiplier); |
||||||
|
} |
||||||
|
case Matrix4Array: { |
||||||
|
final int multiplier = 4 * 4 * 16; |
||||||
|
return estimateArray(field.getValue(), multiplier); |
||||||
|
} |
||||||
|
default: { |
||||||
|
throw new IllegalArgumentException("The type of BO field " + field.getType() + " doesn't support."); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Estimates bytes count to present the value on GPU. |
||||||
|
* |
||||||
|
* @param value the value. |
||||||
|
* @param multiplier the multiplier. |
||||||
|
* @return the estimated bytes cunt. |
||||||
|
*/ |
||||||
|
protected int estimateArray(final Object value, final int multiplier) { |
||||||
|
|
||||||
|
if (value instanceof Object[]) { |
||||||
|
return ((Object[]) value).length * multiplier; |
||||||
|
} else if (value instanceof Collection) { |
||||||
|
return ((Collection) value).size() * multiplier; |
||||||
|
} |
||||||
|
|
||||||
|
throw new IllegalArgumentException("Unexpected value " + value); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Estimates bytes count to present the values on GPU. |
||||||
|
* |
||||||
|
* @param values the values. |
||||||
|
* @return the estimated bytes cunt. |
||||||
|
*/ |
||||||
|
protected int estimate(final float[] values) { |
||||||
|
return values.length * 4; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Estimates bytes count to present the values on GPU. |
||||||
|
* |
||||||
|
* @param values the values. |
||||||
|
* @return the estimated bytes cunt. |
||||||
|
*/ |
||||||
|
protected int estimate(final int[] values) { |
||||||
|
return values.length * 4; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Writes the field to the data buffer. |
||||||
|
* |
||||||
|
* @param field the field. |
||||||
|
* @param data the data buffer. |
||||||
|
*/ |
||||||
|
protected void writeField(final BufferObjectField field, final ByteBuffer data) { |
||||||
|
|
||||||
|
final Object value = field.getValue(); |
||||||
|
|
||||||
|
switch (field.getType()) { |
||||||
|
case Int: { |
||||||
|
data.putInt(((Number) value).intValue()); |
||||||
|
if (layout == Layout.std140) { |
||||||
|
data.putInt(0); |
||||||
|
data.putLong(0); |
||||||
|
} |
||||||
|
break; |
||||||
|
} |
||||||
|
case Float: { |
||||||
|
data.putFloat(((Number) value).floatValue()); |
||||||
|
if (layout == Layout.std140) { |
||||||
|
data.putInt(0); |
||||||
|
data.putLong(0); |
||||||
|
} |
||||||
|
break; |
||||||
|
} |
||||||
|
case Boolean: |
||||||
|
data.put((byte) (((Boolean) value) ? 1 : 0)); |
||||||
|
if (layout == Layout.std140) { |
||||||
|
data.putInt(0); |
||||||
|
data.putLong(0); |
||||||
|
data.putShort((short) 0); |
||||||
|
data.put((byte) 0); |
||||||
|
} |
||||||
|
break; |
||||||
|
case Vector2: |
||||||
|
write(data, (Vector2f) value); |
||||||
|
break; |
||||||
|
case Vector3: |
||||||
|
write(data, (Vector3f) value); |
||||||
|
break; |
||||||
|
case Vector4: |
||||||
|
writeVec4(data, value); |
||||||
|
break; |
||||||
|
case IntArray: { |
||||||
|
write(data, (int[]) value); |
||||||
|
break; |
||||||
|
} |
||||||
|
case FloatArray: { |
||||||
|
write(data, (float[]) value); |
||||||
|
break; |
||||||
|
} |
||||||
|
case Vector2Array: { |
||||||
|
writeVec2Array(data, value); |
||||||
|
break; |
||||||
|
} |
||||||
|
case Vector3Array: { |
||||||
|
writeVec3Array(data, value); |
||||||
|
break; |
||||||
|
} |
||||||
|
case Vector4Array: { |
||||||
|
writeVec4Array(data, value); |
||||||
|
break; |
||||||
|
} |
||||||
|
case Matrix3: { |
||||||
|
write(data, (Matrix3f) value); |
||||||
|
break; |
||||||
|
} |
||||||
|
case Matrix4: { |
||||||
|
write(data, (Matrix4f) value); |
||||||
|
break; |
||||||
|
} |
||||||
|
case Matrix3Array: { |
||||||
|
writeMat3Array(data, value); |
||||||
|
break; |
||||||
|
} |
||||||
|
case Matrix4Array: { |
||||||
|
writeMat4Array(data, value); |
||||||
|
break; |
||||||
|
} |
||||||
|
default: { |
||||||
|
throw new IllegalArgumentException("The type of BO field " + field.getType() + " doesn't support."); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Writes the value to the data buffer. |
||||||
|
* |
||||||
|
* @param data the data buffer. |
||||||
|
* @param value the value. |
||||||
|
*/ |
||||||
|
protected void writeMat3Array(final ByteBuffer data, final Object value) { |
||||||
|
|
||||||
|
if (value instanceof Matrix3f[]) { |
||||||
|
|
||||||
|
final Matrix3f[] values = (Matrix3f[]) value; |
||||||
|
for (final Matrix3f mat : values) { |
||||||
|
write(data, mat); |
||||||
|
} |
||||||
|
|
||||||
|
} else if(value instanceof SafeArrayList) { |
||||||
|
|
||||||
|
final SafeArrayList<Matrix3f> values = (SafeArrayList<Matrix3f>) value; |
||||||
|
for (final Matrix3f mat : values.getArray()) { |
||||||
|
write(data, mat); |
||||||
|
} |
||||||
|
|
||||||
|
} else if(value instanceof Collection) { |
||||||
|
|
||||||
|
final Collection<Matrix3f> values = (Collection<Matrix3f>) value; |
||||||
|
for (final Matrix3f mat : values) { |
||||||
|
write(data, mat); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Writes the value to the data buffer. |
||||||
|
* |
||||||
|
* @param data the data buffer. |
||||||
|
* @param value the value. |
||||||
|
*/ |
||||||
|
protected void writeMat4Array(final ByteBuffer data, final Object value) { |
||||||
|
|
||||||
|
if (value instanceof Matrix4f[]) { |
||||||
|
|
||||||
|
final Matrix4f[] values = (Matrix4f[]) value; |
||||||
|
for (final Matrix4f mat : values) { |
||||||
|
write(data, mat); |
||||||
|
} |
||||||
|
|
||||||
|
} else if(value instanceof SafeArrayList) { |
||||||
|
|
||||||
|
final SafeArrayList<Matrix4f> values = (SafeArrayList<Matrix4f>) value; |
||||||
|
for (final Matrix4f mat : values.getArray()) { |
||||||
|
write(data, mat); |
||||||
|
} |
||||||
|
|
||||||
|
} else if(value instanceof Collection) { |
||||||
|
|
||||||
|
final Collection<Matrix4f> values = (Collection<Matrix4f>) value; |
||||||
|
for (final Matrix4f mat : values) { |
||||||
|
write(data, mat); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Writes the value to the data buffer. |
||||||
|
* |
||||||
|
* @param data the data buffer. |
||||||
|
* @param value the value. |
||||||
|
*/ |
||||||
|
protected void writeVec4Array(final ByteBuffer data, final Object value) { |
||||||
|
|
||||||
|
if (value instanceof Object[]) { |
||||||
|
|
||||||
|
final Object[] values = (Object[]) value; |
||||||
|
for (final Object vec : values) { |
||||||
|
writeVec4(data, vec); |
||||||
|
} |
||||||
|
|
||||||
|
} else if(value instanceof SafeArrayList) { |
||||||
|
|
||||||
|
final SafeArrayList<Object> values = (SafeArrayList<Object>) value; |
||||||
|
for (final Object vec : values.getArray()) { |
||||||
|
writeVec4(data, vec); |
||||||
|
} |
||||||
|
|
||||||
|
} else if(value instanceof Collection) { |
||||||
|
|
||||||
|
final Collection<Object> values = (Collection<Object>) value; |
||||||
|
for (final Object vec : values) { |
||||||
|
writeVec4(data, vec); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Writes the value to the data buffer. |
||||||
|
* |
||||||
|
* @param data the data buffer. |
||||||
|
* @param value the value. |
||||||
|
*/ |
||||||
|
protected void writeVec3Array(final ByteBuffer data, final Object value) { |
||||||
|
|
||||||
|
if (value instanceof Vector3f[]) { |
||||||
|
|
||||||
|
final Vector3f[] values = (Vector3f[]) value; |
||||||
|
for (final Vector3f vec : values) { |
||||||
|
write(data, vec); |
||||||
|
} |
||||||
|
|
||||||
|
} else if(value instanceof SafeArrayList) { |
||||||
|
|
||||||
|
final SafeArrayList<Vector3f> values = (SafeArrayList<Vector3f>) value; |
||||||
|
for (final Vector3f vec : values.getArray()) { |
||||||
|
write(data, vec); |
||||||
|
} |
||||||
|
|
||||||
|
} else if(value instanceof Collection) { |
||||||
|
|
||||||
|
final Collection<Vector3f> values = (Collection<Vector3f>) value; |
||||||
|
for (final Vector3f vec : values) { |
||||||
|
write(data, vec); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Writes the value to the data buffer. |
||||||
|
* |
||||||
|
* @param data the data buffer. |
||||||
|
* @param value the value. |
||||||
|
*/ |
||||||
|
protected void writeVec2Array(final ByteBuffer data, final Object value) { |
||||||
|
|
||||||
|
if (value instanceof Vector2f[]) { |
||||||
|
|
||||||
|
final Vector2f[] values = (Vector2f[]) value; |
||||||
|
for (final Vector2f vec : values) { |
||||||
|
write(data, vec); |
||||||
|
} |
||||||
|
|
||||||
|
} else if(value instanceof SafeArrayList) { |
||||||
|
|
||||||
|
final SafeArrayList<Vector2f> values = (SafeArrayList<Vector2f>) value; |
||||||
|
for (final Vector2f vec : values.getArray()) { |
||||||
|
write(data, vec); |
||||||
|
} |
||||||
|
|
||||||
|
} else if(value instanceof Collection) { |
||||||
|
|
||||||
|
final Collection<Vector2f> values = (Collection<Vector2f>) value; |
||||||
|
for (final Vector2f vec : values) { |
||||||
|
write(data, vec); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Writes the value to the data buffer. |
||||||
|
* |
||||||
|
* @param data the data buffer. |
||||||
|
* @param value the value. |
||||||
|
*/ |
||||||
|
protected void write(final ByteBuffer data, final float[] value) { |
||||||
|
for (float val : value) { |
||||||
|
data.putFloat(val); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Writes the value to the data buffer. |
||||||
|
* |
||||||
|
* @param data the data buffer. |
||||||
|
* @param value the value. |
||||||
|
*/ |
||||||
|
protected void write(final ByteBuffer data, final int[] value) { |
||||||
|
for (int val : value) { |
||||||
|
data.putInt(val); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Writes the value to the data buffer. |
||||||
|
* |
||||||
|
* @param data the data buffer. |
||||||
|
* @param value the value. |
||||||
|
*/ |
||||||
|
protected void writeVec4(final ByteBuffer data, final Object value) { |
||||||
|
|
||||||
|
if (value == null) { |
||||||
|
data.putLong(0).putLong(0); |
||||||
|
} else if (value instanceof Vector4f) { |
||||||
|
|
||||||
|
final Vector4f vec4 = (Vector4f) value; |
||||||
|
data.putFloat(vec4.getX()) |
||||||
|
.putFloat(vec4.getY()) |
||||||
|
.putFloat(vec4.getZ()) |
||||||
|
.putFloat(vec4.getW()); |
||||||
|
|
||||||
|
} else if(value instanceof Quaternion) { |
||||||
|
|
||||||
|
final Quaternion vec4 = (Quaternion) value; |
||||||
|
data.putFloat(vec4.getX()) |
||||||
|
.putFloat(vec4.getY()) |
||||||
|
.putFloat(vec4.getZ()) |
||||||
|
.putFloat(vec4.getW()); |
||||||
|
|
||||||
|
} else if(value instanceof ColorRGBA) { |
||||||
|
|
||||||
|
final ColorRGBA vec4 = (ColorRGBA) value; |
||||||
|
data.putFloat(vec4.getRed()) |
||||||
|
.putFloat(vec4.getGreen()) |
||||||
|
.putFloat(vec4.getBlue()) |
||||||
|
.putFloat(vec4.getAlpha()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Writes the value to the data buffer. |
||||||
|
* |
||||||
|
* @param data the data buffer. |
||||||
|
* @param value the value. |
||||||
|
*/ |
||||||
|
protected void write(final ByteBuffer data, final Vector3f value) { |
||||||
|
|
||||||
|
if (value == null) { |
||||||
|
data.putLong(0).putInt(0); |
||||||
|
} else { |
||||||
|
data.putFloat(value.getX()) |
||||||
|
.putFloat(value.getY()) |
||||||
|
.putFloat(value.getZ()); |
||||||
|
} |
||||||
|
|
||||||
|
if (layout == Layout.std140) { |
||||||
|
data.putInt(0); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Writes the value to the data buffer. |
||||||
|
* |
||||||
|
* @param data the data buffer. |
||||||
|
* @param x the x value. |
||||||
|
* @param y the y value. |
||||||
|
* @param z the z value. |
||||||
|
*/ |
||||||
|
protected void write(final ByteBuffer data, final float x, final float y, final float z) { |
||||||
|
|
||||||
|
data.putFloat(x) |
||||||
|
.putFloat(y) |
||||||
|
.putFloat(z); |
||||||
|
|
||||||
|
if (layout == Layout.std140) { |
||||||
|
data.putInt(0); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Writes the value to the data buffer. |
||||||
|
* |
||||||
|
* @param data the data buffer. |
||||||
|
* @param x the x value. |
||||||
|
* @param y the y value. |
||||||
|
* @param z the z value. |
||||||
|
* @param w the w value. |
||||||
|
*/ |
||||||
|
protected void write(final ByteBuffer data, final float x, final float y, final float z, final float w) { |
||||||
|
data.putFloat(x) |
||||||
|
.putFloat(y) |
||||||
|
.putFloat(z) |
||||||
|
.putFloat(w); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Writes the value to the data buffer. |
||||||
|
* |
||||||
|
* @param data the data buffer. |
||||||
|
* @param value the value. |
||||||
|
*/ |
||||||
|
protected void write(final ByteBuffer data, final Vector2f value) { |
||||||
|
if (value == null) { |
||||||
|
data.putLong(0); |
||||||
|
} else { |
||||||
|
data.putFloat(value.getX()).putFloat(value.getY()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Writes the value to the data buffer. |
||||||
|
* |
||||||
|
* @param data the data buffer. |
||||||
|
* @param value the value. |
||||||
|
*/ |
||||||
|
protected void write(final ByteBuffer data, final Matrix3f value) { |
||||||
|
write(data, value.get(0, 0), value.get(1, 0), value.get(2, 0)); |
||||||
|
write(data, value.get(0, 1), value.get(1, 1), value.get(2, 1)); |
||||||
|
write(data, value.get(0, 2), value.get(1, 2), value.get(2, 2)); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Writes the value to the data buffer. |
||||||
|
* |
||||||
|
* @param data the data buffer. |
||||||
|
* @param value the value. |
||||||
|
*/ |
||||||
|
protected void write(final ByteBuffer data, final Matrix4f value) { |
||||||
|
write(data, value.get(0, 0), value.get(1, 0), value.get(2, 0), value.get(3, 0)); |
||||||
|
write(data, value.get(0, 1), value.get(1, 1), value.get(2, 1), value.get(3, 1)); |
||||||
|
write(data, value.get(0, 2), value.get(1, 2), value.get(2, 2), value.get(3, 2)); |
||||||
|
write(data, value.get(0, 3), value.get(1, 3), value.get(2, 3), value.get(3, 3)); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void deleteObject(final Object rendererObject) { |
||||||
|
|
||||||
|
if (!(rendererObject instanceof Renderer)) { |
||||||
|
throw new IllegalArgumentException("This bo can't be deleted from " + rendererObject); |
||||||
|
} |
||||||
|
|
||||||
|
((Renderer) rendererObject).deleteBuffer(this); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public NativeObject createDestructableClone() { |
||||||
|
return new BufferObject(null, getId()); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void deleteNativeBuffers() { |
||||||
|
super.deleteNativeBuffers(); |
||||||
|
if (previousData != null) { |
||||||
|
BufferUtils.destroyDirectBuffer(previousData); |
||||||
|
previousData = null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public long getUniqueId() { |
||||||
|
return ((long) OBJTYPE_BO << 32) | ((long) id); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,77 @@ |
|||||||
|
package com.jme3.shader; |
||||||
|
|
||||||
|
import static java.util.Objects.requireNonNull; |
||||||
|
|
||||||
|
/** |
||||||
|
* The class to describe a filed in BO. |
||||||
|
* |
||||||
|
* @author JavaSaBr |
||||||
|
*/ |
||||||
|
public class BufferObjectField { |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* The field name. |
||||||
|
*/ |
||||||
|
private final String name; |
||||||
|
|
||||||
|
/** |
||||||
|
* The field type. |
||||||
|
*/ |
||||||
|
private final VarType type; |
||||||
|
|
||||||
|
/** |
||||||
|
* The field value. |
||||||
|
*/ |
||||||
|
private Object value; |
||||||
|
|
||||||
|
public BufferObjectField(final String name, final VarType type) { |
||||||
|
this.name = name; |
||||||
|
this.type = type; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get the field name. |
||||||
|
* |
||||||
|
* @return the field name. |
||||||
|
*/ |
||||||
|
public String getName() { |
||||||
|
return name; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Gets the field type. |
||||||
|
* |
||||||
|
* @return the field type. |
||||||
|
*/ |
||||||
|
public VarType getType() { |
||||||
|
return type; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Gets the field value. |
||||||
|
* |
||||||
|
* @return the field value. |
||||||
|
*/ |
||||||
|
public Object getValue() { |
||||||
|
return value; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Sets the field value. |
||||||
|
* |
||||||
|
* @param value the field value. |
||||||
|
*/ |
||||||
|
public void setValue(final Object value) { |
||||||
|
this.value = requireNonNull(value, "The field's value can't be null."); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String toString() { |
||||||
|
return "BufferObjectField{" + |
||||||
|
"name='" + name + '\'' + |
||||||
|
", type=" + type + |
||||||
|
", value=" + value + |
||||||
|
'}'; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,93 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2009-2018 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; |
||||||
|
|
||||||
|
/** |
||||||
|
* Implementation of shader's buffer block. |
||||||
|
* |
||||||
|
* @author JavaSaBr |
||||||
|
*/ |
||||||
|
public class ShaderBufferBlock extends ShaderVariable { |
||||||
|
|
||||||
|
/** |
||||||
|
* Current used buffer object. |
||||||
|
*/ |
||||||
|
protected BufferObject bufferObject; |
||||||
|
|
||||||
|
/** |
||||||
|
* Set the new buffer object. |
||||||
|
* |
||||||
|
* @param bufferObject the new buffer object. |
||||||
|
*/ |
||||||
|
public void setBufferObject(final BufferObject bufferObject) { |
||||||
|
|
||||||
|
if (bufferObject == null) { |
||||||
|
throw new IllegalArgumentException("for storage block " + name + ": storageData cannot be null"); |
||||||
|
} |
||||||
|
|
||||||
|
this.bufferObject = bufferObject; |
||||||
|
|
||||||
|
updateNeeded = true; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return true if need to update this storage block. |
||||||
|
* |
||||||
|
* @return true if need to update this storage block. |
||||||
|
*/ |
||||||
|
public boolean isUpdateNeeded(){ |
||||||
|
return updateNeeded; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Clear the flag {@link #isUpdateNeeded()}. |
||||||
|
*/ |
||||||
|
public void clearUpdateNeeded(){ |
||||||
|
updateNeeded = false; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Reset this storage block. |
||||||
|
*/ |
||||||
|
public void reset(){ |
||||||
|
updateNeeded = true; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get the current storage data. |
||||||
|
* |
||||||
|
* @return the current storage data. |
||||||
|
*/ |
||||||
|
public BufferObject getBufferObject() { |
||||||
|
return bufferObject; |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue