private static void UpdateProjViewMatrix(Size clientSize) { var verticalFov = (float)Math.PI / 4; var aspect = clientSize.Width / (float)clientSize.Height; var proj = MatrixCM.PerspectiveFovRH(verticalFov, aspect, 1.0f, 5000.0f); projView = proj * view; if (zfirst) { zfirst = false; var lookat = new Vector3(0, 0.5f, 0); //var pos = new Vector4(lookat + 0.1f * (cameraEye - lookat), 1);//new Vector4(1, 2, 3, 1); var pos = new Vector4(0.5f, 1.0f, 0.5f, 1); var projViewRm = projView; projViewRm.Transpose(); var homogeneous = Vector4.Transform(pos, projViewRm); Console.WriteLine("pos: " + pos); Console.WriteLine("posh: " + homogeneous); homogeneous /= homogeneous.W; Console.WriteLine("poshn: " + homogeneous); var projViewRmInv = projViewRm; projViewRmInv.Invert(); Console.WriteLine(); Console.WriteLine(projViewRmInv * projViewRm); Console.WriteLine(); Console.WriteLine(projViewRm * projViewRmInv); Console.WriteLine(); var x = Vector4.Transform(homogeneous, projViewRmInv); Console.WriteLine(x); x /= x.W; Console.WriteLine(x); } }
public void AddSpotlight(Vector3 position, Vector3 lookat, Vector3 up, float theta, Color color, float near, float far, float daRatioConstant, float daRatioLinear, float daRatioQuadratic, float edgeSpotlightAttenuationPercent = 1.0f / 256.0f) { var projCm = MatrixCM.PerspectiveFovRH(theta, 1.0f, near, far); var viewCm = MatrixCM.ViewLookAtRH(position, lookat, up); // solve distance attenuation constants: 1/256 = atten = 1 / (x * darc + far * x * darl + far * far * x * darq) // 256 = x * darc + far * x * darl + far * far * x * darq // 256 = x * (darc + far * darl + far * far * darq) var x = 256 / (daRatioConstant + far * daRatioLinear + far * far * daRatioQuadratic); //Console.WriteLine(x + " " + daRatioConstant + " " + daRatioLinear + " " + daRatioQuadratic); var direction = lookat - position; direction.Normalize(); //Console.WriteLine("@8: " + (daRatioConstant * x + daRatioLinear * x * 8 + daRatioQuadratic * x * 8 * 8)); //Console.WriteLine("@far: " + (daRatioConstant * x + daRatioLinear * x * far + daRatioQuadratic * x * far * far)); // solve spotlight attenuation constant. // edge% = atten_spotlight = dot(spotlightDirectionUnit, objectDirectionUnit) ^ power // edge% = cos(theta) ^ power // Math.Log(edge%, cos(theta)) = power var power = Math.Log(edgeSpotlightAttenuationPercent, Math.Cos(theta)); //Console.WriteLine("Power: " + power); //Console.WriteLine("@far: " + Math.Pow(Math.Cos(theta), power)); var projViewCm = projCm * viewCm; AddSpotlight(new SpotlightInfo { Origin = position, Direction = direction, Color = color, DistanceAttenuationConstant = x * daRatioConstant, DistanceAttenuationLinear = x * daRatioLinear, DistanceAttenuationQuadratic = x * daRatioQuadratic, SpotlightAttenuationPower = (float)power, ProjViewCM = projViewCm, }); }
public static void Main(string[] args) { var graphicsLoop = GraphicsLoop.CreateWithNewWindow(1280, 720, InitFlags.DisableVerticalSync | InitFlags.EnableDebugStats); graphicsLoop.Form.Resize += (s, e) => UpdateProjViewMatrix(graphicsLoop.Form.ClientSize); graphicsLoop.Form.MouseWheel += (s, e) => { var dir = cameraOffset; dir.Normalize(); cameraOffset += dir * (-e.Delta / 100.0f); Console.WriteLine(e.Delta + " " + dir + " " + cameraOffset); view = MatrixCM.ViewLookAtRH(cameraTarget + cameraOffset, cameraTarget, new Vector3(0, 1, 0)); UpdateProjViewMatrix(graphicsLoop.Form.ClientSize); }; UpdateProjViewMatrix(graphicsLoop.Form.ClientSize); //var projViewInv = MatrixCM.Invert(projView); //projViewInv.Transpose(); //var asdf = Vector4.Transform(new Vector4(0, 0, 1, 1), projViewInv); //Console.WriteLine(asdf / asdf.W); //asdf = Vector4.Transform(new Vector4(1, 0, 1, 1), projViewInv); //Console.WriteLine(asdf / asdf.W); //asdf = Vector4.Transform(new Vector4(0, 1, 1, 1), projViewInv); //Console.WriteLine(asdf / asdf.W); //return; var floatingCubesBatch = RenderJobBatch.Create(graphicsLoop.Presets.GetPresetMesh(MeshPreset.UnitCube)); //floatingCubesBatch.Wireframe = true; foreach (var transform in cubeDefaultTransforms) { floatingCubesBatch.Jobs.Add(new RenderJobDescription { WorldTransform = transform, MaterialProperties = { Metallic = 0.0f, Roughness = 0.0f }, MaterialResourcesIndex = -1, Color = Color.White }); } var gizmos = new GizomisidfojdsTSOmethign(graphicsLoop.Input, graphicsLoop.Presets.UnitSphere, graphicsLoop.Presets.UnitCube); var scene = new Scene(); for (var frame = 0; graphicsLoop.IsRunning(out var renderer, out var input); frame++) { var t = (float)graphicsLoop.Statistics.FrameTime.TotalSeconds; //scene.SetTime((float)Math.Sin(t * 1)); scene.SetTime((float)t); var right = Vector3.Cross(-cameraOffset, cameraUp); right.Normalize(); var forward = -cameraOffset; forward.Normalize(); var up = Vector3.Cross(right, forward); if (input.IsMouseDown(MouseButtons.Right)) { var rotation = Matrix.RotationY(-input.DeltaX * 0.005f) * Matrix.RotationAxis(right, -input.DeltaY * 0.005f); cameraOffset = (Vector3)Vector3.Transform(cameraOffset, rotation); } var v = (input.IsKeyDown(Keys.ShiftKey) ? 7.0f : 1.0f) * 50; if (input.IsKeyDown(Keys.Left) || input.IsKeyDown(Keys.A)) { cameraTarget -= right * 0.005f * v; } if (input.IsKeyDown(Keys.Right) || input.IsKeyDown(Keys.D)) { cameraTarget += right * 0.005f * v; } if (input.IsKeyDown(Keys.Up) || input.IsKeyDown(Keys.W)) { cameraTarget += forward * 0.005f * v; } if (input.IsKeyDown(Keys.Down) || input.IsKeyDown(Keys.S)) { cameraTarget -= forward * 0.005f * v; } if (input.IsKeyDown(Keys.Space)) { cameraTarget += cameraUp * 0.005f * (input.IsKeyDown(Keys.ShiftKey) ? -1 : 1); } view = MatrixCM.ViewLookAtRH(cameraTarget + cameraOffset, cameraTarget, new Vector3(0, 1, 0)); UpdateProjViewMatrix(graphicsLoop.Form.ClientSize); scene.Clear(); scene.SetCamera(cameraTarget + cameraOffset, projView); gizmos.HandleFrameEnter(scene, projView); // draw pick ray var viewProj = projView; viewProj.Transpose(); var ray = Ray.GetPickRay(input.X, input.Y, new ViewportF(0, 0, 1280, 720, 1.0f, 100.0f), viewProj); var nspheres = 100; var raySphereBatch = RenderJobBatch.Create(graphicsLoop.Presets.UnitCube); raySphereBatch.Wireframe = true; for (var i = 0; i < nspheres; i++) { raySphereBatch.Jobs.Add(new RenderJobDescription { WorldTransform = MatrixCM.Translation(ray.Position + ray.Direction * i / 10.0f) * MatrixCM.Scaling(0.01f), MaterialProperties = { Metallic = 0.0f, Roughness = 0.0f }, MaterialResourcesIndex = -1, Color = Color.Black, }); } //scene.AddRenderJobBatch(raySphereBatch); // Draw floor // scene.AddRenderable( // graphicsLoop.Presets.UnitCube, // MatrixCM.Scaling(4f, 0.1f, 4f) * MatrixCM.Translation(0, -0.5f, 0) * MatrixCM.RotationX((float)Math.PI), // new MaterialDescription { Properties = { Metallic = 0.0f, Roughness = 0.04f } }, // Color.White); // Draw sun // scene.AddRenderable( // graphicsLoop.Presets.UnitSphere, // MatrixCM.Translation(new Vector3(-10, 3, -3) * 3) * MatrixCM.Scaling(1 * 3), // new MaterialDescription { Properties = { Metallic = 0.0f, Roughness = 0.04f } }, // Color.Yellow); // Draw center cube / sphere scene.AddRenderable( false ? graphicsLoop.Presets.UnitCube : graphicsLoop.Presets.UnitSphere, MatrixCM.Translation(1, 0.5f, 0), new MaterialDescription { Properties = { Metallic = 0.0f, Roughness = 0.04f } }, Color.Red); scene.AddRenderable( false ? graphicsLoop.Presets.UnitCube : graphicsLoop.Presets.UnitSphere, MatrixCM.Translation(0, 1.5f, 0), new MaterialDescription { Properties = { Metallic = 0.0f, Roughness = 0.04f } }, Color.Lime); scene.AddRenderable( false ? graphicsLoop.Presets.UnitCube : graphicsLoop.Presets.UnitSphere, MatrixCM.Translation(0, 0.5f, 1), new MaterialDescription { Properties = { Metallic = 0.0f, Roughness = 0.04f } }, Color.Blue); // Draw floating cubes circling around center cube floatingCubesBatch.BatchTransform = MatrixCM.RotationY(t * (float)Math.PI / 10.0f); floatingCubesBatch.MaterialResourcesIndexOverride = scene.AddMaterialResources(new MaterialResourcesDescription { BaseTexture = graphicsLoop.Presets.SolidCubeTextures[Color.Red, Color.Cyan, Color.Lime, Color.Magenta, Color.Blue, Color.Yellow] }); if (false) { floatingCubesBatch.MaterialResourcesIndexOverride = -1; for (var i = 0; i < floatingCubesBatch.Jobs.Count; i++) { floatingCubesBatch.Jobs.store[i].MaterialResourcesIndex = scene.AddMaterialResources(new MaterialResourcesDescription { BaseTexture = graphicsLoop.Presets.SolidCubeTextures[new Color4(i / (float)(floatingCubesBatch.Jobs.Count - 1), 0, 0, 1)] }); } } // scene.AddRenderJobBatch(floatingCubesBatch); // Add spotlights scene.AddSpotlight( new Vector3(5, 4, 3), new Vector3(0, 0, 0), Vector3.Up, (float)Math.PI / 8.0f, Color.White, 100.0f, 0.0f, 6.0f, 3.0f, 0.5f / 256.0f); scene.AddSpotlight(new Vector3(5, 4, -5), new Vector3(0, 0, 0), Vector3.Up, (float)Math.PI / 8.0f, Color.White, 0.1f, 100.0f, 3.0f, 6.0f, 1.0f); // Draw the scene var snapshot = scene.ExportSnapshot(); renderer.RenderScene(snapshot); snapshot.ReleaseReference(); } }
private void RenderScene_Forward(IDeviceContext context, SceneSnapshot scene, IDepthStencilView backBufferDepthStencilView, IRenderTargetView backBufferRenderTargetView) { RenderShadowMaps(context, scene); // Restore backbuffer rendertarget + scene constant buffer + srvs. context.SetRenderTargets(backBufferDepthStencilView, backBufferRenderTargetView); context.SetViewportRect(new RectangleF(0, 0, backBufferRenderTargetView.Resolution.Width, backBufferRenderTargetView.Resolution.Height)); UpdateSceneConstantBuffer(context, new Vector4(scene.CameraEye, 1.0f), scene.ProjView, scene.ProjViewInv, scene.ProjView, scene.ProjViewInv, true, true, scene.SpotlightInfos.Count, scene.Time); // Clear render/depth, bind srvs after setrendertargets context.ClearRenderTarget(Color.Gray); context.ClearDepthBuffer(1.0f); BindCommonShaderResourceViews(context); // Atmosphere if (false) { _techniques.ForwardSkyFromAtmosphere.BeginPass(context, 0); context.SetDepthConfiguration(DepthConfiguration.Disabled); var(orthoProj, world) = ComputeSceneQuadProjWorld(backBufferRenderTargetView.Resolution, 0, 0, backBufferRenderTargetView.Resolution.Width, backBufferRenderTargetView.Resolution.Height); UpdateSceneConstantBuffer(context, new Vector4(scene.CameraEye, 1), orthoProj, MatrixCM.Invert(orthoProj), scene.ProjView, MatrixCM.Invert(scene.ProjView), false, false, scene.SpotlightInfos.Count, scene.Time); UpdateBatchConstantBuffer(context, Matrix.Identity, DiffuseTextureSamplingMode.FlatUV, 0); DrawScreenQuad(context, world, null); context.SetDepthConfiguration(DepthConfiguration.Enabled); { var projViewInv = MatrixCM.Invert(scene.ProjView); projViewInv.Transpose(); var a = Vector4.Transform(new Vector4(0, 0, 1, 1), projViewInv); a /= a.W; var av = (Vector3)a; av.Normalize(); var b = Vector4.Transform(new Vector4(1, 0, 1, 1), projViewInv); b /= b.W; var bv = (Vector3)b; bv.Normalize(); var c = Vector4.Transform(new Vector4(0, 1, 1, 1), projViewInv); c /= c.W; var cv = (Vector3)c; cv.Normalize(); Console.WriteLine(av + " " + bv + " " + cv); } } // Water if (false) { var pv = scene.ProjView; pv.Transpose(); Console.WriteLine("!!!!!" + Vector3.Transform(new Vector3(-5.00f, -2.18557e-07f, -5.00f), pv)); _techniques.ForwardWater.BeginPass(context, 0); UpdateSceneConstantBuffer(context, new Vector4(scene.CameraEye, 1), scene.ProjView, scene.ProjViewInv, scene.ProjView, scene.ProjViewInv, false, false, scene.SpotlightInfos.Count, scene.Time); UpdateBatchConstantBuffer(context, Matrix.Identity, DiffuseTextureSamplingMode.FlatUV, 0); var instancingBuffer = PickInstancingBuffer(8192); context.SetVertexBuffer(1, instancingBuffer); int n = 40; using (var updater = context.TakeUpdater(instancingBuffer)) { for (var y = -n; y <= n; y++) { for (var x = -n; x <= n; x++) { updater.Write(new RenderJobDescription { WorldTransform = MatrixCM.Scaling(10) * MatrixCM.Translation(x, 0, y) * MatrixCM.RotationX(-(float)Math.PI / 2.0f) * MatrixCM.Translation(-0.5f, -0.5f, 0), MaterialProperties = { Metallic = 0.0f, Roughness = 1.0f }, MaterialResourcesIndex = -1, Color = Color.White, }); } } } context.SetShaderResource(30, _graphicsFacade.Presets.SolidTextures[Color4.White], RenderStage.Pixel); var mrbu = context.TakeUpdater(_materialResourcesBuffer); mrbu.Write(new InternalMaterialResourcesDescription() { BaseColor = Color4.White }.Resolve(30)); mrbu.UpdateCloseAndDispose(); water.Render(context, (2 * n + 1) * (2 * n + 1)); } // Forward render pass for (var pass = 0; pass < _techniques.Forward.Passes; pass++) { _techniques.Forward.BeginPass(context, pass); foreach (var batch in scene.RenderJobBatches) { RenderBatch(context, scene, batch); } } }
public void HandleFrameEnter(Scene scene, Matrix projView) { var viewProj = projView; viewProj.Transpose(); var ray = Ray.GetPickRay(input.X, input.Y, new ViewportF(0, 0, 1280, 720, 1.0f, 100.0f), viewProj); if (input.IsMouseJustDown(MouseButtons.Left)) { var bbx = new BoundingBox(position - new Vector3(0.0f, 0.05f, 0.05f), position + new Vector3(HandleLength, 0.05f, 0.05f)); var bby = new BoundingBox(position - new Vector3(0.05f, 0.0f, 0.05f), position + new Vector3(0.05f, HandleLength, 0.05f)); var bbxy = new BoundingBox(position - new Vector3(0, 0.0f, 0.05f), position + new Vector3(HandleLength, HandleLength, 0.05f)); Vector3 intersectionPoint; if (selected && ray.Intersects(ref bbx, out intersectionPoint)) { isDraggingHandle = true; draggingPlane = new Plane(position, Vector3.UnitZ); dragDirectionBasis = new[] { Vector3.UnitX }; if (!ray.Intersects(ref draggingPlane, out Vector3 p)) { throw new InvalidOperationException(); } someDelta = p - position; } else if (selected && ray.Intersects(ref bby, out intersectionPoint)) { isDraggingHandle = true; draggingPlane = new Plane(position, Vector3.UnitZ); dragDirectionBasis = new[] { Vector3.UnitY }; if (!ray.Intersects(ref draggingPlane, out Vector3 p)) { throw new InvalidOperationException(); } someDelta = p - position; } else if (selected && ray.Intersects(ref bbxy, out intersectionPoint)) { isDraggingHandle = true; draggingPlane = new Plane(position, Vector3.UnitZ); dragDirectionBasis = new[] { Vector3.UnitX, Vector3.UnitY }; if (!ray.Intersects(ref draggingPlane, out Vector3 p)) { throw new InvalidOperationException(); } someDelta = p - position; } else { selected = ray.Intersects(new BoundingSphere(position, 0.5f)); Console.WriteLine(selected); } } if (input.IsMouseUp(MouseButtons.Left)) { isDraggingHandle = false; } if (isDraggingHandle) { if (!ray.Intersects(ref draggingPlane, out Vector3 intersectionPoint)) { throw new InvalidOperationException(); } var unconstrainedDelta = intersectionPoint - position - someDelta; var constrainedDelta = Vector3.Zero; foreach (var v in dragDirectionBasis) { var numerator = Vector3.Dot(v, unconstrainedDelta); var denominator = v.LengthSquared(); constrainedDelta += new Vector3( (v.X * numerator) / denominator, (v.Y * numerator) / denominator, (v.Z * numerator) / denominator); } position += constrainedDelta; } if (selected) { var sphereBatch = RenderJobBatch.Create(sphereMesh); sphereBatch.Wireframe = true; sphereBatch.Jobs.Add(new RenderJobDescription { Color = Color.Cyan, MaterialProperties = { Metallic = 0, Roughness = 0 }, MaterialResourcesIndex = -1, WorldTransform = MatrixCM.Translation(position) * MatrixCM.Scaling(1.1f) }); scene.AddRenderJobBatch(sphereBatch); scene.AddRenderable( cubeMesh, MatrixCM.Translation(position + new Vector3(HandleLength / 2, 0, 0)) * MatrixCM.Scaling(HandleLength, 0.1f, 0.1f), new MaterialDescription { Properties = { Metallic = 0.0f, Roughness = 0.04f } }, Color.Red); scene.AddRenderable( cubeMesh, MatrixCM.Translation(position + new Vector3(0, HandleLength / 2, 0)) * MatrixCM.Scaling(0.1f, HandleLength, 0.1f), new MaterialDescription { Properties = { Metallic = 0.0f, Roughness = 0.04f } }, Color.Lime); scene.AddRenderable( cubeMesh, MatrixCM.Translation(position + new Vector3(0, 0, HandleLength / 2)) * MatrixCM.Scaling(0.1f, 0.1f, HandleLength), new MaterialDescription { Properties = { Metallic = 0.0f, Roughness = 0.04f } }, Color.Blue); scene.AddRenderable( cubeMesh, MatrixCM.Translation(position + new Vector3(HandleLength / 2, HandleLength / 2, 0)) * MatrixCM.Scaling(HandleLength, HandleLength, 0.01f), new MaterialDescription { Properties = { Metallic = 0.0f, Roughness = 0.04f } }, Color.Yellow); scene.AddRenderable( sphereMesh, MatrixCM.Translation(position + new Vector3(HandleLength, HandleLength, 0)) * MatrixCM.Scaling(0.1f), new MaterialDescription { Properties = { Metallic = 0.0f, Roughness = 0.04f } }, Color.Blue); } }