Browse Source

DigitalRain

= 9 năm trước cách đây
mục cha
commit
7f0b78c012

+ 7 - 0
proceduralTexturesLibrary/config.json

@@ -62,6 +62,13 @@
         "proceduralTextures/asciiArt/asciiart.fragment.fx"
       ],
       "output": "babylon.asciiArtPostProcess.js"
+    },
+    {
+      "file": "proceduralTextures/digitalRain/babylon.digitalRainPostProcess.ts",
+      "shaderFiles": [
+        "proceduralTextures/digitalRain/digitalrain.fragment.fx"
+      ],
+      "output": "babylon.digitalRainPostProcess.js"
     }
   ],
   "build": {

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 216 - 0
proceduralTexturesLibrary/dist/babylon.digitalRainPostProcess.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 0
proceduralTexturesLibrary/dist/babylon.digitalRainPostProcess.min.js


+ 273 - 0
proceduralTexturesLibrary/proceduralTextures/digitalRain/babylon.digitalRainPostProcess.ts

@@ -0,0 +1,273 @@
+ /// <reference path="../../../dist/preview release/babylon.d.ts"/>
+ 
+module BABYLON {
+
+    /**
+     * DigitalRainFontTexture is the helper class used to easily create your digital rain font texture.
+     * 
+     * It basically takes care rendering the font front the given font size to a texture.
+     * This is used later on in the postprocess.
+     */
+    export class DigitalRainFontTexture extends BaseTexture {
+        
+        @serialize("font")
+        private _font: string;
+
+        @serialize("text")
+        private _text: string;
+
+        private _charSize: number;
+
+        /**
+         * Gets the size of one char in the texture (each char fits in size * size space in the texture). 
+         */
+        public get charSize(): number {
+            return this._charSize;
+        }
+
+        /**
+         * Create a new instance of the Digital Rain FontTexture class
+         * @param name the name of the texture
+         * @param font the font to use, use the W3C CSS notation
+         * @param text the caracter set to use in the rendering.
+         * @param scene the scene that owns the texture
+         */
+        constructor(name: string, font: string, text: string, scene: Scene) {
+            super(scene);
+
+            this.name = name;
+            this._text == text;
+            this._font == font;
+
+            this.wrapU = Texture.CLAMP_ADDRESSMODE;
+            this.wrapV = Texture.CLAMP_ADDRESSMODE;
+            //this.anisotropicFilteringLevel = 1;
+
+            // Get the font specific info.
+            var maxCharHeight = this.getFontHeight(font);
+            var maxCharWidth = this.getFontWidth(font); 
+
+            this._charSize = Math.max(maxCharHeight.height, maxCharWidth);
+
+            // This is an approximate size, but should always be able to fit at least the maxCharCount.
+            var textureWidth = this._charSize;
+            var textureHeight = Math.ceil(this._charSize * text.length);
+
+            // Create the texture that will store the font characters.
+            this._texture = scene.getEngine().createDynamicTexture(textureWidth, textureHeight, false, Texture.NEAREST_SAMPLINGMODE);
+            //scene.getEngine().setclamp
+            var textureSize = this.getSize();
+
+            // Create a canvas with the final size: the one matching the texture.
+            var canvas = document.createElement("canvas");
+            canvas.width = textureSize.width;
+            canvas.height = textureSize.height;
+            var context = canvas.getContext("2d");
+            context.textBaseline = "top";
+            context.font = font;
+            context.fillStyle = "white";
+            context.imageSmoothingEnabled = false;
+
+            // Sets the text in the texture.
+            for (var i = 0; i < text.length; i++) {
+                context.fillText(text[i], 0, i * this._charSize - maxCharHeight.offset);
+            }        
+
+            // Flush the text in the dynamic texture.
+            this.getScene().getEngine().updateDynamicTexture(this._texture, canvas, false, true);
+        }
+
+        /**
+         * Gets the max char width of a font.
+         * @param font the font to use, use the W3C CSS notation
+         * @return the max char width
+         */
+        private getFontWidth(font: string): number {
+            var fontDraw = document.createElement("canvas");
+            var ctx = fontDraw.getContext('2d');
+            ctx.fillStyle = 'white';
+            ctx.font = font;
+
+            return ctx.measureText("W").width;
+        }
+
+        // More info here: https://videlais.com/2014/03/16/the-many-and-varied-problems-with-measuring-font-height-for-html5-canvas/
+        /**
+         * Gets the max char height of a font.
+         * @param font the font to use, use the W3C CSS notation
+         * @return the max char height
+         */
+        private getFontHeight(font: string): {height: number, offset: number} {
+            var fontDraw = document.createElement("canvas");
+            var ctx = fontDraw.getContext('2d');
+            ctx.fillRect(0, 0, fontDraw.width, fontDraw.height);
+            ctx.textBaseline = 'top';
+            ctx.fillStyle = 'white';
+            ctx.font = font;
+            ctx.fillText('jH|', 0, 0);
+            var pixels = ctx.getImageData(0, 0, fontDraw.width, fontDraw.height).data;
+            var start = -1;
+            var end = -1;
+            for (var row = 0; row < fontDraw.height; row++) {
+                for (var column = 0; column < fontDraw.width; column++) {
+                    var index = (row * fontDraw.width + column) * 4;
+                    if (pixels[index] === 0) {
+                        if (column === fontDraw.width - 1 && start !== -1) {
+                            end = row;
+                            row = fontDraw.height;
+                            break;
+                        }
+                        continue;
+                    }
+                    else {
+                        if (start === -1) {
+                            start = row;
+                        }
+                        break;
+                    }
+                }
+            }
+            return { height: (end - start)+1, offset: start-1}
+        }
+
+        /**
+         * Clones the current DigitalRainFontTexture.
+         * @return the clone of the texture.
+         */
+        public clone(): DigitalRainFontTexture {
+            return new DigitalRainFontTexture(this.name, this._font, this._text, this.getScene());
+        }
+
+        /**
+         * Parses a json object representing the texture and returns an instance of it.
+         * @param source the source JSON representation
+         * @param scene the scene to create the texture for
+         * @return the parsed texture
+         */
+        public static Parse(source: any, scene: Scene): DigitalRainFontTexture {
+            var texture = SerializationHelper.Parse(() => new DigitalRainFontTexture(source.name, source.font, source.text, scene), 
+                source, scene, null);
+
+            return texture;
+        }
+    }
+
+    /**
+     * Option available in the Digital Rain Post Process.
+     */
+    export interface IDigitalRainPostProcessOptions {
+
+        /**
+         * The font to use following the w3c font definition.
+         */
+        font?: string;
+
+        /**
+         * This defines the amount you want to mix the "tile" or caracter space colored in the digital rain.
+         * This number is defined between 0 and 1;
+         */
+        mixToTile?:number;
+
+        /**
+         * This defines the amount you want to mix the normal rendering pass in the digital rain.
+         * This number is defined between 0 and 1;
+         */
+        mixToNormal?:number;
+    }
+
+    /**
+     * DigitalRainPostProcess helps rendering everithing in digital rain.
+     * 
+     * Simmply add it to your scene and let the nerd that lives in you have fun.
+     * Example usage: var pp = new DigitalRainPostProcess("digitalRain", "20px Monospace", camera);
+     */
+    export class DigitalRainPostProcess extends PostProcess {
+
+        /**
+         * The font texture used to render the char in the post process.
+         */
+        private _digitalRainFontTexture: DigitalRainFontTexture;
+
+        /**
+         * This defines the amount you want to mix the "tile" or caracter space colored in the digital rain.
+         * This number is defined between 0 and 1;
+         */
+        public mixToTile:number = 0;
+
+        /**
+         * This defines the amount you want to mix the normal rendering pass in the digital rain.
+         * This number is defined between 0 and 1;
+         */
+        public mixToNormal:number = 0;
+
+        /**
+         * Instantiates a new Digital Rain Post Process.
+         * @param name the name to give to the postprocess
+         * @camera the camera to apply the post process to.
+         * @param options can either be the font name or an option object following the IDigitalRainPostProcessOptions format
+         */
+        constructor(name: string, camera: Camera, options?: string | IDigitalRainPostProcessOptions) {
+            super(name, 
+                'digitalrain', 
+                ['digitalRainFontInfos', 'digitalRainOptions', 'cosTimeZeroOne', 'matrixSpeed'], 
+                ['digitalRainFont'],
+                { 
+                    width: camera.getEngine().getRenderWidth(), 
+                    height: camera.getEngine().getRenderHeight()
+                }, 
+                camera, 
+                Texture.TRILINEAR_SAMPLINGMODE, 
+                camera.getEngine(), 
+                true);
+
+            // Default values.
+            var font = "15px Monospace";
+            var characterSet =  "古池や蛙飛び込む水の音ふるいけやかわずとびこむみずのおと初しぐれ猿も小蓑をほしげ也はつしぐれさるもこみのをほしげなり江戸の雨何石呑んだ時鳥えどのあめなんごくのんだほととぎす";
+
+            // Use options.
+            if (options) {
+                if (typeof(options) === "string") {
+                    font = <string>options;
+                }   
+                else {
+                    font = (<IDigitalRainPostProcessOptions>options).font || font;
+                    this.mixToTile = (<IDigitalRainPostProcessOptions>options).mixToTile || this.mixToTile;
+                    this.mixToNormal = (<IDigitalRainPostProcessOptions>options).mixToNormal || this.mixToNormal;
+                } 
+            }
+
+            this._digitalRainFontTexture = new DigitalRainFontTexture(name, font, characterSet, camera.getScene());
+            var textureSize = this._digitalRainFontTexture.getSize();
+
+            var alpha = 0.0;
+            var cosTimeZeroOne = 0.0;
+            var matrix = new Matrix();
+            for (let i = 0; i < 16; i++) {    
+                matrix.m[i] = Math.random();
+            }
+
+            this.onApply = (effect: Effect) => {
+                effect.setTexture("digitalRainFont", this._digitalRainFontTexture);
+				
+                effect.setFloat4("digitalRainFontInfos", 
+                    this._digitalRainFontTexture.charSize, 
+                    characterSet.length, 
+                    textureSize.width, 
+                    textureSize.height);
+
+                effect.setFloat4("digitalRainOptions",
+                    this.width, 
+                    this.height,
+                    this.mixToNormal, 
+                    this.mixToTile);
+                
+                effect.setMatrix("matrixSpeed",
+                    matrix);
+
+                alpha += 0.003;
+                cosTimeZeroOne = alpha;
+                effect.setFloat('cosTimeZeroOne', cosTimeZeroOne);
+            };
+        }
+    }
+} 

+ 59 - 0
proceduralTexturesLibrary/proceduralTextures/digitalRain/digitalrain.fragment.fx

@@ -0,0 +1,59 @@
+// Samplers.
+varying vec2 vUV;
+uniform sampler2D textureSampler;
+uniform sampler2D digitalRainFont;
+
+// Infos.
+uniform vec4 digitalRainFontInfos;
+uniform vec4 digitalRainOptions;
+uniform mat4 matrixSpeed;
+
+uniform float cosTimeZeroOne;
+
+// Transform color to luminance.
+float getLuminance(vec3 color)
+{
+    return clamp(dot(color, vec3(0.2126, 0.7152, 0.0722)), 0., 1.);
+}
+
+// Main functions.
+void main(void) 
+{
+    float caracterSize = digitalRainFontInfos.x;
+    float numChar = digitalRainFontInfos.y - 1.0;
+    float fontx = digitalRainFontInfos.z;
+    float fonty = digitalRainFontInfos.w;
+
+    float screenx = digitalRainOptions.x;
+    float screeny = digitalRainOptions.y;
+    float ratio = screeny / fonty;
+
+    float columnx = float(floor((gl_FragCoord.x) / caracterSize));
+    float tileX = float(floor((gl_FragCoord.x) / caracterSize)) * caracterSize / screenx;
+    float tileY = float(floor((gl_FragCoord.y) / caracterSize)) * caracterSize / screeny;
+
+    vec2 tileUV = vec2(tileX, tileY);
+    vec4 tileColor = texture2D(textureSampler, tileUV);
+    vec4 baseColor = texture2D(textureSampler, vUV);
+
+    float tileLuminance = getLuminance(tileColor.rgb);
+    
+    int st = int(mod(columnx, 4.0));
+    float speed = cosTimeZeroOne * (sin(tileX * 314.5) * 0.5 + 0.6); 
+    float x = float(mod(gl_FragCoord.x, caracterSize)) / fontx;
+    float y = float(mod(speed + gl_FragCoord.y / screeny, 1.0));
+    y *= ratio;
+
+    vec4 finalColor =  texture2D(digitalRainFont, vec2(x, 1.0 - y));
+    vec3 high = finalColor.rgb * (vec3(1.2,1.2,1.2) * pow(1.0 - y, 30.0));
+
+    finalColor.rgb *= vec3(pow(tileLuminance, 5.0), pow(tileLuminance, 1.5), pow(tileLuminance, 3.0));
+    finalColor.rgb += high;
+    finalColor.rgb = clamp(finalColor.rgb, 0., 1.);
+    finalColor.a = 1.0;
+
+    finalColor =  mix(finalColor, tileColor, digitalRainOptions.w);
+    finalColor =  mix(finalColor, baseColor, digitalRainOptions.z);
+
+    gl_FragColor = finalColor;
+}

+ 4 - 0
proceduralTexturesLibrary/test/add/addDigitalRainPP.js

@@ -0,0 +1,4 @@
+window.addDigitalRainPP = function(camera) {
+    var postProcess = new BABYLON.DigitalRainPostProcess("digitalRain", camera);
+    return postProcess;
+};

+ 27 - 5
proceduralTexturesLibrary/test/index.html

@@ -13,6 +13,7 @@
 	<script src="../dist/babylon.marbleProceduralTexture.js"></script>
 	<script src="../dist/babylon.starfieldProceduralTexture.js"></script>
 	<script src="../dist/babylon.asciiArtPostProcess.js"></script>
+	<script src="../dist/babylon.digitalRainPostProcess.js"></script>
 
 	<style>
 		html, body {
@@ -56,6 +57,7 @@
     <script src="add/addMarblePT.js"></script>
     <script src="add/addStarfieldPT.js"></script>
     <script src="add/addAsciiArtPP.js"></script>
+    <script src="add/addDigitalRainPP.js"></script>
 	<script>
 		if (BABYLON.Engine.isSupported()) {
 			var canvas = document.getElementById("renderCanvas");
@@ -66,7 +68,6 @@
 
 			var camera = new BABYLON.ArcRotateCamera("Camera", Math.PI / 2, Math.PI / 6, 50, BABYLON.Vector3.Zero(), scene);
 			camera.attachControl(canvas, true);
-			scene.postProcessesEnabled = false;
 
 			// Lights
 			var hemisphericLight = new BABYLON.HemisphericLight("hemi", new BABYLON.Vector3(0, 1, 0), scene);
@@ -194,7 +195,12 @@
                 var starfieldPT = addStarfieldPT();
 
 				// Ascii Art
-				var asciiPostProcess = addAsciiArtPP(camera);
+				var asciiArtPostProcess = addAsciiArtPP(camera);
+				camera.detachPostProcess(asciiArtPostProcess);
+
+				// Digital Rain
+				var digitalRainPostProcess = addDigitalRainPP(camera);
+				camera.detachPostProcess(digitalRainPostProcess);
 								
 				// Default to std
 				var currentTexture = diffuseTexture;
@@ -217,8 +223,10 @@
 					this.onResize();
 				}
 				
-				var resetPTOptions = function(){
-					scene.postProcessesEnabled = false;
+				var resetPTOptions = function() {
+					camera.detachPostProcess(asciiArtPostProcess);
+					camera.detachPostProcess(digitalRainPostProcess);
+					
 					//empty options
 					while(PTOptions.length > 0){
 						var option = PTOptions.pop()
@@ -415,7 +423,21 @@
 				});
 
 				gui.add(options, 'ascii').onChange(function() {
-					scene.postProcessesEnabled = !scene.postProcessesEnabled;
+					if (options.ascii) {
+						camera.attachPostProcess(asciiArtPostProcess);
+					}
+					else {
+						camera.detachPostProcess(asciiArtPostProcess);
+					}
+				});
+
+				gui.add(options, 'digitalRain').onChange(function() {
+					if (options.digitalRain) {
+						camera.attachPostProcess(digitalRainPostProcess);
+					}
+					else {
+						camera.detachPostProcess(digitalRainPostProcess);
+					}
 				});
 			});
 		}

+ 2 - 1
proceduralTexturesLibrary/test/index.js

@@ -10,7 +10,8 @@ var options = {
 	spotLight: false,
 	fog: false,
 	skybox: false,
-	ascii: false
+	ascii: false,
+	digitalRain: false
 }
 
 var registeredUIs = {};

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1092 - 311
proceduralTexturesLibrary/test/refs/babylon.max.js