[SoC 2009 - Accepted] Improve Ogre's Compositor Framework

Threads related to Google Summer of Code
Locked
User avatar
Noman
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 714
Joined: Mon Jan 31, 2005 7:21 pm
Location: Israel
x 2
Contact:

Re: [SoC 2009 - Accepted] Improve Ogre's Compositor Framework

Post by Noman »

Ok. Agreed. Updated the wiki with the change. I called it compositor_texture_ref. Its a bit longer, but more self-explanatory - when someone will read a script and see texture_ref, his initial response might be 'referencing what?'...

Also wrote a pseudo-declaration for the scheme handlers. There are a few dilemmas on exactly how to do this, but they are minor (ie - same method with default argument or another method, etc).

Next up is summarizing the strategy for combining pooling and scoping of compositor textures, and then I'll probably get to the light iteration design, which I didn't go deeply into yet...
User avatar
Noman
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 714
Joined: Mon Jan 31, 2005 7:21 pm
Location: Israel
x 2
Contact:

Re: [SoC 2009 - Accepted] Improve Ogre's Compositor Framework

Post by Noman »

Started writing about more subjects in the wiki :
* How will pooling (currently called 'sharing') be handled in these scopes?

Local scope (current texture mode, will be default) will be handled like it currently is. (As aggressive as possible)
Chain scope will allow viewports with parallel compositors to use the same texture instances. We can't be more aggressive than that, because the next compositors in the chain might be able to use it.
Global scope will not support the sharing flag, as there is already exactly one texture per compositor, which the user might want to have access to at any given time.

* How will validation work?

I decided to implement validation only (rather than fixing) in this project, mainly for ease of implementation, but the user doesn't want his compositors re-ordered without knowing about it.
The main thing that needs checking is that when a compositor with a compositor_texture_ref directive is added to a chain, the compositor that it is referencing (and the texture inside) are defined and are before the compositor in the chain. If this is not the case, an exception will be thrown.
Global scoping can not be checked, as the user may use any strategy that they want as to when/how to run this compositor and update the texture. The texture itself will be initialized the first time it is about to be used. target_width/target_height params will either be illegal for this texture type, or initialized with the first viewport size that renders to it.
Tomorrow : light iteration!
User avatar
Noman
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 714
Joined: Mon Jan 31, 2005 7:21 pm
Location: Israel
x 2
Contact:

Re: [SoC 2009 - Accepted] Improve Ogre's Compositor Framework

Post by Noman »

Been thinking quite a bit about how to handle per-light rendering in compositors. Still undecided, but I'll use this as a temporary place to put all my thoughts down to get responses and then work a final idea for the project.

The goal of per-light-rendering is to allow additional passes of the scene (or single objects) to complete the rendering.
The two main use cases are :
A) Rendering individual lights in the deferred shading pipeline - this is currently implemented in the deferred shading demo, and is illustrated very well in the Killzone 2 deferred shading overview - It involves rendering a geometric object (sphere for point light, cone for spotlight and full screen quad for directional light), pulling in the neccesary information from the G-Buffer and adding light to the scene.
B) Rendering shadow maps for texture based shadow techniques. This is currently handled by a different subsystem in ogre altogether, but in some cases (such as deferred shading) the integrated system can not be completely used for shadows.

These two use cases force some constraints on the solution, I will talk about their requirements before laying out the options for the solution :
1) Use case A requires creating custom geometry and rendering it. The deferred shading demo creates the geometry in code and adds it to the scene in a late render queue. Even if this approach is used (which we don't want to force the user to do), I don't think its possible to set this stage up in script only. This means that this compositor will require some code behind it - good thing for CompositorLogic coupling :)
2) Use case B is the more advanced and problematic one. We would like to be able to reuse the same texture for shadow mapping to preserve precious GPU memory. So, the ideal sequence would be this pseudocode:

Code: Select all

for each light:
	if shadow casting:
		render scene from shadow camera to shadow texture
		blend shadow texture to final output
So, setting up such sequences needs to be possible.

Now the question is, how will the scripts that do this look?
Usecase A is pretty simple. The first thing that would need to be done, is to add a directive similar (if not equal) to material pass's 'iteration' directive, to allow composition passes to execute more than once. In addition to that, we have to let the user render the special light geometry.

It would probably look like (all names subject to change):

Code: Select all

//This is the texture generated by the main deferred pass
compositor_texture_ref DeferredPass output_tex DeferredMRT
//This logic will be the one constructing and rendering the light geometry in the 'render_custom' pass
compostior_logic DefferedLightBlend

target rt
{
    // Start with the scene ambient-lit
    input previous
    // SSAO pass
    pass render_custom
    {
        // Render this once per light - this directive is new in compositor-land
        iteration once_per_light

        // Renders a fullscreen quad with a material
        material Ogre/Deferred/DeferredLightBlend
        // The MRT target containing the normals
        input 0 DeferredMRT 0
        // The MRT target containing the specular intensity
        input 1 DeferredMRT 2
    }
}
The CompositorLogic would get a callback once per each light (with the light that is next in line), and will be able to render its custom light geometry (cone/sphere etc) once per each light. I don't think this can be achieved without code, unless 'deferred shading standards' are set, such as fixing the light geometry.

