Browse Source

Merge pull request #7604 from sebavan/master

SpriteMap Fix
David Catuhe 5 years ago
parent
commit
23c1678435
2 changed files with 153 additions and 149 deletions
  1. 26 31
      src/Shaders/spriteMap.fragment.fx
  2. 127 118
      src/Sprites/spriteMap.ts

+ 26 - 31
src/Shaders/spriteMap.fragment.fx

@@ -12,8 +12,6 @@ uniform vec2 spriteMapSize;
 uniform vec2 outputSize;
 uniform vec2 stageSize;
 
-uniform float maxAnimationFrames;
-
 uniform sampler2D frameMap;
 uniform sampler2D tileMaps[LAYERS];
 uniform sampler2D animationMap;
@@ -22,75 +20,72 @@ uniform vec3 colorMul;
 
 float mt;
 
-float fdStep = 1. / 4.;
+const float fdStep = 1. / 4.;
+const float aFrameSteps = 1. / MAX_ANIMATION_FRAMES;
 
 mat4 getFrameData(float frameID){
     float fX = frameID / spriteCount;
     return mat4(
-        texture(frameMap, vec2(fX, 0.), 0.),
-        texture(frameMap, vec2(fX, fdStep * 1.), 0.),
-        texture(frameMap, vec2(fX, fdStep * 2.), 0.),
+        texture2D(frameMap, vec2(fX, 0.), 0.),
+        texture2D(frameMap, vec2(fX, fdStep * 1.), 0.),
+        texture2D(frameMap, vec2(fX, fdStep * 2.), 0.),
         vec4(0.)
     );
 }
 
 void main(){
-    vec4 color = vec4(0.);    
+    vec4 color = vec4(0.);
     vec2 tileUV = fract(tUV);
     #ifdef FLIPU
         tileUV.y = 1.0 - tileUV.y;
     #endif
 
-    vec2 tileID = floor(tUV);	
+    vec2 tileID = floor(tUV);
     vec2 sheetUnits = 1. / spriteMapSize;
     float spriteUnits = 1. / spriteCount;
-    vec2 stageUnits = 1. / stageSize;        
+    vec2 stageUnits = 1. / stageSize;
     
-    for(int i = 0; i < LAYERS; i++){
+    for(int i = 0; i < LAYERS; i++) {
         float frameID;
-            switch(i){
-                #define LAYER_ID_SWITCH      
-            }        
-        
-        vec4 animationData = texture(animationMap, vec2((frameID + 0.5) / spriteCount, 0.), 0.); 
-        
-        if(animationData.y > 0.){
+        #define LAYER_ID_SWITCH
+
+        vec4 animationData = texture2D(animationMap, vec2((frameID + 0.5) / spriteCount, 0.), 0.); 
         
+        if(animationData.y > 0.) {
+
             mt = mod(time*animationData.z, 1.0);
-            float aFrameSteps = 1. / maxAnimationFrames;
-            
-            for(float f = 0.; f < maxAnimationFrames; f++){
+            for(float f = 0.; f < MAX_ANIMATION_FRAMES; f++){
                 if(animationData.y > mt){
                     frameID = animationData.x;
                     break;
                 }
                 
-                animationData = texture(animationMap, vec2((frameID + 0.5) / spriteCount, aFrameSteps * f), 0.); 
+                animationData = texture2D(animationMap, vec2((frameID + 0.5) / spriteCount, aFrameSteps * f), 0.); 
             }
         }
 
         //Get Animation Frame
-        mat4 frameData = getFrameData(frameID + 0.5);	
-        vec2 frameSize = (frameData[0].wz) / spriteMapSize;    
-        vec2 offset = frameData[0].xy * sheetUnits;	
+        mat4 frameData = getFrameData(frameID + 0.5);
+        vec2 frameSize = (frameData[0].wz) / spriteMapSize;
+        vec2 offset = frameData[0].xy * sheetUnits;
         vec2 ratio = frameData[2].xy / frameData[0].wz;
 
         //rotated
-        if(frameData[2].z == 1.){
+        if (frameData[2].z == 1.){
             tileUV.xy = tileUV.yx;
         }
 
-        if(i == 0){
-            color = texture(spriteSheet, tileUV * frameSize+offset);
+        if (i == 0){
+            color = texture2D(spriteSheet, tileUV * frameSize+offset);
         } else {
-            vec4 nc = texture(spriteSheet, tileUV * frameSize+offset);
+            vec4 nc = texture2D(spriteSheet, tileUV * frameSize+offset);
             float alpha = min(color.a + nc.a, 1.0);
             vec3 mixed = mix(color.xyz, nc.xyz, nc.a);
             color = vec4(mixed, alpha);
-        }	
+        }
     }
 
-    color.xyz*=colorMul;   
+    color.xyz *= colorMul;
     
-    gl_FragColor =  color;
+    gl_FragColor = color;
 }

+ 127 - 118
src/Sprites/spriteMap.ts

@@ -149,7 +149,7 @@ export class SpriteMap implements ISpriteMap {
         let am = this._createTileAnimationBuffer(buffer);
         this._animationMap.dispose();
         this._animationMap = am;
-        this._material.setTexture('animationMap', this._animationMap);
+        this._material.setTexture("animationMap", this._animationMap);
     }
 
     /** Scene that the SpriteMap was created in */
@@ -183,124 +183,133 @@ export class SpriteMap implements ISpriteMap {
      */
     constructor(name : string, atlasJSON: ISpriteJSONAtlas, spriteSheet: Texture, options: ISpriteMapOptions, scene : Scene) {
 
-    this.name = name;
-    this.sprites = [];
-    this.atlasJSON = atlasJSON;
-    this.sprites = this.atlasJSON['frames'];
-    this.spriteSheet = spriteSheet;
-
-    /**
-    * Run through the options and set what ever defaults are needed that where not declared.
-    */
-    this.options = options;
-    this.options.stageSize = this.options.stageSize || new Vector2(1, 1);
-    this.options.outputSize = this.options.outputSize || this.options.stageSize;
-    this.options.outputPosition = this.options.outputPosition || Vector3.Zero();
-    this.options.outputRotation = this.options.outputRotation || Vector3.Zero();
-    this.options.layerCount = this.options.layerCount || 1;
-    this.options.maxAnimationFrames = this.options.maxAnimationFrames || 0;
-    this.options.baseTile = this.options.baseTile || 0;
-    this.options.flipU = this.options.flipU || false;
-    this.options.colorMultiply = this.options.colorMultiply || new Vector3(1, 1, 1);
-
-    this._scene = scene;
-
-    this._frameMap = this._createFrameBuffer();
-
-    this._tileMaps = new Array();
-    for (let i = 0; i < this.options.layerCount; i++) {
-        this._tileMaps.push(this._createTileBuffer(null, i));
-    }
+        this.name = name;
+        this.sprites = [];
+        this.atlasJSON = atlasJSON;
+        this.sprites = this.atlasJSON["frames"];
+        this.spriteSheet = spriteSheet;
+
+        /**
+        * Run through the options and set what ever defaults are needed that where not declared.
+        */
+        this.options = options;
+        options.stageSize = options.stageSize || new Vector2(1, 1);
+        options.outputSize = options.outputSize || options.stageSize;
+        options.outputPosition = options.outputPosition || Vector3.Zero();
+        options.outputRotation = options.outputRotation || Vector3.Zero();
+        options.layerCount = options.layerCount || 1;
+        options.maxAnimationFrames = options.maxAnimationFrames || 0;
+        options.baseTile = options.baseTile || 0;
+        options.flipU = options.flipU || false;
+        options.colorMultiply = options.colorMultiply || new Vector3(1, 1, 1);
+
+        this._scene = scene;
+
+        this._frameMap = this._createFrameBuffer();
+
+        this._tileMaps = new Array();
+        for (let i = 0; i < options.layerCount; i++) {
+            this._tileMaps.push(this._createTileBuffer(null, i));
+        }
 
-    this._animationMap = this._createTileAnimationBuffer(null);
+        this._animationMap = this._createTileAnimationBuffer(null);
 
-    let defines = [];
-    defines.push("#define LAYERS " + this.options.layerCount);
+        let defines = [];
+        defines.push("#define LAYERS " + options.layerCount);
 
-    if (this.options.flipU) {
-        defines.push("#define FLIPU");
-    }
+        if (options.flipU) {
+            defines.push("#define FLIPU");
+        }
 
-    let shaderString: string = Effect.ShadersStore['spriteMapPixelShader'];
-    let layerSampleString: string = '';
+        defines.push(`#define MAX_ANIMATION_FRAMES ${options.maxAnimationFrames}.0`);
 
-    for (let i = 0; i < this.options.layerCount; i++) {
-        layerSampleString += 'case ' + i + ' : frameID = texture(tileMaps[' + i + '], (tileID + 0.5) / stageSize, 0.).x;';
-        layerSampleString += 'break;';
-    }
+        let shaderString: string = Effect.ShadersStore["spriteMapPixelShader"];
 
-    Effect.ShadersStore['spriteMap' + this.name + 'PixelShader'] = shaderString.replace('#define LAYER_ID_SWITCH',  layerSampleString);
-
-    this._material = new ShaderMaterial("spriteMap:" + this.name, this._scene, {
-        vertex: "spriteMap",
-        fragment: "spriteMap" + this.name,
-    }, {
-        defines,
-        attributes: ["position", "normal", "uv"],
-        uniforms: [
-            "worldViewProjection",
-            "time",
-            'stageSize',
-            'outputSize',
-            'spriteMapSize',
-            'spriteCount',
-            'time',
-            'maxAnimationFrames',
-            'colorMul',
-            'mousePosition',
-            'curTile',
-            'flipU'
-        ],
-        samplers: [
-           "spriteSheet", "frameMap", "tileMaps", "animationMap"
-        ],
-        needAlphaBlending: true
-    });
-
-    this._time = 0;
-
-    this._material.setFloat('spriteCount', this.spriteCount);
-    this._material.setFloat('maxAnimationFrames', this.options.maxAnimationFrames);
-    this._material.setVector2('stageSize', this.options.stageSize);
-    this._material.setVector2('outputSize', this.options.outputSize);
-    this._material.setTexture('spriteSheet', this.spriteSheet);
-    this._material.setVector2('spriteMapSize', new Vector2(1, 1));
-    this._material.setVector3('colorMul', this.options.colorMultiply);
-
-    let tickSave = 0;
-
-    const bindSpriteTexture = () => {
-        if ((this.spriteSheet) && this.spriteSheet.isReady()) {
-            if (this.spriteSheet._texture) {
-                this._material.setVector2('spriteMapSize', new Vector2(this.spriteSheet._texture.baseWidth || 1, this.spriteSheet._texture.baseHeight || 1));
-                return;
+        let layerSampleString: string;
+        if (this._scene.getEngine().webGLVersion === 1) {
+            layerSampleString = "";
+            for (let i = 0; i < options.layerCount; i++) {
+                layerSampleString += `if (${i} == i) { frameID = texture2D(tileMaps[${i}], (tileID + 0.5) / stageSize, 0.).x; }`;
             }
         }
-        if (tickSave < 100) {
-            setTimeout(() => {tickSave++; bindSpriteTexture(); }, 100);
+        else {
+            layerSampleString = "switch(i) {";
+            for (let i = 0; i < options.layerCount; i++) {
+                layerSampleString += "case " + i + " : frameID = texture(tileMaps[" + i + "], (tileID + 0.5) / stageSize, 0.).x;";
+                layerSampleString += "break;";
+            }
+            layerSampleString += "}";
         }
-    };
 
-    bindSpriteTexture();
+        Effect.ShadersStore["spriteMap" + this.name + "PixelShader"] = shaderString.replace("#define LAYER_ID_SWITCH",  layerSampleString);
+
+        this._material = new ShaderMaterial("spriteMap:" + this.name, this._scene, {
+            vertex: "spriteMap",
+            fragment: "spriteMap" + this.name,
+        }, {
+            defines,
+            attributes: ["position", "normal", "uv"],
+            uniforms: [
+                "worldViewProjection",
+                "time",
+                "stageSize",
+                "outputSize",
+                "spriteMapSize",
+                "spriteCount",
+                "time",
+                "colorMul",
+                "mousePosition",
+                "curTile",
+                "flipU"
+            ],
+            samplers: [
+            "spriteSheet", "frameMap", "tileMaps", "animationMap"
+            ],
+            needAlphaBlending: true
+        });
 
-    this._material.setVector3('colorMul', this.options.colorMultiply);
-    this._material.setTexture("frameMap", this._frameMap);
-    this._material.setTextureArray("tileMaps", this._tileMaps);
-    this._material.setTexture("animationMap", this._animationMap);
-    this._material.setFloat('time', this._time);
+        this._time = 0;
 
-    this._output = Mesh.CreatePlane(name + ":output", 1, scene, true);
-    this._output.scaling.x = this.options.outputSize.x;
-    this._output.scaling.y = this.options.outputSize.y;
+        this._material.setFloat("spriteCount", this.spriteCount);
+        this._material.setVector2("stageSize", options.stageSize);
+        this._material.setVector2("outputSize", options.outputSize);
+        this._material.setTexture("spriteSheet", this.spriteSheet);
+        this._material.setVector2("spriteMapSize", new Vector2(1, 1));
+        this._material.setVector3("colorMul", options.colorMultiply);
 
-    let obfunction = () => {
-        this._time += this._scene.getEngine().getDeltaTime();
-        this._material.setFloat('time', this._time);
-    };
+        let tickSave = 0;
 
-    this._scene.onBeforeRenderObservable.add(obfunction);
-    this._output.material = this._material;
+        const bindSpriteTexture = () => {
+            if ((this.spriteSheet) && this.spriteSheet.isReady()) {
+                if (this.spriteSheet._texture) {
+                    this._material.setVector2("spriteMapSize", new Vector2(this.spriteSheet._texture.baseWidth || 1, this.spriteSheet._texture.baseHeight || 1));
+                    return;
+                }
+            }
+            if (tickSave < 100) {
+                setTimeout(() => {tickSave++; bindSpriteTexture(); }, 100);
+            }
+        };
+
+        bindSpriteTexture();
+
+        this._material.setVector3("colorMul", options.colorMultiply);
+        this._material.setTexture("frameMap", this._frameMap);
+        this._material.setTextureArray("tileMaps", this._tileMaps);
+        this._material.setTexture("animationMap", this._animationMap);
+        this._material.setFloat("time", this._time);
+
+        this._output = Mesh.CreatePlane(name + ":output", 1, scene, true);
+        this._output.scaling.x = options.outputSize.x;
+        this._output.scaling.y = options.outputSize.y;
+
+        let obfunction = () => {
+            this._time += this._scene.getEngine().getDeltaTime();
+            this._material.setFloat("time", this._time);
+        };
 
+        this._scene.onBeforeRenderObservable.add(obfunction);
+        this._output.material = this._material;
     }
 
     /**
@@ -359,15 +368,15 @@ export class SpriteMap implements ISpriteMap {
             data.push(0, 0, 0, 0); //frame
             data.push(0, 0, 0, 0); //spriteSourceSize
             data.push(0, 0, 0, 0); //sourceSize, rotated, trimmed
-            data.push(0, 0, 0, 0); //Keep it pow2 cause I'm cool like that... it helps with sampling accuracy as well. Plus then we have 4 other parameters for future stuff.
+            data.push(0, 0, 0, 0); //Keep it pow2 cause I"m cool like that... it helps with sampling accuracy as well. Plus then we have 4 other parameters for future stuff.
         }
         //Second Pass
         for (let i = 0; i < this.spriteCount; i++) {
-            let f = this.sprites[i]['frame'];
-            let sss = this.sprites[i]['spriteSourceSize'];
-            let ss = this.sprites[i]['sourceSize'];
-            let r = (this.sprites[i]['rotated']) ? 1 : 0;
-            let t = (this.sprites[i]['trimmed']) ? 1 : 0;
+            let f = this.sprites[i]["frame"];
+            let sss = this.sprites[i]["spriteSourceSize"];
+            let ss = this.sprites[i]["sourceSize"];
+            let r = (this.sprites[i]["rotated"]) ? 1 : 0;
+            let t = (this.sprites[i]["trimmed"]) ? 1 : 0;
 
             //frame
             data[i * 4] = f.x;
@@ -543,16 +552,16 @@ export class SpriteMap implements ISpriteMap {
     * Exports the .tilemaps file
     */
     public saveTileMaps(): void {
-        let maps = '';
+        let maps = "";
         for (var i = 0; i < this._tileMaps.length; i++) {
-            if (i > 0) {maps += '\n\r'; }
+            if (i > 0) {maps += "\n\r"; }
 
             maps += this._tileMaps[i]!._texture!._bufferView!.toString();
         }
-        var hiddenElement = document.createElement('a');
-        hiddenElement.href = 'data:octet/stream;charset=utf-8,' + encodeURI(maps);
-        hiddenElement.target = '_blank';
-        hiddenElement.download = this.name + '.tilemaps';
+        var hiddenElement = document.createElement("a");
+        hiddenElement.href = "data:octet/stream;charset=utf-8," + encodeURI(maps);
+        hiddenElement.target = "_blank";
+        hiddenElement.download = this.name + ".tilemaps";
         hiddenElement.click();
         hiddenElement.remove();
     }
@@ -569,9 +578,9 @@ export class SpriteMap implements ISpriteMap {
 
         xhr.onload = () =>
         {
-            let data = xhr.response.split('\n\r');
+            let data = xhr.response.split("\n\r");
             for (let i = 0; i < _lc; i++) {
-                let d = (data[i].split(',')).map(Number);
+                let d = (data[i].split(",")).map(Number);
                 let t = this._createTileBuffer(d);
                 this._tileMaps[i].dispose();
                 this._tileMaps[i] = t;