本文最后更新于158 天前,其中的信息可能已经过时,如有错误请发送邮件到2939296129@qq.com
环境光
单色环境光-1ColAmbient

环境光颜色直接乘上AO贴图
三色环境光-3ColAmbient

三层:
- WorldNormal,向上方向
- WorldNormal,向下方向,g通道(y)乘上-1
- WorldNormal,1-向上方向-向下方向,中间的遮罩
- 三个遮罩分别乘上三层颜色,加起来乘上AO贴图


三色环境光-代码实现

直接贴代码,效果相同
Shader "AP01/L07/L07_3ColAmbientCode"
{
Properties
{
_EnvCol_Up("EnvCol_Up",Color) = (1.0,1.0,1.0,1.0)
_EnvCol_Mid("EnvCol_Mid",Color) = (1.0,1.0,1.0,1.0)
_EnvCol_Down("EnvCol_Down",Color) = (1.0,1.0,1.0,1.0)
_AoMap("AO Map",2d) = "white" {}
}
SubShader
{
Tags { "RenderPipeline" = "UniversalPipeline" "RenderType"="Opaque" }
HLSLINCLUDE
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
CBUFFER_START(UnityPerMaterial)
float4 _AoMap_ST;
float4 _EnvCol_Up;
float4 _EnvCol_Mid;
float4 _EnvCol_Down;
CBUFFER_END
TEXTURE2D(_AoMap);
SAMPLER(sampler_AoMap);
struct a2v
{
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
float3 normal : NORMAL;
};
struct v2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float3 normal : TEXCOORD1;
};
ENDHLSL
Pass
{
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert (a2v v)
{
v2f o;
o.pos = TransformObjectToHClip(v.vertex);
o.uv = TRANSFORM_TEX(v.texcoord, _AoMap);
o.normal = TransformObjectToWorldNormal(v.normal);
return o;
}
float4 frag (v2f i) : SV_Target
{
float3 normalDir = i.normal;
float UpDir = saturate(normalDir.y);
float DownDir = saturate(mul(normalDir.y,-1));
float MidDir = 1- UpDir - DownDir;
float4 AOMap = SAMPLE_TEXTURE2D(_AoMap,sampler_AoMap,i.uv);
float3 UpColor = _EnvCol_Up * UpDir;
float3 DownColor = _EnvCol_Down * DownDir;
float3 MidColor = _EnvCol_Mid * MidDir;
float3 finalColor = (UpColor + DownColor + MidColor)*AOMap;
//return AOMap;
//return float4(AOMap,1.0);
return float4(finalColor,1.0);
}
ENDHLSL
}
}
}
投影
Unity自带投影实现

Ase中同名
代码实现
内置管线

- 输出结构追加:LIGHTING_COORDS(0, 1)
- 此为Unity封装好的输出结构内容,照写就行,暂时不看细节;
- 括号中的参入,如(0, 1);0,1分别代表占用了TEXCOORD1和TEXCOORD2;
- 顶点Shader中必须调用Unity封装好的方法:TRANSFER_VERTEX_TO_FRAGMENT(o);
- 像素Shader中获取投影信息同样通过Unity提供的方法:LIGHT_ATTENUATION( i );
URP管线
URP管线下实现阴影的方法和内置管线有所区别:
- 添加 接收阴影关键字

- 计算 阴影贴图
//方法1
//在输出结构中 定义好ShadowTexcoord
struct v2f
{
float4 pos:SV_POSITION;
float2 uv:TEXCOORD0;
float3 worldPos:TEXCOORD1;
float3 worldNormal:TEXCOORD2;
float3 worldViewDir:TEXCOORD3;
float4 shadowTexcoord:TEXCOORD4;
};
//VertexShader中 计算ShadowTexcoord
//1 通过VertexPositionInputs使用GetShadowCoord()计算
VertexPositionInputs vertexInput = GetVertexPositionInputs(v.vertex);
o.shadowTexcoord = GetShadowCoord(vertexInput);
//2 通过WorldPos,使用TransformWorldToShadowCoord()计算
o.shadowTexcoord=TransformWorldToShadowCoord(o.worldPos);
//fragShader中,得到光照衰减
//1
Light myLight=GetMainLight(i.shadowTexcoord);
float shadow = myLight.shadowAttenuation;
//2
float shadow = MainLightRealtimeShadow(shadowCoord)
//计算漫反射时,乘上shadowAttenuation
half4 mainColor=(diffuse*shadow+specular);
- 在下面增加一段代码调用unity的阴影Shader
UsePass "Universal Render Pipeline/Lit/ShadowCaster"
参考:
OldSchool+
光照构成

