使用regl测试glsl shader 一些尝试代码

16 篇文章 0 订阅
5 篇文章 0 订阅



/// <reference path="../../../../scripts/graphics/webgl/regl/2.1.0/regl.d.ts" />
/// <reference path="../../../../scripts/mathematicsAndPhysics/linearAlgebra/matrix/gl-matrix/3.4.3/dist/index.d.ts" />
/// <reference path="../../../../scripts/graphics/3DGraphics/three.js/r148/types/index.d.ts" />
// vbo fbo ebo vao 
const glsl = {
    //
    highp: 'highp',// // Math.pow(2,16)
    mediump: 'mediump',// Math.pow(2,10)
    lowp: 'lowp', // Math.pow(2,8)
    void: 'void',
    int: 'int',
    float: 'float', // array float f_list[3]
    bool: 'bool',
    vec2: 'vec2',
    vec3: 'vec2',
    vec4: 'vec4',
    bvec2: 'bvec2',
    bvec3: 'bvec2',
    bvec4: 'bvec4',
    ivec2: 'ivec2',
    ivec3: 'ivec2',
    ivec4: 'ivec4',
    mat2: 'mat2',
    mat3: 'mat3',
    mat4: 'mat4',
    sampler2D: 'sampler2D',
    samplerCube: 'samplerCube',
    /**s
     * struct type-name {
        members
      } 
      struct-name[]
    */
    struct: 'struct',
    const: 'const',
    attribute: 'attribute',
    uniform: 'uniform',
    varying: 'varying',
    vert: {
        gl_Position: 'gl_Position', // highp vec4
        gl_PointSize: 'gl_PointSize', // mediump float
    },
    frag: {
        // input
        gl_FragCoord: 'gl_FragCoord',// mediump vec4
        gl_FrontFacing: 'gl_FrontFacing', // bool 碎片属于前向原语
        gl_PointCoord: 'gl_PointCoord', // mediump vec2
        // output
        gl_FragColor: 'gl_FragColor', //mediump vec4
        gl_FragData: 'gl_FragData[n]',// mediump vec4
    },
    builtFunc: {
        // Texture Lookup Functions [8.7]Available only in vertex shaders.
        texture2DLod: (sampler, coord, lod) => { return `texture2DLod(${sampler},${coord},${lod})` },// vec4  texture2DLod(sampler2D sampler, vec2 coord, float lod)
        texture2DProjLod: (sampler, coord, lod) => { return `texture2DProjLod(${sampler},${coord},${lod})` },// vec4  texture2DProjLod(sampler2D sampler, vec3 coord, float lod)
        // texture2DProjLod:(sampler,coord,lod)=>{ return `texture2DProjLod(${sampler},${coord},${lod})`},// vec4  texture2DProjLod(sampler2D sampler, vec4 coord, float lod)
        textureCubeLod: (sampler, coord, lod) => { return `textureCubeLod(${sampler},${coord},${lod})` },// vec4  textureCubeLod(samplerCube sampler, vec3 coord, float lod)
        // Available only in fragment shaders.
        texture2D: (sampler, coord, bias) => { return `texture2D(${sampler},${coord}${bias !== undefined ? ',' + bias : ''})` }, // vec4  texture2D(sampler2D sampler, vec2 coord, float bias)
        texture2DProj: (sampler, coord, bias) => { return `texture2D(${sampler},${coord}${bias !== undefined ? ',' + bias : ''})` },// vec4  texture2DProj(sampler2D sampler, vec3 coord, float bias)
        // texture2D:(sampler,coord,bias)=>{ return `texture2D(${sampler},${coord},${bias})`},// vec4  texture2DProj(sampler2D sampler, vec4 coord, float bias)
        textureCube: (samplerCube, coord, bias) => { return `textureCube(${samplerCube},${coord}${bias !== undefined ? ',' + bias : ''})` }, // vec4  textureCube(samplerCube sampler, vec3 coord, float bias)
        // Available in vertex and fragment shaders.
        // vec4  texture2D(sampler2D sampler, vec2 coord)
        // vec4  texture2DProj(sampler2D sampler, vec3 coord)
        // vec4  texture2DProj(sampler2D sampler, vec4 coord)
        // vec4  textureCube(samplerCube sampler, vec3 coord)
    },
    //  *   /** gl.POINTS */
    // "points" |
    // /** gl.LINES */
    // "lines" |
    // /** gl.LINE_STRIP */
    // "line strip" |
    // /** gl.LINE_LOOP */
    // "line loop" |
    // /** gl.TRIANGLES */
    // "triangles" |
    // /** gl.TRIANGLE_STRIP */
    // "triangle strip" |
    // /** gl.TRIANGLE_FAN */
    // "triangle fan";

    primitive: {
        points: 'points',
        lines: 'lines',
        lineStrip: 'line strip',
        lineLoop: 'line loop',
        triangles: 'triangles',
        triangleStrip: 'triangle strip',
        triangleFan: 'triangle fan'
    }
}

let { vec2, vec3, vec4, mat2, mat2d, mat3, mat4, quat, quat2 } = glMatrix


class Object3D {
    type = "Object3D"
    constructor() {
        this.position = vec3.fromValues(0, 0, 0)
        this.scale = vec3.fromValues(1, 1, 1)
        this.rotation = {
            _x: 0,
            _y: 0,
            _z: 0
        } //欧拉角
        this.quaternion = quat.fromValues(0, 0, 0, 1)
        this.matrixWorld = mat4.create() // 对象的世界矩阵 应用在相机上,就是相机矩阵
        this.matrix = mat4.create() // 局部矩阵

        let updateQuaternion = () => {
            quat.fromEuler(this.quaternion, this.rotation.x, this.rotation.y, this.rotation.z)
        }
        Object.defineProperties(this.rotation, {
            x: {
                get() {
                    return this._x
                },
                set(v) {
                    this._x = v
                    updateQuaternion()
                }
            },
            y: {
                get() {
                    return this._y
                },
                set(v) {
                    this._y = v
                    updateQuaternion()
                }
            },
            z: {
                get() {
                    return this._z
                },
                set(v) {
                    this._z = v
                    updateQuaternion()
                }
            }
        })
    }
    updateMatrix() {
        // mat4.translate(this.matrix,this.matrix,this.position)
        // mat4.rotateX(this.matrix,this.matrix,this.rotation[0])
        // mat4.rotateY(this.matrix,this.matrix,this.rotation[1])
        // mat4.rotateZ(this.matrix,this.matrix,this.rotation[2])
        // mat4.scale(this.matrix,this.matrix,this.scale)
        // 右乘 translate*rotation*scale
        // 左乘 scale*rotation*translate
        mat4.fromRotationTranslationScale(this.matrix, this.quaternion, this.position, this.scale)
    }
    updateMatrixWorld() {
        this.updateMatrix()
        mat4.identity(this.matrixWorld)
        mat4.multiply(this.matrixWorld, this.matrixWorld, this.matrix)
    }
    setPoisition(x, y, z) {
        vec3.set(this.position, x, y, z)
    }
    setScale(x, y, z) {
        vec3.set(this.scale, x, y, z)
    }
    setQuaternion(x, y, z, w = 1) {
        quat.set(this.quaternion, x, y, z, w)
    }
    rotateX(radian) {
        quat.rotateX(this.quaternion, this.quaternion, radian)
    }
    rotateY(radian) {
        quat.rotateY(this.quaternion, this.quaternion, radian)
    }
    rotateZ(radian) {
        quat.rotateZ(this.quaternion, this.quaternion, radian)
    }
    getWorldQuaternion(target) {
        this.updateMatrixWorld()
        let result = target || quat.create()
        mat4.getRotation(result, this.matrixWorld)
        return result
    }
    getWorldDirection2(result) {
        let quaternion = this.getWorldQuaternion()
        result = result || vec3.fromValues(0, 0, 1)
        vec3.transformQuat(result, result, quaternion)
        return result
    }
    getWorldDirection(result) {
        this.updateMatrixWorld()
        let e = this.matrixWorld
        result = result || vec3.fromValues(0, 0, 1)
        let direction = vec3.fromValues(e[8], e[9], e[10])
        vec3.normalize(result, direction)
        return result
    }
    lookAt = (function () {
        let cameraMatrix = mat4.create()
        let viewMatrix = mat4.create()
        let position = vec3.create()
        /**
         * @this {Object3D}
         */
        return function (target) {
            this.updateMatrixWorld()
            if (this.type == 'Camera') {

                // 获取相机世界位置
                mat4.getTranslation(position, this.matrixWorld)
                // 用look at计算相机矩阵。
                
                mat4.lookAt(cameraMatrix, position, target, this.up)
                // 由相机矩阵得出视图矩阵
                // 视图矩阵是将所有物体以相反于相机的方向运动, 尽管相机还是在原点但是相对关系是期望的。我们可以使用 inverse 方法计算逆矩阵( 完全对立的转换矩阵)
                mat4.invert(viewMatrix, cameraMatrix)// threejs的lookat(反转了)与gl-matrix的不一样.
                // 更新视图矩阵到四元数上
                mat4.getRotation(this.quaternion, viewMatrix)
                // 更新
                this.updateMatrixWorld()
            } else {
                // 获取相机世界位置
                mat4.getTranslation(position, this.matrixWorld)
                // 用look at计算相机矩阵。
                mat4.lookAt(cameraMatrix, target, position, this.up)
                // 由相机矩阵得出视图矩阵
                mat4.invert(viewMatrix, cameraMatrix)
                // 更新视图矩阵到四元数上
                mat4.getRotation(this.quaternion, viewMatrix)
                // 更新
                this.updateMatrixWorld()
            }

        }
    }())
}

class Camera extends Object3D {
    type = "Camera"
    constructor(fov = 50, aspect = 1, near = 0.001, far = 1000) {
        super()

        this.fov = fov
        this.aspect = aspect
        this.near = near
        this.far = far
        this.up = vec3.fromValues(0, 1, 0)
        // 从viewMatrix 转换到quaternion再到matrix z轴会变为正
        this.matrixWorldInvert = mat4.create() // 视图矩阵 观察空间矩阵
        this.projectionMatrix = mat4.create() // 投影矩阵
        this.projectionMatrixInverse = mat4.create()
        this.updateProjectionMatrix()
    }
    getWorldDirection2(result) {
        let quaternion = this.getWorldQuaternion()
        result = result || vec3.fromValues(0, 0, -1)
        vec3.transformQuat(result, result, quaternion)
        return result
    }
    getWorldDirection(result) {
        this.updateMatrixWorld()
        let e = this.matrixWorld
        result = result || vec3.fromValues(0, 0, 0)
        let direction = vec3.fromValues(-e[8], -e[9], -e[10])
        vec3.normalize(result, direction)
        return result
    }
    updateMatrixWorld() {
        super.updateMatrixWorld()
        mat4.invert(this.matrixWorldInvert, this.matrixWorld)
    }
    updateProjectionMatrix() {
        mat4.perspective(this.projectionMatrix, this.fov * Math.PI / 180, this.aspect, this.near, this.far)
        mat4.invert(this.projectionMatrixInverse, this.projectionMatrix)
    }

}


class Mesh extends Object3D {
    constructor() {
        super()
    }
    render() {

    }
}
function mouseButtons(ev) {
    if (typeof ev === 'object') {
        if ('buttons' in ev) {
            return ev.buttons
        } else if ('which' in ev) {
            var b = ev.which
            if (b === 2) {
                return 4
            } else if (b === 3) {
                return 2
            } else if (b > 0) {
                return 1 << (b - 1)
            }
        } else if ('button' in ev) {
            var b = ev.button
            if (b === 1) {
                return 4
            } else if (b === 2) {
                return 2
            } else if (b >= 0) {
                return 1 << b
            }
        }
    }
    return 0
}

function lookAt() {

}
class OribtControl {
    constructor(camera, domElement) {
        this.domElement = domElement
        /**@type {Camera}*/
        this.camera = camera

        let actionType = '',
            vec2_start = vec2.create(),
            vec2_end = vec2.create(),
            vec2_offset = vec2.create(),
            vec2_delta = vec2.create()


        let pitch = 0 // 俯仰角 
        let yaw = 0 // 偏航角
        let roll = 0 // 翻滚角

        let onDown = (e) => {
            this.domElement.addEventListener('pointermove', onMove, false)
            this.domElement.addEventListener('pointerup', onUp, false)

            if (e.buttons == 1) {
                actionType = "rotate"
            } else if (e.buttons == 2) {
                actionType = 'pan'
            }
            vec2.set(vec2_start, e.clientX, e.clientY)
        }
        let up = vec3.sub([], this.camera.up, [1, 1, 1])

        let onMove = (e) => {
            e.preventDefault()
            vec2.set(vec2_end, e.clientX, e.clientY)
            vec2.sub(vec2_delta, vec2_start, vec2_end)
            vec2.copy(vec2_start, vec2_end)



            this.camera.position[0] += vec2_delta[0] * 0.01
            this.camera.position[1] += vec2_delta[1] * 0.01

            updateCamera()
        }
        let onUp = () => {
            this.domElement.removeEventListener('pointermove', onMove, false)
            this.domElement.removeEventListener('pointerup', onUp, false)
        }
        let onContextMenu = (e) => {
            e.preventDefault()
        }
        let onWheel = (e) => {

        }
        let updateCamera = () => {
            this.camera.updateMatrixWorld()
        }
        this.attachEvent = function () {
            this.domElement.addEventListener('contextmenu', onContextMenu, false)
            this.domElement.addEventListener('pointerdown', onDown, false)
            this.domElement.addEventListener('wheel', onWheel, false)
        }
        this.detachEvent = function () {
            this.domElement.removeEventListener('contextmenu', onContextMenu, false)
            this.domElement.removeEventListener('pointerdown', onDown, false)
            this.domElement.removeEventListener('wheel', onWheel, false)
        }
        this.attachEvent()
    }


}
let imageResources = {}
function loadImage(name, url) {

    return new Promise((resolve, reject) => {
        let img = new Image()
        requestCORSIfNotSameOrigin(img, url)
        img.onload = () => {
            let item = imageResources[name] = {
                url: url,
                image: img
            }
            resolve(item)
        }
        img.src = url
    })
}
function loadResources(resources) {
    return Promise.allSettled(resources.map(r => {
        return loadImage(r.name, r.url)
    }))
}
function requestCORSIfNotSameOrigin(img, url) {
    if ((new URL(url, window.location.href)).origin !== window.location.origin) {
        img.crossOrigin = "";
    }
}
let boxVertices = [
    // 上 红
    -1, 1, -1,
    -1, 1, 1,
    1, 1, 1,
    1, 1, -1,
    // 下 绿
    -1, -1, -1,
    -1, -1, 1,
    1, -1, 1,
    1, -1, -1,
    // 前 蓝    
    -1, 1, 1,
    -1, -1, 1,
    1, -1, 1,
    1, 1, 1,
    // 后 黄
    - 1, 1, -1,
    -1, -1, -1,
    1, -1, -1,
    1, 1, -1,
    // 左 青
    -1, 1, -1,
    -1, -1, -1,
    -1, -1, 1,
    -1, 1, 1,
    // 右 品红
    1, 1, -1,
    1, -1, -1,
    1, -1, 1,
    1, 1, 1,
]
let boxIndices = [
    // 上
    0, 1, 2,
    0, 3, 2,
    // 下
    4, 5, 6,
    4, 7, 6,
    // 前
    8, 9, 10,
    8, 11, 10,
    // 后
    12, 13, 14,
    12, 15, 14,
    // 左
    16, 17, 18,
    16, 19, 18,
    // 右
    20, 21, 22,
    20, 23, 22
]
let boxColors = [
    // 上 红
    1.0, 0, 0,
    1.0, 0, 0,
    1.0, 0, 0,
    1.0, 0, 0,
    // 下 绿
    0, 1.0, 0,
    0, 1.0, 0,
    0, 1.0, 0,
    0, 1.0, 0,
    // 前 蓝
    0, 0, 1.0,
    0, 0, 1.0,
    0, 0, 1.0,
    0, 0, 1.0,
    // 后 黄
    1.0, 1.0, 0,
    1.0, 1.0, 0,
    1.0, 1.0, 0,
    1.0, 1.0, 0,
    // 左 青
    0, 1.0, 1.0,
    0, 1.0, 1.0,
    0, 1.0, 1.0,
    0, 1.0, 1.0,
    // 右 品红
    1.0, 0, 1.0,
    1.0, 0, 1.0,
    1.0, 0, 1.0,
    1.0, 0, 1.0
]
function generateFace(ctx, faceColor, textColor, text) {
    const { width, height } = ctx.canvas;
    ctx.clearRect(0, 0, width, height)
    ctx.fillStyle = faceColor;
    ctx.fillRect(0, 0, width, height);
    ctx.font = `${width * 0.7}px sans-serif`;
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    ctx.fillStyle = textColor;
    ctx.fillText(text, width / 2, height / 2);
}
function generateCubeFaceTexture(width, height) {
    // 获取二维上下文
    /** @type {CanvasRenderingContext2D} */
    const ctx = document.createElement("canvas").getContext("2d");

    ctx.canvas.width = width;
    ctx.canvas.height = height;

    const faceInfos = [
        { faceColor: '#F00', textColor: '#0FF', text: '+X', key: 'right' },
        { faceColor: '#FF0', textColor: '#00F', text: '-X', key: 'left' },
        { faceColor: '#0F0', textColor: '#F0F', text: '+Y', key: 'top' },
        { faceColor: '#0FF', textColor: '#F00', text: '-Y', key: 'bottom' },
        { faceColor: '#00F', textColor: '#FF0', text: '+Z', key: 'front' },
        { faceColor: '#F0F', textColor: '#0F0', text: '-Z', key: 'back' },
    ];
    let imageDatas = {}
    faceInfos.forEach((faceInfo) => {
        const { faceColor, textColor, text } = faceInfo;
        generateFace(ctx, faceColor, textColor, text);
        let imageData = ctx.getImageData(0, 0, width, height)
        //   let buffer=new ArrayBuffer()
        //  let dataView=new DataView(buffer)

        imageDatas[faceInfo.key] = imageData.data.slice()
    });
    return imageDatas
}



