private void PreRenderMesh(RenderContext context, RenderMesh renderMesh) { var contextParameters = context.Parameters; RenderModelLights renderModelLights; if (!modelToLights.TryGetValue(renderMesh.RenderModel, out renderModelLights)) { contextParameters.Set(LightingKeys.DirectLightGroups, null); contextParameters.Set(LightingKeys.EnvironmentLights, null); return; } // TODO: copy shadow receiver info to mesh var isShadowReceiver = renderMesh.IsShadowReceiver; if (currentModelLightShadersPermutationEntry != renderModelLights.LightShadersPermutation || currentModelShadersParameters != renderModelLights.Parameters || currentShadowReceiver != isShadowReceiver) { currentModelLightShadersPermutationEntry = renderModelLights.LightShadersPermutation; currentModelShadersParameters = renderModelLights.Parameters; currentShadowReceiver = isShadowReceiver; if (currentShadowReceiver) { currentModelShadersParameters.Parameters.CopySharedTo(contextParameters); } else { currentModelShadersParameters.ParametersNoShadows.CopySharedTo(contextParameters); } } }
public RenderModelLights(LightShaderPermutationEntry lightShadersPermutation, LightParametersPermutationEntry parameters) { LightShadersPermutation = lightShadersPermutation; Parameters = parameters; }
protected override void DrawCore(RenderContext context) { modelProcessor = SceneInstance.GetCurrent(context).GetProcessor<ModelProcessor>(); lightProcessor = SceneInstance.GetCurrent(context).GetProcessor<LightProcessor>(); // No light processors means no light in the scene, so we can early exit if (lightProcessor == null || modelProcessor == null) { return; } // Not in the context of a SceneCameraRenderer? just exit sceneCameraRenderer = context.Tags.Get(SceneCameraRenderer.Current); sceneCamera = context.Tags.Get(CameraComponentRenderer.Current); if (sceneCameraRenderer == null || sceneCamera == null) { return; } sceneCullingMask = sceneCameraRenderer.CullingMask; // Setup the callback on the ModelRenderer and shadow map LightGroupRenderer if (!isModelComponentRendererSetup) { // TODO: Check if we could discover declared renderers in a better way than just hacking the tags of a component var modelRenderer = ModelComponentRenderer.GetAttached(sceneCameraRenderer); if (modelRenderer == null) { return; } modelRenderer.Callbacks.PreRenderModel += PrepareRenderModelForRendering; modelRenderer.Callbacks.PreRenderMesh += PreRenderMesh; // TODO: Make this pluggable // TODO: Shadows should work on mobile platforms if (context.GraphicsDevice.Features.Profile >= GraphicsProfile.Level_10_0 && (Platform.Type == PlatformType.Windows || Platform.Type == PlatformType.WindowsStore || Platform.Type == PlatformType.Windows10)) { shadowMapRenderer = new ShadowMapRenderer(modelRenderer.EffectName); shadowMapRenderer.Renderers.Add(typeof(LightDirectional), new LightDirectionalShadowMapRenderer()); shadowMapRenderer.Renderers.Add(typeof(LightSpot), new LightSpotShadowMapRenderer()); } isModelComponentRendererSetup = true; } // Collect all visible lights CollectVisibleLights(); // Draw shadow maps if (shadowMapRenderer != null) shadowMapRenderer.Draw(context, visibleLightsWithShadows); // Prepare active renderers in an ordered list (by type and shadow on/off) CollectActiveLightRenderers(context); currentModelLightShadersPermutationEntry = null; currentModelShadersParameters = null; currentShadowReceiver = true; // Clear the cache of parameter entries lightParameterEntries.Clear(); parameterCollectionEntryPool.Clear(); // Clear association between model and lights modelToLights.Clear(); // Clear all data generated by shader entries foreach (var shaderEntry in shaderEntries) { shaderEntry.Value.ResetGroupDatas(); } }
private unsafe bool PrepareLightParameterEntry(RenderThreadContext context, LightParametersPermutationEntry lightParameterEntry, RenderEffect renderEffect) { var lightShadersPermutation = lightParameterEntry.ShaderPermutationEntry; // Create layout for new light shader permutations if (lightShadersPermutation.PerLightingLayout == null || lightShadersPermutation.PerLightingLayout.Hash != renderEffect.Reflection.ResourceGroupDescriptions[perLightingDescriptorSetSlot.Index].Hash) { var resourceGroupDescription = renderEffect.Reflection.ResourceGroupDescriptions[perLightingDescriptorSetSlot.Index]; if (resourceGroupDescription.DescriptorSetLayout == null) { return(false); } var parameterCollectionLayout = lightShadersPermutation.ParameterCollectionLayout = new ParameterCollectionLayout(); parameterCollectionLayout.ProcessResources(resourceGroupDescription.DescriptorSetLayout); lightShadersPermutation.ResourceCount = parameterCollectionLayout.ResourceCount; // Process PerLighting cbuffer (if any) if (resourceGroupDescription.ConstantBufferReflection != null) { lightShadersPermutation.ConstantBufferReflection = resourceGroupDescription.ConstantBufferReflection; parameterCollectionLayout.ProcessConstantBuffer(resourceGroupDescription.ConstantBufferReflection); } lightShadersPermutation.PerLightingLayout = ResourceGroupLayout.New(RenderSystem.GraphicsDevice, resourceGroupDescription, renderEffect.Effect.Bytecode); } // Assign layout to new parameter permutations var parameters = lightParameterEntry.Parameters; if (parameters.Layout != lightShadersPermutation.ParameterCollectionLayout) { // TODO GRAPHICS REFACTOR should we recompute or store the parameter layout? parameters.UpdateLayout(lightShadersPermutation.ParameterCollectionLayout); } // Do we need to allocate resources? if (lightParameterEntry.LastFrameUsed == RenderSystem.FrameCounter) { return(true); } lightParameterEntry.LastFrameUsed = RenderSystem.FrameCounter; // Set values foreach (var lightGroup in lightParameterEntry.DirectLightGroupDatas) { lightGroup.ApplyParameters(parameters); } foreach (var lightGroup in lightParameterEntry.EnvironmentLightDatas) { lightGroup.ApplyParameters(parameters); } context.ResourceGroupAllocator.PrepareResourceGroup(lightShadersPermutation.PerLightingLayout, BufferPoolAllocationType.UsedMultipleTime, lightParameterEntry.Resources); // Set resource bindings in PerLighting resource set for (int resourceSlot = 0; resourceSlot < lightShadersPermutation.ResourceCount; ++resourceSlot) { lightParameterEntry.Resources.DescriptorSet.SetValue(resourceSlot, parameters.ObjectValues[resourceSlot]); } // Process PerMaterial cbuffer if (lightShadersPermutation.ConstantBufferReflection != null) { var mappedCB = lightParameterEntry.Resources.ConstantBuffer.Data; fixed(byte *dataValues = parameters.DataValues) Utilities.CopyMemory(mappedCB, (IntPtr)dataValues, lightParameterEntry.Resources.ConstantBuffer.Size); } return(true); }
protected override void DrawCore(RenderContext context) { modelProcessor = SceneInstance.GetCurrent(context).GetProcessor <ModelProcessor>(); lightProcessor = SceneInstance.GetCurrent(context).GetProcessor <LightProcessor>(); // No light processors means no light in the scene, so we can early exit if (lightProcessor == null || modelProcessor == null) { return; } // Not in the context of a SceneCameraRenderer? just exit sceneCameraRenderer = context.Tags.Get(SceneCameraRenderer.Current); sceneCamera = context.Tags.Get(CameraComponentRenderer.Current); if (sceneCameraRenderer == null || sceneCamera == null) { return; } sceneCullingMask = sceneCameraRenderer.CullingMask; // Setup the callback on the ModelRenderer and shadow map LightGroupRenderer if (!isModelComponentRendererSetup) { // TODO: Check if we could discover declared renderers in a better way than just hacking the tags of a component var modelRenderer = ModelComponentRenderer.GetAttached(sceneCameraRenderer); if (modelRenderer == null) { return; } modelRenderer.Callbacks.PreRenderModel += PrepareRenderModelForRendering; modelRenderer.Callbacks.PreRenderMesh += PreRenderMesh; // TODO: Make this pluggable // TODO: Shadows should work on mobile platforms if (context.GraphicsDevice.Features.Profile >= GraphicsProfile.Level_10_0 && (Platform.Type == PlatformType.Windows || Platform.Type == PlatformType.WindowsStore || Platform.Type == PlatformType.Windows10)) { shadowMapRenderer = new ShadowMapRenderer(modelRenderer.EffectName); shadowMapRenderer.Renderers.Add(typeof(LightDirectional), new LightDirectionalShadowMapRenderer()); shadowMapRenderer.Renderers.Add(typeof(LightSpot), new LightSpotShadowMapRenderer()); } isModelComponentRendererSetup = true; } // Collect all visible lights CollectVisibleLights(); // Draw shadow maps if (shadowMapRenderer != null) { shadowMapRenderer.Draw(context, visibleLightsWithShadows); } // Prepare active renderers in an ordered list (by type and shadow on/off) CollectActiveLightRenderers(context); currentModelLightShadersPermutationEntry = null; currentModelShadersParameters = null; currentShadowReceiver = true; // Clear the cache of parameter entries lightParameterEntries.Clear(); parameterCollectionEntryPool.Clear(); // Clear association between model and lights modelToLights.Clear(); // Clear all data generated by shader entries foreach (var shaderEntry in shaderEntries) { shaderEntry.Value.ResetGroupDatas(); } }