Merge pull request #293 from davidB/david_materiel_no_render

add TechniqueDef.noRender
experimental
Kirill Vainer 10 years ago
commit 328966ba79
  1. 153
      jme3-core/src/main/java/com/jme3/material/Material.java
  2. 135
      jme3-core/src/main/java/com/jme3/material/TechniqueDef.java
  3. 94
      jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java

@ -69,7 +69,7 @@ import java.util.logging.Logger;
* Setting the parameters can modify the behavior of a * Setting the parameters can modify the behavior of a
* shader. * shader.
* <p/> * <p/>
* *
* @author Kirill Vainer * @author Kirill Vainer
*/ */
public class Material implements CloneableSmartAsset, Cloneable, Savable { public class Material implements CloneableSmartAsset, Cloneable, Savable {
@ -146,7 +146,7 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
public String getName() { public String getName() {
return name; return name;
} }
/** /**
* This method sets the name of the material. * This method sets the name of the material.
* The name is not the same as the asset name. * The name is not the same as the asset name.
@ -222,11 +222,11 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
} }
/** /**
* Compares two materials and returns true if they are equal. * Compares two materials and returns true if they are equal.
* This methods compare definition, parameters, additional render states. * This methods compare definition, parameters, additional render states.
* Since materials are mutable objects, implementing equals() properly is not possible, * Since materials are mutable objects, implementing equals() properly is not possible,
* hence the name contentEquals(). * hence the name contentEquals().
* *
* @param otherObj the material to compare to this material * @param otherObj the material to compare to this material
* @return true if the materials are equal. * @return true if the materials are equal.
*/ */
@ -234,15 +234,15 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
if (!(otherObj instanceof Material)) { if (!(otherObj instanceof Material)) {
return false; return false;
} }
Material other = (Material) otherObj; Material other = (Material) otherObj;
// Early exit if the material are the same object // Early exit if the material are the same object
if (this == other) { if (this == other) {
return true; return true;
} }
// Check material definition // Check material definition
if (this.getMaterialDef() != other.getMaterialDef()) { if (this.getMaterialDef() != other.getMaterialDef()) {
return false; return false;
} }
@ -251,12 +251,12 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
if (this.paramValues.size() != other.paramValues.size()) { if (this.paramValues.size() != other.paramValues.size()) {
return false; return false;
} }
// Checking technique // Checking technique
if (this.technique != null || other.technique != null) { if (this.technique != null || other.technique != null) {
// Techniques are considered equal if their names are the same // Techniques are considered equal if their names are the same
// E.g. if user chose custom technique for one material but // E.g. if user chose custom technique for one material but
// uses default technique for other material, the materials // uses default technique for other material, the materials
// are not equal. // are not equal.
String thisDefName = this.technique != null ? this.technique.getDef().getName() : "Default"; String thisDefName = this.technique != null ? this.technique.getDef().getName() : "Default";
String otherDefName = other.technique != null ? other.technique.getDef().getName() : "Default"; String otherDefName = other.technique != null ? other.technique.getDef().getName() : "Default";
@ -290,7 +290,7 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
return false; return false;
} }
} }
return true; return true;
} }
@ -305,7 +305,7 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
hash = 29 * hash + (this.additionalState != null ? this.additionalState.contentHashCode() : 0); hash = 29 * hash + (this.additionalState != null ? this.additionalState.contentHashCode() : 0);
return hash; return hash;
} }
/** /**
* Returns the currently active technique. * Returns the currently active technique.
* <p> * <p>
@ -436,7 +436,7 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
public Collection<MatParam> getParams() { public Collection<MatParam> getParams() {
return paramValues.values(); return paramValues.values();
} }
/** /**
* Returns the ListMap of all parameters set on this material. * Returns the ListMap of all parameters set on this material.
* *
@ -473,7 +473,7 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
*/ */
public void setParam(String name, VarType type, Object value) { public void setParam(String name, VarType type, Object value) {
checkSetParam(type, name); checkSetParam(type, name);
if (type.isTextureType()) { if (type.isTextureType()) {
setTextureParam(name, type, (Texture)value); setTextureParam(name, type, (Texture)value);
} else { } else {
@ -501,7 +501,7 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
if (matParam == null) { if (matParam == null) {
return; return;
} }
paramValues.remove(name); paramValues.remove(name);
if (matParam instanceof MatParamTexture) { if (matParam instanceof MatParamTexture) {
int texUnit = ((MatParamTexture) matParam).getUnit(); int texUnit = ((MatParamTexture) matParam).getUnit();
@ -728,7 +728,7 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
renderer.renderMesh(mesh, lodLevel, 1, null); renderer.renderMesh(mesh, lodLevel, 1, null);
} }
} }
/** /**
* Uploads the lights in the light list as two uniform arrays.<br/><br/> * * Uploads the lights in the light list as two uniform arrays.<br/><br/> *
* <p> * <p>
@ -747,30 +747,30 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
return 0; return 0;
} }
Uniform lightData = shader.getUniform("g_LightData"); Uniform lightData = shader.getUniform("g_LightData");
lightData.setVector4Length(numLights * 3);//8 lights * max 3 lightData.setVector4Length(numLights * 3);//8 lights * max 3
Uniform ambientColor = shader.getUniform("g_AmbientLightColor"); Uniform ambientColor = shader.getUniform("g_AmbientLightColor");
if (startIndex != 0) {
if (startIndex != 0) {
// apply additive blending for 2nd and future passes // apply additive blending for 2nd and future passes
rm.getRenderer().applyRenderState(additiveLight); rm.getRenderer().applyRenderState(additiveLight);
ambientColor.setValue(VarType.Vector4, ColorRGBA.Black); ambientColor.setValue(VarType.Vector4, ColorRGBA.Black);
}else{ }else{
ambientColor.setValue(VarType.Vector4, getAmbientColor(lightList,true)); ambientColor.setValue(VarType.Vector4, getAmbientColor(lightList,true));
} }
int lightDataIndex = 0; int lightDataIndex = 0;
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
Vector4f tmpVec = vars.vect4f1; Vector4f tmpVec = vars.vect4f1;
int curIndex; int curIndex;
int endIndex = numLights + startIndex; int endIndex = numLights + startIndex;
for (curIndex = startIndex; curIndex < endIndex && curIndex < lightList.size(); curIndex++) { for (curIndex = startIndex; curIndex < endIndex && curIndex < lightList.size(); curIndex++) {
Light l = lightList.get(curIndex); Light l = lightList.get(curIndex);
if(l.getType() == Light.Type.Ambient){ if(l.getType() == Light.Type.Ambient){
endIndex++; endIndex++;
continue; continue;
} }
ColorRGBA color = l.getColor(); ColorRGBA color = l.getColor();
@ -781,14 +781,14 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
l.getType().getId(), l.getType().getId(),
lightDataIndex); lightDataIndex);
lightDataIndex++; lightDataIndex++;
switch (l.getType()) { switch (l.getType()) {
case Directional: case Directional:
DirectionalLight dl = (DirectionalLight) l; DirectionalLight dl = (DirectionalLight) l;
Vector3f dir = dl.getDirection(); Vector3f dir = dl.getDirection();
//Data directly sent in view space to avoid a matrix mult for each pixel //Data directly sent in view space to avoid a matrix mult for each pixel
tmpVec.set(dir.getX(), dir.getY(), dir.getZ(), 0.0f); tmpVec.set(dir.getX(), dir.getY(), dir.getZ(), 0.0f);
rm.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec); rm.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec);
// tmpVec.divideLocal(tmpVec.w); // tmpVec.divideLocal(tmpVec.w);
// tmpVec.normalizeLocal(); // tmpVec.normalizeLocal();
lightData.setVector4InArray(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), -1, lightDataIndex); lightData.setVector4InArray(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), -1, lightDataIndex);
@ -802,7 +802,7 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
Vector3f pos = pl.getPosition(); Vector3f pos = pl.getPosition();
float invRadius = pl.getInvRadius(); float invRadius = pl.getInvRadius();
tmpVec.set(pos.getX(), pos.getY(), pos.getZ(), 1.0f); tmpVec.set(pos.getX(), pos.getY(), pos.getZ(), 1.0f);
rm.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec); rm.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec);
//tmpVec.divideLocal(tmpVec.w); //tmpVec.divideLocal(tmpVec.w);
lightData.setVector4InArray(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), invRadius, lightDataIndex); lightData.setVector4InArray(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), invRadius, lightDataIndex);
lightDataIndex++; lightDataIndex++;
@ -810,37 +810,37 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
lightData.setVector4InArray(0,0,0,0, lightDataIndex); lightData.setVector4InArray(0,0,0,0, lightDataIndex);
lightDataIndex++; lightDataIndex++;
break; break;
case Spot: case Spot:
SpotLight sl = (SpotLight) l; SpotLight sl = (SpotLight) l;
Vector3f pos2 = sl.getPosition(); Vector3f pos2 = sl.getPosition();
Vector3f dir2 = sl.getDirection(); Vector3f dir2 = sl.getDirection();
float invRange = sl.getInvSpotRange(); float invRange = sl.getInvSpotRange();
float spotAngleCos = sl.getPackedAngleCos(); float spotAngleCos = sl.getPackedAngleCos();
tmpVec.set(pos2.getX(), pos2.getY(), pos2.getZ(), 1.0f); tmpVec.set(pos2.getX(), pos2.getY(), pos2.getZ(), 1.0f);
rm.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec); rm.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec);
// tmpVec.divideLocal(tmpVec.w); // tmpVec.divideLocal(tmpVec.w);
lightData.setVector4InArray(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), invRange, lightDataIndex); lightData.setVector4InArray(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), invRange, lightDataIndex);
lightDataIndex++; lightDataIndex++;
//We transform the spot direction in view space here to save 5 varying later in the lighting shader //We transform the spot direction in view space here to save 5 varying later in the lighting shader
//one vec4 less and a vec4 that becomes a vec3 //one vec4 less and a vec4 that becomes a vec3
//the downside is that spotAngleCos decoding happens now in the frag shader. //the downside is that spotAngleCos decoding happens now in the frag shader.
tmpVec.set(dir2.getX(), dir2.getY(), dir2.getZ(), 0.0f); tmpVec.set(dir2.getX(), dir2.getY(), dir2.getZ(), 0.0f);
rm.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec); rm.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec);
tmpVec.normalizeLocal(); tmpVec.normalizeLocal();
lightData.setVector4InArray(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), spotAngleCos, lightDataIndex); lightData.setVector4InArray(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), spotAngleCos, lightDataIndex);
lightDataIndex++; lightDataIndex++;
break; break;
default: default:
throw new UnsupportedOperationException("Unknown type of light: " + l.getType()); throw new UnsupportedOperationException("Unknown type of light: " + l.getType());
} }
} }
vars.release(); vars.release();
//Padding of unsued buffer space //Padding of unsued buffer space
while(lightDataIndex < numLights * 3) { while(lightDataIndex < numLights * 3) {
lightData.setVector4InArray(0f, 0f, 0f, 0f, lightDataIndex); lightData.setVector4InArray(0f, 0f, 0f, 0f, lightDataIndex);
lightDataIndex++; lightDataIndex++;
} }
return curIndex; return curIndex;
} }
@ -887,10 +887,10 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
case Directional: case Directional:
DirectionalLight dl = (DirectionalLight) l; DirectionalLight dl = (DirectionalLight) l;
Vector3f dir = dl.getDirection(); Vector3f dir = dl.getDirection();
//FIXME : there is an inconstency here due to backward //FIXME : there is an inconstency here due to backward
//compatibility of the lighting shader. //compatibility of the lighting shader.
//The directional light direction is passed in the //The directional light direction is passed in the
//LightPosition uniform. The lighting shader needs to be //LightPosition uniform. The lighting shader needs to be
//reworked though in order to fix this. //reworked though in order to fix this.
tmpLightPosition.set(dir.getX(), dir.getY(), dir.getZ(), -1); tmpLightPosition.set(dir.getX(), dir.getY(), dir.getZ(), -1);
lightPos.setValue(VarType.Vector4, tmpLightPosition); lightPos.setValue(VarType.Vector4, tmpLightPosition);
@ -987,11 +987,11 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
for (TechniqueDef techDef : techDefs) { for (TechniqueDef techDef : techDefs) {
if (rendererCaps.containsAll(techDef.getRequiredCaps())) { if (rendererCaps.containsAll(techDef.getRequiredCaps())) {
// use the first one that supports all the caps // use the first one that supports all the caps
tech = new Technique(this, techDef); tech = new Technique(this, techDef);
techniques.put(name, tech); techniques.put(name, tech);
if(tech.getDef().getLightMode() == renderManager.getPreferredLightMode() || if(tech.getDef().getLightMode() == renderManager.getPreferredLightMode() ||
tech.getDef().getLightMode() == LightMode.Disable){ tech.getDef().getLightMode() == LightMode.Disable){
break; break;
} }
} }
lastTech = techDef; lastTech = techDef;
@ -1078,7 +1078,7 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
Uniform u = uniforms.getValue(i); Uniform u = uniforms.getValue(i);
if (!u.isSetByCurrentMaterial()) { if (!u.isSetByCurrentMaterial()) {
if (u.getName().charAt(0) != 'g') { if (u.getName().charAt(0) != 'g') {
// Don't reset world globals! // Don't reset world globals!
// The benefits gained from this are very minimal // The benefits gained from this are very minimal
// and cause lots of matrix -> FloatBuffer conversions. // and cause lots of matrix -> FloatBuffer conversions.
u.clearValue(); u.clearValue();
@ -1093,21 +1093,21 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
* <p> * <p>
* The material is rendered as follows: * The material is rendered as follows:
* <ul> * <ul>
* <li>Determine which technique to use to render the material - * <li>Determine which technique to use to render the material -
* either what the user selected via * either what the user selected via
* {@link #selectTechnique(java.lang.String, com.jme3.renderer.RenderManager) * {@link #selectTechnique(java.lang.String, com.jme3.renderer.RenderManager)
* Material.selectTechnique()}, * Material.selectTechnique()},
* or the first default technique that the renderer supports * or the first default technique that the renderer supports
* (based on the technique's {@link TechniqueDef#getRequiredCaps() requested rendering capabilities})<ul> * (based on the technique's {@link TechniqueDef#getRequiredCaps() requested rendering capabilities})<ul>
* <li>If the technique has been changed since the last frame, then it is notified via * <li>If the technique has been changed since the last frame, then it is notified via
* {@link Technique#makeCurrent(com.jme3.asset.AssetManager, boolean, java.util.EnumSet) * {@link Technique#makeCurrent(com.jme3.asset.AssetManager, boolean, java.util.EnumSet)
* Technique.makeCurrent()}. * Technique.makeCurrent()}.
* If the technique wants to use a shader to render the model, it should load it at this part - * If the technique wants to use a shader to render the model, it should load it at this part -
* the shader should have all the proper defines as declared in the technique definition, * the shader should have all the proper defines as declared in the technique definition,
* including those that are bound to material parameters. * including those that are bound to material parameters.
* The technique can re-use the shader from the last frame if * The technique can re-use the shader from the last frame if
* no changes to the defines occurred.</li></ul> * no changes to the defines occurred.</li></ul>
* <li>Set the {@link RenderState} to use for rendering. The render states are * <li>Set the {@link RenderState} to use for rendering. The render states are
* applied in this order (later RenderStates override earlier RenderStates):<ol> * applied in this order (later RenderStates override earlier RenderStates):<ol>
* <li>{@link TechniqueDef#getRenderState() Technique Definition's RenderState} * <li>{@link TechniqueDef#getRenderState() Technique Definition's RenderState}
* - i.e. specific renderstate that is required for the shader.</li> * - i.e. specific renderstate that is required for the shader.</li>
@ -1120,22 +1120,22 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
* <li>Uniforms bound to material parameters are updated based on the current material parameter values.</li> * <li>Uniforms bound to material parameters are updated based on the current material parameter values.</li>
* <li>Uniforms bound to world parameters are updated from the RenderManager. * <li>Uniforms bound to world parameters are updated from the RenderManager.
* Internally {@link UniformBindingManager} is used for this task.</li> * Internally {@link UniformBindingManager} is used for this task.</li>
* <li>Uniforms bound to textures will cause the texture to be uploaded as necessary. * <li>Uniforms bound to textures will cause the texture to be uploaded as necessary.
* The uniform is set to the texture unit where the texture is bound.</li></ul> * The uniform is set to the texture unit where the texture is bound.</li></ul>
* <li>If the technique uses a shader, the model is then rendered according * <li>If the technique uses a shader, the model is then rendered according
* to the lighting mode specified on the technique definition.<ul> * to the lighting mode specified on the technique definition.<ul>
* <li>{@link LightMode#SinglePass single pass light mode} fills the shader's light uniform arrays * <li>{@link LightMode#SinglePass single pass light mode} fills the shader's light uniform arrays
* with the first 4 lights and renders the model once.</li> * with the first 4 lights and renders the model once.</li>
* <li>{@link LightMode#MultiPass multi pass light mode} light mode renders the model multiple times, * <li>{@link LightMode#MultiPass multi pass light mode} light mode renders the model multiple times,
* for the first light it is rendered opaque, on subsequent lights it is * for the first light it is rendered opaque, on subsequent lights it is
* rendered with {@link BlendMode#AlphaAdditive alpha-additive} blending and depth writing disabled.</li> * rendered with {@link BlendMode#AlphaAdditive alpha-additive} blending and depth writing disabled.</li>
* </ul> * </ul>
* <li>For techniques that do not use shaders, * <li>For techniques that do not use shaders,
* fixed function OpenGL is used to render the model (see {@link GL1Renderer} interface):<ul> * fixed function OpenGL is used to render the model (see {@link GL1Renderer} interface):<ul>
* <li>OpenGL state ({@link FixedFuncBinding}) that is bound to material parameters is updated. </li> * <li>OpenGL state ({@link FixedFuncBinding}) that is bound to material parameters is updated. </li>
* <li>The texture set on the material is uploaded and bound. * <li>The texture set on the material is uploaded and bound.
* Currently only 1 texture is supported for fixed function techniques.</li> * Currently only 1 texture is supported for fixed function techniques.</li>
* <li>If the technique uses lighting, then OpenGL lighting state is updated * <li>If the technique uses lighting, then OpenGL lighting state is updated
* based on the light list on the geometry, otherwise OpenGL lighting is disabled.</li> * based on the light list on the geometry, otherwise OpenGL lighting is disabled.</li>
* <li>The mesh is uploaded and rendered.</li> * <li>The mesh is uploaded and rendered.</li>
* </ul> * </ul>
@ -1147,10 +1147,11 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
*/ */
public void render(Geometry geom, LightList lights, RenderManager rm) { public void render(Geometry geom, LightList lights, RenderManager rm) {
autoSelectTechnique(rm); autoSelectTechnique(rm);
TechniqueDef techDef = technique.getDef();
Renderer r = rm.getRenderer(); if (techDef.isNoRender()) return;
TechniqueDef techDef = technique.getDef(); Renderer r = rm.getRenderer();
if (rm.getForcedRenderState() != null) { if (rm.getForcedRenderState() != null) {
r.applyRenderState(rm.getForcedRenderState()); r.applyRenderState(rm.getForcedRenderState());
@ -1169,7 +1170,7 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
// reset unchanged uniform flag // reset unchanged uniform flag
clearUniformsSetByCurrent(technique.getShader()); clearUniformsSetByCurrent(technique.getShader());
rm.updateUniformBindings(technique.getWorldBindUniforms()); rm.updateUniformBindings(technique.getWorldBindUniforms());
// setup textures and uniforms // setup textures and uniforms
for (int i = 0; i < paramValues.size(); i++) { for (int i = 0; i < paramValues.size(); i++) {
@ -1212,24 +1213,24 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
// any unset uniforms will be set to 0 // any unset uniforms will be set to 0
resetUniformsNotSetByCurrent(shader); resetUniformsNotSetByCurrent(shader);
r.setShader(shader); r.setShader(shader);
renderMeshFromGeometry(r, geom); renderMeshFromGeometry(r, geom);
} }
/** /**
* Called by {@link RenderManager} to render the geometry by * Called by {@link RenderManager} to render the geometry by
* using this material. * using this material.
* *
* Note that this version of the render method * Note that this version of the render method
* does not perform light filtering. * does not perform light filtering.
* *
* @param geom The geometry to render * @param geom The geometry to render
* @param rm The render manager requesting the rendering * @param rm The render manager requesting the rendering
*/ */
public void render(Geometry geom, RenderManager rm) { public void render(Geometry geom, RenderManager rm) {
render(geom, geom.getWorldLightList(), rm); render(geom, geom.getWorldLightList(), rm);
} }
public void write(JmeExporter ex) throws IOException { public void write(JmeExporter ex) throws IOException {
OutputCapsule oc = ex.getCapsule(this); OutputCapsule oc = ex.getCapsule(this);
oc.write(def.getAssetName(), "material_def", null); oc.write(def.getAssetName(), "material_def", null);
@ -1304,14 +1305,14 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
continue; continue;
} }
} }
if (im.getFormatVersion() == 0 && param.getName().startsWith("m_")) { if (im.getFormatVersion() == 0 && param.getName().startsWith("m_")) {
// Ancient version of jME3 ... // Ancient version of jME3 ...
param.setName(param.getName().substring(2)); param.setName(param.getName().substring(2));
} }
if (def.getMaterialParam(param.getName()) == null) { if (def.getMaterialParam(param.getName()) == null) {
logger.log(Level.WARNING, "The material parameter is not defined: {0}. Ignoring..", logger.log(Level.WARNING, "The material parameter is not defined: {0}. Ignoring..",
param.getName()); param.getName());
} else { } else {
checkSetParam(param.getVarType(), param.getName()); checkSetParam(param.getVarType(), param.getName());

@ -40,7 +40,7 @@ import java.util.*;
/** /**
* Describes a technique definition. * Describes a technique definition.
* *
* @author Kirill Vainer * @author Kirill Vainer
*/ */
public class TechniqueDef implements Savable { public class TechniqueDef implements Savable {
@ -49,7 +49,7 @@ public class TechniqueDef implements Savable {
* Version #1: Separate shader language for each shader source. * Version #1: Separate shader language for each shader source.
*/ */
public static final int SAVABLE_VERSION = 1; public static final int SAVABLE_VERSION = 1;
/** /**
* Describes light rendering mode. * Describes light rendering mode.
*/ */
@ -58,15 +58,15 @@ public class TechniqueDef implements Savable {
* Disable light-based rendering * Disable light-based rendering
*/ */
Disable, Disable,
/** /**
* Enable light rendering by using a single pass. * Enable light rendering by using a single pass.
* <p> * <p>
* An array of light positions and light colors is passed to the shader * An array of light positions and light colors is passed to the shader
* containing the world light list for the geometry being rendered. * containing the world light list for the geometry being rendered.
*/ */
SinglePass, SinglePass,
/** /**
* Enable light rendering by using multi-pass rendering. * Enable light rendering by using multi-pass rendering.
* <p> * <p>
@ -77,7 +77,7 @@ public class TechniqueDef implements Savable {
* passes have it set to black. * passes have it set to black.
*/ */
MultiPass, MultiPass,
/** /**
* @deprecated OpenGL1 is not supported anymore * @deprecated OpenGL1 is not supported anymore
*/ */
@ -96,15 +96,16 @@ public class TechniqueDef implements Savable {
private EnumMap<Shader.ShaderType,String> shaderLanguages; private EnumMap<Shader.ShaderType,String> shaderLanguages;
private EnumMap<Shader.ShaderType,String> shaderNames; private EnumMap<Shader.ShaderType,String> shaderNames;
private DefineList presetDefines; private DefineList presetDefines;
private boolean usesNodes = false; private boolean usesNodes = false;
private List<ShaderNode> shaderNodes; private List<ShaderNode> shaderNodes;
private ShaderGenerationInfo shaderGenerationInfo; private ShaderGenerationInfo shaderGenerationInfo;
private boolean noRender = false;
private RenderState renderState; private RenderState renderState;
private RenderState forcedRenderState; private RenderState forcedRenderState;
private LightMode lightMode = LightMode.Disable; private LightMode lightMode = LightMode.Disable;
private ShadowMode shadowMode = ShadowMode.Disable; private ShadowMode shadowMode = ShadowMode.Disable;
@ -115,7 +116,7 @@ public class TechniqueDef implements Savable {
* Creates a new technique definition. * Creates a new technique definition.
* <p> * <p>
* Used internally by the J3M/J3MD loader. * Used internally by the J3M/J3MD loader.
* *
* @param name The name of the technique, should be set to <code>null</code> * @param name The name of the technique, should be set to <code>null</code>
* for default techniques. * for default techniques.
*/ */
@ -135,7 +136,7 @@ public class TechniqueDef implements Savable {
/** /**
* Returns the name of this technique as specified in the J3MD file. * Returns the name of this technique as specified in the J3MD file.
* Default techniques have the name "Default". * Default techniques have the name "Default".
* *
* @return the name of this technique * @return the name of this technique
*/ */
public String getName(){ public String getName(){
@ -153,9 +154,9 @@ public class TechniqueDef implements Savable {
/** /**
* Set the light mode * Set the light mode
* *
* @param lightMode the light mode * @param lightMode the light mode
* *
* @see LightMode * @see LightMode
*/ */
public void setLightMode(LightMode lightMode) { public void setLightMode(LightMode lightMode) {
@ -172,9 +173,9 @@ public class TechniqueDef implements Savable {
/** /**
* Set the shadow mode. * Set the shadow mode.
* *
* @param shadowMode the shadow mode. * @param shadowMode the shadow mode.
* *
* @see ShadowMode * @see ShadowMode
*/ */
public void setShadowMode(ShadowMode shadowMode) { public void setShadowMode(ShadowMode shadowMode) {
@ -184,7 +185,7 @@ public class TechniqueDef implements Savable {
/** /**
* Returns the render state that this technique is using * Returns the render state that this technique is using
* @return the render state that this technique is using * @return the render state that this technique is using
* @see #setRenderState(com.jme3.material.RenderState) * @see #setRenderState(com.jme3.material.RenderState)
*/ */
public RenderState getRenderState() { public RenderState getRenderState() {
return renderState; return renderState;
@ -192,15 +193,37 @@ public class TechniqueDef implements Savable {
/** /**
* Sets the render state that this technique is using. * Sets the render state that this technique is using.
* *
* @param renderState the render state that this technique is using. * @param renderState the render state that this technique is using.
* *
* @see RenderState * @see RenderState
*/ */
public void setRenderState(RenderState renderState) { public void setRenderState(RenderState renderState) {
this.renderState = renderState; this.renderState = renderState;
} }
/**
* Sets if this technique should not be used to render.
*
* @param noRender not render or render ?
*
* @see NoRender
*/
public void setNoRender(boolean noRender) {
this.noRender = noRender;
}
/**
* Returns true if this technique should not be used to render.
* (eg. to not render a material with default technique)
*
* @return true if this technique should not be rendered, false otherwise.
*
*/
public boolean isNoRender(){
return noRender;
}
/** /**
* @deprecated jME3 always requires shaders now * @deprecated jME3 always requires shaders now
*/ */
@ -208,12 +231,12 @@ public class TechniqueDef implements Savable {
public boolean isUsingShaders(){ public boolean isUsingShaders(){
return true; return true;
} }
/** /**
* Returns true if this technique uses Shader Nodes, false otherwise. * Returns true if this technique uses Shader Nodes, false otherwise.
* *
* @return true if this technique uses Shader Nodes, false otherwise. * @return true if this technique uses Shader Nodes, false otherwise.
* *
*/ */
public boolean isUsingShaderNodes(){ public boolean isUsingShaderNodes(){
return usesNodes; return usesNodes;
@ -222,7 +245,7 @@ public class TechniqueDef implements Savable {
/** /**
* Gets the {@link Caps renderer capabilities} that are required * Gets the {@link Caps renderer capabilities} that are required
* by this technique. * by this technique.
* *
* @return the required renderer capabilities * @return the required renderer capabilities
*/ */
public EnumSet<Caps> getRequiredCaps() { public EnumSet<Caps> getRequiredCaps() {
@ -231,7 +254,7 @@ public class TechniqueDef implements Savable {
/** /**
* Sets the shaders that this technique definition will use. * Sets the shaders that this technique definition will use.
* *
* @param vertexShader The name of the vertex shader * @param vertexShader The name of the vertex shader
* @param fragmentShader The name of the fragment shader * @param fragmentShader The name of the fragment shader
* @param vertLanguage The vertex shader language * @param vertLanguage The vertex shader language
@ -242,7 +265,7 @@ public class TechniqueDef implements Savable {
this.shaderNames.put(Shader.ShaderType.Vertex, vertexShader); this.shaderNames.put(Shader.ShaderType.Vertex, vertexShader);
this.shaderLanguages.put(Shader.ShaderType.Fragment, fragLanguage); this.shaderLanguages.put(Shader.ShaderType.Fragment, fragLanguage);
this.shaderNames.put(Shader.ShaderType.Fragment, fragmentShader); this.shaderNames.put(Shader.ShaderType.Fragment, fragmentShader);
requiredCaps.clear(); requiredCaps.clear();
Caps vertCap = Caps.valueOf(vertLanguage); Caps vertCap = Caps.valueOf(vertLanguage);
requiredCaps.add(vertCap); requiredCaps.add(vertCap);
@ -259,17 +282,17 @@ public class TechniqueDef implements Savable {
*/ */
public void setShaderFile(EnumMap<Shader.ShaderType, String> shaderNames, EnumMap<Shader.ShaderType, String> shaderLanguages) { public void setShaderFile(EnumMap<Shader.ShaderType, String> shaderNames, EnumMap<Shader.ShaderType, String> shaderLanguages) {
requiredCaps.clear(); requiredCaps.clear();
for (Shader.ShaderType shaderType : shaderNames.keySet()) { for (Shader.ShaderType shaderType : shaderNames.keySet()) {
String language = shaderLanguages.get(shaderType); String language = shaderLanguages.get(shaderType);
String shaderFile = shaderNames.get(shaderType); String shaderFile = shaderNames.get(shaderType);
this.shaderLanguages.put(shaderType, language); this.shaderLanguages.put(shaderType, language);
this.shaderNames.put(shaderType, shaderFile); this.shaderNames.put(shaderType, shaderFile);
Caps vertCap = Caps.valueOf(language); Caps vertCap = Caps.valueOf(language);
requiredCaps.add(vertCap); requiredCaps.add(vertCap);
if (shaderType.equals(Shader.ShaderType.Geometry)) { if (shaderType.equals(Shader.ShaderType.Geometry)) {
requiredCaps.add(Caps.GeometryShader); requiredCaps.add(Caps.GeometryShader);
} else if (shaderType.equals(Shader.ShaderType.TessellationControl)) { } else if (shaderType.equals(Shader.ShaderType.TessellationControl)) {
@ -280,11 +303,11 @@ public class TechniqueDef implements Savable {
/** /**
* Returns the define name which the given material parameter influences. * Returns the define name which the given material parameter influences.
* *
* @param paramName The parameter name to look up * @param paramName The parameter name to look up
* @return The define name * @return The define name
* *
* @see #addShaderParamDefine(java.lang.String, java.lang.String) * @see #addShaderParamDefine(java.lang.String, java.lang.String)
*/ */
public String getShaderParamDefine(String paramName){ public String getShaderParamDefine(String paramName){
if (defineParams == null) { if (defineParams == null) {
@ -297,11 +320,11 @@ public class TechniqueDef implements Savable {
* Adds a define linked to a material parameter. * Adds a define linked to a material parameter.
* <p> * <p>
* Any time the material parameter on the parent material is altered, * Any time the material parameter on the parent material is altered,
* the appropriate define on the technique will be modified as well. * the appropriate define on the technique will be modified as well.
* See the method * See the method
* {@link DefineList#set(java.lang.String, com.jme3.shader.VarType, java.lang.Object) } * {@link DefineList#set(java.lang.String, com.jme3.shader.VarType, java.lang.Object) }
* on the exact details of how the material parameter changes the define. * on the exact details of how the material parameter changes the define.
* *
* @param paramName The name of the material parameter to link to. * @param paramName The name of the material parameter to link to.
* @param defineName The name of the define parameter, e.g. USE_LIGHTING * @param defineName The name of the define parameter, e.g. USE_LIGHTING
*/ */
@ -314,26 +337,26 @@ public class TechniqueDef implements Savable {
/** /**
* Returns the {@link DefineList} for the preset defines. * Returns the {@link DefineList} for the preset defines.
* *
* @return the {@link DefineList} for the preset defines. * @return the {@link DefineList} for the preset defines.
* *
* @see #addShaderPresetDefine(java.lang.String, com.jme3.shader.VarType, java.lang.Object) * @see #addShaderPresetDefine(java.lang.String, com.jme3.shader.VarType, java.lang.Object)
*/ */
public DefineList getShaderPresetDefines() { public DefineList getShaderPresetDefines() {
return presetDefines; return presetDefines;
} }
/** /**
* Adds a preset define. * Adds a preset define.
* <p> * <p>
* Preset defines do not depend upon any parameters to be activated, * Preset defines do not depend upon any parameters to be activated,
* they are always passed to the shader as long as this technique is used. * they are always passed to the shader as long as this technique is used.
* *
* @param defineName The name of the define parameter, e.g. USE_LIGHTING * @param defineName The name of the define parameter, e.g. USE_LIGHTING
* @param type The type of the define. See * @param type The type of the define. See
* {@link DefineList#set(java.lang.String, com.jme3.shader.VarType, java.lang.Object) } * {@link DefineList#set(java.lang.String, com.jme3.shader.VarType, java.lang.Object) }
* to see why it matters. * to see why it matters.
* *
* @param value The value of the define * @param value The value of the define
*/ */
public void addShaderPresetDefine(String defineName, VarType type, Object value){ public void addShaderPresetDefine(String defineName, VarType type, Object value){
@ -346,18 +369,18 @@ public class TechniqueDef implements Savable {
/** /**
* Returns the name of the fragment shader used by the technique, or null * Returns the name of the fragment shader used by the technique, or null
* if no fragment shader is specified. * if no fragment shader is specified.
* *
* @return the name of the fragment shader to be used. * @return the name of the fragment shader to be used.
*/ */
public String getFragmentShaderName() { public String getFragmentShaderName() {
return shaderNames.get(Shader.ShaderType.Fragment); return shaderNames.get(Shader.ShaderType.Fragment);
} }
/** /**
* Returns the name of the vertex shader used by the technique, or null * Returns the name of the vertex shader used by the technique, or null
* if no vertex shader is specified. * if no vertex shader is specified.
* *
* @return the name of the vertex shader to be used. * @return the name of the vertex shader to be used.
*/ */
public String getVertexShaderName() { public String getVertexShaderName() {
@ -370,7 +393,7 @@ public class TechniqueDef implements Savable {
public String getFragmentShaderLanguage() { public String getFragmentShaderLanguage() {
return shaderLanguages.get(Shader.ShaderType.Fragment); return shaderLanguages.get(Shader.ShaderType.Fragment);
} }
/** /**
* Returns the language of the vertex shader used in this technique. * Returns the language of the vertex shader used in this technique.
*/ */
@ -390,10 +413,10 @@ public class TechniqueDef implements Savable {
public String getShaderProgramName(Shader.ShaderType shaderType){ public String getShaderProgramName(Shader.ShaderType shaderType){
return shaderNames.get(shaderType); return shaderNames.get(shaderType);
} }
/** /**
* Adds a new world parameter by the given name. * Adds a new world parameter by the given name.
* *
* @param name The world parameter to add. * @param name The world parameter to add.
* @return True if the world parameter name was found and added * @return True if the world parameter name was found and added
* to the list of world parameters, false otherwise. * to the list of world parameters, false otherwise.
@ -402,7 +425,7 @@ public class TechniqueDef implements Savable {
if (worldBinds == null){ if (worldBinds == null){
worldBinds = new ArrayList<UniformBinding>(); worldBinds = new ArrayList<UniformBinding>();
} }
try { try {
worldBinds.add( UniformBinding.valueOf(name) ); worldBinds.add( UniformBinding.valueOf(name) );
return true; return true;
@ -418,11 +441,11 @@ public class TechniqueDef implements Savable {
public void setForcedRenderState(RenderState forcedRenderState) { public void setForcedRenderState(RenderState forcedRenderState) {
this.forcedRenderState = forcedRenderState; this.forcedRenderState = forcedRenderState;
} }
/** /**
* Returns a list of world parameters that are used by this * Returns a list of world parameters that are used by this
* technique definition. * technique definition.
* *
* @return The list of world parameters * @return The list of world parameters
*/ */
public List<UniformBinding> getWorldBindings() { public List<UniformBinding> getWorldBindings() {
@ -448,10 +471,11 @@ public class TechniqueDef implements Savable {
oc.write(lightMode, "lightMode", LightMode.Disable); oc.write(lightMode, "lightMode", LightMode.Disable);
oc.write(shadowMode, "shadowMode", ShadowMode.Disable); oc.write(shadowMode, "shadowMode", ShadowMode.Disable);
oc.write(renderState, "renderState", null); oc.write(renderState, "renderState", null);
oc.write(noRender, "noRender", false);
oc.write(usesNodes, "usesNodes", false); oc.write(usesNodes, "usesNodes", false);
oc.writeSavableArrayList((ArrayList)shaderNodes,"shaderNodes", null); oc.writeSavableArrayList((ArrayList)shaderNodes,"shaderNodes", null);
oc.write(shaderGenerationInfo, "shaderGenerationInfo", null); oc.write(shaderGenerationInfo, "shaderGenerationInfo", null);
// TODO: Finish this when Map<String, String> export is available // TODO: Finish this when Map<String, String> export is available
// oc.write(defineParams, "defineParams", null); // oc.write(defineParams, "defineParams", null);
// TODO: Finish this when List<Enum> export is available // TODO: Finish this when List<Enum> export is available
@ -470,7 +494,8 @@ public class TechniqueDef implements Savable {
lightMode = ic.readEnum("lightMode", LightMode.class, LightMode.Disable); lightMode = ic.readEnum("lightMode", LightMode.class, LightMode.Disable);
shadowMode = ic.readEnum("shadowMode", ShadowMode.class, ShadowMode.Disable); shadowMode = ic.readEnum("shadowMode", ShadowMode.class, ShadowMode.Disable);
renderState = (RenderState) ic.readSavable("renderState", null); renderState = (RenderState) ic.readSavable("renderState", null);
noRender = ic.readBoolean("noRender", false);
if (ic.getSavableVersion(TechniqueDef.class) == 0) { if (ic.getSavableVersion(TechniqueDef.class) == 0) {
// Old version // Old version
shaderLanguages.put(Shader.ShaderType.Vertex,ic.readString("shaderLang", null)); shaderLanguages.put(Shader.ShaderType.Vertex,ic.readString("shaderLang", null));
@ -483,7 +508,7 @@ public class TechniqueDef implements Savable {
shaderLanguages.put(Shader.ShaderType.TessellationControl,ic.readString("tsctrlLanguage", null)); shaderLanguages.put(Shader.ShaderType.TessellationControl,ic.readString("tsctrlLanguage", null));
shaderLanguages.put(Shader.ShaderType.TessellationEvaluation,ic.readString("tsevalLanguage", null)); shaderLanguages.put(Shader.ShaderType.TessellationEvaluation,ic.readString("tsevalLanguage", null));
} }
usesNodes = ic.readBoolean("usesNodes", false); usesNodes = ic.readBoolean("usesNodes", false);
shaderNodes = ic.readSavableArrayList("shaderNodes", null); shaderNodes = ic.readSavableArrayList("shaderNodes", null);
shaderGenerationInfo = (ShaderGenerationInfo) ic.readSavable("shaderGenerationInfo", null); shaderGenerationInfo = (ShaderGenerationInfo) ic.readSavable("shaderGenerationInfo", null);
@ -525,6 +550,6 @@ public class TechniqueDef implements Savable {
//todo: make toString return something usefull //todo: make toString return something usefull
@Override @Override
public String toString() { public String toString() {
return "TechniqueDef{" + "requiredCaps=" + requiredCaps + ", name=" + name /*+ ", vertName=" + vertName + ", fragName=" + fragName + ", vertLanguage=" + vertLanguage + ", fragLanguage=" + fragLanguage */+ ", presetDefines=" + presetDefines + ", usesNodes=" + usesNodes + ", shaderNodes=" + shaderNodes + ", shaderGenerationInfo=" + shaderGenerationInfo + ", renderState=" + renderState + ", forcedRenderState=" + forcedRenderState + ", lightMode=" + lightMode + ", shadowMode=" + shadowMode + ", defineParams=" + defineParams + ", worldBinds=" + worldBinds + '}'; return "TechniqueDef{" + "requiredCaps=" + requiredCaps + ", name=" + name /*+ ", vertName=" + vertName + ", fragName=" + fragName + ", vertLanguage=" + vertLanguage + ", fragLanguage=" + fragLanguage */+ ", presetDefines=" + presetDefines + ", usesNodes=" + usesNodes + ", shaderNodes=" + shaderNodes + ", shaderGenerationInfo=" + shaderGenerationInfo + ", renderState=" + renderState + ", forcedRenderState=" + forcedRenderState + ", lightMode=" + lightMode + ", shadowMode=" + shadowMode + ", defineParams=" + defineParams + ", worldBinds=" + worldBinds + ", noRender=" + noRender + '}';
} }
} }

@ -63,7 +63,7 @@ public class J3MLoader implements AssetLoader {
// private ErrorLogger errors; // private ErrorLogger errors;
private ShaderNodeLoaderDelegate nodesLoaderDelegate; private ShaderNodeLoaderDelegate nodesLoaderDelegate;
boolean isUseNodes = false; boolean isUseNodes = false;
private AssetManager assetManager; private AssetManager assetManager;
private AssetKey key; private AssetKey key;
@ -168,7 +168,7 @@ public class J3MLoader implements AssetLoader {
if (tex != null){ if (tex != null){
if (repeat){ if (repeat){
tex.setWrap(WrapMode.Repeat); tex.setWrap(WrapMode.Repeat);
} }
}else{ }else{
tex = new Texture2D(PlaceholderAssets.getPlaceholderImage(assetManager)); tex = new Texture2D(PlaceholderAssets.getPlaceholderImage(assetManager));
if (repeat){ if (repeat){
@ -176,7 +176,7 @@ public class J3MLoader implements AssetLoader {
} }
tex.setKey(texKey); tex.setKey(texKey);
tex.setName(texKey.getName()); tex.setName(texKey.getName());
} }
return tex; return tex;
}else{ }else{
String[] split = value.trim().split(whitespacePattern); String[] split = value.trim().split(whitespacePattern);
@ -222,15 +222,15 @@ public class J3MLoader implements AssetLoader {
} }
} }
} }
// <TYPE> <NAME> [ "(" <FFBINDING> ")" ] [-LINEAR] [ ":" <DEFAULTVAL> ] // <TYPE> <NAME> [ "(" <FFBINDING> ")" ] [-LINEAR] [ ":" <DEFAULTVAL> ]
private void readParam(String statement) throws IOException{ private void readParam(String statement) throws IOException{
String name; String name;
String defaultVal = null; String defaultVal = null;
ColorSpace colorSpace = null; ColorSpace colorSpace = null;
String[] split = statement.split(":"); String[] split = statement.split(":");
// Parse default val // Parse default val
if (split.length == 1){ if (split.length == 1){
// Doesn't contain default value // Doesn't contain default value
@ -239,14 +239,14 @@ public class J3MLoader implements AssetLoader {
throw new IOException("Parameter statement syntax incorrect"); throw new IOException("Parameter statement syntax incorrect");
} }
statement = split[0].trim(); statement = split[0].trim();
defaultVal = split[1].trim(); defaultVal = split[1].trim();
} }
if (statement.endsWith("-LINEAR")) { if (statement.endsWith("-LINEAR")) {
colorSpace = ColorSpace.Linear; colorSpace = ColorSpace.Linear;
statement = statement.substring(0, statement.length() - "-LINEAR".length()); statement = statement.substring(0, statement.length() - "-LINEAR".length());
} }
// Parse ffbinding // Parse ffbinding
int startParen = statement.indexOf("("); int startParen = statement.indexOf("(");
if (startParen != -1){ if (startParen != -1){
@ -256,32 +256,32 @@ public class J3MLoader implements AssetLoader {
// don't care about bindingStr // don't care about bindingStr
statement = statement.substring(0, startParen); statement = statement.substring(0, startParen);
} }
// Parse type + name // Parse type + name
split = statement.split(whitespacePattern); split = statement.split(whitespacePattern);
if (split.length != 2){ if (split.length != 2){
throw new IOException("Parameter statement syntax incorrect"); throw new IOException("Parameter statement syntax incorrect");
} }
VarType type; VarType type;
if (split[0].equals("Color")){ if (split[0].equals("Color")){
type = VarType.Vector4; type = VarType.Vector4;
}else{ }else{
type = VarType.valueOf(split[0]); type = VarType.valueOf(split[0]);
} }
name = split[1]; name = split[1];
Object defaultValObj = null; Object defaultValObj = null;
if (defaultVal != null){ if (defaultVal != null){
defaultValObj = readValue(type, defaultVal); defaultValObj = readValue(type, defaultVal);
} }
if(type.isTextureType()){ if(type.isTextureType()){
materialDef.addMaterialParamTexture(type, name, colorSpace); materialDef.addMaterialParamTexture(type, name, colorSpace);
}else{ }else{
materialDef.addMaterialParam(type, name, defaultValObj); materialDef.addMaterialParam(type, name, defaultValObj);
} }
} }
private void readValueParam(String statement) throws IOException{ private void readValueParam(String statement) throws IOException{
@ -376,7 +376,7 @@ public class J3MLoader implements AssetLoader {
technique.setRenderState(renderState); technique.setRenderState(renderState);
renderState = null; renderState = null;
} }
private void readForcedRenderState(List<Statement> renderStates) throws IOException{ private void readForcedRenderState(List<Statement> renderStates) throws IOException{
renderState = new RenderState(); renderState = new RenderState();
for (Statement statement : renderStates){ for (Statement statement : renderStates){
@ -385,7 +385,7 @@ public class J3MLoader implements AssetLoader {
technique.setForcedRenderState(renderState); technique.setForcedRenderState(renderState);
renderState = null; renderState = null;
} }
// <DEFINENAME> [ ":" <PARAMNAME> ] // <DEFINENAME> [ ":" <PARAMNAME> ]
private void readDefine(String statement) throws IOException{ private void readDefine(String statement) throws IOException{
String[] split = statement.split(":"); String[] split = statement.split(":");
@ -405,9 +405,9 @@ public class J3MLoader implements AssetLoader {
} }
} }
private void readTechniqueStatement(Statement statement) throws IOException{ private void readTechniqueStatement(Statement statement) throws IOException{
String[] split = statement.getLine().split("[ \\{]"); String[] split = statement.getLine().split("[ \\{]");
if (split[0].equals("VertexShader") || if (split[0].equals("VertexShader") ||
split[0].equals("FragmentShader") || split[0].equals("FragmentShader") ||
split[0].equals("GeometryShader") || split[0].equals("GeometryShader") ||
@ -420,12 +420,12 @@ public class J3MLoader implements AssetLoader {
readShadowMode(statement.getLine()); readShadowMode(statement.getLine());
}else if (split[0].equals("WorldParameters")){ }else if (split[0].equals("WorldParameters")){
readWorldParams(statement.getContents()); readWorldParams(statement.getContents());
}else if (split[0].equals("RenderState")){ }else if (split[0].equals("RenderState")){
readRenderState(statement.getContents()); readRenderState(statement.getContents());
}else if (split[0].equals("ForcedRenderState")){ }else if (split[0].equals("ForcedRenderState")){
readForcedRenderState(statement.getContents()); readForcedRenderState(statement.getContents());
}else if (split[0].equals("Defines")){ }else if (split[0].equals("Defines")){
readDefines(statement.getContents()); readDefines(statement.getContents());
} else if (split[0].equals("ShaderNodesDefinitions")) { } else if (split[0].equals("ShaderNodesDefinitions")) {
initNodesLoader(); initNodesLoader();
if (isUseNodes) { if (isUseNodes) {
@ -438,14 +438,16 @@ public class J3MLoader implements AssetLoader {
} }
} else if (split[0].equals("FragmentShaderNodes")) { } else if (split[0].equals("FragmentShaderNodes")) {
initNodesLoader(); initNodesLoader();
if (isUseNodes) { if (isUseNodes) {
nodesLoaderDelegate.readFragmentShaderNodes(statement.getContents()); nodesLoaderDelegate.readFragmentShaderNodes(statement.getContents());
} }
} else if (split[0].equals("NoRender")) {
technique.setNoRender(true);
} else { } else {
throw new MatParseException(null, split[0], statement); throw new MatParseException(null, split[0], statement);
} }
} }
private void readTransparentStatement(String statement) throws IOException{ private void readTransparentStatement(String statement) throws IOException{
String[] split = statement.split(whitespacePattern); String[] split = statement.split(whitespacePattern);
if (split.length != 2){ if (split.length != 2){
@ -465,11 +467,11 @@ public class J3MLoader implements AssetLoader {
} else { } else {
throw new IOException("Technique statement syntax incorrect"); throw new IOException("Technique statement syntax incorrect");
} }
for (Statement statement : techStat.getContents()){ for (Statement statement : techStat.getContents()){
readTechniqueStatement(statement); readTechniqueStatement(statement);
} }
if(isUseNodes){ if(isUseNodes){
nodesLoaderDelegate.computeConditions(); nodesLoaderDelegate.computeConditions();
//used for caching later, the shader here is not a file. //used for caching later, the shader here is not a file.
@ -479,14 +481,14 @@ public class J3MLoader implements AssetLoader {
if (shaderName.containsKey(Shader.ShaderType.Vertex) && shaderName.containsKey(Shader.ShaderType.Fragment)) { if (shaderName.containsKey(Shader.ShaderType.Vertex) && shaderName.containsKey(Shader.ShaderType.Fragment)) {
technique.setShaderFile(shaderName, shaderLanguage); technique.setShaderFile(shaderName, shaderLanguage);
} }
materialDef.addTechniqueDef(technique); materialDef.addTechniqueDef(technique);
technique = null; technique = null;
shaderLanguage.clear(); shaderLanguage.clear();
shaderName.clear(); shaderName.clear();
} }
private void loadFromRoot(List<Statement> roots) throws IOException{ private void loadFromRoot(List<Statement> roots) throws IOException{
if (roots.size() == 2){ if (roots.size() == 2){
Statement exception = roots.get(0); Statement exception = roots.get(0);
String line = exception.getLine(); String line = exception.getLine();
@ -498,7 +500,7 @@ public class J3MLoader implements AssetLoader {
}else if (roots.size() != 1){ }else if (roots.size() != 1){
throw new IOException("Too many roots in J3M/J3MD file"); throw new IOException("Too many roots in J3M/J3MD file");
} }
boolean extending = false; boolean extending = false;
Statement materialStat = roots.get(0); Statement materialStat = roots.get(0);
String materialName = materialStat.getLine(); String materialName = materialStat.getLine();
@ -511,16 +513,16 @@ public class J3MLoader implements AssetLoader {
}else{ }else{
throw new IOException("Specified file is not a Material file"); throw new IOException("Specified file is not a Material file");
} }
String[] split = materialName.split(":", 2); String[] split = materialName.split(":", 2);
if (materialName.equals("")){ if (materialName.equals("")){
throw new MatParseException("Material name cannot be empty", materialStat); throw new MatParseException("Material name cannot be empty", materialStat);
} }
if (split.length == 2){ if (split.length == 2){
if (!extending){ if (!extending){
throw new MatParseException("Must use 'Material' when extending.", materialStat); throw new MatParseException("Must use 'Material' when extending.", materialStat);
} }
String extendedMat = split[1].trim(); String extendedMat = split[1].trim();
@ -535,15 +537,15 @@ public class J3MLoader implements AssetLoader {
// material.setAssetName(fileName); // material.setAssetName(fileName);
}else if (split.length == 1){ }else if (split.length == 1){
if (extending){ if (extending){
throw new MatParseException("Expected ':', got '{'", materialStat); throw new MatParseException("Expected ':', got '{'", materialStat);
} }
materialDef = new MaterialDef(assetManager, materialName); materialDef = new MaterialDef(assetManager, materialName);
// NOTE: pass file name for defs so they can be loaded later // NOTE: pass file name for defs so they can be loaded later
materialDef.setAssetName(key.getName()); materialDef.setAssetName(key.getName());
}else{ }else{
throw new MatParseException("Cannot use colon in material name/path", materialStat); throw new MatParseException("Cannot use colon in material name/path", materialStat);
} }
for (Statement statement : materialStat.getContents()){ for (Statement statement : materialStat.getContents()){
split = statement.getLine().split("[ \\{]"); split = statement.getLine().split("[ \\{]");
String statType = split[0]; String statType = split[0];
@ -561,16 +563,16 @@ public class J3MLoader implements AssetLoader {
}else if (statType.equals("MaterialParameters")){ }else if (statType.equals("MaterialParameters")){
readMaterialParams(statement.getContents()); readMaterialParams(statement.getContents());
}else{ }else{
throw new MatParseException("Expected material statement, got '"+statType+"'", statement); throw new MatParseException("Expected material statement, got '"+statType+"'", statement);
} }
} }
} }
} }
public Object load(AssetInfo info) throws IOException { public Object load(AssetInfo info) throws IOException {
this.assetManager = info.getManager(); this.assetManager = info.getManager();
InputStream in = info.openStream(); InputStream in = info.openStream();
try { try {
key = info.getKey(); key = info.getKey();
if (key.getExtension().equals("j3m") && !(key instanceof MaterialKey)) { if (key.getExtension().equals("j3m") && !(key instanceof MaterialKey)) {
@ -584,7 +586,7 @@ public class J3MLoader implements AssetLoader {
in.close(); in.close();
} }
} }
if (material != null){ if (material != null){
// material implementation // material implementation
return material; return material;
@ -593,7 +595,7 @@ public class J3MLoader implements AssetLoader {
return materialDef; return materialDef;
} }
} }
public MaterialDef loadMaterialDef(List<Statement> roots, AssetManager manager, AssetKey key) throws IOException { public MaterialDef loadMaterialDef(List<Statement> roots, AssetManager manager, AssetKey key) throws IOException {
this.key = key; this.key = key;
this.assetManager = manager; this.assetManager = manager;
@ -615,6 +617,6 @@ public class J3MLoader implements AssetLoader {
nodesLoaderDelegate.setAssetManager(assetManager); nodesLoaderDelegate.setAssetManager(assetManager);
} }
} }
} }
} }

Loading…
Cancel
Save