// render scene internal void RenderScene(double TimeElapsed) { // initialize ResetOpenGlState(); if (OptionWireFrame) { if (Program.CurrentRoute.CurrentFog.Start < Program.CurrentRoute.CurrentFog.End) { const float fogDistance = 600.0f; float n = (fogDistance - Program.CurrentRoute.CurrentFog.Start) / (Program.CurrentRoute.CurrentFog.End - Program.CurrentRoute.CurrentFog.Start); float cr = n * inv255 * Program.CurrentRoute.CurrentFog.Color.R; float cg = n * inv255 * Program.CurrentRoute.CurrentFog.Color.G; float cb = n * inv255 * Program.CurrentRoute.CurrentFog.Color.B; GL.ClearColor(cr, cg, cb, 1.0f); } else { GL.ClearColor(0.0f, 0.0f, 0.0f, 1.0f); } } GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); UpdateViewport(ViewportChangeMode.ChangeToScenery); // set up camera CurrentViewMatrix = Matrix4D.LookAt(Vector3.Zero, new Vector3(Camera.AbsoluteDirection.X, Camera.AbsoluteDirection.Y, -Camera.AbsoluteDirection.Z), new Vector3(Camera.AbsoluteUp.X, Camera.AbsoluteUp.Y, -Camera.AbsoluteUp.Z)); GL.Light(LightName.Light0, LightParameter.Position, new[] { (float)Lighting.OptionLightPosition.X, (float)Lighting.OptionLightPosition.Y, (float)-Lighting.OptionLightPosition.Z, 0.0f }); Lighting.OptionLightingResultingAmount = (Lighting.OptionAmbientColor.R + Lighting.OptionAmbientColor.G + Lighting.OptionAmbientColor.B) / 480.0f; if (Lighting.OptionLightingResultingAmount > 1.0f) { Lighting.OptionLightingResultingAmount = 1.0f; } // fog double fd = Program.CurrentRoute.NextFog.TrackPosition - Program.CurrentRoute.PreviousFog.TrackPosition; if (fd != 0.0) { float fr = (float)((CameraTrackFollower.TrackPosition - Program.CurrentRoute.PreviousFog.TrackPosition) / fd); float frc = 1.0f - fr; Program.CurrentRoute.CurrentFog.Start = Program.CurrentRoute.PreviousFog.Start * frc + Program.CurrentRoute.NextFog.Start * fr; Program.CurrentRoute.CurrentFog.End = Program.CurrentRoute.PreviousFog.End * frc + Program.CurrentRoute.NextFog.End * fr; Program.CurrentRoute.CurrentFog.Color.R = (byte)(Program.CurrentRoute.PreviousFog.Color.R * frc + Program.CurrentRoute.NextFog.Color.R * fr); Program.CurrentRoute.CurrentFog.Color.G = (byte)(Program.CurrentRoute.PreviousFog.Color.G * frc + Program.CurrentRoute.NextFog.Color.G * fr); Program.CurrentRoute.CurrentFog.Color.B = (byte)(Program.CurrentRoute.PreviousFog.Color.B * frc + Program.CurrentRoute.NextFog.Color.B * fr); } else { Program.CurrentRoute.CurrentFog = Program.CurrentRoute.PreviousFog; } // render background GL.Disable(EnableCap.DepthTest); Program.CurrentRoute.UpdateBackground(TimeElapsed, Program.Renderer.CurrentInterface != InterfaceType.Normal); events.Render(Camera.AbsolutePosition); // fog float aa = Program.CurrentRoute.CurrentFog.Start; float bb = Program.CurrentRoute.CurrentFog.End; if (aa < bb & aa < Program.CurrentRoute.CurrentBackground.BackgroundImageDistance) { OptionFog = true; Fog.Start = aa; Fog.End = bb; Fog.Color = Program.CurrentRoute.CurrentFog.Color; SetFogForImmediateMode(); } else { OptionFog = false; } // world layer // opaque face if (AvailableNewRenderer) { //Setup the shader for rendering the scene DefaultShader.Activate(); if (OptionLighting) { DefaultShader.SetIsLight(true); DefaultShader.SetLightPosition(Lighting.OptionLightPosition); DefaultShader.SetLightAmbient(Lighting.OptionAmbientColor); DefaultShader.SetLightDiffuse(Lighting.OptionDiffuseColor); DefaultShader.SetLightSpecular(Lighting.OptionSpecularColor); } if (OptionFog) { DefaultShader.SetIsFog(true); DefaultShader.SetFogStart(Fog.Start); DefaultShader.SetFogEnd(Fog.End); DefaultShader.SetFogColor(Fog.Color); } DefaultShader.SetTexture(0); DefaultShader.SetCurrentProjectionMatrix(CurrentProjectionMatrix); } ResetOpenGlState(); foreach (FaceState face in VisibleObjects.OpaqueFaces) { if (AvailableNewRenderer) { RenderFace(DefaultShader, face); } else { RenderFaceImmediateMode(face); } } // alpha face ResetOpenGlState(); VisibleObjects.SortPolygonsInAlphaFaces(); if (Interface.CurrentOptions.TransparencyMode == TransparencyMode.Performance) { SetBlendFunc(); SetAlphaFunc(AlphaFunction.Greater, 0.0f); GL.DepthMask(false); foreach (FaceState face in VisibleObjects.AlphaFaces) { if (AvailableNewRenderer) { RenderFace(DefaultShader, face); } else { RenderFaceImmediateMode(face); } } } else { UnsetBlendFunc(); SetAlphaFunc(AlphaFunction.Equal, 1.0f); GL.DepthMask(true); foreach (FaceState face in VisibleObjects.AlphaFaces) { if (face.Object.Prototype.Mesh.Materials[face.Face.Material].BlendMode == MeshMaterialBlendMode.Normal && face.Object.Prototype.Mesh.Materials[face.Face.Material].GlowAttenuationData == 0) { if (face.Object.Prototype.Mesh.Materials[face.Face.Material].Color.A == 255) { if (AvailableNewRenderer) { RenderFace(DefaultShader, face); } else { RenderFaceImmediateMode(face); } } } } SetBlendFunc(); SetAlphaFunc(AlphaFunction.Less, 1.0f); GL.DepthMask(false); bool additive = false; foreach (FaceState face in VisibleObjects.AlphaFaces) { if (face.Object.Prototype.Mesh.Materials[face.Face.Material].BlendMode == MeshMaterialBlendMode.Additive) { if (!additive) { UnsetAlphaFunc(); additive = true; } if (AvailableNewRenderer) { RenderFace(DefaultShader, face); } else { RenderFaceImmediateMode(face); } } else { if (additive) { SetAlphaFunc(); additive = false; } if (AvailableNewRenderer) { RenderFace(DefaultShader, face); } else { RenderFaceImmediateMode(face); } } } } // motion blur ResetOpenGlState(); SetAlphaFunc(AlphaFunction.Greater, 0.0f); GL.Disable(EnableCap.DepthTest); GL.DepthMask(false); OptionLighting = false; if (Interface.CurrentOptions.MotionBlur != MotionBlurMode.None) { DefaultShader.Deactivate(); MotionBlur.RenderFullscreen(Interface.CurrentOptions.MotionBlur, FrameRate, Math.Abs(Camera.CurrentSpeed)); } // overlay layer OptionFog = false; UpdateViewport(ViewportChangeMode.ChangeToCab); if (AvailableNewRenderer) { /* * We must reset the shader between overlay and world layers for correct lighting results. * Additionally, the viewport change updates the projection matrix */ DefaultShader.Activate(); ResetShader(DefaultShader); DefaultShader.SetCurrentProjectionMatrix(CurrentProjectionMatrix); } CurrentViewMatrix = Matrix4D.LookAt(Vector3.Zero, new Vector3(Camera.AbsoluteDirection.X, Camera.AbsoluteDirection.Y, -Camera.AbsoluteDirection.Z), new Vector3(Camera.AbsoluteUp.X, Camera.AbsoluteUp.Y, -Camera.AbsoluteUp.Z)); if (Camera.CurrentRestriction == CameraRestrictionMode.NotAvailable || Camera.CurrentRestriction == CameraRestrictionMode.Restricted3D) { ResetOpenGlState(); // TODO: inserted GL.Clear(ClearBufferMask.DepthBufferBit); OptionLighting = true; Color24 prevOptionAmbientColor = Lighting.OptionAmbientColor; Color24 prevOptionDiffuseColor = Lighting.OptionDiffuseColor; Lighting.OptionAmbientColor = Color24.LightGrey; Lighting.OptionDiffuseColor = Color24.LightGrey; if (AvailableNewRenderer) { DefaultShader.SetIsLight(true); DefaultShader.SetLightPosition(Lighting.OptionLightPosition); DefaultShader.SetLightAmbient(Lighting.OptionAmbientColor); DefaultShader.SetLightDiffuse(Lighting.OptionDiffuseColor); DefaultShader.SetLightSpecular(Lighting.OptionSpecularColor); } GL.Light(LightName.Light0, LightParameter.Ambient, new[] { inv255 * 178, inv255 * 178, inv255 * 178, 1.0f }); GL.Light(LightName.Light0, LightParameter.Diffuse, new[] { inv255 * 178, inv255 * 178, inv255 * 178, 1.0f }); // overlay opaque face foreach (FaceState face in VisibleObjects.OverlayOpaqueFaces) { if (AvailableNewRenderer) { RenderFace(DefaultShader, face); } else { RenderFaceImmediateMode(face); } } // overlay alpha face ResetOpenGlState(); VisibleObjects.SortPolygonsInOverlayAlphaFaces(); if (Interface.CurrentOptions.TransparencyMode == TransparencyMode.Performance) { SetBlendFunc(); SetAlphaFunc(AlphaFunction.Greater, 0.0f); GL.DepthMask(false); foreach (FaceState face in VisibleObjects.OverlayAlphaFaces) { if (AvailableNewRenderer) { RenderFace(DefaultShader, face); } else { RenderFaceImmediateMode(face); } } } else { UnsetBlendFunc(); SetAlphaFunc(AlphaFunction.Equal, 1.0f); GL.DepthMask(true); foreach (FaceState face in VisibleObjects.OverlayAlphaFaces) { if (face.Object.Prototype.Mesh.Materials[face.Face.Material].BlendMode == MeshMaterialBlendMode.Normal && face.Object.Prototype.Mesh.Materials[face.Face.Material].GlowAttenuationData == 0) { if (face.Object.Prototype.Mesh.Materials[face.Face.Material].Color.A == 255) { if (AvailableNewRenderer) { RenderFace(DefaultShader, face); } else { RenderFaceImmediateMode(face); } } } } SetBlendFunc(); SetAlphaFunc(AlphaFunction.Less, 1.0f); GL.DepthMask(false); bool additive = false; foreach (FaceState face in VisibleObjects.OverlayAlphaFaces) { if (face.Object.Prototype.Mesh.Materials[face.Face.Material].BlendMode == MeshMaterialBlendMode.Additive) { if (!additive) { UnsetAlphaFunc(); additive = true; } if (AvailableNewRenderer) { RenderFace(DefaultShader, face); } else { RenderFaceImmediateMode(face); } } else { if (additive) { SetAlphaFunc(); additive = false; } if (AvailableNewRenderer) { RenderFace(DefaultShader, face); } else { RenderFaceImmediateMode(face); } } } } Lighting.OptionAmbientColor = prevOptionAmbientColor; Lighting.OptionDiffuseColor = prevOptionDiffuseColor; Lighting.Initialize(); } else { /* * Render 2D Cab * This is actually an animated object generated on the fly and held in memory */ ResetOpenGlState(); OptionLighting = false; SetBlendFunc(); UnsetAlphaFunc(); GL.Disable(EnableCap.DepthTest); GL.DepthMask(false); VisibleObjects.SortPolygonsInOverlayAlphaFaces(); foreach (FaceState face in VisibleObjects.OverlayAlphaFaces) { if (AvailableNewRenderer) { RenderFace(DefaultShader, face); } else { RenderFaceImmediateMode(face); } } } if (AvailableNewRenderer) { /* * Must remember to de-activate at the end of the render sequence if in GL3 mode. * The overlays currently use immediate mode and do not work correctly with the shader active */ DefaultShader.Deactivate(); } // render touch OptionLighting = false; Touch.RenderScene(); // render overlays ResetOpenGlState(); UnsetAlphaFunc(); SetBlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); //FIXME: Remove when text switches between two renderer types GL.Disable(EnableCap.DepthTest); overlays.Render(TimeElapsed); OptionLighting = true; }
// render scene internal void RenderScene(double TimeElapsed) { // initialize ResetOpenGlState(); if (OptionWireFrame) { if (Program.CurrentRoute.CurrentFog.Start < Program.CurrentRoute.CurrentFog.End) { const float fogDistance = 600.0f; float n = (fogDistance - Program.CurrentRoute.CurrentFog.Start) / (Program.CurrentRoute.CurrentFog.End - Program.CurrentRoute.CurrentFog.Start); float cr = n * inv255 * Program.CurrentRoute.CurrentFog.Color.R; float cg = n * inv255 * Program.CurrentRoute.CurrentFog.Color.G; float cb = n * inv255 * Program.CurrentRoute.CurrentFog.Color.B; GL.ClearColor(cr, cg, cb, 1.0f); } else { GL.ClearColor(0.0f, 0.0f, 0.0f, 1.0f); } } GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); // set up camera CurrentViewMatrix = Matrix4D.LookAt(Vector3.Zero, new Vector3(Camera.AbsoluteDirection.X, Camera.AbsoluteDirection.Y, -Camera.AbsoluteDirection.Z), new Vector3(Camera.AbsoluteUp.X, Camera.AbsoluteUp.Y, -Camera.AbsoluteUp.Z)); if (!AvailableNewRenderer) { GL.Light(LightName.Light0, LightParameter.Position, new[] { (float)Lighting.OptionLightPosition.X, (float)Lighting.OptionLightPosition.Y, (float)-Lighting.OptionLightPosition.Z, 0.0f }); } Lighting.OptionLightingResultingAmount = (Lighting.OptionAmbientColor.R + Lighting.OptionAmbientColor.G + Lighting.OptionAmbientColor.B) / 480.0f; if (Lighting.OptionLightingResultingAmount > 1.0f) { Lighting.OptionLightingResultingAmount = 1.0f; } // fog double fd = Program.CurrentRoute.NextFog.TrackPosition - Program.CurrentRoute.PreviousFog.TrackPosition; if (fd != 0.0) { float fr = (float)((CameraTrackFollower.TrackPosition - Program.CurrentRoute.PreviousFog.TrackPosition) / fd); float frc = 1.0f - fr; Program.CurrentRoute.CurrentFog.Start = Program.CurrentRoute.PreviousFog.Start * frc + Program.CurrentRoute.NextFog.Start * fr; Program.CurrentRoute.CurrentFog.End = Program.CurrentRoute.PreviousFog.End * frc + Program.CurrentRoute.NextFog.End * fr; Program.CurrentRoute.CurrentFog.Color.R = (byte)(Program.CurrentRoute.PreviousFog.Color.R * frc + Program.CurrentRoute.NextFog.Color.R * fr); Program.CurrentRoute.CurrentFog.Color.G = (byte)(Program.CurrentRoute.PreviousFog.Color.G * frc + Program.CurrentRoute.NextFog.Color.G * fr); Program.CurrentRoute.CurrentFog.Color.B = (byte)(Program.CurrentRoute.PreviousFog.Color.B * frc + Program.CurrentRoute.NextFog.Color.B * fr); } else { Program.CurrentRoute.CurrentFog = Program.CurrentRoute.PreviousFog; } // render background GL.Disable(EnableCap.DepthTest); Program.CurrentRoute.UpdateBackground(TimeElapsed, false); if (OptionEvents) { RenderEvents(); } // fog float aa = Program.CurrentRoute.CurrentFog.Start; float bb = Program.CurrentRoute.CurrentFog.End; if (aa < bb & aa < Program.CurrentRoute.CurrentBackground.BackgroundImageDistance) { OptionFog = true; Fog.Start = aa; Fog.End = bb; Fog.Color = Program.CurrentRoute.CurrentFog.Color; SetFogForImmediateMode(); } else { OptionFog = false; } // world layer // opaque face if (AvailableNewRenderer) { //Setup the shader for rendering the scene DefaultShader.Activate(); if (OptionLighting) { DefaultShader.SetIsLight(true); TransformedLightPosition = new Vector3(Lighting.OptionLightPosition.X, Lighting.OptionLightPosition.Y, -Lighting.OptionLightPosition.Z); DefaultShader.SetLightPosition(TransformedLightPosition); DefaultShader.SetLightAmbient(Lighting.OptionAmbientColor); DefaultShader.SetLightDiffuse(Lighting.OptionDiffuseColor); DefaultShader.SetLightSpecular(Lighting.OptionSpecularColor); DefaultShader.SetLightModel(Lighting.LightModel); } if (OptionFog) { DefaultShader.SetIsFog(true); DefaultShader.SetFogStart(Fog.Start); DefaultShader.SetFogEnd(Fog.End); DefaultShader.SetFogColor(Fog.Color); } DefaultShader.SetTexture(0); DefaultShader.SetCurrentProjectionMatrix(CurrentProjectionMatrix); } ResetOpenGlState(); foreach (FaceState face in VisibleObjects.OpaqueFaces) { face.Draw(); } // alpha face ResetOpenGlState(); VisibleObjects.SortPolygonsInAlphaFaces(); if (Interface.CurrentOptions.TransparencyMode == TransparencyMode.Performance) { SetBlendFunc(); SetAlphaFunc(AlphaFunction.Greater, 0.0f); GL.DepthMask(false); foreach (FaceState face in VisibleObjects.AlphaFaces) { face.Draw(); } } else { UnsetBlendFunc(); SetAlphaFunc(AlphaFunction.Equal, 1.0f); GL.DepthMask(true); foreach (FaceState face in VisibleObjects.AlphaFaces) { if (face.Object.Prototype.Mesh.Materials[face.Face.Material].BlendMode == MeshMaterialBlendMode.Normal && face.Object.Prototype.Mesh.Materials[face.Face.Material].GlowAttenuationData == 0) { if (face.Object.Prototype.Mesh.Materials[face.Face.Material].Color.A == 255) { face.Draw(); } } } SetBlendFunc(); SetAlphaFunc(AlphaFunction.Less, 1.0f); GL.DepthMask(false); bool additive = false; foreach (FaceState face in VisibleObjects.AlphaFaces) { if (face.Object.Prototype.Mesh.Materials[face.Face.Material].BlendMode == MeshMaterialBlendMode.Additive) { if (!additive) { UnsetAlphaFunc(); additive = true; } face.Draw(); } else { if (additive) { SetAlphaFunc(); additive = false; } face.Draw(); } } } // render overlays if (AvailableNewRenderer) { DefaultShader.Deactivate(); } ResetOpenGlState(); OptionLighting = false; OptionFog = false; UnsetAlphaFunc(); GL.Disable(EnableCap.DepthTest); SetBlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); //FIXME: Remove when text switches between two renderer types RenderOverlays(); OptionLighting = true; }