package openmods.renderer.shaders;
import com.google.common.collect.ImmutableList;
import gnu.trove.map.TObjectIntMap;
import gnu.trove.map.hash.TObjectIntHashMap;
import java.util.List;
public class ShaderProgram {
private final int program;
private final List<Integer> shaders;
private abstract static class ComputingObjectIntMap<T> extends TObjectIntHashMap<T> {
@Override
public int get(Object key) {
int index = index(key);
if (index < 0) {
@SuppressWarnings("unchecked")
final T k = (T)key;
final int result = computeValue(k);
put(k, result);
return result;
} else {
return _values[index];
}
}
protected abstract int computeValue(T key);
}
private final TObjectIntMap<String> uniforms = new ComputingObjectIntMap<String>() {
@Override
protected int computeValue(String key) {
return ShaderHelper.methods().glGetUniformLocation(program, key);
}
};
private final TObjectIntMap<String> attributes = new ComputingObjectIntMap<String>() {
@Override
protected int computeValue(String key) {
return ShaderHelper.methods().glGetAttribLocation(program, key);
}
};
ShaderProgram(int program, List<Integer> shaders) {
this.program = program;
this.shaders = ImmutableList.copyOf(shaders);
}
public void bind() {
ShaderHelper.methods().glUseProgram(program);
}
public void release() {
ShaderHelper.methods().glUseProgram(0);
}
public void destroy() {
for (Integer shader : shaders)
ShaderHelper.methods().glDeleteShader(shader);
ShaderHelper.methods().glUseProgram(0);
ShaderHelper.methods().glDeleteProgram(program);
}
private int getUniformLocation(String uniform) {
return uniforms.get(uniform);
}
private int getAttributeLocation(String attribute) {
return attributes.get(attribute);
}
public void uniform1i(String name, int val) {
final int location = getUniformLocation(name);
if (location >= 0) ShaderHelper.methods().glUniform1i(location, val);
}
public void uniform1f(String name, float val) {
final int location = getUniformLocation(name);
if (location >= 0) ShaderHelper.methods().glUniform1f(location, val);
}
public void uniform3f(String name, float x, float y, float z) {
final int location = getUniformLocation(name);
if (location >= 0) ShaderHelper.methods().glUniform3f(location, x, y, z);
}
public int getProgram() {
return program;
}
public void instanceAttributePointer(String attrib, int size, int type, boolean normalized, int stride, long offset) {
final int index = getAttributeLocation(attrib);
if (index >= 0) instanceAttributePointer(index, size, type, normalized, stride, offset);
}
public void instanceAttributePointer(int index, int size, int type, boolean normalized, int stride, long offset) {
attributePointer(index, size, type, normalized, stride, offset);
ArraysHelper.methods().glVertexAttribDivisor(index, 1);
}
public void attributePointer(String attrib, int size, int type, boolean normalized, int stride, long offset) {
final int index = getAttributeLocation(attrib);
if (index >= 0) attributePointer(index, size, type, normalized, stride, offset);
}
public void attributePointer(int index, int size, int type, boolean normalized, int stride, long offset) {
ShaderHelper.methods().glVertexAttribPointer(index, size, type, normalized, stride, offset);
ShaderHelper.methods().glEnableVertexAttribArray(index);
}
}