gaia.cu9.ari.gaiaorbit.util.override.AtmosphereShader.java Source code

Java tutorial

Introduction

Here is the source code for gaia.cu9.ari.gaiaorbit.util.override.AtmosphereShader.java

Source

package gaia.cu9.ari.gaiaorbit.util.override;

/*******************************************************************************
 * Copyright 2011 See AUTHORS file.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Camera;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.g3d.Attribute;
import com.badlogic.gdx.graphics.g3d.Attributes;
import com.badlogic.gdx.graphics.g3d.Material;
import com.badlogic.gdx.graphics.g3d.Renderable;
import com.badlogic.gdx.graphics.g3d.Shader;
import com.badlogic.gdx.graphics.g3d.attributes.BlendingAttribute;
import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute;
import com.badlogic.gdx.graphics.g3d.attributes.DepthTestAttribute;
import com.badlogic.gdx.graphics.g3d.attributes.FloatAttribute;
import com.badlogic.gdx.graphics.g3d.attributes.IntAttribute;
import com.badlogic.gdx.graphics.g3d.attributes.TextureAttribute;
import com.badlogic.gdx.graphics.g3d.shaders.BaseShader;
import com.badlogic.gdx.graphics.g3d.utils.RenderContext;
import com.badlogic.gdx.graphics.glutils.ShaderProgram;
import com.badlogic.gdx.math.Matrix3;
import com.badlogic.gdx.math.Matrix4;
import com.badlogic.gdx.utils.GdxRuntimeException;

public class AtmosphereShader extends BaseShader {
    public static class Config {
        /** The uber vertex shader to use, null to use the default vertex shader. */
        public String vertexShader = null;
        /** The uber fragment shader to use, null to use the default fragment shader. */
        public String fragmentShader = null;
        /** */
        public boolean ignoreUnimplemented = true;
        /** Set to 0 to disable culling, -1 to inherit from {@link AtmosphereShader#defaultCullFace} */
        public int defaultCullFace = -1;
        /** Set to 0 to disable depth test, -1 to inherit from {@link AtmosphereShader#defaultDepthFunc} */
        public int defaultDepthFunc = -1;

        public Config() {
        }

        public Config(final String vertexShader, final String fragmentShader) {
            this.vertexShader = vertexShader;
            this.fragmentShader = fragmentShader;
        }
    }

    public static class Inputs {
        public final static Uniform projTrans = new Uniform("u_projTrans");
        public final static Uniform viewTrans = new Uniform("u_viewTrans");
        public final static Uniform projViewTrans = new Uniform("u_projViewTrans");
        public final static Uniform cameraPosition = new Uniform("u_cameraPosition");
        public final static Uniform cameraDirection = new Uniform("u_cameraDirection");
        public final static Uniform cameraUp = new Uniform("u_cameraUp");

        public final static Uniform worldTrans = new Uniform("u_worldTrans");
        public final static Uniform viewWorldTrans = new Uniform("u_viewWorldTrans");
        public final static Uniform projViewWorldTrans = new Uniform("u_projViewWorldTrans");
        public final static Uniform normalMatrix = new Uniform("u_normalMatrix");

        public final static Uniform alpha = new Uniform("fAlpha");
        public final static Uniform colorOpacity = new Uniform("fColorOpacity");
        public final static Uniform cameraHeight = new Uniform("fCameraHeight");
        public final static Uniform cameraHeight2 = new Uniform("fCameraHeight2");
        public final static Uniform outerRadius = new Uniform("fOuterRadius");
        public final static Uniform outerRadius2 = new Uniform("fOuterRadius2");
        public final static Uniform innerRadius = new Uniform("fInnerRadius");
        public final static Uniform innerRadius2 = new Uniform("fInnerRadius2");
        public final static Uniform krESun = new Uniform("fKrESun");
        public final static Uniform kmESun = new Uniform("fKmESun");
        public final static Uniform kr4PI = new Uniform("fKr4PI");
        public final static Uniform km4PI = new Uniform("fKm4PI");
        public final static Uniform scale = new Uniform("fScale");
        public final static Uniform scaleDepth = new Uniform("fScaleDepth");
        public final static Uniform scaleOverScaleDepth = new Uniform("fScaleOverScaleDepth");
        public final static Uniform nSamples = new Uniform("nSamples");
        public final static Uniform fSamples = new Uniform("fSamples");
        public final static Uniform g = new Uniform("g");
        public final static Uniform g2 = new Uniform("g2");

        public final static Uniform planetPos = new Uniform("v3PlanetPos");
        public final static Uniform lightPos = new Uniform("v3LightPos");
        public final static Uniform cameraPos = new Uniform("v3CameraPos");
        public final static Uniform invWavelength = new Uniform("v3InvWavelength");

    }

    public static class Setters {
        public final static Setter projTrans = new Setter() {
            @Override
            public boolean isGlobal(BaseShader shader, int inputID) {
                return true;
            }

            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                shader.set(inputID, shader.camera.projection);
            }
        };
        public final static Setter viewTrans = new Setter() {
            @Override
            public boolean isGlobal(BaseShader shader, int inputID) {
                return true;
            }

            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                shader.set(inputID, shader.camera.view);
            }
        };
        public final static Setter projViewTrans = new Setter() {
            @Override
            public boolean isGlobal(BaseShader shader, int inputID) {
                return true;
            }

            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                shader.set(inputID, shader.camera.combined);
            }
        };
        public final static Setter cameraPosition = new Setter() {
            @Override
            public boolean isGlobal(BaseShader shader, int inputID) {
                return true;
            }

            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                shader.set(inputID, shader.camera.position.x, shader.camera.position.y, shader.camera.position.z,
                        1.1881f / (shader.camera.far * shader.camera.far));
            }
        };
        public final static Setter cameraDirection = new Setter() {
            @Override
            public boolean isGlobal(BaseShader shader, int inputID) {
                return true;
            }

            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                shader.set(inputID, shader.camera.direction);
            }
        };
        public final static Setter cameraUp = new Setter() {
            @Override
            public boolean isGlobal(BaseShader shader, int inputID) {
                return true;
            }

            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                shader.set(inputID, shader.camera.up);
            }
        };
        public final static Setter worldTrans = new Setter() {
            @Override
            public boolean isGlobal(BaseShader shader, int inputID) {
                return false;
            }

            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                shader.set(inputID, renderable.worldTransform);
            }
        };
        public final static Setter viewWorldTrans = new Setter() {
            final Matrix4 temp = new Matrix4();

            @Override
            public boolean isGlobal(BaseShader shader, int inputID) {
                return false;
            }

            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                shader.set(inputID, temp.set(shader.camera.view).mul(renderable.worldTransform));
            }
        };
        public final static Setter projViewWorldTrans = new Setter() {
            final Matrix4 temp = new Matrix4();

            @Override
            public boolean isGlobal(BaseShader shader, int inputID) {
                return false;
            }

            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                shader.set(inputID, temp.set(shader.camera.combined).mul(renderable.worldTransform));
            }
        };
        public final static Setter normalMatrix = new Setter() {
            private final Matrix3 tmpM = new Matrix3();

            @Override
            public boolean isGlobal(BaseShader shader, int inputID) {
                return false;
            }

            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                shader.set(inputID, tmpM.set(renderable.worldTransform).inv().transpose());
            }
        };

        public final static Setter alpha = new Setter() {
            @Override
            public boolean isGlobal(BaseShader shader, int inputID) {
                return false;
            }

            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                shader.set(inputID,
                        ((AtmosphereAttribute) (combinedAttributes.get(AtmosphereAttribute.Alpha))).value);
            }
        };

        public final static Setter colorOpacity = new Setter() {
            @Override
            public boolean isGlobal(BaseShader shader, int inputID) {
                return false;
            }

            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                shader.set(inputID,
                        ((AtmosphereAttribute) (combinedAttributes.get(AtmosphereAttribute.ColorOpacity))).value);
            }
        };

        public final static Setter cameraHeight = new Setter() {
            @Override
            public boolean isGlobal(BaseShader shader, int inputID) {
                return false;
            }

            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                shader.set(inputID,
                        ((AtmosphereAttribute) (combinedAttributes.get(AtmosphereAttribute.CameraHeight))).value);
            }
        };

        public final static Setter cameraHeight2 = new Setter() {
            @Override
            public boolean isGlobal(BaseShader shader, int inputID) {
                return false;
            }

            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                shader.set(inputID,
                        ((AtmosphereAttribute) (combinedAttributes.get(AtmosphereAttribute.CameraHeight2))).value);
            }
        };

        public final static Setter outerRadius = new Setter() {
            @Override
            public boolean isGlobal(BaseShader shader, int inputID) {
                return false;
            }

            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                shader.set(inputID,
                        ((AtmosphereAttribute) (combinedAttributes.get(AtmosphereAttribute.OuterRadius))).value);
            }
        };

        public final static Setter outerRadius2 = new Setter() {
            @Override
            public boolean isGlobal(BaseShader shader, int inputID) {
                return false;
            }

            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                shader.set(inputID,
                        ((AtmosphereAttribute) (combinedAttributes.get(AtmosphereAttribute.OuterRadius2))).value);
            }
        };

        public final static Setter innerRadius = new Setter() {
            @Override
            public boolean isGlobal(BaseShader shader, int inputID) {
                return false;
            }

            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                shader.set(inputID,
                        ((AtmosphereAttribute) (combinedAttributes.get(AtmosphereAttribute.InnerRadius))).value);
            }
        };

        public final static Setter innerRadius2 = new Setter() {
            @Override
            public boolean isGlobal(BaseShader shader, int inputID) {
                return false;
            }

            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                shader.set(inputID,
                        ((AtmosphereAttribute) (combinedAttributes.get(AtmosphereAttribute.InnerRadius2))).value);
            }
        };

        public final static Setter krESun = new Setter() {
            @Override
            public boolean isGlobal(BaseShader shader, int inputID) {
                return false;
            }

            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                shader.set(inputID,
                        ((AtmosphereAttribute) (combinedAttributes.get(AtmosphereAttribute.KrESun))).value);
            }
        };

        public final static Setter kmESun = new Setter() {
            @Override
            public boolean isGlobal(BaseShader shader, int inputID) {
                return false;
            }

            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                shader.set(inputID,
                        ((AtmosphereAttribute) (combinedAttributes.get(AtmosphereAttribute.KmESun))).value);
            }
        };

        public final static Setter kr4PI = new Setter() {
            @Override
            public boolean isGlobal(BaseShader shader, int inputID) {
                return false;
            }

            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                shader.set(inputID,
                        ((AtmosphereAttribute) (combinedAttributes.get(AtmosphereAttribute.Kr4PI))).value);
            }
        };

        public final static Setter km4PI = new Setter() {
            @Override
            public boolean isGlobal(BaseShader shader, int inputID) {
                return false;
            }

            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                shader.set(inputID,
                        ((AtmosphereAttribute) (combinedAttributes.get(AtmosphereAttribute.Km4PI))).value);
            }
        };

        public final static Setter scale = new Setter() {
            @Override
            public boolean isGlobal(BaseShader shader, int inputID) {
                return false;
            }

            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                shader.set(inputID,
                        ((AtmosphereAttribute) (combinedAttributes.get(AtmosphereAttribute.Scale))).value);
            }
        };

        public final static Setter scaleDepth = new Setter() {
            @Override
            public boolean isGlobal(BaseShader shader, int inputID) {
                return false;
            }

            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                shader.set(inputID,
                        ((AtmosphereAttribute) (combinedAttributes.get(AtmosphereAttribute.ScaleDepth))).value);
            }
        };

        public final static Setter scaleOverScaleDepth = new Setter() {
            @Override
            public boolean isGlobal(BaseShader shader, int inputID) {
                return false;
            }

            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                shader.set(inputID, ((AtmosphereAttribute) (combinedAttributes
                        .get(AtmosphereAttribute.ScaleOverScaleDepth))).value);
            }
        };

        public final static Setter nSamples = new Setter() {
            @Override
            public boolean isGlobal(BaseShader shader, int inputID) {
                return false;
            }

            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                shader.set(inputID,
                        (int) ((AtmosphereAttribute) (combinedAttributes.get(AtmosphereAttribute.nSamples))).value);
            }
        };

        public final static Setter fSamples = new Setter() {
            @Override
            public boolean isGlobal(BaseShader shader, int inputID) {
                return false;
            }

            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                shader.set(inputID,
                        ((AtmosphereAttribute) (combinedAttributes.get(AtmosphereAttribute.fSamples))).value);
            }
        };

        public final static Setter g = new Setter() {
            @Override
            public boolean isGlobal(BaseShader shader, int inputID) {
                return false;
            }

            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                shader.set(inputID, ((AtmosphereAttribute) (combinedAttributes.get(AtmosphereAttribute.G))).value);
            }
        };

        public final static Setter g2 = new Setter() {
            @Override
            public boolean isGlobal(BaseShader shader, int inputID) {
                return false;
            }

            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                shader.set(inputID, ((AtmosphereAttribute) (combinedAttributes.get(AtmosphereAttribute.G2))).value);
            }
        };
        public final static Setter planetPos = new Setter() {
            @Override
            public boolean isGlobal(BaseShader shader, int inputID) {
                return false;
            }

            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                shader.set(inputID,
                        ((Vector3Attribute) (combinedAttributes.get(Vector3Attribute.PlanetPos))).value);
            }
        };
        public final static Setter cameraPos = new Setter() {
            @Override
            public boolean isGlobal(BaseShader shader, int inputID) {
                return false;
            }

            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                shader.set(inputID,
                        ((Vector3Attribute) (combinedAttributes.get(Vector3Attribute.CameraPos))).value);
            }
        };
        public final static Setter lightPos = new Setter() {
            @Override
            public boolean isGlobal(BaseShader shader, int inputID) {
                return false;
            }

            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                shader.set(inputID, ((Vector3Attribute) (combinedAttributes.get(Vector3Attribute.LightPos))).value);
            }
        };
        public final static Setter invWavelength = new Setter() {
            @Override
            public boolean isGlobal(BaseShader shader, int inputID) {
                return false;
            }

            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                shader.set(inputID,
                        ((Vector3Attribute) (combinedAttributes.get(Vector3Attribute.InvWavelength))).value);
            }
        };

    }

    private static String defaultVertexShader = null;

    public static String getDefaultVertexShader() {
        if (defaultVertexShader == null)
            defaultVertexShader = Gdx.files.classpath("com/badlogic/gdx/graphics/g3d/shaders/default.vertex.glsl")
                    .readString();
        return defaultVertexShader;
    }

    private static String defaultFragmentShader = null;

    public static String getDefaultFragmentShader() {
        if (defaultFragmentShader == null)
            defaultFragmentShader = Gdx.files
                    .classpath("com/badlogic/gdx/graphics/g3d/shaders/default.fragment.glsl").readString();
        return defaultFragmentShader;
    }

    protected static long implementedFlags = BlendingAttribute.Type | TextureAttribute.Diffuse
            | ColorAttribute.Diffuse | ColorAttribute.Specular | FloatAttribute.Shininess;

    /** @deprecated Replaced by {@link Config#defaultCullFace} Set to 0 to disable culling */
    @Deprecated
    public static int defaultCullFace = GL20.GL_BACK;
    /** @deprecated Replaced by {@link Config#defaultDepthFunc} Set to 0 to disable depth test */
    @Deprecated
    public static int defaultDepthFunc = GL20.GL_LEQUAL;

    // Global uniforms
    public final int u_projTrans;
    public final int u_viewTrans;
    public final int u_projViewTrans;
    public final int u_cameraPosition;
    public final int u_cameraDirection;
    public final int u_cameraUp;
    // Object uniforms
    public final int u_worldTrans;
    public final int u_viewWorldTrans;
    public final int u_projViewWorldTrans;
    public final int u_normalMatrix;
    // Material uniforms
    public final int fAlpha;
    public final int fColorOpacity;
    public final int fCameraHeight;
    public final int fCameraHeight2;
    public final int fOuterRadius;
    public final int fOuterRadius2;
    public final int fInnerRadius;
    public final int fInnerRadius2;
    public final int fKrESun;
    public final int fKmESun;
    public final int fKr4PI;
    public final int fKm4PI;
    public final int fScale;
    public final int fScaleDepth;
    public final int fScaleOverScaleDepth;

    public final int nSamples;
    public final int fSamples;

    public final int g;
    public final int g2;

    public final int v3PlanetPos;
    public final int v3LightPos;
    public final int v3CameraPos;
    public final int v3InvWavelength;

    /** The renderable used to create this shader, invalid after the call to init */
    private Renderable renderable;
    private long materialMask;
    protected final Config config;
    /** Material attributes which are not required but always supported. */
    private final static long optionalAttributes = IntAttribute.CullFace | DepthTestAttribute.Type;

    public AtmosphereShader(final Renderable renderable) {
        this(renderable, new Config());
    }

    public AtmosphereShader(final Renderable renderable, final Config config) {
        this(renderable, config, createPrefix(renderable, config));
    }

    public AtmosphereShader(final Renderable renderable, final Config config, final String prefix) {
        this(renderable, config, prefix,
                config.vertexShader != null ? config.vertexShader : getDefaultVertexShader(),
                config.fragmentShader != null ? config.fragmentShader : getDefaultFragmentShader());
    }

    public AtmosphereShader(final Renderable renderable, final Config config, final String prefix,
            final String vertexShader, final String fragmentShader) {
        this(renderable, config, new ShaderProgram(prefix + vertexShader, prefix + fragmentShader));
    }

    public AtmosphereShader(final Renderable renderable, final Config config, final ShaderProgram shaderProgram) {
        this.config = config;
        this.program = shaderProgram;
        this.renderable = renderable;
        materialMask = renderable.material.getMask() | optionalAttributes;

        if (!config.ignoreUnimplemented && (implementedFlags & materialMask) != materialMask)
            throw new GdxRuntimeException("Some attributes not implemented yet (" + materialMask + ")");

        // Global uniforms
        u_projTrans = register(Inputs.projTrans, Setters.projTrans);
        u_viewTrans = register(Inputs.viewTrans, Setters.viewTrans);
        u_projViewTrans = register(Inputs.projViewTrans, Setters.projViewTrans);
        u_cameraPosition = register(Inputs.cameraPosition, Setters.cameraPosition);
        u_cameraDirection = register(Inputs.cameraDirection, Setters.cameraDirection);
        u_cameraUp = register(Inputs.cameraUp, Setters.cameraUp);

        // Object uniforms
        u_worldTrans = register(Inputs.worldTrans, Setters.worldTrans);
        u_viewWorldTrans = register(Inputs.viewWorldTrans, Setters.viewWorldTrans);
        u_projViewWorldTrans = register(Inputs.projViewWorldTrans, Setters.projViewWorldTrans);
        u_normalMatrix = register(Inputs.normalMatrix, Setters.normalMatrix);

        fAlpha = register(Inputs.alpha, Setters.alpha);
        fColorOpacity = register(Inputs.colorOpacity, Setters.colorOpacity);
        fCameraHeight = register(Inputs.cameraHeight, Setters.cameraHeight);
        fCameraHeight2 = register(Inputs.cameraHeight2, Setters.cameraHeight2);
        fOuterRadius = register(Inputs.outerRadius, Setters.outerRadius);
        fOuterRadius2 = register(Inputs.outerRadius2, Setters.outerRadius2);
        fInnerRadius = register(Inputs.innerRadius, Setters.innerRadius);
        fInnerRadius2 = register(Inputs.innerRadius2, Setters.innerRadius2);
        fKrESun = register(Inputs.krESun, Setters.krESun);
        fKmESun = register(Inputs.kmESun, Setters.kmESun);
        fKr4PI = register(Inputs.kr4PI, Setters.kr4PI);
        fKm4PI = register(Inputs.km4PI, Setters.km4PI);
        fScale = register(Inputs.scale, Setters.scale);
        fScaleDepth = register(Inputs.scaleDepth, Setters.scaleDepth);
        fScaleOverScaleDepth = register(Inputs.scaleOverScaleDepth, Setters.scaleOverScaleDepth);
        nSamples = register(Inputs.nSamples, Setters.nSamples);
        fSamples = register(Inputs.fSamples, Setters.fSamples);

        g = register(Inputs.g, Setters.g);
        g2 = register(Inputs.g2, Setters.g2);

        v3PlanetPos = register(Inputs.planetPos, Setters.planetPos);
        v3CameraPos = register(Inputs.cameraPos, Setters.cameraPos);
        v3LightPos = register(Inputs.lightPos, Setters.lightPos);
        v3InvWavelength = register(Inputs.invWavelength, Setters.invWavelength);

    }

    @Override
    public void init() {
        final ShaderProgram program = this.program;
        this.program = null;
        init(program, renderable);
        renderable = null;

    }

    public static String createPrefix(final Renderable renderable, final Config config) {
        String prefix = "";
        return prefix;
    }

    @Override
    public boolean canRender(final Renderable renderable) {
        return true;
    }

    @Override
    public int compareTo(Shader other) {
        if (other == null)
            return -1;
        if (other == this)
            return 0;
        return 0;
    }

    @Override
    public boolean equals(Object obj) {
        return (obj instanceof AtmosphereShader) ? equals((AtmosphereShader) obj) : false;
    }

    public boolean equals(AtmosphereShader obj) {
        return (obj == this);
    }

    @Override
    public int hashCode() {
        return super.hashCode();
    }

    @Override
    public void begin(final Camera camera, final RenderContext context) {
        super.begin(camera, context);

    }

    @Override
    public void render(final Renderable renderable) {
        if (!renderable.material.has(BlendingAttribute.Type))
            context.setBlending(false, GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
        bindMaterial(renderable);
        super.render(renderable);
    }

    @Override
    public void end() {
        currentMaterial = null;
        super.end();
    }

    Material currentMaterial;

    protected void bindMaterial(final Renderable renderable) {
        if (currentMaterial == renderable.material)
            return;

        int cullFace = config.defaultCullFace == -1 ? defaultCullFace : config.defaultCullFace;
        int depthFunc = config.defaultDepthFunc == -1 ? defaultDepthFunc : config.defaultDepthFunc;
        float depthRangeNear = 0f;
        float depthRangeFar = 1f;
        boolean depthMask = true;

        currentMaterial = renderable.material;
        for (final Attribute attr : currentMaterial) {
            final long t = attr.type;
            if (BlendingAttribute.is(t)) {
                context.setBlending(true, ((BlendingAttribute) attr).sourceFunction,
                        ((BlendingAttribute) attr).destFunction);
            } else if ((t & IntAttribute.CullFace) == IntAttribute.CullFace)
                cullFace = ((IntAttribute) attr).value;
            else if ((t & DepthTestAttribute.Type) == DepthTestAttribute.Type) {
                DepthTestAttribute dta = (DepthTestAttribute) attr;
                depthFunc = dta.depthFunc;
                depthRangeNear = dta.depthRangeNear;
                depthRangeFar = dta.depthRangeFar;
                depthMask = dta.depthMask;
            } else if (!config.ignoreUnimplemented)
                throw new GdxRuntimeException("Unknown material attribute: " + attr.toString());
        }

        context.setCullFace(cullFace);
        context.setDepthTest(depthFunc, depthRangeNear, depthRangeFar);
        context.setDepthMask(depthMask);
    }

    @Override
    public void dispose() {
        program.dispose();
        super.dispose();
    }

    public int getDefaultCullFace() {
        return config.defaultCullFace == -1 ? defaultCullFace : config.defaultCullFace;
    }

    public void setDefaultCullFace(int cullFace) {
        config.defaultCullFace = cullFace;
    }

    public int getDefaultDepthFunc() {
        return config.defaultDepthFunc == -1 ? defaultDepthFunc : config.defaultDepthFunc;
    }

    public void setDefaultDepthFunc(int depthFunc) {
        config.defaultDepthFunc = depthFunc;
    }

}