WebGL 绘制Line的bug(二)

Blazor开发WEB程序 Blazor从0到1开发一个项目所遇到的问题汇总 阅读详情

基本思路

上一篇文章简单介绍了WebGL绘制Line的bug,这一篇文章会讲述解决这个问题的work around。

上一篇文章结尾简单提了下解决的思路,就是通过三角形来模拟线条。

以两个端点组成的线段为例,绘制line的时候只用指定两个端点,如果通过三角形来模拟一条线段,则至少需要两个三角形,如下图:


两个三角形模拟的线段

因此要绘制一条线段,则需要六个顶点,两个三角形;当时从上图中,可以看出有些顶点是共享,实际上只需要四个顶点,然后通过索引的方式绘制两个三角形,相信熟悉WebGL的同学都理解这种通过索引来绘制的方式,此处不详细说明。

如果要绘制两条相连的线段呢,则需要增加两个顶点,也就是6个顶点,绘制四个三角形,依次类推,绘制三条相连的线段需要8个顶点,绘制6个三角形;由此可以得出一个结论,绘制有n个端点的Line,需要:2 * n 个顶点, (n-1) * 2个三角形。

对于一条线段而言,控制的参数实际上只有两个端点的坐标和线的宽度。 

从上面的分析,我们知道了给定一系列点(n个)和线的宽度,绘制一条线段需要的顶点数是n * 2. 

如何计算顶点

两个端点的情况

当时 n个顶点数据应该如何计算得到呢? 先举个简单的2维绘图的例子,现在假设给定了两个端点:

(-50,0)和(50,0),要绘制一条宽度为2的线条,那么总共是四个顶点,第一个顶点是从第一个端点 + 线宽造成的偏移量,线宽为2,所以偏移量的基数应该是2 / 2 = 1;

第二个顶点是从第一个端点 + 线宽造成的偏移量 * (-1),同样线宽为2,所以偏移量的基数应该是2 /2 * (-1) = -1;

依次类推,那么应该如何偏移呢? 这个与线段的走向有关,示例中 线段的走向可以用第二个端点 - 第一个端点计算出来:

(50,0) - (-50,0) = (100,0) ,归一化之后就是(1,0),此为线段的方向向量,表示的线段的走向的是沿x轴正方向,对于第一顶点,偏移的方向应该是(1,0)逆时针旋转90度,即和线段走向垂直的方向(与线段垂直的方向有两个,此处基于右手法则,选择逆时针旋转90度的一个),旋转90度之后,向量编程了(0,-1)

从图形学里面的数学知识可以得知,向量(x,y)逆时针旋转90度变成(-y,x);

 对于第二个顶点,偏移的方向应该是(1,0)顺时针旋转90度,但是前面,我们已经把偏移的基数变成-1了,所以可以认为偏移的方向还是(1,0)逆时针旋转90度,如图:



基于线段方向计算顶点偏移方向

由此,可以得出第一个顶点的位置是:

(-50,0) - (0,-1)* 1 = (-50,-1),

第二个顶点的位置是:

(-50,0)-(0,-1) * 1 = (-50,1)

对于第三,第四个顶点的计算也是类似的。


多个端点的情况

上面讨论的是只有两个端点的情况,事实上,如果是多个端点,以上讨论的情况只适合多个端点中第一个端点和最后一个端点的情况,对于中间的端点,偏移的方向要综合考虑这个端点连接的两条线段的情况,同样举例说明:

假设三个端点的情况,三个端点 分别是 (-50,0),(0,0),(0,50),现在要计算第二个端点(0,0)对应的两个顶点(第三、第四个),如图:



三个端点

此时要计算中间的端点的两个顶点位置,则需要考虑改端点连接的两天线段的方向:



线段方向计算偏移方向

计算的大致思路,通过该端点的和前一个端点相减 计算出第一条线段的方向:

(0,0) - (-50,0) = (50,0) = (1,0)(归一化)

在通过该该端点的下一个端点减去该端点计算出第二条线段的方向:

(0,50) - (0,0) = (0,50) = (0,1)(归一化)

然后两个方向向量相加,在旋转逆时针旋转90度,可以得到偏移的方向:

(1,0) + (0,1) = (1,1) = (0.707,0.707)(归一化)

旋转之后,偏移方向编程了(-0.707,0.707),

