Java tutorial
/* * Copyright 2014 Lukas Tenbrink * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package ivorius.ivtoolkit.rendering; import gnu.trove.map.TObjectIntMap; import gnu.trove.map.hash.TObjectIntHashMap; import net.minecraft.client.renderer.OpenGlHelper; import org.apache.logging.log4j.Logger; import org.lwjgl.BufferUtils; import org.lwjgl.opengl.*; import org.lwjgl.util.vector.Matrix; import org.lwjgl.util.vector.Matrix2f; import org.lwjgl.util.vector.Matrix3f; import org.lwjgl.util.vector.Matrix4f; import java.nio.ByteBuffer; import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.util.HashMap; import java.util.Map; public class IvShaderInstance { public Logger logger; private int shaderID = 0; private boolean shaderActive = false; private TObjectIntMap<String> uniformLocations = new TObjectIntHashMap<>(); public int getShaderID() { return shaderID; } public IvShaderInstance(Logger logger) { this.logger = logger; } public void trySettingUpShader(String vertexShaderFile, String fragmentShaderFile) { if (shaderID <= 0) { registerShader(vertexShaderFile, fragmentShaderFile); } } public void registerShader(String vertexShaderCode, String fragmentShaderCode) { deleteShader(); int vertShader = -1; int fragShader = -1; try { if (vertexShaderCode != null) vertShader = createShader(vertexShaderCode, OpenGlHelper.field_153209_q); if (fragmentShaderCode != null) fragShader = createShader(fragmentShaderCode, OpenGlHelper.field_153210_r); } catch (Exception exc) { exc.printStackTrace(); return; } shaderID = OpenGlHelper.func_153183_d(); if (vertShader > 0) { OpenGlHelper.func_153178_b(shaderID, vertShader); OpenGlHelper.func_153180_a(vertShader); } if (fragShader > 0) { OpenGlHelper.func_153178_b(shaderID, fragShader); OpenGlHelper.func_153180_a(fragShader); } OpenGlHelper.func_153179_f(shaderID); if (OpenGlHelper.func_153175_a(shaderID, OpenGlHelper.field_153207_o) == GL11.GL_FALSE) logger.error(OpenGlHelper.func_153166_e(shaderID, 0x8000)); IvOpenGLHelper.glValidateProgram(shaderID); if (OpenGlHelper.func_153175_a(shaderID, IvOpenGLHelper.GL_VALIDATE_STATUS) == GL11.GL_FALSE) logger.error(OpenGlHelper.func_153166_e(shaderID, 0x8000)); } private int createShader(String shaderCode, int shaderType) throws Exception { int shader = 0; try { shader = OpenGlHelper.func_153195_b(shaderType); if (shader == 0) return 0; byte[] shaderCodeBytes = shaderCode.getBytes(); ByteBuffer shaderCodeBuf = BufferUtils.createByteBuffer(shaderCodeBytes.length); shaderCodeBuf.put(shaderCodeBytes); shaderCodeBuf.position(0); OpenGlHelper.func_153169_a(shader, shaderCodeBuf); OpenGlHelper.func_153170_c(shader); if (OpenGlHelper.func_153157_c(shader, OpenGlHelper.field_153208_p) == GL11.GL_FALSE) { throw new RuntimeException("Error creating shader: " + OpenGlHelper.func_153166_e(shader, 0x8000)); } return shader; } catch (Exception exc) { if (shader != 0) OpenGlHelper.func_153180_a(shader); throw new RuntimeException(exc); } } public boolean useShader() { if (shaderID <= 0 && !shaderActive) { return false; } shaderActive = true; OpenGlHelper.func_153161_d(shaderID); return true; } public void stopUsingShader() { if (shaderID <= 0 && shaderActive) { return; } OpenGlHelper.func_153161_d(0); shaderActive = false; } public boolean isShaderActive() { return shaderActive; } public boolean setUniformInts(String key, int... ints) { return setUniformIntsOfType(key, ints.length, ints); } public boolean setUniformIntsOfType(String key, int typeLength, int... ints) { if (shaderID <= 0 || !shaderActive) { return false; } IntBuffer intBuffer = BufferUtils.createIntBuffer(ints.length); intBuffer.put(ints); intBuffer.position(0); switch (typeLength) { case 1: OpenGlHelper.func_153181_a(getUniformLocation(key), intBuffer); break; case 2: OpenGlHelper.func_153182_b(getUniformLocation(key), intBuffer); break; case 3: OpenGlHelper.func_153192_c(getUniformLocation(key), intBuffer); break; case 4: OpenGlHelper.func_153162_d(getUniformLocation(key), intBuffer); break; default: throw new IllegalArgumentException(); } return true; } public boolean setUniformFloats(String key, float... floats) { return setUniformFloatsOfType(key, floats.length, floats); } public boolean setUniformFloatsOfType(String key, int typeLength, float... floats) { if (shaderID <= 0 || !shaderActive) { return false; } FloatBuffer floatBuffer = BufferUtils.createFloatBuffer(floats.length); floatBuffer.put(floats); floatBuffer.position(0); switch (typeLength) { case 1: OpenGlHelper.func_153168_a(getUniformLocation(key), floatBuffer); break; case 2: OpenGlHelper.func_153177_b(getUniformLocation(key), floatBuffer); break; case 3: OpenGlHelper.func_153191_c(getUniformLocation(key), floatBuffer); break; case 4: OpenGlHelper.func_153159_d(getUniformLocation(key), floatBuffer); break; default: throw new IllegalArgumentException(); } return true; } public boolean setUniformMatrix(String key, Matrix matrix) { if (shaderID <= 0 || !shaderActive) { return false; } int width; if (matrix instanceof Matrix2f) width = 2; else if (matrix instanceof Matrix3f) width = 3; else if (matrix instanceof Matrix4f) width = 4; else throw new IllegalArgumentException(); FloatBuffer floatBuffer = BufferUtils.createFloatBuffer(width * width); matrix.store(floatBuffer); floatBuffer.position(0); switch (width) { case 2: OpenGlHelper.func_153173_a(getUniformLocation(key), false, floatBuffer); break; case 3: OpenGlHelper.func_153189_b(getUniformLocation(key), false, floatBuffer); break; default: OpenGlHelper.func_153160_c(getUniformLocation(key), false, floatBuffer); break; } return true; } public Integer getUniformLocation(String key) { if (shaderID <= 0) return 0; if (!uniformLocations.containsKey(key)) uniformLocations.put(key, OpenGlHelper.func_153194_a(shaderID, key)); return uniformLocations.get(key); } public void deleteShader() { if (shaderActive) stopUsingShader(); if (shaderID > 0) { OpenGlHelper.func_153187_e(shaderID); shaderID = 0; } uniformLocations.clear(); } public static void outputShaderInfo(Logger logger) { String renderer = GL11.glGetString(GL11.GL_RENDERER); String vendor = GL11.glGetString(GL11.GL_VENDOR); String version = GL11.glGetString(GL11.GL_VERSION); boolean fboSupported = OpenGlHelper.framebufferSupported; String majorVersion; String minorVersion; String glslVersion; try { glslVersion = GL11.glGetString(GL20.GL_SHADING_LANGUAGE_VERSION); } catch (Exception ex) { glslVersion = "? (No GL20)"; } try { minorVersion = "" + GL11.glGetInteger(GL30.GL_MINOR_VERSION); majorVersion = "" + GL11.glGetInteger(GL30.GL_MAJOR_VERSION); } catch (Exception ex) { minorVersion = "?"; majorVersion = "? (No GL 30)"; } printAlignedInfo("Vendor", vendor, logger); printAlignedInfo("Renderer", renderer, logger); printAlignedInfo("Version", version, logger); printAlignedInfo("Versions", getGLVersions(GLContext.getCapabilities()), logger); printAlignedInfo("Version Range", String.format("%s - %s", minorVersion, majorVersion), logger); printAlignedInfo("GLSL Version", glslVersion, logger); printAlignedInfo("Frame buffer object", fboSupported ? "Supported" : "Unsupported", logger); } private static void printAlignedInfo(String category, String info, Logger logger) { logger.info(String.format("%-20s: %s", category, info)); } private static String getGLVersions(ContextCapabilities cap) { String versions = ""; try { if (cap.OpenGL11) versions += ":11"; if (cap.OpenGL12) versions += ":12"; if (cap.OpenGL13) versions += ":13"; if (cap.OpenGL14) versions += ":14"; if (cap.OpenGL15) versions += ":15"; } catch (Throwable throwable) { versions += ":lwjgl-Error-1"; } try { if (cap.OpenGL20) versions += ":20"; if (cap.OpenGL21) versions += ":21"; } catch (Throwable throwable) { versions += ":lwjgl-Error-2"; } try { if (cap.OpenGL30) versions += ":30"; if (cap.OpenGL31) versions += ":31"; if (cap.OpenGL32) versions += ":32"; if (cap.OpenGL33) versions += ":33"; } catch (Throwable throwable) { versions += ":lwjgl-Error-3"; } // try // { // if (cap.OpenGL40) // { // versions += ":40"; // } // if (cap.OpenGL41) // { // versions += ":41"; // } // if (cap.OpenGL42) // { // versions += ":42"; // } // if (cap.OpenGL43) // { // versions += ":43"; // } // if (cap.OpenGL44) // { // versions += ":44"; // } // } // catch (Throwable throwable) // { // versions += ":lwjgl-Error-4"; // } if (versions.length() > 0) versions = versions.substring(1); return versions; } }