使用计算着色器的光线/网格交点

时间:2018-04-24 17:58:33

标签: c# directx-11 raytracing sharpdx

我试图使用Compute Shader检查光线/网格交叉点。我有一个带有Parallel.ForEach的外循环,它选择每条光线,然后对于每条光线,我使用GPU(带有计算着色器)检查交叉点。
第一个循环工作正常,但在进入第二个循环之前就崩溃了?可能是什么问题?

P.S:我已经尝试了一个简单的(没有并行),但它从未完成......

Parallel.ForEach(pattern, (point) => {
        //foreach (Vector3 point in pattern) { 
            List<Vector3> pointList = new List<Vector3>();
            // same ray origin and different direction for each cycle
            Vector3 origin = proj.Position;
            Vector3 patternPoint = new Vector3(point.X - offset + origin.X, point.Y - offset + origin.Y, origin.Z - point.Z * 0.4f);
            Vector3 direction = new Vector3(patternPoint.X - origin.X, patternPoint.Y - origin.Y, patternPoint.Z - origin.Z);
            Ray ray = new Ray(origin, direction);

            if (D3DApp.backFlag) { proj.Projection(ray, back, pointList); }

            foreach (MeshRenderer mesh in meshList) { // for all the meshes in the list
                if (mesh != null) { if (ray.Intersects(mesh.box)) { proj.Projection(ray, mesh, pointList, context, device); } }
            }

            if (pointList.Any()) {
                Vector3 temp = pointList.FirstOrDefault();
                foreach (Vector3 p in pointList) { // keep only the first intersection found
                    if (Vector3.Distance(p, origin) < Vector3.Distance(temp, origin)) { temp = p; }
                }
                projectedPoints.Add(temp); // add point to projection pointcloud
            }
        });

这是为每条射线调用的投影方法:<​​/ p>

