package com.javamarcher.shader;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import org.lwjgl.opengl.GL20;
public class ShaderCreator {
private static final String INCLUDE_KEYWORD = "#include";
private final int vertexShaderId;
private final int fragmentShaderId;
private int programId = 0;
public ShaderCreator(String vertexFileName, String fragmentFileName) {
vertexShaderId = loadShader(vertexFileName, GL20.GL_VERTEX_SHADER);
fragmentShaderId = loadShader(fragmentFileName, GL20.GL_FRAGMENT_SHADER);
}
/**
* Binds the shader ids to a shader program
* and returns the program id.
*/
public int createShader() {
programId = GL20.glCreateProgram();
GL20.glAttachShader(programId, vertexShaderId);
GL20.glAttachShader(programId, fragmentShaderId);
return programId;
}
public void cleanup() {
GL20.glUseProgram(0);
GL20.glDetachShader(getProgramId(), vertexShaderId);
GL20.glDetachShader(getProgramId(), fragmentShaderId);
GL20.glDeleteShader(vertexShaderId);
GL20.glDeleteShader(fragmentShaderId);
GL20.glDeleteProgram(getProgramId());
}
/**
* Loads the shader based on the given path and returns the shader id.
*/
private int loadShader(String filename, int type) {
final StringBuilder shaderSource = new StringBuilder();
int shaderId = 0;
try {
final BufferedReader reader = new BufferedReader(new FileReader(filename));
String sourceLine;
while((sourceLine = reader.readLine()) != null) {
// Only append if no include pragma was found
if(!parseIncludePragma(shaderSource, sourceLine)) {
shaderSource.append(sourceLine).append("\n");
}
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
shaderId = GL20.glCreateShader(type);
GL20.glShaderSource(shaderId, shaderSource);
GL20.glCompileShader(shaderId);
if(GL20.glGetShaderi(shaderId, GL20.GL_COMPILE_STATUS) == 0) {
System.err.println("Shader compilation failed!");
System.err.println(GL20.glGetShaderInfoLog(shaderId));
System.exit(1);
}
return shaderId;
}
private boolean parseIncludePragma(StringBuilder shaderSource, String currentLine) throws IOException {
if(currentLine.startsWith(INCLUDE_KEYWORD)) {
final String includeFilename = currentLine.substring(currentLine.indexOf("[") + 1, currentLine.indexOf("]"));
final BufferedReader reader = new BufferedReader(new FileReader(includeFilename));
String line;
while((line = reader.readLine()) != null) {
shaderSource.append(line).append("\n");
}
reader.close();
return true;
}
return false;
}
public int getVertexShaderId() {
return vertexShaderId;
}
public int getFragmentShaderId() {
return fragmentShaderId;
}
public int getProgramId() {
return programId;
}
}