Results 1 to 2 of 2

Thread: The upside-down problem

  1. #1
    ClanLib Developer
    Join Date
    Sep 2006
    Location
    Denmark
    Posts
    554

    Default The upside-down problem

    This post is mostly for myself so I can remember and refer to this thread in IRC discussions. Plus I like to talk to myself.

    There is a general problem in ClanLib with viewports, clipping rects and the image direction in textures. The rules of OpenGL, Direct3D and ClanLib 2.3 are as follows:

    • OpenGL: Scissor rects, viewports, textures and render targets are specified with lower left origin. gl_Position uses lower left origin. gl_Position.z uses a -1 to 1 clip range.
    • Direct3D 11: Scissor rects, viewports, textures and render targets are specified with upper left origin. SV_Position users lower left origin. SV_Position.z uses a 0 to 1 clip range.
    • ClanLib 2.3: Scissor rects, viewports, textures and render targets are specified with upper left origin.

    The ClanLib 2.3 rules causes some problems when mixed with OpenGL:

    • Because everything is natively lower left origin in OpenGL the calculated gl_Position.y needs to be upside-down when a frame buffer is bound. This is because we assume 0,0 to be upper left when a texture is used, and OpenGL renders to texture with 0,0 being lower left. By flipping and offsetting gl_Position.y we get the effect we want.
    • The OpenGL targets has to flip and offset all scissor rects and viewports.
    • If an application is using its own program objects it is often more preferable to simply use lower left origin, but then scissors and viewports needs to be flipped manually by the application once again to counter ClanLib's flipping - not nice!
    • If an application prefers lower-left textures we have no (easy) way of uploading such images. CL_PixelBuffer always assumes you want upper-left.

    In similar way if an application is to work with both clanGL and clanD3D you run into some issues:

    • gl_Position and SV_Position both use lower-left origin, but Direct3D itself always flips and offsets SV_Position.y to keep textures top-left. This means clanD3D wants a normal projection matrix always, while clanGL wants a flipped one (but only when a frame buffer is bound). The big issue here is that we generate the standard uniform buffer in clanDisplay, and also any application would have to deal with the same problem with its own matrices.
    • If an application prefers lower-left textures SV_Position.y needs to be upside-down when a frame buffer is bound. Same problem as when we wanted top-left with OpenGL.
    • If an application wants to use lower-left scissor and viewport rects, then they need to be flipped manually by the application to counter ClanLib's flipping - not nice!

    So what this boils down to is that an application may want to apply a flip+offset matrix based on the preferences of the application and the native origin of the display target. And the application may want to set the viewports and clipping rects with upper-left or lower-left origin. The application may also want to upload images bottom-left.

    The flip+offset matrix is basically a function of the native origin vs the desired origin, and if it is render to texture or not. I suggest we call this the viewport direction matrix and add a function on CL_GraphicContext to return it: gc.get_viewport_direction_matrix(enum direction, bool render_to_texture). So the final ObjectToProjection matrix becomes: ViewportDirectionMatrix * EyeToProjection * WorldToEye * ObjectToWorld.

    When specifying the viewports and clipping rects we have two options: 1) let them assume the map direction specified by set_map_mode, or 2) add a second parameter specifying the direction and have it default to upper-left.

    For uploading bottom-up I guess the best way is to add this as an option to CL_ImageDescription. Or is there a better way?

  2. #2
    ClanLib Developer
    Join Date
    Sep 2006
    Location
    Denmark
    Posts
    554

    Default

    After a bit more thinking and implementing this get_viewport_direction_matrix() function I've changed my mind and instead doing the check directly in CL_StandardShaderState::update_buffer() like this:

    Code:
    if (!gc.get_write_frame_buffer().is_null() && gc.get_texture_image_y_axis() != cl_y_axis_top_down)
    {
    	CL_Mat4f viewport_orientation_matrix = CL_Mat4f::scale(1.0f, -1.0f, 1.0f);
    	block.projection = viewport_orientation_matrix * block.projection;
    	block.modelview_projection = viewport_orientation_matrix * block.modelview_projection;
    }
    This is because in reality you either want to output top-down, bottom-up or in the target native direction. It is only in the situation where your desired output direction differs from target native direction that you want to flip the Y direction. For the standard shaders this is only the case when rendering to texture - in the other cases we want to render to the target native direction.
    Last edited by Judas; 08-05-2012 at 04:55 AM.

Similar Threads

  1. Uhhh upside down funny??/
    By darknet12282 in forum Novashell Game Creation System
    Replies: 2
    Last Post: 05-24-2012, 01:50 AM
  2. The upside down problem
    By Judas in forum Official ClanLib SDK Forums
    Replies: 3
    Last Post: 10-17-2010, 03:30 PM
  3. Upside Down
    By Kaladan in forum Novashell Game Creation System
    Replies: 4
    Last Post: 07-18-2010, 10:18 PM
  4. Upside down sprites
    By aclysma in forum Official ClanLib SDK Forums
    Replies: 7
    Last Post: 04-05-2010, 05:05 PM

Bookmarks

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •