Package com.jme3.material

Source Code of com.jme3.material.Technique

/*
* Copyright (c) 2009-2012 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
*   notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
*   notice, this list of conditions and the following disclaimer in the
*   documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
*   may be used to endorse or promote products derived from this software
*   without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jme3.material;

import com.jme3.asset.AssetManager;
import com.jme3.renderer.Caps;
import com.jme3.shader.*;
import com.jme3.util.ListMap;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.logging.Logger;

/**
* Represents a technique instance.
*/
public class Technique /* implements Savable */ {

    private static final Logger logger = Logger.getLogger(Technique.class.getName());
    private TechniqueDef def;
    private Material owner;
    private ArrayList<Uniform> worldBindUniforms;
    private DefineList defines;
    private Shader shader;
    private boolean needReload = true;

    /**
     * Creates a new technique instance that implements the given
     * technique definition.
     *
     * @param owner The material that will own this technique
     * @param def The technique definition being implemented.
     */
    public Technique(Material owner, TechniqueDef def) {
        this.owner = owner;
        this.def = def;
        if (def.isUsingShaders()) {
            this.worldBindUniforms = new ArrayList<Uniform>();
            this.defines = new DefineList();
        }
    }

    /**
     * Serialization only. Do not use.
     */
    public Technique() {
    }

    /**
     * Returns the technique definition that is implemented by this technique
     * instance.
     *
     * @return the technique definition that is implemented by this technique
     * instance.
     */
    public TechniqueDef getDef() {
        return def;
    }

    /**
     * Returns the shader currently used by this technique instance.
     * <p>
     * Shaders are typically loaded dynamically when the technique is first
     * used, therefore, this variable will most likely be null most of the time.
     *
     * @return the shader currently used by this technique instance.
     */
    public Shader getShader() {
        return shader;
    }

    /**
     * Returns a list of uniforms that implements the world parameters
     * that were requested by the material definition.
     *
     * @return a list of uniforms implementing the world parameters.
     */
    public List<Uniform> getWorldBindUniforms() {
        return worldBindUniforms;
    }

    /**
     * Called by the material to tell the technique a parameter was modified.
     * Specify <code>null</code> for value if the param is to be cleared.
     */
    void notifyParamChanged(String paramName, VarType type, Object value) {
        // Check if there's a define binding associated with this
        // parameter.
        String defineName = def.getShaderParamDefine(paramName);
        if (defineName != null) {
            // There is a define. Change it on the define list.
            // The "needReload" variable will determine
            // if the shader will be reloaded when the material
            // is rendered.
           
            if (value == null) {
                // Clear the define.
                needReload = defines.remove(defineName) || needReload;
            } else {
                // Set the define.
                needReload = defines.set(defineName, type, value) || needReload;
            }
        }
    }

    void updateUniformParam(String paramName, VarType type, Object value) {
        if (paramName == null) {
            throw new IllegalArgumentException();
        }
       
        Uniform u = shader.getUniform(paramName);
        switch (type) {
            case TextureBuffer:
            case Texture2D: // fall intentional
            case Texture3D:
            case TextureArray:
            case TextureCubeMap:
            case Int:
                u.setValue(VarType.Int, value);
                break;
            default:
                u.setValue(type, value);
                break;
        }
    }

    /**
     * Returns true if the technique must be reloaded.
     * <p>
     * If a technique needs to reload, then the {@link Material} should
     * call {@link #makeCurrent(com.jme3.asset.AssetManager) } on this
     * technique.
     *
     * @return true if the technique must be reloaded.
     */
    public boolean isNeedReload() {
        return needReload;
    }

    /**
     * Prepares the technique for use by loading the shader and setting
     * the proper defines based on material parameters.
     *
     * @param assetManager The asset manager to use for loading shaders.
     */
    public void makeCurrent(AssetManager assetManager, boolean techniqueSwitched, EnumSet<Caps> rendererCaps) {
        if (!def.isUsingShaders()) {
            // No shaders are used, no processing is neccessary.
            return;
        }
       
        if (techniqueSwitched) {
            // If the technique was switched, check if the define list changed
            // based on material parameters.
           
            ListMap params = owner.getParamsMap();
           
            if (!defines.equalsParams(params, def)) {
                // Defines were changed, update define list
                defines.clear();
                for(int i=0;i<params.size();i++) {
                    MatParam param = (MatParam)params.getValue(i);
                    String defineName = def.getShaderParamDefine(param.getName());
                    if (defineName != null) {
                        defines.set(defineName, param.getVarType(), param.getValue());
                    }
                }
                needReload = true;
            }
        }

        if (needReload) {
            loadShader(assetManager,rendererCaps);
        }
    }

    private void loadShader(AssetManager manager,EnumSet<Caps> rendererCaps) {
       
        ShaderKey key = new ShaderKey(def.getVertexShaderName(),
                    def.getFragmentShaderName(),
                    getAllDefines(),
                    def.getVertexShaderLanguage(),
                    def.getFragmentShaderLanguage());
       
        if (getDef().isUsingShaderNodes()) {                
           manager.getShaderGenerator(rendererCaps).initialize(this);          
           key.setUsesShaderNodes(true);
        }  
        shader = manager.loadShader(key);

        // register the world bound uniforms
        worldBindUniforms.clear();
        if (def.getWorldBindings() != null) {
           for (UniformBinding binding : def.getWorldBindings()) {
               Uniform uniform = shader.getUniform("g_" + binding.name());
               uniform.setBinding(binding);
               worldBindUniforms.add(uniform);
           }
        }       
        needReload = false;
    }
   
    /**
     * Computes the define list
     * @return the complete define list
     */
    public DefineList getAllDefines() {
        DefineList allDefines = new DefineList();
        allDefines.addFrom(def.getShaderPresetDefines());
        allDefines.addFrom(defines);
        return allDefines;
    }
   
    /*
    public void write(JmeExporter ex) throws IOException {
        OutputCapsule oc = ex.getCapsule(this);
        oc.write(def, "def", null);
        oc.writeSavableArrayList(worldBindUniforms, "worldBindUniforms", null);
        oc.write(defines, "defines", null);
        oc.write(shader, "shader", null);
    }

    public void read(JmeImporter im) throws IOException {
        InputCapsule ic = im.getCapsule(this);
        def = (TechniqueDef) ic.readSavable("def", null);
        worldBindUniforms = ic.readSavableArrayList("worldBindUniforms", null);
        defines = (DefineList) ic.readSavable("defines", null);
        shader = (Shader) ic.readSavable("shader", null);
    }
    */
}
 
TOP

Related Classes of com.jme3.material.Technique

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.