Announcement

Collapse
No announcement yet.

Exposing the BRDF Models to the Material Editor?

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

    Exposing the BRDF Models to the Material Editor?

    Poking around at the Unreal Shader Files, is it possible to expose to different PBR BRDF models that are written into the engine to the material editor, so that materials can select them per-material? I'm looking inside BRDF.usf right now in the engine source, and multiple models are there. I assume that we can simply write our own models in here and change the #define PHYSICS_### flags to use that shader when we compile? Is that feasible?

    I'm looking into ways to make the renderer much more flexible. Our options are extremely locked down at the moment. This would also be a great way to bypass the current issues with foliage shading, which are forcing us to use very expensive SSS methods.

    #2
    Originally posted by TheJamsh View Post
    Poking around at the Unreal Shader Files, is it possible to expose to different PBR BRDF models that are written into the engine to the material editor, so that materials can select them per-material? I'm looking inside BRDF.usf right now in the engine source, and multiple models are there. I assume that we can simply write our own models in here and change the #define PHYSICS_### flags to use that shader when we compile? Is that feasible?

    I'm looking into ways to make the renderer much more flexible. Our options are extremely locked down at the moment. This would also be a great way to bypass the current issues with foliage shading, which are forcing us to use very expensive SSS methods.
    No this cannot be exposed to the Material Editor as the BRDF functions are used during the deferred lighting stage, which is done in screen space regardless of the material type. The only thing the material can do is provide inputs into these functions such as Roughness. You can certainly define your own BRDF functions, but then you have to change the one currently in effect. Which means you would not be able to use it just for foliage.

    What you could do if you are willing to put in the effort is define a new Lighting ID for say Foliage, and expose that to the Material Editor (In the same manner as Subsurface and Preintegrated Skin shading is done). Then providing the necessary code in the DeferredLightingCommon.usf to perform your custom dynamic lighting. I originally did this for my hair rendering before I moved away from the deferred renderer, so I do know how to set that up if you want to travel down that path.
    FluidSurface Plugin: https://github.com/Ehamloptiran/UnrealEngine/releases
    TextureMovie Plugin: https://github.com/Ehamloptiran/TextureMoviePlugin

    Comment


      #3
      I did originally look at that idea so I'd be eager to hear more It's a shame you can't change the models, some for example are much better at simulating hard/glossy surfaces than others (e.g. Oren-Nayar vs Cook-Torrence).

      I was hunting for the information about creating custom Lighting ID's but didn't get very far, feel free to share anything you may know about them that could help Even at that stage, is it still impossible to change the BRDF model for that material only? For example, having Translucent Surfaces that use Cook-Torrence, and Pre-Integrated skin using Oren-Nayar. (Just for the sake of example).

      Also, you say you've moved away from the deferred renderer which I'm assuming means you've worked on the forward renderer a little? Do you have things like Light Vectors and custom lighting models working? My project isn't going to be flooded with dynamic lights and reflections, so maybe a switch would benefit this project too.

      Comment


        #4
        Originally posted by TheJamsh View Post
        I did originally look at that idea so I'd be eager to hear more It's a shame you can't change the models, some for example are much better at simulating hard/glossy surfaces than others (e.g. Oren-Nayar vs Cook-Torrence).
        I'll put something together over the weekend for you to take a look through, i still have the deferred code I was using, just not using it anymore.

        Originally posted by TheJamsh View Post
        I was hunting for the information about creating custom Lighting ID's but didn't get very far, feel free to share anything you may know about them that could help Even at that stage, is it still impossible to change the BRDF model for that material only? For example, having Translucent Surfaces that use Cook-Torrence, and Pre-Integrated skin using Oren-Nayar. (Just for the sake of example).
        Yeah you dont set the BRDF model for a material only, the BRDF is dependent on the lighting model, You wouldn't have Pre-Integrated skin using Oren-Nayar for example, you would have a new lighting model called Pre-Integrated Skin Oren-Nayar (Or some other fancy name) that would apply Oren-Nayar to that lighting model and you would use that in place of your Pre-Integrated Skin lighting model. Then in the deferred shading shader, you would check for your new lighting model and then light that section with Oren-Nayar. But you have to be careful with how many lighting ID's you might want to add, since it is just a float that is encoded between 0.f-1.f, and its just a simple (LightingID / 4.f) at the moment (4 being the max lighting ID) so you could effectively have 10, but this also adds to the complexity of the deferred shader.

        This is what I have found during my investigations, if anyone from Epic or otherwise wants to speak up and check that my understanding is correct, that would be great.

        Originally posted by TheJamsh View Post
        Also, you say you've moved away from the deferred renderer which I'm assuming means you've worked on the forward renderer a little? Do you have things like Light Vectors and custom lighting models working? My project isn't going to be flooded with dynamic lights and reflections, so maybe a switch would benefit this project too.
        Well I render in the translucency stage now as I needed alpha. So yeah I have implemented a kind of forward renderer for the hair, it only takes into consideration the primary directional light source and then composites the final color in the scene texture, due to this I will have to limit the number of dynamic lights that can influence the hair (Im thinking 1 directional light + The 4 closest point/spot lights). But it does use a custom lighting model. The hair is lit using the kajiya model with dual highlights. But as of right now its completely hardcoded for only the hair mesh and its still in the deferred renderer itself, just in the translucency stage.
        FluidSurface Plugin: https://github.com/Ehamloptiran/UnrealEngine/releases
        TextureMovie Plugin: https://github.com/Ehamloptiran/TextureMoviePlugin

        Comment


          #5
          Awesome information, the trickiest part is figuring out what sits where, which files to look in etc. Being new to C++ and programming in general makes it slightly harder but I can piece together what's happening with basic knowledge.

          But yeah, would be great to see some more detail on this kind of thing. Epic's Trello road-map does have a Parallel rendering implementation at the highest priority right now but I just want to see the rendered becoming much more flexible.

          Comment


            #6
            So as promised here is a quick rundown of adding a new lighting model ID. In the code below, the new lighting model ID will be called Foliage

            ====================================================================================================================================
            DeferredShadingCommon.usf

            [Line 128] or [Line 253 in v4.2]
            This is where you define new lighting models. Make sure to update the MAX any time you add a new one

            Code:
            #define LIGHTINGMODELID_FOLIAGE 4
            #define LIGHTINDMODELID_NUM 5
            [Line 212] or [Line 340 in v4.2]
            This line encodes the lighting model ID into the range of 0.f - 1.f for storing in the GBuffer

            Code:
            OutGBufferA.a = Data.LightingModelId / ( (float) LIGHTINGMODELID_NUM - 1.f );
            [Line 247] or [Line 374 in v4.2]
            This function decodes the lighting model ID from the GBuffer

            Code:
            int DecodeLightingModelId( float4 InGBufferA )
            {
            	return (int) ( InGBufferA.a * ( (float) LIGHTINGMODELID_NUM - 0.001f ) );
            }
            ====================================================================================================================================
            Engine\Source\Runtime\Engine\Classes\Engine\EngineTypes.h

            [Line 109]
            Engine side definition of the Material Lighting Model. This allows it to be selectable in the Material Editor

            Code:
            MLM_Foliage UMETA( DisplayName = "Foliage" ),
            MLM_MAX
            ====================================================================================================================================
            Engine\Source\Runtime\Engine\Private\Materials\MaterialShared.cpp

            [Line 1131] or [Line 1146 in v4.2]
            Ensure that the shader compiler sets our new custom lighting model if selected

            Code:
            case MLM_Foliage: OutEnvironment.SetDefine( TEXT( "MATERIAL_LIGHTINGMODEL_FOLIAGE" ), TEXT( "1" ) ); break;
            default:
            ====================================================================================================================================
            BasePassPixelShader.usf

            [Line 711] or [Line 731 in v4.2]
            Set the Lighting Model ID based on the Material Lighting Model selected

            Code:
            #elif MATERIAL_LIGHTINGMODEL_FOLIAGE
               Data.LightingModelId = LIGHTINGMODELID_FOLIAGE;
            #else
            ====================================================================================================================================
            DeferredLightingCommon.usf

            [Line 262] or [Line 353 in v4.2]

            GetDynamicLighting
            This function is in charge of calculating lighting for a given position, normal, etc. and this is where you would
            calculate your new lighting based on the LightingModelId

            ====================================================================================================================================

            Click image for larger version

