Unity Shader学习(六)---高级渲染

这篇博客详细介绍了Unity Shader在高级渲染方面的应用,包括抗锯齿技术、实现素描风格的渲染以及模拟水波效果。通过调整Shader属性,可以创建出具有真实感的轮廓线、细腻的素描纹理和波动的水面。内容涵盖Shader代码和相关技术原理。
摘要由CSDN通过智能技术生成
(一)非真实感渲染
(1)卡通风格渲染
基于色调的着色技术:使用漫反射系数对一张以为纹理进行采样,以控制漫反射的色调。
渲染轮廓线:
基于观察角度和表面法线的轮廓线渲染:使用视角方向和表面法线的点乘结果来得到轮廓线的信息。在一个Pass中但效果不好。
过程式几何轮廓线渲染:第一个Pass渲染背面的面片,并使用某些技术让它的轮廓可见;第二个Pass再正常渲染正面的面片。该方法适用于大不多表面光滑的模型,不适用于立方体这样的平整的模型。
基于图像处理的轮廓线渲染:之前介绍的边缘检测就是这样的方法,但是深度和法线变化很小的轮廓无法检测出来。
基于轮廓边检测的轮廓线渲染:检测一条边是否是轮廓线公式: (n0*v>0)!= (n1*v>0) n0 n1为相邻两个三角面片的法向,v是从视角到该边上人意顶点的方向。公式的本质在于检查两个相邻三角面片是否一个朝正面,一个朝背面。但是动画连贯性时会出现帧与帧之间的跳跃性。
最后就是混合上述几种渲染方法,首先找到精确的轮廓边,把模型和轮廓边渲染到纹理中,在使用图像处理的方法识别出轮廓线,并在图像空间下进行风格化渲染。


本例子中使用几何轮廓线渲染方法进行描边。第一个Pass用轮廓线颜色渲染整个背面,并在视角空间下把模型顶点沿着法线方向向外扩张一段距离,以此让背部轮廓线可见。
viewPos = viewNormal * _Outline
但是如果直接使用顶点法线进行扩展,对于一些内凹的模型,可能会发生背面面片遮挡正面面片的情况。我们可以在扩张背面顶点之前,先对顶点法线的z分量进行处理,是他们等于一个定值,然后把法线归一化后再对顶点进行扩张。使扩展后的背面更加扁平化,从而降低了遮挡正面面片的可能性。
viewNormal.z = -0.5
viewNormal = normalize(viewNormal)
viewPos = viewPos + viewNormal * _Outline
blinn-phong模型:float spec = pow(max(0,dot(normal,halfDir)),_Gloss) 对于卡通渲染中的高光反射光照模型,与其类似,但是需要进行一个阈值比较,如果小于该阈值高光反射系数为0,否则返回1.
float spec = dot(worldNormal,worldHalfDir)
spec = step(threshold,spec)
step是CG中的函数,第一个参数是参考值,第二个参数是待比较的数值,第二个参数大于第一个参数,则返回1,否则返回0.
这种方法容易产生锯齿,可以用smoothstep函数。
spec = lerp(0,1,smoothstep(-w,w,spec-threshold))

w是一个很小的值,当spec-threshold小于-w时,返回0,大于w时返回1,否则在0,1间插值。这就实现的抗锯齿。本例子中w为邻域像素之间的近似导数值,可以通过CG的fwidth函数来得到。 

Shader "Unity Shaders Book/Chapter 14/Toon Shading" {
    Properties {
        _Color ("Color Tint"Color) = (1111)
        _MainTex ("Main Tex"2D) = "white" {}
        _Ramp ("Ramp Texture"2D) = "white" {}//控制漫反射色调的渐变纹理
        _Outline ("Outline"Range(01)) = 0.1//控制轮廓线的宽度
        _OutlineColor ("Outline Color"Color) = (0001)//轮廓线颜色
        _Specular ("Specular"Color) = (1111)//高光反射颜色
        _SpecularScale ("Specular Scale"Range(00.1)) = 0.01//高光反射时的阈值
    }
    SubShader {
        Tags { "RenderType"="Opaque" "Queue"="Geometry"}
        
        Pass {
            NAME "OUTLINE"//描边是常用的渲染           
            Cull Front//只渲染背面           
            CGPROGRAM           
            #pragma vertex vert
            #pragma fragment frag            
            #include "UnityCG.cginc"           
            float _Outline;
            fixed4 _OutlineColor;           
            struct a2v {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
            };           
            struct v2f {
                float4 pos : SV_POSITION;
            };           
            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;
            }          
            float4 frag(v2f i) : SV_Target { 
                return float4(_OutlineColor.rgb1);               
            }           
            ENDCG
        }        
        Pass {
            Tags { "LightMode"="ForwardBase" }            
            Cull Back//只渲染正面        
            CGPROGRAM       
            #pragma vertex vert
            #pragma fragment frag           
            #pragma multi_compile_fwdbase        
            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            #include "AutoLight.cginc"
            #include "UnityShaderVariables.cginc"          
            fixed4 _Color;
            sampler2D _MainTex;
            float4 _MainTex_ST;
            sampler2D _Ramp;
            fixed4 _Specular;
            fixed _SpecularScale;       
            struct a2v {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
                float4 texcoord : TEXCOORD0;
                float4 tangent : TANGENT;
            };         
            struct v2f {
                float4 pos : POSITION;
                float2 uv : TEXCOORD0;
                float3 worldNormal : TEXCOORD1;
                float3 worldPos : TEXCOORD2;
                SHADOW_COORDS(3)
            };            
            v2f vert (a2v v) {
                v2f o;               
                o.pos = UnityObjectToClipPos( v.vertex);
                o.uv = TRANSFORM_TEX (v.texcoord, _MainTex);
                o.worldNormal  = UnityObjectToWorldNormal(v.normal);
                o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;               
                TRANSFER_SHADOW(o);                
                return o;
            }           
            float4 frag(v2f i) : SV_Target { 
                fixed3 worldNormal = normalize(i.worldNormal);
                fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
                fixed3 worldViewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
                fixed3 worldHalfDir = normalize(worldLightDir + worldViewDir);              
                fixed4 c = tex2D (_MainTex, i.uv);
                fixed3 albedo = c.rgb * _Color.rgb;                
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;//自然光                
                UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);               
                fixed

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值