diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 8c0b9057d1d..eabcdd2627b 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -22,6 +22,7 @@ import AbilityBar from './ui/ability-bar'; import { BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, applyAbAttrs, initAbilities } from './data/ability'; import Battle from './battle'; import { GameMode } from './game-mode'; +import SpritePipeline from './pipelines/sprite'; const enableAuto = true; const quickStart = false; @@ -87,7 +88,7 @@ export default class BattleScene extends Phaser.Scene { public uiContainer: Phaser.GameObjects.Container; public ui: UI; - //public spritePipeline: SpritePipeline; + public spritePipeline: SpritePipeline; private bgm: Phaser.Sound.BaseSound; private bgmResumeTimer: Phaser.Time.TimerEvent; @@ -295,7 +296,8 @@ export default class BattleScene extends Phaser.Scene { this.load.setBaseURL(); - //this.spritePipeline = (this.renderer as Phaser.Renderer.WebGL.WebGLRenderer).pipelines.get('Sprite') as SpritePipeline; + this.spritePipeline = new SpritePipeline(this.game); + (this.renderer as Phaser.Renderer.WebGL.WebGLRenderer).pipelines.add('Sprite', this.spritePipeline); this.time.delayedCall(20, () => this.launchBattle()); } diff --git a/src/data/battle-anims.ts b/src/data/battle-anims.ts index 516db0492bd..ac6f3613df6 100644 --- a/src/data/battle-anims.ts +++ b/src/data/battle-anims.ts @@ -666,6 +666,7 @@ export abstract class BattleAnim { const spriteSource = isUser ? userSprite : targetSprite; let sprite: Phaser.GameObjects.Sprite; sprite = scene.add.sprite(0, 0, spriteSource.texture, spriteSource.frame.name); + sprite.setPipeline(scene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ] }); spriteSource.on('animationupdate', (_anim, frame) => sprite.setFrame(frame.textureFrame)); scene.field.add(sprite); sprites.push(sprite); @@ -682,6 +683,7 @@ export abstract class BattleAnim { pokemonSprite.setData('locked', frame.locked); pokemonSprite.setAlpha(frame.opacity / 255); + pokemonSprite.pipelineData['tone'] = frame.tone; pokemonSprite.setVisible(frame.visible && (isUser ? user.visible : target.visible)); pokemonSprite.setBlendMode(frame.blendType === AnimBlendType.NORMAL ? Phaser.BlendModes.NORMAL : frame.blendType === AnimBlendType.ADD ? Phaser.BlendModes.ADD : Phaser.BlendModes.DIFFERENCE); } else { @@ -778,10 +780,12 @@ export abstract class BattleAnim { userSprite.setPosition(0, 0); userSprite.setScale(1); userSprite.setAlpha(1); + userSprite.pipelineData['tone'] = [ 0.0, 0.0, 0.0, 0.0 ]; userSprite.setAngle(0); targetSprite.setPosition(0, 0); targetSprite.setScale(1); targetSprite.setAlpha(1); + targetSprite.pipelineData['tone'] = [ 0.0, 0.0, 0.0, 0.0 ]; targetSprite.setAngle(0); userSprite.setVisible(true); targetSprite.setVisible(true); diff --git a/src/main.ts b/src/main.ts index d991cc36051..3e084d667ec 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,6 +1,6 @@ import Phaser from 'phaser'; import BattleScene from './battle-scene'; -//import SpritePipeline from './pipelines/sprite'; +import SpritePipeline from './pipelines/sprite'; const config: Phaser.Types.Core.GameConfig = { type: Phaser.WEBGL, @@ -11,7 +11,6 @@ const config: Phaser.Types.Core.GameConfig = { mode: Phaser.Scale.FIT }, pixelArt: true, - //pipeline: { 'Sprite': SpritePipeline }, scene: [ BattleScene ] }; diff --git a/src/pipelines/sprite.ts b/src/pipelines/sprite.ts new file mode 100644 index 00000000000..b8c98f448c0 --- /dev/null +++ b/src/pipelines/sprite.ts @@ -0,0 +1,94 @@ +const spriteFragShader = ` +#define SHADER_NAME PHASER_MULTI_FS + +#ifdef GL_FRAGMENT_PRECISION_HIGH +precision highp float; +#else +precision mediump float; +#endif + +uniform sampler2D uMainSampler[%count%]; + +varying vec2 outTexCoord; +varying float outTexId; +varying float outTintEffect; +varying vec4 outTint; + +uniform vec4 tone; + +const vec3 lumaF = vec3(.299, .587, .114); + +void main () +{ + vec4 texture; + + %forloop% + + vec4 texel = vec4(outTint.bgr * outTint.a, outTint.a); + + // Multiply texture tint + vec4 color = texture * texel; + + if (outTintEffect == 1.0) + { + // Solid color + texture alpha + color.rgb = mix(texture.rgb, outTint.bgr * outTint.a, texture.a); + } + else if (outTintEffect == 2.0) + { + // Solid color, no texture + color = texel; + } + + /* Apply gray */ + float luma = dot(color.rgb, lumaF); + color.rgb = mix(color.rgb, vec3(luma), tone.w); + + /* Apply tone */ + color.rgb += tone.rgb * (color.a / 255.0); + + gl_FragColor = color; +} +`; + +export default class SpritePipeline extends Phaser.Renderer.WebGL.Pipelines.MultiPipeline +{ + private _tone: number[]; + + constructor(game: Phaser.Game) { + super({ + game: game, + name: 'sprite', + fragShader: spriteFragShader + }); + + this._tone = [ 0, 0, 0, 0 ]; + } + + onPreRender(): void { + this.set4f('tone', this._tone[0], this._tone[1], this._tone[2], this._tone[3]); + } + + onBind(gameObject: Phaser.GameObjects.GameObject): void { + super.onBind(); + + const data = (gameObject as Phaser.GameObjects.Sprite).pipelineData; + const tone = data['tone'] as number[]; + + this.set4f('tone', tone[0], tone[1], tone[2], tone[3]); + } + + onBatch(gameObject: Phaser.GameObjects.GameObject): void { + if (gameObject) { + this.flush(); + } + } + + get tone(): number[] { + return this._tone; + } + + set tone(value: number[]) { + this._tone = value; + } +} \ No newline at end of file diff --git a/src/pokemon.ts b/src/pokemon.ts index 032607aaf8e..90b92092562 100644 --- a/src/pokemon.ts +++ b/src/pokemon.ts @@ -26,6 +26,7 @@ import { Biome } from './data/biome'; import { Abilities, Ability, BattleStatMultiplierAbAttr, BlockCritAbAttr, NonSuperEffectiveImmunityAbAttr, PreApplyBattlerTagAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, abilities, applyBattleStatMultiplierAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs } from './data/ability'; import PokemonData from './system/pokemon-data'; import { BattlerIndex } from './battle'; +import SpritePipeline from './pipelines/sprite'; export enum FieldPosition { CENTER, @@ -144,8 +145,6 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (!species.isObtainable()) this.shiny = false; - //this.setPipeline(this.scene).spritePipeline); - this.calculateStats(); this.fieldPosition = FieldPosition.CENTER; @@ -157,6 +156,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const getSprite = () => { const ret = this.scene.add.sprite(0, 0, `pkmn__${this.isPlayer() ? 'back__' : ''}sub`); ret.setOrigin(0.5, 1); + ret.setPipeline(this.scene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ] }); return ret; };