我不是歪神 2025-10-06 13:24 采纳率: 66.7%
浏览 7
已结题

unity计算着色器缓存区内核间不共享问题QwQ

先在此感谢大家帮助了QWQ,3天方法试遍了,也没有解决

下面是一个IFFT海生成频谱部分的代码,出现问题的具体表现是 计算着色器中
OceanInput[id.xy] = highSpectrumTex;效果为纯黑
OceanInput[id.xy] = highSpectrumTex + float4(1,1,0,0);效果为纯黑
OceanInput[id.xy] = float4(1,1,0,0);效果正常为黄色,
将OffsetSpectrum内核的代码挪动到Start内核,并改成每一帧调用Start内核,显示正常
在OffsetSpectrum中首行添加HighSpectrumTex[id.xy] = float4(1,1,0,0),两个网格全部变为纯黄;
推测可能是缓存区在内核间共享出了问题

using UnityEngine;
using System.Collections.Generic;

public class Ocean : MonoBehaviour
{
    
    
    //Debug

    public List<int> KernelIDs = new List<int>();
    public ComputeShader OceanCompute;



    public int texSize = 256;
    public int gridSize = 32;

    public float OceanA = 10;
    public float WindSP = 10;
    public Vector2 Wind;

    public float time;
    public Renderer HighSpectrumRenderer;
    public Renderer OffsetSpectrumRenderer;

    private RenderTexture HighSpectrum;
    private RenderTexture OffsetSpectrum;
    private ComputeBuffer reBitBuffer;

    void Start()
    {
        KernelIDs.Add(OceanCompute.FindKernel("Start"));
        KernelIDs.Add(OceanCompute.FindKernel("OffsetSpectrum"));
        InitializeReBitBuffer();
        InitializeRenderTexture();
        InitializeCompute();
        StartComputShader();
    }

    private void Update()
    {
        time += Time.deltaTime;
        SetComputeParameters();
        UpdateComputShader();
    }

    void SetComputeParameters()
    {
        OceanCompute.SetFloat("OceanA", OceanA);
        OceanCompute.SetVector("Wind", Wind);
        OceanCompute.SetFloat("WindSP", WindSP);
        OceanCompute.SetFloat("Time", time);
    }

    void InitializeCompute()
    {
        HighSpectrumRenderer.material.mainTexture = HighSpectrum;
        OffsetSpectrumRenderer.material.mainTexture = OffsetSpectrum;
    }

    void InitializeReBitBuffer()
    {
        int[] reBitData = new int[texSize];
        int Bitleng = (int)Mathf.Log(texSize, 2);

        for (int i = 0; i < texSize; i++)
        {
            int Invindex = 0;
            int k = i;
            for (int j = 0; j < Bitleng; j++)
            {
                Invindex = (Invindex << 1) | (k & 1);
                k >>= 1;
            }
            reBitData[i] = Invindex;
        }

        reBitBuffer = new ComputeBuffer(texSize, sizeof(int));
        reBitBuffer.SetData(reBitData);
    }

    void InitializeRenderTexture()
    {
        HighSpectrum = new RenderTexture(texSize, texSize, 0, RenderTextureFormat.ARGB32)
        {
            enableRandomWrite = true,
            wrapMode = TextureWrapMode.Clamp,
            filterMode = FilterMode.Point
        };
        HighSpectrum.Create();
        OffsetSpectrum = new RenderTexture(texSize, texSize, 0, RenderTextureFormat.ARGB32)
        {
            enableRandomWrite = true,
            wrapMode = TextureWrapMode.Clamp,
            filterMode = FilterMode.Point
        };
        OffsetSpectrum.Create(); 
    }

    void StartComputShader()
    {
        OceanCompute.SetFloat("TexSize", texSize);
        OceanCompute.SetInt("GridSize", gridSize);
        OceanCompute.SetTexture(KernelIDs[0], "HighSpectrumTex", HighSpectrum);
        OceanCompute.Dispatch(KernelIDs[0], texSize / 8, texSize / 8, 1);
        OceanCompute.SetTexture(KernelIDs[1], "HighSpectrumTex", HighSpectrum);
        OceanCompute.SetTexture(KernelIDs[1], "OceanInput", OffsetSpectrum);

    }
    void UpdateComputShader()
    {

        OceanCompute.Dispatch(KernelIDs[1], texSize / 8, texSize / 8, 1);
    }

    void OnDestroy()
    {
        if (HighSpectrum != null)
        {
            if (HighSpectrum.IsCreated())
                HighSpectrum.Release();
            DestroyImmediate(HighSpectrum);
        }

        if (OffsetSpectrum != null)
        {
            if (OffsetSpectrum.IsCreated())
                OffsetSpectrum.Release();
            DestroyImmediate(OffsetSpectrum);
        }
        reBitBuffer?.Release();
    }
}

