Java tutorial
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package renderEngine; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.nio.FloatBuffer; import java.util.HashMap; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import org.lwjgl.BufferUtils; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL20; import org.lwjgl.util.vector.Matrix4f; import org.lwjgl.util.vector.Vector2f; import org.lwjgl.util.vector.Vector3f; /** * An abstract class that partly defines all shader programs. * * @author Blackened */ public abstract class ShaderProgram { //<editor-fold defaultstate="collapsed" desc="Properties"> /** * The ID of the shader program. */ private final int programID; /** * The ID of the vertex shader. */ private final int vertexShaderID; /** * The ID of the fragment shader. */ private final int fragmentShaderID; /** * A map of all single (e.g. no arrays) uniform variable locations mapped to * their name. */ private Map<String, Integer> uniformLocations = new HashMap<>(); //</editor-fold> //<editor-fold defaultstate="collapsed" desc="Getters and Setters"> protected Map<String, Integer> getUniformLocations() { return uniformLocations; } //</editor-fold> //<editor-fold defaultstate="collapsed" desc="Constructors"> /** * Creates a new instance of ShaderProgram, and links the program. * * @param vertexFile The relative location of the vertex shader file. * @param fragmentFile The relative location of the fragment shader file. */ public ShaderProgram(String vertexFile, String fragmentFile) { this.vertexShaderID = loadShader(vertexFile, GL20.GL_VERTEX_SHADER); this.fragmentShaderID = loadShader(fragmentFile, GL20.GL_FRAGMENT_SHADER); this.programID = GL20.glCreateProgram(); GL20.glAttachShader(programID, vertexShaderID); GL20.glAttachShader(programID, fragmentShaderID); bindVariablesAndValidate(); } //</editor-fold> //<editor-fold defaultstate="collapsed" desc="Public Methods"> /** * Starts the program. */ public final void start() { GL20.glUseProgram(programID); } /** * Stops the program. */ public final void stop() { GL20.glUseProgram(0); } /** * Cleans the memory from all shaders and the program itself. */ public final void cleanUp() { stop(); GL20.glDetachShader(programID, vertexShaderID); GL20.glDetachShader(programID, fragmentShaderID); GL20.glDeleteShader(vertexShaderID); GL20.glDeleteShader(fragmentShaderID); GL20.glDeleteProgram(programID); } //</editor-fold> //<editor-fold defaultstate="collapsed" desc="Protected Methods"> /** * Will get all uniform locations by calling the getUniformLocation method * for all uniform variables needed. */ protected abstract void getAllUniformLocations(); /** * Get the location for a uniform variable. * * @param uniformName The name of the uniform variable for which the * location will be returned. * @return The location of a uniform variable specified by the name. */ protected int getUniformLocation(String uniformName) { return GL20.glGetUniformLocation(programID, uniformName); } /** * Will bind all necessary attributes by calling the bindAttribute method * for all of them. */ protected abstract void bindAttributes(); /** * Will take in the number of the attribute list in the VAO and bind it to * the variable name in the shader. * * @param attribute The number of the attribute list in the VAO. * @param variableName The name of the variable in the shader. */ protected void bindAttribute(int attribute, String variableName) { GL20.glBindAttribLocation(programID, attribute, variableName); } /** * Loads a float value to the uniform variable in the specified location. * * @param location The location of the uniform variable to which the float * needs to be loaded. * @param value The value that needs to be loaded into the uniform variable. */ protected void loadFloat(int location, float value) { GL20.glUniform1f(location, value); } /** * Loads an integer value to the uniform variable in the specified location. * * @param location The location of the uniform variable to which the integer * needs to be loaded. * @param value The value that needs to be loaded into the uniform variable. */ protected void loadInt(int location, int value) { GL20.glUniform1i(location, value); } /** * Loads a vector value to the uniform variable in the specified location. * * @param location The location of the uniform variable to which the float * needs to be loaded. * @param vector The value that needs to be loaded into the uniform * variable. */ protected void loadVector(int location, Vector3f vector) { GL20.glUniform3f(location, vector.x, vector.y, vector.z); } protected void load2DVector(int location, Vector2f vector) { GL20.glUniform2f(location, vector.x, vector.y); } /** * Loads a boolean value to the uniform variable in the specified location * by converting it to a float first. 1 equals true, 0 equals false; * * @param location The location of the uniform variable to which the boolean * needs to be loaded. * @param value The value that needs to be loaded into the uniform variable. */ protected void loadBoolean(int location, boolean value) { float toLoad = 0; if (value) { toLoad = 1; } GL20.glUniform1f(location, toLoad); } /** * Loads a matrix to the uniform variable in the specified location by * converting it to a float buffer first. * * @param location The location of the uniform variable to which the matrix * needs to be loaded. * @param matrix The matrix that needs to be loaded into the uniform * variable. */ protected void loadMatrix(int location, Matrix4f matrix) { FloatBuffer matrixBuffer = BufferUtils.createFloatBuffer(16); matrix.store(matrixBuffer); matrixBuffer.flip(); GL20.glUniformMatrix4(location, false, matrixBuffer); } //</editor-fold> //<editor-fold defaultstate="collapsed" desc="Private Methods"> /** * Binds the <b>in</b> variables of the vertex shader, the uniform * variables, and links and validates both shaders. */ private void bindVariablesAndValidate() { bindAttributes(); GL20.glLinkProgram(programID); GL20.glValidateProgram(programID); getAllUniformLocations(); } /** * Loads the shader given its content and type. * * @param file The content of the shader file. * @param type The type of shader (lwjgl!). * @return The shader ID. */ private static int loadShader(String file, int type) { StringBuilder shaderSource = new StringBuilder(); try { BufferedReader reader = new BufferedReader(new FileReader(file)); String line; while ((line = reader.readLine()) != null) { shaderSource.append(line).append("\n"); } reader.close(); } catch (IOException ex) { Logger.getLogger(ShaderProgram.class.getName()).log(Level.SEVERE, null, ex); } 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.GL_COMPILE_STATUS); System.out.println("Shader of type: " + type + " did not compile!"); } return shaderID; } //</editor-fold> }