1
\$\begingroup\$

I'm using GLFW to create a little game. (and by little, I mean: small, nonprofit)

After a while of puzzling, I found out that this draws a texture (from an image, for instance) to the screen:

(the syntax is in Go, but the library is the same as the C/C++ version)

gl.BindTexture(gl.TEXTURE_2D, tex)
gl.Color4f(1, 1, 1, 1)

gl.Begin(gl.QUADS)

gl.Normal3f(0, 0, 0)

gl.TexCoord2f(1, 1)                     // top right
gl.Vertex3f(1, -1, 0)

gl.TexCoord2f(0, 1)                     // bottom right
gl.Vertex3f(-1, -1, 0) // = location

gl.TexCoord2f(0, 0)                     // bottom left
gl.Vertex3f(-1, 1, 0)

gl.TexCoord2f(1, 0)                     // top left
gl.Vertex3f(1, 1, 0)

gl.End()

This draws the texture perfectly. There is just one downside: as my screen is 16:9, the texture also gets rendered/displayed as 16:9. But as this is a square image (32 by 32 pixels), how do I get it to draw just those pixels, instead of defining it relative to the screen ratio? (values between -1 and 1)

My first assumption was that I can compute what the values should be, by comparing it with the actual screen size, but this feels like it's not the way to go.

\$\endgroup\$
  • 1
    \$\begingroup\$ You can just use glViewport to set the viewport to be square. \$\endgroup\$ – Soapy May 14 '15 at 13:45
  • 1
    \$\begingroup\$ Have you performed any call to viewport? \$\endgroup\$ – Vaillancourt May 14 '15 at 13:46
  • \$\begingroup\$ I guess there are a lot of stuff that glfw.org/docs/latest/quick.html and related tutorials didn't cover. Thank you both. I wish I could mark the first comment as "Answer". \$\endgroup\$ – Etienne Bruines May 14 '15 at 13:55
2
\$\begingroup\$

CLARIFICATION

glViewport will set the size of your viewport you are rendering to. This answer assumes that you were doing something along the lines of this:

glViewport(0, 0, 1920, 1080);

Which would give you a 16:9 aspect ratio. Setting it to something like:

glViewport(0, 0, 800, 600);

Would give you the correct aspect ratio (and hopefully answers your question). It would be incorrect to do something along the lines of:

glViewport(0, 0, 32, 32);

As this will only render to a small portion of the screen. If this is what you actually want then that's fine.

If you want to render the 32x32 texture to part of the screen, for example as a character sprite that can run around, then you need to look into using transform matrices.

Using matrices mean instead of trying to calucate where the sprite should be in relative to the screen size, you just apply a transform that moves the sprite 'into the background'.

This is all covered in the tutorial site I linked.

P.S Please try to stay away from using deprecated features such as glLoadIdentity, glTranslatef, gl.Vertex3f, etc.


ORIGINAL

Your solutions is glViewport.

You can specify the last two arguments with size of the viewport.

As for your comment GLFW only supplies you with a window with a OpenGL context. Doing anything more that requires something like rendering in different aspect ratios requires you to use OpenGL.

I highly recommend this OpenGL tutorial site to get you started on modern (3.3+) OpenGL, and as a bonus it uses GLFW too!

\$\endgroup\$
  • \$\begingroup\$ I don't think this is what OP needs. If he's trying to draw 32x32 square, then he is probably trying to draw a sprite. I hope he wont start to use a glViewport call to draw every sprite. :D \$\endgroup\$ – HolyBlackCat May 14 '15 at 19:17
1
\$\begingroup\$

You want to draw a 32x32 sprite, right?

If so, Don't do what @Soapy said and don't call glViewport() to draw each sprite in your game!

It probably will be very slow and it is not how you should make your graphics. It's like buying a new hammer each time you want to hammer a nail.

Yes, it may work, but it's not the good way. You can't rotate sprites with this technique, you can't make 3D with it, you can't draw triangles with it.

You should call glViewport() once every time your window is resized to provide the new window size to OpenGL.


What you should do instead is to read about glLoadIdentity(), glScale(), glTranslate() and similar functions. They will allow you to do what you want. For example, if you call this set of functions once

gl.LoadIdentity();
gl.Translatef(-1,-1,0);
gl.Scalef(2.0f/WindowWidth,-2.0f/WindowHeight,0);

then you can use

gl.Begin(gl.QUADS)

gl.TexCoord2f(0, 1)                     // top right
gl.Vertex3f(0, 32, 0)

gl.TexCoord2f(1, 1)                     // bottom right
gl.Vertex3f(32, 32, 0)

gl.TexCoord2f(0, 1)                     // bottom left
gl.Vertex3f(0, 32, 0)

gl.TexCoord2f(0, 0)                     // top left
gl.Vertex3f(0, 0, 0)

gl.End()

to draw a 32x32 square in a top-left corner of your screen. Makes more sense that computing coordinates relative to the screen each time, isn't it?


Tell me if something from my answer does not work, I will try to help.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.