com.badlogic.gdx.tests.g3d.shadows.system.classical.Pass2Shader.java Source code

Java tutorial

Introduction

Here is the source code for com.badlogic.gdx.tests.g3d.shadows.system.classical.Pass2Shader.java

Source

/*******************************************************************************
 * 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.
 ******************************************************************************/

package com.badlogic.gdx.tests.g3d.shadows.system.classical;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.PerspectiveCamera;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.graphics.g3d.Attributes;
import com.badlogic.gdx.graphics.g3d.Renderable;
import com.badlogic.gdx.graphics.g3d.attributes.BlendingAttribute;
import com.badlogic.gdx.graphics.g3d.attributes.DepthTestAttribute;
import com.badlogic.gdx.graphics.g3d.environment.BaseLight;
import com.badlogic.gdx.graphics.g3d.environment.DirectionalLight;
import com.badlogic.gdx.graphics.g3d.environment.PointLight;
import com.badlogic.gdx.graphics.g3d.environment.SpotLight;
import com.badlogic.gdx.graphics.g3d.shaders.BaseShader;
import com.badlogic.gdx.graphics.g3d.shaders.DefaultShader;
import com.badlogic.gdx.graphics.glutils.ShaderProgram;

/** This shader accumulates shadow with blending
 * @author realitix */
public class Pass2Shader extends DefaultShader {
    public static class Config extends DefaultShader.Config {
        public ClassicalShadowSystem shadowSystem;

        public Config(ClassicalShadowSystem shadowSystem) {
            super();
            this.shadowSystem = shadowSystem;
        }
    }

    public static class Inputs extends DefaultShader.Inputs {
        public final static Uniform shadowMapProjViewTrans = new Uniform("u_shadowMapProjViewTrans");
        public final static Uniform shadowTexture = new Uniform("u_shadowTexture");
        public final static Uniform uvTransform = new Uniform("u_uvTransform");
        public final static Uniform lightColor = new Uniform("u_lightColor");
        public final static Uniform lightDirection = new Uniform("u_lightDirection");
        public final static Uniform lightIntensity = new Uniform("u_lightIntensity");
        public final static Uniform lightPosition = new Uniform("u_lightPosition");
        public final static Uniform lightCutoffAngle = new Uniform("u_lightCutoffAngle");
        public final static Uniform lightExponent = new Uniform("u_lightExponent");
    }