let BaseComponent = {
    template: `<div ><div ref="container" :style="style"></div></div>`,
    data() {
        return {
            width: 600,
            height: 400,
            devicePixelRatio: window.devicePixelRatio,
            resources: [],
            extensions: []
        }
    },
    computed: {
        style() {
            return {
                width: this.width + 'px',
                height: this.height + 'px',
                position: 'relative'
            }
        }
    },
    methods: {
        init(regl) { },
        onDown(e) {
            this.$emit('down', e)
        },
        onMove(e) {
            this.$emit('move', e)
        },
        onUp(e) {
            this.$emit('up', e)
        }
    },
    /**@type {createREGL.Regl}*/
    regl: null,
    mounted() {
        var container = this.$refs.container;
        var regl = this.regl = createREGL({
            container: container,
            pixelRatio: this.devicePixelRatio,
            profile: true,
            attributes: {
                antialias: true,
                stencil:true
            },
            extensions: [].concat(this.extensions)
        })

        // 加载资源
        loadResources([{
            name: 'texture',
            url: '/assets/textures/uv_grid_opengl.jpg'
        }, {
            name: "texture2",
            url: '/assets/pics/aya-touhou-teng-soldier.png'
        }, {
            name: "diamonds",
            url: '/assets/sprites/diamonds32x24x5.png'
        }].concat(this.resources)).then(img => {
            this.init(regl)
        })
        window.addEventListener('mousedown', this.onDown)
        window.addEventListener('mousemove', this.onMove)
        window.addEventListener('mouseup', this.onUp)
    },
    destroyed() {
        window.removeEventListener('mousedown', this.onDown)
        window.removeEventListener('mousemove', this.onMove)
        window.removeEventListener('mouseup', this.onUp)
        this.regl.destroy()
    }
}
addExample("绘制边框", function () {
    return {
        extends: BaseComponent,
        data() { return {}; },
        computed: {},
        methods: {
            /**
             * @param {createREGL.Regl} regl
            */
            init(regl) {
                    
            }
        },
        mounted() {
            var container = this.$refs.main;
        }
    }
})
addExample("2d坐标系统", function () {

    // 2d投影矩阵,把世界坐标转换为屏幕
    let width = 500, height = 500


    return {
        extends: BaseComponent,
        data() {
            return {
                width: width,
                height: height
            }
        },
        methods: {
            /**
             * @param {createREGL.Regl} regl
            */
            init(regl) {
                // 2d 左上角是原点(0,0)  
                // 3d 中间是原点(0,0)
                // 平面投影,将2d屏幕坐标转换为裁剪坐标(-1,1)
                // 将屏幕坐标投射为裁剪坐标
                let projectMatrix = mat3.create()
                mat3.projection(projectMatrix, width, height)



                let position = [
                    [100, 100],
                    [200, 100],
                    [200, 200],
                    [100, 200]
                ]
                let strokeRect = regl({
                    vert: `
                        attribute vec2 position;
                        uniform mat3 projectMatrix;
                        uniform mat3 modelMatrix;
                        void main(){
                            vec3 _position=projectMatrix* modelMatrix *vec3(position,1);
                            gl_Position=vec4(vec2(_position),0,1.0);
                        }
                    `,
                    frag: `
                        precision mediump float;
                        uniform vec4 color;
                        void main(){
                            gl_FragColor=color;
                        }
                    `,
                    primitive: "line loop",
                    attributes: {
                        position: position
                    },
                    uniforms: {
                        projectMatrix: regl.prop('projectMatrix'),
                        modelMatrix: regl.prop('modelMatrix'),
                        color: regl.prop('color')
                    },
                    count: position.length,
                    depth: {
                        enable: true,
                        mask: false
                    }
                })

                let modelMatrix = mat3.create()

                let modelMatrix2 = mat3.create()
                let skewX = -0.3, skewY = 0
                let tanX = Math.tan(skewX), tanY = Math.tan(skewY)
                let tanMatrix2 = mat3.fromValues(
                    1, tanX, 0,
                    tanY, 1, 0,
                    0, 0, 1
                )
                mat3.transpose(tanMatrix2, tanMatrix2)
                mat3.translate(modelMatrix2, modelMatrix2, [200, 200])
                mat3.multiply(modelMatrix2, modelMatrix2, tanMatrix2)
                mat3.translate(modelMatrix2, modelMatrix2, [-200, -200])
                let ticker = regl.frame(() => {
                    regl.clear({
                        color: [0, 0, 0, 1],
                        depth: 1
                    })
                    // mat3.translate(modelMatrix,modelMatrix,[100,100])
                    // mat3.rotate(modelMatrix,modelMatrix,0.1)
                    // mat3.translate(modelMatrix,modelMatrix,[-100,-100])
                    strokeRect([{
                        projectMatrix: projectMatrix,
                        modelMatrix: modelMatrix,
                        color: [1, 0, 0, 1]
                    },
                    {
                        projectMatrix: projectMatrix,
                        modelMatrix: modelMatrix2,
                        color: [1, 1, 0, 1]
                    }])



                })
            }
        }
    }
})

addExample("webgl仿2dCanvas", function () {

    // 2d投影矩阵,把世界坐标转换为屏幕
    let width = 500, height = 500

    class GLCanvasPath {
        static uid = 0
        constructor() {
            this.uid = 'path_' + (GLCanvasPath.uid++)
            this.pathData = new Map()
            this.isFill = false
        }
        moveTo(x, y) {
            this.pathData.set('moveTo', [x, y])
        }
        lineTo(x, y) {
            this.pathData.set('lineTo', [x, y])
        }
        rect(x, y, w, h) {
            this.pathData.set('rect', [x, y, w, h])
        }
        toFillPath() {
            let paths = []
            this.pathData.forEach((d, name) => {
                if (name === 'rect') {
                    paths.push(d[0], d[1])
                    paths.push(d[0] + d[2], d[1])
                    paths.push(d[0] + d[2], d[1] + d[3])
                    paths.push(d[0], d[1])
                    paths.push(d[0], d[1] + d[3])
                    paths.push(d[0] + d[2], d[1] + d[3])
                }
            })
            return new Float32Array(paths)
        }
        toStrokePath(lineWidth) {
            let paths = []
            this.pathData.forEach((d, name) => {
                if (name === 'rect') {
                    for (let l = 1; l <= lineWidth; l++) {
                        let x = d[0] - l, y = d[1] - l
                        let w = d[2] + l * 2, h = d[3] + l * 2
                        paths.push(x, y)
                        paths.push(x + w, y)
                        paths.push(x + w, y + h)
                        paths.push(x, y + w)
                        paths.push(x, y)
                    }
                }
            })
            return new Float32Array(paths)
        }
    }
    class GLCanvas {
        /**
         * @type {createREGL.Regl} regl
        */
        regl = null
        constructor(regl) {
            this.projectMatrix = mat3.create()
            this.modelMatrix = mat3.create()
            this.matrixStack = []
            this.regl = regl
            this._gldraw = null
            this.reset()
        }
        updateProjectMatrix() {
            mat3.projection(this.projectMatrix, this.regl._gl.drawingBufferWidth, this.regl._gl.drawingBufferHeight)
        }
        initGLDraw() {
            this.updateProjectMatrix()
            let regl = this.regl
            this._gldraw = regl({
                vert: `
                    attribute vec2 position;
                    uniform mat3 projectMatrix;
                    uniform mat3 modelMatrix;
                    void main(){
                        vec3 _position=projectMatrix* modelMatrix *vec3(position,1);
                        gl_Position=vec4(vec2(_position),0,1.0);
                    }
                `,
                frag: `
                    precision mediump float;
                    uniform vec4 color;
                    void main(){
                        gl_FragColor=color;
                    }
                `,
                primitive: regl.prop('primitive'),
                attributes: {
                    position: regl.prop('position')
                },
                uniforms: {
                    projectMatrix: regl.prop('projectMatrix'),
                    modelMatrix: regl.prop('modelMatrix'),
                    color: regl.prop('color')
                },
                count: (context, props, bachId) => {
                    console.log('props.position.length', props.position.length / 2)
                    return props.position.length / 2
                },
                blend: {
                    enable: true,
                    func: {
                        srcRGB: 'src alpha',
                        srcAlpha: 1,
                        dstRGB: 'one minus src alpha',
                        dstAlpha: 1
                    },
                    equation: {
                        rgb: 'add',
                        alpha: 'add'
                    },
                    color: [0, 0, 0, 0]
                }

            })

        }
        get gldraw() {
            if (!this._gldraw) {
                this.initGLDraw()
            }
            return this._gldraw
        }
        set fillStyle(color) {
            this._fillStyle = color
        }
        get fillStyle() {
            return this._fillStyle
        }
        set strokeStyle(color) {
            this._strokeStyle = color
        }
        get strokeStyle() {
            return this._strokeStyle
        }
        get currentMatrix() {
            return this.matrixStack[this.matrixStack.length - 1]
        }
        save() {
            this.matrixStack.push(mat3.clone(this.currentMatrix))
            return this
        }
        restore() {
            this.matrixStack.pop()
            if (this.matrixStack.length <= 0) {
                this.matrixStack[0] = mat3.create()
            }
            return this
        }
        transform(a, b, c, d, tx, ty) {
            let newMatrix = mat3.create()
            mat3.set(newMatrix, a, b, 0, c, d, 0, tx, ty, 1)
            mat3.multiply(newMatrix, this.currentMatrix, newMatrix)
            this.matrixStack.push(newMatrix)
        }
        setTransform(a, b, c, d, tx, ty) {
            mat3.set(this.currentMatrix, a, b, 0, c, d, 0, tx, ty, 1)
        }
        translate(x, y) {
            mat3.translate(this.currentMatrix, this.currentMatrix, [x, y])
        }
        scale(x, y) {
            mat3.scale(this.currentMatrix, this.currentMatrix, [x, y])
        }
        rotate(radian) {
            mat3.rotate(this.currentMatrix, this.currentMatrix, radian)
        }
        resetMatrix() {
            this.matrixStack.length = 0
            this.matrixStack.push(mat3.create())
        }
        reset() {
            this.currentPath = new GLCanvasPath()
            this.resetMatrix()
            this.drawOptions = Object.create(null)
            this._fillStyle = [0, 0, 0, 1]
            this._strokeStyle = [0, 0, 0, 1]
            this.lineWidth = 1
            this.clearColor([1, 1, 1, 1])
        }
        beginPath() {
            this.currentPath = new GLCanvasPath()
        }
        rect(x, y, w, h) {
            this.currentPath.rect(x, y, w, h)
        }
        fill() {
            if (this.currentPath.isFill) {
                return
            }
            this.currentPath.isFill = true
            this.drawOptions.color = this.fillStyle
            this.drawOptions.position = this.currentPath.toFillPath()
            this.drawOptions.primitive = glsl.primitive.triangles
            this.draw()
        }
        stroke() {
            if (this.currentPath.isStroke) {
                return
            }
            this.currentPath.isStroke = true
            this.drawOptions.color = this.strokeStyle
            this.drawOptions.position = this.currentPath.toStrokePath(this.lineWidth)
            this.drawOptions.primitive = glsl.primitive.lineStrip
            this.draw()
        }
        clearColor(color) {
            this._clearColor = color
        }
        clear() {
            this.regl.clear({
                color: this._clearColor,
                depth: 1
            })
            this.reset()
        }
        draw() {

            this.drawOptions.projectMatrix = this.projectMatrix
            this.drawOptions.modelMatrix = this.currentMatrix
            this.drawOptions.projectMatrix = this.projectMatrix
            this.gldraw(this.drawOptions)
        }
    }
    return {
        extends: BaseComponent,
        data() {
            return {
                width: width,
                height: height,
                devicePixelRatio: 1
            }
        },
        methods: {
            /**
             * @param {createREGL.Regl} regl
            */
            init(regl) {

                let canvas = new GLCanvas(regl)
                canvas.clearColor([0.4, 0.4, 0.4, 1])
                canvas.clear()
                canvas.save()
                canvas.translate(0, 100)
                canvas.rect(100, 100, 100, 100)
                canvas.fillStyle = [1, 1, 1, 1]
                canvas.fill()
                canvas.lineWidth = 5
                canvas.strokeStyle = [0, 0, 0, 1]
                canvas.stroke()
                canvas.restore()

                canvas.translate(150, 200)

                canvas.beginPath()
                canvas.rect(0, 0, 100, 100)
                canvas.fillStyle = [1, 0, 1, 1]
                canvas.fill()
                canvas.translate(0, 100)
                canvas.beginPath()
                canvas.rect(320, 100, 100, 100)
                canvas.fillStyle = [1, 1, 0, 1]
                canvas.fill()

                canvas.setTransform(1, 0, 0, 1, 0, 0)
                canvas.beginPath()
                canvas.rect(430, 100, 100, 100)
                canvas.fillStyle = [0, 1, 0, 1]
                canvas.fill()

            }
        }
    }
})


addExample("3d坐标系统", function ({ gui }) {


    // 2d投影矩阵,把世界坐标转换为屏幕
    let width = 500, height = 500

    return {
        extends: BaseComponent,
        data() {
            return {
                width: width,
                height: height
            }
        },
        methods: {
            /**
             * @param {createREGL.Regl} regl
            */
            init(regl) {
                // 将屏幕坐标投射为裁剪坐标
                let projectMatrix = mat4.create()
                // 将0居中,(-250,250)屏幕坐标转为(-1,1)
                // 正交投影z的变化不影响z的深度
                // mat4.ortho(projectMatrix, width / -2, width / 2, height / 2, height / -2, 0, 500)
                mat4.perspective(projectMatrix, 50 * Math.PI / 180, width / height, 0.1, 1000)
                // 视图矩阵
                let viewMatrix = mat4.create()
                let cameraPosition = vec3.fromValues(0, 2, 5)//  相机所在位置
                let lookTargetPosition = vec3.fromValues(0, 0, 0) // 相机拍摄目标
                let up = vec3.fromValues(0, 1, 0) // 相机自身朝向
                mat4.lookAt(viewMatrix, cameraPosition, lookTargetPosition, up)
                // mat4.invert(viewMatrix,viewMatrix)



                let position = [
                    // 后
                    [-1, -1, -1], //左下 0
                    [1, -1, -1],  // 右下 1
                    [1, 1, -1],   // 右上 2
                    [-1, 1, -1],  // 左上 3
                    // 前
                    [-1, -1, 1], //左下 4
                    [1, -1, 1],// 右下 5
                    [1, 1, 1],// 右上 6
                    [-1, 1, 1],// 左上 7
                ]
                let elements = [
                    // back
                    0, 1, 2,
                    0, 3, 2,
                    // front
                    4, 5, 6,
                    4, 7, 6,
                    // left
                    0, 4, 7,
                    0, 3, 7,
                    //right
                    5, 1, 2,
                    5, 6, 2,
                    //top
                    7, 6, 2,
                    7, 3, 2,
                    // bottom
                    4, 5, 2,
                    4, 3, 2
                ]
                let strokeRect = regl({
                    vert: `
                        attribute vec3 position;
                        uniform mat4 projectMatrix;
                        uniform mat4 viewMatrix;
                        uniform mat4 modelMatrix;
                        void main(){
                            vec4 _position=projectMatrix*viewMatrix* modelMatrix * vec4(position,1.0);
                            gl_Position=_position;
                        }
                    `,
                    frag: `
                        precision mediump float;
                        uniform vec4 color;
                        void main(){
                            gl_FragColor=color;
                        }
                    `,
                    attributes: {
                        position: position
                    },
                    uniforms: {
                        projectMatrix: regl.prop('projectMatrix'),
                        viewMatrix: regl.prop('viewMatrix'),
                        modelMatrix: regl.prop('modelMatrix'),
                        color: regl.prop('color')
                    },

                    elements: regl.elements({
                        primitive: "triangles",
                        data: elements,
                        // count:elements.length,
                        type: "uint8"
                    }),

                    // primitive: "triangles",
                    //count: position.length,

                })

                let modelMatrix = mat4.create()

                let modelQuat = quat.create()



                let ticker = regl.frame(() => {
                    regl.clear({
                        color: [0, 0, 0, 1],
                        depth: 1
                    })
                    quat.rotateY(modelQuat, modelQuat, 0.01)
                    // quat.rotateX(modelQuat,modelQuat,0.01)

                    mat4.fromQuat(modelMatrix, modelQuat)
                    strokeRect({
                        projectMatrix: projectMatrix,
                        viewMatrix: viewMatrix,
                        modelMatrix: modelMatrix,
                        color: [1, 0, 0, 1]
                    })



                })
            }
        }
    }
})



