HDRP图形入门:RTHandle未知问题

news2024/12/23 15:43:55

      正好电脑看奥本海默,全程尿点十足,就一边看一边把之前整合HDRP遇到的问题说一下。
      那就是RTHandle的未知问题,这是官方对RTHandle的说明:
      unity RTHandle
      源代码如下:

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

namespace UnityEngine.Rendering
{
    /// <summary>
    /// A RTHandle is a RenderTexture that scales automatically with the camera size.
    /// This allows proper reutilization of RenderTexture memory when different cameras with various sizes are used during rendering.
    /// <seealso cref="RTHandleSystem"/>
    /// </summary>
    public class RTHandle
    {
        internal RTHandleSystem m_Owner;
        internal RenderTexture m_RT;
        internal Texture m_ExternalTexture;
        internal RenderTargetIdentifier m_NameID;
        internal bool m_EnableMSAA = false;
        internal bool m_EnableRandomWrite = false;
        internal bool m_EnableHWDynamicScale = false;
        internal string m_Name;

        internal bool m_UseCustomHandleScales = false;
        internal RTHandleProperties m_CustomHandleProperties;

        /// <summary>
        /// By default, rtHandleProperties gets the global state of scalers against the global reference mode.
        /// This method lets the current RTHandle use a local custom RTHandleProperties. This function is being used
        /// by scalers such as TAAU and DLSS, which require to have a different resolution for color (independent of the RTHandleSystem).
        /// </summary>
        /// <param name="properties">Properties to set.</param>
        public void SetCustomHandleProperties(in RTHandleProperties properties)
        {
            m_UseCustomHandleScales = true;
            m_CustomHandleProperties = properties;
        }

        /// <summary>
        /// Method that clears any custom handle property being set.
        /// </summary>
        public void ClearCustomHandleProperties()
        {
            m_UseCustomHandleScales = false;
        }

        /// <summary>
        /// Scale factor applied to the RTHandle reference size.
        /// </summary>
        public Vector2 scaleFactor { get; internal set; }
        internal ScaleFunc scaleFunc;

        /// <summary>
        /// Returns true if the RTHandle uses automatic scaling.
        /// </summary>
        public bool useScaling { get; internal set; }
        /// <summary>
        /// Reference size of the RTHandle System associated with the RTHandle
        /// </summary>
        public Vector2Int referenceSize { get; internal set; }
        /// <summary>
        /// Current properties of the RTHandle System. If a custom property has been set through SetCustomHandleProperties method, it will be used that one instead.
        /// </summary>
        public RTHandleProperties rtHandleProperties { get { return m_UseCustomHandleScales ? m_CustomHandleProperties : m_Owner.rtHandleProperties; } }
        /// <summary>
        /// RenderTexture associated with the RTHandle
        /// </summary>
        public RenderTexture rt { get { return m_RT; } }
        /// <summary>
        /// RenderTargetIdentifier associated with the RTHandle
        /// </summary>
        public RenderTargetIdentifier nameID { get { return m_NameID; } }
        /// <summary>
        /// Name of the RTHandle
        /// </summary>
        public string name { get { return m_Name; } }

        /// <summary>
        /// Returns true is MSAA is enabled, false otherwise.
        /// </summary>
        public bool isMSAAEnabled { get { return m_EnableMSAA; } }

        // Keep constructor private
        internal RTHandle(RTHandleSystem owner)
        {
            m_Owner = owner;
        }

        /// <summary>
        /// Implicit conversion operator to RenderTargetIdentifier
        /// </summary>
        /// <param name="handle">Input RTHandle</param>
        /// <returns>RenderTargetIdentifier representation of the RTHandle.</returns>
        public static implicit operator RenderTargetIdentifier(RTHandle handle)
        {
            return handle != null ? handle.nameID : default(RenderTargetIdentifier);
        }

        /// <summary>
        /// Implicit conversion operator to Texture
        /// </summary>
        /// <param name="handle">Input RTHandle</param>
        /// <returns>Texture representation of the RTHandle.</returns>
        public static implicit operator Texture(RTHandle handle)
        {
            // If RTHandle is null then conversion should give a null Texture
            if (handle == null)
                return null;

            Debug.Assert(handle.m_ExternalTexture != null || handle.rt != null);
            return (handle.rt != null) ? handle.rt : handle.m_ExternalTexture;
        }

        /// <summary>
        /// Implicit conversion operator to RenderTexture
        /// </summary>
        /// <param name="handle">Input RTHandle</param>
        /// <returns>RenderTexture representation of the RTHandle.</returns>
        public static implicit operator RenderTexture(RTHandle handle)
        {
            // If RTHandle is null then conversion should give a null RenderTexture
            if (handle == null)
                return null;

            Debug.Assert(handle.rt != null, "RTHandle was created using a regular Texture and is used as a RenderTexture");
            return handle.rt;
        }

        internal void SetRenderTexture(RenderTexture rt)
        {
            m_RT = rt;
            m_ExternalTexture = null;
            m_NameID = new RenderTargetIdentifier(rt);
        }

        internal void SetTexture(Texture tex)
        {
            m_RT = null;
            m_ExternalTexture = tex;
            m_NameID = new RenderTargetIdentifier(tex);
        }

        internal void SetTexture(RenderTargetIdentifier tex)
        {
            m_RT = null;
            m_ExternalTexture = null;
            m_NameID = tex;
        }

        /// <summary>
        /// Get the Instance ID of the RTHandle.
        /// </summary>
        /// <returns>The RTHandle Instance ID.</returns>
        public int GetInstanceID()
        {
            if (m_RT != null)
                return m_RT.GetInstanceID();
            else if (m_ExternalTexture != null)
                return m_ExternalTexture.GetInstanceID();
            else
                return m_NameID.GetHashCode(); // No instance ID so we return the hash code.
        }

        /// <summary>
        /// Release the RTHandle
        /// </summary>
        public void Release()
        {
            m_Owner.Remove(this);
            CoreUtils.Destroy(m_RT);
            m_NameID = BuiltinRenderTextureType.None;
            m_RT = null;
            m_ExternalTexture = null;
        }

        /// <summary>
        /// Return the input size, scaled by the RTHandle scale factor.
        /// </summary>
        /// <param name="refSize">Input size</param>
        /// <returns>Input size scaled by the RTHandle scale factor.</returns>
        public Vector2Int GetScaledSize(Vector2Int refSize)
        {
            if (!useScaling)
                return refSize;

            if (scaleFunc != null)
            {
                return scaleFunc(refSize);
            }
            else
            {
                return new Vector2Int(
                    x: Mathf.RoundToInt(scaleFactor.x * refSize.x),
                    y: Mathf.RoundToInt(scaleFactor.y * refSize.y)
                );
            }
        }

        /// <summary>
        /// Return the scaled size of the RTHandle.
        /// </summary>
        /// <returns>The scaled size of the RTHandle.</returns>
        public Vector2Int GetScaledSize()
        {
            if (scaleFunc != null)
            {
                return scaleFunc(referenceSize);
            }
            else
            {
                return new Vector2Int(
                    x: Mathf.RoundToInt(scaleFactor.x * referenceSize.x),
                    y: Mathf.RoundToInt(scaleFactor.y * referenceSize.y)
                );
            }
        }

#if UNITY_2020_2_OR_NEWER
        /// <summary>
        /// Switch the render target to fast memory on platform that have it.
        /// </summary>
        /// <param name="cmd">Command buffer used for rendering.</param>
        /// <param name="residencyFraction">How much of the render target is to be switched into fast memory (between 0 and 1).</param>
        /// <param name="flags">Flag to determine what parts of the render target is spilled if not fully resident in fast memory.</param>
        /// <param name="copyContents">Whether the content of render target are copied or not when switching to fast memory.</param>

        public void SwitchToFastMemory(CommandBuffer cmd,
            float residencyFraction = 1.0f,
            FastMemoryFlags flags = FastMemoryFlags.SpillTop,
            bool copyContents = false
        )
        {
            residencyFraction = Mathf.Clamp01(residencyFraction);
            cmd.SwitchIntoFastMemory(m_RT, flags, residencyFraction, copyContents);
        }

