2401_86315033 2024-07-16 15:10 采纳率: 20%
浏览 1

unity自制光追不渲染场景中的物体,渲染用时越来越长怎么解决

unity自制光追不渲染场景中的物体,渲染用时越来越长

RTRP.cs

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

public class RTRP : RenderPipeline
{
    public RTRPAsset asset;
    public RTRP(RTRPAsset asset)
    {
        this.asset = asset;
    }
    
    protected override void Render(ScriptableRenderContext context, Camera[] cameras)
    {
        MeshFilter[] Filters = GameObject.FindObjectsByType<MeshFilter>(FindObjectsSortMode.None);
        List<MeshObject> objs = new();
        List<Vector3> vertices = new();
        List<int> indexes = new();
        int regeditedindexcount = 0;
        foreach (MeshFilter f in Filters)
        {
            if (f.sharedMesh != null)
            {
                objs.Add(MeshObject.FromMesh(f.sharedMesh, f.transform.localToWorldMatrix, regeditedindexcount));
                regeditedindexcount += f.sharedMesh.triangles.Length;
                foreach (var v in f.sharedMesh.vertices)
                {
                    vertices.Add(v);
                }
                foreach (var i in f.sharedMesh.triangles)
                {
                    indexes.Add(i + regeditedindexcount);
                }
            }
        }
        ComputeBuffer VB = new(vertices.Count, 12);
        ComputeBuffer IB = new(indexes.Count, 4);
        ComputeBuffer OB = new(objs.Count, 80);
        foreach (var cam in cameras)
        {
            CommandBuffer cmd = new();
            context.SetupCameraProperties(cam);
            
            RenderTexture texture = new(Screen.width, Screen.height, 0, RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Linear)
            {
                enableRandomWrite = true
            };
            asset.RTMain.SetTexture(0, "Result", texture);
            asset.RTMain.SetInt("AAL", asset.AAL);
            asset.RTMain.SetInt("MaxTraceTime", asset.MaxTraceTime);
            asset.RTMain.SetMatrix("CTW", cam.cameraToWorldMatrix);
            asset.RTMain.SetMatrix("CIP", cam.projectionMatrix.inverse);
            asset.RTMain.SetBuffer(0, "vertices", VB);
            asset.RTMain.SetBuffer(0, "indexes", IB);
            asset.RTMain.SetBuffer(0, "MeshObjects", OB);
            cmd.DispatchCompute(asset.RTMain, 0, Mathf.CeilToInt(Screen.width / 8f), Mathf.CeilToInt(Screen.height / 8f), 1);
            cmd.Blit(texture, new(BuiltinRenderTextureType.CameraTarget));
            context.ExecuteCommandBuffer(cmd);
            cmd.Release();
        }
        context.Submit();
    }
}

RTMain.compute

#pragma kernel CSMain

static const float EPSILON = 1e-8;
static const float PI = 3.1415927f;

RWTexture2D<float4> Result;
int AAL, MaxTraceTime;
float4x4 CTW, CIP;
struct Ray
{
    float3 origin, direction, energy;
};
struct RayHit
{
    float3 position, normal, v0, v1, v2;
    float2 uv;
    float distance;
};
class MeshObject
{
    float4x4 LTW;
    int i_o, i_c;
};

Buffer<float3> vertices;
Buffer<int> indexes;
StructuredBuffer<MeshObject> MeshObjects;

Ray NewRay(float3 o, float3 d, float3 e)
{
    Ray r;
    r.origin = o;
    r.direction = d;
    r.energy = e;
    return r;
}
RayHit NewHit()
{
    RayHit h;
    h.distance = 1.#INF;
    h.position = 0.f;
    h.normal = 0.f;
    h.uv = 0.f;
    h.v0 = 0.f;
    h.v1 = 0.f;
    h.v2 = 0.f;
    return h;
}
Ray CamRay(float2 uv)
{
    float3 origin = mul(CTW, float4(0.0f, 0.0f, 0.0f, 1.0f)).xyz;
    float3 direction = mul(CIP, float4(uv * 2.f - 1.f, 0.f, 1.f)).xyz;
    direction = mul(CTW, float4(direction, 0.0f)).xyz;
    direction = normalize(direction);
    return NewRay(origin, direction, 1.f);
}
bool IntersectTriangle(Ray ray, float3 vert0, float3 vert1, float3 vert2, inout float t, inout float u, inout float v)
{
    float3 edge1 = vert1 - vert0;
    float3 edge2 = vert2 - vert0;
    float3 pvec = cross(ray.direction, edge2);
    float det = dot(edge1, pvec);
    if (det < EPSILON) return false;
    float inv_det = 1.0f / det;
    float3 tvec = ray.origin - vert0;
    u = dot(tvec, pvec) * inv_det;
    if (u < 0.0 || u > 1.0f) return false;
    float3 qvec = cross(tvec, edge1);
    v = dot(ray.direction, qvec) * inv_det;
    if (v < 0.0 || u + v > 1.0f) return false;
    t = dot(edge2, qvec) * inv_det;
    return true;
}
void IntersectSphere(Ray ray, inout RayHit bestHit, float4 sphere)
{
    float3 d = ray.origin - sphere.xyz;
    float p1 = -dot(ray.direction, d);
    float p2sqr = p1 * p1 - dot(d, d) + sphere.w * sphere.w;
    if (p2sqr < 0) return;
    float p2 = sqrt(p2sqr);
    float t = p1 - p2 > 0 ? p1 - p2 : p1 + p2;
    if (t > 0 && t < bestHit.distance)
    {
        bestHit.distance = t;
        bestHit.position = ray.origin + t * ray.direction;
        bestHit.normal = normalize(bestHit.position - sphere.xyz);
    }
}
void IntersectMesh(Ray r, inout RayHit h, MeshObject obj)
{
    uint o = obj.i_o;
    uint c = obj.i_o + obj.i_c;
    for (uint a = o; a < c; a += 3)
    {
        float3 v0 = (mul(obj.LTW, float4(vertices[indexes[a]], 1.f))).xyz;
        float3 v1 = (mul(obj.LTW, float4(vertices[indexes[a + 1]], 1.f))).xyz;
        float3 v2 = (mul(obj.LTW, float4(vertices[indexes[a + 2]], 1.f))).xyz;
        float t, u, v;
        if (IntersectTriangle(r, v0, v1, v2, t, u, v))
        {
            if (t < h.distance)
            {
                h.distance = t;
                h.position = r.origin + r.direction * t;
                h.normal = normalize(cross(v1 - v0, v2 - v0));
                h.uv = float2(u, v);
                h.v0 = v0;
                h.v1 = v1;
                h.v2 = v2;
            }
        }
    }
}
RayHit Trace(Ray r)
{
    RayHit h = NewHit();
    uint l, s;
    MeshObjects.GetDimensions(l, s);
    for (uint a = 0; a < l; a++)
    {
        IntersectMesh(r, h, MeshObjects[a]);
    }
    return h;
}
float4 Shade(inout Ray r, RayHit h)
{
    if (h.distance > 0 && h.distance < 1.#INF)
    {
        r.origin = h.position + h.normal * 0.00001f;
        r.direction = reflect(r.direction, h.normal);
        r.energy *= 0.8f;
        float size = distance(cross(h.v1 - h.v0, h.v2 - h.v0), 0);
        float size0 = distance(cross(h.v1 - h.position, h.v2 - h.position), 0);
        float size1 = distance(cross(h.v2 - h.position, h.v0 - h.position), 0);
        float size2 = distance(cross(h.v0 - h.position, h.v1 - h.position), 0);
        return float4(size0 / size, size1 / size, size2 / size, 1.f);
    }
    else
    {
        return 0.f;
    }
}
[numthreads(8,8,1)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
    uint w, h;
    Result.GetDimensions(w, h);
    float4 col = 0.f;
    for (int a = 0; a < AAL; a++)
    {
        for (int b = 0; b < AAL; b++)
        {
            Ray r = CamRay((id.xy + float2(a, b) / AAL) / float2(w, h));
            RayHit h = Trace(r);
            col += Shade(r, h);

        }
    }
    col /= AAL * AAL;
    Result[id.xy] = float4(col.x, col.y, col.z, col.w);
}
  • 写回答

4条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-07-16 15:10
    关注

    引自免费微信小程序:皆我百晓生

    从你的问题描述和提供的代码中,我可以看出你在Unity中使用自制的光追渲染器(Render Pipeline)进行渲染,但在渲染场景中的物体时遇到了问题。具体的问题包括不渲染场景中的物体和渲染用时越来越长。让我们分步解决这些问题。

    1. 不渲染场景中的物体

    在查看你的代码后,我发现你没有将场景中的物体正确地传递到Compute Shader中。在Compute Shader中,你需要知道场景中物体的顶点位置和索引信息来进行光线追踪。在你的代码中,你已经从场景中获取了MeshFilter组件并收集了顶点和索引信息,但是在Compute Shader中你没有正确地使用这些信息。你需要将这些数据传递到Compute Shader的缓冲区中。在Render方法中,你需要使用asset.RTMain.SetBuffer方法来设置这些缓冲区。例如:

    asset.RTMain.SetBuffer(0, "verticesBuffer", VB);
    asset.RTMain.SetBuffer(0, "indexesBuffer", IB);
    

    确保你在Compute Shader中也定义了相应的缓冲区:

    Buffer<float3> verticesBuffer; // 对应VB
    Buffer<int> indexesBuffer;     // 对应IB
    

    然后在你的光线追踪函数中,你可以使用这些缓冲区来获取顶点和索引信息。确保你在计算交点时正确地处理了三角形索引和顶点数据。

    2. 渲染用时越来越长

    关于渲染用时越来越长的问题,这可能是由于多种原因导致的。首先,你的光线追踪算法可能在每次迭代时都在重新计算相同的交点,这会导致效率低下。你可以考虑使用数据结构(如加速结构)来优化光线与物体的交点计算。此外,你的光线追踪算法可能过于复杂或计算量大,导致每次迭代都需要很长时间。你可以尝试优化你的算法,减少不必要的计算。另外,确保你的硬件和Unity版本支持高效的光追计算。

    最后,确保你的Compute Shader在每次渲染循环中都被适当地清理和重置,以避免内存泄漏或其他性能问题。你可以在Render方法的最后使用context.ReleaseTemporaryRT来释放临时渲染目标。

    希望这些建议能帮助你解决问题。如果还有其他问题或需要进一步的帮助,请提供更多信息或代码片段。

    评论 编辑记录

报告相同问题?

问题事件

  • 创建了问题 7月16日

悬赏问题

  • ¥15 35114 SVAC视频验签的问题
  • ¥15 impedancepy
  • ¥15 在虚拟机环境下完成以下,要求截图!
  • ¥15 求往届大挑得奖作品(ppt…)
  • ¥15 如何在vue.config.js中读取到public文件夹下window.APP_CONFIG.API_BASE_URL的值
  • ¥50 浦育平台scratch图形化编程
  • ¥20 求这个的原理图 只要原理图
  • ¥15 vue2项目中,如何配置环境,可以在打完包之后修改请求的服务器地址
  • ¥20 微信的店铺小程序如何修改背景图
  • ¥15 UE5.1局部变量对蓝图不可见