OldSchoolPlus构成

连连看


作业

Shader "AP01/L07/OldSchoolPlus"
{
Properties
{
_MainTex ("MainTex", 2D) = "white" {}
_AOMap("AO Map",2D) = "white" {}
_BaseColor ("Base Color", Color) = (1,1,1,1)
_SpecularColor ("Specular Color", Color) = (1, 1, 1, 1)
_SpecularIntensity ("Specular Intensity", Range(0, 10)) = 0.5
_SpecularRange("Gloss",Range(8,128))=20
_EnvCol_Up("EnvCol_Up",Color) = (1.0,1.0,1.0,1.0)
_EnvCol_Mid("EnvCol_Mid",Color) = (1.0,1.0,1.0,1.0)
_EnvCol_Down("EnvCol_Down",Color) = (1.0,1.0,1.0,1.0)
_EnvIntensity ("Env Intensity", Range(0, 1)) = 0.5
}
SubShader
{
Tags
{
"RenderPipeline" = "UniversalPipeline"
"RenderType"="Opaque"
}
HLSLINCLUDE
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
#pragma multi_compile _ _SHAODW_SOFT
CBUFFER_START(UnityPerMaterial)
half4 _MainTex_ST;
half4 _AOMap_ST;
float4 _BaseColor;
float4 _SpecualrColor;
float _SpecularRange;
float _SpecularIntensity;
float4 _EnvCol_Up;
float4 _EnvCol_Mid;
float4 _EnvCol_Down;
float _EnvIntensity;
CBUFFER_END
TEXTURE2D(_MainTex);
SAMPLER(sampler_MainTex);
TEXTURE2D(_AOMap);
SAMPLER(sampler_AOMap);
struct a2v
{
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
float3 normal : NORMAL;
};
struct v2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float3 normal : TEXCOORD2;
float3 viewDir : TEXCOORD3;
float4 shadowTexcoord : TEXCOORD4;
};
ENDHLSL
Pass
{
Tags
{
"LightMode"="UniversalForward"
}
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
v2f vert(a2v v)
{
v2f o;
VertexPositionInputs vertexInput = GetVertexPositionInputs(v.vertex);
o.shadowTexcoord = GetShadowCoord(vertexInput);
o.pos=TransformObjectToHClip(v.vertex);
o.uv=TRANSFORM_TEX(v.texcoord,_MainTex);
o.normal=TransformObjectToWorldNormal(v.normal);
o.viewDir=normalize(_WorldSpaceCameraPos.xyz-TransformObjectToWorld(v.vertex.xyz));
return o;
}
float4 frag(v2f i) : SV_TARGET
{
float4 MainTex = SAMPLE_TEXTURE2D(_MainTex,sampler_MainTex,i.uv);
float4 AoMap = SAMPLE_TEXTURE2D(_AOMap, sampler_AOMap, i.uv);
Light myLight=GetMainLight(i.shadowTexcoord);
float shadow = myLight.shadowAttenuation;
float3 lightDir=normalize(myLight.direction);
float3 viewDir=normalize(i.viewDir);
float3 normalDir=normalize(i.normal);
float3 halfDir=normalize(lightDir+viewDir);
float3 UpDir = normalDir.y;
float3 DownDir = -1.0 * normalDir.y;
float3 MidDir = 1 - UpDir - DownDir;
float3 UpColor = _EnvCol_Up.rgb * UpDir;
float3 MidColor = _EnvCol_Mid.rgb * MidDir;
float3 DownColor = _EnvCol_Down.rgb * DownDir;
float3 Ambient = (UpColor + MidColor + DownColor) * AoMap * MainTex * _EnvIntensity;
float NdotL = saturate(dot(normalDir,lightDir));
float3 diffuse = NdotL * MainTex;
float NdotH = saturate(dot(halfDir,normalDir));
float specular = pow(NdotH, _SpecularRange);
float3 finalColor = (diffuse + specular) * myLight.color * shadow + Ambient;
return float4(finalColor,1.0);
}
ENDHLSL
}
UsePass "Universal Render Pipeline/Lit/ShadowCaster"
}
}