public void Projection(SharpDX.Ray ray, MeshRenderer obj, List<Vector3> pointList, DeviceContext1 context, Device device) {
        Vector3 intersectionPoint = Vector3.Zero;
        Matrix toLocal = Matrix.Invert(obj.World);
        ray.Position = Vector3.TransformCoordinate(ray.Position, toLocal);
        ray.Direction = Vector3.TransformNormal(ray.Direction, toLocal);
        ray.Direction.Normalize();
        //List<Vector3> localPointList = new List<Vector3>();

        /// PROVO IL RAY/MESH INTERSECT USANDO GLI SHADER
        // V2.0
        Vector3[] vertices = new Vector3[obj.Mesh.Triangles.Count * 3];
        int[] indices = new int[obj.Mesh.Triangles.Count*3];
        int k = 0;
        foreach (Triangle triangle in obj.Mesh.Triangles) {
            vertices[k] = triangle.Points[0];
            vertices[k+1] = triangle.Points[1];
            vertices[k+2] = triangle.Points[2];
            indices[k] = triangle.Indices[0];
            indices[k+1] = triangle.Indices[1];
            indices[k+2] = triangle.Indices[2];
            k += 3;
        }

        /*
         *  INPUT RESOURCES 
         */
        BufferDescription bufferDesc1 = new BufferDescription() {
            BindFlags = BindFlags.ShaderResource,
            Usage = ResourceUsage.Default,
            CpuAccessFlags = CpuAccessFlags.None,
            OptionFlags = ResourceOptionFlags.BufferStructured,
            StructureByteStride = Utilities.SizeOf<Vector3>(),
            SizeInBytes = Utilities.SizeOf<Vector3>() * obj.Mesh.Triangles.Count * 3
        };
        BufferDescription bufferDesc2 = new BufferDescription() {
            BindFlags = BindFlags.ShaderResource,
            Usage = ResourceUsage.Default,
            CpuAccessFlags = CpuAccessFlags.None,
            OptionFlags = ResourceOptionFlags.BufferStructured,
            StructureByteStride = sizeof(int),
            SizeInBytes = sizeof(int) * obj.Mesh.Triangles.Count * 3
        };
        Buffer positionBuffer = new Buffer(device, bufferDesc1);
        context.UpdateSubresource(vertices, positionBuffer);
        Buffer indexBuffer = new Buffer(device, bufferDesc2);
        context.UpdateSubresource(indices, indexBuffer);
        ShaderResourceViewDescription srvDesc = new ShaderResourceViewDescription() {
            Format = SharpDX.DXGI.Format.Unknown,
            Dimension = SharpDX.Direct3D.ShaderResourceViewDimension.ExtendedBuffer, 
            BufferEx = new ShaderResourceViewDescription.ExtendedBufferResource() { Flags = 0, FirstElement = 0, ElementCount = obj.Mesh.Triangles.Count * 3 }
            };

        ShaderResourceView srvPosition = new ShaderResourceView(device, positionBuffer, srvDesc);
        ShaderResourceView srvIndex = new ShaderResourceView(device, indexBuffer, srvDesc);
        context.ComputeShader.SetShaderResource(0, srvPosition); 
        context.ComputeShader.SetShaderResource(1, srvIndex);

        /*
         *  OUTPUT RESOURCES 
         */

        int count = obj.Mesh.Triangles.Count;
        int size = 8; //int+float for every hit
        BufferDescription outputDesc = new BufferDescription() {
            BindFlags = BindFlags.UnorderedAccess | BindFlags.ShaderResource,
            Usage = ResourceUsage.Default,
            CpuAccessFlags = CpuAccessFlags.None,
            OptionFlags = ResourceOptionFlags.BufferStructured,
            StructureByteStride = size,
            SizeInBytes = size * count
        };
        Buffer buffer = new Buffer(device, outputDesc);
        UnorderedAccessViewDescription uavDesc = new UnorderedAccessViewDescription() {
            Buffer = new UnorderedAccessViewDescription.BufferResource() { FirstElement = 0, Flags = UnorderedAccessViewBufferFlags.None, ElementCount = count },
            Format = SharpDX.DXGI.Format.Unknown,
            Dimension = UnorderedAccessViewDimension.Buffer
        };
        UnorderedAccessView uav = new UnorderedAccessView(device, buffer, uavDesc);
        context.ComputeShader.SetUnorderedAccessView(0, uav);

        /*
         *   COMPUTE SHADER
         */

        var computeBuffer = new Buffer(device, Utilities.SizeOf<ConstantBuffers.RayParams>(), ResourceUsage.Default, BindFlags.ConstantBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0);
        var rayBuffer = new ConstantBuffers.RayParams {
            rayFrom = ray.Position,
            rayDir = ray.Direction,
            TriangleCount = (uint)obj.Mesh.Triangles.Count
        };
        context.UpdateSubresource(ref rayBuffer, computeBuffer);
        context.ComputeShader.SetConstantBuffer(0, computeBuffer);

        var code = HLSLCompiler.CompileFromFile(@"Shaders\TestTriangle.hlsl", "CS_RayAppend", "cs_5_0");
        ComputeShader _shader = new ComputeShader(device, code);
        context.ComputeShader.Set(_shader);
        context.Dispatch(1,1,1);
        //Buffer positionsBuffer = new Buffer(device, Utilities.SizeOf<Vector3>(), ResourceUsage.Default, BindFlags.None, CpuAccessFlags.None, ResourceOptionFlags.None, 0);
        //context.UpdateSubresource(ref data, positionsBuffer);

        BufferDescription bufferDesc = new BufferDescription() {
            SizeInBytes = size,
            BindFlags = BindFlags.None,
            CpuAccessFlags = CpuAccessFlags.Read | CpuAccessFlags.Write,
            Usage = ResourceUsage.Staging,
            OptionFlags = ResourceOptionFlags.None,
        };

        Buffer resultBuffer = new Buffer(device, bufferDesc);
        context.CopyResource(buffer, resultBuffer);

        context.Flush();
        context.ComputeShader.SetShaderResource(0, null);
        context.ComputeShader.SetShaderResource(1, null);
        context.ComputeShader.SetConstantBuffer(0, null);
        context.ComputeShader.SetUnorderedAccessView(0, null);
        context.ComputeShader.Set(null);


        DataStream stream;
        context.MapSubresource(resultBuffer, 0, MapMode.Read, MapFlags.None, out stream);
        Vector3[] result = stream.ReadRange<Vector3>(count);
        context.UnmapSubresource(buffer, 0);
        List<Vector3> localPointList = new List<Vector3>(result);

        foreach (Vector3 point in localPointList) {
            // inverted transform to retrieve the original coordinates
            pointList.Add(Vector3.TransformCoordinate(point, obj.World));
        }
    }

0 个答案:

没有答案