Subversion Repositories AndroidProjects

Rev

Rev 796 | Blame | Compare with Previous | Last modification | View Log | RSS feed

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using BauzoidNET.app;
using BauzoidNET.math;
using BauzoidNET.graphics.model;
using BauzoidNET.graphics;

using Tao.OpenGl;

#pragma warning disable 0618

namespace BauzoidNET.graphics.shader
{
    public class ShaderProgram : GraphicsObject
    {
            private static List<ShaderProgram> mManagedShaders = new List<ShaderProgram>();
       
            public static string ATTRIB_POSITION = "aPosition";
            public static string ATTRIB_COLOR = "aColor";
            public static string ATTRIB_NORMAL= "aNormal";
            public static string ATTRIB_TEXCOORD0 = "aTexCoord0";
            public static string ATTRIB_TEXCOORD1 = "aTexCoord1";
            public static string ATTRIB_BLENDINDICES = "aBlendIndex";
            public static string ATTRIB_BLENDWEIGHTS = "aBlendWeight";
       
            public class Shader
            {
                    private int mShaderID = 0;
                    private int mShaderType;
                    private string mShaderCode;

            private static int[] COMPILESTATUS = new int[1];
               
                    public Shader(int shaderType)
                    {
                            mShaderType = shaderType;
                    }
               
                    public void loadShader(string shaderCode)
                    {
                            //ShaderUtil.log(Consts.LOG_TAG, "Loading " + (mShaderType == GL20.GL_VERTEX_SHADER ? "Vertex" : "Fragment") + " Shader");
                LogUtil.log(Consts.LOG_TAG, "Loading " + (mShaderType == Gl.GL_VERTEX_SHADER ? "Vertex" : "Fragment") + " Shader");
                       
                            mShaderCode = shaderCode;
                       
                            if (mShaderID != 0)
                                    unloadShader();
                       
                            mShaderID = Gl.glCreateShader(mShaderType);

                string[] temp = new string[1];
                temp[0] = mShaderCode;

                int[] lengths = new int[1];
                lengths[0] = mShaderCode.Length;
                       
                            //Gl.glShaderSource(mShaderID, mShaderCode);
                Gl.glShaderSource(mShaderID, 1, temp, lengths);
                            Gl.glCompileShader(mShaderID);
                       
                            Gl.glGetShaderiv(mShaderID, Gl.GL_COMPILE_STATUS, COMPILESTATUS);
                       
                            if (COMPILESTATUS[0] != Gl.GL_TRUE)
                            {
                                    //ShaderUtil.log(Consts.LOG_TAG, Gdx.gl20.glGetShaderInfoLog(mShaderID));
                    StringBuilder sb = new StringBuilder(1024);
                    int length = 0;
                    Gl.glGetShaderInfoLog(mShaderID, 1024, (IntPtr)length, sb);
                    LogUtil.log(Consts.LOG_TAG, sb.ToString());
                                    return;
                            }
                       
                            //ShaderUtil.log(Consts.LOG_TAG, "Shader loading successful!");
                LogUtil.log(Consts.LOG_TAG, "Shader loading successful!");
                    }
               
                    public void reloadShader()
                    {                  
                            mShaderID = 0;
                            loadShader(mShaderCode);
                    }
               
                    public void unloadShader()
                    {
                            Gl.glDeleteShader(mShaderID);
                            mShaderID = 0;
                            mShaderCode = "";
                    }

            public int getShaderId()
            {
                return mShaderID;
            }
            };
       


            private Shader mVertexShader = null;
            private Shader mFragmentShader = null;
            private int mProgramID = 0;
       
            // Standard uniforms
            private ShaderUniform mModelViewProjection = null;
            private Matrix4 mModelViewProjectionMatrix = new Matrix4();
       
            public ShaderProgram(Graphics graphics)
            : base(graphics)
            {
                    mVertexShader = new Shader(Gl.GL_VERTEX_SHADER);
            mFragmentShader = new Shader(Gl.GL_FRAGMENT_SHADER);
            }
       
