public override void Extract() { var objectInfoDataHolder = RootRenderFeature.RenderData.GetData(_objectInfoPropertyKey); var blendMatricesDataHolder = RootRenderFeature.RenderData.GetData(_blendMatricesPropertyKey); foreach (var objectNodeReference in RootRenderFeature.ObjectNodeReferences) { var objectNode = RootRenderFeature.GetObjectNode(objectNodeReference); if (!(objectNode.RenderObject is RenderMesh renderMesh)) { continue; } blendMatricesDataHolder[objectNodeReference] = renderMesh.BlendMatrices; // This is for our skinned models. if (!(renderMesh.Source is ModelComponent modelComponent)) { continue; } var objectInfoData = new ObjectInfoData(modelComponent.RenderGroup); objectInfoDataHolder[objectNodeReference] = objectInfoData; #if DEBUG // This is only for debugging purposes, it can be removed. if (_isFirstRun) { System.Diagnostics.Debug.WriteLine($"Entity: {modelComponent.Entity.Name} - renderGrp: {objectInfoData.RenderGroup}"); } #endif } #if DEBUG _isFirstRun = false; #endif }
/// <inheritdoc/> public override void Extract() { var modelObjectInfo = RootRenderFeature.RenderData.GetData(renderObjectInfoKey); foreach (var objectNodeReference in RootRenderFeature.ObjectNodeReferences) { var objectNode = RootRenderFeature.GetObjectNode(objectNodeReference); var renderMesh = objectNode.RenderObject as RenderMesh; if (renderMesh == null) { continue; } int meshIndex = 0; var modelComponent = renderMesh.Source as ModelComponent; if (modelComponent == null) { continue; } for (int i = 0; i < modelComponent.Model.Meshes.Count; i++) { if (modelComponent.Model.Meshes[i] == renderMesh.Mesh) { meshIndex = i; break; } } modelObjectInfo[objectNodeReference] = new PickingObjectInfo(RuntimeIdHelper.ToRuntimeId(modelComponent), meshIndex, renderMesh.Mesh.MaterialIndex); } }
public override void Extract() { var objectInfoDataHolder = RootRenderFeature.RenderData.GetData(_objectInfoPropertyKey); var blendMatricesDataHolder = RootRenderFeature.RenderData.GetData(_blendMatricesPropertyKey); foreach (var objectNodeReference in RootRenderFeature.ObjectNodeReferences) { var objectNode = RootRenderFeature.GetObjectNode(objectNodeReference); if (!(objectNode.RenderObject is RenderMesh renderMesh)) { continue; } blendMatricesDataHolder[objectNodeReference] = renderMesh.BlendMatrices; // This is for our skinned models. int meshIndex = 0; if (!(renderMesh.Source is ModelComponent modelComponent)) { continue; } for (int i = 0; i < modelComponent.Model.Meshes.Count; i++) { if (modelComponent.Model.Meshes[i] == renderMesh.Mesh) { meshIndex = i; break; } } // RuntimeIdHelper.ToRuntimeId is how Stride does it for its 'Picking' scene. // We should probably change this to use something more appropriate for our data. var modelCompId = RuntimeIdHelper.ToRuntimeId(modelComponent); var objectInfoData = new ObjectInfoData((uint)modelCompId, (ushort)meshIndex, (ushort)renderMesh.Mesh.MaterialIndex); objectInfoDataHolder[objectNodeReference] = objectInfoData; #if DEBUG // This is only for debugging purposes, it can be removed. if (_isFirstRun) { System.Diagnostics.Debug.WriteLine($"Entity: {modelComponent.Entity.Name} - modelCompId: {objectInfoData.ModelComponentId} - meshIndex: {objectInfoData.MeshIndex} - matIndex: {objectInfoData.MaterialIndex}"); } #endif } #if DEBUG _isFirstRun = false; #endif }
public override void Extract() { var renderModelObjectInfo = RootRenderFeature.RenderData.GetData(renderModelObjectInfoKey); foreach (var objectNodeReference in RootRenderFeature.ObjectNodeReferences) { var objectNode = RootRenderFeature.GetObjectNode(objectNodeReference); var renderMesh = (RenderMesh)objectNode.RenderObject; Color4 highlightColor; var isHighlighted = MaterialHighlightColors.TryGetValue(renderMesh.MaterialPass.Material, out highlightColor) || MeshHighlightColors.TryGetValue(renderMesh.Mesh, out highlightColor) || MaterialsHighlightedForModel.Contains(renderMesh.MaterialPass.Material) && ModelHighlightColors.TryGetValue(renderMesh.RenderModel.ModelComponent, out highlightColor); renderModelObjectInfo[objectNodeReference] = highlightColor; } }
/// <inheritdoc/> public override void Prepare(RenderDrawContext context) { foreach (var view in RenderSystem.Views) { var viewFeature = view.Features[RootRenderFeature.Index]; RenderViewLightData renderViewData; if (!renderViewDatas.TryGetValue(view.LightingView ?? view, out renderViewData) || viewFeature.Layouts.Count == 0) { continue; } // Find a PerView layout from an effect in normal state ViewResourceGroupLayout firstViewLayout = null; foreach (var viewLayout in viewFeature.Layouts) { // Only process view layouts in normal state if (viewLayout.State != RenderEffectState.Normal) { continue; } var viewLighting = viewLayout.GetLogicalGroup(viewLightingKey); if (viewLighting.Hash != ObjectId.Empty) { firstViewLayout = viewLayout; break; } } // Nothing found for this view (no effects in normal state) if (firstViewLayout == null) { continue; } var viewIndex = renderViews.IndexOf(view); var viewParameterLayout = renderViewData.ViewParameterLayout; var viewParameters = renderViewData.ViewParameters; var firstViewLighting = firstViewLayout.GetLogicalGroup(viewLightingKey); // Prepare layout (should be similar for all PerView) if (firstViewLighting.Hash != renderViewData.ViewLayoutHash) { renderViewData.ViewLayoutHash = firstViewLighting.Hash; // Generate layout viewParameterLayout = renderViewData.ViewParameterLayout = new ParameterCollectionLayout(); viewParameterLayout.ProcessLogicalGroup(firstViewLayout, ref firstViewLighting); viewParameters.UpdateLayout(viewParameterLayout); } // Compute PerView lighting foreach (var directLightGroup in shaderPermutation.DirectLightGroups) { directLightGroup.ApplyViewParameters(context, viewIndex, viewParameters); } foreach (var environmentLight in shaderPermutation.EnvironmentLights) { environmentLight.ApplyViewParameters(context, viewIndex, viewParameters); } // Update PerView foreach (var viewLayout in viewFeature.Layouts) { // Only process view layouts in normal state if (viewLayout.State != RenderEffectState.Normal) { continue; } var viewLighting = viewLayout.GetLogicalGroup(viewLightingKey); if (viewLighting.Hash == ObjectId.Empty) { continue; } if (viewLighting.Hash != firstViewLighting.Hash) { throw new InvalidOperationException("PerView Lighting layout differs between different RenderObject in the same RenderView"); } var resourceGroup = viewLayout.Entries[view.Index].Resources; // Update resources resourceGroup.UpdateLogicalGroup(ref viewLighting, viewParameters); } // PerDraw Dispatcher.ForEach(viewFeature.RenderNodes, () => prepareThreadLocals.Value, (renderNodeReference, locals) => { var renderNode = RootRenderFeature.GetRenderNode(renderNodeReference); // Ignore fallback effects if (renderNode.RenderEffect?.State != RenderEffectState.Normal) { return; } var drawLayout = renderNode.RenderEffect?.Reflection?.PerDrawLayout; if (drawLayout == null) { return; } var drawLighting = drawLayout.GetLogicalGroup(drawLightingKey); if (drawLighting.Hash == ObjectId.Empty) { return; } // First time, let's build layout if (drawLighting.Hash != locals.DrawLayoutHash) { locals.DrawLayoutHash = drawLighting.Hash; // Generate layout var drawParameterLayout = new ParameterCollectionLayout(); drawParameterLayout.ProcessLogicalGroup(drawLayout, ref drawLighting); locals.DrawParameters.UpdateLayout(drawParameterLayout); } // TODO: Does this ever fail? Debug.Assert(drawLighting.Hash == locals.DrawLayoutHash, "PerDraw Lighting layout differs between different RenderObject in the same RenderView"); // Compute PerDraw lighting foreach (var directLightGroup in shaderPermutation.DirectLightGroups) { directLightGroup.ApplyDrawParameters(context, viewIndex, locals.DrawParameters, ref renderNode.RenderObject.BoundingBox); } foreach (var environmentLight in shaderPermutation.EnvironmentLights) { environmentLight.ApplyDrawParameters(context, viewIndex, locals.DrawParameters, ref renderNode.RenderObject.BoundingBox); } // Update resources renderNode.Resources.UpdateLogicalGroup(ref drawLighting, locals.DrawParameters); }); } }
/// <param name="context"></param> /// <inheritdoc/> public override void PrepareEffectPermutations(RenderThreadContext context) { var renderEffects = RootRenderFeature.RenderData.GetData(renderEffectKey); int effectSlotCount = ((RootEffectRenderFeature)RootRenderFeature).EffectPermutationSlotCount; var renderViewObjectInfoData = RootRenderFeature.RenderData.GetData(renderViewObjectInfoKey); var shadowMapEffectSlot = ShadowMapRenderStage != null ? ((RootEffectRenderFeature)RootRenderFeature).GetEffectPermutationSlot(ShadowMapRenderStage) : EffectPermutationSlot.Invalid; foreach (var view in RenderSystem.Views) { if (view.GetType() != typeof(RenderView)) { continue; } RenderViewLightData renderViewData; if (!renderViewDatas.TryGetValue(view, out renderViewData)) { continue; } var viewFeature = view.Features[RootRenderFeature.Index]; foreach (var renderPerViewNodeReference in viewFeature.ViewObjectNodes) { var renderPerViewNode = RootRenderFeature.GetViewObjectNode(renderPerViewNodeReference); var renderMesh = (RenderMesh)renderPerViewNode.RenderObject; if (!renderMesh.Material.IsLightDependent) { continue; } var staticObjectNode = renderMesh.StaticObjectNode; for (int i = 0; i < effectSlotCount; ++i) { // Don't apply lighting for shadow casters if (i == shadowMapEffectSlot.Index) { continue; } var staticEffectObjectNode = staticObjectNode * effectSlotCount + i; var renderEffect = renderEffects[staticEffectObjectNode]; // Skip effects not used during this frame if (renderEffect == null || !renderEffect.IsUsedDuringThisFrame(RenderSystem)) { continue; } var renderModel = renderMesh.RenderModel; var modelComponent = renderModel.ModelComponent; var isShadowReceiver = renderMesh.IsShadowReceiver && modelComponent.IsShadowReceiver; // TODO GRAPHICS REFACTOR: Shader permutations can be collected per-object. Only parameter permutations need to be per-view-object. var renderObjectInfo = PreparePermutationEntryForRendering(renderViewData, isShadowReceiver, ref modelComponent.BoundingBox, modelComponent.Entity.Group, i); renderObjectInfo.ApplyEffectPermutations(renderEffect); renderViewObjectInfoData[renderPerViewNodeReference] = renderObjectInfo; if (renderObjectInfo == null) { continue; } renderEffect.EffectValidator.ValidateParameter(LightingKeys.DirectLightGroups, renderObjectInfo.ShaderPermutationEntry.DirectLightShaders); renderEffect.EffectValidator.ValidateParameter(LightingKeys.EnvironmentLights, renderObjectInfo.ShaderPermutationEntry.EnvironmentLightShaders); } } } }
public RenderNodeFeatureReference(RootRenderFeature rootRenderFeature, RenderNodeReference renderNode, RenderObject renderObject) { RootRenderFeature = rootRenderFeature; RenderNode = renderNode; RenderObject = renderObject; }