        /// <summary>
        /// Switch the render target to fast memory on platform that have it and copies the content.
        /// </summary>
        /// <param name="cmd">Command buffer used for rendering.</param>
        /// <param name="residencyFraction">How much of the render target is to be switched into fast memory (between 0 and 1).</param>
        /// <param name="flags">Flag to determine what parts of the render target is spilled if not fully resident in fast memory.</param>
        public void CopyToFastMemory(CommandBuffer cmd,
            float residencyFraction = 1.0f,
            FastMemoryFlags flags = FastMemoryFlags.SpillTop
        )
        {
            SwitchToFastMemory(cmd, residencyFraction, flags, copyContents: true);
        }

        /// <summary>
        /// Switch out the render target from fast memory back to main memory on platforms that have fast memory.
        /// </summary>
        /// <param name="cmd">Command buffer used for rendering.</param>
        /// <param name="copyContents">Whether the content of render target are copied or not when switching out fast memory.</param>
        public void SwitchOutFastMemory(CommandBuffer cmd, bool copyContents = true)
        {
            cmd.SwitchOutOfFastMemory(m_RT, copyContents);
        }

#endif
    }
}

      我自己把它理解为一个动态的RT,和RT一样的使用,当然写代码用起来很容易。却碰到一个问题,以多迭代高斯滤波为例,使用RTHandle会造成纹理“发黄”,如下:
在这里插入图片描述      当时没感觉有问题,后面同事说这效果好奇怪,好黄?!我就感觉确实。起初我以为我shader颜色计算出问题了,查了半天不是。我百度google查了仅有不多有关RTHandle的帖子,并没找到相关问题,不过有个博主说复制一份RTHandle使用,我尝试做了一下,果然ok了。

//复制一份原始纹理
private RTHandle copySource;

public override void Setup()
{
    if (Shader.Find(shaderName) != null)
    {
        mat = new Material(Shader.Find(shaderName));

        copySource = RTHandles.Alloc(Vector2.one, filterMode: FilterMode.Bilinear, dimension: TextureDimension.Tex2DArray);
    }
    else
        Debug.LogError($"Unable to find shader '{shaderName}'. Post Process Volume GuassBlurPostProcessVolume is unable to load.");
}

public override void Render(CommandBuffer cmd, HDCamera camera, RTHandle source, RTHandle destination)
{
    if (mat == null || !isBlur.value)
    {
        return;
    }

    mat.SetFloat("_Brightness", brightness.value);

    //复制一份纹理
    //注意:由原始的纹理数组传递到单纹理,原始的纹理数组封装了多种平台下纹理集合
    HDUtils.BlitCameraTexture(cmd, source, copySource);

    //使用复制RTH还是原始RTH
    RenderTexture rtinput = isCopyRT.value ? copySource : source;

    int rtwid = rtinput.width / downSample.value;
    int rthei = rtinput.height / downSample.value;

    mat.SetTexture("_InputTex", rtinput);

    //对pass0进行迭代,增加高斯滤波次数和效果
    for (float it = 0; it < iterations.value; it += 0.2f)
    {
        mat.SetFloat("_BlurSpread", 1.0f + it * blurSpread.value);

        //滤波采样一次
        RenderTexture rt1 = RenderTexture.GetTemporary(rtwid, rthei, 0);

        cmd.Blit(rtinput, rt1, mat, 0);
        //叠加滤波
        cmd.Blit(rt1, rtinput);

        RenderTexture.ReleaseTemporary(rt1);
    }

    //采样迭代后的纹理
    mat.SetTexture("_IterTex", rtinput);

    cmd.Blit(rtinput, destination, mat, 1);
}

public override void Cleanup()
{
    CoreUtils.Destroy(mat);
    RTHandles.Release(copySource);
}

      虽然不明白为什么会这样,但确实解决了问题,如下:
在这里插入图片描述      如果大家写渲染功能,碰到类似的问题,不妨Copy一份RTHandle。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1218090.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

react+video.js h5自定义视频暂停图标