Usecase B is the problematic one, and the reason for that is scoping. In the previous example, the 'iteration' directive was placed in the CompositionPass scope. However, for the shadow rendering pipeline, we need to iterate two composition passes (one for creating the shadow texture, one for blending with the result) that render to two different textures (the first to the temporary shadow texture, the second to the result texture). So, this means that the 'iteration' directive can't be in the composition pass scope, and it can't be in the target pass scope either! The next scope is the composition technique scope, which means that the entire compositor will be iterated. This would case the shadow mapping compositor to look something like this :

Code: Select all

//This is the texture generated by the main deferred pass
compositor_texture_ref DeferredPass output_tex DeferredMRT
texture shadow_texture 1024 1024 PF_FLOAT_R32
//This logic will be the one setting up the shadow camera in the render_scene pass
compostior_logic DefferedShadowMap

// Render the entire compositor sequence once per light
iteration once_per_light

target shadow_texture
{
    // Start with a clean texture
    input none
    // Generate shadow map pass
    pass render_scene
    {
        material_scheme shadow
    }
}

target_output
{
    // Start with the scene after the previous processing
    input previous
    // Shadow map blend pass
    pass render_quad
    {
        // Renders a fullscreen quad with a material
        material Ogre/Deferred/ShadowMapBlend
        // The MRT target containing the depth
        input 0 DeferredMRT 1
        // The shadow map texture
        input 1 shadow_texture
    }
}
This is indeed a more advanced compositor, which makes sense because it effectively replaces the entire integrated shadow pipeline for this rendering pipeline. So, the question is, where will the 'iteration' directive be placed? The shadowmap usecase is impossible with the composition pass or the target pass scope. The light blending is possible with the composition technique scope, but would require it to be all alone as a compositor. Is it bad? I dunno. I think it might be the better way to do it, if not we will probably have to support the 'iteration' directive in two scopes.
I also don't see these solutions becoming possible without code intervention. Theoretically we would like to be able to script the entire rendering pipeline, but there are too many options that need to be available. This still reduces the amount of code by a lot, and only requires you to insert code where your pipeline is unique. Lots of dirty work (setting up the correct order of rendering, hooking up between the different stages) is done by the framework, so I do think that this is a good solution to the problem.


IMPORTANT REQUEST!
I really feel that I need feedback for this one, as design-wise its probably the most complicated part of the project. I would really like for as many people to comment about this one. Thanks!
User avatar
Assaf Raman
OGRE Team Member
OGRE Team Member
Posts: 3092
Joined: Tue Apr 11, 2006 3:58 pm
Location: TLV, Israel
x 76

Re: [SoC 2009 - Accepted] Improve Ogre's Compositor Framework

Post by Assaf Raman »

I think we need to think how to improve the readability of the this kind of script, the script file should tell you the story, I am not sure we are optimal in how clear is the script. I need to think more about how to improve this side of it, how to get closer to the pseudo code you wrote and less numbers and counts.
Are remarks the way to go or a better syntax?
Perhaps this is out of your project scope, I am just thinking out loud.
Do you have any script syntax samples of existing game engines and such that do smiler things?
Watch out for my OGRE related tweets here.
User avatar
Praetor
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 3335
Joined: Tue Jun 21, 2005 8:26 pm
Location: Rochester, New York, US
x 3
Contact:

Re: [SoC 2009 - Accepted] Improve Ogre's Compositor Framework

Post by Praetor »

I have never encountered an engine with declarative scripts like Ogre's. If another engine even has something like the compositors, the best it is usually is access from the engine's imperative or functional language, so it looks very different. Constructs like looping (iteration over lights for instance) when scoping is involved is familiar to us with imperative or functional languages. If you need help thinking up how to represent constructs in Ogre's scripts I'd turn to some declarative languages like prolog to see how it is done there. First I'd suggest when you talk about "scoping" it would help readability to actually show that scoping in the scripts. For instance, the compositor version of the "iteration" directive could be an object instead of a property:

Code: Select all

iteration
{
     condition once_per_light

     target ...
     target_output ...
}
I think that is pretty readable. The problem is iteration already has a meaning and representation so this might be confusing.
Game Development, Engine Development, Porting
http://www.darkwindmedia.com
User avatar
sinbad
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 19269
Joined: Sun Oct 06, 2002 11:19 pm
Location: Guernsey, Channel Islands
x 66
Contact:

Re: [SoC 2009 - Accepted] Improve Ogre's Compositor Framework

Post by sinbad »

Ok, some good points and ideas here for sure. I like the scoping arguments you've picked, they make perfect sense.

As for light iteration, what we have here is a classic example of a design decision where we need to pick how general/specific we want to be. Specific solutions will be more elegant for that particular task, whilst general solutions will be more flexible but generally more verbose / difficult to understand for the specific cases.

Ok, first the easy one: use case A. I definitely agree with your 'render_custom' pass, and I think in practice it would be best to implement this 'custom' behaviour in a pluggable, named class, so it might be something like:

