Пример #1
0
    public ControlVertexProvider(Device device, ShaderCache shaderCache,
                                 OccluderLoader occluderLoader,
                                 FigureDefinition definition,
                                 ShaperParameters shaperParameters)
    {
        this.occluderLoader = occluderLoader;
        this.definition     = definition;
        this.shaper         = new GpuShaper(device, shaderCache, definition, shaperParameters);
        this.vertexCount    = shaperParameters.InitialPositions.Length;

        controlVertexInfosBufferManager = new InOutStructuredBufferManager <ControlVertexInfo>(device, vertexCount);
        if (definition.ChannelSystem.Parent == null)
        {
            this.controlVertexInfoStagingBufferManager = new StagingStructuredBufferManager <ControlVertexInfo>(device, vertexCount, BackingArrayCount);
        }
    }
    private void ProcessTexturedSurface(int surfaceIdx, string uvSetName, FileInfo file, bool isLinear)
    {
        bool isOrderedTransparent = surfaceProperties.RenderOrder.Contains(surfaceIdx);
        bool isMaxing             = isOrderedTransparent;

        var context = device.ImmediateContext;

        var opacityTexture     = LoadOpacityTexture(file, isLinear);
        var opacityTextureView = new ShaderResourceView(device, opacityTexture);

        // Not sure by, possibly a nvidia bug, but the vertex buffer padding by an extra element is necessary.
        // Otherwise (0,0) gets passed to the vertex shader instead of the last vertex.
        var uvSet    = figure.UvSets[uvSetName];
        var vertices = uvSet.Uvs;
        var vertexBufferSizeInBytes = Vector2.SizeInBytes * (vertices.Length + 1);
        var vertexBuffer            = Buffer.Create(device, BindFlags.VertexBuffer, vertices, vertexBufferSizeInBytes);

        List <int> faceIdxMap      = new List <int>();
        List <int> triangleIndices = new List <int>();

        for (int faceIdx = 0; faceIdx < faceCount; ++faceIdx)
        {
            if (figure.Geometry.SurfaceMap[faceIdx] != surfaceIdx)
            {
                continue;
            }

            faceIdxMap.Add(faceIdx);

            Quad face = figure.DefaultUvSet.Faces[faceIdx];
            triangleIndices.Add(face.Index0);
            triangleIndices.Add(face.Index1);
            triangleIndices.Add(face.Index2);

            if (!face.IsDegeneratedIntoTriangle)
            {
                triangleIndices.Add(face.Index2);
                triangleIndices.Add(face.Index3);
                triangleIndices.Add(face.Index0);
            }
        }

        var indexBuffer = Buffer.Create(device, BindFlags.IndexBuffer, triangleIndices.ToArray());

        var transparencyCounterBufferManager = new InOutStructuredBufferManager <TransparencyCounters>(device, faceIdxMap.Count);

        context.ClearState();

        states.Apply(context);

        context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
        context.InputAssembler.InputLayout       = inputLayout;
        context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(vertexBuffer, Vector2.SizeInBytes, 0));
        context.InputAssembler.SetIndexBuffer(indexBuffer, Format.R32_UInt, 0);

        context.VertexShader.Set(vertexShader);

        context.Rasterizer.SetViewport(0, 0, opacityTexture.Description.Width, opacityTexture.Description.Height);

        context.PixelShader.Set(isMaxing ? maxingPixelShader : addingPixelShader);
        context.PixelShader.SetShaderResources(0, opacityTextureView);

        context.OutputMerger.SetUnorderedAccessView(0, transparencyCounterBufferManager.OutView);

        context.DrawIndexed(triangleIndices.Count, 0, 0);

        context.ClearState();

        var transparencyCounterStagingBufferManager = new StagingStructuredBufferManager <TransparencyCounters>(device, faceIdxMap.Count);

        transparencyCounterStagingBufferManager.CopyToStagingBuffer(context, transparencyCounterBufferManager.Buffer);
        var array = transparencyCounterStagingBufferManager.FillArrayFromStagingBuffer(context);

        for (int faceIdx = 0; faceIdx < faceIdxMap.Count; ++faceIdx)
        {
            TransparencyCounters transparencyCounter = array[faceIdx];

            if (transparencyCounter.pixelCount > (1 << 24))
            {
                throw new Exception("pixel count overflow");
            }

            float transparency;
            if (isMaxing)
            {
                transparency = (float)transparencyCounter.transparencyCount / 0xff;
            }
            else
            {
                transparency = transparencyCounter.transparencyCount == 0 ? 0 : (float)transparencyCounter.transparencyCount / transparencyCounter.pixelCount / 0xff;
            }
            faceTransparencies[faceIdxMap[faceIdx]] = transparency;
        }

        opacityTextureView.Dispose();
        opacityTexture.Dispose();
        indexBuffer.Dispose();
        vertexBuffer.Dispose();
        transparencyCounterBufferManager.Dispose();
        transparencyCounterStagingBufferManager.Dispose();
    }