Home | History | Annotate | Download | only in glutils
      1 /*******************************************************************************
      2  * Copyright 2011 See AUTHORS file.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *   http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  ******************************************************************************/
     16 
     17 package com.badlogic.gdx.graphics.glutils;
     18 
     19 import java.nio.Buffer;
     20 import java.nio.ByteBuffer;
     21 import java.nio.ByteOrder;
     22 import java.nio.FloatBuffer;
     23 import java.nio.IntBuffer;
     24 
     25 import com.badlogic.gdx.Application;
     26 import com.badlogic.gdx.Gdx;
     27 import com.badlogic.gdx.files.FileHandle;
     28 import com.badlogic.gdx.graphics.Color;
     29 import com.badlogic.gdx.graphics.GL20;
     30 import com.badlogic.gdx.graphics.Mesh;
     31 import com.badlogic.gdx.math.Matrix3;
     32 import com.badlogic.gdx.math.Matrix4;
     33 import com.badlogic.gdx.math.Vector2;
     34 import com.badlogic.gdx.math.Vector3;
     35 import com.badlogic.gdx.utils.Array;
     36 import com.badlogic.gdx.utils.BufferUtils;
     37 import com.badlogic.gdx.utils.Disposable;
     38 import com.badlogic.gdx.utils.ObjectIntMap;
     39 import com.badlogic.gdx.utils.ObjectMap;
     40 
     41 /** <p>
     42  * A shader program encapsulates a vertex and fragment shader pair linked to form a shader program useable with OpenGL ES 2.0.
     43  * </p>
     44  *
     45  * <p>
     46  * After construction a ShaderProgram can be used to draw {@link Mesh}. To make the GPU use a specific ShaderProgram the programs
     47  * {@link ShaderProgram#begin()} method must be used which effectively binds the program.
     48  * </p>
     49  *
     50  * <p>
     51  * When a ShaderProgram is bound one can set uniforms, vertex attributes and attributes as needed via the respective methods.
     52  * </p>
     53  *
     54  * <p>
     55  * A ShaderProgram can be unbound with a call to {@link ShaderProgram#end()}
     56  * </p>
     57  *
     58  * <p>
     59  * A ShaderProgram must be disposed via a call to {@link ShaderProgram#dispose()} when it is no longer needed
     60  * </p>
     61  *
     62  * <p>
     63  * ShaderPrograms are managed. In case the OpenGL context is lost all shaders get invalidated and have to be reloaded. This
     64  * happens on Android when a user switches to another application or receives an incoming call. Managed ShaderPrograms are
     65  * automatically reloaded when the OpenGL context is recreated so you don't have to do this manually.
     66  * </p>
     67  *
     68  * @author mzechner */
     69 public class ShaderProgram implements Disposable {
     70 	/** default name for position attributes **/
     71 	public static final String POSITION_ATTRIBUTE = "a_position";
     72 	/** default name for normal attributes **/
     73 	public static final String NORMAL_ATTRIBUTE = "a_normal";
     74 	/** default name for color attributes **/
     75 	public static final String COLOR_ATTRIBUTE = "a_color";
     76 	/** default name for texcoords attributes, append texture unit number **/
     77 	public static final String TEXCOORD_ATTRIBUTE = "a_texCoord";
     78 	/** default name for tangent attribute **/
     79 	public static final String TANGENT_ATTRIBUTE = "a_tangent";
     80 	/** default name for binormal attribute **/
     81 	public static final String BINORMAL_ATTRIBUTE = "a_binormal";
     82 
     83 	/** flag indicating whether attributes & uniforms must be present at all times **/
     84 	public static boolean pedantic = true;
     85 
     86 	/** code that is always added to the vertex shader code, typically used to inject a #version line. Note that this is added
     87 	 * as-is, you should include a newline (`\n`) if needed. */
     88 	public static String prependVertexCode = "";
     89 
     90 	/** code that is always added to every fragment shader code, typically used to inject a #version line. Note that this is added
     91 	 * as-is, you should include a newline (`\n`) if needed. */
     92 	public static String prependFragmentCode = "";
     93 
     94 	/** the list of currently available shaders **/
     95 	private final static ObjectMap<Application, Array<ShaderProgram>> shaders = new ObjectMap<Application, Array<ShaderProgram>>();
     96 
     97 	/** the log **/
     98 	private String log = "";
     99 
    100 	/** whether this program compiled successfully **/
    101 	private boolean isCompiled;
    102 
    103 	/** uniform lookup **/
    104 	private final ObjectIntMap<String> uniforms = new ObjectIntMap<String>();
    105 
    106 	/** uniform types **/
    107 	private final ObjectIntMap<String> uniformTypes = new ObjectIntMap<String>();
    108 
    109 	/** uniform sizes **/
    110 	private final ObjectIntMap<String> uniformSizes = new ObjectIntMap<String>();
    111 
    112 	/** uniform names **/
    113 	private String[] uniformNames;
    114 
    115 	/** attribute lookup **/
    116 	private final ObjectIntMap<String> attributes = new ObjectIntMap<String>();
    117 
    118 	/** attribute types **/
    119 	private final ObjectIntMap<String> attributeTypes = new ObjectIntMap<String>();
    120 
    121 	/** attribute sizes **/
    122 	private final ObjectIntMap<String> attributeSizes = new ObjectIntMap<String>();
    123 
    124 	/** attribute names **/
    125 	private String[] attributeNames;
    126 
    127 	/** program handle **/
    128 	private int program;
    129 
    130 	/** vertex shader handle **/
    131 	private int vertexShaderHandle;
    132 
    133 	/** fragment shader handle **/
    134 	private int fragmentShaderHandle;
    135 
    136 	/** matrix float buffer **/
    137 	private final FloatBuffer matrix;
    138 
    139 	/** vertex shader source **/
    140 	private final String vertexShaderSource;
    141 
    142 	/** fragment shader source **/
    143 	private final String fragmentShaderSource;
    144 
    145 	/** whether this shader was invalidated **/
    146 	private boolean invalidated;
    147 
    148 	/** reference count **/
    149 	private int refCount = 0;
    150 
    151 	/** Constructs a new ShaderProgram and immediately compiles it.
    152 	 *
    153 	 * @param vertexShader the vertex shader
    154 	 * @param fragmentShader the fragment shader */
    155 
    156 	public ShaderProgram (String vertexShader, String fragmentShader) {
    157 		if (vertexShader == null) throw new IllegalArgumentException("vertex shader must not be null");
    158 		if (fragmentShader == null) throw new IllegalArgumentException("fragment shader must not be null");
    159 
    160 		if (prependVertexCode != null && prependVertexCode.length() > 0)
    161 			vertexShader = prependVertexCode + vertexShader;
    162 		if (prependFragmentCode != null && prependFragmentCode.length() > 0)
    163 			fragmentShader = prependFragmentCode + fragmentShader;
    164 
    165 		this.vertexShaderSource = vertexShader;
    166 		this.fragmentShaderSource = fragmentShader;
    167 		this.matrix = BufferUtils.newFloatBuffer(16);
    168 
    169 		compileShaders(vertexShader, fragmentShader);
    170 		if (isCompiled()) {
    171 			fetchAttributes();
    172 			fetchUniforms();
    173 			addManagedShader(Gdx.app, this);
    174 		}
    175 	}
    176 
    177 	public ShaderProgram (FileHandle vertexShader, FileHandle fragmentShader) {
    178 		this(vertexShader.readString(), fragmentShader.readString());
    179 	}
    180 
    181 	/** Loads and compiles the shaders, creates a new program and links the shaders.
    182 	 *
    183 	 * @param vertexShader
    184 	 * @param fragmentShader */
    185 	private void compileShaders (String vertexShader, String fragmentShader) {
    186 		vertexShaderHandle = loadShader(GL20.GL_VERTEX_SHADER, vertexShader);
    187 		fragmentShaderHandle = loadShader(GL20.GL_FRAGMENT_SHADER, fragmentShader);
    188 
    189 		if (vertexShaderHandle == -1 || fragmentShaderHandle == -1) {
    190 			isCompiled = false;
    191 			return;
    192 		}
    193 
    194 		program = linkProgram(createProgram());
    195 		if (program == -1) {
    196 			isCompiled = false;
    197 			return;
    198 		}
    199 
    200 		isCompiled = true;
    201 	}
    202 
    203 	private int loadShader (int type, String source) {
    204 		GL20 gl = Gdx.gl20;
    205 		IntBuffer intbuf = BufferUtils.newIntBuffer(1);
    206 
    207 		int shader = gl.glCreateShader(type);
    208 		if (shader == 0) return -1;
    209 
    210 		gl.glShaderSource(shader, source);
    211 		gl.glCompileShader(shader);
    212 		gl.glGetShaderiv(shader, GL20.GL_COMPILE_STATUS, intbuf);
    213 
    214 		int compiled = intbuf.get(0);
    215 		if (compiled == 0) {
    216 // gl.glGetShaderiv(shader, GL20.GL_INFO_LOG_LENGTH, intbuf);
    217 // int infoLogLength = intbuf.get(0);
    218 // if (infoLogLength > 1) {
    219 			String infoLog = gl.glGetShaderInfoLog(shader);
    220 			log += infoLog;
    221 // }
    222 			return -1;
    223 		}
    224 
    225 		return shader;
    226 	}
    227 
    228 	protected int createProgram () {
    229 		GL20 gl = Gdx.gl20;
    230 		int program = gl.glCreateProgram();
    231 		return program != 0 ? program : -1;
    232 	}
    233 
    234 	private int linkProgram (int program) {
    235 		GL20 gl = Gdx.gl20;
    236 		if (program == -1) return -1;
    237 
    238 		gl.glAttachShader(program, vertexShaderHandle);
    239 		gl.glAttachShader(program, fragmentShaderHandle);
    240 		gl.glLinkProgram(program);
    241 
    242 		ByteBuffer tmp = ByteBuffer.allocateDirect(4);
    243 		tmp.order(ByteOrder.nativeOrder());
    244 		IntBuffer intbuf = tmp.asIntBuffer();
    245 
    246 		gl.glGetProgramiv(program, GL20.GL_LINK_STATUS, intbuf);
    247 		int linked = intbuf.get(0);
    248 		if (linked == 0) {
    249 // Gdx.gl20.glGetProgramiv(program, GL20.GL_INFO_LOG_LENGTH, intbuf);
    250 // int infoLogLength = intbuf.get(0);
    251 // if (infoLogLength > 1) {
    252 			log = Gdx.gl20.glGetProgramInfoLog(program);
    253 // }
    254 			return -1;
    255 		}
    256 
    257 		return program;
    258 	}
    259 
    260 	final static IntBuffer intbuf = BufferUtils.newIntBuffer(1);
    261 
    262 	/** @return the log info for the shader compilation and program linking stage. The shader needs to be bound for this method to
    263 	 *         have an effect. */
    264 	public String getLog () {
    265 		if (isCompiled) {
    266 // Gdx.gl20.glGetProgramiv(program, GL20.GL_INFO_LOG_LENGTH, intbuf);
    267 // int infoLogLength = intbuf.get(0);
    268 // if (infoLogLength > 1) {
    269 			log = Gdx.gl20.glGetProgramInfoLog(program);
    270 // }
    271 			return log;
    272 		} else {
    273 			return log;
    274 		}
    275 	}
    276 
    277 	/** @return whether this ShaderProgram compiled successfully. */
    278 	public boolean isCompiled () {
    279 		return isCompiled;
    280 	}
    281 
    282 	private int fetchAttributeLocation (String name) {
    283 		GL20 gl = Gdx.gl20;
    284 		// -2 == not yet cached
    285 		// -1 == cached but not found
    286 		int location;
    287 		if ((location = attributes.get(name, -2)) == -2) {
    288 			location = gl.glGetAttribLocation(program, name);
    289 			attributes.put(name, location);
    290 		}
    291 		return location;
    292 	}
    293 
    294 	private int fetchUniformLocation (String name) {
    295 		return fetchUniformLocation(name, pedantic);
    296 	}
    297 
    298 	public int fetchUniformLocation (String name, boolean pedantic) {
    299 		GL20 gl = Gdx.gl20;
    300 		// -2 == not yet cached
    301 		// -1 == cached but not found
    302 		int location;
    303 		if ((location = uniforms.get(name, -2)) == -2) {
    304 			location = gl.glGetUniformLocation(program, name);
    305 			if (location == -1 && pedantic) throw new IllegalArgumentException("no uniform with name '" + name + "' in shader");
    306 			uniforms.put(name, location);
    307 		}
    308 		return location;
    309 	}
    310 
    311 	/** Sets the uniform with the given name. The {@link ShaderProgram} must be bound for this to work.
    312 	 *
    313 	 * @param name the name of the uniform
    314 	 * @param value the value */
    315 	public void setUniformi (String name, int value) {
    316 		GL20 gl = Gdx.gl20;
    317 		checkManaged();
    318 		int location = fetchUniformLocation(name);
    319 		gl.glUniform1i(location, value);
    320 	}
    321 
    322 	public void setUniformi (int location, int value) {
    323 		GL20 gl = Gdx.gl20;
    324 		checkManaged();
    325 		gl.glUniform1i(location, value);
    326 	}
    327 
    328 	/** Sets the uniform with the given name. The {@link ShaderProgram} must be bound for this to work.
    329 	 *
    330 	 * @param name the name of the uniform
    331 	 * @param value1 the first value
    332 	 * @param value2 the second value */
    333 	public void setUniformi (String name, int value1, int value2) {
    334 		GL20 gl = Gdx.gl20;
    335 		checkManaged();
    336 		int location = fetchUniformLocation(name);
    337 		gl.glUniform2i(location, value1, value2);
    338 	}
    339 
    340 	public void setUniformi (int location, int value1, int value2) {
    341 		GL20 gl = Gdx.gl20;
    342 		checkManaged();
    343 		gl.glUniform2i(location, value1, value2);
    344 	}
    345 
    346 	/** Sets the uniform with the given name. The {@link ShaderProgram} must be bound for this to work.
    347 	 *
    348 	 * @param name the name of the uniform
    349 	 * @param value1 the first value
    350 	 * @param value2 the second value
    351 	 * @param value3 the third value */
    352 	public void setUniformi (String name, int value1, int value2, int value3) {
    353 		GL20 gl = Gdx.gl20;
    354 		checkManaged();
    355 		int location = fetchUniformLocation(name);
    356 		gl.glUniform3i(location, value1, value2, value3);
    357 	}
    358 
    359 	public void setUniformi (int location, int value1, int value2, int value3) {
    360 		GL20 gl = Gdx.gl20;
    361 		checkManaged();
    362 		gl.glUniform3i(location, value1, value2, value3);
    363 	}
    364 
    365 	/** Sets the uniform with the given name. The {@link ShaderProgram} must be bound for this to work.
    366 	 *
    367 	 * @param name the name of the uniform
    368 	 * @param value1 the first value
    369 	 * @param value2 the second value
    370 	 * @param value3 the third value
    371 	 * @param value4 the fourth value */
    372 	public void setUniformi (String name, int value1, int value2, int value3, int value4) {
    373 		GL20 gl = Gdx.gl20;
    374 		checkManaged();
    375 		int location = fetchUniformLocation(name);
    376 		gl.glUniform4i(location, value1, value2, value3, value4);
    377 	}
    378 
    379 	public void setUniformi (int location, int value1, int value2, int value3, int value4) {
    380 		GL20 gl = Gdx.gl20;
    381 		checkManaged();
    382 		gl.glUniform4i(location, value1, value2, value3, value4);
    383 	}
    384 
    385 	/** Sets the uniform with the given name. The {@link ShaderProgram} must be bound for this to work.
    386 	 *
    387 	 * @param name the name of the uniform
    388 	 * @param value the value */
    389 	public void setUniformf (String name, float value) {
    390 		GL20 gl = Gdx.gl20;
    391 		checkManaged();
    392 		int location = fetchUniformLocation(name);
    393 		gl.glUniform1f(location, value);
    394 	}
    395 
    396 	public void setUniformf (int location, float value) {
    397 		GL20 gl = Gdx.gl20;
    398 		checkManaged();
    399 		gl.glUniform1f(location, value);
    400 	}
    401 
    402 	/** Sets the uniform with the given name. The {@link ShaderProgram} must be bound for this to work.
    403 	 *
    404 	 * @param name the name of the uniform
    405 	 * @param value1 the first value
    406 	 * @param value2 the second value */
    407 	public void setUniformf (String name, float value1, float value2) {
    408 		GL20 gl = Gdx.gl20;
    409 		checkManaged();
    410 		int location = fetchUniformLocation(name);
    411 		gl.glUniform2f(location, value1, value2);
    412 	}
    413 
    414 	public void setUniformf (int location, float value1, float value2) {
    415 		GL20 gl = Gdx.gl20;
    416 		checkManaged();
    417 		gl.glUniform2f(location, value1, value2);
    418 	}
    419 
    420 	/** Sets the uniform with the given name. The {@link ShaderProgram} must be bound for this to work.
    421 	 *
    422 	 * @param name the name of the uniform
    423 	 * @param value1 the first value
    424 	 * @param value2 the second value
    425 	 * @param value3 the third value */
    426 	public void setUniformf (String name, float value1, float value2, float value3) {
    427 		GL20 gl = Gdx.gl20;
    428 		checkManaged();
    429 		int location = fetchUniformLocation(name);
    430 		gl.glUniform3f(location, value1, value2, value3);
    431 	}
    432 
    433 	public void setUniformf (int location, float value1, float value2, float value3) {
    434 		GL20 gl = Gdx.gl20;
    435 		checkManaged();
    436 		gl.glUniform3f(location, value1, value2, value3);
    437 	}
    438 
    439 	/** Sets the uniform with the given name. The {@link ShaderProgram} must be bound for this to work.
    440 	 *
    441 	 * @param name the name of the uniform
    442 	 * @param value1 the first value
    443 	 * @param value2 the second value
    444 	 * @param value3 the third value
    445 	 * @param value4 the fourth value */
    446 	public void setUniformf (String name, float value1, float value2, float value3, float value4) {
    447 		GL20 gl = Gdx.gl20;
    448 		checkManaged();
    449 		int location = fetchUniformLocation(name);
    450 		gl.glUniform4f(location, value1, value2, value3, value4);
    451 	}
    452 
    453 	public void setUniformf (int location, float value1, float value2, float value3, float value4) {
    454 		GL20 gl = Gdx.gl20;
    455 		checkManaged();
    456 		gl.glUniform4f(location, value1, value2, value3, value4);
    457 	}
    458 
    459 	public void setUniform1fv (String name, float[] values, int offset, int length) {
    460 		GL20 gl = Gdx.gl20;
    461 		checkManaged();
    462 		int location = fetchUniformLocation(name);
    463 		gl.glUniform1fv(location, length, values, offset);
    464 	}
    465 
    466 	public void setUniform1fv (int location, float[] values, int offset, int length) {
    467 		GL20 gl = Gdx.gl20;
    468 		checkManaged();
    469 		gl.glUniform1fv(location, length, values, offset);
    470 	}
    471 
    472 	public void setUniform2fv (String name, float[] values, int offset, int length) {
    473 		GL20 gl = Gdx.gl20;
    474 		checkManaged();
    475 		int location = fetchUniformLocation(name);
    476 		gl.glUniform2fv(location, length / 2, values, offset);
    477 	}
    478 
    479 	public void setUniform2fv (int location, float[] values, int offset, int length) {
    480 		GL20 gl = Gdx.gl20;
    481 		checkManaged();
    482 		gl.glUniform2fv(location, length / 2, values, offset);
    483 	}
    484 
    485 	public void setUniform3fv (String name, float[] values, int offset, int length) {
    486 		GL20 gl = Gdx.gl20;
    487 		checkManaged();
    488 		int location = fetchUniformLocation(name);
    489 		gl.glUniform3fv(location, length / 3, values, offset);
    490 	}
    491 
    492 	public void setUniform3fv (int location, float[] values, int offset, int length) {
    493 		GL20 gl = Gdx.gl20;
    494 		checkManaged();
    495 		gl.glUniform3fv(location, length / 3, values, offset);
    496 	}
    497 
    498 	public void setUniform4fv (String name, float[] values, int offset, int length) {
    499 		GL20 gl = Gdx.gl20;
    500 		checkManaged();
    501 		int location = fetchUniformLocation(name);
    502 		gl.glUniform4fv(location, length / 4, values, offset);
    503 	}
    504 
    505 	public void setUniform4fv (int location, float[] values, int offset, int length) {
    506 		GL20 gl = Gdx.gl20;
    507 		checkManaged();
    508 		gl.glUniform4fv(location, length / 4, values, offset);
    509 	}
    510 
    511 	/** Sets the uniform matrix with the given name. The {@link ShaderProgram} must be bound for this to work.
    512 	 *
    513 	 * @param name the name of the uniform
    514 	 * @param matrix the matrix */
    515 	public void setUniformMatrix (String name, Matrix4 matrix) {
    516 		setUniformMatrix(name, matrix, false);
    517 	}
    518 
    519 	/** Sets the uniform matrix with the given name. The {@link ShaderProgram} must be bound for this to work.
    520 	 *
    521 	 * @param name the name of the uniform
    522 	 * @param matrix the matrix
    523 	 * @param transpose whether the matrix should be transposed */
    524 	public void setUniformMatrix (String name, Matrix4 matrix, boolean transpose) {
    525 		setUniformMatrix(fetchUniformLocation(name), matrix, transpose);
    526 	}
    527 
    528 	public void setUniformMatrix (int location, Matrix4 matrix) {
    529 		setUniformMatrix(location, matrix, false);
    530 	}
    531 
    532 	public void setUniformMatrix (int location, Matrix4 matrix, boolean transpose) {
    533 		GL20 gl = Gdx.gl20;
    534 		checkManaged();
    535 		gl.glUniformMatrix4fv(location, 1, transpose, matrix.val, 0);
    536 	}
    537 
    538 	/** Sets the uniform matrix with the given name. The {@link ShaderProgram} must be bound for this to work.
    539 	 *
    540 	 * @param name the name of the uniform
    541 	 * @param matrix the matrix */
    542 	public void setUniformMatrix (String name, Matrix3 matrix) {
    543 		setUniformMatrix(name, matrix, false);
    544 	}
    545 
    546 	/** Sets the uniform matrix with the given name. The {@link ShaderProgram} must be bound for this to work.
    547 	 *
    548 	 * @param name the name of the uniform
    549 	 * @param matrix the matrix
    550 	 * @param transpose whether the uniform matrix should be transposed */
    551 	public void setUniformMatrix (String name, Matrix3 matrix, boolean transpose) {
    552 		setUniformMatrix(fetchUniformLocation(name), matrix, transpose);
    553 	}
    554 
    555 	public void setUniformMatrix (int location, Matrix3 matrix) {
    556 		setUniformMatrix(location, matrix, false);
    557 	}
    558 
    559 	public void setUniformMatrix (int location, Matrix3 matrix, boolean transpose) {
    560 		GL20 gl = Gdx.gl20;
    561 		checkManaged();
    562 		gl.glUniformMatrix3fv(location, 1, transpose, matrix.val, 0);
    563 	}
    564 
    565 	/** Sets an array of uniform matrices with the given name. The {@link ShaderProgram} must be bound for this to work.
    566 	 *
    567 	 * @param name the name of the uniform
    568 	 * @param buffer buffer containing the matrix data
    569 	 * @param transpose whether the uniform matrix should be transposed */
    570 	public void setUniformMatrix3fv (String name, FloatBuffer buffer, int count, boolean transpose) {
    571 		GL20 gl = Gdx.gl20;
    572 		checkManaged();
    573 		buffer.position(0);
    574 		int location = fetchUniformLocation(name);
    575 		gl.glUniformMatrix3fv(location, count, transpose, buffer);
    576 	}
    577 
    578 	/** Sets an array of uniform matrices with the given name. The {@link ShaderProgram} must be bound for this to work.
    579 	 *
    580 	 * @param name the name of the uniform
    581 	 * @param buffer buffer containing the matrix data
    582 	 * @param transpose whether the uniform matrix should be transposed */
    583 	public void setUniformMatrix4fv (String name, FloatBuffer buffer, int count, boolean transpose) {
    584 		GL20 gl = Gdx.gl20;
    585 		checkManaged();
    586 		buffer.position(0);
    587 		int location = fetchUniformLocation(name);
    588 		gl.glUniformMatrix4fv(location, count, transpose, buffer);
    589 	}
    590 
    591 	public void setUniformMatrix4fv (int location, float[] values, int offset, int length) {
    592 		GL20 gl = Gdx.gl20;
    593 		checkManaged();
    594 		gl.glUniformMatrix4fv(location, length / 16, false, values, offset);
    595 	}
    596 
    597 	public void setUniformMatrix4fv (String name, float[] values, int offset, int length) {
    598 		setUniformMatrix4fv(fetchUniformLocation(name), values, offset, length);
    599 	}
    600 
    601 	/** Sets the uniform with the given name. The {@link ShaderProgram} must be bound for this to work.
    602 	 *
    603 	 * @param name the name of the uniform
    604 	 * @param values x and y as the first and second values respectively */
    605 	public void setUniformf (String name, Vector2 values) {
    606 		setUniformf(name, values.x, values.y);
    607 	}
    608 
    609 	public void setUniformf (int location, Vector2 values) {
    610 		setUniformf(location, values.x, values.y);
    611 	}
    612 
    613 	/** Sets the uniform with the given name. The {@link ShaderProgram} must be bound for this to work.
    614 	 *
    615 	 * @param name the name of the uniform
    616 	 * @param values x, y and z as the first, second and third values respectively */
    617 	public void setUniformf (String name, Vector3 values) {
    618 		setUniformf(name, values.x, values.y, values.z);
    619 	}
    620 
    621 	public void setUniformf (int location, Vector3 values) {
    622 		setUniformf(location, values.x, values.y, values.z);
    623 	}
    624 
    625 	/** Sets the uniform with the given name. The {@link ShaderProgram} must be bound for this to work.
    626 	 *
    627 	 * @param name the name of the uniform
    628 	 * @param values r, g, b and a as the first through fourth values respectively */
    629 	public void setUniformf (String name, Color values) {
    630 		setUniformf(name, values.r, values.g, values.b, values.a);
    631 	}
    632 
    633 	public void setUniformf (int location, Color values) {
    634 		setUniformf(location, values.r, values.g, values.b, values.a);
    635 	}
    636 
    637 	/** Sets the vertex attribute with the given name. The {@link ShaderProgram} must be bound for this to work.
    638 	 *
    639 	 * @param name the attribute name
    640 	 * @param size the number of components, must be >= 1 and <= 4
    641 	 * @param type the type, must be one of GL20.GL_BYTE, GL20.GL_UNSIGNED_BYTE, GL20.GL_SHORT,
    642 	 *           GL20.GL_UNSIGNED_SHORT,GL20.GL_FIXED, or GL20.GL_FLOAT. GL_FIXED will not work on the desktop
    643 	 * @param normalize whether fixed point data should be normalized. Will not work on the desktop
    644 	 * @param stride the stride in bytes between successive attributes
    645 	 * @param buffer the buffer containing the vertex attributes. */
    646 	public void setVertexAttribute (String name, int size, int type, boolean normalize, int stride, Buffer buffer) {
    647 		GL20 gl = Gdx.gl20;
    648 		checkManaged();
    649 		int location = fetchAttributeLocation(name);
    650 		if (location == -1) return;
    651 		gl.glVertexAttribPointer(location, size, type, normalize, stride, buffer);
    652 	}
    653 
    654 	public void setVertexAttribute (int location, int size, int type, boolean normalize, int stride, Buffer buffer) {
    655 		GL20 gl = Gdx.gl20;
    656 		checkManaged();
    657 		gl.glVertexAttribPointer(location, size, type, normalize, stride, buffer);
    658 	}
    659 
    660 	/** Sets the vertex attribute with the given name. The {@link ShaderProgram} must be bound for this to work.
    661 	 *
    662 	 * @param name the attribute name
    663 	 * @param size the number of components, must be >= 1 and <= 4
    664 	 * @param type the type, must be one of GL20.GL_BYTE, GL20.GL_UNSIGNED_BYTE, GL20.GL_SHORT,
    665 	 *           GL20.GL_UNSIGNED_SHORT,GL20.GL_FIXED, or GL20.GL_FLOAT. GL_FIXED will not work on the desktop
    666 	 * @param normalize whether fixed point data should be normalized. Will not work on the desktop
    667 	 * @param stride the stride in bytes between successive attributes
    668 	 * @param offset byte offset into the vertex buffer object bound to GL20.GL_ARRAY_BUFFER. */
    669 	public void setVertexAttribute (String name, int size, int type, boolean normalize, int stride, int offset) {
    670 		GL20 gl = Gdx.gl20;
    671 		checkManaged();
    672 		int location = fetchAttributeLocation(name);
    673 		if (location == -1) return;
    674 		gl.glVertexAttribPointer(location, size, type, normalize, stride, offset);
    675 	}
    676 
    677 	public void setVertexAttribute (int location, int size, int type, boolean normalize, int stride, int offset) {
    678 		GL20 gl = Gdx.gl20;
    679 		checkManaged();
    680 		gl.glVertexAttribPointer(location, size, type, normalize, stride, offset);
    681 	}
    682 
    683 	/** Makes OpenGL ES 2.0 use this vertex and fragment shader pair. When you are done with this shader you have to call
    684 	 * {@link ShaderProgram#end()}. */
    685 	public void begin () {
    686 		GL20 gl = Gdx.gl20;
    687 		checkManaged();
    688 		gl.glUseProgram(program);
    689 	}
    690 
    691 	/** Disables this shader. Must be called when one is done with the shader. Don't mix it with dispose, that will release the
    692 	 * shader resources. */
    693 	public void end () {
    694 		GL20 gl = Gdx.gl20;
    695 		gl.glUseProgram(0);
    696 	}
    697 
    698 	/** Disposes all resources associated with this shader. Must be called when the shader is no longer used. */
    699 	public void dispose () {
    700 		GL20 gl = Gdx.gl20;
    701 		gl.glUseProgram(0);
    702 		gl.glDeleteShader(vertexShaderHandle);
    703 		gl.glDeleteShader(fragmentShaderHandle);
    704 		gl.glDeleteProgram(program);
    705 		if (shaders.get(Gdx.app) != null) shaders.get(Gdx.app).removeValue(this, true);
    706 	}
    707 
    708 	/** Disables the vertex attribute with the given name
    709 	 *
    710 	 * @param name the vertex attribute name */
    711 	public void disableVertexAttribute (String name) {
    712 		GL20 gl = Gdx.gl20;
    713 		checkManaged();
    714 		int location = fetchAttributeLocation(name);
    715 		if (location == -1) return;
    716 		gl.glDisableVertexAttribArray(location);
    717 	}
    718 
    719 	public void disableVertexAttribute (int location) {
    720 		GL20 gl = Gdx.gl20;
    721 		checkManaged();
    722 		gl.glDisableVertexAttribArray(location);
    723 	}
    724 
    725 	/** Enables the vertex attribute with the given name
    726 	 *
    727 	 * @param name the vertex attribute name */
    728 	public void enableVertexAttribute (String name) {
    729 		GL20 gl = Gdx.gl20;
    730 		checkManaged();
    731 		int location = fetchAttributeLocation(name);
    732 		if (location == -1) return;
    733 		gl.glEnableVertexAttribArray(location);
    734 	}
    735 
    736 	public void enableVertexAttribute (int location) {
    737 		GL20 gl = Gdx.gl20;
    738 		checkManaged();
    739 		gl.glEnableVertexAttribArray(location);
    740 	}
    741 
    742 	private void checkManaged () {
    743 		if (invalidated) {
    744 			compileShaders(vertexShaderSource, fragmentShaderSource);
    745 			invalidated = false;
    746 		}
    747 	}
    748 
    749 	private void addManagedShader (Application app, ShaderProgram shaderProgram) {
    750 		Array<ShaderProgram> managedResources = shaders.get(app);
    751 		if (managedResources == null) managedResources = new Array<ShaderProgram>();
    752 		managedResources.add(shaderProgram);
    753 		shaders.put(app, managedResources);
    754 	}
    755 
    756 	/** Invalidates all shaders so the next time they are used new handles are generated
    757 	 * @param app */
    758 	public static void invalidateAllShaderPrograms (Application app) {
    759 		if (Gdx.gl20 == null) return;
    760 
    761 		Array<ShaderProgram> shaderArray = shaders.get(app);
    762 		if (shaderArray == null) return;
    763 
    764 		for (int i = 0; i < shaderArray.size; i++) {
    765 			shaderArray.get(i).invalidated = true;
    766 			shaderArray.get(i).checkManaged();
    767 		}
    768 	}
    769 
    770 	public static void clearAllShaderPrograms (Application app) {
    771 		shaders.remove(app);
    772 	}
    773 
    774 	public static String getManagedStatus () {
    775 		StringBuilder builder = new StringBuilder();
    776 		int i = 0;
    777 		builder.append("Managed shaders/app: { ");
    778 		for (Application app : shaders.keys()) {
    779 			builder.append(shaders.get(app).size);
    780 			builder.append(" ");
    781 		}
    782 		builder.append("}");
    783 		return builder.toString();
    784 	}
    785 
    786 	/** @return the number of managed shader programs currently loaded */
    787 	public static int getNumManagedShaderPrograms () {
    788 		return shaders.get(Gdx.app).size;
    789 	}
    790 
    791 	/** Sets the given attribute
    792 	 *
    793 	 * @param name the name of the attribute
    794 	 * @param value1 the first value
    795 	 * @param value2 the second value
    796 	 * @param value3 the third value
    797 	 * @param value4 the fourth value */
    798 	public void setAttributef (String name, float value1, float value2, float value3, float value4) {
    799 		GL20 gl = Gdx.gl20;
    800 		int location = fetchAttributeLocation(name);
    801 		gl.glVertexAttrib4f(location, value1, value2, value3, value4);
    802 	}
    803 
    804 	IntBuffer params = BufferUtils.newIntBuffer(1);
    805 	IntBuffer type = BufferUtils.newIntBuffer(1);
    806 
    807 	private void fetchUniforms () {
    808 		params.clear();
    809 		Gdx.gl20.glGetProgramiv(program, GL20.GL_ACTIVE_UNIFORMS, params);
    810 		int numUniforms = params.get(0);
    811 
    812 		uniformNames = new String[numUniforms];
    813 
    814 		for (int i = 0; i < numUniforms; i++) {
    815 			params.clear();
    816 			params.put(0, 1);
    817 			type.clear();
    818 			String name = Gdx.gl20.glGetActiveUniform(program, i, params, type);
    819 			int location = Gdx.gl20.glGetUniformLocation(program, name);
    820 			uniforms.put(name, location);
    821 			uniformTypes.put(name, type.get(0));
    822 			uniformSizes.put(name, params.get(0));
    823 			uniformNames[i] = name;
    824 		}
    825 	}
    826 
    827 	private void fetchAttributes () {
    828 		params.clear();
    829 		Gdx.gl20.glGetProgramiv(program, GL20.GL_ACTIVE_ATTRIBUTES, params);
    830 		int numAttributes = params.get(0);
    831 
    832 		attributeNames = new String[numAttributes];
    833 
    834 		for (int i = 0; i < numAttributes; i++) {
    835 			params.clear();
    836 			params.put(0, 1);
    837 			type.clear();
    838 			String name = Gdx.gl20.glGetActiveAttrib(program, i, params, type);
    839 			int location = Gdx.gl20.glGetAttribLocation(program, name);
    840 			attributes.put(name, location);
    841 			attributeTypes.put(name, type.get(0));
    842 			attributeSizes.put(name, params.get(0));
    843 			attributeNames[i] = name;
    844 		}
    845 	}
    846 
    847 	/** @param name the name of the attribute
    848 	 * @return whether the attribute is available in the shader */
    849 	public boolean hasAttribute (String name) {
    850 		return attributes.containsKey(name);
    851 	}
    852 
    853 	/** @param name the name of the attribute
    854 	 * @return the type of the attribute, one of {@link GL20#GL_FLOAT}, {@link GL20#GL_FLOAT_VEC2} etc. */
    855 	public int getAttributeType (String name) {
    856 		return attributeTypes.get(name, 0);
    857 	}
    858 
    859 	/** @param name the name of the attribute
    860 	 * @return the location of the attribute or -1. */
    861 	public int getAttributeLocation (String name) {
    862 		return attributes.get(name, -1);
    863 	}
    864 
    865 	/** @param name the name of the attribute
    866 	 * @return the size of the attribute or 0. */
    867 	public int getAttributeSize (String name) {
    868 		return attributeSizes.get(name, 0);
    869 	}
    870 
    871 	/** @param name the name of the uniform
    872 	 * @return whether the uniform is available in the shader */
    873 	public boolean hasUniform (String name) {
    874 		return uniforms.containsKey(name);
    875 	}
    876 
    877 	/** @param name the name of the uniform
    878 	 * @return the type of the uniform, one of {@link GL20#GL_FLOAT}, {@link GL20#GL_FLOAT_VEC2} etc. */
    879 	public int getUniformType (String name) {
    880 		return uniformTypes.get(name, 0);
    881 	}
    882 
    883 	/** @param name the name of the uniform
    884 	 * @return the location of the uniform or -1. */
    885 	public int getUniformLocation (String name) {
    886 		return uniforms.get(name, -1);
    887 	}
    888 
    889 	/** @param name the name of the uniform
    890 	 * @return the size of the uniform or 0. */
    891 	public int getUniformSize (String name) {
    892 		return uniformSizes.get(name, 0);
    893 	}
    894 
    895 	/** @return the attributes */
    896 	public String[] getAttributes () {
    897 		return attributeNames;
    898 	}
    899 
    900 	/** @return the uniforms */
    901 	public String[] getUniforms () {
    902 		return uniformNames;
    903 	}
    904 
    905 	/** @return the source of the vertex shader */
    906 	public String getVertexShaderSource () {
    907 		return vertexShaderSource;
    908 	}
    909 
    910 	/** @return the source of the fragment shader */
    911 	public String getFragmentShaderSource () {
    912 		return fragmentShaderSource;
    913 	}
    914 }
    915