-
-
Notifications
You must be signed in to change notification settings - Fork 86
/
Copy pathOpenGL.cs
217 lines (181 loc) · 8.3 KB
/
OpenGL.cs
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
using System;
using System.Runtime.InteropServices;
using OpenTK.Graphics.OpenGL;
using SFML.Graphics;
using SFML.System;
using SFML.Window;
namespace opengl
{
internal static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
private static void Main()
{
// NOTE : This is workaround to create a functioning opengl context for OpenTK (for current OpenTK version)
var gameWindow = new OpenTK.GameWindow();
// Request a 24-bits depth buffer when creating the window
var contextSettings = new ContextSettings
{
DepthBits = 24
};
// Create the main window
var window = new RenderWindow(new VideoMode((800, 600)), "SFML graphics with OpenGL", Styles.Default, State.Windowed, contextSettings);
window.SetVerticalSyncEnabled(true);
// Initialize OpenTK
// NOTE : next 2 lines are kept from old examples until we resolve proper OpenTK versioning
//Toolkit.Init();
//GraphicsContext context = new GraphicsContext(new ContextHandle(IntPtr.Zero), null);
// Setup event handlers
window.Closed += new EventHandler(OnClosed);
window.KeyPressed += new EventHandler<KeyEventArgs>(OnKeyPressed);
window.Resized += new EventHandler<SizeEventArgs>(OnResized);
// Create a sprite for the background
var background = new Sprite(new Texture("resources/background.jpg"));
// Create a text to display on top of the OpenGL object
var text = new Text(new Font("resources/sansation.ttf"), "SFML / OpenGL demo")
{
Position = new Vector2f(250, 450),
FillColor = new SFML.Graphics.Color(255, 255, 255, 170)
};
// Make the window the active target for OpenGL calls
_ = window.SetActive();
// Load an OpenGL texture.
// We could directly use a SFML.Graphics.Texture as an OpenGL texture (with its Bind() member function),
// but here we want more control on it (generate mipmaps, ...) so we create a new one
var texture = 0;
using (var image = new SFML.Graphics.Image("resources/texture.jpg"))
{
GL.GenTextures(1, out texture);
GL.BindTexture(TextureTarget.Texture2D, texture);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, (int)image.Size.X, (int)image.Size.Y, 0, PixelFormat.Rgba, PixelType.UnsignedByte, image.Pixels.ToArray());
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
}
// Enable Z-buffer read and write
GL.Enable(EnableCap.DepthTest);
GL.DepthMask(true);
GL.ClearDepth(1);
// Disable lighting
GL.Disable(EnableCap.Lighting);
// Configure the viewport (the same size as the window)
GL.Viewport(0, 0, (int)window.Size.X, (int)window.Size.Y);
// Setup a perspective projection
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
var ratio = (float)window.Size.X / window.Size.Y;
GL.Frustum(-ratio, ratio, -1, 1, 1, 500);
// Bind the texture
GL.Enable(EnableCap.Texture2D);
GL.BindTexture(TextureTarget.Texture2D, texture);
// Define a 3D cube (6 faces made of 2 triangles composed by 3 vertices)
var cube = new float[]
{
// positions // texture coordinates
-20, -20, -20, 0, 0,
-20, 20, -20, 1, 0,
-20, -20, 20, 0, 1,
-20, -20, 20, 0, 1,
-20, 20, -20, 1, 0,
-20, 20, 20, 1, 1,
20, -20, -20, 0, 0,
20, 20, -20, 1, 0,
20, -20, 20, 0, 1,
20, -20, 20, 0, 1,
20, 20, -20, 1, 0,
20, 20, 20, 1, 1,
-20, -20, -20, 0, 0,
20, -20, -20, 1, 0,
-20, -20, 20, 0, 1,
-20, -20, 20, 0, 1,
20, -20, -20, 1, 0,
20, -20, 20, 1, 1,
-20, 20, -20, 0, 0,
20, 20, -20, 1, 0,
-20, 20, 20, 0, 1,
-20, 20, 20, 0, 1,
20, 20, -20, 1, 0,
20, 20, 20, 1, 1,
-20, -20, -20, 0, 0,
20, -20, -20, 1, 0,
-20, 20, -20, 0, 1,
-20, 20, -20, 0, 1,
20, -20, -20, 1, 0,
20, 20, -20, 1, 1,
-20, -20, 20, 0, 0,
20, -20, 20, 1, 0,
-20, 20, 20, 0, 1,
-20, 20, 20, 0, 1,
20, -20, 20, 1, 0,
20, 20, 20, 1, 1
};
// Enable position and texture coordinates vertex components
GL.EnableClientState(ArrayCap.VertexArray);
GL.EnableClientState(ArrayCap.TextureCoordArray);
GL.VertexPointer(3, VertexPointerType.Float, 5 * sizeof(float), Marshal.UnsafeAddrOfPinnedArrayElement(cube, 0));
GL.TexCoordPointer(2, TexCoordPointerType.Float, 5 * sizeof(float), Marshal.UnsafeAddrOfPinnedArrayElement(cube, 3));
// Disable normal and color vertex components
GL.DisableClientState(ArrayCap.NormalArray);
GL.DisableClientState(ArrayCap.ColorArray);
var clock = new Clock();
// Start game loop
while (window.IsOpen)
{
// Process events
window.DispatchEvents();
// Clear the window
GL.Clear(ClearBufferMask.DepthBufferBit);
// Draw background
window.PushGLStates();
window.Draw(background);
window.PopGLStates();
// Clear the depth buffer
GL.Clear(ClearBufferMask.DepthBufferBit);
// We get the position of the mouse cursor, so that we can move the box accordingly
var x = (Mouse.GetPosition(window).X * 200.0F / window.Size.X) - 100.0F;
var y = (-Mouse.GetPosition(window).Y * 200.0F / window.Size.Y) + 100.0F;
// Apply some transformations
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadIdentity();
GL.Translate(x, y, -100.0F);
GL.Rotate(clock.ElapsedTime.AsSeconds() * 50, 1.0F, 0.0F, 0.0F);
GL.Rotate(clock.ElapsedTime.AsSeconds() * 30, 0.0F, 1.0F, 0.0F);
GL.Rotate(clock.ElapsedTime.AsSeconds() * 90, 0.0F, 0.0F, 1.0F);
// Draw the cube
GL.DrawArrays(OpenTK.Graphics.OpenGL.PrimitiveType.Triangles, 0, 36);
// Draw some text on top of our OpenGL object
window.PushGLStates();
window.Draw(text);
window.PopGLStates();
// Finally, display the rendered frame on screen
window.Display();
}
// Don't forget to destroy our texture
GL.DeleteTextures(1, ref texture);
}
/// <summary>
/// Function called when the window is closed
/// </summary>
private static void OnClosed(object sender, EventArgs e)
{
var window = (RenderWindow)sender;
window.Close();
}
/// <summary>
/// Function called when a key is pressed
/// </summary>
private static void OnKeyPressed(object sender, KeyEventArgs e)
{
var window = (RenderWindow)sender;
if (e.Code == Keyboard.Key.Escape)
{
window.Close();
}
}
/// <summary>
/// Function called when the window is resized
/// </summary>
private static void OnResized(object sender, SizeEventArgs e) => GL.Viewport(0, 0, (int)e.Size.X, (int)e.Size.Y);
}
}