com.badlogic.gdx.tests.g3d.shadows.system.realistic.MainShader.java Source code

Java tutorial

Introduction

Here is the source code for com.badlogic.gdx.tests.g3d.shadows.system.realistic.MainShader.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.realistic;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Camera;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.graphics.g3d.Attributes;
import com.badlogic.gdx.graphics.g3d.Environment;
import com.badlogic.gdx.graphics.g3d.Renderable;
import com.badlogic.gdx.graphics.g3d.attributes.DirectionalLightsAttribute;
import com.badlogic.gdx.graphics.g3d.attributes.SpotLightsAttribute;
import com.badlogic.gdx.graphics.g3d.environment.DirectionalLight;
import com.badlogic.gdx.graphics.g3d.environment.SpotLight;
import com.badlogic.gdx.graphics.g3d.shaders.DefaultShader;
import com.badlogic.gdx.graphics.glutils.ShaderProgram;
import com.badlogic.gdx.tests.g3d.shadows.system.BaseShadowSystem.LightProperties;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.ObjectMap;

/** This shader is used by the realistic shadow system. This shader supports normal mapping and specular mapping
 * @author realitix */
public class MainShader extends DefaultShader {
    public static class Config extends DefaultShader.Config {
        public RealisticShadowSystem shadowSystem;

        public Config(RealisticShadowSystem shadowSystem) {
            super();
            numBones = 12;
            numPointLights = 2;
            numSpotLights = 5;
            numDirectionalLights = 2;
            this.shadowSystem = shadowSystem;
        }
    }

    /** **** Directional shadow **** */
    protected final int u_dirShadows0uvTransform = register(new Uniform("u_dirShadows[0].uvTransform"));
    protected final int u_dirShadows1uvTransform = register(new Uniform("u_dirShadows[1].uvTransform"));

    protected int dirShadowsLoc;
    protected int dirShadowsUvTransformOffset;
    protected int dirShadowsSize;

    // Shadow projViewTrans
    protected int u_dirShadowMapProjViewTrans0 = register(new Uniform("u_dirShadowMapProjViewTrans[0]"));
    protected int u_dirShadowMapProjViewTrans1 = register(new Uniform("u_dirShadowMapProjViewTrans[1]"));
    protected int dirShadowMapProjViewTransLoc;
    protected int dirShadowMapProjViewTransSize;

    // Shadow UVTransform
    protected int u_dirShadowMapUVTransform0 = register(new Uniform("u_dirShadowMapUVTransform[0]"));
    protected int u_dirShadowMapUVTransform1 = register(new Uniform("u_dirShadowMapUVTransform[1]"));
    protected int dirShadowMapUVTransformLoc;
    protected int dirShadowMapUVTransformSize;

    /** **** Spot shadow **** */
    protected final int u_spotShadows0uvTransform = register(new Uniform("u_spotShadows[0].uvTransform"));
    protected final int u_spotShadows1uvTransform = register(new Uniform("u_spotShadows[1].uvTransform"));

    protected int spotShadowsLoc;
    protected int spotShadowsUvTransformOffset;
    protected int spotShadowsSize;

    // Shadow projViewTrans
    protected int u_spotShadowMapProjViewTrans0 = register(new Uniform("u_spotShadowMapProjViewTrans[0]"));
    protected int u_spotShadowMapProjViewTrans1 = register(new Uniform("u_spotShadowMapProjViewTrans[1]"));
    protected int spotShadowMapProjViewTransLoc;
    protected int spotShadowMapProjViewTransSize;

    // Shadow UVTransform
    protected int u_spotShadowMapUVTransform0 = register(new Uniform("u_spotShadowMapUVTransform[0]"));
    protected int u_spotShadowMapUVTransform1 = register(new Uniform("u_spotShadowMapUVTransform[1]"));
    protected int spotShadowMapUVTransformLoc;
    protected int spotShadowMapUVTransformSize;

    protected RealisticShadowSystem shadowSystem;

    private static String defaultVertexShader = null;

    public static String getDefaultVertexShader() {
        if (defaultVertexShader == null)
            defaultVertexShader = Gdx.files
                    .classpath("com/badlogic/gdx/tests/g3d/shadows/system/realistic/main.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/realistic/main.fragment.glsl")
                    .readString();
        return defaultFragmentShader;
    }

    public static String createPrefix(final Renderable renderable, final Config config) {
        return DefaultShader.createPrefix(renderable, config);
    }

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

    public MainShader(final Renderable renderable, final Config config, final String prefix) {
        this(renderable, config, prefix, getDefaultVertexShader(), getDefaultFragmentShader());
    }

