unsafe static void DrawBatch(MyScreenDecalType decalType) { if (m_matrices.Count > 0) { var decalCb = MyCommon.GetObjectCB(sizeof(MyDecalConstants) * MAX_DECALS); var N = (int)(Math.Min(MAX_DECALS, m_matrices.Count)); var mapping = MyMapping.MapDiscard(decalCb); for (int i = 0; i < N; ++i) { MyMatrix4x3 worldMatrix = new MyMatrix4x3(); worldMatrix.Matrix4x4 = m_matrices[i]; mapping.stream.Write(worldMatrix); mapping.stream.Write(new Vector4(decalType == MyScreenDecalType.ScreenDecalBump ? 1 : 0, 0, 0, 0)); mapping.stream.Write(Matrix.Transpose(Matrix.Invert(m_matrices[i]))); } mapping.Unmap(); MyImmediateRC.RC.Context.DrawIndexed(36 * N, 0, 0); } m_matrices.Clear(); }
unsafe static void DrawBatches(MyRenderContext RC, MyStringId material, int matIndex, bool transparent) { if (m_jobs.Count == 0) { return; } var matDesc = m_materials[material][matIndex]; MyScreenDecalType type = matDesc.DecalType; if (transparent) { // Always fallback to colormap for transparent surface decals type = MyScreenDecalType.ColorMap; } switch (type) { case MyScreenDecalType.NormalMap: BindResources(RC); RC.SetPS(m_psNormalMap); RC.SetBS(MyRender11.BlendDecalNormal); break; case MyScreenDecalType.ColorMap: if (transparent) { BindResourcesTransparentBillboards(RC); RC.SetPS(m_psColorMapTransparent); } else { BindResources(RC); RC.SetPS(m_psColorMap); RC.SetBS(MyRender11.BlendDecalColor); } break; case MyScreenDecalType.NormalColorMap: BindResources(RC); RC.SetPS(m_psNormalColorMap); RC.SetBS(MyRender11.BlendDecalNormalColor); break; case MyScreenDecalType.NormalColorExtMap: BindResources(RC); RC.SetPS(m_psNormalColorExtMap); RC.SetBS(MyRender11.BlendDecalNormalColorExt); break; default: throw new Exception("Unknown decal type"); } // factor 1 makes overwriting of gbuffer color & subtracting from ao RC.DeviceContext.PixelShader.SetShaderResource(3, MyTextures.GetView(matDesc.AlphamaskTexture)); RC.DeviceContext.PixelShader.SetShaderResource(4, MyTextures.GetView(matDesc.ColorMetalTexture)); RC.DeviceContext.PixelShader.SetShaderResource(5, MyTextures.GetView(matDesc.NormalmapTexture)); RC.DeviceContext.PixelShader.SetShaderResource(6, MyTextures.GetView(matDesc.ExtensionsTexture)); var decalCb = MyCommon.GetObjectCB(sizeof(MyDecalConstants) * DECAL_BATCH_SIZE); int batchCount = m_jobs.Count / DECAL_BATCH_SIZE + 1; int offset = 0; for (int i1 = 0; i1 < batchCount; i1++) { var mapping = MyMapping.MapDiscard(decalCb); int leftDecals = m_jobs.Count - offset; int decalCount = leftDecals > DECAL_BATCH_SIZE ? DECAL_BATCH_SIZE : leftDecals; for (int i2 = 0; i2 < decalCount; ++i2) { MyDecalConstants constants = new MyDecalConstants(); EncodeJobConstants(i2, ref constants); mapping.WriteAndPosition(ref constants); } mapping.Unmap(); // Draw a box without buffer: 36 vertices -> 12 triangles. 2 triangles per face -> 6 faces MyImmediateRC.RC.DeviceContext.DrawIndexed(36 * decalCount, 0, 0); offset += DECAL_BATCH_SIZE; } }
// can be on another job internal unsafe static void Draw() { var decals = IdIndex.Values.ToArray(); // sort visible decals by material Array.Sort(decals, DecalsMaterialComparer); /// // copy gbuffer with normals for read (uhoh) // bind copy and depth for read // bind gbuffer for write var RC = MyImmediateRC.RC; RC.Context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList; RC.SetIB(m_IB.Buffer, m_IB.Format); RC.SetIL(null); RC.Context.Rasterizer.SetViewport(0, 0, MyRender11.ViewportResolution.X, MyRender11.ViewportResolution.Y); RC.SetCB(MyCommon.FRAME_SLOT, MyCommon.FrameConstants); RC.BindDepthRT( MyGBuffer.Main.Get(MyGbufferSlot.DepthStencil), DepthStencilAccess.DepthReadOnly, MyGBuffer.Main.Get(MyGbufferSlot.GBuffer0), MyGBuffer.Main.Get(MyGbufferSlot.GBuffer1), MyGBuffer.Main.Get(MyGbufferSlot.GBuffer2)); RC.SetVS(m_vs); RC.SetPS(m_ps); RC.SetDS(MyDepthStencilState.DepthTest); RC.Context.PixelShader.SetSamplers(0, MyRender11.StandardSamplers); RC.BindSRV(0, MyGBuffer.Main.DepthStencil.Depth); RC.Context.PixelShader.SetShaderResources(1, MyRender11.m_gbuffer1Copy.ShaderView); var decalCb = MyCommon.GetObjectCB(sizeof(MyDecalConstants) * MAX_DECALS); RC.SetCB(2, decalCb); var prevMaterial = new MyStringId(); MyScreenDecalType decalType = MyScreenDecalType.ScreenDecalBump; for (int i = 0; i < decals.Length; ++i) { var index = decals[i]; var material = Decals.Data[index].Material; if (i == 0 || material != prevMaterial) { DrawBatch(decalType); var matDesc = Materials[material]; decalType = matDesc.DecalType; // factor 1 makes overwriting of gbuffer color & subtracting from ao RC.SetBS(MyRender11.BlendDecal, matDesc.DecalType == MyScreenDecalType.ScreenDecalBump ? new SharpDX.Color4(0) : SharpDX.Color4.White); RC.Context.PixelShader.SetShaderResources(3, MyTextures.GetView(matDesc.AlphamaskTexture), MyTextures.GetView(matDesc.ColorMetalTexture), MyTextures.GetView(matDesc.NormalmapTexture)); } var parent = MyIDTracker <MyActor> .FindByID(Decals.Data[index].ParentID); if (parent != null) { var parentMatrix = parent.WorldMatrix; var volumeMatrix = Decals.Data[index].LocalOBB * parentMatrix * Matrix.CreateTranslation(-MyEnvironment.CameraPosition); m_matrices.Add(volumeMatrix); } } DrawBatch(decalType); RC.SetBS(null); }