Code: Select all

    pass render_custom LightGeometry
    {
        // Render this once per light - this directive is new in compositor-land
        iteration once_per_light
Where "LightGeometry" is a CompositionPass subclass (some refactoring will probably be required here) registered with the CompositorManager, which knows how to render light geometry. I'm not sure I can envisage how the 'compositor_logic' option that you showed is supposed to work, since it's declared at a global scope level. I'd find it more intuitive for custom logic to be at a more specific level, like this, where the interface and responsibilities can be more clearly defined.

I also think the 'iteration' param should take all the same options the material system does, including a certain number of times per light, and light type filtering, and support for the 'start_light' parameter and perhaps 'max_lights'. Personally I wouldn't do a directional light as a deferred pass, I'd incorporate it in the first base pass which generates the Lighting Accumulation (RT0 of the GBuffer in the Killzone 2 paper), because there's no point doing it as a separate pass when it's already fullscreen. This means that you need to be able to exclude the directional light from this iteration, which normally means just starting from light #1 (since directional lights are always first in the list, and there's usually only one).

Now, on to use case B. I don't think the rendering of a shadow texture should be considered to be a compositor pass or target. It's quite a nice idea what you have there, in that it's generalised, but when it comes down to it I think it overcomplicates matters. In practice you probably never want to iterate the whole compositor per light, and while introducing a new 'iteration' block as Praetor suggests certainly addresses that, I personally think it may become overcomplicated for what we actually need here. Unless we can think of another reason why you might want to iterate a specific group of passes, I think I would personally shy away from that right now and go for something simpler.

The way I see it, you need 3 things to have an iterated deferred shader with shadows:
1. A way to tell the render_scene the number of shadow textures that should be generated before the main scene render (in deferred shading, if there's one directional light, then this would be 1, otherwise 0)
2. A way to iterate the deferred lighting compositor pass, from a particular light index (covered above)
3. A way to update and bind the corresponding shadow texture for this light to an input on the compositor pass

The simplest solution to this would be something like this:

Code: Select all

target gbuffer
{
    // gbuffer is multiple surfaces, including a light accumulation buffer, normals, depth etc
    input none
    pass render_scene
    {
        // render scene using gbuffer-generating materials
        material_scheme gbuffer
        // only reference the first (directional) light. 
        max_lights 1
        // Render shadow textures up to max_lights (or max number of shadow textures)
        render_shadow_textures true
    }

}
target_output
{
    input none
    // lighting passes
    pass render_custom LightGeometry
    {
        // Render this once per light - this directive is new in compositor-land
        iteration once_per_light
        start_light 1
        // this means render the *corresponding* shadow texture for the light we're processing as a pre-step
        render_shadow_textures true
        
        // Renders a fullscreen quad with a material
        material Ogre/Deferred/DeferredLightBlend
        input 0 gbuffer 0
        input 1 gbuffer 1
        // 'content_type shadow' is a reserved name meaning 'bind shadow texture', with the index being relative to the base light for this pass (so starts at 1 here)
        input 2 content_type shadow 0
    }
}
I realise that's not as flexible as manually constructing a shadow render as a compositor pass, but I also think it's less complicated to write, and also to deal with the edge cases like wanting to render one shadow texture as part of the render_scene. In this case I've taken 'render_shadow_textures' to mean 'render shadow textures corresponding to what I'm rendering anyway, up to the maximum', which also corresponds to the existing default (ie its default is 'true' anyway for render_scene, I've just included it for completeness). I'm struggling to think of a case that this style wouldn't deal with, and the fact that it's slightly more specific will probably also make it easier to implement.
User avatar
Noman
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 714
Joined: Mon Jan 31, 2005 7:21 pm
Location: Israel
x 2
Contact:

Re: [SoC 2009 - Accepted] Improve Ogre's Compositor Framework

Post by Noman »

Thanks for the replies! Now its my turn again :)

About the CompositorLogic binding - I currently think about it mainly as a way to auto-couple CompositorInstances and CompositorListeners. So, the render_custom pass will likely also declare a pass_id like the current 'advanced' compositors do in the demo, and the CompositorLogic will listen to the pass_id that its waiting for and render its custom geometry then. Yes, having named custom CompositorPass'es is possible, but do we want to add another pluggability point? (CompositorLogic also makes the current opportunities possible easily, while this is even more specific)

As for the light iteration, I think I understand what you mean, so let me try to write down your suggestion the way I see it before I address it :
Rendering shadow maps will NOT be possible in the compositor framework. If you do want to render shadow maps, just turn on a flag in the render_scene pass that will tell the engine to render the shadow maps just like it knows. This will allow reusing of a single shadow texture for multiple lights, and be simpler to use / implement, while less flexible. Since Ogre has a shadow framework, we can deal with it.
Does the directive 'render_shadow_textures' mean to ONLY render shadow textures? If so, that will work.
So, the render sequence would look like this :

Code: Select all

1 - Shadow map for directional light is generated (if the compositor treats the directional light differently)
2 - Scene is rendered to the gbuffer, with ambient/directional/directional shadow light information already inside. (again, the user may choose not to do this if they don't want to)
3 - For each light, the shadow texture is rendered (which the currently set ShadowCameraSetup controls), and then the light is added to the scene via the LightGeometry renderer (which will either be named or applied via listening to the pass)
This makes sense.
One of the reasons i thought about generating shadow maps in a render_scene pass was the option to programatically create shadow materials by using a 'shadow' material scheme, which then a material listener could listen to, get the material and dynamically choose the correct material (for example, for semi-transparent objects it would load a material that writes depth only if the transparency is > 0.5, and apply the alpha map texture as the input to that pass).
However, this can be implemented this way too, if we add another callback to the MaterialManager::Listener concerning shadow materials (keeping with the current ogre state of mind that shadows are different from everything else)

It really is a tradeoff like you said - we have to choose between flexible and easy to use/implement. Deferred shading will be possible with this method, and I don't know if there are other 'full scene rendering pipeline' concepts that currently exist. If they do come up, this solution might not be suitable for them, but that sounds like a reasonable risk to take...

I'll think about the 'named compositor passes' vs 'compositor listener pass id' options. Currently still leaning towards the original idea. (In the render_custom case, the listener doesn't just get the callback to 'listen in' but to actually act, as the actual pass does nothing, its just a stub to pass events to the listener which gets auto-added because of the compositor logic)
User avatar
sinbad
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 19269
Joined: Sun Oct 06, 2002 11:19 pm
Location: Guernsey, Channel Islands
x 66
Contact:

Re: [SoC 2009 - Accepted] Improve Ogre's Compositor Framework

Post by sinbad »

Noman wrote:About the CompositorLogic binding - I currently think about it mainly as a way to auto-couple CompositorInstances and CompositorListeners. So, the render_custom pass will likely also declare a pass_id like the current 'advanced' compositors do in the demo, and the CompositorLogic will listen to the pass_id that its waiting for and render its custom geometry then. Yes, having named custom CompositorPass'es is possible, but do we want to add another pluggability point? (CompositorLogic also makes the current opportunities possible easily, while this is even more specific)
Ok, I see what you mean. I was previously thinking that was for app-level logic but I see how you could apply it to a set of 'factory' implementations like this too. The binding is slightly less obvious between the logic and the pass this since it's based on them agreeing on a pass ID, but that's fair enough. Also since it's a listener, it doesn't get the opportunity to alter the compiled state of the compositor like the 'core' pass types do, so I'm not sure if that's going to be restrictive. If while you're doing this, you want to make the listener callbacks more explicit (you're going to have to change them anyway to cope with iteration and light details), feel free to come up with new suggestions.
Does the directive 'render_shadow_textures' mean to ONLY render shadow textures? If so, that will work.
No, it was meant to indicate that it would render the shadow textures from start_light to max_light (or up to the maximum number of allowed shadow textures), before going on to do the rendering of the scene (therefore it really only applied to render_scene passes, or other passes which do that). So the pass both renders the shadow textures, and uses them. I think this is vital for matching the shadow textures generated to the ones used, and re-using the same shadow textures when there is iteration or otherwise more that one of these passes.
So, the render sequence would look like this :

Code: Select all

1 - Shadow map for directional light is generated (if the compositor treats the directional light differently)
2 - Scene is rendered to the gbuffer, with ambient/directional/directional shadow light information already inside. (again, the user may choose not to do this if they don't want to)
3 - For each light, the shadow texture is rendered (which the currently set ShadowCameraSetup controls), and then the light is added to the scene via the LightGeometry renderer (which will either be named or applied via listening to the pass)
Yes, this is what I meant so perhaps I misinterpreted your 'ONLY render shadow textures' comment above, because to create this sequence with the example script I gave (with the proposed logic binding change) the pass is doing both the shadow render and the light application, with matching light details.
One of the reasons i thought about generating shadow maps in a render_scene pass was the option to programatically create shadow materials by using a 'shadow' material scheme, which then a material listener could listen to, get the material and dynamically choose the correct material (for example, for semi-transparent objects it would load a material that writes depth only if the transparency is > 0.5, and apply the alpha map texture as the input to that pass).
However, this can be implemented this way too, if we add another callback to the MaterialManager::Listener concerning shadow materials (keeping with the current ogre state of mind that shadows are different from everything else)
Yes, this can already be done with the shadow_caster_material hooks and altered via material schemes if necessary, so it's probably a good idea not to create another way of doing it, since that would be confusing, as well as the issues around increasing the complexity of the compositor (both for the user and for the implementation).
It really is a tradeoff like you said - we have to choose between flexible and easy to use/implement. Deferred shading will be possible with this method, and I don't know if there are other 'full scene rendering pipeline' concepts that currently exist. If they do come up, this solution might not be suitable for them, but that sounds like a reasonable risk to take...
Yeah, it's a fine line - I usually do like to design for extension later, but at the same time you really want to have some specific kind of extension in mind that can't be recreated with features that are already there to justify adding more complexity. I think from what I know right now, being explicit & special casing the shadow support makes more sense on balance, but I'm willing to reconsider that if a use case arises where the more complicated approach would give significant benefits. And if that arises, of course the specific approach could if necessary be implemented in terms of the more general technique, keeping the usability and not breaking compatibility. I just don't think there's a case for doing it at this stage.
I'll think about the 'named compositor passes' vs 'compositor listener pass id' options. Currently still leaning towards the original idea. (In the render_custom case, the listener doesn't just get the callback to 'listen in' but to actually act, as the actual pass does nothing, its just a stub to pass events to the listener which gets auto-added because of the compositor logic)
Yeah, all ideas welcome here. Good work!
User avatar
Noman
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 714
Joined: Mon Jan 31, 2005 7:21 pm
Location: Israel
x 2
Contact:

Re: [SoC 2009 - Accepted] Improve Ogre's Compositor Framework

Post by Noman »

OK.
My main drawback from this solution is that besides being more specific, it actually might cause more keywords/directive than the more general solution. However, I do understand the motive to make sure that there is one way to do stuff, so rendering shadows should always be done through ogre's shadow framework. I also can't really think of an example where this wouldn't be enough, so its fine.

I'll try to sum this conversation up this week and have a detailed plan up at the wiki. Coding starts in week, but there is still time until I get to the light rendering sequence, so I'll have an opportunity to think it over some more before I start implementing.

The first parts - inter compositor communication (includes scoping/pooling) and non-competing scheme handlers are designed. I didn't get to do scriptable chains yet, but that is almost trivial, I'll add it to the wiki this week as well, and we'll be ready for the ride..

Thanks for the inputs!
User avatar
Noman
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 714
Joined: Mon Jan 31, 2005 7:21 pm
Location: Israel
x 2
Contact:

Re: [SoC 2009 - Accepted] Improve Ogre's Compositor Framework

Post by Noman »

Right. GSoC officially starts today. Updated the wiki with the current state of per-light rendering and all that. Might refine it later on in the project, but its a solution that i'm pretty satisfied with.
On to the coding!

To be continued :)
User avatar
iloseall
Gremlin
Posts: 156
Joined: Sun Sep 14, 2003 3:54 am
Location: Beijing China
Contact:

