From 94b04c02ca14f8e6611e895163c09fd84fa6bf5d Mon Sep 17 00:00:00 2001 From: "Stefanos A." Date: Tue, 17 Dec 2013 11:39:47 +0100 Subject: [PATCH 1/5] Marshal strings as UTF8 (affects #18) Starting with OpenGL 4.2, strings passed to GL.ShaderSource are allowed to contain multi-byte characters in comments (issue #18). This patch modifies the marshaling code to use UTF8.GetBytes in order to marshal strings, instead of Marshal.StringToHGlobalAnsi(). --- Source/Generator.Rewrite/Program.cs | 8 ++-- Source/OpenTK/BindingsBase.cs | 64 ++++++++++++++++++++++++----- 2 files changed, 58 insertions(+), 14 deletions(-) diff --git a/Source/Generator.Rewrite/Program.cs b/Source/Generator.Rewrite/Program.cs index b6d5189e..47531f09 100644 --- a/Source/Generator.Rewrite/Program.cs +++ b/Source/Generator.Rewrite/Program.cs @@ -371,10 +371,10 @@ namespace OpenTK.Rewrite static void EmitStringParameter(MethodDefinition wrapper, TypeReference p, MethodBody body, ILProcessor il) { // string marshaling: - // IntPtr ptr = Marshal.StringToHGlobalAnsi(str); + // IntPtr ptr = MarshalStringToPtr(str); // try { calli } // finally { Marshal.FreeHGlobal(ptr); } - var marshal_str_to_ptr = wrapper.Module.Import(TypeMarshal.Methods.First(m => m.Name == "StringToHGlobalAnsi")); + var marshal_str_to_ptr = wrapper.Module.Import(TypeBindingsBase.Methods.First(m => m.Name == "MarshalStringToPtr")); // IntPtr ptr; var variable_name = p.Name + "_string_ptr"; @@ -396,9 +396,9 @@ namespace OpenTK.Rewrite var p = wrapper.Parameters[i].ParameterType; if (p.Name == "String" && !p.IsArray) { - var free = wrapper.Module.Import(TypeMarshal.Methods.First(m => m.Name == "FreeHGlobal")); + var free = wrapper.Module.Import(TypeBindingsBase.Methods.First(m => m.Name == "FreeStringPtr")); - // Marshal.FreeHGlobal(ptr) + // FreeStringPtr(ptr) var variable_name = p.Name + "_string_ptr"; var v = body.Variables.First(m => m.Name == variable_name); il.Emit(OpCodes.Ldloc, v.Index); diff --git a/Source/OpenTK/BindingsBase.cs b/Source/OpenTK/BindingsBase.cs index 36d421fe..d62d553e 100644 --- a/Source/OpenTK/BindingsBase.cs +++ b/Source/OpenTK/BindingsBase.cs @@ -145,7 +145,57 @@ namespace OpenTK } /// - /// Marshals a string array to unmanaged memory by calling + /// Marshal a System.String to unmanaged memory. + /// The resulting string is encoded in UTF-8 and must be freed + /// with FreeStringPtr. + /// + /// The System.String to marshal. + /// + /// An unmanaged pointer containing the marshalled string. + /// This pointer must be freed with FreeStringPtr + /// + protected static IntPtr MarshalStringToPtr(string str) + { + if (String.IsNullOrEmpty(str)) + { + return IntPtr.Zero; + } + + // Allocate a buffer big enough to hold the marshalled string. + // We use GetMaxByteCount() as it is faster than GetByteCount(). + // The downside is that it may allocate up to 3x more memory than + // strictly necessary. + int max_count = Encoding.UTF8.GetMaxByteCount(str.Length) + 1; + IntPtr ptr = Marshal.AllocHGlobal(max_count); + if (ptr == IntPtr.Zero) + { + throw new OutOfMemoryException(); + } + + // Pin the managed string and convert it to UTF-8 using + // the pointer overload of System.Encoding.UTF8.GetBytes(). + unsafe + { + fixed (char* pstr = str) + { + int actual_count = Encoding.UTF8.GetBytes(pstr, str.Length, (byte*)ptr, max_count); + Marshal.WriteByte(ptr, actual_count, 0); // Append '\0' at the end of the string + return ptr; + } + } + } + + /// + /// Frees a marshalled string that allocated by MarshalStringToPtr. + /// + /// An unmanaged pointer allocated with MarshalStringToPtr + protected static void FreeStringPtr(IntPtr ptr) + { + Marshal.FreeHGlobal(ptr); + } + + /// + /// Marshals a System.String array to unmanaged memory by calling /// Marshal.AllocHGlobal for each element. /// /// An unmanaged pointer to an array of null-terminated strings @@ -163,12 +213,7 @@ namespace OpenTK for (int i = 0; i < str_array.Length; i++) { - IntPtr str = Marshal.StringToHGlobalAnsi(str_array[i]); - if (str == IntPtr.Zero) - { - throw new OutOfMemoryException(); - } - + IntPtr str = MarshalStringToPtr(str_array[i]); Marshal.WriteIntPtr(ptr, i * IntPtr.Size, str); } } @@ -176,10 +221,9 @@ namespace OpenTK } /// - /// Frees a string array that has previously been - /// marshalled by MarshalStringArrayToPtr. + /// Frees a marshalled string that allocated by MarshalStringArrayToPtr. /// - /// An unmanaged pointer allocated by MarshalStringArrayToPtr + /// An unmanaged pointer allocated with MarshalStringArrayToPtr /// The length of the string array. protected static void FreeStringArrayPtr(IntPtr ptr, int length) { From fd0c086e3d317a05e3b8460ea6c01fa2d13576cb Mon Sep 17 00:00:00 2001 From: Stefanos A Date: Tue, 17 Dec 2013 11:39:47 +0100 Subject: [PATCH 2/5] Marshal strings as UTF8 (affects #18) Starting with OpenGL 4.2, strings passed to GL.ShaderSource are allowed to contain multi-byte characters in comments (issue #18). This patch modifies the marshaling code to use UTF8.GetBytes in order to marshal strings, instead of Marshal.StringToHGlobalAnsi(). --- Source/Generator.Rewrite/Program.cs | 8 ++-- Source/OpenTK/BindingsBase.cs | 64 ++++++++++++++++++++++++----- 2 files changed, 58 insertions(+), 14 deletions(-) diff --git a/Source/Generator.Rewrite/Program.cs b/Source/Generator.Rewrite/Program.cs index b6d5189e..47531f09 100644 --- a/Source/Generator.Rewrite/Program.cs +++ b/Source/Generator.Rewrite/Program.cs @@ -371,10 +371,10 @@ namespace OpenTK.Rewrite static void EmitStringParameter(MethodDefinition wrapper, TypeReference p, MethodBody body, ILProcessor il) { // string marshaling: - // IntPtr ptr = Marshal.StringToHGlobalAnsi(str); + // IntPtr ptr = MarshalStringToPtr(str); // try { calli } // finally { Marshal.FreeHGlobal(ptr); } - var marshal_str_to_ptr = wrapper.Module.Import(TypeMarshal.Methods.First(m => m.Name == "StringToHGlobalAnsi")); + var marshal_str_to_ptr = wrapper.Module.Import(TypeBindingsBase.Methods.First(m => m.Name == "MarshalStringToPtr")); // IntPtr ptr; var variable_name = p.Name + "_string_ptr"; @@ -396,9 +396,9 @@ namespace OpenTK.Rewrite var p = wrapper.Parameters[i].ParameterType; if (p.Name == "String" && !p.IsArray) { - var free = wrapper.Module.Import(TypeMarshal.Methods.First(m => m.Name == "FreeHGlobal")); + var free = wrapper.Module.Import(TypeBindingsBase.Methods.First(m => m.Name == "FreeStringPtr")); - // Marshal.FreeHGlobal(ptr) + // FreeStringPtr(ptr) var variable_name = p.Name + "_string_ptr"; var v = body.Variables.First(m => m.Name == variable_name); il.Emit(OpCodes.Ldloc, v.Index); diff --git a/Source/OpenTK/BindingsBase.cs b/Source/OpenTK/BindingsBase.cs index 36d421fe..d62d553e 100644 --- a/Source/OpenTK/BindingsBase.cs +++ b/Source/OpenTK/BindingsBase.cs @@ -145,7 +145,57 @@ namespace OpenTK } /// - /// Marshals a string array to unmanaged memory by calling + /// Marshal a System.String to unmanaged memory. + /// The resulting string is encoded in UTF-8 and must be freed + /// with FreeStringPtr. + /// + /// The System.String to marshal. + /// + /// An unmanaged pointer containing the marshalled string. + /// This pointer must be freed with FreeStringPtr + /// + protected static IntPtr MarshalStringToPtr(string str) + { + if (String.IsNullOrEmpty(str)) + { + return IntPtr.Zero; + } + + // Allocate a buffer big enough to hold the marshalled string. + // We use GetMaxByteCount() as it is faster than GetByteCount(). + // The downside is that it may allocate up to 3x more memory than + // strictly necessary. + int max_count = Encoding.UTF8.GetMaxByteCount(str.Length) + 1; + IntPtr ptr = Marshal.AllocHGlobal(max_count); + if (ptr == IntPtr.Zero) + { + throw new OutOfMemoryException(); + } + + // Pin the managed string and convert it to UTF-8 using + // the pointer overload of System.Encoding.UTF8.GetBytes(). + unsafe + { + fixed (char* pstr = str) + { + int actual_count = Encoding.UTF8.GetBytes(pstr, str.Length, (byte*)ptr, max_count); + Marshal.WriteByte(ptr, actual_count, 0); // Append '\0' at the end of the string + return ptr; + } + } + } + + /// + /// Frees a marshalled string that allocated by MarshalStringToPtr. + /// + /// An unmanaged pointer allocated with MarshalStringToPtr + protected static void FreeStringPtr(IntPtr ptr) + { + Marshal.FreeHGlobal(ptr); + } + + /// + /// Marshals a System.String array to unmanaged memory by calling /// Marshal.AllocHGlobal for each element. /// /// An unmanaged pointer to an array of null-terminated strings @@ -163,12 +213,7 @@ namespace OpenTK for (int i = 0; i < str_array.Length; i++) { - IntPtr str = Marshal.StringToHGlobalAnsi(str_array[i]); - if (str == IntPtr.Zero) - { - throw new OutOfMemoryException(); - } - + IntPtr str = MarshalStringToPtr(str_array[i]); Marshal.WriteIntPtr(ptr, i * IntPtr.Size, str); } } @@ -176,10 +221,9 @@ namespace OpenTK } /// - /// Frees a string array that has previously been - /// marshalled by MarshalStringArrayToPtr. + /// Frees a marshalled string that allocated by MarshalStringArrayToPtr. /// - /// An unmanaged pointer allocated by MarshalStringArrayToPtr + /// An unmanaged pointer allocated with MarshalStringArrayToPtr /// The length of the string array. protected static void FreeStringArrayPtr(IntPtr ptr, int length) { From b15f91a0f24b1e880378b4c8d0e7bd4366c47397 Mon Sep 17 00:00:00 2001 From: Nayuta Taga Date: Thu, 16 Jan 2014 18:27:32 +0900 Subject: [PATCH 3/5] shader source with Japanese comment test --- .../ShaderSourceWithJapaneseCommentTest.cs | 237 ++++++++++++++++++ Source/Examples/OpenTK.Examples.csproj | 1 + 2 files changed, 238 insertions(+) create mode 100644 Source/Examples/OpenGL/4.x/ShaderSourceWithJapaneseCommentTest.cs diff --git a/Source/Examples/OpenGL/4.x/ShaderSourceWithJapaneseCommentTest.cs b/Source/Examples/OpenGL/4.x/ShaderSourceWithJapaneseCommentTest.cs new file mode 100644 index 00000000..abf5f5e9 --- /dev/null +++ b/Source/Examples/OpenGL/4.x/ShaderSourceWithJapaneseCommentTest.cs @@ -0,0 +1,237 @@ +// This code was written for the OpenTK library and has been released +// to the Public Domain. +// It is provided "as is" without express or implied warranty of any kind. + +using System; +using System.Diagnostics; +using System.IO; + +using OpenTK; +using OpenTK.Graphics; +using OpenTK.Graphics.OpenGL; + +namespace Examples.Tutorial +{ + [Example("Shader Source With Japanese Comment Test", ExampleCategory.OpenGL, "4.x")] + public class ShaderSourceWithJapaneseCommentTest : GameWindow + { + string vertexShaderSource = @" +#version 130 + +precision highp float;//日本語文字 Japanese Characters + +uniform mat4 projection_matrix; +uniform mat4 modelview_matrix; + +in vec3 in_position; +in vec3 in_normal; + +out vec3 normal; + +void main(void) +{ + //works only for orthogonal modelview + normal = (modelview_matrix * vec4(in_normal, 0)).xyz; + + gl_Position = projection_matrix * modelview_matrix * vec4(in_position, 1); +}"; + + string fragmentShaderSource = @" +#version 130 + +precision highp float; + +const vec3 ambient = vec3(0.1, 0.1, 0.1); +const vec3 lightVecNormalized = normalize(vec3(0.5, 0.5, 2.0)); +const vec3 lightColor = vec3(0.9, 0.9, 0.7); + +in vec3 normal; + +out vec4 out_frag_color; + +void main(void) +{ + float diffuse = clamp(dot(lightVecNormalized, normalize(normal)), 0.0, 1.0); + out_frag_color = vec4(ambient + diffuse * lightColor, 1.0); +}"; + + int vertexShaderHandle, + fragmentShaderHandle, + shaderProgramHandle, + modelviewMatrixLocation, + projectionMatrixLocation, + vaoHandle, + positionVboHandle, + normalVboHandle, + eboHandle; + + Vector3[] positionVboData = new Vector3[]{ + new Vector3(-1.0f, -1.0f, 1.0f), + new Vector3( 1.0f, -1.0f, 1.0f), + new Vector3( 1.0f, 1.0f, 1.0f), + new Vector3(-1.0f, 1.0f, 1.0f), + new Vector3(-1.0f, -1.0f, -1.0f), + new Vector3( 1.0f, -1.0f, -1.0f), + new Vector3( 1.0f, 1.0f, -1.0f), + new Vector3(-1.0f, 1.0f, -1.0f) }; + + int[] indicesVboData = new int[]{ + // front face + 0, 1, 2, 2, 3, 0, + // top face + 3, 2, 6, 6, 7, 3, + // back face + 7, 6, 5, 5, 4, 7, + // left face + 4, 0, 3, 3, 7, 4, + // bottom face + 0, 1, 5, 5, 4, 0, + // right face + 1, 5, 6, 6, 2, 1, }; + + Matrix4 projectionMatrix, modelviewMatrix; + + public ShaderSourceWithJapaneseCommentTest() + : base(640, 480, + new GraphicsMode(), "OpenGL 3 Example", 0, + DisplayDevice.Default, 4, 2, + GraphicsContextFlags.ForwardCompatible | GraphicsContextFlags.Debug) + { } + + protected override void OnLoad (System.EventArgs e) + { + VSync = VSyncMode.On; + + CreateShaders(); + CreateVBOs(); + CreateVAOs(); + + // Other state + GL.Enable(EnableCap.DepthTest); + GL.ClearColor(System.Drawing.Color.MidnightBlue); + } + + void CreateShaders() + { + vertexShaderHandle = GL.CreateShader(ShaderType.VertexShader); + fragmentShaderHandle = GL.CreateShader(ShaderType.FragmentShader); + + GL.ShaderSource(vertexShaderHandle, vertexShaderSource); + GL.ShaderSource(fragmentShaderHandle, fragmentShaderSource); + + GL.CompileShader(vertexShaderHandle); + string log = GL.GetShaderInfoLog(vertexShaderHandle); + if (log.Length != 0) { + Debug.Print(log); + } + GL.CompileShader(fragmentShaderHandle); + + Debug.WriteLine(GL.GetShaderInfoLog(vertexShaderHandle)); + Debug.WriteLine(GL.GetShaderInfoLog(fragmentShaderHandle)); + + // Create program + shaderProgramHandle = GL.CreateProgram(); + + GL.AttachShader(shaderProgramHandle, vertexShaderHandle); + GL.AttachShader(shaderProgramHandle, fragmentShaderHandle); + + GL.LinkProgram(shaderProgramHandle); + + Debug.WriteLine(GL.GetProgramInfoLog(shaderProgramHandle)); + + GL.UseProgram(shaderProgramHandle); + + // Set uniforms + projectionMatrixLocation = GL.GetUniformLocation(shaderProgramHandle, "projection_matrix"); + modelviewMatrixLocation = GL.GetUniformLocation(shaderProgramHandle, "modelview_matrix"); + + float aspectRatio = ClientSize.Width / (float)(ClientSize.Height); + Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, aspectRatio, 1, 100, out projectionMatrix); + modelviewMatrix = Matrix4.LookAt(new Vector3(0, 3, 5), new Vector3(0, 0, 0), new Vector3(0, 1, 0)); + + GL.UniformMatrix4(projectionMatrixLocation, false, ref projectionMatrix); + GL.UniformMatrix4(modelviewMatrixLocation, false, ref modelviewMatrix); + } + + void CreateVBOs() + { + GL.GenBuffers(1, out positionVboHandle); + GL.BindBuffer(BufferTarget.ArrayBuffer, positionVboHandle); + GL.BufferData(BufferTarget.ArrayBuffer, + new IntPtr(positionVboData.Length * Vector3.SizeInBytes), + positionVboData, BufferUsageHint.StaticDraw); + + GL.GenBuffers(1, out normalVboHandle); + GL.BindBuffer(BufferTarget.ArrayBuffer, normalVboHandle); + GL.BufferData(BufferTarget.ArrayBuffer, + new IntPtr(positionVboData.Length * Vector3.SizeInBytes), + positionVboData, BufferUsageHint.StaticDraw); + + GL.GenBuffers(1, out eboHandle); + GL.BindBuffer(BufferTarget.ElementArrayBuffer, eboHandle); + GL.BufferData(BufferTarget.ElementArrayBuffer, + new IntPtr(sizeof(uint) * indicesVboData.Length), + indicesVboData, BufferUsageHint.StaticDraw); + + GL.BindBuffer(BufferTarget.ArrayBuffer, 0); + GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0); + } + + void CreateVAOs() + { + // GL3 allows us to store the vertex layout in a "vertex array object" (VAO). + // This means we do not have to re-issue VertexAttribPointer calls + // every time we try to use a different vertex layout - these calls are + // stored in the VAO so we simply need to bind the correct VAO. + GL.GenVertexArrays(1, out vaoHandle); + GL.BindVertexArray(vaoHandle); + + GL.EnableVertexAttribArray(0); + GL.BindBuffer(BufferTarget.ArrayBuffer, positionVboHandle); + GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, true, Vector3.SizeInBytes, 0); + GL.BindAttribLocation(shaderProgramHandle, 0, "in_position"); + + GL.EnableVertexAttribArray(1); + GL.BindBuffer(BufferTarget.ArrayBuffer, normalVboHandle); + GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, true, Vector3.SizeInBytes, 0); + GL.BindAttribLocation(shaderProgramHandle, 1, "in_normal"); + + GL.BindBuffer(BufferTarget.ElementArrayBuffer, eboHandle); + + GL.BindVertexArray(0); + } + + protected override void OnUpdateFrame(FrameEventArgs e) + { + Matrix4 rotation = Matrix4.CreateRotationY((float)e.Time); + Matrix4.Mult(ref rotation, ref modelviewMatrix, out modelviewMatrix); + GL.UniformMatrix4(modelviewMatrixLocation, false, ref modelviewMatrix); + + if (Keyboard[OpenTK.Input.Key.Escape]) + Exit(); + } + + protected override void OnRenderFrame(FrameEventArgs e) + { + GL.Viewport(0, 0, Width, Height); + + GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); + + GL.BindVertexArray(vaoHandle); + GL.DrawElements(BeginMode.Triangles, indicesVboData.Length, + DrawElementsType.UnsignedInt, IntPtr.Zero); + + SwapBuffers(); + } + + [STAThread] + public static void Main() + { + using (ShaderSourceWithJapaneseCommentTest example = new ShaderSourceWithJapaneseCommentTest()) + { + Utilities.SetWindowTitle(example); + example.Run(30); + } + } + } +} \ No newline at end of file diff --git a/Source/Examples/OpenTK.Examples.csproj b/Source/Examples/OpenTK.Examples.csproj index c78290e6..3ba0059f 100644 --- a/Source/Examples/OpenTK.Examples.csproj +++ b/Source/Examples/OpenTK.Examples.csproj @@ -146,6 +146,7 @@ Code + Code From b9f57ba4d274fd601b87ef4c8f12d698514f8e7a Mon Sep 17 00:00:00 2001 From: "Stefanos A." Date: Thu, 16 Jan 2014 14:32:11 +0100 Subject: [PATCH 4/5] [OpenTK] Use ASCII encoding Most OpenGL versions work with single-byte ASCII strings exclusively. OpenGL 4.2 adds UTF8 encoded comments to GLSL shaders. Unfortunately, UTF16 (.Net) to UTF8 conversions will usually modify the length of the resulting byte array. This is not currently possible to implement inside OpenTK, since the binding generator does not know which length parameter corresponds to a string parameter. For this reason, and to maintain compatibility with older OpenGL versions, we perform a destructive UTF16-to-ASCII encoding, which replaces unsupported characters by '?'. This allows multi-byte post-4.2. GLSL shaders to work as expected. If non-destructive round-tripping of strings is required, the user will have to use the IntPtr overload for string parameters and perform the UTF16-to-UTF8 encoding/decoding manually. This need is very unlikely to arise in practice. --- Source/OpenTK/BindingsBase.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Source/OpenTK/BindingsBase.cs b/Source/OpenTK/BindingsBase.cs index d62d553e..acc5738a 100644 --- a/Source/OpenTK/BindingsBase.cs +++ b/Source/OpenTK/BindingsBase.cs @@ -146,7 +146,7 @@ namespace OpenTK /// /// Marshal a System.String to unmanaged memory. - /// The resulting string is encoded in UTF-8 and must be freed + /// The resulting string is encoded in ASCII and must be freed /// with FreeStringPtr. /// /// The System.String to marshal. @@ -162,23 +162,23 @@ namespace OpenTK } // Allocate a buffer big enough to hold the marshalled string. - // We use GetMaxByteCount() as it is faster than GetByteCount(). - // The downside is that it may allocate up to 3x more memory than - // strictly necessary. - int max_count = Encoding.UTF8.GetMaxByteCount(str.Length) + 1; + // GetMaxByteCount() appears to allocate space for the final NUL + // character, but allocate an extra one just in case (who knows + // what old Mono version would do here.) + int max_count = Encoding.ASCII.GetMaxByteCount(str.Length) + 1; IntPtr ptr = Marshal.AllocHGlobal(max_count); if (ptr == IntPtr.Zero) { throw new OutOfMemoryException(); } - // Pin the managed string and convert it to UTF-8 using - // the pointer overload of System.Encoding.UTF8.GetBytes(). + // Pin the managed string and convert it to ASCII using + // the pointer overload of System.Encoding.ASCII.GetBytes(). unsafe { fixed (char* pstr = str) { - int actual_count = Encoding.UTF8.GetBytes(pstr, str.Length, (byte*)ptr, max_count); + int actual_count = Encoding.ASCII.GetBytes(pstr, str.Length, (byte*)ptr, max_count); Marshal.WriteByte(ptr, actual_count, 0); // Append '\0' at the end of the string return ptr; } From 8cb353876795c78b3b4d0f903ba7d07ccc7fe051 Mon Sep 17 00:00:00 2001 From: "Stefanos A." Date: Thu, 16 Jan 2014 14:37:27 +0100 Subject: [PATCH 5/5] [Examples] Move UTF8 sample to Test folder --- Source/Examples/OpenTK.Examples.csproj | 2 +- .../Test/TestShaderUtf8Support.cs} | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) rename Source/Examples/{OpenGL/4.x/ShaderSourceWithJapaneseCommentTest.cs => OpenTK/Test/TestShaderUtf8Support.cs} (95%) diff --git a/Source/Examples/OpenTK.Examples.csproj b/Source/Examples/OpenTK.Examples.csproj index 3ba0059f..3c9f126d 100644 --- a/Source/Examples/OpenTK.Examples.csproj +++ b/Source/Examples/OpenTK.Examples.csproj @@ -146,7 +146,7 @@ Code - + Code diff --git a/Source/Examples/OpenGL/4.x/ShaderSourceWithJapaneseCommentTest.cs b/Source/Examples/OpenTK/Test/TestShaderUtf8Support.cs similarity index 95% rename from Source/Examples/OpenGL/4.x/ShaderSourceWithJapaneseCommentTest.cs rename to Source/Examples/OpenTK/Test/TestShaderUtf8Support.cs index abf5f5e9..0de01d45 100644 --- a/Source/Examples/OpenGL/4.x/ShaderSourceWithJapaneseCommentTest.cs +++ b/Source/Examples/OpenTK/Test/TestShaderUtf8Support.cs @@ -12,8 +12,8 @@ using OpenTK.Graphics.OpenGL; namespace Examples.Tutorial { - [Example("Shader Source With Japanese Comment Test", ExampleCategory.OpenGL, "4.x")] - public class ShaderSourceWithJapaneseCommentTest : GameWindow + [Example("Shader UTF8 support", ExampleCategory.OpenTK, "OpenGL")] + public class TestShaderUtf8Support : GameWindow { string vertexShaderSource = @" #version 130 @@ -91,10 +91,10 @@ void main(void) Matrix4 projectionMatrix, modelviewMatrix; - public ShaderSourceWithJapaneseCommentTest() + public TestShaderUtf8Support() : base(640, 480, new GraphicsMode(), "OpenGL 3 Example", 0, - DisplayDevice.Default, 4, 2, + DisplayDevice.Default, 3, 0, GraphicsContextFlags.ForwardCompatible | GraphicsContextFlags.Debug) { } @@ -227,7 +227,7 @@ void main(void) [STAThread] public static void Main() { - using (ShaderSourceWithJapaneseCommentTest example = new ShaderSourceWithJapaneseCommentTest()) + using (TestShaderUtf8Support example = new TestShaderUtf8Support()) { Utilities.SetWindowTitle(example); example.Run(30);