Содержание блога
Программа написана на C# + OpenGL с использованием библиотеки OpenTK. Рисует одну точку красного цвета, размером 10 пикселей с координатами (0.8, 0, 0). Координаты и размер задаются в вершинном шейдере, а цвет задаётся в фрагментном шейдере.
Можете скачать и запустить проект, должно работать в VS2012-VS2015: PointWithCustomSizeAndColour.zip
vShader.glsl (вершинный шейдер)
| glSlang | 1
2
3
4
5
6
7
| #version 330
void main()
{
gl_Position = vec4(0.8, 0.0, 0.0, 1.0);
gl_PointSize = 10.0;
} |
|
fShader.glsl (фрагментный шейдер)
| glSlang | 1
2
3
4
5
6
7
8
| #version 330
out vec4 fragColor;
void main()
{
fragColor = vec4(1.0, 0.0, 0.0, 1.0);
} |
|
Program.cs
| C# | 1
2
3
4
5
6
7
8
9
10
11
12
13
| namespace PointWithCustomSizeAndColour
{
class Program
{
static void Main(string[] args)
{
using (MainWindow mainWindow = new MainWindow())
{
mainWindow.Run(30);
}
}
}
} |
|
MainWindow.cs
| C# | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
| using System;
using System.Drawing;
using OpenTK;
using OpenTK.Graphics.OpenGL;
using System.IO;
namespace PointWithCustomSizeAndColour
{
class MainWindow : GameWindow
{
string vShaderSource = null;
string fShaderSource = null;
bool canDraw = false;
string infoFileName = "info.txt";
int program;
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
Title = "Point With Custom Size And Colour";
Width = 512;
Height = 512;
// Load shaders from files
ShaderLoader.LoadShader(infoFileName, "./Shaders/vShader.glsl", out vShaderSource);
ShaderLoader.LoadShader(infoFileName, "./Shaders/fShader.glsl", out fShaderSource);
if (vShaderSource == null || fShaderSource == null)
{
File.AppendAllText(infoFileName, "Failed to load shaders from files" + Environment.NewLine);
return;
}
// Initialize shaders
if (!ShaderLoader.InitShaders(vShaderSource, fShaderSource, out program))
{
File.AppendAllText(infoFileName, "Failed to initialize the shaders" + Environment.NewLine);
return;
}
// Specify the color for clearing
GL.ClearColor(Color.Black);
GL.Enable(EnableCap.ProgramPointSize);
canDraw = true;
}
protected override void OnRenderFrame(FrameEventArgs e)
{
base.OnRenderFrame(e);
GL.Viewport(0, 0, Width, Height);
if (!canDraw) return;
GL.Clear(ClearBufferMask.ColorBufferBit);
// Draw a point
GL.DrawArrays(PrimitiveType.Points, 0, 1);
GL.Flush();
SwapBuffers();
}
}
} |
|
ShaderLoader.cs
| C# | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
| using System.IO;
using OpenTK.Graphics.OpenGL;
using System;
namespace PointWithCustomSizeAndColour
{
class ShaderLoader
{
private static string infoFileName = null;
///<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 vShader, string fShader, out int program)
{
program = CreateProgram(vShader, fShader);
if (program == 0)
{
File.AppendAllText(infoFileName, "Failed to create program" + Environment.NewLine);
return false;
}
GL.UseProgram(program);
return true;
}
///<summary>
///Load a shader from a file
///</summary>
///<param name="infoFileName">a file name for errors</param>
///<param name="fileName">a file name to a shader</param>
///<param name="shaderSource">a shader source string</param>
public static void LoadShader(string infoFileName, string fileName, out string shaderSource)
{
ShaderLoader.infoFileName = infoFileName;
if (File.Exists(infoFileName))
{
// Clear File
File.WriteAllText(infoFileName, "");
}
shaderSource = null;
using (StreamReader sr = new StreamReader(fileName))
{
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));
File.AppendAllText(infoFileName, 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)
{
File.AppendAllText(infoFileName, "Unable to create shader" + Environment.NewLine);
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}" + Environment.NewLine, shaderType.ToString(), GL.GetShaderInfoLog(shader));
File.AppendAllText(infoFileName, errorString);
GL.DeleteShader(shader);
return 0;
}
return shader;
}
}
} |
|
|