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!");
}
}
}
}