2016-08-12 123 views
-5

我試圖研究WebGL,但我什麼都沒有。 我不想使用這個庫,它們太大了。 我寫我要在畫布上的東西,幫我做它的WebGL畫布到WebGL

https://jsfiddle.net/g9tx903c/

<canvas id="canvas" width="500" height="200"></canvas> 

<script type='text/javascript'> 
    function DrawPoint(x, y, size, blur, opacity) { 
     var c = document.getElementById('canvas'); 
     var ctx = c.getContext('2d'); 

     var halfSize = size/2; 

     var radgrad = ctx.createRadialGradient(halfSize + x, halfSize + y, 0, halfSize + x, halfSize + y, halfSize); 
     radgrad.addColorStop(blur, 'rgba(255, 255, 255, ' + opacity +')'); 
     radgrad.addColorStop(1, 'rgba(255, 255, 255, 0)'); 
     ctx.fillStyle = radgrad; 
     ctx.fillRect(x, y, size, size); 
    } 


    function DrawcGradient() { 
     var w = 500; 
     var h = 200; 

     var pointR = w/2; 
     var x = (w/2); 
     var y = (h/2); 

     var c = document.getElementById('canvas'); 
     var ctx = c.getContext('2d'); 
     var grd = ctx.createRadialGradient(x, y, 0, x, y, pointR); 
     grd.addColorStop(0, '#5A6977'); 
     grd.addColorStop(1, '#000'); 
     ctx.fillStyle = grd; 
     ctx.fillRect(0, 0, w, h); 
    } 


    DrawcGradient(); 
    DrawPoint(50, 100, 50, 0.5, 0.2); 
    DrawPoint(70, 10, 150, 0.93, 0.2); 
</script> 
+2

