2

I wrote a simple WebGL page (well, as simple as I could make it) and can't figure out why normalized coordinates aren't working. That is, I'm trying to draw a square from (-0.5, -0.5) to (0.5, 0.5) via two triangles, and instead I get a large rectangle that goes off screen.

I'm completely unsure what I am doing wrong, so I pasted it into a jsFiddle:

Link

Notice how I define my verts and indices correctly (right?) and my shader and fragment programs are as simple as they come.

Why is it drawing as a weird large off-screen rectangle?

Ricket
  • 33,368
  • 30
  • 112
  • 143

2 Answers2

2

Okay I finally got help from someone in #webgl on Freenode: the <canvas> element needs a width and height attribute, whereas I'm setting them via CSS. Apparently the actual width and height attributes determine the width and height of the OpenGL buffer.

I was not able to find this documented anywhere else, except that WebGL examples have the width and height attribute on the canvas tag.

Ricket
  • 33,368
  • 30
  • 112
  • 143
  • 1
    Yeah, this is a particularly unfortunate bit of weirdness that affects both WebGL and Canvas 2D. There is a small saving grace to it, however. Because of this quirk you can create a canvas that is, say, 800x600 and use CSS to make it fill the screen anyway. This forces the browser to do the upscale, which in turn gives faster performance for a quality tradeoff. That's a nice option to have, especially when you start talking about mobile devices. – Toji Feb 24 '12 at 16:48
  • I'm glad you found the answer. This is extensively documented though and is the same as every other HTML tag. Image tags, Canvas tags, Video tags all behave the same. CSS decides the size to display, other things decide the size of the source. For Image it's the image you download, for video it's the video you reference. For Canvas it's the width/height you specify. – gman Feb 24 '12 at 19:49
  • @gman "Extensively documented" where? Also, I don't know about video tags but for image tags the CSS and attributes have the same effect. Either way the image is loaded from the server and scaled on the client side (it can't be any other way), and both do the same thing. See also [this SO question](http://stackoverflow.com/questions/640190/image-width-height-as-an-attribute-or-in-css). – Ricket Feb 24 '12 at 23:37
0

Same as other elements the size something is displayed is separate from the size it is. Examples:

Display a 4x4 JPGs as 4x4 pixels

<img src="some4x4pixel.jpg" />

Display a 4x4 JPGs at 16x16 pixels

<img src="some4x4pixel.jpg" width="16" height="16" />

Display a 4x4 JPG at 16x16 pixels

<img src="some4x4pixel.jpg" style="width:16px; height:16px;"/>

Display a 4x4 JPG at whatever size it's container is

<img src="some4x4pixel.jpg" style="width:100%; height:100%;"/>

Display a 300x150 pixel canvas (the default size) at 300x150 pixels

 <canvas></canvas>

Display a 4x4 canvas at 4x4 pixels

 <canvas width="4" height="4"></canvas>

Display a 4x4 canvas at 16x16 pixels

 <canvas width="4" height="4" style="width:16px; height:16px;"/></canvas>

Display a 4x4 canvas at whatever size it's container is

 <canvas width="4" height="4" style="width:100%; height:100%;"/></canvas>

If you're doing 3D and using the fairly common perspective function found in most 3D math libraries you generally want to set the aspect ratio to the display size, not the actual size.

 // 45degrees, assumes math library uses radians
 var fieldOfView = Math.PI / 4;  

 // Use the size the canvas is displayed, NOT the size it actually is.
 var aspectRatio = canvas.clientWidth / canvas.clientHeight;

 var zNear = 0.1;
 var zFar = 1000;

 var matrix = someMathLibrary.perspective(fieldOfView, aspectRatio, zNear, zFar, ...)

If you want the size the canvas exists to be the same size as it's displayed use

 canvas.width = canvas.clientWidth;
 canvas.height = canvas.clientHeight;

Though note, a WebGL canvas is not required to be the size you request since various GPUs have limits on size. If you want to know the size you actually got vs the size you requested check

 gl.drawingBufferWidth
 gl.drawingBufferHeight

For the perspective matrix used by most 3D apps the actual size of the canvas is not that important. For certain kinds of effects or for 2D it is often important.

The reason this is hard to find documentation for is because it's taken for granted that people know that CSS decides the display size for all elements regardless of the actual size of their content.

https://www.google.com/webhp?sourceid=chrome-instant&ix=sea&ie=UTF-8&ion=1#sclient=psy-ab&hl=en&site=webhp&source=hp&q=canvas%20size%20css&pbx=1&oq=&aq=&aqi=&aql=&gs_sm=&gs_upl=&fp=f131b50fb368d7bf&ix=sea&ion=1&bav=on.2,or.r_gc.r_pw.r_cp.,cf.osb&biw=1629&bih=931

gman
  • 100,619
  • 31
  • 269
  • 393