addExample("3d 顶点着色", function ({ gui }) {

    // 2d投影矩阵,把世界坐标转换为屏幕
    let width = 500, height = 500
    return {
        extends: BaseComponent,
        data() {
            return {
                width: width,
                height: height
            }
        },
        methods: {
            /**
             * @param {createREGL.Regl} regl
            */
            init(regl) {
                // 将屏幕坐标投射为裁剪坐标
                let projectMatrix = mat4.create()
                // 将0居中,(-250,250)屏幕坐标转为(-1,1)
                // 正交投影z的变化不影响z的深度
                // mat4.ortho(projectMatrix, width / -2, width / 2, height / 2, height / -2, 0, 500)
                mat4.perspective(projectMatrix, 50 * Math.PI / 180, width / height, 0.1, 1000)
                // 视图矩阵
                let viewMatrix = mat4.create()
                let cameraPosition = vec3.fromValues(0, 2, 5)//  相机所在位置
                let lookTargetPosition = vec3.fromValues(0, 0, 0) // 相机拍摄目标
                let up = vec3.fromValues(0, 1, 0) // 相机自身朝向
                mat4.lookAt(viewMatrix, cameraPosition, lookTargetPosition, up)
                // mat4.invert(viewMatrix,viewMatrix)

                let vertexs = [
                    // 上 红
                    -1, 1, -1, 1.0, 0, 0,
                    -1, 1, 1, 1.0, 0, 0,
                    1, 1, 1, 1.0, 0, 0,
                    1, 1, -1, 1.0, 0, 0,
                    // 下 绿
                    -1, -1, -1, 0, 1.0, 0,
                    -1, -1, 1, 0, 1.0, 0,
                    1, -1, 1, 0, 1.0, 0,
                    1, -1, -1, 0, 1.0, 0,
                    // 前 蓝
                    -1, 1, 1, 0, 0, 1.0,
                    -1, -1, 1, 0, 0, 1.0,
                    1, -1, 1, 0, 0, 1.0,
                    1, 1, 1, 0, 0, 1.0,
                    // 后 黄
                    - 1, 1, -1, 1.0, 1.0, 0,
                    -1, -1, -1, 1.0, 1.0, 0,
                    1, -1, -1, 1.0, 1.0, 0,
                    1, 1, -1, 1.0, 1.0, 0,
                    // 左 青
                    -1, 1, -1, 0, 1.0, 1.0,
                    -1, -1, -1, 0, 1.0, 1.0,
                    -1, -1, 1, 0, 1.0, 1.0,
                    -1, 1, 1, 0, 1.0, 1.0,
                    // 右 品红
                    1, 1, -1, 1.0, 0, 1.0,
                    1, -1, -1, 1.0, 0, 1.0,
                    1, -1, 1, 1.0, 0, 1.0,
                    1, 1, 1, 1.0, 0, 1.0
                ]

                let vertexBuffer = regl.buffer({
                    data: vertexs,
                    type: "float",
                    usage: "static"
                })
                let strokeRect = regl({
                    vert: `
                        attribute vec3 position;
                        attribute vec3 color;
                        uniform mat4 projectMatrix;
                        uniform mat4 viewMatrix;
                        uniform mat4 modelMatrix;
                        varying vec3 v_color;
                        void main(){
                            vec4 _position=projectMatrix*viewMatrix* modelMatrix * vec4(position,1.0);
                            gl_Position=_position;
                            v_color=color;
                        }
                    `,
                    frag: `
                        precision mediump float;
                        varying vec3 v_color;
                        void main(){
                            gl_FragColor= vec4(v_color,1.0);
                        }
                    `,
                    attributes: {
                        position: {
                            buffer: vertexBuffer,
                            size: 3,
                            offset: 0,
                            stride: 6 * Float32Array.BYTES_PER_ELEMENT,
                            type: "float"
                        },
                        color: {
                            buffer: vertexBuffer,
                            size: 3,
                            offset: 3 * Float32Array.BYTES_PER_ELEMENT,
                            stride: 6 * Float32Array.BYTES_PER_ELEMENT,
                            type: "float"
                        }
                    },
                    uniforms: {
                        projectMatrix: regl.prop('projectMatrix'),
                        viewMatrix: regl.prop('viewMatrix'),
                        modelMatrix: regl.prop('modelMatrix'),
                    },

                    elements: regl.elements({
                        primitive: "triangles",
                        data: boxIndices,
                        // count:elements.length,
                        type: "uint16"
                    })
                    // primitive: "triangles",
                    //count: position.length,

                })

                let modelMatrix = mat4.create()

                let modelQuat = quat.create()



                let ticker = regl.frame(() => {
                    regl.clear({
                        color: [0, 0, 0, 1],
                        depth: 1
                    })
                    quat.rotateY(modelQuat, modelQuat, 0.01)
                    // quat.rotateX(modelQuat,modelQuat,0.01)

                    mat4.fromQuat(modelMatrix, modelQuat)
                    strokeRect({
                        projectMatrix: projectMatrix,
                        viewMatrix: viewMatrix,
                        modelMatrix: modelMatrix
                    })



                })
            }
        }
    }
})


addExample("3d 顶点单独着色", function ({ gui }) {


    // 2d投影矩阵,把世界坐标转换为屏幕
    let width = 500, height = 500

    return {
        extends: BaseComponent,
        data() {
            return {
                width: width,
                height: height
            }
        },
        methods: {
            /**
             * @param {createREGL.Regl} regl
            */
            init(regl) {
                // 将屏幕坐标投射为裁剪坐标
                let projectMatrix = mat4.create()
                // 将0居中,(-250,250)屏幕坐标转为(-1,1)
                // 正交投影z的变化不影响z的深度
                // mat4.ortho(projectMatrix, width / -2, width / 2, height / 2, height / -2, 0, 500)
                mat4.perspective(projectMatrix, 50 * Math.PI / 180, width / height, 0.1, 1000)
                // 视图矩阵
                let viewMatrix = mat4.create()
                let cameraPosition = vec3.fromValues(0, 2, 5)//  相机所在位置
                let lookTargetPosition = vec3.fromValues(0, 0, 0) // 相机拍摄目标
                let up = vec3.fromValues(0, 1, 0) // 相机自身朝向
                mat4.lookAt(viewMatrix, cameraPosition, lookTargetPosition, up)
                // mat4.invert(viewMatrix,viewMatrix)
                var colors = [
                    // 上 红
                    1.0, 0, 0,
                    1.0, 0, 0,
                    1.0, 0, 0,
                    1.0, 0, 0,
                    // 下 绿
                    0, 1.0, 0,
                    0, 1.0, 0,
                    0, 1.0, 0,
                    0, 1.0, 0,
                    // 前 蓝
                    0, 0, 1.0,
                    0, 0, 1.0,
                    0, 0, 1.0,
                    0, 0, 1.0,
                    // 后 黄
                    1.0, 1.0, 0,
                    1.0, 1.0, 0,
                    1.0, 1.0, 0,
                    1.0, 1.0, 0,
                    // 左 青
                    0, 1.0, 1.0,
                    0, 1.0, 1.0,
                    0, 1.0, 1.0,
                    0, 1.0, 1.0,
                    // 右 品红
                    1.0, 0, 1.0,
                    1.0, 0, 1.0,
                    1.0, 0, 1.0,
                    1.0, 0, 1.0
                ]
                let strokeRect = regl({
                    vert: `
                        attribute vec3 position;
                        attribute vec3 color;
                        uniform mat4 projectMatrix;
                        uniform mat4 viewMatrix;
                        uniform mat4 modelMatrix;
                        varying vec3 v_color;
                        void main(){
                            vec4 _position=projectMatrix*viewMatrix* modelMatrix * vec4(position,1.0);
                            gl_Position=_position;
                            v_color=color;
                        }
                    `,
                    frag: `
                        precision mediump float;
                        varying vec3 v_color;
                        void main(){
                            gl_FragColor= vec4(v_color,1.0);
                        }
                    `,
                    attributes: {
                        position: {
                            buffer: boxVertices,
                            size: 3,
                            offset: 0,
                            stride: 0,
                            type: "float"
                        },
                        color: {
                            buffer: colors,
                            size: 3,
                            offset: 0,
                            stride: 0,
                            type: "float"
                        }
                    },
                    uniforms: {
                        projectMatrix: regl.prop('projectMatrix'),
                        viewMatrix: regl.prop('viewMatrix'),
                        modelMatrix: regl.prop('modelMatrix'),
                    },

                    elements: regl.elements({
                        primitive: "triangles",
                        data: boxIndices,
                        // count:elements.length,
                        type: "uint16"
                    })
                    // primitive: "triangles",
                    //count: position.length,

                })

                let modelMatrix = mat4.create()
                let modelQuat = quat.create()
                let ticker = regl.frame(() => {
                    regl.clear({
                        color: [0, 0, 0, 1],
                        depth: 1
                    })
                    //  quat.rotateY(modelQuat, modelQuat, 0.01)
                    // quat.rotateX(modelQuat,modelQuat,0.01)

                    //  mat4.fromQuat(modelMatrix, modelQuat)
                    strokeRect({
                        projectMatrix: projectMatrix,
                        viewMatrix: viewMatrix,
                        modelMatrix: modelMatrix
                    })



                })
            }
        }
    }
})



