The glCopyTexSubImage copies pixels from the buffer specified by glReadBuffer() before \
(if glReadBuffer() was never called, it's the frontbuffer for single-buffering, backbuffer with double-buffering)

The last 4 args specify x/y/width/height of area to copy from the buffer, the viewport_texture_offset
args specify where in the texture to copy the data (the X and Y offsets of that area)

(More detail in docs:,

I think if you wanted to imitate that, you'd need to copy from the FBO texture
(which replaces the front/back buffer here IIRC) to a square texture, using the
same coordinates. (And use that square texture to draw the screen -
there should be no need to use a square FBO)
Note that copying from texture to texture in OpenGL (other than 4.3) us a major PITA
(You need to draw it to screen and copy from that).
But I think you could use glCopyTexSubImage2D with the FBO's attachment
given to glReadBuffer (but we're using FBO through extension as it's not
a part of GL2 - which is why I'm not 100% sure it will work)
You'd need to get attachment from GL handle of the FBO -
Qt doesn't expose it. So you need to get GL handle from QGLFramebufferObject
Note that this might still be a major PITA because AFAIK there are 2 GL extensions
Qt might be using depending on machine (EXT and ARB_framebuffer_object) and the functions differ.

A different way (and possibly easier to implement?)
way would be to "stretch" the texture coordinates so that
the texcoord values that would map to the bounds of the copied image data
with the square texture in old code would map to bounds of the non-rect texture that
is being used instead in the new code (i.e. to [0,0]-[1,1])
(Just came to my mind, not 100% sure if this is exactly how to do it)

Only if you do this (alternative) and end up with artifacts:
Note that you'd probably end up with some coords outside the [0,0]-[1,1] range,
which might end up repeating the texture weirdly over parts of the screen.
so you might need to use the clampToEdge texture parameter. If still a mess, you might
need to use a fully transparent black (even 1-pixel) on the texture.
See the "border" parameter here:
The default border color should be black transparent (RGBA(0,0,0,0)), if not,

(Note that in the current code, either texture subimage copy or border would need to be added
to the Renderer API -  (the former a major PITA to make sure we don't leak any GL state, the
latter should be rather easy) - I can do that but not right now (thesis) - so it's best to experiment
right on the 4192 revision).

Sorry for the wall of text.

On Wed, Apr 17, 2013 at 9:26 AM, Bogdan Marinov <> wrote:
Hello to all.

I think I've found at least a part of the reason for the spherical
mirror distortion issues, but I need the help of someone who knows
OpenGL to continue.

I've been reading through the changes introduced by Fabien when he
reworked the SMD feature. I'm working with checkouts of revisions 4190
(hereafter: "old code") and 4192 ("new code").

The re-work moves the distortion painting code from
StelViewportDistorter.hpp/.cpp to StelViewportEffect.hpp/.cpp, and
changes the point in which it is applied from global (the
StelMainGraphicsView class) to just the sky view
(StelAppGraphicsWidget). The code that calculates the distortion
itself remains unchanged.

What I noticed yesterday: the old code used a dedicated OpenGL texture
to paint the distortion
(StelViewportDistorterFisheyeToSphericMirror::mirror_texture). The new
code tries to use for the same purpose the texture of a
QGLFramebufferObject, which is a part of a swappable
foreground/background buffer mechanism. At least a part of the problem
is that the old mirror texture was a square, while the new buffers are
the same size/aspect ratio as the screen.

If you look at the old code, mirror_texture was a square with a side
determined by the texture_wh member, which is also used in the
computations in the constructor of the distorter class. It's equal to
the screen width, so I decided to try a small code change to make the
framebuffer objects square. (It's in the first attached patch.)

This had a result - the distortion seemed correct, but the distorted
image was much smaller than usual, huddling like a mushroom at the
bottom of the screen. :) After that, I tried to determine how
mirror_texture was used in the old code, and here's where I need
OpenGL expertise.

In the old ::paintViewportBuffer(), there's a call to
glCopyTexSubImage() which uses viewport size/position parameters and
viewport_texture_offset. It is omitted in the new code, presumable
because it's not needed, but I think that it's significant, because it
uses viewport_texture_offset - in the new code, that value is computed
and used in the texture coordinate transformations, but it's not used
in the distortion drawing code. Perhaps this function call is the
missing step to make the distorted image fill the screen properly?

Attached are two diffs, one for the temporary framebuffer solution,
the other the difference between the old and the new contents of the
StelViewportDistorter class (for a full diff between 4190 and 4192,
see the link above). I think that in the second diff, you can safely
assume that flag_use_ext_framebuffer_object is always false.

Bogdan Marinov

Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
Stellarium-pubdevel mailing list