diff --git a/assets/Shaders/text.vert b/assets/Shaders/text.vert index 8e64a5de83..6733ad3afe 100644 --- a/assets/Shaders/text.vert +++ b/assets/Shaders/text.vert @@ -1,41 +1,20 @@ #version 150 core -uniform mat4 uCurrentProjectionMatrix; -uniform mat4 uCurrentModelViewMatrix; -uniform vec2 uPoint; -uniform vec2 uSize; -uniform vec4 uAtlasLocation; -out vec2 textureCoord; -vec4 viewPos = vec4(0,0,0,0); +// Attributes +attribute vec3 a_position; +attribute vec4 a_color; +attribute vec2 a_texCoords0; + +// Uniforms +uniform mat4 MatrixTransform; + +// Varyings +varying vec4 v_color; +varying vec2 v_texCoords; void main() { - switch(gl_VertexID) - { - case 0: - viewPos = uCurrentModelViewMatrix * vec4(vec3(uPoint.x, uPoint.y, 0), 1.0); - textureCoord = vec2(uAtlasLocation.x, uAtlasLocation.y); - break; - case 1: - viewPos = uCurrentModelViewMatrix * vec4(vec3(uPoint.x + uSize.x, uPoint.y, 0), 1.0); - textureCoord = vec2(uAtlasLocation.x + uAtlasLocation.z, uAtlasLocation.y); - break; - case 2: - viewPos = uCurrentModelViewMatrix * vec4(vec3(uPoint.x + uSize.x, uPoint.y + uSize.y, 0), 1.0); - textureCoord = vec2(uAtlasLocation.x + uAtlasLocation.z, uAtlasLocation.y + uAtlasLocation.w); - break; - case 3: - viewPos = uCurrentModelViewMatrix * vec4(vec3(uPoint.x, uPoint.y, 0), 1.0); - textureCoord = vec2(uAtlasLocation.x, uAtlasLocation.y); - break; - case 4: - viewPos = uCurrentModelViewMatrix * vec4(vec3(uPoint.x, uPoint.y + uSize.y, 0), 1.0); - textureCoord = vec2(uAtlasLocation.x, uAtlasLocation.y + uAtlasLocation.w); - break; - case 5: - viewPos = uCurrentModelViewMatrix * vec4(vec3(uPoint.x + uSize.x, uPoint.y + uSize.y, 0), 1.0); - textureCoord = vec2(uAtlasLocation.x + uAtlasLocation.z, uAtlasLocation.y + uAtlasLocation.w); - break; - } - gl_Position = uCurrentProjectionMatrix * viewPos; + v_color = a_color; + v_texCoords = a_texCoords0; + gl_Position = MatrixTransform * vec4(a_position, 1.0); } diff --git a/source/LibRender2/Backgrounds/Background.cs b/source/LibRender2/Backgrounds/Background.cs index 84e56655bf..1593af1e61 100644 --- a/source/LibRender2/Backgrounds/Background.cs +++ b/source/LibRender2/Backgrounds/Background.cs @@ -1,4 +1,3 @@ -using System; using OpenBveApi.Math; using OpenBveApi.Objects; using OpenBveApi.Routes; @@ -102,14 +101,7 @@ private void RenderStaticBackground(StaticBackground data, float scale) /// The scale private void RenderStaticBackground(StaticBackground data, float alpha, float scale) { - if (renderer.AvailableNewRenderer) - { - RenderStaticBackgroundRetained(data, alpha, scale); - } - else - { - RenderStaticBackgroundImmediate(data, alpha, scale); - } + RenderStaticBackgroundRetained(data, alpha, scale); } /// Renders a static frustrum based background @@ -177,137 +169,6 @@ private void RenderStaticBackgroundRetained(StaticBackground data, float alpha, } } - /// Renders a static frustrum based background - /// The background to render - /// The alpha level - /// The scale - private void RenderStaticBackgroundImmediate(StaticBackground data, float alpha, float scale) - { - Texture t = data.Texture; - if (data.Texture != null && renderer.currentHost.LoadTexture(ref t, OpenGlTextureWrapMode.RepeatClamp)) - { - GL.MatrixMode(MatrixMode.Projection); - GL.PushMatrix(); - GL.LoadIdentity(); - OpenTK.Matrix4d perspective = OpenTK.Matrix4d.Perspective(renderer.Camera.VerticalViewingAngle, -renderer.Screen.AspectRatio, 0.2, 1000.0); - GL.MultMatrix(ref perspective); - double dx = renderer.Camera.AbsoluteDirection.X; - double dy = renderer.Camera.AbsoluteDirection.Y; - double dz = renderer.Camera.AbsoluteDirection.Z; - double ux = renderer.Camera.AbsoluteUp.X; - double uy = renderer.Camera.AbsoluteUp.Y; - double uz = renderer.Camera.AbsoluteUp.Z; - OpenTK.Matrix4d lookat = OpenTK.Matrix4d.LookAt(0.0, 0.0, 0.0, dx, dy, dz, ux, uy, uz); - GL.MatrixMode(MatrixMode.Modelview); - GL.PushMatrix(); - GL.LoadMatrix(ref lookat); - GL.Disable(EnableCap.Lighting); - GL.Enable(EnableCap.Texture2D); - if (alpha == 1.0f) - { - GL.Disable(EnableCap.Blend); - } - else - { - GL.Enable(EnableCap.Blend); - renderer.SetAlphaFunc(AlphaFunction.Greater, 0.0f); - } - GL.BindTexture(TextureTarget.Texture2D, t.OpenGlTextures[(int)OpenGlTextureWrapMode.RepeatClamp].Name); - renderer.LastBoundTexture = t.OpenGlTextures[(int)OpenGlTextureWrapMode.RepeatClamp]; - GL.Color4(1.0f, 1.0f, 1.0f, alpha); - if (renderer.OptionFog) - { - GL.Enable(EnableCap.Fog); - } - if (data.DisplayList > 0) - { - GL.CallList(data.DisplayList); - GL.Disable(EnableCap.Texture2D); - GL.Enable(EnableCap.Blend); - GL.PopMatrix(); - GL.MatrixMode(MatrixMode.Projection); - GL.PopMatrix(); - return; - } - - data.DisplayList = GL.GenLists(1); - GL.NewList(data.DisplayList, ListMode.Compile); - float y0, y1; - if (data.KeepAspectRatio) - { - double hh = Math.PI * data.BackgroundImageDistance * data.Texture.Height / (data.Texture.Width * data.Repetition); - y0 = (float)(-0.5 * hh); - y1 = (float)(1.5 * hh); - } - else - { - y0 = (float)(-0.125 * data.BackgroundImageDistance); - y1 = (float)(0.375 * data.BackgroundImageDistance); - } - const int n = 32; - Vector3[] bottom = new Vector3[n]; - Vector3[] top = new Vector3[n]; - double angleValue = 2.61799387799149 - 3.14159265358979 / n; - const double angleIncrement = 6.28318530717958 / n; - /* - * To ensure that the whole background cylinder is rendered inside the viewing frustum, - * the background is rendered before the scene with z-buffer writes disabled. Then, - * the actual distance from the camera is irrelevant as long as it is inside the frustum. - * */ - for (int i = 0; i < n; i++) - { - float x = (float)(data.BackgroundImageDistance * Math.Cos(angleValue)); - float z = (float)(data.BackgroundImageDistance * Math.Sin(angleValue)); - bottom[i] = new Vector3(scale * x, scale * y0, scale * z); - top[i] = new Vector3(scale * x, scale * y1, scale * z); - angleValue += angleIncrement; - } - float textureStart = 0.5f * (float)data.Repetition / n; - float textureIncrement = -(float)data.Repetition / n; - double textureX = textureStart; - for (int i = 0; i < n; i++) - { - int j = (i + 1) % n; - // side wall - GL.Begin(PrimitiveType.Quads); - GL.TexCoord2(textureX, 0.005f); - GL.Vertex3(top[i].X, top[i].Y, top[i].Z); - GL.TexCoord2(textureX, 0.995f); - GL.Vertex3(bottom[i].X, bottom[i].Y, bottom[i].Z); - GL.TexCoord2(textureX + textureIncrement, 0.995f); - GL.Vertex3(bottom[j].X, bottom[j].Y, bottom[j].Z); - GL.TexCoord2(textureX + textureIncrement, 0.005f); - GL.Vertex3(top[j].X, top[j].Y, top[j].Z); - GL.End(); - // top cap - GL.Begin(PrimitiveType.Triangles); - GL.TexCoord2(textureX, 0.005f); - GL.Vertex3(top[i].X, top[i].Y, top[i].Z); - GL.TexCoord2(textureX + textureIncrement, 0.005f); - GL.Vertex3(top[j].X, top[j].Y, top[j].Z); - GL.TexCoord2(textureX + 0.5 * textureIncrement, 0.1f); - GL.Vertex3(0.0f, top[i].Y, 0.0f); - // bottom cap - GL.TexCoord2(textureX + 0.5 * textureIncrement, 0.9f); - GL.Vertex3(0.0f, bottom[i].Y, 0.0f); - GL.TexCoord2(textureX + textureIncrement, 0.995f); - GL.Vertex3(bottom[j].X, bottom[j].Y, bottom[j].Z); - GL.TexCoord2(textureX, 0.995f); - GL.Vertex3(bottom[i].X, bottom[i].Y, bottom[i].Z); - GL.End(); - // finish - textureX += textureIncrement; - } - GL.EndList(); - GL.CallList(data.DisplayList); - GL.Disable(EnableCap.Texture2D); - GL.Enable(EnableCap.Blend); - GL.PopMatrix(); - GL.MatrixMode(MatrixMode.Projection); - GL.PopMatrix(); - } - } - /// Renders an object based background /// The background object private void RenderBackgroundObject(BackgroundObject data) @@ -315,15 +176,12 @@ private void RenderBackgroundObject(BackgroundObject data) GL.Enable(EnableCap.Blend); // alpha test renderer.SetAlphaFunc(AlphaFunction.Greater, 0.0f); - if (renderer.AvailableNewRenderer) - { - renderer.DefaultShader.Activate(); - renderer.DefaultShader.SetCurrentProjectionMatrix(renderer.CurrentProjectionMatrix); + renderer.DefaultShader.Activate(); + renderer.DefaultShader.SetCurrentProjectionMatrix(renderer.CurrentProjectionMatrix); - if (data.Object.Mesh.VAO == null) - { - VAOExtensions.CreateVAO(data.Object.Mesh, false, renderer.DefaultShader.VertexLayout, renderer); - } + if (data.Object.Mesh.VAO == null) + { + VAOExtensions.CreateVAO(data.Object.Mesh, false, renderer.DefaultShader.VertexLayout, renderer); } foreach (MeshFace face in data.Object.Mesh.Faces) @@ -351,14 +209,7 @@ private void RenderBackgroundObject(BackgroundObject data) } } GL.Enable(EnableCap.DepthClamp); - if (renderer.AvailableNewRenderer) - { - renderer.RenderFace(renderer.DefaultShader, data.ObjectState, face, Matrix4D.NoTransformation, Matrix4D.Scale(1.0) * renderer.CurrentViewMatrix); - } - else - { - renderer.RenderFaceImmediateMode(data.ObjectState, face, Matrix4D.NoTransformation, Matrix4D.Scale(1.0) * renderer.CurrentViewMatrix); - } + renderer.RenderFace(renderer.DefaultShader, data.ObjectState, face, Matrix4D.NoTransformation, Matrix4D.Scale(1.0) * renderer.CurrentViewMatrix); GL.Disable(EnableCap.DepthClamp); } } diff --git a/source/LibRender2/BaseRenderer.cs b/source/LibRender2/BaseRenderer.cs index 29d1ffbab4..f22122e2a3 100644 --- a/source/LibRender2/BaseRenderer.cs +++ b/source/LibRender2/BaseRenderer.cs @@ -7,6 +7,7 @@ using System.Reflection; using System.Runtime.ExceptionServices; using System.Threading; +using FontStashSharp.Interfaces; using LibRender2.Backgrounds; using LibRender2.Cameras; using LibRender2.Fogs; @@ -286,6 +287,8 @@ public Texture ProgramLogo public GameWindow GameWindow; /// The graphics mode in use public GraphicsMode GraphicsMode; + + internal FontStashRenderer FontStashRenderer; public bool LoadLogo() { return currentHost.LoadTexture(ref _programLogo, OpenGlTextureWrapMode.ClampClamp); @@ -299,8 +302,6 @@ public bool LoadLogo() internal static readonly List vboToDelete = new List(); internal static readonly List iboToDelete = new List(); - public bool AvailableNewRenderer => currentOptions != null && currentOptions.IsUseNewRenderer && !ForceLegacyOpenGL; - protected BaseRenderer(HostInterface CurrentHost, BaseOptions CurrentOptions, FileSystem FileSystem) { currentHost = CurrentHost; @@ -352,6 +353,7 @@ public virtual void Initialize() lastColor = Color32.White; DefaultShader.Deactivate(); dummyVao = new VertexArrayObject(); + FontStashRenderer = new FontStashRenderer(this); } catch { @@ -414,11 +416,6 @@ public virtual void Initialize() GL.Disable(EnableCap.Dither); GL.Disable(EnableCap.Lighting); GL.Disable(EnableCap.Fog); - if (!AvailableNewRenderer) - { - GL.Disable(EnableCap.Texture2D); - GL.Fog(FogParameter.FogMode, (int)FogMode.Linear); - } // ReSharper disable once PossibleNullReferenceException string openGLdll = Path.CombineFile(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "opengl32.dll"); @@ -447,20 +444,7 @@ public void DeInitialize() // terminate spinning thread VisibilityThreadShouldRun = false; } - - /// Should be called when the OpenGL version is switched mid-game - /// We need to purge the current shader state and update lighting to avoid glitches - public void SwitchOpenGLVersion() - { - if (currentOptions.IsUseNewRenderer && AvailableNewRenderer) - { - DefaultShader.Activate(); - DefaultShader.Deactivate(); - } - currentOptions.IsUseNewRenderer = !currentOptions.IsUseNewRenderer; - Lighting.Initialize(); - } - + /// Performs cleanup of disposed resources public void ReleaseResources() { @@ -499,13 +483,6 @@ public void ReleaseResources() public virtual void ResetOpenGlState() { GL.Enable(EnableCap.CullFace); - if (!AvailableNewRenderer) - { - GL.Disable(EnableCap.Lighting); - GL.Disable(EnableCap.Fog); - GL.Disable(EnableCap.Texture2D); - } - SetBlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); UnsetBlendFunc(); GL.Enable(EnableCap.DepthTest); @@ -1138,32 +1115,15 @@ public void SetAlphaFunc(AlphaFunction comparison, float value) alphaTestEnabled = true; alphaFuncComparison = comparison; alphaFuncValue = value; - if (AvailableNewRenderer) - { - CurrentShader.SetAlphaTest(true); - CurrentShader.SetAlphaFunction(comparison, value); - } - else - { - GL.Enable(EnableCap.AlphaTest); - GL.AlphaFunc(comparison, value); - } - + CurrentShader.SetAlphaTest(true); + CurrentShader.SetAlphaFunction(comparison, value); } /// Disables OpenGL alpha testing public void UnsetAlphaFunc() { alphaTestEnabled = false; - if (AvailableNewRenderer) - { - CurrentShader.SetAlphaTest(false); - } - else - { - GL.Disable(EnableCap.AlphaTest); - } - + CurrentShader.SetAlphaTest(false); } /// Restores the OpenGL alpha function to it's previous state @@ -1171,28 +1131,12 @@ public void RestoreAlphaFunc() { if (alphaTestEnabled) { - if (AvailableNewRenderer) - { - CurrentShader.SetAlphaTest(true); - CurrentShader.SetAlphaFunction(alphaFuncComparison, alphaFuncValue); - } - else - { - GL.Enable(EnableCap.AlphaTest); - GL.AlphaFunc(alphaFuncComparison, alphaFuncValue); - } - + CurrentShader.SetAlphaTest(true); + CurrentShader.SetAlphaFunction(alphaFuncComparison, alphaFuncValue); } else { - if (AvailableNewRenderer) - { - CurrentShader.SetAlphaTest(false); - } - else - { - GL.Disable(EnableCap.AlphaTest); - } + CurrentShader.SetAlphaTest(false); } } @@ -1459,287 +1403,6 @@ public void RenderFace(Shader shader, ObjectState state, MeshFace face, bool deb lastObjectState = state; } - public void RenderFaceImmediateMode(FaceState state, bool debugTouchMode = false) - { - RenderFaceImmediateMode(state.Object, state.Face, debugTouchMode); - } - - public void RenderFaceImmediateMode(ObjectState state, MeshFace face, bool debugTouchMode = false) - { - Matrix4D modelMatrix = state.ModelMatrix * Camera.TranslationMatrix; - Matrix4D modelViewMatrix = modelMatrix * CurrentViewMatrix; - RenderFaceImmediateMode(state, face, modelMatrix, modelViewMatrix, debugTouchMode); - } - - public void RenderFaceImmediateMode(ObjectState state, MeshFace face, Matrix4D modelMatrix, Matrix4D modelViewMatrix, bool debugTouchMode = false) - { - if (state.Prototype.Mesh.Vertices.Length < 1) - { - return; - } - - VertexTemplate[] vertices = state.Prototype.Mesh.Vertices; - MeshMaterial material = state.Prototype.Mesh.Materials[face.Material]; - - if (!OptionBackFaceCulling || (face.Flags & FaceFlags.Face2Mask) != 0) - { - GL.Disable(EnableCap.CullFace); - } - else if (OptionBackFaceCulling) - { - if ((face.Flags & FaceFlags.Face2Mask) == 0) - { - GL.Enable(EnableCap.CullFace); - } - } - - // matrix - unsafe - { - GL.MatrixMode(MatrixMode.Projection); - GL.PushMatrix(); - fixed (double* matrixPointer = &CurrentProjectionMatrix.Row0.X) - { - GL.LoadMatrix(matrixPointer); - } - GL.MatrixMode(MatrixMode.Modelview); - GL.PushMatrix(); - fixed (double* matrixPointer = &CurrentViewMatrix.Row0.X) - { - GL.LoadMatrix(matrixPointer); - } - - double* matrixPointer2 = &modelMatrix.Row0.X; - { - GL.MultMatrix(matrixPointer2); - } - - GL.MatrixMode(MatrixMode.Texture); - GL.PushMatrix(); - fixed (double* matrixPointer = &state.TextureTranslation.Row0.X) - { - GL.LoadMatrix(matrixPointer); - } - - } - - if (OptionWireFrame || debugTouchMode) - { - GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); - } - - // lighting - if (material.NighttimeTexture == null) - { - if (OptionLighting) - { - GL.Enable(EnableCap.Lighting); - } - } - - GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Emission, (material.Flags & MaterialFlags.Emissive) != 0 ? new Color4(material.EmissiveColor.R, material.EmissiveColor.G, material.EmissiveColor.B, 255) : Color4.Black); - - // fog - if (OptionFog) - { - GL.Enable(EnableCap.Fog); - } - - PrimitiveType drawMode; - - switch (face.Flags & FaceFlags.FaceTypeMask) - { - case FaceFlags.Triangles: - drawMode = PrimitiveType.Triangles; - break; - case FaceFlags.TriangleStrip: - drawMode = PrimitiveType.TriangleStrip; - break; - case FaceFlags.Quads: - drawMode = PrimitiveType.Quads; - break; - case FaceFlags.QuadStrip: - drawMode = PrimitiveType.QuadStrip; - break; - default: - drawMode = PrimitiveType.Polygon; - break; - } - - // blend factor - float distanceFactor; - if (material.GlowAttenuationData != 0) - { - distanceFactor = (float)Glow.GetDistanceFactor(modelMatrix, vertices, ref face, material.GlowAttenuationData); - } - else - { - distanceFactor = 1.0f; - } - - float blendFactor = inv255 * state.DaytimeNighttimeBlend + 1.0f - Lighting.OptionLightingResultingAmount; - if (blendFactor > 1.0) - { - blendFactor = 1.0f; - } - - // daytime polygon - { - // texture - if (material.DaytimeTexture != null) - { - // ReSharper disable once PossibleInvalidOperationException - if (currentHost.LoadTexture(ref material.DaytimeTexture, (OpenGlTextureWrapMode)material.WrapMode)) - { - GL.Enable(EnableCap.Texture2D); - if (LastBoundTexture != material.DaytimeTexture.OpenGlTextures[(int)material.WrapMode]) - { - GL.BindTexture(TextureTarget.Texture2D, material.DaytimeTexture.OpenGlTextures[(int)material.WrapMode].Name); - LastBoundTexture = material.DaytimeTexture.OpenGlTextures[(int)material.WrapMode]; - } - } - } - - // blend mode - float factor; - if (material.BlendMode == MeshMaterialBlendMode.Additive) - { - factor = 1.0f; - GL.Enable(EnableCap.Blend); - GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.One); - GL.Disable(EnableCap.Fog); - } - else if (material.NighttimeTexture == null) - { - factor = 1.0f - 0.7f * blendFactor; - } - else - { - factor = 1.0f; - } - - if ((material.Flags & MaterialFlags.DisableLighting) != 0) - { - GL.Disable(EnableCap.Lighting); - } - - float alphaFactor = distanceFactor; - if (material.NighttimeTexture != null && (material.Flags & MaterialFlags.CrossFadeTexture) != 0) - { - alphaFactor *= 1.0f - blendFactor; - } - - GL.Begin(drawMode); - - if (OptionWireFrame) - { - GL.Color4(inv255 * material.Color.R * factor, inv255 * material.Color.G * factor, inv255 * material.Color.B * factor, 1.0f); - } - else - { - GL.Color4(inv255 * material.Color.R * factor, inv255 * material.Color.G * factor, inv255 * material.Color.B * factor, inv255 * material.Color.A * alphaFactor); - } - - for (int i = 0; i < face.Vertices.Length; i++) - { - GL.Normal3(face.Vertices[i].Normal.X, face.Vertices[i].Normal.Y, -face.Vertices[i].Normal.Z); - GL.TexCoord2(vertices[face.Vertices[i].Index].TextureCoordinates.X, vertices[face.Vertices[i].Index].TextureCoordinates.Y); - - if (vertices[face.Vertices[i].Index] is ColoredVertex v) - { - GL.Color4(v.Color.R, v.Color.G, v.Color.B, v.Color.A); - } - - GL.Vertex3(vertices[face.Vertices[i].Index].Coordinates.X, vertices[face.Vertices[i].Index].Coordinates.Y, -vertices[face.Vertices[i].Index].Coordinates.Z); - } - - GL.End(); - } - - // nighttime polygon - if (blendFactor != 0 && material.NighttimeTexture != null && currentHost.LoadTexture(ref material.NighttimeTexture, (OpenGlTextureWrapMode)material.WrapMode)) - { - // texture - GL.Enable(EnableCap.Texture2D); - if (LastBoundTexture != material.NighttimeTexture.OpenGlTextures[(int)material.WrapMode]) - { - GL.BindTexture(TextureTarget.Texture2D, material.NighttimeTexture.OpenGlTextures[(int)material.WrapMode].Name); - LastBoundTexture = material.NighttimeTexture.OpenGlTextures[(int)material.WrapMode]; - } - - GL.Enable(EnableCap.Blend); - - // alpha test - GL.Enable(EnableCap.AlphaTest); - GL.AlphaFunc(AlphaFunction.Greater, 0.0f); - - // blend mode - float alphaFactor = distanceFactor * blendFactor; - - GL.Begin(drawMode); - - if (OptionWireFrame) - { - GL.Color4(inv255 * material.Color.R, inv255 * material.Color.G, inv255 * material.Color.B, 1.0f); - } - else - { - GL.Color4(inv255 * material.Color.R, inv255 * material.Color.G, inv255 * material.Color.B, inv255 * material.Color.A * alphaFactor); - } - - for (int i = 0; i < face.Vertices.Length; i++) - { - GL.Normal3(face.Vertices[i].Normal.X, face.Vertices[i].Normal.Y, -face.Vertices[i].Normal.Z); - GL.TexCoord2(vertices[face.Vertices[i].Index].TextureCoordinates.X, vertices[face.Vertices[i].Index].TextureCoordinates.Y); - - if (vertices[face.Vertices[i].Index] is ColoredVertex v) - { - GL.Color3(v.Color.R, v.Color.G, v.Color.B); - } - - GL.Vertex3(vertices[face.Vertices[i].Index].Coordinates.X, vertices[face.Vertices[i].Index].Coordinates.Y, -vertices[face.Vertices[i].Index].Coordinates.Z); - } - - GL.End(); - RestoreBlendFunc(); - RestoreAlphaFunc(); - } - - GL.Disable(EnableCap.Texture2D); - - // normals - if (OptionNormals) - { - for (int i = 0; i < face.Vertices.Length; i++) - { - GL.Begin(PrimitiveType.Lines); - GL.Color4(new Color4(material.Color.R, material.Color.G, material.Color.B, 255)); - GL.Vertex3(vertices[face.Vertices[i].Index].Coordinates.X, vertices[face.Vertices[i].Index].Coordinates.Y, -vertices[face.Vertices[i].Index].Coordinates.Z); - GL.Vertex3(vertices[face.Vertices[i].Index].Coordinates.X + face.Vertices[i].Normal.X, vertices[face.Vertices[i].Index].Coordinates.Y + +face.Vertices[i].Normal.Y, -(vertices[face.Vertices[i].Index].Coordinates.Z + face.Vertices[i].Normal.Z)); - GL.End(); - } - } - - // finalize - if (OptionWireFrame || debugTouchMode) - { - GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill); - } - - if (material.BlendMode == MeshMaterialBlendMode.Additive) - { - RestoreBlendFunc(); - } - - GL.PopMatrix(); - - GL.MatrixMode(MatrixMode.Modelview); - GL.PopMatrix(); - - GL.MatrixMode(MatrixMode.Projection); - GL.PopMatrix(); - } - /// Sets the current MouseCursor /// The new cursor public void SetCursor(OpenTK.MouseCursor newCursor) diff --git a/source/LibRender2/LibRender2.csproj b/source/LibRender2/LibRender2.csproj index a342552d1a..4f759273c0 100644 --- a/source/LibRender2/LibRender2.csproj +++ b/source/LibRender2/LibRender2.csproj @@ -47,6 +47,10 @@ prompt + + False + ..\..\..\FontStash\FontStashSharp\src\FontStashSharp\bin\Debug\netstandard2.0\FontStashSharp.dll + ..\..\packages\OpenTK-OpenBVE.1.0.4\lib\net20\OpenTK.dll @@ -114,6 +118,10 @@ + + + + @@ -148,6 +156,7 @@ PreserveNewest + \ No newline at end of file diff --git a/source/LibRender2/Lighting/Lighting.cs b/source/LibRender2/Lighting/Lighting.cs index 72ce53c3e4..e5e5d854fc 100644 --- a/source/LibRender2/Lighting/Lighting.cs +++ b/source/LibRender2/Lighting/Lighting.cs @@ -44,15 +44,6 @@ internal Lighting(BaseRenderer Renderer) /// Updates the lighting model on a per frame basis public void Initialize() { - if (!renderer.AvailableNewRenderer) - { - GL.Light(LightName.Light0, LightParameter.Ambient,new Color4(OptionAmbientColor.R,OptionAmbientColor.G,OptionAmbientColor.B,255)); - GL.Light(LightName.Light0, LightParameter.Diffuse, new Color4(OptionDiffuseColor.R, OptionDiffuseColor.G, OptionDiffuseColor.B, 255)); - GL.LightModel(LightModelParameter.LightModelAmbient, new[] { (float)LightModel.X, (float)LightModel.Y, (float)LightModel.Z, (float)LightModel.W }); - GL.Enable(EnableCap.Light0); - GL.Enable(EnableCap.ColorMaterial); - } - float x = OptionAmbientColor.R + (float)OptionAmbientColor.G + OptionAmbientColor.B; float y = OptionDiffuseColor.R + (float)OptionDiffuseColor.G + OptionDiffuseColor.B; diff --git a/source/LibRender2/Objects/FaceState.cs b/source/LibRender2/Objects/FaceState.cs index 04b951ecdb..1932961b12 100644 --- a/source/LibRender2/Objects/FaceState.cs +++ b/source/LibRender2/Objects/FaceState.cs @@ -25,14 +25,7 @@ public FaceState(ObjectState _object, MeshFace face, BaseRenderer renderer) public void Draw() { - if (Renderer.AvailableNewRenderer) - { - Renderer.RenderFace(this); - } - else - { - Renderer.RenderFaceImmediateMode(this); - } + Renderer.RenderFace(this); } } } diff --git a/source/LibRender2/Primitives/Cube.cs b/source/LibRender2/Primitives/Cube.cs index 2dca663226..ae131213cd 100644 --- a/source/LibRender2/Primitives/Cube.cs +++ b/source/LibRender2/Primitives/Cube.cs @@ -237,14 +237,7 @@ public Cube(BaseRenderer renderer, Color128 color) /// The texture to apply public void Draw(Vector3 Position, Vector3 Direction, Vector3 Up, Vector3 Side, double Size, Vector3 Camera, Texture TextureIndex) { - if (renderer.AvailableNewRenderer) - { - Draw(Position, Direction, Up, Side, new Vector3(Size, Size, Size), Camera, TextureIndex); - } - else - { - DrawImmediate(Position, Direction, Up, Side, new Vector3(Size, Size, Size), Camera, TextureIndex); - } + Draw(Position, Direction, Up, Side, new Vector3(Size, Size, Size), Camera, TextureIndex); } /// Draws a 3D cube @@ -257,14 +250,7 @@ public void Draw(Vector3 Position, Vector3 Direction, Vector3 Up, Vector3 Side, /// The texture to apply public void Draw(Vector3 Position, Vector3 Direction, Vector3 Up, Vector3 Side, Vector3 Size, Vector3 Camera, Texture TextureIndex) { - if (renderer.AvailableNewRenderer) - { - DrawRetained(defaultVAO, Position, Direction, Up, Side, Size, Camera, TextureIndex); - } - else - { - DrawImmediate(Position, Direction, Up, Side, Size, Camera, TextureIndex); - } + DrawRetained(defaultVAO, Position, Direction, Up, Side, Size, Camera, TextureIndex); } /// Draws a 3D cube @@ -300,96 +286,5 @@ private void DrawRetained(VertexArrayObject VAO, Vector3 Position, Vector3 Direc VAO.Draw(PrimitiveType.Quads); GL.Disable(EnableCap.Texture2D); } - - /// Draws a 3D cube in immediate mode - /// The position in world-space - /// The direction vector - /// The up vector - /// The side vector - /// A 3D vector describing the size of the cube - /// The camera position - /// The texture to apply - private void DrawImmediate(Vector3 Position, Vector3 Direction, Vector3 Up, Vector3 Side, Vector3 Size, Vector3 Camera, Texture TextureIndex) - { - renderer.LastBoundTexture = null; - GL.MatrixMode(MatrixMode.Projection); - GL.PushMatrix(); - GL.LoadIdentity(); - OpenTK.Matrix4d perspective = OpenTK.Matrix4d.Perspective(renderer.Camera.VerticalViewingAngle, -renderer.Screen.AspectRatio, 0.2, 1000.0); - GL.MultMatrix(ref perspective); - double dx = renderer.Camera.AbsoluteDirection.X; - double dy = renderer.Camera.AbsoluteDirection.Y; - double dz = renderer.Camera.AbsoluteDirection.Z; - double ux = renderer.Camera.AbsoluteUp.X; - double uy = renderer.Camera.AbsoluteUp.Y; - double uz = renderer.Camera.AbsoluteUp.Z; - OpenTK.Matrix4d lookat = OpenTK.Matrix4d.LookAt(0.0, 0.0, 0.0, dx, dy, dz, ux, uy, uz); - GL.MatrixMode(MatrixMode.Modelview); - GL.PushMatrix(); - GL.LoadMatrix(ref lookat); - Vector3[] v = new Vector3[8]; - v[0] = new Vector3(Size.X, Size.Y, -Size.Z); - v[1] = new Vector3(Size.X, -Size.Y, -Size.Z); - v[2] = new Vector3(-Size.X, -Size.Y, -Size.Z); - v[3] = new Vector3(-Size.X, Size.Y, -Size.Z); - v[4] = new Vector3(Size.X, Size.Y, Size.Z); - v[5] = new Vector3(Size.X, -Size.Y, Size.Z); - v[6] = new Vector3(-Size.X, -Size.Y, Size.Z); - v[7] = new Vector3(-Size.X, Size.Y, Size.Z); - for (int i = 0; i < 8; i++) - { - v[i].Rotate(Direction, Up, Side); - v[i] += Position - Camera; - } - int[][] Faces = new int[6][]; - Faces[0] = new[] { 0, 1, 2, 3 }; - Faces[1] = new[] { 0, 4, 5, 1 }; - Faces[2] = new[] { 0, 3, 7, 4 }; - Faces[3] = new[] { 6, 5, 4, 7 }; - Faces[4] = new[] { 6, 7, 3, 2 }; - Faces[5] = new[] { 6, 2, 1, 5 }; - if (TextureIndex == null || !renderer.currentHost.LoadTexture(ref TextureIndex, OpenGlTextureWrapMode.ClampClamp)) - { - GL.Disable(EnableCap.Texture2D); - for (int i = 0; i < 6; i++) - { - GL.Begin(PrimitiveType.Quads); - for (int j = 0; j < 4; j++) - { - GL.Vertex3(v[Faces[i][j]].X, v[Faces[i][j]].Y, v[Faces[i][j]].Z); - } - GL.End(); - } - GL.PopMatrix(); - - GL.MatrixMode(MatrixMode.Projection); - GL.PopMatrix(); - return; - } - GL.Enable(EnableCap.Texture2D); - GL.BindTexture(TextureTarget.Texture2D, TextureIndex.OpenGlTextures[(int)OpenGlTextureWrapMode.ClampClamp].Name); - Vector2[][] t = new Vector2[6][]; - t[0] = new[] { new Vector2(1.0, 0.0), new Vector2(1.0, 1.0), new Vector2(0.0, 1.0), new Vector2(0.0, 0.0) }; - t[1] = new[] { new Vector2(0.0, 0.0), new Vector2(1.0, 0.0), new Vector2(1.0, 1.0), new Vector2(0.0, 1.0) }; - t[2] = new[] { new Vector2(1.0, 1.0), new Vector2(0.0, 1.0), new Vector2(0.0, 0.0), new Vector2(1.0, 0.0) }; - t[3] = new[] { new Vector2(1.0, 1.0), new Vector2(0.0, 1.0), new Vector2(0.0, 0.0), new Vector2(1.0, 0.0) }; - t[4] = new[] { new Vector2(0.0, 1.0), new Vector2(0.0, 0.0), new Vector2(1.0, 0.0), new Vector2(1.0, 1.0) }; - t[5] = new[] { new Vector2(0.0, 1.0), new Vector2(0.0, 0.0), new Vector2(1.0, 0.0), new Vector2(1.0, 1.0) }; - for (int i = 0; i < 6; i++) - { - GL.Begin(PrimitiveType.Quads); - GL.Color3(1.0, 1.0, 1.0); - for (int j = 0; j < 4; j++) - { - GL.TexCoord2(t[i][j].X, t[i][j].Y); - GL.Vertex3(v[Faces[i][j]].X, v[Faces[i][j]].Y, v[Faces[i][j]].Z); - } - GL.End(); - } - GL.PopMatrix(); - - GL.MatrixMode(MatrixMode.Projection); - GL.PopMatrix(); - } } } diff --git a/source/LibRender2/Primitives/Rectangle.cs b/source/LibRender2/Primitives/Rectangle.cs index 25d57e0d3f..04eac7db70 100644 --- a/source/LibRender2/Primitives/Rectangle.cs +++ b/source/LibRender2/Primitives/Rectangle.cs @@ -101,20 +101,13 @@ public void DrawAlpha(Texture texture, Vector2 point, Color128? color = null, Ve /// A wrap mode if overriding that of the texture public void Draw(Texture texture, Vector2 point, Vector2 size, Color128? color = null, Vector2? textureCoordinates = null, OpenGlTextureWrapMode? wrapMode = null) { - if (renderer.AvailableNewRenderer && Shader != null) + if (textureCoordinates == null) { - if (textureCoordinates == null) - { - DrawWithShader(texture, point, size, color, Vector2.One, wrapMode); - } - else - { - DrawWithShader(texture, point, size, color, (Vector2)textureCoordinates, wrapMode); - } + DrawWithShader(texture, point, size, color, Vector2.One, wrapMode); } else { - DrawImmediate(texture, point, size, color, textureCoordinates, wrapMode); + DrawWithShader(texture, point, size, color, (Vector2)textureCoordinates, wrapMode); } } @@ -125,112 +118,20 @@ public void Draw(Texture texture, Vector2 point, Vector2 size, Color128? color = /// The texture coordinates to be applied public void Draw(Texture texture, Vector2 point, Color128? color = null, Vector2? textureCoordinates = null) { - if (texture == null) + if (texture == null || Shader == null) { return; } - if (renderer.AvailableNewRenderer && Shader != null) + if (textureCoordinates == null) { - if (textureCoordinates == null) - { - DrawWithShader(texture, point, texture.Size, color, Vector2.One); - } - else - { - DrawWithShader(texture, point, texture.Size, color, (Vector2)textureCoordinates); - } + DrawWithShader(texture, point, texture.Size, color, Vector2.One); } else { - DrawImmediate(texture, point, texture.Size, color, textureCoordinates); + DrawWithShader(texture, point, texture.Size, color, (Vector2)textureCoordinates); } } - - private void DrawImmediate(Texture texture, Vector2 point, Vector2 size, Color128? color, Vector2? textureCoordinates = null, OpenGlTextureWrapMode? wrapMode = null) - { - renderer.LastBoundTexture = null; - // TODO: Remove Nullable from color once RenderOverlayTexture and RenderOverlaySolid are fully replaced. - GL.MatrixMode(MatrixMode.Projection); - GL.PushMatrix(); - unsafe - { - fixed (double* matrixPointer = &renderer.CurrentProjectionMatrix.Row0.X) - { - GL.LoadMatrix(matrixPointer); - } - GL.MatrixMode(MatrixMode.Modelview); - GL.PushMatrix(); - fixed (double* matrixPointer = &renderer.CurrentViewMatrix.Row0.X) - { - GL.LoadMatrix(matrixPointer); - } - - } - - if (wrapMode == null) - { - wrapMode = OpenGlTextureWrapMode.ClampClamp; - } - if (texture == null || !renderer.currentHost.LoadTexture(ref texture, (OpenGlTextureWrapMode)wrapMode)) - { - GL.Disable(EnableCap.Texture2D); - - if (color.HasValue) - { - GL.Color4(color.Value.R, color.Value.G, color.Value.B, color.Value.A); - } - - GL.Begin(PrimitiveType.Quads); - GL.Vertex2(point.X, point.Y); - GL.Vertex2(point.X + size.X, point.Y); - GL.Vertex2(point.X + size.X, point.Y + size.Y); - GL.Vertex2(point.X, point.Y + size.Y); - GL.End(); - } - else - { - GL.Enable(EnableCap.Texture2D); - GL.BindTexture(TextureTarget.Texture2D, texture.OpenGlTextures[(int)wrapMode].Name); - - if (color.HasValue) - { - GL.Color4(color.Value.R, color.Value.G, color.Value.B, color.Value.A); - } - - GL.Begin(PrimitiveType.Quads); - if (textureCoordinates == null) - { - GL.TexCoord2(0,0); - GL.Vertex2(point.X, point.Y); - GL.TexCoord2(1,0); - GL.Vertex2(point.X + size.X, point.Y); - GL.TexCoord2(1,1); - GL.Vertex2(point.X + size.X, point.Y + size.Y); - GL.TexCoord2(0,1); - GL.Vertex2(point.X, point.Y + size.Y); - } - else - { - Vector2 v = (Vector2) textureCoordinates; - GL.TexCoord2(0,0); - GL.Vertex2(point.X, point.Y); - GL.TexCoord2(v.X, 0); - GL.Vertex2(point.X + size.X, point.Y); - GL.TexCoord2(v.X, v.Y); - GL.Vertex2(point.X + size.X, point.Y + size.Y); - GL.TexCoord2(0, v.Y); - GL.Vertex2(point.X, point.Y + size.Y); - } - GL.End(); - GL.Disable(EnableCap.Texture2D); - } - - GL.PopMatrix(); - - GL.MatrixMode(MatrixMode.Projection); - GL.PopMatrix(); - } - + private void DrawWithShader(Texture texture, Vector2 point, Vector2 size, Color128? color, Vector2 coordinates, OpenGlTextureWrapMode? wrapMode = null) { Shader.Activate(); diff --git a/source/LibRender2/Shaders/Shader.cs b/source/LibRender2/Shaders/Shader.cs index 1a63c7622b..4813652440 100644 --- a/source/LibRender2/Shaders/Shader.cs +++ b/source/LibRender2/Shaders/Shader.cs @@ -1,7 +1,3 @@ -using System; -using System.IO; -using System.Reflection; -using System.Text; using LibRender2.Fogs; using OpenBveApi.Colors; using OpenBveApi.Math; @@ -9,6 +5,11 @@ using OpenBveApi.Textures; using OpenTK; using OpenTK.Graphics.OpenGL; +using System; +using System.IO; +using System.Numerics; +using System.Reflection; +using System.Text; using Vector2 = OpenBveApi.Math.Vector2; using Vector3 = OpenBveApi.Math.Vector3; using Vector4 = OpenBveApi.Math.Vector4; @@ -476,5 +477,28 @@ public void SetAlphaTest(bool enabled) } #endregion + + public int GetAttribLocation(string attribName) + { + return GL.GetAttribLocation(handle, attribName); + } + + public void SetUniform(string name, int value) + { + int location = GL.GetUniformLocation(handle, name); + GL.ProgramUniform1(handle, location, value); + } + + public unsafe void SetUniform(string name, Matrix4D value) + { + int location = GL.GetUniformLocation(handle, name); + if (location == -1) + { + throw new Exception($"{name} uniform not found on shader."); + } + + Matrix4 matrix = ConvertToMatrix4(value); + GL.ProgramUniformMatrix4(handle, location, false, ref matrix); + } } } diff --git a/source/LibRender2/Text/FontStash.cs b/source/LibRender2/Text/FontStash.cs new file mode 100644 index 0000000000..0a26e097a3 --- /dev/null +++ b/source/LibRender2/Text/FontStash.cs @@ -0,0 +1,139 @@ +using FontStashSharp.Interfaces; +using LibRender2.Shaders; +using OpenTK.Graphics.OpenGL; +using System; +using OpenBveApi.Math; + +namespace LibRender2.Text +{ + internal class FontStashRenderer : IFontStashRenderer2, IDisposable + { + private const int MAX_SPRITES = 2048; + private const int MAX_VERTICES = MAX_SPRITES * 4; + private const int MAX_INDICES = MAX_SPRITES * 6; + private BaseRenderer renderer; + + private readonly Shader shader; + private readonly BufferObject vertexBuffer; + private readonly BufferObject indexBuffer; + private readonly FontStashVAO vao; + private readonly VertexPositionColorTexture[] vertexData = new VertexPositionColorTexture[MAX_VERTICES]; + private FontStashTexture lastTexture; + private int vertexIndex = 0; + + private readonly FontStashTextureManager textureManager; + + public ITexture2DManager TextureManager => textureManager; + + private static readonly ushort[] indexData = GenerateIndexArray(); + + public unsafe FontStashRenderer(BaseRenderer rendererReference) + { + renderer = rendererReference; + textureManager = new FontStashTextureManager(); + vertexBuffer = new BufferObject(MAX_VERTICES, BufferTarget.ArrayBuffer, true); + + indexBuffer = new BufferObject(indexData.Length, BufferTarget.ElementArrayBuffer, false); + indexBuffer.SetData(indexData, 0, indexData.Length); + + shader = new Shader(renderer, "text", "text", true); + shader.Activate(); + vao = new FontStashVAO(sizeof(VertexPositionColorTexture)); + vao.Bind(); + + var location = shader.GetAttribLocation("a_position"); + vao.VertexAttribPointer(location, 3, VertexAttribPointerType.Double, false, 0); + + location = shader.GetAttribLocation("a_color"); + vao.VertexAttribPointer(location, 4, VertexAttribPointerType.UnsignedByte, true, 24); + + location = shader.GetAttribLocation("a_texCoords0"); + vao.VertexAttribPointer(location, 2, VertexAttribPointerType.Double, false, 28); + } + + ~FontStashRenderer() => Dispose(false); + public void Dispose() => Dispose(true); + + protected virtual void Dispose(bool disposing) + { + if (!disposing) + { + return; + } + + vao.Dispose(); + vertexBuffer.Dispose(); + indexBuffer.Dispose(); + shader.Dispose(); + } + + public void Begin() + { + GL.Disable(EnableCap.DepthTest); + + GL.Enable(EnableCap.Blend); + + GL.BlendFunc(BlendingFactor.One, BlendingFactor.OneMinusSrcAlpha); + + + shader.Activate(); + shader.SetUniform("TextureSampler", 0); + + Matrix4D.CreateOrthographicOffCenter(0, renderer.Screen.Width, renderer.Screen.Height, 0, 0, -1, out var transform); + shader.SetUniform("MatrixTransform", transform); + + vao.Bind(); + indexBuffer.Bind(); + vertexBuffer.Bind(); + } + + public void DrawQuad(object texture, ref VertexPositionColorTexture topLeft, ref VertexPositionColorTexture topRight, ref VertexPositionColorTexture bottomLeft, ref VertexPositionColorTexture bottomRight) + { + if (lastTexture != (FontStashTexture)texture) + { + FlushBuffer(); + } + + vertexData[vertexIndex++] = topLeft; + vertexData[vertexIndex++] = topRight; + vertexData[vertexIndex++] = bottomLeft; + vertexData[vertexIndex++] = bottomRight; + lastTexture = (FontStashTexture)texture; + } + + public void End() + { + FlushBuffer(); + } + + private unsafe void FlushBuffer() + { + if (vertexIndex == 0 || lastTexture == null) + { + return; + } + vertexBuffer.Bind(); + vertexBuffer.SetData(vertexData, 0, vertexIndex); + + lastTexture.Bind(); + + GL.DrawElements(PrimitiveType.Triangles, vertexIndex * 6 / 4, DrawElementsType.UnsignedShort, IntPtr.Zero); + vertexIndex = 0; + } + + private static ushort[] GenerateIndexArray() + { + ushort[] result = new ushort[MAX_INDICES]; + for (int i = 0, j = 0; i < MAX_INDICES; i += 6, j += 4) + { + result[i] = (ushort)(j); + result[i + 1] = (ushort)(j + 1); + result[i + 2] = (ushort)(j + 2); + result[i + 3] = (ushort)(j + 3); + result[i + 4] = (ushort)(j + 2); + result[i + 5] = (ushort)(j + 1); + } + return result; + } + } +} diff --git a/source/LibRender2/Text/FontStash/FontStashIBO.cs b/source/LibRender2/Text/FontStash/FontStashIBO.cs new file mode 100644 index 0000000000..7c68b5d851 --- /dev/null +++ b/source/LibRender2/Text/FontStash/FontStashIBO.cs @@ -0,0 +1,48 @@ +using System; +using System.Runtime.InteropServices; +using OpenTK.Graphics.OpenGL; + +namespace LibRender2 +{ + public class BufferObject : IDisposable + { + private readonly int _handle; + private readonly BufferTarget _bufferType; + private readonly int _size; + + public unsafe BufferObject(int size, BufferTarget bufferType, bool isDynamic) + { + _bufferType = bufferType; + _size = size; + + _handle = GL.GenBuffer(); + + Bind(); + + var elementSizeInBytes = Marshal.SizeOf(); + GL.BufferData(bufferType, size * elementSizeInBytes, IntPtr.Zero, isDynamic ? BufferUsageHint.StreamDraw : BufferUsageHint.StaticDraw); + } + + public void Bind() + { + GL.BindBuffer(_bufferType, _handle); + } + + public void Dispose() + { + GL.DeleteBuffer(_handle); + + } + + public unsafe void SetData(T[] data, int startIndex, int elementCount) + { + Bind(); + fixed (T* dataPtr = &data[startIndex]) + { + var elementSizeInBytes = sizeof(T); + + GL.BufferSubData(_bufferType, IntPtr.Zero, elementCount * elementSizeInBytes, new IntPtr(dataPtr)); + } + } + } +} diff --git a/source/LibRender2/Text/FontStash/FontStashTexture.cs b/source/LibRender2/Text/FontStash/FontStashTexture.cs new file mode 100644 index 0000000000..7edc220396 --- /dev/null +++ b/source/LibRender2/Text/FontStash/FontStashTexture.cs @@ -0,0 +1,106 @@ +using FontStashSharp.Interfaces; +using OpenTK.Graphics.OpenGL; +using System; +using System.Drawing; +using PixelFormat = OpenTK.Graphics.OpenGL.PixelFormat; + + +namespace LibRender2.Text +{ + internal class FontStashTextureManager : ITexture2DManager + { + public object CreateTexture(int width, int height) => new FontStashTexture(width, height); + + public Point GetTextureSize(object texture) + { + var t = (FontStashTexture)texture; + return new Point(t.Width, t.Height); + } + + public void SetTextureData(object texture, Rectangle bounds, byte[] data) + { + var t = (FontStashTexture)texture; + t.SetData(bounds, data); + } + } + + public unsafe class FontStashTexture : IDisposable + { + private readonly int _handle; + + public readonly int Width; + public readonly int Height; + + public FontStashTexture(int width, int height) + { + Width = width; + Height = height; + + _handle = GL.GenTexture(); + + Bind(); + + //Reserve enough memory from the gpu for the whole image + GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba8, width, height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, IntPtr.Zero); + + + SetParameters(); + } + + private void SetParameters() + { + //Setting some texture perameters so the texture behaves as expected. + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToEdge); + + + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge); + + + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear); + + + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMinFilter.Linear); + + + //Generating mipmaps. + GL.GenerateMipmap(GenerateMipmapTarget.Texture2D); + + } + + public void Bind(TextureUnit textureSlot = TextureUnit.Texture0) + { + //When we bind a texture we can choose which textureslot we can bind it to. + GL.ActiveTexture(textureSlot); + + + GL.BindTexture(TextureTarget.Texture2D, _handle); + + } + + public void Dispose() + { + //In order to dispose we need to delete the opengl handle for the texure. + GL.DeleteTexture(_handle); + + } + + public void SetData(Rectangle bounds, byte[] data) + { + Bind(); + fixed (byte* ptr = data) + { + GL.TexSubImage2D( + target: TextureTarget.Texture2D, + level: 0, + xoffset: bounds.Left, + yoffset: bounds.Top, + width: bounds.Width, + height: bounds.Height, + format: PixelFormat.Rgba, + type: PixelType.UnsignedByte, + pixels: new IntPtr(ptr) + ); + } + } + } +} diff --git a/source/LibRender2/Text/FontStash/FontStashVAO.cs b/source/LibRender2/Text/FontStash/FontStashVAO.cs new file mode 100644 index 0000000000..aaaab90ea0 --- /dev/null +++ b/source/LibRender2/Text/FontStash/FontStashVAO.cs @@ -0,0 +1,39 @@ +using System; +using OpenTK.Graphics.OpenGL; + +namespace LibRender2 +{ + public class FontStashVAO : IDisposable + { + private readonly uint _handle; + private readonly int _stride; + + public FontStashVAO(int stride) + { + if (stride <= 0) + { + throw new ArgumentOutOfRangeException(nameof(stride)); + } + + _stride = stride; + + GL.GenVertexArrays(1, out _handle); + } + + public void Dispose() + { + GL.DeleteVertexArray(_handle); + } + + public void Bind() + { + GL.BindVertexArray(_handle); + } + + public unsafe void VertexAttribPointer(int location, int size, VertexAttribPointerType type, bool normalized, int offset) + { + GL.EnableVertexAttribArray(location); + GL.VertexAttribPointer(location, size, type, normalized, _stride, new IntPtr(offset)); + } + } +} diff --git a/source/LibRender2/Text/Fonts.cs b/source/LibRender2/Text/Fonts.cs index 192d33af49..d36ff803f3 100644 --- a/source/LibRender2/Text/Fonts.cs +++ b/source/LibRender2/Text/Fonts.cs @@ -1,6 +1,7 @@ -using System.Drawing; -using System.IO; +using FontStashSharp; using OpenBveApi.Hosts; +using System.Drawing; +using System.IO; namespace LibRender2.Text { @@ -92,14 +93,23 @@ public Fonts(HostInterface host, BaseRenderer renderer, string fontName) } + var settings = new FontSystemSettings + { + FontResolutionFactor = 2, + KernelWidth = 2, + KernelHeight = 2 + }; + FontSystem fontSystem = new FontSystem(settings); + fontSystem.AddFont(File.ReadAllBytes(@"DroidSans.ttf")); + float scaleFactor = (float)renderer.ScaleFactor.X; - VerySmallFont = new OpenGlFont(uiFont, 9.0f * scaleFactor); - SmallFont = new OpenGlFont(uiFont, 12.0f * scaleFactor); - NormalFont = new OpenGlFont(uiFont, 16.0f * scaleFactor); - LargeFont = new OpenGlFont(uiFont, 21.0f * scaleFactor); - VeryLargeFont = new OpenGlFont(uiFont, 27.0f * scaleFactor); - EvenLargerFont = new OpenGlFont(uiFont, 34.0f * scaleFactor); + VerySmallFont = new OpenGlFont(renderer, fontSystem.GetFont(9.0f * scaleFactor / 0.75f), 9.0f * scaleFactor); + SmallFont = new OpenGlFont(renderer, fontSystem.GetFont(12.0f * scaleFactor / 0.75f), 12.0f * scaleFactor); + NormalFont = new OpenGlFont(renderer, fontSystem.GetFont(16.0f * scaleFactor / 0.75f), 16.0f * scaleFactor); + LargeFont = new OpenGlFont(renderer, fontSystem.GetFont(21.0f * scaleFactor / 0.75f), 21.0f * scaleFactor); + VeryLargeFont = new OpenGlFont(renderer, fontSystem.GetFont(27.0f * scaleFactor / 0.75f), 27.0f * scaleFactor); + EvenLargerFont = new OpenGlFont(renderer, fontSystem.GetFont(34.0f * scaleFactor / 0.75f), 34.0f * scaleFactor); } } } diff --git a/source/LibRender2/Text/OpenGlFont.cs b/source/LibRender2/Text/OpenGlFont.cs index 1506544337..9e487009cd 100644 --- a/source/LibRender2/Text/OpenGlFont.cs +++ b/source/LibRender2/Text/OpenGlFont.cs @@ -1,58 +1,27 @@ -using System; -using System.Drawing; +using FontStashSharp; +using OpenBveApi.Colors; using OpenBveApi.Math; -using OpenBveApi.Textures; namespace LibRender2.Text { /// Represents a font. - public sealed class OpenGlFont : IDisposable + public sealed class OpenGlFont { - // --- members --- - /// The underlying font. - private readonly Font Font; + private readonly BaseRenderer renderer; /// The size of the underlying font in pixels. public readonly float FontSize; - /// The 4352 tables containing 256 character each to make up 1114112 code points (U+0000...U+10FFFF). - private readonly OpenGlFontTable[] Tables; + + private DynamicSpriteFont Font; private bool disposed; // --- constructors --- /// Creates a new font. - /// The font family. - /// The size in pixels. - public OpenGlFont(FontFamily family, float size) + public OpenGlFont(BaseRenderer renderererReference, DynamicSpriteFont font, float size) { - Font = new Font(family, size, FontStyle.Regular, GraphicsUnit.Pixel); - FontSize = size; - Tables = new OpenGlFontTable[4352]; - } - - // --- functions --- - /// Gets data associated with the specified codepoint. - /// The string containing the codepoint. - /// The offset at which to read the codepoint. For surrogate pairs, two characters are read, and one otherwise. - /// Receives the texture that contains the codepoint. - /// Receives the data that describes the codepoint. - /// The number of characters read. - public int GetCharacterData(string text, int offset, out Texture texture, out OpenGlFontChar data) - { - int value = char.ConvertToUtf32(text, offset); - int hi = value >> 8; - int lo = value & 0xFF; - - if (Tables[hi] == null || Tables[hi].Texture == null) - { - lock (BaseRenderer.GdiPlusLock) - { - Tables[hi] = new OpenGlFontTable(Font, hi << 8); - } - } - - texture = Tables[hi].Texture; - data = Tables[hi].Characters[lo]; - return value >= 0x10000 ? 2 : 1; + renderer = renderererReference; + Font = font; + FontSize= size; } /// Measures the size of a string as it would be rendered using this font. @@ -60,48 +29,16 @@ public int GetCharacterData(string text, int offset, out Texture texture, out Op /// The size of the string. public Vector2 MeasureString(string text) { - double width = 0; - double height = 0; - - if (text != null) - { - for (int i = 0; i < text.Length; i++) - { - i += GetCharacterData(text, i, out Texture _, out OpenGlFontChar data) - 1; - width += data.TypographicSize.X; - - if (data.TypographicSize.Y > height) - { - height = data.TypographicSize.Y; - } - } - } - - return new Vector2(width, height); - } - - private void Dispose(bool disposing) - { - if (!disposed) - { - if (disposing) - { - Font?.Dispose(); - } - - disposed = true; - } - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); + Vector2f size = Font.MeasureString(text); + return new Vector2(size.X, size.Y); } - ~OpenGlFont() + public void DrawString(string text, double left, double top, Color128 color) { - Dispose(true); + renderer.FontStashRenderer.Begin(); + Font.DrawText(renderer.FontStashRenderer, text, new Vector2f(left, top), color); + renderer.FontStashRenderer.End(); + renderer.RestoreBlendFunc(); } } } diff --git a/source/LibRender2/Text/OpenGlString.cs b/source/LibRender2/Text/OpenGlString.cs index f0cd05691b..fa34b22e6f 100644 --- a/source/LibRender2/Text/OpenGlString.cs +++ b/source/LibRender2/Text/OpenGlString.cs @@ -1,9 +1,8 @@ +using FontStashSharp; using LibRender2.Shaders; using OpenBveApi.Colors; using OpenBveApi.Graphics; using OpenBveApi.Math; -using OpenBveApi.Textures; -using OpenTK.Graphics.OpenGL; namespace LibRender2.Text { @@ -18,15 +17,14 @@ internal OpenGlString(BaseRenderer renderer) this.renderer = renderer; try { - this.Shader = new Shader(renderer, "text", "rectangle", true); + this.Shader = new Shader(renderer, "text", "text", true); } catch { renderer.ForceLegacyOpenGL = true; } - } - + /// Renders a string to the screen. /// The font to use. /// The string to render. @@ -40,6 +38,7 @@ public void Draw(OpenGlFont font, string text, Vector2 location, TextAlignment a { return; } + renderer.LastBoundTexture = null; /* * Prepare the top-left coordinates for rendering, incorporating the @@ -47,15 +46,11 @@ public void Draw(OpenGlFont font, string text, Vector2 location, TextAlignment a * */ double left; + Vector2f size = font.MeasureString(text); + if ((alignment & TextAlignment.Left) == 0) { - double width = 0; - - for (int i = 0; i < text.Length; i++) - { - i += font.GetCharacterData(text, i, out _, out OpenGlFontChar data) - 1; - width += data.TypographicSize.X; - } + double width = size.X; if ((alignment & TextAlignment.Right) != 0) { @@ -75,17 +70,7 @@ public void Draw(OpenGlFont font, string text, Vector2 location, TextAlignment a if ((alignment & TextAlignment.Top) == 0) { - double height = 0; - - for (int i = 0; i < text.Length; i++) - { - i += font.GetCharacterData(text, i, out _, out OpenGlFontChar data) - 1; - - if (data.TypographicSize.Y > height) - { - height = data.TypographicSize.Y; - } - } + double height = size.Y; if ((alignment & TextAlignment.Bottom) != 0) { @@ -101,137 +86,11 @@ public void Draw(OpenGlFont font, string text, Vector2 location, TextAlignment a top = location.Y; } - if (renderer.AvailableNewRenderer && Shader != null) - { - DrawWithShader(text, font, left, top, color); - } - else - { - DrawImmediate(text, font, left, top, color); - } - + font.DrawString(text, left, top, color); } - private void DrawImmediate(string text, OpenGlFont font, double left, double top, Color128 color) - { - /* - * Render the string. - * */ - GL.Enable(EnableCap.Texture2D); - - GL.MatrixMode(MatrixMode.Projection); - GL.PushMatrix(); - unsafe - { - fixed (double* matrixPointer = &renderer.CurrentProjectionMatrix.Row0.X) - { - GL.LoadMatrix(matrixPointer); - } - GL.MatrixMode(MatrixMode.Modelview); - GL.PushMatrix(); - fixed (double* matrixPointer = &renderer.CurrentViewMatrix.Row0.X) - { - GL.LoadMatrix(matrixPointer); - } - } - - - for (int i = 0; i < text.Length; i++) - { - i += font.GetCharacterData(text, i, out Texture texture, out OpenGlFontChar data) - 1; - - if (renderer.currentHost.LoadTexture(ref texture, OpenGlTextureWrapMode.ClampClamp)) - { - GL.BindTexture(TextureTarget.Texture2D, texture.OpenGlTextures[(int)OpenGlTextureWrapMode.ClampClamp].Name); - - double x = left - (data.PhysicalSize.X - data.TypographicSize.X) / 2; - double y = top - (data.PhysicalSize.Y - data.TypographicSize.Y) / 2; - - /* - * In the first pass, mask off the background with pure black. - * */ - GL.BlendFunc(BlendingFactor.Zero, BlendingFactor.OneMinusSrcColor); - GL.Begin(PrimitiveType.Quads); - GL.Color4(color.A, color.A, color.A, 1.0f); - GL.TexCoord2(data.TextureCoordinates.X, data.TextureCoordinates.Y); - GL.Vertex2(x, y); - GL.TexCoord2(data.TextureCoordinates.X + data.TextureCoordinates.Z, data.TextureCoordinates.Y); - GL.Vertex2(x + data.PhysicalSize.X, y); - GL.TexCoord2(data.TextureCoordinates.X + data.TextureCoordinates.Z, data.TextureCoordinates.Y + data.TextureCoordinates.W); - GL.Vertex2(x + data.PhysicalSize.X, y + data.PhysicalSize.Y); - GL.TexCoord2(data.TextureCoordinates.X, data.TextureCoordinates.Y + data.TextureCoordinates.W); - GL.Vertex2(x, y + data.PhysicalSize.Y); - GL.End(); - - /* - * In the second pass, add the character onto the background. - * */ - GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.One); - GL.Begin(PrimitiveType.Quads); - GL.Color4(color.R, color.G, color.B, color.A); - GL.TexCoord2(data.TextureCoordinates.X, data.TextureCoordinates.Y); - GL.Vertex2(x, y); - GL.TexCoord2(data.TextureCoordinates.X + data.TextureCoordinates.Z, data.TextureCoordinates.Y); - GL.Vertex2(x + data.PhysicalSize.X, y); - GL.TexCoord2(data.TextureCoordinates.X + data.TextureCoordinates.Z, data.TextureCoordinates.Y + data.TextureCoordinates.W); - GL.Vertex2(x + data.PhysicalSize.X, y + data.PhysicalSize.Y); - GL.TexCoord2(data.TextureCoordinates.X, data.TextureCoordinates.Y + data.TextureCoordinates.W); - GL.Vertex2(x, y + data.PhysicalSize.Y); - GL.End(); - } - - left += data.TypographicSize.X; - } - - renderer.RestoreBlendFunc(); - GL.Disable(EnableCap.Texture2D); - - GL.PopMatrix(); - - GL.MatrixMode(MatrixMode.Projection); - GL.PopMatrix(); - } - - private void DrawWithShader(string text, OpenGlFont font, double left, double top, Color128 color) - { - Shader.Activate(); - renderer.CurrentShader = Shader; - Shader.SetCurrentProjectionMatrix(renderer.CurrentProjectionMatrix); - Shader.SetCurrentModelViewMatrix(renderer.CurrentViewMatrix); - - for (int i = 0; i < text.Length; i++) - { - i += font.GetCharacterData(text, i, out Texture texture, out OpenGlFontChar data) - 1; - if (renderer.currentHost.LoadTexture(ref texture, OpenGlTextureWrapMode.ClampClamp)) - { - GL.BindTexture(TextureTarget.Texture2D, texture.OpenGlTextures[(int)OpenGlTextureWrapMode.ClampClamp].Name); - Shader.SetAtlasLocation(data.TextureCoordinates); - double x = left - (data.PhysicalSize.X - data.TypographicSize.X) / 2; - double y = top - (data.PhysicalSize.Y - data.TypographicSize.Y) / 2; - - /* - * In the first pass, mask off the background with pure black. - */ - GL.BlendFunc(BlendingFactor.Zero, BlendingFactor.OneMinusSrcColor); - Shader.SetColor(new Color128(color.A, color.A, color.A, 1.0f)); - Shader.SetPoint(new Vector2(x, y)); - Shader.SetSize(data.PhysicalSize); - /* - * In order to call GL.DrawArrays with procedural data within the shader, - * we first need to bind a dummy VAO - * If this is not done, it will generate an InvalidOperation error code - */ - renderer.dummyVao.Bind(); - GL.DrawArrays(PrimitiveType.TriangleStrip, 0, 6); - GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.One); - Shader.SetColor(color); - GL.DrawArrays(PrimitiveType.TriangleStrip, 0, 6); - } - left += data.TypographicSize.X; - } - renderer.RestoreBlendFunc(); - } + /// Renders a string to the screen. /// The font to use. /// The string to render. diff --git a/source/LibRender2/app.config b/source/LibRender2/app.config index a1e2bff25d..6ddefebfae 100644 --- a/source/LibRender2/app.config +++ b/source/LibRender2/app.config @@ -10,6 +10,10 @@ + + + + \ No newline at end of file diff --git a/source/LibRender2/openGL/VertexArrayObject.cs b/source/LibRender2/openGL/VertexArrayObject.cs index 12e368c27d..585f9557a2 100644 --- a/source/LibRender2/openGL/VertexArrayObject.cs +++ b/source/LibRender2/openGL/VertexArrayObject.cs @@ -6,6 +6,7 @@ using OpenTK.Graphics.OpenGL; using System; using System.Collections.Generic; +using System.Drawing; using System.Linq; namespace LibRender2 @@ -158,6 +159,12 @@ public void Dispose() BaseRenderer.vaoToDelete.Add(handle); } } + + public unsafe void SetVertexAttribPointer(int location, int size, VertexAttribPointerType type, bool normalized, int offset) + { + GL.EnableVertexAttribArray(handle); + GL.VertexAttribPointer(handle, size, type, normalized, sizeof(ColoredVertex), new IntPtr(offset)); + } } public static class VAOExtensions diff --git a/source/LibRender2/openGL/VertexBufferObject.cs b/source/LibRender2/openGL/VertexBufferObject.cs index f321f30e9e..220423ba73 100644 --- a/source/LibRender2/openGL/VertexBufferObject.cs +++ b/source/LibRender2/openGL/VertexBufferObject.cs @@ -1,4 +1,6 @@ using System; +using FontStashSharp.Interfaces; +using OpenBveApi.Objects; using OpenTK; using OpenTK.Graphics.OpenGL; @@ -53,6 +55,20 @@ internal void BufferSubData(LibRenderVertex[] VertexData, int Offset = 0) GL.BufferSubData(BufferTarget.ArrayBuffer, new IntPtr(Offset * vertexSize), new IntPtr(VertexData.Length * vertexSize), VertexData); } + internal void BufferSubData(ColoredVertex[] vertexData, int startIndex, int elementCount) + { + unsafe + { + fixed (ColoredVertex* dataPtr = &vertexData[startIndex]) + { + var elementSizeInBytes = sizeof(ColoredVertex); + + GL.BufferSubData(BufferTarget.ArrayBuffer, IntPtr.Zero, elementCount * elementSizeInBytes, new IntPtr(dataPtr)); + } + } + + } + /// Enables a specific vertex attribute array internal void EnableAttribute(VertexLayout VertexLayout) { diff --git a/source/LibRender2/packages.config b/source/LibRender2/packages.config index d01acc57a0..4ca32d6980 100644 --- a/source/LibRender2/packages.config +++ b/source/LibRender2/packages.config @@ -1,5 +1,11 @@  + + + + + + \ No newline at end of file diff --git a/source/LibRender2/text.frag b/source/LibRender2/text.frag new file mode 100644 index 0000000000..5db3a503cf --- /dev/null +++ b/source/LibRender2/text.frag @@ -0,0 +1,23 @@ +#version 150 core + +#ifdef GL_ES + #define LOWP lowp + precision mediump float; +#else + #define LOWP +#endif + +out vec4 fragColor; + + +// Uniforms +uniform sampler2D TextureSampler; + +// Varyings +varying vec4 v_color; +varying vec2 v_texCoords; + +void main() +{ + fragColor = v_color * texture2D(TextureSampler, v_texCoords); +} diff --git a/source/ObjectViewer/Graphics/NewRendererS.cs b/source/ObjectViewer/Graphics/NewRendererS.cs index 7c8820b052..54b1977d9e 100644 --- a/source/ObjectViewer/Graphics/NewRendererS.cs +++ b/source/ObjectViewer/Graphics/NewRendererS.cs @@ -97,10 +97,7 @@ internal void ApplyBackgroundColor(byte red, byte green, byte blue) internal void RenderScene(double timeElapsed) { lastObjectState = null; - if (AvailableNewRenderer) - { - CurrentShader.Deactivate(); - } + CurrentShader.Deactivate(); ReleaseResources(); // initialize ResetOpenGlState(); @@ -110,11 +107,7 @@ internal void RenderScene(double timeElapsed) 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)); TransformedLightPosition = new Vector3(Lighting.OptionLightPosition.X, Lighting.OptionLightPosition.Y, -Lighting.OptionLightPosition.Z); TransformedLightPosition.Transform(CurrentViewMatrix); - if (!AvailableNewRenderer) - { - GL.Light(LightName.Light0, LightParameter.Position, new[] { (float)TransformedLightPosition.X, (float)TransformedLightPosition.Y, (float)TransformedLightPosition.Z, 0.0f }); - } - + Lighting.OptionLightingResultingAmount = (Lighting.OptionAmbientColor.R + Lighting.OptionAmbientColor.G + Lighting.OptionAmbientColor.B) / 480.0f; if (Lighting.OptionLightingResultingAmount > 1.0f) @@ -127,41 +120,25 @@ internal void RenderScene(double timeElapsed) if (OptionCoordinateSystem) { UnsetAlphaFunc(); - - if (AvailableNewRenderer) - { - redAxisVAO.Draw(Vector3.Zero, Vector3.Forward, Vector3.Down, Vector3.Right, new Vector3(100.0, 0.01, 0.01), Camera.AbsolutePosition, null); - greenAxisVAO.Draw(Vector3.Zero, Vector3.Forward, Vector3.Down, Vector3.Right, new Vector3(0.01, 100.0, 0.01), Camera.AbsolutePosition, null); - blueAxisVAO.Draw(Vector3.Zero, Vector3.Forward, Vector3.Down, Vector3.Right, new Vector3(0.01, 0.01, 100.0), Camera.AbsolutePosition, null); - } - else - { - GL.Color4(1.0, 0.0, 0.0, 0.2); - Cube.Draw(Vector3.Zero, Vector3.Forward, Vector3.Down, Vector3.Right, new Vector3(100.0, 0.01, 0.01), Camera.AbsolutePosition, null); - GL.Color4(0.0, 1.0, 0.0, 0.2); - Cube.Draw(Vector3.Zero, Vector3.Forward, Vector3.Down, Vector3.Right, new Vector3(0.01, 100.0, 0.01), Camera.AbsolutePosition, null); - GL.Color4(0.0, 0.0, 1.0, 0.2); - Cube.Draw(Vector3.Zero, Vector3.Forward, Vector3.Down, Vector3.Right, new Vector3(0.01, 0.01, 100.0), Camera.AbsolutePosition, null); - } + redAxisVAO.Draw(Vector3.Zero, Vector3.Forward, Vector3.Down, Vector3.Right, new Vector3(100.0, 0.01, 0.01), Camera.AbsolutePosition, null); + greenAxisVAO.Draw(Vector3.Zero, Vector3.Forward, Vector3.Down, Vector3.Right, new Vector3(0.01, 100.0, 0.01), Camera.AbsolutePosition, null); + blueAxisVAO.Draw(Vector3.Zero, Vector3.Forward, Vector3.Down, Vector3.Right, new Vector3(0.01, 0.01, 100.0), Camera.AbsolutePosition, null); } GL.Disable(EnableCap.DepthTest); // opaque face - if (AvailableNewRenderer) + //Setup the shader for rendering the scene + DefaultShader.Activate(); + if (OptionLighting) { - //Setup the shader for rendering the scene - DefaultShader.Activate(); - if (OptionLighting) - { - DefaultShader.SetIsLight(true); - DefaultShader.SetLightPosition(TransformedLightPosition); - DefaultShader.SetLightAmbient(Lighting.OptionAmbientColor); - DefaultShader.SetLightDiffuse(Lighting.OptionDiffuseColor); - DefaultShader.SetLightSpecular(Lighting.OptionSpecularColor); - DefaultShader.SetLightModel(Lighting.LightModel); - } - DefaultShader.SetTexture(0); - DefaultShader.SetCurrentProjectionMatrix(CurrentProjectionMatrix); + DefaultShader.SetIsLight(true); + DefaultShader.SetLightPosition(TransformedLightPosition); + DefaultShader.SetLightAmbient(Lighting.OptionAmbientColor); + DefaultShader.SetLightDiffuse(Lighting.OptionDiffuseColor); + DefaultShader.SetLightSpecular(Lighting.OptionSpecularColor); + DefaultShader.SetLightModel(Lighting.LightModel); } + DefaultShader.SetTexture(0); + DefaultShader.SetCurrentProjectionMatrix(CurrentProjectionMatrix); ResetOpenGlState(); List opaqueFaces, alphaFaces; lock (VisibleObjects.LockObject) @@ -236,11 +213,8 @@ internal void RenderScene(double timeElapsed) } } - if (AvailableNewRenderer) - { - DefaultShader.Deactivate(); - lastVAO = -1; - } + DefaultShader.Deactivate(); + lastVAO = -1; // render overlays ResetOpenGlState(); @@ -322,7 +296,7 @@ private void RenderOverlays(double timeElapsed) else { OpenGlString.Draw(Fonts.SmallFont, $"Position: {Camera.AbsolutePosition.X.ToString("0.00", culture)}, {Camera.AbsolutePosition.Y.ToString("0.00", culture)}, {Camera.AbsolutePosition.Z.ToString("0.00", culture)}", new Vector2((int)(0.5 * Screen.Width - 88), 4), TextAlignment.TopLeft, TextColor); - OpenGlString.Draw(Fonts.SmallFont, ForceLegacyOpenGL ? $"Renderer: Old (GL 1.2)- GL 3.0 not available" : $"Renderer: {(AvailableNewRenderer ? "New (GL 3.0)" : "Old (GL 1.2)")}", new Vector2((int)(0.5 * Screen.Width - 88), 24), TextAlignment.TopLeft, Color128.White); + OpenGlString.Draw(Fonts.SmallFont, $"Renderer: New (GL 3.0)", new Vector2((int)(0.5 * Screen.Width - 88), 24), TextAlignment.TopLeft, Color128.White); int errorPos; if (Program.CurrentHost.Platform == HostPlatform.AppleOSX && IntPtr.Size != 4) @@ -337,7 +311,7 @@ private void RenderOverlays(double timeElapsed) else { OpenGlString.Draw(Fonts.SmallFont, $"Position: {Camera.AbsolutePosition.X.ToString("0.00", culture)}, {Camera.AbsolutePosition.Y.ToString("0.00", culture)}, {Camera.AbsolutePosition.Z.ToString("0.00", culture)}", new Vector2((int)(0.5 * Screen.Width - 88), 4), TextAlignment.TopLeft, TextColor); - OpenGlString.Draw(Fonts.SmallFont, ForceLegacyOpenGL ? $"Renderer: Old (GL 1.2)- GL 3.0 not available" : $"Renderer: {(AvailableNewRenderer ? "New (GL 3.0)" : "Old (GL 1.2)")}", new Vector2((int)(0.5 * Screen.Width - 88), 24), TextAlignment.TopLeft, Color128.White); + OpenGlString.Draw(Fonts.SmallFont, $"Renderer: New (GL 3.0)", new Vector2((int)(0.5 * Screen.Width - 88), 24), TextAlignment.TopLeft, Color128.White); keys = new[] { new[] { "F5" }, new[] { "F7" }, new[] { "del" }, new[] { "F8" }, new[] { "F10" } }; Keys.Render(4, 4, 24, Fonts.SmallFont, keys); OpenGlString.Draw(Fonts.SmallFont, "Reload the currently open objects", new Vector2(32 * scaleFactor, 4), TextAlignment.TopLeft, TextColor); diff --git a/source/ObjectViewer/ProgramS.cs b/source/ObjectViewer/ProgramS.cs index 28fab6c621..d5d6ba1c3c 100644 --- a/source/ObjectViewer/ProgramS.cs +++ b/source/ObjectViewer/ProgramS.cs @@ -598,9 +598,6 @@ internal static void KeyDown(object sender, KeyboardKeyEventArgs e) Renderer.ApplyBackgroundColor(); } break; - case Key.R: - Renderer.SwitchOpenGLVersion(); - break; case Key.F11: Renderer.RenderStatsOverlay = !Renderer.RenderStatsOverlay; break; diff --git a/source/ObjectViewer/app.config b/source/ObjectViewer/app.config index 9706ed099b..3b593dbe21 100644 --- a/source/ObjectViewer/app.config +++ b/source/ObjectViewer/app.config @@ -16,6 +16,10 @@ + + + + diff --git a/source/OpenBVE/Graphics/NewRenderer.cs b/source/OpenBVE/Graphics/NewRenderer.cs index 5124d0f2c2..70d6d314f4 100644 --- a/source/OpenBVE/Graphics/NewRenderer.cs +++ b/source/OpenBVE/Graphics/NewRenderer.cs @@ -162,11 +162,7 @@ internal void RenderScene(double TimeElapsed, double RealTimeElapsed) } TransformedLightPosition = new Vector3(Lighting.OptionLightPosition.X, Lighting.OptionLightPosition.Y, -Lighting.OptionLightPosition.Z); TransformedLightPosition.Transform(CurrentViewMatrix); - if (!AvailableNewRenderer) - { - GL.Light(LightName.Light0, LightParameter.Position, new[] { (float)TransformedLightPosition.X, (float)TransformedLightPosition.Y, (float)TransformedLightPosition.Z, 0.0f }); - } - + Lighting.OptionLightingResultingAmount = (Lighting.OptionAmbientColor.R + Lighting.OptionAmbientColor.G + Lighting.OptionAmbientColor.B) / 480.0f; if (Lighting.OptionLightingResultingAmount > 1.0f) @@ -213,10 +209,6 @@ internal void RenderScene(double TimeElapsed, double RealTimeElapsed) Fog.Color = Program.CurrentRoute.CurrentFog.Color; Fog.Density = Program.CurrentRoute.CurrentFog.Density; Fog.IsLinear = Program.CurrentRoute.CurrentFog.IsLinear; - if (!AvailableNewRenderer) - { - Fog.SetForImmediateMode(); - } } else @@ -226,27 +218,24 @@ internal void RenderScene(double TimeElapsed, double RealTimeElapsed) // world layer // opaque face - if (AvailableNewRenderer) + //Setup the shader for rendering the scene + DefaultShader.Activate(); + if (OptionLighting) { - //Setup the shader for rendering the scene - DefaultShader.Activate(); - if (OptionLighting) - { - DefaultShader.SetIsLight(true); - 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.SetFog(Fog); - } - DefaultShader.SetTexture(0); - DefaultShader.SetCurrentProjectionMatrix(CurrentProjectionMatrix); + DefaultShader.SetIsLight(true); + 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.SetFog(Fog); } + DefaultShader.SetTexture(0); + DefaultShader.SetCurrentProjectionMatrix(CurrentProjectionMatrix); ResetOpenGlState(); List opaqueFaces, alphaFaces, overlayOpaqueFaces, overlayAlphaFaces; lock (VisibleObjects.LockObject) @@ -331,10 +320,7 @@ internal void RenderScene(double TimeElapsed, double RealTimeElapsed) if (Interface.CurrentOptions.MotionBlur != MotionBlurMode.None) { - if (AvailableNewRenderer) - { - DefaultShader.Deactivate(); - } + DefaultShader.Deactivate(); MotionBlur.RenderFullscreen(Interface.CurrentOptions.MotionBlur, FrameRate, Math.Abs(Camera.CurrentSpeed)); } @@ -357,17 +343,14 @@ internal void RenderScene(double TimeElapsed, double RealTimeElapsed) // overlay (cab / interior) 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); - } + + /* + * 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) @@ -379,22 +362,14 @@ internal void RenderScene(double TimeElapsed, double RealTimeElapsed) Color24 prevOptionDiffuseColor = Lighting.OptionDiffuseColor; Lighting.OptionAmbientColor = Color24.LightGrey; Lighting.OptionDiffuseColor = Color24.LightGrey; - if (AvailableNewRenderer) - { - 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); - } - else - { - 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 }); - } - + 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); + // overlay opaque face foreach (FaceState face in overlayOpaqueFaces) @@ -474,11 +449,8 @@ internal void RenderScene(double TimeElapsed, double RealTimeElapsed) */ ResetOpenGlState(); OptionLighting = false; - if (AvailableNewRenderer) - { - DefaultShader.SetIsLight(false); - } - + DefaultShader.SetIsLight(false); + SetBlendFunc(); UnsetAlphaFunc(); GL.Disable(EnableCap.DepthTest); diff --git a/source/OpenBVE/Graphics/Renderers/Overlays.Debug.cs b/source/OpenBVE/Graphics/Renderers/Overlays.Debug.cs index a91c6211c8..ee592bc612 100644 --- a/source/OpenBVE/Graphics/Renderers/Overlays.Debug.cs +++ b/source/OpenBVE/Graphics/Renderers/Overlays.Debug.cs @@ -201,7 +201,7 @@ private void RenderDebugOverlays() "total animated objects: " + ObjectManager.AnimatedWorldObjectsUsed.ToString(Culture), "", "=renderer", - "renderer type: " + (Program.Renderer.AvailableNewRenderer ? "openGL 3.0 (new)" : "openGL 1.2 (old)"), + "renderer type: openGL 3.0 (new)", "opaque faces: " + Program.Renderer.VisibleObjects.OpaqueFaces.Count.ToString(Culture), "alpha faces: " + Program.Renderer.VisibleObjects.AlphaFaces.Count.ToString(Culture), "overlay opaque faces: " + Program.Renderer.VisibleObjects.OverlayOpaqueFaces.Count.ToString(Culture), diff --git a/source/OpenBVE/Graphics/Renderers/Touch.cs b/source/OpenBVE/Graphics/Renderers/Touch.cs index b1a34f2d5d..1f39aa7012 100644 --- a/source/OpenBVE/Graphics/Renderers/Touch.cs +++ b/source/OpenBVE/Graphics/Renderers/Touch.cs @@ -45,23 +45,16 @@ internal Touch(NewRenderer renderer) internal void UpdateViewport() { - if (renderer.AvailableNewRenderer) - { - fbo.Bind(); - fbo.SetTextureBuffer(FrameBufferObject.TargetBuffer.Color, PixelInternalFormat.R32f, PixelFormat.Red, PixelType.Float, renderer.Screen.Width, renderer.Screen.Height); - fbo.DrawBuffers(new[] { DrawBuffersEnum.ColorAttachment0 }); - fbo.UnBind(); - } + fbo.Bind(); + fbo.SetTextureBuffer(FrameBufferObject.TargetBuffer.Color, PixelInternalFormat.R32f, PixelFormat.Red, PixelType.Float, renderer.Screen.Width, renderer.Screen.Height); + fbo.DrawBuffers(new[] { DrawBuffersEnum.ColorAttachment0 }); + fbo.UnBind(); } private void ShowObject(ObjectState state) { touchableObject.Add(state); - - if (renderer.AvailableNewRenderer && state.Prototype.Mesh.VAO == null) - { - VAOExtensions.CreateVAO(state.Prototype.Mesh, state.Prototype.Dynamic, renderer.pickingShader.VertexLayout, renderer); - } + VAOExtensions.CreateVAO(state.Prototype.Mesh, state.Prototype.Dynamic, renderer.pickingShader.VertexLayout, renderer); } private void PreRender() @@ -111,61 +104,44 @@ internal void RenderScene() renderer.ResetOpenGlState(); - if (renderer.AvailableNewRenderer) + fbo.Bind(); + GL.ClearColor(0.0f, 0.0f, 0.0f, 0.0f); + GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); + renderer.pickingShader.Activate(); + renderer.pickingShader.SetCurrentProjectionMatrix(renderer.CurrentProjectionMatrix); + + for (int i = 0; i < touchableObject.Count; i++) { - fbo.Bind(); - GL.ClearColor(0.0f, 0.0f, 0.0f, 0.0f); - GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); - renderer.pickingShader.Activate(); - renderer.pickingShader.SetCurrentProjectionMatrix(renderer.CurrentProjectionMatrix); + renderer.pickingShader.SetObjectIndex(i + 1); - for (int i = 0; i < touchableObject.Count; i++) + foreach (MeshFace face in touchableObject[i].Prototype.Mesh.Faces) { - renderer.pickingShader.SetObjectIndex(i + 1); - - foreach (MeshFace face in touchableObject[i].Prototype.Mesh.Faces) - { - renderer.RenderFace(renderer.pickingShader, touchableObject[i], face); - } + renderer.RenderFace(renderer.pickingShader, touchableObject[i], face); } - - //Must deactivate and unbind here - renderer.pickingShader.Deactivate(); - fbo.UnBind(); } + //Must deactivate and unbind here + renderer.pickingShader.Deactivate(); + fbo.UnBind(); + // for debug if (renderer.DebugTouchMode) { GL.DepthMask(false); GL.Disable(EnableCap.DepthTest); - if (renderer.AvailableNewRenderer) - { - renderer.DefaultShader.Activate(); - renderer.ResetShader(renderer.DefaultShader); - renderer.DefaultShader.SetCurrentProjectionMatrix(renderer.CurrentProjectionMatrix); - - foreach (ObjectState objectState in touchableObject) - { - foreach (MeshFace face in objectState.Prototype.Mesh.Faces) - { - renderer.RenderFace(renderer.DefaultShader, objectState, face, true); - } - } + renderer.DefaultShader.Activate(); + renderer.ResetShader(renderer.DefaultShader); + renderer.DefaultShader.SetCurrentProjectionMatrix(renderer.CurrentProjectionMatrix); - renderer.DefaultShader.Deactivate(); - } - else + foreach (ObjectState objectState in touchableObject) { - foreach (ObjectState objectState in touchableObject) + foreach (MeshFace face in objectState.Prototype.Mesh.Faces) { - foreach (MeshFace face in objectState.Prototype.Mesh.Faces) - { - renderer.RenderFaceImmediateMode(objectState, face, true); - } + renderer.RenderFace(renderer.DefaultShader, objectState, face, true); } } + renderer.DefaultShader.Deactivate(); } } @@ -252,47 +228,6 @@ private static List ParseSelectBuffer(int[] selectBuffer) } } - private ObjectState RenderSceneSelection(Vector2 point, Vector2 delta) - { - // Pre - PreRender(); - renderer.ResetOpenGlState(); - int[] selectBuffer = new int[2048]; - GL.SelectBuffer(selectBuffer.Length, selectBuffer); - GL.RenderMode(RenderingMode.Select); - renderer.PushMatrix(MatrixMode.Projection); - renderer.CurrentProjectionMatrix = CreatePickMatrix(point, delta); - int partID = 0; - GL.InitNames(); - GL.PushName(0); - - // Rendering - foreach (ObjectState objectState in touchableObject) - { - GL.LoadName(partID); - - foreach (MeshFace face in objectState.Prototype.Mesh.Faces) - { - renderer.RenderFaceImmediateMode(objectState, face); - } - - partID++; - } - - // Post - GL.PopName(); - renderer.PopMatrix(MatrixMode.Projection); - int hits = GL.RenderMode(RenderingMode.Render); - - if (hits <= 0) - { - return null; - } - - List pickedObjects = ParseSelectBuffer(selectBuffer); - return pickedObjects.Any() ? touchableObject[pickedObjects.OrderBy(x => x.MinDepth).First().Names[0]] : null; - } - internal bool MoveCheck(Vector2 Point, out MouseCursor.Status Status, out MouseCursor NewCursor) { NewCursor = null; @@ -326,7 +261,7 @@ internal bool MoveCheck(Vector2 Point, out MouseCursor.Status Status, out MouseC return false; } - ObjectState pickedObject = renderer.AvailableNewRenderer ? ParseFBO(Point, 5, 5) : RenderSceneSelection(Point, new Vector2(5.0f)); + ObjectState pickedObject = ParseFBO(Point, 5, 5); foreach (TouchElement TouchElement in TouchElements.Where(x => x.Element.internalObject == pickedObject)) { @@ -383,7 +318,7 @@ internal void TouchCheck(Vector2 Point) return; } - ObjectState pickedObject = renderer.AvailableNewRenderer ? ParseFBO(Point, 5, 5) : RenderSceneSelection(Point, new Vector2(5.0f)); + ObjectState pickedObject = ParseFBO(Point, 5, 5); foreach (TouchElement TouchElement in TouchElements.Where(x => x.Element.internalObject == pickedObject)) { @@ -428,7 +363,7 @@ internal void LeaveCheck(Vector2 Point) return; } - ObjectState pickedObject = renderer.AvailableNewRenderer ? ParseFBO(Point, 5, 5) : RenderSceneSelection(Point, new Vector2(5.0f)); + ObjectState pickedObject = ParseFBO(Point, 5, 5); foreach (TouchElement TouchElement in TouchElements) { diff --git a/source/OpenBVE/System/Input/ProcessControls.Digital.cs b/source/OpenBVE/System/Input/ProcessControls.Digital.cs index 8ea3fff47a..055aaa2095 100644 --- a/source/OpenBVE/System/Input/ProcessControls.Digital.cs +++ b/source/OpenBVE/System/Input/ProcessControls.Digital.cs @@ -1088,10 +1088,6 @@ private static void ProcessDigitalControl(double TimeElapsed, ref Control Contro case Translations.Command.ShowEvents: Interface.CurrentOptions.ShowEvents = !Interface.CurrentOptions.ShowEvents; break; - case Translations.Command.DebugRendererMode: - Interface.CurrentOptions.IsUseNewRenderer = !Interface.CurrentOptions.IsUseNewRenderer; - MessageManager.AddMessage($"Renderer mode: {(Program.Renderer.AvailableNewRenderer ? "New renderer" : "Original renderer")}", MessageDependency.None, GameMode.Expert, MessageColor.White, Program.CurrentRoute.SecondsSinceMidnight + 10.0, null); - break; case Translations.Command.MiscAI: // option: AI if (Interface.CurrentOptions.GameMode == GameMode.Expert) diff --git a/source/OpenBVE/app.config b/source/OpenBVE/app.config index e5213d2369..92b846bf43 100644 --- a/source/OpenBVE/app.config +++ b/source/OpenBVE/app.config @@ -17,6 +17,10 @@ + + + + diff --git a/source/OpenBveApi/Graphics/Colors.cs b/source/OpenBveApi/Graphics/Colors.cs index a81779950f..f20045e234 100644 --- a/source/OpenBveApi/Graphics/Colors.cs +++ b/source/OpenBveApi/Graphics/Colors.cs @@ -652,6 +652,14 @@ public static implicit operator Color32(System.Drawing.Color c) { return new Color32(c.R, c.G, c.B, c.A); } + + /// Casts a Color128 to a Color32, performing narrowing + /// The Color128 + /// The new Color32 + public static implicit operator Color32(Color128 c) + { + return new Color32((byte)(255 * c.R), (byte)(255 * c.G), (byte)(255 * c.B), (byte)(255 * c.A)); + } } diff --git a/source/OpenBveApi/Math/Matrix4.cs b/source/OpenBveApi/Math/Matrix4x4.cs similarity index 100% rename from source/OpenBveApi/Math/Matrix4.cs rename to source/OpenBveApi/Math/Matrix4x4.cs diff --git a/source/OpenBveApi/Math/Vectors/Vector2.cs b/source/OpenBveApi/Math/Vectors/Vector2.cs index 6c005816a9..29d6ddabff 100644 --- a/source/OpenBveApi/Math/Vectors/Vector2.cs +++ b/source/OpenBveApi/Math/Vectors/Vector2.cs @@ -432,10 +432,19 @@ public static double Norm(Vector2 vector) { public static double NormSquared(Vector2 vector) { return vector.X * vector.X + vector.Y * vector.Y; } - - + + /// Transforms the Vector based upon the given transform matrix + /// The matrix by which to transform the Vector + public void Transform(Matrix4D transformMatrix) + { + double x = X * transformMatrix.Row0.X + Y * transformMatrix.Row1.X + transformMatrix.Row3.X; + double y = X * transformMatrix.Row0.Y + Y * transformMatrix.Row1.Y + transformMatrix.Row3.Y; + X = x; + Y = y; + } + // --- read-only fields --- - + /// Represents a null vector. public static readonly Vector2 Null = new Vector2(0.0, 0.0); diff --git a/source/OpenBveApi/Math/Vectors/Vector2f.cs b/source/OpenBveApi/Math/Vectors/Vector2f.cs index 6470d7fece..333e812a5b 100644 --- a/source/OpenBveApi/Math/Vectors/Vector2f.cs +++ b/source/OpenBveApi/Math/Vectors/Vector2f.cs @@ -1,4 +1,4 @@ -#pragma warning disable IDE0064 +#pragma warning disable IDE0064 using System; using System.Globalization; // ReSharper disable MergeCastWithTypeCheck @@ -372,10 +372,13 @@ public static double Norm(Vector2f vector) { public static double NormSquared(Vector2f vector) { return vector.X * vector.X + vector.Y * vector.Y; } - - + + // --- read-only fields --- - + + /// Represents a null vector. + public static readonly Vector2f Zero = new Vector2f(0.0, 0.0); + /// Represents a null vector. public static readonly Vector2f Null = new Vector2f(0.0, 0.0); diff --git a/source/OpenBveApi/OpenBveApi.csproj b/source/OpenBveApi/OpenBveApi.csproj index 5731b4842c..10f2cd19f1 100644 --- a/source/OpenBveApi/OpenBveApi.csproj +++ b/source/OpenBveApi/OpenBveApi.csproj @@ -128,7 +128,7 @@ - + diff --git a/source/Plugins/Route.Bve5/app.config b/source/Plugins/Route.Bve5/app.config index da8aeea264..3400b03fa5 100644 --- a/source/Plugins/Route.Bve5/app.config +++ b/source/Plugins/Route.Bve5/app.config @@ -10,6 +10,10 @@ + + + + diff --git a/source/Plugins/Route.CsvRw/app.config b/source/Plugins/Route.CsvRw/app.config index a1e2bff25d..6ddefebfae 100644 --- a/source/Plugins/Route.CsvRw/app.config +++ b/source/Plugins/Route.CsvRw/app.config @@ -10,6 +10,10 @@ + + + + \ No newline at end of file diff --git a/source/Plugins/Route.Mechanik/app.config b/source/Plugins/Route.Mechanik/app.config index a1e2bff25d..6ddefebfae 100644 --- a/source/Plugins/Route.Mechanik/app.config +++ b/source/Plugins/Route.Mechanik/app.config @@ -10,6 +10,10 @@ + + + + \ No newline at end of file diff --git a/source/Plugins/Train.OpenBve/app.config b/source/Plugins/Train.OpenBve/app.config index a1e2bff25d..6ddefebfae 100644 --- a/source/Plugins/Train.OpenBve/app.config +++ b/source/Plugins/Train.OpenBve/app.config @@ -10,6 +10,10 @@ + + + + \ No newline at end of file diff --git a/source/RouteManager2/CurrentRoute.cs b/source/RouteManager2/CurrentRoute.cs index e5f71ba61a..6bae4526c6 100644 --- a/source/RouteManager2/CurrentRoute.cs +++ b/source/RouteManager2/CurrentRoute.cs @@ -467,10 +467,6 @@ public void UpdateBackground(double TimeElapsed, bool GamePaused) renderer.Fog.Color = CurrentFog.Color; renderer.Fog.Density = CurrentFog.Density; renderer.Fog.IsLinear = CurrentFog.IsLinear; - if (!renderer.AvailableNewRenderer) - { - renderer.Fog.SetForImmediateMode(); - } } else { diff --git a/source/RouteManager2/MessageManager/MessageTypes/GeneralMessage.cs b/source/RouteManager2/MessageManager/MessageTypes/GeneralMessage.cs index ba2f969c73..062d1d9a4a 100644 --- a/source/RouteManager2/MessageManager/MessageTypes/GeneralMessage.cs +++ b/source/RouteManager2/MessageManager/MessageTypes/GeneralMessage.cs @@ -41,7 +41,7 @@ public GeneralMessage() MessageColor = MessageColor.White; MessageEarlyColor = MessageColor.White; MessageLateColor = MessageColor.White; - Font = new OpenGlFont(FontFamily.GenericSansSerif, 12.0f); + //Font = new OpenGlFont(FontFamily.GenericSansSerif, 12.0f); } public override void AddMessage(double currentTime) @@ -102,16 +102,6 @@ public override void AddMessage(double currentTime) public void Dispose() { - Dispose(true); - GC.SuppressFinalize(this); - } - - private void Dispose(bool currentlyDisposing) - { - if (currentlyDisposing) - { - Font.Dispose(); - } } } } diff --git a/source/RouteManager2/app.config b/source/RouteManager2/app.config index a1e2bff25d..6ddefebfae 100644 --- a/source/RouteManager2/app.config +++ b/source/RouteManager2/app.config @@ -10,6 +10,10 @@ + + + + \ No newline at end of file diff --git a/source/RouteViewer/NewRendererR.cs b/source/RouteViewer/NewRendererR.cs index fc1316bc79..f3d7454f28 100644 --- a/source/RouteViewer/NewRendererR.cs +++ b/source/RouteViewer/NewRendererR.cs @@ -112,10 +112,6 @@ internal void RenderScene(double timeElapsed) } TransformedLightPosition = new Vector3(Lighting.OptionLightPosition.X, Lighting.OptionLightPosition.Y, -Lighting.OptionLightPosition.Z); TransformedLightPosition.Transform(CurrentViewMatrix); - if (!AvailableNewRenderer) - { - GL.Light(LightName.Light0, LightParameter.Position, new[] { (float)TransformedLightPosition.X, (float)TransformedLightPosition.Y, (float)TransformedLightPosition.Z, 0.0f }); - } Lighting.OptionLightingResultingAmount = (Lighting.OptionAmbientColor.R + Lighting.OptionAmbientColor.G + Lighting.OptionAmbientColor.B) / 480.0f; @@ -173,10 +169,6 @@ internal void RenderScene(double timeElapsed) Fog.Color = Program.CurrentRoute.CurrentFog.Color; Fog.Density = Program.CurrentRoute.CurrentFog.Density; Fog.IsLinear = Program.CurrentRoute.CurrentFog.IsLinear; - if (!AvailableNewRenderer) - { - Fog.SetForImmediateMode(); - } } else { @@ -185,29 +177,24 @@ internal void RenderScene(double timeElapsed) // world layer // opaque face - - - if (AvailableNewRenderer) + //Setup the shader for rendering the scene + DefaultShader.Activate(); + if (OptionLighting) { - //Setup the shader for rendering the scene - DefaultShader.Activate(); - if (OptionLighting) - { - DefaultShader.SetIsLight(true); - 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.SetFog(Fog); - } - DefaultShader.SetTexture(0); - DefaultShader.SetCurrentProjectionMatrix(CurrentProjectionMatrix); + DefaultShader.SetIsLight(true); + 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.SetFog(Fog); } + DefaultShader.SetTexture(0); + DefaultShader.SetCurrentProjectionMatrix(CurrentProjectionMatrix); ResetOpenGlState(); List opaqueFaces, alphaFaces; lock (VisibleObjects.LockObject) @@ -286,10 +273,7 @@ internal void RenderScene(double timeElapsed) { // TODO: Write a shader to draw point list.... ResetOpenGlState(); - if (AvailableNewRenderer) - { - DefaultShader.Deactivate(); - } + DefaultShader.Deactivate(); unsafe { GL.MatrixMode(MatrixMode.Projection); @@ -327,10 +311,7 @@ internal void RenderScene(double timeElapsed) // render overlays - if (AvailableNewRenderer) - { - DefaultShader.Deactivate(); - } + DefaultShader.Deactivate(); ResetOpenGlState(); OptionLighting = false; OptionFog = false; @@ -671,7 +652,7 @@ private void RenderOverlays(double timeElapsed) double Yaw = Camera.Alignment.Yaw * 57.2957795130824; OpenGlString.Draw(Fonts.SmallFont, $"Position: {GetLengthString(Camera.Alignment.TrackPosition)} (X={GetLengthString(Camera.Alignment.Position.X)}, Y={GetLengthString(Camera.Alignment.Position.Y)}), Orientation: (Yaw={Yaw.ToString("0.00", culture)}°, Pitch={(Camera.Alignment.Pitch * 57.2957795130824).ToString("0.00", culture)}°, Roll={(Camera.Alignment.Roll * 57.2957795130824).ToString("0.00", culture)}°)", new Vector2((int)x, 4), TextAlignment.TopLeft, Color128.White, true); OpenGlString.Draw(Fonts.SmallFont, $"Radius: {GetLengthString(CameraTrackFollower.CurveRadius)}, Cant: {(1000.0 * CameraTrackFollower.CurveCant).ToString("0", culture)} mm, Pitch: {CameraTrackFollower.Pitch.ToString("0", culture)} ‰, Adhesion={(100.0 * CameraTrackFollower.AdhesionMultiplier).ToString("0", culture)}" + " , Rain intensity= " + CameraTrackFollower.RainIntensity +"%", new Vector2((int)x, 20), TextAlignment.TopLeft, Color128.White, true); - OpenGlString.Draw(Fonts.SmallFont, ForceLegacyOpenGL ? $"Renderer: Old (GL 1.2)- GL 3.0 not available" : $"Renderer: {(AvailableNewRenderer ? "New (GL 3.0)" : "Old (GL 1.2)")}", new Vector2((int)x, 40), TextAlignment.TopLeft, Color128.White, true); + OpenGlString.Draw(Fonts.SmallFont, $"Renderer: New (GL 3.0)", new Vector2((int)x, 40), TextAlignment.TopLeft, Color128.White, true); int stationIndex = Program.Renderer.CameraTrackFollower.StationIndex; diff --git a/source/RouteViewer/ProgramR.cs b/source/RouteViewer/ProgramR.cs index cccbf5efbf..22aef29032 100644 --- a/source/RouteViewer/ProgramR.cs +++ b/source/RouteViewer/ProgramR.cs @@ -822,9 +822,6 @@ internal static void KeyDownEvent(object sender, KeyboardKeyEventArgs e) } } break; - case Key.R: - Renderer.SwitchOpenGLVersion(); - break; case Key.P: if (CurrentHost.Platform == HostPlatform.AppleOSX && IntPtr.Size != 4) { diff --git a/source/RouteViewer/app.config b/source/RouteViewer/app.config index 9706ed099b..3b593dbe21 100644 --- a/source/RouteViewer/app.config +++ b/source/RouteViewer/app.config @@ -16,6 +16,10 @@ + + + + diff --git a/source/TrainEditor/app.config b/source/TrainEditor/app.config index 0a9966da17..4052c86d9b 100644 --- a/source/TrainEditor/app.config +++ b/source/TrainEditor/app.config @@ -11,6 +11,10 @@ + + + + diff --git a/source/TrainEditor2/App.config b/source/TrainEditor2/App.config index 92fc90eb4e..92cae81d58 100644 --- a/source/TrainEditor2/App.config +++ b/source/TrainEditor2/App.config @@ -27,6 +27,10 @@ + + + + diff --git a/source/TrainEditor2/Graphics/NewRenderer.cs b/source/TrainEditor2/Graphics/NewRenderer.cs index 5cd6c6ff54..d0dfbb131e 100644 --- a/source/TrainEditor2/Graphics/NewRenderer.cs +++ b/source/TrainEditor2/Graphics/NewRenderer.cs @@ -1,4 +1,6 @@ -using LibRender2; +using System; +using LibRender2; +using LibRender2.Text; using OpenBveApi; using OpenBveApi.FileSystem; using OpenBveApi.Hosts; @@ -17,6 +19,7 @@ public override void Initialize() public NewRenderer(HostInterface currentHost, BaseOptions currentOptions, FileSystem fileSystem) : base(currentHost, currentOptions, fileSystem) { + Fonts = new Fonts(currentHost, this, String.Empty); } } } diff --git a/source/TrainEditor2/Models/Trains/Motor.Functions.cs b/source/TrainEditor2/Models/Trains/Motor.Functions.cs index 7751e32e92..0e41d439b6 100644 --- a/source/TrainEditor2/Models/Trains/Motor.Functions.cs +++ b/source/TrainEditor2/Models/Trains/Motor.Functions.cs @@ -1104,7 +1104,7 @@ internal void DrawGlControl() for (double v = 0.0; v < MaxVelocity; v += 10.0) { - Program.Renderer.OpenGlString.Draw(Fonts.VerySmallFont, v.ToString("0", culture), new Vector2(VelocityToX(v) + 1, 1), TextAlignment.TopLeft, new Color128(Color24.Grey)); + Program.Renderer.OpenGlString.Draw(Program.Renderer.Fonts.VerySmallFont, v.ToString("0", culture), new Vector2(VelocityToX(v) + 1, 1), TextAlignment.TopLeft, new Color128(Color24.Grey)); } GL.Disable(EnableCap.Texture2D); @@ -1140,7 +1140,7 @@ internal void DrawGlControl() for (double p = 0.0; p < MaxPitch; p += 100.0) { - Program.Renderer.OpenGlString.Draw(Fonts.VerySmallFont, p.ToString("0", culture), new Vector2(1, PitchToY(p) + 1), TextAlignment.TopLeft, new Color128(Color24.Grey)); + Program.Renderer.OpenGlString.Draw(Program.Renderer.Fonts.VerySmallFont, p.ToString("0", culture), new Vector2(1, PitchToY(p) + 1), TextAlignment.TopLeft, new Color128(Color24.Grey)); } GL.Disable(EnableCap.Texture2D); @@ -1172,7 +1172,7 @@ internal void DrawGlControl() for (double v = 0.0; v < MaxVolume; v += 128.0) { - Program.Renderer.OpenGlString.Draw(Fonts.VerySmallFont, v.ToString("0", culture), new Vector2(1, VolumeToY(v) + 1), TextAlignment.TopLeft, new Color128(Color24.Grey)); + Program.Renderer.OpenGlString.Draw(Program.Renderer.Fonts.VerySmallFont, v.ToString("0", culture), new Vector2(1, VolumeToY(v) + 1), TextAlignment.TopLeft, new Color128(Color24.Grey)); } GL.Disable(EnableCap.Texture2D); diff --git a/source/TrainEditor2/Systems/Fonts.cs b/source/TrainEditor2/Systems/Fonts.cs deleted file mode 100644 index 904569ea88..0000000000 --- a/source/TrainEditor2/Systems/Fonts.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Drawing; -using LibRender2.Text; - -namespace TrainEditor2.Systems -{ - /// Provides font support. - internal static class Fonts - { - // --- read-only fields --- - - /// Represents a very small sans serif font. - internal static readonly OpenGlFont VerySmallFont = new OpenGlFont(FontFamily.GenericSansSerif, 9.0f); - } -} diff --git a/source/TrainEditor2/TrainEditor2.csproj b/source/TrainEditor2/TrainEditor2.csproj index 106decd248..0c31c08994 100644 --- a/source/TrainEditor2/TrainEditor2.csproj +++ b/source/TrainEditor2/TrainEditor2.csproj @@ -52,6 +52,10 @@ true + + False + ..\..\..\FontStash\FontStashSharp\src\FontStashSharp\bin\Debug\netstandard2.0\FontStashSharp.dll + ..\..\packages\OpenTK-OpenBVE.1.0.4\lib\net20\OpenTK.dll @@ -161,7 +165,6 @@ - diff --git a/source/TrainManager/app.config b/source/TrainManager/app.config index a1e2bff25d..6ddefebfae 100644 --- a/source/TrainManager/app.config +++ b/source/TrainManager/app.config @@ -10,6 +10,10 @@ + + + + \ No newline at end of file