<template>
  <div class="test">
    <div id="glContainner"></div>
    <div id="uiContainner">
      <div class="block">
        <span class="demonstration">b(brightness)</span>
        <el-slider class="slider" v-model="parameters.b" ></el-slider>
      </div>

      <div class="block">
        <span class="demonstration">LOD</span>
        <el-slider class="slider" v-model="parameters.lod" :step="1" :min="0" :max="7" ></el-slider>
      </div>
    </div>
  </div>
</template>

<script lang="ts">
import { Component, Vue, Watch } from 'vue-property-decorator';
import Viewer from '../webgl/Viewer'
import MarmosetAssetsManager from '../webgl/assets/marmosets/MarmosetAssetsManager'
import * as THREE from 'three'
import { MeshMaterial as MarmosetMaterial } from '../webgl/materials/marmoset'


const vertexs = [0, 1, 0, 0.5, 0.5, 1, 0, 0, 0.99609375, 0.5, 0, 0, 1, 0.5, 0.99609375, -1, 0, 0, 0.00390625, 0.5, 0, 0, -1, 0.5, 0.00390625, 0, -1, 0, 0.99609375, 0.00390625, 0, -1, 0, 0.99609375, 0.99609375, 0, -1, 0, 0.00390625, 0.99609375, 0, -1, 0, 0.00390625, 0.00390625, 0.0054687499068677425, 0.9945312738418579, -0.0054687499068677425, 0.501953125, 0.498046875, 0.0054687499068677425, 0.9945312738418579, 0.0054687499068677425, 0.501953125, 0.501953125, -0.0054687499068677425, 0.9945312738418579, 0.0054687499068677425, 0.498046875, 0.501953125, -0.0054687499068677425, 0.9945312738418579, -0.0054687499068677425, 0.498046875, 0.498046875, -0.0054687499068677425, 0, -0.9945312738418579, 0.498046875, 0.005859375, 0.0054687499068677425, 0, -0.9945312738418579, 0.501953125, 0.005859375, 0.9945312738418579, 0, -0.0054687499068677425, 0.994140625, 0.498046875, 0.9945312738418579, 0, 0.0054687499068677425, 0.994140625, 0.501953125, 0.0054687499068677425, 0, 0.9945312738418579, 0.501953125, 0.994140625, -0.0054687499068677425, 0, 0.9945312738418579, 0.498046875, 0.994140625, -0.9945312738418579, 0, 0.0054687499068677425, 0.005859375, 0.501953125, -0.9945312738418579, 0, -0.0054687499068677425, 0.005859375, 0.498046875, 1, 0, 0, 0.9951171875, 0.5, 0, 0, 1, 0.5, 0.9951171875, -1, 0, 0, 0.0048828125, 0.5, 0, 0, -1, 0.5, 0.0048828125, 0, 1, 0, 0.4990234375, 0.5, 0, 1, 0, 0.5, 0.4990234375, 0, 1, 0, 0.5009765625, 0.5, 0, 1, 0, 0.5, 0.5009765625]
const indices = [2, 1, 6, 3, 2, 7, 8, 4, 3, 4, 5, 1, 9, 14, 15, 17, 10, 16, 18, 19, 11, 20, 13, 12, 28, 12, 13, 13, 24, 28, 28, 24, 9, 9, 24, 14, 25, 9, 15, 25, 15, 21, 10, 25, 21, 10, 21, 16, 22, 26, 10, 22, 10, 17, 18, 11, 26, 22, 18, 26, 19, 23, 27, 19, 27, 11, 23, 20, 27, 27, 20, 12]


@Component
export default class RTTest extends Vue {


  parameters = {

    b: 10,
    lod: 7

  }

  callBakes: Function[] = [];

  
  @Watch('parameters', { deep: true })
  onParametersChange( oldValue: any, newValue: any ) {

    this.callBakes.forEach( item => item());
  }