需要注意的是,此时的的偏移基数其实也是发生了变化的,拐角处的偏移量此时应该变成大了,即有了一个放大因子。 可以通过 1 / 偏移方向 点乘 第一条线段的方向 来获取这个放大因子,不过如果两条线段夹角很小,点乘的值也很小,放大因子很大,为了拐角处的尖角不显得是否大,我们一般限定放大因子不超过2. 因此公式可以变成:

1 / max(偏移方向 .  第一条线段的方向,0.5)

如何组织顶点数据

上面大量篇幅讲述了如何计算顶点坐标,事实上,前面文字所述的一切计算方法都是发生在顶点着色器中的,而且也只能在着色器中计算,因为最终显示到屏幕上的顶点与镜头相关,上文中只是简单的用了2维的情况模拟,如果在js端计算,将极大消耗性能。 (那你不是瞎扯吗,我们都还没搞清楚如何计算出要传递给顶点着色器的数据呢),其实不是瞎扯,因为只有搞清楚了在着色器中如何计算最终的顶点,才知道如何向顶点着色器中组织数据,

以上文中“多个端点的情况”的为例,我们可以总结出计算出一个顶点需要哪些数据:

端点坐标,偏移量,前一个端点坐标,后一个端点坐标

因此在着色器中需要定义四个attribute变量 position,offset,positionPrev,positionNext,分别用来接收端点坐标,偏移量,前一个端点坐标,后一个端点坐标。

对于前面两顶点,其端点没有前一个端点,此时前一个端点就取端点坐标,然后在着色器中判断 如果前一个端点点坐标 == 端点坐标,则表明是第一个端点;使用两个端点的情况计算。

低于后面两个顶点,其端点没有后一个端点,此时后一个端点就取端点坐标,然后在着色器中判断 如果后一个端点点坐标 == 端点坐标,则表明是最后一个端点;使用两个端点的情况计算。

对于中间的顶点,既存在端点坐标,也存在前一个端点的坐标,和后一个端点的坐标,就使用前面多个端点的情况计算。

还是以之前三个端点的例子为例,三个端点的(50,0,0),(0,0,0),(0,50,0),线宽为2(注意此时已经是三维坐标了,之前模拟的情况是用屏幕上的2维坐标来模拟顶点在着色器中通过透视变换变成了二维坐标的情况)

那么第一个顶点的四个变量的数据分别是:

端点坐标,      偏移量,  前一个端点坐标,后一个端点坐标

(50,0,0),2/2,       (50,0,0)                  (0,0,0)

第二个顶点的四个变量的数据分别是:

端点坐标,      偏移量,  前一个端点坐标,后一个端点坐标

(50,0,0),-2/2,       (50,0,0)                  (0,0,0)


第三个顶点的四个变量的数据分别是:

端点坐标,      偏移量,  前一个端点坐标,后一个端点坐标

(0,0,0),2/2,       (50,0,0)                  (0,50,0)

第四个顶点的四个变量的数据分别是:

端点坐标,      偏移量,  前一个端点坐标,后一个端点坐标

(0,0,0),-2/2,       (50,0,0)                  (0,50,0)

第五个顶点的四个变量的数据分别是:

端点坐标,      偏移量,  前一个端点坐标,后一个端点坐标

(0,50,0),2/2,       (0,0,0)                  (0,50,0)

第六个顶点的四个变量的数据分别是:

端点坐标,      偏移量,  前一个端点坐标,后一个端点坐标

(0,50,0),-2/2,       (0,0,0)                  (0,50,0)

到此为止,我们知道了如何组织绘制需要的顶点的数据。

下一篇将贴上相关代码说明。

欢迎关注本人的公众号:ITman彪叔

WebGL 绘制Line的bug(一) 熟悉WebGL的同学都知道,WebGL绘制模式有点、线、面三种;通过点的绘制可以实现粒子系统等,通过线可以绘制一些连线关系;面就强大了,通过面,我们可以绘制我们想绘制的所有的三维对象。 一切看起来都很完美,perfect。 然而,不幸的是,WebGL在绘制线条的时候,存在一个缺陷,那就是在一些机器的一些浏览器上面(应该是大多数情况下)线宽只能设置为1,而不能设置成其他的值。 通过网址http 阅读详情

相关推荐

TWaver3D直线、曲线、曲面的绘制

如何绘制3D直线、曲线和曲面?TWaver手把手教你成为绘图大师!

TWaver可视化 3925

