如何在 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 中做精灵的其他答案
我想用一些 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% 确定我理解你的问题但是...
来自您的
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 中做精灵的其他答案