Beispiel #1
0
        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,
            });
        }
Beispiel #3
0
        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);
                }
            }
        }
Beispiel #5
0
        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);
            }
        }