Some questions about glViewport

Started by
10 comments, last by scarypajamas 6 years, 11 months ago

Hello everyone, I have a few questions about glViewport that I hope you can answer.

Q1. Can its x/y parameters be negative? I'm asking because I need a card flip effect that can be positioned anywhere on screen, but rendered from the perspective of a camera looking dead center at it. To achieve this I'm rendering the card in the center of the screen with perspective projection and then offsetting the final rendered pixels with glViewport.

Q2. How does glViewport affect the stencil buffer (if at all)? Lets say I render a 2D point at position (100, 100) and with a glViewport of (-75, -25, 256, 256). Does the stencil buffer update its stencil value at pixel position (100, 100) or (25, 75)? I assume its the later since the final drawn pixel is at (25, 75).

Q3. How does this approach in general sound? Are their alternate solutions for achieving the card flip effect? I'm planning to batch render them using the GL_ARB_viewport_array extension.

Advertisement

Q1. Can its x/y parameters be negative? I'm asking because I need a card flip effect that can be positioned anywhere on screen, but rendered from the perspective of a camera looking dead center at it. To achieve this I'm rendering the card in the center of the screen with perspective projection and then offsetting the final rendered pixels with glViewport.

The parameters x and y can be negative, but the width and height parameters must be non-negative.

Q2. How does glViewport affect the stencil buffer (if at all)? Lets say I render a 2D point at position (100, 100) and with a glViewport of (-75, -25, 256, 256). Does the stencil buffer update its stencil value at pixel position (100, 100) or (25, 75)? I assume its the later since the final drawn pixel is at (25, 75).

The viewport transform is just a coordinate transformation from normalised device coordinates to window (or pixel) coordinates.

Once all transformations (model, view, perspective, or any other transformation you may have) have been applied, you end up in a coordinate system called normalized device coordinate. It is a coordinate system when the visible coordinates ar in the range [-1, 1] along all three axes. For example, -1 to 1 along the X-axis corresponds to what is visible along the X-axis from left to right, independent of Y and Z-coordinate.

This range [-1, 1] along both the X and Y is then transformed by the viewport transform, so that -1 ends up at the pixel coordinates x or y (the parameters to glViewport), and 1 ends up at the pixel coordinates x+width or y+height. The -1 and 1 along the Z-axis is subject to the depth buffer process so will not covered at this stage.

So where your point (100,100) ends up in window space depends on all the transformations you apply to it, and what its normalised device coordinates is. But if you move the viewport around by changing the x and y parameters, you will effectively just translate the rendering region around the window, like grabbing the title bar of any window and moving it around.

Stencil testing, however, is tied to the actual pixel coordinates. Thus, moving the viewport around will render your scene over a different set of actual pixels within the window, and therefore subject the rendered scene to a different region of the stencil buffer.

Q3. How does this approach in general sound? Are their alternate solutions for achieving the card flip effect? I'm planning to batch render them using the GL_ARB_viewport_array extension.

As far as I understand what you want to do and the way you want to use the viewport to achieve this, you need negative width or height to achieve the flipping effect. That is not possible in the first place; see Q1.

How does this approach in general sound? Are their alternate solutions for achieving the card flip effect?
Even if flipping the viewport worked, it wouldn't get you the perspective effect present in the link that you posted. You should use a rotation matrix to rotate the card in order to get that effect.

If you do just want a 2D flip like flipping the viewport would get you, you can do this by moving/scaling your perspective matrix - one easy way is to multiply it with an ortho matrix that does the appropriate scaling.

The parameters x and y can be negative, but the width and height parameters must be non-negative.

Good to hear.

Stencil testing, however, is tied to the actual pixel coordinates. Thus, moving the viewport around will render your scene over a different set of actual pixels within the window, and therefore subject the rendered scene to a different region of the stencil buffer.

Just as I thought.

As far as I understand what you want to do and the way you want to use the viewport to achieve this, you need negative width or height to achieve the flipping effect. That is not possible in the first place; see Q1.

I'm not flipping the card using the viewport, I'm flipping it using a rotation matrix. The purpose of changing the viewports x,y parameters is to translate the card. I could use a translation matrix to translate the card, but then its perspective would not be its dead center.

Observe the following gif. The bottom card shows the incorrect behavior and the top card shows the correct behavior. Both cards use a rotation matrix to flip them. The difference is in how they are translated. The bottom card uses a translation matrix to put the card in the lower-right corner of the screen. The top card renders the card at the dead center of the screen and then uses the viewport to put it in the right place. The latter ensures that the eye is dead center on the card when the rotation is performed thus it looks correct regardless of its final screen position.

[attachment=35974:card.gif]


If you do just want a 2D flip like flipping the viewport would get you, you can do this by moving/scaling your perspective matrix - one easy way is to multiply it with an ortho matrix that does the appropriate scaling.

Thanks for the reply. I typed out my recent post before seeing yours. Could you elaborate more on this?

