123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417 |
- package me.hammerle.snuviengine.api;
- import java.io.IOException;
- import java.net.URL;
- import java.nio.FloatBuffer;
- import java.util.ArrayList;
- import java.util.LinkedList;
- import java.util.List;
- import java.util.Scanner;
- import org.lwjgl.BufferUtils;
- import static org.lwjgl.opengl.GL11.*;
- import static org.lwjgl.opengl.GL14.*;
- import static org.lwjgl.opengl.GL20.*;
- public final class Shader
- {
- private static int program = -1;
-
- private static int width = 1024;
- private static int height = 620;
- private static int scale = 2;
-
- private static final List<Runnable> TASKS = new LinkedList<>();
-
- protected static boolean initDone = false;
-
- private final static FontRenderer FONT_RENDERER = new FontRenderer();
- private final static ColorRenderer COLOR_RENDERER = new ColorRenderer();
- private final static DirectTextureRenderer TEXTURE_RENDERER = new DirectTextureRenderer();
-
- // uniform stuff
- private static int unifViewMatrix = -1;
- private static int unifModelMatrix = -1;
- private static MatrixStack modelMatrix;
-
- private static int unifAmbientLight = -1;
- private static int[][] unifLight;
-
- private static int unifUseTexture = -1;
- private static int unifUseColor = -1;
- private static int unifUseLight = -1;
- private static int unifUseMixColor = -1;
- private static int unifMixColorLoc = -1;
- private static float[] unifMixColor = new float[] {0.0f, 0.0f, 0.0f, 0.0f};
-
- protected static void init()
- {
- program = createShaderProgram("vertex.vs", "fragment.fs");
- glUseProgram(program);
-
- unifViewMatrix = glGetUniformLocation(program, "viewMatrix");
- updateViewMatrix();
-
- unifModelMatrix = glGetUniformLocation(program, "modelMatrix");
- modelMatrix = new MatrixStack(20);
- updateMatrix();
-
- unifAmbientLight = glGetUniformLocation(program, "ambientLight");
- setAmbientLight(1.0f, 1.0f, 1.0f);
-
- unifLight = new int[32][3];
- for(int index = 0; index < unifLight.length; index++)
- {
- unifLight[index][0] = glGetUniformLocation(program, "lights[" + index + "].color");
- unifLight[index][1] = glGetUniformLocation(program, "lights[" + index + "].pos");
- unifLight[index][2] = glGetUniformLocation(program, "lights[" + index + "].strength");
- setLightColor(index, 0.0f, 0.0f, 0.0f);
- setLightLocation(index, 0.0f, 0.0f);
- setLightStrength(index, 0.0f);
- }
-
- unifUseTexture = glGetUniformLocation(program, "useTexture");
- setTextureEnabled(false);
-
- unifUseColor = glGetUniformLocation(program, "useColor");
- setColorEnabled(false);
-
- unifUseLight = glGetUniformLocation(program, "useLight");
- setLightEnabled(false);
-
- unifUseMixColor = glGetUniformLocation(program, "useMixColor");
- setMixColorEnabled(false);
- unifMixColorLoc = glGetUniformLocation(program, "mixColor");
- setMixColor(0.0f, 0.0f, 0.0f, 0.0f);
-
- setViewPort(width, height);
- initDone = true;
- }
-
- protected static int getProgram()
- {
- return program;
- }
-
- protected static void addTask(Runnable r)
- {
- TASKS.add(r);
- }
-
- protected static void doTasks()
- {
- if(!TASKS.isEmpty())
- {
- TASKS.forEach(r -> r.run());
- TASKS.clear();
- }
- }
-
- public static FontRenderer getFontRenderer()
- {
- return FONT_RENDERER;
- }
-
- public static ColorRenderer getColorRenderer()
- {
- return COLOR_RENDERER;
- }
-
- public static DirectTextureRenderer getTextureRenderer()
- {
- return TEXTURE_RENDERER;
- }
-
- private static void updateViewMatrix()
- {
- FloatBuffer buffer = BufferUtils.createFloatBuffer(16);
-
- buffer.put(2.0f / width);
- buffer.put(0.0f);
- buffer.put(0.0f);
- buffer.put(0.0f);
-
- buffer.put(0.0f);
- buffer.put(-2.0f / height);
- buffer.put(0.0f);
- buffer.put(0.0f);
-
- buffer.put(0.0f);
- buffer.put(0.0f);
- buffer.put(-1.0f / height);
- buffer.put(0.0f);
-
- buffer.put(-1.0f);
- buffer.put(1.0f);
- buffer.put(0.5f);
- buffer.put(1.0f);
-
- buffer.flip();
-
- glUniformMatrix4fv(unifViewMatrix, false, buffer);
- }
-
- protected static void setViewPort(int width, int height)
- {
- scale = 1;
- while(width / (scale + 1) >= 400 && height / (scale + 1) >= 300)
- {
- scale++;
- }
- Shader.width = width / scale;
- Shader.height = height / scale;
-
- updateViewMatrix();
- }
-
- public static int getViewScale()
- {
- return scale;
- }
-
- public static int getViewWidth()
- {
- return width;
- }
-
- public static int getViewHeight()
- {
- return height;
- }
-
- public static void updateMatrix()
- {
- glUniformMatrix4fv(unifModelMatrix, false, modelMatrix.getData());
- }
-
- public static void pushMatrix()
- {
- modelMatrix.push();
- }
-
- public static void popMatrix()
- {
- modelMatrix.pop();
- }
-
- public static void translate(float tx, float ty)
- {
- modelMatrix.translate(tx, ty);
- }
-
- public static void translateTo(float tx, float ty)
- {
- modelMatrix.translateTo(tx, ty);
- }
-
- public static void scale(float sx, float sy)
- {
- modelMatrix.scale(sx, sy);
- }
-
- public static void rotate(float angle)
- {
- modelMatrix.rotate(angle);
- }
-
- public static void setAmbientLight(float r, float g, float b)
- {
- glUniform3f(unifAmbientLight, r, g, b);
- }
-
- private static void checkLightIndex(int index)
- {
- if(index < 0 || index > unifLight.length)
- {
- throw new ShaderException("'" + index + "' is not a valid light index");
- }
- }
-
- public static void setLightColor(int index, float r, float g, float b)
- {
- checkLightIndex(index);
- glUniform3f(unifLight[index][0], r, g, b);
- }
-
- public static void setLightLocation(int index, float x, float y)
- {
- checkLightIndex(index);
- glUniform2f(unifLight[index][1], x, y);
- }
-
- public static void setLightStrength(int index, float strength)
- {
- checkLightIndex(index);
- glUniform1f(unifLight[index][2], strength);
- }
-
- public static void setTextureEnabled(boolean use)
- {
- glUniform1i(unifUseTexture, use ? 1 : 0);
- }
-
- public static void setColorEnabled(boolean use)
- {
- glUniform1i(unifUseColor, use ? 1 : 0);
- }
-
- public static void setMixColorEnabled(boolean use)
- {
- glUniform1i(unifUseMixColor, use ? 1 : 0);
- }
-
- public static void setMixColor(float r, float g, float b, float a)
- {
- unifMixColor[0] = r;
- unifMixColor[1] = g;
- unifMixColor[2] = b;
- unifMixColor[3] = a;
- glUniform4fv(unifMixColorLoc, unifMixColor);
- }
-
- public static void setLightEnabled(boolean use)
- {
- glUniform1i(unifUseLight, use ? 1 : 0);
- }
-
- public static void setDepthTestEnabled(boolean use)
- {
- if(use)
- {
- glEnable(GL_DEPTH_TEST);
- glDepthFunc(GL_LEQUAL);
- }
- else
- {
- glDisable(GL_DEPTH_TEST);
- }
- }
-
- public static void setBlendingEnabled(boolean use)
- {
- if(use)
- {
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glBlendEquation(GL_FUNC_ADD);
- }
- else
- {
- glDisable(GL_BLEND);
- }
- }
-
- // -------------------------------------------------------------------------
- // general stuff
- // -------------------------------------------------------------------------
-
- private static String[] readFile(String name)
- {
- URL url = Shader.class.getClassLoader().getResource("me/hammerle/snuviengine/shader/" + name);
- if(url == null)
- {
- throw new ShaderException("failed reading shader '" + name + "'");
- }
- ArrayList<String> strings = new ArrayList<>();
- try(Scanner scanner = new Scanner(url.openStream()))
- {
- while(scanner.hasNext())
- {
- strings.add(scanner.nextLine() + "\n");
- }
- return strings.toArray(new String[strings.size()]);
- }
- catch(IOException ex)
- {
- throw new ShaderException("failed reading shader '" + name + "'");
- }
- }
-
- private static String getError()
- {
- StringBuilder sb = new StringBuilder();
-
- int glErr = glGetError();
- while(glErr != GL_NO_ERROR)
- {
- sb.append(glErr);
- sb.append(" ");
- glErr = glGetError();
- }
-
- return sb.toString();
- }
-
- private static int createShaderProgram(String vertex, String fragment)
- {
- // ---------------------------------------------------------------------
- // vertex shader
- // ---------------------------------------------------------------------
-
- String vShaderSource[] = readFile(vertex);
-
- int vShader = glCreateShader(GL_VERTEX_SHADER);
- glShaderSource(vShader, vShaderSource);
- glCompileShader(vShader);
- String error = getError();
- if(!error.isEmpty())
- {
- throw new ShaderException("failed compiling vertex shader '" + vertex + "' " + error);
- }
-
- int compiled = glGetShaderi(vShader, GL_COMPILE_STATUS);
- if(compiled != 1)
- {
- throw new ShaderException("failed compiling vertex shader '" + vertex + "' " + compiled + " " + glGetShaderInfoLog(vShader));
- }
-
- // ---------------------------------------------------------------------
- // fragment shader
- // ---------------------------------------------------------------------
- String fShaderSource[] = readFile(fragment);
-
- int fShader = glCreateShader(GL_FRAGMENT_SHADER);
- glShaderSource(fShader, fShaderSource);
- glCompileShader(fShader);
- error = getError();
- if(!error.isEmpty())
- {
- throw new ShaderException("failed compiling fragment shader '" + fragment + "' " + error);
- }
-
- compiled = glGetShaderi(fShader, GL_COMPILE_STATUS);
- if(compiled != 1)
- {
- throw new ShaderException("failed compiling fragment shader '" + fragment + "' " + compiled + " " + glGetShaderInfoLog(fShader));
- }
-
- // ---------------------------------------------------------------------
- // linking
- // ---------------------------------------------------------------------
- int vfprogram = glCreateProgram();
- glAttachShader(vfprogram, vShader);
- glAttachShader(vfprogram, fShader);
- glLinkProgram(vfprogram);
- error = getError();
- if(!error.isEmpty())
- {
- throw new ShaderException("failed linking shaders '" + vertex + "' and '" + fragment + "' " + error);
- }
-
- compiled = glGetProgrami(vfprogram, GL_LINK_STATUS);
- if(compiled != 1)
- {
- throw new ShaderException("failed linking shaders '" + vertex + "' and '" + fragment + "' " + compiled + " " + glGetProgramInfoLog(vfprogram));
- }
- glDeleteShader(vShader);
- glDeleteShader(fShader);
-
- return vfprogram;
- }
- }
|