package org.osm2world.core.target.jogl; import java.nio.IntBuffer; import javax.media.opengl.GL; import javax.media.opengl.GL3; /** * Simple base class for a shader program. Manages vertex and fragment shaders, links and validates them. */ public abstract class AbstractShader { protected GL3 gl; protected int vertexShader; protected int fragmentShader; protected int shaderProgram; /** * Loads the vertex and fragment shaders with the basename name and ending <i>vertex</i> and <i>fragment</i> * and creates a shader program for them. The shader is linked but not validated. * {@link #validateShader()} needs to be called manually. * @param name basename of the shader to load */ public AbstractShader(GL3 gl, String name) { this.gl = gl; shaderProgram = gl.glCreateProgram(); if (shaderProgram < 1) throw new RuntimeException("Unable to create shader program."); /* * set up the vertex and fragment shaders. use static methods * for setting up the shaders. These methods return the unique int * identifiers GL assigns to each shader */ vertexShader = ShaderManager.createVertexShader(gl, name+".vertex"); fragmentShader = ShaderManager.createFragmentShader(gl, name+".fragment"); //System.out.printf("Vertex: %d, Fragment: %d\n",vertexShader,fragmentShader); // attach the shaders to the shader program and link gl.glAttachShader(shaderProgram, vertexShader); gl.glAttachShader(shaderProgram, fragmentShader); gl.glLinkProgram(shaderProgram); // validate linking IntBuffer linkStatus = IntBuffer.allocate(1); gl.glGetProgramiv(shaderProgram, GL3.GL_LINK_STATUS, linkStatus); if (linkStatus.get() == GL.GL_FALSE) { ShaderManager.printProgramInfoLog(gl, shaderProgram); throw new RuntimeException("could not link shader"); } ShaderManager.printProgramInfoLog(gl, shaderProgram); } /** * Validates the linked shader program. An exception is raised if the validation fails. */ protected void validateShader() { // tell GL to validate the shader program and grab the created log gl.glValidateProgram(shaderProgram); // perform general validation that the program is usable IntBuffer validateStatus = IntBuffer.allocate(1); gl.glGetProgramiv(shaderProgram, GL3.GL_VALIDATE_STATUS, validateStatus); if (validateStatus.get() == GL.GL_FALSE) { ShaderManager.printProgramInfoLog(gl, shaderProgram); throw new RuntimeException("could not validate shader"); } ShaderManager.printProgramInfoLog(gl, shaderProgram); } /** * Make this shader program active. */ public void useShader() { gl.glUseProgram(this.getProgram()); } public void disableShader() { gl.glUseProgram(0); } public int getProgram() { return shaderProgram; } public void freeResources() { gl.glDetachShader(shaderProgram, vertexShader); gl.glDetachShader(shaderProgram, fragmentShader); gl.glDeleteProgram(shaderProgram); gl.glDeleteShader(vertexShader); gl.glDeleteShader(fragmentShader); gl = null; } @Override protected void finalize() { freeResources(); } /** * Load default values for the shader. Should be called after every {@link #useShader()} and before any draw calls. */ public void loadDefaults() { } }