PDA

View Full Version : OpenGL for Windows forms



Omar Bsoul
03-03-2017, 03:14 PM
Hello,
I'm working on some sort of level editor on C#, so i've been using Tao framework to add OpenGL capability to C#, and now I want to render the OpenGL window into my windows forms,
Any help please?

tusharpandey13
03-03-2017, 08:28 PM
Use OpenTK. It has a glcontrol control which can host gl.

8Observer8
03-04-2017, 05:52 AM
I made the simple examples for you to show how to use OpenTK GLControl in WinForms, WPF and Console GameWindow projects.

You can open and run it in VS2012-VS2015. I use modern OpenGL 3.3 and .NET 2.0 for WinForms and .NET 3.0 for WPF for running apps on Windows XP.


TriangleInOpenTkWinForms.zip (https://dl.dropboxusercontent.com/s/lxrtn85zjy0coin/TriangleInOpenTkWinForms.zip)
TriangleInOpenTkWPF.zip (https://dl.dropboxusercontent.com/s/e55bso03t3fgfsw/TriangleInOpenTkWPF.zip)
TriangleInOpenTkConsoleProjectGameWindow.zip (https://dl.dropboxusercontent.com/s/pzl5ibqs1e2y9ak/TriangleInOpenTkConsoleProjectGameWindow.zip)
TriangleInWebGL (https://jsfiddle.net/8Observer8/fk6zszjx/) (the same code)


TriangleInOpenTkConsoleProjectGameWindow Project:

VertexShader.glsl


#version 330

in vec4 a_Position;

void main()
{
gl_Position = a_Position;
}


FragmentShader.glsl


#version 330

out vec4 fragColor;

void main()
{
fragColor = vec4(0.0, 1.0, 1.0, 1.0);
}


Program.cs


namespace TriangleInOpenTkConsoleProjectGameWindow
{
class Program
{
static void Main(string[] args)
{
using (var mainWindow = new MainWindow())
{
mainWindow.Run(30);
}
}
}
}


MainWindow.cs


using System;
using System.Drawing;
using OpenTK;
using OpenTK.Graphics.OpenGL;
using Utils;

namespace TriangleInOpenTkConsoleProjectGameWindow
{
class MainWindow : GameWindow
{
private bool canDraw = false;
private int program;
private int nVertices;

protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);

Title = "Triangle";
Width = 400;
Height = 400;

// Load shaders from files
string vShaderSource = null;
string fShaderSource = null;
ShaderLoader.LoadShader("./Shaders/VertexShader.glsl", out vShaderSource);
ShaderLoader.LoadShader("./Shaders/FragmentShader.glsl", out fShaderSource);
if (vShaderSource == null || fShaderSource == null)
{
Logger.Append("Failed load shaders from files");
return;
}

// Initialize the shaders
if (!ShaderLoader.InitShaders(vShaderSource, fShaderSource, out program))
{
Logger.Append("Failed to initialize the shaders");
return;
}

// Write the positions of vertices to a vertex shader
nVertices = InitVertexBuffers();
if (nVertices <= 0)
{
Logger.Append("Failed to write the positions of vertices to a vertex shader");
return;
}

// Specify the color for clearing
GL.ClearColor(Color.DarkSlateBlue);

canDraw = true;
}

private int InitVertexBuffers()
{
float[] vertices = new float[] { 0f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f };

// Create a buffer object
int vertexBuffer;
GL.GenBuffers(1, out vertexBuffer);

// Bind the buffer object to target
GL.BindBuffer(BufferTarget.ArrayBuffer, vertexBuffer);

// Write data into the buffer object
GL.BufferData(BufferTarget.ArrayBuffer, vertices.Length * sizeof(float), vertices, BufferUsageHint.StaticDraw);

// Get the storage location of a_Position
int a_Position = GL.GetAttribLocation(program, "a_Position");
if (a_Position < 0)
{
Logger.Append("Failed to get the storage location of a_Position");
return -1;
}

// Assign the buffer object to a_Position variable
GL.VertexAttribPointer(a_Position, 2, VertexAttribPointerType.Float, false, 0, 0);

// Enable the assignment to a_Position variable
GL.EnableVertexAttribArray(a_Position);

return vertices.Length / 2;
}

protected override void OnRenderFrame(FrameEventArgs e)
{
base.OnRenderFrame(e);

GL.Viewport(0, 0, Width, Height);

// Clear the render canvas with the current color
GL.Clear(ClearBufferMask.ColorBufferBit);

if (canDraw)
{
// Draw a triangle
GL.DrawArrays(PrimitiveType.Triangles, 0, nVertices);
}

GL.Flush();
SwapBuffers();
}
}
}


Utils.cs


using System;
using OpenTK.Graphics.OpenGL;
using System.IO;

namespace Utils
{
public class ShaderLoader
{
///<summary>
///Create a program object and make current
///</summary>
///<param name="vShader">a vertex shader program</param>
///<param name="fShader">a fragment shader program</param>
///<param name="program">created program</param>
///<returns>
///return true, if the program object was created and successfully made current
///</returns>
public static bool InitShaders(string vShaderSource, string fShaderSource, out int program)
{
program = CreateProgram(vShaderSource, fShaderSource);
if (program == 0)
{
Logger.Append("Failed to create program");
return false;
}

GL.UseProgram(program);

return true;
}

///<summary>
///Load a shader from a file
///</summary>
///<param name="errorOutputFileName">a file name for error messages</param>
///<param name="fileName">a file name to a shader</param>
///<param name="shaderSource">a shader source string</param>
public static void LoadShader(string shaderFileName, out string shaderSource)
{
if (File.Exists(Logger.logFileName))
{
// Clear File
File.WriteAllText(Logger.logFileName, "");
}

shaderSource = null;

using (StreamReader sr = new StreamReader(shaderFileName))
{
shaderSource = sr.ReadToEnd();
}
}

private static int CreateProgram(string vShader, string fShader)
{
// Create shader object
int vertexShader = LoadShader(ShaderType.VertexShader, vShader);
int fragmentShader = LoadShader(ShaderType.FragmentShader, fShader);
if (vertexShader == 0 || fragmentShader == 0)
{
return 0;
}

// Create a program object
int program = GL.CreateProgram();
if (program == 0)
{
return 0;
}

// Attach the shader objects
GL.AttachShader(program, vertexShader);
GL.AttachShader(program, fragmentShader);

// Link the program object
GL.LinkProgram(program);

// Check the result of linking
int status;
GL.GetProgram(program, GetProgramParameterName.LinkStatus, out status);
if (status == 0)
{
string errorString = string.Format("Failed to link program: {0}" + Environment.NewLine, GL.GetProgramInfoLog(program));
Logger.Append(errorString);
GL.DeleteProgram(program);
GL.DeleteShader(vertexShader);
GL.DeleteShader(fragmentShader);
return 0;
}

return program;
}

private static int LoadShader(ShaderType shaderType, string shaderSource)
{
// Create shader object
int shader = GL.CreateShader(shaderType);
if (shader == 0)
{
Logger.Append("Unable to create shader");
return 0;
}

// Set the shader program
GL.ShaderSource(shader, shaderSource);

// Compile the shader
GL.CompileShader(shader);

// Check the result of compilation
int status;
GL.GetShader(shader, ShaderParameter.CompileStatus, out status);
if (status == 0)
{
string errorString = string.Format("Failed to compile {0} shader: {1}", shaderType.ToString(), GL.GetShaderInfoLog(shader));
Logger.Append(errorString);
GL.DeleteShader(shader);
return 0;
}

return shader;
}
}

public class Logger
{
public static string logFileName = "info.txt";

/// <summary>
/// Write a message to a log file
/// </summary>
/// <param name="message">a message that will append to a log file</param>
public static void Append(string message)
{
File.AppendAllText(logFileName, message + Environment.NewLine);
}
}
}

Omar Bsoul
03-05-2017, 07:24 AM
Use OpenTK. It has a glcontrol control which can host gl.

Thank you I will try it.