平移旋转缩放
平移
在顶点着色器中修改顶点位置的 xyz 值即可
缩放
为了防止朝负方向缩放,+1.0 作为基础值,使原点永远乘以正值
1 2 3 4
| void Scale(inout float3 vertex) { vertex.xyz *= 1.0 + _ScaleRange * sin(frac(_Time.z * _ScaleSpeed) * UNITY_TWO_PI); }
|
旋转
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| void Rotate(inout float3 vertex) { float angleY = _RotateRange * sin(frac(_Time.z * _RotateSpeed) * UNITY_TWO_PI); float radY = radians(angleY); sincos(radY, sinY, cosY); vertex.xz = float2( vertex.x * cosY - vertex.z * sinY, vertex.x * sinY + vertex.z * cosY ); }
|
广告牌 Billboarding
广告牌总是面对着摄像机,
广告牌技术的本质就是构建旋转矩阵,而我们知道一个变换矩阵需要 3 个基向量。广告牌技术使用的基向量通常就是表面法线 (normal)、指向上的方向 (up)以及指向右的方向(right) 除此之外,我们还需要指定一个锚点(anchor location),这个锚点在旋转过程中是固定不变的, 以此来确定多边形在空间中的位置。
构建 3 个相互正交的基向量。计算过程通常是,通过初始计算得到目标的表面法线(例如就是视角方向)和指向上的方向。两者不垂直但其中之一是固定的:
- 当模拟草丛时,我们希望广告牌的指向上的方向永远是 (0,1,0),而法线方向应该随视角变化;
- 当模拟粒子效果时,我们希望广告牌的法线方向是固定内,即总是指向视角方向,指向上的方向则可以发生变化。
这里我们**假设法线方向是固定的 (法线总是指向视角方向)
- 根据初始的表面法线和指向上的方向 $(0,1,0)$ 来 计算出目标方向的指向右的方向 (通过叉积操作): $right = cross(up,normal)$
- 归一化右向量,由法线和右向量叉积得出正交的向上方向 $up’=cross(normal,right)$

Unity 模型要选择 Quad 而不能是 Plane,因为代码要求的多边形的顶点结构在模型空间下必须是竖直排列的。这样才能得到正确的相对于锚点的位置偏移量
fold title:广告牌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 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
| Shader "Custom/SimplerColor" { Properties { [MainTexture] _MainTex ("MainTex", 2D) = "white" {} [MainColor] _BaseColor("BaseColor", Color) = (1,1,1,1) _VerticalBillborading("垂直方向约束",Range(0,1)) = 1 } SubShader { Tags { "RenderType"="Transparent" "Queue" = "Transparent" "RenderPipeline" = "UniversalPipeline" } HLSLINCLUDE #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" CBUFFER_START(UnityPerMaterial) float4 _BaseColor; float4 _MainTex_ST; float _VerticalBillborading; CBUFFER_END
TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex); struct Attributes { float4 positionOS : POSITION; float2 uv : TEXCOORD0; };
struct Varyings { float4 positionCS : SV_POSITION; float2 uv : TEXCOORD0;
}; ENDHLSL
Pass { Blend SrcAlpha OneMinusSrcAlpha ZWrite Off Cull Off Tags { "LightMode" = "UniversalForward" } HLSLPROGRAM #pragma vertex vert #pragma fragment frag
Varyings vert(Attributes input) { Varyings output = (Varyings)0;
float3 centerOS = float3(0,0,0); float3 viewDirOS = TransformWorldToObject(_WorldSpaceCameraPos); float3 normalDirOS = viewDirOS - centerOS;
normalDirOS.y = normalDirOS.y* _VerticalBillborading; normalDirOS = normalize(normalDirOS);
float3 upDir = abs(normalDirOS.y)>0.999?float3(0,0,1):float3(0,1,0); float3 rightDir = normalize(cross(upDir,normalDirOS)); upDir = normalize(cross(normalDirOS,rightDir));
float3 centerOffs = input.positionOS.xyz - centerOS; float3 newPosOS = centerOS + centerOffs.x * rightDir + centerOffs.y * upDir + centerOffs.z * normalDirOS; output.positionCS = TransformObjectToHClip(newPosOS); output.uv =input.uv.xy * _MainTex_ST.xy + _MainTex_ST.zw; return output; }
float4 frag(Varyings input) : SV_Target { float4 MainTex = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, input.uv); float4 finalColor = MainTex * _BaseColor; return finalColor; } ENDHLSL } } FallBack "Packages/com.unity.render-pipelines.universal/FallbackError" }
|