unity里standard pbr(一)

Posted marcher

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了unity里standard pbr(一)相关的知识,希望对你有一定的参考价值。

关注forwardbase下的

standard.shader

#pragma vertex vertBase
#pragma fragment fragBase
#include "UnityStandardCoreForward.cginc"

跟踪到UnityStandardCoreForward.cginc

#if UNITY_STANDARD_SIMPLE
#include "UnityStandardCoreForwardSimple.cginc"
VertexOutputBaseSimple vertBase (VertexInput v) { return vertForwardBaseSimple(v); }
VertexOutputForwardAddSimple vertAdd (VertexInput v) { return vertForwardAddSimple(v); }
half4 fragBase (VertexOutputBaseSimple i) : SV_Target { return fragForwardBaseSimpleInternal(i); }
half4 fragAdd (VertexOutputForwardAddSimple i) : SV_Target { return fragForwardAddSimpleInternal(i); }
#else
#include "UnityStandardCore.cginc"
VertexOutputForwardBase vertBase (VertexInput v) { return vertForwardBase(v); }
VertexOutputForwardAdd vertAdd (VertexInput v) { return vertForwardAdd(v); }
half4 fragBase (VertexOutputForwardBase i) : SV_Target { return fragForwardBaseInternal(i); }
half4 fragAdd (VertexOutputForwardAdd i) : SV_Target { return fragForwardAddInternal(i); }
#endif

 

UNITY_STANDARD_SIMPLE开关是简化版意思,进下边的分支

顶点着色器 vertForwardBase

先看输出

struct VertexOutputForwardBase
{
    float4 pos                          : SV_POSITION;
    float4 tex                          : TEXCOORD0;
    half3 eyeVec                        : TEXCOORD1;
    half4 tangentToWorldAndParallax[3]  : TEXCOORD2;    // [3x3:tangentToWorld | 1x3:viewDirForParallax]
    half4 ambientOrLightmapUV           : TEXCOORD5;    // SH or Lightmap UV
    SHADOW_COORDS(6)
    UNITY_FOG_COORDS(7)

    // next ones would not fit into SM2.0 limits, but they are always for SM3.0+
    #if UNITY_REQUIRE_FRAG_WORLDPOS
        float3 posWorld                 : TEXCOORD8;
    #endif

    #if UNITY_OPTIMIZE_TEXCUBELOD
        #if UNITY_REQUIRE_FRAG_WORLDPOS
            half3 reflUVW               : TEXCOORD9;
        #else
            half3 reflUVW               : TEXCOORD8;
        #endif
    #endif

    UNITY_VERTEX_OUTPUT_STEREO
};
UNITY_REQUIRE_FRAG_WORLDPOS要不要worldpos,要
reflUVW是用来做反射的,要
UNITY_VERTEX_OUTPUT_STEREO 是用来做实例化的,不要
简化成

