Shader——《真三国无双》城墙着火特效

《真三》与我不得不说的三两事  (ಡωಡ)

《真三》系列在我心中有特殊的地位,小学五年级在姥姥家打开小舅的电脑,发现一款游戏(《真三》3),对于当时的我,从来没有玩过电脑游戏的我来说就像打开新世界的大门,在农村昏黄的白炽灯下,伴着鸡叫,我按下逐个键位尝试去操作,进入游戏后我化身关羽,在战场上任意厮杀。虽然游戏运行后非常卡(FPS极低,大概只有个位数),但对于初次接触电脑游戏的我来说,这简直太棒了!  回到家后我跟小伙伴们讲述《真三》有多么刺激,招式是怎样的,并且模仿那些武将的攻击动作。

    当时家用电脑还不普及,我们胡同里七八个小伙伴只有两个人家里有电脑,其中一个就是我的隔壁。我经常去隔壁小伙伴家里看他玩游戏,甚是羡慕,回到家常常幻想我就是游戏中的人物,或是《血战上海滩》中持一把毛瑟与鬼子巷战的抗日战士,或是《魔兽争霸》中英勇无畏的牛头人,或是《侠盗猎车:罪恶都市》中黑白通吃、逍遥法外的克劳德。甚至在学校做值日时,手拿一把扫帚装作持枪模样,嘴里发出“嘚嘚哒”的子弹声......

时至今日,脑海中依旧浮现在昏黄灯下打《真三》,虽然巨卡但是很快乐的画面。

言归正传

《真三》赤壁之战中,火烧船的画面,火苗随机的摇曳:

我实现的效果,树上着火了,火苗随机的摇动:

核心思路:

在片段着色器中,给当前像素一个随机值,让这个像素根据这个随机值偏移。

如何输入随机值?

      传入一个噪声图,用噪声图上某个像素的灰度表示随机值。

扫描二维码关注公众号,回复: 2440947 查看本文章

实现火苗的摇曳?

     上个问题说到的噪波图,噪声图取得像素点根据时间偏移。

核心代码:

片段着色器:

float4 frag(VertexOutput i) : COLOR {

	//光照函数
    i.normalDir = normalize(i.normalDir);
    float3 normalDirection = i.normalDir;
    float3 lightDirection = normalize(_WorldSpaceLightPos0.xyz);
    float3 lightColor = _LightColor0.rgb;

    float attenuation = LIGHT_ATTENUATION(i);
    float3 attenColor = attenuation * _LightColor0.xyz;

    float NdotL = max(0.0,dot( normalDirection, lightDirection ));	
    float3 directDiffuse = max( 0.0, NdotL) * attenColor;
    float3 indirectDiffuse = float3(0,0,0);
    indirectDiffuse += UNITY_LIGHTMODEL_AMBIENT.rgb; 
    
	//x,y方向流动
    float2 FlowUV = (i.uv0+float2((_SpeedX*_Time.g),(_Time.g*_SpeedY)));		
    float4 _NoiseMap_var = tex2D(_NoiseMap,TRANSFORM_TEX(FlowUV, _NoiseMap));
	//噪波强度
    float2 NoiseUV = (i.uv0+(float2(_NoiseMap_var.r,_NoiseMap_var.g)*_NoiseStrength));		
    float4 _MainTex_var = tex2D(_MainTex,TRANSFORM_TEX(NoiseUV, _MainTex));
    float3 diffuseColor = _MainTex_var.rgb;
    float3 diffuse = (directDiffuse + indirectDiffuse) * diffuseColor;

    float3 finalColor = diffuse;
    fixed4 finalRGBA = fixed4(finalColor,1);
    UNITY_APPLY_FOG(i.fogCoord, finalRGBA);
    return finalRGBA;
            }

需要注意的:

  1.注意噪波图不要太平均,因为火苗是块状的。

  2.火焰贴图需要有alpha通道,方便开启透明度融合

源码:

Shader "Custom/NoiseFlow" {
    Properties {
        _MainTex ("主纹理", 2D) = "bump" {}
        _NoiseMap ("噪声图", 2D) = "bump" {}
		_SpeedX("x方向速度",float)=0.02
		_SpeedY("y方向速度",float)=0.02
		_NoiseStrength ("噪波强度",float)=0.1
    }
    SubShader {
	Blend One One
	//Blend SrcAlpha  OneMinusSrcAlpha
	Cull Off
        Tags {
            "Queue"="Transparent"
        }
        Pass {
            Name "FORWARD"
            Tags {
                "LightMode"="ForwardBase"
            }
            
            
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #define UNITY_PASS_FORWARDBASE
            #include "UnityCG.cginc"
            #include "AutoLight.cginc"
            uniform float4 _LightColor0;
            uniform sampler2D _MainTex; uniform float4 _MainTex_ST;
            uniform sampler2D _NoiseMap; uniform float4 _NoiseMap_ST;
            struct VertexInput {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
                float2 texcoord0 : TEXCOORD0;
            };
            struct VertexOutput {
                float4 pos : SV_POSITION;
                float2 uv0 : TEXCOORD0;
                float4 posWorld : TEXCOORD1;
                float3 normalDir : TEXCOORD2;

            };
            VertexOutput vert (VertexInput v) {
                VertexOutput o = (VertexOutput)0;
                o.uv0 = v.texcoord0;
                o.normalDir = UnityObjectToWorldNormal(v.normal);
                o.posWorld = mul(unity_ObjectToWorld, v.vertex);
                float3 lightColor = _LightColor0.rgb;
                o.pos = UnityObjectToClipPos( v.vertex );
                UNITY_TRANSFER_FOG(o,o.pos);
                TRANSFER_VERTEX_TO_FRAGMENT(o)
                return o;
            }

uniform float _SpeedX;
uniform float _SpeedY;
uniform float _NoiseStrength;
float4 frag(VertexOutput i) : COLOR {

	//光照函数
    i.normalDir = normalize(i.normalDir);
    float3 normalDirection = i.normalDir;
    float3 lightDirection = normalize(_WorldSpaceLightPos0.xyz);
    float3 lightColor = _LightColor0.rgb;

    float attenuation = LIGHT_ATTENUATION(i);
    float3 attenColor = attenuation * _LightColor0.xyz;

    float NdotL = max(0.0,dot( normalDirection, lightDirection ));	
    float3 directDiffuse = max( 0.0, NdotL) * attenColor;
    float3 indirectDiffuse = float3(0,0,0);
    indirectDiffuse += UNITY_LIGHTMODEL_AMBIENT.rgb; 
    
	//x,y方向流动
    float2 FlowUV = (i.uv0+float2((_SpeedX*_Time.g),(_Time.g*_SpeedY)));		
    float4 _NoiseMap_var = tex2D(_NoiseMap,TRANSFORM_TEX(FlowUV, _NoiseMap));
	//噪波强度
    float2 NoiseUV = (i.uv0+(float2(_NoiseMap_var.r,_NoiseMap_var.g)*_NoiseStrength));		
    float4 _MainTex_var = tex2D(_MainTex,TRANSFORM_TEX(NoiseUV, _MainTex));
    float3 diffuseColor = _MainTex_var.rgb;
    float3 diffuse = (directDiffuse + indirectDiffuse) * diffuseColor;

    float3 finalColor = diffuse;
    fixed4 finalRGBA = fixed4(finalColor,1);
    UNITY_APPLY_FOG(i.fogCoord, finalRGBA);
    return finalRGBA;
            }
            ENDCG
        }
       
    }
    FallBack "Diffuse"
}

猜你喜欢

转载自blog.csdn.net/roadlun/article/details/81111499