Multi-platform .NET bindings to the Ultralight project.
1using System;
2using System.IO;
3using System.Runtime.InteropServices;
4using ImpromptuNinjas.UltralightSharp.Safe;
5using Silk.NET.Core;
6using Silk.NET.Input;
7using Silk.NET.OpenGLES;
8using Silk.NET.Windowing.Common;
9using Ultz.SuperInvoke;
10
11partial class Program {
12
13 private static readonly float[] _quadVerts = {
14 //X Y Z
15 1f, 1f, 0f,
16 1f, -1f, 0f,
17 -1f, -1f, 0f,
18 -1f, 1f, 1f
19 };
20
21 private static readonly uint[] _quadIndices = {
22 0, 1, 3,
23 1, 2, 3
24 };
25
26 private static OpenGlEsGpuDriverSite _gpuDriverSite = null!;
27
28 private static unsafe void OnLoad() {
29 Console.WriteLine($"Loading...");
30 //Getting the opengl api for drawing to the screen.
31 _gl = LibraryActivator.CreateInstance<GL>(
32 new CustomGlEsLibNameContainer().GetLibraryName(),
33 TemporarySuperInvokeClass.GetLoader(_snView.GLContext)
34 );
35
36 var glVersionInfo = _gl.GetString(StringName.Version);
37 var glVersionMajor = _gl.GetInteger(GetPName.MajorVersion);
38 if (glVersionMajor == 0) {
39 Console.WriteLine("Unable to retrieve API major version.");
40 glVersionMajor = !_automaticFallback ? _glMaj : _useOpenGl ? 3 : _majOES; // bug?
41 }
42 var glVersionMinor = _gl.GetInteger(GetPName.MinorVersion);
43 Console.WriteLine($"{(_useOpenGl?"OpenGL":"OpenGL ES")} v{glVersionMajor}.{glVersionMinor} ({glVersionInfo})");
44
45 var glVendor = _gl.GetString(StringName.Vendor);
46 var glDevice = _gl.GetString(StringName.Renderer);
47 Console.WriteLine($"{glVendor} {glDevice}");
48
49 var glShaderVersionInfo = _gl.GetString(StringName.ShadingLanguageVersion);
50 Console.WriteLine($"Shader Language: {glShaderVersionInfo}");
51
52 _gpuDriverSite = new OpenGlEsGpuDriverSite(_gl, _dbg);
53
54 var gpuDriver = _gpuDriverSite.CreateGpuDriver();
55 Ultralight.SetGpuDriver(gpuDriver);
56
57 using var cfg = new Config();
58
59 var cachePath = Path.Combine(_storagePath, "Cache");
60 cfg.SetCachePath(cachePath);
61
62 var resourcePath = Path.Combine(AsmDir, "resources");
63 cfg.SetResourcePath(resourcePath);
64
65 cfg.SetUseGpuRenderer(true);
66 cfg.SetEnableImages(true);
67 cfg.SetEnableJavaScript(false);
68
69 //cfg.SetForceRepaint(true);
70
71 _ulRenderer = new Renderer(cfg);
72 _ulSession = new Session(_ulRenderer, false, "Demo");
73 var wndSize = _snView.Size;
74 var wndWidth = (uint) wndSize.Width;
75 var wndHeight = (uint) wndSize.Height;
76 var width = (uint) (_scaleX * wndWidth);
77 var height = (uint) (_scaleY * wndHeight);
78
79 _ulView = new View(_ulRenderer, width, height, false, _ulSession);
80 _ulView.SetAddConsoleMessageCallback(ConsoleMessageCallback, default);
81
82 if (_snView is IWindow wnd)
83 wnd.Title = _useOpenGl
84 ? $"UltralightSharp - OpenGL v{glVersionMajor}.{glVersionMinor} (Silk.NET)"
85 : $"UltralightSharp - OpenGL ES v{glVersionMajor}.{glVersionMinor} (Silk.NET)";
86
87 if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) {
88 var monitors = _glfw.GetMonitors(out var monitorCount);
89 var monitorInterface = ((IWindow) _snView).Monitor;
90 var monitor = monitors[monitorInterface.Index];
91 _glfw.GetMonitorContentScale(monitor, out var xScale, out var yScale);
92 _scaleX = xScale;
93 _scaleY = yScale;
94 }
95
96 EnableDebugExtension();
97
98 _gl.Disable(EnableCap.Dither);
99 CheckGl();
100 //_gl.Disable(EnableCap.PointSmooth);
101 //CheckGl();
102 //_gl.Disable(EnableCap.LineSmooth);
103 //CheckGl();
104 //_gl.Disable(EnableCap.PolygonSmooth);
105 //CheckGl();
106 //_gl.Hint(HintTarget.PointSmoothHint, HintMode.DontCare);
107 //CheckGl();
108 //_gl.Hint(HintTarget.LineSmoothHint, HintMode.DontCare);
109 //CheckGl();
110 //_gl.Hint(HintTarget.PolygonSmoothHint, HintMode.DontCare);
111 //CheckGl();
112 //_gl.Disable(EnableCap.Multisample);
113 CheckGl();
114
115 //Vertex data, uploaded to the VBO.
116 var quadVertsLen = (uint) (_quadVerts.Length * sizeof(float));
117
118 //Index data, uploaded to the EBO.
119 var indicesSize = (uint) (_quadIndices.Length * sizeof(uint));
120
121 //Creating a vertex array.
122 _qva = _gl.GenVertexArray();
123 _gl.BindVertexArray(_qva);
124 LabelObject(ObjectIdentifier.VertexArray, _qva, "Quad VAO");
125
126 //Initializing a vertex buffer that holds the vertex data.
127 _qvb = _gl.GenBuffer(); //Creating the buffer.
128 _gl.BindBuffer(BufferTargetARB.ArrayBuffer, _qvb); //Binding the buffer.
129 LabelObject(ObjectIdentifier.Buffer, _qvb, "Quad VBO");
130 _gl.BufferData(BufferTargetARB.ArrayBuffer, quadVertsLen, new Span<float>(_quadVerts), BufferUsageARB.StaticDraw); //Setting buffer data.
131
132 //Initializing a element buffer that holds the index data.
133 _qeb = _gl.GenBuffer(); //Creating the buffer.
134 _gl.BindBuffer(BufferTargetARB.ElementArrayBuffer, _qeb); //Binding the buffer.
135 LabelObject(ObjectIdentifier.Buffer, _qeb, "Quad EBO");
136 _gl.BufferData(BufferTargetARB.ElementArrayBuffer, indicesSize, new Span<uint>(_quadIndices), BufferUsageARB.StaticDraw); //Setting buffer data.
137
138 //Creating a vertex shader.
139 var qvs = _gl.CreateShader(ShaderType.VertexShader);
140 LabelObject(ObjectIdentifier.Shader, qvs, "Quad VS");
141 _gl.ShaderSource(qvs, Utilities.LoadEmbeddedUtf8String("embedded.basic.vert.glsl"));
142 _gl.CompileShader(qvs);
143 CheckGl();
144 _gl.GetShader(qvs, ShaderParameterName.CompileStatus, out var qvsCompileStatus);
145
146 //Checking the shader for compilation errors.
147 var qvsLog = _gl.GetShaderInfoLog(qvs);
148 var qvsLogEmpty = string.IsNullOrWhiteSpace(qvsLog);
149 var qvsCompileSuccess = qvsCompileStatus == (int) GLEnum.True;
150 if (!qvsCompileSuccess || !qvsLogEmpty) {
151 (qvsCompileSuccess ? Console.Out : Console.Error).WriteLine($"{(qvsCompileSuccess ? "Messages" : "Errors")} compiling quad vertex shader\n{qvsLog}");
152 if (!qvsCompileSuccess) {
153 Console.Error.Flush();
154 //Debugger.Break();
155 }
156 }
157
158 CheckGl();
159
160 //Creating a fragment shader.
161 var qfs = _gl.CreateShader(ShaderType.FragmentShader);
162 LabelObject(ObjectIdentifier.Shader, qfs, "Quad FS");
163 _gl.ShaderSource(qfs, Utilities.LoadEmbeddedUtf8String("embedded.basic.frag.glsl"));
164 _gl.CompileShader(qfs);
165 CheckGl();
166 _gl.GetShader(qfs, ShaderParameterName.CompileStatus, out var qfsCompileStatus);
167
168 //Checking the shader for compilation errors.
169 var qfsLog = _gl.GetShaderInfoLog(qfs);
170 var qfsLogEmpty = string.IsNullOrWhiteSpace(qfsLog);
171 var qfsCompileSuccess = qfsCompileStatus == (int) GLEnum.True;
172 if (!qfsCompileSuccess || !qfsLogEmpty) {
173 (qfsCompileSuccess ? Console.Out : Console.Error).WriteLine($"{(qfsCompileSuccess ? "Messages" : "Errors")} compiling quad fragment shader\n{qfsLog}");
174 if (!qfsCompileSuccess) {
175 Console.Error.Flush();
176 //Debugger.Break();
177 }
178 }
179
180 CheckGl();
181
182 //Combining the shaders under one shader program.
183 _qpg = _gl.CreateProgram();
184 LabelObject(ObjectIdentifier.Program, _qpg, "Quad Program");
185 _gl.AttachShader(_qpg, qvs);
186 _gl.AttachShader(_qpg, qfs);
187 _gl.BindAttribLocation(_qpg, 0, "vPos");
188 CheckGl();
189 _gl.EnableVertexAttribArray(0);
190 CheckGl();
191 _gl.LinkProgram(_qpg);
192 CheckGl();
193 _gl.GetProgram(_qpg, ProgramPropertyARB.LinkStatus, out var qpgLinkStatus);
194
195 //Checking the linking for errors.
196 var qpgLog = _gl.GetProgramInfoLog(_qpg);
197 var qpgLogEmpty = string.IsNullOrWhiteSpace(qpgLog);
198 var qpgLinkSuccess = qpgLinkStatus == (int) GLEnum.True;
199 if (!qpgLinkSuccess || !qpgLogEmpty)
200 Console.WriteLine($"{(qpgLinkSuccess ? "Messages" : "Errors")} linking quad shader program:\n{qpgLog}");
201 CheckGl();
202 _gl.ValidateProgram(_qpg);
203 CheckGl();
204
205 _gl.UseProgram(_qpg);
206 var vPos = (uint) _gl.GetAttribLocation(_qpg, "vPos");
207 CheckGl();
208 _gl.VertexAttribPointer(vPos,
209 3, VertexAttribPointerType.Float, false, 0, (void*) 0);
210 CheckGl();
211
212 //Delete the no longer useful individual shaders;
213 _gl.DetachShader(_qpg, qvs);
214 _gl.DetachShader(_qpg, qfs);
215 _gl.DeleteShader(qvs);
216 _gl.DeleteShader(qfs);
217
218 _gpuDriverSite.InitializeShaders();
219
220 var input = _snView.CreateInput();
221 foreach (var kb in input.Keyboards)
222 kb.KeyDown += KeyDown;
223
224 Console.WriteLine("Loading index.html");
225 _ulView.LoadUrl("file:///index.html");
226 }
227
228}