/// <summary> /// Update shadow map. /// </summary> /// <param name="ctx"> /// A <see cref="GraphicsContext"/> used for allocating resources. /// </param> public override void UpdateShadowMap(GraphicsContext ctx, SceneGraph shadowGraph) { CheckCurrentContext(ctx); if (shadowGraph == null) { throw new ArgumentNullException("shadowGraph"); } // Compute light matrix IModelMatrix viewMatrix = new ModelMatrix(); // LocalModel.Multiply(LightMatrix.GetInverseMatrix()).GetInverseMatrix(); viewMatrix.LookAtDirection((Vertex3d)LocalModel.Position, (Vertex3f)Direction, Vertex3d.UnitY); // Set light scene view shadowGraph.ProjectionMatrix = new PerspectiveProjectionMatrix(FalloffAngle * 2.0f, 1.0f, 0.1f, 100.0f); shadowGraph.ViewMatrix = viewMatrix; _ShadowFramebuffer.BindDraw(ctx); // Reset viewport new ViewportState(0, 0, (int)_ShadowMap.Width, (int)_ShadowMap.Height).Apply(ctx, null); _ShadowFramebuffer.Clear(ctx, ClearBufferMask.DepthBufferBit); shadowGraph.Draw(ctx, _ShadowProgram); _ShadowFramebuffer.UnbindDraw(ctx); // Cache view matrix _ShadowViewMatrix = _BiasMatrix.Multiply(shadowGraph.ProjectionMatrix.Multiply(viewMatrix)); }
/// <summary> /// Extract the top plane from a model-view-projection matrix. /// </summary> /// <param name="modelViewProjection"> /// The <see cref="IMatrix4x4"/> that specify the matrix used for drawing the clipped object. /// </param> /// <returns> /// It returns a <see cref="Plane"/> defining the top clipping plane. /// </returns> public static Plane GetFrustumTopPlane(IMatrix4x4 modelViewProjection) { // Compute plane Vertex4d a = new Vertex4d(modelViewProjection.GetRow(3)); Vertex4d b = new Vertex4d(modelViewProjection.GetRow(1)); return(NormalizePlane(NameTop, a - b)); }
/// <summary> /// Extract the far plane from a model-view-projection matrix. /// </summary> /// <param name="modelViewProjection"> /// The <see cref="IMatrix4x4"/> that specify the matrix used for drawing the clipped object. /// </param> /// <returns> /// It returns a <see cref="Plane"/> defining the far clipping plane. /// </returns> public static Plane GetFrustumFarPlane(IMatrix4x4 modelViewProjection) { // Compute plane Vertex4d a = new Vertex4d(modelViewProjection.GetRow(2)); Vertex4d b = new Vertex4d(modelViewProjection.GetRow(3)); return(NormalizePlane(NameFar, b - a)); }
/// <summary> /// Extract the far plane from a model-view-projection matrix. /// </summary> /// <param name="modelViewProjection"> /// The <see cref="IMatrix4x4"/> that specify the matrix used for drawing the clipped object. /// </param> /// <returns> /// It returns a <see cref="Plane"/> defining the far clipping plane. /// </returns> public static Plane GetFrustumFarPlane(IMatrix4x4 modelViewProjection) { // Compute plane Vertex4d a = new Vertex4d(modelViewProjection.GetRow(3)); Vertex4d b = new Vertex4d(modelViewProjection.GetRow(2)); Plane plane = NormalizePlane(NameFar, a - b); plane.Distance = -plane.Distance; return(plane); }
private void RenderChildren(RenderObject obj, IMatrix4x4 viewProjectionMatrix, Camera camera) { foreach (RenderObject child in obj.Children) { RenderChildren(child, viewProjectionMatrix, camera); } if (obj.Model?.Mesh != null && obj.Model?.Shader != null) { Vector <double> cameraPos = camera.GetWorldPosition().Subtract(obj.GetWorldPosition()); RenderModel(obj.Model, viewProjectionMatrix, obj.GetObjectToWorldTransform(), cameraPos); } }
/// <summary> /// Extract all six planes from a model-view-projection matrix. /// </summary> /// <param name="modelViewProjection"> /// The <see cref="IMatrix4x4"/> that specify the matrix used for drawing the clipped object. /// </param> /// <returns> /// It returns a <see cref="IEnumerable{Plane}"/> containing all six clipping planes defined /// by <paramref name="modelViewProjection"/>. /// </returns> public static IEnumerable <Plane> GetFrustumPlanes(IMatrix4x4 modelViewProjection) { List <Plane> planes = new List <Plane>(6); planes.Add(GetFrustumLeftPlane(modelViewProjection)); planes.Add(GetFrustumRightPlane(modelViewProjection)); planes.Add(GetFrustumNearPlane(modelViewProjection)); planes.Add(GetFrustumFarPlane(modelViewProjection)); planes.Add(GetFrustumBottomPlane(modelViewProjection)); planes.Add(GetFrustumTopPlane(modelViewProjection)); return(planes); }
/// <summary> /// Get all geometries compositing this SceneObjectGeometry, filtering them using view-frustum. /// </summary> /// <param name="currentState"> /// A <see cref="State.GraphicsStateSet"/> that specifies the current graphics state to be merged with /// each returned geometry. /// </param> /// <param name="clippingPlanes"> /// /// </param> /// <param name="viewModel"> /// /// </param> /// <returns> /// It returns a <see cref="IEnumerable{SceneObjectBatch}"/>. /// </returns> private IEnumerable <SceneObjectBatch> GetGeometriesViewFrustum(SceneGraphContext ctxScene) { GraphicsStateSet currentState = ctxScene.GraphicsStateStack.Current.Push(); TransformStateBase sceneGeometryModel = (TransformStateBase)currentState[TransformStateBase.StateSetIndex]; IMatrix4x4 viewModel = sceneGeometryModel.ModelView; if (_GeometryInstances.Count > 0) { foreach (Geometry sceneObjectBatch in _GeometryInstances) { IBoundingVolume instanceVolume = sceneObjectBatch.BoundingVolume ?? _BoundingVolume; if (instanceVolume != null && instanceVolume.IsClipped(ctxScene.ViewFrustumPlanes, viewModel)) { continue; } GraphicsStateSet geometryState; if (sceneObjectBatch.State != null) { geometryState = currentState.Push(); geometryState.Merge(sceneObjectBatch.State); } else { geometryState = currentState; } yield return(new SceneObjectBatch( sceneObjectBatch.VertexArray ?? VertexArray, geometryState, sceneObjectBatch.Program ?? Program )); } } else { if (_BoundingVolume != null && _BoundingVolume.IsClipped(ctxScene.ViewFrustumPlanes, viewModel)) { yield break; } if (VertexArray == null) { yield break; } yield return(new SceneObjectBatch(VertexArray, currentState, Program)); } }
public void Render(int width, int height, RenderObject root, Camera camera) { Gl.Viewport(0, 0, width, height); Gl.Enable(EnableCap.DepthTest); Gl.Enable(EnableCap.CullFace); Gl.CullFace(CullFaceMode.Back); Gl.ClearColor(0, 0, 0, 1); Gl.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); IMatrix4x4 viewMatrix = CreateViewMatrix(camera); IMatrix4x4 projectionMatrix = CreateProjectionMatrix(camera); IMatrix4x4 viewProjectionMatrix = projectionMatrix.Multiply(viewMatrix); RenderChildren(root, viewProjectionMatrix, camera); }
private void RenderModel(Render.Model model, IMatrix4x4 viewProjectionMatrix, Matrix <double> modelMatrix, Vector <double> cameraPosition) { if (!model.Shader.SetUniformMatrix("viewProjectionTransformation", viewProjectionMatrix)) { throw new Exception("Vertex shader is missing 'viewProjectionTransformation'"); } if (!model.Shader.SetUniformMatrix("modelTransformation", modelMatrix)) { throw new Exception("Vertex shader is missing 'modelTransformation'"); } model.Shader.SetUniformVector("cameraPos", cameraPosition); Gl.BindVertexArray(model.Mesh.VertexArrayObjectId); Gl.ActiveTexture(TextureUnit.Texture0); Gl.BindTexture(TextureTarget.Texture2d, model.Texture?.Id ?? 0); Gl.UseProgram(model.Shader.Id); Gl.DrawElements(PrimitiveType.Triangles, model.Mesh.IndexCount, DrawElementsType.UnsignedInt, IntPtr.Zero); }
/// <summary> /// Determine whether this bound volume is clipped by all specified planes. /// </summary> /// <param name="clippingPlanes"> /// A <see cref="IEnumerable{Plane}"/> that are used to perform geometry clipping. /// </param> /// <returns> /// It returns a boolean value indicating whether this bound volume is entirely /// clipped by <paramref name="clippingPlanes"/>. /// </returns> public bool IsClipped(IEnumerable <Plane> clippingPlanes, IMatrix4x4 viewModel) { if (clippingPlanes == null) { throw new ArgumentNullException("clippingPlanes"); } Vertex3f[] boundVertices = new Vertex3f[8]; Vertex3f[] viewVertices = new Vertex3f[2]; for (int i = 0; i < 2; i++) { viewVertices[i] = (Vertex3f)viewModel.Multiply(_Bounds[i]); } // Lower box vertices boundVertices[0] = new Vertex3f(viewVertices[1].x, viewVertices[0].y, viewVertices[1].z); boundVertices[1] = new Vertex3f(viewVertices[0].x, viewVertices[0].y, viewVertices[1].z); boundVertices[2] = new Vertex3f(viewVertices[0].x, viewVertices[0].y, viewVertices[0].z); boundVertices[3] = new Vertex3f(viewVertices[1].x, viewVertices[0].y, viewVertices[0].z); // Higher box vertices boundVertices[4] = new Vertex3f(viewVertices[1].x, viewVertices[1].y, viewVertices[1].z); boundVertices[5] = new Vertex3f(viewVertices[0].x, viewVertices[1].y, viewVertices[1].z); boundVertices[6] = new Vertex3f(viewVertices[0].x, viewVertices[1].y, viewVertices[0].z); boundVertices[7] = new Vertex3f(viewVertices[1].x, viewVertices[1].y, viewVertices[0].z); foreach (Plane clipPlane in clippingPlanes) { bool outsidePlane = true; for (int i = 0; i < boundVertices.Length && outsidePlane; i++) { outsidePlane &= clipPlane.GetDistance(boundVertices[i]) < 0.0f; } if (outsidePlane) { return(true); } } return(false); }
internal IEnumerable <SceneObjectBatch> GetBoundingVolumes(SceneGraphContext ctxScene) { GraphicsStateSet currentState = ctxScene.GraphicsStateStack.Current.Push(); TransformStateBase sceneGeometryModel = (TransformStateBase)currentState[TransformStateBase.StateSetIndex]; IMatrix4x4 viewModel = sceneGeometryModel.ModelView; if (_GeometryInstances.Count > 0) { foreach (Geometry sceneObjectBatch in _GeometryInstances) { IBoundingVolume instanceVolume = sceneObjectBatch.BoundingVolume ?? _BoundingVolume; if (instanceVolume != null && instanceVolume.IsClipped(ctxScene.ViewFrustumPlanes, viewModel)) { continue; } GraphicsStateSet volumeState = currentState.Push(); SetBoundingVolumeState(instanceVolume, volumeState); yield return(new SceneObjectBatch( _BoundingVolumeArray, volumeState, _BoundingVolumeProgram )); } } else { if (_BoundingVolume == null || _BoundingVolume.IsClipped(ctxScene.ViewFrustumPlanes, viewModel)) { yield break; } GraphicsStateSet volumeState = currentState.Push(); SetBoundingVolumeState(_BoundingVolume, volumeState); yield return(new SceneObjectBatch(_BoundingVolumeArray, volumeState, _BoundingVolumeProgram)); } }
public void TestProjectionFrustum() { PerspectiveProjectionMatrix projectionMatrix = new PerspectiveProjectionMatrix(90.0f, 1.0f, 1.0f, 10.0f); ModelMatrix modelMatrix = new ModelMatrix(); IMatrix4x4 frustumMatrix = projectionMatrix * modelMatrix; Plane planeL = Plane.GetFrustumLeftPlane(frustumMatrix); Plane planeR = Plane.GetFrustumRightPlane(frustumMatrix); Plane planeB = Plane.GetFrustumBottomPlane(frustumMatrix); Plane planeT = Plane.GetFrustumTopPlane(frustumMatrix); Plane planeN = Plane.GetFrustumNearPlane(frustumMatrix); Assert.IsTrue(planeN.GetDistance(new Vertex3f(0.0f, 0.0f, -5.0f)) > 0.0f); Plane planeF = Plane.GetFrustumFarPlane(frustumMatrix); Assert.IsTrue(planeF.GetDistance(new Vertex3f(0.0f, 0.0f, -5.0f)) > 0.0f); }
/// <summary> /// Set uniform state variable (variant type). /// </summary> /// <param name="ctx"> /// A <see cref="GraphicsContext"/> used for operations. /// </param> /// <param name="uniformName"> /// A <see cref="String"/> that specify the variable name in the shader source. /// </param> /// <param name="m"> /// A <see cref="IMatrix4x4"/> holding the uniform variabile data. /// </param> public void SetVariantUniform(GraphicsContext ctx, string uniformName, IMatrix4x4 m) { if (ctx == null) { throw new ArgumentNullException("ctx"); } UniformBinding uniform = GetUniform(uniformName); switch (uniform.UniformType) { case ShaderUniformType.Mat4x4: SetUniform(ctx, uniformName, (Matrix4x4)m); break; case ShaderUniformType.DoubleMat4x4: SetUniform(ctx, uniformName, (MatrixDouble4x4)m); break; default: throw new ShaderException("unable to set double-precision floating-point matrix 4x4 data to uniform of type {0}", uniform.UniformType); } }
/// <summary> /// Compute the product of this IMatrix with another IMatrix. /// </summary> /// <param name="a"> /// A <see cref="IMatrix4x4"/> that specify the right multiplication operand. /// </param> /// <returns> /// A <see cref="IMatrix"/> resulting from the product of this matrix and the matrix <paramref name="a"/>. /// </returns> IMatrix4x4 IMatrix4x4.Multiply(IMatrix4x4 a) { if (a == null) { throw new ArgumentNullException("a"); } MatrixDouble4x4 otherMatrix = a as MatrixDouble4x4; if (otherMatrix != null) { return(this * otherMatrix); } Matrix4x4 otherMatrix4x4 = a as Matrix4x4; if (otherMatrix4x4 != null) { return(this * (MatrixDouble4x4)otherMatrix4x4); } throw new NotSupportedException("unknown IMatrix4x4 implementation"); }
/// <summary> /// Set uniform state variable (variant type). /// </summary> /// <param name="ctx"> /// A <see cref="GraphicsContext"/> used for operations. /// </param> /// <param name="uniformName"> /// A <see cref="String"/> that specify the variable name in the shader source. /// </param> /// <param name="m"> /// A <see cref="IMatrix4x4"/> holding the uniform variabile data. /// </param> public void SetVariantUniform(GraphicsContext ctx, string uniformName, IMatrix4x4 m) { if (ctx == null) throw new ArgumentNullException("ctx"); UniformBinding uniform = GetUniform(uniformName); switch (uniform.UniformType) { case ShaderUniformType.Mat4x4: SetUniform(ctx, uniformName, (Matrix4x4)m); break; case ShaderUniformType.DoubleMat4x4: SetUniform(ctx, uniformName, (MatrixDouble4x4)m); break; default: throw new ShaderException("unable to set double-precision floating-point matrix 4x4 data to uniform of type {0}", uniform.UniformType); } }
internal IEnumerable <SceneObjectBatch> GetGeometries(State.GraphicsStateSet currentState, IEnumerable <Plane> clippingPlanes, IMatrix4x4 viewModel) { if (_GeometryInstances.Count > 0) { foreach (Geometry sceneObjectBatch in _GeometryInstances) { IBoundingVolume instanceVolume = sceneObjectBatch.BoundingVolume ?? _BoundingVolume; if (instanceVolume != null && instanceVolume.IsClipped(clippingPlanes, viewModel)) { continue; } State.GraphicsStateSet geometryState; if (sceneObjectBatch.State != null) { geometryState = currentState.Push(); geometryState.Merge(sceneObjectBatch.State); } else { geometryState = currentState; } yield return(new SceneObjectBatch( sceneObjectBatch.VertexArray ?? VertexArray, geometryState, sceneObjectBatch.Program ?? Program )); } } else { if (_BoundingVolume != null && _BoundingVolume.IsClipped(clippingPlanes, viewModel)) { yield break; } yield return(new SceneObjectBatch(VertexArray, currentState, Program)); } }
/// <summary> /// Matrix copy constructor. /// </summary> /// <param name="m"> /// A <see cref="Matrix"/> to be copied. /// </param> public Matrix4x4(IMatrix4x4 m) : base(m) { }
/// <summary> /// Matrix copy constructor. /// </summary> /// <param name="m"> /// A <see cref="Matrix"/> to be copied. /// </param> public Matrix4x4(IMatrix4x4 m) : base(m) { }
/// <summary> /// Compute the product of this IMatrix with another IMatrix. /// </summary> /// <param name="a"> /// A <see cref="IMatrix4x4"/> that specifies the right multiplication operand. /// </param> /// <returns> /// A <see cref="IMatrix"/> resulting from the product of this matrix and the matrix <paramref name="a"/>. /// </returns> IMatrix4x4 IMatrix4x4.Multiply(IMatrix4x4 a) { if (a == null) throw new ArgumentNullException("a"); Matrix4x4 otherMatrix4x4 = a as Matrix4x4; if (otherMatrix4x4 != null) return (this * otherMatrix4x4); MatrixDouble4x4 otherMatrixDouble4x4 = a as MatrixDouble4x4; if (otherMatrixDouble4x4 != null) return ((MatrixDouble4x4)this * otherMatrixDouble4x4); throw new NotSupportedException("unknown IMatrix4x4 implementation"); }
bool IBoundingVolume.IsClipped(IEnumerable <Plane> clippingPlanes, IMatrix4x4 viewModel) { throw new NotImplementedException(); }