在Unity引擎中,开发者可以使用Shader编写自定义着色器,来实现对游戏场景中的模型、材质进行更加高级的渲染。其中,光照是Shader编写中十分重要的一个环节,一个较完整的光照着色器需要包括基础光照、多光源、阴影等要素。下面介绍一些实现这些功能的方法:
1. 基础光照
在Unity中,使用Built-in Shader中的“Surface Shader”或“Unlit Shader”都提供基础光照的功能。如果需要自定义光照模型,则需要使用ShaderLab来手动编写对应的光照部分。
在ShaderLab代码中,可以使用光照计算的内置函数,如Lighting
、light
、half4 AmbientLight
等。通过计算每个像素点的法线、反射光、漫反射光等参数,可以模拟光照的效果。
以下是一个简单的基础光照示例:
Shader "Custom/LightingExampleShader" {
Properties {
_MainTex("Texture", 2D) = "white" {}
}
SubShader {
Tags {
"RenderType"="Opaque"
}
CGPROGRAM
#pragma surface surf Standard
struct Input {
float2 uv_MainTex;
};
sampler2D _MainTex;
void surf (Input IN, inout SurfaceOutputStandard o) {
o.Albedo = tex2D(_MainTex, IN.uv_MainTex).rgb;
o.Metallic = 0.5;
o.Smoothness = 0.5;
o.Normal = float3(0,0,1);
}
ENDCG
}
FallBack "Diffuse"
}
2. 多光源
Unity内置提供了多种光源类型,例如:点光源、方向光,聚光灯等。使用Shader编写的时候,可以通过内置的_LightColor0
、_LightColor1
等Uniform来获取不同光源的颜色。同时也可以自定义Uniform变量,来获取光源的位置、方向、光照范围等属性。
以下是一个简单的多光源示例,在渲染过程中,使用了两个点光源和一个方向光:
Shader "Custom/MultiLightExampleShader" {
Properties {
_MainTex("Texture", 2D) = "white" {}
}
SubShader {
Tags {
"RenderType"="Opaque"
}
CGPROGRAM
#pragma surface surf Standard
struct Input {
float2 uv_MainTex;
};
sampler2D _MainTex;
void surf (Input IN, inout SurfaceOutputStandard o) {
float3 lightingColor = float3(0,0,0);
// Point Light 1
float3 pointLight1Dir = _WorldSpaceLightPos0.xyz - UnityObjectToWorldPos(float3(0,0,0));
float3 pointLight1Color = _LightColor0.rgb;
float3 pointLight1Attenuation = UnityInverseSquaredDistance(UnityObjectToWorldPos(float3(0,0,0)), _WorldSpaceLightPos0);
lightingColor += pointLight1Color * pointLight1Attenuation * max(dot(normalize(IN.worldNormal), normalize(pointLight1Dir)), 0);
// Point Light 2
float3 pointLight2Dir = _WorldSpaceLightPos1.xyz - UnityObjectToWorldPos(float3(0,0,0));
float3 pointLight2Color = _LightColor1.rgb;
float3 pointLight2Attenuation = UnityInverseSquaredDistance(UnityObjectToWorldPos(float3(0,0,0)), _WorldSpaceLightPos1);
lightingColor += pointLight2Color * pointLight2Attenuation * max(dot(normalize(IN.worldNormal), normalize(pointLight2Dir)), 0);
// Directional Light
float3 directionalLightDir = _WorldSpaceLightPos2.xyz;
float3 directionalLightColor = _LightColor2.rgb;
lightingColor += directionalLightColor * max(dot(normalize(IN.worldNormal), normalize(directionalLightDir)), 0);
o.Albedo = tex2D(_MainTex, IN.uv_MainTex).rgb;
o.Metallic = 0.5;
o.Smoothness = 0.5;
o.Normal = float3(0,0,1);
o.Emission = lightingColor;
}
ENDCG
}
FallBack "Diffuse"
}
3. 阴影
Unity的光照计算支持实时阴影。使用Shader绘制的物体在有灯光照射下,会产生阴影效果。Unity提供了内置的ShadowMap,可以通过内置的函数来获取阴影采样。
以下是一个简单的实时阴影示例:
Shader "Custom/ShadowExampleShader" {
Properties {
_MainTex("Texture", 2D) = "white" {}
}
SubShader {
Tags {
"RenderType"="Opaque"
}
CGPROGRAM
#pragma surface surf Standard
struct Input {
float2 uv_MainTex;
float3 worldPos;
float3 worldNormal;
};
sampler2D _MainTex;
float4x4 _WorldToShadow;
sampler2D _ShadowMapTexture;
float4 _ShadowMapTexture_ST;
void surf (Input IN, inout SurfaceOutputStandard o) {
float4 shadowUV = UnityShadowCoord(IN.worldPos);
shadowUV.z += 0.0001;
float shadowValue = tex2D(_ShadowMapTexture, shadowUV.xy).r;
float3 lightingColor = float3(0,0,0);
float3 pointLightDir = _WorldSpaceLightPos0.xyz - IN.worldPos;
float3 pointLightColor = _LightColor0.rgb;
float3 pointLightAttenuation = UnityInverseSquaredDistance(IN.worldPos, _WorldSpaceLightPos0);
lightingColor += pointLightColor * pointLightAttenuation * max(dot(normalize(IN.worldNormal), normalize(pointLightDir)), 0) * shadowValue;
o.Albedo = tex2D(_MainTex, IN.uv_MainTex).rgb;
o.Metallic = 0.5;
o.Smoothness = 0.5;
o.Normal = float3(0,0,1);
o.Emission = lightingColor;
}
ENDCG
}
FallBack "Diffuse"
}
以上就是一个较完整的光照Shader的几个要点,开发者可以根据自己的需求来进行进一步的改良。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:unity shader 较完整光照(含有多光源阴影) - Python技术站