Skip to content

Commit cb04548

Browse files
committed
Techniques are now weighted and sorted depending on their LightMode and GLSL version
1 parent c713a06 commit cb04548

File tree

4 files changed

+217
-13
lines changed

4 files changed

+217
-13
lines changed

jme3-core/src/main/java/com/jme3/material/Material.java

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -704,15 +704,14 @@ public void setVector4(String name, Vector4f value) {
704704
* @throws UnsupportedOperationException If no candidate technique supports
705705
* the system capabilities.
706706
*/
707-
public void selectTechnique(String name, RenderManager renderManager) {
707+
public void selectTechnique(String name, final RenderManager renderManager) {
708708
// check if already created
709709
Technique tech = techniques.get(name);
710710
// When choosing technique, we choose one that
711711
// supports all the caps.
712712
if (tech == null) {
713713
EnumSet<Caps> rendererCaps = renderManager.getRenderer().getCaps();
714-
List<TechniqueDef> techDefs = def.getTechniqueDefs(name);
715-
714+
List<TechniqueDef> techDefs = def.getSortedTechniqueDefs(name, renderManager);
716715
if (techDefs == null || techDefs.isEmpty()) {
717716
throw new IllegalArgumentException(
718717
String.format("The requested technique %s is not available on material %s", name, def.getName()));
@@ -724,10 +723,7 @@ public void selectTechnique(String name, RenderManager renderManager) {
724723
// use the first one that supports all the caps
725724
tech = new Technique(this, techDef);
726725
techniques.put(name, tech);
727-
if (tech.getDef().getLightMode() == renderManager.getPreferredLightMode()
728-
|| tech.getDef().getLightMode() == LightMode.Disable) {
729-
break;
730-
}
726+
break;
731727
}
732728
lastTech = techDef;
733729
}
@@ -779,7 +775,7 @@ private int applyOverrides(Renderer renderer, Shader shader, SafeArrayList<MatPa
779775
}
780776

781777
private int updateShaderMaterialParameters(Renderer renderer, Shader shader,
782-
SafeArrayList<MatParamOverride> worldOverrides, SafeArrayList<MatParamOverride> forcedOverrides) {
778+
SafeArrayList<MatParamOverride> worldOverrides, SafeArrayList<MatParamOverride> forcedOverrides) {
783779

784780
int unit = 0;
785781
if (worldOverrides != null) {

jme3-core/src/main/java/com/jme3/material/MaterialDef.java

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,10 @@
3232
package com.jme3.material;
3333

3434
import com.jme3.asset.AssetManager;
35-
import com.jme3.export.*;
35+
import com.jme3.renderer.RenderManager;
3636
import com.jme3.shader.VarType;
3737
import com.jme3.texture.image.ColorSpace;
3838

39-
import java.io.IOException;
4039
import java.util.*;
4140
import java.util.logging.Level;
4241
import java.util.logging.Logger;
@@ -56,6 +55,7 @@ public class MaterialDef{
5655

5756
private Map<String, List<TechniqueDef>> techniques;
5857
private Map<String, MatParam> matParams;
58+
private TechDefComparator comparator = new TechDefComparator();
5959

6060
/**
6161
* Serialization only. Do not use.
@@ -188,6 +188,17 @@ public List<TechniqueDef> getTechniqueDefs(String name) {
188188
return techniques.get(name);
189189
}
190190

191+
public List<TechniqueDef> getSortedTechniqueDefs(String name, RenderManager rm) {
192+
List<TechniqueDef> techDefs = getTechniqueDefs(name);
193+
if (techDefs == null) {
194+
return null;
195+
}
196+
//Sorting the techdef depending on their weight (depending on their glsl version) and on the preferred light mode)
197+
comparator.rm = rm;
198+
Collections.sort(techDefs, comparator);
199+
return techDefs;
200+
}
201+
191202
/**
192203
*
193204
* @return the list of all the technique definitions names.
@@ -196,4 +207,17 @@ public Collection<String> getTechniqueDefsNames(){
196207
return techniques.keySet();
197208
}
198209

210+
public static class TechDefComparator implements Comparator<TechniqueDef> {
211+
212+
RenderManager rm;
213+
214+
@Override
215+
public int compare(TechniqueDef o1, TechniqueDef o2) {
216+
float o1Weight = o1.getWeight() + (o1.getLightMode() == rm.getPreferredLightMode() ? 10f : 0);
217+
float o2Weight = o2.getWeight() + (o2.getLightMode() == rm.getPreferredLightMode() ? 10f : 0);
218+
return (int) Math.signum(o2Weight - o1Weight);
219+
}
220+
}
221+
222+
199223
}

jme3-core/src/main/java/com/jme3/material/TechniqueDef.java

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@
3131
*/
3232
package com.jme3.material;
3333

34-
import com.jme3.material.logic.TechniqueDefLogic;
3534
import com.jme3.asset.AssetManager;
3635
import com.jme3.export.*;
36+
import com.jme3.material.logic.TechniqueDefLogic;
3737
import com.jme3.renderer.Caps;
3838
import com.jme3.shader.*;
3939
import com.jme3.shader.Shader.ShaderType;
@@ -161,6 +161,9 @@ public enum LightSpace {
161161
//The space in which the light should be transposed before sending to the shader.
162162
private LightSpace lightSpace;
163163

164+
//used to find the best fit technique
165+
private float weight = 0;
166+
164167
/**
165168
* Creates a new technique definition.
166169
* <p>
@@ -341,6 +344,8 @@ public void setShaderFile(String vertexShader, String fragmentShader, String ver
341344
requiredCaps.add(vertCap);
342345
Caps fragCap = Caps.valueOf(fragLanguage);
343346
requiredCaps.add(fragCap);
347+
348+
weight = Math.max(vertCap.ordinal(), fragCap.ordinal());
344349
}
345350

346351
/**
@@ -534,22 +539,25 @@ public Shader getShader(AssetManager assetManager, EnumSet<Caps> rendererCaps, D
534539
public void setShaderFile(EnumMap<Shader.ShaderType, String> shaderNames, EnumMap<Shader.ShaderType, String> shaderLanguages) {
535540
requiredCaps.clear();
536541

542+
int maxCap = 0;
537543
for (Shader.ShaderType shaderType : shaderNames.keySet()) {
538544
String language = shaderLanguages.get(shaderType);
539545
String shaderFile = shaderNames.get(shaderType);
540546

541547
this.shaderLanguages.put(shaderType, language);
542548
this.shaderNames.put(shaderType, shaderFile);
543549

544-
Caps vertCap = Caps.valueOf(language);
545-
requiredCaps.add(vertCap);
550+
Caps cap = Caps.valueOf(language);
551+
requiredCaps.add(cap);
552+
maxCap = Math.max(maxCap, cap.ordinal());
546553

547554
if (shaderType.equals(Shader.ShaderType.Geometry)) {
548555
requiredCaps.add(Caps.GeometryShader);
549556
} else if (shaderType.equals(Shader.ShaderType.TessellationControl)) {
550557
requiredCaps.add(Caps.TesselationShader);
551558
}
552559
}
560+
weight = maxCap;
553561
}
554562

555563
/**
@@ -600,6 +608,15 @@ public String getShaderProgramName(Shader.ShaderType shaderType){
600608
return shaderNames.get(shaderType);
601609
}
602610

611+
/**
612+
* returns the weight of the technique def
613+
*
614+
* @return
615+
*/
616+
public float getWeight() {
617+
return weight;
618+
}
619+
603620
/**
604621
* Adds a new world parameter by the given name.
605622
*
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
package com.jme3.material;
2+
3+
import com.jme3.renderer.RenderManager;
4+
import com.jme3.shader.Shader;
5+
import com.jme3.system.NullRenderer;
6+
import org.junit.Test;
7+
8+
import java.util.*;
9+
10+
import static org.junit.Assert.assertEquals;
11+
12+
/**
13+
* Created by Nehon on 14/01/2017.
14+
*/
15+
public class TestTechniqueDefOrdering {
16+
17+
@Test
18+
public void order() {
19+
20+
RenderManager rm = new RenderManager(new NullRenderer());
21+
rm.setPreferredLightMode(TechniqueDef.LightMode.MultiPass);
22+
MaterialDef.TechDefComparator comp = new MaterialDef.TechDefComparator();
23+
comp.rm = rm;
24+
25+
26+
//random case
27+
List<TechniqueDef> defs = new ArrayList<>();
28+
TechniqueDef def = new TechniqueDef("tech", 1);
29+
def.setShaderFile("", "", "GLSL100", "GLSL100");
30+
def.setLightMode(TechniqueDef.LightMode.SinglePass);
31+
defs.add(def);
32+
def = new TechniqueDef("tech2", 1);
33+
def.setShaderFile("", "", "GLSL150", "GLSL150");
34+
def.setLightMode(TechniqueDef.LightMode.MultiPass);
35+
defs.add(def);
36+
def = new TechniqueDef("tech3", 1);
37+
def.setShaderFile("", "", "GLSL110", "GLSL110");
38+
defs.add(def);
39+
def = new TechniqueDef("tech4", 1);
40+
def.setShaderFile("", "", "GLSL120", "GLSL120");
41+
defs.add(def);
42+
def = new TechniqueDef("tech5", 1);
43+
def.setShaderFile("", "", "GLSL130", "GLSL130");
44+
defs.add(def);
45+
46+
Collections.sort(defs, comp);
47+
48+
assertEquals(defs.get(0).getName(), "tech2");
49+
assertEquals(defs.get(1).getName(), "tech5");
50+
assertEquals(defs.get(2).getName(), "tech4");
51+
assertEquals(defs.get(3).getName(), "tech3");
52+
assertEquals(defs.get(4).getName(), "tech");
53+
54+
55+
//Test the unshaded material case: 2 disabled : 150 and 100
56+
defs = new ArrayList<>();
57+
def = new TechniqueDef("unshaded", 1);
58+
def.setShaderFile("", "", "GLSL100", "GLSL100");
59+
defs.add(def);
60+
def = new TechniqueDef("unshaded2", 1);
61+
def.setShaderFile("", "", "GLSL150", "GLSL150");
62+
defs.add(def);
63+
Collections.sort(defs, comp);
64+
65+
assertEquals(defs.get(0).getName(), "unshaded2");
66+
assertEquals(defs.get(1).getName(), "unshaded");
67+
68+
//Test the lighting material case: 2 singlepass : 150 and 100, 2 multipass : 150 and 100
69+
defs = new ArrayList<>();
70+
def = new TechniqueDef("lighting1", 1);
71+
def.setShaderFile("", "", "GLSL100", "GLSL100");
72+
def.setLightMode(TechniqueDef.LightMode.MultiPass);
73+
defs.add(def);
74+
def = new TechniqueDef("lighting2", 1);
75+
def.setShaderFile("", "", "GLSL150", "GLSL150");
76+
def.setLightMode(TechniqueDef.LightMode.MultiPass);
77+
defs.add(def);
78+
def = new TechniqueDef("lighting3", 1);
79+
def.setShaderFile("", "", "GLSL100", "GLSL100");
80+
def.setLightMode(TechniqueDef.LightMode.SinglePass);
81+
defs.add(def);
82+
def = new TechniqueDef("lighting4", 1);
83+
def.setShaderFile("", "", "GLSL150", "GLSL150");
84+
def.setLightMode(TechniqueDef.LightMode.SinglePass);
85+
defs.add(def);
86+
Collections.sort(defs, comp);
87+
88+
assertEquals(defs.get(0).getName(), "lighting2");
89+
assertEquals(defs.get(1).getName(), "lighting1");
90+
assertEquals(defs.get(2).getName(), "lighting4");
91+
assertEquals(defs.get(3).getName(), "lighting3");
92+
93+
//switching preferred lighting mode
94+
rm.setPreferredLightMode(TechniqueDef.LightMode.SinglePass);
95+
Collections.sort(defs, comp);
96+
97+
assertEquals(defs.get(0).getName(), "lighting4");
98+
assertEquals(defs.get(1).getName(), "lighting3");
99+
assertEquals(defs.get(2).getName(), "lighting2");
100+
assertEquals(defs.get(3).getName(), "lighting1");
101+
102+
103+
//test setting source through the enumMaps method with random cases
104+
rm.setPreferredLightMode(TechniqueDef.LightMode.MultiPass);
105+
defs = new ArrayList<>();
106+
def = new TechniqueDef("lighting1", 1);
107+
EnumMap<Shader.ShaderType, String> em = new EnumMap<>(Shader.ShaderType.class);
108+
em.put(Shader.ShaderType.Vertex, "");
109+
em.put(Shader.ShaderType.Fragment, "");
110+
em.put(Shader.ShaderType.Geometry, "");
111+
EnumMap<Shader.ShaderType, String> l = new EnumMap<>(Shader.ShaderType.class);
112+
l.put(Shader.ShaderType.Vertex, "GLSL100");
113+
l.put(Shader.ShaderType.Fragment, "GLSL100");
114+
l.put(Shader.ShaderType.Geometry, "GLSL100");
115+
def.setShaderFile(em, l);
116+
def.setLightMode(TechniqueDef.LightMode.SinglePass);
117+
defs.add(def);
118+
119+
def = new TechniqueDef("lighting2", 1);
120+
em = new EnumMap<>(Shader.ShaderType.class);
121+
em.put(Shader.ShaderType.Vertex, "");
122+
em.put(Shader.ShaderType.Fragment, "");
123+
em.put(Shader.ShaderType.Geometry, "");
124+
l = new EnumMap<>(Shader.ShaderType.class);
125+
l.put(Shader.ShaderType.Vertex, "GLSL100");
126+
l.put(Shader.ShaderType.Fragment, "GLSL100");
127+
l.put(Shader.ShaderType.Geometry, "GLSL100");
128+
def.setShaderFile(em, l);
129+
def.setLightMode(TechniqueDef.LightMode.MultiPass);
130+
defs.add(def);
131+
132+
def = new TechniqueDef("lighting3", 1);
133+
em = new EnumMap<>(Shader.ShaderType.class);
134+
em.put(Shader.ShaderType.Vertex, "");
135+
em.put(Shader.ShaderType.Fragment, "");
136+
em.put(Shader.ShaderType.Geometry, "");
137+
l = new EnumMap<>(Shader.ShaderType.class);
138+
l.put(Shader.ShaderType.Vertex, "GLSL150");
139+
l.put(Shader.ShaderType.Fragment, "GLSL150");
140+
l.put(Shader.ShaderType.Geometry, "GLSL150");
141+
def.setShaderFile(em, l);
142+
def.setLightMode(TechniqueDef.LightMode.MultiPass);
143+
defs.add(def);
144+
145+
def = new TechniqueDef("lighting4", 1);
146+
em = new EnumMap<>(Shader.ShaderType.class);
147+
em.put(Shader.ShaderType.Vertex, "");
148+
em.put(Shader.ShaderType.Fragment, "");
149+
em.put(Shader.ShaderType.Geometry, "");
150+
l = new EnumMap<>(Shader.ShaderType.class);
151+
l.put(Shader.ShaderType.Vertex, "GLSL130");
152+
l.put(Shader.ShaderType.Fragment, "GLSL130");
153+
l.put(Shader.ShaderType.Geometry, "GLSL110");
154+
def.setShaderFile(em, l);
155+
def.setLightMode(TechniqueDef.LightMode.MultiPass);
156+
defs.add(def);
157+
158+
Collections.sort(defs, comp);
159+
160+
assertEquals(defs.get(0).getName(), "lighting3");
161+
assertEquals(defs.get(1).getName(), "lighting4");
162+
assertEquals(defs.get(2).getName(), "lighting2");
163+
assertEquals(defs.get(3).getName(), "lighting1");
164+
165+
166+
}
167+
}

0 commit comments

Comments
 (0)