你可以開始使用[的HelloWorld(http://webglfundamentals.org/webgl/lessons/webgl-fundamentals.html)的例子。 –

+0

你爲什麼要使用WebGL?你的目標是什麼? – LarsH

+0

帆布不會很快 – Fulrus

回答

0

這恰好落到我再次迎頭趕上域。也許不是你想要的,但你可以刪除所有的2D畫布的東西,只是保持webGL的東西。

此演示混合2D和3D畫布接口獲得二維畫布內容的高性能GPU處理。

片段着色器確實接近所謂FragmentShader

徑向漸變創建代碼底部創建漸變的工作,通過計算從中心的距離,得到一個數值0〜1,我用這個值來獲得3個梯度。要改變我乘以的梯度的銳度,請拉下並夾緊這些值。

例如靠近鼠標大圓是1在中心並遠離0。我乘以350得到350到0,然後我下拉270到80到-270,然後我把它鉗到0和1.結果是一個急劇的梯度。

我圓圈定位在從點的線只是在畫布的頂部,一個鼠標沿着線路的其他進一步的附近。

有很多的鍋爐板的東西,今天我多一點,所以你將不得不螺母剩餘部分。

很容易轉換爲所有的webGL。只需將頂部的所有畫布鼠標移除即可。創建一個圖像,並調用startWebGL(image)添加webGL畫布(你在startWebGL函數創建後)的文檔正文並調用至少一次函數webGLRender設置着色器變量和渲染的幀。

警告着色器具有高層次的指令和不支持的代碼不能使用。要與其他設置一起使用,請刪除着色器中所有uniformattribute變量之間的#。即#uniform vec2 mouse;成爲uniform vec2 mouse;

//================================================================================================== 
 
// The following code is support code that provides me with a standard interface to various forums. 
 
// It provides a mouse interface, a full screen canvas, and some global often used variable 
 
// like canvas, ctx, mouse, w, h (width and height), globalTime 
 
// It should not be used as an example of how to write a canvas interface. 
 
// By Blindman67 
 
const U = undefined; 
 
const RESIZE_DEBOUNCE_TIME = 100; 
 
var onresize; // demo use this to do your thing 
 
var w,h,cw,ch,canvas,ctx,mouse,createCanvas,resizeCanvas,setGlobals,globalTime=0,resizeCount = 0; 
 
createCanvas = function() { // create 2D display canvas 
 
    var c,cs; 
 
    cs = (c = document.createElement("canvas")).style; 
 
    cs.position = "absolute"; 
 
    cs.top = cs.left = "0px"; 
 
    cs.zIndex = 1000; 
 
    document.body.appendChild(c); 
 
    return c; 
 
} 
 
resizeCanvas = function() { 
 
    if (canvas === U) { 
 
     canvas = createCanvas(); 
 
    } 
 
    canvas.width = window.innerWidth; 
 
    canvas.height = window.innerHeight; 
 
    ctx = canvas.getContext("2d"); 
 
    if (typeof setGlobals === "function") { 
 
     setGlobals(); 
 
    } 
 
    if (typeof onresize === "function"){ 
 
     resizeCount += 1; 
 
     setTimeout(debounceResize,RESIZE_DEBOUNCE_TIME); 
 
    } 
 
} 
 
function debounceResize(){ 
 
    resizeCount -= 1; 
 
    if(resizeCount <= 0){ 
 
     onresize(); 
 
    } 
 
} 
 
setGlobals = function(){ 
 
    cw = (w = canvas.width)/2; 
 
    ch = (h = canvas.height)/2; 
 
    mouse.updateBounds(); 
 
} 
 
mouse = (function(){ 
 
    function preventDefault(e) { e.preventDefault(); } 
 
    var mouse = { 
 
     x : 0, y : 0, w : 0, alt : false, shift : false, ctrl : false, buttonRaw : 0, over : false, bm : [1, 2, 4, 6, 5, 3], 
 
     active : false,bounds : null, crashRecover : null, mouseEvents : "mousemove,mousedown,mouseup,mouseout,mouseover,mousewheel,DOMMouseScroll".split(",") 
 
    }; 
 
    var m = mouse; 
 
    function mouseMove(e) { 
 
     var t = e.type; 
 
     m.x = e.clientX - m.bounds.left; m.y = e.clientY - m.bounds.top; 
 
     m.alt = e.altKey; m.shift = e.shiftKey; m.ctrl = e.ctrlKey; 
 
     if (t === "mousedown") { m.buttonRaw |= m.bm[e.which-1]; } 
 
     else if (t === "mouseup") { m.buttonRaw &= m.bm[e.which + 2]; } 
 
     else if (t === "mouseout") { m.buttonRaw = 0; m.over = false; } 
 
     else if (t === "mouseover") { m.over = true; } 
 
     else if (t === "mousewheel") { m.w = e.wheelDelta; } 
 
     else if (t === "DOMMouseScroll") { m.w = -e.detail; } 
 
     if (m.callbacks) { m.callbacks.forEach(c => c(e)); } 
 
     if((m.buttonRaw & 2) && m.crashRecover !== null){ if(typeof m.crashRecover === "function"){ setTimeout(m.crashRecover,0);}}   
 
     e.preventDefault(); 
 
    } 
 
    m.updateBounds = function(){ 
 
     if(m.active){ 
 
      m.bounds = m.element.getBoundingClientRect(); 
 
     } 
 
    } 
 
    m.addCallback = function (callback) { 
 
     if (typeof callback === "function") { 
 
      if (m.callbacks === U) { m.callbacks = [callback]; } 
 
      else { m.callbacks.push(callback); } 
 
     } else { throw new TypeError("mouse.addCallback argument must be a function"); } 
 
    } 
 
    m.start = function (element, blockContextMenu) { 
 
     if (m.element !== U) { m.removeMouse(); }   
 
     m.element = element === U ? document : element; 
 
     m.blockContextMenu = blockContextMenu === U ? false : blockContextMenu; 
 
     m.mouseEvents.forEach(n => { m.element.addEventListener(n, mouseMove); }); 
 
     if (m.blockContextMenu === true) { m.element.addEventListener("contextmenu", preventDefault, false); } 
 
     m.active = true; 
 
     m.updateBounds(); 
 
    } 
 
    m.remove = function() { 
 
     if (m.element !== U) { 
 
      m.mouseEvents.forEach(n => { m.element.removeEventListener(n, mouseMove); }); 
 
      if (m.contextMenuBlocked === true) { m.element.removeEventListener("contextmenu", preventDefault);} 
 
      m.element = m.callbacks = m.contextMenuBlocked = U; 
 
      m.active = false; 
 
     } 
 
    } 
 
    return mouse; 
 
})(); 
 
/** SimpleFullCanvasMouse.js end **/ 
 
function display(){ 
 
    ctx.setTransform(1,0,0,1,0,0); // reset transform 
 
    ctx.globalAlpha = 1;   // reset alpha 
 
    ctx.clearRect(0,0,w,h); 
 
    if(webGL !== undefined){ 
 
     webGLRender(); 
 
    } 
 
} 
 
function update(timer){ // Main update loop 
 
    globalTime = timer; 
 
    display(); // call demo code 
 
    requestAnimationFrame(update); 
 
} 
 
// END of boilerplate stuff. 
 

 
/* *************************************************************************************************** 
 
The following functions are helpers for Shader variables. Rather than having to type all the mumbo 
 
jumbo to locate shader variable and then store the location ID getVariables and getLocations does 
 
it for you. uniform and attribute variable that are prefixed with # are can used via the gl.locs.name 
 
(no space between # and variable type #attribute is good # attribute is bad) 
 

 
For example 
 
    #uniform vec3 myVec; // the shader source code 
 
Is located and given the name myVec in gl.locs and can be set in javascript 
 
    gl.uniform3f(gl.locs.myVec, 0.3, 0.5, 0.8); // 
 
    
 
Please not that this makes shaders source code none standard and will not complie as is without these 
 
functions . Just remove the # 
 
*************************************************************************************************** */ 
 
const VAR_TYPES = ["attribute","uniform"]; 
 
const VAR_LOCATE_FUNC = {attribute : "getAttribLocation", uniform : "getUniformLocation"} 
 
// get # delimited variables from shader source 
 
function getVariables(script,types){ 
 
    VAR_TYPES.forEach(f => { 
 
     if(types.items === undefined){ types.items = []; } 
 
     script = script.replace(new RegExp("#" + f+".+;","g"), str => { 
 
      var data = str.replace(/ /g," ").split(" "); 
 
      types.items.push({use : f , type : data[1] , name : data[2].replace(";","")}); 
 
      return str.substr(1); 
 
     }) 
 
    }) 
 
    return script; 
 
} 
 
// get location IDs for shader variables 
 
var getLocations = function(gl,shaders){ 
 
    var locs = {}; 
 
    shaders.variables.items.forEach(v => { locs[v.name] = gl[VAR_LOCATE_FUNC[v.use]](shaders.program, v.name); }); 
 
    return locs; 
 
} 
 
/* end of var heplers ***************************************************************************** */ 
 
// creates vertex and fragment shaders 
 
function createProgramFromScripts(gl, ids) { 
 
    var shaders = []; 
 
    var variables = {}; 
 
    for (var i = 0; i < ids.length; i += 1) { 
 
     var script = shadersSource[ids[i]]; 
 
     if (script !== undefined) { 
 
      var shader = gl.createShader(gl[script.type]); 
 
      var source = getVariables(script.source,variables) 
 
      gl.shaderSource(shader, source); 
 
      gl.compileShader(shader); 
 
      shaders.push(shader); 
 
     }else{ 
 
      throw new ReferenceError("*** Error: unknown script ID : " + ids[i]); 
 
     } 
 
    } 
 
    var program = gl.createProgram(); 
 
    shaders.forEach((shader) => { gl.attachShader(program, shader); }); 
 
    gl.linkProgram(program); 
 
    gl.locs = getLocations(gl,{ program : program,variables : variables}); 
 
    return program; 
 
} 
 
// setup simple 2D webGL image processor 
 
var webGL; 
 
function startWebGL(image) { 
 
    webGL = document.createElement("canvas"); 
 
    webGL.width = image.width; 
 
    webGL.height = image.height; 
 
    var gl = webGL.gl = webGL.getContext("webgl"); 
 
    var program = createProgramFromScripts(gl, ["VertexShader", "FragmentShader"]); 
 
    gl.useProgram(program); 
 
    gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer()); 
 
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0]), gl.STATIC_DRAW); 
 
    gl.enableVertexAttribArray(gl.locs.texCoord); 
 
    gl.vertexAttribPointer(gl.locs.texCoord, 2, gl.FLOAT, false, 0, 0); 
 

 
    gl.bindTexture(gl.TEXTURE_2D, gl.createTexture()); 
 
    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.NEAREST); 
 
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); 
 
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); 
 
    gl.uniform2f(gl.locs.resolution, webGL.width, webGL.height); 
 
    gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer()); 
 
    gl.enableVertexAttribArray(gl.locs.position); 
 
    gl.vertexAttribPointer(gl.locs.position, 2, gl.FLOAT, false, 0, 0); 
 
    setRectangle(gl, 0, 0, image.width, image.height); 
 
} 
 
