git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9129 75d07b2b-3a1a-0410-a2c5-0572b91ccdca3.0
parent
230398c45b
commit
b53a825d35
@ -1,262 +1,263 @@ |
||||
/* |
||||
* Copyright (c) 2009-2010 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.material; |
||||
|
||||
import com.jme3.asset.AssetManager; |
||||
import com.jme3.export.*; |
||||
import com.jme3.shader.*; |
||||
import java.io.IOException; |
||||
import java.util.ArrayList; |
||||
import java.util.Collection; |
||||
import java.util.List; |
||||
import java.util.logging.Logger; |
||||
|
||||
/** |
||||
* Represents a technique instance. |
||||
*/ |
||||
public class Technique implements Savable { |
||||
|
||||
private static final Logger logger = Logger.getLogger(Technique.class.getName()); |
||||
private TechniqueDef def; |
||||
private Material owner; |
||||
private ArrayList<Uniform> worldBindUniforms; |
||||
private DefineList defines; |
||||
private Shader shader; |
||||
private boolean needReload = true; |
||||
|
||||
/** |
||||
* Creates a new technique instance that implements the given |
||||
* technique definition. |
||||
* |
||||
* @param owner The material that will own this technique |
||||
* @param def The technique definition being implemented. |
||||
*/ |
||||
public Technique(Material owner, TechniqueDef def) { |
||||
this.owner = owner; |
||||
this.def = def; |
||||
if (def.isUsingShaders()) { |
||||
this.worldBindUniforms = new ArrayList<Uniform>(); |
||||
this.defines = new DefineList(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Serialization only. Do not use. |
||||
*/ |
||||
public Technique() { |
||||
} |
||||
|
||||
/** |
||||
* Returns the technique definition that is implemented by this technique |
||||
* instance. |
||||
* |
||||
* @return the technique definition that is implemented by this technique |
||||
* instance. |
||||
*/ |
||||
public TechniqueDef getDef() { |
||||
return def; |
||||
} |
||||
|
||||
/** |
||||
* Returns the shader currently used by this technique instance. |
||||
* <p> |
||||
* Shaders are typically loaded dynamically when the technique is first |
||||
* used, therefore, this variable will most likely be null most of the time. |
||||
* |
||||
* @return the shader currently used by this technique instance. |
||||
*/ |
||||
public Shader getShader() { |
||||
return shader; |
||||
} |
||||
|
||||
/** |
||||
* Returns a list of uniforms that implements the world parameters |
||||
* that were requested by the material definition. |
||||
* |
||||
* @return a list of uniforms implementing the world parameters. |
||||
*/ |
||||
public List<Uniform> getWorldBindUniforms() { |
||||
return worldBindUniforms; |
||||
} |
||||
|
||||
/** |
||||
* Called by the material to tell the technique a parameter was modified |
||||
*/ |
||||
void notifySetParam(String paramName, VarType type, Object value) { |
||||
String defineName = def.getShaderParamDefine(paramName); |
||||
if (defineName != null) { |
||||
defines.set(defineName, type, value); |
||||
needReload = true; |
||||
} |
||||
if (shader != null) { |
||||
updateUniformParam(paramName, type, value); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Called by the material to tell the technique a parameter was cleared |
||||
*/ |
||||
void notifyClearParam(String paramName) { |
||||
String defineName = def.getShaderParamDefine(paramName); |
||||
if (defineName != null) { |
||||
defines.remove(defineName); |
||||
needReload = true; |
||||
} |
||||
if (shader != null) { |
||||
if (!paramName.startsWith("m_")) { |
||||
paramName = "m_" + paramName; |
||||
} |
||||
shader.removeUniform(paramName); |
||||
} |
||||
} |
||||
|
||||
void updateUniformParam(String paramName, VarType type, Object value, boolean ifNotOwner) { |
||||
Uniform u = shader.getUniform(paramName); |
||||
|
||||
// if (ifNotOwner && u.getLastChanger() == owner)
|
||||
// return;
|
||||
|
||||
switch (type) { |
||||
case Texture2D: // fall intentional
|
||||
case Texture3D: |
||||
case TextureArray: |
||||
case TextureCubeMap: |
||||
case Int: |
||||
u.setValue(VarType.Int, value); |
||||
break; |
||||
default: |
||||
u.setValue(type, value); |
||||
break; |
||||
} |
||||
// u.setLastChanger(owner);
|
||||
} |
||||
|
||||
void updateUniformParam(String paramName, VarType type, Object value) { |
||||
updateUniformParam(paramName, type, value, false); |
||||
} |
||||
|
||||
/** |
||||
* Returns true if the technique must be reloaded. |
||||
* <p> |
||||
* If a technique needs to reload, then the {@link Material} should |
||||
* call {@link #makeCurrent(com.jme3.asset.AssetManager) } on this |
||||
* technique. |
||||
* |
||||
* @return true if the technique must be reloaded. |
||||
*/ |
||||
public boolean isNeedReload() { |
||||
return needReload; |
||||
} |
||||
|
||||
/** |
||||
* Prepares the technique for use by loading the shader and setting |
||||
* the proper defines based on material parameters. |
||||
* |
||||
* @param assetManager The asset manager to use for loading shaders. |
||||
*/ |
||||
public void makeCurrent(AssetManager assetManager) { |
||||
// check if reload is needed..
|
||||
if (def.isUsingShaders()) { |
||||
DefineList newDefines = new DefineList(); |
||||
Collection<MatParam> params = owner.getParams(); |
||||
for (MatParam param : params) { |
||||
String defineName = def.getShaderParamDefine(param.getName()); |
||||
if (defineName != null) { |
||||
newDefines.set(defineName, param.getVarType(), param.getValue()); |
||||
} |
||||
} |
||||
|
||||
if (!needReload && defines.getCompiled().equals(newDefines.getCompiled())) { |
||||
newDefines = null; |
||||
// defines have not been changed..
|
||||
} else { |
||||
defines.clear(); |
||||
defines.addFrom(newDefines); |
||||
// defines changed, recompile needed
|
||||
loadShader(assetManager); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private void loadShader(AssetManager manager) { |
||||
// recompute define list
|
||||
DefineList allDefines = new DefineList(); |
||||
allDefines.addFrom(def.getShaderPresetDefines()); |
||||
allDefines.addFrom(defines); |
||||
|
||||
ShaderKey key = new ShaderKey(def.getVertexShaderName(), |
||||
def.getFragmentShaderName(), |
||||
allDefines, |
||||
def.getShaderLanguage()); |
||||
shader = manager.loadShader(key); |
||||
if (shader == null) { |
||||
logger.warning("Failed to reload shader!"); |
||||
return; |
||||
} |
||||
|
||||
// refresh the uniform links
|
||||
//owner.updateUniformLinks();
|
||||
|
||||
// register the world bound uniforms
|
||||
worldBindUniforms.clear(); |
||||
for (UniformBinding binding : def.getWorldBindings()) { |
||||
Uniform uniform = shader.getUniform("g_" + binding.name()); |
||||
uniform.setBinding(binding); |
||||
if (uniform != null) { |
||||
worldBindUniforms.add(uniform); |
||||
|
||||
} |
||||
} |
||||
|
||||
needReload = false; |
||||
} |
||||
|
||||
public void write(JmeExporter ex) throws IOException { |
||||
OutputCapsule oc = ex.getCapsule(this); |
||||
oc.write(def, "def", null); |
||||
// TODO:
|
||||
// oc.write(owner, "owner", null);
|
||||
oc.writeSavableArrayList(worldBindUniforms, "worldBindUniforms", null); |
||||
oc.write(defines, "defines", null); |
||||
oc.write(shader, "shader", null); |
||||
} |
||||
|
||||
public void read(JmeImporter im) throws IOException { |
||||
InputCapsule ic = im.getCapsule(this); |
||||
def = (TechniqueDef) ic.readSavable("def", null); |
||||
worldBindUniforms = ic.readSavableArrayList("worldBindUniforms", null); |
||||
defines = (DefineList) ic.readSavable("defines", null); |
||||
shader = (Shader) ic.readSavable("shader", null); |
||||
//if (shader != null)
|
||||
// owner.updateUniformLinks();
|
||||
} |
||||
} |
||||
/* |
||||
* Copyright (c) 2009-2010 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.material; |
||||
|
||||
import com.jme3.asset.AssetManager; |
||||
import com.jme3.export.*; |
||||
import com.jme3.shader.*; |
||||
import java.io.IOException; |
||||
import java.util.ArrayList; |
||||
import java.util.Collection; |
||||
import java.util.List; |
||||
import java.util.logging.Logger; |
||||
|
||||
/** |
||||
* Represents a technique instance. |
||||
*/ |
||||
public class Technique implements Savable { |
||||
|
||||
private static final Logger logger = Logger.getLogger(Technique.class.getName()); |
||||
private TechniqueDef def; |
||||
private Material owner; |
||||
private ArrayList<Uniform> worldBindUniforms; |
||||
private DefineList defines; |
||||
private Shader shader; |
||||
private boolean needReload = true; |
||||
|
||||
/** |
||||
* Creates a new technique instance that implements the given |
||||
* technique definition. |
||||
* |
||||
* @param owner The material that will own this technique |
||||
* @param def The technique definition being implemented. |
||||
*/ |
||||
public Technique(Material owner, TechniqueDef def) { |
||||
this.owner = owner; |
||||
this.def = def; |
||||
if (def.isUsingShaders()) { |
||||
this.worldBindUniforms = new ArrayList<Uniform>(); |
||||
this.defines = new DefineList(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Serialization only. Do not use. |
||||
*/ |
||||
public Technique() { |
||||
} |
||||
|
||||
/** |
||||
* Returns the technique definition that is implemented by this technique |
||||
* instance. |
||||
* |
||||
* @return the technique definition that is implemented by this technique |
||||
* instance. |
||||
*/ |
||||
public TechniqueDef getDef() { |
||||
return def; |
||||
} |
||||
|
||||
/** |
||||
* Returns the shader currently used by this technique instance. |
||||
* <p> |
||||
* Shaders are typically loaded dynamically when the technique is first |
||||
* used, therefore, this variable will most likely be null most of the time. |
||||
* |
||||
* @return the shader currently used by this technique instance. |
||||
*/ |
||||
public Shader getShader() { |
||||
return shader; |
||||
} |
||||
|
||||
/** |
||||
* Returns a list of uniforms that implements the world parameters |
||||
* that were requested by the material definition. |
||||
* |
||||
* @return a list of uniforms implementing the world parameters. |
||||
*/ |
||||
public List<Uniform> getWorldBindUniforms() { |
||||
return worldBindUniforms; |
||||
} |
||||
|
||||
/** |
||||
* Called by the material to tell the technique a parameter was modified |
||||
*/ |
||||
void notifySetParam(String paramName, VarType type, Object value) { |
||||
String defineName = def.getShaderParamDefine(paramName); |
||||
if (defineName != null) { |
||||
defines.set(defineName, type, value); |
||||
needReload = true; |
||||
} |
||||
if (shader != null) { |
||||
updateUniformParam(paramName, type, value); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Called by the material to tell the technique a parameter was cleared |
||||
*/ |
||||
void notifyClearParam(String paramName) { |
||||
String defineName = def.getShaderParamDefine(paramName); |
||||
if (defineName != null) { |
||||
defines.remove(defineName); |
||||
needReload = true; |
||||
} |
||||
if (shader != null) { |
||||
if (!paramName.startsWith("m_")) { |
||||
paramName = "m_" + paramName; |
||||
} |
||||
shader.removeUniform(paramName); |
||||
} |
||||
} |
||||
|
||||
void updateUniformParam(String paramName, VarType type, Object value, boolean ifNotOwner) { |
||||
Uniform u = shader.getUniform(paramName); |
||||
|
||||
// if (ifNotOwner && u.getLastChanger() == owner)
|
||||
// return;
|
||||
|
||||
switch (type) { |
||||
case Texture2D: // fall intentional
|
||||
case Texture3D: |
||||
case TextureArray: |
||||
case TextureCubeMap: |
||||
case Int: |
||||
u.setValue(VarType.Int, value); |
||||
break; |
||||
default: |
||||
u.setValue(type, value); |
||||
break; |
||||
} |
||||
// u.setLastChanger(owner);
|
||||
} |
||||
|
||||
void updateUniformParam(String paramName, VarType type, Object value) { |
||||
updateUniformParam(paramName, type, value, false); |
||||
} |
||||
|
||||
/** |
||||
* Returns true if the technique must be reloaded. |
||||
* <p> |
||||
* If a technique needs to reload, then the {@link Material} should |
||||
* call {@link #makeCurrent(com.jme3.asset.AssetManager) } on this |
||||
* technique. |
||||
* |
||||
* @return true if the technique must be reloaded. |
||||
*/ |
||||
public boolean isNeedReload() { |
||||
return needReload; |
||||
} |
||||
|
||||
/** |
||||
* Prepares the technique for use by loading the shader and setting |
||||
* the proper defines based on material parameters. |
||||
* |
||||
* @param assetManager The asset manager to use for loading shaders. |
||||
*/ |
||||
public void makeCurrent(AssetManager assetManager) { |
||||
// check if reload is needed..
|
||||
if (def.isUsingShaders()) { |
||||
DefineList newDefines = new DefineList(); |
||||
Collection<MatParam> params = owner.getParams(); |
||||
for (MatParam param : params) { |
||||
String defineName = def.getShaderParamDefine(param.getName()); |
||||
if (defineName != null) { |
||||
newDefines.set(defineName, param.getVarType(), param.getValue()); |
||||
} |
||||
} |
||||
|
||||
if (!needReload && defines.getCompiled().equals(newDefines.getCompiled())) { |
||||
newDefines = null; |
||||
// defines have not been changed..
|
||||
} else { |
||||
defines.clear(); |
||||
defines.addFrom(newDefines); |
||||
// defines changed, recompile needed
|
||||
loadShader(assetManager); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private void loadShader(AssetManager manager) { |
||||
// recompute define list
|
||||
DefineList allDefines = new DefineList(); |
||||
allDefines.addFrom(def.getShaderPresetDefines()); |
||||
allDefines.addFrom(defines); |
||||
|
||||
ShaderKey key = new ShaderKey(def.getVertexShaderName(), |
||||
def.getFragmentShaderName(), |
||||
allDefines, |
||||
def.getShaderLanguage()); |
||||
shader = manager.loadShader(key); |
||||
if (shader == null) { |
||||
logger.warning("Failed to reload shader!"); |
||||
return; |
||||
} |
||||
|
||||
// refresh the uniform links
|
||||
//owner.updateUniformLinks();
|
||||
|
||||
// register the world bound uniforms
|
||||
worldBindUniforms.clear(); |
||||
if (def.getWorldBindings() != null) { |
||||
for (UniformBinding binding : def.getWorldBindings()) { |
||||
Uniform uniform = shader.getUniform("g_" + binding.name()); |
||||
uniform.setBinding(binding); |
||||
if (uniform != null) { |
||||
worldBindUniforms.add(uniform); |
||||
} |
||||
} |
||||
} |
||||
|
||||
needReload = false; |
||||
} |
||||
|
||||
public void write(JmeExporter ex) throws IOException { |
||||
OutputCapsule oc = ex.getCapsule(this); |
||||
oc.write(def, "def", null); |
||||
// TODO:
|
||||
// oc.write(owner, "owner", null);
|
||||
oc.writeSavableArrayList(worldBindUniforms, "worldBindUniforms", null); |
||||
oc.write(defines, "defines", null); |
||||
oc.write(shader, "shader", null); |
||||
} |
||||
|
||||
public void read(JmeImporter im) throws IOException { |
||||
InputCapsule ic = im.getCapsule(this); |
||||
def = (TechniqueDef) ic.readSavable("def", null); |
||||
worldBindUniforms = ic.readSavableArrayList("worldBindUniforms", null); |
||||
defines = (DefineList) ic.readSavable("defines", null); |
||||
shader = (Shader) ic.readSavable("shader", null); |
||||
//if (shader != null)
|
||||
// owner.updateUniformLinks();
|
||||
} |
||||
} |
||||
|
Loading…
Reference in new issue