From 2335c150210c2ce0aa38dc0041771fcdb8ca44f4 Mon Sep 17 00:00:00 2001 From: Pyrdacor Date: Mon, 6 Mar 2023 12:08:31 +0100 Subject: [PATCH] Fixed fantasy intro drawing, reworked shader positions --- Ambermoon.Common/Rect.cs | 10 ++ Ambermoon.Core/Render/IRenderLayer.cs | 6 +- .../Serialization/DataReader.cs | 2 + .../Serialization/FantasyIntroData.cs | 5 +- .../Serialization/IntroData.cs | 2 - .../AlphaTextureShader.cs | 4 +- Ambermoon.Renderer.OpenGL/ColorShader.cs | 4 +- Ambermoon.Renderer.OpenGL/EffectShader.cs | 4 +- .../FloatPositionBuffer.cs | 90 ++++++++++++++ Ambermoon.Renderer.OpenGL/FowShader.cs | 8 +- Ambermoon.Renderer.OpenGL/ImageShader.cs | 4 +- .../OpaqueTextureShader.cs | 4 +- Ambermoon.Renderer.OpenGL/RenderBuffer.cs | 112 ++++++++---------- Ambermoon.Renderer.OpenGL/RenderLayer.cs | 3 +- Ambermoon.Renderer.OpenGL/RenderView.cs | 38 ++++-- .../ScreenRenderBuffer.cs | 4 +- Ambermoon.Renderer.OpenGL/ScreenShader.cs | 4 +- Ambermoon.Renderer.OpenGL/SkyShader.cs | 4 +- Ambermoon.Renderer.OpenGL/TextShader.cs | 4 +- Ambermoon.Renderer.OpenGL/TextureShader.cs | 4 +- .../VertexArrayObject.cs | 25 +++- Ambermoon.net/FantasyIntro.cs | 13 +- 22 files changed, 239 insertions(+), 115 deletions(-) create mode 100644 Ambermoon.Renderer.OpenGL/FloatPositionBuffer.cs diff --git a/Ambermoon.Common/Rect.cs b/Ambermoon.Common/Rect.cs index d68981df..ee8225dc 100644 --- a/Ambermoon.Common/Rect.cs +++ b/Ambermoon.Common/Rect.cs @@ -110,6 +110,16 @@ public void ClipRect(Position position, Size size) size.Height = bottom - position.Y; } + public void ClipRect(FloatPosition position, FloatSize size) + { + float right = Math.Min(position.X + size.Width, Right); + float bottom = Math.Min(position.Y + size.Height, Bottom); + position.X = Math.Max(position.X, X); + position.Y = Math.Max(position.Y, Y); + size.Width = right - position.X; + size.Height = bottom - position.Y; + } + public void Trap(Position position) { position.X = Util.Limit(Left, position.X, Right); diff --git a/Ambermoon.Core/Render/IRenderLayer.cs b/Ambermoon.Core/Render/IRenderLayer.cs index f1277080..e9aafef9 100644 --- a/Ambermoon.Core/Render/IRenderLayer.cs +++ b/Ambermoon.Core/Render/IRenderLayer.cs @@ -1,7 +1,7 @@ /* * IRenderLayer.cs - Render layer interface * - * Copyright (C) 2020-2021 Robert Schneckenhaus + * Copyright (C) 2020-2023 Robert Schneckenhaus * * This file is part of Ambermoon.net. * @@ -21,8 +21,8 @@ namespace Ambermoon.Render { - public delegate Position PositionTransformation(Position position); - public delegate Size SizeTransformation(Size size); + public delegate FloatPosition PositionTransformation(FloatPosition position); + public delegate FloatSize SizeTransformation(FloatSize size); public interface IRenderLayer { diff --git a/Ambermoon.Data.Legacy/Serialization/DataReader.cs b/Ambermoon.Data.Legacy/Serialization/DataReader.cs index 75537770..66c90d06 100644 --- a/Ambermoon.Data.Legacy/Serialization/DataReader.cs +++ b/Ambermoon.Data.Legacy/Serialization/DataReader.cs @@ -7,9 +7,11 @@ namespace Ambermoon.Data.Legacy.Serialization { +#pragma warning disable CS8981 using word = UInt16; using dword = UInt32; using qword = UInt64; +#pragma warning restore CS8981 public class DataReader : IDataReader, ICustomReader { diff --git a/Ambermoon.Data.Legacy/Serialization/FantasyIntroData.cs b/Ambermoon.Data.Legacy/Serialization/FantasyIntroData.cs index 58b2cf34..142fc174 100644 --- a/Ambermoon.Data.Legacy/Serialization/FantasyIntroData.cs +++ b/Ambermoon.Data.Legacy/Serialization/FantasyIntroData.cs @@ -1,11 +1,8 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; namespace Ambermoon.Data.Legacy.Serialization { - - public class FantasyIntroData : IFantasyIntroData { static readonly Position[] WandSparkPositions = new[] diff --git a/Ambermoon.Data.Legacy/Serialization/IntroData.cs b/Ambermoon.Data.Legacy/Serialization/IntroData.cs index ebe61a9f..4e56128e 100644 --- a/Ambermoon.Data.Legacy/Serialization/IntroData.cs +++ b/Ambermoon.Data.Legacy/Serialization/IntroData.cs @@ -3,8 +3,6 @@ namespace Ambermoon.Data.Legacy.Serialization { - - public class IntroData : IIntroData { readonly List introPalettes = new(); diff --git a/Ambermoon.Renderer.OpenGL/AlphaTextureShader.cs b/Ambermoon.Renderer.OpenGL/AlphaTextureShader.cs index 67602eb5..b81dc771 100644 --- a/Ambermoon.Renderer.OpenGL/AlphaTextureShader.cs +++ b/Ambermoon.Renderer.OpenGL/AlphaTextureShader.cs @@ -69,7 +69,7 @@ internal class AlphaTextureShader : TextureShader protected static string[] AlphaTextureVertexShader(State state) => new string[] { GetVertexShaderHeader(state), - $"in ivec2 {DefaultPositionName};", + $"in vec2 {DefaultPositionName};", $"in ivec2 {DefaultTexCoordName};", $"in uint {DefaultLayerName};", $"in uint {DefaultPaletteIndexName};", @@ -87,7 +87,7 @@ internal class AlphaTextureShader : TextureShader $"void main()", $"{{", $" vec2 atlasFactor = vec2(1.0f / float({DefaultAtlasSizeName}.x), 1.0f / float({DefaultAtlasSizeName}.y));", - $" vec2 pos = vec2(float({DefaultPositionName}.x) + 0.49f, float({DefaultPositionName}.y) + 0.49f);", + $" vec2 pos = vec2({DefaultPositionName}.x + 0.49f, {DefaultPositionName}.y + 0.49f);", $" varTexCoord = atlasFactor * vec2({DefaultTexCoordName}.x, {DefaultTexCoordName}.y);", $" palIndex = float({DefaultPaletteIndexName});", $" a = float({DefaultAlphaName}) / 255.0f;", diff --git a/Ambermoon.Renderer.OpenGL/ColorShader.cs b/Ambermoon.Renderer.OpenGL/ColorShader.cs index 9331a80c..8b02937c 100644 --- a/Ambermoon.Renderer.OpenGL/ColorShader.cs +++ b/Ambermoon.Renderer.OpenGL/ColorShader.cs @@ -76,7 +76,7 @@ protected static string GetVertexShaderHeader(State state) static string[] ColorVertexShader(State state) => new string[] { GetVertexShaderHeader(state), - $"in ivec2 {DefaultPositionName};", + $"in vec2 {DefaultPositionName};", $"in uint {DefaultLayerName};", $"in uvec4 {DefaultColorName};", $"uniform float {DefaultZName};", @@ -86,7 +86,7 @@ protected static string GetVertexShaderHeader(State state) $"", $"void main()", $"{{", - $" vec2 pos = vec2(float({DefaultPositionName}.x) + 0.49f, float({DefaultPositionName}.y) + 0.49f);", + $" vec2 pos = vec2({DefaultPositionName}.x + 0.49f, {DefaultPositionName}.y + 0.49f);", $" pixelColor = vec4(float({DefaultColorName}.r) / 255.0f, float({DefaultColorName}.g) / 255.0f, float({DefaultColorName}.b) / 255.0f, float({DefaultColorName}.a) / 255.0f);", $" ", $" gl_Position = {DefaultProjectionMatrixName} * {DefaultModelViewMatrixName} * vec4(pos, 1.0f - {DefaultZName} - float({DefaultLayerName}) * 0.00001f, 1.0f);", diff --git a/Ambermoon.Renderer.OpenGL/EffectShader.cs b/Ambermoon.Renderer.OpenGL/EffectShader.cs index 2eb32240..ca13fd04 100644 --- a/Ambermoon.Renderer.OpenGL/EffectShader.cs +++ b/Ambermoon.Renderer.OpenGL/EffectShader.cs @@ -65,7 +65,7 @@ internal class EffectShader : ScreenShader static string[] EffectVertexShader(State state) => new string[] { GetVertexShaderHeader(state), - $"in ivec2 {DefaultPositionName};", + $"in vec2 {DefaultPositionName};", $"uniform mat4 {DefaultProjectionMatrixName};", $"uniform mat4 {DefaultModelViewMatrixName};", $"uniform vec2 {DefaultResolutionName};", @@ -73,7 +73,7 @@ internal class EffectShader : ScreenShader $"", $"void main()", $"{{", - $" vec2 pos = vec2(float({DefaultPositionName}.x), float({DefaultPositionName}.y));", + $" vec2 pos = vec2({DefaultPositionName}.x, {DefaultPositionName}.y);", $" varTexCoord = vec2(pos.x / {DefaultResolutionName}.x, ({DefaultResolutionName}.y - pos.y) / {DefaultResolutionName}.y);", $" gl_Position = {DefaultProjectionMatrixName} * {DefaultModelViewMatrixName} * vec4(pos, 0.001f, 1.0f);", $"}}" diff --git a/Ambermoon.Renderer.OpenGL/FloatPositionBuffer.cs b/Ambermoon.Renderer.OpenGL/FloatPositionBuffer.cs new file mode 100644 index 00000000..4a87f8b3 --- /dev/null +++ b/Ambermoon.Renderer.OpenGL/FloatPositionBuffer.cs @@ -0,0 +1,90 @@ +/* + * FloatPositionBuffer.cs - Buffer for shader floating-point position data + * + * Copyright (C) 2023 Robert Schneckenhaus + * + * This file is part of Ambermoon.net. + * + * Ambermoon.net is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Ambermoon.net is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Ambermoon.net. If not, see . + */ + +using System; + +namespace Ambermoon.Renderer +{ + internal class FloatPositionBuffer : BufferObject + { + public override int Dimension => 2; + + public FloatPositionBuffer(State state, bool staticData) + : base(state, staticData) + { + + } + + bool UpdatePositionData(float[] buffer, int index, Tuple position) + { + bool changed = false; + float x = position.Item1; + float y = position.Item2; + + if (!Util.FloatEqual(buffer[index + 0], x) || + !Util.FloatEqual(buffer[index + 1], y)) + { + buffer[index + 0] = x; + buffer[index + 1] = y; + changed = true; + } + + return changed || index == Size; + } + + public int Add(float x, float y, int index = -1) + { + return Add(UpdatePositionData, Tuple.Create(x, y), index); + } + + public void Update(int index, float x, float y) + { + Update(UpdatePositionData, index, Tuple.Create(x, y)); + } + + public void TransformAll(Func, Tuple> updater) + { + bool TransformPositionData(float[] buffer, int index, Tuple _) + { + bool changed = false; + var position = Tuple.Create(buffer[index + 0], buffer[index + 1]); + var newPosition = updater(index, position); + float x = newPosition.Item1; + float y = newPosition.Item2; + + if (!Util.FloatEqual(buffer[index + 0], x) || + !Util.FloatEqual(buffer[index + 1], y)) + { + buffer[index + 0] = x; + buffer[index + 1] = y; + changed = true; + } + + return changed || index == Size; + } + + for (int i = 0; i < Size; ++i) + { + Update>(TransformPositionData, i, null); + } + } + } +} diff --git a/Ambermoon.Renderer.OpenGL/FowShader.cs b/Ambermoon.Renderer.OpenGL/FowShader.cs index 40f18e24..e7bc25bf 100644 --- a/Ambermoon.Renderer.OpenGL/FowShader.cs +++ b/Ambermoon.Renderer.OpenGL/FowShader.cs @@ -45,9 +45,9 @@ internal class FowShader : ColorShader protected static string[] FowVertexShader(State state) => new string[] { GetVertexShaderHeader(state), - $"in ivec2 {DefaultPositionName};", + $"in vec2 {DefaultPositionName};", $"in uint {DefaultLayerName};", - $"in ivec2 {DefaultCenterName};", + $"in vec2 {DefaultCenterName};", $"in uint {DefaultRadiusName};", $"uniform float {DefaultZName};", $"uniform mat4 {DefaultProjectionMatrixName};", @@ -58,8 +58,8 @@ internal class FowShader : ColorShader $"", $"void main()", $"{{", - $" vec2 pos = vec2(float({DefaultPositionName}.x), float({DefaultPositionName}.y));", - $" fowCenter = vec2(float({DefaultCenterName}.x), float({DefaultCenterName}.y));", + $" vec2 pos = vec2({DefaultPositionName}.x, {DefaultPositionName}.y);", + $" fowCenter = vec2({DefaultCenterName}.x, {DefaultCenterName}.y);", $" fowRadius = float({DefaultRadiusName});", $" currentPos = pos;", $" gl_Position = {DefaultProjectionMatrixName} * {DefaultModelViewMatrixName} * vec4(pos + vec2(0.49f, 0.49f), 1.0f - {DefaultZName} - float({DefaultLayerName}) * 0.00001f, 1.0f);", diff --git a/Ambermoon.Renderer.OpenGL/ImageShader.cs b/Ambermoon.Renderer.OpenGL/ImageShader.cs index 8c8c66e0..577a78c8 100644 --- a/Ambermoon.Renderer.OpenGL/ImageShader.cs +++ b/Ambermoon.Renderer.OpenGL/ImageShader.cs @@ -42,7 +42,7 @@ internal class ImageShader : TextureShader static string[] ImageVertexShader(State state) => new string[] { GetVertexShaderHeader(state), - $"in ivec2 {DefaultPositionName};", + $"in vec2 {DefaultPositionName};", $"in ivec2 {DefaultTexCoordName};", $"in uint {DefaultLayerName};", $"in uint {DefaultAlphaName};", @@ -56,7 +56,7 @@ internal class ImageShader : TextureShader $"void main()", $"{{", $" vec2 atlasFactor = vec2(1.0f / float({DefaultAtlasSizeName}.x), 1.0f / float({DefaultAtlasSizeName}.y));", - $" vec2 pos = vec2(float({DefaultPositionName}.x), float({DefaultPositionName}.y));", + $" vec2 pos = vec2({DefaultPositionName}.x, {DefaultPositionName}.y);", $" varTexCoord = atlasFactor * vec2({DefaultTexCoordName}.x, {DefaultTexCoordName}.y);", $" float z = 1.0f - {DefaultZName} - float({DefaultLayerName}) * 0.00001f;", $" a = float({DefaultAlphaName}) / 255.0f;", diff --git a/Ambermoon.Renderer.OpenGL/OpaqueTextureShader.cs b/Ambermoon.Renderer.OpenGL/OpaqueTextureShader.cs index d9865d00..2878ba9b 100644 --- a/Ambermoon.Renderer.OpenGL/OpaqueTextureShader.cs +++ b/Ambermoon.Renderer.OpenGL/OpaqueTextureShader.cs @@ -52,7 +52,7 @@ internal class OpaqueTextureShader : TextureShader protected static string[] OpaqueTextureVertexShader(State state) => new string[] { GetVertexShaderHeader(state), - $"in ivec2 {DefaultPositionName};", + $"in vec2 {DefaultPositionName};", $"in ivec2 {DefaultTexCoordName};", $"in uint {DefaultLayerName};", $"in uint {DefaultPaletteIndexName};", @@ -67,7 +67,7 @@ internal class OpaqueTextureShader : TextureShader $"void main()", $"{{", $" vec2 atlasFactor = vec2(1.0f / float({DefaultAtlasSizeName}.x), 1.0f / float({DefaultAtlasSizeName}.y));", - $" vec2 pos = vec2(float({DefaultPositionName}.x) + 0.49f, float({DefaultPositionName}.y) + 0.49f);", + $" vec2 pos = vec2({DefaultPositionName}.x + 0.49f, {DefaultPositionName}.y + 0.49f);", $" varTexCoord = atlasFactor * vec2({DefaultTexCoordName}.x, {DefaultTexCoordName}.y);", $" palIndex = float({DefaultPaletteIndexName});", $" gl_Position = {DefaultProjectionMatrixName} * {DefaultModelViewMatrixName} * vec4(pos, 1.0f - {DefaultZName} - float({DefaultLayerName}) * 0.00001f, 1.0f);", diff --git a/Ambermoon.Renderer.OpenGL/RenderBuffer.cs b/Ambermoon.Renderer.OpenGL/RenderBuffer.cs index 53eb5b86..661da1bc 100644 --- a/Ambermoon.Renderer.OpenGL/RenderBuffer.cs +++ b/Ambermoon.Renderer.OpenGL/RenderBuffer.cs @@ -36,11 +36,10 @@ public class RenderBuffer : IDisposable bool disposed = false; readonly State state; uint textureFactor = 1; - bool usePalette = true; readonly VertexArrayObject vertexArrayObject = null; readonly VectorBuffer vectorBuffer = null; - readonly PositionBuffer positionBuffer = null; + readonly FloatPositionBuffer positionBuffer = null; readonly PositionBuffer textureAtlasOffsetBuffer = null; readonly WordBuffer baseLineBuffer = null; readonly ColorBuffer colorBuffer = null; @@ -55,7 +54,7 @@ public class RenderBuffer : IDisposable readonly ByteBuffer billboardOrientationBuffer = null; readonly ByteBuffer alphaBuffer = null; readonly FloatBuffer extrudeBuffer = null; - readonly PositionBuffer centerBuffer = null; + readonly FloatPositionBuffer centerBuffer = null; readonly ByteBuffer radiusBuffer = null; static readonly Dictionary colorShaders = new Dictionary(); static readonly Dictionary textureShaders = new Dictionary(); @@ -71,11 +70,10 @@ public class RenderBuffer : IDisposable public RenderBuffer(State state, bool is3D, bool supportAnimations, bool layered, bool noTexture = false, bool isBillboard = false, bool isText = false, bool opaque = false, bool fow = false, bool sky = false, bool texturesWithAlpha = false, bool noPaletteImage = false, - bool usePalette = true, uint textureFactor = 1) + uint textureFactor = 1) { this.state = state; this.textureFactor = textureFactor; - this.usePalette = usePalette; Opaque = opaque; if (is3D) @@ -160,7 +158,7 @@ public RenderBuffer(State state, bool is3D, bool supportAnimations, bool layered alphaBuffer = new ByteBuffer(state, true); } else - positionBuffer = new PositionBuffer(state, false); + positionBuffer = new FloatPositionBuffer(state, false); indexBuffer = new IndexBuffer(state); if (texturesWithAlpha || noPaletteImage) @@ -169,7 +167,7 @@ public RenderBuffer(State state, bool is3D, bool supportAnimations, bool layered if (fow) { baseLineBuffer = new WordBuffer(state, true); - centerBuffer = new PositionBuffer(state, false); + centerBuffer = new FloatPositionBuffer(state, false); radiusBuffer = new ByteBuffer(state, false); vertexArrayObject.AddBuffer(ColorShader.DefaultLayerName, baseLineBuffer); @@ -273,11 +271,6 @@ internal void SetTextureFactor(uint factor) } } - internal void UsePalette(bool use) - { - usePalette = use; - } - internal ColorShader ColorShader => colorShaders[state]; internal TextureShader TextureShader => textureShaders[state]; internal OpaqueTextureShader OpaqueTextureShader => opaqueTextureShaders[state]; @@ -293,9 +286,9 @@ public int GetDrawIndex(Render.IFow fow, Render.PositionTransformation positionTransformation, Render.SizeTransformation sizeTransformation) { - var position = new Position(fow.X, fow.Y); - var size = new Size(fow.Width, fow.Height); - var center = new Position(fow.Center); + var position = new FloatPosition(fow.X, fow.Y); + var size = new FloatSize(fow.Width, fow.Height); + var center = new FloatPosition(fow.Center); if (positionTransformation != null) { @@ -306,29 +299,29 @@ public int GetDrawIndex(Render.IFow fow, if (sizeTransformation != null) size = sizeTransformation(size); - int index = positionBuffer.Add((short)position.X, (short)position.Y); - positionBuffer.Add((short)(position.X + size.Width), (short)position.Y, index + 1); - positionBuffer.Add((short)(position.X + size.Width), (short)(position.Y + size.Height), index + 2); - positionBuffer.Add((short)position.X, (short)(position.Y + size.Height), index + 3); + int index = positionBuffer.Add(position.X, position.Y); + positionBuffer.Add(position.X + size.Width, position.Y, index + 1); + positionBuffer.Add(position.X + size.Width, position.Y + size.Height, index + 2); + positionBuffer.Add(position.X, position.Y + size.Height, index + 3); indexBuffer.InsertQuad(index / 4); - var baseLineOffsetSize = new Size(0, fow.BaseLineOffset); + var baseLineOffsetSize = new FloatSize(0, fow.BaseLineOffset); if (sizeTransformation != null) baseLineOffsetSize = sizeTransformation(baseLineOffsetSize); - ushort baseLine = (ushort)Math.Min(ushort.MaxValue, position.Y + size.Height + baseLineOffsetSize.Height); + ushort baseLine = (ushort)Math.Min(ushort.MaxValue, position.Y + size.Height + Util.Round(baseLineOffsetSize.Height)); baseLineBuffer.Add(baseLine, index); baseLineBuffer.Add(baseLine, index + 1); baseLineBuffer.Add(baseLine, index + 2); baseLineBuffer.Add(baseLine, index + 3); - centerBuffer.Add((short)center.X, (short)center.Y, index); - centerBuffer.Add((short)center.X, (short)center.Y, index + 1); - centerBuffer.Add((short)center.X, (short)center.Y, index + 2); - centerBuffer.Add((short)center.X, (short)center.Y, index + 3); + centerBuffer.Add(center.X, center.Y, index); + centerBuffer.Add(center.X, center.Y, index + 1); + centerBuffer.Add(center.X, center.Y, index + 2); + centerBuffer.Add(center.X, center.Y, index + 3); radiusBuffer.Add(fow.Radius, index); radiusBuffer.Add(fow.Radius, index + 1); @@ -342,8 +335,8 @@ public int GetDrawIndex(Render.IColoredRect coloredRect, Render.PositionTransformation positionTransformation, Render.SizeTransformation sizeTransformation) { - var position = new Position(coloredRect.X, coloredRect.Y); - var size = new Size(coloredRect.Width, coloredRect.Height); + var position = new FloatPosition(coloredRect.X, coloredRect.Y); + var size = new FloatSize(coloredRect.Width, coloredRect.Height); if (positionTransformation != null) position = positionTransformation(position); @@ -351,10 +344,10 @@ public int GetDrawIndex(Render.IColoredRect coloredRect, if (sizeTransformation != null) size = sizeTransformation(size); - int index = positionBuffer.Add((short)position.X, (short)position.Y); - positionBuffer.Add((short)(position.X + size.Width), (short)position.Y, index + 1); - positionBuffer.Add((short)(position.X + size.Width), (short)(position.Y + size.Height), index + 2); - positionBuffer.Add((short)position.X, (short)(position.Y + size.Height), index + 3); + int index = positionBuffer.Add(position.X, position.Y); + positionBuffer.Add(position.X + size.Width, position.Y, index + 1); + positionBuffer.Add(position.X + size.Width, position.Y + size.Height, index + 2); + positionBuffer.Add(position.X, position.Y + size.Height, index + 3); indexBuffer.InsertQuad(index / 4); @@ -382,7 +375,7 @@ public int GetDrawIndex(Render.IColoredRect coloredRect, public int GetDrawIndex(Render.ISprite sprite, Render.PositionTransformation positionTransformation, Render.SizeTransformation sizeTransformation, byte? textColorIndex = null) { - var position = new Position(sprite.X, sprite.Y); + var position = new FloatPosition(sprite.X, sprite.Y); var spriteSize = new Size(sprite.Width, sprite.Height); var textureAtlasOffset = new Position(sprite.TextureAtlasOffset); var textureSize = new Size(sprite.TextureSize ?? spriteSize); @@ -391,8 +384,8 @@ public int GetDrawIndex(Render.ISprite sprite, Render.PositionTransformation pos { float textureWidthFactor = spriteSize.Width / textureSize.Width; float textureHeightFactor = spriteSize.Height / textureSize.Height; - int oldX = position.X; - int oldY = position.Y; + float oldX = position.X; + float oldY = position.Y; int oldWidth = spriteSize.Width; int oldHeight = spriteSize.Height; sprite.ClipArea.ClipRect(position, spriteSize); @@ -402,8 +395,8 @@ public int GetDrawIndex(Render.ISprite sprite, Render.PositionTransformation pos if (sprite.MirrorX) { - int oldRight = oldX + oldWidth; - int newRight = position.X + spriteSize.Width; + float oldRight = oldX + oldWidth; + float newRight = position.X + spriteSize.Width; textureAtlasOffset.X += Util.Round((oldRight - newRight) / textureWidthFactor); } else @@ -412,7 +405,7 @@ public int GetDrawIndex(Render.ISprite sprite, Render.PositionTransformation pos } } - var size = new Size(spriteSize); + var size = new FloatSize(spriteSize); if (positionTransformation != null) position = positionTransformation(position); @@ -420,10 +413,10 @@ public int GetDrawIndex(Render.ISprite sprite, Render.PositionTransformation pos if (sizeTransformation != null) size = sizeTransformation(size); - int index = positionBuffer.Add((short)position.X, (short)position.Y); - positionBuffer.Add((short)(position.X + size.Width), (short)position.Y, index + 1); - positionBuffer.Add((short)(position.X + size.Width), (short)(position.Y + size.Height), index + 2); - positionBuffer.Add((short)position.X, (short)(position.Y + size.Height), index + 3); + int index = positionBuffer.Add(position.X, position.Y); + positionBuffer.Add(position.X + size.Width, position.Y, index + 1); + positionBuffer.Add(position.X + size.Width, position.Y + size.Height, index + 2); + positionBuffer.Add(position.X, position.Y + size.Height, index + 3); indexBuffer.InsertQuad(index / 4); @@ -455,12 +448,12 @@ public int GetDrawIndex(Render.ISprite sprite, Render.PositionTransformation pos if (baseLineBuffer != null) { - var baseLineOffsetSize = new Size(0, sprite.BaseLineOffset); + var baseLineOffsetSize = new FloatSize(0, sprite.BaseLineOffset); if (sizeTransformation != null) baseLineOffsetSize = sizeTransformation(baseLineOffsetSize); - ushort baseLine = (ushort)Math.Min(ushort.MaxValue, position.Y + size.Height + baseLineOffsetSize.Height); + ushort baseLine = (ushort)Math.Min(ushort.MaxValue, position.Y + size.Height + Util.Round(baseLineOffsetSize.Height)); int baseLineBufferIndex = baseLineBuffer.Add(baseLine, index); baseLineBuffer.Add(baseLine, baseLineBufferIndex + 1); baseLineBuffer.Add(baseLine, baseLineBufferIndex + 2); @@ -668,11 +661,10 @@ public int GetDrawIndex(Render.ISurface3D surface) public void UpdatePosition(int index, Render.IRenderNode renderNode, int baseLineOffset, Render.PositionTransformation positionTransformation, Render.SizeTransformation sizeTransformation) { - var position = new Position(renderNode.X, renderNode.Y); - var size = new Size(renderNode.Width, renderNode.Height); + var position = new FloatPosition(renderNode.X, renderNode.Y); + var size = new FloatSize(renderNode.Width, renderNode.Height); - if (renderNode.ClipArea != null) - renderNode.ClipArea.ClipRect(position, size); + renderNode.ClipArea?.ClipRect(position, size); if (positionTransformation != null) position = positionTransformation(position); @@ -680,17 +672,17 @@ public void UpdatePosition(int index, Render.IRenderNode renderNode, int baseLin if (sizeTransformation != null) size = sizeTransformation(size); - positionBuffer.Update(index, (short)position.X, (short)position.Y); - positionBuffer.Update(index + 1, (short)(position.X + size.Width), (short)position.Y); - positionBuffer.Update(index + 2, (short)(position.X + size.Width), (short)(position.Y + size.Height)); - positionBuffer.Update(index + 3, (short)position.X, (short)(position.Y + size.Height)); + positionBuffer.Update(index, position.X, position.Y); + positionBuffer.Update(index + 1, position.X + size.Width, position.Y); + positionBuffer.Update(index + 2, position.X + size.Width, position.Y + size.Height); + positionBuffer.Update(index + 3, position.X, position.Y + size.Height); if (baseLineBuffer != null) { var baseLineOffsetSize = new Size(0, baseLineOffset); if (sizeTransformation != null) - baseLineOffsetSize = sizeTransformation(baseLineOffsetSize); + baseLineOffsetSize = sizeTransformation(new FloatSize(baseLineOffsetSize)).ToSize(); ushort baseLine = (ushort)Math.Min(ushort.MaxValue, position.Y + size.Height + baseLineOffsetSize.Height); @@ -822,7 +814,7 @@ public void UpdateTextureAtlasOffset(int index, Render.ISprite sprite) var position = new Position(sprite.X, sprite.Y); var spriteSize = new Size(sprite.Width, sprite.Height); var textureAtlasOffset = new Position(sprite.TextureAtlasOffset); - var textureSize = new Size(sprite.TextureSize ?? new Size(sprite.Width, sprite.Height)); + var textureSize = new Size(sprite.TextureSize ?? new Size(spriteSize)); if (sprite.ClipArea != null) { @@ -975,15 +967,15 @@ public void UpdateCenter(int index, Position center, { if (centerBuffer != null) { - center = new Position(center); + var floatCenter = new FloatPosition(center); if (positionTransformation != null) - center = positionTransformation(center); + floatCenter = positionTransformation(floatCenter); - centerBuffer.Update(index, (short)center.X, (short)center.Y); - centerBuffer.Update(index + 1, (short)center.X, (short)center.Y); - centerBuffer.Update(index + 2, (short)center.X, (short)center.Y); - centerBuffer.Update(index + 3, (short)center.X, (short)center.Y); + centerBuffer.Update(index, floatCenter.X, floatCenter.Y); + centerBuffer.Update(index + 1, floatCenter.X, floatCenter.Y); + centerBuffer.Update(index + 2, floatCenter.X, floatCenter.Y); + centerBuffer.Update(index + 3, floatCenter.X, floatCenter.Y); } } @@ -1008,7 +1000,7 @@ public void FreeDrawIndex(int index) if (positionBuffer != null) { - positionBuffer.Update(index + i, short.MaxValue, short.MaxValue); // ensure it is not visible + positionBuffer.Update(index + i, float.MaxValue, float.MaxValue); // ensure it is not visible positionBuffer.Remove(index + i); } else if (vectorBuffer != null) diff --git a/Ambermoon.Renderer.OpenGL/RenderLayer.cs b/Ambermoon.Renderer.OpenGL/RenderLayer.cs index cce575ce..d26e611e 100644 --- a/Ambermoon.Renderer.OpenGL/RenderLayer.cs +++ b/Ambermoon.Renderer.OpenGL/RenderLayer.cs @@ -355,7 +355,7 @@ public RenderLayer(State state, Layer layer, Texture texture, Texture palette) RenderBuffer = new RenderBuffer(state, layer == Layer.Map3DCeiling || layer == Layer.Map3D || layer == Layer.Billboards3D, supportAnimations, layered, !Config.SupportTextures, layer == Layer.Billboards3D, layer == Layer.Text, opaque, layer == Layer.FOW, layer == Layer.Map3DBackground, layer == Layer.Misc || layer == Layer.OutroText, layer == Layer.Images, - Config.UsePalette, Config.TextureFactor); + Config.TextureFactor); if (Config.SupportColoredRects) renderBufferColorRects = new RenderBuffer(state, false, false, true, true); @@ -371,7 +371,6 @@ public void UsePalette(bool use) return; Config = Config with { UsePalette = use }; - RenderBuffer.UsePalette(use); } public void SetTextureFactor(uint factor) diff --git a/Ambermoon.Renderer.OpenGL/RenderView.cs b/Ambermoon.Renderer.OpenGL/RenderView.cs index 5a188225..0a854d54 100644 --- a/Ambermoon.Renderer.OpenGL/RenderView.cs +++ b/Ambermoon.Renderer.OpenGL/RenderView.cs @@ -111,17 +111,11 @@ public class RenderView : RenderLayerFactory, IRenderView, IDisposable #region Coordinate transformations - PositionTransformation PositionTransformation => (Position position) => - new Position(Misc.Round(position.X * RenderFactorX), Misc.Round(position.Y * RenderFactorY)); + PositionTransformation PositionTransformation => (FloatPosition position) => + new FloatPosition(position.X * RenderFactorX, position.Y * RenderFactorY); - SizeTransformation SizeTransformation => (Size size) => - { - // don't scale a dimension of 0 - int width = (size.Width == 0) ? 0 : Misc.Ceiling(size.Width * RenderFactorX); - int height = (size.Height == 0) ? 0 : Misc.Ceiling(size.Height * RenderFactorY); - - return new Size(width, height); - }; + SizeTransformation SizeTransformation => (FloatSize size) => + new FloatSize(size.Width * RenderFactorX, size.Height * RenderFactorY); #endregion @@ -168,6 +162,23 @@ public RenderView(IContextProvider contextProvider, IGameData gameData, IGraphic var textureAtlasManager = textureAtlasManagerProvider?.Invoke(); var palette = textureAtlasManager.CreatePalette(graphicProvider, additionalPalettes); + static void Set320x256View(IRenderLayer renderLayer) + { + // To keep the aspect ration of 16:10 we use a virtual screen of 409,6 x 256. + // All positions are in this screen even though position values will only be + // in the range 320 x 256. There will be a black border left and right. + // The factor 200/256 is used to transform all positions. All X coordinates + // are increased by (409,6 - 320) / 2 (44.8) to center the display. But this + // values has to be factored by 200/256 as well and will become exactly 35. + const float factorY = 200.0f / 256.0f; + const float factorX = factorY;// factorY * (1.0f + 0.4f / 410.0f); + + renderLayer.PositionTransformation = (FloatPosition position) => + new FloatPosition(35.0f + position.X * factorX, position.Y * factorY); + renderLayer.SizeTransformation = (FloatSize size) => + new FloatSize(size.Width * factorX, size.Height * factorY); + } + foreach (var layer in Enum.GetValues()) { if (layer == Layer.None) @@ -181,6 +192,9 @@ public RenderView(IContextProvider contextProvider, IGameData gameData, IGraphic if (layer != Layer.Map3DBackground && layer != Layer.Map3DCeiling && layer != Layer.Map3D && layer != Layer.Billboards3D) renderLayer.Visible = true; + if (layer == Layer.FantasyIntroGraphics) + Set320x256View(renderLayer); + AddLayer(renderLayer); } catch (Exception ex) @@ -534,8 +548,8 @@ public void Render(FloatPosition viewportOffset) camera3D.Activate(); State.RestoreProjectionMatrix(State.ProjectionMatrix3D); var mapViewArea = new Rect(Global.Map3DViewX, Global.Map3DViewY, Global.Map3DViewWidth + 1, Global.Map3DViewHeight + 1); - mapViewArea.Position = PositionTransformation(mapViewArea.Position); - mapViewArea.Size = SizeTransformation(mapViewArea.Size); + mapViewArea.Position = PositionTransformation(mapViewArea.Position).Round(); + mapViewArea.Size = SizeTransformation(mapViewArea.Size).ToSize(); var viewport = frameBufferWindowArea; if (useEffectFrameBuffer) { diff --git a/Ambermoon.Renderer.OpenGL/ScreenRenderBuffer.cs b/Ambermoon.Renderer.OpenGL/ScreenRenderBuffer.cs index 4f7eac75..7736bedc 100644 --- a/Ambermoon.Renderer.OpenGL/ScreenRenderBuffer.cs +++ b/Ambermoon.Renderer.OpenGL/ScreenRenderBuffer.cs @@ -34,7 +34,7 @@ internal class ScreenRenderBuffer : IDisposable readonly State state; readonly VertexArrayObject vertexArrayObject = null; - readonly PositionBuffer positionBuffer = null; + readonly FloatPositionBuffer positionBuffer = null; readonly IndexBuffer indexBuffer = null; Size size = null; @@ -44,7 +44,7 @@ public ScreenRenderBuffer(State state, ScreenShader screenShader) { this.state = state; vertexArrayObject = new VertexArrayObject(state, screenShader.ShaderProgram); - positionBuffer = new PositionBuffer(state, true); + positionBuffer = new FloatPositionBuffer(state, true); positionBuffer.Add(0, 0, 0); positionBuffer.Add(Global.VirtualScreenWidth, 0, 1); positionBuffer.Add(Global.VirtualScreenWidth, Global.VirtualScreenHeight, 2); diff --git a/Ambermoon.Renderer.OpenGL/ScreenShader.cs b/Ambermoon.Renderer.OpenGL/ScreenShader.cs index 9f6e6134..4c69ea3e 100644 --- a/Ambermoon.Renderer.OpenGL/ScreenShader.cs +++ b/Ambermoon.Renderer.OpenGL/ScreenShader.cs @@ -291,7 +291,7 @@ protected static string GetVertexShaderHeader(State state) { GetVertexShaderHeader(state), $"uniform float {DefaultPrimaryModeName};", - $"in ivec2 {DefaultPositionName};", + $"in vec2 {DefaultPositionName};", $"uniform mat4 {DefaultProjectionMatrixName};", $"uniform mat4 {DefaultModelViewMatrixName};", $"uniform vec2 {DefaultResolutionName};", @@ -300,7 +300,7 @@ protected static string GetVertexShaderHeader(State state) $"", $"void main()", $"{{", - $" vec2 pos = vec2(float({DefaultPositionName}.x), float({DefaultPositionName}.y));", + $" vec2 pos = vec2({DefaultPositionName}.x, {DefaultPositionName}.y);", $" float u = pos.x > 0.5f ? endUV.x : 0.0f;", $" float v = pos.y > 0.5f ? endUV.y : 0.0f;", $" varTexCoord = vec2(u, 1.0f - v);", diff --git a/Ambermoon.Renderer.OpenGL/SkyShader.cs b/Ambermoon.Renderer.OpenGL/SkyShader.cs index d593709b..9546298f 100644 --- a/Ambermoon.Renderer.OpenGL/SkyShader.cs +++ b/Ambermoon.Renderer.OpenGL/SkyShader.cs @@ -65,7 +65,7 @@ internal class SkyShader : TextureShader protected static string[] SkyVertexShader(State state) => new string[] { GetVertexShaderHeader(state), - $"in ivec2 {DefaultPositionName};", + $"in vec2 {DefaultPositionName};", $"in ivec2 {DefaultTexCoordName};", $"in uint {DefaultLayerName};", $"in uint {DefaultPaletteIndexName};", @@ -83,7 +83,7 @@ internal class SkyShader : TextureShader $" int index = int(mod(gl_VertexID, 4));", $" float dx = index == 0 || index == 3 ? -0.49f : 0.49f;", $" float dy = index < 2 ? -0.49f : 0.49f;", - $" vec2 pos = vec2(float({DefaultPositionName}.x) + dx, float({DefaultPositionName}.y) + dy);", + $" vec2 pos = vec2({DefaultPositionName}.x + dx, {DefaultPositionName}.y + dy);", $" varTexCoord = atlasFactor * vec2({DefaultTexCoordName}.x, {DefaultTexCoordName}.y);", $" palIndex = float({DefaultPaletteIndexName});", $" gl_Position = {DefaultProjectionMatrixName} * {DefaultModelViewMatrixName} * vec4(pos, 1.0f - {DefaultZName} - float({DefaultLayerName}) * 0.00001f, 1.0f);", diff --git a/Ambermoon.Renderer.OpenGL/TextShader.cs b/Ambermoon.Renderer.OpenGL/TextShader.cs index 41348a80..31d58b4f 100644 --- a/Ambermoon.Renderer.OpenGL/TextShader.cs +++ b/Ambermoon.Renderer.OpenGL/TextShader.cs @@ -66,7 +66,7 @@ internal class TextShader : TextureShader static string[] TextVertexShader(State state) => new string[] { GetVertexShaderHeader(state), - $"in ivec2 {DefaultPositionName};", + $"in vec2 {DefaultPositionName};", $"in ivec2 {DefaultTexCoordName};", $"in uint {DefaultLayerName};", $"in uint {DefaultPaletteIndexName};", @@ -82,7 +82,7 @@ internal class TextShader : TextureShader $"void main()", $"{{", $" vec2 atlasFactor = vec2(1.0f / float({DefaultAtlasSizeName}.x), 1.0f / float({DefaultAtlasSizeName}.y));", - $" vec2 pos = vec2(float({DefaultPositionName}.x) + 0.49f, float({DefaultPositionName}.y) + 0.49f);", + $" vec2 pos = vec2({DefaultPositionName}.x + 0.49f, {DefaultPositionName}.y + 0.49f);", $" varTexCoord = atlasFactor * vec2({DefaultTexCoordName}.x, {DefaultTexCoordName}.y);", $" palIndex = float({DefaultPaletteIndexName});", $" textColIndex = float({DefaultTextColorIndexName});", diff --git a/Ambermoon.Renderer.OpenGL/TextureShader.cs b/Ambermoon.Renderer.OpenGL/TextureShader.cs index 9fade7be..d63c7621 100644 --- a/Ambermoon.Renderer.OpenGL/TextureShader.cs +++ b/Ambermoon.Renderer.OpenGL/TextureShader.cs @@ -80,7 +80,7 @@ internal class TextureShader : ColorShader protected static string[] TextureVertexShader(State state) => new string[] { GetVertexShaderHeader(state), - $"in ivec2 {DefaultPositionName};", + $"in vec2 {DefaultPositionName};", $"in ivec2 {DefaultTexCoordName};", $"in uint {DefaultLayerName};", $"in uint {DefaultPaletteIndexName};", @@ -96,7 +96,7 @@ internal class TextureShader : ColorShader $"void main()", $"{{", $" vec2 atlasFactor = vec2(1.0f / float({DefaultAtlasSizeName}.x), 1.0f / float({DefaultAtlasSizeName}.y));", - $" vec2 pos = vec2(float({DefaultPositionName}.x) + 0.49f, float({DefaultPositionName}.y) + 0.49f);", + $" vec2 pos = vec2({DefaultPositionName}.x + 0.49f, {DefaultPositionName}.y + 0.49f);", $" varTexCoord = atlasFactor * vec2({DefaultTexCoordName}.x, {DefaultTexCoordName}.y);", $" palIndex = float({DefaultPaletteIndexName});", $" maskColIndex = float({DefaultMaskColorIndexName});", diff --git a/Ambermoon.Renderer.OpenGL/VertexArrayObject.cs b/Ambermoon.Renderer.OpenGL/VertexArrayObject.cs index 03e8ebec..6a96474c 100644 --- a/Ambermoon.Renderer.OpenGL/VertexArrayObject.cs +++ b/Ambermoon.Renderer.OpenGL/VertexArrayObject.cs @@ -30,7 +30,8 @@ namespace Ambermoon.Renderer internal class VertexArrayObject : IDisposable { uint index = 0; - readonly Dictionary positionBuffers = new Dictionary(4); + readonly Dictionary positionBuffers = new Dictionary(3); + readonly Dictionary floatPositionBuffers = new Dictionary(3); readonly Dictionary wordBuffers = new Dictionary(4); readonly Dictionary colorBuffers = new Dictionary(4); readonly Dictionary byteBuffers = new Dictionary(4); @@ -74,6 +75,11 @@ public void AddBuffer(string name, PositionBuffer buffer) positionBuffers.Add(name, buffer); } + public void AddBuffer(string name, FloatPositionBuffer buffer) + { + floatPositionBuffers.Add(name, buffer); + } + public void AddBuffer(string name, VectorBuffer buffer) { vectorBuffers.Add(name, buffer); @@ -119,6 +125,11 @@ public void BindBuffers() bufferLocations[buffer.Key] = (int)program.BindInputBuffer(buffer.Key, buffer.Value); } + foreach (var buffer in floatPositionBuffers) + { + bufferLocations[buffer.Key] = (int)program.BindInputBuffer(buffer.Key, buffer.Value); + } + foreach (var buffer in vectorBuffers) { bufferLocations[buffer.Key] = (int)program.BindInputBuffer(buffer.Key, buffer.Value); @@ -169,6 +180,12 @@ public void UnbindBuffers() bufferLocations[buffer.Key] = -1; } + foreach (var buffer in floatPositionBuffers) + { + program.UnbindInputBuffer((uint)bufferLocations[buffer.Key]); + bufferLocations[buffer.Key] = -1; + } + foreach (var buffer in vectorBuffers) { program.UnbindInputBuffer((uint)bufferLocations[buffer.Key]); @@ -235,6 +252,12 @@ void InternalBind(bool bindOnly) buffersChanged = true; } + foreach (var buffer in floatPositionBuffers) + { + if (buffer.Value.RecreateUnbound()) + buffersChanged = true; + } + foreach (var buffer in vectorBuffers) { if (buffer.Value.RecreateUnbound()) diff --git a/Ambermoon.net/FantasyIntro.cs b/Ambermoon.net/FantasyIntro.cs index 34c6f15d..10e643d3 100644 --- a/Ambermoon.net/FantasyIntro.cs +++ b/Ambermoon.net/FantasyIntro.cs @@ -57,23 +57,22 @@ public FantasyIntro(IRenderView renderView, IFantasyIntroData fantasyIntroData, background.PaletteIndex = GetPaletteIndex(FantasyIntroGraphic.Background); background.TextureAtlasOffset = textureAtlas.GetOffset((uint)FantasyIntroGraphic.Background); background.X = 0; - background.Y = -28; + background.Y = 0; background.Visible = false; fairy = renderView.SpriteFactory.Create(64, 71, true, 7) as ILayerSprite; fairy.Layer = renderLayer; fairy.PaletteIndex = GetPaletteIndex(FantasyIntroGraphic.Fairy); fairy.TextureAtlasOffset = textureAtlas.GetOffset((uint)FantasyIntroGraphic.Fairy); - fairy.ClipArea = new Rect(0, 0, 320, 200); + fairy.ClipArea = new Rect(0, 0, 320, 256); fairy.Visible = false; - writing = renderView.SpriteFactory.Create(208, 83, true, 4) as ILayerSprite; + writing = renderView.SpriteFactory.Create(0, 83, true, 4) as ILayerSprite; // width will be increased later up to 208 writing.Layer = renderLayer; writing.PaletteIndex = GetPaletteIndex(FantasyIntroGraphic.Writing); writing.TextureAtlasOffset = textureAtlas.GetOffset((uint)FantasyIntroGraphic.Writing); writing.X = 64; - writing.Y = 146 - 28; // - 28 because screen height is only 200 - writing.ClipArea = new Rect(64, 0, 64, 200); // width will be increased later + writing.Y = 146; writing.Visible = false; fadeArea = renderView.ColoredRectFactory.Create(Global.VirtualScreenWidth, Global.VirtualScreenHeight, Color.Black, 255); @@ -291,7 +290,7 @@ void ProcessAction(long frame, FantasyIntroAction action) case FantasyIntroCommand.MoveFairy: { fairy.X = action.Parameters[0]; - fairy.Y = action.Parameters[1] - 28; + fairy.Y = action.Parameters[1]; fairy.Visible = true; playFairyAnimation = false; break; @@ -304,7 +303,7 @@ void ProcessAction(long frame, FantasyIntroAction action) case FantasyIntroCommand.AddWritingPart: { // Each time by 4 pixels - writing.ClipArea = writing.ClipArea.CreateModified(0, 0, 4, 0); + writing.Resize(writing.Width + 4, writing.Height); writing.Visible = true; break; }