/// <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); }
public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex) { lock (drawLock) { DrawInternal(context, renderView, renderViewStage, startIndex, endIndex); } }
/// <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; }
//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(); }
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); }
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); }
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; }
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(); } }
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); }
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); } }
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)); }
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); } }
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(); }
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(); } }
public CameraRotateSceneTool(RenderView renderView) { this.renderView = renderView; }
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]); } }
public CameraZoomSceneTool(RenderView renderView) { this.renderView = renderView; }
public EntityMoveSceneTool(RenderView renderView, System.Collections.Generic.List <Entity> selectedEntities) { this.renderView = renderView; this.selectedEntities = selectedEntities; }
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); } }
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); }
public abstract void Collect(RenderContext context, RenderView sourceView, LightShadowMapTexture lightShadowMap);
public void Render(VoxelStorageContext storageContext, RenderDrawContext drawContext, RenderView view) { }
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); } } } } } }
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); } } }
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); } }
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); } }
public LineNumberRenderer(RenderView editor) { _editor = editor ?? throw new ArgumentNullException("editor"); }
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(); } }
public ViewObjectNode(RenderObject renderObject, RenderView renderView, ObjectNodeReference objectNode) { RenderObject = renderObject; RenderView = renderView; ObjectNode = objectNode; }
public abstract float ComputeScreenCoverage(RenderView renderView, Vector3 position, Vector3 direction);
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); } }
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); }
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(); }
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); }
/// <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; }
/// <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(); } }
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); } }
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); }
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); } }
/// <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; }
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(); } }
public ADTRenderer(RenderView controller, ADT adt) { Controller = controller; ADT = adt; MeshRenderers = new GenericCollectionRenderer <MeshRenderer>(Controller); }