  mounted() {

    let marmosetAssetsManager = new MarmosetAssetsManager();

    let containner = this.$el.querySelector("#glContainner") as HTMLDivElement;
    let viewer = new Viewer();
    viewer.start(containner)
    

    let rtGeometry = new THREE.BufferGeometry();
        rtGeometry.setAttribute("p", new THREE.Float32BufferAttribute([-1, -1, 0.5, 1,  3, -1, 0.5, 1,  -1, 3, 0.5, 1], 4));
        rtGeometry.setIndex([0, 1, 2])

    let rtMaterial = new THREE.ShaderMaterial({

      uniforms: {
        tex: {value: null},
        b: { value: this.parameters.b },
        lod: { value: this.parameters.lod }
      }, 
      vertexShader: `
        precision highp float;

        
        attribute vec4 p;

        uniform float lod;

        varying vec2 tc;

        void main(){ 

            gl_Position = p;
            tc = vec2(0.5, 0.5/8.0) * p.xy + vec2(0.5, (lod + .5)/8.0); 
            
        }

      `,
      fragmentShader: `
        
        precision highp float;

        varying vec2 tc;

        uniform sampler2D tex;
        uniform float b;

        void main() {    
            
            vec4 s = texture2D(tex,tc);
            gl_FragColor.xyz = s.xyz*(b*s.w);
            
        }
      `
    
    });
     
    let rt = new THREE.WebGLRenderTarget(256,256, { format: THREE.RGBAFormat })

    let rtMesh = new THREE.Mesh( rtGeometry, rtMaterial );
    let rtCamera = new THREE.OrthographicCamera(-100, 100, 100, -100, 0.1, 100);
        rtCamera.position.set(0,0,50)
    let rtScene = new THREE.Scene();
        rtScene.add(rtMesh);

    let rtRenderer = new THREE.WebGLRenderer();
        rtRenderer.setSize(rt.width, rt.height)
        rtRenderer.domElement.style.position = 'fixed'
        rtRenderer.domElement.style.zIndex = '1000'
        //document.body.append(rtRenderer.domElement)
        
    rtRenderer.setRenderTarget(rt)
    rtRenderer.render(rtScene, rtCamera);


  
    let textureData = new Uint8Array(rt.width * rt.height * 4);
    let backgroundTexture = new THREE.DataTexture(textureData, rt.width, rt.height, THREE.RGBAFormat, THREE.UnsignedByteType);
        backgroundTexture.minFilter = THREE.LinearFilter
        backgroundTexture.magFilter = THREE.LinearFilter
    

    marmosetAssetsManager.loadAssets('static/model/vivfox/vivfox.mview').then( bundle => {

      let files = bundle[0];
      let sceneInfo = bundle[1];

      let skyData = files.get("sky.dat");

        if(skyData) {

          let skyBuffer = new Uint8Array(skyData.data)

          if(!skyBuffer) { throw ("解压失败") };

          let textureBuffer = new Uint8Array(skyData.data.byteLength);
          for (var d = skyBuffer.length, e = d / 4, g = 0, h = 0; g < d; ++h)
              textureBuffer[g++] = skyBuffer[h + 2 * e],
              textureBuffer[g++] = skyBuffer[h + e],
              textureBuffer[g++] = skyBuffer[h],
              textureBuffer[g++] = skyBuffer[h + 3 * e];

          let texture = new THREE.DataTexture( textureBuffer, 256, 2048, THREE.RGBAFormat);
              texture.generateMipmaps = true;
              texture.premultiplyAlpha = true
              texture.magFilter = THREE.LinearMipMapLinearFilter
              texture.minFilter = THREE.LinearMipMapLinearFilter
              texture.flipY = true;       


          rtMaterial.uniforms['tex'].value = texture;
          rtMaterial.needsUpdate = true

          rtRenderer.setRenderTarget(rt)
          rtRenderer.render(rtScene, rtCamera);
          rtRenderer.readRenderTargetPixels( rt, 0, 0, rt.width, rt.height, textureData)
          
          material.uniforms['tSkyTexture'].value = backgroundTexture
      }

    });
  
  
    let vertexBuffer = new THREE.InterleavedBuffer(new Float32Array(vertexs), 5);

    let geometry = new THREE.BufferGeometry();
    geometry.setAttribute('position', new THREE.InterleavedBufferAttribute(vertexBuffer, 3, 0));
    geometry.setAttribute('uv', new THREE.InterleavedBufferAttribute(vertexBuffer, 2, 3))
    geometry.setIndex(new THREE.Uint16BufferAttribute(new Uint16Array(indices), 3))
    geometry.scale(1000, 1000, 1000)

    let material = new THREE.ShaderMaterial({
            side: THREE.DoubleSide,
            defines: {

                SKYMODE: 2
                
            },
            uniforms: {

                uSkyCoefficients: { value: null },
                uAlpha: { value: null},
                tSkyTexture: {value: null}

            },
            transparent: false,
            opacity: 1,
            vertexShader: `
           
                uniform mat4 uInverseSkyMatrix;
                uniform mat4 uViewProjection;

                attribute vec3 vPosition;
                attribute vec2 vTexCoord;


                #if SKYMODE == 3
                varying vec3 jJ;
                #else
                varying vec2 d;
                #endif

                vec4 h(mat4 i,vec3 p)
                {
                    return i[0]*p.x+(i[1]*p.y+(i[2]*p.z+i[3]));
                }

                vec4 u(mat4 i,vec3 v)
                {
                    return i[0]*v.x+i[1]*v.y+i[2]*v.z;
                }


                
                void main(void)
                {
                    mat4 s;
                    s[0] = vec4(1, 0, -7.179587147021493e-9, 0);
                    s[1] = vec4(0, 1, 0, 0);
                    s[2] = vec4(7.179587147021493e-9, 0, 1, 0);
                    s[3] = vec4(0, 0, 0, 1);

                    //vec3 p=h(modelViewMatrix,vPosition).xyz;
                    //gl_Position=u(s,p);
                    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
                    
                    gl_Position.z-=(1.0/65535.0)*gl_Position.w;

                    #if SKYMODE == 3
                    //jJ=vPosition;
                    jJ = position;

                    jJ.xy+=1e-20*vTexCoord;
                    #else
                    //d=vTexCoord;
                    d=uv;
                    #endif
                }

            `,

            fragmentShader: `
            
                precision highp float;

                uniform sampler2D tSkyTexture;
                uniform float uAlpha;
                
                varying vec2 d;
                
                void main(void)
                {
                    vec3 r=texture2D(tSkyTexture,d).xyz;
                    gl_FragColor.xyz= r * r * 60.0;
                
                   
                    gl_FragColor.w=uAlpha;
                }
            `
        })


    let sky = new THREE.Mesh(geometry, material)
    
    viewer.add(sky);


    let callBack = () => {

      rtMaterial.uniforms['b'].value = this.parameters.b;
      rtMaterial.uniforms['lod'].value = this.parameters.lod

      rtRenderer.setRenderTarget(rt)
      rtRenderer.render(rtScene, rtCamera);
      rtRenderer.readRenderTargetPixels( rt, 0, 0, rt.width, rt.height, textureData)
        
      backgroundTexture.needsUpdate = true
    }

    this.callBakes.push(callBack)

  }
}
</script>
<style lang="less" scoped>

  #glContainner {

    position: fixed;
    left: 0;
    top:0;
    width: 100%;
    height: 100%;

  }

  #uiContainner {

    color: rgba(0,0,0,0.5);
    opacity: 0.99;

    width: 300px;
    height: 500px;
    padding: 15px;
    .demonstration {

      color: white;
    }

  }

</style>
