You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Raymarching着色器以RenderTexture为目标时无法渲染的问题

Unity Raymarching体积渲染RenderTexture无输出问题修复

问题描述

从Unity官方Texture3D文档获取的Raymarching着色器,直接挂载到材质并赋予Texture3D后可正常渲染;但通过相机渲染到RenderTexture时,RenderTexture无任何内容输出。

材质渲染结果

材质正常渲染效果

RenderTexture渲染结果

RenderTexture无输出

问题原因分析

  1. 射线方向计算错误:Shader中转换世界空间向量到物体空间时,错误使用点向量(w=1)而非方向向量(w=0),导致射线方向被物体平移变换干扰,无法正确进入体积采样范围。
  2. RenderTexture资源未释放:脚本中每次创建临时RenderTexture但未释放,易引发资源泄漏和渲染状态异常。
  3. 着色器参数传递不全:使用RenderWithShader时仅全局设置了_Texture3D,_Alpha、_StepSize等参数未赋值,可能影响采样叠加效果。

修复方案

1. 修复Shader射线方向计算

修改Shader中vert函数内的射线方向代码:
原代码:

float3 rayDirection = mul(unity_WorldToObject, float4(normalize(i.vectorToSurface), 1));

修改为:

float3 rayDirection = mul(unity_WorldToObject, float4(normalize(i.vectorToSurface), 0));

解释:方向向量无需平移变换,将w分量设为0,确保矩阵乘法仅应用旋转和缩放,避免射线方向偏移。

2. 修复脚本RenderTexture资源泄漏

在OnRenderImage方法的Graphics.Blit后添加释放代码:

Graphics.Blit(m_volumeTex, dst);
// 释放临时RenderTexture
RenderTexture.ReleaseTemporary(m_volumeTex);

3. 完善着色器参数传递(可选)

若需自定义采样参数,在脚本中添加全局参数设置:

// 在Shader.SetGlobalTexture之后添加
Shader.SetGlobalFloat("_Alpha", alpha); // alpha为自定义变量
Shader.SetGlobalFloat("_StepSize", stepSize); // stepSize为自定义变量

完整修复后的Shader代码

Shader "Test/basic_VolumeRendering"
{
    Properties
    {
        _Texture3D("Texture3D", 3D) = "white" {}
        _Alpha("Alpha", float) = 0.02
        _StepSize("Step Size", float) = 0.01
    }
        SubShader
        {
            Tags { "Queue" = "Transparent" "RenderType" = "Transparent" }
            Blend One OneMinusSrcAlpha
            LOD 100

            Pass
            {
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag

                #include "UnityCG.cginc"

                #define MAX_STEP_COUNT 128
                #define EPSILON 0.00001f

                struct appdata
                {
                    float4 vertex : POSITION;
                };

                struct v2f
                {
                    float4 vertex : SV_POSITION;
                    float3 objectVertex : TEXCOORD0;
                    float3 vectorToSurface : TEXCOORD1;
                };

                sampler3D _Texture3D;
                float4 _MainTex_ST;
                float _Alpha;
                float _StepSize;

                v2f vert(appdata v)
                {
                    v2f o;
                    o.objectVertex = v.vertex;

                    float3 worldVertex = mul(unity_ObjectToWorld, v.vertex).xyz;
                    o.vectorToSurface = worldVertex - _WorldSpaceCameraPos;

                    o.vertex = UnityObjectToClipPos(v.vertex);
                    return o;
                }

                float4 BlendUnder(float4 color, float4 newColor)
                {
                    color.rgb += (1.0 - color.a) * newColor.a * newColor.rgb;
                    color.a += (1.0 - color.a) * newColor.a;
                    return color;
                }

                fixed4 frag(v2f i) : SV_Target
                {
                    float3 rayOrigin = i.objectVertex;
                    float3 rayDirection = mul(unity_WorldToObject, float4(normalize(i.vectorToSurface), 0));

                    float4 color = float4(0, 0, 0, 0);
                    float3 samplePosition = rayOrigin;

                    for (int stepIdx = 0; stepIdx < MAX_STEP_COUNT; stepIdx++)
                    {
                        if (max(abs(samplePosition.x), max(abs(samplePosition.y), abs(samplePosition.z))) < 0.5f + EPSILON)
                        {
                            float4 sampledColor = tex3D(_Texture3D, samplePosition + float3(0.5f, 0.5f, 0.5f));
                            sampledColor.a *= _Alpha;
                            color = BlendUnder(color, sampledColor);
                            samplePosition += rayDirection * _StepSize;
                        }
                    }

                    return color;
                }
                ENDCG
            }
        }
}

完整修复后的脚本代码

using UnityEngine;

[ExecuteInEditMode]
public class Volume_Renderer_Debug : MonoBehaviour
{
    public Shader volumeShader;
    public Texture3D data;
    public float alpha = 0.02f;
    public float stepSize = 0.01f;
    private Camera m_camera = null;
    private Camera m_cameraCopy = null;
    private GameObject cameraCopyObj = null;


    void Awake()
    {
        m_camera = GetComponent<Camera>();
        if (cameraCopyObj != null)
        {
            DestroyImmediate(cameraCopyObj);
        }
        cameraCopyObj = new GameObject("cameraCopy");
        cameraCopyObj.hideFlags = HideFlags.DontSave;
        cameraCopyObj.transform.parent = transform;
        cameraCopyObj.transform.localPosition = Vector3.zero;
        m_cameraCopy = cameraCopyObj.AddComponent<Camera>();
        m_cameraCopy.CopyFrom(m_camera);
        m_cameraCopy.clearFlags = CameraClearFlags.SolidColor;
        m_cameraCopy.enabled = false;
    }

    void OnDestroy()
    {
        DestroyImmediate(cameraCopyObj);
    }

    void OnPreRender()
    {
        m_camera.cullingMask = 0;
    }

    void OnRenderImage(RenderTexture src, RenderTexture dst)
    {
        RenderTexture m_volumeTex = RenderTexture.GetTemporary(Screen.width, Screen.height, 24, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
        m_cameraCopy.targetTexture = m_volumeTex;
        m_cameraCopy.backgroundColor = new Color(0.7f, 0.5f, 0.7f, 0.0f);
        m_cameraCopy.clearFlags = CameraClearFlags.Color;
        m_cameraCopy.cullingMask = 1 << LayerMask.NameToLayer("Volume");
        
        Shader.SetGlobalTexture("_Texture3D", data);
        Shader.SetGlobalFloat("_Alpha", alpha);
        Shader.SetGlobalFloat("_StepSize", stepSize);
        
        m_cameraCopy.RenderWithShader(volumeShader, null);
        Graphics.Blit(m_volumeTex, dst);
        
        RenderTexture.ReleaseTemporary(m_volumeTex);
    }
}

内容的提问来源于stack exchange,提问作者HTTRCH

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 18:05:25