|
前言:
已经进入“高级篇”啦,但愿大师多多撑持,多多存眷,这将对我发生非常愉悦的正反馈~
“《Unity Shader 入门精要》从Bulit-in 到URP”是一个辅佐Unity Shader学习者以冯乐乐女神《Unity Shader 入门精要》为基础学习用HLSL语言编写URP着色器的案例教学系列。
作者自学能力有限,抛砖引玉,如有建议和问题请各位大佬和同仁交流斧正。 如安在URP中实现后措置参见:
Bulit-in版:
- // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
- Shader ”Unity Shaders Book/Chapter 13/Fog With Depth Texture” {
- Properties {
- _MainTex (”Base (RGB)”, 2D) = ”white” {}
- _FogDensity (”Fog Density”, Float) = 1.0
- _FogColor (”Fog Color”, Color) = (1, 1, 1, 1)
- _FogStart (”Fog Start”, Float) = 0.0
- _FogEnd (”Fog End”, Float) = 1.0
- }
- SubShader {
- CGINCLUDE
-
- #include ”UnityCG.cginc”
-
- float4x4 _FrustumCornersRay;
-
- sampler2D _MainTex;
- half4 _MainTex_TexelSize;
- sampler2D _CameraDepthTexture;
- half _FogDensity;
- fixed4 _FogColor;
- float _FogStart;
- float _FogEnd;
-
- struct v2f {
- float4 pos : SV_POSITION;
- half2 uv : TEXCOORD0;
- half2 uv_depth : TEXCOORD1;
- float4 interpolatedRay : TEXCOORD2;
- };
-
- v2f vert(appdata_img v) {
- v2f o;
- o.pos = UnityObjectToClipPos(v.vertex);
-
- o.uv = v.texcoord;
- o.uv_depth = v.texcoord;
-
- #if UNITY_UV_STARTS_AT_TOP
- if (_MainTex_TexelSize.y < 0)
- o.uv_depth.y = 1 - o.uv_depth.y;
- #endif
-
- int index = 0;
- if (v.texcoord.x < 0.5 && v.texcoord.y < 0.5) {
- index = 0;
- } else if (v.texcoord.x > 0.5 && v.texcoord.y < 0.5) {
- index = 1;
- } else if (v.texcoord.x > 0.5 && v.texcoord.y > 0.5) {
- index = 2;
- } else {
- index = 3;
- }
- #if UNITY_UV_STARTS_AT_TOP
- if (_MainTex_TexelSize.y < 0)
- index = 3 - index;
- #endif
-
- o.interpolatedRay = _FrustumCornersRay[index];
-
- return o;
- }
-
- fixed4 frag(v2f i) : SV_Target {
- float linearDepth = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv_depth));
- float3 worldPos = _WorldSpaceCameraPos + linearDepth * i.interpolatedRay.xyz;
-
- float fogDensity = (_FogEnd - worldPos.y) / (_FogEnd - _FogStart);
- fogDensity = saturate(fogDensity * _FogDensity);
-
- fixed4 finalColor = tex2D(_MainTex, i.uv);
- finalColor.rgb = lerp(finalColor.rgb, _FogColor.rgb, fogDensity);
-
- return finalColor;
- }
-
- ENDCG
-
- Pass {
- ZTest Always Cull Off ZWrite Off
-
- CGPROGRAM
-
- #pragma vertex vert
- #pragma fragment frag
-
- ENDCG
- }
- }
- FallBack Off
- }
复制代码 URP版:
Unity项目源码: - Shader ”Unlit/Chapter13-FogWithDepthTexture”
- {
- Properties {
- _MainTex (”Base (RGB)”, 2D) = ”white” {}
- _FogDensity (”Fog Density”, Float) = 1.0
- _FogColor (”Fog Color”, Color) = (1, 1, 1, 1)
- _FogStart (”Fog Start”, Float) = 0.0
- _FogEnd (”Fog End”, Float) = 1.0
- }
- SubShader
- {
- Tags { ”RenderPipeline” = ”UniversalPipeline” }
-
- HLSLINCLUDE
- #include ”Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl”
- #include ”Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl”
- CBUFFER_START(UnityPerMaterial)
- float4x4 _FrustumCornersRay;
-
- half4 _MainTex_TexelSize;
- half _FogDensity;
- half4 _FogColor;
- float _FogStart;
- float _FogEnd;
- CBUFFER_END
- TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex);
- TEXTURE2D(_CameraDepthTexture); SAMPLER(sampler_CameraDepthTexture);
- //如果在URP Asset设置下勾选 depth texture选项系统会自动生成一张以_CameraDepthTexture为名的深度图,抽时间会写一篇相关文章并把链接补充到本篇中。
- struct appdata{
- float4 vertex : POSITION;
- float2 texcoord : TEXCOORD0;
- };
- struct v2f {
- float4 pos : SV_POSITION;
- half2 uv : TEXCOORD0;
- half2 uv_depth : TEXCOORD1;
- float4 interpolatedRay : TEXCOORD2;
- };
- v2f vert(appdata v) {
- v2f o;
-
- o.pos = TransformObjectToHClip(v.vertex);
-
- o.uv = v.texcoord;
- o.uv_depth = v.texcoord;
- #if UNITY_UV_STARTS_AT_TOP
- if (_MainTex_TexelSize.y < 0)
- o.uv_depth.y = 1 - o.uv_depth.y;
- #endif
- int index = 0;
- if (v.texcoord.x < 0.5 && v.texcoord.y < 0.5) {
- index = 0;
- } else if (v.texcoord.x > 0.5 && v.texcoord.y < 0.5) {
- index = 1;
- } else if (v.texcoord.x > 0.5 && v.texcoord.y > 0.5) {
- index = 2;
- } else {
- index = 3;
- }
- #if UNITY_UV_STARTS_AT_TOP
- if (_MainTex_TexelSize.y < 0)
- index = 3 - index;
- #endif
-
- o.interpolatedRay = _FrustumCornersRay[index];
- //尽管我们这里使用了很多判断语句,但由于屏幕后措置所用的模型是一个四边形网格,只包含4个顶点,因此这些操作不会对性能造成很大影响。
-
- return o;
- }
- half4 frag(v2f i) : SV_Target {
- float linearDepth = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, sampler_CameraDepthTexture,i.uv_depth), _ZBufferParams);
- //使用LinearEyeDepth得到视角空间下的线性深度值
- float3 worldPos = _WorldSpaceCameraPos + linearDepth * i.interpolatedRay.xyz;
-
- float fogDensity = (_FogEnd - worldPos.y) / (_FogEnd - _FogStart);
- fogDensity = saturate(fogDensity * _FogDensity);
-
- half4 finalColor = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv);
- finalColor.rgb = lerp(finalColor.rgb, _FogColor.rgb, fogDensity);
-
- return finalColor;
- }
-
- ENDHLSL
-
- Pass {
- ZTest Always Cull Off ZWrite Off
-
- HLSLPROGRAM
-
- #pragma vertex vert
- #pragma fragment frag
-
- ENDHLSL
- }
- }
- FallBack ”Packages/com.unity.render-pipelines.universal/FallbackError”
- }
复制代码 URP后措置脚本
因为和上面提供的(Post-processing : RenderFeature + VolumeComponent)模板有些许差异,因此在此提供对应源码。- using System;
- using UnityEngine;
- using UnityEngine.Rendering;
- using UnityEngine.Rendering.Universal;
- public class FogWithDepthTexture : ScriptableRendererFeature
- {
- [Serializable, VolumeComponentMenu(”Ding Post-processing/13.3 FogWithDepthTexture”)]
- public class CustomVolumeComponent : DingVolumeComponentBase
- {
- public ClampedFloatParameter FogDensity = new ClampedFloatParameter(1.0f, 0, 3.0f);
- public MinFloatParameter FogStart = new MinFloatParameter(0f, 0f);
- public MinFloatParameter FogEnd = new MinFloatParameter(2.0f, 0f);
- public ColorParameter FogColor = new ColorParameter(Color.white, false, false, true);
-
- public override bool IsActive() => isRender.value;
- public override bool IsTileCompatible() => false;
- }
- class CustomRenderPass : ScriptableRenderPass
- {
-
- public Material material;
- private Matrix4x4 frustumCorners;
- //RT的滤波模式
- public FilterMode filterMode {get; set;}
- //当前衬着阶段的colorRT
- //RenderTargetIdentifier、RenderTargetHandle都可以理解为RT,Identifier为camera提供的需要被应用的texture,Handle为被shader措置衬着过的RT
- private RenderTargetIdentifier source {get; set;}
- //private RenderTargetHandle destination {get; set;}
- //辅助RT
- private RenderTargetHandle tempTexture;
- string m_ProfilerTag;
- //Profiling上显示
- public CustomVolumeComponent volume;
- ProfilingSampler m_ProfilingSampler = new ProfilingSampler(”URPDing”);
- public CustomRenderPass(RenderPassEvent renderPassEvent, Shader shader, CustomVolumeComponent volume, string tag){
- //确定在哪个阶段插入衬着
- this.renderPassEvent = renderPassEvent;
- this.volume = volume;
- if(shader == null){return;}
- this.material = CoreUtils.CreateEngineMaterial(shader);
- m_ProfilerTag = tag;
- //初始化辅助RT的名字
- tempTexture.Init(”_TempRTexture”);
- }
- public void Setup(RenderTargetIdentifier source){
- this.source = source;
- //this.destination = destination;
- }
-
-
- public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
- {
- if (!volume.IsActive()) {
- return;
- }
- CommandBuffer cmd = CommandBufferPool.Get(”m_ProfilerTag”);
- //using 方式可以实此刻FrameDebug上查看衬着过程
- using(new ProfilingScope(cmd, m_ProfilingSampler)){
- Camera camera = renderingData.cameraData.camera;
- //获取摄像机
- Transform cameraTransform = camera.transform;
- float fov = camera.fieldOfView;
- float near = camera.nearClipPlane;
- float far = camera.farClipPlane;
- float aspect = camera.aspect;
- float halfHeight = near * Mathf.Tan(fov * 0.5f * Mathf.Deg2Rad);
- Vector3 toRight = cameraTransform.right * halfHeight * aspect;
- Vector3 toTop = cameraTransform.up * halfHeight;
- Vector3 topLeft = cameraTransform.forward * near + toTop - toRight;
- float scale = topLeft.magnitude / near;
- topLeft.Normalize();
- topLeft *= scale;
- Vector3 topRight = cameraTransform.forward * near + toRight + toTop;
- topRight.Normalize();
- topRight *= scale;
- Vector3 bottomLeft = cameraTransform.forward * near - toTop - toRight;
- bottomLeft.Normalize();
- bottomLeft *= scale;
- Vector3 bottomRight = cameraTransform.forward * near + toRight - toTop;
- bottomRight.Normalize();
- bottomRight *= scale;
- frustumCorners.SetRow(0, bottomLeft);
- frustumCorners.SetRow(1, bottomRight);
- frustumCorners.SetRow(2, topRight);
- frustumCorners.SetRow(3, topLeft);
- material.SetMatrix(”_FrustumCornersRay”, frustumCorners);
- material.SetMatrix(”_ViewProjectionInverseMatrix”, (camera.projectionMatrix * camera.worldToCameraMatrix).inverse);
- material.SetFloat(”_FogDensity”, volume.FogDensity.value);
- material.SetFloat(”_FogStart”, volume.FogStart.value);
- material.SetFloat(”_FogEnd”, volume.FogEnd.value);
- material.SetColor(”_FogColor”, volume.FogColor.value);
- //创建一张RT
- RenderTextureDescriptor cameraTextureDesc = renderingData.cameraData.cameraTargetDescriptor;
- cameraTextureDesc.depthBufferBits = 0;
- cameraTextureDesc.msaaSamples = 1;
- //打消抗锯齿措置,抗锯齿会影响unity自动在DX与OpenGL间的坐标转换
- cmd.GetTemporaryRT(tempTexture.id, cameraTextureDesc, filterMode);
-
- //将当前帧的colorRT用着色器(shader in material)衬着后输出到之前创建的贴图(辅助RT)上
- Blit(cmd, source, tempTexture.Identifier(), material, 0);
- //将措置后的辅助RT从头衬着到当前帧的colorRT上
- Blit(cmd, tempTexture.Identifier(), source);
- }
- //执行衬着
- context.ExecuteCommandBuffer(cmd);
- //释放回收
- CommandBufferPool.Release(cmd);
- }
- public override void FrameCleanup(CommandBuffer cmd){
- base.FrameCleanup(cmd);
- cmd.ReleaseTemporaryRT(tempTexture.id);
- }
- }
- [System.Serializable]
- public class Settings{
- public RenderPassEvent Event = RenderPassEvent.AfterRenderingTransparents;
- public Shader shader;
- }
- public Settings settings = new Settings();
- CustomVolumeComponent volume;
- CustomRenderPass m_ScriptablePass;
-
- /// <inheritdoc/>
- //feature被创建时调用
- public override void Create()
- {
- var stack = VolumeManager.instance.stack;
- volume = stack.GetComponent<CustomVolumeComponent>();
- if (volume == null) {
- CoreUtils.Destroy(m_ScriptablePass.material);
- return;
- }
- m_ScriptablePass = new CustomRenderPass(settings.Event, settings.shader, volume, name);
- }
- //每一帧城市调用
- public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
- {
- var src = renderer.cameraColorTarget;
- //var dest = RenderTargetHandle.CameraTarget;
- if(settings.shader == null){
- Debug.LogWarningFormat(”shader丢掉”,GetType().Name);
- return;
- }
- //将当前衬着的colorRT传到Pass中
- m_ScriptablePass.Setup(src);
- //将Pass添加到衬着队列中
- renderer.EnqueuePass(m_ScriptablePass);
- }
- protected override void Dispose(bool disposing)
- {
- base.Dispose(disposing);
-
- }
- }
复制代码 效果图:
因为我在sense中使用的是图片,图片上没有深度分歧,所以无法在图片上不雅察看到深度分歧的雾效区别,图片以外区域可以感到感染到稍微明显的深度雾效。
如有收获,请留下“存眷”和“附和”~ |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|