Guest User

Untitled

a guest
Jan 17th, 2020
149
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. class Gfx {
  2.     constructor() {
  3.         this.canvas = document.getElementById("canvas");
  4.         this.gl = canvas.getContext("webgl");
  5.  
  6.         //viewPos changes as you drag your cursor across the canvas
  7.         this.x_viewPos = 0;
  8.         this.y_viewPos = 0;
  9.     }
  10.     init() {
  11.         this.resizeCanvas(window.innerWidth, window.innerHeight);
  12.  
  13.         const vsSource = `
  14.             attribute vec4 aVertPos;
  15.  
  16.             uniform mat4 uMVMat;
  17.             uniform mat4 uProjMat;
  18.  
  19.             void main() {
  20.                 gl_Position = uProjMat * uMVMat * aVertPos;
  21.             }
  22.         `;
  23.  
  24.         //my tiles get drawn in the frag shader below
  25.         const fsSource = `
  26.             precision mediump float;
  27.  
  28.             uniform vec2 uViewPos;
  29.             uniform vec2 uTileColorSampSize;
  30.             uniform sampler2D uTileColorSamp;
  31.  
  32.             void main() {
  33.                 //tile width and height are both 33px including a 1px border
  34.                 const float lineThickness = (1.0/33.0);
  35.  
  36.                 //gridMult components will either be 0.0 or 1.0. This is used to place the grid lines
  37.                 vec2 gridMult = vec2(
  38.                     ceil(max(0.0, fract((gl_FragCoord.x-uViewPos.x)/33.0) - lineThickness)),
  39.                     ceil(max(0.0, fract((gl_FragCoord.y-uViewPos.y)/33.0) - lineThickness))
  40.                 );
  41.                 //tileIndex is used to pull color data from the sampler texture
  42.                 //add 0.5 due to pixel coords being off in gl
  43.                 vec2 tileIndex = vec2(
  44.                     floor((gl_FragCoord.x-uViewPos.x)/33.0) + 0.5,
  45.                     floor((gl_FragCoord.y-uViewPos.y)/33.0) + 0.5
  46.                 );
  47.  
  48.                 //divide by samp size as tex coords are 0.0 to 1.0
  49.                 vec4 tileColor = texture2D(uTileColorSamp, vec2(
  50.                     tileIndex.x/uTileColorSampSize.x,
  51.                     tileIndex.y/uTileColorSampSize.y
  52.                 ));
  53.  
  54.                 gl_FragColor = vec4(
  55.                     tileColor.x * gridMult.x * gridMult.y,
  56.                     tileColor.y * gridMult.x * gridMult.y,
  57.                     tileColor.z * gridMult.x * gridMult.y,
  58.                     1.0 //the 4th rgba in our sampler is always 1.0 anyway
  59.                 );
  60.             }
  61.         `;
  62.  
  63.         const shader = this.buildShader(vsSource, fsSource);
  64.         this.programInfo = {
  65.             program: shader,
  66.             attribLocs: {
  67.                 vertexPosition: this.gl.getAttribLocation(shader, 'aVertPos')
  68.             },
  69.             uniformLocs: {
  70.                 projMat: this.gl.getUniformLocation(shader, 'uProjMat'),
  71.                 MVMat: this.gl.getUniformLocation(shader, 'uMVMat'),
  72.                 viewPos: this.gl.getUniformLocation(shader, 'uViewPos'),
  73.                 tileColorSamp: this.gl.getUniformLocation(shader, 'uTileColorSamp'),
  74.                 tileColorSampSize: this.gl.getUniformLocation(shader, 'uTileColorSampSize')
  75.             }
  76.         };
  77.         const buffers = this.initBuffers();
  78.  
  79.         //check and enable OES_texture_float to allow us to create our sampler tex
  80.         if (!this.gl.getExtension("OES_texture_float")) {
  81.             alert("Sorry, your browser/GPU/driver doesn't support floating point textures");
  82.         }
  83.  
  84.         this.gl.clearColor(0.0, 0.0, 0.15, 1.0);
  85.         this.gl.clearDepth(1.0);
  86.         this.gl.enable(this.gl.DEPTH_TEST);
  87.         this.gl.depthFunc(this.gl.LEQUAL);
  88.  
  89.         const FOV = 45 * Math.PI / 180;   // in radians
  90.         const aspect = this.gl.canvas.width / this.gl.canvas.height;
  91.         this.projMat = glMatrix.mat4.create();
  92.         glMatrix.mat4.perspective(this.projMat, FOV, aspect, 0.0, 100.0);
  93.         this.MVMat = glMatrix.mat4.create();
  94.         glMatrix.mat4.translate(this.MVMat, this.MVMat, [-0.0, -0.0, -1.0]);
  95.  
  96.         this.gl.bindBuffer(this.gl.ARRAY_BUFFER, buffers.position);
  97.         this.gl.vertexAttribPointer(this.programInfo.attribLocs.vertPos, 2, this.gl.FLOAT, false, 0, 0);
  98.         this.gl.enableVertexAttribArray(this.programInfo.attribLocs.vertPos);
  99.  
  100.         this.glDraw();
  101.     }
  102.     //glDraw() gets called once above, as well as in every frame of my render loop
  103.     //(not included here as I have it in a seperate Timing class)
  104.     glDraw() {
  105.         this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);
  106.         this.gl.useProgram(this.programInfo.program);
  107.  
  108.         //X and Y TILE_COUNTs varrified to correspond to colorArray size in testing
  109.         //(colorArray.length = rgbaLength * X_TILE_COUNT * Y_TILE_COUNT)
  110.         //(colorArray.length = rgbaLength * widthInTiles * heightInTiles)
  111.         //(colorArray.length = 4 * 27 * 20)
  112.         let x_tileColorSampSize = X_TILE_COUNT;
  113.         let y_tileColorSampSize = Y_TILE_COUNT;
  114.  
  115.         //getTileColorArray() produces a flat array of floats between 0.0and 1.0
  116.         //equal in length to rgbaLength * X_TILE_COUNT * Y_TILE_COUNT
  117.         //every 4th value is 1.0, representing tile alpha
  118.         let colorArray = this.getTileColorArray();
  119.  
  120.         let colorTex = this.colorMapTexFromArray(
  121.             x_tileColorSampSize,
  122.             y_tileColorSampSize,
  123.             colorArray
  124.         );
  125.         //SO solution said to use anyting between 0 and 15 for texUnit, they used 3
  126.         //I imagine this is just an arbitrary location in memory to hold a texture
  127.         let texUnit = 3;
  128.         this.gl.activeTexture(this.gl.TEXTURE0 + texUnit);
  129.         this.gl.bindTexture(this.gl.TEXTURE_2D, colorTex);
  130.         this.gl.uniform1i(
  131.             this.programInfo.uniformLocs.tileColorSamp,
  132.             texUnit
  133.         );
  134.         this.gl.uniform2fv(
  135.             this.programInfo.uniformLocs.tileColorSampSize,
  136.             [x_tileColorSampSize, y_tileColorSampSize]
  137.         );
  138.         this.gl.uniform2fv(
  139.             this.programInfo.uniformLocs.viewPos,
  140.             [-this.x_viewPos, this.y_viewPos] //these change as you drag your cursor across the canvas
  141.         );
  142.  
  143.         this.gl.uniformMatrix4fv(
  144.             this.programInfo.uniformLocs.projMat,
  145.             false,
  146.             this.projMat
  147.         );
  148.         this.gl.uniformMatrix4fv(
  149.             this.programInfo.uniformLocs.MVMat,
  150.             false,
  151.             this.MVMat
  152.         );
  153.  
  154.         this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4);
  155.     }
  156.     colorMapTexFromArray(width, height, colorArray) {
  157.         let float32Arr = Float32Array.from(colorArray);
  158.         let oldActive = this.gl.getParameter(this.gl.ACTIVE_TEXTURE);
  159.         //SO solution said "working register 31, thanks", next to next line
  160.         //not sure what that means but I think they're just looking for any
  161.         //arbitrary place to store the texture?
  162.         this.gl.activeTexture(this.gl.TEXTURE15);  
  163.  
  164.         var texture = this.gl.createTexture();
  165.         this.gl.bindTexture(this.gl.TEXTURE_2D, texture);
  166.         this.gl.texImage2D(
  167.             this.gl.TEXTURE_2D, 0, this.gl.RGBA,
  168.             //if I replace width and height with certain magic numbers
  169.             //like 4 or 8 (all the way up to 32 for width and 16 for height)
  170.             //I will see colored tiles, though obviously they don't map correctly.
  171.             //I THINK I've only seen it work with a widths and heights that are
  172.             //a power of 2... could the issue be that I need my texture to have
  173.             //width and height equal to a power of 2?
  174.             width, height, 0,
  175.             this.gl.RGBA, this.gl.FLOAT, float32Arr
  176.         );
  177.  
  178.         //use gl.NEAREST to prevent gl from blurring texture
  179.         this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.NEAREST);
  180.         this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.NEAREST);
  181.  
  182.  
  183.         this.gl.bindTexture(this.gl.TEXTURE_2D, null);
  184.         this.gl.activeTexture(oldActive);
  185.  
  186.         return texture;
  187.     }
  188.  
  189.     //I don't think the issue would be in the functions below, but I included them anyway
  190.     resizeCanvas(baseWidth, baseHeight) {
  191.         let widthMod = 0;
  192.         let heightMod = 0;
  193.         //...some math is done here to account for some DOM elements that consume window space...
  194.         this.canvas.width = baseWidth + widthMod;
  195.         this.canvas.height = baseHeight + heightMod;
  196.         this.gl.viewport(0, 0, this.gl.canvas.width, this.gl.canvas.height);
  197.     }
  198.     initBuffers() {
  199.         const posBuff = this.gl.createBuffer();
  200.         this.gl.bindBuffer(this.gl.ARRAY_BUFFER, posBuff);
  201.         const positions = [
  202.             -1.0,  1.0,
  203.              1.0,  1.0,
  204.             -1.0, -1.0,
  205.              1.0, -1.0,
  206.         ];
  207.         this.gl.bufferData(
  208.             this.gl.ARRAY_BUFFER,
  209.             new Float32Array(positions),
  210.             this.gl.STATIC_DRAW
  211.         );
  212.         return {
  213.             position: posBuff
  214.         };
  215.     }
  216.     buildShader(vsSource, fsSource) {
  217.         const vertShader = this.loadShader(this.gl.VERTEX_SHADER, vsSource);
  218.         const fragShader = this.loadShader(this.gl.FRAGMENT_SHADER, fsSource);
  219.  
  220.         const shaderProg = this.gl.createProgram();
  221.         this.gl.attachShader(shaderProg, vertShader);
  222.         this.gl.attachShader(shaderProg, fragShader);
  223.         this.gl.linkProgram(shaderProg);
  224.  
  225.         if (!this.gl.getProgramParameter(shaderProg, this.gl.LINK_STATUS)) {
  226.             console.error('Unable to initialize the shader program: ' + gl.getProgramInfoLog(shaderProg));
  227.             return null;
  228.         }
  229.  
  230.         return shaderProg;
  231.     }
  232.     loadShader(type, source) {
  233.         const shader = this.gl.createShader(type);      
  234.         this.gl.shaderSource(shader, source);
  235.         this.gl.compileShader(shader);
  236.  
  237.         if (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {
  238.             console.error('An error occurred compiling the shaders: ' + this.gl.getShaderInfoLog(shader));
  239.             this.gl.deleteShader(shader);
  240.             return null;
  241.         }
  242.         return shader;
  243.     }
  244.  
  245.     //getTileColorArray as it appears in my code, in case you want to take a peak.
  246.     //every tileGrid[i][j] has a color, which is an array of 4 values between 0.0 and 1.0
  247.     //the fourth (last) value in tileGrid[i][j].color is always 1.0
  248.     getTileColorArray() {
  249.         let i_min = Math.max(0, Math.floor(this.x_pxPosToTilePos(this.x_viewPos)));
  250.         let i_max = Math.min(GLOBAL.map.worldWidth-1, i_min + Math.ceil(this.x_pxPosToTilePos(this.canvas.width)) + 1);
  251.         let j_min = Math.max(0, Math.floor(this.y_pxPosToTilePos(this.y_viewPos)));
  252.         let j_max = Math.min(GLOBAL.map.worldHeight-1, j_min + Math.ceil(this.y_pxPosToTilePos(this.canvas.height)) + 1);
  253.  
  254.         let colorArray = [];
  255.         for (let i=i_min; i <= i_max; i++) {
  256.             for (let j=j_min; j <= j_max; j++) {
  257.                 colorArray = colorArray.concat(GLOBAL.map.tileGrid[i][j].color);
  258.             }
  259.         }
  260.         return colorArray;
  261.     }
Advertisement
Add Comment
Please, Sign In to add comment