public override void ApplyViewParameters(RenderDrawContext context, int viewIndex, ParameterCollection parameters)
            {
                CurrentLights.Clear();
                var lightRange = LightRanges[viewIndex];

                for (int i = lightRange.Start; i < lightRange.End; ++i)
                {
                    CurrentLights.Add(Lights[i]);
                }

                base.ApplyViewParameters(context, viewIndex, parameters);

                foreach (var lightEntry in CurrentLights)
                {
                    var light = lightEntry.Light;
                    lightsData.Add(new DirectionalLightData
                    {
                        DirectionWS = light.Direction,
                        Color       = light.Color,
                    });
                }

                parameters.Set(countKey, lightsData.Count);
                parameters.Set(lightsKey, lightsData.Count, ref lightsData.Items[0]);
                lightsData.Clear();
            }
        public int ApplyViewParameters_PopulateParameterLightsOrig()
        {
            int sum = 0;

            for (int ii = 0; ii < N; ii++)
            {
                for (int viewIndex = 0; viewIndex < lightRanges.Length; viewIndex++)
                {
                    var lightRange = lightRanges[viewIndex];
                    PopulateLightsInRange(ref lights, lightRange, ref currentLights);

                    lightsData.Clear();
                    // ----- Test
                    foreach (var lightEntry in currentLights)
                    {
                        var light = lightEntry.Light;
                        lightsData.Add(new DirectionalLightData
                        {
                            DirectionWS = light.Direction,
                            Color       = light.Color,
                        });
                    }

                    // ----- End Test
                    sum += lightsData.Count;
                }
            }
            return(sum);
        }
Пример #3
0
            public override void ApplyViewParameters(FastListStruct <LightDynamicEntry>?lightList, RenderDrawContext context, int viewIndex, ParameterCollection parameters)
            {
                FastListStruct <DirectionalLightData> lightsData = new FastListStruct <DirectionalLightData>(8);

                if (lightList == null)
                {
                    lightList = new FastListStruct <LightDynamicEntry>(8);
                }
                FastListStruct <LightDynamicEntry> currentLights = lightList.Value;
                var lightRange = lightRanges[viewIndex];

                for (int i = lightRange.Start; i < lightRange.End; ++i)
                {
                    currentLights.Add(lights[i]);
                }

                base.ApplyViewParameters(currentLights, context, viewIndex, parameters);

                foreach (var lightEntry in currentLights)
                {
                    var light = lightEntry.Light;
                    lightsData.Add(new DirectionalLightData
                    {
                        DirectionWS = light.Direction,
                        Color       = light.Color,
                    });
                }

                parameters.Set(countKey, lightsData.Count);
                parameters.Set(lightsKey, lightsData.Count, ref lightsData.Items[0]);
            }
Пример #4
0
        public void Initialize()
        {
            EffectValues = new FastListStruct <EffectParameterEntry>(4);

            // Add a dummy value so that an effect without parameter fails validation first time
            EffectValues.Add(new EffectParameterEntry());
        }
Пример #5
0
        public override void FillParameterCollections(ref FastListStruct <ParameterCollection> parameterCollections)
        {
            var material = Material;

            if (material != null && material.Parameters != null)
            {
                parameterCollections.Add(material.Parameters);
            }

            if (RenderModel.ModelComponent.Parameters != null)
            {
                parameterCollections.Add(RenderModel.ModelComponent.Parameters);
            }

            // TODO: Should we add RenderMesh.Parameters before ModelComponent.Parameters to allow user overiddes at component level?
            parameterCollections.Add(parameters);
        }
            public override void ApplyDrawParameters(RenderDrawContext context, int viewIndex, ParameterCollection parameters, ref BoundingBoxExt boundingBox)
            {
                if (currentLights.Items == null)
                {
                    currentLights = new FastListStruct <LightDynamicEntry>(8);
                }
                else
                {
                    currentLights.Clear();
                }
                if (lightsData.Items == null)
                {
                    lightsData = new FastListStruct <SpotLightData>(8);
                }

                var lightRange = lightRanges[viewIndex];

                for (int i = lightRange.Start; i < lightRange.End; ++i)
                {
                    currentLights.Add(lights[i]);
                }

                base.ApplyDrawParameters(context, viewIndex, parameters, ref boundingBox);

                // TODO: Octree structure to select best lights quicker
                var boundingBox2 = (BoundingBox)boundingBox;

                for (int i = 0; i < currentLights.Count; i++)
                {
                    var light = currentLights[i].Light;

                    if (light.BoundingBox.Intersects(ref boundingBox2))
                    {
                        var spotLight = (LightSpot)light.Type;
                        lightsData.Add(new SpotLightData
                        {
                            PositionWS  = light.Position,
                            DirectionWS = light.Direction,
                            AngleOffsetAndInvSquareRadius = new Vector3(spotLight.LightAngleScale, spotLight.LightAngleOffset, spotLight.InvSquareRange),
                            Color = light.Color,
                        });

                        // Did we reach max number of simultaneous lights?
                        // TODO: Still collect everything but sort by importance and remove the rest?
                        if (lightsData.Count >= LightCurrentCount)
                        {
                            break;
                        }
                    }
                }

                parameters.Set(countKey, lightsData.Count);
                parameters.Set(lightsKey, lightsData.Count, ref lightsData.Items[0]);

                TextureProjectionShaderGroupData?.ApplyDrawParameters(context, parameters, currentLights, ref boundingBox);

                lightsData.Clear();
            }
Пример #7
0
            public override void ApplyDrawParameters(RenderDrawContext context, int viewIndex, ParameterCollection parameters, ref BoundingBoxExt boundingBox)
            {
                if (currentLights.Items == null)
                {
                    currentLights = new FastListStruct <LightDynamicEntry>(8);
                }
                else
                {
                    currentLights.Clear();
                }
                if (lightsData.Items == null)
                {
                    lightsData = new FastListStruct <PointLightData>(8);
                }

                var lightRange = lightRanges[viewIndex];

                for (int i = lightRange.Start; i < lightRange.End; ++i)
                {
                    currentLights.Add(lights[i]);
                }

                base.ApplyDrawParameters(context, viewIndex, parameters, ref boundingBox);

                // TODO: Since we cull per object, we could maintain a higher number of allowed light than the shader support (i.e. 4 lights active per object even though the scene has many more of them)
                // TODO: Octree structure to select best lights quicker
                var boundingBox2 = (BoundingBox)boundingBox;

                foreach (var lightEntry in currentLights)
                {
                    var light = lightEntry.Light;

                    if (light.BoundingBox.Intersects(ref boundingBox2))
                    {
                        var pointLight = (LightPoint)light.Type;
                        lightsData.Add(new PointLightData
                        {
                            PositionWS      = light.Position,
                            InvSquareRadius = pointLight.InvSquareRadius,
                            Color           = light.Color,
                        });

                        // Did we reach max number of simultaneous lights?
                        // TODO: Still collect everything but sort by importance and remove the rest?
                        if (lightsData.Count >= LightCurrentCount)
                        {
                            break;
                        }
                    }
                }

                parameters.Set(countKey, lightsData.Count);
                parameters.Set(lightsKey, lightsData.Count, ref lightsData.Items[0]);
                lightsData.Clear();
            }
Пример #8
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));
            }
        }
Пример #9
0
        public override void FillParameterCollections(ref FastListStruct <ParameterCollection> parameterCollections)
        {
            // Test common types to avoid struct enumerator boxing
            var localParameterCollectionsList = localParameterCollections as List <ParameterCollection>;

            if (localParameterCollectionsList != null)
            {
                foreach (var parameter in localParameterCollectionsList)
                {
                    if (parameter != null)
                    {
                        parameterCollections.Add(parameter);
                    }
                }
            }
            else
            {
                var localParameterCollectionsArray = localParameterCollections as ParameterCollection[];
                if (localParameterCollectionsArray != null)
                {
                    foreach (var parameter in localParameterCollectionsArray)
                    {
                        if (parameter != null)
                        {
                            parameterCollections.Add(parameter);
                        }
                    }
                }
                else
                {
                    // Slow: enumerator will be boxed
                    foreach (var parameter in localParameterCollections)
                    {
                        if (parameter != null)
                        {
                            parameterCollections.Add(parameter);
                        }
                    }
                }
            }
        }
 public void GlobalSetup()
 {
     for (int i = 0; i < TotalLights; i++)
     {
         lights.Add(new LightDynamicEntry(new RenderLight(), shadowMapTexture: null));
     }
     lightRanges = new[]
     {
         new LightShaderGroupDynamic.LightRange(0, 4),
         new LightShaderGroupDynamic.LightRange(4, 8),
     };
 }
Пример #11
0
 public override void FillParameterCollections(ref FastListStruct<ParameterCollection> parameterCollections)
 {
     // Test common types to avoid struct enumerator boxing
     var localParameterCollectionsList = localParameterCollections as List<ParameterCollection>;
     if (localParameterCollectionsList != null)
     {
         foreach (var parameter in localParameterCollectionsList)
         {
             if (parameter != null)
             {
                 parameterCollections.Add(parameter);
             }
         }
     }
     else
     {
         var localParameterCollectionsArray = localParameterCollections as ParameterCollection[];
         if (localParameterCollectionsArray != null)
         {
             foreach (var parameter in localParameterCollectionsArray)
             {
                 if (parameter != null)
                 {
                     parameterCollections.Add(parameter);
                 }
             }
         }
         else
         {
             // Slow: enumerator will be boxed
             foreach (var parameter in localParameterCollections)
             {
                 if (parameter != null)
                 {
                     parameterCollections.Add(parameter);
                 }
             }
         }
     }
 }
Пример #12
0
        private void AssignRectangle(LightShadowMapTexture lightShadowMapTexture)
        {
            var size = lightShadowMapTexture.Size;

            // Try to fit the shadow map into an existing atlas
            ShadowMapAtlasTexture currentAtlas = null;

            foreach (var atlas in atlases)
            {
                if (atlas.TryInsert(size, size, lightShadowMapTexture.CascadeCount, (int index, ref Rectangle rectangle) => lightShadowMapTexture.SetRectangle(index, rectangle)))
                {
                    currentAtlas = atlas;
                    break;
                }
            }

            // Allocate a new atlas texture
            if (currentAtlas == null)
            {
                // For now, our policy is to allow only one shadow map, esp. because we can have only one shadow texture per lighting group
                // TODO: Group by DirectLightGroups, so that we can have different atlas per lighting group
                // TODO: Allow multiple textures per LightingGroup (using array of Texture?)
                if (atlases.Count == 0)
                {
                    // TODO: handle FilterType texture creation here
                    // TODO: This does not work for Omni lights
                    // TODO: Allow format selection externally

                    var texture = Texture.New2D(RenderSystem.GraphicsDevice, maximumTextureSize, maximumTextureSize, 1, PixelFormat.D32_Float, TextureFlags.DepthStencil | TextureFlags.ShaderResource);
                    currentAtlas = new ShadowMapAtlasTexture(texture, atlases.Count)
                    {
                        FilterType = lightShadowMapTexture.FilterType
                    };
                    atlases.Add(currentAtlas);

                    for (int i = 0; i < lightShadowMapTexture.CascadeCount; i++)
                    {
                        var rect = Rectangle.Empty;
                        currentAtlas.Insert(size, size, ref rect);
                        lightShadowMapTexture.SetRectangle(i, rect);
                    }
                }
            }

            // Make sure the atlas cleared (will be clear just once)
            lightShadowMapTexture.Atlas     = currentAtlas;
            lightShadowMapTexture.TextureId = (byte)(currentAtlas?.Id ?? 0);
        }
            public override void ApplyDrawParameters(RenderDrawContext context, int viewIndex, ParameterCollection parameters, ref BoundingBoxExt boundingBox)
            {
                // TODO THREADING: Make CurrentLights and lightData (thread-) local
                lock (applyLock)
                {
                    CurrentLights.Clear();
                    var lightRange = LightRanges[viewIndex];
                    for (int i = lightRange.Start; i < lightRange.End; ++i)
                    {
                        CurrentLights.Add(Lights[i]);
                    }

                    base.ApplyDrawParameters(context, viewIndex, parameters, ref boundingBox);

                    // TODO: Octree structure to select best lights quicker
                    var boundingBox2 = (BoundingBox)boundingBox;
                    for (int i = 0; i < CurrentLights.Count; i++)
                    {
                        var light = CurrentLights[i].Light;

                        if (light.BoundingBox.Intersects(ref boundingBox2))
                        {
                            var spotLight = (LightSpot)light.Type;
                            lightsData.Add(new SpotLightData
                            {
                                PositionWS  = light.Position,
                                DirectionWS = light.Direction,
                                AngleOffsetAndInvSquareRadius = new Vector3(spotLight.LightAngleScale, spotLight.LightAngleOffset, spotLight.InvSquareRange),
                                Color = light.Color,
                            });

                            // Did we reach max number of simultaneous lights?
                            // TODO: Still collect everything but sort by importance and remove the rest?
                            if (lightsData.Count >= LightCurrentCount)
                            {
                                break;
                            }
                        }
                    }

                    parameters.Set(countKey, lightsData.Count);
                    parameters.Set(lightsKey, lightsData.Count, ref lightsData.Items[0]);
                    lightsData.Clear();
                }
            }
