package com.team.futurecraft.rendering; import static org.lwjgl.opengl.GL11.GL_TRUE; import static org.lwjgl.opengl.GL20.GL_COMPILE_STATUS; import static org.lwjgl.opengl.GL20.GL_FRAGMENT_SHADER; import static org.lwjgl.opengl.GL20.GL_VERTEX_SHADER; import static org.lwjgl.opengl.GL20.glAttachShader; import static org.lwjgl.opengl.GL20.glCompileShader; import static org.lwjgl.opengl.GL20.glCreateProgram; import static org.lwjgl.opengl.GL20.glCreateShader; import static org.lwjgl.opengl.GL20.glDeleteShader; import static org.lwjgl.opengl.GL20.glGetShaderInfoLog; import static org.lwjgl.opengl.GL20.glGetShaderi; import static org.lwjgl.opengl.GL20.glLinkProgram; import static org.lwjgl.opengl.GL20.glShaderSource; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.HashMap; import java.util.Iterator; import java.util.Map.Entry; import java.util.Set; import org.lwjgl.opengl.GL20; import com.team.futurecraft.Mat4f; import com.team.futurecraft.Vec3f; import net.minecraft.client.Minecraft; import net.minecraft.util.ResourceLocation; public class Shader { public int id; private static HashMap<String, Integer> shaders = new HashMap<String, Integer>(); private static HashMap<Integer, Integer> BoundVsh = new HashMap<Integer, Integer>(); private static HashMap<Integer, Integer> BoundFsh = new HashMap<Integer, Integer>(); public Shader(int id) { this.id = id; } public void bind() { GL20.glUseProgram(id); } public void unBind() { GL20.glUseProgram(0); } public void uniformMat4(Mat4f mat, String name) { int uniform = GL20.glGetUniformLocation(this.id, name); GL20.glUniformMatrix4(uniform, false, mat.getBuffer()); } public void uniformFloat(float value, String name) { int uniform = GL20.glGetUniformLocation(this.id, name); GL20.glUniform1f(uniform, value); } public void uniformVec3f(Vec3f vec, String name) { int uniform = GL20.glGetUniformLocation(this.id, name); GL20.glUniform3f(uniform, (float)vec.x, (float)vec.y, (float)vec.z); } public static Shader loadShader(String name) { if (shaders.containsKey(name)) { return new Shader(shaders.get(name)); } else { System.out.println("loading shader: " + name + " from file"); int id = glCreateProgram(); loadProgram(name + ".vsh", name + ".fsh", id); shaders.put(name, id); return new Shader(id); } } public static void reloadShaders() { Set<Entry<String, Integer>> entrySet = shaders.entrySet(); Iterator<Entry<String, Integer>> iterator = entrySet.iterator(); while (iterator.hasNext()) { Entry<String, Integer> entry = iterator.next(); String key = entry.getKey(); int value = entry.getValue(); GL20.glDetachShader(value, BoundVsh.get(value)); GL20.glDetachShader(value, BoundFsh.get(value)); loadProgram(key + ".vsh", key + ".fsh", value); } } private static void loadProgram(String vshPath, String fshPath, int id) { String vertexSource = loadShaderFile(vshPath); String fragmentSource = loadShaderFile(fshPath); //compile shaders int vertexShader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertexShader, vertexSource); glCompileShader(vertexShader); int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragmentShader, fragmentSource); glCompileShader(fragmentShader); //check shaders int status = glGetShaderi(vertexShader, GL_COMPILE_STATUS); if (status != GL_TRUE) { throw new RuntimeException(glGetShaderInfoLog(vertexShader, 1000)); } int status2 = glGetShaderi(fragmentShader, GL_COMPILE_STATUS); if (status2 != GL_TRUE) { throw new RuntimeException(glGetShaderInfoLog(fragmentShader, 1000)); } BoundVsh.put(id, vertexShader); BoundFsh.put(id, fragmentShader); //create shader program glAttachShader(id, vertexShader); glAttachShader(id, fragmentShader); glLinkProgram(id); glDeleteShader(vertexShader); glDeleteShader(fragmentShader); } private static String loadShaderFile(String path) { Minecraft mc = Minecraft.getMinecraft(); String shader = ""; try { InputStream stream = mc.getResourceManager().getResource(new ResourceLocation("futurecraft", "shaders/" + path)).getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); String line = null; while ((line = reader.readLine()) != null) { shader += line + "\n"; } } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } return shader; } }