Unity Shader 学习笔记(27)渲染轮廓线(描边)方法、卡通风格渲染、素描风格渲染

来源:互联网 发布:linux版jdk1.8下载 编辑:程序博客网 时间:2024/04/28 10:23

Unity Shader 学习笔记(27)渲染轮廓线(描边)方法、卡通风格渲染、素描风格渲染

参考书籍:《Unity Shader 入门精要》


渲染轮廓线(描边)

五种方法:
- 基于观察角度和表面法线。即视角方向和表面法线点乘结果判断(接近0,表示面接近垂直与视角)。
- 过程式几何。两个Pass:第一个Pass渲染背面并且让轮廓可见(顶点外扩);第二个Pass正常渲染正面。适应于大多数表面平滑的模型,不适合立方体等平整模型。
- 基于图像处理。前面两种边缘检测就是了:直接用算子判断和使用深度和法线纹理。但如果一些深度和法线变化很小的无法检测出来,如桌子上一张纸。
- 基于轮廓边。检测方法:相邻两个三角是否一个面向视角,另一个背向视角,就是边。即 (n0·v > 0) ≠ (n1·v > 0)。 缺点是轮廓是逐帧单独提取的,帧与帧之间会出现跳跃性。
- 混合上述方法。首先找到轮廓线(方法4),把模型和轮廓边渲染到纹理中,再使用图像处理识别轮廓线(方法3),在图像空间进行风格化渲染。


卡通风格渲染

使用描边方法2,以及卡通风格的高光反射光照模型实现。
描边注意:在背面顶点扩展时,可能有正面的面,这时会出错。可想象一个半实心球,内部有个面向视角的面,顶点外扩时,内部的面会超出外表面,遮挡了外表面。解决办法是先让背面法线z值减0.5再归一化(背面压扁)。
高光实现:镜面反射使用Blinn模型,计算(n·h)时,做阈值比较,小于的就是高光部分。

