如何在 webgl 上渲染具有指定宽度和高度的 2d 精灵

How to render 2d sprites with specified width and height on webgl

我想用一些 width/height 渲染 2d 精灵。我试试这个:

顶点设置:

  // width/height in canvas dimensions space
  const width = 100,
        height = 100;

  const left = 0,
        right = width,
        down = 0,
        up = height;
  /*
    (-1, 1).( 1, 1)
    .
    (-1,-1).( 1,-1)
  */
  let positions = [
    left, down,
    left, up,
    right, down,
    left, up,
    right, down,
    right, up
  ];


  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);

顶点着色器:

in vec2 a_position;

out vec2 vQuadCoord;

uniform vec2 uResolution;

uniform mat3 uMatrix;

void main() {

  vec2 position = (uMatrix * vec3(a_position, 1)).xy;

  vec2 zeroToOne = position / uResolution;
  vec2 zeroToTwo = zeroToOne * 2.0;
  vec2 clipSpace = zeroToTwo - 1.0;

  // no translation for quad coordinates
  vQuadCoord = (a_position / uResolution) * 2.0 - 1.0;

  gl_Position = vec4(clipSpace, 0, 1);

}

uResolution统一是[gl.canvas.width, gl.canvas.height]。 问题是当我将宽度设置为较小的尺寸时,精灵内部的形状不会缩放。 这是使用指定 width/height 渲染精灵的正确方法吗?

不是 100% 确定我理解你的问题但是...

来自您的 you hadn't finished reading the article。这个问题遵循相同的模式,因为你的着色器来自文章的顶部,而文章的整个要点是将着色器简化为

in vec2 a_position;

uniform mat3 u_matrix;

void main() {
  gl_Position = vec4((u_matrix * vec3(a_position, 1)).xy, 0, 1);
}

一旦你这样做了,只需改变你传入的矩阵就可以很容易地调整更多的东西。在你的问题中,投影是硬编码的,所以用矩阵来做可以说更好。

本文以计算这样的矩阵结束

var matrix = m3.projection(gl.canvas.clientWidth, gl.canvas.clientHeight);
matrix = m3.translate(matrix, translation[0], translation[1]);
matrix = m3.rotate(matrix, rotationInRadians);
matrix = m3.scale(matrix, scale[0], scale[1]);

第一部分

var matrix = m3.projection(gl.canvas.clientWidth, gl.canvas.clientHeight);

定义 canvas 中代表的单位数量。通过像上面一样设置它,它总是与 canvas 显示的大小相同,因此无论 canvas 的大小如何,10 个单位宽的内容在页面上将是 10 像素。

如果您希望 canvas 中的所有内容在您更改其大小时缩放,那么您需要自己选择适合 canvas 的单位数。像

var aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;
var unitsDownCanvas = 100;
var unitsAcrossCanvas = unitsDownCanvas * aspect;
var matrix = m3.projection(unitsAcrossCanvas, unitsDownCanvas);

现在无论 canvas 显示的尺寸如何,canvas 下方都会有 100 个单位。

至于缩放精灵,上面代码中的 scale 行选择缩放

var matrix = m3.projection(gl.canvas.clientWidth, gl.canvas.clientHeight);
matrix = m3.translate(matrix, translation[0], translation[1]);
matrix = m3.rotate(matrix, rotationInRadians);
matrix = m3.scale(matrix, scale[0], scale[1]);   // this line

在那之后,通常你会用精灵绘制纹理,所以你 pass texture coordinates to your fragment shader and render with textures

如果你想要一个灵活的 2D sprite 函数,该系列将继续制作 here. It also covers 3D sprites here

还有一些在 webgl 中做精灵的其他答案