budnhead/org.budnhead/graphics/ShaderProgram.cs

198 lines
4.4 KiB
C#

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<Shader>(vertexShader),
ResourceLibrary.getResource<Shader>(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);
}
}
}