Search code examples
javascriptglslwebglshadervertex-shader

Sprite is being stretched inversely proportional to canvas dimensions


I have a small program I'm working on to render sprites with 2D transformations, link here. My problem is that I'm trying to render a 100px by 100px square, but it's being stretched into a rectangle. I have absolutely zero idea what the offending code is, but here's some relevant pieces.

const position = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, position)
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
  -w/2,  h/2,
   w/2,  h/2,
  -w/2, -h/2,
   w/2, -h/2
]), gl.STATIC_DRAW)

 

gl.bindBuffer(gl.ARRAY_BUFFER, position)
gl.vertexAttribPointer(attrib.vertexPosition,
                      2, gl.FLOAT, false, 0, 0)
gl.enableVertexAttribArray(attrib.vertex)

 

gl.uniformMatrix2fv(uniform.transformMatrix, false, transform)
gl.uniform2f(uniform.translation, x+w/2, y+h/2)
gl.uniform2f(uniform.screenRes, gl.canvas.width, gl.canvas.height)

Vertex shader:

attribute vec2 aVertexPosition;
attribute vec2 aTextureCoord;

uniform mat2 uTransformMatrix;
uniform vec2 uTranslation;
uniform vec2 uScreenRes;

varying vec2 vTextureCoord;

void main() {
  gl_Position = vec4(2.0 * (uTransformMatrix * aVertexPosition + uTranslation) / uScreenRes - 1.0, 1.0, 1.0);
  vTextureCoord = aTextureCoord;
}

Feel free to toy around with the variables in the pen, especially the canvas dimensions; when you scale a dimension down, that dimension of the sprite scales up, and vice versa.

P.S. I'm not concerned about how the texture is inverted. I'm shelving that for later.


Solution

  • Your code is correct, however you forgot to specify the viewport. Add this right before you make any draw calls (in your case, ideally after gl.clear())

    gl.viewport(0, 0, gl.canvas.width, gl.canvas.height)
    

    The WebGLRenderingContext.viewport() method of the WebGL API sets the viewport, which specifies the affine transformation of x and y from normalized device coordinates to window coordinates.