function setRectangle(gl, x, y, width, height) { // set draw rectangle 
 
    var x1 = x + width; 
 
    var y1 = y + height; 
 
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ x, y, x1, y, x, y1, x, y1, x1, y, x1, y1]), gl.STATIC_DRAW); 
 
} 
 
var shadersSource = { 
 
    VertexShader : { 
 
     type : "VERTEX_SHADER", 
 
     source : ` 
 
      // the # is a higher level directive to indicate that the variable needs to 
 
      // be loacted as value set or read 
 
      #attribute vec2 position; 
 
      #attribute vec2 texCoord; 
 
      #uniform vec2 resolution; 
 
      varying vec2 u_texCoord; // varying means this is moved to the frag shader 
 
      float aspect = resolution.x/resolution.y; 
 
      varying float aspect1; 
 
      void main() { 
 
       vec2 zeroToOne = position/resolution; 
 
       vec2 zeroToTwo = zeroToOne * 2.0; 
 
       vec2 clipSpace = zeroToTwo - 1.0; 
 
       gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1); 
 
       u_texCoord = vec2(texCoord.x ,texCoord.y/aspect); 
 
       aspect1 = aspect; 
 
      }` 
 
    }, 
 
    FragmentShader : { 
 
     type : "FRAGMENT_SHADER", 
 
     source : ` 
 
      // the # is a higher level directive to indicate that the variable needs to 
 
      // be loacted as value set or read   
 
      precision mediump float; 
 
      #uniform sampler2D u_image; 
 
      #uniform vec4 backDark; // the background dark colour 
 
      #uniform vec4 backLight; // backgroun light colour 
 
      #uniform vec4 ringCol; // rings colour 
 
      #uniform vec2 lightLoc; // location of point from which to project second ring 
 
      #uniform vec2 mouse;  // location of big ring 
 
      varying float aspect1; 
 
      varying vec2 u_texCoord; // texture coord for all mapping and comes from the 
 
             // vertext shader. If you change the name here 
 
             // change it in the vert shader 
 
      float dist;    // used for background gradient 
 
      vec4 pixelCol;   // to hold the final pixel colour 
 
      vec2 gradCenter = vec2(0.5,0.25); // location of background gradient center 
 
      vec2 secondRing = lightLoc+ (mouse - lightLoc) * (1.2 + distance(mouse,lightLoc)); 
 

 
      
 
      void main() { 
 
       pixelCol = texture2D(u_image, vec2(u_texCoord.x,u_texCoord.y * aspect1)); 
 
       //pixelCol = texture2D(u_image, vec2(u_texCoord.x,u.texCoord.y); 
 
       // get distance from center of background gradient 
 
       dist = distance(gradCenter,u_texCoord)/0.707; 
 
       // use dist to caculate the background gradient 
 
       pixelCol += (backDark - backLight) * dist + backLight; 
 
       // add the big ring colour to the background. mouse is the center of big ring 
 
       pixelCol += clamp((1.0-distance(mouse,u_texCoord)) * 345.0 - 270.5 ,0.0,1.0) * ringCol; 
 
       // add the second rign colour to the background colour. secondRing is location of second ring 
 
       pixelCol += clamp((1.0-distance(secondRing,u_texCoord)) * 29.0 - 27. ,0.0,1.0) * ringCol; 
 

 
       gl_FragColor = pixelCol; // set the fragment to the colour caculated 
 
      }` 
 
    } 
 
} 
 