C#Web开发之blazor体验

使用blazor搭建一个局域网环境使用的APP管理平台。

大星星的专栏 4467

Blazor.WebGL

Blazor.WebGL Blazor的库将WebGL方法包装在画布中进行3D渲染。 用法 添加到您的_ViewImports.cshtml。 @using Blazor . WebGL @addTagHelper * , Blazor . WebGL 使用组件。 @inherits TestProject . MyComponent < WebGLCanvas xss=removed> 获取WebGLContext并将其用于您的需求。 namespace TestProject { public class MyComponent : BlazorComponent { protected WebGLCanvas Canvas { get ; set ; } protected override void On

探索与创新:Blazor Extensions Canvas——将HTML5 Canvas带入Blazor世界

在这个快速发展的Web开发领域中,[Blazor](https://blazor.net)以其独特的魅力和强大的潜力成为前端开发的新生力量。然而,在使用Blazor构建富交互应用时,有时我们可能会怀念HTML5的Canvas API。现在,有了[Blazor Extensions Canvas](https://github.com/BlazorExtensions/Canvas),我们可以无缝地

gitblog_00043的博客 1150

cpnucleo-blazor:一个示例应用程序,在构建.NET 5 Blazor WASM项目时可实现最佳性能

Cpnucleo剃刀 一个示例应用程序,在构建.NET 5 Blazor WASM项目时可实现最佳性能 如果您正在寻找为该客户端提供动力的API,请访问

Canvas:适用于Microsoft BlazorHTML5 Canvas API实现

帆布 适用于Microsoft BlazorHTML5 Canvas API实现 开拓者扩展 Blazor Extensions是一组软件包,目的是向添加有用的东西。 开拓者扩展画布 该软件包包装了 API。 Canvas 2D和WebGL均受支持。 Blazor服务器应用程序和Blazor WebAssembly应用程序均受支持。 注意当前以WebAssembly的3.2.0为目标的Blazor v3.1.5 安装 Install-Package Blazor.Extensions.Canvas 样本 用法 在index.html文件(WebAssembly Apps)或_Host.cshtml (服务器应用程序)文件中,放置对库脚本文件的引用: < script src =" _content/Blazor.Extensions.Canvas/blazor.extensions.

WebGL 绘制Line的bug(三)

之前铺垫了许多,今天可以来分享点纯干货了。 上一篇已经讲述了通过面模拟线条时候,每一个顶点的顶点数据包括:端点坐标、偏移量、前一个端点坐标、后一个端点坐标,当然如果我们通过索引的方式来绘制的话,还包括索引数组,下面的代码通过传递一组线条的端点数组来创建上述相关数据: bk.Line3D = function (points,colors){ this.points = p

TWaver可视化 1165

dotnet-Blazor实验UI框架通过webassembly在浏览器中运行NET

Blazor 实验UI框架通过webassembly在浏览器中运行.NET

eShopBlazor:一个使用Blazor并显示一些其他优化功能的eShop演示

eShopOnBlazor 将传统的ASP.NET Web窗体应用程序迁移到Blazor

宏杉MacroSan存储开局指导-流程

目录 1. 导入ODSP授权 2.1.版本确认 2.2.存储设备升级U盘、升级光盘制作方法 开局流程如下: 1. 导入ODSP授权 ODSP授权文件随设备附带,拆箱可见 2.1.版本确认 java模式 html模式 2.2.存储设备升级U盘、升级光盘制作方法 准备工具 空白U盘: 1个,容量要求大于等于4GB。仅制作升级U盘时需要。 制作升级U盘步骤 1.将U盘插入PC机USB口,保证PC机能识别到U盘。 2.运行UltraISO,选择菜单中的 文件-&g...

飞天板砖 4280

1173:阶乘和

1173:阶乘和 时间限制: 1000 ms 内存限制: 65536 KB 提交数: 6010 通过数: 3049 【题目描述】 用高精度计算出S=1!+2!+3!+…+n!(n≤50),其中“!”表示阶乘,例如:5!=5×4×3×2×1。 输入正整数n,输出计算结果S。 【输入】 一个正整数n。 【输出】 计算结果S。 【输入样例】 5 【输出样例】 153 思路: ...

zqhf123的博客 1261
上一篇: WebGL 绘制Line的bug(一)
下一篇: WebGL 单通道wireframe渲染
netcy
博客等级 码龄19年 189粉丝 158原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值