org.terasology.rendering.ShaderManagerLwjgl.java Source code

Java tutorial

Introduction

Here is the source code for org.terasology.rendering.ShaderManagerLwjgl.java

Source

/*
 * Copyright 2013 MovingBlocks
 *
 * 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 org.terasology.rendering;

import org.lwjgl.LWJGLUtil;
import org.lwjgl.Sys;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL13;
import org.lwjgl.opengl.GL20;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.terasology.asset.AssetManager;
import org.terasology.asset.AssetType;
import org.terasology.asset.AssetUri;
import org.terasology.asset.Assets;
import org.terasology.registry.CoreRegistry;
import org.terasology.rendering.assets.material.Material;
import org.terasology.rendering.assets.material.MaterialData;
import org.terasology.rendering.assets.shader.Shader;
import org.terasology.rendering.assets.texture.Texture;
import org.terasology.rendering.opengl.GLSLMaterial;
import org.terasology.rendering.shader.ShaderParameters;
import org.terasology.rendering.shader.ShaderParametersBlock;
import org.terasology.rendering.shader.ShaderParametersChunk;
import org.terasology.rendering.shader.ShaderParametersCombine;
import org.terasology.rendering.shader.ShaderParametersDebug;
import org.terasology.rendering.shader.ShaderParametersDefault;
import org.terasology.rendering.shader.ShaderParametersHdr;
import org.terasology.rendering.shader.ShaderParametersLightBufferPass;
import org.terasology.rendering.shader.ShaderParametersLightGeometryPass;
import org.terasology.rendering.shader.ShaderParametersLightShaft;
import org.terasology.rendering.shader.ShaderParametersOcDistortion;
import org.terasology.rendering.shader.ShaderParametersParticle;
import org.terasology.rendering.shader.ShaderParametersPost;
import org.terasology.rendering.shader.ShaderParametersPrePost;
import org.terasology.rendering.shader.ShaderParametersSSAO;
import org.terasology.rendering.shader.ShaderParametersShadowMap;
import org.terasology.rendering.shader.ShaderParametersSky;
import org.terasology.rendering.shader.ShaderParametersSobel;

import static com.google.common.base.Preconditions.checkNotNull;

/**
 * Provides support for loading and applying shaders.
 *
 * @author Benjamin Glatzel <benjamin.glatzel@me.com>
 */
public class ShaderManagerLwjgl implements ShaderManager {

    private static final Logger logger = LoggerFactory.getLogger(ShaderManagerLwjgl.class);

    private GLSLMaterial activeMaterial;
    private GLSLMaterial defaultShaderProgram;
    private GLSLMaterial defaultTexturedShaderProgram;

    public ShaderManagerLwjgl() {
        logger.info("Loading Terasology shader manager...");
        logger.info("LWJGL: {} / {}", Sys.getVersion(), LWJGLUtil.getPlatformName());
        logger.info("GL_VENDOR: {}", GL11.glGetString(GL11.GL_VENDOR));
        logger.info("GL_RENDERER: {}", GL11.glGetString(GL11.GL_RENDERER));
        logger.info("GL_VERSION: {}", GL11.glGetString(GL11.GL_VERSION));
        logger.info("SHADING_LANGUAGE VERSION: {}", GL11.glGetString(GL20.GL_SHADING_LANGUAGE_VERSION));

        String extStr = GL11.glGetString(GL11.GL_EXTENSIONS);

        // log shader extensions in smaller packages, 
        // because the full string can be extremely long 
        int extsPerLine = 8;

        // starting with OpenGL 3.0, extensions can also listed using
        // GL_NUM_EXTENSIONS and glGetStringi(GL_EXTENSIONS, idx)
        String[] exts = extStr.split(" ");
        if (exts.length > 0) {
            StringBuilder bldr = new StringBuilder(exts[0]);
            for (int i = 1; i < exts.length; i++) {
                if (i % extsPerLine == 0) {
                    logger.info("EXTENSIONS: {}", bldr.toString());
                    bldr.setLength(0);
                } else {
                    bldr.append(" ");
                }
                bldr.append(exts[i]);
            }
            if (bldr.length() > 0) {
                logger.info("EXTENSIONS: {}", bldr.toString());
            }
        }
    }

