当前位置: 首页 > 知识库问答 >
问题:

在使用WebGL中的texture2D渲染图像到画布时,如何保持纵横比?

东门秦迟
2023-03-14

我有一个宽*高=1442 * 1303的图像,我能够阅读它们,并通过webgl的文本2D成功地渲染到画布上。

在客户端,我有一个数组缓冲区,它获取大小=宽度*高度*4的图像数据。

所以,当我的画布宽度和高度为窗口时,如何保持图像的纵横比。innerWidth*0.90和窗口。内部高度*0.90。

此外,我必须直接渲染使用数组缓冲区通过WEBGL 2d的纹理,所以,我不能使用任何2d canvs API,如绘制图像。请提出一些建议。

共有1个答案

袁骏祥
2023-03-14

这个问题有一百万个答案。

首先是图像的大小,然后是您决定绘制的大小,画布的大小,然后是画布显示的大小。还有你使用的顶点的位置,可以是任何东西。

请参阅WebGL上的这篇文章,其中指出WebGL使用剪辑空间坐标(-1到1),这篇文章指出画布显示的大小与其分辨率是分开的。

让我们假设您希望将图像绘制得尽可能大,并使其适合画布。

首先让我们查看画布显示的大小

var canvasDisplayWidth  = gl.canvas.clientWidth;
var canvasDisplayHeight = gl.canvas.clientHeight;

让我们假设我们想要绘制的图像尽可能大所以首先尝试拟合的宽度到画布

var imageDisplayWidth  = canvasDisplayWidth;
var imageDisplayHeight = img.height * imageDisplayWidth / img.width;

现在让我们看看它是否合适?如果没有,我们就用高度

if (imageDrawHeight > canvasDisplayHeight) { 
  imageDisplayHeight = canvasDisplayHeight;
  imageDisplayWidth  = img.width * imageDisplayHeight / img.height;
}

现在我们需要将imageDisplayWidthimageDisplayHeight转换为画布中像素的大小。注意:如果画布显示的大小与其分辨率相同,则可以跳过此步骤,因为显示大小和绘图大小将相同。

// make our image take into account the pixel aspect
var canvasPixelsAcrossPerDisplayPixel = gl.canvas.width  / canvasDisplayWidth;
var canvasPixelsDownPerDisplayPixel   = gl.canvas.height / canvasDisplayHeight;

var imageDrawWidth  = imageDisplayWidth  * canvasPixelsAcrossPerDisplayPixel;
var imageDrawHeight = imageDisplayHeight * canvasPixelsDownPerDisplayPixel;     

现在我们需要把它转换成夹子空间

var clipWidth  = imageDrawWidth  / canvas.width;
var clipHeight = imageDrawHeight / canvas.height;

现在,给定一个单位四,我们可以缩放它以适应那个尺寸。

var m = m4.identity();

// convert our square unit quad match the size we want
m4.scale(m, [clipWidth, clipHeight, 1], m);

// move our unit square from 0,0 (the center) to the bottom, top corner
m4.translate(m, [-1, 1, 0], m);

// scale our unit sqaure to cover the clip space
m4.scale(m, [2, -2, 1], m); 

现在我们可以用矩阵和我们的单位四元组画图了

var m4 = twgl.m4;
var gl = twgl.getWebGLContext(document.getElementById("c"));
var programInfo = twgl.createProgramInfo(gl, ["vs", "fs"]);

var arrays = {
  position: {
    numComponents: 2,
    data: [
      0, 0,
      1, 0,
      0, 1,
      0, 1,
      1, 0,
      1, 1,
    ],
  },
};
var bufferInfo = twgl.createBufferInfoFromArrays(gl, arrays);

// Lets make a texture using a 2d canvas
// There's a circle in the middle. If our
// code is correct it will be a circle when
// drawn (not an oval or ellipse)
var ctx = document.createElement("canvas").getContext("2d");
ctx.canvas.width = 100;
ctx.canvas.height = 75;
ctx.fillStyle = "red";
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.fillStyle = "blue";
ctx.fillRect(10, 10, ctx.canvas.width - 20, ctx.canvas.height - 20);
ctx.strokeStyle = "yellow";
ctx.lineWidth = 20;
ctx.beginPath();
ctx.arc(
  ctx.canvas.width / 2, ctx.canvas.height / 2,
  Math.min(ctx.canvas.width, ctx.canvas.height) / 2 - 20,
  0, Math.PI * 2, false);
ctx.stroke();

var img = ctx.canvas;
      
var tex = twgl.createTexture(gl, {
  src: img,
});

var canvasDisplayWidth  = gl.canvas.clientWidth;
var canvasDisplayHeight = gl.canvas.clientHeight;

