示例#1
0
        private void UpdateMaterial(RenderMesh renderMesh, MaterialPass materialPass, MaterialInstance modelMaterialInstance, ModelComponent modelComponent)
        {
            renderMesh.MaterialPass = materialPass;

            renderMesh.IsShadowCaster = modelComponent.IsShadowCaster;
            if (modelMaterialInstance != null)
            {
                renderMesh.IsShadowCaster = renderMesh.IsShadowCaster && modelMaterialInstance.IsShadowCaster;
            }
        }
示例#2
0
        private void CheckMeshes(RenderModel renderModel)
        {
            // Check if model changed
            var model = renderModel.ModelComponent.Model;

            if (renderModel.Model == model)
            {
                return;
            }

            // Remove old meshes
            if (renderModel.Meshes != null)
            {
                foreach (var renderMesh in renderModel.Meshes)
                {
                    // Unregister from render system
                    VisibilityGroup.RenderObjects.Remove(renderMesh);
                }
            }

            if (model == null)
            {
                return;
            }

            // Create render meshes
            var renderMeshes   = new RenderMesh[model.Meshes.Count];
            var modelComponent = renderModel.ModelComponent;

            for (int index = 0; index < model.Meshes.Count; index++)
            {
                var mesh = model.Meshes[index];

                // TODO: Somehow, if material changed we might need to remove/add object in render system again (to evaluate new render stage subscription)
                var materialIndex = mesh.MaterialIndex;
                renderMeshes[index] = new RenderMesh
                {
                    RenderModel = renderModel,
                    Mesh        = mesh,
                };

                // Update material
                UpdateMaterial(renderMeshes[index], modelComponent.Materials.GetItemOrNull(materialIndex), model.Materials.GetItemOrNull(materialIndex), modelComponent);
            }

            renderModel.Model  = model;
            renderModel.Meshes = renderMeshes;

            // Update and register with render system
            foreach (var renderMesh in renderMeshes)
            {
                VisibilityGroup.RenderObjects.Add(renderMesh);
            }
        }
示例#3
0
        private void PrepareRenderMeshes(RenderModel renderModel, List <Mesh> meshes, ref FastListStruct <RenderMesh> renderMeshes, RenderItemCollection opaqueList, RenderItemCollection transparentList)
        {
            // Add new render meshes
            for (int i = renderMeshes.Count; i < meshes.Count; i++)
            {
                var renderMesh = new RenderMesh(renderModel, meshes[i]);
                renderMeshes.Add(renderMesh);
            }

            // Create the bounding frustum locally on the stack, so that frustum.Contains is performed with boundingBox that is also on the stack
            var frustum = new BoundingFrustum(ref ViewProjectionMatrix);

            var sceneCameraRenderer = Context.Tags.Get(SceneCameraRenderer.Current);
            var cullingMode         = CullingModeOverride ?? (sceneCameraRenderer?.CullingMode ?? CameraCullingMode.None);

            for (int i = 0; i < renderMeshes.Count; i++)
            {
                var renderMesh = renderMeshes[i];
                // Update the model hierarchy
                var modelViewHierarchy = renderModel.ModelComponent.Skeleton;
                modelViewHierarchy.UpdateRenderMesh(renderMesh);

                if (!renderMesh.Enabled || !renderMesh.UpdateMaterial())
                {
                    continue;
                }

                // Upload skinning blend matrices
                BoundingBoxExt boundingBox;
                skinningUpdater.Update(modelViewHierarchy, renderMesh, out boundingBox);

                // Fast AABB transform: http://zeuxcg.org/2010/10/17/aabb-from-obb-with-component-wise-abs/
                // Compute transformed AABB (by world)
                // TODO: CameraCullingMode should be pluggable
                // TODO: This should not be necessary. Add proper bounding boxes to gizmos etc.
                if (cullingMode == CameraCullingMode.Frustum && boundingBox.Extent != Vector3.Zero && !frustum.Contains(ref boundingBox))
                {
                    continue;
                }

                // Project the position
                // TODO: This could be done in a SIMD batch, but we need to figure-out how to plugin in with RenderMesh object
                var     worldPosition = new Vector4(renderMesh.WorldMatrix.TranslationVector, 1.0f);
                Vector4 projectedPosition;
                Vector4.Transform(ref worldPosition, ref ViewProjectionMatrix, out projectedPosition);
                var projectedZ = projectedPosition.Z / projectedPosition.W;

                renderMesh.RasterizerState = renderMesh.IsGeometryInverted ? RasterizerStateForInvertedGeometry : RasterizerState;
                renderMesh.ForceRasterizer = ForceRasterizer;

                var list = renderMesh.HasTransparency ? transparentList : opaqueList;
                list.Add(new RenderItem(this, renderMesh, projectedZ));
            }
        }
示例#4
0
        private void UpdateMaterial(RenderMesh renderMesh, Material materialOverride, MaterialInstance modelMaterialInstance, ModelComponent modelComponent)
        {
            renderMesh.Material = materialOverride ?? modelMaterialInstance?.Material ?? fallbackMaterial;

            renderMesh.IsShadowCaster   = modelComponent.IsShadowCaster;
            renderMesh.IsShadowReceiver = modelComponent.IsShadowReceiver;
            if (modelMaterialInstance != null)
            {
                renderMesh.IsShadowCaster   = renderMesh.IsShadowCaster && modelMaterialInstance.IsShadowCaster;
                renderMesh.IsShadowReceiver = renderMesh.IsShadowReceiver && modelMaterialInstance.IsShadowReceiver;
            }
        }
示例#5
0
        /// <summary>
        /// Updates previously computed world matrices to TransformationKeys.World for each <see cref="RenderMesh" />.
        /// </summary>
        /// <param name="renderMesh">The render mesh.</param>
        internal void UpdateRenderMesh(RenderMesh renderMesh)
        {
            var nodeIndex = renderMesh.Mesh.NodeIndex;
            var enabled   = nodeTransformations[nodeIndex].RenderingEnabledRecursive;

            renderMesh.Enabled = enabled;
            if (enabled && renderMesh.MatrixCounter != matrixCounter)
            {
                renderMesh.WorldMatrix        = nodeTransformations[nodeIndex].WorldMatrix;
                renderMesh.IsGeometryInverted = nodeTransformations[nodeIndex].IsScalingNegative;
                renderMesh.MatrixCounter      = matrixCounter;
            }
        }
示例#6
0
        public void Update(SkeletonUpdater hierarchyUpdater, RenderMesh renderMesh, out BoundingBoxExt boundingBox)
        {
            var mesh     = renderMesh.Mesh;
            var skinning = mesh.Skinning;

            if (skinning == null)
            {
                // For unskinned meshes, use the original bounding box
                var boundingBoxExt = (BoundingBoxExt)mesh.BoundingBox;
                boundingBoxExt.Transform(renderMesh.WorldMatrix);
                boundingBox = boundingBoxExt;
                return;
            }

            var bones = skinning.Bones;

            // Make sure there is enough spaces in boneMatrices
            if (bones.Length > boneMatrices.Length)
            {
                boneMatrices = new Matrix[bones.Length];
            }

            var bindPoseBoundingBox = new BoundingBoxExt(renderMesh.Mesh.BoundingBox);

            boundingBox = BoundingBoxExt.Empty;

            for (int index = 0; index < bones.Length; index++)
            {
                var nodeIndex = bones[index].NodeIndex;

                // Compute bone matrix
                Matrix.Multiply(ref bones[index].LinkToMeshMatrix, ref hierarchyUpdater.NodeTransformations[nodeIndex].WorldMatrix, out boneMatrices[index]);

                // Calculate and extend bounding box for each bone
                // TODO: Move runtime bounding box into ModelViewHierarchyUpdater?

                // Fast AABB transform: http://zeuxcg.org/2010/10/17/aabb-from-obb-with-component-wise-abs/
                // Compute transformed AABB (by world)
                var boundingBoxExt = bindPoseBoundingBox;
                boundingBoxExt.Transform(boneMatrices[index]);
                BoundingBoxExt.Merge(ref boundingBox, ref boundingBoxExt, out boundingBox);
            }

            // Upload bones
            renderMesh.Parameters.Set(TransformationSkinningKeys.BlendMatrixArray, boneMatrices, 0, bones.Length);
        }
