mirror of
https://github.com/Ryujinx/Opentk.git
synced 2025-01-25 16:31:08 +00:00
Merge branch 'utf8' into develop
This commit is contained in:
commit
e1ef27d593
|
@ -146,6 +146,7 @@
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="OpenGL\1.x\TextRendering.cs" />
|
<Compile Include="OpenGL\1.x\TextRendering.cs" />
|
||||||
|
<Compile Include="OpenTK\Test\TestShaderUtf8Support.cs" />
|
||||||
<Compile Include="SamplesTreeViewSorter.cs">
|
<Compile Include="SamplesTreeViewSorter.cs">
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
|
237
Source/Examples/OpenTK/Test/TestShaderUtf8Support.cs
Normal file
237
Source/Examples/OpenTK/Test/TestShaderUtf8Support.cs
Normal file
|
@ -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 UTF8 support", ExampleCategory.OpenTK, "OpenGL")]
|
||||||
|
public class TestShaderUtf8Support : 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 TestShaderUtf8Support()
|
||||||
|
: base(640, 480,
|
||||||
|
new GraphicsMode(), "OpenGL 3 Example", 0,
|
||||||
|
DisplayDevice.Default, 3, 0,
|
||||||
|
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<Vector3>(BufferTarget.ArrayBuffer,
|
||||||
|
new IntPtr(positionVboData.Length * Vector3.SizeInBytes),
|
||||||
|
positionVboData, BufferUsageHint.StaticDraw);
|
||||||
|
|
||||||
|
GL.GenBuffers(1, out normalVboHandle);
|
||||||
|
GL.BindBuffer(BufferTarget.ArrayBuffer, normalVboHandle);
|
||||||
|
GL.BufferData<Vector3>(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 (TestShaderUtf8Support example = new TestShaderUtf8Support())
|
||||||
|
{
|
||||||
|
Utilities.SetWindowTitle(example);
|
||||||
|
example.Run(30);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -371,10 +371,10 @@ namespace OpenTK.Rewrite
|
||||||
static void EmitStringParameter(MethodDefinition wrapper, TypeReference p, MethodBody body, ILProcessor il)
|
static void EmitStringParameter(MethodDefinition wrapper, TypeReference p, MethodBody body, ILProcessor il)
|
||||||
{
|
{
|
||||||
// string marshaling:
|
// string marshaling:
|
||||||
// IntPtr ptr = Marshal.StringToHGlobalAnsi(str);
|
// IntPtr ptr = MarshalStringToPtr(str);
|
||||||
// try { calli }
|
// try { calli }
|
||||||
// finally { Marshal.FreeHGlobal(ptr); }
|
// 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;
|
// IntPtr ptr;
|
||||||
var variable_name = p.Name + "_string_ptr";
|
var variable_name = p.Name + "_string_ptr";
|
||||||
|
@ -396,9 +396,9 @@ namespace OpenTK.Rewrite
|
||||||
var p = wrapper.Parameters[i].ParameterType;
|
var p = wrapper.Parameters[i].ParameterType;
|
||||||
if (p.Name == "String" && !p.IsArray)
|
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 variable_name = p.Name + "_string_ptr";
|
||||||
var v = body.Variables.First(m => m.Name == variable_name);
|
var v = body.Variables.First(m => m.Name == variable_name);
|
||||||
il.Emit(OpCodes.Ldloc, v.Index);
|
il.Emit(OpCodes.Ldloc, v.Index);
|
||||||
|
|
|
@ -145,7 +145,57 @@ namespace OpenTK
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Marshals a string array to unmanaged memory by calling
|
/// Marshal a <c>System.String</c> to unmanaged memory.
|
||||||
|
/// The resulting string is encoded in ASCII and must be freed
|
||||||
|
/// with <c>FreeStringPtr</c>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="str">The <c>System.String</c> to marshal.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// An unmanaged pointer containing the marshalled string.
|
||||||
|
/// This pointer must be freed with <c>FreeStringPtr</c>
|
||||||
|
/// </returns>
|
||||||
|
protected static IntPtr MarshalStringToPtr(string str)
|
||||||
|
{
|
||||||
|
if (String.IsNullOrEmpty(str))
|
||||||
|
{
|
||||||
|
return IntPtr.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate a buffer big enough to hold the marshalled string.
|
||||||
|
// 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 ASCII using
|
||||||
|
// the pointer overload of System.Encoding.ASCII.GetBytes().
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
fixed (char* pstr = str)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Frees a marshalled string that allocated by <c>MarshalStringToPtr</c>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ptr">An unmanaged pointer allocated with <c>MarshalStringToPtr</param>
|
||||||
|
protected static void FreeStringPtr(IntPtr ptr)
|
||||||
|
{
|
||||||
|
Marshal.FreeHGlobal(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Marshals a <c>System.String</c> array to unmanaged memory by calling
|
||||||
/// Marshal.AllocHGlobal for each element.
|
/// Marshal.AllocHGlobal for each element.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>An unmanaged pointer to an array of null-terminated strings</returns>
|
/// <returns>An unmanaged pointer to an array of null-terminated strings</returns>
|
||||||
|
@ -163,12 +213,7 @@ namespace OpenTK
|
||||||
|
|
||||||
for (int i = 0; i < str_array.Length; i++)
|
for (int i = 0; i < str_array.Length; i++)
|
||||||
{
|
{
|
||||||
IntPtr str = Marshal.StringToHGlobalAnsi(str_array[i]);
|
IntPtr str = MarshalStringToPtr(str_array[i]);
|
||||||
if (str == IntPtr.Zero)
|
|
||||||
{
|
|
||||||
throw new OutOfMemoryException();
|
|
||||||
}
|
|
||||||
|
|
||||||
Marshal.WriteIntPtr(ptr, i * IntPtr.Size, str);
|
Marshal.WriteIntPtr(ptr, i * IntPtr.Size, str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -176,10 +221,9 @@ namespace OpenTK
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Frees a string array that has previously been
|
/// Frees a marshalled string that allocated by <c>MarshalStringArrayToPtr</c>.
|
||||||
/// marshalled by <c>MarshalStringArrayToPtr</c>.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="ptr">An unmanaged pointer allocated by <c>MarshalStringArrayToPtr</c></param>
|
/// <param name="ptr">An unmanaged pointer allocated with <c>MarshalStringArrayToPtr</c></param>
|
||||||
/// <param name="length">The length of the string array.</param>
|
/// <param name="length">The length of the string array.</param>
|
||||||
protected static void FreeStringArrayPtr(IntPtr ptr, int length)
|
protected static void FreeStringArrayPtr(IntPtr ptr, int length)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue