From 6d0a8cc535fd254d823486e02159296fbcc6bb46 Mon Sep 17 00:00:00 2001 From: shr Date: Sun, 17 Sep 2023 07:39:20 +0900 Subject: [PATCH] testing poyopoyo --- .../graphics/framebuffer/FrameBuffer.hx | 99 ++++++++++++++++ .../framebuffer/FrameBufferManager.hx | 109 ++++++++++++++++++ .../funkin/graphics/framebuffer/SpriteCopy.hx | 51 ++++++++ 3 files changed, 259 insertions(+) create mode 100644 source/funkin/graphics/framebuffer/FrameBuffer.hx create mode 100644 source/funkin/graphics/framebuffer/FrameBufferManager.hx create mode 100644 source/funkin/graphics/framebuffer/SpriteCopy.hx diff --git a/source/funkin/graphics/framebuffer/FrameBuffer.hx b/source/funkin/graphics/framebuffer/FrameBuffer.hx new file mode 100644 index 000000000..480bbf111 --- /dev/null +++ b/source/funkin/graphics/framebuffer/FrameBuffer.hx @@ -0,0 +1,99 @@ +package funkin.graphics.framebuffer; + +import openfl.geom.Rectangle; +import openfl.geom.Matrix; +import openfl.display.BitmapData; +import flixel.util.FlxColor; +import flixel.FlxCamera; +import openfl.Lib; +import openfl.display3D.textures.TextureBase; + +class FrameBuffer +{ + /** + * The bitmap data of the frame buffer. + */ + public var bitmap(default, null):BitmapData = null; + + var texture:TextureBase; + final camera:FlxCamera; + final spriteCopies:Array = []; + + public function new() + { + camera = new FlxCamera(); + camera.bgColor = FlxColor.TRANSPARENT; + camera.flashSprite.cacheAsBitmap = true; + } + + /** + * Creates a frame buffer with the given size. + * @param width the width + * @param height the height + */ + public function create(width:Int, height:Int):Void + { + dispose(); + final c3d = Lib.current.stage.context3D; + texture = c3d.createTexture(width, height, BGRA, true); + bitmap = BitmapData.fromTexture(texture); + } + + /** + * Makes the internal camera follows the target camera. + * @param target the target camera + */ + public function follow(target:FlxCamera):Void + { + camera.scroll.copyFrom(target.scroll); + camera.setScale(target.scaleX, target.scaleY); + } + + /** + * Locks the frame buffer and clears the buffer. + */ + @:access(flixel.FlxCamera) + public function lock():Void + { + camera.clearDrawStack(); + camera.canvas.graphics.clear(); + camera.fill(camera.bgColor.to24Bit(), camera.useBgAlphaBlending, camera.bgColor.alphaFloat); + } + + /** + * Renders all sprite copies. + */ + public function render():Void + { + for (spriteCopy in spriteCopies) + { + spriteCopy.render(camera); + } + } + + /** + * Unlocks the frame buffer and makes the bitmap ready to use. + */ + @:access(flixel.FlxCamera) + public function unlock():Void + { + bitmap.fillRect(new Rectangle(0, 0, bitmap.width, bitmap.height), 0); + bitmap.draw(camera.flashSprite, new Matrix(1, 0, 0, 1, camera.flashSprite.x, camera.flashSprite.y)); + } + + public function dispose():Void + { + if (texture != null) + { + texture.dispose(); + texture = null; + bitmap.dispose(); + bitmap = null; + } + } + + public function addSpriteCopy(spriteCopy:SpriteCopy):Void + { + spriteCopies.push(spriteCopy); + } +} diff --git a/source/funkin/graphics/framebuffer/FrameBufferManager.hx b/source/funkin/graphics/framebuffer/FrameBufferManager.hx new file mode 100644 index 000000000..2326b6c43 --- /dev/null +++ b/source/funkin/graphics/framebuffer/FrameBufferManager.hx @@ -0,0 +1,109 @@ +package funkin.graphics.framebuffer; + +import openfl.display.BitmapData; +import flixel.FlxSprite; +import flixel.FlxCamera; + +class FrameBufferManager +{ + final camera:FlxCamera; + final frameBufferMap:Map = []; + + /** + * Creates a frame buffer manager that targets `camera`. + * @param camera the target camera. + */ + public function new(camera:FlxCamera) + { + this.camera = camera; + } + + /** + * Creates a new frame buffer with a name. + * @param name the name + */ + public function createFrameBuffer(name:String):Void + { + if (frameBufferMap.exists(name)) + { + FlxG.log.warn('frame buffer "$name" already exists'); + } + else + { + final fb = new FrameBuffer(); + fb.create(camera.width, camera.height); + frameBufferMap[name] = fb; + } + } + + /** + * Adds a copy of the sprite to the frame buffer. + * @param name the name of the frame buffer + * @param sprite the sprite + * @param color if this is not `-1`, the sprite will have the color while keeping its shape + */ + public function addSpriteTo(name:String, sprite:FlxSprite, color:Int = -1):Void + { + if (!frameBufferMap.exists(name)) + { + createFrameBuffer(name); + } + frameBufferMap[name].addSpriteCopy(new SpriteCopy(sprite, color)); + } + + /** + * Call this before everything is drawn. + */ + public function lock():Void + { + for (_ => fb in frameBufferMap) + { + fb.lock(); + } + } + + /** + * Renders all the copies of the sprites. Make sure this is called between + * `lock` and `unlock`. + */ + public function render():Void + { + for (_ => fb in frameBufferMap) + { + fb.render(); + } + } + + /** + * After calling this you can use bitmap data of all frame buffers. + */ + public function unlock():Void + { + for (_ => fb in frameBufferMap) + { + fb.unlock(); + } + } + + /** + * Returns the bitmap data of the frame buffer + * @param name the name of the frame buffer + * @return the ready-to-use bitmap data + */ + public function getFrameBuffer(name:String):BitmapData + { + return frameBufferMap[name].bitmap; + } + + /** + * Disposes all frame buffers. + */ + public function dispose():Void + { + for (_ => fb in frameBufferMap) + { + fb.dispose(); + } + frameBufferMap.clear(); + } +} diff --git a/source/funkin/graphics/framebuffer/SpriteCopy.hx b/source/funkin/graphics/framebuffer/SpriteCopy.hx new file mode 100644 index 000000000..aaa6bb730 --- /dev/null +++ b/source/funkin/graphics/framebuffer/SpriteCopy.hx @@ -0,0 +1,51 @@ +package funkin.graphics.framebuffer; + +import flixel.FlxCamera; +import flixel.FlxSprite; + +class SpriteCopy +{ + final sprite:FlxSprite; + var color:Int; + + public function new(sprite:FlxSprite, color:Int = -1) + { + this.sprite = sprite; + this.color = color; + } + + /** + * Renders the copy to the camera. + * @param camera the camera + */ + @:access(flixel.FlxSprite) + public function render(camera:FlxCamera):Void + { + final rMult = sprite.colorTransform.redMultiplier; + final gMult = sprite.colorTransform.greenMultiplier; + final bMult = sprite.colorTransform.blueMultiplier; + final aMult = sprite.colorTransform.alphaMultiplier; + final rOff = Std.int(sprite.colorTransform.redOffset); + final gOff = Std.int(sprite.colorTransform.greenOffset); + final bOff = Std.int(sprite.colorTransform.blueOffset); + final aOff = Std.int(sprite.colorTransform.alphaOffset); + final tmpCameras = sprite._cameras; + + sprite._cameras = [camera]; + + if (color != -1) + { + final red = color >> 16 & 0xFF; + final green = color >> 8 & 0xFF; + final blue = color & 0xFF; + sprite.setColorTransform(0, 0, 0, 1, red, green, blue, 0); + } + sprite.draw(); + + sprite._cameras = tmpCameras; + if (color != -1) + { + sprite.setColorTransform(rMult, gMult, bMult, aMult, rOff, gOff, bOff, aOff); + } + } +}