示例#7
0
        /// <summary>
        /// Create or update the Effect of the effect mesh.
        /// </summary>
        protected void UpdateEffect(RenderContext context, RenderMesh renderMesh, ParameterCollection passParameters)
        {
            if (dynamicEffectCompiler.Update(renderMesh, passParameters))
            {
                try
                {
                    renderMesh.Initialize(context.GraphicsDevice);
                }
                catch (Exception e)
                {
                    Log.Error("Could not initialize RenderMesh, trying again with error fallback effect", e);

                    // Try again with error effect to show user something failed with this model
                    // TODO: What if an exception happens in this case too? Mark renderMesh as ignored or null?
                    dynamicEffectCompiler.SwitchFallbackEffect(FallbackEffectType.Error, renderMesh, passParameters);
                    renderMesh.Initialize(context.GraphicsDevice);
                }
            }
        }
        public void Update(SkeletonUpdater hierarchyUpdater, RenderMesh renderMesh, out BoundingBoxExt boundingBox)
        {
            var mesh = renderMesh.Mesh;
            var skinning = mesh.Skinning;

            if (skinning == null)
            {
                // For unskinned meshes, use the original bounding box
                var boundingBoxExt = (BoundingBoxExt)mesh.BoundingBox;
                boundingBoxExt.Transform(renderMesh.WorldMatrix);
                boundingBox = boundingBoxExt;
                return;
            }

            var bones = skinning.Bones;

            // Make sure there is enough spaces in boneMatrices
            if (bones.Length > boneMatrices.Length)
                boneMatrices = new Matrix[bones.Length];

            var bindPoseBoundingBox = new BoundingBoxExt(renderMesh.Mesh.BoundingBox);
            boundingBox = BoundingBoxExt.Empty;

            for (int index = 0; index < bones.Length; index++)
            {
                var nodeIndex = bones[index].NodeIndex;

                // Compute bone matrix
                Matrix.Multiply(ref bones[index].LinkToMeshMatrix, ref hierarchyUpdater.NodeTransformations[nodeIndex].WorldMatrix, out boneMatrices[index]);

                // Calculate and extend bounding box for each bone
                // TODO: Move runtime bounding box into ModelViewHierarchyUpdater?

                // Fast AABB transform: http://zeuxcg.org/2010/10/17/aabb-from-obb-with-component-wise-abs/
                // Compute transformed AABB (by world)
                var boundingBoxExt = bindPoseBoundingBox;
                boundingBoxExt.Transform(boneMatrices[index]);
                BoundingBoxExt.Merge(ref boundingBox, ref boundingBoxExt, out boundingBox);
            }

            // Upload bones
            renderMesh.Parameters.Set(TransformationSkinningKeys.BlendMatrixArray, boneMatrices, 0, bones.Length);
        }
        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);
                }
            }
        }
示例#10
0
        /// <summary>
        /// Create or update the Effect of the effect mesh.
        /// </summary>
        protected void UpdateEffect(RenderContext context, RenderMesh renderMesh, ParameterCollection passParameters)
        {
            if (dynamicEffectCompiler.Update(renderMesh, passParameters))
            {
                try
                {
                    renderMesh.Initialize(context.GraphicsDevice);
                }
                catch (Exception e)
                {
                    Log.Error("Could not initialize RenderMesh, trying again with error fallback effect", e);

                    // Try again with error effect to show user something failed with this model
                    // TODO: What if an exception happens in this case too? Mark renderMesh as ignored or null?
                    dynamicEffectCompiler.SwitchFallbackEffect(FallbackEffectType.Error, renderMesh, passParameters);
                    renderMesh.Initialize(context.GraphicsDevice);
                }
            }
        }
示例#11
0
        private void PrepareRenderMeshes(RenderModel renderModel, List<Mesh> meshes, ref FastListStruct<RenderMesh> renderMeshes, RenderItemCollection opaqueList, RenderItemCollection transparentList)
        {
            // Add new render meshes
            for (int i = renderMeshes.Count; i < meshes.Count; i++)
            {
                var renderMesh = new RenderMesh(renderModel, meshes[i]);
                renderMeshes.Add(renderMesh);
            }

            // Create the bounding frustum locally on the stack, so that frustum.Contains is performed with boundingBox that is also on the stack
            var frustum = new BoundingFrustum(ref ViewProjectionMatrix);

            var sceneCameraRenderer = Context.Tags.Get(SceneCameraRenderer.Current);
            var cullingMode = CullingModeOverride ?? (sceneCameraRenderer?.CullingMode ?? CameraCullingMode.None);

            for (int i = 0; i < renderMeshes.Count; i++)
            {
                var renderMesh = renderMeshes[i];
                // Update the model hierarchy
                var modelViewHierarchy = renderModel.ModelComponent.Skeleton;
                modelViewHierarchy.UpdateRenderMesh(renderMesh);

                if (!renderMesh.Enabled || !renderMesh.UpdateMaterial())
                {
                    continue;
                }

                // Upload skinning blend matrices
                BoundingBoxExt boundingBox;
                skinningUpdater.Update(modelViewHierarchy, renderMesh, out boundingBox);

                // Fast AABB transform: http://zeuxcg.org/2010/10/17/aabb-from-obb-with-component-wise-abs/
                // Compute transformed AABB (by world)
                // TODO: CameraCullingMode should be pluggable
                // TODO: This should not be necessary. Add proper bounding boxes to gizmos etc.
                if (cullingMode == CameraCullingMode.Frustum && boundingBox.Extent != Vector3.Zero && !frustum.Contains(ref boundingBox))
                {
                    continue;
                }

                // Project the position
                // TODO: This could be done in a SIMD batch, but we need to figure-out how to plugin in with RenderMesh object
                var worldPosition = new Vector4(renderMesh.WorldMatrix.TranslationVector, 1.0f);
                Vector4 projectedPosition;
                Vector4.Transform(ref worldPosition, ref ViewProjectionMatrix, out projectedPosition);
                var projectedZ = projectedPosition.Z / projectedPosition.W;

                renderMesh.RasterizerState = renderMesh.IsGeometryInverted ? RasterizerStateForInvertedGeometry : RasterizerState;
                renderMesh.ForceRasterizer = ForceRasterizer;

                var list = renderMesh.HasTransparency ? transparentList : opaqueList;
                list.Add(new RenderItem(this, renderMesh, projectedZ));
            }
        }
示例#12
0
 /// <summary>
 /// Updates previously computed world matrices to TransformationKeys.World for each <see cref="RenderMesh" />.
 /// </summary>
 /// <param name="renderMesh">The render mesh.</param>
 internal void UpdateRenderMesh(RenderMesh renderMesh)
 {
     var nodeIndex = renderMesh.Mesh.NodeIndex;
     var enabled = nodeTransformations[nodeIndex].RenderingEnabledRecursive;
     renderMesh.Enabled = enabled;
     if (enabled && renderMesh.MatrixCounter != matrixCounter)
     {
         renderMesh.WorldMatrix = nodeTransformations[nodeIndex].WorldMatrix;
         renderMesh.IsGeometryInverted = nodeTransformations[nodeIndex].IsScalingNegative;
         renderMesh.MatrixCounter = matrixCounter;
     }
 }