在自己的VFShader中调用标准光照模型

    我们知道在surfaceShader中可以通过#pragma surface surf Standard 直接调用标准光照模型,Unity对surfaceShader封装了太多东西。本节参照NewSurfaceShader编译成的VFShader实现自己的VFSahder中的标准光照模型。

代码如下:

Shader "Unlit/NewUnlitShader"

{

Properties

{

_Color("Color", Color) = (1,1,1,1)

_MainTex("Albedo (RGB)", 2D) = "white" {}

_Glossiness("Smoothness", Range(0,1)) = 0.5

_Metallic("Metallic", Range(0,1)) = 0.0

}

SubShader

{

Tags { "RenderType" = "Opaque" }

LOD 100



Pass

{

CGPROGRAM

#pragma vertex vert

#pragma fragment frag

#include "UnityCG.cginc"

#include "Lighting.cginc"

#include "UnityPBSLighting.cginc"

#include "AutoLight.cginc"



sampler2D _MainTex;

half _Glossiness;

half _Metallic;

fixed4 _Color;

struct v2f

{

float4 pos : SV_POSITION;

half3 worldNormal : TEXCOORD1;

float3 worldPos : TEXCOORD2;

float2 uv:TEXCOORD0;

};



v2f vert (appdata_full v)

{

v2f o;

o.pos = UnityObjectToClipPos(v.vertex);

float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;//世界空间的顶点坐标和法线

float3 worldNormal = UnityObjectToWorldNormal(v.normal);

o.worldPos = worldPos;

o.worldNormal = worldNormal;

o.uv = v.texcoord;

return o;

}

fixed4 frag (v2f i) : SV_Target

{

float3 worldPos = i.worldPos;

fixed3 lightDir = normalize(UnityWorldSpaceLightDir(worldPos));

fixed3 worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos));



//-------配置LightingStandard_GI()和LightingStandard()的第一个参数

SurfaceOutputStandard o = (SurfaceOutputStandard)0;

fixed4 col= tex2D(_MainTex, i.uv)*_Color;

o.Albedo = col.rgb;

o.Metallic = _Metallic;

o.Smoothness = _Glossiness;

o.Normal = i.worldNormal;

//---------------end

//---------------提取的光照部分

fixed4 c = 0;

//配置LightingStandard()的第三个参数

UnityGI gi;

gi.indirect.diffuse = 0;

gi.indirect.specular = 0;

gi.light.color = _LightColor0.rgb;

gi.light.dir = lightDir;

// 配置LightingStandard_GI()的第二个参数

UnityGIInput giInput;

giInput.worldViewDir = worldViewDir;

LightingStandard_GI(o, giInput, gi);

c += LightingStandard(o, worldViewDir, gi);

//------------------------end

return c;

}

ENDCG

}

}

}

 

右侧是unity默认Standard材质,两者差异还是蛮大的,因为unity内置的standard Shader 在n多个pass里面针对不同情况分别做了包括forwardadd和延迟光照渲染等不同的处理,所以效果会比左侧单个pass实现的光照模型效果要好很多。不管哪个pass,调用的光照模型是一样的。

下面我们将提取的光照部分独立出来封装成自己的cginc文件:

StandardLight.cginc文件代码

#ifndef StandardLight
#define StandardLight
float4 GetLightModel(SurfaceOutputStandard o, float3 worldPos, fixed3 lightDir, fixed3 worldViewDir) {
    //---------------提取的光照部分
     fixed4 c = 0;
    //配置LightingStandard()的第三个参数
    UnityGI gi;
    gi.indirect.diffuse = 0;
    gi.indirect.specular = 0;
    gi.light.color = _LightColor0.rgb;
    gi.light.dir = lightDir;
    // 配置LightingStandard_GI()的第二个参数
    UnityGIInput giInput;
    giInput.worldViewDir = worldViewDir;
    LightingStandard_GI(o, giInput, gi);
    c += LightingStandard(o, worldViewDir, gi);
    //------------------------end
    return c;
}

Shader部分代码:

Shader "Unlit/NewUnlitShader"
{
    Properties
    {
        _Color("Color", Color) = (1,1,1,1)
        _MainTex("Albedo (RGB)", 2D) = "white" {}
        _Glossiness("Smoothness", Range(0,1)) = 0.5
        _Metallic("Metallic", Range(0,1)) = 0.0
    }
        SubShader
    {
        Tags { "RenderType" = "Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            #include "UnityPBSLighting.cginc"
            #include "AutoLight.cginc"
            #include"StandardLight.cginc"

        sampler2D _MainTex;
        half _Glossiness;
        half _Metallic;
        fixed4 _Color;
            
        struct v2f
        {
            float4 pos : SV_POSITION;
            half3 worldNormal : TEXCOORD1;
            float3 worldPos : TEXCOORD2;
            float2 uv:TEXCOORD0;
        };    

            v2f vert (appdata_full v)
            {
                v2f o;        
                o.pos = UnityObjectToClipPos(v.vertex);            
                float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;//世界空间的顶点坐标和法线
                float3 worldNormal = UnityObjectToWorldNormal(v.normal);
                o.worldPos = worldPos;
                o.worldNormal = worldNormal;
                o.uv = v.texcoord;
                return o;
            }
            
            fixed4 frag (v2f i) : SV_Target
            {
            float3 worldPos = i.worldPos;
            fixed3 lightDir = normalize(UnityWorldSpaceLightDir(worldPos));
            fixed3 worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos));
            //-------配置LightingStandard_GI()和LightingStandard()的第一个参数
            SurfaceOutputStandard o = (SurfaceOutputStandard)0;
            fixed4 col = tex2D(_MainTex, i.uv)*_Color;
            o.Albedo = col.rgb;
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Normal = i.worldNormal;
            //---------------end            
            return GetLightModel(o, worldPos, lightDir, worldViewDir);
            }
            ENDCG
        }
    }
}


如果不希望借用SurfaceOutputStandard结构体和LightingStandard()来实现金属光泽和光滑度等效果,可直接调UNITY_BRDF_PBS()方法,过滤掉LightingStandard()中对金属光泽和光滑度等参数的封装和自发光等效果的实现。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值