diff --git a/js/fragshader.glsl b/js/fragshader.glsl index 41bb128..e7d1594 100644 --- a/js/fragshader.glsl +++ b/js/fragshader.glsl @@ -18,7 +18,7 @@ vec2 invMobius(vec2 a, vec2 b, vec2 c, vec2 d, vec2 z){ } -void mainImage( out vec4 fragColor, in vec2 fragCoord ) +vec4 mainImage( vec2 fragCoord ) { vec2 uv = fragCoord.xy / iResolution.xy; uv = uv- vec2(0.5,0.5); @@ -30,3 +30,7 @@ void mainImage( out vec4 fragColor, in vec2 fragCoord ) vec2 transCoord = invMobius(a,b,c,d,uv); fragColor = length(transCoord)>1.0?vec4(1,1,1,1):texture(iChannel0,transCoord); } + +void main(){ + gl_FragColor = mainImage(gl_FragCoord); +} \ No newline at end of file diff --git a/js/mobius.js b/js/mobius.js index 0e4af06..7b34080 100644 --- a/js/mobius.js +++ b/js/mobius.js @@ -1,6 +1,10 @@ var buffer; var gl; var canvas; +var glCanvas; +var program; +var tex; + function add_2d_ctrl(parent,variable,label,min_x,max_x,min_y,max_y) { @@ -59,8 +63,8 @@ function add_vector_field(){ canvas = document.createElement('canvas'); canvas.style.border = "1px solid"; canvas.id = 'canvas' - canvas.height = 600; - canvas.width = 600 + canvas.height = 500; + canvas.width = 500; ctx = canvas.getContext('2d'); document.body.appendChild(canvas); @@ -101,13 +105,81 @@ function render(a,b,c,d){ } -function renderGL() { +function renderGL(texture) { + + - window.requestAnimationFrame(render, canvas); + window.requestAnimationFrame(renderGL, canvas); gl.clearColor(1.0, 0.0, 0.0, 1.0); gl.clear(gl.COLOR_BUFFER_BIT); + + positionLocation = gl.getAttribLocation(program, "a_position"); + gl.enableVertexAttribArray(positionLocation); + gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0); + + + + + + gl.uniform2f(gl.getUniformLocation(program, "a"),a.re,a.im); + gl.uniform2f(gl.getUniformLocation(program, "b"),b.re,b.im); + gl.uniform2f(gl.getUniformLocation(program, "c"),c.re,c.im); + gl.uniform2f(gl.getUniformLocation(program, "d"),d.re,d.im); + + gl.drawArrays(gl.TRIANGLES, 0, 6); } +//Load Texture function from MDN +function loadTexture(gl, url) { + const texture = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, texture); + + // Because images have to be download over the internet + // they might take a moment until they are ready. + // Until then put a single pixel in the texture so we can + // use it immediately. When the image has finished downloading + // we'll update the texture with the contents of the image. + const level = 0; + const internalFormat = gl.RGBA; + const width = 1; + const height = 1; + const border = 0; + const srcFormat = gl.RGBA; + const srcType = gl.UNSIGNED_BYTE; + const pixel = new Uint8Array([0, 0, 255, 255]); // opaque blue + gl.texImage2D(gl.TEXTURE_2D, level, internalFormat, + width, height, border, srcFormat, srcType, + pixel); + + const image = new Image(); + image.onload = function() { + gl.bindTexture(gl.TEXTURE_2D, texture); + gl.texImage2D(gl.TEXTURE_2D, level, internalFormat, + srcFormat, srcType, image); + + // WebGL1 has different requirements for power of 2 images + // vs non power of 2 images so check if the image is a + // power of 2 in both dimensions. + if (isPowerOf2(image.width) && isPowerOf2(image.height)) { + // Yes, it's a power of 2. Generate mips. + gl.generateMipmap(gl.TEXTURE_2D); + } else { + // No, it's not a power of 2. Turn of mips and set + // wrapping to clamp to edge + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + } + }; + image.src = url; + + return texture; +} + +function isPowerOf2(value) { + return (value & (value - 1)) == 0; +} + var Complex = function(_re,_im){ this.im = _im; @@ -150,6 +222,7 @@ var d = new Complex(0,0); $(function () {//document is ready, setup everything + //Create GUI div guibox = document.createElement('div'); guibox.id = "gui-box"; @@ -162,10 +235,61 @@ $(function () {//document is ready, setup everything add_vector_field(); - gl = canvas.getContext('experimental-webgl'); + glCanvas = document.createElement("canvas"); + glCanvas.id = 'glcanvas'; + glCanvas.width = 500; + glCanvas.height = 500; + document.body.appendChild(glCanvas); + + gl = glCanvas.getContext('experimental-webgl'); gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); - renderGL(); + buffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, buffer); + gl.bufferData( + gl.ARRAY_BUFFER, + new Float32Array([ + -1.0, -1.0, + 1.0, -1.0, + -1.0, 1.0, + -1.0, 1.0, + 1.0, -1.0, + 1.0, 1.0]), + gl.STATIC_DRAW + ); + + tex = loadTexture(gl,"img/uvgrid.png"); + + var shaderScript; + var shaderSource; + var vertexShader; + var fragmentShader; + + shaderScript = document.getElementById("2d-vertex-shader"); + shaderSource = shaderScript.text; + vertexShader = gl.createShader(gl.VERTEX_SHADER); + gl.shaderSource(vertexShader, shaderSource); + gl.compileShader(vertexShader); + + shaderScript = document.getElementById("2d-fragment-shader"); + shaderSource = shaderScript.text; + fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); + gl.shaderSource(fragmentShader, shaderSource); + gl.compileShader(fragmentShader); + + console.log(gl.getShaderInfoLog(fragmentShader)); + + program = gl.createProgram(); + gl.attachShader(program, vertexShader); + gl.attachShader(program, fragmentShader); + gl.linkProgram(program); + gl.useProgram(program); + + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, tex); + gl.uniform1i(gl.getUniformLocation(program, 'sampler'), 0); + + renderGL(program,tex); }); diff --git a/mobius.html b/mobius.html index 7817d37..6d68495 100644 --- a/mobius.html +++ b/mobius.html @@ -15,5 +15,76 @@ + + + + \ No newline at end of file