Re: [SoC 2009 - Accepted] Improve Ogre's Compositor Framework

Post by iloseall »

the deferred shading example in the wiki
[url]ttp://www.ogre3d.org/wiki/index.php/SoC2009_C ... get_Design[/url].

I think another example difference for defeered shading .

Code: Select all

target gbuffer
{
  input none
  pass render_scene
  {
    first_render_queue 20  //solid object start
    last_render_queue 60  //solid object finished
    material_scheme gbuffer
    //no light setting ,beacause the example use cube diffuse map as global light,that's is not support direct in ogre.

//set stencil with 1
    stencil 
    {
       check on
       comp_func always_pass 
       pass_op replace 
       ref_value  1
    }
  }
}
target down_sample_depth_buffer //for off_screen particle
{
  pass render_quad
  { 
    ....
  }
}

Code: Select all

target lightbuffer
{

  pass render_scene
   {
    stencil 
    {
       check on
       comp_func not_equal
       pass_op keep 
       ref_value  1
    }
     first_render_queue 1   //background object (just like layer cloud ,sky)
     last_render_queue  2 
     material_scheme default
   }

   pass render_scene
   {
     first_render_queue 65   //light object start
     last_render_queue  66  //light object finished
     material_scheme default

     //we have 3 light for example:
     // 1st is point light, use custom cube map (red_lamp_with_noise.dds) as light color use sphere as light geometry.
     // 2nd is point light too,use another texture (cloud_filter.dds) as light color.use sphere as light geometry.
    //3th is volume light. with Convex hull as geometry. render need two pass,first render back and then render front with custom stencil
    //all light geometry onwer material just like another entity.
    // in the light geometry material,we need use the texture from the 

compositor.
    //in the light geometry material,we need use stencil for each pass.
   }

  //render sky and far object with stencil != 1
  pass render_scene
  {
    stencil 
    {
       check on
       comp_func not_equal 
       pass_op keep 
       ref_value  1
    }
   pass render_scene
   {
     first_render_queue 1   //Render Sky ,Far billboard ,etc
     last_render_queue  5 
     material_scheme default
  }
  }

  pass render_scene
   {
    stencil 
    {
       check off
    }
     first_render_queue 70  //alpha blend object ( particle ,fire and other....)
     last_render_queue  90 
     material_scheme default
     //particle material should use the down_sample_depth_buffer as texture input
   }
  
}
//material for light 1:

Code: Select all

{
  tech
 {
    scheme default
    pass
    {
     //**** Can we control stencil in material pass?
     stencil 
     {
       check on
       comp_func equal 
       pass_op increment 
       ref_value  1
     }
     depth write off
     depth check on
     color write off
     cull  back

    }
    pass
    {

     stencil 
     {
       check on
       comp_func equal 
       pass_op decrement
       ref_value  2
     }
     depth write off
     depth check off
     color write on //write to light buffer
     cull front

     program_ref deffered_shadding_point_cube_light
     texture_unit
    {
        type cube map
        texture_name "red_lamp_with_noise.dds"
    }
     texture_unit 
     {
  //********how can I ref texture of currernt active compositor?
       compositor_texture_ref gbuffer 1
     }
     texture_unit 
     {
        compositor_texture_ref gbuffer 2
     }
     texture_unit 
     {
        compositor_texture_ref gbuffer 3
     }
    }
 }
}
edit 2009-05-25:
questions:
1 Can we control stencil in material pass?
2 Can we use texture of currernt active compositor in entity's material?
//A:compositor_texture_ref
3 Can we expand ogre's light with custom geometry and how can I let shadow work with custom light?
Last edited by iloseall on Wed May 27, 2009 12:18 am, edited 3 times in total.
User avatar
Noman
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 714
Joined: Mon Jan 31, 2005 7:21 pm
Location: Israel
x 2
Contact:

Re: [SoC 2009 - Accepted] Improve Ogre's Compositor Framework

Post by Noman »

The point of the examples in the 'target design' section was not to be the actual implementation of deferred shading using this framework, but just as short examples showcasing the new script options that will be available, and how they make specific techniques possible. When the time for modifying the demo will come, more advanced use of these features will take place. Don't worry, and thanks for the input!
User avatar
Noman
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 714
Joined: Mon Jan 31, 2005 7:21 pm
Location: Israel
x 2
Contact:

