用代码在极坐标下画一朵花

707 阅读4分钟

在实际画画中,我们面对是一个白纸,其实就是一个笛卡尔坐标系。有另外一个坐标叫做极坐标,在这个坐标系的函数很多都有美妙螺旋,重复。本文将学习Shader的极坐标的一些基本用法,下面都是社区中一些美妙的极坐标绘图

2406221651

www.shadertoy.com/view/WsScDK

2406221234 www.shadertoy.com/view/XtcfRH

极坐标介绍

极坐标系统和笛卡尔坐标系统都是描述平面上点位置的方法,但是使用不同的方式来表示这些点。两个坐标系在解决不同类型的问题时都很有用。例如,有些时候极坐标对于解决涉及圆形或斜率的问题更为直观和简洁,而笛卡尔坐标则在处理与直角相关的问题方面更为方便。

笛卡尔坐标系统(Cartesian Coordinate System)

笛卡尔坐标系统是一种使用两个或三个数值来确定点位置的直角坐标系统。在二维空间中,一个点的位置通过一个横坐标(X轴上的值)和一个纵坐标(Y轴上的值)来指定。如果我们将这些坐标放置在一个图上,横坐标(x)定义了点沿着X轴的位置,而纵坐标(y)定义了点沿着Y轴的位置。在三维空间中,这个系统增加了第三个坐标(z),用于沿Z轴的位置。

例如,笛卡尔坐标点 (3, 4) 指的是距离原点(交点,通常是 (0, 0))沿着X轴移动3个单位,沿着Y轴移动4个单位的位置。

极坐标系统(Polar Coordinate System)

与笛卡尔坐标相比,极坐标通过一个点与极点(通常是原点或 (0, 0))之间的直线距离(半径r)和该直线与参考方向(通常是X轴的正方向)之间的角度(极角θ)来定位点的位置。

在极坐标中,一个点表示为 (r, θ),其中r是半径,θ是角度。角度通常用度或弧度来度量,而半径则是一个非负实数。

例如,极坐标点 (5, π/3) 表示一个距离极点(原点)5个单位长度,从参考方向(X轴正方向)逆时针旋转π/3弧度的位置。

Shader绘制坐标

2406224012

公式

这两个系统之间存在转换公式,允许你将一个点从一个系统转换到另一个系统。

从极坐标到笛卡尔坐标:

x=rcos(θ)y=rsin(θ)x = r \cdot \cos(\theta) \\ y = r \cdot \sin(\theta)

从笛卡尔坐标到极坐标:

r=x2+y2θ=arctan(yx)r = \sqrt{x^2 + y^2} \\ \theta = \arctan\left(\frac{y}{x}\right)

笛卡尔坐标绘制

在上一节和之前很多文章里面,都是用了 fract 去做空间重复,画笛卡尔坐标其实就是画一堆格子,思考逻辑是我将变成了很多[0, 1] , 当x或者y 小于 0.01的时候,画白色,否者画黑色

	// 
    vec2 uv = (2.*fragCoord.xy - iResolution.xy) / iResolution.y;
   
    float fraction = 1.;
    uv = fract(uv * fraction);
    uv = 2. * uv - 1.0;  
	float d = min(abs(uv.x), abs(uv.y));
	float c = smoothstep(-0.02, 0.02, d);
    vec3 col = vec3( 1.0, 1.0, 1.0 ) * ( c);

于是出现下面图形 2406225307

极坐标绘制

写shader一定要时刻提醒自己,永远在[-1, 1] 或者 [0, 1]的空间里面做事情。 一个圆的所有角度加起来是2π=6.282\pi=6.28。在使用角度的时候转化到[0, 1] . 用 st 表示极坐标, 于是有


vec2 st = vec2(atan(uv.x, uv.y), length(uv));
st.x = st.x / 2.0 / PI + .5;

这个时候如果用角度作为颜色,可以看到一个从黑到白的圆,表示着值从0到1 2406225947 同样,角度接近于0或者2派时,我们画白色,否者画黑色


   float cc = min(st.x, 1.-st.x);
    vec3 col = cc <= 0.01 ? vec3(1.0): vec3(0.0);
    

2406220329

这个时候如果我们对于角度做fract, 其实就是对圆进行分割, 同时使用1x\frac{1}{x}

    st.x = fract(st.x * 3.0);
	vec3 col = vec3(1.0) * 0.008 / st.x; 

2406220723

同时对极坐标第二个参数距离,做fract,就可以获得多个同心圆

    float c1 = 0.02 / min(st.y, 1.0-st.y);
    float c2 = 0.02 / (min(st.x, 1.0-st.x));
    vec3 col = vec3(1.0) * (c1 + c2);

2406220944

画一个花瓣

旋转

在极坐标下,旋转是一个非常简单的事情。 只需要给角度加上一个时间,就能得到完美的旋转。

    st.x += iTime * 0.2;

2406221355

笛卡尔坐标下的锯齿

2406221943 以上的函数形成了一个锯齿。如果将这个函数放到笛卡尔坐标下,同时让x轴随着时间改变。 就会得到一个移动的锯齿

	uv.x += iTime;
    uv.x = fract(uv.x * 2.0);
    uv.x = min(uv.x, 1.0 - uv.x);
    float m = uv.x - uv.y;  

2406223130

极坐标下的花瓣

如果吧上面的锯齿逻辑放到极坐标下,就会有奇妙的花瓣效果,所要做的只是将uv笛卡尔坐标,改为st极坐标

	st.x += iTime;
    st.x = fract(st.x * 3.0);
    st.x = min(st.x, 1.0 - st.x);
    float m = st.x - st.y;

2406223423

REFERENCE