• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2009-2010 jMonkeyEngine
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  *   notice, this list of conditions and the following disclaimer.
11  *
12  * * Redistributions in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in the
14  *   documentation and/or other materials provided with the distribution.
15  *
16  * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
17  *   may be used to endorse or promote products derived from this software
18  *   without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 package com.jme3.material;
34 
35 import com.jme3.export.*;
36 import com.jme3.renderer.Caps;
37 import com.jme3.renderer.Renderer;
38 import com.jme3.shader.DefineList;
39 import com.jme3.shader.UniformBinding;
40 import com.jme3.shader.VarType;
41 import java.io.IOException;
42 import java.util.ArrayList;
43 import java.util.EnumSet;
44 import java.util.HashMap;
45 import java.util.List;
46 
47 /**
48  * Describes a technique definition.
49  *
50  * @author Kirill Vainer
51  */
52 public class TechniqueDef implements Savable {
53 
54     /**
55      * Describes light rendering mode.
56      */
57     public enum LightMode {
58         /**
59          * Disable light-based rendering
60          */
61         Disable,
62 
63         /**
64          * Enable light rendering by using a single pass.
65          * <p>
66          * An array of light positions and light colors is passed to the shader
67          * containing the world light list for the geometry being rendered.
68          */
69         SinglePass,
70 
71         /**
72          * Enable light rendering by using multi-pass rendering.
73          * <p>
74          * The geometry will be rendered once for each light. Each time the
75          * light position and light color uniforms are updated to contain
76          * the values for the current light. The ambient light color uniform
77          * is only set to the ambient light color on the first pass, future
78          * passes have it set to black.
79          */
80         MultiPass,
81 
82         /**
83          * Enable light rendering by using the
84          * {@link Renderer#setLighting(com.jme3.light.LightList) renderer's setLighting}
85          * method.
86          * <p>
87          * The specific details of rendering the lighting is up to the
88          * renderer implementation.
89          */
90         FixedPipeline,
91     }
92 
93     public enum ShadowMode {
94         Disable,
95         InPass,
96         PostPass,
97     }
98 
99     private EnumSet<Caps> requiredCaps = EnumSet.noneOf(Caps.class);
100     private String name;
101 
102     private String vertName;
103     private String fragName;
104     private String shaderLang;
105     private DefineList presetDefines;
106     private boolean usesShaders;
107 
108     private RenderState renderState;
109     private LightMode lightMode   = LightMode.Disable;
110     private ShadowMode shadowMode = ShadowMode.Disable;
111 
112     private HashMap<String, String> defineParams;
113     private ArrayList<UniformBinding> worldBinds;
114 
115     /**
116      * Creates a new technique definition.
117      * <p>
118      * Used internally by the J3M/J3MD loader.
119      *
120      * @param name The name of the technique, should be set to <code>null</code>
121      * for default techniques.
122      */
TechniqueDef(String name)123     public TechniqueDef(String name){
124         this.name = name == null ? "Default" : name;
125     }
126 
127     /**
128      * Serialization only. Do not use.
129      */
TechniqueDef()130     public TechniqueDef(){
131     }
132 
133     /**
134      * Returns the name of this technique as specified in the J3MD file.
135      * Default techniques have the name "Default".
136      *
137      * @return the name of this technique
138      */
getName()139     public String getName(){
140         return name;
141     }
142 
143     /**
144      * Returns the light mode.
145      * @return the light mode.
146      * @see LightMode
147      */
getLightMode()148     public LightMode getLightMode() {
149         return lightMode;
150     }
151 
152     /**
153      * Set the light mode
154      *
155      * @param lightMode the light mode
156      *
157      * @see LightMode
158      */
setLightMode(LightMode lightMode)159     public void setLightMode(LightMode lightMode) {
160         this.lightMode = lightMode;
161     }
162 
163     /**
164      * Returns the shadow mode.
165      * @return the shadow mode.
166      */
getShadowMode()167     public ShadowMode getShadowMode() {
168         return shadowMode;
169     }
170 
171     /**
172      * Set the shadow mode.
173      *
174      * @param shadowMode the shadow mode.
175      *
176      * @see ShadowMode
177      */
setShadowMode(ShadowMode shadowMode)178     public void setShadowMode(ShadowMode shadowMode) {
179         this.shadowMode = shadowMode;
180     }
181 
182     /**
183      * Returns the render state that this technique is using
184      * @return the render state that this technique is using
185      * @see #setRenderState(com.jme3.material.RenderState)
186      */
getRenderState()187     public RenderState getRenderState() {
188         return renderState;
189     }
190 
191     /**
192      * Sets the render state that this technique is using.
193      *
194      * @param renderState the render state that this technique is using.
195      *
196      * @see RenderState
197      */
setRenderState(RenderState renderState)198     public void setRenderState(RenderState renderState) {
199         this.renderState = renderState;
200     }
201 
202     /**
203      * Returns true if this technique uses shaders, false otherwise.
204      *
205      * @return true if this technique uses shaders, false otherwise.
206      *
207      * @see #setShaderFile(java.lang.String, java.lang.String, java.lang.String)
208      */
isUsingShaders()209     public boolean isUsingShaders(){
210         return usesShaders;
211     }
212 
213     /**
214      * Gets the {@link Caps renderer capabilities} that are required
215      * by this technique.
216      *
217      * @return the required renderer capabilities
218      */
getRequiredCaps()219     public EnumSet<Caps> getRequiredCaps() {
220         return requiredCaps;
221     }
222 
223     /**
224      * Sets the shaders that this technique definition will use.
225      *
226      * @param vertexShader The name of the vertex shader
227      * @param fragmentShader The name of the fragment shader
228      * @param shaderLanguage The shader language
229      */
setShaderFile(String vertexShader, String fragmentShader, String shaderLanguage)230     public void setShaderFile(String vertexShader, String fragmentShader, String shaderLanguage){
231         this.vertName = vertexShader;
232         this.fragName = fragmentShader;
233         this.shaderLang = shaderLanguage;
234 
235         Caps langCap = Caps.valueOf(shaderLanguage);
236         requiredCaps.add(langCap);
237 
238         usesShaders = true;
239     }
240 
241     /**
242      * Returns the define name which the given material parameter influences.
243      *
244      * @param paramName The parameter name to look up
245      * @return The define name
246      *
247      * @see #addShaderParamDefine(java.lang.String, java.lang.String)
248      */
getShaderParamDefine(String paramName)249     public String getShaderParamDefine(String paramName){
250         if (defineParams == null)
251             return null;
252 
253         return defineParams.get(paramName);
254     }
255 
256     /**
257      * Adds a define linked to a material parameter.
258      * <p>
259      * Any time the material parameter on the parent material is altered,
260      * the appropriate define on the technique will be modified as well.
261      * See the method
262      * {@link DefineList#set(java.lang.String, com.jme3.shader.VarType, java.lang.Object) }
263      * on the exact details of how the material parameter changes the define.
264      *
265      * @param paramName The name of the material parameter to link to.
266      * @param defineName The name of the define parameter, e.g. USE_LIGHTING
267      */
addShaderParamDefine(String paramName, String defineName)268     public void addShaderParamDefine(String paramName, String defineName){
269         if (defineParams == null)
270             defineParams = new HashMap<String, String>();
271 
272         defineParams.put(paramName, defineName);
273     }
274 
275     /**
276      * Returns the {@link DefineList} for the preset defines.
277      *
278      * @return the {@link DefineList} for the preset defines.
279      *
280      * @see #addShaderPresetDefine(java.lang.String, com.jme3.shader.VarType, java.lang.Object)
281      */
getShaderPresetDefines()282     public DefineList getShaderPresetDefines() {
283         return presetDefines;
284     }
285 
286     /**
287      * Adds a preset define.
288      * <p>
289      * Preset defines do not depend upon any parameters to be activated,
290      * they are always passed to the shader as long as this technique is used.
291      *
292      * @param defineName The name of the define parameter, e.g. USE_LIGHTING
293      * @param type The type of the define. See
294      * {@link DefineList#set(java.lang.String, com.jme3.shader.VarType, java.lang.Object) }
295      * to see why it matters.
296      *
297      * @param value The value of the define
298      */
addShaderPresetDefine(String defineName, VarType type, Object value)299     public void addShaderPresetDefine(String defineName, VarType type, Object value){
300         if (presetDefines == null)
301             presetDefines = new DefineList();
302 
303         presetDefines.set(defineName, type, value);
304     }
305 
306     /**
307      * Returns the name of the fragment shader used by the technique, or null
308      * if no fragment shader is specified.
309      *
310      * @return the name of the fragment shader to be used.
311      */
getFragmentShaderName()312     public String getFragmentShaderName() {
313         return fragName;
314     }
315 
316 
317     /**
318      * Returns the name of the vertex shader used by the technique, or null
319      * if no vertex shader is specified.
320      *
321      * @return the name of the vertex shader to be used.
322      */
getVertexShaderName()323     public String getVertexShaderName() {
324         return vertName;
325     }
326 
327     /**
328      * Returns the shader language of the shaders used in this technique.
329      *
330      * @return the shader language of the shaders used in this technique.
331      */
getShaderLanguage()332     public String getShaderLanguage() {
333         return shaderLang;
334     }
335 
336     /**
337      * Adds a new world parameter by the given name.
338      *
339      * @param name The world parameter to add.
340      * @return True if the world parameter name was found and added
341      * to the list of world parameters, false otherwise.
342      */
addWorldParam(String name)343     public boolean addWorldParam(String name) {
344         if (worldBinds == null){
345             worldBinds = new ArrayList<UniformBinding>();
346         }
347 
348         try {
349             worldBinds.add( UniformBinding.valueOf(name) );
350             return true;
351         } catch (IllegalArgumentException ex){
352             return false;
353         }
354     }
355 
356     /**
357      * Returns a list of world parameters that are used by this
358      * technique definition.
359      *
360      * @return The list of world parameters
361      */
getWorldBindings()362     public List<UniformBinding> getWorldBindings() {
363         return worldBinds;
364     }
365 
write(JmeExporter ex)366     public void write(JmeExporter ex) throws IOException{
367         OutputCapsule oc = ex.getCapsule(this);
368         oc.write(name, "name", null);
369         oc.write(vertName, "vertName", null);
370         oc.write(fragName, "fragName", null);
371         oc.write(shaderLang, "shaderLang", null);
372         oc.write(presetDefines, "presetDefines", null);
373         oc.write(lightMode, "lightMode", LightMode.Disable);
374         oc.write(shadowMode, "shadowMode", ShadowMode.Disable);
375         oc.write(renderState, "renderState", null);
376         oc.write(usesShaders, "usesShaders", false);
377         // TODO: Finish this when Map<String, String> export is available
378 //        oc.write(defineParams, "defineParams", null);
379         // TODO: Finish this when List<Enum> export is available
380 //        oc.write(worldBinds, "worldBinds", null);
381     }
382 
read(JmeImporter im)383     public void read(JmeImporter im) throws IOException{
384         InputCapsule ic = im.getCapsule(this);
385         name = ic.readString("name", null);
386         vertName = ic.readString("vertName", null);
387         fragName = ic.readString("fragName", null);
388         shaderLang = ic.readString("shaderLang", null);
389         presetDefines = (DefineList) ic.readSavable("presetDefines", null);
390         lightMode = ic.readEnum("lightMode", LightMode.class, LightMode.Disable);
391         shadowMode = ic.readEnum("shadowMode", ShadowMode.class, ShadowMode.Disable);
392         renderState = (RenderState) ic.readSavable("renderState", null);
393         usesShaders = ic.readBoolean("usesShaders", false);
394     }
395 
396 }
397