public unsafe bool UpdateSimpleMaterialBGFX(RendererBGFXInstance *sys, ref SimpleMaterial mat, ref SimpleMaterialBGFX matBGFX, bool srgbColors) { // if constants changed, need to update packed value matBGFX.constAlbedo_Opacity = srgbColors ? new float4(Color.LinearToSRGB(mat.constAlbedo), mat.constOpacity) : new float4(mat.constAlbedo, mat.constOpacity); // if texture entity OR load state changed need to update texture handles // content of texture change should transparently update texture referenced by handle bool stillLoading = false; if (InitTexture(ref matBGFX.texAlbedoOpacity, mat.texAlbedoOpacity, sys->m_whiteTexture)) { stillLoading = true; } // if twoSided or hasalpha changed, need to update state matBGFX.state = (ulong)(bgfx.StateFlags.WriteRgb | bgfx.StateFlags.WriteA | bgfx.StateFlags.DepthTestLess); if (!mat.twoSided && !mat.billboarded) { matBGFX.state |= (ulong)bgfx.StateFlags.CullCw; } if (mat.transparent) { matBGFX.state |= RendererBGFXStatic.MakeBGFXBlend(bgfx.StateFlags.BlendOne, bgfx.StateFlags.BlendInvSrcAlpha); } else { matBGFX.state |= (ulong)bgfx.StateFlags.WriteZ; } matBGFX.mainTextureScaleTranslate = new float4(mat.scale, mat.offset); matBGFX.billboarded = new float4(mat.billboarded ? 1 : 0, 0, 0, 0); return(!stillLoading); }
public static unsafe MeshBGFX CreateStaticMesh(RendererBGFXInstance *inst, ushort *indices, int nindices, SimpleVertex *vertices, int nvertices, SkinnedMeshVertex *skinningdata = null) { bool hasSkinningData = skinningdata != null; #if ENABLE_DOTSRUNTIME_PROFILER ProfilerStats.AccumStats.memMeshCount.Accumulate(1); long bytes = nvertices * sizeof(SimpleVertex) + nindices * sizeof(ushort); if (hasSkinningData) { bytes += nvertices * sizeof(SkinnedMeshVertex); } ProfilerStats.AccumStats.memMesh.Accumulate(bytes); ProfilerStats.AccumStats.memReservedGFX.Accumulate(bytes); ProfilerStats.AccumStats.memUsedGFX.Accumulate(bytes); #endif if (hasSkinningData) { int simpleVertexSize = sizeof(SimpleVertex); int skinningVertexSize = sizeof(SkinnedMeshVertex); int totalVertexSize = simpleVertexSize + skinningVertexSize; byte *tmpBlock = (byte *)UnsafeUtility.Malloc(totalVertexSize * nvertices, 4, Allocator.Temp); UnsafeUtility.MemCpyStride(tmpBlock, totalVertexSize, vertices, simpleVertexSize, simpleVertexSize, nvertices); UnsafeUtility.MemCpyStride(tmpBlock + simpleVertexSize, totalVertexSize, skinningdata, skinningVertexSize, skinningVertexSize, nvertices); bgfx.Memory *bgfxMemory = RendererBGFXStatic.CreateMemoryBlock((byte *)tmpBlock, nvertices * totalVertexSize); UnsafeUtility.Free(tmpBlock, Allocator.Temp); return(new MeshBGFX { indexBufferHandle = bgfx.create_index_buffer(RendererBGFXStatic.CreateMemoryBlock((byte *)indices, nindices * 2), (ushort)bgfx.BufferFlags.None).idx, vertexBufferHandle = bgfx.create_vertex_buffer(bgfxMemory, &inst->m_simpleSkinnedVertexBufferDecl, (ushort)bgfx.BufferFlags.None).idx, indexCount = nindices, vertexCount = nvertices, maxIndexCount = nindices, maxVertexCount = nvertices, vertexLayoutHandle = inst->m_simpleSkinnedVertexBufferDeclHandle, isDynamic = false, vertexSize = totalVertexSize, }); } else { return(new MeshBGFX { indexBufferHandle = bgfx.create_index_buffer(RendererBGFXStatic.CreateMemoryBlock((byte *)indices, nindices * 2), (ushort)bgfx.BufferFlags.None).idx, vertexBufferHandle = bgfx.create_vertex_buffer(RendererBGFXStatic.CreateMemoryBlock((byte *)vertices, nvertices * sizeof(SimpleVertex)), &inst->m_simpleVertexBufferDecl, (ushort)bgfx.BufferFlags.None).idx, indexCount = nindices, vertexCount = nvertices, maxIndexCount = nindices, maxVertexCount = nvertices, vertexLayoutHandle = inst->m_simpleVertexBufferDeclHandle, isDynamic = false, vertexSize = sizeof(SimpleVertex), }); } }
public unsafe bool UpdateLitMaterialBGFX(RendererBGFXInstance *sys, ref LitMaterial mat, ref LitMaterialBGFX matBGFX, bool srgbColors) { bool stillLoading = false; if (InitTexture(ref matBGFX.texAlbedoOpacity, mat.texAlbedoOpacity, sys->m_whiteTexture)) { stillLoading = true; } if (InitTexture(ref matBGFX.texNormal, mat.texNormal, sys->m_upTexture)) { stillLoading = true; } if (InitTexture(ref matBGFX.texMetal, mat.texMetal, sys->m_whiteTexture)) { stillLoading = true; } if (InitTexture(ref matBGFX.texEmissive, mat.texEmissive, sys->m_whiteTexture)) { stillLoading = true; } InitShader(ref matBGFX.shaderProgram, mat.shader, sys->m_litShader.m_prog); matBGFX.constAlbedo_Opacity = srgbColors ? new float4(Color.LinearToSRGB(mat.constAlbedo), mat.constOpacity) : new float4(mat.constAlbedo, mat.constOpacity); matBGFX.constMetal_Smoothness_Billboarded = new float4(mat.constMetal, mat.constSmoothness, mat.billboarded ? 1 : 0, 0); matBGFX.constEmissive_normalMapZScale = srgbColors ? new float4(Color.LinearToSRGB(mat.constEmissive), mat.normalMapZScale) : new float4(mat.constEmissive, mat.normalMapZScale); matBGFX.mainTextureScaleTranslate = new float4(mat.scale, mat.offset); matBGFX.smoothness = new float4(0.0f); matBGFX.smoothness.x = (!mat.transparent && mat.smoothnessAlbedoAlpha) ? 1 : 0; matBGFX.smoothness.y = (!mat.transparent && !mat.smoothnessAlbedoAlpha) ? 1 : 0; matBGFX.smoothness.z = !mat.transparent ? 1 : 0; // if twoSided, need to update state matBGFX.state = (ulong)(bgfx.StateFlags.WriteRgb | bgfx.StateFlags.WriteA | bgfx.StateFlags.DepthTestLess); if (!mat.twoSided && !mat.billboarded) { matBGFX.state |= (ulong)bgfx.StateFlags.CullCcw; } if (mat.transparent) { matBGFX.state |= RendererBGFXStatic.MakeBGFXBlend(bgfx.StateFlags.BlendOne, bgfx.StateFlags.BlendInvSrcAlpha); } else { matBGFX.state |= (ulong)bgfx.StateFlags.WriteZ; } return(!stillLoading); }
protected override void OnUpdate() { var shader = World.GetExistingSystem <SpriteRendererSubmitSystem>().DefaultShader; if (!shader.IsInitialized) { return; } var cmd = m_Barrier.CreateCommandBuffer(); Dependency = Entities .WithName("CreateMesh2D") .WithoutBurst() .WithNone <SpriteMeshBuffers>() .ForEach((Entity entity, in Sprite sprite) => { var blob = sprite.Mesh; var indexCount = blob.Value.Indices.Length; var vertexCount = blob.Value.Vertices.Length; unsafe { cmd.AddComponent(entity, new SpriteMeshBuffers { IndexCount = indexCount, VertexCount = vertexCount, VertexLayoutHandle = shader.LayoutHandle, IndexBufferHandle = bgfx.create_index_buffer(RendererBGFXStatic.CreateMemoryBlock((byte *)blob.Value.Indices.GetUnsafePtr(), indexCount * 2), (ushort)bgfx.BufferFlags.None).idx, VertexBufferHandle = bgfx.create_vertex_buffer(RendererBGFXStatic.CreateMemoryBlock((byte *)blob.Value.Vertices.GetUnsafePtr(), vertexCount * sizeof(SpriteVertex)), (bgfx.VertexLayout *)shader.VertexLayout.GetUnsafeReadOnlyPtr(), (ushort)bgfx.BufferFlags.None).idx }); } }).Schedule(Dependency); Dependency = Entities .WithName("RemoveMesh2D") .WithoutBurst() .WithNone <Sprite>() .ForEach((Entity entity, in SpriteMeshBuffers mesh) => { bgfx.destroy_index_buffer(new bgfx.IndexBufferHandle { idx = mesh.IndexBufferHandle }); bgfx.destroy_vertex_buffer(new bgfx.VertexBufferHandle { idx = mesh.VertexBufferHandle }); cmd.RemoveComponent(entity, typeof(SpriteMeshBuffers)); }).Schedule(Dependency); m_Barrier.AddJobHandleForProducer(Dependency); }
public ulong state; // includes blending and culling! internal unsafe bool Update(EntityManager em, RendererBGFXInstance *sys, ref BitmapFontMaterial mat) { constClipRect = mat.ConstClipRect; constMaskSoftness = mat.ConstMaskSoftness; // if texture entity OR load state changed need to update texture handles // content of texture change should transparently update texture referenced by handle bool stillLoading = UpdateTextMaterialsSystem.InitTexture(em, ref texAtlas, mat.AtlasTexture, sys->m_whiteTexture); // text is always two-sided and transparent state = (ulong)(bgfx.StateFlags.WriteRgb | bgfx.StateFlags.WriteA | bgfx.StateFlags.DepthTestLess); state |= RendererBGFXStatic.MakeBGFXBlend(bgfx.StateFlags.BlendSrcAlpha, bgfx.StateFlags.BlendInvSrcAlpha); return(!stillLoading); }
public unsafe void UpdateDynamic(ushort *indexSrc, int numIndices, byte *vertexSrc, int numVertices, int sizeofVertex) { Assert.IsTrue(isDynamic); Assert.IsTrue(numVertices <= maxVertexCount); Assert.IsTrue(numIndices <= maxIndexCount); #if ENABLE_DOTSRUNTIME_PROFILER Assert.IsTrue(vertexSize == sizeofVertex); ProfilerStats.AccumStats.memUsedGFX.Accumulate(-(vertexCount * vertexSize + indexCount * sizeof(ushort))); ProfilerStats.AccumStats.memUsedGFX.Accumulate(numVertices * vertexSize + numIndices * sizeof(ushort)); #endif bgfx.update_dynamic_index_buffer(GetDynamicIndexBufferHandle(), 0, RendererBGFXStatic.CreateMemoryBlock((byte *)indexSrc, numIndices * 2)); indexCount = numIndices; bgfx.update_dynamic_vertex_buffer(GetDynamicVertexBufferHandle(), 0, RendererBGFXStatic.CreateMemoryBlock(vertexSrc, numVertices * sizeofVertex)); vertexCount = numVertices; }
public static unsafe MeshBGFX CreateStaticMesh(RendererBGFXInstance *inst, ushort *indices, int nindices, SimpleVertex *vertices, int nvertices) { #if ENABLE_DOTSRUNTIME_PROFILER ProfilerStats.AccumStats.memMeshCount.Accumulate(1); long bytes = nvertices * sizeof(SimpleVertex) + nindices * sizeof(ushort); ProfilerStats.AccumStats.memMesh.Accumulate(bytes); ProfilerStats.AccumStats.memReservedGFX.Accumulate(bytes); ProfilerStats.AccumStats.memUsedGFX.Accumulate(bytes); #endif return(new MeshBGFX { indexBufferHandle = bgfx.create_index_buffer(RendererBGFXStatic.CreateMemoryBlock((byte *)indices, nindices * 2), (ushort)bgfx.BufferFlags.None).idx, vertexBufferHandle = bgfx.create_vertex_buffer(RendererBGFXStatic.CreateMemoryBlock((byte *)vertices, nvertices * sizeof(SimpleVertex)), &inst->m_simpleVertexBufferDecl, (ushort)bgfx.BufferFlags.None).idx, indexCount = nindices, vertexCount = nvertices, maxIndexCount = nindices, maxVertexCount = nvertices, vertexLayoutHandle = inst->m_simpleVertexBufferDeclHandle, isDynamic = false, vertexSize = sizeof(SimpleVertex), }); }
public static unsafe void EncodeLinePreTransformed(RendererBGFXInstance *sys, bgfx.Encoder *encoder, ushort viewId, SimpleVertex *vertices, int n) { bgfx.TransientIndexBuffer tib; bgfx.TransientVertexBuffer tvb; int ni = (n / 4) * 6; if (!bgfx.alloc_transient_buffers(&tvb, &sys->m_simpleVertexBufferDecl, (uint)n, &tib, (uint)ni)) { throw new InvalidOperationException("Out of transient bgfx memory!"); } UnsafeUtility.MemCpy((SimpleVertex *)tvb.data, vertices, sizeof(SimpleVertex) * n); ushort *indices = (ushort *)tib.data; for (int i = 0; i < n; i += 4) { indices[0] = (ushort)i; indices[1] = (ushort)(i + 1); indices[2] = (ushort)(i + 2); indices[3] = (ushort)(i + 2); indices[4] = (ushort)(i + 3); indices[5] = (ushort)i; indices += 6; } bgfx.encoder_set_transient_index_buffer(encoder, &tib, 0, (uint)ni); bgfx.encoder_set_transient_vertex_buffer(encoder, 0, &tvb, 0, (uint)n, sys->m_simpleVertexBufferDeclHandle); // material uniforms setup ulong state = (ulong)(bgfx.StateFlags.DepthTestLess | bgfx.StateFlags.WriteRgb) | RendererBGFXStatic.MakeBGFXBlend(bgfx.StateFlags.BlendOne, bgfx.StateFlags.BlendInvSrcAlpha); bgfx.encoder_set_state(encoder, state, 0); bgfx.encoder_submit(encoder, viewId, sys->m_lineShader.m_prog, 0, (byte)bgfx.DiscardFlags.All); }
protected override void OnUpdate() { var bgfxinst = World.GetExistingSystem <RendererBGFXSystem>().InstancePointer(); if (!bgfxinst->m_initialized) { return; } // setup bgfx side Entities.WithoutBurst().ForEach((Entity e, ref RenderPass pass) => { if (pass.viewId == 0xffff) { RenderDebug.LogFormat("Render pass entity {0} on render node entity {1} is not referenced by the render graph. It should be deleted.", e, pass.inNode); Assert.IsTrue(false); return; } bool rtt = EntityManager.HasComponent <FramebufferBGFX>(pass.inNode); if (rtt) { pass.passFlags = RenderPassFlags.RenderToTexture; } else { pass.passFlags = 0; } // those could be more shared ... (that is, do all passes really need a copy of view & projection?) unsafe { fixed(float4x4 * viewp = &pass.viewTransform, projp = &pass.projectionTransform) { if (bgfxinst->m_homogeneousDepth && bgfxinst->m_originBottomLeft) // gl style { bgfx.set_view_transform(pass.viewId, viewp, projp); pass.passFlags &= ~RenderPassFlags.FlipCulling; } else // dx style { bool yflip = !bgfxinst->m_originBottomLeft && rtt; float4x4 adjustedProjection = RendererBGFXStatic.AdjustProjection(ref pass.projectionTransform, !bgfxinst->m_homogeneousDepth, yflip); bgfx.set_view_transform(pass.viewId, viewp, &adjustedProjection); if (yflip) { pass.passFlags |= RenderPassFlags.FlipCulling; } else { pass.passFlags &= ~RenderPassFlags.FlipCulling; } } // make a viewProjection pass.viewProjectionTransform = math.mul(pass.projectionTransform, pass.viewTransform); } } bgfx.set_view_mode(pass.viewId, (bgfx.ViewMode)pass.sorting); bgfx.set_view_rect(pass.viewId, pass.viewport.x, pass.viewport.y, pass.viewport.w, pass.viewport.h); bgfx.set_view_scissor(pass.viewId, pass.scissor.x, pass.scissor.y, pass.scissor.w, pass.scissor.h); bgfx.set_view_clear(pass.viewId, (ushort)pass.clearFlags, pass.clearRGBA, pass.clearDepth, pass.clearStencil); if (rtt) { var rttbgfx = EntityManager.GetComponentData <FramebufferBGFX>(pass.inNode); bgfx.set_view_frame_buffer(pass.viewId, rttbgfx.handle); } else { bgfx.set_view_frame_buffer(pass.viewId, new bgfx.FrameBufferHandle { idx = 0xffff }); } // touch it? needed? bgfx.touch(pass.viewId); }).Run(); }