zoukankan      html  css  js  c++  java
  • 游戏编程精粹学习

    灯光衰减图可以模拟3D贴图的效果,但也有一定的局限性。给灯光使用衰减图可以一定程度的控制灯光形状。

    应该也是某种程度的灯光cookie。

    使用衰减图与翻页动画制作的灯火效果:

    优点

    • 一定程度上的3D Texture
    • 可以拿来做摇曳灯火等

    缺点:

    • 定制性比较高,真正使用可能要借助CB
    • 相比3D Texture可控程度有限

    原文先从泛光灯公式讲起,后讲到XY与Z的贴图拆分。这里仅大致实现。测试shader如下:

    Shader "Custom/VirtualPointLight"
    {
        Properties
        {
            _MainTex("Texture", 2D) = "white" {}
            _AtteTex_XY("Atte Texture XY", 2D) = "white" {}
            _AtteTex_Z("Atte Texture Z", 2D) = "white" {}
            _VirtualLightPos("Virtual Light Position", vector) = (0, 0, 0, 0)
            _VirtualLightRange("Virtual Light Range", float) = 0.5
            _VirtualLightColor("Virtual Light Color", Color) = (0, 0, 0, 0)
            _Shininess("Shininess", range(0.1, 100)) = 1
        }
    
        SubShader
        {
            Tags{ "RenderType" = "Opaque" }
    
            Pass
            {
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
    
                #include "UnityCG.cginc"
    
                struct appdata
                {
                    float4 vertex : POSITION;
                    float2 uv : TEXCOORD0;
                    float3 normal :  NORMAL;
                };
    
                struct v2f
                {
                    float2 uv : TEXCOORD0;
                    float4 vertex : SV_POSITION;
                    float4 lightVolume : TEXCOORD1;
                    float3 d01 : TEXCOORD2;
                };
    
                sampler2D _MainTex;
    
                sampler2D _AtteTex_XY;
                sampler2D _AtteTex_Z;
    
                float4 _MainTex_ST;
                float4 _VirtualLightPos;
                float4 _VirtualLightColor;
                float _Shininess;
                float _VirtualLightRange;
    
                v2f vert(appdata v)
                {
                    v2f o;
                    o.vertex = UnityObjectToClipPos(v.vertex);
                    o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    
                    float4 worldPosition = mul(unity_ObjectToWorld, v.vertex);
                    float4 N = normalize(mul(unity_ObjectToWorld, v.normal));
                    float3 d = _VirtualLightPos - worldPosition;
    
                    o.d01 = d / _VirtualLightRange;
    
                    float3 L = d;
                    float3 V = normalize(_WorldSpaceCameraPos.xyz - worldPosition.xyz).xyz;
                    float3 H = normalize(L + V);
    
                    float4 diffuse = max(dot(N, L), 0);
                    float specular = pow(max(0, dot(H, N)), _Shininess);
    
                    o.lightVolume = diffuse + specular;
                    o.lightVolume = o.lightVolume;
    
                    return o;
                }
    
                fixed4 frag(v2f i) : SV_Target
                {
                    fixed4 col = tex2D(_MainTex, i.uv);
                    fixed d01_xy = tex2D(_AtteTex_XY, i.d01.xy + 0.5).r;
                    fixed d01_z = tex2D(_AtteTex_Z, half2(i.d01.z + 0.5, 0.5)).r;
    
                    fixed atte = 1 - (d01_xy + d01_z);
                    return col * _VirtualLightColor * (i.lightVolume * atte);
                }
                ENDCG
            }
        }
    }

    测试C#脚本:

    public class VirtualLightBind : MonoBehaviour
    {
        void Update()
        {
            material.SetVector("_VirtualLightPos", transform.position);
        }
    }
  • 相关阅读:
    memcache 应用场景
    如何写接口文档(登录)
    PHP常见错误级别及错误码
    ex33 while 循环
    ex32 循环和列表
    ex31--作出决定
    ex29-30 if,elif and else.
    ex28 布尔表达式练习
    ex25 更多更多的实践
    ex21 函数可以返回某些东西
  • 原文地址:https://www.cnblogs.com/hont/p/10990564.html
Copyright © 2011-2022 走看看