First, I'll update on what is the current state.
I believed, that graphics subsystem should be constructed like that: Geometry and transformations->Polygon rendering->Post processing->Screen draw.
So, if I'll take my "Plan minimum", that is, to render in 960x1080 resolution, but stretch this image to 1920x1080. That way Reshade+Depth3D could step in, and it will be an already playable result. And that stretching could be easy implemented on the last step, "Screen draw".
But it appeared to be more convoluted than that. My impression is that graphics pipe in FS is quite not like that. There seems to be not enough encapsulation and quite many dependencies on several instances like "max_screen_width", "window_width", "clipping width" etc. (I'm writing by memory and can be wrong with exact naming), some of functions on the other hand, don't use these values but instead query subsystems for current window size. So, it appears not that easy. I was surprised to see the functions based on glViewport to set rendering area there and again in postprocessing etc. (even for single textures, I believe those are used as quasi-buffers). Chains of redefinitions that looks like simple renaming to me, also left me wondering, for example: gr_set_viewport<-gf_set_viewport<-gr_opengl_set_viewport<-glViewport and still using glViewport, but ok. In the end I couldn't find exact "Screen draw" phase, which should be the only place to implement stretching. Which is to my surprise, because in all OpenGL guides I encountered, this viewport transformation is performed just with a single glViewport call, following the logic of this scheme:
So I decided to try to go for all those loosely coupled places where sizes of render region are set.
I went for glViewport calls, halving width, like this: glViewport(0,0,gr_screen.max_w/2,gr_screen.max_h);
I got this:
Here we can see that only HUD rendered to the expected half of the window, but it has wrong AR. And seems like we have "progressive stretching", my guess that "width = width/2" is being passed down the chain. In the leftmost part we have something totally fishy, and I think that is postprocessing with wrong sizes and progressive squeezing. And of course mouse cursor was out of it's place as well.
I thought that it is too much of change points for a task that looked simple enough at start and decided to go the other way, as with window hook that I used. So I started the game in 960x1080 and instead changed the call of window creation:
SDL_Window* window = SDL_CreateWindow(props.title.c_str(),
So I got 1920x1080 window. Video intro, pilots profile menu and main menu appears stretched to full screen size (just what I wanted, and that reveals that some graphic functions are dependent on actual window size, not on stored values). But when I started mission, its loading screen and in-flight screen are 960x1080 again. HUD and all graphics are in perfect sync of course, but it seems that to stretch this screen to the full window is the same difficult task as in previous variant.
I just can't take the thought out of my head, that there should be some screen buffer swap operation or something in which it can be performed easily.
But OK, we have perfect picture at a half of the screen, we may consider to place another viewport for the right eye alongside it, and have true SBS. And here we need second camera, etc. I think that there is something wrong with the idea to set cameras with 30 degrees difference, it should be far less to my expectations. Moreover not only we need cameras to be angled, but we need an asymmetrical frustum. More on this could be found here
But for now I'm not at this level of understanding of how FSO rendering works (as you can see from my results). Any help would be appreciated.