As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center作为指导。
                            
                        
                    
                
                7年前关闭。
            
        

为了在webgl中实现鼠标手势,我想允许用户以“在屏幕上绘制”手绘模式。在3D webgl中进行此操作将使所使用的画笔具有良好的着色器效果,例如火焰效果,发光或其他炫酷的图形糖果。

在webgl中有效地在屏幕上绘制的当前推荐方式是什么?

谢谢!

最佳答案

您有2个选择。

您可以绘制到fbo,然后将fbo绘制到画布

要么

创建webgl上下文时,您可以请求'preserveDrawingBuffer:true'。



var canvas = document.getElementById("canvas");
var gl = canvas.getContext("webgl", {preserveDrawingBuffer:true});

program = twgl.createProgramFromScripts(gl, ["2d-vertex-shader", "2d-fragment-shader"]);
gl.useProgram(program);

var positionLoc = gl.getAttribLocation(program, "v_position");
var offsetLoc = gl.getUniformLocation(program, "u_offset");

var res = 1;
setupQuad(gl, res, positionLoc);

canvas.addEventListener('mousemove', draw, false);

function draw(event) {
  var m = getNoPaddingNoBorderCanvasRelativeMousePosition(event);
  // convert mouse coords to clip space since that's what this
  // particular shader is using. See
  // https://webglfundamentals.org
  // for how to use pixels instead of clip space.
  var x = m.x / gl.canvas.width * 2 - 1;
  var y = m.y / gl.canvas.height * -2 + 1;  // flip y

  drawBrush(x, y);
}

function drawBrush(x, y) {
  gl.uniform2f(offsetLoc, x, y);

  gl.drawElements(gl.TRIANGLES, res * res * 6, gl.UNSIGNED_SHORT, 0);
}

drawBrush(0, 0);



function setupQuad(gl, gridRes, positionLoc) {
  var scale = 0.05;
  var objects = [];

  var vertsAcross = gridRes + 1;
  var numVerts = vertsAcross * vertsAcross;
  var positions = new Float32Array(numVerts * 2);
  var indices = new Uint16Array(6 * gridRes * gridRes);
  var poffset = 0;

  for (var zz = 0; zz <= gridRes; ++zz) {
    for (var xx = 0; xx <= gridRes; ++xx) {
      var u = xx / gridRes;
      var v = zz / gridRes;
      positions[poffset + 0] = (-1 + 2 * u) * scale;
      positions[poffset + 1] = (-1 + 2 * v) * scale;
      poffset += 2;
    }
  }

  var tbase = 0;
  for (var zz = 0; zz < gridRes; ++zz) {
    var index = zz * vertsAcross;
    for (var xx = 0; xx < gridRes; ++xx) {
      indices[tbase + 0] = index + 0;
      indices[tbase + 1] = index + 1;
      indices[tbase + 2] = index + vertsAcross;
      indices[tbase + 3] = index + vertsAcross;
      indices[tbase + 4] = index + 1;
      indices[tbase + 5] = index + vertsAcross + 1;
      index += 1;
      tbase += 6;
    }
  }

  function makeBuffer(data, type, size, loc) {
    var buf = gl.createBuffer();
    gl.bindBuffer(type, buf);
    gl.bufferData(type, data, gl.STATIC_DRAW);
    if (type == gl.ARRAY_BUFFER) {
      gl.enableVertexAttribArray(loc);
      gl.vertexAttribPointer(loc, size, gl.FLOAT, false, 0, 0);
    }
    return buf;
  }

  objects.push(makeBuffer(positions, gl.ARRAY_BUFFER, 2, positionLoc));
  objects.push(makeBuffer(indices, gl.ELEMENT_ARRAY_BUFFER));

  return objects;
};

function getRelativeMousePosition(event, target) {
  target = target || event.target;
  var rect = target.getBoundingClientRect();

  return {
    x: event.clientX - rect.left,
    y: event.clientY - rect.top,
  }
}

// assumes target or event.target is canvas
function getNoPaddingNoBorderCanvasRelativeMousePosition(event, target) {
  target = target || event.target;
  var pos = getRelativeMousePosition(event, target);

  pos.x = pos.x * target.width  / canvas.clientWidth;
  pos.y = pos.y * target.height / canvas.clientHeight;

  return pos;
}

canvas { border: 1px solid black; }

<script src="https://twgljs.org/dist/twgl.min.js"></script>
<script id="2d-vertex-shader" type="x-shader/x-vertex">
attribute vec2 v_position;
uniform vec2 u_offset;

void main() {
    gl_Position = vec4(v_position + u_offset, 0, 1);
}
</script>
<script id="2d-fragment-shader" type="x-shader/x-fragment">
precision mediump float;
void main() {
    gl_FragColor = vec4(0, 1, 0, 1);
}
</script>
<canvas id="canvas" width="400" height="300"></canvas>

关于javascript - 在webgl中进行全屏徒手画的正确方法是什么? ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/10834002/

10-13 01:32