Re: [SoC 2009 - Accepted] Improve Ogre's Compositor Framework

Post by Noman »

Small progress update - coding has started. Scripting/definition side of compositor referencing and compositor logics are done. Next step will be to actually hook up the textures and add validation. After that, I'll add the CompositorLogic interface (which will just be a way to auto-couple compositors and listeners, initially) and then start changing the deferred shading demo to work with this instead.
User avatar
Noman
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 714
Joined: Mon Jan 31, 2005 7:21 pm
Location: Israel
x 2
Contact:

Re: [SoC 2009 - Accepted] Improve Ogre's Compositor Framework

Post by Noman »

Working on the combination of implementing cross-compositor referencing and changing the deferred shading demo to use it.
Progress coming along nicely, but I just noticed another minor change that the compositor framework will have to undergo :
target_output passes should no longer be mandatory in composition techniques. Since some compositors don't actually post-process the scene, but just prepare textures that other compositors will use (Deferred shading GBuffer is the perfect example for this), it now makes sense for some compositors to not output to the final scene composition.

I don't think its a big change - the final compositor in a chain will still have this requirement, and if a compositor doesn't have one, this part of the pipeline will skip it.
User avatar
Noman
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 714
Joined: Mon Jan 31, 2005 7:21 pm
Location: Israel
x 2
Contact:

Re: [SoC 2009 - Accepted] Improve Ogre's Compositor Framework

Post by Noman »

Well. I thought that the target_output thing would be an issue, but apparently, its not.
I just comitted in another small change to the demo, and it works!
The current state of deffered.compositor is this :

Code: Select all

// Postfilter doing full deferred shading

compositor DeferredShading/GBuffer
{
	technique
	{
		// temporary textures
		texture mrt_output target_width target_height PF_FLOAT16_RGBA PF_FLOAT16_RGBA chain_scope
		
		target mrt_output
        {
            input none
        	pass clear
			{
			}
			
			// everything but the lights and their meshes
			// could do this with something like a visibility mask too
			pass render_scene
			{
				first_render_queue 22
				last_render_queue  90	
			}
        }
	}
}

compositor DeferredShading/ShowLit
{
	technique
	{
		//Reference the main Gbuffer texture
		texture_ref mrt_output DeferredShading/GBuffer mrt_output
		
        target_output
        {
			input none
			
			// render skies
			pass render_scene
			{
				first_render_queue 5
				last_render_queue  5			
			}
						
			// just the lights and their meshes
			pass render_scene
			{
				first_render_queue 20
				last_render_queue 21
			}
		}
	}
}

// Postfilter that shows the colour channel
compositor DeferredShading/ShowColour
{
	technique 
	{
		//Reference the main Gbuffer texture
		texture_ref mrt_output DeferredShading/GBuffer mrt_output
		
		target_output
        {
			input none
			
			pass render_quad
			{
				material DeferredShading/Post/ShowColour
				input 0 mrt_output 0
				input 1 mrt_output 1
			}
        }
	}
}

// Postfilter that shows the normal channel
compositor DeferredShading/ShowNormals
{
	technique 
	{
		//Reference the main Gbuffer texture
		texture_ref mrt_output DeferredShading/GBuffer mrt_output
		
		target_output
        {
			input none
			
			pass render_quad
			{
				material DeferredShading/Post/ShowNormal
				input 0 mrt_output 0
				input 1 mrt_output 1
			}
        }
	}
}

// Postfilter that shows the depth and specular channel
compositor DeferredShading/ShowDepthSpecular
{
	technique 
	{
		//Reference the main Gbuffer texture
		texture_ref mrt_output DeferredShading/GBuffer mrt_output

		target_output
        {
			input none
			
			pass render_quad
			{
				material DeferredShading/Post/ShowDS
				input 0 mrt_output 0
				input 1 mrt_output 1
			}
        }
	}
}
And it works just like the previous demo!
The feature is still far from complete (global scoping not implemented yet, neither has pooling) but texture referencing and validation both work as expected!

Just to illustrate the advantages of this approach already :
The target pass inside the DeferredShading/GBuffer compositor was present in ALL of the compositors previously. This means script duplication. We don't like script duplication :)

Now, each compositor just references the first one, and finishes the process however it sees fit.
User avatar
Praetor
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 3335
Joined: Tue Jun 21, 2005 8:26 pm
Location: Rochester, New York, US
x 3
Contact:

Re: [SoC 2009 - Accepted] Improve Ogre's Compositor Framework

Post by Praetor »

That's a big change all on itself. This means that as a script designer you can save renders whereas before you could not. Good for optimizing the render pipeline for special rendering (like deferred rendering).
Game Development, Engine Development, Porting
http://www.darkwindmedia.com
User avatar
Noman
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 714
Joined: Mon Jan 31, 2005 7:21 pm
Location: Israel
x 2
Contact:

Re: [SoC 2009 - Accepted] Improve Ogre's Compositor Framework

Post by Noman »

When I said "I thought that the target_output thing would be an issue, but apparently, its not." I didn't mean that it was an easy change to make, I meant that the demo works fine without the change. I didn't dive deep yet to understand why it works (maybe Ogre already deals with this) but I'll get to it.