addExample("3d 纹理贴图", function ({ gui }) {

    // 图片坐标:是左上角(0,0)开始,右下角(1,1)
    // 纹理坐标:是左上角(0,1),右下角(1,0)
    // 在设置时,坐标
    // 2d投影矩阵,把世界坐标转换为屏幕
    let width = 500, height = 500

    return {
        extends: BaseComponent,
        data() {
            return {
                width: width,
                height: height
            }
        },
        methods: {
            /**
             * @param {createREGL.Regl} regl
            */
            init(regl) {
                // 将屏幕坐标投射为裁剪坐标
                let projectMatrix = mat4.create()
                mat4.perspective(projectMatrix, 50 * Math.PI / 180, width / height, 0.1, 1000)
                // 视图矩阵
                let viewMatrix = mat4.create()
                let cameraPosition = vec3.fromValues(0, 0, 5)//  相机所在位置
                let lookTargetPosition = vec3.fromValues(0, 0, 0) // 相机拍摄目标
                let up = vec3.fromValues(0, 1, 0) // 相机自身朝向
                mat4.lookAt(viewMatrix, cameraPosition, lookTargetPosition, up)
                // mat4.invert(viewMatrix,viewMatrix)

                /**
                (0,0) --> (-1,1,0)
                (1,0) --> (1,1,0)
                (1,1) --> (1,-1,0)
                (0,1) --> (-1,-1,0)
                其映射关系为 
                u = (x + 1) / 2
                v = (1 - y) / 2

                默认:纹理坐标是网页2d坐标:左上角(0,0) 右上角(1,0) 左下角(0,1) 右下角(1,1)
                通过 flipY 翻转Y轴:左上角(0,1) 右上角(1,1) 左下角(0,0) 右下角(1,0)

                目前下面定义未按上面一一对应,如果按上面对应图片是倒的.原因未知,需要flipY:true
                下面是按照网页2d坐标来映射
                    (0,0) --> (-1,1,0)
                    (1,0) --> (1,1,0)
                    (1,1) --> (1,-1,0)
                    (0,1) --> (-1,-1,0)
                 * 
                 * */
                var uv = [
                    // 上 红
                    0, 0,
                    0, 1,
                    1, 1,
                    1, 0,
                    // 下 绿
                    0, 0,
                    0, 1,
                    1, 1,
                    1, 0,
                    // 前 蓝
                    0, 1,
                    0, 0,
                    1, 0,
                    1, 1,
                    // 后 黄
                    0, 0,
                    0, 1,
                    1, 1,
                    1, 0,
                    // 左 青
                    0, 0,
                    0, 1,
                    1, 1,
                    1, 0,
                    // 右 品红
                    0, 0,
                    0, 1,
                    1, 1,
                    1, 0,
                ]
                var texture = regl.texture({
                    data: imageResources.texture.image,
                    wrapS: "clamp",
                    wrapT: "clamp",
                    //   min:"nearest",
                    //   format:"rgb",
                    //    type:"uint8",
                    // flipY:true
                    // mag:"nearest"
                })
                let strokeRect = regl({
                    vert: `
                        attribute vec3 position;
                        attribute vec2 a_texCoord;
                        uniform mat4 projectMatrix;
                        uniform mat4 viewMatrix;
                        uniform mat4 modelMatrix;
                        varying vec2 v_texCoord;
                        void main(){
                            vec4 _position=projectMatrix*viewMatrix* modelMatrix * vec4(position,1.0);
                            gl_Position=_position;
                            // 将纹理坐标传给片断着色器
                            // GPU会在点之间进行插值
                          
                            v_texCoord=a_texCoord;
                        }
                    `,
                    frag: `
                        precision mediump float;
                        // 纹理
                        uniform sampler2D u_image;       
                        // 从顶点着色器传入的纹理坐标
                        varying vec2 v_texCoord;
                        void main(){
                            // 翻转y轴
                            vec2 flipY= vec2(v_texCoord.x,1.0-v_texCoord.y);
                            // 在纹理上寻找对应颜色值
                            gl_FragColor = texture2D(u_image, flipY);
                        }
                    `,
                    attributes: {
                        position: {
                            buffer: boxVertices,
                            size: 3,
                            offset: 0,
                            stride: 0,
                            type: "float"
                        },
                        a_texCoord: {
                            buffer: uv,
                            size: 2,
                            offset: 0,
                            stride: 0,
                            type: "float"
                        }
                    },
                    uniforms: {
                        projectMatrix: regl.prop('projectMatrix'),
                        viewMatrix: regl.prop('viewMatrix'),
                        modelMatrix: regl.prop('modelMatrix'),
                        u_image: texture
                    },

                    elements: regl.elements({
                        primitive: "triangles",
                        data: boxIndices,
                        // count:elements.length,
                        type: "uint16"
                    })
                    // primitive: "triangles",
                    //count: position.length,

                })

                let modelMatrix = mat4.create()
                let modelQuat = quat.create()
                let ticker = regl.frame(() => {
                    regl.clear({
                        color: [0, 0, 0, 1],
                        depth: 1
                    })
                    //  quat.rotateY(modelQuat, modelQuat, 0.01)
                    // quat.rotateX(modelQuat,modelQuat,0.01)

                    // mat4.fromQuat(modelMatrix, modelQuat)
                    strokeRect({
                        projectMatrix: projectMatrix,
                        viewMatrix: viewMatrix,
                        modelMatrix: modelMatrix
                    })



                })
            }
        }
    }
})
addExample("3d 立体纹理贴图", function ({ gui }) {
    let width = 500, height = 500
    return {
        extends: BaseComponent,
        data() {
            return {
                width: width,
                height: height
            }
        },
        methods: {
            /**
             * @param {createREGL.Regl} regl
            */
            init(regl) {
                // 将屏幕坐标投射为裁剪坐标
                let camera = new Camera(45, width / height, 0.001, 1000)
                camera.setPoisition(0, 2, 5)
                camera.lookAt(vec3.fromValues(0, 0, 0))
                let oribt = new OribtControl(camera, regl._gl.canvas)
                let textureImageData = generateCubeFaceTexture(500, 500)
                var texture = regl.cube({
                    width: 500,
                    height: 500,
                    wrap: "clamp",
                    //min:"linear mipmap linear",
                    faces: [
                        textureImageData.right, textureImageData.left,
                        textureImageData.top, textureImageData.bottom,
                        textureImageData.front, textureImageData.back
                    ]
                })

                let strokeRect = regl({
                    vert: `
                        attribute vec3 position;
                        uniform mat4 projectMatrix;
                        uniform mat4 viewMatrix;
                        uniform mat4 modelMatrix;
                        varying vec3 v_normal;
                        void main(){
                            vec4 _position=projectMatrix*viewMatrix* modelMatrix * vec4(position,1.0);
                            gl_Position=_position;
                            // 传递法向量。因为位置是以几何中心为原点的
                            // 我们可以直接传递位置
                            v_normal = normalize(position.xyz);
                        }
                    `,
                    frag: `
                        precision mediump float;
                        // 纹理
                        uniform samplerCube u_texture;       
                        // 从顶点着色器传入的纹理
                        varying vec3 v_normal;
                        void main(){
                            // 在纹理上寻找对应颜色值
                            gl_FragColor = textureCube(u_texture, normalize(v_normal));
                        }
                    `,
                    attributes: {
                        position: {
                            buffer: boxVertices,
                            size: 3,
                            offset: 0,
                            stride: 0,
                            type: "float"
                        }
                    },
                    uniforms: {
                        projectMatrix: regl.prop('projectMatrix'),
                        viewMatrix: regl.prop('viewMatrix'),
                        modelMatrix: regl.prop('modelMatrix'),
                        u_texture: texture
                    },

                    elements: regl.elements({
                        primitive: "triangles",
                        data: boxIndices,
                        // count:elements.length,
                        type: "uint16"
                    })
                    // primitive: "triangles",
                    //count: position.length,

                })

                let obj = new Object3D()
                addGuiScheme(gui, {
                    controls: {
                        vec3: (api) => {

                            api.gui.add(api.value, 0, ...api.scheme.params).name(api.name + '.x').onChange(api.onChange)
                            api.gui.add(api.value, 1, ...api.scheme.params).name(api.name + '.y').onChange(api.onChange)
                            api.gui.add(api.value, 2, ...api.scheme.params).name(api.name + '.z').onChange(api.onChange)
                        }
                    },
                    source: {
                        'position': camera.position,
                        'direction': () => {
                            console.log('getWorldDirection', camera.getWorldDirection())
                        },
                        'direction2': () => {
                            console.log('getWorldDirection2', camera.getWorldDirection2())
                        }
                    },
                    schemes: {
                        'position': {
                            type: "vec3",
                            params: [-10, 10, 0.1]
                        }
                    },
                    onChange(d) {
                        //  camera.setRotation(d['rotate.x'],d['rotate.y'],d['rotate.z'])
                        camera.lookAt(vec3.fromValues(0, 0, 0))
                    }
                })
                let ticker = regl.frame(() => {
                    regl.clear({
                        color: [0, 0, 0, 1],
                        depth: 1
                    })
                    strokeRect({
                        projectMatrix: camera.projectionMatrix,
                        viewMatrix: camera.matrixWorldInvert,
                        modelMatrix: obj.matrixWorld
                    })
                })
            }
        }
    }
})
addExample("3d 交互", function ({ gui }) {


    // 2d投影矩阵,把世界坐标转换为屏幕
    let width = 500, height = 500

    return {
        extends: BaseComponent,
        data() {
            return {
                width: width,
                height: height
            }
        },
        methods: {
            /**
             * @param {createREGL.Regl} regl
            */
            init(regl) {


                let strokeRect = regl({
                    vert: `
                        attribute vec3 position;
                        attribute vec3 color;
                        uniform mat4 projectMatrix;
                        uniform mat4 viewMatrix;
                        uniform mat4 modelMatrix;
                        varying vec3 v_color;
                        void main(){
                            vec4 _position=projectMatrix*viewMatrix* modelMatrix * vec4(position,1.0);
                            gl_Position=_position;
                            v_color=color;
                        }
                    `,
                    frag: `
                        precision mediump float;
                        varying vec3 v_color;
                        void main(){
                            gl_FragColor= vec4(v_color,1.0);
                        }
                    `,
                    attributes: {
                        position: {
                            buffer: boxVertices,
                            size: 3,
                            offset: 0,
                            stride: 0,
                            type: "float"
                        },
                        color: {
                            buffer: boxColors,
                            size: 3,
                            offset: 0,
                            stride: 0,
                            type: "float"
                        }
                    },
                    uniforms: {
                        projectMatrix: regl.prop('projectMatrix'),
                        viewMatrix: regl.prop('viewMatrix'),
                        modelMatrix: regl.prop('modelMatrix'),
                    },

                    elements: regl.elements({
                        primitive: "triangles",
                        data: boxIndices,
                        // count:elements.length,
                        type: "uint16"
                    })
                    // primitive: "triangles",
                    //count: position.length,

                })

                let camera = new Camera(45, width / height, 0.001, 1000)
                camera.setPoisition(0, 2, 5)
                camera.lookAt(vec3.fromValues(0, 0, 0))

                let box = new Object3D()
                box.updateMatrixWorld()
                let ray = new Ray3D.Ray()
                this.$on('down', (e) => {
                    let rayOrigin = vec3.create(), // 相机在世界空间的坐标
                        rayPoint = vec3.create(),// 从鼠标位置裁剪坐标转换为世界空间坐标(与相机在同一个空间)
                        rayDirection = vec3.create() // rayPoint-rayOrigin 得到归一化,的方向向量
                    let rect = regl._gl.canvas.getBoundingClientRect()

                    // 获取相机世界位置
                    // vec3.transformMat4(rayOrigin,rayOrigin, camera.matrixWorld)
                    mat4.getTranslation(rayOrigin, camera.matrixWorld)
                    // 将屏幕坐标转换为gl裁剪坐标
                    let x = (e.clientX - rect.left) / rect.width * 2 - 1
                    let y = -(e.clientY - rect.top) / rect.height * 2 + 1
                    // 设置鼠标世界坐标
                    vec3.set(rayPoint, x, y, 0.5)
                    // var vp = mat4.multiply([], camera.projectionMatrix, camera.matrixWorldInvert)
                    // var invVp = mat4.invert([], vp)

                    // console.log('fff',vec3.transformMat4([],rayPoint,invVp))

                    // console.log('fff2',vec3.transformMat4([],vec3.transformMat4([],rayPoint,camera.projectionMatrixInverse),camera.matrixWorld))
                    // 将投影截剪坐标转为世界坐标,
                    vec3.transformMat4(rayPoint, rayPoint, camera.projectionMatrixInverse)
                    // 相对相机世界坐标
                    vec3.transformMat4(rayPoint, rayPoint, camera.matrixWorld)
                    // 得到相对原点向量
                    vec3.sub(rayDirection, rayPoint, rayOrigin)
                    // 得到单位向量,方向
                    vec3.normalize(rayDirection, rayDirection)

                    // console.log('rayPoint', rayPoint, 'rayDirection', rayDirection, ',rayOrigin:', rayOrigin)
                    // console.log('camera-direction', camera.getWorldDirection(vec3.create()))
                    ray.origin = rayOrigin
                    ray.direction = rayDirection

                    let a, b, c, p1 = vec3.create(), p2 = vec3.create(), p3 = vec3.create(), triangle = new Array(3)
                    let triangleInterserect
                    for (let i = 0; i < boxIndices.length; i += 3) {
                        a = boxIndices[i] * 3
                        b = boxIndices[i + 1] * 3
                        c = boxIndices[i + 2] * 3
                        vec3.set(p1, boxVertices[a], boxVertices[a + 1], boxVertices[a + 2])
                        vec3.set(p2, boxVertices[b], boxVertices[b + 1], boxVertices[b + 2])
                        vec3.set(p3, boxVertices[c], boxVertices[c + 1], boxVertices[c + 2])
                        vec3.transformMat4(p1, p1, box.matrixWorld)
                        vec3.transformMat4(p2, p2, box.matrixWorld)
                        vec3.transformMat4(p3, p3, box.matrixWorld)

                        triangle[0] = p1
                        triangle[1] = p2
                        triangle[2] = p3
                        // triangleInterserect=Ray3D.intersectRayTriangle([],rayPoint,rayDirection,triangle)
                        triangleInterserect = ray.intersectsTriangle(triangle)
                        if (triangleInterserect != null) {
                            console.log('点击')
                            break
                        }
                    }
                })
                this.$on('move', (e) => {

                })
                let ticker = regl.frame(() => {
                    regl.clear({
                        color: [0, 0, 0, 1],
                        depth: 1
                    })
                    //  quat.rotateY(modelQuat, modelQuat, 0.01)
                    // quat.rotateX(modelQuat,modelQuat,0.01)

                    //  mat4.fromQuat(modelMatrix, modelQuat)
                    strokeRect({
                        projectMatrix: camera.projectionMatrix,
                        viewMatrix: camera.matrixWorldInvert,
                        modelMatrix: box.matrixWorld
                    })



                })
            }
        }
    }
})
addExample("3d 天空盒", function ({ gui }) {


    // 2d投影矩阵,把世界坐标转换为屏幕
    let width = 500, height = 500
    const faceInfos = [
        {
            // target: gl.TEXTURE_CUBE_MAP_POSITIVE_X,
            url: 'http://localhost:8349/webgl/resources/images/computer-history-museum/pos-x.jpg',
        },
        {
            //  target: gl.TEXTURE_CUBE_MAP_NEGATIVE_X,
            url: 'http://localhost:8349/webgl/resources/images/computer-history-museum/neg-x.jpg',
        },
        {
            //   target: gl.TEXTURE_CUBE_MAP_POSITIVE_Y,
            url: 'http://localhost:8349/webgl/resources/images/computer-history-museum/pos-y.jpg',
        },
        {
            //  target: gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,
            url: 'http://localhost:8349/webgl/resources/images/computer-history-museum/neg-y.jpg',
        },
        {
            //  target: gl.TEXTURE_CUBE_MAP_POSITIVE_Z,
            url: 'http://localhost:8349/webgl/resources/images/computer-history-museum/pos-z.jpg',
        },
        {
            // target: gl.TEXTURE_CUBE_MAP_NEGATIVE_Z,
            url: 'http://localhost:8349/webgl/resources/images/computer-history-museum/neg-z.jpg',
        },
    ].map(d => {
        let index = d.url.lastIndexOf('/')
        return {
            name: d.url,
            url: d.url
        }
    });
    return {
        extends: BaseComponent,
        data() {
            return {
                width: width,
                height: height,
                resources: faceInfos
            }
        },
        methods: {
            /**
             * @param {createREGL.Regl} regl
            */
            init(regl) {

                let cubeTexture = regl.cube({
                    width: 512,
                    height: 512,
                    faces: faceInfos.map(d => imageResources[d.name].image),
                    format: "rgba",
                    type: "uint8",
                    mipmap: "nice",
                    min: "linear mipmap linear",

                })

                let drawEnvmap = regl({
                    vert: `
                        attribute vec4 a_position;
                        varying vec4 v_position;
                        void main() {
                            v_position = a_position;
                            gl_Position = a_position;
                            gl_Position.z = 1.0;
                        }
                    `,
                    frag: `
                    precision mediump float;

                    uniform samplerCube u_skybox;
                    uniform mat4 projectionMatrixInverse;
                    uniform mat4 cameraWorldMatrix;
                    uniform mat4 u_viewDirectionProjectionInverse;
                    
                    varying vec4 v_position;
                    void main() {
                      vec4 t = u_viewDirectionProjectionInverse * v_position;
                      gl_FragColor =textureCube(u_skybox, normalize(t.xyz / t.w));
                     //  gl_FragColor=vec4(1.0,0,0,1.0);
                    }
                    `,
                    attributes: {
                        a_position: {
                            buffer: regl.buffer({
                                data: [
                                    -1, -1,
                                    1, -1,
                                    -1, 1,
                                    -1, 1,
                                    1, -1,
                                    1, 1,
                                ],
                                usage: "static",
                                type: "float"
                            }),
                            offset: 0,
                            stride: 0,
                            normalized: false,
                            size: 2,
                            type: "float"
                        }
                    },
                    uniforms: {
                        u_skybox: cubeTexture,
                        u_viewDirectionProjectionInverse: regl.prop('u_viewDirectionProjectionInverse')
                    },
                    primitive: "triangles",
                    count: 6,
                    depth: {
                        enable: true,
                        func: 'lequal'
                    }

                })
                let envmap = new Object3D()
                envmap.draw = drawEnvmap


                let camera = new Camera(60, width / height, 0.001, 1000)
                camera.lookAt(vec3.fromValues(0, 0, 0))

                var viewMatrix = mat4.create()

                var viewDirectionProjectionMatrix = mat4.create()
                var viewDirectionProjectionInverseMatrix = mat4.create()




                let ticker = regl.frame(({ time }) => {

                    regl.clear({
                        color: [0, 0, 0, 1],
                        depth: 1
                    })

                    camera.position[0] = Math.cos(time * .1)
                    camera.position[1] = 0
                    camera.position[2] = Math.sin(time * .1)
                    camera.lookAt(vec3.fromValues(0, 0, 0))
                    // camera.updateMatrix()

                    // 获取相机视图矩阵
                    mat4.copy(viewMatrix, camera.matrixWorldInvert)
                    // mat4.invert(viewMatrix,viewMatrix)
                    // 我们只关心方向所以清除移动的部分
                    viewMatrix[12] = 0
                    viewMatrix[13] = 0
                    viewMatrix[14] = 0

                    mat4.mul(viewDirectionProjectionMatrix, camera.projectionMatrix, viewMatrix)
                    mat4.invert(viewDirectionProjectionInverseMatrix, viewDirectionProjectionMatrix)


                    envmap.draw({
                        u_viewDirectionProjectionInverse: viewDirectionProjectionInverseMatrix,
                        // viewMatrix:camera.viewMatrix
                    })
                    //  ticker.cancel()
                })
            }
        }
    }
})

addExample("drawimage", function () {
    return {
        template: `<div><div ref="main"></div></div>`,
        extends: BaseComponent,
        data() { return {}; },
        computed: {},
        methods: {
            /**
            * @param {createREGL.Regl} regl
            */
            init(regl) {

                let imageTexture = regl.texture({

                    width: 160,
                    height: 24,
                    data: imageResources.diamonds.image,
                    format: "rgba",
                    wrap: "clamp",
                    mag: "linear",
                    type: "uint8",
                    //   colorSpace:"browser",
                    //   premultiplyAlpha:false
                    flipY: true
                })
                let buildRect = function (x, y, width, height) {

                    return [
                        x, y,
                        x + width, y,
                        x, y + height,
                        x, y + height,
                        x + width, y,
                        x + width, y + height
                    ]
                }
                let dragRect = regl({
                    context: {
                        projection: function (context) {
                            return mat3.projection([], context.viewportWidth, context.viewportHeight)
                        }
                    },
                    vert: `
                     precision mediump float;
                     attribute vec2 position;
                     uniform mat3 projection;
                     void main(){
                         vec3 pos=projection*vec3(position,1.0);
                         gl_Position=vec4(pos.xy,0,1.0);
                     }
                     `,
                    frag: `
                     precision mediump float;
                     uniform vec4 color;
                     void main () {
                       gl_FragColor = color;
                     }`,
                    attributes: {
                        position: buildRect(100, 100, 160, 24)
                    },
                    uniforms: {
                        projection: regl.context('projection'),
                        color: [1.0, 0, 0, 1]
                    },
                    count: 6,
                    primitive: "triangles"
                })
                let dragImage = regl({
                    context: {
                        projection: function (context) {
                            return mat3.projection([], context.viewportWidth, context.viewportHeight)
                        }
                    },
                    vert: `
                     precision mediump float;
                     attribute vec2 position;
                     attribute vec2 auv;
                     uniform mat3 projection;
                     varying vec2 uv;
                     void main(){
                         vec3 pos=projection*vec3(position,1.0);
                         gl_Position=vec4(pos.xy,0,1.0);
                         uv=auv;
                     }
                     `,
                    frag: `
                     precision mediump float;
                     uniform sampler2D texture;
                     varying vec2 uv;
                     void main () {
                       gl_FragColor = texture2D(texture, uv);
                     }`,
                    attributes: {
                        position: buildRect(100, 100, 160, 24),
                        auv: [
                            0, 1,
                            1, 1,
                            0, 0,
                            0, 0,
                            1, 1,
                            1, 0
                        ]
                    },
                    uniforms: {
                        projection: regl.context('projection'),
                        texture: imageTexture
                    },
                    blend: {
                        enable: true,
                        func: {
                            src: "src alpha",
                            dst: "one minus src alpha"
                        }
                    },
                    count: 6,
                    primitive: "triangles"
                })

                regl.clear({
                    depth: 1,
                    color: [0, 0, 0, 1.0],
                    stencil: 1
                })
                // dragRect()
                dragImage({})
            }
        },
        mounted() {
            var container = this.$refs.main;
        }
    }
})


