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.pswp.cn/news/714811.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/714811.shtml
英文地址,請注明出處:http://en.pswp.cn/news/714811.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

圖數據庫 之 Neo4j - 應用場景4 - 反洗錢(9)

原理 Neo4j圖數據庫可以用于構建和分析數據之間的關系。它使用節點和關系來表示數據,并提供實時查詢能力。通過使用Neo4j,可以將大量的交易數據導入圖數據庫,并通過查詢和分析圖結構來發現洗錢行為中的模式和關聯。 案例分析 假設有一家轉賬服務公司,有以下交易數據,每個…

YOLOv9有效改進|使用空間和通道重建卷積SCConv改進RepNCSPELAN4

專欄介紹&#xff1a;YOLOv9改進系列 | 包含深度學習最新創新&#xff0c;主力高效漲點&#xff01;&#xff01;&#xff01; 一、改進點介紹 SCConv是一種即插即用的空間和通道重建卷積。 RepNCSPELAN4是YOLOv9中的特征提取模塊&#xff0c;類似YOLOv5和v8中的C2f與C3模塊。 …

突破編程_C++_設計模式(建造者模式)

1 建造者模式的概念 建造者模式&#xff08;Builder Pattern&#xff09;是一種創建型設計模式&#xff0c;也被稱為生成器模式。它的核心思想是將一個復雜對象的構建與它的表示分離&#xff0c;使得同樣的構建過程可以創建不同的表示。 在建造者模式中&#xff0c;通常包括以…

MySQL進階:MySQL事務、并發事務問題及隔離級別

&#x1f468;?&#x1f393;作者簡介&#xff1a;一位大四、研0學生&#xff0c;正在努力準備大四暑假的實習、 &#x1f30c;上期文章&#xff1a;MySQL進階&#xff1a;視圖&&存儲過程&&存儲函數&&觸發器 &#x1f4da;訂閱專欄&#xff1a;MySQL進…

Docker Machine windows系統下 安裝

如果你是 Windows 平臺&#xff0c;可以使用 Git BASH&#xff0c;并輸入以下命令&#xff1a; basehttps://github.com/docker/machine/releases/download/v0.16.0 &&mkdir -p "$HOME/bin" &&curl -L $base/docker-machine-Windows-x86_64.exe >…

點燃技能火花:探索PyTorch學習網站,開啟AI編程之旅!

介紹&#xff1a;PyTorch是一個開源的Python機器學習庫&#xff0c;它基于Torch&#xff0c;專為深度學習和科學計算而設計&#xff0c;特別適合于自然語言處理等應用程序。以下是對PyTorch的詳細介紹&#xff1a; 歷史背景&#xff1a;PyTorch起源于Torch&#xff0c;一個用于…

【真機Bug】異步加載資源未完成訪問單例導致資源創建失敗

1.錯誤表現描述 抽卡時&#xff0c;10抽展示界面為A。抽取內容可能是整卡或者碎片&#xff0c;抽到整卡&#xff0c;會有立繪展示和點擊詳情的按鈕。點擊詳情后出現詳情頁B。【此時界面A預制體被銷毀&#xff0c;卡片數據進入數據緩存池】點擊頁面B的返回按鈕&#xff0c;單例…

C++——模版

前言&#xff1a;哈嘍小伙伴們好久不見&#xff0c;這是2024年的第一篇博文&#xff0c;我們將繼續C的學習&#xff0c;今天這篇文章&#xff0c;我們來習一下——模版。 目錄 一.什么是模版 二.模版分類 1.函數模版 2.類模板 總結 一.什么是模版 說起模版&#xff0c;我們…

線索二叉樹

線索二叉樹即從前、中、后序三種遍歷中其中一種來看&#xff0c;樹中的左右孩子都不會是空著的&#xff0c;都會指向對應的前驅和后驅。 以中序遍歷為例&#xff0c;二叉樹線索化過程如下&#xff1a; 先是樹的結構 typedef struct ThreadNode{Elemetype data;struct ThreadNo…

微服務面試題之套路一

