544 lines
26 KiB
Java
544 lines
26 KiB
Java
package electrosphere.renderer.shader;
|
|
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.nio.file.Files;
|
|
import java.util.HashMap;
|
|
import java.util.LinkedList;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.regex.Matcher;
|
|
import java.util.regex.Pattern;
|
|
|
|
import javax.management.RuntimeErrorException;
|
|
|
|
import org.lwjgl.opengl.GL40;
|
|
|
|
import electrosphere.engine.Globals;
|
|
import electrosphere.engine.assetmanager.AssetDataStrings;
|
|
import electrosphere.logger.LoggerInterface;
|
|
import electrosphere.renderer.OpenGLState;
|
|
import electrosphere.renderer.RenderingEngine;
|
|
import electrosphere.util.FileUtils;
|
|
|
|
/**
|
|
* A visual shader program
|
|
*/
|
|
public class VisualShader implements Shader {
|
|
|
|
/**
|
|
* The vertex shader location
|
|
*/
|
|
int vertexShader;
|
|
|
|
/**
|
|
* The fragment shader location
|
|
*/
|
|
int fragmentShader;
|
|
|
|
/**
|
|
* The shader's ID
|
|
*/
|
|
int shaderId;
|
|
|
|
|
|
|
|
/**
|
|
* The map of uniform location -> current value of uniform
|
|
*/
|
|
public Map<Integer,Object> uniformMap = new HashMap<Integer,Object>();
|
|
|
|
/**
|
|
* The map of path -> already compiled shader
|
|
*/
|
|
static Map<String,VisualShader> alreadyCompiledMap = new HashMap<String,VisualShader>();
|
|
|
|
|
|
/**
|
|
* Recursively preprocesses a file
|
|
* @param currentFile The file to preprocess
|
|
* @return The contents of the file
|
|
*/
|
|
private static String recursivelyPreprocessFile(String input){
|
|
return VisualShader.recursivelyPreprocessFile(FileUtils.getAssetFile(input), new LinkedList<String>());
|
|
}
|
|
|
|
/**
|
|
* Recursively preprocesses a file
|
|
* @param currentFile The file to preprocess
|
|
* @return The contents of the file
|
|
*/
|
|
private static String recursivelyPreprocessFile(File currentFile, List<String> includes){
|
|
String contents = null;
|
|
try {
|
|
contents = Files.readString(currentFile.toPath());
|
|
} catch (IOException e) {
|
|
LoggerInterface.loggerRenderer.ERROR(e);
|
|
}
|
|
Pattern includePattern = Pattern.compile("#include \"(.*)\"");
|
|
Matcher matcher = includePattern.matcher(contents);
|
|
int i = 1;
|
|
while(matcher.find()){
|
|
String group = matcher.group(i);
|
|
if(!includes.contains(group)){
|
|
File directory = currentFile.getParentFile();
|
|
File newFile = new File(directory.getPath() + "/" + group);
|
|
String includeContent = VisualShader.recursivelyPreprocessFile(newFile, includes);
|
|
contents = contents.replace("#include \"" + group + "\"", includeContent);
|
|
}
|
|
i++;
|
|
}
|
|
//remove strings that we don't want to include
|
|
contents = contents.replace("#extension GL_ARB_shading_language_include : require","");
|
|
return contents;
|
|
}
|
|
|
|
/**
|
|
* Smart assembles a shader
|
|
* @param ContainsBones true if the mesh contains bones
|
|
* @param apply_lighting true if lighting should be applied
|
|
* @return The visual shader
|
|
*/
|
|
public static VisualShader smartAssembleShader(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
|
|
//
|
|
VisualShader rVal = new VisualShader();
|
|
//
|
|
//Read in shader programs
|
|
//
|
|
String vertexShaderSource = VisualShader.recursivelyPreprocessFile(vertex_shader_path);
|
|
String fragmentShaderSource = VisualShader.recursivelyPreprocessFile(fragment_shader_path);
|
|
//Creates a new shader object and assigns its 'pointer' to the integer "vertexShader"
|
|
rVal.vertexShader = GL40.glCreateShader(GL40.GL_VERTEX_SHADER);
|
|
//This alerts openGL to the presence of a vertex shader and points the shader at its source
|
|
GL40.glShaderSource(rVal.vertexShader, vertexShaderSource);
|
|
//Compiles the source for the vertex shader object
|
|
GL40.glCompileShader(rVal.vertexShader);
|
|
//The following tests if the vertex shader compiles successfully
|
|
int success;
|
|
success = GL40.glGetShaderi(rVal.vertexShader, GL40.GL_COMPILE_STATUS);
|
|
if (success != GL40.GL_TRUE) {
|
|
LoggerInterface.loggerRenderer.WARNING("Vertex Shader failed to compile!");
|
|
LoggerInterface.loggerRenderer.WARNING("Source is: ");
|
|
LoggerInterface.loggerRenderer.WARNING(GL40.glGetShaderSource(rVal.vertexShader));
|
|
LoggerInterface.loggerRenderer.ERROR("Runtime Exception", new RuntimeException(GL40.glGetShaderInfoLog(rVal.vertexShader)));
|
|
}
|
|
//Creates and opengl object for a fragment shader and assigns its 'pointer' to the integer fragmentShader
|
|
rVal.fragmentShader = GL40.glCreateShader(GL40.GL_FRAGMENT_SHADER);
|
|
//This points the opengl shadder object to its proper source
|
|
GL40.glShaderSource(rVal.fragmentShader, fragmentShaderSource);
|
|
//This compiles the shader object
|
|
GL40.glCompileShader(rVal.fragmentShader);
|
|
//This tests for the success of the compile attempt
|
|
success = GL40.glGetShaderi(rVal.fragmentShader, GL40.GL_COMPILE_STATUS);
|
|
if (success != GL40.GL_TRUE) {
|
|
LoggerInterface.loggerRenderer.WARNING("Fragment Shader failed to compile!");
|
|
LoggerInterface.loggerRenderer.WARNING("Source is: ");
|
|
LoggerInterface.loggerRenderer.WARNING(GL40.glGetShaderSource(rVal.fragmentShader));
|
|
LoggerInterface.loggerRenderer.ERROR("Runtime Exception", new RuntimeException(GL40.glGetShaderInfoLog(rVal.fragmentShader)));
|
|
}
|
|
//This creates a shader program opengl object and assigns its 'pointer' to the integer shaderProgram
|
|
rVal.shaderId = GL40.glCreateProgram();
|
|
//This attaches the vertex and fragment shaders to the program
|
|
GL40.glAttachShader(rVal.shaderId, rVal.vertexShader);
|
|
GL40.glAttachShader(rVal.shaderId, rVal.fragmentShader);
|
|
//This links the program to the GPU (I think its to the GPU anyway)
|
|
GL40.glLinkProgram(rVal.shaderId);
|
|
//Tests for the success of the shader program creation
|
|
success = GL40.glGetProgrami(rVal.shaderId, GL40.GL_LINK_STATUS);
|
|
if (success != GL40.GL_TRUE) {
|
|
throw new RuntimeException(GL40.glGetProgramInfoLog(rVal.shaderId));
|
|
}
|
|
|
|
//Deletes the individual shader objects to free up memory
|
|
GL40.glDeleteShader(rVal.vertexShader);
|
|
GL40.glDeleteShader(rVal.fragmentShader);
|
|
|
|
|
|
|
|
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 VisualShader 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/core/oit/general/VertexShader.vs";
|
|
} else {
|
|
vertex_shader_path = "/Shaders/core/oit/general/VertexShaderNoBones.vs";
|
|
}
|
|
|
|
String fragment_shader_path = "/Shaders/core/oit/general/FragmentShader.fs";
|
|
//
|
|
//Create ShaderProgram object
|
|
//
|
|
VisualShader rVal = new VisualShader();
|
|
//
|
|
//Read in shader programs
|
|
//
|
|
String vertexShaderSource = VisualShader.recursivelyPreprocessFile(vertex_shader_path);
|
|
String fragmentShaderSource = VisualShader.recursivelyPreprocessFile(fragment_shader_path);
|
|
//Creates a new shader object and assigns its 'pointer' to the integer "vertexShader"
|
|
rVal.vertexShader = GL40.glCreateShader(GL40.GL_VERTEX_SHADER);
|
|
//This alerts openGL to the presence of a vertex shader and points the shader at its source
|
|
GL40.glShaderSource(rVal.vertexShader, vertexShaderSource);
|
|
//Compiles the source for the vertex shader object
|
|
GL40. glCompileShader(rVal.vertexShader);
|
|
//The following tests if the vertex shader compiles successfully
|
|
int success;
|
|
success = GL40.glGetShaderi(rVal.vertexShader, GL40.GL_COMPILE_STATUS);
|
|
if (success != GL40.GL_TRUE) {
|
|
LoggerInterface.loggerRenderer.WARNING("Vertex Shader failed to compile!");
|
|
LoggerInterface.loggerRenderer.WARNING("Source is: ");
|
|
LoggerInterface.loggerRenderer.WARNING(GL40.glGetShaderSource(rVal.vertexShader));
|
|
LoggerInterface.loggerRenderer.ERROR("Runtime Exception", new RuntimeException(GL40.glGetShaderInfoLog(rVal.vertexShader)));
|
|
}
|
|
//Creates and opengl object for a fragment shader and assigns its 'pointer' to the integer fragmentShader
|
|
rVal.fragmentShader = GL40.glCreateShader(GL40.GL_FRAGMENT_SHADER);
|
|
//This points the opengl shadder object to its proper source
|
|
GL40.glShaderSource(rVal.fragmentShader, fragmentShaderSource);
|
|
//This compiles the shader object
|
|
GL40.glCompileShader(rVal.fragmentShader);
|
|
//This tests for the success of the compile attempt
|
|
success = GL40.glGetShaderi(rVal.fragmentShader, GL40.GL_COMPILE_STATUS);
|
|
if (success != GL40.GL_TRUE) {
|
|
LoggerInterface.loggerRenderer.WARNING("Fragment Shader failed to compile!");
|
|
LoggerInterface.loggerRenderer.WARNING("Source is: ");
|
|
LoggerInterface.loggerRenderer.WARNING(GL40.glGetShaderSource(rVal.fragmentShader));
|
|
LoggerInterface.loggerRenderer.ERROR("Runtime Exception", new RuntimeException(GL40.glGetShaderInfoLog(rVal.fragmentShader)));
|
|
}
|
|
//This creates a shader program opengl object and assigns its 'pointer' to the integer shaderProgram
|
|
rVal.shaderId = GL40.glCreateProgram();
|
|
//This attaches the vertex and fragment shaders to the program
|
|
GL40.glAttachShader(rVal.shaderId, rVal.vertexShader);
|
|
GL40.glAttachShader(rVal.shaderId, rVal.fragmentShader);
|
|
//This links the program to the GPU (I think its to the GPU anyway)
|
|
GL40. glLinkProgram(rVal.shaderId);
|
|
//Tests for the success of the shader program creation
|
|
success = GL40.glGetProgrami(rVal.shaderId, GL40.GL_LINK_STATUS);
|
|
if (success != GL40.GL_TRUE) {
|
|
throw new RuntimeException(GL40.glGetProgramInfoLog(rVal.shaderId));
|
|
}
|
|
|
|
//Deletes the individual shader objects to free up memory
|
|
GL40.glDeleteShader(rVal.vertexShader);
|
|
GL40.glDeleteShader(rVal.fragmentShader);
|
|
|
|
|
|
|
|
alreadyCompiledMap.put(shaderKey,rVal);
|
|
|
|
return rVal;
|
|
}
|
|
|
|
|
|
/**
|
|
* Loads the default shader program
|
|
* @return The default shader
|
|
*/
|
|
public static VisualShader loadDefaultShaderProgram(){
|
|
|
|
|
|
//
|
|
//Create ShaderProgram object
|
|
//
|
|
VisualShader rVal = new VisualShader();
|
|
//
|
|
//Read in shader programs
|
|
//
|
|
String vertexShaderSource = VisualShader.recursivelyPreprocessFile(AssetDataStrings.SHADER_DEFAULT_VERT);
|
|
String fragmentShaderSource = VisualShader.recursivelyPreprocessFile(AssetDataStrings.SHADER_DEFAULT_FRAG);
|
|
//Creates a new shader object and assigns its 'pointer' to the integer "vertexShader"
|
|
rVal.vertexShader = GL40.glCreateShader(GL40.GL_VERTEX_SHADER);
|
|
//This alerts openGL to the presence of a vertex shader and points the shader at its source
|
|
GL40.glShaderSource(rVal.vertexShader, vertexShaderSource);
|
|
//Compiles the source for the vertex shader object
|
|
GL40.glCompileShader(rVal.vertexShader);
|
|
//The following tests if the vertex shader compiles successfully
|
|
int success;
|
|
success = GL40.glGetShaderi(rVal.vertexShader, GL40.GL_COMPILE_STATUS);
|
|
if (success != GL40.GL_TRUE) {
|
|
LoggerInterface.loggerRenderer.WARNING("Vertex Shader failed to compile!");
|
|
LoggerInterface.loggerRenderer.WARNING("Source is: ");
|
|
LoggerInterface.loggerRenderer.WARNING(GL40.glGetShaderSource(rVal.vertexShader));
|
|
LoggerInterface.loggerRenderer.ERROR("Runtime Exception", new RuntimeException(GL40.glGetShaderInfoLog(rVal.vertexShader)));
|
|
}
|
|
//Creates and opengl object for a fragment shader and assigns its 'pointer' to the integer fragmentShader
|
|
rVal.fragmentShader = GL40.glCreateShader(GL40.GL_FRAGMENT_SHADER);
|
|
//This points the opengl shadder object to its proper source
|
|
GL40.glShaderSource(rVal.fragmentShader, fragmentShaderSource);
|
|
//This compiles the shader object
|
|
GL40.glCompileShader(rVal.fragmentShader);
|
|
//This tests for the success of the compile attempt
|
|
success = GL40.glGetShaderi(rVal.fragmentShader, GL40.GL_COMPILE_STATUS);
|
|
if (success != GL40.GL_TRUE) {
|
|
LoggerInterface.loggerRenderer.WARNING("Fragment Shader failed to compile!");
|
|
LoggerInterface.loggerRenderer.WARNING("Source is: ");
|
|
LoggerInterface.loggerRenderer.WARNING(GL40.glGetShaderSource(rVal.fragmentShader));
|
|
LoggerInterface.loggerRenderer.ERROR("Runtime Exception", new RuntimeException(GL40.glGetShaderInfoLog(rVal.fragmentShader)));
|
|
}
|
|
//This creates a shader program opengl object and assigns its 'pointer' to the integer shaderProgram
|
|
rVal.shaderId = GL40.glCreateProgram();
|
|
//This attaches the vertex and fragment shaders to the program
|
|
GL40.glAttachShader(rVal.shaderId, rVal.vertexShader);
|
|
GL40.glAttachShader(rVal.shaderId, rVal.fragmentShader);
|
|
//This links the program to the GPU (I think its to the GPU anyway)
|
|
GL40.glLinkProgram(rVal.shaderId);
|
|
//Tests for the success of the shader program creation
|
|
success = GL40.glGetProgrami(rVal.shaderId, GL40.GL_LINK_STATUS);
|
|
if (success != GL40.GL_TRUE) {
|
|
throw new RuntimeException(GL40.glGetProgramInfoLog(rVal.shaderId));
|
|
}
|
|
|
|
//Deletes the individual shader objects to free up memory
|
|
GL40.glDeleteShader(rVal.vertexShader);
|
|
GL40.glDeleteShader(rVal.fragmentShader);
|
|
|
|
|
|
|
|
return rVal;
|
|
}
|
|
|
|
/**
|
|
* Loads a specific shader
|
|
* @param vertexPath The vertex shader's path
|
|
* @param fragmentPath The fragment shader's path
|
|
* @return The visual shader
|
|
*/
|
|
public static VisualShader loadSpecificShader(String vertexPath, String fragmentPath){
|
|
VisualShader rVal = new VisualShader();
|
|
|
|
//
|
|
//Read in shader programs
|
|
//
|
|
String vertexShaderSource = VisualShader.recursivelyPreprocessFile(vertexPath);
|
|
String fragmentShaderSource = VisualShader.recursivelyPreprocessFile(fragmentPath);
|
|
//Creates a new shader object and assigns its 'pointer' to the integer "vertexShader"
|
|
rVal.vertexShader = GL40.glCreateShader(GL40.GL_VERTEX_SHADER);
|
|
//This alerts openGL to the presence of a vertex shader and points the shader at its source
|
|
GL40.glShaderSource(rVal.vertexShader, vertexShaderSource);
|
|
//Compiles the source for the vertex shader object
|
|
GL40.glCompileShader(rVal.vertexShader);
|
|
//The following tests if the vertex shader compiles successfully
|
|
int success;
|
|
success = GL40.glGetShaderi(rVal.vertexShader, GL40.GL_COMPILE_STATUS);
|
|
if (success != GL40.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(GL40.glGetShaderSource(rVal.vertexShader));
|
|
errorLines.add(new RuntimeException(GL40.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 = GL40.glCreateShader(GL40.GL_VERTEX_SHADER);
|
|
//This alerts openGL to the presence of a vertex shader and points the shader at its source
|
|
GL40.glShaderSource(rVal.vertexShader, vertexShaderSource);
|
|
//Compiles the source for the vertex shader object
|
|
GL40.glCompileShader(rVal.vertexShader);
|
|
//The following tests if the vertex shader compiles successfully
|
|
success = GL40.glGetShaderi(rVal.vertexShader, GL40.GL_COMPILE_STATUS);
|
|
if (success == GL40.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(GL40.glGetShaderSource(rVal.vertexShader));
|
|
errorLines.add(new RuntimeException(GL40.glGetShaderInfoLog(rVal.vertexShader)));
|
|
}
|
|
}
|
|
if(success != GL40.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 = GL40.glCreateShader(GL40.GL_FRAGMENT_SHADER);
|
|
//This points the opengl shadder object to its proper source
|
|
GL40.glShaderSource(rVal.fragmentShader, fragmentShaderSource);
|
|
//This compiles the shader object
|
|
GL40.glCompileShader(rVal.fragmentShader);
|
|
//This tests for the success of the compile attempt
|
|
success = GL40.glGetShaderi(rVal.fragmentShader, GL40.GL_COMPILE_STATUS);
|
|
if (success != GL40.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(GL40.glGetShaderSource(rVal.fragmentShader));
|
|
errorLines.add(new RuntimeException(GL40.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 = GL40.glCreateShader(GL40.GL_FRAGMENT_SHADER);
|
|
//This alerts openGL to the presence of a vertex shader and points the shader at its source
|
|
GL40.glShaderSource(rVal.fragmentShader, fragmentShaderSource);
|
|
//Compiles the source for the vertex shader object
|
|
GL40.glCompileShader(rVal.fragmentShader);
|
|
//The following tests if the vertex shader compiles successfully
|
|
success = GL40.glGetShaderi(rVal.fragmentShader, GL40.GL_COMPILE_STATUS);
|
|
if (success == GL40.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(GL40.glGetShaderSource(rVal.fragmentShader));
|
|
errorLines.add(new RuntimeException(GL40.glGetShaderInfoLog(rVal.fragmentShader)));
|
|
}
|
|
}
|
|
if(success != GL40.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 = GL40.glCreateProgram();
|
|
//This attaches the vertex and fragment shaders to the program
|
|
GL40.glAttachShader(rVal.shaderId, rVal.vertexShader);
|
|
GL40.glAttachShader(rVal.shaderId, rVal.fragmentShader);
|
|
//This links the program to the GPU (I think its to the GPU anyway)
|
|
GL40.glLinkProgram(rVal.shaderId);
|
|
//Tests for the success of the shader program creation
|
|
success = GL40.glGetProgrami(rVal.shaderId, GL40.GL_LINK_STATUS);
|
|
if (success != GL40.GL_TRUE) {
|
|
LoggerInterface.loggerRenderer.ERROR(GL40.glGetProgramInfoLog(rVal.shaderId), new RuntimeException(GL40.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
|
|
GL40.glDeleteShader(rVal.vertexShader);
|
|
GL40.glDeleteShader(rVal.fragmentShader);
|
|
Globals.renderingEngine.checkError();
|
|
|
|
|
|
|
|
return rVal;
|
|
}
|
|
|
|
|
|
/**
|
|
* 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){
|
|
//
|
|
//Error checking
|
|
if(uniformName == null || uniformName.equals("")){
|
|
throw new IllegalArgumentException("Trying to set invalid uniform name");
|
|
}
|
|
if(this.getId() != openGLState.getActiveShader().getId()){
|
|
throw new IllegalStateException("Trying to set uniform on shader that is not active");
|
|
}
|
|
|
|
//
|
|
//get uniform location
|
|
int uniformLocation = GL40.glGetUniformLocation(this.getId(), uniformName);
|
|
int glErrorCode = Globals.renderingEngine.getError();
|
|
if(glErrorCode != 0){
|
|
LoggerInterface.loggerRenderer.DEBUG_LOOP(RenderingEngine.getErrorInEnglish(glErrorCode));
|
|
LoggerInterface.loggerRenderer.DEBUG_LOOP("Shader id: " + this.getId());
|
|
}
|
|
|
|
//
|
|
//set the uniform
|
|
if(uniformLocation == INVALID_UNIFORM_NAME){
|
|
LoggerInterface.loggerRenderer.DEBUG_LOOP("Searched for uniform in a shader that does not contain it. Uniform name: \"" + uniformName + "\"");
|
|
} else {
|
|
ShaderUtils.setUniform(openGLState, this.uniformMap, uniformLocation, value);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets the location of a given uniform
|
|
* @param uniformName The name of the uniform
|
|
* @return The location of the uniform
|
|
*/
|
|
public int getUniformLocation(String uniformName){
|
|
return GL40.glGetUniformLocation(this.getId(), uniformName);
|
|
}
|
|
|
|
|
|
@Override
|
|
public int getId() {
|
|
return this.shaderId;
|
|
}
|
|
|
|
}
|