SHARE
TWEET

Untitled

a guest Mar 21st, 2012 48 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. package space.engine;
  2.  
  3. import java.io.BufferedReader;
  4. import java.io.IOException;
  5. import java.io.InputStream;
  6. import java.io.InputStreamReader;
  7. import java.nio.FloatBuffer;
  8. import java.nio.IntBuffer;
  9. import java.util.HashMap;
  10.  
  11. import org.lwjgl.opengl.ARBShaderObjects;
  12. import org.lwjgl.opengl.ContextCapabilities;
  13. import org.lwjgl.opengl.GL11;
  14. import org.lwjgl.opengl.GL20;
  15. import org.lwjgl.opengl.GLContext;
  16. import org.newdawn.slick.SlickException;
  17. import org.newdawn.slick.util.Log;
  18. import org.newdawn.slick.util.ResourceLoader;
  19.  
  20. public class ShaderProgram {
  21.  
  22.         private static boolean strict = true;
  23.        
  24.         public static boolean isSupported() {
  25.                 ContextCapabilities c = GLContext.getCapabilities();
  26.                 return c.GL_ARB_shader_objects && c.GL_ARB_vertex_shader && c.GL_ARB_fragment_shader;
  27.         }
  28.        
  29.         public static void setStrictMode(boolean enabled) {
  30.                 strict = enabled;
  31.         }
  32.        
  33.         public static boolean isStrictMode() {
  34.                 return strict;
  35.         }
  36.        
  37.         /**
  38.          * Disables all shader use.
  39.          */
  40.         public static void bindNone() {
  41.                 ARBShaderObjects.glUseProgramObjectARB(0);
  42.         }
  43.        
  44.        
  45.         protected int program;
  46.        
  47.         protected String log = "";
  48.        
  49.         protected HashMap<String, Integer> uniforms = new HashMap<String, Integer>();
  50.         protected HashMap<String, Integer> attributes = new HashMap<String, Integer>();
  51.        
  52.        
  53.         protected Shader vert, frag;
  54.        
  55.         public static ShaderProgram loadProgram(String vertFile, String fragFile) throws SlickException {
  56.                 return new ShaderProgram(loadSource(vertFile), loadSource(fragFile));
  57.         }
  58.        
  59.         public static String loadSource(String ref) throws SlickException {
  60.                 InputStream in = ResourceLoader.getResourceAsStream(ref);
  61.                 try { return loadSource(in); }
  62.                 catch (SlickException e) {
  63.                         throw new SlickException("could not load source file: "+ref);
  64.                 }
  65.         }
  66.        
  67.     public static String loadSource(InputStream in) throws SlickException {
  68.         try {
  69.                 BufferedReader br = new BufferedReader(new InputStreamReader(in));
  70.                 String line = "";
  71.                 String txt = "";
  72.                 while ((line=br.readLine()) != null)
  73.                         txt += line + "\n";
  74.                 br.close();
  75.                 return txt.trim();
  76.         } catch (IOException e) {
  77.                 throw new SlickException("could not load source file");
  78.         }
  79.     }
  80.        
  81.     public ShaderProgram(String vertexShaderSource, String fragShaderSource) throws SlickException {
  82.         this(new Shader(Shader.VERTEX_SHADER, vertexShaderSource),
  83.                  new Shader(Shader.FRAGMENT_SHADER, fragShaderSource));
  84.     }
  85.    
  86.         public ShaderProgram(Shader vert, Shader frag) throws SlickException {
  87.                 //do some error checking before we tell OpenGL to create the program
  88.                 if (!isSupported())
  89.                         throw new SlickException("no shader support found; driver does not support extension GL_ARB_shader_objects");
  90.                 if (vert==null || frag==null || !vert.valid() || !frag.valid()) {
  91.                         throw new IllegalArgumentException("shaders must be non-null and valid before linking");
  92.                 }
  93.                 if (vert.getType()!=Shader.VERTEX_SHADER)
  94.                         throw new IllegalArgumentException("vertex shader not of type VERTEX_SHADER");
  95.                 if (frag.getType()!=Shader.FRAGMENT_SHADER)
  96.                         throw new IllegalArgumentException("vertex shader not of type FRAGMENT_SHADER");
  97.                
  98.                
  99.                 create();
  100.                
  101.                 this.vert = vert;
  102.                 this.frag = frag;
  103.                 link();
  104.         }
  105.        
  106.         /**
  107.          * Creates a program object with nothing attached to it; a vertex and fragment shader should
  108.          * be set before linking.
  109.          *
  110.          * @throws SlickException
  111.          */
  112.         public ShaderProgram() throws SlickException {
  113.                 create();
  114.         }
  115.        
  116.         private void create() throws SlickException {
  117.                 if (!isSupported())
  118.                         throw new SlickException("no shader support found; driver does not support extension GL_ARB_shader_objects");
  119.                 program = ARBShaderObjects.glCreateProgramObjectARB();
  120.                 if (program == 0)
  121.                         throw new SlickException("could not create program; check ShaderProgram.isSupported()");
  122.         }
  123.        
  124.         /**
  125.          * Compiles this program by attaching the current Frag/Vertex shaders,
  126.          * linking the program, and detaching the shaders (since they are now linked
  127.          * to the program).
  128.          *
  129.          * @throws IllegalStateException
  130.          *             if we are trying to link an invalid (released) program, or if
  131.          *             the current shaders are null/invalid
  132.          * @throws SlickException
  133.          *             if the link was unsuccessful
  134.          */
  135.         public void link() throws SlickException {
  136.                 if (!valid())
  137.                         throw new IllegalStateException("trying to link a released program");
  138.                 if (vert==null || frag==null || !vert.valid() || !frag.valid())
  139.                         throw new IllegalArgumentException("shaders must be non-null and valid before linking");
  140.                
  141.                 uniforms.clear();
  142.                 attributes.clear();
  143.                
  144.                 vert.attach(this);
  145.                 frag.attach(this);
  146.         ARBShaderObjects.glLinkProgramARB(program);
  147.        
  148.         //GL20.glValidateProgram(program);
  149.         int comp = ARBShaderObjects.glGetObjectParameteriARB(program, GL20.GL_LINK_STATUS);
  150.        
  151.         //shaders no longer need to be attached to the program
  152.         vert.detach(this);
  153.         frag.detach(this);
  154.         int len = ARBShaderObjects.glGetObjectParameteriARB(program, GL20.GL_INFO_LOG_LENGTH);
  155.                 log += ARBShaderObjects.glGetInfoLogARB(program, len);
  156.         if (comp==GL11.GL_FALSE)
  157.                         throw new SlickException("ERROR: Error in linking shaders\n"+log);
  158.         else if (log!=null&&log.length()!=0)
  159.                         Log.warn("GLSL link warning: "+log);
  160.                 fetchUniforms();
  161. //              fetchAttributes();
  162.         }
  163.        
  164.         /**
  165.          * Returns the log info
  166.          * @return the log info for this program object
  167.          */
  168.         public String getLinkLog() {
  169.                 return log;
  170.         }
  171.        
  172.         /**
  173.          * Concats the shader's compile info and this program's link info and returns the result.
  174.          * @return the full log of this ShaderProgram
  175.          */
  176.         public String getLog() {
  177.                 String s = "";
  178.                 if (vert!=null)
  179.                         s += vert.getCompileLog();
  180.                 if (frag!=null)
  181.                         s += frag.getCompileLog();
  182.                 return s + getLinkLog();
  183.         }
  184.        
  185.         /**
  186.          * Sets the vertex shader to be used on next link. This will have no effect until
  187.          * link() is called, in which case it will be attached to the program before linking
  188.          * (and then detached from the program after linking).
  189.          * @param shader the new vertex shader
  190.          */
  191.         public void setVertexShader(Shader shader) {
  192.                 if (shader.getType()!=Shader.VERTEX_SHADER)
  193.                         throw new IllegalArgumentException("vertex shader not of type VERTEX_SHADER");
  194.                 this.vert = shader;
  195.         }
  196.        
  197.         public void setFragmentShader(Shader shader) {
  198.                 if (shader.getType()!=Shader.FRAGMENT_SHADER)
  199.                         throw new IllegalArgumentException("fragment shader not of type FRAGMENT_SHADER");
  200.                 this.frag = shader;
  201.         }
  202.        
  203.         /**
  204.          * Enables this shader for use. Only one shader can be active at a time.
  205.          * @throw IllegalStateException if this program is invalid
  206.          */
  207.         public void bind() {
  208.                 if (!valid())
  209.                         throw new IllegalStateException("trying to enable a program that is not valid");
  210.                 ARBShaderObjects.glUseProgramObjectARB(program);
  211.         }
  212.  
  213.         /**
  214.          * Unbinds this program and disables shaders via bindNone. This isn't necessary to
  215.          * call immediately before another shader bind(), as only one shader can be active
  216.          * at a time.
  217.          */
  218.         public void unbind() {
  219.                 ShaderProgram.bindNone();
  220.         }
  221.        
  222.         /**
  223.          * Releases this program and the current vertex/fragment shaders. If you wish to only release
  224.          * the program (i.e. not the shaders as well), then use releaseProgram(). Programs shouldn't
  225.          * be used after being released.
  226.          */
  227.         public void release() {
  228.                 if (program!=0) {
  229.                         vert.release();
  230.                         frag.release();
  231.                         releaseProgram();
  232.                 }
  233.         }
  234.        
  235.         /**
  236.          * Releases this program and sets its ID to zero -- this will not release the current shaders.
  237.          * Programs shouldn't be used after being released.
  238.          */
  239.         public void releaseProgram() {
  240.                 if (program!=0) {
  241.                         ARBShaderObjects.glDeleteObjectARB(program);
  242.                         program = 0;
  243.                 }
  244.         }
  245.        
  246.         /**
  247.          * The ID of a shader, the value given by glCreateProgram.
  248.          * @return the program ID
  249.          */
  250.         public int getID() {
  251.                 return program;
  252.         }
  253.        
  254.         /**
  255.          * A shader program is "valid" if it's ID is not zero.
  256.          * @return whether this program is valid
  257.          */
  258.         public boolean valid() {
  259.                 return program != 0;
  260.         }
  261.        
  262. //      protected int findAttributeLocation(String name) {
  263. //              int location = attributes.get(name);
  264. //              if (location!=-1)
  265. //                      return location;
  266. //              location = ARBVertexShader.glGetAttribLocationARB(program, name);
  267. //              if (location == -1 && strict)
  268. //                      throw new IllegalArgumentException("no active attribute by name '"+name+"'");
  269. //              attributes.put(name, location);
  270. //              return location;
  271. //      }
  272.        
  273.         protected int findUniformLocation(String name) {
  274.                 Integer locI = uniforms.get(name);
  275.                 int location = locI==null ? -1 : locI.intValue();
  276.                 if (location!=-1)
  277.                         return location;
  278.                 location = ARBShaderObjects.glGetUniformLocationARB(program, name);
  279.                 if (location == -1 && strict)
  280.                         throw new IllegalArgumentException("no active uniform by name '"+name+"' (disable strict compiling to suppress warnings)");
  281.                 uniforms.put(name, location);
  282.                 return location;
  283.         }
  284.        
  285.         private void fetchUniforms() {
  286.                 int len = ARBShaderObjects.glGetObjectParameteriARB(program, GL20.GL_ACTIVE_UNIFORMS);
  287.                 //max length of all uniforms stored in program
  288.                 int strLen = ARBShaderObjects.glGetObjectParameteriARB(program, GL20.GL_ACTIVE_UNIFORM_MAX_LENGTH);
  289.                
  290.                 for (int i=0; i<len; i++) {
  291.                         String name = ARBShaderObjects.glGetActiveUniformARB(program, i, strLen);
  292.                         int id = ARBShaderObjects.glGetUniformLocationARB(program, name);
  293.                         uniforms.put(name, id);
  294.                 }
  295.         }
  296.        
  297. //      private void fetchAttributes() {
  298. //              int len = ARBShaderObjects.glGetObjectParameteriARB(program, GL20.GL_ACTIVE_ATTRIBUTES);
  299. //              //max length of all uniforms stored in program
  300. //              int strLen = ARBShaderObjects.glGetObjectParameteriARB(program, GL20.GL_ACTIVE_ATTRIBUTE_MAX_LENGTH);
  301. //              for (int i=0; i<len; i++) {
  302. //                      String name = ARBVertexShader.glGetActiveAttribARB(program, i, strLen);
  303. //                      int id = ARBVertexShader.glGetAttribLocationARB(program, name);
  304. //                      uniforms.put(name, id);
  305. //              }
  306. //      }
  307.        
  308.         public int getUniformID(String name) {
  309.                 return findUniformLocation(name);
  310.         }
  311.        
  312. //      public int getAttributeID(String name) {
  313. //              return findAttributeLocation(name);
  314. //      }
  315.        
  316. //      public String[] getAttributes() {
  317. //              return attributes.keySet().toArray(new String[attributes.size()]);
  318. //      }
  319.        
  320.         public String[] getUniformNames() {
  321.                 return uniforms.keySet().toArray(new String[uniforms.size()]);
  322.         }
  323.        
  324.         public Shader getVertexShader() {
  325.                 return vert;
  326.         }
  327.        
  328.         public Shader getFragmentShader() {
  329.                 return frag;
  330.         }
  331.  
  332.         public boolean getUniform(String name, FloatBuffer buf) {
  333.                 int id = getUniformID(name);
  334.                 if (id==-1) return false;
  335.                 ARBShaderObjects.glGetUniformARB(program, id, buf);
  336.                 return true;
  337.         }
  338.        
  339.         public boolean getUniform(String name, IntBuffer buf) {
  340.                 int id = getUniformID(name);
  341.                 if (id==-1) return false;
  342.                 ARBShaderObjects.glGetUniformARB(program, id, buf);
  343.                 return true;
  344.         }
  345.        
  346.         public boolean hasUniform(String name) {
  347.                 return uniforms.containsKey(name);
  348.         }
  349.        
  350.         public boolean hasAttribute(String name) {
  351.                 return attributes.containsKey(name);
  352.         }
  353.  
  354.         public void setUniform1f(String name, float f) {
  355.                 int id = getUniformID(name);
  356.                 if (id==-1) return;
  357.                 ARBShaderObjects.glUniform1fARB(id, f);
  358.         }
  359.        
  360.         public void setUniform1i(String name, int i) {
  361.                 int id = getUniformID(name);
  362.                 if (id==-1) return;
  363.                 ARBShaderObjects.glUniform1iARB(id, i);
  364.         }
  365.        
  366.         public void setUniform2f(String name, float a, float b) {
  367.                 int id = getUniformID(name);
  368.                 if (id==-1) return;
  369.                 ARBShaderObjects.glUniform2fARB(id, a, b);
  370.         }
  371.        
  372.         public void setUniform3f(String name, float a, float b, float c) {
  373.                 int id = getUniformID(name);
  374.                 if (id==-1) return;
  375.                 ARBShaderObjects.glUniform3fARB(id, a, b, c);
  376.         }
  377.        
  378.         public void setUniform4f(String name, float a, float b, float c, float d) {
  379.                 int id = getUniformID(name);
  380.                 if (id==-1) return;
  381.                 ARBShaderObjects.glUniform4fARB(id, a, b, c, d);
  382.         }
  383.        
  384.        
  385.         // TODO: include more setUniforms/getUniforms
  386. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top