The bottom card shows the incorrect behavior and the top card shows the correct behavior. Both cards use a rotation matrix to flip them. The difference is in how they are translated. The bottom card uses a translation matrix to put the card in the lower-right corner of the screen. The top card renders the card at the dead center of the screen and then uses the viewport to put it in the right place. The later ensures that the eye is dead center on the card when the rotation is performed thus it looks correct regardless of its final screen position.

What kind of projection are you using ?

The bottom card shows the incorrect behavior and the top card shows the correct behavior. Both cards use a rotation matrix to flip them. The difference is in how they are translated. The bottom card uses a translation matrix to put the card in the lower-right corner of the screen. The top card renders the card at the dead center of the screen and then uses the viewport to put it in the right place. The later ensures that the eye is dead center on the card when the rotation is performed thus it looks correct regardless of its final screen position.

What kind of projection are you using ?

Perspective projection. I'm not using orthogonal projection at all.

Here is how the "correct" card flip is done:

  1. Start with vertices comprising an upright card centered around the origin.
  2. Apply a rotation matrix to rotate the card.
  3. Apply a translation matrix moving the card forward so its dead center in front of the eye.
  4. Before rendering, use glViewport to translate the card anywhere on screen.

Here is how the "incorrect" card flip is done (step #4 is the only step that's different):

  1. Start with vertices comprising an upright card centered around the origin.
  2. Apply a rotation matrix to rotate the card.
  3. Apply a translation matrix moving the card forward so its dead center in front of the eye.
  4. Apply another translation matrix moving the card so its in the lower-right corner of the screen.

The bottom card shows the incorrect behavior and the top card shows the correct behavior. Both cards use a rotation matrix to flip them. The difference is in how they are translated. The bottom card uses a translation matrix to put the card in the lower-right corner of the screen. The top card renders the card at the dead center of the screen and then uses the viewport to put it in the right place. The later ensures that the eye is dead center on the card when the rotation is performed thus it looks correct regardless of its final screen position.

What kind of projection are you using ?

Perspective projection. I'm not using orthogonal projection at all.

Any reasons for this ?

Just because you use a perspective to render flat things and you "disable" the perspective transformation. So what left for the perspective ? If you have other models needing perspective, then you can simply render your cards on top of them by using a simple orthogonal projection.

Well I just want to know why you use a perspective here, maybe that could help me understand things I currently have no idea yet :)

The bottom card shows the incorrect behavior and the top card shows the correct behavior. Both cards use a rotation matrix to flip them. The difference is in how they are translated. The bottom card uses a translation matrix to put the card in the lower-right corner of the screen. The top card renders the card at the dead center of the screen and then uses the viewport to put it in the right place. The later ensures that the eye is dead center on the card when the rotation is performed thus it looks correct regardless of its final screen position.

What kind of projection are you using ?

Perspective projection. I'm not using orthogonal projection at all.

Any reasons for this ?

Just because you use a perspective to render flat things and you "disable" the perspective transformation. So what left for the perspective ? If you have other models needing perspective, then you can simply render your cards on top of them by using a simple orthogonal projection.

Well I just want to know why you use a perspective here, maybe that could help me understand things I currently have no idea yet :)

There may be a gap in my knowledge, but I don't know how to 3D transform (in this case, flip) a sprite without the perspective matrix. Can this be done with an orthogonal matrix?

Here is how the "correct" card flip is done:

  1. Start with vertices comprising an upright card centered around the origin.
  2. Apply a rotation matrix to rotate the card.
  3. Apply a translation matrix moving the card forward so its dead center in front of the eye.
  4. Before rendering, use glViewport to translate the card anywhere on screen.

I see now what you intend to do. If you consider the view of a single card as its own viewport then what you describe here is precisely what glViewport is for; you define the region of the window where you want the scene (your single card) to be drawn.

It even gives you possibly positive side effects, such as clipping. Consider for example if you zoom in a little on the card while it's rotating, or if the viewport is too small. If the corners or the card extend beyond the viewport while rotating it, they will be clipped to the viewport region and won't interfere with things outside the defined viewport. For this purpose, the viewport is typically set together with the scissor region; look up glScissor.

Here is how the "correct" card flip is done:

  1. Start with vertices comprising an upright card centered around the origin.
  2. Apply a rotation matrix to rotate the card.
  3. Apply a translation matrix moving the card forward so its dead center in front of the eye.
  4. Before rendering, use glViewport to translate the card anywhere on screen.

I see now what you intend to do. If you consider the view of a single card as its own viewport then what you describe here is precisely what glViewport is for; you define the region of the window where you want the scene (your single card) to be drawn.

Thanks Brother Bob that's good to hear. I apologize for any confusion. It looks like GL_ARB_viewport_array supports a unique scissor rectangle per viewport so I'm in luck. I'm planning to use that extension so I can batch render the sprites.

I asked about the stencil buffer because I may need card-like transformations for widgets as part of the GUI. Since parent widgets clip their children I was thinking about using the stencil buffer to make sure children get masked away.

I'm still wondering if there is some "matrix transformation magic" that exists as an alternative solution to the problem. Some kind of ortho/perspective hybrid maybe? I'd love to hear alternative solutions to this problem. Thanks again.

This topic is closed to new replies.

Advertisement