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 package com.jme3.material;
33 
34 import com.jme3.export.*;
35 import com.jme3.scene.Mesh;
36 import com.jme3.scene.Mesh.Mode;
37 import java.io.IOException;
38 
39 /**
40  * <code>RenderState</code> specifies material rendering properties that cannot
41  * be controlled by a shader on a {@link Material}. The properties
42  * allow manipulation of rendering features such as depth testing, alpha blending,
43  * face culling, stencil operations, and much more.
44  *
45  * @author Kirill Vainer
46  */
47 public class RenderState implements Cloneable, Savable {
48 
49     /**
50      * The <code>DEFAULT</code> render state is the one used by default
51      * on all materials unless changed otherwise by the user.
52      *
53      * <p>
54      * It has the following properties:
55      * <ul>
56      * <li>Back Face Culling</li>
57      * <li>Depth Testing Enabled</li>
58      * <li>Depth Writing Enabled</li>
59      * </ul>
60      */
61     public static final RenderState DEFAULT = new RenderState();
62 
63     /**
64      * The <code>NULL</code> render state is identical to the {@link RenderState#DEFAULT}
65      * render state except that depth testing and face culling are disabled.
66      */
67     public static final RenderState NULL = new RenderState();
68 
69     /**
70      * The <code>ADDITIONAL</code> render state is identical to the
71      * {@link RenderState#DEFAULT} render state except that all apply
72      * values are set to false. This allows the <code>ADDITIONAL</code> render
73      * state to be combined with other state but only influencing values
74      * that were changed from the original.
75      */
76     public static final RenderState ADDITIONAL = new RenderState();
77 
78     /**
79      * <code>TestFunction</code> specifies the testing function for stencil test
80      * function and alpha test function.
81      *
82      * <p>The functions work similarly as described except that for stencil
83      * test function, the reference value given in the stencil command is
84      * the input value while the reference is the value already in the stencil
85      * buffer.
86      */
87     public enum TestFunction {
88 
89         /**
90          * The test always fails
91          */
92         Never,
93         /**
94          * The test succeeds if the input value is equal to the reference value.
95          */
96         Equal,
97         /**
98          * The test succeeds if the input value is less than the reference value.
99          */
100         Less,
101         /**
102          * The test succeeds if the input value is less than or equal to
103          * the reference value.
104          */
105         LessOrEqual,
106         /**
107          * The test succeeds if the input value is greater than the reference value.
108          */
109         Greater,
110         /**
111          * The test succeeds if the input value is greater than or equal to
112          * the reference value.
113          */
114         GreaterOrEqual,
115         /**
116          * The test succeeds if the input value does not equal the
117          * reference value.
118          */
119         NotEqual,
120         /**
121          * The test always passes
122          */
123         Always,}
124 
125     /**
126      * <code>BlendMode</code> specifies the blending operation to use.
127      *
128      * @see RenderState#setBlendMode(com.jme3.material.RenderState.BlendMode)
129      */
130     public enum BlendMode {
131 
132         /**
133          * No blending mode is used.
134          */
135         Off,
136         /**
137          * Additive blending. For use with glows and particle emitters.
138          * <p>
139          * Result = Source Color + Destination Color -> (GL_ONE, GL_ONE)
140          */
141         Additive,
142         /**
143          * Premultiplied alpha blending, for use with premult alpha textures.
144          * <p>
145          * Result = Source Color + (Dest Color * (1 - Source Alpha) ) -> (GL_ONE, GL_ONE_MINUS_SRC_ALPHA)
146          */
147         PremultAlpha,
148         /**
149          * Additive blending that is multiplied with source alpha.
150          * For use with glows and particle emitters.
151          * <p>
152          * Result = (Source Alpha * Source Color) + Dest Color -> (GL_SRC_ALPHA, GL_ONE)
153          */
154         AlphaAdditive,
155         /**
156          * Color blending, blends in color from dest color
157          * using source color.
158          * <p>
159          * Result = Source Color + (1 - Source Color) * Dest Color -> (GL_ONE, GL_ONE_MINUS_SRC_COLOR)
160          */
161         Color,
162         /**
163          * Alpha blending, interpolates to source color from dest color
164          * using source alpha.
165          * <p>
166          * Result = Source Alpha * Source Color +
167          *          (1 - Source Alpha) * Dest Color -> (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
168          */
169         Alpha,
170         /**
171          * Multiplies the source and dest colors.
172          * <p>
173          * Result = Source Color * Dest Color -> (GL_DST_COLOR, GL_ZERO)
174          */
175         Modulate,
176         /**
177          * Multiplies the source and dest colors then doubles the result.
178          * <p>
179          * Result = 2 * Source Color * Dest Color -> (GL_DST_COLOR, GL_SRC_COLOR)
180          */
181         ModulateX2
182     }
183 
184     /**
185      * <code>FaceCullMode</code> specifies the criteria for faces to be culled.
186      *
187      * @see RenderState#setFaceCullMode(com.jme3.material.RenderState.FaceCullMode)
188      */
189     public enum FaceCullMode {
190 
191         /**
192          * Face culling is disabled.
193          */
194         Off,
195         /**
196          * Cull front faces
197          */
198         Front,
199         /**
200          * Cull back faces
201          */
202         Back,
203         /**
204          * Cull both front and back faces.
205          */
206         FrontAndBack
207     }
208 
209     /**
210      * <code>StencilOperation</code> specifies the stencil operation to use
211      * in a certain scenario as specified in {@link RenderState#setStencil(boolean,
212      * com.jme3.material.RenderState.StencilOperation,
213      * com.jme3.material.RenderState.StencilOperation,
214      * com.jme3.material.RenderState.StencilOperation,
215      * com.jme3.material.RenderState.StencilOperation,
216      * com.jme3.material.RenderState.StencilOperation,
217      * com.jme3.material.RenderState.StencilOperation,
218      * com.jme3.material.RenderState.StencilFunction,
219      * com.jme3.material.RenderState.StencilFunction)}
220      */
221     public enum StencilOperation {
222 
223         /**
224          * Keep the current value.
225          */
226         Keep,
227         /**
228          * Set the value to 0
229          */
230         Zero,
231         /**
232          * Replace the value in the stencil buffer with the reference value.
233          */
234         Replace,
235 
236         /**
237          * Increment the value in the stencil buffer, clamp once reaching
238          * the maximum value.
239          */
240         Increment,
241 
242         /**
243          * Increment the value in the stencil buffer and wrap to 0 when
244          * reaching the maximum value.
245          */
246         IncrementWrap,
247         /**
248          * Decrement the value in the stencil buffer and clamp once reaching 0.
249          */
250         Decrement,
251         /**
252          * Decrement the value in the stencil buffer and wrap to the maximum
253          * value when reaching 0.
254          */
255         DecrementWrap,
256 
257         /**
258          * Does a bitwise invert of the value in the stencil buffer.
259          */
260         Invert
261     }
262 
263     static {
264         NULL.cullMode = FaceCullMode.Off;
265         NULL.depthTest = false;
266     }
267 
268     static {
269         ADDITIONAL.applyPointSprite = false;
270         ADDITIONAL.applyWireFrame = false;
271         ADDITIONAL.applyCullMode = false;
272         ADDITIONAL.applyDepthWrite = false;
273         ADDITIONAL.applyDepthTest = false;
274         ADDITIONAL.applyColorWrite = false;
275         ADDITIONAL.applyBlendMode = false;
276         ADDITIONAL.applyAlphaTest = false;
277         ADDITIONAL.applyAlphaFallOff = false;
278         ADDITIONAL.applyPolyOffset = false;
279     }
280 
281     boolean pointSprite = false;
282     boolean applyPointSprite = true;
283 
284     boolean wireframe = false;
285     boolean applyWireFrame = true;
286 
287     FaceCullMode cullMode = FaceCullMode.Back;
288     boolean applyCullMode = true;
289 
290     boolean depthWrite = true;
291     boolean applyDepthWrite = true;
292 
293     boolean depthTest = true;
294     boolean applyDepthTest = true;
295 
296     boolean colorWrite = true;
297     boolean applyColorWrite = true;
298 
299     BlendMode blendMode = BlendMode.Off;
300     boolean applyBlendMode = true;
301 
302     boolean alphaTest = false;
303     boolean applyAlphaTest = true;
304 
305     float alphaFallOff = 0;
306     boolean applyAlphaFallOff = true;
307 
308     float offsetFactor = 0;
309     float offsetUnits = 0;
310     boolean offsetEnabled = false;
311     boolean applyPolyOffset = true;
312 
313     boolean stencilTest = false;
314     boolean applyStencilTest = false;
315     StencilOperation frontStencilStencilFailOperation = StencilOperation.Keep;
316     StencilOperation frontStencilDepthFailOperation = StencilOperation.Keep;
317     StencilOperation frontStencilDepthPassOperation = StencilOperation.Keep;
318     StencilOperation backStencilStencilFailOperation = StencilOperation.Keep;
319     StencilOperation backStencilDepthFailOperation = StencilOperation.Keep;
320     StencilOperation backStencilDepthPassOperation = StencilOperation.Keep;
321     TestFunction frontStencilFunction = TestFunction.Always;
322     TestFunction backStencilFunction = TestFunction.Always;
323 
write(JmeExporter ex)324     public void write(JmeExporter ex) throws IOException {
325         OutputCapsule oc = ex.getCapsule(this);
326         oc.write(pointSprite, "pointSprite", false);
327         oc.write(wireframe, "wireframe", false);
328         oc.write(cullMode, "cullMode", FaceCullMode.Back);
329         oc.write(depthWrite, "depthWrite", true);
330         oc.write(depthTest, "depthTest", true);
331         oc.write(colorWrite, "colorWrite", true);
332         oc.write(blendMode, "blendMode", BlendMode.Off);
333         oc.write(alphaTest, "alphaTest", false);
334         oc.write(alphaFallOff, "alphaFallOff", 0);
335         oc.write(offsetEnabled, "offsetEnabled", false);
336         oc.write(offsetFactor, "offsetFactor", 0);
337         oc.write(offsetUnits, "offsetUnits", 0);
338         oc.write(stencilTest, "stencilTest", false);
339         oc.write(frontStencilStencilFailOperation, "frontStencilStencilFailOperation", StencilOperation.Keep);
340         oc.write(frontStencilDepthFailOperation, "frontStencilDepthFailOperation", StencilOperation.Keep);
341         oc.write(frontStencilDepthPassOperation, "frontStencilDepthPassOperation", StencilOperation.Keep);
342         oc.write(backStencilStencilFailOperation, "frontStencilStencilFailOperation", StencilOperation.Keep);
343         oc.write(backStencilDepthFailOperation, "backStencilDepthFailOperation", StencilOperation.Keep);
344         oc.write(backStencilDepthPassOperation, "backStencilDepthPassOperation", StencilOperation.Keep);
345         oc.write(frontStencilFunction, "frontStencilFunction", TestFunction.Always);
346         oc.write(backStencilFunction, "backStencilFunction", TestFunction.Always);
347 
348         // Only "additional render state" has them set to false by default
349         oc.write(applyPointSprite,  "applyPointSprite",  true);
350         oc.write(applyWireFrame,    "applyWireFrame",    true);
351         oc.write(applyCullMode,     "applyCullMode",     true);
352         oc.write(applyDepthWrite,   "applyDepthWrite",   true);
353         oc.write(applyDepthTest,    "applyDepthTest",    true);
354         oc.write(applyColorWrite,   "applyColorWrite",   true);
355         oc.write(applyBlendMode,    "applyBlendMode",    true);
356         oc.write(applyAlphaTest,    "applyAlphaTest",    true);
357         oc.write(applyAlphaFallOff, "applyAlphaFallOff", true);
358         oc.write(applyPolyOffset,   "applyPolyOffset",   true);
359 
360     }
361 
read(JmeImporter im)362     public void read(JmeImporter im) throws IOException {
363         InputCapsule ic = im.getCapsule(this);
364         pointSprite = ic.readBoolean("pointSprite", false);
365         wireframe = ic.readBoolean("wireframe", false);
366         cullMode = ic.readEnum("cullMode", FaceCullMode.class, FaceCullMode.Back);
367         depthWrite = ic.readBoolean("depthWrite", true);
368         depthTest = ic.readBoolean("depthTest", true);
369         colorWrite = ic.readBoolean("colorWrite", true);
370         blendMode = ic.readEnum("blendMode", BlendMode.class, BlendMode.Off);
371         alphaTest = ic.readBoolean("alphaTest", false);
372         alphaFallOff = ic.readFloat("alphaFallOff", 0);
373         offsetEnabled = ic.readBoolean("offsetEnabled", false);
374         offsetFactor = ic.readFloat("offsetFactor", 0);
375         offsetUnits = ic.readFloat("offsetUnits", 0);
376         stencilTest = ic.readBoolean("stencilTest", false);
377         frontStencilStencilFailOperation = ic.readEnum("frontStencilStencilFailOperation", StencilOperation.class, StencilOperation.Keep);
378         frontStencilDepthFailOperation = ic.readEnum("frontStencilDepthFailOperation", StencilOperation.class, StencilOperation.Keep);
379         frontStencilDepthPassOperation = ic.readEnum("frontStencilDepthPassOperation", StencilOperation.class, StencilOperation.Keep);
380         backStencilStencilFailOperation = ic.readEnum("backStencilStencilFailOperation", StencilOperation.class, StencilOperation.Keep);
381         backStencilDepthFailOperation = ic.readEnum("backStencilDepthFailOperation", StencilOperation.class, StencilOperation.Keep);
382         backStencilDepthPassOperation = ic.readEnum("backStencilDepthPassOperation", StencilOperation.class, StencilOperation.Keep);
383         frontStencilFunction = ic.readEnum("frontStencilFunction", TestFunction.class, TestFunction.Always);
384         backStencilFunction = ic.readEnum("backStencilFunction", TestFunction.class, TestFunction.Always);
385 
386         applyPointSprite =  ic.readBoolean("applyPointSprite",  true);
387         applyWireFrame =    ic.readBoolean("applyWireFrame",    true);
388         applyCullMode =     ic.readBoolean("applyCullMode",     true);
389         applyDepthWrite =   ic.readBoolean("applyDepthWrite",   true);
390         applyDepthTest =    ic.readBoolean("applyDepthTest",    true);
391         applyColorWrite =   ic.readBoolean("applyColorWrite",   true);
392         applyBlendMode =    ic.readBoolean("applyBlendMode",    true);
393         applyAlphaTest =    ic.readBoolean("applyAlphaTest",    true);
394         applyAlphaFallOff = ic.readBoolean("applyAlphaFallOff", true);
395         applyPolyOffset =   ic.readBoolean("applyPolyOffset",   true);
396     }
397 
398     /**
399      * Create a clone of this <code>RenderState</code>
400      *
401      * @return Clone of this render state.
402      */
403     @Override
clone()404     public RenderState clone() {
405         try {
406             return (RenderState) super.clone();
407         } catch (CloneNotSupportedException ex) {
408             throw new AssertionError();
409         }
410     }
411 
412     /**
413      * Enables point sprite mode.
414      *
415      * <p>When point sprite is enabled, any meshes
416      * with the type of {@link Mode#Points} will be rendered as 2D quads
417      * with texturing enabled. Fragment shaders can write to the
418      * <code>gl_PointCoord</code> variable to manipulate the texture coordinate
419      * for each pixel. The size of the 2D quad can be controlled by writing
420      * to the <code>gl_PointSize</code> variable in the vertex shader.
421      *
422      * @param pointSprite Enables Point Sprite mode.
423      */
setPointSprite(boolean pointSprite)424     public void setPointSprite(boolean pointSprite) {
425         applyPointSprite = true;
426         this.pointSprite = pointSprite;
427     }
428 
429     /**
430      * Sets the alpha fall off value for alpha testing.
431      *
432      * <p>If the pixel's alpha value is greater than the
433      * <code>alphaFallOff</code> then the pixel will be rendered, otherwise
434      * the pixel will be discarded.
435      *
436      * @param alphaFallOff The alpha of all rendered pixels must be higher
437      * than this value to be rendered. This value should be between 0 and 1.
438      *
439      * @see RenderState#setAlphaTest(boolean)
440      */
setAlphaFallOff(float alphaFallOff)441     public void setAlphaFallOff(float alphaFallOff) {
442         applyAlphaFallOff = true;
443         this.alphaFallOff = alphaFallOff;
444     }
445 
446     /**
447      * Enable alpha testing.
448      *
449      * <p>When alpha testing is enabled, all input pixels' alpha are compared
450      * to the {@link RenderState#setAlphaFallOff(float) constant alpha falloff}.
451      * If the input alpha is greater than the falloff, the pixel will be rendered,
452      * otherwise it will be discarded.
453      *
454      * @param alphaTest Set to true to enable alpha testing.
455      *
456      * @see RenderState#setAlphaFallOff(float)
457      */
setAlphaTest(boolean alphaTest)458     public void setAlphaTest(boolean alphaTest) {
459         applyAlphaTest = true;
460         this.alphaTest = alphaTest;
461     }
462 
463     /**
464      * Enable writing color.
465      *
466      * <p>When color write is enabled, the result of a fragment shader, the
467      * <code>gl_FragColor</code>, will be rendered into the color buffer
468      * (including alpha).
469      *
470      * @param colorWrite Set to true to enable color writing.
471      */
setColorWrite(boolean colorWrite)472     public void setColorWrite(boolean colorWrite) {
473         applyColorWrite = true;
474         this.colorWrite = colorWrite;
475     }
476 
477     /**
478      * Set the face culling mode.
479      *
480      * <p>See the {@link FaceCullMode} enum on what each value does.
481      * Face culling will project the triangle's points onto the screen
482      * and determine if the triangle is in counter-clockwise order or
483      * clockwise order. If a triangle is in counter-clockwise order, then
484      * it is considered a front-facing triangle, otherwise, it is considered
485      * a back-facing triangle.
486      *
487      * @param cullMode the face culling mode.
488      */
setFaceCullMode(FaceCullMode cullMode)489     public void setFaceCullMode(FaceCullMode cullMode) {
490         applyCullMode = true;
491         this.cullMode = cullMode;
492     }
493 
494     /**
495      * Set the blending mode.
496      *
497      * <p>When blending is enabled, (<code>blendMode</code> is not {@link BlendMode#Off})
498      * the input pixel will be blended with the pixel
499      * already in the color buffer. The blending operation is determined
500      * by the {@link BlendMode}. For example, the {@link BlendMode#Additive}
501      * will add the input pixel's color to the color already in the color buffer:
502      * <br/>
503      * <code>Result = Source Color + Destination Color</code>
504      *
505      * @param blendMode The blend mode to use. Set to {@link BlendMode#Off}
506      * to disable blending.
507      */
setBlendMode(BlendMode blendMode)508     public void setBlendMode(BlendMode blendMode) {
509         applyBlendMode = true;
510         this.blendMode = blendMode;
511     }
512 
513     /**
514      * Enable depth testing.
515      *
516      * <p>When depth testing is enabled, a pixel must pass the depth test
517      * before it is written to the color buffer.
518      * The input pixel's depth value must be less than or equal than
519      * the value already in the depth buffer to pass the depth test.
520      *
521      * @param depthTest Enable or disable depth testing.
522      */
setDepthTest(boolean depthTest)523     public void setDepthTest(boolean depthTest) {
524         applyDepthTest = true;
525         this.depthTest = depthTest;
526     }
527 
528     /**
529      * Enable depth writing.
530      *
531      * <p>After passing the {@link RenderState#setDepthTest(boolean) depth test},
532      * a pixel's depth value will be written into the depth buffer if
533      * depth writing is enabled.
534      *
535      * @param depthWrite True to enable writing to the depth buffer.
536      */
setDepthWrite(boolean depthWrite)537     public void setDepthWrite(boolean depthWrite) {
538         applyDepthWrite = true;
539         this.depthWrite = depthWrite;
540     }
541 
542     /**
543      * Enables wireframe rendering mode.
544      *
545      * <p>When in wireframe mode, {@link Mesh meshes} rendered in triangle mode
546      * will not be solid, but instead, only the edges of the triangles
547      * will be rendered.
548      *
549      * @param wireframe True to enable wireframe mode.
550      */
setWireframe(boolean wireframe)551     public void setWireframe(boolean wireframe) {
552         applyWireFrame = true;
553         this.wireframe = wireframe;
554     }
555 
556     /**
557      * Offsets the on-screen z-order of the material's polygons, to combat visual artefacts like
558      * stitching, bleeding and z-fighting for overlapping polygons.
559      * Factor and units are summed to produce the depth offset.
560      * This offset is applied in screen space,
561      * typically with positive Z pointing into the screen.
562      * Typical values are (1.0f, 1.0f) or (-1.0f, -1.0f)
563      *
564      * @see <a href="http://www.opengl.org/resources/faq/technical/polygonoffset.htm" rel="nofollow">http://www.opengl.org/resources/faq/technical/polygonoffset.htm</a>
565      * @param factor scales the maximum Z slope, with respect to X or Y of the polygon
566      * @param units scales the minimum resolvable depth buffer value
567      **/
setPolyOffset(float factor, float units)568     public void setPolyOffset(float factor, float units) {
569         applyPolyOffset = true;
570         offsetEnabled = true;
571         offsetFactor = factor;
572         offsetUnits = units;
573     }
574 
575     /**
576      * Enable stencil testing.
577      *
578      * <p>Stencil testing can be used to filter pixels according to the stencil
579      * buffer. Objects can be rendered with some stencil operation to manipulate
580      * the values in the stencil buffer, then, other objects can be rendered
581      * to test against the values written previously.
582      *
583      * @param enabled Set to true to enable stencil functionality. If false
584      * all other parameters are ignored.
585      *
586      * @param _frontStencilStencilFailOperation Sets the operation to occur when
587      * a front-facing triangle fails the front stencil function.
588      * @param _frontStencilDepthFailOperation Sets the operation to occur when
589      * a front-facing triangle fails the depth test.
590      * @param _frontStencilDepthPassOperation Set the operation to occur when
591      * a front-facing triangle passes the depth test.
592      * @param _backStencilStencilFailOperation Set the operation to occur when
593      * a back-facing triangle fails the back stencil function.
594      * @param _backStencilDepthFailOperation Set the operation to occur when
595      * a back-facing triangle fails the depth test.
596      * @param _backStencilDepthPassOperation Set the operation to occur when
597      * a back-facing triangle passes the depth test.
598      * @param _frontStencilFunction Set the test function for front-facing triangles.
599      * @param _backStencilFunction Set the test function for back-facing triangles.
600      */
setStencil(boolean enabled, StencilOperation _frontStencilStencilFailOperation, StencilOperation _frontStencilDepthFailOperation, StencilOperation _frontStencilDepthPassOperation, StencilOperation _backStencilStencilFailOperation, StencilOperation _backStencilDepthFailOperation, StencilOperation _backStencilDepthPassOperation, TestFunction _frontStencilFunction, TestFunction _backStencilFunction)601     public void setStencil(boolean enabled,
602             StencilOperation _frontStencilStencilFailOperation,
603             StencilOperation _frontStencilDepthFailOperation,
604             StencilOperation _frontStencilDepthPassOperation,
605             StencilOperation _backStencilStencilFailOperation,
606             StencilOperation _backStencilDepthFailOperation,
607             StencilOperation _backStencilDepthPassOperation,
608             TestFunction _frontStencilFunction,
609             TestFunction _backStencilFunction) {
610 
611         stencilTest = enabled;
612         applyStencilTest = true;
613         this.frontStencilStencilFailOperation = _frontStencilStencilFailOperation;
614         this.frontStencilDepthFailOperation = _frontStencilDepthFailOperation;
615         this.frontStencilDepthPassOperation = _frontStencilDepthPassOperation;
616         this.backStencilStencilFailOperation = _backStencilStencilFailOperation;
617         this.backStencilDepthFailOperation = _backStencilDepthFailOperation;
618         this.backStencilDepthPassOperation = _backStencilDepthPassOperation;
619         this.frontStencilFunction = _frontStencilFunction;
620         this.backStencilFunction = _backStencilFunction;
621     }
622 
623     /**
624      * Check if stencil test is enabled.
625      *
626      * @return True if stencil test is enabled.
627      */
isStencilTest()628     public boolean isStencilTest() {
629         return stencilTest;
630     }
631 
632     /**
633      * Retrieve the front stencil fail operation.
634      *
635      * @return the front stencil fail operation.
636      *
637      * @see RenderState#setStencil(boolean,
638      * com.jme3.material.RenderState.StencilOperation,
639      * com.jme3.material.RenderState.StencilOperation,
640      * com.jme3.material.RenderState.StencilOperation,
641      * com.jme3.material.RenderState.StencilOperation,
642      * com.jme3.material.RenderState.StencilOperation,
643      * com.jme3.material.RenderState.StencilOperation,
644      * com.jme3.material.RenderState.TestFunction,
645      * com.jme3.material.RenderState.TestFunction)
646      */
getFrontStencilStencilFailOperation()647     public StencilOperation getFrontStencilStencilFailOperation() {
648         return frontStencilStencilFailOperation;
649     }
650 
651     /**
652      * Retrieve the front depth test fail operation.
653      *
654      * @return the front depth test fail operation.
655      *
656      * @see RenderState#setStencil(boolean,
657      * com.jme3.material.RenderState.StencilOperation,
658      * com.jme3.material.RenderState.StencilOperation,
659      * com.jme3.material.RenderState.StencilOperation,
660      * com.jme3.material.RenderState.StencilOperation,
661      * com.jme3.material.RenderState.StencilOperation,
662      * com.jme3.material.RenderState.StencilOperation,
663      * com.jme3.material.RenderState.TestFunction,
664      * com.jme3.material.RenderState.TestFunction)
665      */
getFrontStencilDepthFailOperation()666     public StencilOperation getFrontStencilDepthFailOperation() {
667         return frontStencilDepthFailOperation;
668     }
669 
670     /**
671      * Retrieve the front depth test pass operation.
672      *
673      * @return the front depth test pass operation.
674      *
675      * @see RenderState#setStencil(boolean,
676      * com.jme3.material.RenderState.StencilOperation,
677      * com.jme3.material.RenderState.StencilOperation,
678      * com.jme3.material.RenderState.StencilOperation,
679      * com.jme3.material.RenderState.StencilOperation,
680      * com.jme3.material.RenderState.StencilOperation,
681      * com.jme3.material.RenderState.StencilOperation,
682      * com.jme3.material.RenderState.TestFunction,
683      * com.jme3.material.RenderState.TestFunction)
684      */
getFrontStencilDepthPassOperation()685     public StencilOperation getFrontStencilDepthPassOperation() {
686         return frontStencilDepthPassOperation;
687     }
688 
689     /**
690      * Retrieve the back stencil fail operation.
691      *
692      * @return the back stencil fail operation.
693      *
694      * @see RenderState#setStencil(boolean,
695      * com.jme3.material.RenderState.StencilOperation,
696      * com.jme3.material.RenderState.StencilOperation,
697      * com.jme3.material.RenderState.StencilOperation,
698      * com.jme3.material.RenderState.StencilOperation,
699      * com.jme3.material.RenderState.StencilOperation,
700      * com.jme3.material.RenderState.StencilOperation,
701      * com.jme3.material.RenderState.TestFunction,
702      * com.jme3.material.RenderState.TestFunction)
703      */
getBackStencilStencilFailOperation()704     public StencilOperation getBackStencilStencilFailOperation() {
705         return backStencilStencilFailOperation;
706     }
707 
708     /**
709      * Retrieve the back depth test fail operation.
710      *
711      * @return the back depth test fail operation.
712      *
713      * @see RenderState#setStencil(boolean,
714      * com.jme3.material.RenderState.StencilOperation,
715      * com.jme3.material.RenderState.StencilOperation,
716      * com.jme3.material.RenderState.StencilOperation,
717      * com.jme3.material.RenderState.StencilOperation,
718      * com.jme3.material.RenderState.StencilOperation,
719      * com.jme3.material.RenderState.StencilOperation,
720      * com.jme3.material.RenderState.TestFunction,
721      * com.jme3.material.RenderState.TestFunction)
722      */
getBackStencilDepthFailOperation()723     public StencilOperation getBackStencilDepthFailOperation() {
724         return backStencilDepthFailOperation;
725     }
726 
727     /**
728      * Retrieve the back depth test pass operation.
729      *
730      * @return the back depth test pass operation.
731      *
732      * @see RenderState#setStencil(boolean,
733      * com.jme3.material.RenderState.StencilOperation,
734      * com.jme3.material.RenderState.StencilOperation,
735      * com.jme3.material.RenderState.StencilOperation,
736      * com.jme3.material.RenderState.StencilOperation,
737      * com.jme3.material.RenderState.StencilOperation,
738      * com.jme3.material.RenderState.StencilOperation,
739      * com.jme3.material.RenderState.TestFunction,
740      * com.jme3.material.RenderState.TestFunction)
741      */
getBackStencilDepthPassOperation()742     public StencilOperation getBackStencilDepthPassOperation() {
743         return backStencilDepthPassOperation;
744     }
745 
746     /**
747      * Retrieve the front stencil function.
748      *
749      * @return the front stencil function.
750      *
751      * @see RenderState#setStencil(boolean,
752      * com.jme3.material.RenderState.StencilOperation,
753      * com.jme3.material.RenderState.StencilOperation,
754      * com.jme3.material.RenderState.StencilOperation,
755      * com.jme3.material.RenderState.StencilOperation,
756      * com.jme3.material.RenderState.StencilOperation,
757      * com.jme3.material.RenderState.StencilOperation,
758      * com.jme3.material.RenderState.TestFunction,
759      * com.jme3.material.RenderState.TestFunction)
760      */
getFrontStencilFunction()761     public TestFunction getFrontStencilFunction() {
762         return frontStencilFunction;
763     }
764 
765     /**
766      * Retrieve the back stencil function.
767      *
768      * @return the back stencil function.
769      *
770      * @see RenderState#setStencil(boolean,
771      * com.jme3.material.RenderState.StencilOperation,
772      * com.jme3.material.RenderState.StencilOperation,
773      * com.jme3.material.RenderState.StencilOperation,
774      * com.jme3.material.RenderState.StencilOperation,
775      * com.jme3.material.RenderState.StencilOperation,
776      * com.jme3.material.RenderState.StencilOperation,
777      * com.jme3.material.RenderState.TestFunction,
778      * com.jme3.material.RenderState.TestFunction)
779      */
getBackStencilFunction()780     public TestFunction getBackStencilFunction() {
781         return backStencilFunction;
782     }
783 
784     /**
785      * Retrieve the blend mode.
786      *
787      * @return the blend mode.
788      */
getBlendMode()789     public BlendMode getBlendMode() {
790         return blendMode;
791     }
792 
793     /**
794      * Check if point sprite mode is enabled
795      *
796      * @return True if point sprite mode is enabled.
797      *
798      * @see RenderState#setPointSprite(boolean)
799      */
isPointSprite()800     public boolean isPointSprite() {
801         return pointSprite;
802     }
803 
804     /**
805      * Check if alpha test is enabled.
806      *
807      * @return True if alpha test is enabled.
808      *
809      * @see RenderState#setAlphaTest(boolean)
810      */
isAlphaTest()811     public boolean isAlphaTest() {
812         return alphaTest;
813     }
814 
815     /**
816      * Retrieve the face cull mode.
817      *
818      * @return the face cull mode.
819      *
820      * @see RenderState#setFaceCullMode(com.jme3.material.RenderState.FaceCullMode)
821      */
getFaceCullMode()822     public FaceCullMode getFaceCullMode() {
823         return cullMode;
824     }
825 
826     /**
827      * Check if depth test is enabled.
828      *
829      * @return True if depth test is enabled.
830      *
831      * @see RenderState#setDepthTest(boolean)
832      */
isDepthTest()833     public boolean isDepthTest() {
834         return depthTest;
835     }
836 
837     /**
838      * Check if depth write is enabled.
839      *
840      * @return True if depth write is enabled.
841      *
842      * @see RenderState#setDepthWrite(boolean)
843      */
isDepthWrite()844     public boolean isDepthWrite() {
845         return depthWrite;
846     }
847 
848     /**
849      * Check if wireframe mode is enabled.
850      *
851      * @return True if wireframe mode is enabled.
852      *
853      * @see RenderState#setWireframe(boolean)
854      */
isWireframe()855     public boolean isWireframe() {
856         return wireframe;
857     }
858 
859     /**
860      * Check if color writing is enabled.
861      *
862      * @return True if color writing is enabled.
863      *
864      * @see RenderState#setColorWrite(boolean)
865      */
isColorWrite()866     public boolean isColorWrite() {
867         return colorWrite;
868     }
869 
870     /**
871      * Retrieve the poly offset factor value.
872      *
873      * @return the poly offset factor value.
874      *
875      * @see RenderState#setPolyOffset(float, float)
876      */
getPolyOffsetFactor()877     public float getPolyOffsetFactor() {
878         return offsetFactor;
879     }
880 
881     /**
882      * Retrieve the poly offset units value.
883      *
884      * @return the poly offset units value.
885      *
886      * @see RenderState#setPolyOffset(float, float)
887      */
getPolyOffsetUnits()888     public float getPolyOffsetUnits() {
889         return offsetUnits;
890     }
891 
892     /**
893      * Check if polygon offset is enabled.
894      *
895      * @return True if polygon offset is enabled.
896      *
897      * @see RenderState#setPolyOffset(float, float)
898      */
isPolyOffset()899     public boolean isPolyOffset() {
900         return offsetEnabled;
901     }
902 
903     /**
904      * Retrieve the alpha falloff value.
905      *
906      * @return the alpha falloff value.
907      *
908      * @see RenderState#setAlphaFallOff(float)
909      */
getAlphaFallOff()910     public float getAlphaFallOff() {
911         return alphaFallOff;
912     }
913 
isApplyAlphaFallOff()914     public boolean isApplyAlphaFallOff() {
915         return applyAlphaFallOff;
916     }
917 
isApplyAlphaTest()918     public boolean isApplyAlphaTest() {
919         return applyAlphaTest;
920     }
921 
isApplyBlendMode()922     public boolean isApplyBlendMode() {
923         return applyBlendMode;
924     }
925 
isApplyColorWrite()926     public boolean isApplyColorWrite() {
927         return applyColorWrite;
928     }
929 
isApplyCullMode()930     public boolean isApplyCullMode() {
931         return applyCullMode;
932     }
933 
isApplyDepthTest()934     public boolean isApplyDepthTest() {
935         return applyDepthTest;
936     }
937 
isApplyDepthWrite()938     public boolean isApplyDepthWrite() {
939         return applyDepthWrite;
940     }
941 
isApplyPointSprite()942     public boolean isApplyPointSprite() {
943         return applyPointSprite;
944     }
945 
isApplyPolyOffset()946     public boolean isApplyPolyOffset() {
947         return applyPolyOffset;
948     }
949 
isApplyWireFrame()950     public boolean isApplyWireFrame() {
951         return applyWireFrame;
952     }
953 
954     /**
955      * Merges <code>this</code> state and <code>additionalState</code> into
956      * the parameter <code>state</code> based on a specific criteria.
957      *
958      * <p>The criteria for this merge is the following:<br/>
959      * For every given property, such as alpha test or depth write, check
960      * if it was modified from the original in the <code>additionalState</code>
961      * if it was modified, then copy the property from the <code>additionalState</code>
962      * into the parameter <code>state</code>, otherwise, copy the property from <code>this</code>
963      * into the parameter <code>state</code>. If <code>additionalState</code>
964      * is <code>null</code>, then no modifications are made and <code>this</code> is returned,
965      * otherwise, the parameter <code>state</code> is returned with the result
966      * of the merge.
967      *
968      * @param additionalState The <code>additionalState</code>, from which data is taken only
969      * if it was modified by the user.
970      * @param state Contains output of the method if <code>additionalState</code>
971      * is not null.
972      * @return <code>state</code> if <code>additionalState</code> is non-null,
973      * otherwise returns <code>this</code>
974      */
copyMergedTo(RenderState additionalState, RenderState state)975     public RenderState copyMergedTo(RenderState additionalState, RenderState state) {
976         if (additionalState == null) {
977             return this;
978         }
979 
980         if (additionalState.applyPointSprite) {
981             state.pointSprite = additionalState.pointSprite;
982         } else {
983             state.pointSprite = pointSprite;
984         }
985         if (additionalState.applyWireFrame) {
986             state.wireframe = additionalState.wireframe;
987         } else {
988             state.wireframe = wireframe;
989         }
990 
991         if (additionalState.applyCullMode) {
992             state.cullMode = additionalState.cullMode;
993         } else {
994             state.cullMode = cullMode;
995         }
996         if (additionalState.applyDepthWrite) {
997             state.depthWrite = additionalState.depthWrite;
998         } else {
999             state.depthWrite = depthWrite;
1000         }
1001         if (additionalState.applyDepthTest) {
1002             state.depthTest = additionalState.depthTest;
1003         } else {
1004             state.depthTest = depthTest;
1005         }
1006         if (additionalState.applyColorWrite) {
1007             state.colorWrite = additionalState.colorWrite;
1008         } else {
1009             state.colorWrite = colorWrite;
1010         }
1011         if (additionalState.applyBlendMode) {
1012             state.blendMode = additionalState.blendMode;
1013         } else {
1014             state.blendMode = blendMode;
1015         }
1016         if (additionalState.applyAlphaTest) {
1017             state.alphaTest = additionalState.alphaTest;
1018         } else {
1019             state.alphaTest = alphaTest;
1020         }
1021 
1022         if (additionalState.applyAlphaFallOff) {
1023             state.alphaFallOff = additionalState.alphaFallOff;
1024         } else {
1025             state.alphaFallOff = alphaFallOff;
1026         }
1027         if (additionalState.applyPolyOffset) {
1028             state.offsetEnabled = additionalState.offsetEnabled;
1029             state.offsetFactor = additionalState.offsetFactor;
1030             state.offsetUnits = additionalState.offsetUnits;
1031         } else {
1032             state.offsetEnabled = offsetEnabled;
1033             state.offsetFactor = offsetFactor;
1034             state.offsetUnits = offsetUnits;
1035         }
1036         if (additionalState.applyStencilTest){
1037             state.stencilTest = additionalState.stencilTest;
1038 
1039             state.frontStencilStencilFailOperation = additionalState.frontStencilStencilFailOperation;
1040             state.frontStencilDepthFailOperation   = additionalState.frontStencilDepthFailOperation;
1041             state.frontStencilDepthPassOperation   = additionalState.frontStencilDepthPassOperation;
1042 
1043             state.backStencilStencilFailOperation = additionalState.backStencilStencilFailOperation;
1044             state.backStencilDepthFailOperation   = additionalState.backStencilDepthFailOperation;
1045             state.backStencilDepthPassOperation   = additionalState.backStencilDepthPassOperation;
1046 
1047             state.frontStencilFunction = additionalState.frontStencilFunction;
1048             state.backStencilFunction = additionalState.backStencilFunction;
1049         }else{
1050             state.stencilTest = stencilTest;
1051 
1052             state.frontStencilStencilFailOperation = frontStencilStencilFailOperation;
1053             state.frontStencilDepthFailOperation   = frontStencilDepthFailOperation;
1054             state.frontStencilDepthPassOperation   = frontStencilDepthPassOperation;
1055 
1056             state.backStencilStencilFailOperation = backStencilStencilFailOperation;
1057             state.backStencilDepthFailOperation   = backStencilDepthFailOperation;
1058             state.backStencilDepthPassOperation   = backStencilDepthPassOperation;
1059 
1060             state.frontStencilFunction = frontStencilFunction;
1061             state.backStencilFunction = backStencilFunction;
1062         }
1063         return state;
1064     }
1065 
1066     @Override
toString()1067     public String toString() {
1068         return "RenderState[\n" + "pointSprite=" + pointSprite + "\napplyPointSprite=" + applyPointSprite + "\nwireframe=" + wireframe + "\napplyWireFrame=" + applyWireFrame + "\ncullMode=" + cullMode + "\napplyCullMode=" + applyCullMode + "\ndepthWrite=" + depthWrite + "\napplyDepthWrite=" + applyDepthWrite + "\ndepthTest=" + depthTest + "\napplyDepthTest=" + applyDepthTest + "\ncolorWrite=" + colorWrite + "\napplyColorWrite=" + applyColorWrite + "\nblendMode=" + blendMode + "\napplyBlendMode=" + applyBlendMode + "\nalphaTest=" + alphaTest + "\napplyAlphaTest=" + applyAlphaTest + "\nalphaFallOff=" + alphaFallOff + "\napplyAlphaFallOff=" + applyAlphaFallOff + "\noffsetEnabled=" + offsetEnabled + "\napplyPolyOffset=" + applyPolyOffset + "\noffsetFactor=" + offsetFactor + "\noffsetUnits=" + offsetUnits + "\n]";
1069     }
1070 }
1071