Kacper Pietrzak Posted July 14, 2017 Share Posted July 14, 2017 Hey everyone! I've implemented simple dynamic lightning in my project, but what I'm missing is soft light edges effect. This what it looks like now: https://youtu.be/M-idTMGYvsw I use sprites' masks to achieve that, code looks somewhat like this: updateShowingLayer() { + this.showMaskGraphics.clear(); + this.showMaskGraphics.lineStyle( 2, 0xffffff, 1 ); + this.showMaskGraphics.beginFill( 0x00000000 ); + this.showMaskGraphics.moveTo( this.player.x, this.player.y ); + + for ( let i = 0; i < NUMBER_OF_RAYS; i++ ) { + const rayAngle = mouseAngle - ( LIGHT_ANGLE / 2 ) + ( LIGHT_ANGLE / NUMBER_OF_RAYS ) * i; + let lastX = this.player.x; + let lastY = this.player.y; + for ( let j = 1; j <= RAY_LENGTH; j++ ) { + const landingX = Math.round( this.player.x - ( 2 * j ) * Math.cos( rayAngle ) ); + const landingY = Math.round( this.player.y - ( 2 * j ) * Math.sin( rayAngle ) ); + if ( !this.isTileBlocking( landingX, landingY ) ) { + lastX = landingX; + lastY = landingY; + } else { + break; + } + } + this.showMaskGraphics.lineTo( lastX, lastY ); + } + this.showMaskGraphics.lineTo( this.player.x, this.player.y ); + this.showMaskGraphics.endFill(); } } And then I just set masks in corresponding sprites to `this.showMaskGraphics` The full code is available here: https://github.com/PiGames/Project-Nostradamus/blob/dynamic-lightning/src/objects/Flashlight.js Does anyone have an idea how to make this light soft ? Thanks Link to comment Share on other sites More sharing options...
samid737 Posted July 14, 2017 Share Posted July 14, 2017 Maybe you can apply a bluf filter to your sprites. Im not sure if this will work (WEBGL only) in your specific case, but it might be useful . Here it is applied to an example (you can uncomment the code in create): Link to comment Share on other sites More sharing options...
Kacper Pietrzak Posted July 14, 2017 Author Share Posted July 14, 2017 @samid737 Well It doesn't work actually because the sprite that is basically the light is a solid color, so it looks exactly the same blurred but thanks Link to comment Share on other sites More sharing options...
samid737 Posted July 14, 2017 Share Posted July 14, 2017 The blur filter should apply to a solid color too I believe (the border sprite around the first example is actually a solid copy of the dude). Another idea, maybe you can use a glow filter?: Link to comment Share on other sites More sharing options...
Kacper Pietrzak Posted July 14, 2017 Author Share Posted July 14, 2017 The thing is, the way that I'm handling dynamic lighting is creating mask that cuts off the shape of light from flashlight that is precisely calculated, so any effect that makes this light bigger, like glow filter, is useless for now. because it gets cut off, have to think about it Link to comment Share on other sites More sharing options...
samid737 Posted July 15, 2017 Share Posted July 15, 2017 I checked out the game, nice work! why not just add an extra glow graphics layer?: this.shadowLayer = this.player.game.add.image(0, 0, 'layer-background'); this.shadowLayer.width = this.player.game.camera.width * 1.5; this.shadowLayer.height = this.player.game.camera.height * 1.5; this.shadowLayer.alpha = _FlashlightConstants.WORLD_SHADOW_ALPHA; this.flickerLayer = this.player.game.add.image(0, 0, 'layer-background'); this.flickerLayer.width = _FlashlightConstants.RAY_LENGTH * 4.5; this.flickerLayer.height = _FlashlightConstants.RAY_LENGTH * 4.5; this.flickerLayer.anchor.setTo(0.5); this.hideMaskGraphics = this.player.game.add.graphics(0, 0); this.shadowLayer.mask = this.hideMaskGraphics; this.showMaskGraphics = this.player.game.add.graphics(0, 0); zombies.setAll('mask', this.showMaskGraphics); this.zombies = zombies; this.showMaskGraphics.filters=[this.glowFilter]; //add the extra glow layer, the padding is necessary for a soft light effect this.glowGraphics = this.player.game.add.graphics(0, 0); this.glowGraphics.boundsPadding=200; this.glowFilter=new Phaser.Filter.Glow(this); this.glowGraphics.filters=[this.glowFilter]; this.hideMaskGraphics.clear(); this.hideMaskGraphics.moveTo(this.shadowLayer.x, this.shadowLayer.y); this.hideMaskGraphics.lineStyle(2, 0xfff000, 1); this.hideMaskGraphics.beginFill(0x00000000); this.hideMaskGraphics.lineTo(this.player.x, this.player.y); //the extra glow layer this.glowGraphics.clear(); this.glowGraphics.lineStyle(1, 0xfff0f0,0.0 ); this.glowGraphics.beginFill(0xffffff,Math.random()*0.05+0.02); //light flickering effect this.glowGraphics.lineTo(this.player.x, this.player.y); var mouseX = this.player.game.input.mousePointer.worldX; var mouseY = this.player.game.input.mousePointer.worldY; var mouseAngle = Math.atan2(this.player.y - mouseY, this.player.x - mouseX); for (var i = 0; i < _FlashlightConstants.NUMBER_OF_RAYS; i++) { var rayAngle = mouseAngle - _FlashlightConstants.LIGHT_ANGLE / 2 + _FlashlightConstants.LIGHT_ANGLE / _FlashlightConstants.NUMBER_OF_RAYS * i; var lastX = this.player.x; var lastY = this.player.y; for (var j = 1; j <= _FlashlightConstants.RAY_LENGTH; j++) { var landingX = Math.round(this.player.x - 2 * j * Math.cos(rayAngle)); var landingY = Math.round(this.player.y - 2 * j * Math.sin(rayAngle)); if (!this.isTileBlocking(landingX, landingY)) { lastX = landingX; lastY = landingY; } else { break; } } this.hideMaskGraphics.lineTo(lastX, lastY); //draw the glow layer this.glowGraphics.lineTo(lastX,lastY); } this.hideMaskGraphics.lineTo(this.player.x, this.player.y); this.hideMaskGraphics.lineTo(this.shadowLayer.x, this.shadowLayer.y); this.hideMaskGraphics.lineTo(this.shadowLayer.x + this.shadowLayer.width, 0); this.hideMaskGraphics.lineTo(this.shadowLayer.x + this.shadowLayer.width, this.shadowLayer.y + this.shadowLayer.height); this.hideMaskGraphics.lineTo(0, this.shadowLayer.y + this.shadowLayer.height); this.hideMaskGraphics.lineTo(this.shadowLayer.x, this.shadowLayer.y); this.hideMaskGraphics.endFill(); It should be possible , it looks quite nice imho, but it does affect performance significantly..... I've added the game.js file. The glow effect also has some flickering effect so the flickeringLayer graphics might not be needed. The filter can be adjusted to add more glow to it (fiddling with the numbers).It also has an extra alpha attributethat could be set, so that the flickering is done within the fragment shader (possible performance benefit, not sure)... the filter: Phaser.Filter.Glow = function (game) { 'use strict'; Phaser.Filter.call(this, game); this.uniforms.alpha = { type: '1f', value: 1.0 }; this.fragmentSrc = [ 'precision lowp float;', 'varying vec2 vTextureCoord;', 'varying vec4 vColor;', 'uniform sampler2D uSampler;', 'uniform float alpha;', 'void main() {', 'vec4 sum = vec4(0);', 'vec2 texcoord = vTextureCoord;', 'for(int xx = -16; xx <= 12; xx++) {', 'for(int yy = -8; yy <= 8; yy++) {', 'float dist = sqrt(float(xx*xx) + float(yy*yy));', 'float factor = 0.0;', 'if (dist == 0.0) {', 'factor = 8.0;', '} else {', 'factor = 8.0/abs(float(dist));', '}', 'sum += texture2D(uSampler, texcoord + vec2(xx, yy) * 0.004) * factor;', '}', '}', 'gl_FragColor = sum * 0.025 + texture2D(uSampler, texcoord)*alpha;', '}' ]; }; Phaser.Filter.Glow.prototype = Object.create(Phaser.Filter.prototype); Phaser.Filter.Glow.prototype.constructor = Phaser.Filter.Glow; Object.defineProperty(Phaser.Filter.Glow.prototype, 'alpha', { get: function() { return this.uniforms.alpha.value; }, set: function(value) { this.uniforms.alpha.value = value; } }); Another possibility might be to add A bitmapData copy of the lightmask on the go and apply some filter to it.. But using filters is the only idea I can think of to do this.. game.js Link to comment Share on other sites More sharing options...
Kacper Pietrzak Posted July 15, 2017 Author Share Posted July 15, 2017 I am sorry, but I couldn't get your solution working, even game.js file that you attached doesn't seem to work for me I cannot tell the difference between the gameplay from original file and the one that you've send me. Also there are couple mistakes in code snippets that you've send, could you please send me only Flaslight.js file that works for you ? And again thanks for your time, I really appreciate Link to comment Share on other sites More sharing options...
Kacper Pietrzak Posted July 15, 2017 Author Share Posted July 15, 2017 @samid737 Thank you, I had to think it through and I managed to achieve desired effect by using this glow filter that you sent me. Here is the code: https://github.com/PiGames/Project-Nostradamus/blob/dynamic-lightning/src/objects/Flashlight.js Link to comment Share on other sites More sharing options...
samid737 Posted July 15, 2017 Share Posted July 15, 2017 @Kacper Pietrzak The performance was not very well in my version after adding the filter and extra graphics layer, but you probably have it optimized looking at Flashlight.js. The effect looks nice though (dynamic lighting too)... Nice job in any case! Kacper Pietrzak 1 Link to comment Share on other sites More sharing options...
Recommended Posts