一、前因
前几天刷完了最近特别火的一部电视剧《隐秘的角落》,里面秦昊饰演的张东升提到了一个笛卡尔的心形函数:r=a(1-sinθ)。
出于好奇我就去查了一下这个函数的图形,但感觉并不恨像心行,有点像桃子。
所以我打算使用Unity的Shader画一个更好的心形函数。
二、实现
1.要渲染到全屏,就需要相机Camera的Texture进行材质修改,所以先创建一个RenderTexture的脚本
1 2 3 4 5 6 7 8 9 | public class RenderControl : MonoBehaviour { [SerializeField] Material mat; private void OnRenderImage(RenderTexture source, RenderTexture destination) { Graphics.Blit(destination, mat); } } |
把它挂在场景的相机上
赋予材质Test1然后就是对改材质的shader进行编写。
2.先在网上找一个心形函数的公式
在Shader进行改公式的计算
1 2 3 4 5 6 7 8 9 10 11 12 13 | float heart(float2 st) { //调整位置 st = (st - float2(0.5, 0.38)) * float2(2.1, 2.8); //心形函数计算 return pow(st.x, 2) + pow(st.y - sqrt(abs(st.x)), 2); } fixed4 frag (v2f i) : SV_Target { float d = heart(i.uv); return d; } |
的到如下心形图案
使用step()函数让心形的边界分明
1 | d = step(d, 1); |
得到如下图
还可以让心动起来
1 | d = step(d, abs(sin(d * 8 - _Time.w * 2))); |
最后在给它加个红色
1 2 3 4 5 6 7 8 9 | float d = heart(i.uv); //循环动画 d = step(d, abs(sin(d * 8 - _Time.w * 2))); //上色 float4 col = fixed4(d, 0.2, 0.21, 1); if(d < 1){ col = fixed4(d, 0, 0, 1); } return col; |
三、最终效果
四、完整shader代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | Shader "XYH/Test1" { Properties { _MainTex ("Texture", 2D) = "white" {} } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; UNITY_FOG_COORDS(1) float4 vertex : SV_POSITION; }; sampler2D _MainTex; float4 _MainTex_ST; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); return o; } float heart(float2 st) { //调整位置 st = (st - float2(0.5, 0.38)) * float2(2.1, 2.8); //心形函数计算 return pow(st.x, 2) + pow(st.y - sqrt(abs(st.x)), 2); } fixed4 frag (v2f i) : SV_Target { float d = heart(i.uv); //循环动画 d = step(d, abs(sin(d * 8 - _Time.w * 2))); //上色 float4 col = fixed4(d, 0.2, 0.21, 1); if(d < 1){ col = fixed4(d, 0, 0, 1); } return col; } ENDCG } } } |