    @Override
    public void initShaders() {
        defaultShaderProgram = prepareAndStoreShaderProgramInstance("default", new ShaderParametersDefault());
        defaultTexturedShaderProgram = prepareAndStoreShaderProgramInstance("defaultTextured",
                new ShaderParametersDefault());

        // TODO: Find a better way to do this
        prepareAndStoreShaderProgramInstance("post", new ShaderParametersPost());
        prepareAndStoreShaderProgramInstance("ssao", new ShaderParametersSSAO());
        prepareAndStoreShaderProgramInstance("lightshaft", new ShaderParametersLightShaft());
        prepareAndStoreShaderProgramInstance("sobel", new ShaderParametersSobel());
        prepareAndStoreShaderProgramInstance("prePost", new ShaderParametersPrePost());
        prepareAndStoreShaderProgramInstance("combine", new ShaderParametersCombine());
        prepareAndStoreShaderProgramInstance("highp", new ShaderParametersDefault());
        prepareAndStoreShaderProgramInstance("blur", new ShaderParametersDefault());
        prepareAndStoreShaderProgramInstance("down", new ShaderParametersDefault());
        prepareAndStoreShaderProgramInstance("hdr", new ShaderParametersHdr());
        prepareAndStoreShaderProgramInstance("sky", new ShaderParametersSky());
        prepareAndStoreShaderProgramInstance("chunk", new ShaderParametersChunk());
        prepareAndStoreShaderProgramInstance("particle", new ShaderParametersParticle());
        prepareAndStoreShaderProgramInstance("block", new ShaderParametersBlock());
        prepareAndStoreShaderProgramInstance("shadowMap", new ShaderParametersShadowMap());
        prepareAndStoreShaderProgramInstance("debug", new ShaderParametersDebug());
        prepareAndStoreShaderProgramInstance("ocDistortion", new ShaderParametersOcDistortion());
        prepareAndStoreShaderProgramInstance("lightBufferPass", new ShaderParametersLightBufferPass());
        prepareAndStoreShaderProgramInstance("lightGeometryPass", new ShaderParametersLightGeometryPass());
        prepareAndStoreShaderProgramInstance("simple", new ShaderParametersDefault());
        prepareAndStoreShaderProgramInstance("ssaoBlur", new ShaderParametersDefault());
    }

    @Override
    public void setActiveMaterial(Material material) {
        // TODO: is this the best way to convert the material to the lwjgl version?  Do we need more checks?
        GLSLMaterial glslMaterial = (GLSLMaterial) material;
        if (!glslMaterial.equals(activeMaterial)) {
            activeMaterial = glslMaterial;
        }
    }

    @Override
    public void bindTexture(int slot, Texture texture) {
        if (activeMaterial != null && !activeMaterial.isDisposed()) {
            GL13.glActiveTexture(GL13.GL_TEXTURE0 + slot);
            // TODO: Need to be cubemap aware, only need to clear bind when switching from cubemap to 2D and vice versa,
            // TODO: Don't bind if already bound to the same
            GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture.getId());
            GL13.glActiveTexture(GL13.GL_TEXTURE0);
        }
    }

    @Override
    public Material getActiveMaterial() {
        return activeMaterial;
    }

    @Override
    public void recompileAllShaders() {
        for (Shader shader : CoreRegistry.get(AssetManager.class).listLoadedAssets(AssetType.SHADER,
                Shader.class)) {
            shader.recompile();
        }

        for (Material material : CoreRegistry.get(AssetManager.class).listLoadedAssets(AssetType.MATERIAL,
                Material.class)) {
            material.recompile();
        }

        activeMaterial = null;
    }

    private GLSLMaterial prepareAndStoreShaderProgramInstance(String title, ShaderParameters params) {
        String uri = "engine:" + title;
        Shader shader = Assets.getShader(uri);
        checkNotNull(shader, "Failed to resolve %s", uri);
        shader.recompile();
        GLSLMaterial material = Assets.generateAsset(new AssetUri(AssetType.MATERIAL, "engine:prog." + title),
                new MaterialData(shader), GLSLMaterial.class);
        material.setShaderParameters(params);

        return material;
    }

    /**
     * Enables the default shader program.
     */
    @Override
    public void enableDefault() {
        defaultShaderProgram.enable();
    }

    /**
     * Enables the default shader program.
     */
    @Override
    public void enableDefaultTextured() {
        defaultTexturedShaderProgram.enable();
    }

    @Override
    public void disableShader() {
        GL20.glUseProgram(0);
        activeMaterial = null;
    }

}