using System; using System.IO; using OpenTK.Graphics.OpenGL; using OpenTK; using org.budnhead.tools; /** * ShaderProgram Class * * Defines a shading program to use for drawing operations * * The coordinate space used to describe the world is called "WorldSpace" * * Each object to be drawn/used in the "World" is based on its individual coordinate space "ObjectSpace" * Each object provides a Transformation Matrix "mObject" which translates ObjectSpace to WorldSpace. * * WorldSpace = mObject * ObjectSpace * * To render the scene another coordinate space is used, which is called "CameraSpace" * The transformation matrix used to translate from WorldSpace to CameraSpace is called "mCamera" * * CameraSpace = (mObject * mCamera) * ObjectSpace * * As convention the following data will be given to shaders: * * Uniform: * * mObject Transformation Matrix ObjectSpace -> WorldSpace * mCamera Transformation Matrix WorldSpace -> CameraSpace * mProjection Projection Matrix for 2D Rendering * * mObjectCamera mObject * mCamera * * mObjectCameraIT (mObjectCamera^-1)^T * * * Stream Data: * * iv_position Vertex coordinate * iv_color Vertex Color * iv_normal Vertex normal * iv_uv Vertex texture coordinate * * **/ namespace org.budnhead.graphics { public class ShaderProgram { Shader vertexShader; Shader fragmentShader; int id; int nm_Object, nm_Camera, nm_Projection, nm_ObjectCamera, nm_ObjectCameraIT, nm_Scene; public ShaderProgram(Shader vertexShader, Shader fragmentShader) { init(vertexShader, fragmentShader); } public ShaderProgram(String vertexShader, String fragmentShader) { init( ResourceLibrary.getResource(vertexShader), ResourceLibrary.getResource(fragmentShader) ); } public ShaderProgram(Stream vertexShader, Stream fragmentShader) { init( new Shader(ShaderType.VertexShader, new StreamReader(vertexShader).ReadToEnd()), new Shader(ShaderType.FragmentShader, new StreamReader(fragmentShader).ReadToEnd()) ); } private void init(Shader vertexShader, Shader fragmentShader){ this.vertexShader = vertexShader; this.fragmentShader = fragmentShader; this.id = GL.CreateProgram(); GL.AttachShader(this.id, this.vertexShader.ID); GL.AttachShader(this.id, this.fragmentShader.ID); GL.BindAttribLocation(this.id, 0, "iv_position"); GL.BindAttribLocation(this.id, 1, "iv_color"); GL.BindAttribLocation(this.id, 2, "iv_normal"); GL.BindAttribLocation(this.id, 3, "iv_uv"); GL.LinkProgram(this.id); Console.WriteLine("Shader Program Result: {0}", GL.GetProgramInfoLog(this.id)); nm_Object = GL.GetUniformLocation(this.ID, "mObject"); nm_Camera = GL.GetUniformLocation(this.ID, "mCamera"); nm_ObjectCamera = GL.GetUniformLocation(this.ID, "mObjectCamera"); nm_ObjectCameraIT = GL.GetUniformLocation(this.ID, "mObjectCameraIT"); nm_Projection = GL.GetUniformLocation(this.ID, "mProjection"); nm_Scene = GL.GetUniformLocation(this.ID, "mScene"); } public int ID { get { return this.id; } } public int nmObject { get { return nm_Object; } } public int nmCamera { get { return nm_Camera; } } public int nmObjectCamera { get { return nm_ObjectCamera; } } public int nmObjectCameraIT { get { return nm_ObjectCameraIT; } } public int nmProjection { get { return nm_Projection; } } public int nmScene { get { return nm_Scene; } } public void use(){ GL.UseProgram(this.id); } public void setup(Matrix4 _mObject,GLSceneOrientation scene){ Matrix4 mObject, mCamera, mObjectCamera, mObjectCameraIT, mProjection, mScene; mObject = _mObject; mCamera = scene.mCamera(); mObjectCamera = mObject * mCamera; mObjectCameraIT = mObjectCamera.Inverted(); mObjectCameraIT.Transpose(); mProjection = scene.mProjection(); mScene = mObjectCamera * mProjection; GL.UniformMatrix4(nm_Object, false, ref mObject); GL.UniformMatrix4(nm_Camera, false, ref mCamera); GL.UniformMatrix4(nm_ObjectCamera, false, ref mObjectCamera); GL.UniformMatrix4(nm_Projection, false, ref mProjection); GL.UniformMatrix4(nm_ObjectCameraIT,false, ref mObjectCameraIT); GL.UniformMatrix4(nm_Scene, false, ref mScene); } } }