struct VertexOutputForwardBase
{
    float4 pos                          : SV_POSITION;
    float4 tex                          : TEXCOORD0;
    half3 eyeVec                        : TEXCOORD1;
    half4 tangentToWorldAndParallax[3]  : TEXCOORD2;    // [3x3:tangentToWorld | 1x3:viewDirForParallax]
    half4 ambientOrLightmapUV           : TEXCOORD5;    // SH or Lightmap UV
    SHADOW_COORDS(6)
    UNITY_FOG_COORDS(7)
    float3 posWorld                     : TEXCOORD8;
    half3 reflUVW                       : TEXCOORD9;
};
再来看顶点着色器
VertexOutputForwardBase vertForwardBase (VertexInput v)
{
    VertexOutputForwardBase o;
    UNITY_SETUP_INSTANCE_ID(v);
    UNITY_INITIALIZE_OUTPUT(VertexOutputForwardBase, o);
    UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);

    float4 posWorld = mul(unity_ObjectToWorld, v.vertex);
    #if UNITY_REQUIRE_FRAG_WORLDPOS
        o.posWorld = posWorld.xyz;
    #endif
    o.pos = UnityObjectToClipPos(v.vertex);

    o.tex = TexCoords(v);
    o.eyeVec = NormalizePerVertexNormal(posWorld.xyz - _WorldSpaceCameraPos);
    float3 normalWorld = UnityObjectToWorldNormal(v.normal);
    #ifdef _TANGENT_TO_WORLD
        float4 tangentWorld = float4(UnityObjectToWorldDir(v.tangent.xyz), v.tangent.w);

        float3x3 tangentToWorld = CreateTangentToWorldPerVertex(normalWorld, tangentWorld.xyz, tangentWorld.w);
        o.tangentToWorldAndParallax[0].xyz = tangentToWorld[0];
        o.tangentToWorldAndParallax[1].xyz = tangentToWorld[1];
        o.tangentToWorldAndParallax[2].xyz = tangentToWorld[2];
    #else
        o.tangentToWorldAndParallax[0].xyz = 0;
        o.tangentToWorldAndParallax[1].xyz = 0;
        o.tangentToWorldAndParallax[2].xyz = normalWorld;
    #endif
    //We need this for shadow receving
    TRANSFER_SHADOW(o);

    o.ambientOrLightmapUV = VertexGIForward(v, posWorld, normalWorld);

    #ifdef _PARALLAXMAP
        TANGENT_SPACE_ROTATION;
        half3 viewDirForParallax = mul (rotation, ObjSpaceViewDir(v.vertex));
        o.tangentToWorldAndParallax[0].w = viewDirForParallax.x;
        o.tangentToWorldAndParallax[1].w = viewDirForParallax.y;
        o.tangentToWorldAndParallax[2].w = viewDirForParallax.z;
    #endif

    #if UNITY_OPTIMIZE_TEXCUBELOD
        o.reflUVW       = reflect(o.eyeVec, normalWorld);
    #endif

    UNITY_TRANSFER_FOG(o,o.pos);
    return o;
}

 

UNITY_SETUP_INSTANCE_ID是instance用的,不要
UNITY_INITIALIZE_OUTPUT啥也没干,不要
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO不要
NormalizePerVertexNormal相等于什么都没做
_TANGENT_TO_WORLD是切线空间和世界空间转换矩阵 保留
o.ambientOrLightmapUV = VertexGIForward(v, posWorld, normalWorld);
因为打算用pbr来做角色,没有lightmap,所以这儿等于

 

o.ambientOrLightmapUV = 0 ;
_PARALLAXMAP视差贴图,不用
去掉分支后代码如下

VertexOutputForwardBase vertForwardBase (VertexInput v)
{
    VertexOutputForwardBase o;
    float4 posWorld = mul(unity_ObjectToWorld, v.vertex);
    o.posWorld = posWorld.xyz;
    o.pos = UnityObjectToClipPos(v.vertex);
    o.tex = TexCoords(v);
    o.eyeVec = NormalizePerVertexNormal(posWorld.xyz - _WorldSpaceCameraPos);
    float3 normalWorld = UnityObjectToWorldNormal(v.normal);
	float4 tangentWorld = float4(UnityObjectToWorldDir(v.tangent.xyz), v.tangent.w);

	float3x3 tangentToWorld = CreateTangentToWorldPerVertex(normalWorld, tangentWorld.xyz, tangentWorld.w);
	o.tangentToWorldAndParallax[0].xyz = tangentToWorld[0];
	o.tangentToWorldAndParallax[1].xyz = tangentToWorld[1];
	o.tangentToWorldAndParallax[2].xyz = tangentToWorld[2];
    //We need this for shadow receving
    TRANSFER_SHADOW(o);
    o.ambientOrLightmapUV = 0;
	o.reflUVW       = reflect(o.eyeVec, normalWorld);
    UNITY_TRANSFER_FOG(o,o.pos);
    return o;
}

 至此顶点着色器完事,下篇开始像素着色器

 
 
 

 













以上是关于unity里standard pbr(一)的主要内容,如果未能解决你的问题,请参考以下文章

关于unity里pbr技术和材质 unity5默认shader和传统的对比

PBR

Unity性能最高的Shader: Unlit

unity之PBR材质流程与材质制作实践

unity性能最高的Shader:Unlit

Unity 之 ShaderGraph PBR 和 Unlit 主节点介绍