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 115f31626..1cdc426ef 100644 --- a/jme3-core/src/main/java/com/jme3/material/Material.java +++ b/jme3-core/src/main/java/com/jme3/material/Material.java @@ -676,7 +676,7 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable { */ public void setUniformBufferObject(final String name, final BufferObject value) { value.setBufferType(BufferObject.BufferType.UniformBufferObject); - setParam(name, VarType.UniformBufferObject, value); + setParam(name, VarType.BufferObject, value); } /** @@ -687,7 +687,7 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable { */ public void setShaderStorageBufferObject(final String name, final BufferObject value) { value.setBufferType(BufferObject.BufferType.ShaderStorageBufferObject); - setParam(name, VarType.ShaderStorageBufferObject, value); + setParam(name, VarType.BufferObject, value); } /** @@ -861,7 +861,7 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable { * @return true if the type is Buffer Object's type. */ private boolean isBO(final VarType type) { - return type == VarType.ShaderStorageBufferObject || type == VarType.UniformBufferObject; + return type == VarType.BufferObject; } private void updateRenderState(RenderManager renderManager, Renderer renderer, TechniqueDef techniqueDef) { diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java index 345ec9e95..790e538f8 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java @@ -1231,6 +1231,14 @@ public final class GLRenderer implements Renderer { final int shaderId = shader.getId(); final BufferObject.BufferType bufferType = bufferObject.getBufferType(); + bindBuffer(bufferBlock, bufferObject, shaderId, bufferType); + + bufferBlock.clearUpdateNeeded(); + } + + private void bindBuffer(final ShaderBufferBlock bufferBlock, final BufferObject bufferObject, final int shaderId, + final BufferObject.BufferType bufferType) { + switch (bufferType) { case UniformBufferObject: { final int blockIndex = gl3.glGetUniformBlockIndex(shaderId, bufferBlock.getName()); @@ -1248,8 +1256,6 @@ public final class GLRenderer implements Renderer { throw new IllegalArgumentException("Doesn't support binding of " + bufferType); } } - - bufferBlock.clearUpdateNeeded(); } protected void updateShaderUniforms(Shader shader) { diff --git a/jme3-core/src/main/java/com/jme3/shader/BufferObject.java b/jme3-core/src/main/java/com/jme3/shader/BufferObject.java index 043ec675d..d3ca74587 100644 --- a/jme3-core/src/main/java/com/jme3/shader/BufferObject.java +++ b/jme3-core/src/main/java/com/jme3/shader/BufferObject.java @@ -9,7 +9,8 @@ import com.jme3.util.SafeArrayList; import java.nio.ByteBuffer; import java.util.Collection; -import java.util.LinkedHashMap; +import java.util.HashMap; +import java.util.List; import java.util.Map; /** @@ -19,6 +20,46 @@ import java.util.Map; */ public class BufferObject extends NativeObject { + private static final Map, 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); + 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 */ @@ -55,7 +96,7 @@ public class BufferObject extends NativeObject { /** * The field's array. */ - private final BufferObjectField[] fieldArray; + private final SafeArrayList fieldArray; /** * The buffer's data layout. @@ -77,36 +118,63 @@ public class BufferObject extends NativeObject { */ private ByteBuffer previousData; - public BufferObject(final int binding, final Layout layout, final BufferType bufferType, final BufferObjectField... fields) { + 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 LinkedHashMap<>(fields.length); - for (final BufferObjectField field : fields) { - this.fields.put(field.getName(), field); - } - this.fieldArray = fields; + 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 Layout layout, final BufferObjectField... fields) { - this(binding, layout, BufferType.UniformBufferObject, fields); + public BufferObject(final int binding, final BufferType bufferType) { + this(binding, Layout.std140, bufferType); } - public BufferObject(final int binding, final BufferObjectField... fields) { - this(binding, Layout.std140, BufferType.UniformBufferObject, fields); + public BufferObject(final BufferType bufferType) { + this(1, Layout.std140, bufferType); } - public BufferObject(final BufferObjectField... fields) { - this(1, Layout.std140, BufferType.UniformBufferObject, fields); + public BufferObject(final Layout layout) { + this(1, layout, BufferType.UniformBufferObject); } - public BufferObject(final int id) { + 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.binding = -2; + this.fieldArray = null; this.fields = null; this.layout = null; - this.fieldArray = 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); } /** @@ -140,9 +208,11 @@ public class BufferObject extends NativeObject { */ public void setValue(final String name, final Object value) { - final BufferObjectField field = fields.get(name); + BufferObjectField field = fields.get(name); + if (field == null) { - throw new IllegalArgumentException("Unknown a field with the name " + name); + declareField(name, getVarTypeByValue(value)); + field = fields.get(name); } field.setValue(value); @@ -739,7 +809,7 @@ public class BufferObject extends NativeObject { @Override public NativeObject createDestructableClone() { - return new BufferObject(id); + return new BufferObject(null, getId()); } @Override diff --git a/jme3-core/src/main/java/com/jme3/shader/BufferObjectField.java b/jme3-core/src/main/java/com/jme3/shader/BufferObjectField.java index f9b53612f..798b418fc 100644 --- a/jme3-core/src/main/java/com/jme3/shader/BufferObjectField.java +++ b/jme3-core/src/main/java/com/jme3/shader/BufferObjectField.java @@ -9,16 +9,6 @@ import static java.util.Objects.requireNonNull; */ public class BufferObjectField { - /** - * The method to create a new field. - * - * @param name the field's name. - * @param type the field's type. - * @return the new field. - */ - public static BufferObjectField field(final String name, final VarType type) { - return new BufferObjectField(name, type); - } /** * The field name. diff --git a/jme3-core/src/main/java/com/jme3/shader/VarType.java b/jme3-core/src/main/java/com/jme3/shader/VarType.java index 049c87786..2319e7903 100644 --- a/jme3-core/src/main/java/com/jme3/shader/VarType.java +++ b/jme3-core/src/main/java/com/jme3/shader/VarType.java @@ -58,8 +58,7 @@ public enum VarType { TextureArray(false,true,"sampler2DArray|sampler2DArrayShadow"), TextureCubeMap(false,true,"samplerCube"), Int("int"), - UniformBufferObject(false, false, "dynamic"), - ShaderStorageBufferObject(false, false, "dynamic"); + BufferObject(false, false, "custom"); private boolean usesMultiData = false; private boolean textureType = false;