/** * Copyright (c) Lambda Innovation, 2013-2015 * 本作品版权由Lambda Innovation所有。 * http://www.li-dev.cn/ * * This project is open-source, and it is distributed under * the terms of GNU General Public License. You can modify * and distribute freely as long as you follow the license. * 本项目是一个开源项目,且遵循GNU通用公共授权协议。 * 在遵照该协议的情况下,您可以自由传播和修改。 * http://www.gnu.org/licenses/gpl.html */ package cn.liutils.util.client.shader; import static org.lwjgl.opengl.GL11.*; import static org.lwjgl.opengl.GL20.*; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.io.IOUtils; import cn.liutils.core.LIUtils; import cn.liutils.util.generic.RegistryUtils; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import net.minecraft.util.ResourceLocation; /** * A simple GL Shader Program wrapper. * @author WeAthFolD */ @SideOnly(Side.CLIENT) public class ShaderProgram { static Map<ResourceLocation, Integer> loadedShaders = new HashMap(); public static void releaseResources() { for(Integer e : loadedShaders.values()) glDeleteShader(e); loadedShaders.clear(); } private boolean compiled = false; private int programID; private List<Integer> attachedShaders = new ArrayList(); public ShaderProgram() { programID = glCreateProgram(); } public void linkShader(ResourceLocation location, int type) { try { int shaderID; if(loadedShaders.containsKey(location)) { shaderID = loadedShaders.get(location); } else { String str = IOUtils.toString(RegistryUtils.getResourceStream(location)); shaderID = glCreateShader(type); glShaderSource(shaderID, str); glCompileShader(shaderID); int successful = glGetShaderi(shaderID, GL_COMPILE_STATUS); if(successful == GL_FALSE) { String log = glGetShaderInfoLog(shaderID, glGetShaderi(shaderID, GL_INFO_LOG_LENGTH)); LIUtils.log.error("Error when linking shader '" + location + "'. code: " + successful + ", Error string: \n" + log); throw new RuntimeException(); } } attachedShaders.add(shaderID); glAttachShader(programID, shaderID); } catch (IOException e) { LIUtils.log.error("Error when linking shader " + location, e); throw new RuntimeException(); } } public int getProgramID() { return programID; } public void useProgram() { if(compiled) { glUseProgram(programID); } else { LIUtils.log.error("Trying to use a uncompiled program"); throw new RuntimeException(); } } public int getUniformLocation(String name) { return glGetUniformLocation(getProgramID(), name); } public void compile() { if(compiled) { LIUtils.log.error("Trying to compile shader " + this + " twice."); throw new RuntimeException(); } glLinkProgram(programID); for(Integer i : attachedShaders) glDetachShader(programID, i); attachedShaders = null; int status = glGetProgrami(programID, GL_LINK_STATUS); if(status == GL_FALSE) { String log = glGetProgramInfoLog(programID, glGetProgrami(programID, GL_INFO_LOG_LENGTH)); LIUtils.log.error("Error when linking program #" + programID + ". Error code: " + status + ", Error string: "); LIUtils.log.error(log); throw new RuntimeException(); } compiled = true; } /** * Get the src of a shader in liutils namespace. * @param name * @return */ public static ResourceLocation getShader(String name) { return new ResourceLocation("liutils:shaders/" + name); } }