Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save LeetCodes/1c7f7cc53e0d99382b64679f55fb9e3a to your computer and use it in GitHub Desktop.

Select an option

Save LeetCodes/1c7f7cc53e0d99382b64679f55fb9e3a to your computer and use it in GitHub Desktop.

Revisions

  1. LeetCodes created this gist Nov 17, 2021.
    7 changes: 7 additions & 0 deletions cube-mapped-box-webgl-fragment-shader.markdown
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,7 @@
    Cube Mapped Box/WebGL Fragment Shader
    -------------------------------------
    Fragment shader, just math - no framework. JS window is webgl bootstrap and texture loading/attaching to canvas. HTML window is the fragment and vertex shaders. Basically I'm making a 3D scene that is projected on the canvas by using distance fields (mathematical formulas that represent an object.)

    A [Pen](https://codepen.io/leetcodes/pen/porqpVN) by [󠀁󠀃󠀃󠀇󠀌󠀀󠀍󠀎](https://codepen.io/leetcodes) on [CodePen](https://codepen.io).

    [License](https://codepen.io/leetcodes/pen/porqpVN/license).
    357 changes: 357 additions & 0 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,357 @@
    <!-- VertexShader code here -->
    <script id="vertexShader" type="x-shader/x-vertex">#version 300 es
    precision highp float;
    in vec2 a_texCoord;
    in vec4 vPosition;
    out vec2 v_texcoord;
    void main() {
    gl_Position = vPosition;
    v_texcoord = a_texCoord;
    }
    </script>
    <!-- FragmentShader code here -->
    <script id="fragmentShader" type="x-shader/x-fragment">#version 300 es
    #if __VERSION__ < 130
    #define TEXTURE2D texture2D
    #else
    #define TEXTURE2D texture
    #endif

    precision highp float;
    out vec4 fragColor;
    uniform sampler2D iChannel0;
    uniform sampler2D iChannel1;
    uniform sampler2D iChannel2;
    uniform sampler2D iChannel3;
    uniform vec2 v_texCoord;
    uniform vec4 mouse;
    uniform vec2 resolution;
    uniform float time;

    #define R resolution
    #define T time
    #define M mouse

    #define PI 3.14159265359
    #define PI2 6.28318530718

    #define MAX_DIST 100.
    #define MIN_DIST .0001

    float hash21(vec2 p){ return fract(sin(dot(p,vec2(26.34,45.32)))*4324.23); }
    mat2 rot(float a){ return mat2(cos(a),sin(a),-sin(a),cos(a)); }
    float vmax(vec3 p){ return max(max(p.x,p.y),p.z); }
    //@iq
    float cap( vec3 p, float h, float r ){
    vec2 d = abs(vec2(length(p.xz),p.y)) - vec2(h,r);
    return min(max(d.x,d.y),0.0) + length(max(d,0.0));
    }
    //@iq
    float vcap( vec3 p, float h, float r ){
    p.y -= clamp( p.y, 0.0, h );
    return length( p ) - r;
    }

    float modPolar(inout vec2 p, float rep) {
    float angle = 2.*PI/rep;
    float a = atan(p.y, p.x) + angle/2.;
    float c = floor(a/angle);
    a = mod(a,angle) - angle/2.;
    p = vec2(cos(a), sin(a))*length(p);
    return (abs(c) >= (rep/2.)) ? abs(c) : c;
    }

    float box(vec3 p, vec3 b){
    vec3 d = abs(p) - b;
    return length(max(d,vec3(0))) + vmax(min(d,vec3(0)));
    }

    vec3 hit=vec3(0),hitPoint=vec3(0);
    mat2 ria,gia,turn,spin;

    const float sz = 3.;
    const float hf = sz*.5;

    vec2 map(vec3 pos, float sg){
    vec2 res = vec2(1e5,0.);
    pos.y+=1.25;;
    vec3 q = pos-vec3(0,2.5,0);
    vec3 b = pos-vec3(0,1.05,0);

    q.yx*=spin;
    q.zx*=spin;

    float d1 = box(q,vec3(1.5))-.0423;
    if(d1<res.x){
    res = vec2(d1,2.);
    hit=q;
    }

    b.xz=abs(abs(abs(b.xz)-12.)-6.)-3.;
    vec3 hitb = b;

    float pillar = cap(b,.3,1.5);
    vec3 tb =vec3(b.x,abs(b.y),b.z);
    float pcap = box(tb-vec3(0,1.45,0),vec3(.5,.15,.5))-.005;
    pcap=min(cap(tb-vec3(0,1.3,0),.4,.05),pcap);

    modPolar(b.xz,16.);
    vec3 bt = b-vec3(.3,-1.1,0);

    float grv = vcap(bt,2.2,.045);
    pillar = max(pillar,-grv);
    pillar = min(pcap,pillar);

    if(pillar<res.x)
    {
    res = vec2(pillar*.75,3.);
    hit=hitb;
    }

    float ground =pos.y+.5;
    if(ground<res.x){
    res = vec2(ground,1.);
    hit=pos;
    }

    return res;
    }

    vec3 normal(vec3 p, float t){
    float e = MIN_DIST*t;
    vec2 h =vec2(1,-1)*.5773;
    vec3 n = h.xyy * map(p+h.xyy*e,0.).x+
    h.yyx * map(p+h.yyx*e,0.).x+
    h.yxy * map(p+h.yxy*e,0.).x+
    h.xxx * map(p+h.xxx*e,0.).x;
    return normalize(n);
    }

    vec2 marcher(vec3 ro, vec3 rd, int maxsteps, float sg){
    float d = 0.;
    float m = 0.;
    for(int i=0;i<maxsteps;i++){
    vec2 ray = map(ro + rd * d, sg);
    if(ray.x<MIN_DIST*d||d>MAX_DIST) break;
    d += ray.x * .85;
    m = ray.y;
    }
    return vec2(d,m);
    }

    // Tri-Planar blending function. GPU Gems 3 - Ryan Geiss:
    vec3 tex3D(sampler2D t, in vec3 p, in vec3 n ){
    n = max(abs(n), MIN_DIST);
    n /= dot(n, vec3(1));
    vec3 tx = texture(t, p.yz).xyz;
    vec3 ty = texture(t, p.zx).xyz;
    vec3 tz = texture(t, p.xy).xyz;
    return mat3(tx*tx, ty*ty, tz*tz)*n;
    //return (tx*tx*n.x + ty*ty*n.y + tz*tz*n.z);
    }

    float sface;
    vec3 getFace(int face, vec3 p){
    float cir = 0.;
    vec2 uv;

    if(face==0) uv=p.yz;
    if(face==1) uv=p.zx;
    if(face==2) uv=p.xy;
    if(face==3) uv=p.xy;
    if(face==4) uv=p.xz;
    if(face==5) uv=p.zy;
    uv*=2.;

    float px = fwidth(uv.x);
    vec2 grid_uv = fract(uv)-.5;
    vec2 grid_id = floor(uv);

    float chk = mod(grid_id.y + grid_id.x,2.) * 2. - 1.;
    float hs = hash21(grid_id);
    if(hs>.5) grid_uv.x*=-1.;

    vec2 d2 = vec2(length(grid_uv-.5), length(grid_uv+.5));
    vec2 gx = d2.x<d2.y? vec2(grid_uv-.5) : vec2(grid_uv+.5);

    float circle = length(gx)-.5;
    float circle2 =abs(circle)-.025;
    circle2=smoothstep(.001+px,-px,circle2);
    circle=(chk>0.^^ hs>.5)?smoothstep(-px,.001+px,circle):smoothstep(.001+px,-px,circle);

    cir= mix(cir,.0,circle);
    cir= mix(cir,1.,circle2);
    sface=mix(0.,1.,circle);
    return vec3(cir);
    }
    // based on bmp mapping from
    // https://www.shadertoy.com/view/ld3yDn
    vec3 doBumpMap( vec3 p, vec3 n, float bf, float per, int face){
    vec2 e = vec2(per*MIN_DIST, 0);
    mat3 m = mat3(
    getFace(face, p - e.xyy),
    getFace(face, p - e.yxy),
    getFace(face, p - e.yyx)
    );
    vec3 g = vec3(0.299, 0.587, 0.114) * m;
    g = (g - dot(getFace(face, p), vec3(0.299, 0.587, 0.114)) )/e.x; g -= n*dot(n, g);
    return normalize( n + g*bf );
    }

    vec4 FC = vec4(0.019,0.019,0.019,0.);

    vec4 render(inout vec3 ro, inout vec3 rd, inout vec3 ref, bool last, inout float d, vec2 uv) {

    vec3 C = vec3(0);
    vec2 ray = marcher(ro,rd,128, 1.);

    hitPoint = hit;
    gia=ria;
    d = ray.x;
    float m = ray.y;
    float alpha = 0.;

    if(d<MAX_DIST)
    {
    vec3 p = ro + rd * d;
    vec3 n = normal(p,d);
    vec3 lpos =vec3(3.,8,3.);
    vec3 lpos2 =vec3(5.,5,-5.);
    vec3 l = normalize(lpos-p);
    vec3 l2 = normalize(lpos2-p);

    vec3 h = vec3(.5);
    vec3 hp = hitPoint;
    vec3 cuv;
    int face;
    vec3 tn = n;
    vec3 cn = n;
    if(m==2.){
    tn = n;
    tn.yx*=spin;
    tn.zx*=spin;
    //https://www.shadertoy.com/view/3sVBDd
    //finding the face of a cube using normal
    vec3 aN = abs(tn);
    ivec3 idF = ivec3(tn.x<-.25? 0 : 5, tn.y<-.25? 1 : 4, tn.z<-.25? 2 : 3);
    face = aN.x>.5? idF.x : aN.y>.5? idF.y : idF.z;

    // set coords
    if(face==0) cuv = hp.xyz;
    if(face==1) cuv = hp.xyz;
    if(face==2) cuv = hp.xyz;
    if(face==3) cuv = hp.xyz;
    if(face==4) cuv = hp.zyx;
    if(face==5) cuv = hp.xyz;

    // get bump map surface
    n=doBumpMap( cuv, n, .05, d, face);
    }

    float diff = clamp(dot(n,l),0.,1.);
    float diff2 = clamp(dot(n,l2),0.,1.);
    float fresnel = pow(clamp(1.+dot(rd, n), 0., 1.), 9.);
    fresnel = mix(.01, .7, fresnel);

    float shdw = 1.0;
    for( float t=.01; t < 11.; )
    {
    float h = map(p + l*t,0.).x;
    if( h<MIN_DIST ) { shdw = 0.; break; }
    shdw = min(shdw, 16.*h/t);
    t += h;
    if( shdw<MIN_DIST || t>32. ) break;
    }
    float shdw2 = 1.0;
    for( float t=.01; t < 11.; )
    {
    float h = map(p + l2*t,0.).x;
    if( h<MIN_DIST ) { shdw2 = 0.; break; }
    shdw2 = min(shdw2, 16.*h/t);
    t += h;
    if( shdw2<MIN_DIST || t>32. ) break;
    }

    diff = mix(diff,diff*shdw,.75);
    diff2 = mix(diff2,diff2*shdw2,.75);

    vec3 diffMix =vec3(0);
    diffMix = diff * vec3(0.502,0.290,0.000);
    diffMix += diff2 * vec3(0.004,0.510,0.894);

    vec3 view = normalize(p - ro);
    vec3 ret = reflect(normalize(lpos), n);
    float spec = 0.5 * pow(max(dot(view, ret), 0.), (m==2.||m==4.)?24.:64.);

    // materials
    if(m==1.){
    h=tex3D(iChannel1,hitPoint*.25,n).rgb;
    C = (diffMix*h);
    ref = vec3(clamp(.35-fresnel-(d*.01),.01,1.));
    }
    if(m==2.){
    h = mix(tex3D(iChannel0,cuv*.55,tn).rgb, tex3D(iChannel2,cuv*.75,tn).rgb ,sface);
    C = (diffMix*h)+spec;
    ref = vec3(clamp(sface-fresnel,.01,.9));
    }
    if(m==3.){
    h=clamp(tex3D(iChannel2,hitPoint*.5,tn).rrr+.5+fresnel,vec3(0),vec3(.8));//vec3(.2);
    C = (diffMix*h);
    ref = clamp((h-fresnel)-.5,vec3(0),vec3(1));
    }

    C = mix(FC.rgb,C,exp(-.00015*d*d*d));
    ro = p+n*.001;
    rd = reflect(rd,n);
    } else {
    if(last) C = mix(FC.rgb,C,exp(-.000015*d*d*d));
    }
    C = clamp(C,vec3(0),vec3(1));
    return vec4(C,alpha);
    }

    void main()
    {
    float timer = T*04.*PI/180.;
    turn = rot(timer);
    spin = rot(T*15.*PI/180.);

    vec2 F = gl_FragCoord.xy;
    vec2 uv = (2.*F.xy-R.xy)/max(R.x,R.y);
    vec3 ro = vec3(0,0,7.75);
    vec3 rd = normalize(vec3(uv,-1));

    //mouse
    float x = M.xy == vec2(0) ? 0. : -(M.y/R.y * 1. - .5) * PI;
    float y = M.xy == vec2(0) ? 0. : -(M.x/R.x * 1. - .5) * PI;
    if(x<-.15)x=-.15;
    mat2 rx = rot(x+.1);
    mat2 ry = rot(y+timer);

    ro.yz *= rx;
    rd.yz *= rx;
    ro.xz *= ry;
    rd.xz *= ry;

    // reflection loop (@BigWings)
    vec3 C = vec3(0);
    vec3 ref=vec3(0), fil=vec3(1);
    float d =0.;
    float numBounces = 2.;
    // 3 is pretty but slows down
    for(float i=0.; i<numBounces; i++) {
    vec4 pass = render(ro, rd, ref, i==numBounces-1., d, uv);
    C += pass.rgb*fil;
    fil*=ref;
    if(i==0.) FC = vec4(FC.rgb,exp(-.000075*d*d*d));
    }

    C = mix(C,FC.rgb,1.-FC.w);
    // gamma
    C = clamp(C,vec3(0),vec3(1));
    C = pow(C, vec3(.4545));
    fragColor = vec4(C,1.);
    }

    </script>
    <div id="container" />
    331 changes: 331 additions & 0 deletions script.babel
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,331 @@
    // Mouse Class for movments and attaching to dom //
    class Mouse {
    constructor(element) {
    this.element = element || window;
    this.drag = false;
    this.x =
    ~~(document.documentElement.clientWidth, window.innerWidth || 0) / 2;
    this.y =
    ~~(document.documentElement.clientHeight, window.innerHeight || 0) / 2;
    this.pointer = this.pointer.bind(this);
    this.getCoordinates = this.getCoordinates.bind(this);
    this.events = ["mouseenter", "mousemove"];
    this.events.forEach((eventName) => {
    this.element.addEventListener(eventName, this.getCoordinates);
    });
    this.element.addEventListener("mousedown", () => {
    this.drag = true;
    });
    this.element.addEventListener("mouseup", () => {
    this.drag = false;
    });
    }
    reset = () => {
    this.x =
    ~~(document.documentElement.clientWidth, window.innerWidth || 0) / 2;
    this.y =
    ~~(document.documentElement.clientHeight, window.innerHeight || 0) / 2;
    };
    getCoordinates(event) {
    event.preventDefault();
    const x = event.pageX;
    const y = event.pageY;
    if (this.drag) {
    this.x = x;
    this.y = y;
    }
    }
    pointer() {
    return {
    x: this.x,
    y: this.y
    };
    }
    }

    const woodTexture = "https://assets.codepen.io/163598/tile01.jpg";
    const rockTexture = "https://assets.codepen.io/163598/texture3.jpg";
    const stoneTexture = "https://assets.codepen.io/163598/texture2.jpg";
    const textureList = [stoneTexture, woodTexture, rockTexture];

    // Boostrap for WebGL and Attaching Shaders //
    // Fragment & Vertex Shaders in HTML window //
    class Render {
    constructor() {
    this.start = Date.now();
    this.umouse = [0.0, 0.0, 0.0, 0.0];
    this.tmouse = [0.0, 0.0, 0.0, 0.0];
    // Setup WebGL canvas and surface object //
    // Make Canvas and get WebGl2 Context //
    let width = (this.width = ~~(document.documentElement.clientWidth,
    window.innerWidth || 0));
    let height = (this.height = ~~(document.documentElement.clientHeight,
    window.innerHeight || 0));
    const canvas = (this.canvas = document.createElement("canvas"));
    const container = document.getElementById("container");
    canvas.id = "GLShaders";

    canvas.width = width;
    canvas.height = height;
    this.mouse = new Mouse(canvas);
    document.body.appendChild(canvas);
    const gl = (this.gl = canvas.getContext("webgl2"));

    if (!gl) {
    console.warn("WebGL 2 is not available.");
    return;
    }
    // WebGl and WebGl2 Extension //
    this.gl.getExtension("OES_standard_derivatives");
    this.gl.getExtension("EXT_shader_texture_lod");
    this.gl.getExtension("OES_texture_float");
    this.gl.getExtension("WEBGL_color_buffer_float");
    this.gl.getExtension("OES_texture_float_linear");

    this.gl.viewport(0, 0, canvas.width, canvas.height);
    // always nice to let people resize
    window.addEventListener(
    "resize",
    () => {
    let width = ~~(document.documentElement.clientWidth,
    window.innerWidth || 0);
    let height = ~~(document.documentElement.clientHeight,
    window.innerHeight || 0);
    this.mouse.reset();
    this.canvas.width = width;
    this.canvas.height = height;
    this.gl.viewport(0, 0, this.canvas.width, this.canvas.height);
    this.resolution = new Float32Array([width, height]);
    this.gl.uniform2fv(
    this.gl.getUniformLocation(this.program, "resolution"),
    this.resolution
    );
    this.clearCanvas();
    },
    false
    );

    this.init();
    }

    // Shader Bootstrap code //
    createShader = (type, source) => {
    const shader = this.gl.createShader(type);
    this.gl.shaderSource(shader, source);
    this.gl.compileShader(shader);
    const success = this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS);
    if (!success) {
    console.log(this.gl.getShaderInfoLog(shader));
    this.gl.deleteShader(shader);
    return false;
    }
    return shader;
    };

    createWebGL = (vertexSource, fragmentSource, images) => {
    // Setup Vertext/Fragment Shader functions
    this.vertexShader = this.createShader(this.gl.VERTEX_SHADER, vertexSource);
    this.fragmentShader = this.createShader(
    this.gl.FRAGMENT_SHADER,
    fragmentSource
    );

    // Setup Program and Attach Shader functions
    this.program = this.gl.createProgram();
    this.gl.attachShader(this.program, this.vertexShader);
    this.gl.attachShader(this.program, this.fragmentShader);
    this.gl.linkProgram(this.program);
    this.gl.useProgram(this.program);

    if (!this.gl.getProgramParameter(this.program, this.gl.LINK_STATUS)) {
    console.warn(
    "Unable to initialize the shader program: " +
    this.gl.getProgramInfoLog(this.program)
    );
    return null;
    }

    // Create and Bind buffer //
    const buffer = this.gl.createBuffer();
    this.gl.bindBuffer(this.gl.ARRAY_BUFFER, buffer);

    this.gl.bufferData(
    this.gl.ARRAY_BUFFER,
    new Float32Array([-1, 1, -1, -1, 1, -1, 1, 1]),
    this.gl.STATIC_DRAW
    );

    const vPosition = this.gl.getAttribLocation(this.program, "vPosition");

    this.gl.enableVertexAttribArray(vPosition);
    this.gl.vertexAttribPointer(
    vPosition,
    2, // size: 2 components per iteration
    this.gl.FLOAT, // type: the data is 32bit floats
    false, // normalize: don't normalize the data
    0, // stride: 0 = move forward size * sizeof(type) each iteration to get the next position
    0 // start at the beginning of the buffer
    );

    this.clearCanvas();
    this.importUniforms(images);
    };
    /**
    Textures
    */

    isPowerOf2 = (value) => {
    return (value & (value - 1)) == 0;
    };

    getImage = (url) => {
    return new Promise((resolve, reject) => {
    let img = new Image();
    img.crossOrigin = "Anonymous";
    img.addEventListener("load", (e) => resolve(img));
    img.addEventListener("error", () => {
    reject(new Error(`Failed to load image's URL: ${url}`));
    });
    img.src = url;
    });
    };

    loadTexture = (textureList) => {
    const lockNames = [
    this.gl.TEXTURE0,
    this.gl.TEXTURE1,
    this.gl.TEXTURE2,
    this.gl.TEXTURE3
    ];
    const textureOptions = [
    [this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE],
    [this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE],
    [this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.NEAREST],
    [this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.NEAREST]
    ];

    let promises = textureList.map((item) => this.getImage(item));

    Promise.all(promises).then((images) => {
    const amount = images.length;
    let textures = [];
    for (let ii = 0; ii < amount; ++ii) {
    const texture = this.gl.createTexture();
    this.gl.bindTexture(this.gl.TEXTURE_2D, texture);
    // Upload the image into the texture.
    this.gl.texImage2D(
    this.gl.TEXTURE_2D,
    0,
    this.gl.RGBA,
    this.gl.RGBA,
    this.gl.UNSIGNED_BYTE,
    images[ii]
    );

    if (
    this.isPowerOf2(images[ii].width) &&
    this.isPowerOf2(images[ii].height)
    ) {
    this.gl.generateMipmap(this.gl.TEXTURE_2D);
    } else {
    // Set the parameters so we can render any size image.
    this.gl.texParameteri(...textureOptions[0]);
    this.gl.texParameteri(...textureOptions[1]);
    this.gl.texParameteri(...textureOptions[2]);
    this.gl.texParameteri(...textureOptions[3]);
    }

    // add the texture to the array of textures.
    textures.push(texture);
    }

    // lookup the sampler locations.
    const u_image0Location = this.gl.getUniformLocation(
    this.program,
    "iChannel0"
    );
    const u_image1Location = this.gl.getUniformLocation(
    this.program,
    "iChannel1"
    );
    const u_image2Location = this.gl.getUniformLocation(
    this.program,
    "iChannel2"
    );
    // set which texture units to render with.
    this.gl.uniform1i(u_image0Location, 0); // texture unit 0
    this.gl.uniform1i(u_image1Location, 1); // texture unit 1
    this.gl.uniform1i(u_image2Location, 2); // texture unit 1

    this.gl.activeTexture(this.gl.TEXTURE0);
    this.gl.bindTexture(this.gl.TEXTURE_2D, textures[0]);
    this.gl.activeTexture(this.gl.TEXTURE1);
    this.gl.bindTexture(this.gl.TEXTURE_2D, textures[1]);
    this.gl.activeTexture(this.gl.TEXTURE2);
    this.gl.bindTexture(this.gl.TEXTURE_2D, textures[2]);
    });

    console.log("done loading textures");
    };
    clearCanvas = () => {
    this.gl.clearColor(0, 0, 0, 0);
    this.gl.clear(this.gl.COLOR_BUFFER_BIT);
    };
    // add other uniforms here
    importUniforms = (images) => {
    const width = ~~(document.documentElement.clientWidth,
    window.innerWidth || 0);
    const height = ~~(document.documentElement.clientHeight,
    window.innerHeight || 0);
    this.resolution = new Float32Array([width, height]);
    this.gl.uniform2fv(
    this.gl.getUniformLocation(this.program, "resolution"),
    this.resolution
    );
    // get the uniform ins from the shader fragments
    this.ut = this.gl.getUniformLocation(this.program, "time");
    this.ms = this.gl.getUniformLocation(this.program, "mouse");
    this.loadTexture(images);
    };
    // things that need to be updated per frame
    updateUniforms = () => {
    let tm = (Date.now() - this.start) / 1000;
    //prevent time from getting too big
    if (tm > 2000) this.start = Date.now();
    this.gl.uniform1f(this.ut, (Date.now() - this.start) / 1000);
    const mouse = this.mouse.pointer();
    this.umouse = [mouse.x, this.canvas.height - mouse.y, 0];

    const factor = 0.15;
    this.tmouse[0] =
    this.tmouse[0] - (this.tmouse[0] - this.umouse[0]) * factor;
    this.tmouse[1] =
    this.tmouse[1] - (this.tmouse[1] - this.umouse[1]) * factor;
    this.tmouse[2] = this.mouse.drag ? 1 : 0;

    this.gl.uniform4fv(this.ms, this.tmouse);

    this.gl.drawArrays(
    this.gl.TRIANGLE_FAN, // primitiveType
    0, // Offset
    4 // Count
    );
    };

    // setup shaders and send to render loop
    init = () => {
    this.createWebGL(
    document.getElementById("vertexShader").textContent,
    document.getElementById("fragmentShader").textContent,
    textureList
    );
    this.renderLoop();
    };

    renderLoop = () => {
    this.updateUniforms();
    this.animation = window.requestAnimationFrame(this.renderLoop);
    };
    }

    const demo = new Render(document.body);
    21 changes: 21 additions & 0 deletions style.less
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,21 @@
    html {
    height: 100%;
    }
    img {
    display: none;
    }
    body {
    background: #000;
    overflow: hidden;
    padding: 0;
    margin: 0;
    width: 100%;
    height: 100%;
    text-align: center;
    }

    canvas {
    height: 100%;
    width: 100%;
    margin: auto;
    }