Rybar Posted November 15, 2016 Share Posted November 15, 2016 The above screenshot is from one of Deepnight's games, Delicious Cortex. I've attached it to show the effect I'm trying to achieve. I've figured out how to properly scale my game to 3x with crisp rendering, and how to apply a filter to the whole game world. I've hit a snag with the filter step though; Sebastian applies a 3px by 3px mosaic grid in overlay mode to a game that's scaled 3x. When I apply a shader to the game world it's being rendered before its scaled (as expected), but the effect I'm going for would require access to the screen post-scaling. Is this possible? I've successfully re-created the effect in my js13k entry Super Glitch Box, but that was a canvas-rendered game, and not Phaser. I would like to avoid simply scaling up all the assets in-game and leaving the game scale at 1.0, to preserve the appearance of pixel-perfect movement. drhayes 1 Link to comment Share on other sites More sharing options...
Rybar Posted November 18, 2016 Author Share Posted November 18, 2016 I've poked around at Phaser's code, As far as I can tell seems like display objects at nearly every level have a filters array, but not the 'final output' of the renderer after scaling. Still looking for some assistance here; Has anyone here tried something like rendering the game to a texture and then passing that to a fragment shader? I could do something incredibly hackish in vanillaJS, was looking for some procedure that stayed within the Phaser framework first. Here's a quick screenshot further that more clearly shows what I'm going for: Link to comment Share on other sites More sharing options...
Rybar Posted November 22, 2016 Author Share Posted November 22, 2016 I'm getting very close to the look I'm going for! It's still a bit dark, but I've figured out how to render a tiny game to a bigger texture and then run a filter on it, which was the biggest hurdle so far. Can see it in action here: http://ryanmalm.com/testbed/build/ Link to comment Share on other sites More sharing options...
drhayes Posted November 22, 2016 Share Posted November 22, 2016 Did you end up setting the filter on the stage? What was your solution? Link to comment Share on other sites More sharing options...
Rybar Posted November 22, 2016 Author Share Posted November 22, 2016 var game = {}; game.preload = function() { var logo; var helicopter; var renderTexture; var renderTexture2; var currentTexture; var stageSprite; var outputSprite; var gameMatrix; var gameGroup; var cam; } game.create = function () { //post effect----------- var fragmentSrc = [ "precision mediump float;", // Incoming texture coordinates. 'varying vec2 vTextureCoord;', // Incoming vertex color 'varying vec4 vColor;', // Sampler for a) sprite image or b) rendertarget in case of game.world.filter 'uniform sampler2D uSampler;', "uniform vec2 resolution;", "uniform float time;", "uniform vec2 mouse;", "vec4 gray = vec4(0.5, 0.5, 0.5, 1.0);", "void main( void ) {", // scanlines //"gl_FragColor = texture2D(uSampler, vTextureCoord) * mod(gl_FragCoord.y,2.0);", //first try at pixel mosaic effect "gl_FragColor = gray * mod(gl_FragCoord.y, 3.0) * gray * mod(gl_FragCoord.x , 3.0) * texture2D(uSampler, vTextureCoord);", //should do nothing //"gl_FragColor = texture2D(uSampler, vTextureCoord);", "}" ]; scanlineFilter = new Phaser.Filter(game, null, fragmentSrc); game.world.setBounds(0, 0, 1000, 1000); game.stage.smoothed = false; cursors = game.input.keyboard.createCursorKeys(); game.camera.width = 266; game.camera.height = 200; game.camera.roundPx = true; gameGroup = game.make.group(); helicopter = game.make.sprite(0,0, 'helicopter'); game.physics.enable(helicopter, Phaser.Physics.ARCADE); gameGroup.add(helicopter); logo = game.make.sprite(100,100, 'logo'); logo.scale.setTo(0.25,0.25); logo.anchor.setTo(0.5,0.5) game.physics.enable(logo, Phaser.Physics.ARCADE); gameGroup.add(logo); renderTexture = game.make.renderTexture(266, 200, 'texture1'); renderTexture2 = game.make.renderTexture(798, 600, '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(3,0,0,3,0,0); console.log(game); }; game.preRender = function(){ gameGroup.visible = false; } game.render = function(){ //do nothing gameGroup.visible = true; renderTexture.render(gameGroup, game.stage.worldTransform, true); renderTexture2.render(stageSprite, gameMatrix, true); } module.exports = game; This is the whole game state sans update(), including the fragment shader in its current state. I admittedly don't really know what I'm doing in GLSL, but I'm learning. I'm using 2 render textures, one to render the 1x scale game and then rendering it scaled 3x into another renderTexture. I've added the filter to the outputSprite, which is on the stage. I'd love it if someone who's attempted any deferred rendering stuff like this would look this over to see if I'm doing anything wasteful or unnecessary. Link to comment Share on other sites More sharing options...
Rybar Posted November 30, 2016 Author Share Posted November 30, 2016 I got this working pretty well. I've posted my repo so you can poke at my setup yourself if you like. http://www.github.com/rybar/gamenought/ Live demo at https://rybar.github.io/gamenought/wwwroot/build/ drhayes 1 Link to comment Share on other sites More sharing options...
drhayes Posted November 30, 2016 Share Posted November 30, 2016 Wow, that is hot. That looks really good! BTW, it took a long time to load the demo page because the livereload.js script was pending for about a minute; not sure if that is happening to anyone else. I'm gonna try applying your filter to the stage in my scaled up game later today, see how it looks. Thanks for solving that! I'm a big fan of the effect. Rybar 1 Link to comment Share on other sites More sharing options...
Recommended Posts