// Let's assume we want to draw the image as large as possible so
// first try fitting the width to the canvas

var imageDisplayWidth  = canvasDisplayWidth;
var imageDisplayHeight = img.height * imageDisplayWidth / img.width;

// Now let's check if it fit? If not let's use the height
if (imageDisplayHeight > canvasDisplayHeight) { 
  imageDisplayHeight  = canvasDisplayHeight;
  imageDisplayWidth   = img.width * imageDisplayHeight / img.height;
}
      
// Now we need to convert `imageDisplayWidth` and `imageDisplayHeight` to the size of pixels
// in the canvas. Note: If the canvas is being displayed the same size
// as the its resolution you can skip this step

var canvasPixelsAcrossPerDisplayPixel = gl.canvas.width  / canvasDisplayWidth;
var canvasPixelsDownPerDisplayPixel   = gl.canvas.height / canvasDisplayHeight;

var imageDrawWidth  = imageDisplayWidth  * canvasPixelsAcrossPerDisplayPixel;
var imageDrawHeight = imageDisplayHeight * canvasPixelsDownPerDisplayPixel;     

// Now we need to convert that to clip space

var clipWidth  = imageDrawWidth  / gl.canvas.width;
var clipHeight = imageDrawHeight / gl.canvas.height;

// Now, given a unit quad we can just scale it to fit that size.
var m = m4.identity();

// convert our square unit quad to something to match the image's aspect
m4.scale(m, [clipWidth, clipHeight, 1], m);

// move our unit square from 0,0 (the center) to the bottom, left corner
m4.translate(m, [-1, 1, 0], m);

// scale our unit square to cover the clip space
m4.scale(m, [2, -2, 1], m); 

var uniforms = {
  texture: tex,
  matrix: m,
};

gl.useProgram(programInfo.program);
twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
twgl.setUniforms(programInfo, uniforms);
twgl.drawBufferInfo(gl, gl.TRIANGLES, bufferInfo);
<script id="vs" type="notjs">
attribute vec4 position; 

uniform mat4 matrix; 
varying vec2 v_texcoord; 

void main() {
  gl_Position = matrix * position; 
  
  // using position since we know it's a unit quad 
  v_texcoord = position.xy;
}
</script>
<script id="fs" type="notjs">
precision mediump float; 

uniform sampler2D texture; 

varying vec2 v_texcoord; 

void main() { 
  gl_FragColor = texture2D(texture, v_texcoord); 
}
</script>
<script src="https://twgljs.org/dist/twgl-full.min.js"></script>
<canvas id="c" width="50" height="100" style="width: 300px; height: 150px; border: 1px solid black;"></canvas>
 类似资料:
  • 我有一个宽度为1900和高度为1000的图像,我使用的是和但我希望div高度与图像更改的高度相同。 示例: 在1366个屏幕中,图像将缩小尺寸以适应屏幕大小(宽度100%),因此,图像高度也将减小,因此我想获得该高度。 我试图做的是: HTML: CSS: 问题:vw是用滚动条宽度计算的,我想要没有,我可以使用宽度%而不是vw吗? 我接受别人的想法来做这件事,但我更喜欢使用CSS。

  • 使用CSS flex box模型,如何强制图像保持其纵横比? JS小提琴:http://jsfiddle.net/xLc2Le0k/2/ 请注意,为了填充容器的宽度,图像会拉伸或收缩。这很好,但是我们也能让它拉伸或收缩高度来保持图像比例吗? HTML CSS

  • 我使用引导创建旋转木马,我有大的图像,所以当屏幕小于图像时,比例不会保持不变。 我怎么能改变呢? 这是我的代码: http://jsfiddle.net/DRQkQ/ 我需要图像适合100%的宽度,但保持其高度为500px(我认为是500px),这应该意味着在较小的屏幕上,我们看不到图像的最左边和最右边。 我尝试将图像包含在div中并添加 但这不管用 非常感谢。

  • 编辑:我应该提到的是,我知道纵横比公式:原始高度/原始宽度x新宽度=新高度,但是,我不知道如何正确地使用它,以我的优势。

  • 问题内容: 我有一个48x48的div,里面有一个img元素,我想将它放到div中而不丢失任何部分,同时保持比例,是否可以使用html和css实现? 问题答案: 如果您在编写CSS时不知道图像的尺寸,则需要一些JavaScript来防止裁剪。 HTML和JavaScript 的CSS 如果您使用JavaScript库,则可能要利用它。

  • 我希望一个图像填充其容器宽度的100%,并且我希望它设置最大高度属性,所有这些都保持纵横比,但允许丢失图像的任何部分。 我知道可以用背景大小属性做类似的事情,但我想把它变成内联的 你知道我如何使用CSS实现这一点吗?还是javascript?