addExample("摄像机", function () {
    function createCameraBufferInfo(scale = 1) {
        // 首先,让我们添加一个立方体。它的范围是 1 到 3,
        // 因为相机看向的是 -Z 方向,所以我们想要相机在 Z = 0 处开始。
        // 我们会把一个圆锥放到该立方体的前面,
        // 且该圆锥的开口方向朝 -Z 方向。
        const positions = [
            -1, -1, 1,  // 立方体的顶点
            1, -1, 1,
            -1, 1, 1,
            1, 1, 1,
            -1, -1, 3,
            1, -1, 3,
            -1, 1, 3,
            1, 1, 3,
            0, 0, 1,  // 圆锥的尖头
        ];
        const indices = [
            0, 1, 1, 3, 3, 2, 2, 0, // 立方体的索引
            4, 5, 5, 7, 7, 6, 6, 4,
            0, 4, 1, 5, 3, 7, 2, 6,
        ];
        // 添加圆锥的片段
        const numSegments = 6;
        const coneBaseIndex = positions.length / 3;
        const coneTipIndex = coneBaseIndex - 1;
        for (let i = 0; i < numSegments; ++i) {
            const u = i / numSegments;
            const angle = u * Math.PI * 2;
            const x = Math.cos(angle);
            const y = Math.sin(angle);
            positions.push(x, y, 0);
            // 从圆锥尖头到圆锥边缘的线段
            indices.push(coneTipIndex, coneBaseIndex + i);
            // 从圆锥边缘一点到圆锥边缘下一点的线段
            indices.push(coneBaseIndex + i, coneBaseIndex + (i + 1) % numSegments);
        }
        positions.forEach((v, ndx) => {
            positions[ndx] *= scale;
        });
        return { positions, indices }
    }
    return {
        template: `<div><div ref="main"></div></div>`,
        extends: BaseComponent,
        data() { return {}; },
        computed: {},
        methods: {
            /**
            * @param {createREGL.Regl} regl
            */
            init(regl) {

                let box = new THREE.BoxBufferGeometry(1, 1, 1)
                let position = box.getAttribute('position').array
                let elements = box.getIndex().array
                let { positions: cameraPositions, indices: cameraIndices } = createCameraBufferInfo(1)
                let drawCamera = regl({
                    vert: `
                     precision mediump float;
                     attribute vec3 position;
                     void main(){
                         gl_Position=vec4(position,1.0);
                     }
                     `,
                    frag: `
                     precision mediump float;
                     uniform vec4 color;
                     void main () {
                       gl_FragColor = color;
                     }`,
                    attributes: {
                        position: cameraPositions,
                    },
                    uniforms: {
                        color: [1.0, 0, 0, 1]
                    },
                    elements: regl.elements({
                        primitive: "lines",
                        data: new Uint16Array(cameraIndices),
                        //  length:position.length,
                        //    count:elements.length,
                        type: "uint16"
                    }),
                    // count:position.length

                })


                regl.clear({
                    depth: 1,
                    color: [0, 0, 0, 1.0],
                    stencil: 1
                })
                drawCamera()
            }
        },
        mounted() {
            var container = this.$refs.main;
        }
    }
})

addExample("three", function () {
    return {
        template: `<div><div ref="main"></div></div>`,
        data() { return {}; },
        computed: {},
        methods: {},
        mounted() {
            var container = this.$refs.main;
            let renderer = new THREE.WebGLRenderer({
                antialias: true
            })
            container.appendChild(renderer.domElement)
            renderer.setSize(500, 500)

            renderer.setClearColor(0x000000)
            renderer.clearColor()
            let camera = new THREE.PerspectiveCamera(50, 1, 0.001, 1000)
            camera.position.set(0, 1, 2)
            camera.lookAt(0, 0, 0)

            let geometry = new THREE.BoxBufferGeometry(1, 1, 1)
            let box = new THREE.Mesh(geometry, new THREE.MeshBasicMaterial({
                color: 0xff0000
            }))
            let scene = new THREE.Scene()

            scene.add(box)
            renderer.render(scene, camera)
        }
    }
})


addExample("callface", function () {

    let width = 500, height = 500

    return {
        extends: BaseComponent,
        data() {
            return {
                width: width,
                height: height
            }
        },
        methods: {
            /**
             * @param {createREGL.Regl} regl
            */
            init(regl) {

                let projectMatrix = mat3.create()
                mat3.projection(projectMatrix, width, height)
                const modelMatrix = mat3.create()

                const createRect = (x, y, w, h) => {
                    // 顺时针,反面
                    let clockwise = new Float32Array([
                        x, y,
                        x, y + h,
                        x + w, y,

                    ])
                    // 逆时针,正面
                    let inverse = new Float32Array([
                        x + w, y + h,
                        x, y + h,
                        x + w, y])
                    return {
                        clockwise,
                        inverse
                    }
                }

                let { clockwise, inverse } = createRect(100, 100, 100, 100)

                let fillRectScope = regl({
                    vert: `
                        attribute vec2 position;
                        uniform mat3 projectMatrix;
                        uniform mat3 modelMatrix;
                        void main(){
                            vec3 _position=projectMatrix* modelMatrix *vec3(position,1);
                            gl_Position=vec4(vec2(_position),0,1.0);
                        }
                    `,
                    frag: `
                        precision mediump float;
                        uniform vec4 color;
                        void main(){
                            gl_FragColor=color;
                        }
                    `,
                    primitive: "triangles",
                    uniforms: {
                        projectMatrix: projectMatrix,
                        modelMatrix: modelMatrix,
                    },
                    //frontFace: 'ccw'
                    colorMask: [true, true, true, true],
                    depth: {
                        enable: true,
                        // mask: false
                    },
                    //    cull:{
                    //         enable:true
                    //    }
                })
                let fillRect = regl({
                    // blend:regl.prop('blend'),
                    attributes: {
                        position: regl.prop('position')
                    },
                    uniforms: {
                        color: regl.prop('color')
                    },
                    count: (c, props, bachId) => {
                        return props.position.length / 2
                    },
                    // ccw(逆时为正面,顺时为反面) 默认,cw(逆时为反面,顺时为正面)
                    frontFace: regl.prop('frontFace'),
                    cull: {
                        // 是否启用易除正面或反面,如果禁用,就同时绘制正反面
                        enable: regl.prop('cull.enable'),
                        // 剔除反面
                        face: regl.prop('cull.face'),
                    }
                })

                const guiData = addGuiScheme(this.$gui, {
                    source: {
                        cullFace: 'back',
                        cullFace2: 'back',
                        frontFace: "ccw"
                    },
                    schemes: {
                        cullFace: {
                            type: "list",
                            params: ['back', 'front']
                        },
                        cullFace2: {
                            type: "list",
                            params: ['back', 'front']
                        },
                        frontFace: {
                            type: "list",
                            params: ['ccw', 'cw']
                        }
                    }
                })

                let ticker = regl.frame(() => {
                    regl.clear({
                        color: [1, 1, 1, 1],
                        depth: 1
                    })

                    fillRectScope(() => {
                        fillRect({
                            position: clockwise,
                            color: [1, 0, 0, 1],
                            frontFace: guiData.frontFace,
                            cull: {
                                enable: true,
                                face: guiData.cullFace
                            }
                        })
                        fillRect({
                            position: inverse,
                            color: [0, 1, 0, 1],
                            frontFace: guiData.frontFace,
                            cull: {
                                enable: true,
                                face: guiData.cullFace2
                            }
                        })
                    })
                })
            }
        }
    }
})

