Jump to content

The Deepnight Effect Help


Rybar
 Share

Recommended Posts

Screenshot 2016-11-14 20.40.29.png

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. 

Link to comment
Share on other sites

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:

CxYqXPRUcAA-cD1.jpg

Link to comment
Share on other sites

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

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.

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...