package electrosphere.renderer.shader; 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_LINK_STATUS; 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.glGetProgramInfoLog; import static org.lwjgl.opengl.GL20.glGetProgrami; import static org.lwjgl.opengl.GL20.glGetShaderi; import static org.lwjgl.opengl.GL20.glGetUniformLocation; import static org.lwjgl.opengl.GL20.glLinkProgram; import static org.lwjgl.opengl.GL20.glShaderSource; import static org.lwjgl.opengl.GL32.GL_GEOMETRY_SHADER; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import javax.management.RuntimeErrorException; import org.joml.Matrix4d; import org.joml.Matrix4f; import org.joml.Vector3f; import org.lwjgl.BufferUtils; import org.lwjgl.opengl.GL20; import org.lwjgl.opengl.GL40; import electrosphere.engine.Globals; import electrosphere.logger.LoggerInterface; import electrosphere.renderer.OpenGLState; import electrosphere.util.FileUtils; /** * A shader program */ public class ShaderProgram { // //Program stuff // int vertexShader; int geometryShader; int fragmentShader; int shaderId; // //Uniform locations // public int shaderVertexModelLoc; public int shaderVertexViewLoc; public int shaderVertexProjectionLoc; public int shaderVertexViewPosLoc; public int shaderVertexBonesLoc; public int shaderVertexHasBonesLoc; public int shaderVertexNumBonesLoc; //Uniforms public Map uniformMap = new HashMap(); //keeps track of programs that have already been compiled and returns them instead of recompiling from scratch static Map alreadyCompiledMap = new HashMap(); public static ShaderProgram smart_assemble_shader(boolean ContainsBones, boolean apply_lighting){ //return shader if it has already been compiled String shaderKey = ContainsBones + "-" + apply_lighting; if(alreadyCompiledMap.containsKey(shaderKey)){ return alreadyCompiledMap.get(shaderKey); } String vertex_shader_path = ""; if(ContainsBones){ vertex_shader_path = "/Shaders/VertexShader.vs"; } else { vertex_shader_path = "/Shaders/VertexShaderNoBones.vs"; } String fragment_shader_path = "/Shaders/FragmentShader.fs"; // //Create ShaderProgram object // ShaderProgram rVal = new ShaderProgram(); // //Read in shader programs // String tempForReadingShaders = ""; try { BufferedReader br = new BufferedReader(new InputStreamReader(FileUtils.getAssetFileAsStream(vertex_shader_path))); try { StringBuilder sb = new StringBuilder(); String line = br.readLine(); while (line != null) { sb.append(line); sb.append(System.lineSeparator()); line = br.readLine(); } tempForReadingShaders = sb.toString(); } finally { br.close(); } } catch (IOException e) { } String vertexShaderSource = tempForReadingShaders; //This try-catch block reads the FragmentShader source into memory try { BufferedReader br = new BufferedReader(new InputStreamReader(FileUtils.getAssetFileAsStream(fragment_shader_path))); try { StringBuilder sb = new StringBuilder(); String line = br.readLine(); while (line != null) { sb.append(line); sb.append(System.lineSeparator()); line = br.readLine(); } tempForReadingShaders = sb.toString(); } finally { br.close(); } } catch (IOException e) { } String fragmentShaderSource = tempForReadingShaders; //Creates a new shader object and assigns its 'pointer' to the integer "vertexShader" rVal.vertexShader = glCreateShader(GL20.GL_VERTEX_SHADER); //This alerts openGL to the presence of a vertex shader and points the shader at its source glShaderSource(rVal.vertexShader, vertexShaderSource); //Compiles the source for the vertex shader object glCompileShader(rVal.vertexShader); //The following tests if the vertex shader compiles successfully int success; success = glGetShaderi(rVal.vertexShader, GL_COMPILE_STATUS); if (success != GL_TRUE) { LoggerInterface.loggerRenderer.WARNING("Vertex Shader failed to compile!"); LoggerInterface.loggerRenderer.WARNING("Source is: "); LoggerInterface.loggerRenderer.WARNING(GL20.glGetShaderSource(rVal.vertexShader)); LoggerInterface.loggerRenderer.ERROR("Runtime Exception", new RuntimeException(GL20.glGetShaderInfoLog(rVal.vertexShader))); } //Creates and opengl object for a fragment shader and assigns its 'pointer' to the integer fragmentShader rVal.fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); //This points the opengl shadder object to its proper source glShaderSource(rVal.fragmentShader, fragmentShaderSource); //This compiles the shader object glCompileShader(rVal.fragmentShader); //This tests for the success of the compile attempt success = glGetShaderi(rVal.fragmentShader, GL_COMPILE_STATUS); if (success != GL_TRUE) { LoggerInterface.loggerRenderer.WARNING("Fragment Shader failed to compile!"); LoggerInterface.loggerRenderer.WARNING("Source is: "); LoggerInterface.loggerRenderer.WARNING(GL20.glGetShaderSource(rVal.fragmentShader)); LoggerInterface.loggerRenderer.ERROR("Runtime Exception", new RuntimeException(GL20.glGetShaderInfoLog(rVal.fragmentShader))); } //This creates a shader program opengl object and assigns its 'pointer' to the integer shaderProgram rVal.shaderId = glCreateProgram(); //This attaches the vertex and fragment shaders to the program glAttachShader(rVal.shaderId, rVal.vertexShader); glAttachShader(rVal.shaderId, rVal.fragmentShader); //This links the program to the GPU (I think its to the GPU anyway) glLinkProgram(rVal.shaderId); //Tests for the success of the shader program creation success = glGetProgrami(rVal.shaderId, GL_LINK_STATUS); if (success != GL_TRUE) { throw new RuntimeException(glGetProgramInfoLog(rVal.shaderId)); } //Deletes the individual shader objects to free up memory glDeleteShader(rVal.vertexShader); glDeleteShader(rVal.fragmentShader); // //Set locations // rVal.shaderVertexModelLoc = glGetUniformLocation(rVal.shaderId, "model"); rVal.shaderVertexViewLoc = glGetUniformLocation(rVal.shaderId, "view"); rVal.shaderVertexProjectionLoc = glGetUniformLocation(rVal.shaderId, "projection"); rVal.shaderVertexViewPosLoc = glGetUniformLocation(rVal.shaderId, "viewPos"); if(ContainsBones){ rVal.shaderVertexBonesLoc = glGetUniformLocation(rVal.shaderId, "bones"); rVal.shaderVertexNumBonesLoc = glGetUniformLocation(rVal.shaderId, "numBones"); } rVal.shaderVertexHasBonesLoc = glGetUniformLocation(rVal.shaderId, "hasBones"); alreadyCompiledMap.put(shaderKey,rVal); return rVal; } /** * Intelligently assembles a shader for use in OIT part of render pipeline * @param ContainsBones True if contains bones * @param apply_lighting True if should apply lighting * @return The int-pointer to the shader compiled */ public static ShaderProgram smartAssembleOITProgram(boolean ContainsBones, boolean apply_lighting){ //return shader if it has already been compiled String shaderKey = "oit" + ContainsBones + "-" + apply_lighting; if(alreadyCompiledMap.containsKey(shaderKey)){ return alreadyCompiledMap.get(shaderKey); } String vertex_shader_path = ""; if(ContainsBones){ vertex_shader_path = "/Shaders/oit/general/VertexShader.vs"; } else { vertex_shader_path = "/Shaders/oit/general/VertexShaderNoBones.vs"; } String fragment_shader_path = "/Shaders/oit/general/FragmentShader.fs"; // //Create ShaderProgram object // ShaderProgram rVal = new ShaderProgram(); // //Read in shader programs // String tempForReadingShaders = ""; try { BufferedReader br = new BufferedReader(new InputStreamReader(FileUtils.getAssetFileAsStream(vertex_shader_path))); try { StringBuilder sb = new StringBuilder(); String line = br.readLine(); while (line != null) { sb.append(line); sb.append(System.lineSeparator()); line = br.readLine(); } tempForReadingShaders = sb.toString(); } finally { br.close(); } } catch (IOException e) { } String vertexShaderSource = tempForReadingShaders; //This try-catch block reads the FragmentShader source into memory try { BufferedReader br = new BufferedReader(new InputStreamReader(FileUtils.getAssetFileAsStream(fragment_shader_path))); try { StringBuilder sb = new StringBuilder(); String line = br.readLine(); while (line != null) { sb.append(line); sb.append(System.lineSeparator()); line = br.readLine(); } tempForReadingShaders = sb.toString(); } finally { br.close(); } } catch (IOException e) { } String fragmentShaderSource = tempForReadingShaders; //Creates a new shader object and assigns its 'pointer' to the integer "vertexShader" rVal.vertexShader = glCreateShader(GL20.GL_VERTEX_SHADER); //This alerts openGL to the presence of a vertex shader and points the shader at its source glShaderSource(rVal.vertexShader, vertexShaderSource); //Compiles the source for the vertex shader object glCompileShader(rVal.vertexShader); //The following tests if the vertex shader compiles successfully int success; success = glGetShaderi(rVal.vertexShader, GL_COMPILE_STATUS); if (success != GL_TRUE) { LoggerInterface.loggerRenderer.WARNING("Vertex Shader failed to compile!"); LoggerInterface.loggerRenderer.WARNING("Source is: "); LoggerInterface.loggerRenderer.WARNING(GL20.glGetShaderSource(rVal.vertexShader)); LoggerInterface.loggerRenderer.ERROR("Runtime Exception", new RuntimeException(GL20.glGetShaderInfoLog(rVal.vertexShader))); } //Creates and opengl object for a fragment shader and assigns its 'pointer' to the integer fragmentShader rVal.fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); //This points the opengl shadder object to its proper source glShaderSource(rVal.fragmentShader, fragmentShaderSource); //This compiles the shader object glCompileShader(rVal.fragmentShader); //This tests for the success of the compile attempt success = glGetShaderi(rVal.fragmentShader, GL_COMPILE_STATUS); if (success != GL_TRUE) { LoggerInterface.loggerRenderer.WARNING("Fragment Shader failed to compile!"); LoggerInterface.loggerRenderer.WARNING("Source is: "); LoggerInterface.loggerRenderer.WARNING(GL20.glGetShaderSource(rVal.fragmentShader)); LoggerInterface.loggerRenderer.ERROR("Runtime Exception", new RuntimeException(GL20.glGetShaderInfoLog(rVal.fragmentShader))); } //This creates a shader program opengl object and assigns its 'pointer' to the integer shaderProgram rVal.shaderId = glCreateProgram(); //This attaches the vertex and fragment shaders to the program glAttachShader(rVal.shaderId, rVal.vertexShader); glAttachShader(rVal.shaderId, rVal.fragmentShader); //This links the program to the GPU (I think its to the GPU anyway) glLinkProgram(rVal.shaderId); //Tests for the success of the shader program creation success = glGetProgrami(rVal.shaderId, GL_LINK_STATUS); if (success != GL_TRUE) { throw new RuntimeException(glGetProgramInfoLog(rVal.shaderId)); } //Deletes the individual shader objects to free up memory glDeleteShader(rVal.vertexShader); glDeleteShader(rVal.fragmentShader); // //Set locations // rVal.shaderVertexModelLoc = glGetUniformLocation(rVal.shaderId, "model"); rVal.shaderVertexViewLoc = glGetUniformLocation(rVal.shaderId, "view"); rVal.shaderVertexProjectionLoc = glGetUniformLocation(rVal.shaderId, "projection"); rVal.shaderVertexViewPosLoc = glGetUniformLocation(rVal.shaderId, "viewPos"); if(ContainsBones){ rVal.shaderVertexBonesLoc = glGetUniformLocation(rVal.shaderId, "bones"); rVal.shaderVertexNumBonesLoc = glGetUniformLocation(rVal.shaderId, "numBones"); } rVal.shaderVertexHasBonesLoc = glGetUniformLocation(rVal.shaderId, "hasBones"); alreadyCompiledMap.put(shaderKey,rVal); return rVal; } public static ShaderProgram load_default_shader_program(){ // //Create ShaderProgram object // ShaderProgram rVal = new ShaderProgram(); // //Read in shader programs // String tempForReadingShaders = ""; try { BufferedReader br = new BufferedReader(new FileReader(FileUtils.getAssetFile("/Shaders/VertexShader.vs"))); try { StringBuilder sb = new StringBuilder(); String line = br.readLine(); while (line != null) { sb.append(line); sb.append(System.lineSeparator()); line = br.readLine(); } tempForReadingShaders = sb.toString(); } finally { br.close(); } } catch (IOException e) { } String vertexShaderSource = tempForReadingShaders; //This try-catch block reads the FragmentShader source into memory try { BufferedReader br = new BufferedReader(new FileReader(FileUtils.getAssetFile("/Shaders/FragmentShader.fs"))); try { StringBuilder sb = new StringBuilder(); String line = br.readLine(); while (line != null) { sb.append(line); sb.append(System.lineSeparator()); line = br.readLine(); } tempForReadingShaders = sb.toString(); } finally { br.close(); } } catch (IOException e) { } String fragmentShaderSource = tempForReadingShaders; //Creates a new shader object and assigns its 'pointer' to the integer "vertexShader" rVal.vertexShader = glCreateShader(GL_VERTEX_SHADER); //This alerts openGL to the presence of a vertex shader and points the shader at its source glShaderSource(rVal.vertexShader, vertexShaderSource); //Compiles the source for the vertex shader object glCompileShader(rVal.vertexShader); //The following tests if the vertex shader compiles successfully int success; success = glGetShaderi(rVal.vertexShader, GL_COMPILE_STATUS); if (success != GL_TRUE) { LoggerInterface.loggerRenderer.WARNING("Vertex Shader failed to compile!"); LoggerInterface.loggerRenderer.WARNING("Source is: "); LoggerInterface.loggerRenderer.WARNING(GL20.glGetShaderSource(rVal.vertexShader)); LoggerInterface.loggerRenderer.ERROR("Runtime Exception", new RuntimeException(GL20.glGetShaderInfoLog(rVal.vertexShader))); } //Creates and opengl object for a fragment shader and assigns its 'pointer' to the integer fragmentShader rVal.fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); //This points the opengl shadder object to its proper source glShaderSource(rVal.fragmentShader, fragmentShaderSource); //This compiles the shader object glCompileShader(rVal.fragmentShader); //This tests for the success of the compile attempt success = glGetShaderi(rVal.fragmentShader, GL_COMPILE_STATUS); if (success != GL_TRUE) { LoggerInterface.loggerRenderer.WARNING("Fragment Shader failed to compile!"); LoggerInterface.loggerRenderer.WARNING("Source is: "); LoggerInterface.loggerRenderer.WARNING(GL20.glGetShaderSource(rVal.fragmentShader)); LoggerInterface.loggerRenderer.ERROR("Runtime Exception", new RuntimeException(GL20.glGetShaderInfoLog(rVal.fragmentShader))); } //This creates a shader program opengl object and assigns its 'pointer' to the integer shaderProgram rVal.shaderId = glCreateProgram(); //This attaches the vertex and fragment shaders to the program glAttachShader(rVal.shaderId, rVal.vertexShader); glAttachShader(rVal.shaderId, rVal.fragmentShader); //This links the program to the GPU (I think its to the GPU anyway) glLinkProgram(rVal.shaderId); //Tests for the success of the shader program creation success = glGetProgrami(rVal.shaderId, GL_LINK_STATUS); if (success != GL_TRUE) { throw new RuntimeException(glGetProgramInfoLog(rVal.shaderId)); } //Deletes the individual shader objects to free up memory glDeleteShader(rVal.vertexShader); glDeleteShader(rVal.fragmentShader); // //Set locations // rVal.shaderVertexModelLoc = glGetUniformLocation(rVal.shaderId, "model"); rVal.shaderVertexViewLoc = glGetUniformLocation(rVal.shaderId, "view"); rVal.shaderVertexProjectionLoc = glGetUniformLocation(rVal.shaderId, "projection"); rVal.shaderVertexViewPosLoc = glGetUniformLocation(rVal.shaderId, "viewPos"); rVal.shaderVertexBonesLoc = glGetUniformLocation(rVal.shaderId, "bones"); rVal.shaderVertexNumBonesLoc = glGetUniformLocation(rVal.shaderId, "numBones"); rVal.shaderVertexHasBonesLoc = glGetUniformLocation(rVal.shaderId, "hasBones"); return rVal; } public static ShaderProgram loadSpecificShader(String vertexPath, String fragmentPath){ ShaderProgram rVal = new ShaderProgram(); // //Read in shader programs // String vertexShaderSource = ""; String fragmentShaderSource = ""; try { vertexShaderSource = FileUtils.getAssetFileAsString(vertexPath); fragmentShaderSource = FileUtils.getAssetFileAsString(fragmentPath); } catch(IOException ex){ } //Creates a new shader object and assigns its 'pointer' to the integer "vertexShader" rVal.vertexShader = glCreateShader(GL_VERTEX_SHADER); //This alerts openGL to the presence of a vertex shader and points the shader at its source glShaderSource(rVal.vertexShader, vertexShaderSource); //Compiles the source for the vertex shader object glCompileShader(rVal.vertexShader); //The following tests if the vertex shader compiles successfully int success; success = glGetShaderi(rVal.vertexShader, GL_COMPILE_STATUS); if (success != GL_TRUE) { List errorLines = new LinkedList(); LoggerInterface.loggerRenderer.WARNING("Failed to load " + vertexPath + " ... attempting alternatives"); //report failed to load shader errorLines.add("Vertex Shader failed to compile!"); errorLines.add("Source File is: " + vertexPath); errorLines.add("Source is: "); errorLines.add(GL20.glGetShaderSource(rVal.vertexShader)); errorLines.add(new RuntimeException(GL20.glGetShaderInfoLog(rVal.vertexShader))); // LoggerInterface.loggerRenderer.WARNING("Vertex Shader failed to compile!"); // LoggerInterface.loggerRenderer.WARNING("Source File is: " + vertexPath); // LoggerInterface.loggerRenderer.WARNING("Source is: "); // LoggerInterface.loggerRenderer.WARNING(GL20.glGetShaderSource(rVal.vertexShader)); // LoggerInterface.loggerRenderer.ERROR("Runtime Exception", new RuntimeException(GL20.glGetShaderInfoLog(rVal.vertexShader))); //attempt loading alternative shaders List availableAlternatives = Globals.shaderOptionMap.getAlternativesForFile(vertexPath); int alternativesAttempted = 0; if(availableAlternatives != null){ for(String alternative : availableAlternatives){ alternativesAttempted++; //load file try { vertexShaderSource = FileUtils.getAssetFileAsString(alternative); } catch (IOException e) { LoggerInterface.loggerEngine.ERROR("Failed to load shader alternative " + alternative, e); } //Creates a new shader object and assigns its 'pointer' to the integer "vertexShader" rVal.vertexShader = glCreateShader(GL_VERTEX_SHADER); //This alerts openGL to the presence of a vertex shader and points the shader at its source glShaderSource(rVal.vertexShader, vertexShaderSource); //Compiles the source for the vertex shader object glCompileShader(rVal.vertexShader); //The following tests if the vertex shader compiles successfully success = glGetShaderi(rVal.vertexShader, GL_COMPILE_STATUS); if (success == GL_TRUE) { LoggerInterface.loggerRenderer.WARNING("Successfully loaded alternative shader " + alternative); break; } else { errorLines.add("Vertex Shader failed to compile!"); errorLines.add("Source File is: " + vertexPath); errorLines.add("Source is: "); errorLines.add(GL20.glGetShaderSource(rVal.vertexShader)); errorLines.add(new RuntimeException(GL20.glGetShaderInfoLog(rVal.vertexShader))); // LoggerInterface.loggerRenderer.WARNING("Vertex Shader failed to compile!"); // LoggerInterface.loggerRenderer.WARNING("Source File is: " + vertexPath); // LoggerInterface.loggerRenderer.WARNING("Source is: "); // LoggerInterface.loggerRenderer.WARNING(GL20.glGetShaderSource(rVal.vertexShader)); // LoggerInterface.loggerRenderer.ERROR("Runtime Exception", new RuntimeException(GL20.glGetShaderInfoLog(rVal.vertexShader))); } } if(success != GL_TRUE){ for(Object object : errorLines){ if(object instanceof String){ LoggerInterface.loggerRenderer.WARNING((String)object); } else if(object instanceof RuntimeErrorException){ LoggerInterface.loggerRenderer.ERROR("Runtime Exception", (RuntimeErrorException)object); } } } LoggerInterface.loggerRenderer.WARNING("Attempted " + alternativesAttempted + " alternative shaders"); } } //Creates and opengl object for a fragment shader and assigns its 'pointer' to the integer fragmentShader rVal.fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); //This points the opengl shadder object to its proper source glShaderSource(rVal.fragmentShader, fragmentShaderSource); //This compiles the shader object glCompileShader(rVal.fragmentShader); //This tests for the success of the compile attempt success = glGetShaderi(rVal.fragmentShader, GL_COMPILE_STATUS); if (success != GL_TRUE) { List errorLines = new LinkedList(); LoggerInterface.loggerRenderer.WARNING("Failed to load " + fragmentPath + " ... attempting alternatives"); //report failed to load shader errorLines.add("Fragment Shader failed to compile!"); errorLines.add("Source File is: " + fragmentPath); errorLines.add("Source is: "); errorLines.add(GL20.glGetShaderSource(rVal.fragmentShader)); errorLines.add(new RuntimeException(GL20.glGetShaderInfoLog(rVal.fragmentShader))); // LoggerInterface.loggerRenderer.WARNING("Fragment Shader failed to compile!"); // LoggerInterface.loggerRenderer.WARNING("Source File is: " + fragmentPath); // LoggerInterface.loggerRenderer.WARNING("Source is: "); // LoggerInterface.loggerRenderer.WARNING(GL20.glGetShaderSource(rVal.fragmentShader)); // LoggerInterface.loggerRenderer.ERROR("Runtime Exception", new RuntimeException(GL20.glGetShaderInfoLog(rVal.fragmentShader))); //attempt loading alternative shaders List availableAlternatives = Globals.shaderOptionMap.getAlternativesForFile(fragmentPath); int alternativesAttempted = 0; if(availableAlternatives != null){ for(String alternative : availableAlternatives){ alternativesAttempted++; //load file try { fragmentShaderSource = FileUtils.getAssetFileAsString(alternative); } catch (IOException e) { LoggerInterface.loggerEngine.ERROR("Failed to load shader alternative " + alternative, e); } //Creates a new shader object and assigns its 'pointer' to the integer "vertexShader" rVal.fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); //This alerts openGL to the presence of a vertex shader and points the shader at its source glShaderSource(rVal.fragmentShader, fragmentShaderSource); //Compiles the source for the vertex shader object glCompileShader(rVal.fragmentShader); //The following tests if the vertex shader compiles successfully success = glGetShaderi(rVal.fragmentShader, GL_COMPILE_STATUS); if (success == GL_TRUE) { LoggerInterface.loggerRenderer.WARNING("Successfully loaded alternative shader " + alternative); break; } else { errorLines.add("Fragment Shader failed to compile!"); errorLines.add("Source File is: " + fragmentPath); errorLines.add("Source is: "); errorLines.add(GL20.glGetShaderSource(rVal.fragmentShader)); errorLines.add(new RuntimeException(GL20.glGetShaderInfoLog(rVal.fragmentShader))); // LoggerInterface.loggerRenderer.WARNING("Fragment Shader failed to compile!"); // LoggerInterface.loggerRenderer.WARNING("Source File is: " + fragmentPath); // LoggerInterface.loggerRenderer.WARNING("Source is: "); // LoggerInterface.loggerRenderer.WARNING(GL20.glGetShaderSource(rVal.fragmentShader)); // LoggerInterface.loggerRenderer.ERROR("Runtime Exception", new RuntimeException(GL20.glGetShaderInfoLog(rVal.fragmentShader))); } } if(success != GL_TRUE){ for(Object object : errorLines){ if(object instanceof String){ LoggerInterface.loggerRenderer.WARNING((String)object); } else if(object instanceof RuntimeErrorException){ LoggerInterface.loggerRenderer.ERROR("Runtime Exception", (RuntimeErrorException)object); } } } LoggerInterface.loggerRenderer.WARNING("Attempted " + alternativesAttempted + " alternative shaders"); } } //This creates a shader program opengl object and assigns its 'pointer' to the integer shaderProgram rVal.shaderId = glCreateProgram(); //This attaches the vertex and fragment shaders to the program glAttachShader(rVal.shaderId, rVal.vertexShader); glAttachShader(rVal.shaderId, rVal.fragmentShader); //This links the program to the GPU (I think its to the GPU anyway) glLinkProgram(rVal.shaderId); //Tests for the success of the shader program creation success = glGetProgrami(rVal.shaderId, GL_LINK_STATUS); if (success != GL_TRUE) { LoggerInterface.loggerRenderer.ERROR(glGetProgramInfoLog(rVal.shaderId), new RuntimeException(glGetProgramInfoLog(rVal.shaderId))); LoggerInterface.loggerRenderer.WARNING("Shader sources: " + vertexPath + " " + fragmentPath); return Globals.defaultMeshShader; // throw new RuntimeException(glGetProgramInfoLog(rVal.shaderProgram)); } //Deletes the individual shader objects to free up memory glDeleteShader(rVal.vertexShader); glDeleteShader(rVal.fragmentShader); // //Set locations // rVal.shaderVertexModelLoc = glGetUniformLocation(rVal.shaderId, "model"); rVal.shaderVertexViewLoc = glGetUniformLocation(rVal.shaderId, "view"); rVal.shaderVertexProjectionLoc = glGetUniformLocation(rVal.shaderId, "projection"); rVal.shaderVertexViewPosLoc = glGetUniformLocation(rVal.shaderId, "viewPos"); return rVal; } public static ShaderProgram loadSpecificShader(String vertexPath, String geometryPath, String fragmentPath){ ShaderProgram rVal = new ShaderProgram(); // //Read in shader programs // String vertexShaderSource = ""; String geometryShaderSource = ""; String fragmentShaderSource = ""; try { vertexShaderSource = FileUtils.getAssetFileAsString(vertexPath); geometryShaderSource = FileUtils.getAssetFileAsString(geometryPath); fragmentShaderSource = FileUtils.getAssetFileAsString(fragmentPath); } catch(IOException ex){ } //Creates a new shader object and assigns its 'pointer' to the integer "vertexShader" rVal.vertexShader = glCreateShader(GL_VERTEX_SHADER); //This alerts openGL to the presence of a vertex shader and points the shader at its source glShaderSource(rVal.vertexShader, vertexShaderSource); //Compiles the source for the vertex shader object glCompileShader(rVal.vertexShader); //The following tests if the vertex shader compiles successfully int success; success = glGetShaderi(rVal.vertexShader, GL_COMPILE_STATUS); if (success != GL_TRUE) { LoggerInterface.loggerRenderer.WARNING("Vertex Shader failed to compile!"); LoggerInterface.loggerRenderer.WARNING("Source is: "); LoggerInterface.loggerRenderer.WARNING(GL20.glGetShaderSource(rVal.vertexShader)); LoggerInterface.loggerRenderer.ERROR("Runtime Exception", new RuntimeException(GL20.glGetShaderInfoLog(rVal.vertexShader))); } //Creates a new shader object and assigns its 'pointer' to the integer "vertexShader" rVal.geometryShader = glCreateShader(GL_GEOMETRY_SHADER); //This alerts openGL to the presence of a vertex shader and points the shader at its source glShaderSource(rVal.geometryShader, geometryShaderSource); //Compiles the source for the vertex shader object glCompileShader(rVal.geometryShader); //The following tests if the vertex shader compiles successfully success = glGetShaderi(rVal.geometryShader, GL_COMPILE_STATUS); if (success != GL_TRUE) { LoggerInterface.loggerRenderer.WARNING("Geometry Shader failed to compile!"); LoggerInterface.loggerRenderer.WARNING("Source is: "); LoggerInterface.loggerRenderer.WARNING(GL20.glGetShaderSource(rVal.geometryShader)); LoggerInterface.loggerRenderer.ERROR("Runtime Exception", new RuntimeException(GL20.glGetShaderInfoLog(rVal.geometryShader))); } //Creates and opengl object for a fragment shader and assigns its 'pointer' to the integer fragmentShader rVal.fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); //This points the opengl shadder object to its proper source glShaderSource(rVal.fragmentShader, fragmentShaderSource); //This compiles the shader object glCompileShader(rVal.fragmentShader); //This tests for the success of the compile attempt success = glGetShaderi(rVal.fragmentShader, GL_COMPILE_STATUS); if (success != GL_TRUE) { LoggerInterface.loggerRenderer.WARNING("Fragment Shader failed to compile!"); LoggerInterface.loggerRenderer.WARNING("Source is: "); LoggerInterface.loggerRenderer.WARNING(GL20.glGetShaderSource(rVal.fragmentShader)); LoggerInterface.loggerRenderer.ERROR("Runtime Exception", new RuntimeException(GL20.glGetShaderInfoLog(rVal.fragmentShader))); } //This creates a shader program opengl object and assigns its 'pointer' to the integer shaderProgram rVal.shaderId = glCreateProgram(); //This attaches the vertex and fragment shaders to the program glAttachShader(rVal.shaderId, rVal.vertexShader); glAttachShader(rVal.shaderId, rVal.geometryShader); glAttachShader(rVal.shaderId, rVal.fragmentShader); //This links the program to the GPU (I think its to the GPU anyway) glLinkProgram(rVal.shaderId); //Tests for the success of the shader program creation success = glGetProgrami(rVal.shaderId, GL_LINK_STATUS); if (success != GL_TRUE) { throw new RuntimeException(glGetProgramInfoLog(rVal.shaderId)); } //Deletes the individual shader objects to free up memory glDeleteShader(rVal.vertexShader); glDeleteShader(rVal.geometryShader); glDeleteShader(rVal.fragmentShader); // //Set locations // rVal.shaderVertexModelLoc = glGetUniformLocation(rVal.shaderId, "model"); rVal.shaderVertexViewLoc = glGetUniformLocation(rVal.shaderId, "view"); rVal.shaderVertexProjectionLoc = glGetUniformLocation(rVal.shaderId, "projection"); rVal.shaderVertexViewPosLoc = glGetUniformLocation(rVal.shaderId, "viewPos"); return rVal; } /** * Sets the value of a uniform on this shader * @param uniformLocation the uniform location * @param value the value */ public void setUniform(int uniformLocation, Object value){ if(!uniformMap.containsKey(uniformLocation) || !uniformMap.get(uniformLocation).equals(value)){ uniformMap.put(uniformLocation,value); if(value instanceof Matrix4f){ Matrix4f currentUniform = (Matrix4f)value; GL40.glUniformMatrix4fv(uniformLocation, false, currentUniform.get(new float[16])); } if(value instanceof Matrix4d){ Matrix4d currentUniform = (Matrix4d)value; GL40.glUniformMatrix4fv(uniformLocation, false, currentUniform.get(new float[16])); } if(value instanceof Vector3f){ Vector3f currentUniform = (Vector3f)value; GL40.glUniform3fv(uniformLocation, currentUniform.get(BufferUtils.createFloatBuffer(3))); } if(value instanceof Integer){ int currentInform = (Integer)value; GL40.glUniform1i(uniformLocation, currentInform); } } } //returned if the uniform isn't found public static final int INVALID_UNIFORM_NAME = -1; /** * Tries to set a uniform * @param uniformName The name of the uniform * @param value The value to set the uniform to */ public void setUniform(OpenGLState openGLState, String uniformName, Object value){ int uniformLocation = glGetUniformLocation(this.getShaderId(), uniformName); if(uniformLocation == INVALID_UNIFORM_NAME){ LoggerInterface.loggerRenderer.DEBUG_LOOP("Searched for uniform in a shader that does not contain it. Uniform name: \"" + uniformName + "\""); } else { setUniform(uniformLocation, value); } } /** * Gets the id of the shader * @return The shader id */ public int getShaderId(){ return shaderId; } }