/** * */ package rajawali.renderer.plugins; import android.opengl.GLES20; import rajawali.Geometry3D; import rajawali.renderer.RajawaliRenderer; import rajawali.util.RajLog; /** * Most plugins should generally inherit from this Plugin abstract class. * @author Andrew Jo */ public abstract class Plugin implements IRendererPlugin { protected Geometry3D mGeometry; protected RajawaliRenderer mRenderer; // Field variables for shader programs. protected String mVertexShader; protected String mFragmentShader; protected int mVShaderHandle; protected int mFShaderHandle; protected int mProgram; protected boolean mProgramCreated = false; /** * Instantiates a new renderer plugin. * @param renderer RajawaliRenderer instance which will be using this plugin. */ public Plugin(RajawaliRenderer renderer) { mGeometry = new Geometry3D(); mRenderer = renderer; init(); } protected int createProgram(String vertexShader, String fragmentShader) { mVShaderHandle = loadShader(GLES20.GL_VERTEX_SHADER, vertexShader); if (mVShaderHandle == 0) { return 0; } mFShaderHandle = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShader); if (mFShaderHandle == 0) { return 0; } int program = GLES20.glCreateProgram(); if (program != 0) { GLES20.glAttachShader(program, mVShaderHandle); GLES20.glAttachShader(program, mFShaderHandle); GLES20.glLinkProgram(program); int[] linkStatus = new int[1]; GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0); if (linkStatus[0] != GLES20.GL_TRUE) { RajLog.e("Could not link program in " + getClass().getCanonicalName() +": "); RajLog.e(GLES20.glGetProgramInfoLog(program)); RajLog.d("-=-=-= VERTEX SHADER =-=-=-"); RajLog.d(mVertexShader); RajLog.d("-=-=-= FRAGMENT SHADER =-=-=-"); RajLog.d(mFragmentShader); GLES20.glDeleteProgram(program); program = 0; } } return program; } public void destroy() { unload(); } protected int getUniformLocation(String name) { return GLES20.glGetUniformLocation(mProgram, name); } protected int getAttribLocation(String name) { return GLES20.glGetAttribLocation(mProgram, name); } /** * Be sure to set up all the GL buffers and other initializations here. */ protected void init() {} protected int loadShader(int shaderType, String source) { int shader = GLES20.glCreateShader(shaderType); if (shader != 0) { GLES20.glShaderSource(shader, source); GLES20.glCompileShader(shader); int[] compiled = new int[1]; GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0); if (compiled[0] == 0) { RajLog.e("[" +getClass().getName()+ "] Could not compile " + (shaderType == GLES20.GL_FRAGMENT_SHADER ? "fragment" : "vertex") + " shader:"); RajLog.e("Shader log: " + GLES20.glGetShaderInfoLog(shader)); GLES20.glDeleteShader(shader); shader = 0; } } return shader; } /* (non-Javadoc) * @see rajawali.renderer.plugins.IRendererPlugin#reload() */ public void reload() { mGeometry.reload(); setShaders(mVertexShader, mFragmentShader); } /* (non-Javadoc) * @see rajawali.renderer.plugins.IRendererPlugin#render() */ public void render() {} protected void setData(float[] vertices, float[] normals, float[] textureCoords, float[] colors, int[] indices) { mGeometry.setData(vertices, normals, textureCoords, colors, indices); } protected void setShaders(String vertexShader, String fragmentShader) { mVertexShader = vertexShader; mFragmentShader = fragmentShader; mProgram = createProgram(vertexShader, fragmentShader); if (mProgram == 0) { RajLog.e("Failed to create program"); return; } mProgramCreated = true; } /** * Unloads and deletes references to the shader program */ public void unload() { GLES20.glDeleteShader(mVShaderHandle); GLES20.glDeleteShader(mFShaderHandle); GLES20.glDeleteProgram(mProgram); } protected void useProgram(int programHandle) { if(!mProgramCreated) { reload(); } // Signal that we'll be using the shader program. GLES20.glUseProgram(programHandle); } }