在shader中使用极坐标绘图

利用极坐标绘制图案

极坐标系统中任意位置可由一个夹角和一段相对原点—极点的距离来表示。极坐标系统Polar coordinate system方程:

x = r c o s θ y = r s i n θ r = x 2 + y 2 θ = a t a n 2 ( x , y ) = a t a n ( y x ) x=rcosθ\\ y=rsinθ\\ r=\sqrt{x^2+y^2}\\ θ=atan2(x,y)=atan(\frac{y}{x}) x=rcosθy=rsinθr=x2+y2 θ=atan2(x,y)=atan(xy)
在这里插入图片描述

极坐标与直角坐标相互转换代码:

// 直角坐标影射为极坐标
function toPolar(x, y) { 
    const r = Math.hypot(x, y); 
    const θ= Math.atan2(y, x); 
    return [r, θ];
}
//在shader中通常写成:
vec2 pos = vec2(0.5)-st;//将坐标系统转化为[-0.5,0.5]
float r = length(pos)*2.0;
float a = atan(pos.y,pos.x);

// 极坐标映射为直角坐标
function fromPolar(r, θ) { 
    const x = r * cos(θ); 
    const y = r * sin(θ); 
    return [x, y];
}

[1]用极坐标绘制圆

首先将st直角坐标系原点移动到画布中心,然后将其转为极坐标系统,最后利用极坐标的性质绘图。例如下图的圆因为在及坐标系中圆的半径是一个常量值,所以取 smoothstep(st.x, st.x + 0.01, 0.2),就能得到一个半径为 0.2 的圆了(也是采用距离场的思想),而在直角坐标系中,点到圆心的距离 d 需要用 x、y 平方和的开方来计算,而在极坐标下,点的极坐标 r 值正好表示了点到圆心的距离 d,所以计算起来就比直角坐标系简单了很多。

在这里插入图片描述

可以对比使用直角坐标系和极坐标系绘制相同的圆的思想:

float r = length(st);
float c = smoothstep(0.2,0.2,r);
gl_FragColor = vec4(vec3(c,c,c),1.0);

下面对于使用极坐标的另一种方式画圆
在这里插入图片描述

在这里插入图片描述

[2]利用相应的极坐标方程绘制复杂的曲线图

下面利用一些极坐标方程绘制复杂些的图形

使用玫瑰线的极坐标方程 r = a ∗ c o s ( k ∗ θ ) r = a * cos(k * θ) r=acos(kθ)绘制如下图形,利用距离场的思维所有玫瑰线上的点都满足 0 = a ∗ c o s ( k ∗ θ ) − r 0 = a * cos(k * θ) - r 0=acos(kθ)r,最后以距离场的形式(并根据情况填写a、k 参数)写入下面代码及可绘制相应的图案

在这里插入图片描述

了解了玫瑰线的绘制之后在其之上绘制一些图形便变得简单得多了,例如直接修改k参数

[3]圆柱坐标

圆柱坐标可以说是极坐标的三维形式,在极坐标的基础下添加了z轴分量,通常使用它来绘制一些三维曲线,比如螺旋线、圆内螺旋线、费马曲线等等。

在这里插入图片描述

因为极坐标系可以和直角坐标系相互转换,所以直角坐标系和圆柱坐标系也可以相互转换,公式如下:

在这里插入图片描述

从上面的公式中你会发现,我们只转换了 x、y 的坐标,因为它们是极坐标,而 z 的坐标因为本身就是直角坐标不用转换。因此圆柱坐标系又被称为半极坐标系

[4]球坐标

我们还可以进一步将圆柱坐标系转为球坐标系,而球坐标系通常在三维图形绘制、球面定位、碰撞检测等等可视化实现中使用到。

在这里插入图片描述

同样地,圆柱坐标系也可以和球坐标系相互转换,公式如下

在这里插入图片描述

### 极坐标Shader中的应用 #### 使用极坐标转换实现径向渐变效果 为了在着色器中利用极坐标系,可以将笛卡尔坐标 (x, y) 转换成极坐标 (r, θ),其中 r 表示半径距离而 θ 是角度。这种变换对于创建基于中心点辐射的效果非常有用。 ```hlsl float2 cartesianToPolar(float2 uv){ float angle = atan2(uv.y - 0.5, uv.x - 0.5); float radius = length(uv - 0.5); return float2(radius, angle); } ``` 上述代码片段展示了如何通过 `atan2` 函数计算给定点相对于屏幕中心的角度,并使用 `length()` 来获取该点到中心的距离[^1]。 #### 创建漩涡效果 当涉及到更复杂的视觉特效时,比如漩涡效果,则可以通过调整 UV 坐标的旋转来模拟物体围绕某一点打转的现象。这通常涉及到了时间变量 t 的引入以及对原始坐标的偏移操作: ```hlsl // 时间参数t用于控制动画速度 half timeOffset = _Time * speed; // 将UV映射至[-1,1]区间内方便处理 float2 centeredUV = input.uv.xy * 2 - 1; // 计算当前像素位置对应的极角并加上随时间变化的相位差 float theta = atan2(centeredUV.y ,centeredUV.x ) + timeOffset; // 根据新的θ重新计算xy分量从而形成扭曲后的纹理采样坐标 outputColor.rgb = tex2D(_MainTex,float2(cos(theta),sin(theta))*.5+.5).rgb; ``` 这段 HLSL 代码实现了基本的漩涡变形逻辑,它会随着渲染帧数增加不断改变图像上各点的位置,最终呈现出一种被吸入黑洞般的动态感[^2]。 #### 利用噪声函数增强自然度 为了让生成的结果看起来更加真实随机,在某些情况下还可以结合 Perlin 或 Simplex 这样的经典算法所提供的伪随机数值作为扰动因子加入进来,使得整个过程不再那么机械刻板: ```c // 添加Perlin Noise干扰项让漩涡边缘显得不那么生硬 float noiseValue = snoise(input.worldPos.xyz *_NoiseScale ); theta += noiseValue*_Strength ; ``` 这里运用了空间噪波技术(如 simplex noise),并通过调节强度系数 `_Strength` 和尺度比例 `_NoiseScale` 参数来自定义所期望达到的具体外观特征[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

seeooco

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值