OpenTK Uniform Blocks

C# Code:
using System;
using System.IO;
using System.Windows.Forms;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;

namespace OpenTKTest {
 public class GLForm : Form {
  protected static GLControl cglGLView;
  protected static Label clblLog;
  protected static bool cbGLReady;
  protected static uint[] cauiVBOIDs;
  protected static int ciProgramID;

  protected const int UNIFORMBINDING = 15;
  protected const int ATTRIBLOCATION = 10;
  protected const int ATTRIBCOLORS = 15;

  public static void Main() {
   GLForm frmGL;

   //Create the form and give it control
   frmGL = new GLForm();
   Application.Run(frmGL);

   return;
  }

   public GLForm() {
   //Initialize Log label
   clblLog = new Label();

   clblLog.Top = 485;
   clblLog.Left = 0;
   clblLog.Width = 800;
   clblLog.Height = 125;
   clblLog.Text = "";

   Controls.Add(clblLog);

   cbGLReady = false;

   cglGLView = new GLControl();

   //Position and configure the controls
   cglGLView.Top = 0;
   cglGLView.Left = 0;
   cglGLView.Width = 640;
   cglGLView.Height = 480;

   //Define callbacks for the controls
   cglGLView.Load += new EventHandler(GLViewLoading);  
   cglGLView.Paint += new PaintEventHandler(GLViewPainting); 
   Controls.Add(cglGLView);

   //Position and configure the form
   this.Width = 775;
   this.Height = 670;
   this.FormBorderStyle = FormBorderStyle.FixedSingle;

   return;
  }

  public int WriteLog(string strText) {
   string strCurrText, strNewText;
   string[] astrList;
   int iCtr;

   strCurrText = clblLog.Text;
   astrList = strCurrText.Split('\n');

   if (astrList.Length > 9) { //log shows too man lines, truncate
    strCurrText = "";
    for (iCtr = 0; iCtr < 10; iCtr++) {
     strCurrText = astrList[astrList.Length - iCtr - 1] + "\n" + strCurrText;
    }
   } else { //Array has space, just add line
    strCurrText = clblLog.Text;
   }

   strNewText = strCurrText + "\n" + strText;

   //Remove extraneous new lines
   strNewText = strNewText.Replace("\n\n", "\n");
   while (strNewText.Substring(0, 1) == "\n") {
    strNewText = strNewText.Substring(1, strNewText.Length - 2);
   }

   //Put the log in the label
   clblLog.Text = strNewText;
   return 0;
   }

  private void GLViewLoading(object oSender, EventArgs eaArgs) {
   //The GLControl is now loading
   Matrix4 pmatMatrix;
   float fAspect;
   Vector3[] av3Triangle;
   float[] afUniform;

   WriteLog("GLControl: Loading...");
   WriteLog("OpenGL Version: " + GL.GetString(StringName.Version));

   //Setup GL
   GL.ClearColor(0.0f, 0.0f, 0.2f, 0.0f);
   GL.Enable(EnableCap.DepthTest);

   //Setup the viewport
   GL.Viewport(0, 0, cglGLView.Width, cglGLView.Height);
   fAspect = cglGLView.Width / cglGLView.Height;
   pmatMatrix = Matrix4.CreatePerspectiveFieldOfView(MathHelper.PiOver4, fAspect, 0.1f, 100.0f);
   GL.MatrixMode(MatrixMode.Projection);
   GL.LoadMatrix(ref pmatMatrix);
   GL.MatrixMode(MatrixMode.Modelview);

   //Create video memory buffers
   cauiVBOIDs = new uint[2];
   GL.GenBuffers(2, cauiVBOIDs);

   //Setup vertexes
   av3Triangle = new Vector3[6];

   av3Triangle[0].X = 2.5f;
   av3Triangle[0].Y = -1.0f;
   av3Triangle[0].Z = -8.0f;
   av3Triangle[1].X = 1.5f;
   av3Triangle[1].Y = 1.0f;
   av3Triangle[1].Z = -8.0f;
   av3Triangle[2].X = 0.5f;
   av3Triangle[2].Y = -1.0f;
   av3Triangle[2].Z = -8.0f;

   av3Triangle[3].X = -2.5f;
   av3Triangle[3].Y = -1.0f;
   av3Triangle[3].Z = -8.0f;
   av3Triangle[4].X = -1.5f;
   av3Triangle[4].Y = 1.0f;
   av3Triangle[4].Z = -8.0f;
   av3Triangle[5].X = -0.5f;
   av3Triangle[5].Y = -1.0f;
   av3Triangle[5].Z = -8.0f;

   //Setup our uniform data
   afUniform = new float[20];

   afUniform[0] = pmatMatrix.Row0.X;
   afUniform[1] = pmatMatrix.Row1.X;
   afUniform[2] = pmatMatrix.Row2.X;
   afUniform[3] = pmatMatrix.Row3.X;
   afUniform[4] = pmatMatrix.Row0.Y;
   afUniform[5] = pmatMatrix.Row1.Y;
   afUniform[6] = pmatMatrix.Row2.Y;
   afUniform[7] = pmatMatrix.Row3.Y;
   afUniform[8] = pmatMatrix.Row0.Z;
   afUniform[9] = pmatMatrix.Row1.Z;
   afUniform[10] = pmatMatrix.Row2.Z;
   afUniform[11] = pmatMatrix.Row3.Z;
   afUniform[12] = pmatMatrix.Row0.W;
   afUniform[13] = pmatMatrix.Row1.W;
   afUniform[14] = pmatMatrix.Row2.W;
   afUniform[15] = pmatMatrix.Row3.W;

   afUniform[16] = 0.5f;
   afUniform[17] = 0.5f;
   afUniform[18] = 1.0f;
   afUniform[19] = 1.0f;

   //Copy the vertex data into video memory
   GL.BindBuffer(BufferTarget.ArrayBuffer, cauiVBOIDs[0]);
   GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(av3Triangle.Length * Vector3.SizeInBytes), av3Triangle, BufferUsageHint.StaticDraw);

   GL.BindBuffer(BufferTarget.UniformBuffer, cauiVBOIDs[1]);
   GL.BufferData(BufferTarget.UniformBuffer, (IntPtr)(afUniform.Length * sizeof(float)), afUniform, BufferUsageHint.StaticDraw);
   GL.BindBufferBase(BufferTarget.UniformBuffer, UNIFORMBINDING, cauiVBOIDs[1]);

   //Load Shaders
   ciProgramID = LoadShaders("Vertex.glsl", "Fragment.glsl");

   //Done setting up GL for use
   cbGLReady = true;

   return;
  }

   private void GLViewPainting(object oSender, EventArgs eaArgs) {
   if (cbGLReady == false)  {//Control is not loaded, do nothing
    return;
   }
   WriteLog("Painting...");

   //Specify Shader
   GL.UseProgram(ciProgramID);

   //Clear the GL View
   GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
   GL.MatrixMode(MatrixMode.Modelview);

   GL.BindBuffer(BufferTarget.ArrayBuffer, cauiVBOIDs[0]);

   GL.EnableVertexAttribArray(0);
   GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, Vector3.SizeInBytes, 0);
   GL.DrawArrays(PrimitiveType.Triangles, 0, 6);
   GL.DisableVertexAttribArray(0);

   //Drawing complete
   cglGLView.SwapBuffers();

   return;
   }

  private int LoadShaders(string strVertexFile, string strFragFile) {
   int iProgram, iVertShader, iFragShader, iUniformID;

   //Create vertex shader
   iVertShader = GL.CreateShader(ShaderType.VertexShader);
   using (StreamReader srShader = new StreamReader(strVertexFile)) {
    GL.ShaderSource(iVertShader, srShader.ReadToEnd());
   }
   GL.CompileShader(iVertShader);
   WriteLog("Vertex Shader: " + GL.GetShaderInfoLog(iVertShader));

   //Create fragment shader
   iFragShader = GL.CreateShader(ShaderType.FragmentShader);
   using (StreamReader srShader = new StreamReader(strFragFile)) {
    GL.ShaderSource(iFragShader, srShader.ReadToEnd());
   }
   GL.CompileShader(iFragShader);
   WriteLog("Fragment Shader: " + GL.GetShaderInfoLog(iFragShader));

   //Build GL program
   iProgram = GL.CreateProgram();
   GL.AttachShader(iProgram, iVertShader);
   GL.AttachShader(iProgram, iFragShader);

   //Link the shading program
   GL.LinkProgram(iProgram);
   WriteLog("Shader Link: " + GL.GetProgramInfoLog(iProgram));

   //Define Uniform block
   iUniformID = GL.GetUniformBlockIndex(iProgram, "staticdata");
   GL.UniformBlockBinding(iProgram, iUniformID, UNIFORMBINDING);

   //Cleanup
   GL.DeleteShader(iVertShader);
   GL.DeleteShader(iFragShader);

   return iProgram;
  }
 }
}


Vertex Shader, GLSL Code:
#version 130
#extension GL_ARB_uniform_buffer_object : enable

uniform staticdata {
 mat4 m4Projection;
 vec4 v4Color;
};

void main() {
 gl_Position = gl_Vertex * m4Projection;
}


Fragment Shader, GLSL Code:
#version 130
#extension GL_ARB_uniform_buffer_object : enable

uniform staticdata {
 mat4 m4Projection;
 vec4 v4Color;
};

void main() {
 gl_FragColor = v4Color;
}

No comments:

Post a Comment