Anyway, more thinking out loud for me. In this episode : Global scope textures.
I already took care of local (default, current) and chain (visible to other compositors in chain) scope textures, but global is a bit harder. The reason for that is that currently, Ogre::CompositorInstances are the ones who create (and store) textures, and thats fine.
However, it is not fine for global textures, as they don't exist on a per-instance scope. The question is, where are they kept and how are they accessed later?

I currently see two solutions :
A) (My preferred solution) : Ogre::CompositionTechnique will now keep a list of textures similar to CompositorInstance's mLocalTextures (Will probably be called mGlobalTextures). This will keep the texture names (or pointers) to the global textures. Then, CompositorInstance's getSourceForTex (which is where I'm making a lot of the modifications) will identify a TextureDefinition as global and will know to delegate the call to the CompositionTechnique it belongs to.
Upside - coherent with ogre's current design, no naming collisions
Downside - CompositionTechnique no longer just a data structure containing creation data, now contains real resource pointers and stuff, possible code duplication (handling mLocalTextures is similar to mGlobalTextures).

B) Other solution : Coordination of global textures will be completely name-based. Pseudo-random numbers will NOT be added to the texture name generated by Ogre::CompositorInstance, which will mean that if two different instances request this texture, the same texture name (and thus the same texture) will be returned.
Upside - CompositionTechnique remains simple, less code duplication. Might be simpler altogether
Downside - Less 'controlled' IMO by relying on naming conventions, possible name collisions.

I'm leaning towards A mainly because the code will be more explicit and self-explanatory, but I haven't fully decided yet. Thoughts?
User avatar
sinbad
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 19269
Joined: Sun Oct 06, 2002 11:19 pm
Location: Guernsey, Channel Islands
x 66
Contact:

Re: [SoC 2009 - Accepted] Improve Ogre's Compositor Framework

Post by sinbad »

When I first read about making target_output non-mandatory, I thought it didn't make sense. But of course, it makes perfect sense given your additions - all of a sudden compositors become able to be drop-in components. I love it.

As for the global textures, I think option A's style is nicer, although I'm not sure whether CompositorTechnique is the right place, more likely Compositor itself I think. That's because when you refer to a global texture I don't think you'd be specific about which technique you wanted to use, and if the technique switched at runtime (possible, I do this sometimes to temporarily switch to a cheaper option or similar) you don't really want 2+ sets of global textures being stored, and you probably want the texture as seen externally to change seamlessly with the technique change. When a compositor exposes a global texture, it implicitly is required to expose it from all techniques anyway (otherwise external compositors could not rely on it), so it makes sense for them to share I think.
User avatar
Noman
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 714
Joined: Mon Jan 31, 2005 7:21 pm
Location: Israel
x 2
Contact:

Re: [SoC 2009 - Accepted] Improve Ogre's Compositor Framework

Post by Noman »

Hmm...

My original thought was to have them defined at the Compositor scope as well, but textures are defined at the CompositionTechnique scope, which caused me to think about putting it over there.
I'm a bit afraid of some implicitness that putting this in the Compositor scope will have, but that can be solved using good documentation and validation (I can check that if a global texture is defined, it is defined in all of the CompositionTechniques in a compositor).

Thinking about it again, it might be the better option.
User avatar
Noman
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 714
Joined: Mon Jan 31, 2005 7:21 pm
Location: Israel
x 2
Contact:

Re: [SoC 2009 - Accepted] Improve Ogre's Compositor Framework

Post by Noman »

Another week, another progress report. Just finished organizing my work and putting it all in SVN. Progress summary :

Implemented global scoping technique
Design decision : they will be accessible at Compositor scope. When the texture is created (when the Compositor resource is loaded), the supported techniques are scanned. The characteristics for the global textures are taken from the first supported technique, then the rest of them are scanned for consistency.

Implemented compositor logic pipeline
Design decision : I am using the rendersystem-like pattern, and not the resource-like pattern. CompositorManager has a registerCompositorLogic method, and its up to the code to make sure that they are registered. This makes it easy to add compositor logic plugins.
The API itself is minimal. This is the relevant part :

Code: Select all

/** Interface for compositor logics, which can be automatically binded to compositors,
	*	allowing per-compositor logic (such as attaching a relevant listener) to happen
	*	automatically.
	*	@remarks All methods have empty implementations to not force an implementer into
	*		extending all of them.
    */
    class _OgreExport CompositorLogic
    {
	public:
		/** Called when a compositor instance has been created.
			@remarks
			This happens after its setup was finished, so the chain is also accessible.
			This is an ideal method to automatically attach a compositor listener.
        */
		virtual void compositorInstanceCreated(CompositorInstance* newInstance) {}

		/** Called when a compositor instance has been destroyed
			@remarks
			The chain that contained the compositor is still alive during this call.
        */
		virtual void compositorInstanceDestroyed(CompositorInstance* destroyedInstance) {}

		/** Called when a compositor instance's enabled state has changed
        */
		virtual void compositorInstanceEnabledChanged(CompositorInstance* instance, bool enabled) {}
	};
Note that the logic does not get called per-frame. It is up to the compositorInstanceCreated callback to add a listener to the compositor instance that has been created. I didn't want to add redundancy to ogre, and I want my changes to be completely backward compatible, so I couldn't remove the Listener. The CompositorLogic classes will most likely act as CompositorInstance::Listener factories, but that is just a recommended design pattern.

