unity shader效果教程附详细代码_屏幕后处理效果

写在前面

这个系列来源于书籍冯乐乐老师的《unity shader 入门精要》,
参考的代码库“https://github.com/candycat1992/Unity_Shaders_Book”
我自己跟着写了一遍代码,并在代码块里给shader代码加上了比较详细的注释
更为仔细的解释和unity shader原理和知识书里都有,本blog不做详细解释,推荐买书来看。
本项目的所有代码在https://github.com/takashiwangbh/Unity-shader-effect-reproduction/tree/main

介绍

屏幕后处理效果是游戏种实现屏幕特效的常见方法,是对游戏画面在渲染完成后进行的视觉调整,比如亮度、对比度、模糊、光晕等,提升画面质量和艺术效果。

要实现屏幕后处理的基础在于得到渲染后的屏幕图像,也就是抓取屏幕,而unity提供了一个方便的接口——OnRenderImage。这部分的shader都是挂在摄像机上,其实是通过摄像机去渲染我们想要的效果,而不是直接渲染物体,所以在unity的Scene界面看不到效果,在game界面就能看到最后的效果。

C# 脚本:控制和管理逻辑

  • 职责:处理逻辑,设置参数,控制流程。
  • 作用
    • 管理 Shader 的参数,例如亮度阈值、模糊半径等。
    • 控制后处理效果的强度和行为,比如动态调整模糊层级。
    • 处理渲染目标(RenderTexture)的创建和释放。
  • 实现
    • 在 C# 中,通过 Material 将参数值传递给 Shader。
    • 使用 Graphics.Blit 将图像从一个渲染目标复制到另一个,并应用 Shader。

Shader:具体的视觉效果实现

  • 职责:定义像素的渲染规则,决定屏幕效果如何呈现。
  • 作用
    • 操作每个像素的颜色和亮度,比如提取高亮部分。
    • 执行模糊、合并等操作,创造特定的视觉效果。
    • 实现 C# 脚本中配置的视觉逻辑。

总的来说就是C# 脚本负责控制逻辑和传递参数,Shader 负责实现具体的视觉效果,二者配合完成后处理渲染。

本期将会使用屏幕后处理效果实现一些图像处理的功能。

调整亮度,饱和度和对比度

给相机加上脚本

/*
这个脚本用于实现屏幕后处理效果中的亮度、饱和度和对比度调整。
它通过自定义的 Shader 来处理图像,并允许开发者在 Unity Inspector 中
调整亮度、饱和度和对比度的数值,从而实时影响画面效果。
*/

using UnityEngine;
using System.Collections;

public class BrightnessSaturationAndContrast : PostEffectsBase {
   
   

    // 引用一个自定义 Shader,用于调整亮度、饱和度和对比度
    public Shader briSatConShader;

    // 基于 Shader 创建的材质,用于应用屏后处理效果
    private Material briSatConMaterial;

    // 延迟加载材质,当需要时自动检查 Shader 并创建材质
    public Material material {
   
     
        get {
   
   
            // 检查 Shader 是否支持并创建材质
            briSatConMaterial = CheckShaderAndCreateMaterial(briSatConShader, briSatConMaterial);
            return briSatConMaterial;
        }  
    }

    // 亮度调整范围(从 0.0 到 3.0),默认值为 1.0
    [Range(0.0f, 3.0f)]
    public float brightness = 1.0f;

    // 饱和度调整范围(从 0.0 到 3.0),默认值为 1.0
    [Range(0.0f, 3.0f)]
    public float saturation = 1.0f;

    // 对比度调整范围(从 0.0 到 3.0),默认值为 1.0
    [Range(0.0f, 3.0f)]
    public float contrast = 1.0f;