addExample("blend", function () {

    let width = 300, height = 300
    /**
     * blendFunc(sfactor, dfactor)
     * 下列常数可用于  sfactor 和dfactor.
  
  混合颜色的公式可以这样描述: color(RGBA) = (sourceColor * sfactor) + (destinationColor * dfactor). RBGA 值在 0 到 1 之间。
  
   S=srcColor
   C=blendColor
   D=distColor

   Constant	Factor	Description
    持续的	因素	描述
    gl.ZERO	0,0,0,0	将所有颜色乘以 0。
    gl.ONE	1,1,1,1	将所有颜色乘以 1。
    gl.SRC_COLOR	R S , G S , B S , A S	将所有颜色乘以源颜色。
    gl.ONE_MINUS_SRC_COLOR	1-R S , 1-G S , 1-B S , 1-A S	将所有颜色乘以 (1 减去每种源颜色)。
    gl.DST_COLOR	R D , G D , B D , A D	将所有颜色乘以目标颜色。
    gl.ONE_MINUS_DST_COLOR	1-R D , 1-G D , 1-B D , 1-A D	将所有颜色乘以 (1 减去每种目标颜色)。
    gl.SRC_ALPHA	A S , A S , A S , A S	将所有颜色乘以源 Alpha 值。
    gl.ONE_MINUS_SRC_ALPHA	1-A S , 1-A S , 1-A S , 1-A S	将所有颜色乘以 (1 减去源 Alpha 值)。
    gl.DST_ALPHA	A D , A D , A D , A D	将所有颜色乘以目标 alpha 值。
    gl.ONE_MINUS_DST_ALPHA	1-A D , 1-A D , 1-A D , 1-A D	将所有颜色乘以 (1 减去目标 alpha 值)。
    gl.CONSTANT_COLOR	R C , G C , B C , A C	将所有颜色乘以一个常数颜色。
    gl.ONE_MINUS_CONSTANT_COLOR	1-R C , 1-G C , 1-B C , 1-A C	将所有颜色乘以 (1 减去一个常数颜色)。
    gl.CONSTANT_ALPHA	A C , A C , A C , A C	将所有颜色乘以恒定的 alpha 值。
    gl.ONE_MINUS_CONSTANT_ALPHA	1-A C , 1-A C , 1-A C , 1-A C	将所有颜色乘以 (1 减去恒定的 alpha 值)。
    gl.SRC_ALPHA_SATURATE	min(A S , 1 - A D ), min(A S , 1 - A D ), min(A S , 1 - A D ), 1	将 RGB 颜色乘以源 Alpha 值或 1 减去目标 Alpha 值中的较小者。alpha 值乘以 1。
  
  将 RGB 颜色乘以源 alpha 值或 1 减去目标 alpha 值中的较小值。alpha 值乘以 1.

  s0表示源(深度近),d表示目的(深度远),c表示有glBlendColor设置进来的常量。
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //默认是这个 sourceColor=[0,1,0,0.6] distColor=[1,0,0,1]   rgba=sourceColor*0.6+(distColor*(1-0.6))
 深度小的是source,深度大的是destination.
 


 blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha)
 以下常量可用于srcRGB、dstRGB、 srcAlpha和dstAlpha

混合因子的公式可以这样描述(所有 RGBA 值都在 0 和 1 之间):

颜色(RGB) = (sourceColor * srcRGB ) + (destinationColor * dstRGB )
颜色(A) = (sourceAlpha * srcAlpha ) + (destinationAlpha * dstAlpha )
    */
    return {
        template: `<div @mousedown="onDown" @mousemove="onMove" @mouseup="onUp">
        <div>
            <div class="row">
                <div class="col-auto">
                <div>canvas</div>
                <canvas ref="preview" :width="width" :height="height"></canvas>
                 </div>
                 <div class="col-auto">
                 <div>webgl</div>
                 <div ref="container" :style="style"></div>
                 </div>
         </div>
        </div>
      
        </div>`,
        extends: BaseComponent,
        data() {
            return {
                width: width,
                height: height,
                src: [],
                extensions: ['EXT_blend_minmax', 'EXT_blend_minmax']
            }
        },
        methods: {
            calcBlendColor(type, sourcColor, distColor, blendColor) {
                blendColor = blendColor || [0, 0, 0, 0]
                let [r, g, b, a] = sourcColor
                let [dr, dg, db, da] = distColor
                let [br, bg, bb, ba] = blendColor
                // let tColor=tinycolor.fromRatio({ r: color[0], g: color[1], b: color[] });
                if (type === 'zero') {
                    return [0, 0, 0, 0]
                } else if (type === 'one') {
                    return [1, 1, 1, 1]
                } else if (type === 'src color') {
                    return [r, g, b, a]
                } else if (type === 'one minus src color') {
                    return [1 - r, 1 - g, 1 - b, 1 - a]
                } else if (type === 'dst color') {
                    return [dr, dg, db, da]
                } else if (type === 'one minus dst color') {
                    return [1 - dr, 1 - dg, 1 - db, 1 - da]
                } else if (type === 'src alpha') {
                    return [a, a, a, a]
                } else if (type === 'one minus src alpha') {
                    return [1 - a, 1 - a, 1 - a, 1 - a]
                } else if (type === 'dst alpha') {
                    return [da, da, da, da]
                } else if (type === 'one minus dst alpha') {
                    return [1 - da, 1 - da, 1 - da, 1 - da]
                } else if (type === 'constant color') {
                    return [br, bg, bb, ba]
                } else if (type === 'one minus constant color') {
                    return [1 - br, 1 - bg, 1 - bb, 1 - ba]
                } else if (type === 'constant alpha') {
                    return [ba, ba, ba, ba]
                } else if (type === 'one minus constant alpha') {
                    return [1 - ba, 1 - ba, 1 - ba, 1 - ba]
                } else if (type === 'src alpha saturate') {
                    // min(A S , 1 - A D ), min(A S , 1 - A D ), min(A S , 1 - A D ), 1
                    return [Math.min(a, 1 - da), Math.min(a, 1 - da), Math.min(a, 1 - da), 1]
                }
                return [1, 1, 1, 1]
            },
            multColor(a, b) {
                return [a[0] * b[0], a[1] * b[1], a[2] * b[2], a[3] * b[3]]
            },
            createPreview() {
                let preview = this.$refs.preview
                let ctx = preview.getContext('2d')
                let blendColor = [0, 0, 0, 0];
                //   let srcColor=[0, 1, 0, 1],distColor= [1, 0, 0, 1]
                let width = this.width, height = this.height
                let batchId = 0
                let eachDrawRect = (rect, callback) => {
                    let x = rect[0], x2 = rect[0] + rect[2], y = rect[1], y2 = rect[1] + rect[3]
                    for (let r = y; r < y2; r++) {
                        for (let c = x; c < x2; c++) {
                            let index = (r * rect[2] + c) * 4
                            callback(index, r, c)
                        }
                    }
                }

                let drawBlendRect = (sourceColor, equation, sourceFactorType, sAlphaType, destinationFactorType, dAlphaType, rect) => {
                    batchId++
                    // 获取当前区域像表
                    let imageData = ctx.getImageData(rect[0], rect[1], rect[2], rect[3])
                    let data = imageData.data

                    eachDrawRect([0, 0, rect[2], rect[3]], (index, r, c) => {
                        let dstR = data[index] / 255, dstG = data[index + 1] / 255, dstB = data[index + 2] / 255, dstA = data[index + 3] / 255
                        let destinationColor = [dstR, dstG, dstB, dstA]

                        //  混合颜色的公式可以这样描述: color(RGBA) = (sourceColor * sfactor) + (destinationColor * dfactor). RBGA 值在 0 到 1 之间。
                        let sourceFactorColor = this.calcBlendColor(sourceFactorType, sourceColor, destinationColor)
                        let destinationFactorColor = this.calcBlendColor(destinationFactorType, sourceColor, destinationColor)
                        // 计算透明值
                        let sourceFactorAlpha = this.calcBlendColor(sAlphaType, sourceColor, destinationColor)
                        let destinationFactorAlpha = this.calcBlendColor(dAlphaType, sourceColor, destinationColor)
                        let sAlpha = sourceFactorAlpha[3], dAlpha = destinationFactorAlpha[3]
                        let rgba = []
                        if (equation == 'add') {
                            rgba[0] = sourceColor[0] * sourceFactorColor[0] + destinationColor[0] * destinationFactorColor[0]
                            rgba[1] = sourceColor[1] * sourceFactorColor[1] + destinationColor[1] * destinationFactorColor[1]
                            rgba[2] = sourceColor[2] * sourceFactorColor[2] + destinationColor[2] * destinationFactorColor[2]
                            //  rgba[3]=sourceColor[3]*sourceFactorColor[3]+destinationColor[3]*destinationFactorColor[3]
                            rgba[3] = sourceColor[3] * sAlpha + destinationColor[3] * dAlpha
                        } else if (equation == 'subtract') {
                            rgba[0] = sourceColor[0] * sourceFactorColor[0] - destinationColor[0] * destinationFactorColor[0]
                            rgba[1] = sourceColor[1] * sourceFactorColor[1] - destinationColor[1] * destinationFactorColor[1]
                            rgba[2] = sourceColor[2] * sourceFactorColor[2] - destinationColor[2] * destinationFactorColor[2]
                            // rgba[3]=sourceColor[3]*sourceFactorColor[3]-destinationColor[3]*destinationFactorColor[3]
                            rgba[3] = sourceColor[3] * sAlpha - destinationColor[3] * dAlpha
                        } else if (equation == 'reverse subtract') {
                            rgba[0] = destinationColor[0] * destinationFactorColor[0] - sourceColor[0] * sourceFactorColor[0]
                            rgba[1] = destinationColor[1] * destinationFactorColor[1] - sourceColor[1] * sourceFactorColor[1]
                            rgba[2] = destinationColor[2] * destinationFactorColor[2] - sourceColor[2] * sourceFactorColor[2]
                            // rgba[3]=destinationColor[3]*destinationFactorColor[3]-sourceColor[3]*sourceFactorColor[3]
                            rgba[3] = destinationColor[3] * dAlpha - sourceColor[3] * sAlpha
                        } else if (equation == 'min') {
                            rgba[0] = Math.min(sourceColor[0] * sourceFactorColor[0], destinationColor[0] * destinationFactorColor[0])
                            rgba[1] = Math.min(sourceColor[1] * sourceFactorColor[1], destinationColor[1] * destinationFactorColor[1])
                            rgba[2] = Math.min(sourceColor[2] * sourceFactorColor[2], destinationColor[2] * destinationFactorColor[2])
                            // rgba[3]=Math.min(sourceColor[3]*sourceFactorColor[3],destinationColor[3]*destinationFactorColor[3])
                            rgba[3] = Math.min(sourceColor[3] * sAlpha, destinationColor[3] * dAlpha)
                        } else if (equation == 'max') {
                            rgba[0] = Math.max(sourceColor[0] * sourceFactorColor[0], destinationColor[0] * destinationFactorColor[0])
                            rgba[1] = Math.max(sourceColor[1] * sourceFactorColor[1], destinationColor[1] * destinationFactorColor[1])
                            rgba[2] = Math.max(sourceColor[2] * sourceFactorColor[2], destinationColor[2] * destinationFactorColor[2])
                            // rgba[3]=Math.max(sourceColor[3]*sourceFactorColor[3],destinationColor[3]*destinationFactorColor[3])
                            rgba[3] = Math.max(sourceColor[3] * sAlpha, destinationColor[3] * dAlpha)
                        }
                        data[index] = rgba[0] * 255
                        data[index + 1] = rgba[1] * 255
                        data[index + 2] = rgba[2] * 255
                        data[index + 3] = rgba[3] * 255

                    })
                    ctx.putImageData(imageData, rect[0], rect[1])
                }
                let drawRect = (sourceColor, rect) => {
                    let imageData = ctx.getImageData(rect[0], rect[1], rect[2], rect[3])
                    let data = imageData.data
                    eachDrawRect([0, 0, rect[2], rect[3]], (index, r, c) => {
                        data[index] = sourceColor[0] * 255
                        data[index + 1] = sourceColor[1] * 255
                        data[index + 2] = sourceColor[2] * 255
                        data[index + 3] = sourceColor[3] * 255

                    })
                    ctx.putImageData(imageData, rect[0], rect[1])
                }
                return {
                    clear: () => {
                        batchId = 0
                        //ctx.clearRect(0,0,width,height)
                        ctx.fillStyle = '#000'
                        ctx.fillRect(0, 0, width, height)
                    },
                    drawRect: drawRect,
                    drawBlendRect: drawBlendRect
                }

            },
            createRect: function (x, y, w, h) {

                return new Float32Array([
                    x, y,
                    x, y + h,
                    x + w, y,
                    x + w, y + h,
                    x + w, y,
                    x, y + h
                ])
            },
            /**
             * @param {createREGL.Regl} regl
            */
            init(regl) {


                let projectMatrix = mat3.create()
                mat3.projection(projectMatrix, width, height)
                const modelMatrix = mat3.create()



                let destRect = this.createRect(100, 100, 100, 100)
                let srcRect = this.createRect(150, 100, 100, 100)
                let fillRect = regl({
                    vert: `
                        attribute vec2 position;
                        uniform mat3 projectMatrix;
                        uniform mat3 modelMatrix;
                        void main(){
                            vec3 _position=projectMatrix* modelMatrix *vec3(position,1);
                            gl_Position=vec4(vec2(_position),0,1.0);
                        }
                    `,
                    frag: `
                        precision mediump float;
                        uniform vec4 color;
                        void main(){
                            gl_FragColor=color;
                        }
                    `,
                    primitive: "triangles",
                    attributes: {
                        position: regl.prop('position')
                    },
                    uniforms: {
                        projectMatrix: projectMatrix,
                        modelMatrix: modelMatrix,
                        color: regl.prop('color')
                    },
                    //frontFace: 'ccw'
                    // colorMask: [true, true, true, true],
                    depth: {
                        enable: true,
                        mask: true, // 是否禁用写入深度缓存区
                        range: [0, 1],
                        /*
                        gl.NEVER(从不通过)
                        gl.LESS(如果传入值小于深度缓冲区值则通过)
                        gl.EQUAL(如果传入值等于深度缓冲区值,则通过)
                        gl.LEQUAL(如果传入值小于或等于深度缓冲区值,则通过)
                        gl.GREATER(如果传入值大于深度缓冲区值则通过)
                        gl.NOTEQUAL(如果传入值不等于深度缓冲区值则通过)
                        gl.GEQUAL(如果传入值大于或等于深度缓冲区值则通过)
                        gl.ALWAYS(总是通过)
                        */
                        func: regl.prop('depthFunc')

                    },
                    stencil:{
                        enable:regl.prop('stencil.enable'),
                        mask:regl.prop('stencil.mask'),
                        func:regl.prop('stencil.func'),
                        op:regl.prop('stencil.op'),
                       // opBack:regl.prop('stencil.opBack'),
                    },
                    blend: {
                        enable: regl.prop('blend.enable'),
                        equation: regl.prop('blend.equation'),
                        color: regl.prop('blendColor'),
                        func: function (ctx, prop, batchId) {
                            return prop.blend.enable ? prop.blend.func : {
                                srcRGB: "one",
                                srcAlpha: 1,
                                dstRGB: "zero",
                                dstAlpha: 0
                            }
                        }
                    },
                    count: function (ctx, props) {
                        return props.position.length / 2
                    }

                })
                const stencilOperationType =
                /* `gl.ZERO` */
                ["zero" ,
                /* `gl.KEEP` */
                "keep" ,
                /* `gl.REPLACE` */
                "replace" ,
                /* `gl.INVERT` */
                "invert" ,
                /* `gl.INCR` */
                "increment" ,
                /* `gl.DECR` */
                "decrement" ,
                /* `gl.INCR_WRAP` */
                "increment wrap" ,
                /* `gl.DECR_WRAP` */
                "decrement wrap"];
                /** 
                gl.KEEP
                保持当前值。
                
                gl.ZERO
                将模板缓冲区值设置为 0。
                
                gl.REPLACE
                将模板缓冲区值设置为 指定的参考值 WebGLRenderingContext.stencilFunc()。
                
                gl.INCR
                增加当前模板缓冲区值。钳位到最大可表示的无符号值。
                
                gl.INCR_WRAP
                增加当前模板缓冲区值。当递增最大可表示无符号值时,将模板缓冲区值包装为零。
                
                gl.DECR
                减少当前模板缓冲区值。钳位到 0。
                
                gl.DECR_WRAP
                减少当前模板缓冲区值。当递减模板缓冲区值 0 时,将模板缓冲区值包装为最大可表示无符号值。
                
                gl.INVERT
                按位反转当前模板缓冲区值。
                **/
                let blendFuncs = {
                    'zero': 'gl.ZERO',
                    'one': 'gl.ONE',
                    'src color': 'gl.SRC_COLOR',
                    'one minus src color': 'gl.ONE_MINUS_SRC_COLOR',
                    'src alpha': 'gl.SRC_ALPHA',
                    'one minus src alpha': 'gl.ONE_MINUS_SRC_ALPHA',
                    'dst color': 'gl.DST_COLOR',
                    'one minus dst color': 'gl.ONE_MINUS_DST_COLOR',

                    'dst alpha': 'gl.DST_ALPHA',
                    'one minus dst alpha': 'gl.ONE_MINUS_DST_ALPHA',
                    'constant color': 'gl.CONSTANT_COLOR',

                    'one minus constant color': 'gl.ONE_MINUS_CONSTANT_COLOR',
                    'constant alpha': 'gl.CONSTANT_ALPHA',
                    'one minus constant alpha': 'gl.ONE_MINUS_CONSTANT_ALPHA',
                    'src alpha saturate': 'gl.SRC_ALPHA_SATURATE',
                }
                blendFuncs = Object.keys(blendFuncs).reduce((a, b) => {
                    a[blendFuncs[b]] = b
                    return a
                }, {})
                const equations = ['add', 'subtract', 'reverse subtract', 'min', 'max']
                const guiData = addGuiScheme(this.$gui, {
                    source: {
                        depthFunc: 'lequal',// webgl默认是less
                        blendColor:'0,0,0,0',
                        blendEnable: false,
                        equation: 'add',
                        color:'1,0,0,1',
                        srcFactor: 'one',
                        dstFactor: 'zero',
                        srcAlpha: 'one',
                        dstAlpha: 'zero',
                        blendEnable2: true,
                        equation2: 'add',
                        color2:'0,1,0,0.5',
                        srcFactor2: 'one',
                        dstFactor2: 'zero',
                        srcAlpha2: 'one',
                        dstAlpha2: 'zero',
                        stencil:{
                            enable:true,
                            mask:1,
                            func:{
                                cmp:"always",
                                ref:0,
                                mask:1,
                            },
                            op:{
                                fail:"keep",
                                zfail:"keep",
                                zpass:"keep"
                            }
                        },
                        stencil2:{
                            enable:false,
                            mask:1,
                            func:{
                                cmp:"always",
                                ref:0,
                                mask:1,
                            },
                            op:{
                                fail:"keep",
                                zfail:"keep",
                                zpass:"keep"
                            }
                        }
                    },
                    schemes: {
                        depthFunc: {
                            type: "list",
                            params: ["never",
                                /* `gl.ALWAYS` */
                                "always",
                                /* `gl.LESS` */
                                "less", "<",
                                /* `gl.LEQUAL` */
                                "lequal", "<=",
                                /* `gl.GREATER` */
                                "greater", ">",
                                /* `gl.GEQUAL` */
                                "gequal", ">=",
                                /* `gl.EQUAL` */
                                "equal", "=",
                                /* `gl.NOTEQUAL` */
                                "notequal", "!="]
                        },
                        srcFactor: {
                            type: "list",
                            params: blendFuncs
                        },
                        dstFactor: {
                            type: "list",
                            params: blendFuncs
                        },
                        srcFactor2: {
                            type: "list",
                            params: blendFuncs
                        },
                        dstFactor2: {
                            type: "list",
                            params: blendFuncs
                        },
                        equation: {
                            type: "list",
                            params: equations
                        },
                        equation2: {
                            type: "list",
                            params: equations
                        },
                        srcAlpha: {
                            type: "list",
                            params: blendFuncs
                        },
                        dstAlpha: {
                            type: "list",
                            params: blendFuncs
                        },
                        srcAlpha2: {
                            type: "list",
                            params: blendFuncs
                        },
                        dstAlpha2: {
                            type: "list",
                            params: blendFuncs
                        },
                        stencil:{
                            schemes:{
                                func:{
                                   schemes:{
                                      cmp:{
                                        type:"list",
                                        params: ["never",
                                        /* `gl.ALWAYS` */
                                        "always",
                                        /* `gl.LESS` */
                                        "less", "<",
                                        /* `gl.LEQUAL` */
                                        "lequal", "<=",
                                        /* `gl.GREATER` */
                                        "greater", ">",
                                        /* `gl.GEQUAL` */
                                        "gequal", ">=",
                                        /* `gl.EQUAL` */
                                        "equal", "=",
                                        /* `gl.NOTEQUAL` */
                                        "notequal", "!="]
                                      }
                                   }
                                },
                                op:{
                                    schemes:{
                                        fail:{
                                            type:"list",
                                            params:stencilOperationType
                                        },
                                        zfail:{
                                            type:"list",
                                            params:stencilOperationType
                                        },
                                        zpass:{
                                            type:"list",
                                            params:stencilOperationType
                                        }
                                    }
                                }
                            }
                        },
                        stencil2:{
                            schemes:{
                                func:{
                                   schemes:{
                                      cmp:{
                                        type:"list",
                                        params: ["never",
                                        /* `gl.ALWAYS` */
                                        "always",
                                        /* `gl.LESS` */
                                        "less", "<",
                                        /* `gl.LEQUAL` */
                                        "lequal", "<=",
                                        /* `gl.GREATER` */
                                        "greater", ">",
                                        /* `gl.GEQUAL` */
                                        "gequal", ">=",
                                        /* `gl.EQUAL` */
                                        "equal", "=",
                                        /* `gl.NOTEQUAL` */
                                        "notequal", "!="]
                                      }
                                   }
                                },
                                op:{
                                    schemes:{
                                        fail:{
                                            type:"list",
                                            params:stencilOperationType
                                        },
                                        zfail:{
                                            type:"list",
                                            params:stencilOperationType
                                        },
                                        zpass:{
                                            type:"list",
                                            params:stencilOperationType
                                        }
                                    }
                                }
                            }
                        }
                    },
                    onFinishChange: () => {
                        renderDraw()
                    }
                })

                const { clear, drawRect, drawBlendRect } = this.createPreview()
                const renderDraw = () => {
                    let color=guiData.color.split(',').map(Number)
                    let color2=guiData.color2.split(',').map(Number)
                    let blendColor=guiData.blendColor.split(',').map(Number)
                    regl.clear({
                        color: [0, 0, 0, 1],
                        depth: 1,
                        stencil:0
                    })
                    fillRect([{
                        position: destRect,
                        color: color,
                        blendColor:blendColor,
                        blend: {
                            enable: guiData.blendEnable,
                            func: {
                                srcRGB: guiData.srcFactor,
                                srcAlpha: guiData.srcAlpha,
                                dstRGB: guiData.dstFactor,
                                dstAlpha: guiData.dstAlpha
                            },
                            equation: guiData.equation
                        },
                        stencil:{
                            enable:guiData.stencil.enable,
                            mask:guiData.stencil.mask,
                            func:guiData.stencil.func,
                            op:guiData.stencil.op
                        },
                        depthFunc: guiData.depthFunc
                    }, {
                        position: srcRect,
                        color: color2,
                        blendColor:blendColor,
                        blend: {
                            enable: guiData.blendEnable2,
                            func: {
                                srcRGB: guiData.srcFactor2,
                                srcAlpha: guiData.srcAlpha2,
                                dstRGB: guiData.dstFactor2,
                                dstAlpha: guiData.dstAlpha2
                            },
                            equation: guiData.equation2
                        },
                        stencil:{
                            enable:guiData.stencil2.enable,
                            mask:guiData.stencil2.mask,
                            func:guiData.stencil2.func,
                            op:guiData.stencil2.op
                        },
                        depthFunc: guiData.depthFunc

                    }])
                    clear()
                    drawBlendRect([1, 0, 0, 1], guiData.equation, guiData.srcFactor, guiData.srcAlpha, guiData.dstFactor, guiData.dstAlpha, [100, 100, 100, 100])
                    drawBlendRect([0, 1, 0, 1], guiData.equation2, guiData.srcFactor2, guiData.srcAlpha2, guiData.dstFactor2, guiData.dstAlpha2, [150, 100, 100, 100])
                }
                renderDraw()
            }
        }
    }
})

