unity 写一个 bloom shader (built-in 和 urp 实现方式)

在Unity中编写一个Bloom(发光)shader是一个相对复杂的任务,因为它涉及到多个渲染步骤和后期处理效果。Bloom效果通常是通过提取场景中的高亮部分,并将它们模糊后叠加回原始图像来实现的。

下面是一个简单的Bloom shader示例,它使用了Unity的ShaderLab语言。请注意,这个示例是一个基本的框架,你可能需要根据你的具体需求进行调整和优化。

首先,创建一个新的shader文件(例如Bloom.shader),并输入以下代码:

 

shader复制代码

Shader "Custom/Bloom"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_BloomThreshold ("Bloom Threshold", Range(0, 1)) = 0.5
_BloomIntensity ("Bloom Intensity", Range(0, 5)) = 1.0
_BlurRadius ("Blur Radius", Range(0, 10)) = 2.0
}
SubShader
{
// No lighting
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float _BloomThreshold;
float _BloomIntensity;
float _BlurRadius;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
float brightness = dot(col.rgb, float3(0.299, 0.587, 0.114)); // 计算亮度(简单加权平均)
float bloomAmount = smoothstep(_BloomThreshold, _BloomThreshold + 0.01, brightness); // 使用smoothstep函数平滑过渡
col.rgb += bloomAmount * _BloomIntensity; // 应用发光强度
return col;
}
ENDCG
}
// 这里可以添加额外的Pass来处理模糊效果,例如使用四方向模糊或者高斯模糊。
// 由于模糊通常涉及多个采样和复杂的计算,它通常作为后期处理步骤在屏幕空间中进行。
}
}

这个shader的基本思路是:

  1. 在片段着色器frag中计算像素的亮度。
  2. 使用smoothstep函数基于亮度和阈值来确定像素是否应该发光。
  3. 将发光量乘以强度并加到原始颜色上。

这个简单的shader并没有包含实际的模糊步骤,因为模糊通常作为后期处理步骤在屏幕空间中进行,而不是在物体的材质上直接进行。实现屏幕空间模糊效果需要创建一个后期处理shader,它将在整个渲染的场景上操作,并使用诸如高斯模糊等算法。

要在Unity中实现完整的Bloom效果,你通常会使用Unity的后期处理堆栈(Post-processing Stack),这是一个强大的工具集,允许你通过简单的配置来添加各种后期处理效果,包括Bloom。如果你想要从头开始实现自己的后期处理效果,你需要深入了解Unity的渲染管线和后期处理原理,并编写相应的C#脚本和shader代码。

在Unity的Universal Render Pipeline (URP)中实现Bloom效果需要编写一个自定义的后期处理shader,并将其集成到URP的后期处理堆栈中。下面是一个简化的步骤指南,帮助你开始编写一个基于URP的Bloom shader。

步骤 1: 创建后期处理shader
首先,你需要创建一个shader文件(例如Bloom.shader),并编写用于后期处理的片段着色器代码。这通常涉及到读取场景的颜色缓冲区,并根据亮度应用发光效果。

shader
复制代码
Shader "Custom/Bloom"  
{  
    Properties  
    {  
        _MainTex ("Texture", 2D) = "white" {}  
        _BloomThreshold ("Bloom Threshold", Range(0, 1)) = 0.5  
        _BloomIntensity ("Bloom Intensity", Range(0, 5)) = 1.0  
        _BlurRadius ("Blur Radius", Range(0, 10)) = 2.0  
    }  
    SubShader  
    {  
        Tags { "RenderType"="Opaque" "ReverbMaterial"="Universal" "RenderPipeline"="UniversalRenderPipeline" }  
        LOD 100  
  
        Pass  
        {  
            Name "Bloom"  
            Tags { "LightMode"="UniversalForward" }  
  
            CGPROGRAM  
            #pragma vertex vert  
            #pragma fragment frag  
  
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"  
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"  
  
            struct appdata  
            {  
                float4 vertex : POSITION;  
                float2 uv : TEXCOORD0;  
            };  
  
            struct v2f  
            {  
                float2 uv : TEXCOORD0;  
                float4 vertex : SV_POSITION;  
            };  
  
            sampler2D _MainTex;  
            float4 _MainTex_ST;  
            float _BloomThreshold;  
            float _BloomIntensity;  
            float _BlurRadius;  
  
            v2f vert (appdata v)  
            {  
                v2f o;  
                o.vertex = TransformObjectToHClip(v.vertex.xyz);  
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);  
                return o;  
            }  
  
            half4 frag (v2f i) : SV_Target  
            {  
                half4 col = SAMPLE_TEXTURE2D(_MainTex, s_sampler_MainTex, i.uv);  
                float brightness = dot(col.rgb, float3(0.299, 0.587, 0.114)); // 计算亮度  
                float bloomAmount = smoothstep(_BloomThreshold, _BloomThreshold + 0.01, brightness); // 应用阈值  
                col.rgb += bloomAmount * _BloomIntensity; // 应用发光强度  
                return col;  
            }  
            ENDCG  
        }  
    }  
}

步骤 2: 创建后期处理效果脚本

接下来,你需要创建一个C#脚本(例如BloomEffect.cs),用于控制后期处理效果的参数,并将其应用到渲染的图像上。

 

csharp复制代码

using UnityEngine;
using UnityEngine.Rendering.Universal;
[Serializable, VolumeComponentMenu("Custom/Bloom")]
public class BloomEffect : VolumeComponent, IPostProcessComponent
{
public ClampedFloatParameter bloomThreshold = new ClampedFloatParameter(0.5f, 0f, 1f);
public ClampedFloatParameter bloomIntensity = new ClampedFloatParameter(1f, 0f, 5f);
public ClampedFloatParameter blurRadius = new ClampedFloatParameter(2f, 0f, 10f);
public bool IsActive() => bloomThreshold.value > 0f;
public void Render(ScriptableRenderContext context, ref RenderingData renderingData)
{
var cmd = CommandBufferPool.Get("Bloom");
var sheet = new MaterialPropertyBlock();
sheet.SetFloat("_BloomThreshold", bloomThreshold.value);
sheet.SetFloat("_BloomIntensity", bloomIntensity.value);
sheet.SetFloat("_BlurRadius", blurRadius.value);
var t = Shader.Find("Custom/Bloom");
var bloomMaterial = new Material(t);
// 这里你需要添加代码来创建模糊效果,这通常涉及创建一个单独的渲染目标来存储发光部分,并对其进行模糊。

// 然后,将模糊后的发光部分与原始图像混合。

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值