    public MainShader(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 MainShader(final Renderable renderable, final Config config, final ShaderProgram shaderProgram) {
        super(renderable, config, shaderProgram);
        this.shadowSystem = config.shadowSystem;
    }

    @Override
    public void init() {
        super.init();

        // Directional Shadow
        dirShadowsLoc = loc(u_dirShadows0uvTransform);
        dirShadowsUvTransformOffset = loc(u_dirShadows0uvTransform) - dirShadowsLoc;
        dirShadowsSize = loc(u_dirShadows1uvTransform) - dirShadowsLoc;
        if (dirShadowsSize < 0)
            dirShadowsSize = 0;

        dirShadowMapProjViewTransLoc = loc(u_dirShadowMapProjViewTrans0);
        dirShadowMapProjViewTransSize = loc(u_dirShadowMapProjViewTrans1) - dirShadowMapProjViewTransLoc;

        dirShadowMapUVTransformLoc = loc(u_dirShadowMapUVTransform0);
        dirShadowMapUVTransformSize = loc(u_dirShadowMapUVTransform1) - dirShadowMapUVTransformLoc;

        // Spot Shadow
        spotShadowsLoc = loc(u_spotShadows0uvTransform);
        spotShadowsUvTransformOffset = loc(u_spotShadows0uvTransform) - spotShadowsLoc;
        spotShadowsSize = loc(u_spotShadows1uvTransform) - spotShadowsLoc;
        if (spotShadowsSize < 0)
            spotShadowsSize = 0;

        spotShadowMapProjViewTransLoc = loc(u_spotShadowMapProjViewTrans0);
        spotShadowMapProjViewTransSize = loc(u_spotShadowMapProjViewTrans1) - spotShadowMapProjViewTransLoc;

        spotShadowMapUVTransformLoc = loc(u_spotShadowMapUVTransform0);
        spotShadowMapUVTransformSize = loc(u_spotShadowMapUVTransform1) - spotShadowMapUVTransformLoc;
    }

    @Override
    protected void bindLights(final Renderable renderable, final Attributes attributes) {
        super.bindLights(renderable, attributes);
        final Environment environment = renderable.environment;

        bindDirectionalShadows(attributes);
        bindSpotShadows(attributes);

        if (shadowSystem.getTexture() != null) {
            set(u_shadowTexture, shadowSystem.getTexture());
        }
    }

    public void bindDirectionalShadows(final Attributes attributes) {
        final DirectionalLightsAttribute dla = attributes.get(DirectionalLightsAttribute.class,
                DirectionalLightsAttribute.Type);
        final Array<DirectionalLight> dirs = dla == null ? null : dla.lights;

        if (dirLightsLoc >= 0) {
            for (int i = 0; i < directionalLights.length; i++) {
                if (dirs == null || dirs.size <= i) {
                    continue;
                }

                int idx = dirShadowsLoc + i * dirShadowsSize;

                // Shadow
                ObjectMap<DirectionalLight, LightProperties> dirCameras = shadowSystem.getDirectionalCameras();

                DirectionalLight dl = dirs.get(i);
                if (shadowSystem.hasLight(dl)) {
                    // UVTransform
                    final TextureRegion tr = dirCameras.get(dl).region;
                    Camera cam = dirCameras.get(dl).camera;

                    if (cam != null) {
                        program.setUniformf(idx + dirShadowsUvTransformOffset, tr.getU(), tr.getV(),
                                tr.getU2() - tr.getU(), tr.getV2() - tr.getV());

                        // ProjViewTrans
                        idx = dirShadowMapProjViewTransLoc + i * dirShadowMapProjViewTransSize;
                        program.setUniformMatrix(idx, dirCameras.get(dl).camera.combined);
                    }
                }

                if (dirLightsSize <= 0)
                    break;
            }
        }
    }

    public void bindSpotShadows(final Attributes attributes) {
        final SpotLightsAttribute sla = attributes.get(SpotLightsAttribute.class, SpotLightsAttribute.Type);
        final Array<SpotLight> spots = sla == null ? null : sla.lights;

        if (spotLightsLoc >= 0) {
            for (int i = 0; i < spotLights.length; i++) {
                if (spots == null || spots.size <= i) {
                    continue;
                }

                int idx = spotShadowsLoc + i * spotShadowsSize;

                // Shadow
                ObjectMap<SpotLight, LightProperties> spotCameras = shadowSystem.getSpotCameras();

                SpotLight sl = spots.get(i);
                if (shadowSystem.hasLight(sl)) {
                    // UVTransform
                    final TextureRegion tr = spotCameras.get(sl).region;
                    Camera cam = spotCameras.get(sl).camera;

                    if (cam != null) {
                        program.setUniformf(idx + spotShadowsUvTransformOffset, tr.getU(), tr.getV(),
                                tr.getU2() - tr.getU(), tr.getV2() - tr.getV());

                        // ProjViewTrans
                        idx = spotShadowMapProjViewTransLoc + i * spotShadowMapProjViewTransSize;
                        program.setUniformMatrix(idx, spotCameras.get(sl).camera.combined);
                    }
                }

                if (spotLightsSize <= 0)
                    break;
            }
        }
    }
}