            public void loadShaderProgram(string vertexShaderCode, string fragmentShaderCode)
            {
                    mVertexShader.loadShader(vertexShaderCode);
                    mFragmentShader.loadShader(fragmentShaderCode);
               
                    mProgramID = Gl.glCreateProgram();
               
                    Gl.glAttachShader(mProgramID, mVertexShader.getShaderId());
            Gl.glAttachShader(mProgramID, mFragmentShader.getShaderId());
               
                    // default attrib locations
                    /*GLES20.glBindAttribLocation(mProgramID, SimpleGeometry.COORD_ATTRIB_INDEX, "vPosition");
                    GLES20.glBindAttribLocation(mProgramID, SimpleGeometry.COLOR_ATTRIB_INDEX, "vColor");
                    GLES20.glBindAttribLocation(mProgramID, SimpleGeometry.NORMAL_ATTRIB_INDEX, "vNormal");
                    GLES20.glBindAttribLocation(mProgramID, SimpleGeometry.TEX_COORD_ATTRIB_INDEX, "vTexCoord");*/


            Gl.glBindAttribLocation(mProgramID, VertexAttribute.POSITION, ATTRIB_POSITION);
            Gl.glBindAttribLocation(mProgramID, VertexAttribute.COLOR, ATTRIB_COLOR);
            Gl.glBindAttribLocation(mProgramID, VertexAttribute.NORMAL, ATTRIB_NORMAL);
            Gl.glBindAttribLocation(mProgramID, VertexAttribute.TEXCOORD0, ATTRIB_TEXCOORD0);
            Gl.glBindAttribLocation(mProgramID, VertexAttribute.TEXCOORD1, ATTRIB_TEXCOORD1);
            Gl.glBindAttribLocation(mProgramID, VertexAttribute.BLENDINDICES, ATTRIB_BLENDINDICES);
            Gl.glBindAttribLocation(mProgramID, VertexAttribute.BLENDWEIGHTS, ATTRIB_BLENDWEIGHTS);

            Gl.glLinkProgram(mProgramID);
               
                    // obtain uniforms for standard names
                    mModelViewProjection = getUniform("uMVPMatrix");
               
                    mManagedShaders.Add(this);
            }
       
            public void reloadShaderProgram()
            {
                    mVertexShader.reloadShader();
                    mFragmentShader.reloadShader();

            mProgramID = Gl.glCreateProgram();

            Gl.glAttachShader(mProgramID, mVertexShader.getShaderId());
            Gl.glAttachShader(mProgramID, mFragmentShader.getShaderId());
               
                    // default attrib locations
            Gl.glBindAttribLocation(mProgramID, VertexAttribute.POSITION, ATTRIB_POSITION);
            Gl.glBindAttribLocation(mProgramID, VertexAttribute.COLOR, ATTRIB_COLOR);
            Gl.glBindAttribLocation(mProgramID, VertexAttribute.NORMAL, ATTRIB_NORMAL);
            Gl.glBindAttribLocation(mProgramID, VertexAttribute.TEXCOORD0, ATTRIB_TEXCOORD0);
            Gl.glBindAttribLocation(mProgramID, VertexAttribute.TEXCOORD1, ATTRIB_TEXCOORD1);
            Gl.glBindAttribLocation(mProgramID, VertexAttribute.BLENDINDICES, ATTRIB_BLENDINDICES);
            Gl.glBindAttribLocation(mProgramID, VertexAttribute.BLENDWEIGHTS, ATTRIB_BLENDWEIGHTS);

            Gl.glLinkProgram(mProgramID);
            }
       
            public void dispose()
            {
                    mManagedShaders.Remove(this);

            Gl.glDeleteProgram(mProgramID);    
               
                    mVertexShader.unloadShader();
                    mFragmentShader.unloadShader();
               
                    mProgramID = 0;
            }
       
            public void activate()
            {
                    // TODO: state management!
            Gl.glUseProgram(mProgramID);
               
                    // apply standard uniforms
                    if (mModelViewProjection != null)
                    {
                            getRenderStates().getModelViewProjection(mModelViewProjectionMatrix);
                            mModelViewProjection.set(mModelViewProjectionMatrix);
                    }
            }
       
            public void deactivate()
            {
            Gl.glUseProgram(0);
            }
       
            public ShaderUniform getUniform(string uniformName)
            {
                    if (mProgramID == 0)
                            return null;
               
                    int handle = getUniformHandle(uniformName);
               
                    if (handle == -1)
                    {
                            //Log.e(Consts.LOG_TAG, "Error getting uniform '" + uniformName + "'!");
                            return null;
                    }
               
                    return new ShaderUniform(this, uniformName);
            }
       
            public int getUniformHandle(string uniformName)
            {
            return Gl.glGetUniformLocation(mProgramID, uniformName);
            }

            public Shader getVertexShader()
            {
                    return mVertexShader;
            }
       
            public Shader getFragmentShader()
            {
                    return mFragmentShader;
            }
       
            public static void reloadManagedShaders()
            {
                    for (int i = 0; i < mManagedShaders.Count; i++)
                    {
                ShaderProgram shader = mManagedShaders[i];
                            shader.reloadShaderProgram();
                            //ShaderUtil.log(Consts.LOG_TAG, "ShaderProgram reloaded!");
                    }
            }
    }
}