Techniques are now weighted and sorted depending on their LightMode and GLSL version
This commit is contained in:
parent
c713a06146
commit
cb04548fd5
@ -704,15 +704,14 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
|
||||
* @throws UnsupportedOperationException If no candidate technique supports
|
||||
* the system capabilities.
|
||||
*/
|
||||
public void selectTechnique(String name, RenderManager renderManager) {
|
||||
public void selectTechnique(String name, final RenderManager renderManager) {
|
||||
// check if already created
|
||||
Technique tech = techniques.get(name);
|
||||
// When choosing technique, we choose one that
|
||||
// supports all the caps.
|
||||
if (tech == null) {
|
||||
EnumSet<Caps> rendererCaps = renderManager.getRenderer().getCaps();
|
||||
List<TechniqueDef> techDefs = def.getTechniqueDefs(name);
|
||||
|
||||
List<TechniqueDef> techDefs = def.getSortedTechniqueDefs(name, renderManager);
|
||||
if (techDefs == null || techDefs.isEmpty()) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("The requested technique %s is not available on material %s", name, def.getName()));
|
||||
@ -724,11 +723,8 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
|
||||
// use the first one that supports all the caps
|
||||
tech = new Technique(this, techDef);
|
||||
techniques.put(name, tech);
|
||||
if (tech.getDef().getLightMode() == renderManager.getPreferredLightMode()
|
||||
|| tech.getDef().getLightMode() == LightMode.Disable) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
lastTech = techDef;
|
||||
}
|
||||
if (tech == null) {
|
||||
|
@ -32,11 +32,10 @@
|
||||
package com.jme3.material;
|
||||
|
||||
import com.jme3.asset.AssetManager;
|
||||
import com.jme3.export.*;
|
||||
import com.jme3.renderer.RenderManager;
|
||||
import com.jme3.shader.VarType;
|
||||
import com.jme3.texture.image.ColorSpace;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
@ -56,6 +55,7 @@ public class MaterialDef{
|
||||
|
||||
private Map<String, List<TechniqueDef>> techniques;
|
||||
private Map<String, MatParam> matParams;
|
||||
private TechDefComparator comparator = new TechDefComparator();
|
||||
|
||||
/**
|
||||
* Serialization only. Do not use.
|
||||
@ -188,6 +188,17 @@ public class MaterialDef{
|
||||
return techniques.get(name);
|
||||
}
|
||||
|
||||
public List<TechniqueDef> getSortedTechniqueDefs(String name, RenderManager rm) {
|
||||
List<TechniqueDef> techDefs = getTechniqueDefs(name);
|
||||
if (techDefs == null) {
|
||||
return null;
|
||||
}
|
||||
//Sorting the techdef depending on their weight (depending on their glsl version) and on the preferred light mode)
|
||||
comparator.rm = rm;
|
||||
Collections.sort(techDefs, comparator);
|
||||
return techDefs;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the list of all the technique definitions names.
|
||||
@ -196,4 +207,17 @@ public class MaterialDef{
|
||||
return techniques.keySet();
|
||||
}
|
||||
|
||||
public static class TechDefComparator implements Comparator<TechniqueDef> {
|
||||
|
||||
RenderManager rm;
|
||||
|
||||
@Override
|
||||
public int compare(TechniqueDef o1, TechniqueDef o2) {
|
||||
float o1Weight = o1.getWeight() + (o1.getLightMode() == rm.getPreferredLightMode() ? 10f : 0);
|
||||
float o2Weight = o2.getWeight() + (o2.getLightMode() == rm.getPreferredLightMode() ? 10f : 0);
|
||||
return (int) Math.signum(o2Weight - o1Weight);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -31,9 +31,9 @@
|
||||
*/
|
||||
package com.jme3.material;
|
||||
|
||||
import com.jme3.material.logic.TechniqueDefLogic;
|
||||
import com.jme3.asset.AssetManager;
|
||||
import com.jme3.export.*;
|
||||
import com.jme3.material.logic.TechniqueDefLogic;
|
||||
import com.jme3.renderer.Caps;
|
||||
import com.jme3.shader.*;
|
||||
import com.jme3.shader.Shader.ShaderType;
|
||||
@ -161,6 +161,9 @@ public class TechniqueDef implements Savable {
|
||||
//The space in which the light should be transposed before sending to the shader.
|
||||
private LightSpace lightSpace;
|
||||
|
||||
//used to find the best fit technique
|
||||
private float weight = 0;
|
||||
|
||||
/**
|
||||
* Creates a new technique definition.
|
||||
* <p>
|
||||
@ -341,6 +344,8 @@ public class TechniqueDef implements Savable {
|
||||
requiredCaps.add(vertCap);
|
||||
Caps fragCap = Caps.valueOf(fragLanguage);
|
||||
requiredCaps.add(fragCap);
|
||||
|
||||
weight = Math.max(vertCap.ordinal(), fragCap.ordinal());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -534,6 +539,7 @@ public class TechniqueDef implements Savable {
|
||||
public void setShaderFile(EnumMap<Shader.ShaderType, String> shaderNames, EnumMap<Shader.ShaderType, String> shaderLanguages) {
|
||||
requiredCaps.clear();
|
||||
|
||||
int maxCap = 0;
|
||||
for (Shader.ShaderType shaderType : shaderNames.keySet()) {
|
||||
String language = shaderLanguages.get(shaderType);
|
||||
String shaderFile = shaderNames.get(shaderType);
|
||||
@ -541,8 +547,9 @@ public class TechniqueDef implements Savable {
|
||||
this.shaderLanguages.put(shaderType, language);
|
||||
this.shaderNames.put(shaderType, shaderFile);
|
||||
|
||||
Caps vertCap = Caps.valueOf(language);
|
||||
requiredCaps.add(vertCap);
|
||||
Caps cap = Caps.valueOf(language);
|
||||
requiredCaps.add(cap);
|
||||
maxCap = Math.max(maxCap, cap.ordinal());
|
||||
|
||||
if (shaderType.equals(Shader.ShaderType.Geometry)) {
|
||||
requiredCaps.add(Caps.GeometryShader);
|
||||
@ -550,6 +557,7 @@ public class TechniqueDef implements Savable {
|
||||
requiredCaps.add(Caps.TesselationShader);
|
||||
}
|
||||
}
|
||||
weight = maxCap;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -600,6 +608,15 @@ public class TechniqueDef implements Savable {
|
||||
return shaderNames.get(shaderType);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the weight of the technique def
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public float getWeight() {
|
||||
return weight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new world parameter by the given name.
|
||||
*
|
||||
|
@ -0,0 +1,167 @@
|
||||
package com.jme3.material;
|
||||
|
||||
import com.jme3.renderer.RenderManager;
|
||||
import com.jme3.shader.Shader;
|
||||
import com.jme3.system.NullRenderer;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Created by Nehon on 14/01/2017.
|
||||
*/
|
||||
public class TestTechniqueDefOrdering {
|
||||
|
||||
@Test
|
||||
public void order() {
|
||||
|
||||
RenderManager rm = new RenderManager(new NullRenderer());
|
||||
rm.setPreferredLightMode(TechniqueDef.LightMode.MultiPass);
|
||||
MaterialDef.TechDefComparator comp = new MaterialDef.TechDefComparator();
|
||||
comp.rm = rm;
|
||||
|
||||
|
||||
//random case
|
||||
List<TechniqueDef> defs = new ArrayList<>();
|
||||
TechniqueDef def = new TechniqueDef("tech", 1);
|
||||
def.setShaderFile("", "", "GLSL100", "GLSL100");
|
||||
def.setLightMode(TechniqueDef.LightMode.SinglePass);
|
||||
defs.add(def);
|
||||
def = new TechniqueDef("tech2", 1);
|
||||
def.setShaderFile("", "", "GLSL150", "GLSL150");
|
||||
def.setLightMode(TechniqueDef.LightMode.MultiPass);
|
||||
defs.add(def);
|
||||
def = new TechniqueDef("tech3", 1);
|
||||
def.setShaderFile("", "", "GLSL110", "GLSL110");
|
||||
defs.add(def);
|
||||
def = new TechniqueDef("tech4", 1);
|
||||
def.setShaderFile("", "", "GLSL120", "GLSL120");
|
||||
defs.add(def);
|
||||
def = new TechniqueDef("tech5", 1);
|
||||
def.setShaderFile("", "", "GLSL130", "GLSL130");
|
||||
defs.add(def);
|
||||
|
||||
Collections.sort(defs, comp);
|
||||
|
||||
assertEquals(defs.get(0).getName(), "tech2");
|
||||
assertEquals(defs.get(1).getName(), "tech5");
|
||||
assertEquals(defs.get(2).getName(), "tech4");
|
||||
assertEquals(defs.get(3).getName(), "tech3");
|
||||
assertEquals(defs.get(4).getName(), "tech");
|
||||
|
||||
|
||||
//Test the unshaded material case: 2 disabled : 150 and 100
|
||||
defs = new ArrayList<>();
|
||||
def = new TechniqueDef("unshaded", 1);
|
||||
def.setShaderFile("", "", "GLSL100", "GLSL100");
|
||||
defs.add(def);
|
||||
def = new TechniqueDef("unshaded2", 1);
|
||||
def.setShaderFile("", "", "GLSL150", "GLSL150");
|
||||
defs.add(def);
|
||||
Collections.sort(defs, comp);
|
||||
|
||||
assertEquals(defs.get(0).getName(), "unshaded2");
|
||||
assertEquals(defs.get(1).getName(), "unshaded");
|
||||
|
||||
//Test the lighting material case: 2 singlepass : 150 and 100, 2 multipass : 150 and 100
|
||||
defs = new ArrayList<>();
|
||||
def = new TechniqueDef("lighting1", 1);
|
||||
def.setShaderFile("", "", "GLSL100", "GLSL100");
|
||||
def.setLightMode(TechniqueDef.LightMode.MultiPass);
|
||||
defs.add(def);
|
||||
def = new TechniqueDef("lighting2", 1);
|
||||
def.setShaderFile("", "", "GLSL150", "GLSL150");
|
||||
def.setLightMode(TechniqueDef.LightMode.MultiPass);
|
||||
defs.add(def);
|
||||
def = new TechniqueDef("lighting3", 1);
|
||||
def.setShaderFile("", "", "GLSL100", "GLSL100");
|
||||
def.setLightMode(TechniqueDef.LightMode.SinglePass);
|
||||
defs.add(def);
|
||||
def = new TechniqueDef("lighting4", 1);
|
||||
def.setShaderFile("", "", "GLSL150", "GLSL150");
|
||||
def.setLightMode(TechniqueDef.LightMode.SinglePass);
|
||||
defs.add(def);
|
||||
Collections.sort(defs, comp);
|
||||
|
||||
assertEquals(defs.get(0).getName(), "lighting2");
|
||||
assertEquals(defs.get(1).getName(), "lighting1");
|
||||
assertEquals(defs.get(2).getName(), "lighting4");
|
||||
assertEquals(defs.get(3).getName(), "lighting3");
|
||||
|
||||
//switching preferred lighting mode
|
||||
rm.setPreferredLightMode(TechniqueDef.LightMode.SinglePass);
|
||||
Collections.sort(defs, comp);
|
||||
|
||||
assertEquals(defs.get(0).getName(), "lighting4");
|
||||
assertEquals(defs.get(1).getName(), "lighting3");
|
||||
assertEquals(defs.get(2).getName(), "lighting2");
|
||||
assertEquals(defs.get(3).getName(), "lighting1");
|
||||
|
||||
|
||||
//test setting source through the enumMaps method with random cases
|
||||
rm.setPreferredLightMode(TechniqueDef.LightMode.MultiPass);
|
||||
defs = new ArrayList<>();
|
||||
def = new TechniqueDef("lighting1", 1);
|
||||
EnumMap<Shader.ShaderType, String> em = new EnumMap<>(Shader.ShaderType.class);
|
||||
em.put(Shader.ShaderType.Vertex, "");
|
||||
em.put(Shader.ShaderType.Fragment, "");
|
||||
em.put(Shader.ShaderType.Geometry, "");
|
||||
EnumMap<Shader.ShaderType, String> l = new EnumMap<>(Shader.ShaderType.class);
|
||||
l.put(Shader.ShaderType.Vertex, "GLSL100");
|
||||
l.put(Shader.ShaderType.Fragment, "GLSL100");
|
||||
l.put(Shader.ShaderType.Geometry, "GLSL100");
|
||||
def.setShaderFile(em, l);
|
||||
def.setLightMode(TechniqueDef.LightMode.SinglePass);
|
||||
defs.add(def);
|
||||
|
||||
def = new TechniqueDef("lighting2", 1);
|
||||
em = new EnumMap<>(Shader.ShaderType.class);
|
||||
em.put(Shader.ShaderType.Vertex, "");
|
||||
em.put(Shader.ShaderType.Fragment, "");
|
||||
em.put(Shader.ShaderType.Geometry, "");
|
||||
l = new EnumMap<>(Shader.ShaderType.class);
|
||||
l.put(Shader.ShaderType.Vertex, "GLSL100");
|
||||
l.put(Shader.ShaderType.Fragment, "GLSL100");
|
||||
l.put(Shader.ShaderType.Geometry, "GLSL100");
|
||||
def.setShaderFile(em, l);
|
||||
def.setLightMode(TechniqueDef.LightMode.MultiPass);
|
||||
defs.add(def);
|
||||
|
||||
def = new TechniqueDef("lighting3", 1);
|
||||
em = new EnumMap<>(Shader.ShaderType.class);
|
||||
em.put(Shader.ShaderType.Vertex, "");
|
||||
em.put(Shader.ShaderType.Fragment, "");
|
||||
em.put(Shader.ShaderType.Geometry, "");
|
||||
l = new EnumMap<>(Shader.ShaderType.class);
|
||||
l.put(Shader.ShaderType.Vertex, "GLSL150");
|
||||
l.put(Shader.ShaderType.Fragment, "GLSL150");
|
||||
l.put(Shader.ShaderType.Geometry, "GLSL150");
|
||||
def.setShaderFile(em, l);
|
||||
def.setLightMode(TechniqueDef.LightMode.MultiPass);
|
||||
defs.add(def);
|
||||
|
||||
def = new TechniqueDef("lighting4", 1);
|
||||
em = new EnumMap<>(Shader.ShaderType.class);
|
||||
em.put(Shader.ShaderType.Vertex, "");
|
||||
em.put(Shader.ShaderType.Fragment, "");
|
||||
em.put(Shader.ShaderType.Geometry, "");
|
||||
l = new EnumMap<>(Shader.ShaderType.class);
|
||||
l.put(Shader.ShaderType.Vertex, "GLSL130");
|
||||
l.put(Shader.ShaderType.Fragment, "GLSL130");
|
||||
l.put(Shader.ShaderType.Geometry, "GLSL110");
|
||||
def.setShaderFile(em, l);
|
||||
def.setLightMode(TechniqueDef.LightMode.MultiPass);
|
||||
defs.add(def);
|
||||
|
||||
Collections.sort(defs, comp);
|
||||
|
||||
assertEquals(defs.get(0).getName(), "lighting3");
|
||||
assertEquals(defs.get(1).getName(), "lighting4");
|
||||
assertEquals(defs.get(2).getName(), "lighting2");
|
||||
assertEquals(defs.get(3).getName(), "lighting1");
|
||||
|
||||
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user