title category import { OrbitControl } from "@oasis-engine/controls" ; import * as dat from "dat.gui" ; import { AssetType , BlendFactor , Camera , CullMode , Engine , Material , RenderQueueType , Script , Shader , Sprite , SpriteRenderer , Texture2D , WebGLEngine } from "oasis-engine" ; init ( ) ; function init ( ) { const engine = new WebGLEngine ( "canvas" ) ; engine . canvas . resizeByClientSize ( ) ; const rootEntity = engine . sceneManager . activeScene . createRootEntity ( ) ; const cameraEntity = rootEntity . createChild ( "Camera" ) ; cameraEntity . transform . setPosition ( 0 , 0 , 12 ) ; cameraEntity . addComponent ( Camera ) ; cameraEntity . addComponent ( OrbitControl ) ; engine . resourceManager . load ( { url : "https://gw.alipayobjects.com/mdn/rms_7c464e/afts/img/A*5wypQ5JyDLkAAAAAAAAAAAAAARQnAQ" , type : AssetType . Texture2D } ) . then ( ( texture ) => { const spriteEntity = rootEntity . createChild ( "GlitchSprite" ) ; const material = addCustomMaterial ( engine ) ; const renderer = spriteEntity . addComponent ( SpriteRenderer ) ; renderer . sprite = new Sprite ( engine , texture ) ; renderer . setMaterial ( material ) ; const script = spriteEntity . addComponent ( AnimateScript ) ; script . material = material ; script . time = 0.0 ; addDataGUI ( script . material , script ) ; } ) ; engine . run ( ) ; } function addCustomMaterial ( engine ) { const material = new Material ( engine , Shader . find ( "SpriteGlitchRGBSplit" ) ) ; const renderState = material . renderState ; const target = renderState . blendState . targetBlendState ; target . enabled = true ; target . sourceColorBlendFactor = BlendFactor . SourceAlpha ; target . destinationColorBlendFactor = BlendFactor . OneMinusSourceAlpha ; target . sourceAlphaBlendFactor = BlendFactor . One ; target . destinationAlphaBlendFactor = BlendFactor . OneMinusSourceAlpha ; renderState . depthState . writeEnabled = false ; renderState . rasterState . cullMode = CullMode . Off ; material . renderQueueType = RenderQueueType . Transparent ; const { shaderData } = material ; shaderData . setFloat ( "u_time" , 0.0 ) ; shaderData . setFloat ( "u_indensity" , 0.5 ) ; return material ; } /**
 * Add data GUI.
 */ function addDataGUI ( material , animationScript ) { const { shaderData } = material ; const gui = new dat . GUI ( ) ; const guiData = { indensity : 0.5 , reset : ( ) => { guiData . indensity = 0.5 ; shaderData . setFloat ( "u_indensity" , 0.5 ) ; shaderData . setFloat ( "u_time" , 0.0 ) ; animationScript . time = 0 ; } } ; gui . add ( guiData , "indensity" , 0.0 , 1.0 , 0.01 ) . onChange ( ( value ) => { shaderData . setFloat ( "u_indensity" , value ) ; shaderData . setFloat ( "u_time" , 0.0 ) ; animationScript . time = 0 ; } ) . listen ( ) ; gui . add ( guiData , "reset" ) . name ( "重置" ) ; return guiData ; } class AnimateScript extends Script { material : Material ; time : number = 0 ; param deltaTime onUpdate ( deltaTime ) { this . time += deltaTime * 0.1 ; this . time = this . time % 1 ; this . material . shaderData . setFloat ( "u_time" , this . time ) ; } } const spriteVertShader = `
  uniform mat4 u_VPMat;

  attribute vec3 POSITION;
  attribute vec2 TEXCOORD_0;
  attribute vec4 COLOR_0;

  varying vec4 v_color;
  varying vec2 v_uv;

  void main()
  {
    gl_Position = u_VPMat * vec4(POSITION, 1.0);
    v_color = COLOR_0;
    v_uv = TEXCOORD_0;
  }
` ; const spriteFragmentShader = `
  uniform sampler2D u_spriteTexture;
  uniform float u_time;
  uniform float u_indensity;

  varying vec2 v_uv;
  varying vec4 v_color;

  float randomNoise(float time) {
    return fract(sin(dot(vec2(time, 2), vec2(12.9898, 78.233))));
  }

  void main() {
    float splitAmount = u_indensity * randomNoise(u_time);

    vec4 normalColor = texture2D(u_spriteTexture, v_uv);
    float r = texture2D(u_spriteTexture, vec2(v_uv.x + splitAmount, v_uv.y)).r;
    float b = texture2D(u_spriteTexture, vec2(v_uv.x - splitAmount, v_uv.y)).b;
    gl_FragColor = vec4(r, normalColor.g, b, normalColor.a) * v_color;
  }
` ; Shader . create ( "SpriteGlitchRGBSplit" , spriteVertShader , spriteFragmentShader ) ;