Shader tm
This commit is contained in:
204
src/com/osufx/sunpy/Shader.java
Normal file
204
src/com/osufx/sunpy/Shader.java
Normal file
@@ -0,0 +1,204 @@
|
||||
package com.osufx.sunpy;
|
||||
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
import org.newdawn.slick.util.Log;
|
||||
import org.newdawn.slick.util.ResourceLoader;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.nio.Buffer;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import java.util.*;
|
||||
|
||||
public class Shader {
|
||||
public String name;
|
||||
public int programId = -1;
|
||||
public boolean loaded = false;
|
||||
public boolean started = false;
|
||||
|
||||
public PropertyCollection Properties;
|
||||
|
||||
public static HashMap<String, Object> globalProperties = new HashMap<>();
|
||||
public static List<Shader> loadedShaders = new ArrayList<>();
|
||||
public static int currentShader = 0;
|
||||
|
||||
private HashMap<String, Integer> attribLoc = new HashMap<>();
|
||||
private static final String[] attribs = new String[] {
|
||||
"m_Position",
|
||||
"m_Color",
|
||||
"m_TexCoord",
|
||||
"m_Time",
|
||||
"m_Direction"
|
||||
};
|
||||
|
||||
private HashMap<Integer, String> shaderParts = new HashMap<>();
|
||||
private int previousShader;
|
||||
|
||||
public Shader(String vertexShader, String fragmentShader) {
|
||||
String vertexString;
|
||||
String fragmentString;
|
||||
|
||||
try {
|
||||
InputStream vertexStream = ResourceLoader.getResourceAsStream(vertexShader);
|
||||
vertexString = convertStreamToString(vertexStream);
|
||||
|
||||
InputStream fragmentStream = ResourceLoader.getResourceAsStream(fragmentShader);
|
||||
fragmentString = convertStreamToString(fragmentStream);
|
||||
} catch (Exception e){
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
this.name = String.format("%s/%s", vertexShader, fragmentShader);
|
||||
this.Properties = new PropertyCollection(this);
|
||||
|
||||
this.programId = GL20.glCreateProgram();
|
||||
|
||||
this.shaderParts.put(GL20.glCreateShader(GL20.GL_VERTEX_SHADER), vertexString);
|
||||
this.shaderParts.put(GL20.glCreateShader(GL20.GL_FRAGMENT_SHADER), fragmentString);
|
||||
this.CompileParts();
|
||||
this.Compile();
|
||||
}
|
||||
|
||||
public Shader(String shader, final int shaderType) {
|
||||
if (shaderType != GL20.GL_FRAGMENT_SHADER && shaderType != GL20.GL_VERTEX_SHADER){
|
||||
System.out.println("Invalid shader type");
|
||||
return;
|
||||
}
|
||||
|
||||
String shaderString;
|
||||
|
||||
try {
|
||||
InputStream shaderStream = ResourceLoader.getResourceAsStream(shader);
|
||||
shaderString = convertStreamToString(shaderStream);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
this.name = String.format("%s/%s",
|
||||
shaderType == GL20.GL_FRAGMENT_SHADER ? "Fragment" : "Vertex",
|
||||
shader);
|
||||
this.Properties = new PropertyCollection(this);
|
||||
|
||||
this.programId = GL20.glCreateProgram();
|
||||
|
||||
this.shaderParts.put(GL20.glCreateShader(shaderType), shaderString);
|
||||
this.CompileParts();
|
||||
this.Compile();
|
||||
}
|
||||
|
||||
public void CompileParts() {
|
||||
for (Map.Entry<Integer, String> entry : this.shaderParts.entrySet()) {
|
||||
int handle = entry.getKey();
|
||||
String source = entry.getValue();
|
||||
|
||||
GL20.glShaderSource(handle, source);
|
||||
GL20.glCompileShader(handle);
|
||||
|
||||
int res = GL20.glGetShaderi(handle, GL20.GL_COMPILE_STATUS);
|
||||
if (res != GL11.GL_TRUE) {
|
||||
String error = GL20.glGetShaderInfoLog(handle, 1024);
|
||||
Log.error("Shader compilation failed.", new Exception(error));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Compile() {
|
||||
this.Properties.Clear();
|
||||
|
||||
for (int handler : this.shaderParts.keySet()) {
|
||||
GL20.glAttachShader(this.programId, handler);
|
||||
}
|
||||
|
||||
GL20.glLinkProgram(this.programId);
|
||||
|
||||
int res = GL20.glGetProgrami(this.programId, GL20.GL_LINK_STATUS);
|
||||
if (res != GL11.GL_TRUE) {
|
||||
String error = GL20.glGetProgramInfoLog(this.programId, 1024);
|
||||
Log.error("Program linking failed.", new Exception(error));
|
||||
}
|
||||
|
||||
for (int handler : this.shaderParts.keySet()) {
|
||||
GL20.glDeleteShader(handler);
|
||||
}
|
||||
|
||||
for (int i = 0; i < attribs.length; i++) {
|
||||
int attrib = GL20.glGetAttribLocation(this.programId, attribs[i]);
|
||||
this.attribLoc.put(attribs[i], attrib);
|
||||
//GL20.glBindAttribLocation(this.programId, i, attribLoc[i]);
|
||||
}
|
||||
|
||||
/*for (int handler : this.shaderParts.keySet()) {
|
||||
GL20.glDetachShader(this.programId, handler);
|
||||
}*/
|
||||
|
||||
this.loaded = res == GL11.GL_TRUE;
|
||||
|
||||
if (this.loaded) {
|
||||
int uniCount = GL20.glGetProgrami(this.programId, GL20.GL_ACTIVE_UNIFORMS);
|
||||
|
||||
for (int i = 0; i < uniCount; i++) {
|
||||
IntBuffer length = BufferUtils.createIntBuffer(1);
|
||||
IntBuffer size = BufferUtils.createIntBuffer(1);
|
||||
IntBuffer type = BufferUtils.createIntBuffer(1);
|
||||
ByteBuffer name = ByteBuffer.allocateDirect(64);
|
||||
|
||||
GL20.glGetActiveUniform(this.programId, i, length, size, type, name);
|
||||
|
||||
|
||||
byte[] buf = new byte[length.get(0)];
|
||||
|
||||
name.get(buf, 0, buf.length);
|
||||
String propName = new String(buf);
|
||||
int propLocation = GL20.glGetUniformLocation(programId, propName);
|
||||
|
||||
UniformType propUniformType = UniformType.map.get(type.get(0));
|
||||
Class propType = ShaderProperty.ConvertType(propUniformType.name());
|
||||
|
||||
System.out.println(String.format("propName:%s PropUniformType:%s PropType:%s", propName, propUniformType, propType));
|
||||
|
||||
this.Properties.Add(new ShaderProperty(
|
||||
propName,
|
||||
propLocation,
|
||||
propType,
|
||||
propUniformType
|
||||
));
|
||||
}
|
||||
|
||||
for (Map.Entry<String, Object> entry : globalProperties.entrySet()) {
|
||||
this.Properties.Replace(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
loadedShaders.add(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void Begin(){
|
||||
if (this.started || !this.loaded)
|
||||
return;
|
||||
|
||||
GL20.glUseProgram(this.programId);
|
||||
this.previousShader = currentShader;
|
||||
currentShader = this.programId;
|
||||
|
||||
this.started = true;
|
||||
}
|
||||
|
||||
public void End() {
|
||||
if (!this.started)
|
||||
return;
|
||||
|
||||
GL20.glUseProgram(this.previousShader);
|
||||
currentShader = this.previousShader;
|
||||
|
||||
this.started = false;
|
||||
}
|
||||
|
||||
static String convertStreamToString(InputStream is) {
|
||||
Scanner s = new Scanner(is).useDelimiter("\\A");
|
||||
return s.hasNext() ? s.next() : "";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user