addExample("渲染大量数量(快)", function () {
    let box = new THREE.BoxBufferGeometry(1, 1, 1)
    let boxObj = new THREE.Object3D()
    let boxPosition = box.attributes.position.array
    let boxElements = box.getIndex().array
    // let camera = new THREE.OrthographicCamera(800 / -2, 800 / 2, 600 / 2, 600 / -2, 0.1, 1000)
    let camera = new THREE.PerspectiveCamera(50, 800 / 600, 0.1, 10000)
    camera.position.set(0, 1, 5)

    camera.updateWorldMatrix(false, false)
    return {
        template: `<div><canvas width="800" height="600" ref="main"></canvas></div>`,
        data() { return {}; },
        mounted() {
            var container = this.$refs.main;
            let regl = window.regl = createREGL({
                canvas: container,
            })
            var oribt = new THREE.OrbitControls(camera, regl._gl.canvas)
            let setupDraw = regl({
                context: {
                    projectionMatrix(context, props) {
                        return camera.projectionMatrix.elements
                    }
                },
                attributes: {
                    position: regl.prop('position'),
                },
                uniforms: {
                    projectionMatrix: regl.context('projectionMatrix'),
                    // modelViewMatrix:regl.prop('modelViewMatrix'),
                },
                elements: regl.prop('elements')
            })
            let drawRect = regl({
                vert: `
                    attribute vec3 position;
                    uniform mat4 projectionMatrix;
                    uniform mat4 modelViewMatrix;
                    void main(){
                        gl_Position=projectionMatrix*modelViewMatrix*vec4(position,1.0);

                    }
                `,
                frag: `
                    precision mediump float;
                    uniform vec4 color;
                    void main(){
                        gl_FragColor=color;
                    }
                `,
                // attributes: {
                //     position: regl.prop('position'),
                // },
                uniforms: {
                    modelViewMatrix: regl.prop('modelViewMatrix'),
                    color: regl.prop('color')
                },
                //primitive: 'triangle',
                // elements:regl.prop('elements')
                //count: boxPosition.length / 3
            })
            // console.log('boxElements',boxElements)
            // 生成
            const buildCube = (count) => {
                const drawObjects = new THREE.Object3D()
                for (let i = 0; i < count; i++) {
                    let obj = new THREE.Object3D();
                    obj.position.z = -i
                    obj.drawObj = {
                        color: [1, Math.random(), Math.random(), 1],
                        modelViewMatrix: obj.modelViewMatrix.elements
                    }

                    drawObjects.add(obj)
                }
                return drawObjects
            }
            const drawObjects = buildCube(5000)
            const stats = new Stats()
            stats.showPanel(0)
            document.body.appendChild(stats.dom)
            const boxElement = regl.elements({
                primitive: "triangle",
                data: boxElements,
                type: "uint16",
            })
            const render = () => {
                stats.begin()
                regl.clear({
                    color: [1, 1, 1, 1],
                    depth: 1
                })
                camera.updateMatrixWorld()
                drawObjects.updateMatrixWorld();
                setupDraw({
                    position: boxPosition,
                    elements: boxElement,
                }, (context, props) => {
                    const draws = []
                    drawObjects.children.forEach((obj) => {
                        obj.rotation.y+=0.01;
                        obj.modelViewMatrix.multiplyMatrices(camera.matrixWorldInverse, obj.matrixWorld)
                        obj.drawObj.modelViewMatrix = obj.modelViewMatrix.elements
                        draws.push(obj.drawObj)

                        //obj.position.x+=1
                       
                    })
                    drawRect(draws)
                })
                stats.end()

            }
            regl.frame(render)
            oribt.addEventListener('change', () => {
                console.log('oribt')

                // camera.updateProjectionMatrix()
                // render()
            })
            // render()


        }
    }
})

addExample("渲染大量数量(慢)", function () {
    let box = new THREE.BoxBufferGeometry(1, 1, 1)
    let boxObj = new THREE.Object3D()
    let boxPosition = box.attributes.position.array
    let boxElements = box.getIndex().array
    // let camera = new THREE.OrthographicCamera(800 / -2, 800 / 2, 600 / 2, 600 / -2, 0.1, 1000)
    let camera = new THREE.PerspectiveCamera(50, 800 / 600, 0.1, 10000)
    camera.position.set(0, 1, 5)

    camera.updateWorldMatrix(false, false)
    return {
        template: `<div><canvas width="800" height="600" ref="main"></canvas></div>`,
        data() { return {}; },
        mounted() {
            var container = this.$refs.main;
            let regl = window.regl = createREGL({
                canvas: container,
            })
            var oribt = new THREE.OrbitControls(camera, regl._gl.canvas)
            let setupDraw = regl({
                context: {
                    projectionMatrix(context, props) {
                        return camera.projectionMatrix.elements
                    }
                },
                uniforms: {
                    projectionMatrix: regl.context('projectionMatrix'),
                    // modelViewMatrix:regl.prop('modelViewMatrix'),
                }
            })
            let drawRect = regl({
                vert: `
                    attribute vec3 position;
                    uniform mat4 projectionMatrix;
                    uniform mat4 modelViewMatrix;
                    void main(){
                        gl_Position=projectionMatrix*modelViewMatrix*vec4(position,1.0);

                    }
                `,
                frag: `
                    precision mediump float;
                    uniform vec4 color;
                    void main(){
                        gl_FragColor=color;
                    }
                `,
                attributes: {
                    position: regl.prop('position'),
                },
                uniforms: {
                    modelViewMatrix: regl.prop('modelViewMatrix'),
                    color: regl.prop('color')
                },
                elements: regl.prop('elements')
                //primitive: 'triangle',
                // elements:regl.prop('elements')
                //count: boxPosition.length / 3
            })
            // console.log('boxElements',boxElements)
            // 生成
            const buildCube = (count) => {
                const drawObjects = new THREE.Object3D()
                for (let i = 0; i < count; i++) {
                    let obj = new THREE.Object3D();
                    obj.position.z = -i
                    obj.drawObj = {
                        position: boxPosition,
                        elements: boxElement,
                        color: [1, Math.random(), Math.random(), 1],
                        modelViewMatrix: obj.modelViewMatrix.elements
                    }

                    drawObjects.add(obj)
                }
                return drawObjects
            }

            const stats = new Stats()
            stats.showPanel(0)
            document.body.appendChild(stats.dom)
            const boxElement = regl.elements({
                primitive: "triangle",
                data: boxElements,
                type: "uint16",
            })
            const drawObjects = buildCube(5000)
            const render = () => {
                stats.begin()
                regl.clear({
                    color: [1, 1, 1, 1],
                    depth: 1
                })
                camera.updateMatrixWorld()
                drawObjects.updateMatrixWorld();
                setupDraw({
    
                }, (context, props) => {
                    const draws = []
                    drawObjects.children.forEach((obj) => {
                        obj.modelViewMatrix.multiplyMatrices(camera.matrixWorldInverse, obj.matrixWorld)
                        obj.drawObj.modelViewMatrix = obj.modelViewMatrix.elements
                        draws.push(obj.drawObj)

                        //obj.position.x+=1
                       
                    })
                    drawRect(draws)
                })
                stats.end()

            }
            regl.frame(render)
            oribt.addEventListener('change', () => {
                console.log('oribt')

                // camera.updateProjectionMatrix()
                // render()
            })
            // render()


        }
    }
})

addExample("所有blend效果", function () {
    return {
        extends: BaseComponent,
        data() {
            return {
                extensions:['EXT_blend_minmax','EXT_float_blend'],
                width: 1100,
                height: 600,
                devicePixelRatio:1
            };
        },
        computed: {},
        methods: {
            /**
            * @param {createREGL.Regl} regl
           */
            init(regl) {
                function createRect(x, y, w, h) {

                    return new Float32Array([
                        x, y,
                        x, y + h,
                        x + w, y,
                        x + w, y + h,
                        x + w, y,
                        x, y + h
                    ])
                }
                const cameraPosition = [0, 0]
                const superDraw = regl({
                    uniforms: {
                        resolution: (ctx) => {
                            // console.log('viewportWidth',ctx.viewportHeight)
                            return [ctx.viewportWidth, ctx.viewportHeight];
                        },
                        offset: () => {
                            return cameraPosition
                        }
                    },
                    depth: {
                        enable: regl.prop('depth.enable'),
                        func: regl.prop('depth.func')
                    },
                })
                let event = null
                this.$on('down', (e) => {
                    event = { x: e.clientX - cameraPosition[0], y: e.clientY - cameraPosition[1] }
                })
                this.$on('move', (e) => {
                    if (event) {
                        cameraPosition[0] = e.clientX - event.x;
                        cameraPosition[1] = e.clientY - event.y;
                        renderGraphics()
                    }
                })
                this.$on('up', (e) => {
                    event = null
                })


                const draw = regl({
                    vert: `
                            attribute vec2 position;
                            uniform vec2 resolution;
                            uniform vec2 offset;
                            uniform vec2 selfOffset;
                            void main(){
                            
                                 // 从像素坐标转换到 0.0 到 1.0
                                 vec2 zeroToOne = (position+offset+selfOffset) / resolution;
                              
                                 // 再把 0->1 转换 0->2
                                 vec2 zeroToTwo = zeroToOne * vec2(2.0,-2.0);
                              
                                 // 把 0->2 转换到 -1->+1 (裁剪空间)
                                 vec2 clipSpace = zeroToTwo - vec2(1.0,-1.0);
                              
                                 gl_Position = vec4(clipSpace, 0, 1);

                                // gl_Position=vec4(bPos,0,1.0);
                            }
                        `,
                    frag: `
                            precision mediump float;
                            uniform vec4 color;
                            void main(){
                                gl_FragColor=color;
                            }
                        `,
                    attributes: {
                        position: regl.prop('position')
                    },
                    uniforms: {
                        color: regl.prop('color'),
                        selfOffset: (ctx, prop) => {
                            return prop.selfOffset ? prop.selfOffset : [0, 0]
                        }
                    },
                    blend: {
                        enable: regl.prop('blend.enable'),
                        equation: regl.prop('blend.equation'),
                        func: function (ctx, prop, batchId) {
                            //{ src: 'src alpha', dst: 'one minus src alpha' }
                            // {
                            //     srcRGB:prop.blend.func.src,
                            //     dstRGB:prop.blend.func.dst,
                            //     srcAlpha:"one",
                            //     dstAlpha:"one"
                            // } 
                            return prop.blend.enable ?{
                                
                                    srcRGB:prop.blend.func.src,
                                    dstRGB:prop.blend.func.dst,
                                    srcAlpha:prop.blend.func.srcAlpha,
                                    dstAlpha:prop.blend.func.dstAlpha
                                
                            }: false ? { src: 'src alpha', dst: 'one minus src alpha' } : {
                                src: "one",
                                dst: "zero"
                            }
                        },
                        color: [0, 0, 0, 0]
                    },
                    primitive: "triangles",
                    elements: regl.prop('elements'),
                    count: (ctx, prop) => {
                        return prop.elements ? prop.elements.length : prop.position.length / 2
                    }
                })

              //  let ext= regl._gl.getExtension('EXT_blend_minmax')
              //  console.log('e',ext)
                const equations = ['add', 'subtract', 'reverse subtract', 'min', 'max']
                const depthFuncs = [ /* `gl.NEVER` */
                    "never",
                    /* `gl.ALWAYS` */
                    "always",
                    /* `gl.LESS` */
                    "less",
                    /* `gl.LEQUAL` */
                    "lequal",
                    /* `gl.GREATER` */
                    "greater",
                    /* `gl.GEQUAL` */
                    "gequal",
                    /* `gl.EQUAL` */
                    "equal",
                    /* `gl.NOTEQUAL` */
                    "notequal"];
                const blends = [/* `gl.ZERO` */"zero",
                    /* `gl.ONE` */
                    "one",
                    /* `gl.SRC_COLOR` */
                    "src color",
                    /* `gl.ONE_MINUS_SRC_COLOR` */
                    "one minus src color",
                    /* `gl.SRC_ALPHA` */
                    "src alpha",
                    /* `gl.ONE_MINUS_SRC_ALPHA` */
                    "one minus src alpha",
                    /* `gl.DST_COLOR` */
                    "dst color",
                    /* `gl.ONE_MINUS_DST_COLOR` */
                    "one minus dst color",
                    /* `gl.DST_ALPHA` */
                    "dst alpha",
                    /* `gl.ONE_MINUS_DST_ALPHA` */
                    "one minus dst alpha",
                    /* `gl.CONSTANT_COLOR` */
                    "constant color",
                    /* `gl.ONE_MINUS_CONSTANT_COLOR` */
                    "one minus constant color",
                    /* `gl.CONSTANT_ALPHA` */
                     "constant alpha" ,
                    /* `gl.ONE_MINUS_CONSTANT_ALPHA` */
                     "one minus constant alpha" ,
                    /* `gl.SRC_ALPHA_SATURATE` */
                    // "src alpha saturate"
                ];

                const guiData = addGuiScheme(this.$gui, {
                    source: {
                        depthFunc: "lequal",
                        equation: 'add',
                        src: "one",
                        dst: 'zero',
                    },
                    schemes: {
                        depthFunc: {
                            type: "list",
                            params: depthFuncs
                        },
                        equation: {
                            type: "list",
                            params: equations
                        },
                        src: {
                            type: "list",
                            params: blends
                        },
                        dst: {
                            type: "list",
                            params: blends
                        },
                      
                    },
                    onChange() {
                        renderGraphics()
                    }
                })
               

                function crossRecursive(...values) {
                    let maxDepth = values.length, count = 0;
                    let result = []
                    function processData(root, depth, parents = []) {
                        let isLast = depth + 1 >= maxDepth;
                        root[depth].forEach(function (item, index) {
                            if (isLast) {
                                result.push([].concat(parents, item))
                            } else {
                                parents.push(item)
                                processData(root, depth + 1, parents)
                                parents.pop()
                            }
                        })
                    }
                    if (values.length > 0) {
                        processData(values, 0)
                    }
                    return result
                }
                const schemes = crossRecursive(blends,blends,blends,blends)
                const textMap = new Map()
                const that = this;
                function updateDraw() {
                    regl.clear({
                        color: [1, 1, 1, 1],
                        depth: 1
                    })
                    let drawObjects = []
                    const drawTexts = []
                    let equation=guiData.equation
                    // if(equation==='min'){
                    //     equation=ext.MIN_EXT
                    // }
                    // if(equation==='max'){
                    //     equation=ext.MAX_EXT
                    // }
                    console.log('schemes', schemes.length)
                    schemes.forEach((scheme, i) => {
                        let columnCount=8
                        let row = Math.floor(i / columnCount), sh2 = 75, sw2 = 75, sw = 50, sh = 50;
                        let col = i % columnCount;
                        let x = col * sw2 + (col + 1) * 50;
                        let y = row * sh2 + (row + 1) * 50;
                        let y2=y+cameraPosition[1];
                        if(y2<-50||y2>600){   
                            return false
                        }
                        drawObjects.push({
                            y:y,
                            x:y,
                            position: createRect(x, y, sw, sh),
                            color: [0.2, 0.7, 0.2, 1],
                            blend: {
                                enable: true,
                                equation: equation,
                                func: {
                                    src: guiData.src,
                                    dst: guiData.dst,
                                    srcAlpha:"one",
                                    dstAlpha:"zero",
                                }
                            }
                        })
                        drawObjects.push({
                            y:y+sh/2,
                            x:x,
                            position: createRect(x + sw / 2, y + sh / 2, sw, sh),
                            color: [0.3, 0.3, 0.3, 1],
                            blend: {
                                enable: true,
                                equation: equation,
                                func: {
                                    src: scheme[0],
                                    dst: scheme[1],
                                    // srcAlpha:"one",
                                    // dstAlpha:"zero",
                                    srcAlpha: scheme[2],
                                    dstAlpha: scheme[3],
                                }
                            }
                        })
                        // let cacheKey=scheme.join(' ')
                        // if(!textMap.has(cacheKey)){
                        //     const textMesh = VectorizeText.default('你好', {
                        //        // width:300,
                        //        // height:100,
                        //         textAlign: 'center',
                        //         textBaseline: 'middle'
                        //     })
                        //     textMap.set(cacheKey,textMesh)
                        // }
                        drawTexts.push({
                            x: x,
                            y: y + sh * 1.5,
                            text: scheme.join('<br/>')
                            // position:textMap.get(cacheKey).positions,
                            // color:[0,0,0,1],
                            // selfOffset:[x,y],
                            // elements:textMap.get(cacheKey).edges,
                            // blend:{
                            //     enable:false,
                            //     equation:'add',
                            //     func:{

                            //     }
                            // }
                        })
                    })
                    // drawObjects=drawObjects.filter((d,i)=>{    
                    //     let y2=d.y+cameraPosition[1];
                    //     if(y2<-50||y2>600){   
                    //         return false
                    //     }
                    //     return true
                    // })
                    superDraw({
                        depth: {
                            enable: true,
                            func: guiData.depthFunc
                        }
                    }, (ctx, props) => {
                        draw(drawObjects)
                    })

                    let frament = document.createDocumentFragment()
                    let bound = that.$refs.container.getBoundingClientRect()
                    drawTexts.forEach((d,i) => {
                        // let y2=d.y+cameraPosition[1];
                        // if(y2<-50||y2>600){   
                        //     return;
                        // }
                        let span = document.createElement('span')
                        span.title = d.text;
                        span.innerHTML = d.text
                        span.style.textOverflow = "ellipsis"
                        span.style.whiteSpace = "nowrap";
                        span.style.overflow = 'hidden'
                        span.style.width = '125px'
                        span.style.fontSize = '12px'
                        span.style.position = 'absolute'
                        span.style.pointerEvents = 'auto'
                        span.style.transform = `scale(${1/that.devicePixelRatio}) translate(${d.x + cameraPosition[0]}px,${d.y + cameraPosition[1]}px)`
                     //   textContainer.style.transform=`scale(${1/window.devicePixelRatio})`
                     span.style.transformOrigin="left top"
                        frament.appendChild(span)
                        let minY = 0, maxY = bound.bottom;

                    })
                   // console.log('row',drawObjects.length,drawTexts.length,cameraPosition[1])
                    let textContainer = document.getElementById('textContainer')
                    if (!textContainer) {

                        let bound = that.$refs.container.getBoundingClientRect()
                        textContainer = document.createElement('div');
                        textContainer.id = 'textContainer'
                        textContainer.style.width = bound.width + 'px'
                        textContainer.style.height = bound.height + 'px'
                        textContainer.style.position = 'absolute'
                
                        textContainer.style.userSelect = "none"
                        textContainer.style.pointerEvents = 'none'
                        textContainer.style.left = bound.left + 'px'
                        textContainer.style.top = bound.top + 'px'
                        textContainer.style.overflow = "hidden"

                        //textContainer.style.zIndex=-1
                        document.body.appendChild(textContainer)


                    } else {
                        textContainer.innerHTML = ''
                    }
                    textContainer.appendChild(frament)
                    //textContainer.style.paddingTop=cameraPosition[1]+'px';
                    isRendering = false
                }


                let isRendering = false
                function renderGraphics() {
                    if (isRendering) {
                        return
                    }
                    isRendering = true;
                    window.requestAnimationFrame(updateDraw)
                }
                renderGraphics()
            }
        },
        mounted() {

        }
    }
})