Added scheme-specific material listeners
This one went exactly like expected. Nothing surprising.

Next up on the TODO list :
  • Pooling support for chain-scoped textures
  • Compositor Chain scripting support
  • Modifying the deferred shading demo to use all of these cool new features.
Questions for myself
I've been mainly thinking about the compositor chain scripts. The idea is very straightforward - the scripts will be very simple - something along the lines of :

Code: Select all

CompositorChain DefferedShading
{
	DeferredComposition
	DeferredBlend
	SSAO
	"Motion Blur"
}
I don't plan to add additional parameters to the chain definitions besides the names, so it will be very straightforward.
The questions are :
  • Who will be charge of these scripts? Will the CompositorManager be in charge of two script types? I personally think so.
  • Will mixing and matching be allowed? I'm currently leaning towards no. Setting a predefined chain on a viewport that already has a compositor chain defined will lead to either A) exception / warning + do nothing or B) Completely overwrite the new chain with the predefined one.
These questions aren't very hard to answer, I'll probably think about it a bit more and make some decisions.

Most of my efforts will be going into modifying the deferred shading demo in the next weeks. When that is ready, it means that all the work that has been done so far really works and has a usage example. After the demo is working, I will also set up a wiki page that explains the motives and ideas behind the deferred shading demo, as its more complex than most of the other demos design-wise, and should be reusable to some extent.

*Sigh* long post.
User avatar
Noman
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 714
Joined: Mon Jan 31, 2005 7:21 pm
Location: Israel
x 2
Contact:

Re: [SoC 2009 - Accepted] Improve Ogre's Compositor Framework

Post by Noman »

Lots of progress made on the deferred shading demo in the last week.
I've restructured it to make use of the features implemented so far (texture referencing + scheme handlers + compositor logic), and the code is starting to be a whole lot nicer (and way less code duplication).
The demo still has a long way to go, but I need the render_custom sequence for that one, so it will wait for the 2nd phase of the project.
This was also a good testbed for my changes, it was good to see that everything works.

I'm having second thoughts about compositor chain scripts. Dunno if they are that important. For now, I'm waiting with this until a later part of the project. It isn't hard to implement, but feels a little bloated to me. I'll let it sink in for a while before I make my next move about it.

Next up
  • Adding a pluggable SSAO compositor to the demo
  • Pooling support for chain-scoped textures
After these two (not very big) steps are done, I'll continue to the render_custom sequence. Fun fun fun!
User avatar
iloseall
Gremlin
Posts: 156
Joined: Sun Sep 14, 2003 3:54 am
Location: Beijing China
Contact:

Re: [SoC 2009 - Accepted] Improve Ogre's Compositor Framework

Post by iloseall »

happy to see the progress.
Thanks for your work.
and, sorry,
what step is the feature just like "compositor_texture_ref" in material ?
User avatar
Noman
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 714
Joined: Mon Jan 31, 2005 7:21 pm
Location: Israel
x 2
Contact:

Re: [SoC 2009 - Accepted] Improve Ogre's Compositor Framework

Post by Noman »

I decided not to add a material<->compositor integration layer (or similar), mainly because of time constraints. It was out of the scope of this project. However, when the project is finished, much of the work that is being done will make implementing such a bridge easier.

But, its a matter of choosing where to invest energy. I'd rather do all the things I wanted to do on the compositor side (and do them well) instead of ending up with half-assed solutions on both sides...
User avatar
iloseall
Gremlin
Posts: 156
Joined: Sun Sep 14, 2003 3:54 am
Location: Beijing China
Contact:

Re: [SoC 2009 - Accepted] Improve Ogre's Compositor Framework

Post by iloseall »

OK, I agree that you keep mind on major thing.
And, I think material<->compositor integration layer is very import thing for Compositor Framework,But It maybe not be in the SOC2009 with you.
I try to find another way to provider it (or similar) after you Improve Compositor .
User avatar
Noman
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 714
Joined: Mon Jan 31, 2005 7:21 pm
Location: Israel
x 2
Contact:

Re: [SoC 2009 - Accepted] Improve Ogre's Compositor Framework

Post by Noman »

I have some good news and bad news. Being a passimist, I'll start with the bad news :

SSAO incorporation delayed until big demo change of project. Nullsqured's SSAO needs linear depth in order to work correctly, and changing all of the shaders will be a big task, and will need to be modified again after the light iteration stage as well, so I'll wait with it until then. The current 'debugging' utils demonstrate the use of cross-compositor referencing, so it is enough for the infrastructure to be tested correctly.

For the good news :
Chain-scope texture pooling done. This also includes a fix for the current sharing/pooling framework when dealing with MRTs, so some of the work is already making its way into the main branch.

So, next up is the biggest stage - the light_iteration stage. I might have some minor (hopefully not more than that) changes during this phase, but I'm hoping for the best.

My tests in the university are coming up so I'll have less time to invest in the coming month, but I've already made it to the midterm point in terms of progress (besides the SSAO compositor, but the debug features compensate for that) so I'm OK. Hopefully, I'll find the time here and there and make progress. My finals finish 2 weeks before the SoC is done, so I'll be able to invest all of my time during the last section of the project...
Locked