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(); } }