Avalonia学习(二十八)-OpenGL

Avalonia已经继承了opengl,详细的大家可以自己查阅。Avalonia里面启用opengl继承OpenGlControlBase类就可以了。有三个方法。分别是初始化、绘制、释放。

这里把官方源码的例子扒出来给大家看一下。源码在我以前发布的单组件里面。地址在前面的界面总结博文里面。

关键源码:

    public class OpenGlPageControl : OpenGlControlBase{private float _yaw;public static readonly DirectProperty<OpenGlPageControl, float> YawProperty =AvaloniaProperty.RegisterDirect<OpenGlPageControl, float>("Yaw", o => o.Yaw, (o, v) => o.Yaw = v);public float Yaw{get => _yaw;set => SetAndRaise(YawProperty, ref _yaw, value);}private float _pitch;public static readonly DirectProperty<OpenGlPageControl, float> PitchProperty =AvaloniaProperty.RegisterDirect<OpenGlPageControl, float>("Pitch", o => o.Pitch, (o, v) => o.Pitch = v);public float Pitch{get => _pitch;set => SetAndRaise(PitchProperty, ref _pitch, value);}private float _roll;public static readonly DirectProperty<OpenGlPageControl, float> RollProperty =AvaloniaProperty.RegisterDirect<OpenGlPageControl, float>("Roll", o => o.Roll, (o, v) => o.Roll = v);public float Roll{get => _roll;set => SetAndRaise(RollProperty, ref _roll, value);}private float _disco;public static readonly DirectProperty<OpenGlPageControl, float> DiscoProperty =AvaloniaProperty.RegisterDirect<OpenGlPageControl, float>("Disco", o => o.Disco, (o, v) => o.Disco = v);public float Disco{get => _disco;set => SetAndRaise(DiscoProperty, ref _disco, value);}private string _info = string.Empty;public static readonly DirectProperty<OpenGlPageControl, string> InfoProperty =AvaloniaProperty.RegisterDirect<OpenGlPageControl, string>("Info", o => o.Info, (o, v) => o.Info = v);public string Info{get => _info;private set => SetAndRaise(InfoProperty, ref _info, value);}private int _vertexShader;private int _fragmentShader;private int _shaderProgram;private int _vertexBufferObject;private int _indexBufferObject;private int _vertexArrayObject;private string GetShader(bool fragment, string shader){var version = GlVersion.Type == GlProfileType.OpenGL ?RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? 150 : 120 :100;var data = "#version " + version + "\n";if (GlVersion.Type == GlProfileType.OpenGLES)data += "precision mediump float;\n";if (version >= 150){shader = shader.Replace("attribute", "in");if (fragment)shader = shader.Replace("varying", "in").Replace("//DECLAREGLFRAG", "out vec4 outFragColor;").Replace("gl_FragColor", "outFragColor");elseshader = shader.Replace("varying", "out");}data += shader;return data;}private string VertexShaderSource => GetShader(false, @"attribute vec3 aPos;attribute vec3 aNormal;uniform mat4 uModel;uniform mat4 uProjection;uniform mat4 uView;varying vec3 FragPos;varying vec3 VecPos;  varying vec3 Normal;uniform float uTime;uniform float uDisco;void main(){float discoScale = sin(uTime * 10.0) / 10.0;float distortionX = 1.0 + uDisco * cos(uTime * 20.0) / 10.0;float scale = 1.0 + uDisco * discoScale;vec3 scaledPos = aPos;scaledPos.x = scaledPos.x * distortionX;scaledPos *= scale;gl_Position = uProjection * uView * uModel * vec4(scaledPos, 1.0);FragPos = vec3(uModel * vec4(aPos, 1.0));VecPos = aPos;Normal = normalize(vec3(uModel * vec4(aNormal, 1.0)));}
");private string FragmentShaderSource => GetShader(true, @"varying vec3 FragPos; varying vec3 VecPos; varying vec3 Normal;uniform float uMaxY;uniform float uMinY;uniform float uTime;uniform float uDisco;//DECLAREGLFRAGvoid main(){float y = (VecPos.y - uMinY) / (uMaxY - uMinY);float c = cos(atan(VecPos.x, VecPos.z) * 20.0 + uTime * 40.0 + y * 50.0);float s = sin(-atan(VecPos.z, VecPos.x) * 20.0 - uTime * 20.0 - y * 30.0);vec3 discoColor = vec3(0.5 + abs(0.5 - y) * cos(uTime * 10.0),0.25 + (smoothstep(0.3, 0.8, y) * (0.5 - c / 4.0)),0.25 + abs((smoothstep(0.1, 0.4, y) * (0.5 - s / 4.0))));vec3 objectColor = vec3((1.0 - y), 0.40 +  y / 4.0, y * 0.75 + 0.25);objectColor = objectColor * (1.0 - uDisco) + discoColor * uDisco;float ambientStrength = 0.3;vec3 lightColor = vec3(1.0, 1.0, 1.0);vec3 lightPos = vec3(uMaxY * 2.0, uMaxY * 2.0, uMaxY * 2.0);vec3 ambient = ambientStrength * lightColor;vec3 norm = normalize(Normal);vec3 lightDir = normalize(lightPos - FragPos);  float diff = max(dot(norm, lightDir), 0.0);vec3 diffuse = diff * lightColor;vec3 result = (ambient + diffuse) * objectColor;gl_FragColor = vec4(result, 1.0);}
");[StructLayout(LayoutKind.Sequential, Pack = 4)]private struct Vertex{public Vector3 Position;public Vector3 Normal;}private readonly Vertex[] _points;private readonly ushort[] _indices;private readonly float _minY;private readonly float _maxY;public OpenGlPageControl(){var name = typeof(OpenGlPage).Assembly.GetManifestResourceNames().First(x => x.Contains("teapot.bin"));using (var sr = new BinaryReader(typeof(OpenGlPage).Assembly.GetManifestResourceStream(name)!)){var buf = new byte[sr.ReadInt32()];sr.Read(buf, 0, buf.Length);var points = new float[buf.Length / 4];Buffer.BlockCopy(buf, 0, points, 0, buf.Length);buf = new byte[sr.ReadInt32()];sr.Read(buf, 0, buf.Length);_indices = new ushort[buf.Length / 2];Buffer.BlockCopy(buf, 0, _indices, 0, buf.Length);_points = new Vertex[points.Length / 3];for (var primitive = 0; primitive < points.Length / 3; primitive++){var srci = primitive * 3;_points[primitive] = new Vertex{Position = new Vector3(points[srci], points[srci + 1], points[srci + 2])};}for (int i = 0; i < _indices.Length; i += 3){Vector3 a = _points[_indices[i]].Position;Vector3 b = _points[_indices[i + 1]].Position;Vector3 c = _points[_indices[i + 2]].Position;var normal = Vector3.Normalize(Vector3.Cross(c - b, a - b));_points[_indices[i]].Normal += normal;_points[_indices[i + 1]].Normal += normal;_points[_indices[i + 2]].Normal += normal;}for (int i = 0; i < _points.Length; i++){_points[i].Normal = Vector3.Normalize(_points[i].Normal);_maxY = Math.Max(_maxY, _points[i].Position.Y);_minY = Math.Min(_minY, _points[i].Position.Y);}}}private static void CheckError(GlInterface gl){int err;while ((err = gl.GetError()) != GlConsts.GL_NO_ERROR)Console.WriteLine(err);}protected override unsafe void OnOpenGlInit(GlInterface GL){CheckError(GL);Info = $"Renderer: {GL.GetString(GlConsts.GL_RENDERER)} Version: {GL.GetString(GlConsts.GL_VERSION)}";// Load the source of the vertex shader and compile it._vertexShader = GL.CreateShader(GlConsts.GL_VERTEX_SHADER);Console.WriteLine(GL.CompileShaderAndGetError(_vertexShader, VertexShaderSource));// Load the source of the fragment shader and compile it._fragmentShader = GL.CreateShader(GlConsts.GL_FRAGMENT_SHADER);Console.WriteLine(GL.CompileShaderAndGetError(_fragmentShader, FragmentShaderSource));// Create the shader program, attach the vertex and fragment shaders and link the program._shaderProgram = GL.CreateProgram();GL.AttachShader(_shaderProgram, _vertexShader);GL.AttachShader(_shaderProgram, _fragmentShader);const int positionLocation = 0;const int normalLocation = 1;GL.BindAttribLocationString(_shaderProgram, positionLocation, "aPos");GL.BindAttribLocationString(_shaderProgram, normalLocation, "aNormal");Console.WriteLine(GL.LinkProgramAndGetError(_shaderProgram));CheckError(GL);// Create the vertex buffer object (VBO) for the vertex data._vertexBufferObject = GL.GenBuffer();// Bind the VBO and copy the vertex data into it.GL.BindBuffer(GlConsts.GL_ARRAY_BUFFER, _vertexBufferObject);CheckError(GL);var vertexSize = Marshal.SizeOf<Vertex>();fixed (void* pdata = _points)GL.BufferData(GlConsts.GL_ARRAY_BUFFER, new nint(_points.Length * vertexSize),new nint(pdata), GlConsts.GL_STATIC_DRAW);_indexBufferObject = GL.GenBuffer();GL.BindBuffer(GlConsts.GL_ELEMENT_ARRAY_BUFFER, _indexBufferObject);CheckError(GL);fixed (void* pdata = _indices)GL.BufferData(GlConsts.GL_ELEMENT_ARRAY_BUFFER, new nint(_indices.Length * sizeof(ushort)), new nint(pdata),GlConsts.GL_STATIC_DRAW);CheckError(GL);_vertexArrayObject = GL.GenVertexArray();GL.BindVertexArray(_vertexArrayObject);CheckError(GL);GL.VertexAttribPointer(positionLocation, 3, GlConsts.GL_FLOAT,0, vertexSize, nint.Zero);GL.VertexAttribPointer(normalLocation, 3, GlConsts.GL_FLOAT,0, vertexSize, new nint(12));GL.EnableVertexAttribArray(positionLocation);GL.EnableVertexAttribArray(normalLocation);CheckError(GL);}protected override void OnOpenGlDeinit(GlInterface GL){// Unbind everythingGL.BindBuffer(GlConsts.GL_ARRAY_BUFFER, 0);GL.BindBuffer(GlConsts.GL_ELEMENT_ARRAY_BUFFER, 0);GL.BindVertexArray(0);GL.UseProgram(0);// Delete all resources.GL.DeleteBuffer(_vertexBufferObject);GL.DeleteBuffer(_indexBufferObject);GL.DeleteVertexArray(_vertexArrayObject);GL.DeleteProgram(_shaderProgram);GL.DeleteShader(_fragmentShader);GL.DeleteShader(_vertexShader);}static Stopwatch St = Stopwatch.StartNew();protected override unsafe void OnOpenGlRender(GlInterface gl, int fb){gl.ClearColor(0, 0, 0, 0);gl.Clear(GlConsts.GL_COLOR_BUFFER_BIT | GlConsts.GL_DEPTH_BUFFER_BIT);gl.Enable(GlConsts.GL_DEPTH_TEST);gl.Viewport(0, 0, (int)Bounds.Width, (int)Bounds.Height);var GL = gl;GL.BindBuffer(GlConsts.GL_ARRAY_BUFFER, _vertexBufferObject);GL.BindBuffer(GlConsts.GL_ELEMENT_ARRAY_BUFFER, _indexBufferObject);GL.BindVertexArray(_vertexArrayObject);GL.UseProgram(_shaderProgram);CheckError(GL);var projection =Matrix4x4.CreatePerspectiveFieldOfView((float)(Math.PI / 4), (float)(Bounds.Width / Bounds.Height),0.01f, 1000);var view = Matrix4x4.CreateLookAt(new Vector3(25, 25, 25), new Vector3(), new Vector3(0, 1, 0));var model = Matrix4x4.CreateFromYawPitchRoll(_yaw, _pitch, _roll);var modelLoc = GL.GetUniformLocationString(_shaderProgram, "uModel");var viewLoc = GL.GetUniformLocationString(_shaderProgram, "uView");var projectionLoc = GL.GetUniformLocationString(_shaderProgram, "uProjection");var maxYLoc = GL.GetUniformLocationString(_shaderProgram, "uMaxY");var minYLoc = GL.GetUniformLocationString(_shaderProgram, "uMinY");var timeLoc = GL.GetUniformLocationString(_shaderProgram, "uTime");var discoLoc = GL.GetUniformLocationString(_shaderProgram, "uDisco");GL.UniformMatrix4fv(modelLoc, 1, false, &model);GL.UniformMatrix4fv(viewLoc, 1, false, &view);GL.UniformMatrix4fv(projectionLoc, 1, false, &projection);GL.Uniform1f(maxYLoc, _maxY);GL.Uniform1f(minYLoc, _minY);GL.Uniform1f(timeLoc, (float)St.Elapsed.TotalSeconds);GL.Uniform1f(discoLoc, _disco);CheckError(GL);GL.DrawElements(GlConsts.GL_TRIANGLES, _indices.Length, GlConsts.GL_UNSIGNED_SHORT, nint.Zero);CheckError(GL);if (_disco > 0.01)RequestNextFrameRendering();}protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change){if (change.Property == YawProperty || change.Property == RollProperty || change.Property == PitchProperty ||change.Property == DiscoProperty)RequestNextFrameRendering();base.OnPropertyChanged(change);}}

另外还需要一个teapot.bin文件,嵌入方式。你如果想运行,还得下载源码或者下载我得代码。

运行效果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/503765.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue cesium加载点与定位到指定位置

vue cesium定位到指定位置 window.viewer.camera.flyTo({destination: Cesium.Cartesian3.fromDegrees(point.longDeg, point.latDeg, 6500000), orientation: {heading: 6.2079384332084935, roll: 0.00031509431759868534, pitch: -1.535}, duration: 3})vue cesium加载点 …

[技巧]Arcgis之图斑四至范围批量计算

ArcGIS图层&#xff08;点、线、面三类图形&#xff09;四至范围计算 例外一篇介绍&#xff1a;[技巧]Arcgis之图斑四至点批量计算 说明&#xff1a;如下图画出来的框&#xff08;范围标记不是很准&#xff09; &#xff0c;图斑的x最大和x最小&#xff0c;y最大&#xff0c;…

css实现居中

基础代码&#xff1a; <div class"box"><div class"content"></div> </div> css实现居中的几种方式&#xff1a; 1、flex布局&#xff08;水平垂直&#xff09; .box {width: 200px;height: 200px;background-color: pink;disp…

如何利用Flutter来写后端 服务端应用

前言 Flutter是谷歌推出的一款跨平台开发框架&#xff0c;现在属于此领域star最多的框架&#xff0c;其被广泛应用于构建前台界面&#xff0c;但或许很少人知道&#xff0c;他也可以写后端应用。 本文主角 flutter非常著名的getx库推出的get server jonataslaw/get_server:…

管家婆云上管家新帐套建立步骤

第一步&#xff0c;客户服务管理&#xff1b; 第二步&#xff0c;添加帐套&#xff1b; 第三步&#xff0c;点击“管理”进入&#xff1b;第四步&#xff0c;添加帐套信息&#xff1b; 第五步&#xff0c;找到客户&#xff0c;查看帐套信息&#xff1b; 第六步&#xff0c;确认…

ShardingJdbc分库分表-浅谈分表原理

文章目录 为什么要分库分表一、分库分表二、不停机分库分表数据迁移 为什么要分库分表 一般的机器&#xff08;4核16G&#xff09;&#xff0c;单库的MySQL并发&#xff08;QPSTPS&#xff09;超过了2k&#xff0c;系统基本就完蛋了。最好是并发量控制在1k左右。这里就引出一个…

Springboot+vue的制造装备物联及生产管理ERP系统(有报告)。Javaee项目,springboot vue前后端分离项目。

演示视频&#xff1a; Springbootvue的制造装备物联及生产管理ERP系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot vue前后端分离项 项目介绍&#xff1a; 本文设计了一个基于Springbootvue的制造装备物联及生产管理ERP系统&#xff0c;采用M&#xff…

软件设计师软考题目解析15 --每日五题

想说的话&#xff1a;要准备软考了。0.0&#xff0c;其实我是不想考的&#xff0c;但是吧&#xff0c;由于本人已经学完所有知识了&#xff0c;只是被学校的课程给锁在那里了&#xff0c;不然早找工作去了。寻思着反正也无聊&#xff0c;就考个证玩玩。 本人github地址&#xf…

C 嵌入式系统设计模式 16:循环执行模式

本书的原著为&#xff1a;《Design Patterns for Embedded Systems in C ——An Embedded Software Engineering Toolkit 》&#xff0c;讲解的是嵌入式系统设计模式&#xff0c;是一本不可多得的好书。 本系列描述我对书中内容的理解。本文章描述嵌入式并发和资源管理模式之二…

python实现AES加密解密

1. 前言 AES是一种对称加密&#xff0c;所谓对称加密就是加密与解密使用的秘钥是一个。 之前写过一片关于python AES加密解密的文章&#xff0c;但是这里面细节实在很多&#xff0c;这次我从 参数类型、加密模式、编码模式、补全模式、等等方面 系统的说明如何使用AES加密解密…

网络编程day3

1.思维导图 2.TCP机械臂测试 通过&#xff1a;w(红色臂角度增大) s(红色臂角度减小) d(蓝色臂角度增大) a(蓝色臂角度减小) 按键控制机械臂 注意&#xff1a;关闭计算机的杀毒软件&#xff0c;电脑管家&#xff0c;防火墙 1&#xff09;基于TCP服务器的机械臂&#xff0c;端…

Java智慧云HIS医院信息化系统源码 更具灵活性、扩展性

目录 什么是云HIS 趋势与转变 HIS上云后有哪些好处 解决方案 云HIS组成 1、门诊挂号 2、住院管理 3、电子病历 4、药物管理 5、统计报表 6、综合维护 7、运营运维 什么是云HIS 云HIS是一种基于云计算技术的医院信息管理系统。云HIS可以帮助医院管理各类医院信息&a…