Vertax Shader
precision mediump float; attribute vec2 vPos; void main() { gl_Position = vec4(vPos, 0.0, 1.0); }
Fragment Shader
precision mediump float; uniform vec2 viewportDimensions; uniform float minI; uniform float maxI; uniform float minR; uniform float maxR; void main(){ //[0,1080] -> [-2.0, 2.0] (1): Multiply by (2.0 - -2.0) / (1080 - 0) //높이 //[0,4.0] -> [-2.0, 2.0] (2): //[-2.0, 2.0] //그릴 위치 vec2 c = vec2( gl_FragCoord.x * (maxR -minR) / viewportDimensions.x + minR, gl_FragCoord.y * ( maxI - minI) / viewportDimensions.y + minI ); //Mandelbrot formula! vec2 z = c; float iterations = 0.0; float maxIterations = 2000.0; const int imaxIterations = 2000; //이거 넘으면 동작 없음. for(int i = 0; i < imaxIterations; i++){ float t = 2.0 * z.x * z.y + c.y; z.x = z.x* z.x - z.y *z.y + c.x; z.y = t; if(z.x*z.x +z.y*z.y > 4.0){ break; } iterations += 1.0; } if(iterations < maxIterations){ discard; //실행안함. }else{ gl_FragColor = vec4(0.0,0.0, 1.0, 1.0); } }
Script
var gl; var program; var canvas; function WebGLRenderApp(modelObj,imgSource) { AddEvent(window, 'resize', OnResizeWindow); AddEvent(window, 'wheel', OnZoom); AddEvent(window, 'mousemove', onMouseMove); canvas = document.getElementById("canvas-element-id"); gl = canvas.getContext('webgl'); if(!gl){ console.log("WebGL not supported falling back on experimental-webgl"); gl = canvas.getContext('experimental-webgl'); } if(!gl){ alert("Your browser does not support WebGL"); } // gl.enable(gl.DEPTH_TEST); // gl.enable(gl.CULL_FACE); // gl.frontFace(gl.CCW); // gl.cullFace(gl.BACK); var fragmentShader = getShader(gl, "shader-fs"); var vertexShader = getShader(gl, "shader-vs"); //program program = gl.createProgram(); gl.attachShader(program, vertexShader); gl.attachShader(program, fragmentShader); gl.linkProgram(program); if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { console.log('There was a problem with the PROGRAM :\n\n'+ gl.getProgramInfoLog(program)); gl.deleteProgram(program); } gl.validateProgram(program); if (!gl.getProgramParameter(program, gl.VALIDATE_STATUS)) { console.error('Error validating program!', gl.getProgramInfoLog(program)); } gl.useProgram(program); //========================= uniform var uniforms = { viewportDimensions:gl.getUniformLocation(program,'viewportDimensions'), minI:gl.getUniformLocation(program,'minI'), maxI:gl.getUniformLocation(program,'maxI'), minR:gl.getUniformLocation(program,'minR'), maxR:gl.getUniformLocation(program,'maxR') } //setCPU-side variables for all of our shader variables var vpDimensions = [canvas.width, canvas.height]; var minI = -2.0; var maxI = 2.0; var minR = -2.0; var maxR = 2.0; //create buffer var vertexBuffer = gl.createBuffer(); var vertices = [ -1, 1, -1, -1, 1, -1, -1,1, 1,1, 1,-1 ]; gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); var vPosAttrib = gl.getAttribLocation(program, 'vPos'); gl.vertexAttribPointer( vPosAttrib, 2, gl.FLOAT, gl.FALSE, 2 * Float32Array.BYTES_PER_ELEMENT, 0 ); gl.enableVertexAttribArray(vPosAttrib); //================================================== var thisframetime; var lastframetime = performance.now(); var dt; var frames = []; var lastPrintTime = performance.now(); var loop = function(){ thisframetime = performance.now(); dt = thisframetime - lastframetime; lastframetime = thisframetime; if(lastPrintTime + 750 < thisframetime){ lastPrintTime = this.frametime; var average = 0; for(var i= 0; i < frames.length; i++){ average += frames[i]; } average /= frames.length; document.title = 1000/ average + ' fps'; } gl.clearColor(0.75, 0.85, 0.8, 1.0); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); gl.uniform2fv(uniforms.viewportDimensions, vpDimensions); gl.uniform1f(uniforms.minI, minI); gl.uniform1f(uniforms.maxI, maxI); gl.uniform1f(uniforms.minR, minR); gl.uniform1f(uniforms.maxR, maxR); //$$$ 텍스쳐 // gl.bindTexture(gl.TEXTURE_2D, modelTexture); // gl.activeTexture(gl.TEXTURE0); //0,1 순서대로 들어간다. // gl.drawElements(gl.TRIANGLES, modelIndices.length, gl.UNSIGNED_SHORT, 0); //처음엔 없어서 에러.. gl.drawArrays(gl.TRIANGLES, 0, 6); //처음엔 없어서 에러.. // gl.viewport(0,0,canvas.width, canvas.height); //0-1사이의 값이 화면과 대칭되도록 설정. requestAnimationFrame(loop); } requestAnimationFrame(loop); OnResizeWindow(); function OnResizeWindow(){ if(!canvas){ return; } // canvas.width = window.innerWidth; // canvas.height = window.innerHeight; vpDimensions = [canvas.width,canvas.height]; var oldRealRange = maxR - minR; maxR = (maxI - minI) * (canvas.width / canvas.height) / 1.4 + minR; var newRealRange = maxR - minR; minR -= (newRealRange - oldRealRange) /2; maxR = (maxI - minI) * (canvas.width / canvas.height) / 1.4 + minR; gl.viewport(0,0,canvas.width, canvas.height); } function OnZoom(e){ var imaginaryRange = maxI - minI; var newRange; if(e.deltaY < 0){ newRange = imaginaryRange * 0.95; }else{ newRange = imaginaryRange * 1.05; } var delta = newRange - imaginaryRange; minI -= delta /2; maxI = minI + newRange; //console.log(delta, minI, maxI); OnResizeWindow(); } var last_position = {}; function onMouseMove(e){ if(e.buttons === 1){ //ie var movementX = (last_position.x ? e.clientX - last_position.x : 0); var movementY = (last_position.y ? e.clientY - last_position.y : 0); var iRange = maxI - minI; var rRange = maxR - minR; var iDelta = (movementY / canvas.height) * iRange; var rDelta = (movementX / canvas.width) * rRange; minI += iDelta; maxI += iDelta; minR -= rDelta; maxR -= rDelta; } last_position = { x : e.clientX, y : e.clientY }; } }