Name:	FoliageLighting01.jpg
Views:	1
Size:	33.6 KB
ID:	1051136
            You should see a new option in the material editor for your new lighting model

            Click image for larger version

Name:	FoliageLighting02.jpg
Views:	1
Size:	77.1 KB
ID:	1051137
            Click image for larger version

Name:	FoliageLighting03.jpg
Views:	1
Size:	68.4 KB
ID:	1051138
            To ensure your new lighting model ID is being applied, you can use the Lighting Model buffer visualization. Your new lighting model will be white. If you plan on having addition lighting models, you will need to update MaterialTemplate.usf at Line 797 to include new colors to be able to differentiate between the different models (Otherwise they will all appear white)

            Click image for larger version

Name:	FoliageLighting04.jpg
Views:	1
Size:	170.9 KB
ID:	1051139
            Here is an example of applying Oren-Nayar diffuse to the new lighting model, compared to the existing Default Lit lighting model
            Last edited by Ehamloptiran; 06-08-2014, 05:04 AM. Reason: Added line numbers for v4.2 as per insides post
            FluidSurface Plugin: https://github.com/Ehamloptiran/UnrealEngine/releases
            TextureMovie Plugin: https://github.com/Ehamloptiran/TextureMoviePlugin

            Comment


              #7
              Originally posted by Ehamloptiran View Post
              [ATTACH=CONFIG]4735[/ATTACH]
              Here is an example of applying Oren-Nayar diffuse to the new lighting model, compared to the existing Default Lit lighting model
              Wow!

              I really like your end result Ehamloptiran!

              Any chance of Oren_Nayar diffuse plugin/github/anything ? It looks very good

              Great work!

              Rama
              100+ UE4 C++ Tutorials on the UE4 Code Wiki, including UE4 Multi-Threading!

              UE4 Marketplace: Melee Weapon Plugin & Compressed Binary Save System Plugin | Rama's C++ AI Jumping Videos | Vertex Snap Editor Plugin

              Visit www.ue4code.com to see lots of videos about my C++ Creations! ♥ Rama

              Comment


                #8
                Originally posted by Rama View Post
                Wow!

                I really like your end result Ehamloptiran!
                I cannot take any credit for the Oren Nayar lighting, the code is already present in the shaders. All I did was use it in a custom lighting model. All credit to Epic.

                Originally posted by Rama View Post
                Any chance of Oren_Nayar diffuse plugin/github/anything ? It looks very good

                Great work!

                Rama
                I can github the above changes as they are required in the engine code, but for now the above will do as I am looking into a way to possibly expose the ability to create custom lighting models in the editor, creating a new material function (like a light function) that you would assign an ID that could be selected in your material which would change the way it is lit during the deferred shading pass. This will require a fair amount of tinkering and the end result will not be able to be a plugin. I will upload the source to github so it can just be dropped in and compiled once I am done. (This may be a fair while away though as I have a number of other projects to complete prior).
                FluidSurface Plugin: https://github.com/Ehamloptiran/UnrealEngine/releases
                TextureMovie Plugin: https://github.com/Ehamloptiran/TextureMoviePlugin

                Comment


                  #9
                  Originally posted by Rama View Post
                  Wow!

                  I really like your end result Ehamloptiran!

                  Any chance of Oren_Nayar diffuse plugin/github/anything ? It looks very good

                  Great work!

                  Rama
                  You just need to change single #define in BRDF.usf
                  It's hard to miss:

                  Code:
                  // Diffuse model
                  // 0: Lambert
                  // 1: Burley
                  // 2: Oren-Nayar
                  #define PHYSICAL_DIFFUSE	2
                  The you just start your game, and wait till all shaders recompile.
                  https://github.com/iniside/ActionRPGGame - Action RPG Starter kit. Work in Progress. You can use it in whatever way you wish.

                  Comment


                    #10
                    Originally posted by iniside View Post
                    You just need to change single #define in BRDF.usf
                    It's hard to miss:

                    Code:
                    // Diffuse model
                    // 0: Lambert
                    // 1: Burley
                    // 2: Oren-Nayar
                    #define PHYSICAL_DIFFUSE	2
                    The you just start your game, and wait till all shaders recompile.
                    Except that changes it for all materials. (If that doesn't matter, then yes that is the preferred method). Where as the above code allows you to only change it for certain materials.
                    FluidSurface Plugin: https://github.com/Ehamloptiran/UnrealEngine/releases
                    TextureMovie Plugin: https://github.com/Ehamloptiran/TextureMoviePlugin

                    Comment


                      #11
                      In any case thanks for tutorial! Un 4.2 version the line numbers are bit different in shader files though, so if anyone else wondering:

                      DeferredShadingCommon.usf
                      It start from line 253.

                      BasePassPixelShader.usf
                      Line 723

                      DeferredLightingCommon.usf
                      Line 353.

                      Could you also post code that you added in GetDynamicLighting function ?
                      I looked at it, and honestly I started doubting myself after seeing all those #if #endif BRANCH defines.
                      https://github.com/iniside/ActionRPGGame - Action RPG Starter kit. Work in Progress. You can use it in whatever way you wish.

                      Comment


                        #12
                        Originally posted by iniside View Post
                        In any case thanks for tutorial! Un 4.2 version the line numbers are bit different in shader files though, so if anyone else wondering:

                        DeferredShadingCommon.usf
                        It start from line 253.

                        BasePassPixelShader.usf
                        Line 723

                        DeferredLightingCommon.usf
                        Line 353.

                        Could you also post code that you added in GetDynamicLighting function ?
                        I looked at it, and honestly I started doubting myself after seeing all those #if #endif BRANCH defines.
                        Thanks for listing those numbers. I am using v4.1.1 still. I have updated the original post to include them.

                        Okay first I just duplicated the PointLightDiffuse function and changed it to use Oren Nayar as such:

                        Code:
                        float3 PointLightDiffuseOrenNayar( FScreenSpaceData ScreenSpaceData, float3 VectorToLight, float3 V, half3 N )
                        {
                        	FGBufferData InGBufferData = ScreenSpaceData.GBuffer;
                        
                        	float3 L = normalize( VectorToLight );
                        
                        	float3 H = normalize(V + L);
                        	float NoL = saturate( dot(N, L) );
                        	float NoV = saturate( dot(N, V) );
                        	float VoH = saturate( dot(V, H) );
                        	
                        	return Diffuse_OrenNayar( InGBufferData.DiffuseColor, InGBufferData.Roughness, NoV, NoL, VoH );
                        }
                        Then in the GetDynamicLighting function where it calculates the DiffuseLighting variable I changed it from:

                        Code:
                        float3 DiffuseLighting = PointLightDiffuse( ScreenSpaceData, L, -CameraVector, N );
                        to

                        Code:
                        float3 DiffuseLighting = float3( 0.f, 0.f, 0.f );
                        if( LightingModelId == LIGHTINGMODELID_FOLIAGE )
                        {
                        	DiffuseLighting = PointLightDiffuseOrenNayar( ScreenSpaceData, L, -CameraVector, N );
                        }
                        else
                        {
                        	DiffuseLighting = PointLightDiffuse( ScreenSpaceData, L, -CameraVector, N );
                        }
                        And thats it. Remember this was just a quick solution to show a different lighting model, there are better ways to do the lighting calculations.
                        Last edited by Ehamloptiran; 06-08-2014, 05:04 AM.
                        FluidSurface Plugin: https://github.com/Ehamloptiran/UnrealEngine/releases
                        TextureMovie Plugin: https://github.com/Ehamloptiran/TextureMoviePlugin

                        Comment


                          #13
                          Ok thank you very much this!

                          I just want to tinker around bit, and yours solution is given perfect starting point to get something going (;.
                          https://github.com/iniside/ActionRPGGame - Action RPG Starter kit. Work in Progress. You can use it in whatever way you wish.

                          Comment


                            #14
                            You my friend... are my new favourite person

                            Comment


                              #15
                              Have you guys had any luck implementing this in 4.4? The code files have changes considerably with the advent of the new Shading Models. I'm trying to add a custom Minnaert BRDF model for a custom shader called 'Moon', but there's no more 'Diffuse Lighting' function to switch out the shader model.

                              Comment

                              Working...
                              X