//Load our default setup! private void SetUpEditorScene(GraphicsDevice graphics) { //////////////////////////////////////////////////////////////////////// // Camera //Set up our starting camera position // NOTE: Coordinate system depends on Camera.up, // Right now z is going up, it's not depth! Camera = new Camera(position: new Vector3(-88, -11f, 4), lookat: new Vector3(38, 8, 32)); EnvironmentSample = new EnvironmentSample(new Vector3(-45, -5, 5)); VolumeTexture = new VolumeTextureEntity("Content/Sponza/sponza_sdf.sdff", graphics, new Vector3(-7, 0, 63), new Vector3(200, 100, 100)) { NeedsUpdate = true }; _sdfGenerator = new SDFGenerator(); //////////////////////////////////////////////////////////////////////// // GUI //////////////////////////////////////////////////////////////////////// // Static geometry // NOTE: If you don't pass a materialEffect it will use the default material from the object BasicEntity testEntity = AddEntity(model: _assets.SponzaModel, position: Vector3.Zero, angleX: Math.PI / 2, angleY: 0, angleZ: 0, scale: 0.1f, hasStaticPhysics: false);//CHANGE BACK //AddEntity(model: _assets.CloneTrooper, // position: new Vector3(20, 0, 10), // angleX: Math.PI / 2, // angleY: 0, // angleZ: 0, // scale: 10.4f); for (int x = -5; x <= 5; x++) { for (int y = -5; y <= 5; y++) { AddEntity(model: _assets.Plane, materialEffect: ((x + 5 + y + 5) % 2 == 1) ? _assets.MirrorMaterial : _assets.MetalRough03Material, position: new Vector3(30 + x * 4, y * 4 + 4, 0), angleX: 0, angleY: 0, angleZ: 0, scale: 2); } } AddEntity(model: _assets.StanfordDragon, materialEffect: _assets.BaseMaterial, position: new Vector3(40, -10, 0), angleX: Math.PI / 2, angleY: 0, angleZ: 0, scale: 10); //////////////////////////////////////////////////////////////////////// // Dynamic geometry // NOTE: We first have to create a physics object and then apply said object to a rendered model // BEPU could use non-default meshes, but that is much much more expensive so I am using just default ones right now // ... so -> spheres, boxes etc. // For dynamic meshes I could use the same way i have static meshes, but use - MobileMesh - instead // NOTE: Our physics entity's position will be overwritten, so it doesn't matter // NOTE: If a physics object has mass it will move, otherwise it is static Entity physicsEntity; //Just a ground box where nothing should fall through //_physicsSpace.Add(new Box(new BEPUutilities.Vector3(0, 0, -0.5f), 1000, 1000, 1)); _physicsSpace.Add(physicsEntity = new Sphere(position: BEPUutilities.Vector3.Zero, radius: 5, mass: 50)); AddEntity(model: _assets.IsoSphere, materialEffect: _assets.AlphaBlendRim, position: new Vector3(20, 0, 10), angleX: Math.PI / 2, angleY: 0, angleZ: 0, scale: 5, PhysicsEntity: physicsEntity); testEntity.ApplyTransformation(); _sdfGenerator.Generate(testEntity); for (int i = 0; i < 10; i++) { MaterialEffect test = _assets.SilverMaterial.Clone(); test.Roughness = i / 9.0f + 0.1f; test.Metallic = 1; _physicsSpace.Add(physicsEntity = new Sphere(position: BEPUutilities.Vector3.Zero, radius: 5, mass: 50)); AddEntity(model: _assets.IsoSphere, materialEffect: test, position: new Vector3(30 + i * 10, 0, 10), angleX: Math.PI / 2, angleY: 0, angleZ: 0, scale: 5, PhysicsEntity: physicsEntity); } //////////////////////////////////////////////////////////////////////// // Decals Decals.Add(new Decal(_assets.IconDecal, new Vector3(-6, 22, 15), 0, -Math.PI / 2, 0, Vector3.One * 10)); //////////////////////////////////////////////////////////////////////// // Dynamic lights AddPointLight(position: new Vector3(-61, 0, 107), radius: 150, color: new Color(104, 163, 223), intensity: 20, castShadows: false, shadowResolution: 1024, staticShadow: false, isVolumetric: true); AddPointLight(position: new Vector3(15, 0, 107), radius: 150, color: new Color(104, 163, 223), intensity: 30, castShadows: false, shadowResolution: 1024, staticShadow: false, isVolumetric: true); AddPointLight(position: new Vector3(66, 0, 40), radius: 120, color: new Color(255, 248, 232), intensity: 120, castShadows: true, shadowResolution: 1024, softShadowBlurAmount: 0, staticShadow: false, isVolumetric: false); //volumetric light! //AddPointLight(position: new Vector3(-4, 40, 66), // radius: 80, // color: Color.White, // intensity: 50, // castShadows: true, // shadowResolution: 1024, // staticShadow: false, // isVolumetric: true, // volumetricDensity: 3); // Spawn a lot of lights to test performance //int sides = 4; //float distance = 20; //Vector3 startPosition = new Vector3(-30, 30, 1); ////amount of lights is sides*sides* sides*2 //for (int x = 0; x < sides * 2; x++) // for (int y = 0; y < sides; y++) // for (int z = 0; z < sides; z++) // { // Vector3 position = new Vector3(x, -y, z) * distance + startPosition; // AddPointLight(position, distance, FastRand.NextColor(), 50, false, false, 0.9f); // } //AddDirectionalLight(direction: new Vector3(0.2f, 0.2f, -1), // intensity: 100, // color: Color.White, // position: Vector3.UnitZ * 2, // drawShadows: true, // shadowWorldSize: 450, // shadowDepth: 180, // shadowResolution: 1024, // shadowFilteringFiltering: DirectionalLightSource.ShadowFilteringTypes.SoftPCF3x, // screenspaceShadowBlur: false); }
/// <summary> /// Update whether or not Objects are in the viewFrustum and need to be rendered or not. /// </summary> /// <param name="entities"></param> /// <param name="boundingFrustrum"></param> /// <param name="hasCameraChanged"></param> public bool FrustumCulling(List <BasicEntity> entities, BoundingFrustum boundingFrustrum, bool hasCameraChanged, Vector3 cameraPosition) { //Check if the culling mode has changed if (_previousMode != GameSettings.g_CPU_Culling) { if (_previousMode) { //If we previously did cull and now don't we need to set all the submeshes to render for (int index1 = 0; index1 < Index; index1++) { MaterialLibrary matLib = MaterialLib[index1]; for (int i = 0; i < matLib.Index; i++) { MeshLibrary meshLib = matLib.GetMeshLibrary()[i]; for (int j = 0; j < meshLib.Rendered.Length; j++) { meshLib.Rendered[j] = _previousMode; } } } } _previousMode = GameSettings.g_CPU_Culling; } if (!GameSettings.g_CPU_Culling) { return(false); } for (int index1 = 0; index1 < entities.Count; index1++) { BasicEntity entity = entities[index1]; if (!hasCameraChanged && !entity.WorldTransform.HasChanged)// && entity.DynamicPhysicsObject == null) { continue; } if (entity.WorldTransform.HasChanged)// || entity.DynamicPhysicsObject != null) { entity.ApplyTransformation(); } } bool hasAnythingChanged = false; //Ok we applied the transformation to all the entities, now update the submesh boundingboxes! // Parallel.For(0, Index, index1 => for (int index1 = 0; index1 < Index; index1++) { float distance = 0; int counter = 0; MaterialLibrary matLib = GameSettings.g_CPU_Sort ? MaterialLib[MaterialLibPointer[index1]] : MaterialLib[index1]; for (int i = 0; i < matLib.Index; i++) { MeshLibrary meshLib = matLib.GetMeshLibrary()[i]; float? distanceSq = meshLib.UpdatePositionAndCheckRender(hasCameraChanged, boundingFrustrum, cameraPosition, _defaultBoundingSphere); //If we get a new distance, apply it to the material if (distanceSq != null) { distance += (float)distanceSq; counter++; hasAnythingChanged = true; } } if (Math.Abs(distance) > 0.00001f) { distance /= counter; matLib.DistanceSquared = distance; matLib.HasChangedThisFrame = true; } } //); //finally sort the materials by distance. Bubble sort should in theory be fast here since little changes. if (hasAnythingChanged) { SortByDistance(); } return(hasAnythingChanged); }