我只是在學習Compute Shaders並嘗試使用Unity(我對shaders太不熟悉),並且我正在嘗試做一些簡單的raycast並從Compute Shader寫入渲染紋理。一切工作都很完美,我得到了想要的結果。光線三角形的交叉發生得非常快 - 僅僅不到半秒。但是,現在我嘗試將新顏色應用於渲染紋理,性能下降。所需時間跳至5秒。我無法擺脫一個循環而不會使性能進一步惡化。我甚至無法在循環中使用布爾標誌,如果它在循環中設置爲true,我可以在循環外使用更新紋理顏色。使用Compute Shaders編寫渲染紋理的速度很慢?
表現變得非常糟糕。我將如何更新渲染紋理顏色?
這裏是着色器代碼:任何幫助表示讚賞。
//--------------------------------------------------------------------
#pragma kernel MainCS
//--------------------------------------------------------------------
struct Triangle
{
float3 v0;
float3 v1;
float3 v2;
float3 n;
};
// Precomputed and set from C# script
struct Pixel
{
float3 position;
float3 direction;
int index;
float pixelColor;
};
//-----------------------------------------------------------------------------
#define blocksize 8
// variables
int imageSize;
// buffers
RWStructuredBuffer<Pixel> pixels : register(u0); // UAV
RWTexture2D<float4> rendTex : register(u1); // UAV
const StructuredBuffer<Triangle> tris : register(t0); // SRV
// This kernel writes some color in the current pixel if there is ray intersection with some of the triangles from the tris buffer. In general works well but slow. The intersection part without writing to the render texture is SUPER FAST. When i attempt to write to the texture - gets SUPER SLOW. Render Texture random write is enabled from the C# script
[numthreads(blocksize,blocksize,1)]
void MainCS (uint3 id : SV_DispatchThreadID, uint3 Gid : SV_GroupID, uint3 GTid : SV_GroupThreadID, uint GI : SV_GroupIndex)
{
// Get the current pixel ID - pixels is 1D array
int pixelID = (int)(id.y * imageSize + id.x);
// Ray
float3 rayO = pixels[pixelID].position;
float3 rayD = pixels[pixelID].direction;
// Intersection variables
float3 pt0, pt1, pt2, edge0, edge1, edge2, cross1, cross2, cross3, n;
float angle1, angle2, angle3;
float r, _a, b;
float3 w0, I;
bool bIntersect = false;
[loop][allow_uav_condition]
for (uint tr = 0; tr < tris.Length; tr++)
{
// Somecalculations
pt0 = tris[tr].v0; pt1 = tris[tr].v1; pt2 = tris[tr].v2;
edge0 = rayO - pt0; edge1 = rayO - pt1; edge2 = rayO - pt2;
// First check - is the ray intersecting the triangle
if (dot(rayD, cross(edge0, edge1)) >= 0.0 ||
dot(rayD, cross(edge1, edge2)) >= 0.0 ||
dot(rayD, cross(edge2, edge0)) >= 0.0) continue;
// Fiding the intersection point
n = normalize(cross(pt0 - pt1, pt0 - pt2));
w0 = rayO - pt0;
_a = -dot(n, w0);
b = dot(n, rayD);
r = _a/b;
I = rayO + rayD * r;
// Second check - before validate the hitpoint
if (_a < 0.0)
{
// Here i would want to update texture colors
// ==============================================
// Variant 1 =======================================
// Only update the texture without break;
// Gives proper result but is SLOW - 3 seconds
rendTex[id.xy] = float4(1.0, 0.0, 0.0, 1.0);
// if add break; - MUCH SLOWER
break;
// ===============================================
// Variant 2 - Part 1 ==================================
// rising flag to true - fast
if(!bIntersect)
{
bIntersect = true;
}
}
}
// Variant 2 - Part 2 - When using the flag - updating Render texture colror is SUPER SLOW but acurate
if(bIntersect)
rendTex[id.xy] = float4(1.0, 0.0, 0.0, 1.0);
}
感謝您的建議。但我實際上正在試圖製作一個GPU RayTracer - 至少在它的基礎層面上 - 只拍攝主光線和檢測三角形。所有需要的數據都是在C#腳本中預先計算的,然後使用緩衝區和RWTexture2D上傳到Compute Shader。我做了一些研究,並認爲使用渲染紋理最適合於此目的,但它允許隨機讀寫訪問 - 在將渲染紋理上傳到GPU內存之前,在C#腳本中啓用此選項。這不是用ComputeShader將信息寫入紋理的正確方法嗎? –