beta implementation of SSBO.
This commit is contained in:
parent
c154b6ae23
commit
cdb42a50c7
@ -46,10 +46,7 @@ import com.jme3.renderer.RenderManager;
|
|||||||
import com.jme3.renderer.Renderer;
|
import com.jme3.renderer.Renderer;
|
||||||
import com.jme3.renderer.queue.RenderQueue.Bucket;
|
import com.jme3.renderer.queue.RenderQueue.Bucket;
|
||||||
import com.jme3.scene.Geometry;
|
import com.jme3.scene.Geometry;
|
||||||
import com.jme3.shader.Shader;
|
import com.jme3.shader.*;
|
||||||
import com.jme3.shader.Uniform;
|
|
||||||
import com.jme3.shader.UniformBindingManager;
|
|
||||||
import com.jme3.shader.VarType;
|
|
||||||
import com.jme3.texture.Image;
|
import com.jme3.texture.Image;
|
||||||
import com.jme3.texture.Texture;
|
import com.jme3.texture.Texture;
|
||||||
import com.jme3.texture.image.ColorSpace;
|
import com.jme3.texture.image.ColorSpace;
|
||||||
@ -794,20 +791,29 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < paramValues.size(); i++) {
|
for (int i = 0; i < paramValues.size(); i++) {
|
||||||
|
|
||||||
MatParam param = paramValues.getValue(i);
|
MatParam param = paramValues.getValue(i);
|
||||||
VarType type = param.getVarType();
|
VarType type = param.getVarType();
|
||||||
Uniform uniform = shader.getUniform(param.getPrefixedName());
|
|
||||||
|
|
||||||
if (uniform.isSetByCurrentMaterial()) {
|
if(type == VarType.ShaderStorageBufferObject) {
|
||||||
continue;
|
|
||||||
}
|
final StorageBlock storageBlock = shader.getStorageBlock(name);
|
||||||
|
storageBlock.setValue(param.getValue());
|
||||||
|
|
||||||
if (type.isTextureType()) {
|
|
||||||
renderer.setTexture(unit, (Texture) param.getValue());
|
|
||||||
uniform.setValue(VarType.Int, unit);
|
|
||||||
unit++;
|
|
||||||
} else {
|
} else {
|
||||||
uniform.setValue(type, param.getValue());
|
|
||||||
|
Uniform uniform = shader.getUniform(param.getPrefixedName());
|
||||||
|
if (uniform.isSetByCurrentMaterial()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type.isTextureType()) {
|
||||||
|
renderer.setTexture(unit, (Texture) param.getValue());
|
||||||
|
uniform.setValue(VarType.Int, unit);
|
||||||
|
unit++;
|
||||||
|
} else {
|
||||||
|
uniform.setValue(type, param.getValue());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -394,7 +394,11 @@ public enum Caps {
|
|||||||
/**
|
/**
|
||||||
* GPU can provide and accept binary shaders.
|
* GPU can provide and accept binary shaders.
|
||||||
*/
|
*/
|
||||||
BinaryShader;
|
BinaryShader,
|
||||||
|
/**
|
||||||
|
* Supporting working with ShaderStorageBufferObjects.
|
||||||
|
*/
|
||||||
|
ShaderStorageBufferObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if given the renderer capabilities, the texture
|
* Returns true if given the renderer capabilities, the texture
|
||||||
|
@ -51,6 +51,8 @@ public interface GL4 extends GL3 {
|
|||||||
* Accepted by the {@code target} parameters of BindBuffer, BufferData, BufferSubData, MapBuffer, UnmapBuffer, GetBufferSubData, and GetBufferPointerv.
|
* Accepted by the {@code target} parameters of BindBuffer, BufferData, BufferSubData, MapBuffer, UnmapBuffer, GetBufferSubData, and GetBufferPointerv.
|
||||||
*/
|
*/
|
||||||
public static final int GL_SHADER_STORAGE_BUFFER = 0x90D2;
|
public static final int GL_SHADER_STORAGE_BUFFER = 0x90D2;
|
||||||
|
public static final int GL_SHADER_STORAGE_BLOCK = 0x92E6;
|
||||||
|
public static final int GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS = 0x90DD;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p><a target="_blank" href="http://docs.gl/gl4/glPatchParameteri">Reference Page</a></p>
|
* <p><a target="_blank" href="http://docs.gl/gl4/glPatchParameteri">Reference Page</a></p>
|
||||||
@ -60,4 +62,28 @@ public interface GL4 extends GL3 {
|
|||||||
* @param count the new value for the parameter given by {@code pname}
|
* @param count the new value for the parameter given by {@code pname}
|
||||||
*/
|
*/
|
||||||
public void glPatchParameter(int count);
|
public void glPatchParameter(int count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the unsigned integer index assigned to a resource named name in the interface type programInterface of
|
||||||
|
* program object program.
|
||||||
|
*
|
||||||
|
* @param program the name of a program object whose resources to query.
|
||||||
|
* @param programInterface a token identifying the interface within program containing the resource named name.
|
||||||
|
* @param name the name of the resource to query the index of.
|
||||||
|
* @return the index of a named resource within a program.
|
||||||
|
*/
|
||||||
|
public int glGetProgramResourceIndex(int program, int programInterface, String name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cchanges the active shader storage block with an assigned index of storageBlockIndex in program object program.
|
||||||
|
* storageBlockIndex must be an active shader storage block index in program. storageBlockBinding must be less
|
||||||
|
* than the value of {@code #GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS}. If successful, glShaderStorageBlockBinding specifies
|
||||||
|
* that program will use the data store of the buffer object bound to the binding point storageBlockBinding to
|
||||||
|
* read and write the values of the buffer variables in the shader storage block identified by storageBlockIndex.
|
||||||
|
*
|
||||||
|
* @param program the name of a program object whose resources to query.
|
||||||
|
* @param storageBlockIndex The index storage block within the program.
|
||||||
|
* @param storageBlockBinding The index storage block binding to associate with the specified storage block.
|
||||||
|
*/
|
||||||
|
public void glShaderStorageBlockBinding(int program, int storageBlockIndex, int storageBlockBinding);
|
||||||
}
|
}
|
||||||
|
@ -45,12 +45,9 @@ import com.jme3.scene.VertexBuffer;
|
|||||||
import com.jme3.scene.VertexBuffer.Format;
|
import com.jme3.scene.VertexBuffer.Format;
|
||||||
import com.jme3.scene.VertexBuffer.Type;
|
import com.jme3.scene.VertexBuffer.Type;
|
||||||
import com.jme3.scene.VertexBuffer.Usage;
|
import com.jme3.scene.VertexBuffer.Usage;
|
||||||
import com.jme3.shader.Attribute;
|
import com.jme3.shader.*;
|
||||||
import com.jme3.shader.Shader;
|
|
||||||
import com.jme3.shader.Shader.ShaderSource;
|
import com.jme3.shader.Shader.ShaderSource;
|
||||||
import com.jme3.shader.Shader.ShaderType;
|
import com.jme3.shader.Shader.ShaderType;
|
||||||
import com.jme3.shader.ShaderStorageBufferObject;
|
|
||||||
import com.jme3.shader.Uniform;
|
|
||||||
import com.jme3.texture.FrameBuffer;
|
import com.jme3.texture.FrameBuffer;
|
||||||
import com.jme3.texture.FrameBuffer.RenderBuffer;
|
import com.jme3.texture.FrameBuffer.RenderBuffer;
|
||||||
import com.jme3.texture.Image;
|
import com.jme3.texture.Image;
|
||||||
@ -481,6 +478,10 @@ public final class GLRenderer implements Renderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hasExtension("GL_ARB_shader_storage_buffer_object")) {
|
||||||
|
caps.add(Caps.ShaderStorageBufferObject);
|
||||||
|
}
|
||||||
|
|
||||||
// Print context information
|
// Print context information
|
||||||
logger.log(Level.INFO, "OpenGL Renderer Information\n" +
|
logger.log(Level.INFO, "OpenGL Renderer Information\n" +
|
||||||
" * Vendor: {0}\n" +
|
" * Vendor: {0}\n" +
|
||||||
@ -1184,22 +1185,37 @@ public final class GLRenderer implements Renderer {
|
|||||||
Integer i = (Integer) uniform.getValue();
|
Integer i = (Integer) uniform.getValue();
|
||||||
gl.glUniform1i(loc, i.intValue());
|
gl.glUniform1i(loc, i.intValue());
|
||||||
break;
|
break;
|
||||||
case ShaderStorageBufferObject: {
|
|
||||||
|
|
||||||
final ShaderStorageBufferObject ssbo = (ShaderStorageBufferObject) uniform.getValue();
|
|
||||||
if (ssbo.getUniqueId() == -1 || ssbo.isUpdateNeeded()) {
|
|
||||||
updateBufferData(ssbo);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
throw new UnsupportedOperationException("Unsupported uniform type: " + uniform.getVarType());
|
throw new UnsupportedOperationException("Unsupported uniform type: " + uniform.getVarType());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the storage block for the shader.
|
||||||
|
*
|
||||||
|
* @param shader the shader.
|
||||||
|
* @param storageBlock the storage block.
|
||||||
|
*/
|
||||||
|
protected void updateShaderStorageBlock(final Shader shader, final StorageBlock storageBlock) {
|
||||||
|
|
||||||
|
int shaderId = shader.getId();
|
||||||
|
|
||||||
|
assert storageBlock.getName() != null;
|
||||||
|
assert shader.getId() > 0;
|
||||||
|
|
||||||
|
bindProgram(shader);
|
||||||
|
|
||||||
|
final ShaderStorageBufferObject storageData = (ShaderStorageBufferObject) storageBlock.getStorageData();
|
||||||
|
if (storageData.getUniqueId() == -1 || storageData.isUpdateNeeded()) {
|
||||||
|
updateBufferData(storageData);
|
||||||
|
}
|
||||||
|
|
||||||
|
final int blockIndex = gl4.glGetProgramResourceIndex(shaderId, GL4.GL_SHADER_STORAGE_BLOCK, storageBlock.getName());
|
||||||
|
|
||||||
|
gl4.glShaderStorageBlockBinding(shaderId, blockIndex, storageData.getBinding());
|
||||||
|
gl4.glBindBufferBase(GL4.GL_SHADER_STORAGE_BUFFER, storageData.getBinding(), storageData.getId());
|
||||||
|
}
|
||||||
|
|
||||||
protected void updateShaderUniforms(Shader shader) {
|
protected void updateShaderUniforms(Shader shader) {
|
||||||
ListMap<String, Uniform> uniforms = shader.getUniformMap();
|
ListMap<String, Uniform> uniforms = shader.getUniformMap();
|
||||||
for (int i = 0; i < uniforms.size(); i++) {
|
for (int i = 0; i < uniforms.size(); i++) {
|
||||||
@ -1210,12 +1226,17 @@ public final class GLRenderer implements Renderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void updateShaderStorageBlocks(Shader shader) {
|
/**
|
||||||
ListMap<String, Uniform> uniforms = shader.getUniformMap();
|
* Updates all shader's storage blocks.
|
||||||
|
*
|
||||||
|
* @param shader the shader.
|
||||||
|
*/
|
||||||
|
protected void updateShaderStorageBlocks(final Shader shader) {
|
||||||
|
final ListMap<String, StorageBlock> uniforms = shader.getStorageBlockMap();
|
||||||
for (int i = 0; i < uniforms.size(); i++) {
|
for (int i = 0; i < uniforms.size(); i++) {
|
||||||
Uniform uniform = uniforms.getValue(i);
|
final StorageBlock storageBlock = uniforms.getValue(i);
|
||||||
if (uniform.isUpdateNeeded()) {
|
if (storageBlock.isUpdateNeeded()) {
|
||||||
updateUniform(shader, uniform);
|
updateShaderStorageBlock(shader, storageBlock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1438,6 +1459,7 @@ public final class GLRenderer implements Renderer {
|
|||||||
assert shader.getId() > 0;
|
assert shader.getId() > 0;
|
||||||
|
|
||||||
updateShaderUniforms(shader);
|
updateShaderUniforms(shader);
|
||||||
|
updateShaderStorageBlocks(shader);
|
||||||
bindProgram(shader);
|
bindProgram(shader);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2529,6 +2551,10 @@ public final class GLRenderer implements Renderer {
|
|||||||
@Override
|
@Override
|
||||||
public void updateBufferData(final ShaderStorageBufferObject ssbo) {
|
public void updateBufferData(final ShaderStorageBufferObject ssbo) {
|
||||||
|
|
||||||
|
if (!caps.contains(Caps.ShaderStorageBufferObject)) {
|
||||||
|
throw new IllegalArgumentException("The current video hardware doesn't support SSBO.");
|
||||||
|
}
|
||||||
|
|
||||||
final ByteBuffer data = ssbo.getData();
|
final ByteBuffer data = ssbo.getData();
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
throw new IllegalArgumentException("Can't upload SSBO without data.");
|
throw new IllegalArgumentException("Can't upload SSBO without data.");
|
||||||
|
@ -413,6 +413,11 @@ public final class Shader extends NativeObject {
|
|||||||
uniform.reset(); // fixes issue with re-initialization
|
uniform.reset(); // fixes issue with re-initialization
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (storageBlocks != null) {
|
||||||
|
for (StorageBlock storageBlock : storageBlocks.values()) {
|
||||||
|
storageBlock.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
if (attribs != null) {
|
if (attribs != null) {
|
||||||
for (Entry<Attribute> entry : attribs) {
|
for (Entry<Attribute> entry : attribs) {
|
||||||
entry.getValue().location = ShaderVariable.LOC_UNKNOWN;
|
entry.getValue().location = ShaderVariable.LOC_UNKNOWN;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2017 jMonkeyEngine
|
* Copyright (c) 2009-2018 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -31,425 +31,63 @@
|
|||||||
*/
|
*/
|
||||||
package com.jme3.shader;
|
package com.jme3.shader;
|
||||||
|
|
||||||
import com.jme3.math.*;
|
/**
|
||||||
import com.jme3.util.BufferUtils;
|
* Implementation of shader's storage block.
|
||||||
import com.jme3.util.TempVars;
|
*
|
||||||
|
* @author JavaSaBr
|
||||||
import java.nio.Buffer;
|
*/
|
||||||
import java.nio.FloatBuffer;
|
|
||||||
import java.nio.IntBuffer;
|
|
||||||
|
|
||||||
public class StorageBlock extends ShaderVariable {
|
public class StorageBlock extends ShaderVariable {
|
||||||
|
|
||||||
private static final Integer ZERO_INT = 0;
|
/**
|
||||||
private static final Float ZERO_FLT = Float.valueOf(0);
|
* Current used buffer object.
|
||||||
private static final FloatBuffer ZERO_BUF = BufferUtils.createFloatBuffer(4*4);
|
*/
|
||||||
|
protected Object storageData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Currently set value of the uniform.
|
* Set the new storage data.
|
||||||
|
*
|
||||||
|
* @param storageData the new storage data
|
||||||
*/
|
*/
|
||||||
protected Object value = null;
|
public void setStorageData(final Object storageData) {
|
||||||
|
|
||||||
/**
|
|
||||||
* For arrays or matrices, efficient format
|
|
||||||
* that can be sent to GL faster.
|
|
||||||
*/
|
|
||||||
protected FloatBuffer multiData = null;
|
|
||||||
|
|
||||||
/**
|
if (storageData == null) {
|
||||||
* Type of uniform
|
throw new IllegalArgumentException("for storage block " + name + ": storageData cannot be null");
|
||||||
*/
|
|
||||||
protected VarType varType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Binding to a renderer value, or null if user-defined uniform
|
|
||||||
*/
|
|
||||||
protected UniformBinding binding;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used to track which uniforms to clear to avoid
|
|
||||||
* values leaking from other materials that use that shader.
|
|
||||||
*/
|
|
||||||
protected boolean setByCurrentMaterial = false;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
int hash = 5;
|
|
||||||
hash = 31 * hash + (this.value != null ? this.value.hashCode() : 0);
|
|
||||||
hash = 31 * hash + (this.varType != null ? this.varType.hashCode() : 0);
|
|
||||||
hash = 31 * hash + (this.binding != null ? this.binding.hashCode() : 0);
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (this == obj) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (obj == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
final StorageBlock other = (StorageBlock) obj;
|
|
||||||
if (this.value != other.value && (this.value == null || !this.value.equals(other.value))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return this.binding == other.binding && this.varType == other.varType;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString(){
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
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 FloatBuffer getMultiData() {
|
|
||||||
return multiData;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSetByCurrentMaterial() {
|
|
||||||
return setByCurrentMaterial;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clearSetByCurrentMaterial(){
|
|
||||||
setByCurrentMaterial = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clearValue(){
|
|
||||||
updateNeeded = true;
|
|
||||||
|
|
||||||
if (multiData != null){
|
|
||||||
multiData.clear();
|
|
||||||
|
|
||||||
while (multiData.remaining() > 0){
|
|
||||||
ZERO_BUF.clear();
|
|
||||||
ZERO_BUF.limit( Math.min(multiData.remaining(), 16) );
|
|
||||||
multiData.put(ZERO_BUF);
|
|
||||||
}
|
|
||||||
|
|
||||||
multiData.clear();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (varType == null) {
|
this.storageData = storageData;
|
||||||
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:
|
|
||||||
if (this.value != null) {
|
|
||||||
((Vector2f) this.value).set(Vector2f.ZERO);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Vector3:
|
|
||||||
if (this.value != null) {
|
|
||||||
((Vector3f) this.value).set(Vector3f.ZERO);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Vector4:
|
|
||||||
if (this.value != null) {
|
|
||||||
if (this.value instanceof ColorRGBA) {
|
|
||||||
((ColorRGBA) this.value).set(ColorRGBA.BlackNoAlpha);
|
|
||||||
} else if (this.value instanceof Vector4f) {
|
|
||||||
((Vector4f) this.value).set(Vector4f.ZERO);
|
|
||||||
} else {
|
|
||||||
((Quaternion) this.value).set(Quaternion.ZERO);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// won't happen because those are either textures
|
|
||||||
// or multidata types
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setValue(VarType type, Object value){
|
|
||||||
if (location == LOC_NOT_DEFINED) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (varType != null && varType != type) {
|
|
||||||
throw new IllegalArgumentException("Expected a " + varType.name() + " value!");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value == null) {
|
|
||||||
throw new IllegalArgumentException("for uniform " + name + ": value cannot be null");
|
|
||||||
}
|
|
||||||
|
|
||||||
setByCurrentMaterial = true;
|
|
||||||
|
|
||||||
switch (type){
|
|
||||||
case Matrix3:
|
|
||||||
if (value.equals(this.value)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Matrix3f m3 = (Matrix3f) value;
|
|
||||||
if (multiData == null) {
|
|
||||||
multiData = BufferUtils.createFloatBuffer(9);
|
|
||||||
}
|
|
||||||
m3.fillFloatBuffer(multiData, true);
|
|
||||||
multiData.clear();
|
|
||||||
if (this.value == null) {
|
|
||||||
this.value = new Matrix3f(m3);
|
|
||||||
} else {
|
|
||||||
((Matrix3f)this.value).set(m3);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Matrix4:
|
|
||||||
if (value.equals(this.value)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Matrix4f m4 = (Matrix4f) value;
|
|
||||||
if (multiData == null) {
|
|
||||||
multiData = BufferUtils.createFloatBuffer(16);
|
|
||||||
}
|
|
||||||
m4.fillFloatBuffer(multiData, true);
|
|
||||||
multiData.clear();
|
|
||||||
if (this.value == null) {
|
|
||||||
this.value = new Matrix4f(m4);
|
|
||||||
} else {
|
|
||||||
((Matrix4f)this.value).copy(m4);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case IntArray:
|
|
||||||
int[] ia = (int[]) value;
|
|
||||||
if (this.value == null) {
|
|
||||||
this.value = BufferUtils.createIntBuffer(ia);
|
|
||||||
} else {
|
|
||||||
this.value = BufferUtils.ensureLargeEnough((IntBuffer)this.value, ia.length);
|
|
||||||
}
|
|
||||||
((IntBuffer)this.value).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:
|
|
||||||
Vector4f[] v4a = (Vector4f[]) 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;
|
|
||||||
case Vector2:
|
|
||||||
if (value.equals(this.value)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (this.value == null) {
|
|
||||||
this.value = new Vector2f((Vector2f) value);
|
|
||||||
} else {
|
|
||||||
((Vector2f) this.value).set((Vector2f) value);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Vector3:
|
|
||||||
if (value.equals(this.value)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (this.value == null) {
|
|
||||||
this.value = new Vector3f((Vector3f) value);
|
|
||||||
} else {
|
|
||||||
((Vector3f) this.value).set((Vector3f) value);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Vector4:
|
|
||||||
if (value.equals(this.value)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
TempVars vars = TempVars.get();
|
|
||||||
Vector4f vec4 = vars.vect4f1;
|
|
||||||
//handle the null case
|
|
||||||
if (this.value == null) {
|
|
||||||
try {
|
|
||||||
this.value = value.getClass().newInstance();
|
|
||||||
} catch (InstantiationException | IllegalAccessException e) {
|
|
||||||
throw new IllegalArgumentException("Cannot instanciate param of class " + value.getClass().getCanonicalName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//feed the pivot vec 4 with the correct value
|
|
||||||
if (value instanceof ColorRGBA) {
|
|
||||||
ColorRGBA c = (ColorRGBA) value;
|
|
||||||
vec4.set(c.r, c.g, c.b, c.a);
|
|
||||||
} else if (value instanceof Vector4f) {
|
|
||||||
vec4.set((Vector4f) value);
|
|
||||||
} else {
|
|
||||||
Quaternion q = (Quaternion) value;
|
|
||||||
vec4.set(q.getX(), q.getY(), q.getZ(), q.getW());
|
|
||||||
}
|
|
||||||
|
|
||||||
//feed this.value with the collected values.
|
|
||||||
if (this.value instanceof ColorRGBA) {
|
|
||||||
((ColorRGBA) this.value).set(vec4.x, vec4.y, vec4.z, vec4.w);
|
|
||||||
} else if (value instanceof Vector4f) {
|
|
||||||
((Vector4f) this.value).set(vec4);
|
|
||||||
} else {
|
|
||||||
((Quaternion) this.value).set(vec4.x, vec4.y, vec4.z, vec4.w);
|
|
||||||
}
|
|
||||||
vars.release();
|
|
||||||
break;
|
|
||||||
// Only use check if equals optimization for primitive values
|
|
||||||
case Int:
|
|
||||||
case Float:
|
|
||||||
case Boolean:
|
|
||||||
if (value.equals(this.value)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.value = value;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
this.value = value;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if (multiData != null) {
|
|
||||||
// this.value = multiData;
|
|
||||||
// }
|
|
||||||
|
|
||||||
varType = type;
|
|
||||||
updateNeeded = true;
|
updateNeeded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setVector4Length(int length){
|
/**
|
||||||
if (location == -1) {
|
* Return true if need to update this storage block.
|
||||||
return;
|
*
|
||||||
}
|
* @return true if need to update this storage block.
|
||||||
|
*/
|
||||||
multiData = BufferUtils.ensureLargeEnough(multiData, length * 4);
|
|
||||||
value = multiData;
|
|
||||||
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!");
|
|
||||||
}
|
|
||||||
|
|
||||||
multiData.position(index * 4);
|
|
||||||
multiData.put(x).put(y).put(z).put(w);
|
|
||||||
multiData.rewind();
|
|
||||||
updateNeeded = true;
|
|
||||||
setByCurrentMaterial = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isUpdateNeeded(){
|
public boolean isUpdateNeeded(){
|
||||||
return updateNeeded;
|
return updateNeeded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the flag {@link #isUpdateNeeded()}.
|
||||||
|
*/
|
||||||
public void clearUpdateNeeded(){
|
public void clearUpdateNeeded(){
|
||||||
updateNeeded = false;
|
updateNeeded = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset this storage block.
|
||||||
|
*/
|
||||||
public void reset(){
|
public void reset(){
|
||||||
setByCurrentMaterial = false;
|
|
||||||
location = -2;
|
|
||||||
updateNeeded = true;
|
updateNeeded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteNativeBuffers() {
|
/**
|
||||||
if (value instanceof Buffer) {
|
* Get the current storage data.
|
||||||
BufferUtils.destroyDirectBuffer((Buffer)value);
|
*
|
||||||
value = null; // ????
|
* @return the current storage data.
|
||||||
}
|
*/
|
||||||
|
public Object getStorageData() {
|
||||||
|
return storageData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user