/**
* Copyright 2008 - 2015 The Loon Game Engine Authors
*
* 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.
*
* @project loon
* @author cping
* @email:javachenpeng@yahoo.com
* @version 0.5
*/
package loon.opengl;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import loon.LRelease;
import loon.LSystem;
import loon.LGame;
import loon.canvas.LColor;
import loon.geom.Matrix3;
import loon.geom.Matrix4;
import loon.geom.Vector2f;
import loon.geom.Vector3f;
import loon.geom.Vector4f;
import loon.utils.ObjectIntMap;
import loon.utils.ObjectMap;
import loon.utils.TArray;
public class ShaderProgram implements LRelease {
public static class Mini implements LRelease {
private final GL20 gl;
private final int vertexShader, fragmentShader;
public final int id;
public Mini(GL20 gl, String vertexSource, String fragmentSource) {
this.gl = gl;
String glslVersion = "#version " + gl.getGlslVersion() + "\n";
int id = 0, vertexShader = 0, fragmentShader = 0;
try {
id = gl.glCreateProgram();
if (id == 0) {
throw LSystem.runThrow("Failed to create program: "
+ gl.glGetError());
}
gl.checkError("glCreateProgram");
vertexShader = compileShader(GL20.GL_VERTEX_SHADER, glslVersion
+ vertexSource);
gl.glAttachShader(id, vertexShader);
gl.checkError("glAttachShader / vertex");
fragmentShader = compileShader(GL20.GL_FRAGMENT_SHADER,
glslVersion + fragmentSource);
gl.glAttachShader(id, fragmentShader);
gl.checkError("glAttachShader / fragment");
gl.glLinkProgram(id);
int[] linkStatus = new int[1];
gl.glGetProgramiv(id, GL20.GL_LINK_STATUS, linkStatus, 0);
if (linkStatus[0] == GL20.GL_FALSE) {
String log = gl.glGetProgramInfoLog(id);
gl.glDeleteProgram(id);
throw LSystem.runThrow("Failed to link program: " + log);
}
this.id = id;
this.vertexShader = vertexShader;
this.fragmentShader = fragmentShader;
id = vertexShader = fragmentShader = 0;
} finally {
if (id != 0) {
gl.glDeleteProgram(id);
}
if (vertexShader != 0) {
gl.glDeleteShader(vertexShader);
}
if (fragmentShader != 0) {
gl.glDeleteShader(fragmentShader);
}
}
}
public int getUniformLocation(String name) {
int loc = gl.glGetUniformLocation(id, name);
return loc;
}
public int getAttribLocation(String name) {
int loc = gl.glGetAttribLocation(id, name);
return loc;
}
public void activate() {
gl.glUseProgram(id);
}
public void unactivate() {
gl.glUseProgram(0);
}
@Override
public void close() {
gl.glDeleteShader(vertexShader);
gl.glDeleteShader(fragmentShader);
gl.glDeleteProgram(id);
}
public void setUniform(int location, int... values) {
if (values.length > 4)
throw LSystem.runThrow(
"Uniform component cannot have more than 4 components");
switch (values.length) {
case 1:
gl.glUniform1i(location, values[0]);
break;
case 2:
gl.glUniform2i(location, values[0], values[1]);
break;
case 3:
gl.glUniform3i(location, values[0], values[1], values[2]);
break;
case 4:
gl.glUniform4i(location, values[0], values[1], values[2],
values[3]);
break;
}
}
public void setUniform(String name, int... values) {
setUniform(getUniformLocation(name), values);
}
public void setUniform(String name, float... values) {
setUniform(getUniformLocation(name), values);
}
public void setUniform(int location, Vector2f value) {
setUniform(location, value.getX(), value.getY());
}
public void setUniform(int location, float... values) {
if (values.length > 4)
throw LSystem.runThrow(
"Uniform component cannot have more than 4 components");
switch (values.length) {
case 1:
gl.glUniform1f(location, values[0]);
break;
case 2:
gl.glUniform2f(location, values[0], values[1]);
break;
case 3:
gl.glUniform3f(location, values[0], values[1], values[2]);
break;
case 4:
gl.glUniform4f(location, values[0], values[1], values[2],
values[3]);
break;
}
}
public void setUniform(int location, Vector3f value) {
setUniform(location, value.getX(), value.getY(), value.getZ());
}
public void setUniform(int location, LColor value) {
setUniform(location, value.getVector4());
}
public void setUniform(int location, Vector4f value) {
setUniform(location, value.getX(), value.getY(), value.getZ(),
value.getW());
}
public void setUniform(String name, Vector2f value) {
setUniform(name, value.getX(), value.getY());
}
public void setUniform(String name, Vector3f value) {
setUniform(name, value.getX(), value.getY(), value.getZ());
}
public void setUniform(String name, Vector4f value) {
setUniform(name, value.getX(), value.getY(), value.getZ(),
value.getW());
}
public void setUniform(String name, LColor value) {
setUniform(name, value.getVector4());
}
public void setUniform(int location, Matrix3 value) {
setUniform(location, false, value);
}
public void setUniform(int location, boolean transpose, Matrix3 value) {
gl.glUniformMatrix3fv(location, 1, transpose, value.val, 0);
}
public void setUniform(int location, Matrix4 value) {
setUniform(location, false, value);
}
public void setUniform(int location, boolean transpose, Matrix4 value) {
gl.glUniformMatrix3fv(location, 1, transpose, value.val, 0);
}
public void setUniform(String name, boolean transpose, Matrix3 value) {
setUniform(getUniformLocation(name), transpose, value);
}
public void setUniform(String name, Matrix3 value) {
setUniform(name, false, value);
}
public void setUniform(String name, boolean transpose, Matrix4 value) {
setUniform(getUniformLocation(name), transpose, value);
}
public void setUniform(String name, Matrix4 value) {
setUniform(name, false, value);
}
private int compileShader(int type, final String shaderSource) {
int shader = gl.glCreateShader(type);
if (shader == 0) {
throw LSystem.runThrow("Failed to create shader (" + type
+ "): " + gl.glGetError());
}
gl.glShaderSource(shader, shaderSource);
gl.glCompileShader(shader);
int[] compiled = new int[1];
gl.glGetShaderiv(shader, GL20.GL_COMPILE_STATUS, compiled, 0);
if (compiled[0] == GL20.GL_FALSE) {
String log = gl.glGetShaderInfoLog(shader);
gl.glDeleteShader(shader);
throw LSystem.runThrow("Failed to compile shader (" + type
+ "): " + log);
}
return shader;
}
}
public static final String POSITION_ATTRIBUTE = "a_position";
public static final String NORMAL_ATTRIBUTE = "a_normal";
public static final String COLOR_ATTRIBUTE = "a_color";
public static final String TEXCOORD_ATTRIBUTE = "a_texCoord";
public static final String TANGENT_ATTRIBUTE = "a_tangent";
public static final String BINORMAL_ATTRIBUTE = "a_binormal";
public static boolean pedantic = true;
private final static ObjectMap<LGame, TArray<ShaderProgram>> shaders = new ObjectMap<LGame, TArray<ShaderProgram>>();
private String log = "";
private boolean isCompiled;
private final ObjectIntMap<String> uniforms = new ObjectIntMap<String>();
private final ObjectIntMap<String> uniformTypes = new ObjectIntMap<String>();
private final ObjectIntMap<String> uniformSizes = new ObjectIntMap<String>();
private String[] uniformNames;
private final ObjectIntMap<String> attributes = new ObjectIntMap<String>();
private final ObjectIntMap<String> attributeTypes = new ObjectIntMap<String>();
private final ObjectIntMap<String> attributeSizes = new ObjectIntMap<String>();
private String[] attributeNames;
private int program;
private int vertexShaderHandle;
private int fragmentShaderHandle;
private final String vertexShaderSource;
private final String fragmentShaderSource;
private boolean invalidated;
private final int[] params = new int[2];
private final int[] length = new int[1];
private final int[] size = new int[1];
private final int[] type = new int[1];
private byte[] namebytes;
final IntBuffer intbuf;
public ShaderProgram(String vertexShader, String fragmentShader) {
if (vertexShader == null) {
throw new IllegalArgumentException("vertex shader must not be null");
}
if (fragmentShader == null) {
throw new IllegalArgumentException(
"fragment shader must not be null");
}
String glslVersion = "#version 100\n";
if (LSystem.base() != null && LSystem.base().graphics() != null) {
glslVersion = "#version "
+ LSystem.base().graphics().gl.getGlslVersion() + "\n";
}
this.intbuf = LSystem.base().support().newIntBuffer(1);
this.vertexShaderSource = vertexShader;
this.fragmentShaderSource = fragmentShader;
compileShaders(glslVersion + vertexShader, glslVersion + fragmentShader);
if (isCompiled()) {
fetchAttributesAndUniforms();
addManagedShader(LSystem.base(), this);
}
}
private void compileShaders(String vertexShader, String fragmentShader) {
vertexShaderHandle = loadShader(GL20.GL_VERTEX_SHADER, vertexShader);
fragmentShaderHandle = loadShader(GL20.GL_FRAGMENT_SHADER,
fragmentShader);
if (vertexShaderHandle == -1 || fragmentShaderHandle == -1) {
isCompiled = false;
return;
}
program = linkProgram(createProgram());
if (program == -1) {
isCompiled = false;
return;
}
isCompiled = true;
}
private int loadShader(int type, String source) {
GL20 gl = LSystem.base().graphics().gl;
IntBuffer intbuf = LSystem.base().support().newIntBuffer(1);
int shader = gl.glCreateShader(type);
if (shader == 0) {
return -1;
}
gl.glShaderSource(shader, source);
gl.glCompileShader(shader);
gl.glGetShaderiv(shader, GL20.GL_COMPILE_STATUS, intbuf);
int compiled = intbuf.get(0);
if (compiled == 0) {
String infoLog = gl.glGetShaderInfoLog(shader);
log += infoLog;
return -1;
}
return shader;
}
protected int createProgram() {
GL20 gl = LSystem.base().graphics().gl;
int program = gl.glCreateProgram();
return program != 0 ? program : -1;
}
private int linkProgram(int program) {
GL20 gl = LSystem.base().graphics().gl;
if (program == -1) {
return -1;
}
gl.glAttachShader(program, vertexShaderHandle);
gl.glAttachShader(program, fragmentShaderHandle);
gl.glLinkProgram(program);
ByteBuffer tmp = ByteBuffer.allocateDirect(4);
tmp.order(ByteOrder.nativeOrder());
IntBuffer intbuf = tmp.asIntBuffer();
gl.glGetProgramiv(program, GL20.GL_LINK_STATUS, intbuf);
int linked = intbuf.get(0);
if (linked == 0) {
log = LSystem.base().graphics().gl.glGetProgramInfoLog(program);
return -1;
}
return program;
}
public String getLog() {
if (isCompiled) {
log = LSystem.base().graphics().gl.glGetProgramInfoLog(program);
return log;
} else {
return log;
}
}
public boolean isCompiled() {
return isCompiled;
}
private int fetchAttributeLocation(String name) {
GL20 gl = LSystem.base().graphics().gl;
int location;
if ((location = attributes.get(name, -2)) == -2) {
location = gl.glGetAttribLocation(program, name);
attributes.put(name, location);
}
return location;
}
private int fetchUniformLocation(String name) {
return fetchUniformLocation(name, pedantic);
}
public int fetchUniformLocation(String name, boolean pedantic) {
GL20 gl = LSystem.base().graphics().gl;
int location;
if ((location = uniforms.get(name, -2)) == -2) {
location = gl.glGetUniformLocation(program, name);
if (location == -1 && pedantic) {
throw new IllegalArgumentException("no uniform with name '"
+ name + "' in shader");
}
uniforms.put(name, location);
}
return location;
}
public void setUniformi(String name, int value) {
GL20 gl = LSystem.base().graphics().gl;
checkManaged();
int location = fetchUniformLocation(name);
gl.glUniform1i(location, value);
}
public void setUniformi(int location, int value) {
GL20 gl = LSystem.base().graphics().gl;
checkManaged();
gl.glUniform1i(location, value);
}
public void setUniformi(String name, int value1, int value2) {
GL20 gl = LSystem.base().graphics().gl;
checkManaged();
int location = fetchUniformLocation(name);
gl.glUniform2i(location, value1, value2);
}
public void setUniformi(int location, int value1, int value2) {
GL20 gl = LSystem.base().graphics().gl;
checkManaged();
gl.glUniform2i(location, value1, value2);
}
public void setUniformi(String name, int value1, int value2, int value3) {
GL20 gl = LSystem.base().graphics().gl;
checkManaged();
int location = fetchUniformLocation(name);
gl.glUniform3i(location, value1, value2, value3);
}
public void setUniformi(int location, int value1, int value2, int value3) {
GL20 gl = LSystem.base().graphics().gl;
checkManaged();
gl.glUniform3i(location, value1, value2, value3);
}
public void setUniformi(String name, int value1, int value2, int value3,
int value4) {
GL20 gl = LSystem.base().graphics().gl;
checkManaged();
int location = fetchUniformLocation(name);
gl.glUniform4i(location, value1, value2, value3, value4);
}
public void setUniformi(int location, int value1, int value2, int value3,
int value4) {
GL20 gl = LSystem.base().graphics().gl;
checkManaged();
gl.glUniform4i(location, value1, value2, value3, value4);
}
public void setUniformf(String name, float value) {
GL20 gl = LSystem.base().graphics().gl;
checkManaged();
int location = fetchUniformLocation(name);
gl.glUniform1f(location, value);
}
public void setUniformf(String name, LColor values) {
setUniformf(name, values.r, values.g, values.b, values.a);
}
public void setUniformf(int location, LColor values) {
setUniformf(location, values.r, values.g, values.b, values.a);
}
public void setUniformf(int location, float value) {
GL20 gl = LSystem.base().graphics().gl;
checkManaged();
gl.glUniform1f(location, value);
}
public void setUniformf(String name, float value1, float value2) {
GL20 gl = LSystem.base().graphics().gl;
checkManaged();
int location = fetchUniformLocation(name);
gl.glUniform2f(location, value1, value2);
}
public void setUniformf(int location, float value1, float value2) {
GL20 gl = LSystem.base().graphics().gl;
checkManaged();
gl.glUniform2f(location, value1, value2);
}
public void setUniformf(String name, float value1, float value2,
float value3) {
GL20 gl = LSystem.base().graphics().gl;
checkManaged();
int location = fetchUniformLocation(name);
gl.glUniform3f(location, value1, value2, value3);
}
public void setUniformf(int location, float value1, float value2,
float value3) {
GL20 gl = LSystem.base().graphics().gl;
checkManaged();
gl.glUniform3f(location, value1, value2, value3);
}
public void setUniformf(String name, float value1, float value2,
float value3, float value4) {
GL20 gl = LSystem.base().graphics().gl;
checkManaged();
int location = fetchUniformLocation(name);
gl.glUniform4f(location, value1, value2, value3, value4);
}
public void setUniformf(int location, float value1, float value2,
float value3, float value4) {
GL20 gl = LSystem.base().graphics().gl;
checkManaged();
gl.glUniform4f(location, value1, value2, value3, value4);
}
public void setUniform1fv(String name, float[] values, int offset,
int length) {
GL20 gl = LSystem.base().graphics().gl;
checkManaged();
int location = fetchUniformLocation(name);
gl.glUniform1fv(location, length, values, offset);
}
public void setUniform1fv(int location, float[] values, int offset,
int length) {
GL20 gl = LSystem.base().graphics().gl;
checkManaged();
gl.glUniform1fv(location, length, values, offset);
}
public void setUniform2fv(String name, float[] values, int offset,
int length) {
GL20 gl = LSystem.base().graphics().gl;
checkManaged();
int location = fetchUniformLocation(name);
gl.glUniform2fv(location, length / 2, values, offset);
}
public void setUniform2fv(int location, float[] values, int offset,
int length) {
GL20 gl = LSystem.base().graphics().gl;
checkManaged();
gl.glUniform2fv(location, length / 2, values, offset);
}
public void setUniform3fv(String name, float[] values, int offset,
int length) {
GL20 gl = LSystem.base().graphics().gl;
checkManaged();
int location = fetchUniformLocation(name);
gl.glUniform3fv(location, length / 3, values, offset);
}
public void setUniform3fv(int location, float[] values, int offset,
int length) {
GL20 gl = LSystem.base().graphics().gl;
checkManaged();
gl.glUniform3fv(location, length / 3, values, offset);
}
public void setUniform4fv(String name, float[] values, int offset,
int length) {
GL20 gl = LSystem.base().graphics().gl;
checkManaged();
int location = fetchUniformLocation(name);
gl.glUniform4fv(location, length / 4, values, offset);
}
public void setUniform4fv(int location, float[] values, int offset,
int length) {
GL20 gl = LSystem.base().graphics().gl;
checkManaged();
gl.glUniform4fv(location, length / 4, values, offset);
}
public void setUniformMatrix(String name, Matrix4 matrix) {
setUniformMatrix(name, matrix, false);
}
public void setUniformMatrix(String name, Matrix4 matrix, boolean transpose) {
setUniformMatrix(fetchUniformLocation(name), matrix, transpose);
}
public void setUniformMatrix(int location, Matrix4 matrix) {
setUniformMatrix(location, matrix, false);
}
public void setUniformMatrix(int location, Matrix4 matrix, boolean transpose) {
GL20 gl = LSystem.base().graphics().gl;
checkManaged();
gl.glUniformMatrix4fv(location, 1, transpose, matrix.val, 0);
}
public void setUniformMatrix(String name, Matrix3 matrix) {
setUniformMatrix(name, matrix, false);
}
public void setUniformMatrix(String name, Matrix3 matrix, boolean transpose) {
setUniformMatrix(fetchUniformLocation(name), matrix, transpose);
}
public void setUniformMatrix(int location, Matrix3 matrix) {
setUniformMatrix(location, matrix, false);
}
public void setUniformMatrix(int location, Matrix3 matrix, boolean transpose) {
GL20 gl = LSystem.base().graphics().gl;
checkManaged();
gl.glUniformMatrix3fv(location, 1, transpose, matrix.val, 0);
}
public void setUniformMatrix3fv(String name, FloatBuffer buffer, int count,
boolean transpose) {
GL20 gl = LSystem.base().graphics().gl;
checkManaged();
buffer.position(0);
int location = fetchUniformLocation(name);
gl.glUniformMatrix3fv(location, count, transpose, buffer);
}
public void setUniformMatrix4fv(String name, FloatBuffer buffer, int count,
boolean transpose) {
GL20 gl = LSystem.base().graphics().gl;
checkManaged();
buffer.position(0);
int location = fetchUniformLocation(name);
gl.glUniformMatrix4fv(location, count, transpose, buffer);
}
public void setUniformMatrix4fv(int location, float[] values, int offset,
int length) {
GL20 gl = LSystem.base().graphics().gl;
checkManaged();
gl.glUniformMatrix4fv(location, length / 16, false, values, offset);
}
public void setUniformMatrix4fv(String name, float[] values, int offset,
int length) {
setUniformMatrix4fv(fetchUniformLocation(name), values, offset, length);
}
public void setUniformf(String name, Vector2f values) {
setUniformf(name, values.x, values.y);
}
public void setUniformf(int location, Vector2f values) {
setUniformf(location, values.x, values.y);
}
public void setUniformf(String name, Vector3f values) {
setUniformf(name, values.x, values.y, values.z);
}
public void setUniformf(int location, Vector3f values) {
setUniformf(location, values.x, values.y, values.z);
}
public void setVertexAttribute(String name, int size, int type,
boolean normalize, int stride, Buffer buffer) {
GL20 gl = LSystem.base().graphics().gl;
checkManaged();
int location = fetchAttributeLocation(name);
if (location == -1) {
return;
}
gl.glVertexAttribPointer(location, size, type, normalize, stride,
buffer);
}
public void setVertexAttribute(int location, int size, int type,
boolean normalize, int stride, Buffer buffer) {
GL20 gl = LSystem.base().graphics().gl;
checkManaged();
gl.glVertexAttribPointer(location, size, type, normalize, stride,
buffer);
}
public void setVertexAttribute(String name, int size, int type,
boolean normalize, int stride, int offset) {
GL20 gl = LSystem.base().graphics().gl;
checkManaged();
int location = fetchAttributeLocation(name);
if (location == -1)
return;
gl.glVertexAttribPointer(location, size, type, normalize, stride,
offset);
}
public void setVertexAttribute(int location, int size, int type,
boolean normalize, int stride, int offset) {
GL20 gl = LSystem.base().graphics().gl;
checkManaged();
gl.glVertexAttribPointer(location, size, type, normalize, stride,
offset);
}
public void begin() {
GL20 gl = LSystem.base().graphics().gl;
checkManaged();
gl.glUseProgram(program);
}
public void glUseProgramBind() {
GL20 gl = LSystem.base().graphics().gl;
gl.glUseProgram(program);
}
public void glUseProgramUnBind() {
if (!LSystem.mainDrawRunning()) {
GL20 gl = LSystem.base().graphics().gl;
gl.glUseProgram(0);
}
}
public void end() {
if (!LSystem.mainDrawRunning()) {
GL20 gl = LSystem.base().graphics().gl;
gl.glUseProgram(0);
}
}
public void close() {
GL20 gl = LSystem.base().graphics().gl;
if (!LSystem.mainDrawRunning()) {
gl.glUseProgram(0);
}
gl.glDeleteShader(vertexShaderHandle);
gl.glDeleteShader(fragmentShaderHandle);
gl.glDeleteProgram(program);
if (shaders.get(LSystem.base()) != null) {
shaders.get(LSystem.base()).removeValue(this, true);
}
}
public void disableVertexAttribute(String name) {
GL20 gl = LSystem.base().graphics().gl;
checkManaged();
int location = fetchAttributeLocation(name);
if (location == -1) {
return;
}
gl.glDisableVertexAttribArray(location);
}
public void disableVertexAttribute(int location) {
GL20 gl = LSystem.base().graphics().gl;
checkManaged();
gl.glDisableVertexAttribArray(location);
}
public void enableVertexAttribute(String name) {
GL20 gl = LSystem.base().graphics().gl;
checkManaged();
int location = fetchAttributeLocation(name);
if (location == -1) {
return;
}
gl.glEnableVertexAttribArray(location);
}
public void enableVertexAttribute(int location) {
GL20 gl = LSystem.base().graphics().gl;
checkManaged();
gl.glEnableVertexAttribArray(location);
}
private void checkManaged() {
if (invalidated) {
compileShaders(vertexShaderSource, fragmentShaderSource);
invalidated = false;
}
}
private void addManagedShader(LGame self, ShaderProgram shaderProgram) {
TArray<ShaderProgram> managedResources = shaders.get(self);
if (managedResources == null) {
managedResources = new TArray<ShaderProgram>();
}
managedResources.add(shaderProgram);
shaders.put(self, managedResources);
}
public static void invalidateAllShaderPrograms(LGame self) {
if (LSystem.base().graphics().gl == null) {
return;
}
TArray<ShaderProgram> shaderArray = shaders.get(self);
if (shaderArray == null) {
return;
}
for (int i = 0; i < shaderArray.size; i++) {
shaderArray.get(i).invalidated = true;
shaderArray.get(i).checkManaged();
}
}
public static void clearAllShaderPrograms(LGame self) {
shaders.remove(self);
}
public static String getManagedStatus() {
StringBuilder builder = new StringBuilder();
builder.append("Managed shaders/self: { ");
for (LGame self : shaders.keys()) {
builder.append(shaders.get(self).size);
builder.append(" ");
}
builder.append("}");
return builder.toString();
}
public void setAttributef(String name, float value1, float value2,
float value3, float value4) {
GL20 gl = LSystem.base().graphics().gl;
int location = fetchAttributeLocation(name);
gl.glVertexAttrib4f(location, value1, value2, value3, value4);
}
public void setAttributef(String name, LColor color) {
GL20 gl = LSystem.base().graphics().gl;
int location = fetchAttributeLocation(name);
gl.glVertexAttrib4f(location, color.r, color.g, color.b, color.a);
}
private void fetchAttributesAndUniforms() {
GL20 gl = LSystem.base().graphics().gl;
if (gl instanceof GLExt) {
IntBuffer params = LSystem.base().support().newIntBuffer(1);
IntBuffer type = LSystem.base().support().newIntBuffer(1);
params.clear();
gl.glGetProgramiv(program, GL20.GL_ACTIVE_ATTRIBUTES, params);
int numAttributes = params.get(0);
attributeNames = new String[numAttributes];
GLExt ext = (GLExt) gl;
for (int i = 0; i < numAttributes; i++) {
params.clear();
params.put(0, 1);
type.clear();
String name = ext.glGetActiveAttrib(program, i, params, type);
int location = gl.glGetAttribLocation(program, name);
attributes.put(name, location);
attributeTypes.put(name, type.get(0));
attributeSizes.put(name, params.get(0));
attributeNames[i] = name;
}
params.clear();
gl.glGetProgramiv(program, GL20.GL_ACTIVE_UNIFORMS, params);
int numUniforms = params.get(0);
uniformNames = new String[numUniforms];
for (int i = 0; i < numUniforms; i++) {
params.clear();
params.put(0, 1);
type.clear();
String name = ext.glGetActiveUniform(program, i, params, type);
int location = gl.glGetUniformLocation(program, name);
uniforms.put(name, location);
uniformTypes.put(name, type.get(0));
uniformSizes.put(name, params.get(0));
uniformNames[i] = name;
}
} else {
gl.glGetProgramiv(program, GL20.GL_ACTIVE_ATTRIBUTES, params, 0);
gl.glGetProgramiv(program, GL20.GL_ACTIVE_ATTRIBUTE_MAX_LENGTH,
params, 1);
int numAttributes = params[0];
int maxAttributeLength = params[1];
namebytes = new byte[maxAttributeLength];
attributeNames = new String[numAttributes];
for (int i = 0; i < numAttributes; i++) {
gl.glGetActiveAttrib(program, i, maxAttributeLength, length, 0,
size, 0, type, 0, namebytes, 0);
String name = new String(namebytes, 0, length[0]);
attributes.put(name, gl.glGetAttribLocation(program, name));
attributeTypes.put(name, type[0]);
attributeSizes.put(name, params[0]);
attributeNames[i] = name;
}
gl.glGetProgramiv(program, GL20.GL_ACTIVE_UNIFORMS, params, 0);
gl.glGetProgramiv(program, GL20.GL_ACTIVE_UNIFORM_MAX_LENGTH,
params, 1);
int numUniforms = params[0];
int maxUniformLength = params[1];
namebytes = new byte[maxUniformLength];
uniformNames = new String[numUniforms];
for (int i = 0; i < numUniforms; i++) {
gl.glGetActiveUniform(program, i, maxUniformLength, length, 0,
size, 0, type, 0, namebytes, 0);
String name = new String(namebytes, 0, length[0]);
uniforms.put(name, gl.glGetUniformLocation(program, name));
uniformTypes.put(name, type[0]);
uniformSizes.put(name, params[0]);
uniformNames[i] = name;
}
}
}
public boolean hasAttribute(String name) {
return attributes.containsKey(name);
}
public int getAttributeType(String name) {
return attributeTypes.get(name, 0);
}
public int getAttributeLocation(String name) {
return attributes.get(name, -1);
}
public int getAttributeSize(String name) {
return attributeSizes.get(name, 0);
}
public boolean hasUniform(String name) {
return uniforms.containsKey(name);
}
public int getUniformType(String name) {
return uniformTypes.get(name, 0);
}
public int getUniformLocation(String name) {
return uniforms.get(name, -1);
}
public int getUniformSize(String name) {
return uniformSizes.get(name, 0);
}
public String[] getAttributes() {
return attributeNames;
}
public String[] getUniforms() {
return uniformNames;
}
public String getVertexShaderSource() {
return vertexShaderSource;
}
public String getFragmentShaderSource() {
return fragmentShaderSource;
}
}