/// <summary>Function called to update items per frame on the layer.</summary> protected override void OnUpdate() { if (Camera.NeedsUpdate) { if (Camera.ProjectionChanged) { Camera.GetProjectionMatrix(out DX.Matrix projectionMatrix); SetProjection(ref projectionMatrix); } if (Camera.ViewChanged) { Camera.GetViewMatrix(out DX.Matrix viewMatrix); SetView(ref viewMatrix); } } Camera.GetViewMatrix(out DX.Matrix view); _drawPlanets.Clear(); for (int i = 0; i < Planets.Count; ++i) { Planet planet = Planets[i]; planet.Update(); DX.RectangleF aabb = DX.RectangleF.Empty; for (int j = 0; j < planet.Layers.Count; ++j) { PlanetaryLayer layer = planet.Layers[j]; DX.Vector3 originalPosition = layer.Mesh.Position; UpdateMeshWorldMatrix(layer.Mesh); DX.RectangleF meshAabb = layer.Mesh.GetAABB(); if (!meshAabb.IsEmpty) { if (aabb.IsEmpty) { aabb = meshAabb; } else { aabb = DX.RectangleF.Union(meshAabb, aabb); } } layer.Mesh.Position = originalPosition; } // Cull the planet if it's outside of our view. if (Camera.ViewableRegion.Intersects(aabb)) { _drawPlanets.Add(planet); } } }
/// <summary> /// Function to load the resources for the layer. /// </summary> public override void LoadResources() { _drawCalls = new List <GorgonDrawIndexCall>(); BuildConstantBuffers(); for (int i = 0; i < Planets.Count; ++i) { Planet planet = Planets[i]; for (int j = 0; j < planet.Layers.Count; ++j) { PlanetaryLayer layer = planet.Layers[j]; GorgonVertexShader vertexShader = _resources.VertexShaders[layer.Mesh.Material.VertexShader]; GorgonPixelShader pixelShader = _resources.PixelShaders[layer.Mesh.Material.PixelShader]; // Create our vertex layout now. if (_vertexLayout == null) { _vertexLayout = _vertexLayout = GorgonInputLayout.CreateUsingType <Vertex3D>(_graphics, vertexShader); } // Set up a pipeline state for the mesh. GorgonPipelineState pipelineState = _stateBuilder.Clear() .PixelShader(pixelShader) .VertexShader(vertexShader) .BlendState(layer.Mesh.Material.BlendState) .PrimitiveType(PrimitiveType.TriangleList) .Build(); _drawCallBuilder.Clear() .PipelineState(pipelineState) .IndexBuffer(layer.Mesh.IndexBuffer, 0, layer.Mesh.IndexCount) .VertexBuffer(_vertexLayout, new GorgonVertexBufferBinding(layer.Mesh.VertexBuffer, Vertex3D.Size)) .ConstantBuffer(ShaderType.Vertex, _viewProjectionBuffer) .ConstantBuffer(ShaderType.Vertex, _worldBuffer, 1) .ConstantBuffer(ShaderType.Pixel, _cameraBuffer) .ConstantBuffer(ShaderType.Pixel, _lightBuffer, 1) .ConstantBuffer(ShaderType.Pixel, _materialBuffer, 2); (int startTexture, int textureCount) = layer.Mesh.Material.Textures.GetDirtyItems(); for (int k = startTexture; k < startTexture + textureCount; ++k) { GorgonTexture2DView texture = _resources.Textures[layer.Mesh.Material.Textures[k]]; _drawCallBuilder.ShaderResource(ShaderType.Pixel, texture, k); // We should have this in the material, but since we know what we've got here, this will be fine. _drawCallBuilder.SamplerState(ShaderType.Pixel, GorgonSamplerState.Wrapping, k); } _drawCalls.Add(_drawCallBuilder.Build()); } } UpdateLightTransforms(); }
/// <summary> /// Function to render the layer data. /// </summary> public override void Render() { int drawCallIndex = 0; if (_drawPlanets.Count == 0) { return; } // Apply active lights Array.Clear(_lightData, 0, _lightData.Length); for (int i = 0; i < ActiveLights.Count.Min(_lightData.Length); ++i) { Light light = ActiveLights[i]; if (light == null) { continue; } _lightData[i] = new LightData { SpecularPower = light.SpecularPower, Attenuation = light.Attenuation, LightColor = light.Color, LightPosition = new DX.Vector3(light.Position.X, light.Position.Y, -light.Position.Z), SpecularColor = GorgonColor.White, Intensity = light.Intensity }; } if (ActiveLights.Count > 0) { _lightBuffer.Buffer.SetData(_lightData); } for (int i = 0; i < _drawPlanets.Count; ++i) { Planet planet = _drawPlanets[i]; for (int j = 0; j < planet.Layers.Count; ++j) { PlanetaryLayer layer = planet.Layers[j]; MoveableMesh mesh = layer.Mesh; UpdateMaterial(mesh); UpdateWorldTransform(mesh); _graphics.Submit(_drawCalls[drawCallIndex++]); } } }