Shader "Custom/Chapter 14/Toon Shading" {    Properties {        _Color ("Color Tint", Color) = (1, 1, 1, 1)        _MainTex ("Main Tex", 2D) = "white" {}        _Ramp ("Ramp Texture", 2D) = "white" {}                     // 漫反射渐变纹理        _Outline ("Outline", Range(0, 1)) = 0.1                     // 轮廓线宽度        _OutlineColor ("Outline Color", Color) = (0, 0, 0, 1)       // 轮廓线颜色        _Specular ("Specular", Color) = (1, 1, 1, 1)        _SpecularScale ("Specular Scale", Range(0, 0.1)) = 0.01     // 高光反射的阈值    }    SubShader {        Tags { "RenderType"="Opaque" "Queue"="Geometry"}        // 第一个Pass,延展背面顶点,实现描边。        Pass {            NAME "OUTLINE"            Cull Front      // 剔除正面,只渲染正面            ...            v2f vert (a2v v) {                v2f o;                // 顶点和法线变换到视角空间下,让描边可以在观察空间达到最好的效果                float4 pos = mul(UNITY_MATRIX_MV, v.vertex);                 float3 normal = mul((float3x3)UNITY_MATRIX_IT_MV, v.normal);                  normal.z = -0.5;    // 让法线向视角方向外扩,避免物体有背面遮挡正面                pos = pos + float4(normalize(normal), 0) * _Outline;        //对外扩展,出现轮廓                o.pos = mul(UNITY_MATRIX_P, pos);                return o;            }            ...        }        // 第二个Pass,基于Blinn光照模型,使用自定义高光光照模型,实现高光。        Pass {            Tags { "LightMode"="ForwardBase" }            Cull Back            ...            float4 frag(v2f i) : SV_Target {                 ...                fixed spec = dot(worldNormal, worldHalfDir);                // 高光区域抗锯齿操作,fwidth:邻域像素的近似导数。                fixed w = fwidth(spec) * 2.0;                       // _SpecularScale为0会完全消除高光反射,smoothstep:小于-w为0,大于w为1,否则在01之间插值。                fixed3 specular = _Specular.rgb * lerp(0, 1, smoothstep(-w, w, spec + _SpecularScale - 1)) * step(0.0001, _SpecularScale);                    return fixed4(ambient + diffuse + specular, 1.0);            }            ENDCG        }    }    FallBack "Diffuse"}

素描风格渲染

通过判断不同光照下漫反射值,使用不同的渲染纹理。纹理组成一个色调艺术映射(Tonal Art Map, TAM)。

// 素描风格Shader "Custom/Chapter 14/Hatching" {    Properties {        _Color ("Color Tint", Color) = (1, 1, 1, 1)        _TileFactor ("Tile Factor", Float) = 1  // 平铺系数        _Outline ("Outline", Range(0, 1)) = 0.1        _Hatch0 ("Hatch 0", 2D) = "white" {}    // 6张素描纹理,模拟不同阴影使用的纹理        _Hatch1 ("Hatch 1", 2D) = "white" {}        _Hatch2 ("Hatch 2", 2D) = "white" {}        _Hatch3 ("Hatch 3", 2D) = "white" {}        _Hatch4 ("Hatch 4", 2D) = "white" {}        _Hatch5 ("Hatch 5", 2D) = "white" {}    }    SubShader {        Tags { "RenderType"="Opaque" "Queue"="Geometry"}        UsePass "Custom/Chapter 14/Toon Shading/OUTLINE"    // 使用前面的描边渲染Pass        Pass {            ...            struct v2f {                float4 pos : SV_POSITION;                float2 uv : TEXCOORD0;                fixed3 hatchWeights0 : TEXCOORD1;   // 6张纹理存在两个fixed3中                fixed3 hatchWeights1 : TEXCOORD2;                float3 worldPos : TEXCOORD3;                SHADOW_COORDS(4)            };            v2f vert(a2v v) {                ...                o.hatchWeights0 = fixed3(0, 0, 0);                o.hatchWeights1 = fixed3(0, 0, 0);                float hatchFactor = diff * 7.0; // 放大7倍,便于分成7块,混合权重。                if (hatchFactor > 6.0) {                    // 纯白                } else if (hatchFactor > 5.0) {                    o.hatchWeights0.x = hatchFactor - 5.0;                } else if (hatchFactor > 4.0) {                    o.hatchWeights0.x = hatchFactor - 4.0;                    o.hatchWeights0.y = 1.0 - o.hatchWeights0.x;                } else if (hatchFactor > 3.0) {                    o.hatchWeights0.y = hatchFactor - 3.0;                    o.hatchWeights0.z = 1.0 - o.hatchWeights0.y;                } else if (hatchFactor > 2.0) {                    o.hatchWeights0.z = hatchFactor - 2.0;                    o.hatchWeights1.x = 1.0 - o.hatchWeights0.z;                } else if (hatchFactor > 1.0) {                    o.hatchWeights1.x = hatchFactor - 1.0;                    o.hatchWeights1.y = 1.0 - o.hatchWeights1.x;                } else {                    o.hatchWeights1.y = hatchFactor;                    o.hatchWeights1.z = 1.0 - o.hatchWeights1.y;                }                o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;                TRANSFER_SHADOW(o);                return o;             }            fixed4 frag(v2f i) : SV_Target {                            fixed4 hatchTex0 = tex2D(_Hatch0, i.uv) * i.hatchWeights0.x;                fixed4 hatchTex1 = tex2D(_Hatch1, i.uv) * i.hatchWeights0.y;                fixed4 hatchTex2 = tex2D(_Hatch2, i.uv) * i.hatchWeights0.z;                fixed4 hatchTex3 = tex2D(_Hatch3, i.uv) * i.hatchWeights1.x;                fixed4 hatchTex4 = tex2D(_Hatch4, i.uv) * i.hatchWeights1.y;                fixed4 hatchTex5 = tex2D(_Hatch5, i.uv) * i.hatchWeights1.z;                // 全白和最浅的纹理混合。                fixed4 whiteColor = fixed4(1, 1, 1, 1) * (1 - i.hatchWeights0.x - i.hatchWeights0.y - i.hatchWeights0.z -                             i.hatchWeights1.x - i.hatchWeights1.y - i.hatchWeights1.z);                fixed4 hatchColor = hatchTex0 + hatchTex1 + hatchTex2 + hatchTex3 + hatchTex4 + hatchTex5 + whiteColor;                UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);                return fixed4(hatchColor.rgb * _Color.rgb * atten, 1.0);            }            ENDCG        }    }    FallBack "Diffuse"}
阅读全文
0 0
原创粉丝点击