IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> 【shader】游戏特效-仿《崩坏3》希儿魇夜星渊大招特效(运用CommandBuffer和屏幕后处理) -> 正文阅读

[游戏开发]【shader】游戏特效-仿《崩坏3》希儿魇夜星渊大招特效(运用CommandBuffer和屏幕后处理)

《崩坏3》4.8版本上线了希儿的新S级装甲。里面的这个大招特效让我印象特别深刻。在这里插入图片描述
(图取自b站视频,up主:橙汁玻璃瓶)
在这里插入图片描述
红色的背景加上黑色的人物剪影,这样的场面给人留下了华丽的印象并且带来了强烈的视觉冲击。其配色效果要远比黑底白影、白底黑影、蓝黑甚至黑底红影都更加出色。

这么棒的效果,没什么理由不去分析了,打开unity打开VS就开干!

Command Buffer简介

传送门:Unity官方文档
CommandBuffer就是要执行的图形命令列表。
这应该也是个缓存区,用来保存各种各样的渲染命令。
渲染命令可以选在图中任何一个绿点上执行,
摄像机上、光照上、屏幕后处理上这些的。
在这里插入图片描述

方法一:纯CommandBuffer

这个方法很简单,简单到完全不用shader,C#代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;

public class EasyMode : MonoBehaviour
{
    public Material material;
    public Renderer _renderer;

    private CommandBuffer CB;

    private void OnEnable()
    {
        CB = new CommandBuffer();
        CB.ClearRenderTarget(false, true, Color.red);
        CB.DrawRenderer(_renderer,material);
        Camera.main.AddCommandBuffer(CameraEvent.AfterImageEffects, CB);
    }

    private void OnDisable()
    {
        Camera.main.RemoveCommandBuffer(CameraEvent.AfterImageEffects,CB);
        CB.Clear();	
        CB.Release();
    }
}

效果如图:
在这里插入图片描述
主要就是这几句话起作用

CB.ClearRenderTarget(false, true, Color.red);
CB.DrawRenderer(_renderer,material);
Camera.main.AddCommandBuffer(CameraEvent.AfterImageEffects, CB);

第一句话是清除指令,会清楚掉渲染目标的深度缓存(第一个参数)和颜色缓存(第二个参数),第三个参数决定用什么颜色去覆盖渲染目标。
第二句话就是用指定材质绘制渲染器。第三句话就是将该渲染指令添加到摄像机上。

实际应用时你就在动画帧上分别设置开关脚本的事件就可以啦。

方法二:CommandBuffer + 屏幕后处理

虽然方法一很简单易懂,但是还差了下面这个效果:
在这里插入图片描述
没有溶解过渡啊!所以我决定还是写个方法二来解决。

思路是这样的:将要渲染的对象印在一张RenderTexture(以下简称RT)上,再用一张噪音图对该RT做“剔除”,形成消融效果。
最终效果长这样:
在这里插入图片描述
C#代码(挂在摄像机上):

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;

public class PostProcessing01 : MonoBehaviour
{
    public Shader shader;
    public Renderer[] renderers;	//需要渲染成黑影的对象,把他们的MeshRenderer或SkinnedMeshRenderer拖进来即可
    public Material material;	//屏幕材质
    public Material characterMaterial;	//渲染对象的材质

    private CommandBuffer CB;	

    // Start is called before the first frame update
    void Start()
    {
        //if (shader != null)
        //    material = new Material(shader);
        //else
        //{ Debug.LogError("shader出错!未能成功创建材质球!"); }
        //material.hideFlags = HideFlags.HideAndDontSave;
        
    }

    [Range(0.0f, 1.0f)]
    public float _Threshold = 0.0f;
    
    private void OnEnable()
    {
        CB = new CommandBuffer();
        //将数组中每一个渲染器都画出来
        foreach (Renderer renderer in renderers)
        { CB.DrawRenderer(renderer, characterMaterial); }
    }

    private void OnDisable()
    {
    	//一旦禁用此脚本便清理缓存
        CB.Clear();
        CB.Release();
    }

