Advertisement
KpoKec

posteffect-outline.js

Jul 30th, 2020
1,372
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // --------------- POST EFFECT DEFINITION --------------- //
  2. Object.assign(pc, function () {
  3.  
  4.     /**
  5.      * @class
  6.      * @name pc.OutlineEffect
  7.      * @classdesc Applies an outline effect on input render target
  8.      * @description Creates new instance of the post effect.
  9.      * @augments pc.PostEffect
  10.      * @param {pc.GraphicsDevice} graphicsDevice - The graphics device of the application.
  11.      * @property {pc.Texture} texture The outline texture to use.
  12.      * @property {pc.Color} color The outline color.
  13.      */
  14.    
  15.     var OutlineEffect = function (graphicsDevice, thickness) {
  16.         pc.PostEffect.call(this, graphicsDevice);
  17.  
  18.         this.copyShader = new pc.Shader(graphicsDevice, {
  19.             attributes: {
  20.                 aPosition: pc.SEMANTIC_POSITION
  21.             },
  22.             vshader: [
  23.                 "attribute vec2 aPosition;",
  24.                 "",
  25.                 "varying vec2 vUv0;",
  26.                 "",
  27.                 "void main(void)",
  28.                 "{",
  29.                 "    gl_Position = vec4(aPosition, 0.0, 1.0);",
  30.                 "    vUv0 = (aPosition.xy + 1.0) * 0.5;",
  31.                 "}"
  32.             ].join("\n"),
  33.             fshader: [
  34.                 "precision " + graphicsDevice.precision + " float;",
  35.                 "varying vec2 vUv0;",
  36.                 "uniform sampler2D uColorBuffer;",
  37.                 "",
  38.                 "void main(void) {",
  39.                 "   gl_FragColor = texture2D(uColorBuffer, vUv0);",
  40.                 "}"
  41.             ].join("\n")
  42.         });
  43.        
  44.         this.shader = new pc.Shader(graphicsDevice, {
  45.             attributes: {
  46.                 aPosition: pc.SEMANTIC_POSITION
  47.             },
  48.             vshader: [
  49.                 "attribute vec2 aPosition;",
  50.                 "",
  51.                 "varying vec2 vUv0;",
  52.                 "",
  53.                 "void main(void)",
  54.                 "{",
  55.                 "    gl_Position = vec4(aPosition, 0.0, 1.0);",
  56.                 "    vUv0 = (aPosition.xy + 1.0) * 0.5;",
  57.                 "}"
  58.             ].join("\n"),
  59.             fshader: [
  60.                 "precision " + graphicsDevice.precision + " float;",
  61.                 "",
  62.                 "uniform float uWidth;",
  63.                 "uniform float uHeight;",
  64.                 "uniform vec4 uOutlineCol;",
  65.                 "uniform sampler2D uColorBuffer;",
  66.                 "uniform sampler2D uOutlineTex;",
  67.                 "uniform sampler2D uOutlineTex2;",
  68.                 "uniform float uOutlineStrength;",
  69.                 "",
  70.                 "varying vec2 vUv0;",
  71.                 "",
  72.                 "void main(void)",
  73.                 "{",
  74.                 "    vec4 texel1 = texture2D(uColorBuffer, vUv0);",
  75.                 "    float sample0 = texture2D(uOutlineTex, vUv0).a;",
  76.                 "    float sample1 = texture2D(uOutlineTex2, vUv0).a;",
  77.                 "    float outline = step(sample1, 0.999) * sample0;",
  78.                 "    outline = clamp(outline * uOutlineStrength, 0.0, 1.0);",
  79.                 "    gl_FragColor = mix(texel1, uOutlineCol, outline * uOutlineCol.a);",
  80.                 "}"
  81.             ].join("\n")
  82.         });
  83.  
  84.         var attributes = {
  85.             aPosition: pc.SEMANTIC_POSITION
  86.         };
  87.         var passThroughVert = [
  88.             "attribute vec2 aPosition;",
  89.             "",
  90.             "varying vec2 vUv0;",
  91.             "",
  92.             "void main(void)",
  93.             "{",
  94.             "    gl_Position = vec4(aPosition, 0.0, 1.0);",
  95.             "    vUv0 = (aPosition + 1.0) * 0.5;",
  96.             "}"
  97.         ].join("\n");
  98.         var blurXFrag = [
  99.             "precision " + graphicsDevice.precision + " float;",
  100.             "varying vec2 vUv0;",
  101.             "uniform float uBlur;",
  102.             "uniform sampler2D uColorBuffer;",
  103.             "",
  104.             "void main(void) {",
  105.             "   vec4 sum = vec4(0.0);",
  106.             "",
  107.             "   sum += texture2D(uColorBuffer, vec2(vUv0.x - 4.0 * uBlur, vUv0.y)) * 0.05;",
  108.             "   sum += texture2D(uColorBuffer, vec2(vUv0.x - 3.0 * uBlur, vUv0.y)) * 0.09;",
  109.             "   sum += texture2D(uColorBuffer, vec2(vUv0.x - 2.0 * uBlur, vUv0.y)) * 0.12;",
  110.             "   sum += texture2D(uColorBuffer, vec2(vUv0.x - uBlur, vUv0.y)) * 0.15;",
  111.             "   sum += texture2D(uColorBuffer, vec2(vUv0.x, vUv0.y)) * 0.16;",
  112.             "   sum += texture2D(uColorBuffer, vec2(vUv0.x + uBlur, vUv0.y)) * 0.15;",
  113.             "   sum += texture2D(uColorBuffer, vec2(vUv0.x + 2.0 * uBlur, vUv0.y)) * 0.12;",
  114.             "   sum += texture2D(uColorBuffer, vec2(vUv0.x + 3.0 * uBlur, vUv0.y)) * 0.09;",
  115.             "   sum += texture2D(uColorBuffer, vec2(vUv0.x + 4.0 * uBlur, vUv0.y)) * 0.05;",
  116.             "",
  117.             "   gl_FragColor = vec4(pow(sum.a, 0.90));",
  118.             //"   gl_FragColor = sum;",
  119.             "}"
  120.         ].join("\n");
  121.         var blurYFrag = [
  122.             "precision " + graphicsDevice.precision + " float;",
  123.             "varying vec2 vUv0;",
  124.             "uniform float uBlur;",
  125.             "uniform sampler2D uColorBuffer;",
  126.             "",
  127.             "void main(void) {",
  128.             "   vec4 sum = vec4(0.0);",
  129.             "",
  130.             "   sum += texture2D(uColorBuffer, vec2(vUv0.x, vUv0.y - 4.0 * uBlur)) * 0.05;",
  131.             "   sum += texture2D(uColorBuffer, vec2(vUv0.x, vUv0.y - 3.0 * uBlur)) * 0.09;",
  132.             "   sum += texture2D(uColorBuffer, vec2(vUv0.x, vUv0.y - 2.0 * uBlur)) * 0.12;",
  133.             "   sum += texture2D(uColorBuffer, vec2(vUv0.x, vUv0.y - uBlur)) * 0.15;",
  134.             "   sum += texture2D(uColorBuffer, vec2(vUv0.x, vUv0.y)) * 0.16;",
  135.             "   sum += texture2D(uColorBuffer, vec2(vUv0.x, vUv0.y + uBlur)) * 0.15;",
  136.             "   sum += texture2D(uColorBuffer, vec2(vUv0.x, vUv0.y + 2.0 * uBlur)) * 0.12;",
  137.             "   sum += texture2D(uColorBuffer, vec2(vUv0.x, vUv0.y + 3.0 * uBlur)) * 0.09;",
  138.             "   sum += texture2D(uColorBuffer, vec2(vUv0.x, vUv0.y + 4.0 * uBlur)) * 0.05;",
  139.             "",
  140.             "   gl_FragColor = vec4(pow(sum.a, 0.90));",
  141.             //"   gl_FragColor = sum;",
  142.             "}"
  143.         ].join("\n");
  144.         this.blurXShader = new pc.Shader(graphicsDevice, {
  145.             attributes: attributes,
  146.             vshader: passThroughVert,
  147.             fshader: blurXFrag
  148.         });
  149.         this.blurYShader = new pc.Shader(graphicsDevice, {
  150.             attributes: attributes,
  151.             vshader: passThroughVert,
  152.             fshader: blurYFrag
  153.         });
  154.        
  155.         // Render targets
  156.         this.width = graphicsDevice.width;
  157.         this.height = graphicsDevice.height;
  158.        
  159.         this.blurYAmount = 1/512;
  160.         this.blurXAmount = 1/512 * (this.height / this.width);
  161.  
  162.         this.targets = [];
  163.         for (var i = 0; i < 3; i++) {
  164.             var colorBuffer = new pc.Texture(graphicsDevice, {
  165.                 format: pc.PIXELFORMAT_R8_G8_B8_A8,
  166.                 width: this.width / 2,
  167.                 height: this.height / 2
  168.             });
  169.             colorBuffer.minFilter = pc.FILTER_LINEAR;
  170.             colorBuffer.magFilter = pc.FILTER_LINEAR;
  171.             colorBuffer.addressU = pc.ADDRESS_CLAMP_TO_EDGE;
  172.             colorBuffer.addressV = pc.ADDRESS_CLAMP_TO_EDGE;
  173.             var target = new pc.RenderTarget(graphicsDevice, colorBuffer, { depth: false });
  174.  
  175.             this.targets.push(target);
  176.         }
  177.  
  178.         // Uniforms
  179.         this.color = new pc.Color(1, 1, 1, 1);
  180.         this.texture = new pc.Texture(graphicsDevice);
  181.         this.texture.name = 'pe-outline';
  182.         this.blur = 2.0;
  183.         this.power = 1.0;
  184.     };
  185.  
  186.     OutlineEffect.prototype = Object.create(pc.PostEffect.prototype);
  187.     OutlineEffect.prototype.constructor = OutlineEffect;
  188.  
  189.     OutlineEffect.prototype.set_power = function(value) {
  190.         this.power = value;
  191.     };
  192.  
  193.     OutlineEffect.prototype.set_blur = function(value) {
  194.         this.blur = value;
  195.     };
  196.  
  197.     OutlineEffect.prototype.set_color = function(value) {
  198.         this.color = value;
  199.     };
  200.  
  201.     Object.assign(OutlineEffect.prototype, {
  202.         render: function (inputTarget, outputTarget, rect) {
  203.             var device = this.device;
  204.             var scope = device.scope;
  205.            
  206.             scope.resolve("uColorBuffer").setValue(this.texture);
  207.             pc.drawFullscreenQuad(device, this.targets[0], this.vertexBuffer, this.blurXShader);
  208.            
  209.             scope.resolve("uBlur").setValue(this.blurXAmount * this.blur);
  210.             scope.resolve("uColorBuffer").setValue(this.targets[0]);
  211.             pc.drawFullscreenQuad(device, this.targets[1], this.vertexBuffer, this.blurXShader);
  212.  
  213.             scope.resolve("uBlur").setValue(this.blurYAmount * this.blur);
  214.             scope.resolve("uColorBuffer").setValue(this.targets[1].colorBuffer);
  215.             pc.drawFullscreenQuad(device, this.targets[2], this.vertexBuffer, this.blurYShader);
  216.  
  217.             scope.resolve("uWidth").setValue(inputTarget.width);
  218.             scope.resolve("uHeight").setValue(inputTarget.height);
  219.             scope.resolve("uOutlineCol").setValue([this.color.r, this.color.g, this.color.b, this.color.a]);
  220.             scope.resolve("uColorBuffer").setValue(inputTarget.colorBuffer);
  221.             scope.resolve("uOutlineTex").setValue(this.targets[2].colorBuffer);
  222.             scope.resolve("uOutlineTex2").setValue(this.texture); //
  223.             scope.resolve("uOutlineStrength").setValue(this.power);
  224.             pc.drawFullscreenQuad(device, outputTarget, this.vertexBuffer, this.shader, rect);
  225.         }
  226.     });
  227.  
  228.     return {
  229.         OutlineEffect: OutlineEffect
  230.     };
  231. }());
  232.  
  233. // ----------------- SCRIPT DEFINITION ------------------ //
  234. var Outline = pc.createScript('outline');
  235.  
  236. Outline.attributes.add('color', { type: 'rgb', default: [0.5, 0.5, 0.5, 1], title: 'Color' });
  237. Outline.attributes.add('texture', { type: 'asset', assetType: 'texture', title: 'Texture' });
  238. Outline.attributes.add('power', { type:'number'});
  239. Outline.attributes.add('blur', { type:'number'});
  240.  
  241. Outline.prototype.initialize = function () {
  242.     this.effect = new pc.OutlineEffect(this.app.graphicsDevice);
  243.     this.effect.color = this.color;
  244.     this.effect.texture = this.texture.resource;
  245.  
  246.     var queue = this.entity.camera.postEffects;
  247.  
  248.     queue.addEffect(this.effect);
  249.  
  250.     this.on('state', function (enabled) {
  251.         if (enabled) {
  252.             queue.addEffect(this.effect);
  253.         } else {
  254.             queue.removeEffect(this.effect);
  255.         }
  256.     });
  257.  
  258.     this.on('destroy', function () {
  259.         queue.removeEffect(this.effect);
  260.     });
  261.  
  262.     this.on('attr:color', function (value) {
  263.         this.effect.set_color(value);
  264.     }, this);
  265.  
  266.     this.on('attr:texture', function (value) {
  267.         this.effect.texture = value ? value.resource : null;
  268.     }, this);
  269.    
  270.     this.on('attr:power', function(value) {
  271.         this.effect.set_power(value);
  272.     }, this);
  273.    
  274.     this.on('attr:blur', function(value) {
  275.         this.effect.set_blur(value);
  276.     }, this);
  277.  
  278. };
  279.  
  280.  
  281.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement