diff --git a/indigo/indigo/src/main/scala/indigo/platform/renderer/shared/CameraHelper.scala b/indigo/indigo/src/main/scala/indigo/platform/renderer/shared/CameraHelper.scala index c8337c93d..c64dd671a 100644 --- a/indigo/indigo/src/main/scala/indigo/platform/renderer/shared/CameraHelper.scala +++ b/indigo/indigo/src/main/scala/indigo/platform/renderer/shared/CameraHelper.scala @@ -8,7 +8,8 @@ object CameraHelper: def calculateCameraMatrix( screenWidth: Double, screenHeight: Double, - magnification: Double, + renderMagnification: Double, + actualMagnification: Double, cameraX: Double, cameraY: Double, cameraZoom: Double, @@ -16,8 +17,8 @@ object CameraHelper: cameraRotation: Radians, isLookAt: Boolean ): CheapMatrix4 = - val newWidth = screenWidth / magnification - val newHeight = screenHeight / magnification + val newWidth = screenWidth / renderMagnification + val newHeight = screenHeight / renderMagnification val bounds: (Float, Float, Float, Float) = if isLookAt then zoom(0, 0, newWidth.toFloat, newHeight.toFloat, cameraZoom.toFloat) @@ -25,17 +26,23 @@ object CameraHelper: val mat = if isLookAt then - CheapMatrix4.identity - .translate(-cameraX.toFloat, -cameraY.toFloat, 1.0f) - .rotate(cameraRotation.toFloat) - .translate(newWidth.toFloat / 2.0f, newHeight.toFloat / 2.0f, 1.0f) * - CheapMatrix4 - .orthographic( - bounds._1, - bounds._2, - bounds._3, - bounds._4 + val m1 = + CheapMatrix4.identity + .translate(-cameraX.toFloat, -cameraY.toFloat, 1.0f) + .rotate(cameraRotation.toFloat) + .translate( + Math.floor(newWidth.toFloat / (2.0f * actualMagnification.toFloat)).toFloat, + Math.floor(newHeight.toFloat / (2.0f * actualMagnification.toFloat)).toFloat, + 1.0f ) + + m1 * CheapMatrix4 + .orthographic( + bounds._1, + bounds._2, + bounds._3, + bounds._4 + ) else CheapMatrix4.identity .rotate(cameraRotation.toFloat) * diff --git a/indigo/indigo/src/main/scala/indigo/platform/renderer/webgl1/RendererWebGL1.scala b/indigo/indigo/src/main/scala/indigo/platform/renderer/webgl1/RendererWebGL1.scala index b092fa37b..e268a393d 100644 --- a/indigo/indigo/src/main/scala/indigo/platform/renderer/webgl1/RendererWebGL1.scala +++ b/indigo/indigo/src/main/scala/indigo/platform/renderer/webgl1/RendererWebGL1.scala @@ -114,6 +114,7 @@ final class RendererWebGL1( cNc.canvas.width.toDouble, cNc.canvas.height.toDouble, m.toDouble, + m.toDouble, 0, 0, 1, @@ -130,6 +131,7 @@ final class RendererWebGL1( cNc.canvas.width.toDouble, cNc.canvas.height.toDouble, cNc.magnification.toDouble, + 1.0, c.position.x.toDouble, c.position.y.toDouble, c.zoom.toDouble, @@ -146,6 +148,7 @@ final class RendererWebGL1( cNc.canvas.width.toDouble, cNc.canvas.height.toDouble, m.toDouble, + 1.0, c.position.x.toDouble, c.position.y.toDouble, c.zoom.toDouble, diff --git a/indigo/indigo/src/main/scala/indigo/platform/renderer/webgl2/RendererWebGL2.scala b/indigo/indigo/src/main/scala/indigo/platform/renderer/webgl2/RendererWebGL2.scala index 9c42497df..aeb824744 100644 --- a/indigo/indigo/src/main/scala/indigo/platform/renderer/webgl2/RendererWebGL2.scala +++ b/indigo/indigo/src/main/scala/indigo/platform/renderer/webgl2/RendererWebGL2.scala @@ -22,7 +22,6 @@ import indigo.shared.platform.ProcessedSceneData import indigo.shared.platform.RendererConfig import indigo.shared.scenegraph.Blend import indigo.shared.scenegraph.BlendFactor -import indigo.shared.scenegraph.Camera import indigo.shared.shader.RawShaderCode import indigo.shared.shader.ShaderId import indigo.shared.shader.StandardShaders @@ -248,7 +247,8 @@ final class RendererWebGL2( .calculateCameraMatrix( lastWidth.toDouble, lastHeight.toDouble, - 1.0d, // Layers aren't magnified + 1.0d, // Layers aren't magnified during rendering. + layer.magnification.map(_.toDouble).getOrElse(1.0), c.position.x.toDouble, c.position.y.toDouble, c.zoom.toDouble, @@ -287,6 +287,7 @@ final class RendererWebGL2( lastWidth.toDouble, lastHeight.toDouble, m.toDouble, + 1.0d, // During merge, we always used a fixed camera, so irrelevant. 0, 0, 1, diff --git a/indigo/sandbox/src/main/scala/com/example/sandbox/SandboxGame.scala b/indigo/sandbox/src/main/scala/com/example/sandbox/SandboxGame.scala index e70315147..4623dfb79 100644 --- a/indigo/sandbox/src/main/scala/com/example/sandbox/SandboxGame.scala +++ b/indigo/sandbox/src/main/scala/com/example/sandbox/SandboxGame.scala @@ -5,6 +5,7 @@ import com.example.sandbox.scenes.BoundingCircleScene import com.example.sandbox.scenes.BoundsScene import com.example.sandbox.scenes.BoxesScene import com.example.sandbox.scenes.CameraScene +import com.example.sandbox.scenes.CameraWithCloneTilesScene import com.example.sandbox.scenes.ClipScene import com.example.sandbox.scenes.ConfettiScene import com.example.sandbox.scenes.CratesScene @@ -46,7 +47,7 @@ object SandboxGame extends IndigoGame[SandboxBootData, SandboxStartupData, Sandb val viewportHeight: Int = gameHeight * magnificationLevel // 256 def initialScene(bootData: SandboxBootData): Option[SceneName] = - Some(OriginalScene.name) + Some(CameraWithCloneTilesScene.name) def scenes(bootData: SandboxBootData): NonEmptyList[Scene[SandboxStartupData, SandboxGameModel, SandboxViewModel]] = NonEmptyList( @@ -71,7 +72,8 @@ object SandboxGame extends IndigoGame[SandboxBootData, SandboxStartupData, Sandb UltravioletScene, PointersScene, BoundingCircleScene, - LineReflectionScene + LineReflectionScene, + CameraWithCloneTilesScene ) val eventFilters: EventFilters = EventFilters.Permissive diff --git a/indigo/sandbox/src/main/scala/com/example/sandbox/scenes/CameraWithCloneTilesScene.scala b/indigo/sandbox/src/main/scala/com/example/sandbox/scenes/CameraWithCloneTilesScene.scala new file mode 100644 index 000000000..84e9c65c1 --- /dev/null +++ b/indigo/sandbox/src/main/scala/com/example/sandbox/scenes/CameraWithCloneTilesScene.scala @@ -0,0 +1,70 @@ +package com.example.sandbox.scenes + +import com.example.sandbox.SandboxAssets +import com.example.sandbox.SandboxGameModel +import com.example.sandbox.SandboxStartupData +import com.example.sandbox.SandboxViewModel +import indigo.* +import indigo.scenes.* +import indigo.syntax.* + +object CameraWithCloneTilesScene extends Scene[SandboxStartupData, SandboxGameModel, SandboxViewModel]: + + type SceneModel = Unit + type SceneViewModel = Unit + + def eventFilters: EventFilters = + EventFilters.Permissive + + def modelLens: Lens[SandboxGameModel, Unit] = + Lens.unit + + def viewModelLens: Lens[SandboxViewModel, Unit] = + Lens.unit + + def name: SceneName = + SceneName("crates with camera") + + def subSystems: Set[SubSystem] = + Set() + + def updateModel( + context: SceneContext[SandboxStartupData], + model: Unit + ): GlobalEvent => Outcome[Unit] = + _ => Outcome(model) + + def updateViewModel( + context: SceneContext[SandboxStartupData], + model: Unit, + viewModel: Unit + ): GlobalEvent => Outcome[Unit] = + _ => Outcome(viewModel) + + val graphic = Graphic(64, 64, SandboxAssets.cratesMaterial.withLighting(LightingModel.Unlit)) + + val cloneId: CloneId = CloneId("crates") + + val cloneBlanks: Batch[CloneBlank] = + Batch(CloneBlank(cloneId, graphic).static) + + val crates = + (0 to 5).flatMap { row => + (0 to 5).map { col => + CloneTileData(col * 32, row * 32, Radians.zero, 1.0, 1.0, 0, 0, 32, 32) + } + }.toBatch + + def present( + context: SceneContext[SandboxStartupData], + model: Unit, + viewModel: Unit + ): Outcome[SceneUpdateFragment] = + Outcome( + SceneUpdateFragment( + Layer( + CloneTiles(cloneId, crates) + ).withMagnification(2) + .withCamera(Camera.LookAt(Point(96))) + ).addCloneBlanks(cloneBlanks) + )