    public static class Setters extends DefaultShader.Setters {
        public final static Setter shadowMapProjViewTrans = new GlobalSetter() {
            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                shader.set(inputID, shadowSystem.getCurrentLightProperties().camera.combined);
            }
        };
        public final static Setter shadowTexture = new GlobalSetter() {
            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                shader.set(inputID, shadowSystem.getTexture(0));
            }
        };
        public final static Setter uvTransform = new GlobalSetter() {
            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                final TextureRegion tr = shadowSystem.getCurrentLightProperties().region;
                shader.set(inputID, tr.getU(), tr.getV(), tr.getU2() - tr.getU(), tr.getV2() - tr.getV());
            }
        };
        public final static Setter lightColor = new GlobalSetter() {
            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                BaseLight l = shadowSystem.getCurrentLight();
                float intensity = 1;
                if (l instanceof PointLight)
                    intensity = ((PointLight) l).intensity;
                if (l instanceof SpotLight)
                    intensity = ((SpotLight) l).intensity;
                shader.set(inputID, l.color.r * intensity, l.color.g * intensity, l.color.b * intensity);
            }
        };
        public final static Setter lightDirection = new GlobalSetter() {
            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                BaseLight l = shadowSystem.getCurrentLight();
                if (l instanceof DirectionalLight) {
                    shader.set(inputID, ((DirectionalLight) l).direction);
                }
                if (l instanceof SpotLight) {
                    shader.set(inputID, ((SpotLight) l).direction);
                }
                if (l instanceof PointLight) {
                    shader.set(inputID, shadowSystem.getCurrentLightProperties().camera.direction);
                }
            }
        };
        public final static Setter lightIntensity = new GlobalSetter() {
            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                BaseLight l = shadowSystem.getCurrentLight();
                if (l instanceof PointLight) {
                    shader.set(inputID, ((PointLight) l).intensity);
                }
                if (l instanceof SpotLight) {
                    shader.set(inputID, ((SpotLight) l).intensity);
                }
            }
        };
        public final static Setter lightPosition = new GlobalSetter() {
            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                BaseLight l = shadowSystem.getCurrentLight();
                if (l instanceof PointLight) {
                    shader.set(inputID, ((PointLight) l).position);
                }
                if (l instanceof SpotLight) {
                    shader.set(inputID, ((SpotLight) l).position);
                }
            }
        };
        public final static Setter lightCutoffAngle = new GlobalSetter() {
            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                if (!(shadowSystem.getCurrentLight() instanceof DirectionalLight)) {
                    shader.set(inputID,
                            ((PerspectiveCamera) shadowSystem.getCurrentLightProperties().camera).fieldOfView);
                }

            }
        };
        public final static Setter lightExponent = new GlobalSetter() {
            @Override
            public void set(BaseShader shader, int inputID, Renderable renderable, Attributes combinedAttributes) {
                BaseLight l = shadowSystem.getCurrentLight();
                if (l instanceof SpotLight) {
                    shader.set(inputID, ((SpotLight) l).exponent);
                }
                if (l instanceof PointLight) {
                    shader.set(inputID, (float) 0);
                }
            }
        };
    }

    protected static ClassicalShadowSystem shadowSystem;
    private static String defaultVertexShader = null;

    public static String getDefaultVertexShader() {
        if (defaultVertexShader == null)
            defaultVertexShader = Gdx.files
                    .classpath("com/badlogic/gdx/tests/g3d/shadows/system/classical/pass2.vertex.glsl")
                    .readString();
        return defaultVertexShader;
    }

    private static String defaultFragmentShader = null;

    public static String getDefaultFragmentShader() {
        if (defaultFragmentShader == null)
            defaultFragmentShader = Gdx.files
                    .classpath("com/badlogic/gdx/tests/g3d/shadows/system/classical/pass2.fragment.glsl")
                    .readString();
        return defaultFragmentShader;
    }

    protected BlendingAttribute blend = new BlendingAttribute(GL20.GL_ONE, GL20.GL_ONE);
    protected DepthTestAttribute depth = new DepthTestAttribute(GL20.GL_LEQUAL);
    protected int lightType = -1;
    public static final int LIGHT_SPOT = 0;
    public static final int LIGHT_DIR = 1;

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

    public Pass2Shader(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 Pass2Shader(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 Pass2Shader(final Renderable renderable, final Config config, final ShaderProgram shaderProgram) {
        super(renderable, config, shaderProgram);
        shadowSystem = config.shadowSystem;
        register(Inputs.shadowMapProjViewTrans, Setters.shadowMapProjViewTrans);
        register(Inputs.shadowTexture, Setters.shadowTexture);
        register(Inputs.uvTransform, Setters.uvTransform);
        register(Inputs.lightColor, Setters.lightColor);
        register(Inputs.lightDirection, Setters.lightDirection);
        register(Inputs.lightPosition, Setters.lightPosition);
        register(Inputs.lightIntensity, Setters.lightIntensity);
        register(Inputs.lightCutoffAngle, Setters.lightCutoffAngle);
        register(Inputs.lightExponent, Setters.lightExponent);
    }

    public static String createPrefix(final Renderable renderable, final Config config) {
        String prefix = DefaultShader.createPrefix(renderable, config);
        boolean dir = (config.shadowSystem.getCurrentLight() instanceof DirectionalLight);
        if (dir)
            prefix += "#define directionalLight\n";
        else
            prefix += "#define spotLight\n";
        return prefix;
    }

    @Override
    public void render(Renderable renderable, Attributes combinedAttributes) {
        if (shadowSystem.isFirstCallPass2())
            combinedAttributes.remove(BlendingAttribute.Type);
        else
            combinedAttributes.set(blend);

        combinedAttributes.set(depth);

        super.render(renderable, combinedAttributes);
    }

    @Override
    public boolean canRender(Renderable renderable) {
        boolean ok = super.canRender(renderable);
        boolean dir = (shadowSystem.getCurrentLight() instanceof DirectionalLight);

        if (lightType == -1) {
            lightType = LIGHT_SPOT;
            if (dir)
                lightType = LIGHT_DIR;
        }

        if (dir && lightType != LIGHT_DIR)
            ok = false;
        if (!dir && lightType != LIGHT_SPOT)
            ok = false;
        return ok;
    }

}