Advertisement
Guest User

Untitled

a guest
Mar 21st, 2012
71
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 11.81 KB | None | 0 0
  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. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement