/// <summary>
        /// 
        /// </summary>
        /// <param name="viewIndex"></param>
        /// <param name="renderView"></param>
        /// <param name="lightCount"></param>
        /// <returns>The number of lights accepted in <see cref="CurrentLights"/>.</returns>
        public virtual int AddView(int viewIndex, RenderView renderView, int lightCount)
        {
            LightRanges[viewIndex] = new LightRange(Lights.Count, Lights.Count + lightCount);
            LightCurrentCount = Math.Max(LightCurrentCount, ComputeLightCount(lightCount));

            return Math.Min(LightCurrentCount, lightCount);
        }
예제 #2
0
 public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
 {
     lock (drawLock)
     {
         DrawInternal(context, renderView, renderViewStage, startIndex, endIndex);
     }
 }
예제 #3
0
            /// <inheritdoc/>
            public override int AddView(int viewIndex, RenderView renderView, int lightCount)
            {
                base.AddView(viewIndex, renderView, lightCount);

                // We allow more lights than LightCurrentCount (they will be culled)
                return lightCount;
            }
예제 #4
0
 //private void ThreadProcUnsafe() {
 //   renderView1.Refresh();
 // }
 private void InitializeComponent()
 {
     this.button1 = new System.Windows.Forms.Button();
     this.renderView1 = new Project.RenderView();
     this.timeBox = new System.Windows.Forms.TextBox();
     this.SuspendLayout();
     //
     // button1
     //
     this.button1.Location = new System.Drawing.Point(377, 12);
     this.button1.Name = "button1";
     this.button1.Size = new System.Drawing.Size(95, 23);
     this.button1.TabIndex = 0;
     this.button1.Text = "Set parameter";
     this.button1.UseVisualStyleBackColor = true;
     this.button1.Click += new System.EventHandler(this.setupTimer);
     //
     // renderView1
     //
     this.renderView1.Location = new System.Drawing.Point(12, 53);
     this.renderView1.Name = "renderView1";
     this.renderView1.Size = new System.Drawing.Size(460, 305);
     this.renderView1.TabIndex = 2;
     this.renderView1.Text = "renderView1";
     //
     // timeBox
     //
     this.timeBox.Location = new System.Drawing.Point(12, 14);
     this.timeBox.Name = "timeBox";
     this.timeBox.Size = new System.Drawing.Size(359, 20);
     this.timeBox.TabIndex = 3;
     //
     // MainForm
     //
     this.ClientSize = new System.Drawing.Size(484, 370);
     this.Controls.Add(this.timeBox);
     this.Controls.Add(this.renderView1);
     this.Controls.Add(this.button1);
     this.Name = "MainForm";
     this.Text = "Project";
     this.ResumeLayout(false);
     this.PerformLayout();
 }
예제 #5
0
파일: GUI.cs 프로젝트: chartly/flood
        public GUI(string textureName, string defaultFontName, int defaultFontSize)
        {
            PlatformManager = new PlatformManager(CreateWxPlatformManager());

            Engine = new Engine(PlatformManager);
            Engine.Init();

            // Search for the location of the main assets folder.
            string assetsPath;
            if (!SearchForAssetsDirectory(out assetsPath))
                throw new Exception("Editor assets were not found");

            Archive = new ArchiveVirtual();
            Archive.MountDirectories(assetsPath, Allocator.GetHeap());

            ResourceManager = Engine.ResourceManager;
            ResourceManager.Archive = Archive;

            WindowManager = Engine.WindowManager;

            MainWindow = CreateWindow();
            var context = MainWindow.CreateContext(new RenderContextSettings());

            MainView = MainWindow.CreateView();
            MainView.ClearColor = Color.Red;

            MainWindow.MakeCurrent();
            context.Init();

            RenderDevice = Engine.RenderDevice;
            RenderDevice.ActiveView = MainView;

            var options = new ResourceLoadOptions {Name = textureName, AsynchronousLoad = false};
            var imageHandle = ResourceManager.LoadResource<Image>(options);
            if (imageHandle.Id == 0)
                return;

            Renderer = new GwenRenderer();
            Skin = new TexturedSkin(Renderer, imageHandle, new Flood.GUI.Font(defaultFontName, defaultFontSize));

            if (!Directory.Exists(StoredValuesDirectory))
                Directory.CreateDirectory(StoredValuesDirectory);
        }
예제 #6
0
        public override float ComputeScreenCoverage(RenderView renderView, Vector3 position, Vector3 direction)
        {
            // http://stackoverflow.com/questions/21648630/radius-of-projected-sphere-in-screen-space
            var targetPosition = new Vector4(position, 1.0f);
            Vector4 projectedTarget;
            Vector4.Transform(ref targetPosition, ref renderView.ViewProjection, out projectedTarget);

            var d = Math.Abs(projectedTarget.W) + 0.00001f;
            var r = Radius;

            // Handle correctly the case where the eye is inside the sphere
            if (d < r)
                return Math.Max(renderView.ViewSize.X, renderView.ViewSize.Y);

            var coTanFovBy2 = renderView.Projection.M22;
            var pr = r * coTanFovBy2 / (Math.Sqrt(d * d - r * r) + 0.00001f);

            // Size on screen
            return (float)pr * Math.Max(renderView.ViewSize.X, renderView.ViewSize.Y);
        }
    public ScrollBarRenderView(RenderView renderview)
        : base(2, 2, false)
    {
        this.renderview = renderview;
        Attach(renderview, 0, 1, 0, 1,
               AttachOptions.Expand | AttachOptions.Fill,
               AttachOptions.Expand | AttachOptions.Fill, 0, 0);

        Adjustment hadjustment = new Adjustment(0, -10, 10, 1, 2, 2);
        HScrollbar hscroll = new HScrollbar(hadjustment);
        Attach(hscroll, 0, 1, 1, 2,
                 AttachOptions.Expand | AttachOptions.Fill, 0, 0, 0);

        Adjustment vadjustment = new Adjustment(0, -10, 10, 1, 2, 2);
        VScrollbar vscroll = new VScrollbar(vadjustment);
        Attach(vscroll, 1, 2, 0, 1,
                 0, AttachOptions.Expand | AttachOptions.Fill, 0, 0);

        renderview.SetAdjustments(hadjustment, vadjustment);
    }
예제 #8
0
파일: EditorBase.cs 프로젝트: chartly/flood
        public EditorBase()
        {
            PlatformManager = new PlatformManager(CreateWxPlatformManager());

            Engine = new Engine(PlatformManager);
            Engine.Init();

            // Search for the location of the main assets folder.
            string assetsPath;
            if (!SearchForAssetsDirectory(out assetsPath))
                throw new Exception("Editor assets were not found");

            Archive = new ArchiveVirtual();
            Archive.MountDirectories(assetsPath, Allocator.GetHeap());

            ResourceManager = Engine.ResourceManager;
            ResourceManager.Archive = Archive;

            EditorWindow = new EditorWindow();

            WindowManager = Engine.WindowManager;

            MainWindow = CreateWindow();
            var context = MainWindow.CreateContext(new RenderContextSettings());

            MainView = MainWindow.CreateView();
            MainView.ClearColor = Color.Red;

            MainWindow.Idle += Update;
            MainWindow.Render += Render;
            MainWindow.TargetResize += Resize;
            MainWindow.Show(true);

            MainWindow.MakeCurrent();
            context.Init();

            RenderDevice = Engine.RenderDevice;
        }
예제 #9
0
        internal void Init(Flood.Window window, RenderDevice renderDevice,
            RenderContext renderContext)
        {
            nativeWindow = window;
            device = renderDevice;

            if (renderContext == null)
            {
                RenderContext = window.CreateContext(new RenderContextSettings());
                window.MakeCurrent();
                RenderContext.Init();
            }
            else
            {
                RenderContext = renderContext;
                nativeWindow.Context = RenderContext;
            }

            view = window.CreateView();

            window.Render += Render;
            window.TargetResize += Resize;
        }
        public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            var target = context.RenderContext.Tags.GetSafe(RenderFrame.Current);
            var graphicsDevice = context.GraphicsDevice;
            var destination = new RectangleF(0, 0, 1, 1);

            for (int index = startIndex; index < endIndex; index++)
            {
                var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode;
                var renderNode = GetRenderNode(renderNodeReference);
                var renderBackground = (RenderBackground)renderNode.RenderObject;
                var texture = renderBackground.Texture;
                
                var imageBufferMinRatio = Math.Min(texture.ViewWidth / (float)target.Width, texture.ViewHeight / (float)target.Height);
                var sourceSize = new Vector2(target.Width * imageBufferMinRatio, target.Height * imageBufferMinRatio);
                var source = new RectangleF((texture.ViewWidth - sourceSize.X) / 2, (texture.ViewHeight - sourceSize.Y) / 2, sourceSize.X, sourceSize.Y);

                // TODO GRAPHICS REFACTOR: Disable depth once we sort properly
                spriteBatch.Begin(context.GraphicsContext, SpriteSortMode.FrontToBack, BlendStates.Opaque, graphicsDevice.SamplerStates.LinearClamp, DepthStencilStates.DepthRead, null, backgroundEffect);
                spriteBatch.Parameters.Set(BackgroundEffectKeys.Intensity, renderBackground.Intensity);
                spriteBatch.Draw(texture, destination, source, Color.White, 0, Vector2.Zero, layerDepth: -0.5f);
                spriteBatch.End();
            }
        }
예제 #11
0
        public RenderView CollectViews(VoxelStorageContext context, RenderContext RenderContext, RenderView view)
        {
            if (RenderMethod == RenderMethods.GeometryShader)
            {
                float  maxRes      = Math.Max(ClipMapResolution.X, Math.Max(ClipMapResolution.Y, ClipMapResolution.Z));
                Matrix aspectScale = Matrix.Scaling(ClipMapResolution / maxRes);
                view.Projection    *= aspectScale;
                view.ViewProjection = view.View * view.Projection;

                view.ViewSize = new Vector2(maxRes * 8, maxRes * 8);// * 8 improves shadow quality drastically, TODO: maybe should be configurable?
                RenderContext.RenderSystem.Views.Add(view);
                RenderContext.VisibilityGroup.TryCollect(view);
                return(view);
            }
            return(null);
        }
예제 #12
0
 public LightComponentKey(LightComponent lightComponent, RenderView renderView)
 {
     LightComponent = lightComponent;
     RenderView     = renderView;
 }
        private void UpdateFrustum(RenderView renderView)
        {
            var projectionToView = renderView.Projection;
            projectionToView.Invert();

            // Compute frustum-dependent variables (common for all shadow maps)
            var projectionToWorld = renderView.ViewProjection;
            projectionToWorld.Invert();

            // Transform Frustum corners in World Space (8 points) - algorithm is valid only if the view matrix does not do any kind of scale/shear transformation
            for (int i = 0; i < 8; ++i)
            {
                Vector3.TransformCoordinate(ref FrustumBasePoints[i], ref projectionToWorld, out frustumCornersWS[i]);
                Vector3.TransformCoordinate(ref FrustumBasePoints[i], ref projectionToView, out frustumCornersVS[i]);
            }
        }
        /// <inheritdoc/>
        public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            var commandList = context.CommandList;

            // TODO: PerView data
            Matrix viewInverse;

            Matrix.Invert(ref renderView.View, out viewInverse);

            Array.Resize(ref descriptorSets, EffectDescriptorSetSlotCount);

            for (var index = startIndex; index < endIndex; index++)
            {
                var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode;
                var renderNode          = GetRenderNode(renderNodeReference);

                var renderParticleEmitter = (RenderParticleEmitter)renderNode.RenderObject;
                if (renderParticleEmitter.ParticleEmitter.VertexBuilder.ResourceContext == null)
                {
                    continue;
                }

                // Generate vertices
                // TODO: Just just unmap/barrier here
                renderParticleEmitter.ParticleEmitter.BuildVertexBuffer(context.CommandList, ref viewInverse);

                // Get effect
                var renderEffect = renderNode.RenderEffect;
                if (renderEffect.Effect == null)
                {
                    continue;
                }

                // TODO GRAPHICS REFACTOR: Extract data
                var particleSystemComponent = renderParticleEmitter.RenderParticleSystem.ParticleSystemComponent;
                var particleSystem          = particleSystemComponent.ParticleSystem;
                var vertexBuilder           = renderParticleEmitter.ParticleEmitter.VertexBuilder;

                // Bind VB
                var vertexBuffer = vertexBuilder.ResourceContext.VertexBuffer;
                var indexBuffer  = vertexBuilder.ResourceContext.IndexBuffer;
                commandList.SetVertexBuffer(0, vertexBuffer.Buffer, vertexBuffer.Offset, vertexBuffer.Stride);
                commandList.SetIndexBuffer(indexBuffer.Buffer, indexBuffer.Offset, indexBuffer.Is32Bit);

                var resourceGroupOffset = ComputeResourceGroupOffset(renderNodeReference);

                // Update cbuffer
                renderEffect.Reflection.BufferUploader.Apply(context.CommandList, ResourceGroupPool, resourceGroupOffset);

                // Bind descriptor sets
                for (int i = 0; i < descriptorSets.Length; ++i)
                {
                    var resourceGroup = ResourceGroupPool[resourceGroupOffset++];
                    if (resourceGroup != null)
                    {
                        descriptorSets[i] = resourceGroup.DescriptorSet;
                    }
                }

                commandList.SetPipelineState(renderEffect.PipelineState);
                commandList.SetDescriptorSets(0, descriptorSets);

                commandList.DrawIndexed(vertexBuilder.LivingQuads * vertexBuilder.IndicesPerQuad, vertexBuilder.ResourceContext.IndexBufferPosition);
            }
        }
예제 #15
0
        private Vector2 ComputeCascadeSplits(RenderContext context, RenderView sourceView, ref LightShadowMapTexture lightShadowMap)
        {
            var shadow = (LightDirectionalShadowMap)lightShadowMap.Shadow;

            var cameraNear  = sourceView.NearClipPlane;
            var cameraFar   = sourceView.FarClipPlane;
            var cameraRange = cameraFar - cameraNear;

            var minDistance = cameraNear + LightDirectionalShadowMap.DepthRangeParameters.DefaultMinDistance;
            var maxDistance = cameraNear + LightDirectionalShadowMap.DepthRangeParameters.DefaultMaxDistance;

            if (shadow.DepthRange.IsAutomatic)
            {
                minDistance = Math.Max(sourceView.MinimumDistance, cameraNear);
                maxDistance = Math.Max(sourceView.MaximumDistance, minDistance);

                if (lightShadowMap.CurrentMinDistance <= 0)
                {
                    lightShadowMap.CurrentMinDistance = minDistance;
                }

                if (lightShadowMap.CurrentMaxDistance <= 0)
                {
                    lightShadowMap.CurrentMaxDistance = maxDistance;
                }

                // Increase the maximum depth in small logarithmic steps, decrease it in larger logarithmic steps
                var threshold = maxDistance > lightShadowMap.CurrentMaxDistance ? DepthIncreaseThreshold : DepthDecreaseThreshold;
                maxDistance = lightShadowMap.CurrentMaxDistance = LogCeiling(maxDistance / lightShadowMap.CurrentMaxDistance, threshold) * lightShadowMap.CurrentMaxDistance;

                // Increase/decrease the distance between maximum and minimum depth in small/large logarithmic steps
                var range        = maxDistance - minDistance;
                var currentRange = lightShadowMap.CurrentMaxDistance - lightShadowMap.CurrentMinDistance;
                threshold   = range > currentRange ? DepthIncreaseThreshold : DepthDecreaseThreshold;
                minDistance = maxDistance - LogCeiling(range / currentRange, threshold) * currentRange;
                minDistance = lightShadowMap.CurrentMinDistance = Math.Max(minDistance, cameraNear);
            }
            else
            {
                minDistance = cameraNear + shadow.DepthRange.ManualMinDistance;
                maxDistance = cameraNear + shadow.DepthRange.ManualMaxDistance;
            }

            var manualPartitionMode      = shadow.PartitionMode as LightDirectionalShadowMap.PartitionManual;
            var logarithmicPartitionMode = shadow.PartitionMode as LightDirectionalShadowMap.PartitionLogarithmic;

            if (logarithmicPartitionMode != null)
            {
                var minZ = minDistance;
                var maxZ = maxDistance;

                var range    = maxZ - minZ;
                var ratio    = maxZ / minZ;
                var logRatio = MathUtil.Clamp(1.0f - logarithmicPartitionMode.PSSMFactor, 0.0f, 1.0f);

                for (int cascadeLevel = 0; cascadeLevel < lightShadowMap.CascadeCount; ++cascadeLevel)
                {
                    // Compute cascade split (between znear and zfar)
                    float distrib  = (float)(cascadeLevel + 1) / lightShadowMap.CascadeCount;
                    float logZ     = (float)(minZ * Math.Pow(ratio, distrib));
                    float uniformZ = minZ + range * distrib;
                    float distance = MathUtil.Lerp(uniformZ, logZ, logRatio);
                    cascadeSplitRatios[cascadeLevel] = distance;
                }
            }
            else if (manualPartitionMode != null)
            {
                if (lightShadowMap.CascadeCount == 1)
                {
                    cascadeSplitRatios[0] = minDistance + manualPartitionMode.SplitDistance1 * maxDistance;
                }
                else if (lightShadowMap.CascadeCount == 2)
                {
                    cascadeSplitRatios[0] = minDistance + manualPartitionMode.SplitDistance1 * maxDistance;
                    cascadeSplitRatios[1] = minDistance + manualPartitionMode.SplitDistance3 * maxDistance;
                }
                else if (lightShadowMap.CascadeCount == 4)
                {
                    cascadeSplitRatios[0] = minDistance + manualPartitionMode.SplitDistance0 * maxDistance;
                    cascadeSplitRatios[1] = minDistance + manualPartitionMode.SplitDistance1 * maxDistance;
                    cascadeSplitRatios[2] = minDistance + manualPartitionMode.SplitDistance2 * maxDistance;
                    cascadeSplitRatios[3] = minDistance + manualPartitionMode.SplitDistance3 * maxDistance;
                }
            }

            // Convert distance splits to ratios cascade in the range [0, 1]
            for (int i = 0; i < cascadeSplitRatios.Length; i++)
            {
                cascadeSplitRatios[i] = (cascadeSplitRatios[i] - cameraNear) / cameraRange;
            }

            return(new Vector2(minDistance, maxDistance));
        }
예제 #16
0
        public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            if (renderMeshesToGenerateAEN.Count > 0)
            {
                var tessellationStates = RootRenderFeature.RenderData.GetData(tessellationStateKey);

                foreach (var renderMesh in renderMeshesToGenerateAEN)
                {
                    var tessellationState = tessellationStates[renderMesh.StaticObjectNode];
                    if (tessellationState.GeneratedIndicesAEN != null)
                        continue;

                    var tessellationMeshDraw = tessellationState.MeshDraw;

                    var indicesAEN = IndexExtensions.GenerateIndexBufferAEN(tessellationMeshDraw.IndexBuffer, tessellationMeshDraw.VertexBuffers[0], context.CommandList);
                    tessellationState.GeneratedIndicesAEN = Buffer.Index.New(Context.GraphicsDevice, indicesAEN);
                    tessellationMeshDraw.IndexBuffer = new IndexBufferBinding(tessellationState.GeneratedIndicesAEN, true, tessellationMeshDraw.IndexBuffer.Count*12/3);
                    tessellationMeshDraw.DrawCount = 12/3*tessellationMeshDraw.DrawCount;
                }

                renderMeshesToGenerateAEN.Clear();
            }
        }
        public override void Collect(RenderContext context, RenderView sourceView, LightShadowMapTexture lightShadowMap)
        {
            var shaderData = shaderDataPool.Add();

            lightShadowMap.ShaderData  = shaderData;
            shaderData.Texture         = lightShadowMap.Atlas.Texture;
            shaderData.DepthBias       = lightShadowMap.Light.Shadow.BiasParameters.DepthBias;
            shaderData.OffsetScale     = lightShadowMap.Light.Shadow.BiasParameters.NormalOffsetScale;
            shaderData.DepthParameters = GetShadowMapDepthParameters(lightShadowMap);

            var clippingPlanes = GetLightClippingPlanes((LightPoint)lightShadowMap.Light);

            var textureMapSize = lightShadowMap.GetRectangle(0).Size;

            // Calculate angle of the projection with border pixels taken into account to allow filtering
            float halfMapSize = (float)textureMapSize.Width / 2;
            float halfFov     = (float)Math.Atan((halfMapSize + BorderPixels) / halfMapSize);

            shaderData.Projection = Matrix.PerspectiveFovRH(halfFov * 2, 1.0f, clippingPlanes.X, clippingPlanes.Y);

            Vector2 atlasSize = new Vector2(lightShadowMap.Atlas.Width, lightShadowMap.Atlas.Height);

            for (int i = 0; i < 6; i++)
            {
                Rectangle faceRectangle = lightShadowMap.GetRectangle(i);
                shaderData.FaceOffsets[i] = new Vector2(faceRectangle.Left + BorderPixels, faceRectangle.Top + BorderPixels) / atlasSize;

                // Compute view parameters
                GetViewParameters(lightShadowMap, i, out shaderData.View[i]);

                // Allocate shadow render view
                var shadowRenderView = CreateRenderView();
                shadowRenderView.RenderView       = sourceView;
                shadowRenderView.ShadowMapTexture = lightShadowMap;
                shadowRenderView.Rectangle        = faceRectangle;
                shadowRenderView.ViewSize         = new Vector2(faceRectangle.Width, faceRectangle.Height);

                shadowRenderView.NearClipPlane = clippingPlanes.X;
                shadowRenderView.FarClipPlane  = clippingPlanes.Y;

                shadowRenderView.View       = shaderData.View[i];
                shadowRenderView.Projection = shaderData.Projection;
                Matrix.Multiply(ref shadowRenderView.View, ref shadowRenderView.Projection, out shadowRenderView.ViewProjection);

                // Create projection matrix with adjustment
                var textureCoords = new Vector4(
                    (float)shadowRenderView.Rectangle.Left / lightShadowMap.Atlas.Width,
                    (float)shadowRenderView.Rectangle.Top / lightShadowMap.Atlas.Height,
                    (float)shadowRenderView.Rectangle.Right / lightShadowMap.Atlas.Width,
                    (float)shadowRenderView.Rectangle.Bottom / lightShadowMap.Atlas.Height);
                float leftX   = (float)lightShadowMap.Size / lightShadowMap.Atlas.Width * 0.5f;
                float leftY   = (float)lightShadowMap.Size / lightShadowMap.Atlas.Height * 0.5f;
                float centerX = 0.5f * (textureCoords.X + textureCoords.Z);
                float centerY = 0.5f * (textureCoords.Y + textureCoords.W);

                var projectionToShadow = Matrix.Scaling(leftX, -leftY, 1.0f) * Matrix.Translation(centerX, centerY, 0.0f);
                Matrix.Multiply(ref shadowRenderView.ViewProjection, ref projectionToShadow, out shaderData.WorldToShadow[i]);

                shadowRenderView.VisiblityIgnoreDepthPlanes = false;

                // Add the render view for the current frame
                context.RenderSystem.Views.Add(shadowRenderView);
            }
        }
예제 #18
0
        public void Render(VoxelStorageContext storageContext, RenderDrawContext drawContext, RenderView view)
        {
            RenderView voxelizationView = view;
            Int2       ViewSize         = VoxelizationViewSizes[view];

            if (VoxelUtils.DisposeTextureBySpecs(MSAARenderTarget, new Vector3(ViewSize.X, ViewSize.Y, 1), PixelFormat.R8G8B8A8_UNorm, MultisampleCount))
            {
                MSAARenderTarget = Texture.New(storageContext.device, TextureDescription.New2D(ViewSize.X, ViewSize.Y, new MipMapCount(false), PixelFormat.R8G8B8A8_UNorm, TextureFlags.RenderTarget, 1, GraphicsResourceUsage.Default, MultisampleCount), null);
            }

            drawContext.CommandList.ResetTargets();
            if (MSAARenderTarget != null)
            {
                drawContext.CommandList.SetRenderTarget(null, MSAARenderTarget);
            }

            var renderSystem = drawContext.RenderContext.RenderSystem;

            drawContext.CommandList.SetViewport(new Viewport(0, 0, ViewSize.X, ViewSize.Y));

            renderSystem.Draw(drawContext, voxelizationView, renderSystem.RenderStages[voxelizationView.RenderStages[0].Index]);
            drawContext.CommandList.ResetTargets();
        }
예제 #19
0
        public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            base.Draw(context, renderView, renderViewStage, startIndex, endIndex);

            Matrix viewInverse;

            Matrix.Invert(ref renderView.View, out viewInverse);

            BlendStateDescription?       previousBlendState        = null;
            DepthStencilStateDescription?previousDepthStencilState = null;
            EffectInstance previousEffect = null;

            //TODO string comparison ...?
            var isPicking = renderViewStage.RenderStage.Name == "Picking";

            var device = RenderSystem.GraphicsDevice;

            bool hasBegin = false;

            for (var index = startIndex; index < endIndex; index++)
            {
                var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode;
                var renderNode          = GetRenderNode(renderNodeReference);

                var renderSprite = (RenderSprite)renderNode.RenderObject;

                var spriteComp        = renderSprite.SpriteComponent;
                var transfoComp       = renderSprite.TransformComponent;
                var depthStencilState = renderSprite.SpriteComponent.IgnoreDepth ? DepthStencilStates.None : DepthStencilStates.Default;

                var sprite = spriteComp.CurrentSprite;
                if (sprite == null)
                {
                    continue;
                }

                // TODO: this should probably be moved to Prepare()
                // 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(renderSprite.TransformComponent.WorldMatrix.TranslationVector, 1.0f);

                Vector4 projectedPosition;
                Vector4.Transform(ref worldPosition, ref renderView.ViewProjection, out projectedPosition);
                var projectedZ = projectedPosition.Z / projectedPosition.W;

                // Update the sprite batch
                var blendState    = isPicking ? BlendStates.Default : sprite.IsTransparent ? (spriteComp.PremultipliedAlpha ? BlendStates.AlphaBlend : BlendStates.NonPremultiplied) : BlendStates.Opaque;
                var currentEffect = isPicking ? GetOrCreatePickingSpriteEffect() : null; // TODO remove this code when material are available
                if (previousEffect != currentEffect || blendState != previousBlendState || depthStencilState != previousDepthStencilState)
                {
                    if (hasBegin)
                    {
                        sprite3DBatch.End();
                    }
                    sprite3DBatch.Begin(context.GraphicsContext, renderView.ViewProjection, SpriteSortMode.Deferred, blendState, null, depthStencilState, RasterizerStates.CullNone, currentEffect);
                    hasBegin = true;
                }
                previousEffect            = currentEffect;
                previousBlendState        = blendState;
                previousDepthStencilState = depthStencilState;

                var sourceRegion = sprite.Region;
                var texture      = sprite.Texture;
                var color        = spriteComp.Color;
                if (isPicking) // TODO move this code corresponding to picking out of the runtime code.
                {
                    var compId = RuntimeIdHelper.ToRuntimeId(spriteComp);
                    color = new Color4(compId);
                }

                // skip the sprite if no texture is set.
                if (texture == null)
                {
                    continue;
                }

                // determine the element world matrix depending on the type of sprite
                var worldMatrix = transfoComp.WorldMatrix;
                if (spriteComp.SpriteType == SpriteType.Billboard)
                {
                    worldMatrix = viewInverse;

                    // remove scale of the camera
                    worldMatrix.Row1 /= ((Vector3)viewInverse.Row1).Length();
                    worldMatrix.Row2 /= ((Vector3)viewInverse.Row2).Length();

                    // set the scale of the object
                    worldMatrix.Row1 *= ((Vector3)transfoComp.WorldMatrix.Row1).Length();
                    worldMatrix.Row2 *= ((Vector3)transfoComp.WorldMatrix.Row2).Length();

                    // set the position
                    worldMatrix.TranslationVector = transfoComp.WorldMatrix.TranslationVector;
                }

                // calculate normalized position of the center of the sprite (takes into account the possible rotation of the image)
                var normalizedCenter = new Vector2(sprite.Center.X / sourceRegion.Width - 0.5f, 0.5f - sprite.Center.Y / sourceRegion.Height);
                if (sprite.Orientation == ImageOrientation.Rotated90)
                {
                    var oldCenterX = normalizedCenter.X;
                    normalizedCenter.X = -normalizedCenter.Y;
                    normalizedCenter.Y = oldCenterX;
                }
                // apply the offset due to the center of the sprite
                var centerOffset = Vector2.Modulate(normalizedCenter, sprite.SizeInternal);
                worldMatrix.M41 -= centerOffset.X * worldMatrix.M11 + centerOffset.Y * worldMatrix.M21;
                worldMatrix.M42 -= centerOffset.X * worldMatrix.M12 + centerOffset.Y * worldMatrix.M22;
                worldMatrix.M43 -= centerOffset.X * worldMatrix.M13 + centerOffset.Y * worldMatrix.M23;

                // draw the sprite
                sprite3DBatch.Draw(texture, ref worldMatrix, ref sourceRegion, ref sprite.SizeInternal, ref color, sprite.Orientation, SwizzleMode.None, projectedZ);
            }

            if (hasBegin)
            {
                sprite3DBatch.End();
            }
        }
예제 #20
0
 public CameraRotateSceneTool(RenderView renderView)
 {
     this.renderView = renderView;
 }
예제 #21
0
        public void Render(VoxelStorageContext context, RenderDrawContext drawContext, RenderView view)
        {
            var renderSystem = drawContext.RenderContext.RenderSystem;

            var resolution = ClipMapResolution;


            float maxResolution = Math.Max(Math.Max(resolution.X, resolution.Y), resolution.Z);

            drawContext.CommandList.SetViewport(new Viewport(0, 0, (int)maxResolution, (int)maxResolution));

            if (RenderMethod == RenderMethods.GeometryShader)
            {
                renderSystem.Draw(drawContext, view, renderSystem.RenderStages[view.RenderStages[0].Index]);
            }
        }
예제 #22
0
 public CameraZoomSceneTool(RenderView renderView)
 {
     this.renderView = renderView;
 }
예제 #23
0
 public EntityMoveSceneTool(RenderView renderView, System.Collections.Generic.List <Entity> selectedEntities)
 {
     this.renderView       = renderView;
     this.selectedEntities = selectedEntities;
 }
예제 #24
0
 public CameraOrbitSceneTool(RenderView renderView)
 {
     this.renderView = renderView;
 }
        public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            var commandList = context.CommandList;

            var descriptorSets = new DescriptorSet[EffectDescriptorSetSlotCount];

            for (int index = startIndex; index < endIndex; index++)
            {
                var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode;
                var renderNode = GetRenderNode(renderNodeReference);

                // Get effect
                // TODO: Use real effect slot
                var renderEffect = renderNode.RenderEffect;
                if (renderEffect.Effect == null)
                    continue;

                commandList.SetPipelineState(renderEffect.PipelineState);

                var resourceGroupOffset = ComputeResourceGroupOffset(renderNodeReference);
                renderEffect.Reflection.BufferUploader.Apply(context.CommandList, ResourceGroupPool, resourceGroupOffset);

                // Bind descriptor sets
                for (int i = 0; i < descriptorSets.Length; ++i)
                {
                    var resourceGroup = ResourceGroupPool[resourceGroupOffset++];
                    if (resourceGroup != null)
                        descriptorSets[i] = resourceGroup.DescriptorSet;
                }

                commandList.SetDescriptorSets(0, descriptorSets);

                commandList.DrawQuad();
            }
        }
        public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            base.Draw(context, renderView, renderViewStage, startIndex, endIndex);

            var currentRenderFrame = context.RenderContext.Tags.Get(RenderFrame.Current);

            var uiProcessor = renderView.SceneInstance.GetProcessor <UIRenderProcessor>();

            if (uiProcessor == null)
            {
                return;
            }

            //foreach (var uiRoot in uiProcessor.UIRoots)
            //{
            //    // Perform culling on group and accept
            //    if (!renderView.SceneCameraRenderer.CullingMask.Contains(uiRoot.UIComponent.Entity.Group))
            //        continue;

            //    // skips empty UI elements
            //    if (uiRoot.UIComponent.RootElement == null)
            //        continue;

            //    // Project the position
            //    // TODO: This code is duplicated from SpriteComponent -> unify it at higher level?
            //    var worldPosition = new Vector4(uiRoot.TransformComponent.WorldMatrix.TranslationVector, 1.0f);

            //    float projectedZ;
            //    if (uiRoot.UIComponent.IsFullScreen)
            //    {
            //        projectedZ = -uiRoot.TransformComponent.WorldMatrix.M43;
            //    }
            //    else
            //    {
            //        Vector4 projectedPosition;
            //        var cameraComponent = renderView.Camera;
            //        if (cameraComponent == null)
            //            continue;

            //        Vector4.Transform(ref worldPosition, ref cameraComponent.ViewProjectionMatrix, out projectedPosition);
            //        projectedZ = projectedPosition.Z / projectedPosition.W;
            //    }

            //    transparentList.Add(new RenderItem(this, uiRoot, projectedZ));
            //}

            // build the list of the UI elements to render
            uiElementStates.Clear();
            for (var index = startIndex; index < endIndex; index++)
            {
                var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode;
                var renderNode          = GetRenderNode(renderNodeReference);
                var renderElement       = (RenderUIElement)renderNode.RenderObject;

                uiElementStates.Add(renderElement);
            }

            // evaluate the current draw time (game instance is null for thumbnails)
            var drawTime = game != null ? game.DrawTime : new GameTime();

            // update the rendering context
            renderingContext.GraphicsContext = context.GraphicsContext;
            renderingContext.Time            = drawTime;
            renderingContext.RenderTarget    = currentRenderFrame.RenderTargets[0]; // TODO: avoid hardcoded index 0

            // cache the ratio between viewport and target.
            var viewportSize = context.CommandList.Viewport.Size;

            viewportTargetRatio = new Vector2(viewportSize.X / renderingContext.RenderTarget.Width, viewportSize.Y / renderingContext.RenderTarget.Height);

            // compact all the pointer events that happened since last frame to avoid performing useless hit tests.
            CompactPointerEvents();

            // allocate temporary graphics resources if needed
            Texture scopedDepthBuffer = null;

            foreach (var uiElement in uiElementStates)
            {
                if (uiElement.UIComponent.IsFullScreen)
                {
                    var renderTarget = renderingContext.RenderTarget;
                    var description  = TextureDescription.New2D(renderTarget.Width, renderTarget.Height, PixelFormat.D24_UNorm_S8_UInt, TextureFlags.DepthStencil);
                    scopedDepthBuffer = context.RenderContext.Allocator.GetTemporaryTexture(description);
                    break;
                }
            }

            // render the UI elements of all the entities
            foreach (var uiElementState in uiElementStates)
            {
                var uiComponent = uiElementState.UIComponent;
                var rootElement = uiComponent.RootElement;
                if (rootElement == null)
                {
                    continue;
                }

                var updatableRootElement = (IUIElementUpdate)rootElement;

                // calculate the size of the virtual resolution depending on target size (UI canvas)
                var virtualResolution = uiComponent.Resolution;
                var targetSize        = new Vector2(renderingContext.RenderTarget.Width, renderingContext.RenderTarget.Height);
                if (uiComponent.IsFullScreen)
                {
                    // update the virtual resolution of the renderer
                    if (uiComponent.ResolutionStretch == ResolutionStretch.FixedWidthAdaptableHeight)
                    {
                        virtualResolution.Y = virtualResolution.X * targetSize.Y / targetSize.X;
                    }
                    if (uiComponent.ResolutionStretch == ResolutionStretch.FixedHeightAdaptableWidth)
                    {
                        virtualResolution.X = virtualResolution.Y * targetSize.X / targetSize.Y;
                    }
                }

                // Update the view parameters
                if (uiComponent.IsFullScreen)
                {
                    viewParameters.Update(uiComponent.Entity, virtualResolution);
                }
                else
                {
                    var cameraComponent = context.RenderContext.Tags.Get(CameraComponentRendererExtensions.Current);
                    if (cameraComponent != null)
                    {
                        viewParameters.Update(uiComponent.Entity, cameraComponent);
                    }
                }

                // Analyze the input and trigger the UI element touch and key events
                // Note: this is done before measuring/arranging/drawing the element in order to avoid one frame latency on clicks.
                //       But by doing so the world matrices taken for hit test are the ones calculated during last frame.
                using (Profiler.Begin(UIProfilerKeys.TouchEventsUpdate))
                {
                    foreach (var uiState in uiElementStates)
                    {
                        if (uiState.UIComponent.RootElement == null)
                        {
                            continue;
                        }

                        UpdateMouseOver(uiState);
                        UpdateTouchEvents(uiState, drawTime);
                    }
                }

                // update the rendering context values specific to this element
                renderingContext.Resolution           = virtualResolution;
                renderingContext.ViewMatrix           = viewParameters.ViewMatrix;
                renderingContext.ProjectionMatrix     = viewParameters.ProjectionMatrix;
                renderingContext.ViewProjectionMatrix = viewParameters.ViewProjectionMatrix;
                renderingContext.DepthStencilBuffer   = uiComponent.IsFullScreen ? scopedDepthBuffer : currentRenderFrame.DepthStencil;
                renderingContext.ShouldSnapText       = uiComponent.SnapText;

                // calculate an estimate of the UI real size by projecting the element virtual resolution on the screen
                var virtualOrigin            = viewParameters.ViewProjectionMatrix.Row4;
                var virtualWidth             = new Vector4(virtualResolution.X / 2, 0, 0, 1);
                var virtualHeight            = new Vector4(0, virtualResolution.Y / 2, 0, 1);
                var transformedVirtualWidth  = Vector4.Zero;
                var transformedVirtualHeight = Vector4.Zero;
                for (int i = 0; i < 4; i++)
                {
                    transformedVirtualWidth[i]  = virtualWidth[0] * viewParameters.ViewProjectionMatrix[0 + i] + viewParameters.ViewProjectionMatrix[12 + i];
                    transformedVirtualHeight[i] = virtualHeight[1] * viewParameters.ViewProjectionMatrix[4 + i] + viewParameters.ViewProjectionMatrix[12 + i];
                }
                var projectedOrigin        = virtualOrigin.XY() / virtualOrigin.W;
                var projectedVirtualWidth  = viewportSize * (transformedVirtualWidth.XY() / transformedVirtualWidth.W - projectedOrigin);
                var projectedVirtualHeight = viewportSize * (transformedVirtualHeight.XY() / transformedVirtualHeight.W - projectedOrigin);

                // set default resource dictionary
                rootElement.ResourceDictionary = uiSystem.DefaultResourceDictionary;

                // update layouting context.
                layoutingContext.VirtualResolution          = virtualResolution;
                layoutingContext.RealResolution             = viewportSize;
                layoutingContext.RealVirtualResolutionRatio = new Vector2(projectedVirtualWidth.Length() / virtualResolution.X, projectedVirtualHeight.Length() / virtualResolution.Y);
                rootElement.LayoutingContext = layoutingContext;

                // perform the time-based updates of the UI element
                updatableRootElement.Update(drawTime);

                // update the UI element disposition
                rootElement.Measure(virtualResolution);
                rootElement.Arrange(virtualResolution, false);

                // update the UI element hierarchical properties
                var rootMatrix = Matrix.Translation(-virtualResolution / 2); // UI world is rotated of 180degrees along Ox
                updatableRootElement.UpdateWorldMatrix(ref rootMatrix, rootMatrix != uiElementState.LastRootMatrix);
                updatableRootElement.UpdateElementState(0);
                uiElementState.LastRootMatrix = rootMatrix;

                // clear and set the Depth buffer as required
                if (uiComponent.IsFullScreen)
                {
                    context.CommandList.Clear(renderingContext.DepthStencilBuffer, DepthStencilClearOptions.DepthBuffer | DepthStencilClearOptions.Stencil);
                }
                context.CommandList.SetRenderTargetAndViewport(renderingContext.DepthStencilBuffer, renderingContext.RenderTarget);

                // start the image draw session
                renderingContext.StencilTestReferenceValue = 0;
                batch.Begin(context.GraphicsContext, ref viewParameters.ViewProjectionMatrix, BlendStates.AlphaBlend, uiSystem.KeepStencilValueState, renderingContext.StencilTestReferenceValue);

                // Render the UI elements in the final render target
                ReccursiveDrawWithClipping(context, rootElement);

                // end the image draw session
                batch.End();
            }

            // clear the list of compacted pointer events of time frame
            ClearPointerEvents();

            // revert the depth stencil buffer to the default value
            context.CommandList.SetRenderTargetsAndViewport(currentRenderFrame.DepthStencil, currentRenderFrame.RenderTargets);

            // Release scroped texture
            if (scopedDepthBuffer != null)
            {
                context.RenderContext.Allocator.ReleaseReference(scopedDepthBuffer);
            }
        }
예제 #27
0
        public override float ComputeScreenCoverage(RenderView renderView, Vector3 position, Vector3 direction)
        {
            // http://stackoverflow.com/questions/21648630/radius-of-projected-sphere-in-screen-space
            // Use a sphere at target point to compute the screen coverage. This is a very rough approximation.
            // We compute the sphere at target point where the size of light is the largest
            // TODO: Check if we can improve this calculation with a better model
            var targetPosition = new Vector4(position + direction * Range, 1.0f);
            Vector4 projectedTarget;
            Vector4.Transform(ref targetPosition, ref renderView.ViewProjection, out projectedTarget);

            var d = Math.Abs(projectedTarget.W) + 0.00001f;
            var r = Range * Math.Sin(MathUtil.DegreesToRadians(AngleOuter/2.0f));

            // Handle correctly the case where the eye is inside the sphere
            if (d < r)
                return Math.Max(renderView.ViewSize.X, renderView.ViewSize.Y);

            var coTanFovBy2 = renderView.Projection.M22;
            var pr = r * coTanFovBy2 / (Math.Sqrt(d * d - r * r) + 0.00001f);

            // Size on screen
            return (float)pr * Math.Max(renderView.ViewSize.X, renderView.ViewSize.Y);
        }
예제 #28
0
 public abstract void Collect(RenderContext context, RenderView sourceView, LightShadowMapTexture lightShadowMap);
예제 #29
0
 public void Render(VoxelStorageContext storageContext, RenderDrawContext drawContext, RenderView view)
 {
 }
예제 #30
0
        public virtual void Draw(RenderDrawContext drawContext, Shadows.IShadowMapRenderer ShadowMapRenderer)
        {
            if (renderVoxelVolumes == null || renderVoxelVolumes.Count == 0)
            {
                return;
            }

            if (drawContext.GraphicsDevice.Features.CurrentProfile < GraphicsProfile.Level_11_0)
            {
                return;
            }

            var context = drawContext;

            using (drawContext.PushRenderTargetsAndRestore())
            {
                // Draw all shadow views generated for the current view
                foreach (var processedVolumeKeyValue in renderVoxelVolumeData)
                {
                    var processedVolume = processedVolumeKeyValue.Value;
                    if (!processedVolume.Voxelize)
                    {
                        continue;
                    }

                    VoxelStorageContext storageContext = processedVolume.StorageContext;

                    using (drawContext.QueryManager.BeginProfile(Color.Black, PassesVoxelizationProfilingKey))
                    {
                        foreach (VoxelizationPass pass in processedVolume.passList.passes)
                        {
                            RenderView voxelizeRenderView = pass.view;

                            if (pass.requireShadows)
                            {
                                //Render Shadow Maps
                                RenderView oldView = drawContext.RenderContext.RenderView;

                                drawContext.RenderContext.RenderView = voxelizeRenderView;
                                ShadowMapRenderer.Draw(drawContext);
                                drawContext.RenderContext.RenderView = oldView;
                            }

                            //Render/Collect voxel fragments
                            using (drawContext.QueryManager.BeginProfile(Color.Black, FragmentVoxelizationProfilingKey))
                            {
                                using (drawContext.PushRenderTargetsAndRestore())
                                {
                                    pass.method.Render(storageContext, context, pass.view);
                                }
                            }
                        }
                        foreach (VoxelizationPass pass in processedVolume.passList.passes)
                        {
                            pass.method.Reset();
                        }
                    }

                    //Fill and write to voxel volume
                    using (drawContext.QueryManager.BeginProfile(Color.Black, BufferProcessingVoxelizationProfilingKey))
                    {
                        processedVolume.Storage.PostProcess(storageContext, context, processedVolume);
                    }

                    //Mipmap
                    using (drawContext.QueryManager.BeginProfile(Color.Black, MipmappingVoxelizationProfilingKey))
                    {
                        foreach (var attr in processedVolume.Attributes)
                        {
                            if (attr.Output)
                            {
                                attr.Attribute.PostProcess(context);
                            }
                        }
                    }
                }
            }
        }
예제 #31
0
        private void PrepareLightGroups(RenderDrawContext context, FastList <RenderView> renderViews, RenderView renderView, RenderViewLightData renderViewData, IShadowMapRenderer shadowMapRenderer, RenderGroup group)
        {
            var viewIndex = renderViews.IndexOf(renderView);

            foreach (var activeRenderer in renderViewData.ActiveRenderers)
            {
                // Find lights
                var lightCollection = activeRenderer.LightGroup.FindLightCollectionByGroup(group);

                // Indices of lights in lightCollection that need processing
                lightIndicesToProcess.Clear();
                for (int i = 0; i < lightCollection.Count; i++)
                {
                    lightIndicesToProcess.Add(i);
                }

                // Loop over all the renderers in order
                int rendererIndex = 0;
                foreach (var renderer in activeRenderer.Renderers)
                {
                    var processLightsParameters = new LightGroupRendererBase.ProcessLightsParameters
                    {
                        Context                   = context,
                        ViewIndex                 = viewIndex,
                        View                      = renderView,
                        Views                     = renderViews,
                        Renderers                 = activeRenderer.Renderers,
                        RendererIndex             = rendererIndex++,
                        LightCollection           = lightCollection,
                        LightIndices              = lightIndicesToProcess,
                        LightType                 = activeRenderer.LightGroup.LightType,
                        ShadowMapRenderer         = shadowMapRenderer,
                        ShadowMapTexturesPerLight = renderViewData.RenderLightsWithShadows,
                    };
                    renderer.ProcessLights(processLightsParameters);
                }
            }
        }
예제 #32
0
        private static void PrepareLightGroups(RenderDrawContext context, FastList <RenderView> renderViews, RenderView renderView, RenderViewLightData renderViewData, ShadowMapRenderer shadowMapRenderer, EntityGroup group)
        {
            foreach (var activeRenderer in renderViewData.ActiveRenderers)
            {
                // Find lights
                var lightRenderer   = activeRenderer.LightRenderer;
                var lightCollection = activeRenderer.LightGroup.FindLightCollectionByGroup(group);

                var processLightsParameters = new LightGroupRendererBase.ProcessLightsParameters
                {
                    Context                   = context,
                    ViewIndex                 = renderViewData.ViewIndex,
                    View                      = renderView,
                    Views                     = renderViews,
                    LightCollection           = lightCollection,
                    LightType                 = activeRenderer.LightGroup.LightType,
                    LightStart                = 0,
                    LightEnd                  = lightCollection.Count,
                    ShadowMapRenderer         = shadowMapRenderer,
                    ShadowMapTexturesPerLight = renderViewData.LightComponentsWithShadows,
                };

                lightRenderer.ProcessLights(processLightsParameters);
            }
        }
예제 #33
0
        public override void Collect(RenderContext context, RenderView sourceView, LightShadowMapTexture lightShadowMap)
        {
            var shadow = (LightDirectionalShadowMap)lightShadowMap.Shadow;

            // TODO: Min and Max distance can be auto-computed from readback from Z buffer

            Matrix.Invert(ref sourceView.View, out var viewToWorld);

            // Update the frustum infos
            UpdateFrustum(sourceView);

            // Computes the cascade splits
            var minMaxDistance = ComputeCascadeSplits(context, sourceView, ref lightShadowMap);
            var direction      = lightShadowMap.RenderLight.Direction;

            // Fake value
            // It will be setup by next loop
            Vector3 side        = Vector3.UnitX;
            Vector3 upDirection = Vector3.UnitX;

            // Select best Up vector
            // TODO: User preference?
            foreach (var vectorUp in VectorUps)
            {
                if (Math.Abs(Vector3.Dot(direction, vectorUp)) < (1.0 - 0.0001))
                {
                    side        = Vector3.Normalize(Vector3.Cross(vectorUp, direction));
                    upDirection = Vector3.Normalize(Vector3.Cross(direction, side));
                    break;
                }
            }

            int cascadeCount = lightShadowMap.CascadeCount;

            // Get new shader data from pool
            ShaderData shaderData;

            if (cascadeCount == 1)
            {
                shaderData = shaderDataPoolCascade1.Add();
            }
            else if (cascadeCount == 2)
            {
                shaderData = shaderDataPoolCascade2.Add();
            }
            else
            {
                shaderData = shaderDataPoolCascade4.Add();
            }
            lightShadowMap.ShaderData = shaderData;
            shaderData.Texture        = lightShadowMap.Atlas.Texture;
            shaderData.DepthBias      = shadow.BiasParameters.DepthBias;
            shaderData.OffsetScale    = shadow.BiasParameters.NormalOffsetScale;

            float splitMaxRatio = (minMaxDistance.X - sourceView.NearClipPlane) / (sourceView.FarClipPlane - sourceView.NearClipPlane);
            float splitMinRatio = 0;

            for (int cascadeLevel = 0; cascadeLevel < cascadeCount; ++cascadeLevel)
            {
                var oldSplitMinRatio = splitMinRatio;
                // Calculate frustum corners for this cascade
                splitMinRatio = splitMaxRatio;
                splitMaxRatio = cascadeSplitRatios[cascadeLevel];

                for (int j = 0; j < 4; j++)
                {
                    // Calculate frustum in WS and VS
                    float overlap = 0;
                    if (cascadeLevel > 0 && shadow.DepthRange.IsBlendingCascades)
                    {
                        overlap = 0.2f * (splitMinRatio - oldSplitMinRatio);
                    }

                    var frustumRangeWS = frustumCornersWS[j + 4] - frustumCornersWS[j];
                    var frustumRangeVS = frustumCornersVS[j + 4] - frustumCornersVS[j];

                    cascadeFrustumCornersWS[j]     = frustumCornersWS[j] + frustumRangeWS * (splitMinRatio - overlap);
                    cascadeFrustumCornersWS[j + 4] = frustumCornersWS[j] + frustumRangeWS * splitMaxRatio;

                    cascadeFrustumCornersVS[j]     = frustumCornersVS[j] + frustumRangeVS * (splitMinRatio - overlap);
                    cascadeFrustumCornersVS[j + 4] = frustumCornersVS[j] + frustumRangeVS * splitMaxRatio;
                }

                Vector3 cascadeMinBoundLS;
                Vector3 cascadeMaxBoundLS;
                Vector3 target;

                if (shadow.StabilizationMode == LightShadowMapStabilizationMode.ViewSnapping || shadow.StabilizationMode == LightShadowMapStabilizationMode.ProjectionSnapping)
                {
                    // Make sure we are using the same direction when stabilizing
                    var boundingVS = BoundingSphere.FromPoints(cascadeFrustumCornersVS);

                    // Compute bounding box center & radius
                    target = Vector3.TransformCoordinate(boundingVS.Center, viewToWorld);
                    var radius = boundingVS.Radius;

                    //if (shadow.AutoComputeMinMax)
                    //{
                    //    var snapRadius = (float)Math.Ceiling(radius / snapRadiusValue) * snapRadiusValue;
                    //    Debug.WriteLine("Radius: {0} SnapRadius: {1} (snap: {2})", radius, snapRadius, snapRadiusValue);
                    //    radius = snapRadius;
                    //}

                    cascadeMaxBoundLS = new Vector3(radius, radius, radius);
                    cascadeMinBoundLS = -cascadeMaxBoundLS;

                    if (shadow.StabilizationMode == LightShadowMapStabilizationMode.ViewSnapping)
                    {
                        // Snap camera to texel units (so that shadow doesn't jitter when light doesn't change direction but camera is moving)
                        // Technique from ShaderX7 - Practical Cascaded Shadows Maps -  p310-311
                        var   shadowMapHalfSize = lightShadowMap.Size * 0.5f;
                        float x = (float)Math.Ceiling(Vector3.Dot(target, upDirection) * shadowMapHalfSize / radius) * radius / shadowMapHalfSize;
                        float y = (float)Math.Ceiling(Vector3.Dot(target, side) * shadowMapHalfSize / radius) * radius / shadowMapHalfSize;
                        float z = Vector3.Dot(target, direction);

                        //target = up * x + side * y + direction * R32G32B32_Float.Dot(target, direction);
                        target = upDirection * x + side * y + direction * z;
                    }
                }
                else
                {
                    var cascadeBoundWS = BoundingBox.FromPoints(cascadeFrustumCornersWS);
                    target = cascadeBoundWS.Center;

                    // Computes the bouding box of the frustum cascade in light space
                    var lightViewMatrix = Matrix.LookAtRH(target, target + direction, upDirection);
                    cascadeMinBoundLS = new Vector3(float.MaxValue);
                    cascadeMaxBoundLS = new Vector3(-float.MaxValue);
                    for (int i = 0; i < cascadeFrustumCornersWS.Length; i++)
                    {
                        Vector3 cornerViewSpace;
                        Vector3.TransformCoordinate(ref cascadeFrustumCornersWS[i], ref lightViewMatrix, out cornerViewSpace);

                        cascadeMinBoundLS = Vector3.Min(cascadeMinBoundLS, cornerViewSpace);
                        cascadeMaxBoundLS = Vector3.Max(cascadeMaxBoundLS, cornerViewSpace);
                    }

                    // TODO: Adjust orthoSize by taking into account filtering size
                }

                // Update the shadow camera. The calculation of the eye position assumes RH coordinates.
                var    viewMatrix       = Matrix.LookAtRH(target - direction * cascadeMaxBoundLS.Z, target, upDirection); // View;;
                var    nearClip         = 0.0f;
                var    farClip          = cascadeMaxBoundLS.Z - cascadeMinBoundLS.Z;
                var    projectionMatrix = Matrix.OrthoOffCenterRH(cascadeMinBoundLS.X, cascadeMaxBoundLS.X, cascadeMinBoundLS.Y, cascadeMaxBoundLS.Y, nearClip, farClip); // Projection
                Matrix viewProjectionMatrix;
                Matrix.Multiply(ref viewMatrix, ref projectionMatrix, out viewProjectionMatrix);

                // Stabilize the Shadow matrix on the projection
                if (shadow.StabilizationMode == LightShadowMapStabilizationMode.ProjectionSnapping)
                {
                    var shadowPixelPosition = viewProjectionMatrix.TranslationVector * lightShadowMap.Size * 0.5f; // shouln't it be scale and not translation ?
                    shadowPixelPosition.Z = 0;
                    var shadowPixelPositionRounded = new Vector3((float)Math.Round(shadowPixelPosition.X), (float)Math.Round(shadowPixelPosition.Y), 0.0f);

                    var shadowPixelOffset = new Vector4(shadowPixelPositionRounded - shadowPixelPosition, 0.0f);
                    shadowPixelOffset     *= 2.0f / lightShadowMap.Size;
                    projectionMatrix.Row4 += shadowPixelOffset;
                    Matrix.Multiply(ref viewMatrix, ref projectionMatrix, out viewProjectionMatrix);
                }

                shaderData.ViewMatrix[cascadeLevel]       = viewMatrix;
                shaderData.ProjectionMatrix[cascadeLevel] = projectionMatrix;
                shaderData.DepthRange[cascadeLevel]       = new Vector2(nearClip, farClip); //////////////////////

                // Cascade splits in light space using depth: Store depth on first CascaderCasterMatrix in last column of each row
                shaderData.CascadeSplits[cascadeLevel] = MathUtil.Lerp(sourceView.NearClipPlane, sourceView.FarClipPlane, cascadeSplitRatios[cascadeLevel]);

                var shadowMapRectangle = lightShadowMap.GetRectangle(cascadeLevel);

                var cascadeTextureCoords = new Vector4((float)shadowMapRectangle.Left / lightShadowMap.Atlas.Width,
                                                       (float)shadowMapRectangle.Top / lightShadowMap.Atlas.Height,
                                                       (float)shadowMapRectangle.Right / lightShadowMap.Atlas.Width,
                                                       (float)shadowMapRectangle.Bottom / lightShadowMap.Atlas.Height);

                shaderData.TextureCoords[cascadeLevel] = cascadeTextureCoords;

                //// Add border (avoid using edges due to bilinear filtering and blur)
                //var borderSizeU = VsmBlurSize / lightShadowMap.Atlas.Width;
                //var borderSizeV = VsmBlurSize / lightShadowMap.Atlas.Height;
                //cascadeTextureCoords.X += borderSizeU;
                //cascadeTextureCoords.Y += borderSizeV;
                //cascadeTextureCoords.Z -= borderSizeU;
                //cascadeTextureCoords.W -= borderSizeV;

                float leftX   = (float)lightShadowMap.Size / lightShadowMap.Atlas.Width * 0.5f;
                float leftY   = (float)lightShadowMap.Size / lightShadowMap.Atlas.Height * 0.5f;
                float centerX = 0.5f * (cascadeTextureCoords.X + cascadeTextureCoords.Z);
                float centerY = 0.5f * (cascadeTextureCoords.Y + cascadeTextureCoords.W);

                // Compute receiver view proj matrix
                Matrix adjustmentMatrix = Matrix.Scaling(leftX, -leftY, 1.0f) * Matrix.Translation(centerX, centerY, 0.0f);
                // Calculate View Proj matrix from World space to Cascade space
                Matrix.Multiply(ref viewProjectionMatrix, ref adjustmentMatrix, out shaderData.WorldToShadowCascadeUV[cascadeLevel]);

                // Allocate shadow render view
                var shadowRenderView = CreateRenderView();
                shadowRenderView.RenderView       = sourceView;
                shadowRenderView.ShadowMapTexture = lightShadowMap;
                shadowRenderView.Rectangle        = shadowMapRectangle;
                shadowRenderView.View             = viewMatrix;
                shadowRenderView.ViewSize         = new Vector2(shadowMapRectangle.Width, shadowMapRectangle.Height);
                shadowRenderView.Projection       = projectionMatrix;
                shadowRenderView.ViewProjection   = viewProjectionMatrix;
                shadowRenderView.NearClipPlane    = nearClip;
                shadowRenderView.FarClipPlane     = farClip;

                // Add the render view for the current frame
                context.RenderSystem.Views.Add(shadowRenderView);
            }
        }
예제 #34
0
 public LineNumberRenderer(RenderView editor)
 {
     _editor = editor ?? throw new ArgumentNullException("editor");
 }
예제 #35
0
        public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            base.Draw(context, renderView, renderViewStage, startIndex, endIndex);

            var isMultisample = RenderSystem.RenderStages[renderViewStage.Index].Output.MultisampleCount != MultisampleCount.None;

            var batchContext = threadContext.Value;

            Matrix viewInverse;

            Matrix.Invert(ref renderView.View, out viewInverse);

            uint previousBatchState = uint.MaxValue;

            //TODO string comparison ...?
            var isPicking = RenderSystem.RenderStages[renderViewStage.Index].Name == "Picking";

            bool hasBegin = false;

            for (var index = startIndex; index < endIndex; index++)
            {
                var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode;
                var renderNode          = GetRenderNode(renderNodeReference);

                var renderSprite = (RenderSprite)renderNode.RenderObject;

                var spriteComp  = renderSprite.SpriteComponent;
                var transfoComp = renderSprite.TransformComponent;

                var sprite = spriteComp.CurrentSprite;
                if (sprite == null)
                {
                    continue;
                }

                // TODO: this should probably be moved to Prepare()
                // 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(renderSprite.TransformComponent.WorldMatrix.TranslationVector, 1.0f);

                Vector4 projectedPosition;
                Vector4.Transform(ref worldPosition, ref renderView.ViewProjection, out projectedPosition);
                var projectedZ = projectedPosition.Z / projectedPosition.W;

                BlendModes     blendMode;
                EffectInstance currentEffect = null;
                if (isPicking)
                {
                    blendMode     = BlendModes.Default;
                    currentEffect = batchContext.GetOrCreatePickingSpriteEffect(RenderSystem.EffectSystem);
                }
                else
                {
                    var spriteBlend = spriteComp.BlendMode;
                    if (spriteBlend == SpriteComponent.SpriteBlend.Auto)
                    {
                        spriteBlend = sprite.IsTransparent ? SpriteComponent.SpriteBlend.AlphaBlend: SpriteComponent.SpriteBlend.None;
                    }

                    if (spriteBlend == SpriteComponent.SpriteBlend.AlphaBlend)
                    {
                        blendMode = spriteComp.PremultipliedAlpha ? BlendModes.Alpha: BlendModes.NonPremultiplied;
                    }
                    else
                    {
                        blendMode = spriteBlendToBlendMode[spriteBlend];
                    }
                }

                // Check if the current blend state has changed in any way, if not
                // Note! It doesn't really matter in what order we build the bitmask, the result is not preserved anywhere except in this method
                var currentBatchState = (uint)blendMode;
                currentBatchState = (currentBatchState << 1) + (renderSprite.SpriteComponent.IgnoreDepth ? 1U : 0U);
                currentBatchState = (currentBatchState << 1) + (spriteComp.IsAlphaCutoff ? 1U : 0U);
                currentBatchState = (currentBatchState << 2) + ((uint)renderSprite.SpriteComponent.Sampler);

                if (previousBatchState != currentBatchState)
                {
                    var blendState = blendModeToDescription[blendMode];

                    if (spriteComp.IsAlphaCutoff)
                    {
                        currentEffect = batchContext.GetOrCreateAlphaCutoffSpriteEffect(RenderSystem.EffectSystem);
                    }

                    var depthStencilState = renderSprite.SpriteComponent.IgnoreDepth ? DepthStencilStates.None : DepthStencilStates.Default;

                    var samplerState = context.GraphicsDevice.SamplerStates.LinearClamp;
                    if (renderSprite.SpriteComponent.Sampler != SpriteComponent.SpriteSampler.LinearClamp)
                    {
                        switch (renderSprite.SpriteComponent.Sampler)
                        {
                        case SpriteComponent.SpriteSampler.PointClamp:
                            samplerState = context.GraphicsDevice.SamplerStates.PointClamp;
                            break;

                        case SpriteComponent.SpriteSampler.AnisotropicClamp:
                            samplerState = context.GraphicsDevice.SamplerStates.AnisotropicClamp;
                            break;
                        }
                    }

                    if (hasBegin)
                    {
                        batchContext.SpriteBatch.End();
                    }

                    var rasterizerState = RasterizerStates.CullNone;
                    if (isMultisample)
                    {
                        rasterizerState.MultisampleCount         = RenderSystem.RenderStages[renderViewStage.Index].Output.MultisampleCount;
                        rasterizerState.MultisampleAntiAliasLine = true;
                    }

                    batchContext.SpriteBatch.Begin(context.GraphicsContext, renderView.ViewProjection, SpriteSortMode.Deferred, blendState, samplerState, depthStencilState, rasterizerState, currentEffect);
                    hasBegin = true;
                }
                previousBatchState = currentBatchState;

                var sourceRegion = sprite.Region;
                var texture      = sprite.Texture;
                var color        = spriteComp.ColorFinal;
                if (isPicking) // TODO move this code corresponding to picking out of the runtime code.
                {
                    var compId = RuntimeIdHelper.ToRuntimeId(spriteComp);
                    color = new Color4(compId, 0.0f, 0.0f, 0.0f);
                }

                // skip the sprite if no texture is set.
                if (texture == null)
                {
                    continue;
                }

                // determine the element world matrix depending on the type of sprite
                var worldMatrix = transfoComp.WorldMatrix;
                if (spriteComp.SpriteType == SpriteType.Billboard)
                {
                    worldMatrix = viewInverse;

                    // remove scale of the camera
                    worldMatrix.Row1 /= ((Vector3)viewInverse.Row1).Length();
                    worldMatrix.Row2 /= ((Vector3)viewInverse.Row2).Length();

                    // set the scale of the object
                    worldMatrix.Row1 *= ((Vector3)transfoComp.WorldMatrix.Row1).Length();
                    worldMatrix.Row2 *= ((Vector3)transfoComp.WorldMatrix.Row2).Length();

                    // set the position
                    worldMatrix.TranslationVector = transfoComp.WorldMatrix.TranslationVector;

                    // set the rotation
                    var localRotationZ = transfoComp.RotationEulerXYZ.Z;
                    if (localRotationZ != 0)
                    {
                        worldMatrix = Matrix.RotationZ(localRotationZ) * worldMatrix;
                    }
                }

                // calculate normalized position of the center of the sprite (takes into account the possible rotation of the image)
                var normalizedCenter = new Vector2(sprite.Center.X / sourceRegion.Width - 0.5f, 0.5f - sprite.Center.Y / sourceRegion.Height);
                if (sprite.Orientation == ImageOrientation.Rotated90)
                {
                    var oldCenterX = normalizedCenter.X;
                    normalizedCenter.X = -normalizedCenter.Y;
                    normalizedCenter.Y = oldCenterX;
                }
                // apply the offset due to the center of the sprite
                var centerOffset = Vector2.Modulate(normalizedCenter, sprite.SizeInternal);
                worldMatrix.M41 -= centerOffset.X * worldMatrix.M11 + centerOffset.Y * worldMatrix.M21;
                worldMatrix.M42 -= centerOffset.X * worldMatrix.M12 + centerOffset.Y * worldMatrix.M22;
                worldMatrix.M43 -= centerOffset.X * worldMatrix.M13 + centerOffset.Y * worldMatrix.M23;

                // adapt the source region to match what is expected at full resolution
                if (texture.ViewType == ViewType.Full && texture.ViewWidth != texture.FullQualitySize.Width)
                {
                    var fullQualitySize = texture.FullQualitySize;
                    var horizontalRatio = texture.ViewWidth / (float)fullQualitySize.Width;
                    var verticalRatio   = texture.ViewHeight / (float)fullQualitySize.Height;
                    sourceRegion.X      *= horizontalRatio;
                    sourceRegion.Width  *= horizontalRatio;
                    sourceRegion.Y      *= verticalRatio;
                    sourceRegion.Height *= verticalRatio;
                }

                // register resource usage.
                Context.StreamingManager?.StreamResources(texture);

                // draw the sprite
                batchContext.SpriteBatch.Draw(texture, ref worldMatrix, ref sourceRegion, ref sprite.SizeInternal, ref color, sprite.Orientation, spriteComp.Swizzle, projectedZ);
            }

            if (hasBegin)
            {
                batchContext.SpriteBatch.End();
            }
        }
예제 #36
0
 public ViewObjectNode(RenderObject renderObject, RenderView renderView, ObjectNodeReference objectNode)
 {
     RenderObject = renderObject;
     RenderView = renderView;
     ObjectNode = objectNode;
 }
예제 #37
0
 public abstract float ComputeScreenCoverage(RenderView renderView, Vector3 position, Vector3 direction);
예제 #38
0
        private static void PrepareLightGroups(RenderDrawContext context, FastList<RenderView> renderViews, RenderView renderView, RenderViewLightData renderViewData, ShadowMapRenderer shadowMapRenderer, EntityGroup group)
        {
            foreach (var activeRenderer in renderViewData.ActiveRenderers)
            {
                // Find lights
                var lightRenderer = activeRenderer.LightRenderer;
                var lightCollection = activeRenderer.LightGroup.FindLightCollectionByGroup(group);

                var processLightsParameters = new LightGroupRendererBase.ProcessLightsParameters
                {
                    Context = context,
                    ViewIndex = renderViewData.ViewIndex,
                    View = renderView,
                    Views = renderViews,
                    LightCollection = lightCollection,
                    LightType = activeRenderer.LightGroup.LightType,
                    LightStart = 0,
                    LightEnd = lightCollection.Count,
                    ShadowMapRenderer = shadowMapRenderer,
                    ShadowMapTexturesPerLight = renderViewData.LightComponentsWithShadows,
                };

                lightRenderer.ProcessLights(processLightsParameters);
            }
        }
예제 #39
0
        protected override void OnInitialized(EventArgs e)
        {
            if (!IsD3D10Supported())
                return;

            var renderView = new RenderView();
            var renderer = new TileControl.RendererD3DSharpDX();
            renderer.RenderData = renderView.RenderData;

            m_renderer = renderer;
            m_renderView = renderView;

            SetRenderer(renderer);

            this.TileLayoutChanged += OnTileArrangementChanged;
            this.AboutToRender += OnAboutToRender;

            m_renderer.TileSet = GameData.Data.TileSet;
            GameData.Data.TileSetChanged += OnTileSetChanged;

            base.OnInitialized(e);
        }
예제 #40
0
        public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            base.Draw(context, renderView, renderViewStage, startIndex, endIndex);

            Matrix viewInverse;
            Matrix.Invert(ref renderView.View, out viewInverse);

            BlendStateDescription? previousBlendState = null;
            DepthStencilStateDescription? previousDepthStencilState = null;
            EffectInstance previousEffect = null;

            //TODO string comparison ...?
            var isPicking = renderViewStage.RenderStage.Name == "Picking";

            bool hasBegin = false;
            for (var index = startIndex; index < endIndex; index++)
            {
                var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode;
                var renderNode = GetRenderNode(renderNodeReference);

                var renderSprite = (RenderSprite)renderNode.RenderObject;

                var spriteComp = renderSprite.SpriteComponent;
                var transfoComp = renderSprite.TransformComponent;
                var depthStencilState = renderSprite.SpriteComponent.IgnoreDepth ? DepthStencilStates.None : DepthStencilStates.Default;

                var sprite = spriteComp.CurrentSprite;
                if (sprite == null)
                    continue;

                // TODO: this should probably be moved to Prepare()
                // 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(renderSprite.TransformComponent.WorldMatrix.TranslationVector, 1.0f);

                Vector4 projectedPosition;
                Vector4.Transform(ref worldPosition, ref renderView.ViewProjection, out projectedPosition);
                var projectedZ = projectedPosition.Z / projectedPosition.W;

                // Update the sprite batch
                var blendState = isPicking ? BlendStates.Default : sprite.IsTransparent ? (spriteComp.PremultipliedAlpha ? BlendStates.AlphaBlend : BlendStates.NonPremultiplied) : BlendStates.Opaque;
                var currentEffect = isPicking ? GetOrCreatePickingSpriteEffect() : null; // TODO remove this code when material are available
                if (previousEffect != currentEffect || blendState != previousBlendState || depthStencilState != previousDepthStencilState)
                {
                    if (hasBegin)
                    {
                        sprite3DBatch.End();
                    }
                    sprite3DBatch.Begin(context.GraphicsContext, renderView.ViewProjection, SpriteSortMode.Deferred, blendState, null, depthStencilState, RasterizerStates.CullNone, currentEffect);
                    hasBegin = true;
                }
                previousEffect = currentEffect;
                previousBlendState = blendState;
                previousDepthStencilState = depthStencilState;

                var sourceRegion = sprite.Region;
                var texture = sprite.Texture;
                var color = spriteComp.Color;                
                if (isPicking) // TODO move this code corresponding to picking out of the runtime code.
                {
                    var compId = RuntimeIdHelper.ToRuntimeId(spriteComp);
                    color = new Color4(compId);
                }

                // skip the sprite if no texture is set.
                if (texture == null)
                    continue;

                // determine the element world matrix depending on the type of sprite
                var worldMatrix = transfoComp.WorldMatrix;
                if (spriteComp.SpriteType == SpriteType.Billboard)
                {
                    worldMatrix = viewInverse;

                    // remove scale of the camera
                    worldMatrix.Row1 /= ((Vector3)viewInverse.Row1).Length();
                    worldMatrix.Row2 /= ((Vector3)viewInverse.Row2).Length();

                    // set the scale of the object
                    worldMatrix.Row1 *= ((Vector3)transfoComp.WorldMatrix.Row1).Length();
                    worldMatrix.Row2 *= ((Vector3)transfoComp.WorldMatrix.Row2).Length();

                    // set the position
                    worldMatrix.TranslationVector = transfoComp.WorldMatrix.TranslationVector;
                }

                // calculate normalized position of the center of the sprite (takes into account the possible rotation of the image)
                var normalizedCenter = new Vector2(sprite.Center.X / sourceRegion.Width - 0.5f, 0.5f - sprite.Center.Y / sourceRegion.Height);
                if (sprite.Orientation == ImageOrientation.Rotated90)
                {
                    var oldCenterX = normalizedCenter.X;
                    normalizedCenter.X = -normalizedCenter.Y;
                    normalizedCenter.Y = oldCenterX;
                }
                // apply the offset due to the center of the sprite
                var centerOffset = Vector2.Modulate(normalizedCenter, sprite.SizeInternal);
                worldMatrix.M41 -= centerOffset.X * worldMatrix.M11 + centerOffset.Y * worldMatrix.M21;
                worldMatrix.M42 -= centerOffset.X * worldMatrix.M12 + centerOffset.Y * worldMatrix.M22;
                worldMatrix.M43 -= centerOffset.X * worldMatrix.M13 + centerOffset.Y * worldMatrix.M23;

                // draw the sprite
                sprite3DBatch.Draw(texture, ref worldMatrix, ref sourceRegion, ref sprite.SizeInternal, ref color, sprite.Orientation, SwizzleMode.None, projectedZ);
            }

            if(hasBegin) sprite3DBatch.End();
        }
예제 #41
0
 public abstract float ComputeScreenCoverage(RenderView renderView, Vector3 position, Vector3 direction);
예제 #42
0
        public override void Collect(RenderContext context, RenderView sourceView, LightShadowMapTexture lightShadowMap)
        {
            // TODO: Min and Max distance can be auto-computed from readback from Z buffer  // Yeah sure... good luck with that.
            var shadow = (LightStandardShadowMap)lightShadowMap.Shadow;

            // Computes the cascade splits
            var lightComponent = lightShadowMap.LightComponent;
            var spotLight      = (LightSpot)lightComponent.Type;

            // Get new shader data from pool
            var shaderData = shaderDataPool.Add();

            lightShadowMap.ShaderData = shaderData;
            shaderData.Texture        = lightShadowMap.Atlas.Texture;

            shaderData.DepthBias   = shadow.BiasParameters.DepthBias;
            shaderData.OffsetScale = shadow.BiasParameters.NormalOffsetScale;

            // TODO: Calculation of near and far is hardcoded/approximated. We should find a better way to calculate it.
            var nearClip = 0.01f;                                   // TODO: This should be configurable.
            var farClip  = spotLight.Range * 2.0f;                  // TODO: For some reason this multiplication by two is required. This should be investigated and fixed properly.

            shaderData.DepthRange = new Vector2(nearClip, farClip); //////////////////////////////////////////

            // Update the shadow camera
            var viewMatrix = lightComponent.Entity.Transform.WorldMatrix;

            viewMatrix.Invert();
            var projectionMatrix = Matrix.PerspectiveFovRH(spotLight.AngleOuterInRadians, spotLight.AspectRatio, nearClip, farClip); // Perspective Projection for spotlights

            Matrix.Multiply(ref viewMatrix, ref projectionMatrix, out var viewProjectionMatrix);

            var shadowMapRectangle = lightShadowMap.GetRectangle(0);

            var cascadeTextureCoords = new Vector4(
                (float)shadowMapRectangle.Left / lightShadowMap.Atlas.Width,
                (float)shadowMapRectangle.Top / lightShadowMap.Atlas.Height,
                (float)shadowMapRectangle.Right / lightShadowMap.Atlas.Width,
                (float)shadowMapRectangle.Bottom / lightShadowMap.Atlas.Height);

            //// Add border (avoid using edges due to bilinear filtering and blur)
            //var borderSizeU = VsmBlurSize / lightShadowMap.Atlas.Width;
            //var borderSizeV = VsmBlurSize / lightShadowMap.Atlas.Height;
            //cascadeTextureCoords.X += borderSizeU;
            //cascadeTextureCoords.Y += borderSizeV;
            //cascadeTextureCoords.Z -= borderSizeU;
            //cascadeTextureCoords.W -= borderSizeV;

            float leftX   = (float)lightShadowMap.Size / lightShadowMap.Atlas.Width * 0.5f;
            float leftY   = (float)lightShadowMap.Size / lightShadowMap.Atlas.Height * 0.5f;
            float centerX = 0.5f * (cascadeTextureCoords.X + cascadeTextureCoords.Z);
            float centerY = 0.5f * (cascadeTextureCoords.Y + cascadeTextureCoords.W);

            // Compute receiver view proj matrix
            Matrix adjustmentMatrix = Matrix.Scaling(leftX, -leftY, 1.0f) * Matrix.Translation(centerX, centerY, 0.0f);

            // Calculate View Proj matrix from World space to Cascade space
            Matrix.Multiply(ref viewProjectionMatrix, ref adjustmentMatrix, out shaderData.WorldToShadowCascadeUV);

            //Matrix rotationMatrix = Matrix.RotationZ(rotationZ);
            //Matrix.Multiply(ref viewProjectionMatrix, ref rotationMatrix, out shaderData.worldToShadowProjectiveTextureUV);

            shaderData.ViewMatrix       = viewMatrix;
            shaderData.ProjectionMatrix = projectionMatrix;

            // Allocate shadow render view
            var shadowRenderView = CreateRenderView();

            shadowRenderView.RenderView       = sourceView;
            shadowRenderView.ShadowMapTexture = lightShadowMap;
            shadowRenderView.Rectangle        = lightShadowMap.GetRectangle(0);
            // Compute view parameters
            shadowRenderView.View       = shaderData.ViewMatrix;
            shadowRenderView.Projection = shaderData.ProjectionMatrix;
            Matrix.Multiply(ref shadowRenderView.View, ref shadowRenderView.Projection, out shadowRenderView.ViewProjection);
            shadowRenderView.ViewSize      = new Vector2(shadowMapRectangle.Width, shadowMapRectangle.Height);
            shadowRenderView.NearClipPlane = nearClip;
            shadowRenderView.FarClipPlane  = farClip;

            // Add the render view for the current frame
            context.RenderSystem.Views.Add(shadowRenderView);

            // Collect objects in shadow views
            context.VisibilityGroup.TryCollect(shadowRenderView);
        }
예제 #43
0
        /// <summary>
        /// Called when thumbnail rendering begins.
        /// </summary>
        /// <param name="task">The scene rendering task to customize.</param>
        /// <param name="context">The GPU rendering context.</param>
        /// <param name="req">The request data.</param>
        public void OnThumbnailRenderingBegin(SceneRenderTask task, GPUContext context, ref CameraCutThumbnailRenderer.Request req)
        {
            var view        = new RenderView();
            var track       = (CameraCutTrack)Track;
            var cam         = track.Camera;
            var viewport    = new FlaxEngine.Viewport(Vector2.Zero, task.Buffers.Size);
            var orientation = Quaternion.Identity;

            view.Near = 10.0f;
            view.Far  = 20000.0f;
            var usePerspective    = true;
            var orthoScale        = 1.0f;
            var fov               = 60.0f;
            var customAspectRatio = 0.0f;

            // Try to evaluate camera properties based on the initial camera state
            if (cam)
            {
                view.Position     = cam.Position;
                orientation       = cam.Orientation;
                view.Near         = cam.NearPlane;
                view.Far          = cam.FarPlane;
                usePerspective    = cam.UsePerspective;
                orthoScale        = cam.OrthographicScale;
                fov               = cam.FieldOfView;
                customAspectRatio = cam.CustomAspectRatio;
            }

            // Try to evaluate camera properties based on the animated tracks
            var time = req.ThumbnailIndex == 0 ? Start : Start + Duration;

            foreach (var subTrack in track.SubTracks)
            {
                if (subTrack is MemberTrack memberTrack)
                {
                    object value = memberTrack.Evaluate(time);
                    if (value != null)
                    {
                        // TODO: try to make it better
                        if (memberTrack.MemberName == "Position" && value is Vector3 asPosition)
                        {
                            view.Position = asPosition;
                        }
                        else if (memberTrack.MemberName == "Orientation" && value is Quaternion asRotation)
                        {
                            orientation = asRotation;
                        }
                        else if (memberTrack.MemberName == "NearPlane" && value is float asNearPlane)
                        {
                            view.Near = asNearPlane;
                        }
                        else if (memberTrack.MemberName == "FarPlane" && value is float asFarPlane)
                        {
                            view.Far = asFarPlane;
                        }
                        else if (memberTrack.MemberName == "UsePerspective" && value is bool asUsePerspective)
                        {
                            usePerspective = asUsePerspective;
                        }
                        else if (memberTrack.MemberName == "FieldOfView" && value is float asFieldOfView)
                        {
                            fov = asFieldOfView;
                        }
                        else if (memberTrack.MemberName == "CustomAspectRatio" && value is float asCustomAspectRatio)
                        {
                            customAspectRatio = asCustomAspectRatio;
                        }
                        else if (memberTrack.MemberName == "OrthographicScale" && value is float asOrthographicScale)
                        {
                            orthoScale = asOrthographicScale;
                        }
                    }
                }
            }

            // Build view
            view.Direction = Vector3.Forward * orientation;
            if (usePerspective)
            {
                float aspect = customAspectRatio <= 0.0f ? viewport.AspectRatio : customAspectRatio;
                view.Projection = Matrix.PerspectiveFov(fov * Mathf.DegreesToRadians, aspect, view.Near, view.Far);
            }
            else
            {
                view.Projection = Matrix.Ortho(viewport.Width * orthoScale, viewport.Height * orthoScale, view.Near, view.Far);
            }
            Vector3 target = view.Position + view.Direction;
            var     up     = Vector3.Transform(Vector3.Up, orientation);

            view.View = Matrix.LookAt(view.Position, target, up);
            view.NonJitteredProjection = view.Projection;
            view.TemporalAAJitter      = Vector4.Zero;
            view.Flags = ViewFlags.Reflections | ViewFlags.SSR | ViewFlags.AO | ViewFlags.GI |
                         ViewFlags.DirectionalLights | ViewFlags.PointLights | ViewFlags.SpotLights | ViewFlags.SkyLights |
                         ViewFlags.Shadows | ViewFlags.SpecularLight | ViewFlags.AntiAliasing | ViewFlags.CustomPostProcess |
                         ViewFlags.Bloom | ViewFlags.ToneMapping | ViewFlags.CameraArtifacts | ViewFlags.LensFlares | ViewFlags.Decals |
                         ViewFlags.DepthOfField | ViewFlags.Fog;
            task.View = view;
        }
예제 #44
0
        /// <inheritdoc/>
        public override unsafe void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            var commandList = context.CommandList;

            // Per view - this code was moved here from Prepare(...) so that we can apply the correct Viewport
            {
                var view        = renderView;
                var viewFeature = view.Features[Index];

                Matrix.Multiply(ref view.View, ref view.Projection, out view.ViewProjection);

                // Copy ViewProjection to PerFrame cbuffer
                foreach (var viewLayout in viewFeature.Layouts)
                {
                    var resourceGroup = viewLayout.Entries[view.Index].Resources;
                    var mappedCB      = resourceGroup.ConstantBuffer.Data;

                    // PerView constant buffer
                    var perViewOffset = viewLayout.GetConstantBufferOffset(this.perViewCBufferOffset);
                    if (perViewOffset != -1)
                    {
                        var perView = (ParticleUtilitiesPerView *)((byte *)mappedCB + perViewOffset);
                        perView->ViewMatrix           = view.View;
                        perView->ProjectionMatrix     = view.Projection;
                        perView->ViewProjectionMatrix = view.ViewProjection;
                        perView->ViewFrustum          = new Vector4(view.ViewSize.X, view.ViewSize.Y, view.NearClipPlane, view.FarClipPlane);

                        perView->Viewport = new Vector4(0,
                                                        0,
                                                        ((float)context.CommandList.Viewport.Width) / ((float)context.CommandList.RenderTarget.Width),
                                                        ((float)context.CommandList.Viewport.Height) / ((float)context.CommandList.RenderTarget.Height));
                    }
                }
            }

            var renderParticleNodeData = RenderData.GetData(renderParticleNodeKey);

            // TODO: stackalloc?
            var descriptorSetsLocal = descriptorSets.Value;

            if (descriptorSetsLocal == null || descriptorSetsLocal.Length < EffectDescriptorSetSlotCount)
            {
                descriptorSetsLocal = descriptorSets.Value = new DescriptorSet[EffectDescriptorSetSlotCount];
            }

            for (var index = startIndex; index < endIndex; index++)
            {
                var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode;

                // Get effect
                var renderEffect = GetRenderNode(renderNodeReference).RenderEffect;
                if (renderEffect.Effect == null)
                {
                    continue;
                }

                // Get the extra node data
                var nodeData = renderParticleNodeData[renderNodeReference];
                if (nodeData.IndexCount <= 0)
                {
                    continue;
                }

                var resourceGroupOffset = ComputeResourceGroupOffset(renderNodeReference);

                // Update cbuffer
                renderEffect.Reflection.BufferUploader.Apply(commandList, ResourceGroupPool, resourceGroupOffset);

                // Bind descriptor sets
                for (int i = 0; i < descriptorSetsLocal.Length; ++i)
                {
                    var resourceGroup = ResourceGroupPool[resourceGroupOffset++];
                    if (resourceGroup != null)
                    {
                        descriptorSetsLocal[i] = resourceGroup.DescriptorSet;
                    }
                }

                commandList.SetPipelineState(renderEffect.PipelineState);
                commandList.SetDescriptorSets(0, descriptorSetsLocal);

                // Bind the buffers and draw
                commandList.SetVertexBuffer(0, nodeData.VertexBuffer, nodeData.VertexBufferOffset, nodeData.VertexBufferStride);
                commandList.SetIndexBuffer(nodeData.IndexBuffer, nodeData.IndexBufferOffset, ParticleBufferContext.IndexStride != sizeof(short));
                commandList.DrawIndexed(nodeData.IndexCount, 0);
            }
        }
        public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            base.Draw(context, renderView, renderViewStage, startIndex, endIndex);

            var batchContext = threadContext.Value;

            Matrix viewInverse;
            Matrix.Invert(ref renderView.View, out viewInverse);

            uint previousBatchState = uint.MaxValue;

            //TODO string comparison ...?
            var isPicking = renderViewStage.RenderStage.Name == "Picking";

            bool hasBegin = false;
            for (var index = startIndex; index < endIndex; index++)
            {
                var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode;
                var renderNode = GetRenderNode(renderNodeReference);

                var renderSprite = (RenderSprite)renderNode.RenderObject;

                var spriteComp = renderSprite.SpriteComponent;
                var transfoComp = renderSprite.TransformComponent;

                var sprite = spriteComp.CurrentSprite;
                if (sprite == null)
                    continue;

                // TODO: this should probably be moved to Prepare()
                // 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(renderSprite.TransformComponent.WorldMatrix.TranslationVector, 1.0f);

                Vector4 projectedPosition;
                Vector4.Transform(ref worldPosition, ref renderView.ViewProjection, out projectedPosition);
                var projectedZ = projectedPosition.Z / projectedPosition.W;

                // Check if the current blend state has changed in any way, if not
                // Note! It doesn't really matter in what order we build the bitmask, the result is not preserved anywhere except in this method
                var currentBatchState = isPicking ? 0U : sprite.IsTransparent ? (spriteComp.PremultipliedAlpha ? 1U : 2U) : 3U;
                currentBatchState = (currentBatchState << 1) + (renderSprite.SpriteComponent.IgnoreDepth ? 1U : 0U);
                currentBatchState = (currentBatchState << 2) + ((uint)renderSprite.SpriteComponent.Sampler);

                if (previousBatchState != currentBatchState)
                {
                    var blendState = isPicking ? BlendStates.Default : sprite.IsTransparent ? (spriteComp.PremultipliedAlpha ? BlendStates.AlphaBlend : BlendStates.NonPremultiplied) : BlendStates.Opaque;
                    var currentEffect = isPicking ? batchContext.GetOrCreatePickingSpriteEffect(RenderSystem.EffectSystem) : null; // TODO remove this code when material are available
                    var depthStencilState = renderSprite.SpriteComponent.IgnoreDepth ? DepthStencilStates.None : DepthStencilStates.Default;

                    var samplerState = context.GraphicsDevice.SamplerStates.LinearClamp;
                    if (renderSprite.SpriteComponent.Sampler != SpriteComponent.SpriteSampler.LinearClamp)
                    {
                        switch (renderSprite.SpriteComponent.Sampler)
                        {
                            case SpriteComponent.SpriteSampler.PointClamp:
                                samplerState = context.GraphicsDevice.SamplerStates.PointClamp;
                                break;
                            case SpriteComponent.SpriteSampler.AnisotropicClamp:
                                samplerState = context.GraphicsDevice.SamplerStates.AnisotropicClamp;
                                break;
                        }
                    }

                    if (hasBegin)
                    {
                        batchContext.SpriteBatch.End();
                    }

                    batchContext.SpriteBatch.Begin(context.GraphicsContext, renderView.ViewProjection, SpriteSortMode.Deferred, blendState, samplerState, depthStencilState, RasterizerStates.CullNone, currentEffect);
                    hasBegin = true;
                }
                previousBatchState = currentBatchState;

                var sourceRegion = sprite.Region;
                var texture = sprite.Texture;
                var color = spriteComp.Color;                
                if (isPicking) // TODO move this code corresponding to picking out of the runtime code.
                {
                    var compId = RuntimeIdHelper.ToRuntimeId(spriteComp);
                    color = new Color4(compId);
                }

                // skip the sprite if no texture is set.
                if (texture == null)
                    continue;

                // determine the element world matrix depending on the type of sprite
                var worldMatrix = transfoComp.WorldMatrix;
                if (spriteComp.SpriteType == SpriteType.Billboard)
                {
                    worldMatrix = viewInverse;

                    // remove scale of the camera
                    worldMatrix.Row1 /= ((Vector3)viewInverse.Row1).Length();
                    worldMatrix.Row2 /= ((Vector3)viewInverse.Row2).Length();

                    // set the scale of the object
                    worldMatrix.Row1 *= ((Vector3)transfoComp.WorldMatrix.Row1).Length();
                    worldMatrix.Row2 *= ((Vector3)transfoComp.WorldMatrix.Row2).Length();

                    // set the position
                    worldMatrix.TranslationVector = transfoComp.WorldMatrix.TranslationVector;
                }

                // calculate normalized position of the center of the sprite (takes into account the possible rotation of the image)
                var normalizedCenter = new Vector2(sprite.Center.X / sourceRegion.Width - 0.5f, 0.5f - sprite.Center.Y / sourceRegion.Height);
                if (sprite.Orientation == ImageOrientation.Rotated90)
                {
                    var oldCenterX = normalizedCenter.X;
                    normalizedCenter.X = -normalizedCenter.Y;
                    normalizedCenter.Y = oldCenterX;
                }
                // apply the offset due to the center of the sprite
                var centerOffset = Vector2.Modulate(normalizedCenter, sprite.SizeInternal);
                worldMatrix.M41 -= centerOffset.X * worldMatrix.M11 + centerOffset.Y * worldMatrix.M21;
                worldMatrix.M42 -= centerOffset.X * worldMatrix.M12 + centerOffset.Y * worldMatrix.M22;
                worldMatrix.M43 -= centerOffset.X * worldMatrix.M13 + centerOffset.Y * worldMatrix.M23;

                // draw the sprite
                batchContext.SpriteBatch.Draw(texture, ref worldMatrix, ref sourceRegion, ref sprite.SizeInternal, ref color, sprite.Orientation, SwizzleMode.None, projectedZ);
            }

            if (hasBegin)
            {
                batchContext.SpriteBatch.End();
            }
        }
예제 #46
0
        private void DrawInternal(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            base.Draw(context, renderView, renderViewStage, startIndex, endIndex);

            var uiProcessor = SceneInstance.GetCurrent(context.RenderContext).GetProcessor <UIRenderProcessor>();

            if (uiProcessor == null)
            {
                return;
            }


            // build the list of the UI elements to render
            uiElementStates.Clear();
            for (var index = startIndex; index < endIndex; index++)
            {
                var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode;
                var renderNode          = GetRenderNode(renderNodeReference);
                var renderElement       = (RenderUIElement)renderNode.RenderObject;

                uiElementStates.Add(new UIElementState(renderElement));
            }

            // evaluate the current draw time (game instance is null for thumbnails)
            var drawTime = game != null ? game.DrawTime : new GameTime();

            // update the rendering context
            renderingContext.GraphicsContext = context.GraphicsContext;
            renderingContext.Time            = drawTime;
            renderingContext.RenderTarget    = context.CommandList.RenderTargets[0]; // TODO: avoid hardcoded index 0

            // Prepare content required for Picking and MouseOver events
            PickingPrepare();

            // allocate temporary graphics resources if needed
            Texture scopedDepthBuffer = null;

            foreach (var uiElement in uiElementStates)
            {
                if (uiElement.RenderObject.IsFullScreen)
                {
                    var renderTarget = renderingContext.RenderTarget;
                    var description  = TextureDescription.New2D(renderTarget.Width, renderTarget.Height, PixelFormat.D24_UNorm_S8_UInt, TextureFlags.DepthStencil);
                    scopedDepthBuffer = context.RenderContext.Allocator.GetTemporaryTexture(description);
                    break;
                }
            }

            // update view parameters and perform UI picking
            foreach (var uiElementState in uiElementStates)
            {
                var renderObject = uiElementState.RenderObject;
                var rootElement  = renderObject.Page?.RootElement;
                if (rootElement == null)
                {
                    continue;
                }

                // calculate the size of the virtual resolution depending on target size (UI canvas)
                var virtualResolution = renderObject.Resolution;

                if (renderObject.IsFullScreen)
                {
                    //var targetSize = viewportSize;
                    var targetSize = new Vector2(renderingContext.RenderTarget.Width, renderingContext.RenderTarget.Height);

                    // update the virtual resolution of the renderer
                    if (renderObject.ResolutionStretch == ResolutionStretch.FixedWidthAdaptableHeight)
                    {
                        virtualResolution.Y = virtualResolution.X * targetSize.Y / targetSize.X;
                    }
                    if (renderObject.ResolutionStretch == ResolutionStretch.FixedHeightAdaptableWidth)
                    {
                        virtualResolution.X = virtualResolution.Y * targetSize.X / targetSize.Y;
                    }

                    uiElementState.Update(renderObject, virtualResolution);
                }
                else
                {
                    var cameraComponent = renderView.Camera;
                    if (cameraComponent != null)
                    {
                        uiElementState.Update(renderObject, (CameraComponent)cameraComponent);
                    }
                }

                // Check if the current UI component is being picked based on the current ViewParameters (used to draw this element)
                using (Profiler.Begin(UIProfilerKeys.TouchEventsUpdate))
                {
                    PickingUpdate(uiElementState.RenderObject, context.CommandList.Viewport, ref uiElementState.WorldViewProjectionMatrix, drawTime);
                }
            }

            // render the UI elements of all the entities
            foreach (var uiElementState in uiElementStates)
            {
                var renderObject = uiElementState.RenderObject;
                var rootElement  = renderObject.Page?.RootElement;
                if (rootElement == null)
                {
                    continue;
                }

                var updatableRootElement = (IUIElementUpdate)rootElement;
                var virtualResolution    = renderObject.Resolution;

                // update the rendering context values specific to this element
                renderingContext.Resolution           = virtualResolution;
                renderingContext.ViewProjectionMatrix = uiElementState.WorldViewProjectionMatrix;
                renderingContext.DepthStencilBuffer   = renderObject.IsFullScreen ? scopedDepthBuffer : context.CommandList.DepthStencilBuffer;
                renderingContext.ShouldSnapText       = renderObject.SnapText;
                renderingContext.IsFullscreen         = renderObject.IsFullScreen;

                // calculate an estimate of the UI real size by projecting the element virtual resolution on the screen
                var virtualOrigin            = uiElementState.WorldViewProjectionMatrix.Row4;
                var virtualWidth             = new Vector4(virtualResolution.X / 2, 0, 0, 1);
                var virtualHeight            = new Vector4(0, virtualResolution.Y / 2, 0, 1);
                var transformedVirtualWidth  = Vector4.Zero;
                var transformedVirtualHeight = Vector4.Zero;
                for (var i = 0; i < 4; i++)
                {
                    transformedVirtualWidth[i]  = virtualWidth[0] * uiElementState.WorldViewProjectionMatrix[0 + i] + uiElementState.WorldViewProjectionMatrix[12 + i];
                    transformedVirtualHeight[i] = virtualHeight[1] * uiElementState.WorldViewProjectionMatrix[4 + i] + uiElementState.WorldViewProjectionMatrix[12 + i];
                }

                var viewportSize           = context.CommandList.Viewport.Size;
                var projectedOrigin        = virtualOrigin.XY() / virtualOrigin.W;
                var projectedVirtualWidth  = viewportSize * (transformedVirtualWidth.XY() / transformedVirtualWidth.W - projectedOrigin);
                var projectedVirtualHeight = viewportSize * (transformedVirtualHeight.XY() / transformedVirtualHeight.W - projectedOrigin);

                // Set default services
                rootElement.UIElementServices = new UIElementServices {
                    Services = RenderSystem.Services
                };

                // set default resource dictionary

                // update layouting context.
                layoutingContext.VirtualResolution          = virtualResolution;
                layoutingContext.RealResolution             = viewportSize;
                layoutingContext.RealVirtualResolutionRatio = new Vector2(projectedVirtualWidth.Length() / virtualResolution.X, projectedVirtualHeight.Length() / virtualResolution.Y);
                rootElement.LayoutingContext = layoutingContext;

                // perform the time-based updates of the UI element
                updatableRootElement.Update(drawTime);

                // update the UI element disposition
                rootElement.Measure(virtualResolution);
                rootElement.Arrange(virtualResolution, false);

                // update the UI element hierarchical properties
                var rootMatrix = Matrix.Translation(-virtualResolution / 2); // UI world is translated by a half resolution compared to its quad, which is centered around the origin
                updatableRootElement.UpdateWorldMatrix(ref rootMatrix, rootMatrix != uiElementState.RenderObject.LastRootMatrix);
                updatableRootElement.UpdateElementState(0);
                uiElementState.RenderObject.LastRootMatrix = rootMatrix;

                // set the depth buffer, although we are probably not writing to it
                context.CommandList.SetRenderTarget(renderingContext.DepthStencilBuffer, renderingContext.RenderTarget);

                // start the image draw session
                renderingContext.StencilTestReferenceValue = 0;
                batch.Begin(context.GraphicsContext, ref uiElementState.WorldViewProjectionMatrix, BlendStates.AlphaBlend, uiSystem.KeepStencilValueState, renderingContext.StencilTestReferenceValue);

                // Render the UI elements in the final render target
                RecursiveDrawWithClipping(context, rootElement, ref uiElementState.WorldViewProjectionMatrix);

                // end the image draw session
                batch.End();
            }

            PickingClear();

            // revert the depth stencil buffer to the default value
            context.CommandList.SetRenderTargets(context.CommandList.DepthStencilBuffer, context.CommandList.RenderTargetCount, context.CommandList.RenderTargets);

            // Release scroped texture
            if (scopedDepthBuffer != null)
            {
                context.RenderContext.Allocator.ReleaseReference(scopedDepthBuffer);
            }
        }
예제 #47
0
 public override float ComputeScreenCoverage(RenderView renderView, Vector3 position, Vector3 direction)
 {
     // As the directional light is covering the whole screen, we take the max of current width, height
     return Math.Max(renderView.ViewSize.X, renderView.ViewSize.Y);
 }
예제 #48
0
        public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            // Do not call into VL if not running
            var renderContext = context.RenderContext;
            var runtime       = this.runtime ?? (this.runtime = renderContext.Services.GetService <IVLRuntime>());

            if (runtime != null && !runtime.IsRunning)
            {
                return;
            }

            // Build the list of layers to render
            singleCallLayers.Clear();
            layers.Clear();
            for (var index = startIndex; index < endIndex; index++)
            {
                var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode;
                var renderNode          = GetRenderNode(renderNodeReference);
                var renderElement       = (RenderDrawEffect)renderNode.RenderObject;

                if (renderElement.Enabled)
                {
                    if (renderElement.SingleCallPerFrame)
                    {
                        singleCallLayers.Add(renderElement.Layer);
                    }
                    else
                    {
                        layers.Add(renderElement.Layer);
                    }
                }
            }

            // Tell VL that we're calling into it - ensures that no hotswap will be happening
            RuntimeGraph.Enter(this);
            try
            {
                // Call layers which want to get invoked only once per frame first
                var currentFrameNr = renderContext.Time.FrameCount;
                if (lastFrameNr != currentFrameNr)
                {
                    lastFrameNr = currentFrameNr;
                    foreach (var layer in singleCallLayers)
                    {
                        try
                        {
                            layer?.Draw(Context, context, renderView, renderViewStage, context.CommandList);
                        }
                        catch (Exception e)
                        {
                            RuntimeGraph.ReportException(e);
                        }
                    }
                }

                // Call layers which can get invoked twice per frame (for each eye)
                foreach (var layer in layers)
                {
                    try
                    {
                        layer?.Draw(Context, context, renderView, renderViewStage, context.CommandList);
                    }
                    catch (Exception e)
                    {
                        RuntimeGraph.ReportException(e);
                    }
                }
            }
            finally
            {
                RuntimeGraph.Exit(this);
            }
        }
예제 #49
0
        /// <summary>
        /// Called when thumbnail rendering begins.
        /// </summary>
        /// <param name="task">The scene rendering task to customize.</param>
        /// <param name="context">The GPU rendering context.</param>
        /// <param name="req">The request data.</param>
        public void OnThumbnailRenderingBegin(SceneRenderTask task, GPUContext context, ref CameraCutThumbnailRenderer.Request req)
        {
            RenderView view        = new RenderView();
            var        track       = (CameraCutTrack)Track;
            Camera     cam         = track.Camera;
            var        viewport    = new FlaxEngine.Viewport(Float2.Zero, task.Buffers.Size);
            Quaternion orientation = Quaternion.Identity;

            view.Near = 10.0f;
            view.Far  = 20000.0f;
            bool  usePerspective    = true;
            float orthoScale        = 1.0f;
            float fov               = 60.0f;
            float customAspectRatio = 0.0f;

            view.RenderLayersMask = new LayersMask(uint.MaxValue);

            // Try to evaluate camera properties based on the initial camera state
            if (cam)
            {
                view.Position         = cam.Position;
                orientation           = cam.Orientation;
                view.Near             = cam.NearPlane;
                view.Far              = cam.FarPlane;
                usePerspective        = cam.UsePerspective;
                orthoScale            = cam.OrthographicScale;
                fov                   = cam.FieldOfView;
                customAspectRatio     = cam.CustomAspectRatio;
                view.RenderLayersMask = cam.RenderLayersMask;
            }

            // Try to evaluate camera properties based on the animated tracks
            float time = Start;

            if (req.ThumbnailIndex == 1)
            {
                time += Duration;
            }
            else if (req.ThumbnailIndex == 2)
            {
                time += Duration * 0.5f;
            }
            foreach (var subTrack in track.SubTracks)
            {
                if (subTrack is MemberTrack memberTrack)
                {
                    object value = memberTrack.Evaluate(time);
                    if (value != null)
                    {
                        // TODO: try to make it better
                        if (memberTrack.MemberName == "Position" && value is Vector3 asPosition)
                        {
                            view.Position = asPosition;
                        }

                        else if (memberTrack.MemberName == "Orientation" && value is Quaternion asRotation)
                        {
                            orientation = asRotation;
                        }

                        else if (memberTrack.MemberName == "NearPlane" && value is float asNearPlane)
                        {
                            view.Near = asNearPlane;
                        }

                        else if (memberTrack.MemberName == "FarPlane" && value is float asFarPlane)
                        {
                            view.Far = asFarPlane;
                        }

                        else if (memberTrack.MemberName == "UsePerspective" && value is bool asUsePerspective)
                        {
                            usePerspective = asUsePerspective;
                        }

                        else if (memberTrack.MemberName == "FieldOfView" && value is float asFieldOfView)
                        {
                            fov = asFieldOfView;
                        }

                        else if (memberTrack.MemberName == "CustomAspectRatio" && value is float asCustomAspectRatio)
                        {
                            customAspectRatio = asCustomAspectRatio;
                        }

                        else if (memberTrack.MemberName == "OrthographicScale" && value is float asOrthographicScale)
                        {
                            orthoScale = asOrthographicScale;
                        }
                    }
                }
            }

            // Build view
            view.Direction = Float3.Forward * orientation;
            if (usePerspective)
            {
                float aspect = customAspectRatio <= 0.0f ? viewport.AspectRatio : customAspectRatio;
                view.Projection = Matrix.PerspectiveFov(fov * Mathf.DegreesToRadians, aspect, view.Near, view.Far);
            }
            else
            {
                view.Projection = Matrix.Ortho(viewport.Width * orthoScale, viewport.Height * orthoScale, view.Near, view.Far);
            }

            Vector3 target = view.Position + view.Direction;
            var     up     = Float3.Transform(Float3.Up, orientation);

            view.View = Matrix.LookAt(view.Position, target, up);
            view.NonJitteredProjection  = view.Projection;
            view.TemporalAAJitter       = Float4.Zero;
            view.ModelLODDistanceFactor = 100.0f;
            view.Flags = ViewFlags.DefaultGame & ~(ViewFlags.MotionBlur);
            view.UpdateCachedData();
            task.View = view;
        }
예제 #50
0
        private void DrawInternal(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            base.Draw(context, renderView, renderViewStage, startIndex, endIndex);

            var currentRenderFrame = context.RenderContext.Tags.Get(RenderFrame.Current);

            var uiProcessor = renderView.SceneInstance.GetProcessor<UIRenderProcessor>();
            if (uiProcessor == null)
                return;


            // build the list of the UI elements to render
            uiElementStates.Clear();
            for (var index = startIndex; index < endIndex; index++)
            {
                var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode;
                var renderNode = GetRenderNode(renderNodeReference);
                var renderElement = (RenderUIElement)renderNode.RenderObject;
 
                uiElementStates.Add(new UIElementState(renderElement));
            }

            // evaluate the current draw time (game instance is null for thumbnails)
            var drawTime = game != null ? game.DrawTime : new GameTime();

            // update the rendering context
            renderingContext.GraphicsContext = context.GraphicsContext;
            renderingContext.Time = drawTime;
            renderingContext.RenderTarget = currentRenderFrame.RenderTargets[0]; // TODO: avoid hardcoded index 0

            // Prepare content required for Picking and MouseOver events
            PickingPrepare();

            // allocate temporary graphics resources if needed
            Texture scopedDepthBuffer = null;
            foreach (var uiElement in uiElementStates)
            {
                if (uiElement.RenderObject.UIComponent.IsFullScreen)
                {
                    var renderTarget = renderingContext.RenderTarget;
                    var description = TextureDescription.New2D(renderTarget.Width, renderTarget.Height, PixelFormat.D24_UNorm_S8_UInt, TextureFlags.DepthStencil);
                    scopedDepthBuffer = context.RenderContext.Allocator.GetTemporaryTexture(description);
                    break;
                }
            }

            // update view parameters and perform UI picking
            foreach (var uiElementState in uiElementStates)
            {
                var uiComponent = uiElementState.RenderObject.UIComponent;
                var rootElement = uiComponent.Page?.RootElement;
                if (rootElement == null)
                    continue;
                
                // calculate the size of the virtual resolution depending on target size (UI canvas)
                var virtualResolution = uiComponent.Resolution;

                if (uiComponent.IsFullScreen)
                {
                    //var targetSize = viewportSize;
                    var targetSize = new Vector2(renderingContext.RenderTarget.Width, renderingContext.RenderTarget.Height);

                    // update the virtual resolution of the renderer
                    if (uiComponent.ResolutionStretch == ResolutionStretch.FixedWidthAdaptableHeight)
                        virtualResolution.Y = virtualResolution.X * targetSize.Y / targetSize.X;
                    if (uiComponent.ResolutionStretch == ResolutionStretch.FixedHeightAdaptableWidth)
                        virtualResolution.X = virtualResolution.Y * targetSize.X / targetSize.Y;

                    uiElementState.Update(uiComponent.Entity, virtualResolution);
                }
                else
                {
                    var cameraComponent = context.RenderContext.Tags.Get(CameraComponentRendererExtensions.Current);
                    if (cameraComponent != null)
                        uiElementState.Update(uiComponent.Entity, cameraComponent);
                }

                // Check if the current UI component is being picked based on the current ViewParameters (used to draw this element)
                using (Profiler.Begin(UIProfilerKeys.TouchEventsUpdate))
                {
                    PickingUpdate(uiElementState.RenderObject, context.CommandList.Viewport, ref uiElementState.WorldViewProjectionMatrix, drawTime);
                }
            }

            // render the UI elements of all the entities
            foreach (var uiElementState in uiElementStates)
            {
                var uiComponent = uiElementState.RenderObject.UIComponent;
                var rootElement = uiComponent.Page?.RootElement;
                if (rootElement == null)
                    continue;

                var updatableRootElement = (IUIElementUpdate)rootElement;
                var virtualResolution = uiComponent.Resolution;

                // update the rendering context values specific to this element
                renderingContext.Resolution = virtualResolution;
                renderingContext.ViewProjectionMatrix = uiElementState.WorldViewProjectionMatrix;
                renderingContext.DepthStencilBuffer = uiComponent.IsFullScreen ? scopedDepthBuffer : currentRenderFrame.DepthStencil;
                renderingContext.ShouldSnapText = uiComponent.SnapText;

                // calculate an estimate of the UI real size by projecting the element virtual resolution on the screen
                var virtualOrigin = uiElementState.WorldViewProjectionMatrix.Row4;
                var virtualWidth = new Vector4(virtualResolution.X / 2, 0, 0, 1);
                var virtualHeight = new Vector4(0, virtualResolution.Y / 2, 0, 1);
                var transformedVirtualWidth = Vector4.Zero;
                var transformedVirtualHeight = Vector4.Zero;
                for (var i = 0; i < 4; i++)
                {
                    transformedVirtualWidth[i] = virtualWidth[0] * uiElementState.WorldViewProjectionMatrix[0 + i] + uiElementState.WorldViewProjectionMatrix[12 + i];
                    transformedVirtualHeight[i] = virtualHeight[1] * uiElementState.WorldViewProjectionMatrix[4 + i] + uiElementState.WorldViewProjectionMatrix[12 + i];
                }

                var viewportSize = context.CommandList.Viewport.Size;
                var projectedOrigin = virtualOrigin.XY() / virtualOrigin.W;
                var projectedVirtualWidth = viewportSize * (transformedVirtualWidth.XY() / transformedVirtualWidth.W - projectedOrigin);
                var projectedVirtualHeight = viewportSize * (transformedVirtualHeight.XY() / transformedVirtualHeight.W - projectedOrigin);

                // Set default services
                rootElement.UIElementServices = new UIElementServices { Services = RenderSystem.Services };

                // set default resource dictionary
                rootElement.ResourceDictionary = uiSystem.DefaultResourceDictionary;

                // update layouting context.
                layoutingContext.VirtualResolution = virtualResolution;
                layoutingContext.RealResolution = viewportSize;
                layoutingContext.RealVirtualResolutionRatio = new Vector2(projectedVirtualWidth.Length() / virtualResolution.X, projectedVirtualHeight.Length() / virtualResolution.Y);
                rootElement.LayoutingContext = layoutingContext;

                // perform the time-based updates of the UI element
                updatableRootElement.Update(drawTime);

                // update the UI element disposition
                rootElement.Measure(virtualResolution);
                rootElement.Arrange(virtualResolution, false);

                // update the UI element hierarchical properties
                var rootMatrix = Matrix.Translation(-virtualResolution / 2); // UI world is translated by a half resolution compared to its quad, which is centered around the origin
                updatableRootElement.UpdateWorldMatrix(ref rootMatrix, rootMatrix != uiElementState.RenderObject.LastRootMatrix);
                updatableRootElement.UpdateElementState(0);
                uiElementState.RenderObject.LastRootMatrix = rootMatrix;

                // clear and set the Depth buffer as required
                if (uiComponent.IsFullScreen)
                {
                    context.CommandList.Clear(renderingContext.DepthStencilBuffer, DepthStencilClearOptions.DepthBuffer | DepthStencilClearOptions.Stencil);
                }
                context.CommandList.SetRenderTarget(renderingContext.DepthStencilBuffer, renderingContext.RenderTarget);

                // start the image draw session
                renderingContext.StencilTestReferenceValue = 0;
                batch.Begin(context.GraphicsContext, ref uiElementState.WorldViewProjectionMatrix, BlendStates.AlphaBlend, uiSystem.KeepStencilValueState, renderingContext.StencilTestReferenceValue);

                // Render the UI elements in the final render target
                RecursiveDrawWithClipping(context, rootElement, ref uiElementState.WorldViewProjectionMatrix);

                // end the image draw session
                batch.End();
            }

            PickingClear();

            // revert the depth stencil buffer to the default value 
            context.CommandList.SetRenderTargets(currentRenderFrame.DepthStencil, currentRenderFrame.RenderTargets);

            // Release scroped texture
            if (scopedDepthBuffer != null)
            {
                context.RenderContext.Allocator.ReleaseReference(scopedDepthBuffer);
            }
        }
        public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            base.Draw(context, renderView, renderViewStage, startIndex, endIndex);

            BlendStateDescription?       previousBlendState        = null;
            DepthStencilStateDescription?previousDepthStencilState = null;
            EffectInstance previousEffect = null;

            //TODO string comparison ...?
            var isPicking = renderViewStage.RenderStage.Name == "Picking";

            var device = RenderSystem.GraphicsDevice;

            var hasBegin = false;

            for (var index = startIndex; index < endIndex; index++)
            {
                var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode;
                var renderNode          = GetRenderNode(renderNodeReference);

                var spriteState = (RenderSpriteStudio)renderNode.RenderObject;

                var transfoComp       = spriteState.TransformComponent;
                var depthStencilState = DepthStencilStates.DepthRead;

                foreach (var node in spriteState.SpriteStudioComponent.SortedNodes)
                {
                    if (node.Sprite?.Texture == null || node.Sprite.Region.Width <= 0 || node.Sprite.Region.Height <= 0f || node.Hide != 0)
                    {
                        continue;
                    }

                    // Update the sprite batch

                    BlendStateDescription spriteBlending;
                    switch (node.BaseNode.AlphaBlending)
                    {
                    case SpriteStudioBlending.Mix:
                        spriteBlending = BlendStates.AlphaBlend;
                        break;

                    case SpriteStudioBlending.Multiplication:
                        spriteBlending = MultBlendState;
                        break;

                    case SpriteStudioBlending.Addition:
                        spriteBlending = BlendStates.Additive;
                        break;

                    case SpriteStudioBlending.Subtraction:
                        spriteBlending = SubBlendState;
                        break;

                    default:
                        throw new ArgumentOutOfRangeException();
                    }

                    // TODO: this should probably be moved to Prepare()
                    // 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(transfoComp.WorldMatrix.TranslationVector, 1.0f);

                    Vector4 projectedPosition;
                    Vector4.Transform(ref worldPosition, ref renderView.ViewProjection, out projectedPosition);
                    var projectedZ = projectedPosition.Z / projectedPosition.W;

                    var blendState = isPicking ? BlendStates.Default : spriteBlending;
                    // TODO: the current impementation to determine if the sprite is selected does not work. This should be fixed later at some point
                    //var currentEffect = isPicking ? GetOrCreatePickingSpriteEffect() : ShadowObject.IsObjectSelected(spriteState.SpriteStudioComponent) ? GetOrCreateSelectedSpriteEffect() : null;
                    var currentEffect = isPicking ? GetOrCreatePickingSpriteEffect() : null;
                    // TODO remove this code when material are available
                    if (previousEffect != currentEffect || blendState != previousBlendState || depthStencilState != previousDepthStencilState)
                    {
                        if (hasBegin)
                        {
                            sprite3DBatch.End();
                        }
                        sprite3DBatch.Begin(context.GraphicsContext, renderView.ViewProjection, SpriteSortMode.Deferred, blendState, null, depthStencilState, RasterizerStates.CullNone, currentEffect);
                        hasBegin = true;
                    }

                    previousEffect            = currentEffect;
                    previousBlendState        = blendState;
                    previousDepthStencilState = depthStencilState;

                    var sourceRegion = node.Sprite.Region;
                    var texture      = node.Sprite.Texture;

                    // skip the sprite if no texture is set.
                    if (texture == null)
                    {
                        continue;
                    }

                    var color4 = Color4.White;
                    if (isPicking)
                    {
                        // TODO move this code corresponding to picking out of the runtime code.
                        color4 = new Color4(RuntimeIdHelper.ToRuntimeId(spriteState.SpriteStudioComponent));
                    }
                    else
                    {
                        if (node.BlendFactor > 0.0f)
                        {
                            switch (node.BlendType) //todo this should be done in a shader
                            {
                            case SpriteStudioBlending.Mix:
                                color4 = Color4.Lerp(color4, node.BlendColor, node.BlendFactor) * node.FinalTransparency;
                                break;

                            case SpriteStudioBlending.Multiplication:
                                color4 = Color4.Lerp(color4, node.BlendColor, node.BlendFactor) * node.FinalTransparency;
                                break;

                            case SpriteStudioBlending.Addition:
                                color4 = Color4.Lerp(color4, node.BlendColor, node.BlendFactor) * node.FinalTransparency;
                                break;

                            case SpriteStudioBlending.Subtraction:
                                color4 = Color4.Lerp(color4, node.BlendColor, node.BlendFactor) * node.FinalTransparency;
                                break;

                            default:
                                throw new ArgumentOutOfRangeException();
                            }
                        }
                        else
                        {
                            color4 *= node.FinalTransparency;
                        }
                    }

                    var worldMatrix = node.ModelTransform * transfoComp.WorldMatrix;

                    // calculate normalized position of the center of the sprite (takes into account the possible rotation of the image)
                    var normalizedCenter = new Vector2(node.Sprite.Center.X / sourceRegion.Width - 0.5f, 0.5f - node.Sprite.Center.Y / sourceRegion.Height);
                    if (node.Sprite.Orientation == ImageOrientation.Rotated90)
                    {
                        var oldCenterX = normalizedCenter.X;
                        normalizedCenter.X = -normalizedCenter.Y;
                        normalizedCenter.Y = oldCenterX;
                    }
                    // apply the offset due to the center of the sprite
                    var size         = node.Sprite.Size;
                    var centerOffset = Vector2.Modulate(normalizedCenter, size);
                    worldMatrix.M41 -= centerOffset.X * worldMatrix.M11 + centerOffset.Y * worldMatrix.M21;
                    worldMatrix.M42 -= centerOffset.X * worldMatrix.M12 + centerOffset.Y * worldMatrix.M22;

                    // draw the sprite
                    sprite3DBatch.Draw(texture, ref worldMatrix, ref sourceRegion, ref size, ref color4, node.Sprite.Orientation, SwizzleMode.None, projectedZ);
                }
            }

            if (hasBegin)
            {
                sprite3DBatch.End();
            }
        }
예제 #52
0
 public ADTRenderer(RenderView controller, ADT adt)
 {
     Controller    = controller;
     ADT           = adt;
     MeshRenderers = new GenericCollectionRenderer <MeshRenderer>(Controller);
 }