Пример #14
0
        protected override void DrawCore(RenderContext context, RenderItemCollection renderItemList, int fromIndex, int toIndex)
        {
            if (dynamicEffectCompiler == null)
            {
                throw new InvalidOperationException("This instance is not correctly initialized (no EffectName)");
            }

            // Get all meshes from render models
            meshesToRender.Clear();
            for (int i = fromIndex; i <= toIndex; i++)
            {
                meshesToRender.Add((RenderMesh)renderItemList[i].DrawContext);
            }

            // Slow path there is a callback
            if (Callbacks.UpdateMeshes != null)
            {
                Callbacks.UpdateMeshes(context, ref meshesToRender);
            }

            // Fetch callback on PreRenderGroup
            var preRenderMesh = Callbacks.PreRenderMesh;

            for (int i = 0; i < meshesToRender.Count; i++)
            {
                var renderMesh = meshesToRender[i];

                // If the EntityGroup is changing, call the callback to allow to plug specific parameters for this group
                if (preRenderMesh != null)
                {
                    preRenderMesh(context, renderMesh);
                }

                // Update Effect and mesh
                UpdateEffect(context, renderMesh, context.Parameters);

                // Draw the mesh
                renderMesh.Draw(context);
            }
        }
Пример #15
0
        /// <summary>
        /// Draw this effect mesh.
        /// </summary>
        public void Draw(RenderContext context)
        {
            // Retrieve effect parameters
            var graphicsDevice    = context.GraphicsDevice;
            var mesh              = Mesh;
            var currentRenderData = mesh.Draw;
            var material          = Material;
            var vao           = vertexArrayObject;
            var drawCount     = currentRenderData.DrawCount;
            var primitiveType = currentRenderData.PrimitiveType;

            parameters.Set(TransformationKeys.World, WorldMatrix);

            // TODO: We should clarify exactly how to override rasterizer states. Currently setup here on Context.Parameters to allow Material/ModelComponent overrides, but this is ugly
            // Apply rasterizer
            var rasterizer = RasterizerState;

            if (!ForceRasterizer && Material.CullMode.HasValue && Material.CullMode.Value != RasterizerState.Description.CullMode)
            {
                switch (Material.CullMode.Value)
                {
                case CullMode.Back:
                    rasterizer = graphicsDevice.RasterizerStates.CullBack;
                    break;

                case CullMode.Front:
                    rasterizer = graphicsDevice.RasterizerStates.CullFront;
                    break;

                case CullMode.None:
                    rasterizer = graphicsDevice.RasterizerStates.CullNone;
                    break;
                }
            }
            context.Parameters.Set(Effect.RasterizerStateKey, rasterizer);

            // Handle picking
            if (context.IsPicking()) // TODO move this code corresponding to picking outside of the runtime code!
            {
                parameters.Set(ModelComponentPickingShaderKeys.ModelComponentId, new Color4(RuntimeIdHelper.ToRuntimeId(RenderModel.ModelComponent)));
                parameters.Set(ModelComponentPickingShaderKeys.MeshId, new Color4(RenderModel.ModelComponent.Model.Meshes.IndexOf(Mesh)));
                parameters.Set(ModelComponentPickingShaderKeys.MaterialId, new Color4(Mesh.MaterialIndex));

                // Don't use the materials blend state on picking targets
                parameters.Set(Effect.BlendStateKey, null);
            }

            if (material != null && material.TessellationMethod != XenkoTessellationMethod.None)
            {
                var tessellationMethod = material.TessellationMethod;

                // adapt the primitive type and index buffer to the tessellation used
                if (tessellationMethod.PerformsAdjacentEdgeAverage())
                {
                    vao       = GetOrCreateVertexArrayObjectAEN(context);
                    drawCount = 12 / 3 * drawCount;
                }
                primitiveType = tessellationMethod.GetPrimitiveType();
            }

            //using (Profiler.Begin(ProfilingKeys.PrepareMesh))
            {
                // Order of application of parameters:
                // - RenderPass.Parameters
                // - ModelComponent.Parameters
                // - RenderMesh.Parameters (originally copied from mesh parameters)
                // The order is based on the granularity level of each element and how shared it can be. Material is heavily shared, a model contains many meshes. An renderMesh is unique.
                // TODO: really copy mesh parameters into renderMesh instead of just referencing the meshDraw parameters.

                //var modelComponent = RenderModel.ModelComponent;
                //var hasModelComponentParams = modelComponent != null && modelComponent.Parameters != null;

                //var materialParameters = material != null && material.Parameters != null ? material.Parameters : null;

                parameterCollections.Clear();

                parameterCollections.Add(context.Parameters);
                FillParameterCollections(ref parameterCollections);

                // Check if we need to recreate the EffectParameterCollectionGroup
                // TODO: We can improve performance by redesigning FillParameterCollections to avoid ArrayExtensions.ArraysReferenceEqual (or directly check the appropriate parameter collections)
                // This also happens in another place: DynamicEffectCompiler (we probably want to factorize it when doing additional optimizations)
                if (parameterCollectionGroup == null || parameterCollectionGroup.Effect != Effect || !ArrayExtensions.ArraysReferenceEqual(ref previousParameterCollections, ref parameterCollections))
                {
                    previousParameterCollections.Clear();
                    previousParameterCollections.AddRange(parameterCollections);
                    parameterCollectionGroup = new EffectParameterCollectionGroup(context.GraphicsDevice, Effect, previousParameterCollections.Count, previousParameterCollections.Items);
                }

                Effect.Apply(context.GraphicsDevice, parameterCollectionGroup, true);
            }

            //using (Profiler.Begin(ProfilingKeys.RenderMesh))
            {
                if (currentRenderData != null)
                {
                    graphicsDevice.SetVertexArrayObject(vao);

                    if (currentRenderData.IndexBuffer == null)
                    {
                        graphicsDevice.Draw(primitiveType, drawCount, currentRenderData.StartLocation);
                    }
                    else
                    {
                        graphicsDevice.DrawIndexed(primitiveType, drawCount, currentRenderData.StartLocation);
                    }
                }
            }
        }
Пример #16
0
        public override void FillParameterCollections(ref FastListStruct<ParameterCollection> parameterCollections)
        {
            var material = Material;
            if (material != null && material.Parameters != null)
            {
                parameterCollections.Add(material.Parameters);
            }

            if (RenderModel.ModelComponent.Parameters != null)
            {
                parameterCollections.Add(RenderModel.ModelComponent.Parameters);
            }

            // TODO: Should we add RenderMesh.Parameters before ModelComponent.Parameters to allow user overiddes at component level?
            parameterCollections.Add(parameters);
        }
Пример #17
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);

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

                if (!renderMesh.Enabled)
                {
                    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: CullingMode should be pluggable
                // TODO: This should not be necessary. Add proper bounding boxes to gizmos etc.
                if (CullingMode == CullingMode.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.UpdateMaterial();

                var list = renderMesh.HasTransparency ? transparentList : opaqueList;
                list.Add(new RenderItem(this, renderMesh, projectedZ));
            }
        }