xainey Posted January 18, 2018 Share Posted January 18, 2018 I played a ludem dare game a few years ago and finally re-found the game http://deepnight.net/games/last-breath/ I loved this beveled pixel effect and have been trying to use it in phaser. Deepnight referenced this one Reddit post on how to implement the style, but I have not been able to successfully do anything with it yet. I've tried desperately to use the following shader example by Rybar but always seem to fall a little bit short. I wanted to render the effect on the entire game.world instead of having to add everything manually to a group like Rybar did in his examples. I tried to use his shader and capture the world, scale it up, and render it to a sprite on top everything. Using this method causes all of the camera, and physics to be off. I've made a simple example of my closest attempt using Phaser CE and some boilerplate. I've added some debug boxes to show where the original sprites are located in the background. <!doctype html> <html lang="en"> <head> <meta charset="UTF-8" /> <title>Phaser - Making your first game, part 7</title> <script type="text/javascript" src="js/phaser.min.js"></script> <style type="text/css"> body { margin: 0; } </style> </head> <body> <script type="text/javascript"> var w = 800 var h = 600; var player; var platforms; var cursors; var renderTexture; var renderTexture2; var stageSprite; var outputSprite; var gameMatrix; var gameGroup; var game = new Phaser.Game(w, h, Phaser.WEBGL, '', { preload: preload, create: create, update: update, render: render, preRender: preRender }); function preload() { game.load.image('sky', 'assets/sky.png'); game.load.image('ground', 'assets/platform.png'); game.load.spritesheet('dude', 'assets/dude.png', 32, 48); } function create() { game.physics.startSystem(Phaser.Physics.ARCADE); game.add.sprite(0, 0, 'sky'); platforms = game.add.group(); platforms.enableBody = true; var ground = platforms.create(0, game.world.height - 64, 'ground'); ground.scale.setTo(2, 2); ground.body.immovable = true; var ledge = platforms.create(0, 110, 'ground'); ledge.body.immovable = true; ledge = platforms.create(250, 255, 'ground'); ledge.body.immovable = true; // player = game.make.sprite(32, game.world.height - 150, 'dude'); // move the player to the top platform player = game.make.sprite(0, 0, 'dude'); game.physics.arcade.enable(player); player.body.gravity.y = 300; player.body.collideWorldBounds = true; player.animations.add('left', [0, 1, 2, 3], 10, true); player.animations.add('right', [5, 6, 7, 8], 10, true); cursors = game.input.keyboard.createCursorKeys(); game.camera.follow(player) var fragmentSrc = [ 'precision mediump float;', 'varying vec2 vTextureCoord;', 'varying vec4 vColor;', 'uniform sampler2D uSampler;', 'uniform vec2 resolution;', 'uniform float time;', 'uniform vec2 mouse;', 'void main( void ) {', 'vec2 st = vTextureCoord.xy;', 'st *= resolution;', // this makes the box defined below tiny and repeat across the screen 'st = fract(st);', 'vec2 bl = step(vec2(0.25, 0.75) , st);', 'float pct = bl.x * bl.y;', 'vec2 tr = step(vec2(0.5, 0.00),1.0-st);', 'pct *= tr.x * tr.y;', 'pct *= 0.15;', // knock it down to gray 'vec3 src = texture2D(uSampler, vTextureCoord).xyz;', // game art 'vec3 dst = vec3(pct) + vec3(0.4);', // the overlay pattern 'vec3 color = vec3((dst.x <= 0.5) ? (2.0 * src.x * dst.x) : (1.0 - 2.0 * (1.0 - dst.x) * (1.0 - src.x)),' + '(dst.y <= 0.5) ? (2.0 * src.y * dst.y) : (1.0 - 2.0 * (1.0 - dst.y) * (1.0 - src.y)),' + '(dst.z <= 0.5) ? (2.0 * src.z * dst.z) : (1.0 - 2.0 * (1.0 - dst.z) * (1.0 - src.z)));', 'gl_FragColor.rgb = clamp(color, 0.0, 1.0);', 'gl_FragColor.w = 1.0;', '}' ] gameGroup = game.make.group(); gameGroup.add(platforms) gameGroup.add(player) gameGroup.add(ledge) scanlineFilter = new Phaser.Filter(game, null, fragmentSrc); scanlineFilter.setResolution(w/4,h/4); game.world.setBounds(0, 0, 2000, 2000); game.stage.smoothed = false; renderTexture = game.make.renderTexture(w/4, h/4, 'texture1'); renderTexture2 = game.make.renderTexture(w, h, 'texture2'); renderTexture2.renderer.renderSession.roundPixels = true; renderTexture2.baseTexture.scaleMode = PIXI.scaleModes.NEAREST; stageSprite = game.make.sprite(0,0, renderTexture); stageSprite.smoothed = false; outputSprite = game.add.sprite(0,0, renderTexture2); outputSprite.smoothed = false; outputSprite.filters = [scanlineFilter]; gameMatrix = new Phaser.Matrix(4,0,0,4,0,0); } function preRender(){ // gameGroup.visible = false; } function render(){ // gameGroup.visible = true; // renderTexture.render(player, game.stage.worldTransform, true); // renderTexture2.render(stageSprite, gameMatrix, true); // Debug game.debug.spriteBounds(player, 'pink', false) game.debug.body(player, 'red', false) game.debug.spriteBounds(stageSprite, 'yellow', false) game.debug.body(stageSprite, 'orange', false) game.debug.spriteBounds(outputSprite, 'cyan', false) game.debug.body(outputSprite, 'blue', false) } function update() { game.physics.arcade.collide(player, platforms); // renderTexture.clear() // renderTexture2.clear() outputSprite.sendToBack() renderTexture.render(game.world, null, true); renderTexture2.render(stageSprite, gameMatrix, true); outputSprite.bringToTop() player.body.velocity.x = 0; if (cursors.left.isDown) { player.body.velocity.x = -150; player.animations.play('left'); } else if (cursors.right.isDown) { player.body.velocity.x = 150; player.animations.play('right'); } else { player.animations.stop(); player.frame = 4; } if (cursors.up.isDown && player.body.touching.down) { player.body.velocity.y = -350; } } </script> </body> </html> I've also tried scaling the game up then set the filter to the world but the filter is applied before it is scaled. game.scale.scaleMode = Phaser.ScaleManager.USER_SCALE game.scale.setUserScale(4, 4) game.renderer.renderSession.roundPixels = true Phaser.Canvas.setImageRenderingCrisp(game.canvas) var scanlineFilter = new Phaser.Filter(game, null, fragmentSrc); scanlineFilter.setResolution(game.width / 4, game.height / 4) game.world.filters = [scanlineFilter]; Can anyone help me get this working or suggest a better approach? Link to comment Share on other sites More sharing options...
xainey Posted January 22, 2018 Author Share Posted January 22, 2018 I still haven't figured out how to get this working. I found out I need to use updateTransform() to fix the physics bodies after using render. Now I need help getting the camera aligned properly with the game being scaled. Here is my closest attempt, It's pretty close. Any ideas? Alexalten 1 Link to comment Share on other sites More sharing options...
xainey Posted January 23, 2018 Author Share Posted January 23, 2018 For anyone interested I was able to get something working. I've set the camera to follow the player, scaled the size of the camera, and updated the output sprite's coords to the camera's coords each pass. If this could be optimized I'd love to know. It seems ok and runs at 60FPS. Fenopiù and Rybar 2 Link to comment Share on other sites More sharing options...
Rybar Posted February 7, 2018 Share Posted February 7, 2018 This is looking good! I abandoned this last year to work on my own tiny render-engine very shortly after getting the shader working, hadn't bothered with getting a camera properly scaled. It'd probably be trivial to make a custom debug drawing function that's scaled properly too I'd think. I'm revisiting Phaser for a larger project now that 3.0 release is pending, very excited to see someone else make use of the little shader I managed to cobble together. Link to comment Share on other sites More sharing options...
Recommended Posts