package net.tylermurphy.Minecraft.Render.Util; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.nio.FloatBuffer; import org.lwjgl.BufferUtils; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL20; import org.joml.Matrix4f; import org.joml.Vector2f; import org.joml.Vector3f; import org.joml.Vector4f; import net.tylermurphy.Minecraft.Util.Constants; public abstract class ShaderProgram { private int programID; private int vertexShaderID; private int fragmentShaderID; private static FloatBuffer matrixBuffer = BufferUtils.createFloatBuffer(16); public ShaderProgram(String vertexFile,String fragmentFile){ vertexShaderID = loadShader(vertexFile,GL20.GL_VERTEX_SHADER); fragmentShaderID = loadShader(fragmentFile,GL20.GL_FRAGMENT_SHADER); programID = GL20.glCreateProgram(); GL20.glAttachShader(programID, vertexShaderID); GL20.glAttachShader(programID, fragmentShaderID); bindAttributes(); GL20.glLinkProgram(programID); GL20.glValidateProgram(programID); getAllUniformLocations(); } protected abstract void getAllUniformLocations(); protected int getUniformLocation(String uniformName){ return GL20.glGetUniformLocation(programID,uniformName); } public void start(){ GL20.glUseProgram(programID); } public void stop(){ GL20.glUseProgram(0); } public void cleanUp(){ stop(); GL20.glDetachShader(programID, vertexShaderID); GL20.glDetachShader(programID, fragmentShaderID); GL20.glDeleteShader(vertexShaderID); GL20.glDeleteShader(fragmentShaderID); GL20.glDeleteProgram(programID); } protected abstract void bindAttributes(); protected void bindAttribute(int attribute, String variableName){ GL20.glBindAttribLocation(programID, attribute, variableName); } protected void loadFloat(int location, float value){ GL20.glUniform1f(location, value); } protected void loadInt(int location, int value){ GL20.glUniform1i(location, value); } protected void loadVector(int location, Vector3f vector){ GL20.glUniform3f(location,vector.x,vector.y,vector.z); } protected void loadVector(int location, Vector4f vector){ GL20.glUniform4f(location,vector.x,vector.y,vector.z, vector.w); } protected void load2DVector(int location, Vector2f vector){ GL20.glUniform2f(location,vector.x,vector.y); } protected void loadBoolean(int location, boolean value){ float toLoad = 0; if(value){ toLoad = 1; } GL20.glUniform1f(location, toLoad); } protected void loadMatrix(int location, Matrix4f matrix){ matrix.get(matrixBuffer); GL20.glUniformMatrix4fv(location, false, matrixBuffer); } private static int loadShader(String file, int type){ StringBuilder shaderSource = new StringBuilder(); try{ FileReader fr = new FileReader(new File(Constants.SHADER_LOCATION + file)); BufferedReader reader = new BufferedReader(fr); String line; while((line = reader.readLine())!=null){ shaderSource.append(line).append("//\n"); } reader.close(); }catch(IOException e){ e.printStackTrace(); System.exit(-1); } int shaderID = GL20.glCreateShader(type); GL20.glShaderSource(shaderID, shaderSource); GL20.glCompileShader(shaderID); if(GL20.glGetShaderi(shaderID, GL20.GL_COMPILE_STATUS )== GL11.GL_FALSE){ System.out.println(GL20.glGetShaderInfoLog(shaderID, 500)); System.err.println("Could not compile shader!"); System.exit(-1); } return shaderID; } }