webgl でマウス ジェスチャを実装するには、ユーザーがフリーハンド モードで「画面に描画」できるようにしたいと考えています。3D webgl でそれを行うと、使用されているブラシに、炎の効果、グロー、その他のクールなグラフィカル キャンディーなどの優れたシェーダー効果を持たせることができます。
webglで画面上に効率的に描画するための現在推奨される方法は何ですか?
ありがとう!
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>