我有两个文件 (NewComputeShader.compute和ShaderRun.cs).ShaderRun.cs运行着色器并在摄像机上绘制其纹理(脚本是摄像机的组件)
开始时,Unity会在左下角绘制一个白色像素。(Twidth = 256,Thight = 256,Agentsnum = 10)
新计算着色器。计算:
// Each #kernel tells which function to compile; you can have many kernels
#pragma kernel CSUpdate
// Create a RenderTexture with enableRandomWrite flag and set it
// with cs.SetTexture
RWTexture2D<float4> Result;
uint width = 256;
uint height = 256;
int numAgents = 10;
float moveSpeed = 100;
uint PI = 3.1415926535;
float DeltaTime = 1;
uint hash(uint state) {
state ^= 2747636419u;
state *= 2654435769u;
state ^= state >> 16;
state *= 2654435769u;
state ^= state >> 16;
state *= 2654435769u;
return state;
}
uint scaleToRange01(uint state) {
state /= 4294967295.0;
return state;
}
struct Agent {
float2 position;
float angle;
};
RWStructuredBuffer<Agent> agents;
[numthreads(8,8,1)]
void CSUpdate(uint3 id : SV_DispatchThreadID)
{
//if (id.x >= numAgents) { return; }
Agent agent = agents[id.x];
uint random = hash(agent.position.y * width + agent.position.x + hash(id.x));
float2 direction = float2(cos(agent.angle), sin(agent.angle));
float2 newPos = agent.position + direction * moveSpeed * DeltaTime;
if (newPos.x < 0 || newPos.x >= width || newPos.y < 0 || newPos.y >= height) {
newPos.x = min(width - 0.01, max(0, newPos.x));
newPos.y = min(height - 0.01, max(0, newPos.y));
agents[id.x].angle = scaleToRange01(random) * 2 * PI;
}
agents[id.x].position = newPos;
Result[int2(newPos.x, newPos.y)] = float4(1,1,1,1);
}
着色器运行.cs:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ShaderRun : MonoBehaviour
{
public ComputeShader computeShader;
public RenderTexture renderTexture;
public int twidth;
public int theight;
public int agentsnum;
ComputeBuffer agentsBuffer;
struct MyAgent
{
public Vector2 position;
public float angle;
};
// Start is called before the first frame update
void Start()
{
renderTexture = new RenderTexture(twidth, theight, 24);
renderTexture.enableRandomWrite = true;
renderTexture.Create();
computeShader.SetTexture(0, "Result", renderTexture);
agentsBuffer = new ComputeBuffer(agentsnum, sizeof(float)*3); //make new compute buffer with specified size, and specified "stride" //stride is like the size of each element, in your case it would be 3 floats, since Vector3 is 3 floats.
ResetAgents();
computeShader.SetBuffer(0, "agents", agentsBuffer); //Linking the compute shader and cs shader buffers
computeShader.Dispatch(0, renderTexture.width / 8, renderTexture.height / 8, 1);
}
void OnRenderImage(RenderTexture src, RenderTexture dest)
{
Graphics.Blit(renderTexture, dest);
}
private void ResetAgents()
{
MyAgent[] aArray = new MyAgent[agentsnum];
for (int i=0; i<agentsnum; i++)
{
MyAgent a = new MyAgent();
a.position = new Vector2(128, 128);
a.angle = 2 * (float)Math.PI * (i / agentsnum);
aArray[i] = a;
}
agentsBuffer.SetData(aArray);
ComputeStepFrame();
}
private void ComputeStepFrame()
{
computeShader.SetFloat("DeltaTime", Time.deltaTime);
int kernelHandle = computeShader.FindKernel("CSUpdate");
computeShader.SetBuffer(kernelHandle, "agents", agentsBuffer);
computeShader.Dispatch(0, renderTexture.width / 8, renderTexture.height / 8, 1);
}
// Update is called once per frame
void Update()
{
ComputeStepFrame();
}
}
这也是一个重新创建代码的尝试:https://www.youtube.com/watch?v=X-iSQQgOd1A&t=730s(部件号:结果必须像第一次演示的视频中的代理。编辑:我真的建议你去看看这个视频,非常好!
3条答案
按热度按时间vs91vp4v1#
我也在做同样的事情。要启动scaleToRange01函数,可能应该返回一个浮点数。至于位置,你可能想看看C#端,你是如何初始化代理并将数据放入缓冲区的?需要在C#中创建一个类似的结构,然后像下面这样为其赋值。
bpzcxfmw2#
我也在尝试重新创建它。问题是塞巴斯蒂安遗漏了他的c#代码和一些HLSL,因此很难将不存在的部分组合在一起。昨天我不间断地工作了一整天,终于让它执行了演示2。对我来说最困难的事情是正确地获得线程,让GPU计算我需要的所有项目。我害怕开始线索消散和线索感,但老实说,演示2的感觉很棒,这也是促使我坚持下去的原因。这个项目的每件事都很敏感,不适合普通的程序员。(如果你还没有学习过HLSL的话,也要学习一下。)另外一件事是我没有使用他的随机Angular 发生器,我只是创建了自己的。我知道这没有帮助,但我知道其他人也在试图通过这一点。塞巴斯蒂安是一个天才。
anauzrmj3#
Found this question after so much time. But theme is still interesting. Maybe my answer will help passersby here later. BTW look at this video . Slime is a game life form now!
The problem with the code from original question is ambiguity with what are you going to process with kernel.
In this kernel you are intended to process 1D array of agents. You need to dispatch this code like this:
And of course you need to correct kernel TGS:
For 2D texture you need to keep kernel like
And only then it is okay to dispatch it with second dimension:
P.S. And there is a link to github repo under video.