    [ImageEffectOpaque]	//在渲染完不透明物体后立即执行
    private void OnRenderImage(RenderTexture source, RenderTexture destination)
    {
    	//获得抓取的屏幕图像并返回给RT
        RenderTexture Tex1 = RenderTexture.GetTemporary(source.width, source.height);
        material.SetFloat("_Threshold", _Threshold);
        Graphics.Blit(source,Tex1, material, 0);
        material.SetTexture("_ScreenTex", source);
        //将CommandBuffer的渲染目标设置为RT
        CB.SetRenderTarget(Tex1);
        //执行命令缓存区
        Graphics.ExecuteCommandBuffer(CB);
        Graphics.Blit( Tex1, destination,material,1);
        RenderTexture.ReleaseTemporary(Tex1);
    }
}

shader代码(角色材质的):
(其实就是返回个颜色)

Shader "Unlit/ObjectShader" 
{
    SubShader 
    {
        Tags { "RenderType"="Opaque" }
        Pass 
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            struct v2f {
                float4 pos : SV_POSITION;
            };

            v2f vert( appdata_base v ) {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
				return o;
            }


            fixed4 frag(v2f i) : SV_Target {
                return fixed4(0,0,0,1);
            }
            ENDCG
        }
    }
}

Shader代码(屏幕的):

Shader "Unlit/ScreenDissolve"
{
    Properties
    {
        _MainTex ("主纹理", 2D) = "white" {}
		_NoiseTex ("噪音纹理",2D) = "white" {}
		_Threshold ("阙值",Range(0.0,1.0)) = 1.0
		_Color ("屏幕主颜色",Color) = (1,1,1,1)
		_ScreenTex("屏幕图像",2D) = "white"{}
		_Color2("边缘颜色",Color) = (1,1,1,1)
    }
    SubShader
    {
		ZWrite Off Cull Off
        Tags { "RenderType"="Transparent" "Queue" = "Transparent"}

        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;
			fixed4 _Color;

            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
            {
                return _Color;
            }
            ENDCG
        }

		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_TexelSize;
			sampler2D _ScreenTex;
			float4 _ScreenTex_TexelSize;
			sampler2D _NoiseTex;
			float4 _NoiseTex_ST;
			fixed _Threshold;
			fixed4 _Color2;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                // sample the texture
                fixed4 col1 = tex2D(_MainTex, i.uv);
				fixed4 col2 = tex2D(_ScreenTex,i.uv);
				fixed4 noise = tex2D(_NoiseTex,i.uv);

				//clip(_Threshold - noise.r);
				//可能clip太暴力,把需要的原屏幕片元也剔除了。
				//return col1;

				if(_Threshold - noise.r >= 0.02)
				{
					return col1;
				}
				else if(_Threshold - noise.r < 0)
				{
					return col2;
				}
				else
				{
					return _Color2;
				}
            }
            ENDCG
        
		}
    }
}

补充:
1、任何具有ImageEffectOpaque的图像效果都将在不透明物体渲染之后但在透明物体之前渲染。这使得大量使用深度缓冲器(比如SSAO)的效果仅影响不透明像素。该属性可用于通过后期处理减少场景中的视觉瑕疵。(参考来源:Unity官方文档

2、在OnRenderImage函数中给RT赋值的应该是RenderTexture.GetTemporary(source.width, source.height);
但我不小心写成了GetTemporary(Screen.width, Screen.height)。期间发生了很奇怪很恼火的问题,我经过两个晚上的排查后一直以为这句话是万恶之源。但是后来才发现,Screen的宽高与source的宽高其实一模一样,真正造成我问题的其实是问题3。

3、做消融效果我最早用的是clip函数,理想很丰满,但是clip可能是把原屏幕的片元也一起剔除了,导致我的消融出现了很诡异的效果。所以我决定还是用if语句返回不同的结果实现消融。

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2021-08-23 17:01:20  更:2021-08-23 17:01:32 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/5 3:33:03-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码