目录 参考网址 效果图&#xff0c;暂停时显示暂停图标&#xff0c;播放时隐藏暂停图标 代码说明&#xff0c;代码传入url后&#xff0c;可直接复制使用 VideoPausedIcon.ts 组件 VideoCom.tsx Video.module.less 参考网址 在Video.js播放器中定制自己的组件 - acgtofe 效…

【vue2】前端如何播放rtsp 视频流,拿到rtsp视频流地址如何处理,海康视频rtsp h264 如何播放

文章目录 测试以vue2 为例新建 webrtcstreamer.js下载webrtc-streamervideo.vue页面中调用 最近在写vue2 项目其中有个需求是实时播放摄像头的视频&#xff0c;摄像头是 海康的设备&#xff0c;搞了很长时间终于监控视频出来了&#xff0c;记录一下&#xff0c;放置下次遇到。…

《QT从基础到进阶·三十》QVariant的基础用法

很多时候&#xff0c;需要几种不同的数据类型需要传递&#xff0c;如果用结构体&#xff0c;又不大方便&#xff0c;容器保存的也只是一种数据类型&#xff0c;而QVariant则可以统统搞定。 QVariant可以保存QT和C常用类型&#xff0c;如果是自定义类型&#xff0c;比如struct,c…

克鲁斯卡尔算法(C++)

目录 克鲁斯卡尔算法 ​编辑代码&#xff1a; 结果&#xff1a; 克鲁斯卡尔算法 克鲁斯卡尔算法是一种用于求解最小生成树的算法。最小生成树是指一棵包含了所有节点的连通图&#xff0c;并且边的权值之和最小。 克鲁斯卡尔算法的基本思想是&#xff0c;每次选择图中最小的…

【漏洞复现】OneThink前台注入漏洞

漏洞描述 OneThink 是一个基于 PHP 的开源内容管理框架&#xff0c;旨在简化和加速Web应用程序的开发过程。它提供了一系列通用的模块和功能&#xff0c;使开发者能够更轻松地构建具有灵活性和可扩展性的内容管理系统&#xff08;CMS&#xff09;和其他Web应用。 免责声明 …

nodejs+vue教室管理系统的设计与实现-微信小程序-安卓-python-PHP-计算机毕业设计

用户 用户管理&#xff1a;查看&#xff0c;修改自己的个人信息 教室预约&#xff1a;可以预约今天明天的教室&#xff0c;按着时间段预约&#xff08;可多选&#xff09;&#xff0c;如果当前时间超过预约时间段不能预约该时间段的教室 预约教室的时候要有个预约用途&#xff…

Python爬虫教程:从入门到实战

更多Python学习内容&#xff1a;ipengtao.com 大家好&#xff0c;我是涛哥&#xff0c;今天为大家分享 Python爬虫教程&#xff1a;从入门到实战&#xff0c;文章3800字&#xff0c;阅读大约15分钟&#xff0c;大家enjoy~~ 网络上的信息浩如烟海&#xff0c;而爬虫&#xff08;…

Javaweb之Vue指令的详细解析

2.3 Vue指令 在上述的快速入门中&#xff0c;我们发现了html中输入了一个没有学过的属性v-model&#xff0c;这个就是vue的指令。 指令&#xff1a;HTML 标签上带有 v- 前缀的特殊属性&#xff0c;不同指令具有不同含义。例如&#xff1a;v-if&#xff0c;v-for… 在vue中&a…

人工智能基础_机器学习039_sigmoid函数_逻辑回归_逻辑斯蒂回归_分类神器_代码实现逻辑回归图---人工智能工作笔记0079

逻辑斯蒂回归(Logistic Regression)是一种常用的分类算法,其基本思想是通过拟合一个逻辑斯蒂函数来预测样本所属的类别。它广泛应用于各个领域,如医学、金融、市场营销等,具有较好的解释性和可解释性。在逻辑斯蒂回归中,我们通常使用的是二分类问题,即样本只属于两个类别…

Vue+ElementUI技巧分享:自定义表单项label的文字提示

文章目录 概要在表单项label后添加文字提示1. 使用 Slot 自定义 Label2. 添加问号图标与提示信息 slot的作用详解1. 基本用法2. 具名插槽 显示多行文字提示的方法1. 问题背景2. 实现多行内容显示3. 样式优化 结语 概要 在Vue和ElementUI的丰富组件库中&#xff0c;定制化表单是…

01_SHELL编程之变量定义(一)

SHELL编程 该课程主要包括以下内容&#xff1a; ① Shell的基本语法结构 如&#xff1a;变量定义、条件判断、循环语句(for、until、while)、分支语句、函数和数组等&#xff1b; ② 基本正则表达式的运用&#xff1b; ③ 文件处理三剑客&#xff1a;grep、sed、awk工具的使用&…

确保人工智能的公平性:生成无偏差综合数据的策略

一、介绍 合成数据生成涉及创建密切模仿现实世界数据但不包含任何实际个人信息的人工数据&#xff0c;从而保护隐私和机密性。然而&#xff0c;至关重要的是&#xff0c;这些数据必须以公平、公正的方式生成&#xff0c;以防止人工智能应用中现有的偏见长期存在或扩大。 在数据…

R语言——taxize(第二部分)

taxize&#xff08;第二部分&#xff09; 3. taxize 文档中译3.10. classification&#xff08;根据类群ID检索分类阶元层级&#xff09;示例1&#xff1a;传递单个ID值示例2&#xff1a;传递多个ID值示例3&#xff1a;传递单个名称示例4&#xff1a;传递多个名称示例5&#xf…

Spring SPI

SPI 服务供给接口&#xff08;Service Provider Interface&#xff09;。是Java 1.5新添加的一个内置标准&#xff0c;允许不同的开发者去实现某个特定的服务。 1 SPI 介绍 一个接口&#xff0c;可能会有许多个实现&#xff0c;我们在编写代码时希望能动态切换具体实现&#…

微服务测试怎么做

开发团队越来越多地选择微服务架构而不是单体结构&#xff0c;以提高应用程序的敏捷性、可扩展性和可维护性。随着决定切换到模块化软件架构——其中每个服务都是一个独立的单元&#xff0c;具有自己的逻辑和数据库&#xff0c;通过 API 与其他单元通信——需要新的测试策略和新…

关系代数、SQL语句和Go语言示例

近些年&#xff0c;数据库领域发展日新月异&#xff0c;除传统的关系型数据库外&#xff0c;还出现了许多新型的数据库&#xff0c;比如&#xff1a;以HBase、Cassandra、MongoDB为代表的NoSQL数据库&#xff0c;以InfluxDB、TDEngine为代表的时序数据[1]库&#xff0c;以Neo4J…

设计模式-代理模式-笔记

动机&#xff08;Motivation&#xff09; 在面向对象系统中&#xff0c;有些对象由于某种原因&#xff08;比如对象创建的开销很大&#xff0c;或者某些操作需要安全控制&#xff0c;或者需要远程外的访问等&#xff09;&#xff0c;直接访问会给使用者、或者系统结构带来很多…

【Linux网络】工作环境救急——关于yum安装的5个花式操作

目录 1、只下载不安装&#xff0c;离线安装软件 2、自行打包创建元数据 第一步&#xff1a;先准备好nginx的软件包&#xff0c;放在一个文件夹下 第二步&#xff1a;在本地下载createrepo命令软件&#xff0c;用于创建元信息&#xff0c;这个一定是对包的上一级目录使用命令…

cpolar+LightPicture,将个人电脑改造成公网图床服务器

文章目录 1.前言2. Lightpicture网站搭建2.1. Lightpicture下载和安装2.2. Lightpicture网页测试2.3.cpolar的安装和注册 3.本地网页发布3.1.Cpolar云端设置3.2.Cpolar本地设置 4.公网访问测试5.结语 1.前言 现在的手机越来越先进&#xff0c;功能也越来越多&#xff0c;而手机…

QNX Typed memory介绍

文章目录 前言一、什么是 Typed memory二、查看系统已有Typed memory 的方法三、Typed memory 的使用方法1.定义一个packet memory并从系统内存中分出它1.1 as_add()1.2 as_add_containing()2. 从 Typed memory 中申请内存2.1 POSIX method 申请内存2.2 QNX Neutrino method 申…