I did manage to draw a red triangle, but when I tried to pass data from vertex Shader to Fragment Shader. My computer screen is all black, and after a few second a windows popup a message “Display driver stopped responding and has recovered”. The program didn’t generate any error.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using SharpGL;
using SharpGL.Shaders;
namespace Vector
{
/// <summary>
/// The main form class.
/// </summary>
public partial class SharpGLForm : Form
{
/// <summary>
/// Initializes a new instance of the <see cref="SharpGLForm"/> class.
/// </summary>
public SharpGLForm()
{
InitializeComponent();
}
/// <summary>
/// Handles the OpenGLDraw event of the openGLControl control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="RenderEventArgs"/> instance containing the event data.</param>
private void openGLControl_OpenGLDraw(object sender, RenderEventArgs e)
{
}
/// <summary>
/// Handles the OpenGLInitialized event of the openGLControl control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private void openGLControl_OpenGLInitialized(object sender, EventArgs e)
{
// TODO: Initialise OpenGL here.
// Get the OpenGL object.
OpenGL gl = openGLControl.OpenGL;
// Set the clear color.
gl.ClearColor(0, 0, 0, 0);
}
/// <summary>
/// Handles the Resized event of the openGLControl control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private void openGLControl_Resized(object sender, EventArgs e)
{
OpenGL gl = openGLControl.OpenGL;
Shader sd = new Shader(gl);
gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);
// Vertex Shader
string vertexShaderSource = System.IO.File.ReadAllText("shader.vert");
string fragmentShaderSource = System.IO.File.ReadAllText("shader.frag");
uint shaderProgram = sd.Loader(vertexShaderSource, fragmentShaderSource);
gl.UseProgram(shaderProgram);
float[] vertices = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
uint[] VBO = new uint[1];
gl.GenBuffers(1, VBO);
gl.BindBuffer(OpenGL.GL_ARRAY_BUFFER, VBO[0]);
gl.BufferData(OpenGL.GL_ARRAY_BUFFER, vertices, OpenGL.GL_STATIC_DRAW);
gl.VertexAttribPointer(0, 3, OpenGL.GL_FLOAT, false, 12, IntPtr.Zero);
gl.EnableVertexAttribArray(0);
gl.DrawArrays(OpenGL.GL_TRIANGLES, 0, 3);
}
}
class Shader
{
private uint vertexShader;
private uint fragmentShader;
private uint shaderProgram { get; set; }
private OpenGL gl;
public Shader(OpenGL gl)
{
this.gl = gl;
}
public uint Loader(string vertexShaderSource, string fragmentShaderSource)
{
// Vertex Shader
vertexShader = gl.CreateShader(OpenGL.GL_VERTEX_SHADER);
gl.ShaderSource(vertexShader, vertexShaderSource);
gl.CompileShader(vertexShader);
if (GetCompileStatus(gl, vertexShader) == false)
{
throw new ShaderCompilationException(string.Format("Failed to compile shader with ID {0}.", vertexShader), GetCompileInfoLog(vertexShader));
}
// Fragment Shader
fragmentShader = gl.CreateShader(OpenGL.GL_FRAGMENT_SHADER);
gl.ShaderSource(fragmentShader, fragmentShaderSource);
gl.CompileShader(fragmentShader);
if (GetCompileStatus(gl, fragmentShader) == false)
{
throw new ShaderCompilationException(string.Format("Failed to compile shader with ID {0}.", fragmentShader), GetCompileInfoLog(fragmentShader));
}
// Link shaders
shaderProgram = gl.CreateProgram();
gl.AttachShader(shaderProgram, vertexShader);
gl.AttachShader(shaderProgram, fragmentShader);
gl.LinkProgram(shaderProgram);
if (GetLinkStatus(gl) == false)
{
throw new ShaderCompilationException(string.Format("Failed to link shader program with ID {0}.", shaderProgram), GetLinkInfoLog(gl));
}
gl.DeleteShader(vertexShader);
gl.DeleteShader(fragmentShader);
return shaderProgram;
}
private string GetCompileInfoLog(uint shaderObject)
{
// Get the info log length.
int[] infoLength = new int[] { 0 };
gl.GetShader(shaderObject, OpenGL.GL_INFO_LOG_LENGTH, infoLength);
int bufSize = infoLength[0];
// Get the compile info.
StringBuilder il = new StringBuilder(bufSize);
gl.GetShaderInfoLog(shaderObject, bufSize, IntPtr.Zero, il);
return il.ToString();
}
private bool GetCompileStatus(OpenGL gl, uint shaderObject)
{
int[] parameters = new int[] { 0 };
gl.GetShader(shaderObject, OpenGL.GL_COMPILE_STATUS, parameters);
return parameters[0] == OpenGL.GL_TRUE;
}
public string GetLinkInfoLog(OpenGL gl)
{
// Get the info log length.
int[] infoLength = new int[] { 0 };
gl.GetProgram(shaderProgram, OpenGL.GL_INFO_LOG_LENGTH, infoLength);
int bufSize = infoLength[0];
// Get the compile info.
StringBuilder il = new StringBuilder(bufSize);
gl.GetProgramInfoLog(shaderProgram, bufSize, IntPtr.Zero, il);
return il.ToString();
}
public bool GetLinkStatus(OpenGL gl)
{
int[] parameters = new int[] { 0 };
gl.GetProgram(shaderProgram, OpenGL.GL_LINK_STATUS, parameters);
return parameters[0] == OpenGL.GL_TRUE;
}
}
}
I can draw a red triangle with this shader code
VertexShader
#version 330 core
layout(location = 0) in vec3 position;
void main(){
gl_Position = vec4(position ,1);
}
Fragment Shader
#version 330 core
out vec4 color;
void main()
{
color = vec4(1.0f, 0.0f, 0.0f, 1.0f);
}
but I can not with this code
VertexShader
#version 330 core
layout(location = 0) in vec3 position;
out vec4 vcolor;
void main(){
gl_Position = vec4(position ,1);
vcolor = vec4(1.0f, 0.0f, 0.0f, 1.0f);
}
Fragment Shader
#version 330 core
in vec4 vcolor;
out vec4 color;
void main()
{
color = vcolor;
}