var firstRun = true; 
 
function webGLRender(){ 
 
    var gl = webGL.gl; 
 
    if(firstRun){ 
 
     firstRun = false; 
 
     gl.uniform4f(gl.locs.backDark, 0,0,0,1) 
 
     gl.uniform4f(gl.locs.backLight, 0.3,0.5,0.8,1) 
 
     gl.uniform4f(gl.locs.ringCol, 0.1,0.1,0.38,0.41) 
 
     gl.uniform2f(gl.locs.lightLoc, 0.5,0.0); 
 
    } 
 
    gl.uniform2f(gl.locs.mouse, mouse.x/w,mouse.y/h); 
 
    gl.drawArrays(gl.TRIANGLES, 0, 6); 
 
    ctx.drawImage(webGL,0,0, canvas.width, canvas.height); 
 
} 
 
function createImageAndStartWebGL(){ 
 
    var image = document.createElement("canvas"); 
 
    image.width = canvas.width; 
 
    image.height = canvas.height; 
 
    image.ctx = image.getContext("2d"); 
 
    image.ctx.fillRect(0,0,canvas.width,canvas.height); 
 
    image.ctx.font = "48px arial"; 
 
    image.ctx.textAlign = "center"; 
 
    image.ctx.fillStyle = "white"; 
 
    image.ctx.fillText("WebGL & Canvas 2D demo",canvas.width/2,48); 
 
    image.ctx.font = "16px arial"; 
 
    image.ctx.fillText("WebGL fragment shader processing 2D canvas image, then render back to 2D canvas.",canvas.width/2,66); 
 
    firstRun = true; 
 
    startWebGL(image); 
 
} 
 
// Add the setup to the debounced resize 
 
onresize = createImageAndStartWebGL; 
 

 
// start it all happening 
 
resizeCanvas(); 
 
mouse.start(canvas,true); 
 
window.addEventListener("resize",resizeCanvas); 
 
requestAnimationFrame(update);

+0

謝謝您的例子 – Fulrus

+0

試試我怎麼可以,如果我需要產生很多球?我想要達到這個效果http://huaban.com/pins/604178757/ – Fulrus

+0

@Fulrus你需要一個webGL 2D粒子FX,或者可以用反饋紋理完成,但是會非常棘手,並且可能無法很好地工作機器。 webGL粒子將是最好的解決方案,甚至在2D畫布中也能正常工作。 – Blindman67