/******************************************************************************* * 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.graphics.g3d; import com.badlogic.gdx.graphics.Camera; import com.badlogic.gdx.graphics.g3d.utils.BaseShaderProvider; import com.badlogic.gdx.graphics.g3d.utils.RenderContext; import com.badlogic.gdx.graphics.g3d.utils.ShaderProvider; import com.badlogic.gdx.graphics.glutils.ShaderProgram; import com.badlogic.gdx.utils.Disposable; /** Interface which is used to render one or more {@link Renderable}s.</p> * * A Shader is responsible for the actual rendering of an {@link Renderable}. Typically, when using OpenGL ES 2.0 or higher, it * encapsulates a {@link ShaderProgram} and takes care of all OpenGL calls necessary to render the {@link Renderable}. When using * OpenGL ES 1.x it takes care of the fixed pipeline.</p> * * To start rendering the {@link #begin(Camera, RenderContext)} method must be called. After which the {@link #end()} method must * be called to stop rendering. In between one or more calls to the {@link #render(Renderable)} method can be made to render a * {@link Renderable}. The {@link #render(Renderable)} method must not be called before a call to * {@link #begin(Camera, RenderContext)} or after a call to {@link #end()}. Each Shader needs exclusive access to the OpenGL state * and {@link RenderContext} between the {@link #begin(Camera, RenderContext)} and {@link #end()} methods, therefore only one * shader can be used at a time (they must not be nested).</p> * * A specific Shader instance might be (and usually is) dedicated to a specific type of {@link Renderable}. For example it might * use a {@link ShaderProgram} that is compiled with uniforms (shader input) for specific {@link Attribute} types. Therefore the * {@link #canRender(Renderable)} method can be used to check if the Shader instance can be used for a specific {@link Renderable} * . Rendering a {@link Renderable} using a Shader for which {@link #canRender(Renderable)} returns false might result in * unpredicted behavior or crash the application.</p> * * To manage multiple shaders and create a new shader when required, a {@link ShaderProvider} can be used. Therefore, in practice, * a specific Shader implementation is usually accompanied by a specific {@link ShaderProvider} implementation (usually extending * {@link BaseShaderProvider}).</p> * * When a Shader is constructed, the {@link #init()} method must be called before it can be used. Most commonly, the * {@link #init()} method compiles the {@link ShaderProgram}, fetches uniform locations and performs other preparations for usage * of the Shader. When the shader is no longer needed, it must disposed using the {@link Disposable#dispose()} method. This, for * example, disposed (unloads for memory) the used {@link ShaderProgram}.</p> * @author Xoppa */ public interface Shader extends Disposable { /** Initializes the Shader, must be called before the Shader can be used. This typically compiles a {@link ShaderProgram}, * fetches uniform locations and performs other preparations for usage of the Shader. */ void init (); /** Compare this shader against the other, used for sorting, light weight shaders are rendered first. */ int compareTo (Shader other); // TODO: probably better to add some weight value to sort on /** Checks whether this shader is intended to render the {@link Renderable}. Use this to make sure a call to the * {@link #render(Renderable)} method will succeed. This is expected to be a fast, non-blocking method. Note that this method * will only return true if it is intended to be used. Even when it returns false the Shader might still be capable of * rendering, but it's not preferred to do so. * @param instance The renderable to check against this shader. * @return true if this shader is intended to render the {@link Renderable}, false otherwise. */ boolean canRender (Renderable instance); /** Initializes the context for exclusive rendering by this shader. Use the {@link #render(Renderable)} method to render a * {@link Renderable}. When done rendering the {@link #end()} method must be called. * @param camera The camera to use when rendering * @param context The context to be used, which must be exclusive available for the shader until the call to the {@link #end()} * method. */ void begin (Camera camera, RenderContext context); /** Renders the {@link Renderable}, must be called between {@link #begin(Camera, RenderContext)} and {@link #end()}. The Shader * instance might not be able to render every type of {@link Renderable}s. Use the {@link #canRender(Renderable)} method to * check if the Shader is capable of rendering a specific {@link Renderable}. * @param renderable The renderable to render, all required fields (e.g. {@link Renderable#material} and others) must be set. * The {@link Renderable#shader} field will be ignored. */ void render (final Renderable renderable); /** Cleanup the context so other shaders can render. Must be called when done rendering using the {@link #render(Renderable)} * method, which must be preceded by a call to {@link #begin(Camera, RenderContext)}. After a call to this method an call to * the {@link #render(Renderable)} method will fail until the {@link #begin(Camera, RenderContext)} is called. */ void end (); }