private void AddMappedLight(ref LightingBGFX r, ref ShadowmappedLight sml, ref Light l, ref float4x4 tx, ref LightMatrices txCache, RendererBGFXInstance *sys, bool isSpot, float4 spotmask, bool srgbColors) { if (r.numMappedLights >= LightingBGFX.maxMappedLights) { throw new InvalidOperationException("Too many mapped lights"); } bgfx.TextureHandle texShadowMap = sys->m_noShadow; int shadowMapSize = 1; if (sml.shadowMap != Entity.Null && EntityManager.HasComponent <TextureBGFX>(sml.shadowMap)) { var imShadowMap = EntityManager.GetComponentData <Image2D>(sml.shadowMap); Assert.IsTrue(imShadowMap.imagePixelWidth == imShadowMap.imagePixelHeight); shadowMapSize = imShadowMap.imagePixelHeight; texShadowMap = EntityManager.GetComponentData <TextureBGFX>(sml.shadowMap).handle; } float4 mask = isSpot ? spotmask : new float4(0.0f, 0.0f, 0.0f, 1.0f); float4 worldPosOrDir = isSpot? new float4(tx.c3.xyz, 1.0f) : new float4(-tx.c2.xyz, 0.0f); float3 c = srgbColors?Color.LinearToSRGB(l.color):l.color; r.SetMappedLight(r.numMappedLights, txCache.mvp, c * l.intensity, worldPosOrDir, l.clipZFar, mask, texShadowMap, shadowMapSize); r.numMappedLights++; }
private void AddMappedLight(ref LightingBGFX r, ref ShadowmappedLight sml, ref Light l, ref float4x4 tx, ref LightMatrices txCache, RendererBGFXSystem sys, bool isSpot) { if (r.numMappedLights >= LightingBGFX.maxMappedLights) throw new InvalidOperationException("Too many mapped lights"); }
private void AddCascadeMappedLight(ref LightingBGFX r, ref ShadowmappedLight sml, ref Light l, ref float4x4 tx, ref LightMatrices txCache, ref CascadeShadowmappedLight csm, ref CascadeShadowmappedLightCache csmData, RendererBGFXInstance *sys, bool srgbColors) { if (r.numCsmLights >= LightingBGFX.maxCsmLights) { throw new InvalidOperationException("Too many cascade mapped lights"); } bgfx.TextureHandle texShadowMap = sys->m_noShadow; int shadowMapSize = 1; if (sml.shadowMap != Entity.Null && EntityManager.HasComponent <TextureBGFX>(sml.shadowMap)) { var imShadowMap = EntityManager.GetComponentData <Image2D>(sml.shadowMap); Assert.IsTrue(imShadowMap.imagePixelWidth == imShadowMap.imagePixelHeight); shadowMapSize = imShadowMap.imagePixelHeight; texShadowMap = EntityManager.GetComponentData <TextureBGFX>(sml.shadowMap).handle; } float4 worldPosOrDir = new float4(math.normalize(-tx.c2.xyz), 0.0f); float4 mask = new float4(0); float3 c = srgbColors?Color.LinearToSRGB(l.color):l.color; r.SetMappedLight(LightingBGFX.maxMappedLights + r.numCsmLights, txCache.mvp, c * l.intensity, worldPosOrDir, l.clipZFar, mask, texShadowMap, shadowMapSize); unsafe { r.csmOffsetScale[0] = csmData.c0.offset.x; r.csmOffsetScale[1] = csmData.c0.offset.y; r.csmOffsetScale[2] = 0; r.csmOffsetScale[3] = csmData.c0.scale; r.csmOffsetScale[4] = csmData.c1.offset.x; r.csmOffsetScale[5] = csmData.c1.offset.y; r.csmOffsetScale[6] = 0; r.csmOffsetScale[7] = csmData.c1.scale; r.csmOffsetScale[8] = csmData.c2.offset.x; r.csmOffsetScale[9] = csmData.c2.offset.y; r.csmOffsetScale[10] = 0; r.csmOffsetScale[11] = csmData.c2.scale; r.csmOffsetScale[12] = csmData.c3.offset.x; r.csmOffsetScale[13] = csmData.c3.offset.y; r.csmOffsetScale[14] = 0; r.csmOffsetScale[15] = csmData.c3.scale; } // r.csmLightsis set in SetMappedLight r.numCsmLights++; }
protected override void OnUpdate() { var bgfxsys = World.GetExistingSystem <RendererBGFXSystem>(); if (!bgfxsys.Initialized) { return; } // make sure passes have viewid, transform, scissor rect and view rect set // reset alreadyAdded state // we expect < 100 or so passes, so the below code does not need to be crazy great Entities.ForEach((ref RenderNode rnode) => { rnode.alreadyAdded = false; }); Entities.ForEach((ref RenderPass pass) => { pass.viewId = 0xffff; }); // there SHOULD not be any passes around that are not referenced by the graph... // get all nodes, sort (bgfx issues in-order per view. a better api could use the render graph to issue without gpu // barriers where possible) // sort into eval order, assign pass viewId ushort nextViewId = 0; Entities.WithAll <RenderNodePrimarySurface>().ForEach((Entity eNode) => { RecAddPasses(eNode, ref nextViewId); }); Entities.WithAll <RenderPassAutoSizeToNode>().ForEach((Entity e, ref RenderPass pass) => { if (EntityManager.HasComponent <RenderNodePrimarySurface>(pass.inNode)) { var di = World.TinyEnvironment().GetConfigData <DisplayInfo>(); pass.viewport.x = 0; pass.viewport.y = 0; pass.viewport.w = (ushort)di.width; pass.viewport.h = (ushort)di.height; return; } if (EntityManager.HasComponent <RenderNodeTexture>(pass.inNode)) { var texRef = EntityManager.GetComponentData <RenderNodeTexture>(pass.inNode); pass.viewport = texRef.rect; } // TODO: add others like cubemap }); // auto update passes that are matched with a camera Entities.ForEach((Entity e, ref RenderPass pass, ref RenderPassUpdateFromCamera fromCam) => { Entity eCam = fromCam.camera; CameraMatrices camData = EntityManager.GetComponentData <CameraMatrices>(eCam); pass.viewTransform = camData.view; pass.projectionTransform = camData.projection; if (EntityManager.HasComponent <Frustum>(eCam)) { if (EntityManager.HasComponent <Frustum>(e)) { EntityManager.SetComponentData(e, EntityManager.GetComponentData <Frustum>(eCam)); } } else { if (EntityManager.HasComponent <Frustum>(e)) { EntityManager.SetComponentData(e, new Frustum()); } } }); // auto update passes that are matched with a light Entities.ForEach((Entity e, ref RenderPass pass, ref RenderPassUpdateFromLight fromLight) => { Entity eLight = fromLight.light; LightMatrices lightData = EntityManager.GetComponentData <LightMatrices>(eLight); pass.viewTransform = lightData.view; pass.projectionTransform = lightData.projection; if (EntityManager.HasComponent <Frustum>(eLight)) { if (EntityManager.HasComponent <Frustum>(e)) { EntityManager.SetComponentData(e, EntityManager.GetComponentData <Frustum>(eLight)); } } else { if (EntityManager.HasComponent <Frustum>(e)) { EntityManager.SetComponentData(e, new Frustum()); } } }); // set up extra pass data Entities.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); // 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 (bgfxsys.m_homogeneousDepth && bgfxsys.m_originBottomLeft) // gl style { bgfx.set_view_transform(pass.viewId, viewp, projp); pass.flipCulling = 0; } else // dx style { bool yflip = !bgfxsys.m_originBottomLeft && rtt; float4x4 adjustedProjection = RendererBGFXSystem.AdjustProjection(ref pass.projectionTransform, !bgfxsys.m_homogeneousDepth, yflip); bgfx.set_view_transform(pass.viewId, viewp, &adjustedProjection); pass.flipCulling = yflip ? (byte)3 : (byte)0; } } } 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); }); }