maui-linux/Xamarin.Forms.ControlGaller.../AdvancedOpenGLView.cs

215 строки
6.7 KiB
C#

using OpenTK;
using OpenTK.Graphics.OpenGL;
using System;
namespace Xamarin.Forms.ControlGallery.GTK
{
public class AdvancedOpenGLApp : Application
{
public AdvancedOpenGLApp()
{
MainPage = new AdvancedOpenGLView();
}
}
public class AdvancedOpenGLView : ContentPage
{
private const string VertexShader = @"
uniform mat4 uMVPMatrix;
attribute vec4 vColor;
attribute vec4 vPosition;
varying vec4 color;
void main()
{
color = vColor;
gl_Position = uMVPMatrix * vPosition;
}";
private const string FragmentShader = @"
varying lowp vec4 color;
void main (void)
{
gl_FragColor = color;
}";
private bool _initGl = false;
private int _viewportWidth;
private int _viewportHeight;
private Vector4[] _vertices;
private Vector4[] _colors;
private uint _mProgramHandle;
private int _mColorHandle;
private int _mPositionHandle;
private int _mMVPMatrixHandle;
private Matrix4 _mProjectionMatrix;
private Matrix4 _mViewMatrix;
private Matrix4 _mModelViewProjectionMatrix;
private Xamarin.Forms.OpenGLView _openGLView = null;
public AdvancedOpenGLView()
{
Title = "Advanced OpenGLView Sample";
var titleLabel = new Label
{
Text = "OpenGLView",
FontSize = 36
};
_openGLView = new OpenGLView
{
HeightRequest = 300,
WidthRequest = 300,
HasRenderLoop = true
};
_openGLView.OnDisplay = r =>
{
if (!_initGl)
{
double width_in_pixels = 300;
double height_in_pixels = 300;
InitGl((int)width_in_pixels, (int)height_in_pixels);
}
Render();
};
var stack = new StackLayout
{
Padding = new Size(12, 12),
Children = { titleLabel, _openGLView }
};
Content = stack;
}
void InitGl(int width, int height)
{
_viewportHeight = width;
_viewportWidth = height;
_vertices = new Vector4[]
{
new Vector4(0.0f, 0.5f, 0.0f, 1.0f),
new Vector4(0.5f, -0.5f, 0.0f, 1.0f),
new Vector4(-0.5f, -0.5f, 0.0f, 1.0f)
};
_colors = new Vector4[]
{
new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
new Vector4(0.0f, 0.0f, 1.0f, 1.0f)
};
uint vertexShader = CompileShader(VertexShader, ShaderType.VertexShader);
uint fragmentShader = CompileShader(FragmentShader, ShaderType.FragmentShader);
_mProgramHandle = (uint)GL.CreateProgram();
if (_mProgramHandle == 0)
throw new InvalidOperationException("Unable to create program");
GL.AttachShader(_mProgramHandle, vertexShader);
GL.AttachShader(_mProgramHandle, fragmentShader);
GL.BindAttribLocation(_mProgramHandle, 0, "vPosition");
GL.LinkProgram(_mProgramHandle);
GL.Viewport(0, 0, _viewportWidth, _viewportHeight);
GL.UseProgram(_mProgramHandle);
_initGl = true;
}
public static uint CompileShader(string shaderString, ShaderType shaderType)
{
uint shaderHandle = (uint)GL.CreateShader(shaderType);
GL.ShaderSource((int)shaderHandle, shaderString);
GL.CompileShader(shaderHandle);
return shaderHandle;
}
public static void UniformMatrix4(int location, Matrix4 value)
{
GL.UniformMatrix4(location, 1, false, ref value.Row0.X);
}
void Render()
{
GL.UseProgram(_mProgramHandle);
GL.ClearColor(0.7f, 0.7f, 0.7f, 1);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit | ClearBufferMask.StencilBufferBit);
float aspectRatio = ((float)Width) / ((float)Height);
float ratio = ((float)_viewportWidth) / ((float)_viewportHeight);
_mProjectionMatrix = Matrix4.CreateOrthographicOffCenter(-ratio, ratio, -1, 1, 0.1f, 10.0f);
_mViewMatrix = Matrix4.LookAt(new Vector3(0, 0, 5), new Vector3(0, 0, 0), new Vector3(0, 1, 0));
_mModelViewProjectionMatrix = Matrix4.Mult(_mViewMatrix, _mProjectionMatrix);
Matrix4 mModel = Matrix4.CreateRotationY((float)(Math.PI * 2.0 * ReferenceTime.GetTimeFromReferenceMs() / 5000.0));
_mModelViewProjectionMatrix = Matrix4.Mult(_mModelViewProjectionMatrix, mModel);
_mPositionHandle = GL.GetAttribLocation(_mProgramHandle, "vPosition");
_mColorHandle = GL.GetAttribLocation(_mProgramHandle, "vColor");
GL.EnableVertexAttribArray(_mPositionHandle);
GL.EnableVertexAttribArray(_mColorHandle);
unsafe
{
fixed (Vector4* pvertices = _vertices)
{
GL.VertexAttribPointer(_mPositionHandle, Vector4.SizeInBytes / 4, VertexAttribPointerType.Float, false, 0, new IntPtr(pvertices));
}
fixed (Vector4* pcolors = _colors)
{
GL.VertexAttribPointer(_mColorHandle, Vector4.SizeInBytes / 4, VertexAttribPointerType.Float, false, 0, new IntPtr(pcolors));
}
}
_mMVPMatrixHandle = GL.GetUniformLocation(_mProgramHandle, "uMVPMatrix");
UniformMatrix4(_mMVPMatrixHandle, _mModelViewProjectionMatrix);
GL.DrawArrays(BeginMode.Triangles, 0, 3);
GL.Finish();
GL.DisableVertexAttribArray(_mPositionHandle);
GL.DisableVertexAttribArray(_mColorHandle);
}
}
public class ReferenceTime
{
private static DateTime reference_time;
private static bool reference_time_set = false;
public static double GetTimeFromReferenceMs()
{
if (!reference_time_set)
{
reference_time = DateTime.Now;
reference_time_set = true;
return 0.0;
}
DateTime actual_time = DateTime.Now;
TimeSpan ts = new TimeSpan(actual_time.Ticks - reference_time.Ticks);
return ts.TotalMilliseconds;
}
}
}