#pragma kernel Start
#pragma kernel OffsetSpectrum
#define PI 3.14159265358979323846f 
#define G 9.81


StructuredBuffer<int> ReBit;

int GridSize;
float TexSize;
float OceanA;
float2 Wind;
float WindSP;

float Time;

RWTexture2D<float4> HighSpectrumTex;
RWTexture2D<float4> OceanInput;


uint getHash(uint seed)
{
    seed = (seed ^ 61) ^ (seed >> 16);
    seed *= 9;
    seed = seed ^ (seed >> 4);
    seed *= 0x27d4eb2d;
    seed = seed ^ (seed >> 15);
    return seed;
}

float2 getRand(uint seed)
{
    seed ^= (seed << 13);
    seed ^= (seed >> 17);
    seed ^= (seed << 5);
    float rand1 = seed / 4294967296.0f;
    
    seed ^= (seed << 13);
    seed ^= (seed >> 17);
    seed ^= (seed << 5);
    float rand2 = seed / 4294967296.0f;
    
    return float2(rand1, rand2);
}

float2 Gaussian(uint2 id)
{
    uint seed = getHash(id.y * GridSize + id.x);
    float2 randValues = getRand(seed);
    
    float x1 = max(1e-6f, randValues.x);
    float x2 = max(1e-6f, randValues.y);
    
    float g1 = sqrt(-2.0f * log(x1)) * cos(2.0f * PI * x2);
    float g2 = sqrt(-2.0f * log(x1)) * sin(2.0f * PI * x2);

    return float2(g1, g2);
}

float Phillips(float2 k)
{

    float norK = max(0.001f, length(k));
    float norK2 = norK * norK;
    float norK4 = norK2 * norK2;

    float L = WindSP * WindSP / G;
    float L2 = L * L;

    float dwad = dot(k, normalize(Wind));
    dwad *= WindSP;

    float damping = 0.001f;
    float La2 = L2 * damping * damping;

    return OceanA * dwad * dwad * exp(-1.0f / (norK2 * L2)) / norK4 * exp(-norK2 * La2);
}

float2 HighSpectrum(int2 id)
{
    float2 k = float2(2.0f * PI * id.x / TexSize - PI, 2.0f * PI * id.y / TexSize - PI);
    float2 gaussian = Gaussian(id);
    float phillips = Phillips(k);
    return gaussian * sqrt(phillips * 0.5f);
}

[numthreads(8,8,1)]
void Start (uint3 id : SV_DispatchThreadID)
{
    float2 posFreq = HighSpectrum((int2)id.xy);
    float2 negFreq = HighSpectrum(-(int2)id.xy) * float2(1, -1);
    HighSpectrumTex[id.xy] = float4(posFreq, negFreq);
}

[numthreads(8,8,1)]
void OffsetSpectrum (uint3 id : SV_DispatchThreadID)
{
    float4 highSpectrumTex = HighSpectrumTex[id.xy];
    float2 xy = highSpectrumTex.xy;
    float2 zw = highSpectrumTex.zw;

    float2 k = float2(2.0f * PI * id.x / TexSize - PI, 2.0f * PI * id.y / TexSize - PI);

    float wt = sqrt(length(k) * G) * Time;
    float cosWT = cos(wt);
    float sinWT = sin(wt);

    float2 a = float2(cosWT * xy.x - sinWT * xy.y, cosWT * xy.y + sinWT * xy.x);
    float2 b = float2(cosWT * zw.x - sinWT * zw.y, cosWT * zw.y + sinWT * zw.x);
    OceanInput[id.xy] = highSpectrumTex + float4(1,1,0,0);
}

  • 写回答

6条回答 默认 最新

  • 阿里嘎多学长 2025-10-06 13:24
    关注

    阿里嘎多学长整理AIGC生成,因移动端显示问题导致当前答案未能完全显示,请使用PC端查看更加详细的解答过程

    问题分析

    你遇到的问题是 Unity 中的着色器计算中,缓存区内核间不共享导致的 OceanInput[id.xy] = highSpectrumTex 这个语句无法正常工作。

    解决方案

    1. 检查缓存区的共享设置:确保缓存区的共享设置正确,特别是当你使用多个内核时。
    2. 使用共享变量:尝试使用共享变量来存储和共享数据。
    3. 检查数据类型:确保 OceanInput 和 highSpectrumTex 的数据类型匹配。
    4. 检查内核的顺序:检查内核的执行顺序是否正确,确保每个内核都能正常访问共享数据。

    核心代码

    // 使用共享变量
    shared float4 sharedData;
    
    // 在每个内核中更新共享变量
    sharedData = highSpectrumTex[id.xy];
    
    // 在每个内核中使用共享变量
    OceanInput[id.xy] = sharedData;
    

    注意:上述代码仅提供了一个解决方案的示例,具体的解决方案可能需要根据你的具体情况进行调整。

    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 10月12日
  • 创建了问题 10月6日