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 */
32package com.jme3.material;
33
34import com.jme3.export.*;
35import com.jme3.scene.Mesh;
36import com.jme3.scene.Mesh.Mode;
37import 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 */
47public 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
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
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
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     **/
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
780    public TestFunction getBackStencilFunction() {
781        return backStencilFunction;
782    }
783
784    /**
785     * Retrieve the blend mode.
786     *
787     * @return the blend mode.
788     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
910    public float getAlphaFallOff() {
911        return alphaFallOff;
912    }
913
914    public boolean isApplyAlphaFallOff() {
915        return applyAlphaFallOff;
916    }
917
918    public boolean isApplyAlphaTest() {
919        return applyAlphaTest;
920    }
921
922    public boolean isApplyBlendMode() {
923        return applyBlendMode;
924    }
925
926    public boolean isApplyColorWrite() {
927        return applyColorWrite;
928    }
929
930    public boolean isApplyCullMode() {
931        return applyCullMode;
932    }
933
934    public boolean isApplyDepthTest() {
935        return applyDepthTest;
936    }
937
938    public boolean isApplyDepthWrite() {
939        return applyDepthWrite;
940    }
941
942    public boolean isApplyPointSprite() {
943        return applyPointSprite;
944    }
945
946    public boolean isApplyPolyOffset() {
947        return applyPolyOffset;
948    }
949
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     */
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
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