Implements SSBO (Shader Storage Buffer Object) and UBO (Uniform Buffer Object) support
This commit is contained in:
parent
302e746a94
commit
266d8b0828
@ -46,10 +46,7 @@ import com.jme3.renderer.RenderManager;
|
||||
import com.jme3.renderer.Renderer;
|
||||
import com.jme3.renderer.queue.RenderQueue.Bucket;
|
||||
import com.jme3.scene.Geometry;
|
||||
import com.jme3.shader.Shader;
|
||||
import com.jme3.shader.Uniform;
|
||||
import com.jme3.shader.UniformBindingManager;
|
||||
import com.jme3.shader.VarType;
|
||||
import com.jme3.shader.*;
|
||||
import com.jme3.texture.Image;
|
||||
import com.jme3.texture.Texture;
|
||||
import com.jme3.texture.image.ColorSpace;
|
||||
@ -412,6 +409,17 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
|
||||
return paramValues.get(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current parameter's value.
|
||||
*
|
||||
* @param name the parameter name to look up.
|
||||
* @return current value or null if the parameter wasn't set.
|
||||
*/
|
||||
public <T> T getParamValue(final String name) {
|
||||
final MatParam param = paramValues.get(name);
|
||||
return param == null ? null : (T) param.getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the texture parameter set on this material with the given name,
|
||||
* returns <code>null</code> if the parameter is not set.
|
||||
@ -660,6 +668,28 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
|
||||
setParam(name, VarType.Vector4, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass an uniform buffer object to the material shader.
|
||||
*
|
||||
* @param name the name of the buffer object defined in the material definition (j3md).
|
||||
* @param value the buffer object.
|
||||
*/
|
||||
public void setUniformBufferObject(final String name, final BufferObject value) {
|
||||
value.setBufferType(BufferObject.BufferType.UniformBufferObject);
|
||||
setParam(name, VarType.BufferObject, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass a shader storage buffer object to the material shader.
|
||||
*
|
||||
* @param name the name of the buffer object defined in the material definition (j3md).
|
||||
* @param value the buffer object.
|
||||
*/
|
||||
public void setShaderStorageBufferObject(final String name, final BufferObject value) {
|
||||
value.setBufferType(BufferObject.BufferType.ShaderStorageBufferObject);
|
||||
setParam(name, VarType.BufferObject, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass a Vector2f to the material shader.
|
||||
*
|
||||
@ -794,10 +824,18 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
|
||||
}
|
||||
|
||||
for (int i = 0; i < paramValues.size(); i++) {
|
||||
|
||||
MatParam param = paramValues.getValue(i);
|
||||
VarType type = param.getVarType();
|
||||
Uniform uniform = shader.getUniform(param.getPrefixedName());
|
||||
|
||||
if (isBO(type)) {
|
||||
|
||||
final ShaderBufferBlock bufferBlock = shader.getBufferBlock(param.getPrefixedName());
|
||||
bufferBlock.setBufferObject((BufferObject) param.getValue());
|
||||
|
||||
} else {
|
||||
|
||||
Uniform uniform = shader.getUniform(param.getPrefixedName());
|
||||
if (uniform.isSetByCurrentMaterial()) {
|
||||
continue;
|
||||
}
|
||||
@ -810,11 +848,22 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
|
||||
uniform.setValue(type, param.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//TODO HACKY HACK remove this when texture unit is handled by the uniform.
|
||||
return unit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the type is Buffer Object's type.
|
||||
*
|
||||
* @param type the material parameter type.
|
||||
* @return true if the type is Buffer Object's type.
|
||||
*/
|
||||
private boolean isBO(final VarType type) {
|
||||
return type == VarType.BufferObject;
|
||||
}
|
||||
|
||||
private void updateRenderState(RenderManager renderManager, Renderer renderer, TechniqueDef techniqueDef) {
|
||||
if (renderManager.getForcedRenderState() != null) {
|
||||
renderer.applyRenderState(renderManager.getForcedRenderState());
|
||||
|
@ -394,7 +394,15 @@ public enum Caps {
|
||||
/**
|
||||
* GPU can provide and accept binary shaders.
|
||||
*/
|
||||
BinaryShader;
|
||||
BinaryShader,
|
||||
/**
|
||||
* Supporting working with UniformBufferObject.
|
||||
*/
|
||||
UniformBufferObject,
|
||||
/**
|
||||
* Supporting working with ShaderStorageBufferObjects.
|
||||
*/
|
||||
ShaderStorageBufferObject;
|
||||
|
||||
/**
|
||||
* Returns true if given the renderer capabilities, the texture
|
||||
|
@ -62,4 +62,20 @@ public enum Limits {
|
||||
ColorTextureSamples,
|
||||
DepthTextureSamples,
|
||||
TextureAnisotropy,
|
||||
|
||||
// UBO
|
||||
UniformBufferObjectMaxVertexBlocks,
|
||||
UniformBufferObjectMaxFragmentBlocks,
|
||||
UniformBufferObjectMaxGeometryBlocks,
|
||||
UniformBufferObjectMaxBlockSize,
|
||||
|
||||
// SSBO
|
||||
ShaderStorageBufferObjectMaxBlockSize,
|
||||
ShaderStorageBufferObjectMaxVertexBlocks,
|
||||
ShaderStorageBufferObjectMaxFragmentBlocks,
|
||||
ShaderStorageBufferObjectMaxGeometryBlocks,
|
||||
ShaderStorageBufferObjectMaxTessControlBlocks,
|
||||
ShaderStorageBufferObjectMaxTessEvaluationBlocks,
|
||||
ShaderStorageBufferObjectMaxComputeBlocks,
|
||||
ShaderStorageBufferObjectMaxCombineBlocks,
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ import com.jme3.material.RenderState;
|
||||
import com.jme3.math.ColorRGBA;
|
||||
import com.jme3.scene.Mesh;
|
||||
import com.jme3.scene.VertexBuffer;
|
||||
import com.jme3.shader.BufferObject;
|
||||
import com.jme3.shader.Shader;
|
||||
import com.jme3.shader.Shader.ShaderSource;
|
||||
import com.jme3.system.AppSettings;
|
||||
@ -267,12 +268,26 @@ public interface Renderer {
|
||||
*/
|
||||
public void updateBufferData(VertexBuffer vb);
|
||||
|
||||
/**
|
||||
* Uploads data of the buffer object on the GPU.
|
||||
*
|
||||
* @param bo the buffer object to upload.
|
||||
*/
|
||||
public void updateBufferData(BufferObject bo);
|
||||
|
||||
/**
|
||||
* Deletes a vertex buffer from the GPU.
|
||||
* @param vb The vertex buffer to delete
|
||||
*/
|
||||
public void deleteBuffer(VertexBuffer vb);
|
||||
|
||||
/**
|
||||
* Deletes the buffer object from the GPU.
|
||||
*
|
||||
* @param bo the buffer object to delete.
|
||||
*/
|
||||
public void deleteBuffer(BufferObject bo);
|
||||
|
||||
/**
|
||||
* Renders <code>count</code> meshes, with the geometry data supplied and
|
||||
* per-instance data supplied.
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -83,6 +83,46 @@ public interface GL3 extends GL2 {
|
||||
public static final int GL_RGB_INTEGER = 36248;
|
||||
public static final int GL_RGBA_INTEGER = 36249;
|
||||
|
||||
public static final int GL_UNIFORM_OFFSET = 0x8A3B;
|
||||
|
||||
/**
|
||||
* Accepted by the {@code target} parameters of BindBuffer, BufferData, BufferSubData, MapBuffer, UnmapBuffer, GetBufferSubData, and GetBufferPointerv.
|
||||
*/
|
||||
public static final int GL_UNIFORM_BUFFER = 0x8A11;
|
||||
|
||||
/**
|
||||
* Accepted by the {@code pname} parameter of GetActiveUniformBlockiv.
|
||||
*/
|
||||
public static final int GL_UNIFORM_BLOCK_BINDING = 0x8A3F;
|
||||
public static final int GL_UNIFORM_BLOCK_DATA_SIZE = 0x8A40;
|
||||
public static final int GL_UNIFORM_BLOCK_NAME_LENGTH = 0x8A41;
|
||||
public static final int GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS = 0x8A42;
|
||||
public static final int GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES = 0x8A43;
|
||||
public static final int GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER = 0x8A44;
|
||||
public static final int GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER = 0x8A45;
|
||||
public static final int GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER = 0x8A46;
|
||||
|
||||
/**
|
||||
* Accepted by the <pname> parameter of GetBooleanv, GetIntegerv,
|
||||
* GetFloatv, and GetDoublev:
|
||||
*/
|
||||
public static final int GL_MAX_VERTEX_UNIFORM_BLOCKS = 0x8A2B;
|
||||
public static final int GL_MAX_GEOMETRY_UNIFORM_BLOCKS = 0x8A2C;
|
||||
public static final int GL_MAX_FRAGMENT_UNIFORM_BLOCKS = 0x8A2D;
|
||||
public static final int GL_MAX_COMBINED_UNIFORM_BLOCKS = 0x8A2E;
|
||||
public static final int GL_MAX_UNIFORM_BUFFER_BINDINGS = 0x8A2F;
|
||||
public static final int GL_MAX_UNIFORM_BLOCK_SIZE = 0x8A30;
|
||||
public static final int GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS = 0x8A31;
|
||||
public static final int GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS = 0x8A32;
|
||||
public static final int GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS = 0x8A33;
|
||||
public static final int GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT = 0x8A34;
|
||||
|
||||
/**
|
||||
* Accepted by the {@code target} parameters of BindBuffer, BufferData, BufferSubData, MapBuffer, UnmapBuffer, GetBufferSubData, GetBufferPointerv,
|
||||
* BindBufferRange, BindBufferOffset and BindBufferBase.
|
||||
*/
|
||||
public static final int GL_TRANSFORM_FEEDBACK_BUFFER = 0x8C8E;
|
||||
|
||||
/**
|
||||
* <p><a target="_blank" href="http://docs.gl/gl4/glBindFragDataLocation">Reference Page</a></p>
|
||||
* <p>
|
||||
@ -128,4 +168,47 @@ public interface GL3 extends GL2 {
|
||||
* @param index the index of the particular element being queried.
|
||||
*/
|
||||
public String glGetString(int name, int index); /// GL3+
|
||||
|
||||
|
||||
/**
|
||||
* <p><a target="_blank" href="http://docs.gl/gl4/glGetUniformBlockIndex">Reference Page</a></p>
|
||||
*
|
||||
* Retrieves the index of a named uniform block.
|
||||
*
|
||||
* @param program the name of a program containing the uniform block.
|
||||
* @param uniformBlockName an array of characters to containing the name of the uniform block whose index to retrieve.
|
||||
* @return the block index.
|
||||
*/
|
||||
public int glGetUniformBlockIndex(int program, String uniformBlockName);
|
||||
|
||||
/**
|
||||
* <p><a target="_blank" href="http://docs.gl/gl4/glBindBufferBase">Reference Page</a></p>
|
||||
*
|
||||
* Binds a buffer object to an indexed buffer target.
|
||||
*
|
||||
* @param target the target of the bind operation. One of:<br><table><tr><td>{@link #GL_TRANSFORM_FEEDBACK_BUFFER TRANSFORM_FEEDBACK_BUFFER}</td><td>{@link #GL_UNIFORM_BUFFER UNIFORM_BUFFER}</td><td>{@link GL4#GL_ATOMIC_COUNTER_BUFFER ATOMIC_COUNTER_BUFFER}</td><td>{@link GL4#GL_SHADER_STORAGE_BUFFER SHADER_STORAGE_BUFFER}</td></tr></table>
|
||||
* @param index the index of the binding point within the array specified by {@code target}
|
||||
* @param buffer a buffer object to bind to the specified binding point
|
||||
*/
|
||||
public void glBindBufferBase(int target, int index, int buffer);
|
||||
|
||||
/**
|
||||
* Binding points for active uniform blocks are assigned using glUniformBlockBinding. Each of a program's active
|
||||
* uniform blocks has a corresponding uniform buffer binding point. program is the name of a program object for
|
||||
* which the command glLinkProgram has been issued in the past.
|
||||
* <p>
|
||||
* If successful, glUniformBlockBinding specifies that program will use the data store of the buffer object bound
|
||||
* to the binding point uniformBlockBinding to extract the values of the uniforms in the uniform block identified
|
||||
* by uniformBlockIndex.
|
||||
* <p>
|
||||
* When a program object is linked or re-linked, the uniform buffer object binding point assigned to each of its
|
||||
* active uniform blocks is reset to zero.
|
||||
*
|
||||
* @param program The name of a program object containing the active uniform block whose binding to
|
||||
* assign.
|
||||
* @param uniformBlockIndex The index of the active uniform block within program whose binding to assign.
|
||||
* @param uniformBlockBinding Specifies the binding point to which to bind the uniform block with index
|
||||
* uniformBlockIndex within program.
|
||||
*/
|
||||
public void glUniformBlockBinding(int program, int uniformBlockIndex, int uniformBlockBinding);
|
||||
}
|
||||
|
@ -42,6 +42,32 @@ public interface GL4 extends GL3 {
|
||||
public static final int GL_TESS_EVALUATION_SHADER = 0x8E87;
|
||||
public static final int GL_PATCHES = 0xE;
|
||||
|
||||
/**
|
||||
* Accepted by the {@code target} parameter of BindBufferBase and BindBufferRange.
|
||||
*/
|
||||
public static final int GL_ATOMIC_COUNTER_BUFFER = 0x92C0;
|
||||
|
||||
/**
|
||||
* 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_BLOCK = 0x92E6;
|
||||
|
||||
/**
|
||||
* Accepted by the <pname> parameter of GetIntegerv, GetBooleanv,
|
||||
* GetInteger64v, GetFloatv, and GetDoublev:
|
||||
*/
|
||||
public static final int GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS = 0x90D6;
|
||||
public static final int GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS = 0x90D7;
|
||||
public static final int GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS = 0x90D8;
|
||||
public static final int GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS = 0x90D9;
|
||||
public static final int GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS = 0x90DA;
|
||||
public static final int GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS = 0x90DB;
|
||||
public static final int GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS = 0x90DC;
|
||||
public static final int GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS = 0x90DD;
|
||||
public static final int GL_MAX_SHADER_STORAGE_BLOCK_SIZE = 0x90DE;
|
||||
public static final int GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT = 0x90DF;
|
||||
|
||||
/**
|
||||
* <p><a target="_blank" href="http://docs.gl/gl4/glPatchParameteri">Reference Page</a></p>
|
||||
* <p>
|
||||
@ -50,4 +76,28 @@ public interface GL4 extends GL3 {
|
||||
* @param count the new value for the parameter given by {@code pname}
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
@ -83,6 +83,19 @@ public class GLDebugDesktop extends GLDebugES implements GL2, GL3, GL4 {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int glGetUniformBlockIndex(final int program, final String uniformBlockName) {
|
||||
final int result = gl3.glGetUniformBlockIndex(program, uniformBlockName);
|
||||
checkError();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void glBindBufferBase(final int target, final int index, final int buffer) {
|
||||
gl3.glBindBufferBase(target, index, buffer);
|
||||
checkError();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void glDeleteVertexArrays(IntBuffer arrays) {
|
||||
gl3.glDeleteVertexArrays(arrays);
|
||||
@ -95,8 +108,27 @@ public class GLDebugDesktop extends GLDebugES implements GL2, GL3, GL4 {
|
||||
checkError();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int glGetProgramResourceIndex(int program, int programInterface, String name) {
|
||||
final int result = gl4.glGetProgramResourceIndex(program, programInterface, name);
|
||||
checkError();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void glShaderStorageBlockBinding(int program, int storageBlockIndex, int storageBlockBinding) {
|
||||
gl4.glShaderStorageBlockBinding(program, storageBlockIndex, storageBlockBinding);
|
||||
checkError();
|
||||
}
|
||||
|
||||
public void glBlendEquationSeparate(int colorMode, int alphaMode) {
|
||||
gl.glBlendEquationSeparate(colorMode, alphaMode);
|
||||
checkError();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void glUniformBlockBinding(final int program, final int uniformBlockIndex, final int uniformBlockBinding) {
|
||||
gl3.glUniformBlockBinding(program, uniformBlockIndex, uniformBlockBinding);
|
||||
checkError();
|
||||
}
|
||||
}
|
||||
|
@ -45,11 +45,9 @@ import com.jme3.scene.VertexBuffer;
|
||||
import com.jme3.scene.VertexBuffer.Format;
|
||||
import com.jme3.scene.VertexBuffer.Type;
|
||||
import com.jme3.scene.VertexBuffer.Usage;
|
||||
import com.jme3.shader.Attribute;
|
||||
import com.jme3.shader.Shader;
|
||||
import com.jme3.shader.*;
|
||||
import com.jme3.shader.Shader.ShaderSource;
|
||||
import com.jme3.shader.Shader.ShaderType;
|
||||
import com.jme3.shader.Uniform;
|
||||
import com.jme3.texture.FrameBuffer;
|
||||
import com.jme3.texture.FrameBuffer.RenderBuffer;
|
||||
import com.jme3.texture.Image;
|
||||
@ -61,17 +59,17 @@ import com.jme3.util.BufferUtils;
|
||||
import com.jme3.util.ListMap;
|
||||
import com.jme3.util.MipMapGenerator;
|
||||
import com.jme3.util.NativeObjectManager;
|
||||
import java.nio.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumMap;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import jme3tools.shader.ShaderDebug;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import java.nio.ShortBuffer;
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import jme3tools.shader.ShaderDebug;
|
||||
|
||||
public final class GLRenderer implements Renderer {
|
||||
|
||||
@ -480,6 +478,26 @@ public final class GLRenderer implements Renderer {
|
||||
}
|
||||
}
|
||||
|
||||
if (hasExtension("GL_ARB_shader_storage_buffer_object")) {
|
||||
caps.add(Caps.ShaderStorageBufferObject);
|
||||
limits.put(Limits.ShaderStorageBufferObjectMaxBlockSize, getInteger(GL4.GL_MAX_SHADER_STORAGE_BLOCK_SIZE));
|
||||
limits.put(Limits.ShaderStorageBufferObjectMaxComputeBlocks, getInteger(GL4.GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS));
|
||||
limits.put(Limits.ShaderStorageBufferObjectMaxGeometryBlocks, getInteger(GL4.GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS));
|
||||
limits.put(Limits.ShaderStorageBufferObjectMaxFragmentBlocks, getInteger(GL4.GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS));
|
||||
limits.put(Limits.ShaderStorageBufferObjectMaxVertexBlocks, getInteger(GL4.GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS));
|
||||
limits.put(Limits.ShaderStorageBufferObjectMaxTessControlBlocks, getInteger(GL4.GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS));
|
||||
limits.put(Limits.ShaderStorageBufferObjectMaxTessEvaluationBlocks, getInteger(GL4.GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS));
|
||||
limits.put(Limits.ShaderStorageBufferObjectMaxCombineBlocks, getInteger(GL4.GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS));
|
||||
}
|
||||
|
||||
if (hasExtension("GL_ARB_uniform_buffer_object")) {
|
||||
caps.add(Caps.UniformBufferObject);
|
||||
limits.put(Limits.UniformBufferObjectMaxBlockSize, getInteger(GL3.GL_MAX_UNIFORM_BLOCK_SIZE));
|
||||
limits.put(Limits.UniformBufferObjectMaxGeometryBlocks, getInteger(GL3.GL_MAX_GEOMETRY_UNIFORM_BLOCKS));
|
||||
limits.put(Limits.UniformBufferObjectMaxFragmentBlocks, getInteger(GL3.GL_MAX_FRAGMENT_UNIFORM_BLOCKS));
|
||||
limits.put(Limits.UniformBufferObjectMaxVertexBlocks, getInteger(GL3.GL_MAX_VERTEX_UNIFORM_BLOCKS));
|
||||
}
|
||||
|
||||
// Print context information
|
||||
logger.log(Level.INFO, "OpenGL Renderer Information\n" +
|
||||
" * Vendor: {0}\n" +
|
||||
@ -1050,12 +1068,25 @@ public final class GLRenderer implements Renderer {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postFrame() {
|
||||
objManager.deleteUnused(this);
|
||||
OpenCLObjectManager.getInstance().deleteUnusedObjects();
|
||||
gl.resetStats();
|
||||
}
|
||||
|
||||
protected void bindProgram(Shader shader) {
|
||||
int shaderId = shader.getId();
|
||||
if (context.boundShaderProgram != shaderId) {
|
||||
gl.glUseProgram(shaderId);
|
||||
statistics.onShaderUse(shader, true);
|
||||
context.boundShader = shader;
|
||||
context.boundShaderProgram = shaderId;
|
||||
} else {
|
||||
statistics.onShaderUse(shader, false);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************\
|
||||
|* Shaders *|
|
||||
\*********************************************************************/
|
||||
@ -1070,18 +1101,6 @@ public final class GLRenderer implements Renderer {
|
||||
}
|
||||
}
|
||||
|
||||
protected void bindProgram(Shader shader) {
|
||||
int shaderId = shader.getId();
|
||||
if (context.boundShaderProgram != shaderId) {
|
||||
gl.glUseProgram(shaderId);
|
||||
statistics.onShaderUse(shader, true);
|
||||
context.boundShader = shader;
|
||||
context.boundShaderProgram = shaderId;
|
||||
} else {
|
||||
statistics.onShaderUse(shader, false);
|
||||
}
|
||||
}
|
||||
|
||||
protected void updateUniform(Shader shader, Uniform uniform) {
|
||||
int shaderId = shader.getId();
|
||||
|
||||
@ -1187,6 +1206,58 @@ public final class GLRenderer implements Renderer {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the buffer block for the shader.
|
||||
*
|
||||
* @param shader the shader.
|
||||
* @param bufferBlock the storage block.
|
||||
*/
|
||||
protected void updateShaderBufferBlock(final Shader shader, final ShaderBufferBlock bufferBlock) {
|
||||
|
||||
assert bufferBlock.getName() != null;
|
||||
assert shader.getId() > 0;
|
||||
|
||||
final BufferObject bufferObject = bufferBlock.getBufferObject();
|
||||
if (bufferObject.getUniqueId() == -1 || bufferObject.isUpdateNeeded()) {
|
||||
updateBufferData(bufferObject);
|
||||
}
|
||||
|
||||
if (!bufferBlock.isUpdateNeeded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
bindProgram(shader);
|
||||
|
||||
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());
|
||||
gl3.glBindBufferBase(GL3.GL_UNIFORM_BUFFER, bufferObject.getBinding(), bufferObject.getId());
|
||||
gl3.glUniformBlockBinding(GL3.GL_UNIFORM_BUFFER, blockIndex, bufferObject.getBinding());
|
||||
break;
|
||||
}
|
||||
case ShaderStorageBufferObject: {
|
||||
final int blockIndex = gl4.glGetProgramResourceIndex(shaderId, GL4.GL_SHADER_STORAGE_BLOCK, bufferBlock.getName());
|
||||
gl4.glShaderStorageBlockBinding(shaderId, blockIndex, bufferObject.getBinding());
|
||||
gl4.glBindBufferBase(GL4.GL_SHADER_STORAGE_BUFFER, bufferObject.getBinding(), bufferObject.getId());
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new IllegalArgumentException("Doesn't support binding of " + bufferType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void updateShaderUniforms(Shader shader) {
|
||||
ListMap<String, Uniform> uniforms = shader.getUniformMap();
|
||||
for (int i = 0; i < uniforms.size(); i++) {
|
||||
@ -1197,6 +1268,18 @@ public final class GLRenderer implements Renderer {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all shader's buffer blocks.
|
||||
*
|
||||
* @param shader the shader.
|
||||
*/
|
||||
protected void updateShaderBufferBlocks(final Shader shader) {
|
||||
final ListMap<String, ShaderBufferBlock> bufferBlocks = shader.getBufferBlockMap();
|
||||
for (int i = 0; i < bufferBlocks.size(); i++) {
|
||||
updateShaderBufferBlock(shader, bufferBlocks.getValue(i));
|
||||
}
|
||||
}
|
||||
|
||||
protected void resetUniformLocations(Shader shader) {
|
||||
ListMap<String, Uniform> uniforms = shader.getUniformMap();
|
||||
for (int i = 0; i < uniforms.size(); i++) {
|
||||
@ -1415,6 +1498,7 @@ public final class GLRenderer implements Renderer {
|
||||
assert shader.getId() > 0;
|
||||
|
||||
updateShaderUniforms(shader);
|
||||
updateShaderBufferBlocks(shader);
|
||||
bindProgram(shader);
|
||||
}
|
||||
}
|
||||
@ -2503,6 +2587,58 @@ public final class GLRenderer implements Renderer {
|
||||
vb.clearUpdateNeeded();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBufferData(final BufferObject bo) {
|
||||
|
||||
int maxSize = Integer.MAX_VALUE;
|
||||
|
||||
final BufferObject.BufferType bufferType = bo.getBufferType();
|
||||
|
||||
if (!caps.contains(bufferType.getRequiredCaps())) {
|
||||
throw new IllegalArgumentException("The current video hardware doesn't support " + bufferType);
|
||||
}
|
||||
|
||||
final ByteBuffer data = bo.computeData(maxSize);
|
||||
if (data == null) {
|
||||
throw new IllegalArgumentException("Can't upload BO without data.");
|
||||
}
|
||||
|
||||
int bufferId = bo.getId();
|
||||
if (bufferId == -1) {
|
||||
|
||||
// create buffer
|
||||
intBuf1.clear();
|
||||
gl.glGenBuffers(intBuf1);
|
||||
bufferId = intBuf1.get(0);
|
||||
|
||||
bo.setId(bufferId);
|
||||
|
||||
objManager.registerObject(bo);
|
||||
}
|
||||
|
||||
data.rewind();
|
||||
|
||||
switch (bufferType) {
|
||||
case UniformBufferObject: {
|
||||
gl3.glBindBuffer(GL3.GL_UNIFORM_BUFFER, bufferId);
|
||||
gl3.glBufferData(GL4.GL_UNIFORM_BUFFER, data, GL3.GL_DYNAMIC_DRAW);
|
||||
gl3.glBindBuffer(GL4.GL_UNIFORM_BUFFER, 0);
|
||||
break;
|
||||
}
|
||||
case ShaderStorageBufferObject: {
|
||||
gl4.glBindBuffer(GL4.GL_SHADER_STORAGE_BUFFER, bufferId);
|
||||
gl4.glBufferData(GL4.GL_SHADER_STORAGE_BUFFER, data, GL4.GL_DYNAMIC_COPY);
|
||||
gl4.glBindBuffer(GL4.GL_SHADER_STORAGE_BUFFER, 0);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new IllegalArgumentException("Doesn't support binding of " + bufferType);
|
||||
}
|
||||
}
|
||||
|
||||
bo.clearUpdateNeeded();
|
||||
}
|
||||
|
||||
public void deleteBuffer(VertexBuffer vb) {
|
||||
int bufId = vb.getId();
|
||||
if (bufId != -1) {
|
||||
@ -2516,6 +2652,23 @@ public final class GLRenderer implements Renderer {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteBuffer(final BufferObject bo) {
|
||||
|
||||
int bufferId = bo.getId();
|
||||
if (bufferId == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
intBuf1.clear();
|
||||
intBuf1.put(bufferId);
|
||||
intBuf1.flip();
|
||||
|
||||
gl.glDeleteBuffers(intBuf1);
|
||||
|
||||
bo.resetObject();
|
||||
}
|
||||
|
||||
public void clearVertexAttribs() {
|
||||
IDList attribList = context.attribIndexList;
|
||||
for (int i = 0; i < attribList.oldLen; i++) {
|
||||
|
828
jme3-core/src/main/java/com/jme3/shader/BufferObject.java
Normal file
828
jme3-core/src/main/java/com/jme3/shader/BufferObject.java
Normal file
@ -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 +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -52,6 +52,11 @@ public final class Shader extends NativeObject {
|
||||
*/
|
||||
private final ListMap<String, Uniform> uniforms;
|
||||
|
||||
/**
|
||||
* Maps storage block name to the buffer block variables.
|
||||
*/
|
||||
private final ListMap<String, ShaderBufferBlock> bufferBlocks;
|
||||
|
||||
/**
|
||||
* Uniforms bound to {@link UniformBinding}s.
|
||||
*
|
||||
@ -220,10 +225,11 @@ public final class Shader extends NativeObject {
|
||||
*/
|
||||
public Shader(){
|
||||
super();
|
||||
shaderSourceList = new ArrayList<ShaderSource>();
|
||||
uniforms = new ListMap<String, Uniform>();
|
||||
attribs = new IntMap<Attribute>();
|
||||
boundUniforms = new ArrayList<Uniform>();
|
||||
shaderSourceList = new ArrayList<>();
|
||||
uniforms = new ListMap<>();
|
||||
bufferBlocks = new ListMap<>();
|
||||
attribs = new IntMap<>();
|
||||
boundUniforms = new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -240,6 +246,7 @@ public final class Shader extends NativeObject {
|
||||
}
|
||||
|
||||
uniforms = null;
|
||||
bufferBlocks = null;
|
||||
boundUniforms = null;
|
||||
attribs = null;
|
||||
}
|
||||
@ -288,10 +295,40 @@ public final class Shader extends NativeObject {
|
||||
return uniform;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets or creates a buffer block by the name.
|
||||
*
|
||||
* @param name the buffer block's name.
|
||||
* @return the buffer block.
|
||||
*/
|
||||
public ShaderBufferBlock getBufferBlock(final String name) {
|
||||
|
||||
assert name.startsWith("m_");
|
||||
|
||||
ShaderBufferBlock block = bufferBlocks.get(name);
|
||||
|
||||
if (block == null) {
|
||||
block = new ShaderBufferBlock();
|
||||
block.name = name;
|
||||
bufferBlocks.put(name, block);
|
||||
}
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
public void removeUniform(String name){
|
||||
uniforms.remove(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a buffer block by the name.
|
||||
*
|
||||
* @param name the buffer block's name.
|
||||
*/
|
||||
public void removeBufferBlock(final String name){
|
||||
bufferBlocks.remove(name);
|
||||
}
|
||||
|
||||
public Attribute getAttribute(VertexBuffer.Type attribType){
|
||||
int ordinal = attribType.ordinal();
|
||||
Attribute attrib = attribs.get(ordinal);
|
||||
@ -307,6 +344,15 @@ public final class Shader extends NativeObject {
|
||||
return uniforms;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the buffer blocks map.
|
||||
*
|
||||
* @return the buffer blocks map.
|
||||
*/
|
||||
public ListMap<String, ShaderBufferBlock> getBufferBlockMap() {
|
||||
return bufferBlocks;
|
||||
}
|
||||
|
||||
public ArrayList<Uniform> getBoundUniforms() {
|
||||
return boundUniforms;
|
||||
}
|
||||
@ -320,6 +366,7 @@ public final class Shader extends NativeObject {
|
||||
return getClass().getSimpleName() +
|
||||
"[numSources=" + shaderSourceList.size() +
|
||||
", numUniforms=" + uniforms.size() +
|
||||
", numBufferBlocks=" + bufferBlocks.size() +
|
||||
", shaderSources=" + getSources() + "]";
|
||||
}
|
||||
|
||||
@ -343,7 +390,7 @@ public final class Shader extends NativeObject {
|
||||
* Resets all uniforms that do not have the "set-by-current-material" flag
|
||||
* to their default value (usually all zeroes or false).
|
||||
* When a uniform is modified, that flag is set, to remove the flag,
|
||||
* use {@link #clearUniformsSetByCurrent() }.
|
||||
* use {@link #clearUniformsSetByCurrentFlag() }.
|
||||
*/
|
||||
public void resetUniformsNotSetByCurrent() {
|
||||
int size = uniforms.size();
|
||||
@ -366,6 +413,11 @@ public final class Shader extends NativeObject {
|
||||
uniform.reset(); // fixes issue with re-initialization
|
||||
}
|
||||
}
|
||||
if (bufferBlocks != null) {
|
||||
for (ShaderBufferBlock shaderBufferBlock : bufferBlocks.values()) {
|
||||
shaderBufferBlock.reset();
|
||||
}
|
||||
}
|
||||
if (attribs != null) {
|
||||
for (Entry<Attribute> entry : attribs) {
|
||||
entry.getValue().location = ShaderVariable.LOC_UNKNOWN;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -57,7 +57,8 @@ public enum VarType {
|
||||
Texture3D(false,true,"sampler3D"),
|
||||
TextureArray(false,true,"sampler2DArray|sampler2DArrayShadow"),
|
||||
TextureCubeMap(false,true,"samplerCube"),
|
||||
Int("int");
|
||||
Int("int"),
|
||||
BufferObject(false, false, "custom");
|
||||
|
||||
private boolean usesMultiData = false;
|
||||
private boolean textureType = false;
|
||||
|
@ -31,9 +31,6 @@
|
||||
*/
|
||||
package com.jme3.system;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.EnumSet;
|
||||
|
||||
import com.jme3.light.LightList;
|
||||
import com.jme3.material.RenderState;
|
||||
import com.jme3.math.ColorRGBA;
|
||||
@ -44,12 +41,16 @@ import com.jme3.renderer.Renderer;
|
||||
import com.jme3.renderer.Statistics;
|
||||
import com.jme3.scene.Mesh;
|
||||
import com.jme3.scene.VertexBuffer;
|
||||
import com.jme3.shader.BufferObject;
|
||||
import com.jme3.shader.Shader;
|
||||
import com.jme3.shader.Shader.ShaderSource;
|
||||
import com.jme3.texture.FrameBuffer;
|
||||
import com.jme3.texture.Image;
|
||||
import com.jme3.texture.Texture;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.EnumMap;
|
||||
import java.util.EnumSet;
|
||||
|
||||
public class NullRenderer implements Renderer {
|
||||
|
||||
@ -148,9 +149,17 @@ public class NullRenderer implements Renderer {
|
||||
public void updateBufferData(VertexBuffer vb) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBufferData(BufferObject bo) {
|
||||
}
|
||||
public void deleteBuffer(VertexBuffer vb) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteBuffer(BufferObject bo) {
|
||||
|
||||
}
|
||||
|
||||
public void renderMesh(Mesh mesh, int lod, int count, VertexBuffer[] instanceData) {
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,8 @@ public abstract class NativeObject implements Cloneable {
|
||||
OBJTYPE_SHADERSOURCE = 5,
|
||||
OBJTYPE_AUDIOBUFFER = 6,
|
||||
OBJTYPE_AUDIOSTREAM = 7,
|
||||
OBJTYPE_FILTER = 8;
|
||||
OBJTYPE_FILTER = 8,
|
||||
OBJTYPE_BO = 9;
|
||||
|
||||
/**
|
||||
* The object manager to which this NativeObject is registered to.
|
||||
|
@ -4,12 +4,11 @@ import com.jme3.renderer.RendererException;
|
||||
import com.jme3.renderer.opengl.GL;
|
||||
import com.jme3.renderer.opengl.GL2;
|
||||
import com.jme3.renderer.opengl.GL3;
|
||||
|
||||
import java.nio.*;
|
||||
|
||||
import com.jme3.renderer.opengl.GL4;
|
||||
import com.jogamp.opengl.GLContext;
|
||||
|
||||
import java.nio.*;
|
||||
|
||||
public class JoglGL implements GL, GL2, GL3, GL4 {
|
||||
|
||||
private static int getLimitBytes(ByteBuffer buffer) {
|
||||
@ -634,4 +633,30 @@ public class JoglGL implements GL, GL2, GL3, GL4 {
|
||||
checkLimit(arrays);
|
||||
GLContext.getCurrentGL().getGL2ES3().glDeleteVertexArrays(arrays.limit(), arrays);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int glGetUniformBlockIndex(final int program, final String uniformBlockName) {
|
||||
return GLContext.getCurrentGL().getGL3bc().glGetUniformBlockIndex(program, uniformBlockName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void glBindBufferBase(final int target, final int index, final int buffer) {
|
||||
GLContext.getCurrentGL().getGL3bc().glBindBufferBase(target, index, buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int glGetProgramResourceIndex(final int program, final int programInterface, final String name) {
|
||||
throw new UnsupportedOperationException();
|
||||
//return GLContext.getCurrentGL().getGL4bc().glGetProgramResourceIndex(program, programInterface, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void glShaderStorageBlockBinding(final int program, final int storageBlockIndex, final int storageBlockBinding) {
|
||||
GLContext.getCurrentGL().getGL4bc().glShaderStorageBlockBinding(program, storageBlockIndex, storageBlockBinding);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void glUniformBlockBinding(final int program, final int uniformBlockIndex, final int uniformBlockBinding) {
|
||||
GLContext.getCurrentGL().getGL3bc().glUniformBlockBinding(program, uniformBlockIndex, uniformBlockBinding);
|
||||
}
|
||||
}
|
||||
|
@ -4,16 +4,12 @@ import com.jme3.renderer.RendererException;
|
||||
import com.jme3.renderer.opengl.GL;
|
||||
import com.jme3.renderer.opengl.GL2;
|
||||
import com.jme3.renderer.opengl.GL3;
|
||||
import java.nio.Buffer;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import java.nio.ShortBuffer;
|
||||
|
||||
import com.jme3.renderer.opengl.GL4;
|
||||
import com.jme3.util.BufferUtils;
|
||||
import org.lwjgl.opengl.*;
|
||||
|
||||
import java.nio.*;
|
||||
|
||||
public final class LwjglGL implements GL, GL2, GL3, GL4 {
|
||||
|
||||
IntBuffer tmpBuff = BufferUtils.createIntBuffer(1);
|
||||
@ -488,9 +484,34 @@ public final class LwjglGL implements GL, GL2, GL3, GL4 {
|
||||
GL40.glPatchParameteri(GL40.GL_PATCH_VERTICES,count);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int glGetProgramResourceIndex(final int program, final int programInterface, final String name) {
|
||||
return GL43.glGetProgramResourceIndex(program, programInterface, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void glShaderStorageBlockBinding(final int program, final int storageBlockIndex, final int storageBlockBinding) {
|
||||
GL43.glShaderStorageBlockBinding(program, storageBlockIndex, storageBlockBinding);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void glDeleteVertexArrays(IntBuffer arrays) {
|
||||
checkLimit(arrays);
|
||||
ARBVertexArrayObject.glDeleteVertexArrays(arrays);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int glGetUniformBlockIndex(final int program, final String uniformBlockName) {
|
||||
return GL31.glGetUniformBlockIndex(program, uniformBlockName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void glBindBufferBase(final int target, final int index, final int buffer) {
|
||||
GL30.glBindBufferBase(target, index, buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void glUniformBlockBinding(final int program, final int uniformBlockIndex, final int uniformBlockBinding) {
|
||||
GL31.glUniformBlockBinding(program, uniformBlockIndex, uniformBlockBinding);
|
||||
}
|
||||
}
|
||||
|
@ -616,9 +616,34 @@ public class LwjglGL extends LwjglRender implements GL, GL2, GL3, GL4 {
|
||||
GL40.glPatchParameteri(GL40.GL_PATCH_VERTICES, count);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int glGetProgramResourceIndex(final int program, final int programInterface, final String name) {
|
||||
return GL43.glGetProgramResourceIndex(program, programInterface, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void glShaderStorageBlockBinding(final int program, final int storageBlockIndex, final int storageBlockBinding) {
|
||||
GL43.glShaderStorageBlockBinding(program, storageBlockIndex, storageBlockBinding);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void glDeleteVertexArrays(final IntBuffer arrays) {
|
||||
checkLimit(arrays);
|
||||
ARBVertexArrayObject.glDeleteVertexArrays(arrays);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int glGetUniformBlockIndex(final int program, final String uniformBlockName) {
|
||||
return GL31.glGetUniformBlockIndex(program, uniformBlockName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void glBindBufferBase(final int target, final int index, final int buffer) {
|
||||
GL30.glBindBufferBase(target, index, buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void glUniformBlockBinding(final int program, final int uniformBlockIndex, final int uniformBlockBinding) {
|
||||
GL31.glUniformBlockBinding(program, uniformBlockIndex, uniformBlockBinding);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user