addExample("2d纹理",function(){
        return {
           extends:BaseComponent,
           data(){ return {devicePixelRatio:1}},
           methods:{
            /**
             * @param {createREGL.Regl} regl
             */
            init(regl){

                const setup=regl({
                    context:{
                        uResolution(ctx){
                            return [ctx.viewportWidth,ctx.viewportHeight]
                        }
                    },
                    uniforms:{
                        uResolution:regl.context('uResolution')
                    }
                })
                const drawTexture=regl({
                    vert:`
                        attribute vec2 aPosition;
                        uniform vec2 uResolution;
                        uniform vec2 u_offset;
                        void main(){
                            // 从屏幕转换为-1>1.0
                            vec2 pos=(aPosition/uResolution)*2.0-1.0;
                            vec2 clipPosition=pos*vec2(1.0,-1.0)+u_offset;// y轴倒过来
                           // v_positionWithOffset = pos + u_offset;
                           gl_Position=vec4(clipPosition,0,1.0);
                        }
                    `,
                    frag:`
                    precision mediump float; 
                    
                    uniform sampler2D u_texture;
                    void main(){
                        vec2 texcoord = vec2(0.5, 0.5);  // 获取纹理中心的值
                        gl_FragColor = texture2D(u_texture, texcoord);
                    }
                    `,
                    attributes:{
                        aPosition:regl.prop('aPosition')
                    },
                    uniforms:{
                        u_texture:regl.prop('u_texture'),
                        u_offset:[0,0]
                    },
                    primitive:"triangles",
                   count:regl.prop('count')
                })
                regl.clear({
                    color:[1,1,1,1]
                })
                let box=[
                    [100,100],
                    [200,100],
                    [100,200],
                    [200,200],
                    [100,200],
                    [200,100]
                ]
                let texture=regl.texture({
                    width:3,
                    height:1,
                    type:"uint8",
                    format:"rgba",
                    
                    data:new Uint8ClampedArray([
                        255,0,0,255,
                        0,255,0,255,
                        0,0,255,255,

                    ])
                })
                setup(()=>{
                    drawTexture({
                        aPosition:box,
                        u_texture:texture,
                        count:box.length
                    })
                })
            }
           }
        }
})


addExample("着色片段",function(){
    return {
       extends:BaseComponent,
       data(){ return {devicePixelRatio:1}},
       methods:{
        /**
         * @param {createREGL.Regl} regl
         */
        init(regl){

            const setup=regl({
                context:{
                    uResolution(ctx){
                        return [ctx.viewportWidth,ctx.viewportHeight]
                    }
                },
                uniforms:{
                    uResolution:regl.context('uResolution')
                }
            })
            const drawTexture=regl({
                vert:`
                    attribute vec2 aPosition;
                    uniform vec2 uResolution;
                    uniform vec2 u_offset;
                    varying vec4 v_positionWithOffset;
                    void main(){
                        // 从屏幕转换为-1>1.0
                        vec2 pos=(aPosition/uResolution)*2.0-1.0;
                        vec2 clipPosition=pos*vec2(1.0,-1.0)+u_offset;// y轴倒过来
                        gl_Position=vec4(clipPosition,0,1.0);
                        v_positionWithOffset =vec4(clipPosition,0,1.0);
                    }
                `,
                frag:`
                precision mediump float; 

                varying vec4 v_positionWithOffset;
                void main(){
                        // 从裁剪空间 (-1 <-> +1) 转换到颜色空间 (0 -> 1).
                        // 片元执行次数,如果采用的是triangles绘制,相当要把三角形内的顶点都要着色
                        vec4 color = v_positionWithOffset * 0.5 + 0.5;
                        gl_FragColor = color;
                }
                `,
                attributes:{
                    aPosition:regl.prop('aPosition')
                },
                uniforms:{
                    u_offset:regl.prop('u_offset')
                   // u_texture:regl.prop('u_texture')
                },
                primitive:"triangles",
               count:regl.prop('count')
            })
            regl.clear({
                color:[1,1,1,1]
            })
            let createBox=(x,y,w,h)=>{
                return [
                    [x,y],
                    [x+w,y],
                    [x,y+h],
                    [x+w,y+h],
                    [x,y+h],
                    [x+w,y]
                ]
            }
            let box=createBox(0,0,this.width,this.height)
            let texture=regl.texture({
                width:3,
                height:1,
                type:"uint8",
                format:"rgba",
                
                data:new Uint8ClampedArray([
                    255,0,0,255,
                    0,255,0,255,
                    0,0,255,255,

                ])
            })
            setup(()=>{
                drawTexture({
                    aPosition:box,
                    u_offset:[0,0],
                 //   u_texture:texture,
                    count:box.length
                })
            })
        }
       }
    }
})



addExample("FBO", function () {

    // let camera = new THREE.OrthographicCamera(800 / -2, 800 / 2, 600 / 2, 600 / -2, 0.1, 1000)
    let camera = new THREE.PerspectiveCamera(50, 800 / 600, 0.1, 10000)
    camera.position.set(0, 1, 5)
    const scene=new THREE.Scene();
    return {
        template: `<div><canvas width="800" height="600" ref="main"></canvas></div>`,
        data() { return {}; },
        mounted() {
            var container = this.$refs.main;
            let regl = window.regl = createREGL({
                canvas: container,
            })
            var oribt = new THREE.OrbitControls(camera, regl._gl.canvas)
  
            let drawBox = regl({
                vert: `
                    attribute vec3 position;
                    uniform mat4 projectionMatrix;
                    uniform mat4 modelViewMatrix;
                    void main(){
                        gl_Position=projectionMatrix*modelViewMatrix*vec4(position,1.0);

                    }
                `,
                frag: `
                    precision mediump float;
                    uniform vec4 color;
                    void main(){
                        gl_FragColor=color;
                    }
                `,
                attributes: {
                    position: regl.prop('position'),
                },
                uniforms: {
                    projectionMatrix:regl.prop('projectionMatrix'),
                    modelViewMatrix: regl.prop('modelViewMatrix'),
                    color: regl.prop('color')
                },
                //primitive: 'triangle',
                elements:regl.prop('elements')
                //count: boxPosition.length / 3
            })

            const stats = new Stats()
            stats.showPanel(0)
            document.body.appendChild(stats.dom)
         


            const box=new THREE.Mesh(new THREE.BoxGeometry(1,1,1),new THREE.MeshBasicMaterial({
                color:0xff0000
            }))
            scene.add(box)

            const geometryMap=new Map()

            /**
             * @param {THREE.Mesh} mesh
             * @param {THREE.PerspectiveCamera} camera 
            */
            const renderMesh=(mesh,camera)=>{
                const {geometry,material}=mesh
                const geometryPosition=geometry.getAttribute('position').array;
                const geometryElements = geometry.getIndex().array
                const modelViewMatrix=mesh.modelViewMatrix.multiplyMatrices(camera.matrixWorldInverse,mesh.matrixWorld);

                if(geometry.type==="BoxGeometry"){
                     drawBox({
                        elements:geometryElements,
                        position:geometryPosition,
                        projectionMatrix:camera.projectionMatrix.elements,
                        modelViewMatrix:modelViewMatrix.elements,
                        color:[material.color.r,material.color.g,material.color.b,1]
                     })
                }
            }
            /**
             * 
             * @param {THREE.Scene} scene 
             * @param {THREE.PerspectiveCamera} camera 
             */
            const renderScene=(scene,camera)=>{
                if(camera.matrixAutoUpdate){
                    camera.updateMatrixWorld()
                }
                scene.updateMatrixWorld()
                scene.traverseVisible(obj=>{
                    if(obj.type==='Mesh'){
                        renderMesh(obj,camera)
                    }
                })
            }
            const render = () => {
                stats.begin()
                regl.clear({
                    color: [1, 1, 1, 1],
                    depth: 1
                })
                renderScene(scene,camera)
          
                stats.end()

            }
            regl.frame(render)
            oribt.addEventListener('change', () => {
                console.log('oribt')
                // camera.updateProjectionMatrix()
                // render()
            })
            // render()


        }
    }
})


addExample("stencil模板测试",function(){
        return {
           template:`<div><canvas ref="canvas"></canvas></div>`,
           data(){ return {};},
           computed:{},
           methods:{},
           mounted(){
              var width=500,height=500;
              var canvas=this.$refs.canvas;
              canvas.width=width
              canvas.height=height
              let projectMatrix = mat3.create()
              mat3.projection(projectMatrix, width, height)
    

              function createRect(x,y,w,h){
                return  new Float32Array([
                    x, y,
                    x, y + h,
                    x + w, y,
                    x + w, y + h,
                    x + w, y,
                    x, y + h
                ])
              }
              var regl=createREGL({
                    canvas:canvas,
                    attributes:{
                        antialias:true,
                        stencil:true,// 开启模板测试
                    }
              })
              var drawRect=regl({
                vert: `
                attribute vec2 position;
                uniform mat3 projectMatrix;
                uniform mat3 modelMatrix;
                void main(){
                    vec3 _position=projectMatrix* modelMatrix *vec3(position,1);
                    gl_Position=vec4(vec2(_position),0,1.0);
                }
            `,
            frag: `
                precision mediump float;
                uniform vec4 color;
                void main(){
                    gl_FragColor=color;
                }
            `,
            primitive: "triangles",
            attributes: {
                position: regl.prop('position')
            },
            uniforms: {
                projectMatrix: projectMatrix,
                modelMatrix: regl.prop('modelMatrix'),
                color: regl.prop('color')
            },
            //frontFace: 'ccw'
            colorMask: regl.prop('colorMask'),
            depth: {
                enable: true,
                mask: true, // 是否禁用写入深度缓存区
                range: [0, 1],
                /*
                通过就写入深度缓冲区,深度缓冲区,主要用于图层的远近顺序
                该函数将传入的像素深度与当前深度缓冲区值进行比较。

                gl.NEVER(从不通过)
                gl.LESS(如果传入值小于深度缓冲区值则通过)
                gl.EQUAL(如果传入值等于深度缓冲区值,则通过)
                gl.LEQUAL(如果传入值小于或等于深度缓冲区值,则通过)
                gl.GREATER(如果传入值大于深度缓冲区值则通过)
                gl.NOTEQUAL(如果传入值不等于深度缓冲区值则通过)
                gl.GEQUAL(如果传入值大于或等于深度缓冲区值则通过)
                gl.ALWAYS(总是通过)
                */
                func:"lequal" 

            },
            stencil:{
                enable:regl.prop('stencil.enable'),// 开启模板测试
                //gl.stencilMask(0xFF); // 每一位写入模板缓冲时都保持原样
                //gl.stencilMask(0x00); // 每一位在写入模板缓冲时都会变成0(禁用写入)
                mask:regl.prop('stencil.mask'),
                //确定后续的渲染,和当前模板缓冲中的像素模板值对比之后,是否丢弃掉渲染的结果。
                /*
                    gl.NEVER: 永不通过。
                    gl.LESS:通过如果 (ref & mask) < (stencil & mask)。
                    gl.EQUAL:通过如果 (ref & mask) = (stencil & mask)。
                    gl.LEQUAL:通过如果 (ref & mask) <= (stencil & mask)。
                    gl.GREATER:通过如果 (ref & mask) > (stencil & mask)。
                    gl.NOTEQUAL:通过如果 (ref & mask) !== (stencil & mask)。
                    gl.GEQUAL:通过如果 (ref & mask) >= (stencil & mask)。
                    gl.ALWAYS: 总是通过。
                */
                func:regl.prop('stencil.func'),
                // 设定如何根据下一次渲染的结果来更新模板缓冲中的值。
                //sfail:模板测试失败时采取的行为。
               // dpfail:模板测试通过,但深度测试失败时采取的行为。
               // dppass:模板测试和深度测试都通过时采取的行为。
               /**
                * 具体可以传递的参数如下:
                    KEEP(不改变,这也是默认值)
                    ZERO(回零)
                    REPLACE(使用测试条件中的设定值来代替当前模板值,stencilFunc方法中的ref参数)
                    INCR(增加1,但如果已经是最大值,则保持不变)
                    INCR_WRAP(增加1,但如果已经是最大值,则从零重新开始)
                    DECR(减少1,但如果已经是零,则保持不变)
                    DECR_WRAP(减少1,但如果已经是零,则重新设置为最大值)
                    INVERT(按位取反)
               */
                    /* `gl.ZERO` */
                    // "zero" |
                    // /* `gl.KEEP` */
                    // "keep" |
                    // /* `gl.REPLACE` */
                    // "replace" |
                    // /* `gl.INVERT` */
                    // "invert" |
                    // /* `gl.INCR` */
                    // "increment" |
                    // /* `gl.DECR` */
                    // "decrement" |
                    // /* `gl.INCR_WRAP` */
                    // "increment wrap" |
                    // /* `gl.DECR_WRAP` */
                    // "decrement wrap";
                op:regl.prop('stencil.op'),
               // opBack:regl.prop('stencil.opBack'),
                },
                count: function (ctx, props) {
                    return props.position.length / 2
                }
            });
            const rectPosition=createRect(0,0,100,100);
            const modelMatrix1=mat3.create();
            mat3.translate(modelMatrix1,modelMatrix1,[100,100])

            const modelMatrix2=mat3.create();
            mat3.translate(modelMatrix2,modelMatrix2,[150,100])

            const update=()=>{
                  //  regl._gl.colorMask(true,false,true,true) // 控制颜色缓冲区,哪个颜色可以写入
                    regl.clear({
                        color:[1,1,1,1],
                        depth:1,
                        stencil:0, // 清除模板缓冲区,将值初始为0
                    });
                    // 将当前这个矩形,
                    drawRect({
                        color:[1,0,0,1],
                        position:rectPosition,
                        modelMatrix:modelMatrix1,
                        // 设置是否可以写入颜色缓冲区
                        colorMask:[true,true,true,true],
                        stencil:{
                            enable:true,
                            mask:0x4,// 允许写入的mask
                            func:{
                                cmp: 'always', 
                                ref: 7, 
                                mask: 0xff // 与ref 做与运算判断是否通过
                            },
                            op:{
                                fail:"keep",
                                zfail: "keep",
                                zpass: "replace",// increment 加+1
                            }
                        }
                    });

                    // 将颜色缓冲区的清掉
                    regl._gl.clear(regl._gl.COLOR_BUFFER_BIT);

                    // 只绘制与模板缓冲相交的地方
                    drawRect({
                        color:[0,1,0,1],
                        position:rectPosition,
                        modelMatrix:modelMatrix2,
                        // 设置是否可以写入颜色缓冲区
                        colorMask:[true,true,true,true],
                        stencil:{
                            enable:true,
                            mask:0xff,
                            func:{
                                cmp: 'equal', 
                                ref: 4, 
                                mask: 0xff // 
                            },
                            op:{
                                fail:"keep",
                                zfail: "keep",
                                zpass: "keep",
                            }
                        }
                    })
          
                   // regl._gl.flush()
            }
            update()



           }
        }
})

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值