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