关于如何使用TWGL https://github.com/greggman/twgl.js/tree/master/examples绘制3d内容,有几十个例子。但是如何用它来绘制二维图像呢?特别是我对如何在不使用着色器的情况下做到这一点很感兴趣?
发布于 2016-06-20 22:01:59
TWGL的唯一目的是减少WebGL的冗长性,但是WebGL基本上只做1件事情,那就是用你提供的着色器画东西。所以你真的不能在没有着色器的TWGL中做任何事情,就像你不能在没有着色器的WebGL中做任何事情一样。
如果你不想写任何着色器,那么你需要使用更高级别的3D库,如three.js、pixi.js或p5.js,甚至像Unity3D之类的东西,因为它们为你提供着色器。
否则,下面的代码基本上是使用TWGL在WebGL中实现canvas 2d的WebGL函数的
var m4 = twgl.m4;
var gl = twgl.getWebGLContext(document.getElementById("c"));
var programInfo = twgl.createProgramInfo(gl, ["vs", "fs"]);
// a unit quad
var bufferInfo = twgl.primitives.createXYQuadBufferInfo(gl);
// we're only using 1 texture so just make and bind it now
var tex = twgl.createTexture(gl, {
src: 'https://farm6.staticflickr.com/5695/21506311038_9557089086_m_d.jpg',
crossOrigin: '', // not needed if image on same origin
}, function(err, tex, img) {
// wait for the image to load because we need to know it's size
startRendering(img);
});
function startRendering(img) {
requestAnimationFrame(render);
function render(time) {
time *= 0.001;
twgl.resizeCanvasToDisplaySize(gl.canvas);
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
drawImage(
gl.canvas.width, gl.canvas.height,
tex, img.width, img.height,
Math.sin(time) * 50, Math.sin(time * 1.1) * 50);
requestAnimationFrame(render);
}
}
// we pass in texWidth and texHeight because unlike images
// we can't look up the width and height of a texture
// we pass in targetWidth and targetHeight to tell it
// the size of the thing we're drawing too. We could look
// up the size of the canvas with gl.canvas.width and
// gl.canvas.height but maybe we want to draw to a framebuffer
// etc.. so might as well pass those in.
// srcX, srcY, srcWidth, srcHeight are in pixels
// computed from texWidth and texHeight
// dstX, dstY, dstWidth, dstHeight are in pixels
// computed from targetWidth and targetHeight
function drawImage(
targetWidth, targetHeight,
tex, texWidth, texHeight,
srcX, srcY, srcWidth, srcHeight,
dstX, dstY, dstWidth, dstHeight) {
if (srcWidth === undefined) {
srcWidth = texWidth;
srcHeight = texHeight;
}
if (dstX === undefined) {
dstX = srcX;
dstY = srcY;
srcX = 0;
srcY = 0;
}
if (dstWidth === undefined) {
dstWidth = srcWidth;
dstHeight = srcHeight;
}
var mat = m4.identity();
var tmat = m4.identity();
var uniforms = {
matrix: mat,
textureMatrix: tmat,
texture: tex,
};
// these adjust the unit quad to generate texture coordinates
// to select part of the src texture
// NOTE: no check is done that srcX + srcWidth go outside of the
// texture or are in range in any way. Same for srcY + srcHeight
m4.translate(tmat, [srcX / texWidth, srcY / texHeight, 0], tmat);
m4.scale(tmat, [srcWidth / texWidth, srcHeight / texHeight, 1], tmat);
// these convert from pixels to clip space
m4.ortho(0, targetWidth, targetHeight, 0, -1, 1, mat)
// these move and scale the unit quad into the size we want
// in the target as pixels
m4.translate(mat, [dstX, dstY, 0], mat);
m4.scale(mat, [dstWidth, dstHeight, 1], mat);
gl.useProgram(programInfo.program);
twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
twgl.setUniforms(programInfo, uniforms);
twgl.drawBufferInfo(gl, bufferInfo);
}
body { margin: 0; }
canvas { width: 100vw; height: 100vh; display: block; }
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
<script id="vs" type="not-js">
// we will always pass a 0 to 1 unit quad
// and then use matrices to manipulate it
attribute vec4 position;
uniform mat4 matrix;
uniform mat4 textureMatrix;
varying vec2 texcoord;
void main () {
gl_Position = matrix * position;
texcoord = (textureMatrix * position).xy;
}
</script>
<script id="fs" type="not-js">
precision mediump float;
varying vec2 texcoord;
uniform sampler2D texture;
void main() {
if (texcoord.x < 0.0 || texcoord.x > 1.0 ||
texcoord.y < 0.0 || texcoord.y > 1.0) {
discard;
}
gl_FragColor = texture2D(texture, texcoord);
}
</script>
<canvas id="c"></canvas>
有关更详细的解释,请参见从2D画布和本文讨论如何实现像2D画布这样的矩阵堆栈。。
https://stackoverflow.com/questions/37927359
复制相似问题