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