    // Unity 中的屏后处理方法,在摄像机渲染完成后调用
    void OnRenderImage(RenderTexture src, RenderTexture dest) {
   
   
        // 检查材质是否可用
        if (material != null) {
   
   
            // 将亮度、饱和度和对比度的值传递给 Shader
            material.SetFloat("_Brightness", brightness);
            material.SetFloat("_Saturation", saturation);
            material.SetFloat("_Contrast", contrast);

            // 使用材质将源纹理 (src) 渲染到目标纹理 (dest)
            Graphics.Blit(src, dest, material);
        } else {
   
   
            // 如果材质不可用,直接将源纹理复制到目标纹理
            Graphics.Blit(src, dest);
        }
    }
}

在相机的属性界面,在挂脚本的组件里引用shader

/*
这个 Shader 用于调整图像的亮度、饱和度和对比度。
开发者可以通过在 Unity Inspector 中设置对应的参数值,
实时改变画面效果,从而实现所需的图像调整功能。
*/

Shader "Basic properties of images" {
   
   
    Properties {
   
   
        // 定义 Shader 可调节的属性:主纹理、亮度、饱和度和对比度
        _MainTex ("Base (RGB)", 2D) = "white" {
   
   }
        _Brightness ("Brightness", Float) = 1
        _Saturation("Saturation", Float) = 1
        _Contrast("Contrast", Float) = 1
    }
    SubShader {
   
   
        Pass {
   
     
            // 禁用深度测试和剔除,设置为始终渲染
            ZTest Always Cull Off ZWrite Off
            
            CGPROGRAM  
            #pragma vertex vert  
            #pragma fragment frag  
              
            #include "UnityCG.cginc"  
              
            // 定义纹理和调节参数
            sampler2D _MainTex;  
            half _Brightness;
            half _Saturation;
            half _Contrast;
              
            // 顶点着色器输出结构
            struct v2f {
   
   
                float4 pos : SV_POSITION;  // 顶点位置
                half2 uv: TEXCOORD0;       // 纹理坐标
            };
              
            // 顶点着色器:将顶点坐标转换为剪辑空间坐标,并传递纹理坐标
            v2f vert(appdata_img v) {
   
   
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv = v.texcoord;
                return o;
            }
        
            // 片段着色器:对图像像素应用亮度、饱和度和对比度调整
            fixed4 frag(v2f i) : SV_Target {
   
   
                // 读取纹理像素颜色
                fixed4 renderTex = tex2D(_MainTex, i.uv);  
                  
                // 调整亮度
                fixed3 finalColor = renderTex.rgb * _Brightness;
                
                // 调整饱和度
                fixed luminance = 0.2125 * renderTex.r + 0.7154 * renderTex.g + 0.0721 * renderTex.b; // 计算亮度值
                fixed3 luminanceColor = fixed3(luminance, luminance, luminance); // 构造灰度图
                finalColor = lerp(luminanceColor, finalColor, _Saturation); // 根据饱和度插值
                
                // 调整对比度
                fixed3 avgColor = fixed3(0.5, 0.5, 0.5); // 基准值
                finalColor = lerp(avgColor, finalColor, _Contrast); // 根据对比度插值
                
                // 返回调整后的颜色,保留原始透明度
                return fixed4(finalColor, renderTex.a);  
            }  
              
            ENDCG
        }  
    }
    
    // 禁用回退到默认 Shader
    Fallback Off
}

效果展示

请添加图片描述

边缘检测

给相机加上脚本

/*
这个脚本用于实现屏幕后处理的边缘检测效果。
通过自定义 Shader,对图像的边缘进行检测,并允许用户调整边缘的显示方式,
如边缘透明度、边缘颜色和背景颜色。

*/

using UnityEngine;
using System.Collections;

public class EdgeDetection : PostEffectsBase {
   
   

    // 引用用于边缘检测的 Shader
    public Shader edgeDetectShader;

    // 用于存储和应用 Shader 的材质
    private Material edgeDetectMaterial = null;

    // 延迟加载材质,确保 Shader 检查通过后创建材质
    public Material material {
   
     
        get {
   
   
            edgeDetectMaterial = CheckShaderAndCreateMaterial(edgeDetectShader, edgeDetectMaterial);
            return edgeDetectMaterial;
        }  
    }

    // 边缘显示的强度范围(0 表示完全显示背景,1 表示只显示边缘)
    [
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值