Results 1 to 14 of 14

Thread: Rendering to texture

  1. #1
    Lesser Knight
    Join Date
    Jul 2011
    Posts
    57

    Default Rendering to texture

    Hello again.

    Now I have a question about rendering to texture. I'm using it to implement game pause - during the normal game I render directly to gc and when switching to pause screen I just make the same rendering loop but to the texture, and then using this texture as pause screen background.
    But as you can see on the attached screenshots, I got a different picture for direct and texture renders. Seems like it have different default blending modes for both cases since I didn't change any settings between two rendering loops, I just switched framebuffer but got different results.
    Is there some more options I should set up before rendering to texture to get the same output as in the case of direct rendering? I think the difference is in blending mode but I couldn't find out what was wrong exactly by myself.
    Attached Images Attached Images   

  2. #2
    ClanLib Developer
    Join Date
    May 2007
    Posts
    1,824

    Default

    Try using:

    Code:
    	CL_BlendMode blendmode;
    	blendmode.enable_blending(true);
    	blendmode.set_blend_function(cl_blend_one, cl_blend_one_minus_src_alpha, cl_blend_one, cl_blend_one_minus_src_alpha);
    	gc.set_blend_mode(blendmode);
    
    	draw_all_gui_windows()
    
    	gc.reset_blend_mode();
    The above is used by clanGUI texture manager. clanGUI direct window manager does not contain that code.

    If that doesn't work, try commenting out that "blendmode.set_blend_function()" function

  3. #3
    Lesser Knight
    Join Date
    Jul 2011
    Posts
    57

    Default

    And that's what I got by adding blend functions.
    blendmode.enable_blending(true) isn't giving anything by itself - I get the same blackened picture.
    Attached Images Attached Images  

  4. #4
    ClanLib Developer
    Join Date
    May 2007
    Posts
    1,824

    Default

    Humm, why white....

    I'm a bit tired today, I am not sure how to solve the problem. But it "should" be easy.

    All I can think, is that the background that you draw the gui window to, is not black. Even so, it should work.

    I have seen that problem a long time ago, but I cannot remember what it was.

    The GUI Texture WM performs "gc.clear(CL_Colorf::black);" to the CL_Texture framebuffer.

    So the background RGBA is: "0.0f, 0.0f, 0.0f, 1.0f"

    The GUI Direct WM simply draws the gui onto the window. So maybe "blendmode.set_blend_function(cl_blend_one, cl_blend_one_minus_src_alpha, cl_blend_one, cl_blend_one_minus_src_alpha);" required the alpha to be set to 1.0f initially.

    I will pass the question onto the ClanLib blend expert

  5. #5
    Lesser Knight
    Join Date
    Jul 2011
    Posts
    57

    Default

    Oh, I forgot to mention - I'm not using clanGUI.
    I just use my own texture for rendering into it. I use the same method in some of the main menu screens and it is working just right so I don't understand why results are different in this case.

  6. #6
    ClanLib Developer
    Join Date
    May 2007
    Posts
    1,824

    Default

    Silly me. I do apologise, I saw "direct and texture" and assumed you were refering to clanGUI

    Rendering to a texture should be the same as rendering direct to the screen.

    Did you clear the texture first ? Using gc.clear(), but this should not be required if you are always drawing with the alpha = 1.0f;

    When drawing the texture back to the screen, ensure the constant color is CL_Colorf(1.0f, 1.0f, 1.0f, 1.0f). (Unless you use the alpha channel to slowly blend in the texture)

  7. #7
    Lesser Knight
    Join Date
    Jul 2011
    Posts
    57

    Default

    The problem isn't in drawing texture to the screen, but in the drawing to the texture. Some elements are identical but some are somehow rendered different. The background image is the same when rendered directly or to the texture, but other elements rendered over it are differ. And I can't find where this difference come from.

  8. #8
    ClanLib Developer
    Join Date
    May 2007
    Posts
    1,824

    Default

    Quote Originally Posted by Noro View Post
    ... The background image is the same when rendered directly or to the texture, but other elements rendered over it are differ....
    Well that is very interesting.

    I cannot think of a logical reason what would cause that.

    I am assuming that you are using clanGL.

    If the background image was different, I could explain it.... (for example)
    • Ensure that the CL_Texture image get_size() is identical to the gc.get_size() (before framebuffer was bound).
    • If using "CL_OpenGLWindowDescription desc;", and desc.set_multisampling() is set to more than 0, try setting to 0.


    If you do solve the problem please let use know, it's an interesting program.

    Hopefully other developers will have some ideas.

    If not, can you create a very basic example (with a small test background image, and a small test object image that displays incorrectly)

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

    Default

    The only thing I can think of is the blending mode. There's nothing in CL_Sprite and friends that make it act differently if it is rendering to a texture instead of the back buffer.

    Having said that, for render-to-texture to function correctly it is extremely important that the blend mode used when rendering to texture outputs pre-multiplied alpha. There are other articles out there that explain the advantages better than anything I can write shortly here, but I'll try give a simple explanation here anyway. If it sounds confusing try google for a better explanation.

    When you are using pre-multiplied alpha the best way to describe a pixel value is to say that the RGB components represents the light (photons) that are emitting from it, while the alpha component specifies how much of light behind it is exposed. This definition is important because as you render one RGBA image onto another (your texture), then the result is another image in RGBA. Simply put you need a sane equation of how to calculate the blend into the texture and not just some random equation that 'seems right'. If both the source and destination texture is using pre-multiplied alpha the equation becomes rather simple:

    Code:
    dest.rgba = src.rgba + dest.rgba * (1-src.a);
    Using our photon description above, the destination color becomes the emitting RGB plus the exposed part of what was before in that pixel. The new pixel is again in pre-multiplied alpha format.

    The blend function for the above equation looks like this:

    Code:
    CL_BlendMode blendmode;
    blendmode.enable_blending(true);
    blendmode.set_blend_function(cl_blend_one, cl_blend_one_minus_src_alpha, cl_blend_one, cl_blend_one_minus_src_alpha);
    gc.set_blend_mode(blendmode);
    However this equation only works if the input texture is also pre-multiplied alpha format. If it is not we have to use this equation instead:

    Code:
    dest.rgb = src.rgb * src.a + dest.rgb * (1-src.a);
    dest.a = src.a + dest.a * (1-src.a);
    In this version we multiply the alpha for RGB as we blend and then continue as usual. This method has the disadvantage that it doesn't work so well for scaled linear filtering since the transparency may 'bleed' into neighboring pixels. I can't remember if ClanLib uses pre-multiplied textures for its sprites or not (ideally it does), but if the above blend mode didn't work for you, then try this one instead. In ClanLib syntax it looks like this:

    Code:
    CL_BlendMode blendmode;
    blendmode.enable_blending(true);
    blendmode.set_blend_function(cl_blend_one, cl_blend_one_minus_src_alpha, cl_src_alpha, cl_blend_one_minus_src_alpha);
    gc.set_blend_mode(blendmode);
    In both cases you end up with an output texture that is using pre-multiplied alpha, which means that when you finally render the texture to the back buffer you must use the first blend mode when rendering it. Otherwise transparent parts will not look correct.

    Finally there's one last detail: fonts. Font subpixel rendering uses the RGB channels in a special way to triple the resolution and to do this it stores transparency in the RGB channels instead and renders it with a special blend mode. This is not compatible with render-to-texture unless the part the text is written to is already opaque. So either only write in opaque places or disable subpixel rendering on your fonts.

    Just for completeness the equation used by the subpixel font rendering is:

    Code:
    dest.rgb = src.rgb * fontcolor.rgb + dest.rgb * (1-src.rgb)
    dest.a = dest.a
    Or in blend mode syntax:

    Code:
    CL_BlendMode blend_mode;
    blend_mode.set_blend_color(fontcolor);
    blend_mode.set_blend_function(cl_blend_constant_color, cl_blend_one_minus_src_color, cl_blend_zero, cl_blend_one);
    gc.set_blend_mode(blend_mode);
    I hope that help fix your problem.

  10. #10
    Lesser Knight
    Join Date
    Jul 2011
    Posts
    57

    Default

    Thank you for explanation but my problem still persist.
    I tried to set a blending mode you suggested and got the same results - it seems that it is already used by default for rendering in texture. And I still get results different from direct render.
    I've made a simplified example of my problem with actual sprites I use - please see attachment.
    Attached Files Attached Files

  11. #11
    ClanLib Developer
    Join Date
    May 2007
    Posts
    1,824

    Default

    Your code looks perfect.

    I'll have a look at debugging it early next week. (I'm not at a development pc at the moment)

    I expect there to be a problem with the GL1 target.

    For interest, have you tried clanGL or clanSWRender?

  12. #12
    Lesser Knight
    Join Date
    Jul 2011
    Posts
    57

    Default

    Silly me.
    Of course I thought it was me doing it wrong and didn't tried other rendering targets. Now I've tried and got perfect results with clanGL. clanSWRender meanwhile giving the same picture as GL1 with that somewhere-gone-wrong blending. So I'll be using clanGL for the present moment.

    And by the way, I found another little error with texture rendering(or maybe it is error in direct render). When drawing primitives, there is difference in calculating vertical position for direct render and rendering to texture. Most confusing that it is differ for different primitives. I've tried only point and line drawing and got following results:

    For direct render:
    point (y = 0) - not shown (outside screen bounds)
    point (y = 1) - shown at the first pixel position of client area
    line (y = 0) - shown at first pixel
    line (y = 1) - shown at second pixel

    For rendering to texture:
    point (y = 0) - shown at first pixel
    point (y = 1) - shown at second pixel
    line (y = 0) - not shown
    line (y = 1) - shown at first pixel

    As for horisontal position, primitives with (x = 0) never shown(outside screen), with (x = 1) shown at firs pixel position in both modes.

    Positions of sprites, textures and fonts are not affected by the framebuffer settings.

  13. #13
    ClanLib Developer
    Join Date
    May 2007
    Posts
    1,824

    Default

    Two ClanLib 2.3 SVN and ClanLib 2.4 SVN patches:

    1) clanGL1 to support BlendFuncSeparateEXT (where available)
    2) Modify the clanGL1 matrix rules to match the clanGL matrix rules

    For reference, see http://www.rtsoft.com/forums/archive...hp/t-3005.html

    We now have:
    Code:
    		if (cl1BlendFuncSeparate)
    		{
    			cl1BlendFuncSeparate( 
    				to_enum(mode.get_blend_function_src()),
    				to_enum(mode.get_blend_function_dest()),
    				to_enum(mode.get_blend_function_src_alpha()),
    				to_enum(mode.get_blend_function_dest_alpha()) );
    		}
    		else
    		{
    			//throw CL_Exception("BlendFuncSeparate is not supported for OpenGL 1.3");
    			if (cl1BlendFunc)
    				cl1BlendFunc(to_enum(mode.get_blend_function_src()), to_enum(mode.get_blend_function_dest()));
    		}
    	}
    cl1BlendFuncSeparate is loaded as: "glBlendFuncSeparate" or "glBlendFuncSeparateEXT".

    The clanGL1 projection/modelview/viewport matricies code did not match the rules that clanGL uses. This has now beeen synchronised.

    For a quick fix to your code, so you do not have to use the SVN version. And maybe a better method anyway...

    Code:
    			if (use_fb)
    			{
    				gc.reset_frame_buffer();
    				gc.clear();
    
    				CL_BlendMode myblend;
    				myblend.enable_blending(false);
    				gc.set_blend_mode(myblend);
    
    				gc.set_texture(0, t1);
    				CL_Draw::texture(gc, CL_Rectf(0, 0, 800, 600));
    				gc.reset_texture(0);
    				gc.reset_blend_mode();
    			}
    (Note the myblend.enable_blending(false); )

  14. #14
    Lesser Knight
    Join Date
    Jul 2011
    Posts
    57

    Default

    Thanks, that solves it.
    (except from software renderer, but I don't think I'll be using it)

Similar Threads

  1. Transparent text rendering?
    By Noro in forum Official ClanLib SDK Forums
    Replies: 5
    Last Post: 08-13-2011, 03:38 PM
  2. Rendering to textures that has special size
    By Ferrum in forum Official ClanLib SDK Forums
    Replies: 3
    Last Post: 07-10-2011, 07:23 AM
  3. GUI / Rendering Display
    By Fr3DBr in forum Official ClanLib SDK Forums
    Replies: 4
    Last Post: 08-22-2009, 11:00 PM
  4. The GDI Target Rendering Pixelbuffers
    By rombust in forum Official ClanLib SDK Forums
    Replies: 2
    Last Post: 02-15-2009, 09:46 PM
  5. Font rendering acceleration in v0.9
    By z42 in forum Official ClanLib SDK Forums
    Replies: 3
    Last Post: 02-18-2008, 12:09 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
  •