【发布时间】:2017-06-06 23:32:43
【问题描述】:
我只是在学习计算着色器并尝试使用 Unity(我对着色器不太熟悉),并且我正在尝试做一些简单的光线投射并从计算着色器写入渲染纹理。一切都很完美,我得到了想要的结果。射线与三角形的交点发生得非常快——不到半秒。但是,目前我尝试将新颜色应用于渲染纹理,性能下降。所需时间跃升至 5 秒。我无法在不进一步恶化性能的情况下摆脱循环。我什至不能在循环中使用 bool 标志,如果它在循环中设置为 true,我可以在循环外使用它来更新纹理颜色。
性能变得非常糟糕。我将如何更新渲染纹理颜色?
这是着色器代码:感谢任何帮助。
//--------------------------------------------------------------------
#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);
}
【问题讨论】:
标签: unity3d