793 lines
38 KiB
Java
793 lines
38 KiB
Java
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<Integer,Object> uniformMap = new HashMap<Integer,Object>();
|
|
|
|
//keeps track of programs that have already been compiled and returns them instead of recompiling from scratch
|
|
static Map<String,ShaderProgram> alreadyCompiledMap = new HashMap<String,ShaderProgram>();
|
|
|
|
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<Object> errorLines = new LinkedList<Object>();
|
|
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<String> 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<Object> errorLines = new LinkedList<Object>();
|
|
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<String> 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;
|
|
}
|
|
|
|
}
|