面試題 一、你的項目是從SpringBoot演進到微服務架構的&#xff0c;你在此過程中有調研過哪些技術&#xff0c;怎么調研落地的? 微服務通信框架&#xff1a; 需要選擇適合項目的微服務通信框架&#xff0c;如Dubbo、Spring Cloud或gRPC Feign RestTemplate 等。調研方式可以是…

高性能通信之Netty

一, 同步IO(BIO)模型的架構 一般針對性能不高的情況下可以使用. 二,異步IO(NIO)模型的架構 多路復用(epoll模型):

【LeetCode:124. 二叉樹中的最大路徑和 + 二叉樹+遞歸】

&#x1f680; 算法題 &#x1f680; &#x1f332; 算法刷題專欄 | 面試必備算法 | 面試高頻算法 &#x1f340; &#x1f332; 越難的東西,越要努力堅持&#xff0c;因為它具有很高的價值&#xff0c;算法就是這樣? &#x1f332; 作者簡介&#xff1a;碩風和煒&#xff0c;…

前端開發人員如何做好SEO

前端開發人員如何做好SEO SEO工作不僅限于專業人員。前端開發者也可以在日常開發中實施一些代碼層面的SEO優化。 以下是一些前端常用的SEO方法&#xff1a; 設置合理的title、keywords、description title、keywords、description對SEO至關重要&#xff0c;需貼合頁面內容編…

Codeforces Round 931 (Div. 2) (A~B)

比賽&#xff1a;Codeforces Round 931 (Div. 2) (A~B) 目錄&#xff1a;A B A題&#xff1a;Too Min Too Max 標簽: 構造算法&#xff08;constructive algorithms&#xff09;貪心&#xff08;greedy&#xff09;數學&#xff08;math&#xff09; 題目大意 對數組 a 找到…

【力扣hot100】刷題筆記Day19

前言 回溯回溯回溯&#xff01;早上整理檔案竟然用了桶排序&#xff0c;不愧是算法狂魔們 79. 單詞搜索 - 力扣&#xff08;LeetCode&#xff09; DFS class Solution:def exist(self, board: List[List[str]], word: str) -> bool:m, n len(board), len(board[0])# used…

mysql timestamp轉換為datetime

MySQL timestamp轉換為datetime的方法 1. 流程概述 在MySQL中&#xff0c;timestamp和datetime是兩種不同的數據類型。timestamp存儲了日期和時間&#xff0c;并且會自動更新&#xff0c;可以用于記錄數據的創建和修改時間。datetime則是一個固定的日期和時間&#xff0c;不會自…

談談高并發系統的設計方法論

談談高并發系統的設計方法論 何為高并發系統&#xff1f;什么是并發&#xff08;Conurrent&#xff09;&#xff1f;什么是高并發&#xff08;Hight Concurrnet&#xff09;&#xff1f;高并發的衡量指標有哪些&#xff1f; 實現高并發系統的兩大板塊高并發系統應用程序側的設計…

騰訊云學生服務器使用教程_申請騰訊云學生機詳細流程

2024年騰訊云學生服務器優惠活動「云校園」&#xff0c;學生服務器優惠價格&#xff1a;輕量應用服務器2核2G學生價30元3個月、58元6個月、112元一年&#xff0c;輕量應用服務器4核8G配置191.1元3個月、352.8元6個月、646.8元一年&#xff0c;CVM云服務器2核4G配置842.4元一年&…

還在用Jenkins?快來試試這款簡而輕的自動部署軟件!

最近發現了一個比 Jenkins 使用更簡單的項目構建和部署工具&#xff0c;完全可以滿足個人以及一些小企業的需求&#xff0c;分享一下。 Jpom 是一款 Java 開發的簡單輕量的低侵入式在線構建、自動部署、日常運維、項目監控軟件。 日常開發中&#xff0c;Jpom 可以解決下面這些…

Nginx的多線程支持探究

文章中心思想: Nginx本身并不直接支持多線程處理模型。它采用的是基于事件驅動的單線程或多進程架構,而非多線程模型。然而,通過Nginx的模塊和第三方擴展,可以實現類似多線程的并發處理效果。 詳細說明: Nginx,作為一款高性能的Web服務器和反向代理服務器,其架構和并發…