* Add convenience methods clearUniformsSetByCurrentFlag() and resetUniformsNotSetByCurrent() to Shader (normally this is performed by Material)
git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@10772 75d07b2b-3a1a-0410-a2c5-0572b91ccdcaexperimental
parent
67ce41ee57
commit
55ab8f5d30
@ -1,334 +1,366 @@ |
|||||||
/* |
/* |
||||||
* Copyright (c) 2009-2012 jMonkeyEngine |
* Copyright (c) 2009-2012 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 |
||||||
* modification, are permitted provided that the following conditions are |
* modification, are permitted provided that the following conditions are |
||||||
* met: |
* met: |
||||||
* |
* |
||||||
* * Redistributions of source code must retain the above copyright |
* * Redistributions of source code must retain the above copyright |
||||||
* notice, this list of conditions and the following disclaimer. |
* notice, this list of conditions and the following disclaimer. |
||||||
* |
* |
||||||
* * Redistributions in binary form must reproduce the above copyright |
* * Redistributions in binary form must reproduce the above copyright |
||||||
* notice, this list of conditions and the following disclaimer in the |
* notice, this list of conditions and the following disclaimer in the |
||||||
* documentation and/or other materials provided with the distribution. |
* documentation and/or other materials provided with the distribution. |
||||||
* |
* |
||||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||||
* may be used to endorse or promote products derived from this software |
* may be used to endorse or promote products derived from this software |
||||||
* without specific prior written permission. |
* without specific prior written permission. |
||||||
* |
* |
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
*/ |
*/ |
||||||
package com.jme3.shader; |
package com.jme3.shader; |
||||||
|
|
||||||
import com.jme3.renderer.Renderer; |
import com.jme3.renderer.Renderer; |
||||||
import com.jme3.scene.VertexBuffer; |
import com.jme3.scene.VertexBuffer; |
||||||
import com.jme3.util.IntMap; |
import com.jme3.util.IntMap; |
||||||
import com.jme3.util.IntMap.Entry; |
import com.jme3.util.IntMap.Entry; |
||||||
import com.jme3.util.ListMap; |
import com.jme3.util.ListMap; |
||||||
import com.jme3.util.NativeObject; |
import com.jme3.util.NativeObject; |
||||||
import java.util.ArrayList; |
import java.util.ArrayList; |
||||||
import java.util.Collection; |
import java.util.Collection; |
||||||
|
|
||||||
public final class Shader extends NativeObject { |
public final class Shader extends NativeObject { |
||||||
|
|
||||||
/** |
/** |
||||||
* A list of all shader sources currently attached. |
* A list of all shader sources currently attached. |
||||||
*/ |
*/ |
||||||
private ArrayList<ShaderSource> shaderSourceList; |
private ArrayList<ShaderSource> shaderSourceList; |
||||||
|
|
||||||
/** |
/** |
||||||
* Maps uniform name to the uniform variable. |
* Maps uniform name to the uniform variable. |
||||||
*/ |
*/ |
||||||
private ListMap<String, Uniform> uniforms; |
private ListMap<String, Uniform> uniforms; |
||||||
|
|
||||||
/** |
/** |
||||||
* Maps attribute name to the location of the attribute in the shader. |
* Maps attribute name to the location of the attribute in the shader. |
||||||
*/ |
*/ |
||||||
private IntMap<Attribute> attribs; |
private IntMap<Attribute> attribs; |
||||||
|
|
||||||
/** |
/** |
||||||
* Type of shader. The shader will control the pipeline of it's type. |
* Type of shader. The shader will control the pipeline of it's type. |
||||||
*/ |
*/ |
||||||
public static enum ShaderType { |
public static enum ShaderType { |
||||||
/** |
/** |
||||||
* Control fragment rasterization. (e.g color of pixel). |
* Control fragment rasterization. (e.g color of pixel). |
||||||
*/ |
*/ |
||||||
Fragment, |
Fragment, |
||||||
|
|
||||||
/** |
/** |
||||||
* Control vertex processing. (e.g transform of model to clip space) |
* Control vertex processing. (e.g transform of model to clip space) |
||||||
*/ |
*/ |
||||||
Vertex, |
Vertex, |
||||||
|
|
||||||
/** |
/** |
||||||
* Control geometry assembly. (e.g compile a triangle list from input data) |
* Control geometry assembly. (e.g compile a triangle list from input data) |
||||||
*/ |
*/ |
||||||
Geometry; |
Geometry; |
||||||
} |
} |
||||||
|
|
||||||
/** |
/** |
||||||
* Shader source describes a shader object in OpenGL. Each shader source |
* Shader source describes a shader object in OpenGL. Each shader source |
||||||
* is assigned a certain pipeline which it controls (described by it's type). |
* is assigned a certain pipeline which it controls (described by it's type). |
||||||
*/ |
*/ |
||||||
public static class ShaderSource extends NativeObject { |
public static class ShaderSource extends NativeObject { |
||||||
|
|
||||||
ShaderType sourceType; |
ShaderType sourceType; |
||||||
String language; |
String language; |
||||||
String name; |
String name; |
||||||
String source; |
String source; |
||||||
String defines; |
String defines; |
||||||
|
|
||||||
public ShaderSource(ShaderType type){ |
public ShaderSource(ShaderType type){ |
||||||
super(); |
super(); |
||||||
this.sourceType = type; |
this.sourceType = type; |
||||||
if (type == null) { |
if (type == null) { |
||||||
throw new IllegalArgumentException("The shader type must be specified"); |
throw new IllegalArgumentException("The shader type must be specified"); |
||||||
} |
} |
||||||
} |
} |
||||||
|
|
||||||
protected ShaderSource(ShaderSource ss){ |
protected ShaderSource(ShaderSource ss){ |
||||||
super(ss.id); |
super(ss.id); |
||||||
// No data needs to be copied.
|
// No data needs to be copied.
|
||||||
// (This is a destructable clone)
|
// (This is a destructable clone)
|
||||||
} |
} |
||||||
|
|
||||||
public ShaderSource(){ |
public ShaderSource(){ |
||||||
super(); |
super(); |
||||||
} |
} |
||||||
|
|
||||||
public void setName(String name){ |
public void setName(String name){ |
||||||
this.name = name; |
this.name = name; |
||||||
} |
} |
||||||
|
|
||||||
public String getName(){ |
public String getName(){ |
||||||
return name; |
return name; |
||||||
} |
} |
||||||
|
|
||||||
public ShaderType getType() { |
public ShaderType getType() { |
||||||
return sourceType; |
return sourceType; |
||||||
} |
} |
||||||
|
|
||||||
public String getLanguage() { |
public String getLanguage() { |
||||||
return language; |
return language; |
||||||
} |
} |
||||||
|
|
||||||
public void setLanguage(String language) { |
public void setLanguage(String language) { |
||||||
if (language == null) { |
if (language == null) { |
||||||
throw new IllegalArgumentException("Shader language cannot be null"); |
throw new IllegalArgumentException("Shader language cannot be null"); |
||||||
} |
} |
||||||
this.language = language; |
this.language = language; |
||||||
setUpdateNeeded(); |
setUpdateNeeded(); |
||||||
} |
} |
||||||
|
|
||||||
public void setSource(String source){ |
public void setSource(String source){ |
||||||
if (source == null) { |
if (source == null) { |
||||||
throw new IllegalArgumentException("Shader source cannot be null"); |
throw new IllegalArgumentException("Shader source cannot be null"); |
||||||
} |
} |
||||||
this.source = source; |
this.source = source; |
||||||
setUpdateNeeded(); |
setUpdateNeeded(); |
||||||
} |
} |
||||||
|
|
||||||
public void setDefines(String defines){ |
public void setDefines(String defines){ |
||||||
if (defines == null) { |
if (defines == null) { |
||||||
throw new IllegalArgumentException("Shader defines cannot be null"); |
throw new IllegalArgumentException("Shader defines cannot be null"); |
||||||
} |
} |
||||||
this.defines = defines; |
this.defines = defines; |
||||||
setUpdateNeeded(); |
setUpdateNeeded(); |
||||||
} |
} |
||||||
|
|
||||||
public String getSource(){ |
public String getSource(){ |
||||||
return source; |
return source; |
||||||
} |
} |
||||||
|
|
||||||
public String getDefines(){ |
public String getDefines(){ |
||||||
return defines; |
return defines; |
||||||
} |
} |
||||||
|
|
||||||
@Override |
@Override |
||||||
public long getUniqueId() { |
public long getUniqueId() { |
||||||
return ((long)OBJTYPE_SHADERSOURCE << 32) | ((long)id); |
return ((long)OBJTYPE_SHADERSOURCE << 32) | ((long)id); |
||||||
} |
} |
||||||
|
|
||||||
@Override |
@Override |
||||||
public String toString(){ |
public String toString(){ |
||||||
String nameTxt = ""; |
String nameTxt = ""; |
||||||
if (name != null) |
if (name != null) |
||||||
nameTxt = "name="+name+", "; |
nameTxt = "name="+name+", "; |
||||||
if (defines != null) |
if (defines != null) |
||||||
nameTxt += "defines, "; |
nameTxt += "defines, "; |
||||||
|
|
||||||
|
|
||||||
return getClass().getSimpleName() + "["+nameTxt+"type=" |
return getClass().getSimpleName() + "["+nameTxt+"type=" |
||||||
+ sourceType.name()+", language=" + language + "]"; |
+ sourceType.name()+", language=" + language + "]"; |
||||||
} |
} |
||||||
|
|
||||||
public void resetObject(){ |
public void resetObject(){ |
||||||
id = -1; |
id = -1; |
||||||
setUpdateNeeded(); |
setUpdateNeeded(); |
||||||
} |
} |
||||||
|
|
||||||
public void deleteObject(Object rendererObject){ |
public void deleteObject(Object rendererObject){ |
||||||
((Renderer)rendererObject).deleteShaderSource(ShaderSource.this); |
((Renderer)rendererObject).deleteShaderSource(ShaderSource.this); |
||||||
} |
} |
||||||
|
|
||||||
public NativeObject createDestructableClone(){ |
public NativeObject createDestructableClone(){ |
||||||
return new ShaderSource(ShaderSource.this); |
return new ShaderSource(ShaderSource.this); |
||||||
} |
} |
||||||
} |
} |
||||||
|
|
||||||
/** |
/** |
||||||
* Initializes the shader for use, must be called after the |
* Initializes the shader for use, must be called after the |
||||||
* constructor without arguments is used. |
* constructor without arguments is used. |
||||||
*/ |
*/ |
||||||
public void initialize() { |
public void initialize() { |
||||||
shaderSourceList = new ArrayList<ShaderSource>(); |
shaderSourceList = new ArrayList<ShaderSource>(); |
||||||
uniforms = new ListMap<String, Uniform>(); |
uniforms = new ListMap<String, Uniform>(); |
||||||
attribs = new IntMap<Attribute>(); |
attribs = new IntMap<Attribute>(); |
||||||
} |
} |
||||||
|
|
||||||
/** |
/** |
||||||
* Creates a new shader, {@link #initialize() } must be called |
* Creates a new shader, {@link #initialize() } must be called |
||||||
* after this constructor for the shader to be usable. |
* after this constructor for the shader to be usable. |
||||||
*/ |
*/ |
||||||
public Shader(){ |
public Shader(){ |
||||||
super(); |
super(); |
||||||
} |
} |
||||||
|
|
||||||
/** |
/** |
||||||
* Do not use this constructor. Used for destructable clones only. |
* Do not use this constructor. Used for destructable clones only. |
||||||
*/ |
*/ |
||||||
protected Shader(Shader s){ |
protected Shader(Shader s){ |
||||||
super(s.id); |
super(s.id); |
||||||
|
|
||||||
// Shader sources cannot be shared, therefore they must
|
// Shader sources cannot be shared, therefore they must
|
||||||
// be destroyed together with the parent shader.
|
// be destroyed together with the parent shader.
|
||||||
shaderSourceList = new ArrayList<ShaderSource>(); |
shaderSourceList = new ArrayList<ShaderSource>(); |
||||||
for (ShaderSource source : s.shaderSourceList){ |
for (ShaderSource source : s.shaderSourceList){ |
||||||
shaderSourceList.add( (ShaderSource)source.createDestructableClone() ); |
shaderSourceList.add( (ShaderSource)source.createDestructableClone() ); |
||||||
} |
} |
||||||
} |
} |
||||||
|
|
||||||
/** |
/** |
||||||
* Adds source code to a certain pipeline. |
* Adds source code to a certain pipeline. |
||||||
* |
* |
||||||
* @param type The pipeline to control |
* @param type The pipeline to control |
||||||
* @param source The shader source code (in GLSL). |
* @param source The shader source code (in GLSL). |
||||||
* @param defines Preprocessor defines (placed at the beginning of the shader) |
* @param defines Preprocessor defines (placed at the beginning of the shader) |
||||||
* @param language The shader source language, currently accepted is GLSL### |
* @param language The shader source language, currently accepted is GLSL### |
||||||
* where ### is the version, e.g. GLSL100 = GLSL 1.0, GLSL330 = GLSL 3.3, etc. |
* where ### is the version, e.g. GLSL100 = GLSL 1.0, GLSL330 = GLSL 3.3, etc. |
||||||
*/ |
*/ |
||||||
public void addSource(ShaderType type, String name, String source, String defines, String language){ |
public void addSource(ShaderType type, String name, String source, String defines, String language){ |
||||||
ShaderSource shaderSource = new ShaderSource(type); |
ShaderSource shaderSource = new ShaderSource(type); |
||||||
shaderSource.setSource(source); |
shaderSource.setSource(source); |
||||||
shaderSource.setName(name); |
shaderSource.setName(name); |
||||||
shaderSource.setLanguage(language); |
shaderSource.setLanguage(language); |
||||||
if (defines != null) { |
if (defines != null) { |
||||||
shaderSource.setDefines(defines); |
shaderSource.setDefines(defines); |
||||||
} |
} |
||||||
shaderSourceList.add(shaderSource); |
shaderSourceList.add(shaderSource); |
||||||
setUpdateNeeded(); |
setUpdateNeeded(); |
||||||
} |
} |
||||||
|
|
||||||
public Uniform getUniform(String name){ |
public Uniform getUniform(String name){ |
||||||
Uniform uniform = uniforms.get(name); |
Uniform uniform = uniforms.get(name); |
||||||
if (uniform == null){ |
if (uniform == null){ |
||||||
uniform = new Uniform(); |
uniform = new Uniform(); |
||||||
uniform.name = name; |
uniform.name = name; |
||||||
uniforms.put(name, uniform); |
uniforms.put(name, uniform); |
||||||
} |
} |
||||||
return uniform; |
return uniform; |
||||||
} |
} |
||||||
|
|
||||||
public void removeUniform(String name){ |
public void removeUniform(String name){ |
||||||
uniforms.remove(name); |
uniforms.remove(name); |
||||||
} |
} |
||||||
|
|
||||||
public Attribute getAttribute(VertexBuffer.Type attribType){ |
public Attribute getAttribute(VertexBuffer.Type attribType){ |
||||||
int ordinal = attribType.ordinal(); |
int ordinal = attribType.ordinal(); |
||||||
Attribute attrib = attribs.get(ordinal); |
Attribute attrib = attribs.get(ordinal); |
||||||
if (attrib == null){ |
if (attrib == null){ |
||||||
attrib = new Attribute(); |
attrib = new Attribute(); |
||||||
attrib.name = attribType.name(); |
attrib.name = attribType.name(); |
||||||
attribs.put(ordinal, attrib); |
attribs.put(ordinal, attrib); |
||||||
} |
} |
||||||
return attrib; |
return attrib; |
||||||
} |
} |
||||||
|
|
||||||
public ListMap<String, Uniform> getUniformMap(){ |
public ListMap<String, Uniform> getUniformMap(){ |
||||||
return uniforms; |
return uniforms; |
||||||
} |
} |
||||||
|
|
||||||
public Collection<ShaderSource> getSources(){ |
public Collection<ShaderSource> getSources(){ |
||||||
return shaderSourceList; |
return shaderSourceList; |
||||||
} |
} |
||||||
|
|
||||||
@Override |
@Override |
||||||
public String toString() { |
public String toString() { |
||||||
return getClass().getSimpleName() + |
return getClass().getSimpleName() + |
||||||
"[numSources=" + shaderSourceList.size() + |
"[numSources=" + shaderSourceList.size() + |
||||||
", numUniforms=" + uniforms.size() + |
", numUniforms=" + uniforms.size() + |
||||||
", shaderSources=" + getSources() + "]"; |
", shaderSources=" + getSources() + "]"; |
||||||
} |
} |
||||||
|
|
||||||
/** |
/** |
||||||
* Usually called when the shader itself changes or during any |
* Removes the "set-by-current-material" flag from all uniforms. |
||||||
* time when the variable locations need to be refreshed. |
* When a uniform is modified after this call, the flag shall |
||||||
*/ |
* become "set-by-current-material". |
||||||
public void resetLocations() { |
* A call to {@link #resetUniformsNotSetByCurrent() } will reset |
||||||
if (uniforms != null) { |
* all uniforms that do not have the "set-by-current-material" flag |
||||||
// NOTE: Shader sources will be reset seperately from the shader itself.
|
* to their default value (usually all zeroes or false). |
||||||
for (Uniform uniform : uniforms.values()) { |
*/ |
||||||
uniform.reset(); // fixes issue with re-initialization
|
public void clearUniformsSetByCurrentFlag() { |
||||||
} |
int size = uniforms.size(); |
||||||
} |
for (int i = 0; i < size; i++) { |
||||||
if (attribs != null) { |
Uniform u = uniforms.getValue(i); |
||||||
for (Entry<Attribute> entry : attribs) { |
u.clearSetByCurrentMaterial(); |
||||||
entry.getValue().location = ShaderVariable.LOC_UNKNOWN; |
} |
||||||
} |
} |
||||||
} |
|
||||||
} |
/** |
||||||
|
* Resets all uniforms that do not have the "set-by-current-material" flag |
||||||
@Override |
* to their default value (usually all zeroes or false). |
||||||
public void setUpdateNeeded(){ |
* When a uniform is modified, that flag is set, to remove the flag, |
||||||
super.setUpdateNeeded(); |
* use {@link #clearUniformsSetByCurrent() }. |
||||||
resetLocations(); |
*/ |
||||||
} |
public void resetUniformsNotSetByCurrent() { |
||||||
|
int size = uniforms.size(); |
||||||
/** |
for (int i = 0; i < size; i++) { |
||||||
* Called by the object manager to reset all object IDs. This causes |
Uniform u = uniforms.getValue(i); |
||||||
* the shader to be reuploaded to the GPU incase the display was restarted. |
if (!u.isSetByCurrentMaterial()) { |
||||||
*/ |
u.clearValue(); |
||||||
@Override |
} |
||||||
public void resetObject() { |
} |
||||||
this.id = -1; |
} |
||||||
for (ShaderSource source : shaderSourceList){ |
|
||||||
source.resetObject(); |
/** |
||||||
} |
* Usually called when the shader itself changes or during any |
||||||
setUpdateNeeded(); |
* time when the variable locations need to be refreshed. |
||||||
} |
*/ |
||||||
|
public void resetLocations() { |
||||||
@Override |
if (uniforms != null) { |
||||||
public void deleteObject(Object rendererObject) { |
// NOTE: Shader sources will be reset seperately from the shader itself.
|
||||||
((Renderer)rendererObject).deleteShader(this); |
for (Uniform uniform : uniforms.values()) { |
||||||
} |
uniform.reset(); // fixes issue with re-initialization
|
||||||
|
} |
||||||
public NativeObject createDestructableClone(){ |
} |
||||||
return new Shader(this); |
if (attribs != null) { |
||||||
} |
for (Entry<Attribute> entry : attribs) { |
||||||
|
entry.getValue().location = ShaderVariable.LOC_UNKNOWN; |
||||||
@Override |
} |
||||||
public long getUniqueId() { |
} |
||||||
return ((long)OBJTYPE_SHADER << 32) | ((long)id); |
} |
||||||
} |
|
||||||
} |
@Override |
||||||
|
public void setUpdateNeeded(){ |
||||||
|
super.setUpdateNeeded(); |
||||||
|
resetLocations(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Called by the object manager to reset all object IDs. This causes |
||||||
|
* the shader to be reuploaded to the GPU incase the display was restarted. |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public void resetObject() { |
||||||
|
this.id = -1; |
||||||
|
for (ShaderSource source : shaderSourceList){ |
||||||
|
source.resetObject(); |
||||||
|
} |
||||||
|
setUpdateNeeded(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void deleteObject(Object rendererObject) { |
||||||
|
((Renderer)rendererObject).deleteShader(this); |
||||||
|
} |
||||||
|
|
||||||
|
public NativeObject createDestructableClone(){ |
||||||
|
return new Shader(this); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public long getUniqueId() { |
||||||
|
return ((long)OBJTYPE_SHADER << 32) | ((long)id); |
||||||
|
} |
||||||
|
} |
||||||
|
Loading…
Reference in new issue