OpenGLHelpers::enableScissorTest confusion

I’m a bit confused about the OpenGLHelpers::enableScissorTest function which is implemented this way:

void OpenGLHelpers::enableScissorTest (Rectangle<int> clip)
    glEnable (GL_SCISSOR_TEST);
    glScissor (clip.getX(), clip.getY(), clip.getWidth(), clip.getHeight());

The documentation of glScissor says:

void glScissor(	GLint x,
 	GLint y,
 	GLsizei width,
 	GLsizei height);

x, y
Specify the lower left corner of the scissor box. Initially (0, 0).

width, height
Specify the width and height of the scissor box. When a GL context is first attached to a window, width and height are set to the dimensions of that window.

The docs for juce::Rectangle::getY() says:
Returns the y coordinate of the rectangle's top edge.

What is confusing:
A juce rectangle defines the size and the top left corner of an area, glScissor takes the size and the bottom left corner of an are. Shouldn’t there be some coordinate system transform math from the juce 2D space with the origin at top left to the GL space with the origin at bottom left in this function? In the way it is currently implemented the user needs to be aware of the fact that the rectangle passed in has to have “wrong” values regarding to the coordinate system standard used everywhere in juce to work, however there is not even a comment with this function that clarifies this.

Any statement on this?

if you change glScissor to use:

glScissor( clip.getX(), clip.getBottom(), clip.getWidth(), clip.getHeight() );

what happens?

@PluginPenguin, your assumption is correct. If you want to use this helper function, you need to do the coordinate system transform yourself. Also make sure to take into account OpenGLContext::getRenderingScale(), the logical coordinate system JUCE uses doesn’t necessarily reflect actual pixels.

This doesn’t work, however this was my first intuitive approach too :wink: . Consider the following example:

The main component that uses GL rendering has a dimension of 100 x 100. I place a rectangle of the size 50 x 50 at position 20 x 20 (juce-conform coordinate system with origin at top left). The equivalent position in coordinates for glScissor would have a position of 20 x 30. A call to getBottom however would return 70.

Yes, I’m aware of that the rendering scale needs to be taken into account. Finally, I ended up doing all the transforms myself correctly, however this was not as trivial as expected first.

In the end, I think this helper function just could use some clarification through some comments to make the user aware of all this, to me it seemed to do all this work internally as I expect that a function taking an object that describes an area in the juce coordinate system will expect values according to this coordinate system and there was no comment telling me something different :wink:

Would AffineTransform::verticalFlip() have been helpful here?

Probably yes! Thank you, didn’t have in mind to have a look at the AffineTransform class. In the end I might have done something similar, however this could clean up my code a bit…

1 Like