Home Technical Talk

Physically based rendering in games

13567

Replies

  • James Ordner
    Drew++ wrote: »
    Nope! In Physically based rendering, most metallic materials should have a pure black diffuse. Literally the brightness and color of your reflection is defined by what we call "substance" or "specular map"; This is called "energy conserving". You can see it at the very beginning of my video. When I darken the specular color, it shows more diffuse. :)

    All physically based shading must not work the same way then, because it works a little differently in UE4. I'm afraid to say more though because of NDA.
  • marks
    Offline / Send Message
    marks greentooth
    Yeah, works differently in our inhouse PB shading too.
  • JordanW
    Offline / Send Message
    JordanW polycounter lvl 19
    Yeah workflow/input can change on different implementations of PBR. PBR is a fuzzy word for saying the rendering using more correct algorithms to closely match the physical world. And in some cases building functionality into those algorithms that doesn't allow for unrealistic materials. For example it's now common to have energy conserving highlights, this means as roughness increases the highlight dims, this is because the same amount of energy is reflected. A smaller highlight is brighter because the same amount of energy is reflected in a smaller area. Another example is all specular/reflection responses should have fresnel built in. Most non-metallic surfaces are only something like 2-10% reflective at facing angles and are 100% reflective on grazing angles.
  • Drew++
    Offline / Send Message
    Drew++ polycounter lvl 14
    JordanW wrote: »
    Yeah workflow/input can change on different implementations of PBR. PBR is a fuzzy word for saying the rendering using more correct algorithms to closely match the physical world. And in some cases building functionality into those algorithms that doesn't allow for unrealistic materials. For example it's now common to have energy conserving highlights, this means as roughness increases the highlight dims, this is because the same amount of energy is reflected. A smaller highlight is brighter because the same amount of energy is reflected in a smaller area. Another example is all specular/reflection responses should have fresnel built in. Most non-metallic surfaces are only something like 2-10% reflective at facing angles and are 100% reflective on grazing angles.

    Well put, amigo! These last few pages could almost be broken in off into a "physically based shading" thread of it's own. xD Maybe when I or someone else releases a shader it could happen.
  • marks
    Offline / Send Message
    marks greentooth
    There are already PB viewport shaders publically available. Aside from experimentation though it's unlikely to become a widespread talking point/adopted practice amongst non-pro work until a PBS/PBL engine becomes freely available (Yes, I'm looking at you UDK and CE).

    On a slightly different tangent, 10% reflectance sounds kinda high to me for a dielectric material, the numbers getting quoted around here top out at around 3-4%. I'd be interested to see where other people are getting their real-world reference data from. Beyond the MERL100 I've found it actually pretty difficult to find sources of reliable data online.
  • iniside
    Offline / Send Message
    iniside polycounter lvl 6
    The problem with real-world measruments, is that every engine take diffrent range of values.
    Some materiasl have real world reflectance of 5%. Ok. How about setting it in range from 0-100 0-1 or 0-255 ? What does it even mean for and engine implementation ? Even worse case you can't setup it directly, but you have to paint it on texture.

    I personally just ended up eye-balling materials. I just look for most neutral reference I can find, and try to replicate it in neutral lighting in engine.

    As it was said before, I think it's less about getting realistic values, and more about getting consistent look in diffrent lighting conditions.
  • osman
    Offline / Send Message
    osman polycounter lvl 18
    I'm really fascinated reading all of you guys talking about these fancy new things, but I have to say I really hope we prevent these super realistic sterile boring looking environments. I know I know that it the end it's all about the art direction and art team, but I hope the tools/techniques compliment THEM, and not the goal for nearly 100% correct lighting/shading. In the end, pushing for that little bit of realism in your shading won't make that much of a difference if the end-users screen sucks or some other silly reason.
  • almighty_gir
    Offline / Send Message
    almighty_gir ngon master
    osman wrote: »
    I'm really fascinated reading all of you guys talking about these fancy new things, but I have to say I really hope we prevent these super realistic sterile boring looking environments. I know I know that it the end it's all about the art direction and art team, but I hope the tools/techniques compliment THEM, and not the goal for nearly 100% correct lighting/shading. In the end, pushing for that little bit of realism in your shading won't make that much of a difference if the end-users screen sucks or some other silly reason.

    title.jpg
  • osman
    Offline / Send Message
    osman polycounter lvl 18
    Hah, not saying we shouldn't strive for that quality, just saying that I'd be interested in talking about other aspects of unreal engine 4 as well, since this is the UE4 thread right? There's so much more in it that I want to know about, that's all.
  • iniside
    Offline / Send Message
    iniside polycounter lvl 6
    We are under NDA, we can't talk about anything else that wasn't yet unveiled by Epic. And Material Layers and PBR are thing unveiled.
  • marks
    Offline / Send Message
    marks greentooth
    iniside wrote: »
    We are under NDA, we can't talk about anything else that wasn't yet unveiled by Epic. And Material Layers and PBR are thing unveiled.

    This. Although the PBR topic probably warrants its own thread in fairness.
  • /anty/
    Offline / Send Message
    /anty/ polycounter lvl 7
    osman
    PBR is not just about some realism, this realism is totally dependent from your artistic ideas ( Disney's Wreck-It Ralph for instance), this more in some cases about consistency, how consistent spec across all surfaces, how all objects react on environment, how they fit to the scene in every place. All this old school - tweak a bit here and there - comes from inconsistency of surface behavior. This doesn't mean that system is forcing you to be less creative, instead gives you more power.
    You could setup even now similar materials system for UDK which will bring you similar logic of consistent behavior of surfaces, with your own vision of physical behavior of materials.

    What Epic's gave to artists with UE's layer system is insane ability to make more procedural artistic side of production, you can do more with less controls, it should be way simpler to combine different shaders with some additional functions like adding snow by Z vector or making surfaces wet below specific hight, or make them changeable with the time, and thanks to PBR there will be no problems to make all these sub elements behave exact same way across any part of the game.
    Next gen is not about more polygons or more shader instructions, it more in changing approach from current crafting method to wise way of production, with higher quantity and quality content with smaller dev teams, in more predictable time, with simpler iterating of content and ability modify lots of things fast and simple
  • osman
    Offline / Send Message
    osman polycounter lvl 18
    Anty, don't worry I get that, my first post in this thread is pretty much what you said :).

    I think I'm misunderstood in my last post, all I was saying is that while I'm very interested in PBR and all I'd much rather focus on the broader scope of UE4 and 'next-gen' and not go into microscopic detail on PBR. But as some quickly pointed out, many people are under NDA so I guess that's all we can talk about for now.

    Also, once we're done here with KZ:SF I'll be allowed to explain why I personally do not care about the last 2% quality in the PBR.
  • BlvdNights
    Offline / Send Message
    BlvdNights polycounter lvl 8
    PBR is here to stay. Doesnt mean old techniques are going away. Just new ways of looking at creating environments and tools to incorporate and blend with others to make more visually stunning work.
  • osman
    Offline / Send Message
    osman polycounter lvl 18
    Yeah and I find it actually much easier and more fun to work with.
  • BlvdNights
    Offline / Send Message
    BlvdNights polycounter lvl 8
    osman wrote: »
    Yeah and I find it actually much easier and more fun to work with.

    Ditto and a lot less ground work needs to be made to get the base look of the material right first.
  • artquest
    Offline / Send Message
    artquest polycounter lvl 14
    All physically based shading must not work the same way then, because it works a little differently in UE4. I'm afraid to say more though because of NDA.

    A shot in the dark here: Behind the scenes things **might be** running roughly the same. It's just a matter of how the engine is setup to handle the input. I have a feeling that in UE4 the diffuse color is is being shifted into being used as the reflectence color and the metallic slider is moving the diffuse color closer to black the more it's activated.
  • EarthQuake
    I've pulled some comments out of the UE4 thread and merged them with this PBR thread.
  • passerby
    Offline / Send Message
    passerby polycounter lvl 12
    good job, does anyone know of any engines, that will allow me to play with this stuff now. kodde has a cgfx maya shader for it, but not seen many engines that i can get a hold of that support pbr
  • James Ordner
    passerby wrote: »
    good job, does anyone know of any engines, that will allow me to play with this stuff now. kodde has a cgfx maya shader for it, but not seen many engines that i can get a hold of that support pbr

    Someone wrote a custom shader for UDK using PBL here. From what I remember from using it though, it doesn't support lightmap baking - for example, if you had a single dominant directional light and relied on lightmass for your skylight and indirect lighting, your model would be completely black on the shadowed side.
  • passerby
    Offline / Send Message
    passerby polycounter lvl 12
    Someone wrote a custom shader for UDK using PBL here. From what I remember from using it though, it doesn't support lightmap baking - for example, if you had a single dominant directional light and relied on lightmass for your skylight and indirect lighting, your model would be completely black on the shadowed side.

    i prolly have to also bring my cubemaps to PS and blur on the mipmap levels too
  • almighty_gir
    Offline / Send Message
    almighty_gir ngon master
    to simulate the mipmap blur for the time being, couldn't you just have two cubemaps, one at 1k, and one at 128 res, and lerp between them?
  • Santewi
    to simulate the mipmap blur for the time being, couldn't you just have two cubemaps, one at 1k, and one at 128 res, and lerp between them?

    Yes you could, but it doesn't look good because the details in the high-res cube remain very visible.
  • marks
    Offline / Send Message
    marks greentooth
    FYI here are the links to slides/course notes from SIGGRAPH physically based shading course

    2012: http://blog.selfshadow.com/publications/s2012-shading-course/
    2013: http://blog.selfshadow.com/publications/s2013-shading-course/
  • CrazyButcher
    Offline / Send Message
    CrazyButcher polycounter lvl 20
    for cubemap mipmap blur use something like https://code.google.com/p/cubemapgen/ cause you will need to blur properly across the cubefaces
  • almighty_gir
    Offline / Send Message
    almighty_gir ngon master
    just came across this gem on the interwebs:
    http://graphicrants.blogspot.co.uk/2013/08/specular-brdf-reference.html

    saving it to my HDD :D

    just out of curiosity, what is the term "m" used to describe? for example part of the code is:
    (n.m)
    

    i know it's n dot "something", just don't know what the m is.
  • mAlkAv!An
    Offline / Send Message
    mAlkAv!An polycounter lvl 5
    microsurface normals
    have a read trough this for example (3. microfacet theory)
    http://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.pdf
  • almighty_gir
    Offline / Send Message
    almighty_gir ngon master
    cool, got it.

    in extreme simplified terms then,
    m = half dot(v,l)
    
    ?
  • Drew++
    Offline / Send Message
    Drew++ polycounter lvl 14
    just out of curiosity, what is the term "m" used to describe? for example part of the code is:

    in most of these cases m simply = ( L + V )

    e: which is kind of confusing in shader code, since we define our roughness as "m" :V
  • almighty_gir
    Offline / Send Message
    almighty_gir ngon master
    you'd need to normalize that result right? so in code it's:
    float3 m = normalize(L+V)
    

    right?
  • almighty_gir
    Offline / Send Message
    almighty_gir ngon master
    hahaha okay, so i've tried, and failed horribly, to recreate the stuff in that artical, in unity.

    here's the stuff i wrote, and it doesn't work. i've indented the portion which breaks it.
    //Shader properties (that are visible to the user).
            Properties {
                                    _Maintex ("Diffuse", 2D) = "white" {}
                                    _Masktex ("range", Range(0.0,1.0)) = 0.0
                                    _Normal ("Normalmap", 2D) = "bump" {}
                                    _value ("value", Range(0.0,1.0)) = 0.0             
            		   }
           
           
            
            
            SubShader {
                    Tags { "RenderType"="Opaque" }
                    LOD 200
                   
                    CGPROGRAM
                    #pragma surface surf CustomBDRF        
                    #include "UnityCG.cginc"
                    #pragma target 3.0
                   
                    //Calling in various things to use later on. sampler2D are textures, floats are 8 bit numbers (a number with 8 digits), float2 is two 8 bit numbers etc. 
                    sampler2D _Maintex;
                    float _Masktex;
                    sampler2D _Normal;
                    //lightDir and viewDir are float3 because they have 3 directions to calculate: x,y, and z. each of those is an 8bit number, totalling 3 floats. 
                    float3 lightDir;
                    float3 viewDir;
                    float f0;
                    float _value;
                    
                    const float PI = 3.1415927;              
                    
    //here's what we're trying to reproduce:
    //f(l,v) = (D(h)F(v,h)G(l,v,h))/4(n.l)(n.v)
    //referenced here: http://graphicrants.blogspot.co.uk/2013/08/specular-brdf-reference.html          
                    
                             
                    
                    //our final lighting calculation is done here.
                    fixed4 LightingCustomBDRF(SurfaceOutput s, float3 viewDir, float3 lightDir, float _Masktex)
                    {
                   			//precalculating a bunch of values we can use later on without having to redo calculations.
                   			//roughness value
                   			float a1 = lerp(0.0,1.0,_Masktex);
                   			
                   			//roughness squared
                   			float a2 = a1*a1;
                   			
                   			//metalness value
                   			float mtl = lerp(0.0,1.0,_Masktex);
                   			
                   			//dot product of normal and light direction
                   			float ndotl = dot(s.Normal,lightDir);
                    
                    		//dot product of normal and view direction
    		                float ndotv = dot(s.Normal,viewDir);
    		                
    		                //microfacet direction.
    		                float3 m = normalize(lightDir + viewDir);
    		                
    		                //half angle vector
    		                half3 h = normalize(lightDir + viewDir);
    		                
    		                //dot product of view direction and half angle vector
    		                float vdoth = dot(viewDir,h);
    		                
    		                //dot product of normal and microfacet direction
    		                float ndotm = dot(s.Normal,m);               
    		                
    		                //remapping k
    		                float k = a2/2;	
    						          		
    						          		
    										//calculating Trowbridge-Reitz GGX for Specular Distribution
    						          		float GGX = (a2*a2)/(PI*pow(((ndotm*ndotm)*((a2*a2)-1)+1),2));
    						                
    						                //calculating schlick approximation of smith geometric shadowing
    						                float SGGX = ndotv/((ndotv)*(1-k)+k);
    						                
    						                //calculating schlick fresnel
    						                float F = f0 + (1 - f0)*pow((1-vdoth),5);
    						                
    						                //final calculation
    						                float pbr = (GGX*F*SGGX)/(4*ndotl*ndotv);              		            
    		                      
    		                //lambertian diffuse
    		                half diff = saturate (dot(s.Normal,lightDir)) * _LightColor0.rgb;                 
    		 
    		                half4 c;
    		                c.rgb = (s.Albedo * pbr * _LightColor0.rgb * diff);
    		                c.a = s.Alpha;
    		                return c;
                    }      
                                   
                   
                    struct Input { 
                   
                    float2 uv_Maintex;
                    float2 uv_Masktex;
                    float2 uv_Normal;
                    float3 viewDir;
                    float _value;        
                           
                    };             
                    void surf (Input IN, inout SurfaceOutput o) {
                            half4 tex = tex2D (_Maintex, IN.uv_Maintex);
                            half4 n = tex2D (_Normal, IN.uv_Normal);                                       
                            o.Albedo = tex.rgb * _value;
                            o.Normal = n.rgb;
                    }
                    ENDCG
            }
    }
    

    i think i figured out where i fucked up, trying to fix it now :D
  • e-freak
    Nicolas Schulz, one of our rendering engineers, wrote this feature on PBR for Making Games magazine. See if you can get a hold of it - I hope they will release the full article online as well at some point :)

    735454_517369568332172_852460688_o.jpg
  • almighty_gir
    Offline / Send Message
    almighty_gir ngon master
    work in progress stuff, but it's starting to come together!
    //physical based lighting shader test
    Shader "Custom/PBR_test" {
    
    //Shader properties (that are visible to the user).
            Properties {
                                    _Maintex ("Diffuse", 2D) = "white" {}
                                    _Masktex ("Masks", 2D) = "white" {}
                                    _Normal ("Normalmap", 2D) = "bump" {}
                                    _Cube ("Equirectangular cube", 2D) = "white" {}             
            		   }
           
           
            
            
            SubShader {
                    Tags { "RenderType"="Opaque" }
                    LOD 200
                   
                    CGPROGRAM
                    #pragma surface surf CustomBDRF        
                    #include "UnityCG.cginc"
                    #pragma target 3.0
                   
                    //Calling in various things to use later on. sampler2D are textures, floats are 8 bit numbers (a number with 8 digits), float2 is two 8 bit numbers etc. 
                    sampler2D _Maintex;
                    sampler2D _Masktex;
                    sampler2D _Normal;
                    sampler2D _Cube;
                    //lightDir and viewDir are float3 because they have 3 directions to calculate: x,y, and z. each of those is an 8bit number, totalling 3 floats. 
                    float3 lightDir;
                    float3 viewDir;
                    float _value; 
                    
                    const float pi = 3.1415927;           
                    
    //here's what we're trying to reproduce:
    //f(l,v) = (D(h)F(v,h)G(l,v,h))/4(n.l)(n.v)
    //referenced here: http://graphicrants.blogspot.co.uk/2013/08/specular-brdf-reference.html          
                    struct SurfaceOutputCustom
    
    				{
    					
    					    fixed3 Albedo;
    					
    					    fixed3 Normal;
    					
    					    fixed3 Emission;
    					
    					    half Specular;
    					
    					    fixed Gloss;
    					
    					    fixed Alpha;
    					
    					 
    					
    					    fixed3 Mask;
    					
    				};
                             
                    
                    //our final lighting calculation is done here.
                    fixed4 LightingCustomBDRF(SurfaceOutputCustom s, float3 viewDir, float3 lightDir, float3 _Masktex)
                    {
                   			//precalculating a bunch of values we can use later on without having to redo calculations.
                   			//roughness value
                   			float a1 = lerp(0.01,1.0,s.Mask.r);
                   			
                   			//roughness squared
                   			float a2 = a1*a1;
                   			
                   			//metalness value
                   			float mtl = lerp(0.0,1.0,s.Mask.g); 
                   			
                   			//specular intensity mask
                   			float intensity = s.Mask.b;
                   			
                   			//dot product of normal and light direction
                   			float ndotl = dot(s.Normal,lightDir);
                    
                    		//dot product of normal and view direction
    		                float ndotv = dot(s.Normal,viewDir);		                
    		                               
    		                //half angle vector
    		                float3 h = normalize(lightDir + viewDir);
    		                
    		                //dot product of view direction and half angle vector
    		                float vdoth = dot(viewDir,h);
    		                
    		                //dot product of normal and microfacet direction
    		                float ndoth = dot(s.Normal,h); 
    		                
    		                
    		                
    		                //Geometric term
    		                float geo_b = (ndoth * ndotv) / vdoth;
    		                float geo_c = (ndoth * ndotl) / vdoth;
    		                float geo_t = min(1.0f,min(geo_b,geo_c));		                
    		                
    		                //Beckman roughness
    		                float roughness_a = 1.0f / (4.0f * a2 * pow (ndoth,4));
    		                float roughness_b = ndoth * ndoth -1.0f;
    		                float roughness_c = a2 * ndoth * ndoth;
    		                float roughness = roughness_a * exp(roughness_b/roughness_c);
    		                
    		                //Gaussian distribution, use for non skin		                
    		                //float alpha = acos(ndoth);
    		                //float gaussian = 1.0f * exp(-(alpha/a2));		                
    		                
    		                //Fresnel term
    		                float fresnel= pow(1.0f - saturate (vdoth), 5);
    		                
    		                //start pulling the terms together
    		                float3 rs_n = (fresnel * geo_t * roughness);
    		                float rs_d = ndotv * ndotl;
    		                float3 spec = rs_n/rs_d;
    		                
    		                
    		                //combine with albedo		                
    		                float3 diff = saturate( max(0.0f,ndotl) * _LightColor0.rgb);                 
    		 
    		                fixed4 c;
    		                //metalness calculation worked into final lighting.
    		                //if a surface is metallic (defined by mask) the albedo goes to black. 
    		                //if a surface is metallic (defined by mask) the specular is tinted by the albedo.
    		                c.rgb = ((s.Albedo * (1 - mtl) * _LightColor0.rgb) + (spec * s.Albedo * mtl) + spec * (1 - mtl)) * intensity;
    		                c.a = s.Alpha;
    		                return c;
                    }      
                                   
                   
                    struct Input { 
                   
                    float2 uv_Maintex;
                    float2 uv_Masktex;
                    float2 uv_Normal;
                    float2 uv_Cube;
                    float3 viewDir;
                    float _value;        
                           
                    };             
                    void surf (Input IN, inout SurfaceOutputCustom o) {
                            half4 c = tex2D (_Maintex, IN.uv_Maintex);
                            half4 n = tex2D (_Normal, IN.uv_Normal); 
                            half4 mask = tex2D (_Masktex, IN.uv_Masktex);                                      
                            o.Albedo = c.rgb;
                            o.Mask = mask.rgb;
                            o.Normal = n.rgb;
                    }
                    ENDCG
            }
            FallBack "Diffuse"
    }
    

    if anyone wants to have a play about, that's where i've gotten to so far.

    in the mask texture:
    r = roughness (black = very rough, white = very shiny)
    g = metalness (black = non metal, white = metal) < it's possible to use mid-tones, but it's better to stick to purely black or white.
    b = specular intensity < probably going to phase this out at some point over the next couple of days when...

    ...i need to put in cubemaps and energy conservation. those will be happening asap. and of course if anybody wants to help or contribute, feel free!
  • Jerc
    Offline / Send Message
    Jerc interpolator
    It's probably a good idea to keep the spec intensity. In some cases you may want to "help" a bit the PBR with some non-accurate specularity multiplier. Also, you shoud invert your roughness, most engines use white as rough and black as shiny.
    I'll test that guy as soon as I find some time to.
  • almighty_gir
    Offline / Send Message
    almighty_gir ngon master
    anybody got any idea why lighting (in unity) would work correctly when you're adjusting sliders/values/using photoshop, but as soon as you click inside the editor window it goes all messed up?
    http://i.imgur.com/0U6iQVF.png <--- correct lighting when not in the editor
    http://i.imgur.com/ICLPvqB.png <--- messed up lighting when in the editor
  • marks
    Offline / Send Message
    marks greentooth
    Jerc wrote: »
    It's probably a good idea to keep the spec intensity.

    /agree - because also different things reflect different amounts of light in the real world too. Probably can just be a scalar input though rather than a texture read.
    Jerc wrote: »
    Also, you shoud invert your roughness, most engines use white as rough and black as shiny.

    imo it's actually more intuitive to use a "Glossiness" term, with white being more glossy and black being more rough. That's the way artists have been authoring specular power textures for years. Obviously that gets inverted in your BRDF calcs for your roughness term.
  • iniside
    Offline / Send Message
    iniside polycounter lvl 6
    I'm not sure if that's more intuitive.
    Roughness:
    Black - 0 - zero roughness (Mirror surface).
    White - 1 - completly rough surface.
    It seems logical to me.
    IMO it's better to push that way, so artists who are coming from old pipeline will be forced to forgot all their old habits and learn new ones (As they will have anyway). It will be less prone to error and mistakes in future imo.
  • Money
    Offline / Send Message
    Money polycounter lvl 8
    Yeah, seems more intuitive to me that the higher the value goes the rougher the surface will be.
  • almighty_gir
    Offline / Send Message
    almighty_gir ngon master
    leaving specular intensity in is not really a problem, BUT from what i gather, once i've got the energy conserving part working, that becomes a bit of a non-issue anyway.

    until i can sort out the lighting issue in my post above, i'm at a bit of a stand-still, unfortunately.
  • EarthQuake
    iniside wrote: »
    I'm not sure if that's more intuitive.
    Roughness:
    Black - 0 - zero roughness (Mirror surface).
    White - 1 - completly rough surface.
    It seems logical to me.
    IMO it's better to push that way, so artists who are coming from old pipeline will be forced to forgot all their old habits and learn new ones (As they will have anyway). It will be less prone to error and mistakes in future imo.

    "Roughness" is not a new concept nor do artists need to forget everything they know to understand a PBR system. Glossiness has been in rendering apps for decades and has always been an approximation of surface roughness, and in the vast majority of cases black = rough and white = glossy.

    Switching them up just for the sake of switching it will not be any less prone to error, it will be more prone to error because people will assume that roughness works the same way as glossiness, as they are basically the same thing. The difference is in how it is rendered, ie: energy conservation that modulates the reflection intensity as well as the highlight size as apposed to simple glossiness parameters that only effect highlight size.

    This notion that PBR is so drastically different from what we have been doing and our puny artists brains can't possibly understand it so we have to forget everything we know and re-learn art, well, its just rather silly to be honest with you. If you have a decent grasp of traditional art theory you understand the relationship between surface roughness and specular reflection, in most cases transitioning over to a PBR system is very easy, and really just makes the job of the artist easier and more convenient as you will spend a lot less time tweaking shaders or painting lighting to fake certain effects. Especially if you've used a current generation Diffuse/Normals/Specular/Gloss workflow, much of that transfers over in a fairly logical manner.
  • iniside
    Offline / Send Message
    iniside polycounter lvl 6
    "Roughness" is not a new concept nor do artists need to forget everything they know to understand a PBR system. Glossiness has been in rendering apps for decades and has always been an approximation of surface roughness, and in the vast majority of cases black = rough and white = glossy.
    Yes. But you read roughness and think ok 0 = zero roughness 1 = full roughness. I don't see why you would even think otherwise, then name itself impiles what values it take in what ranges.
    This notion that PBR is so drastically different from what we have been doing and our puny artists brains can't possibly understand it so we have to forget everything we know and re-learn art, well, its just rather silly to be honest with you. If you have a decent grasp of traditional art theory you understand the relationship between surface roughness and specular reflection, in most cases transitioning over to a PBR system is very easy, and really just makes the job of the artist easier and more convenient as you will spend a lot less time tweaking shaders or painting lighting to fake certain effects. Especially if you've used a current generation Diffuse/Normals/Specular/Gloss workflow, much of that transfers over in a fairly logical manner.
    Well i probaly worded it badly.
    Yes PBR in general is more logical and easier, no doubt at it.
    But, they way people faked materials so far, will not work in PBR (or at least in some implmentations of it).
    For example Unreal does not take any RGB values except for color, normal and subsurface. So the way of faking surface with colored specular and baking everything into color map will simply not work here (or will give you unexpected results).
    Once you get around it seting up good looking materials is straight forward and very easy. Most of the times you don't even need textures except for normal map (and even that might not be needed, depending on where you intended to use material).
  • EarthQuake
    iniside wrote: »
    Yes. But you read roughness and think ok 0 = zero roughness 1 = full roughness. I don't see why you would even think otherwise, then name itself impiles what values it take in what ranges.

    Creating content based on... The name of the input? So now that we've arbitrarily changed the name of a gloss map to a roughness map (even though they do the same thing) we should flip the content as well?

    I think people get far too caught up in what the input names are, what you name your inputs, weather its glossiness/roughness, substance/specularity/base reflection, diffuse/color/albedo, or what have you, has very little relevance in physically accurate rendering. These are just names for inputs, thats it.
    Well i probaly worded it badly.
    Yes PBR in general is more logical and easier, no doubt at it.
    But, they way people faked materials so far, will not work in PBR (or at least in some implmentations of it).
    For example Unreal does not take any RGB values except for color, normal and subsurface. So the way of faking surface with colored specular and baking everything into color map will simply not work here (or will give you unexpected results).
    Sure, if you're jumping straight from mobile-spec full on (or even slightly higher spec but still with a lot of hand painted lighting) straight to a PBR workflow, its going to be more challenging. However, if you've used a current generation system that takes diffuse/normal/spec/gloss inputs, the concepts are extremely similar.
    Once you get around it seting up good looking materials is straight forward and very easy. Most of the times you don't even need textures except for normal map (and even that might not be needed, depending on where you intended to use material).
    Well, you still need texture maps for the various inputs to create any sort of variation, wear, or natural texture that a surface type will have. Not to mention any material that has multiple surface types.

    So, I think its important to sort of break down a physically based rendering system into various components.

    A. The rendering system. For the most part, the rendering system/shaders in PBL workflows will all be pretty similar (atleast from an artist perspective) as the goal is simply to render materials in the most physically accurate way. This will vary quite a bit on the technical side, depending on exactly how your lighting system is set up, how you do your diffuse/specular IBL convolutions, how you do your fresnel, and lots of other technical implementation things. How you generate your IBL cubemaps (if you pull them from the actual level content, how/where you generate them, how you blend them) can also vary a bit as well.

    Something most people probably do not know, but if you've used Marmoset Toolbag 1, you've used a game engine with a physically based rendering system. The image based lighting system that was developed back in 2007 or so (before PBR was really a buzz word) is very accurate from a PBR perspective. Though Toolbag 1 has some technical limitations, mainly limited range in cubemap blurriness (low gloss levels aren't great(seams) and the max gloss is limited to a fairly low cubemap resolution(so you can't get full on mirror reflections), as well as a sort of weird fresnel implimentation. All of this is much improved in TB2 however. Marmoset Skyshop is somewhere between Toolbag 1 and 2 in terms of technical sophistication.

    2. Art content management/art direction/accuracy of texture inputs. So, #1 is the first step, you need to have physically accurate rendering/shaders, but equally important is having art content that corresponds to realistic, accurate values for real world materials. #1 gives you the potential to create physically accurate materials, #1 + #2 gives you a physically accurate rendering system.

    3. Implementation. Implementation is going to vary to a large degree, including how you name your inputs, how you pack your inputs (full color spec to define base reflection + gloss vs 8bit inputs for each packed in a multi map, for instance). Some PBR shaders have a metalness input, though this is not a requirement to have a PBR system. Metalness is really just a way to pull specular color from the diffuse map (and possibly do some other things like specific fresnel settings, or darkening the diffuse content). Now, personally, I prefer full color spec input, simply because it gives me more control. You can do the exact same thing with a diffuse map, full color spec map, and gloss map that you can do with a metalness input, a grayscale spec and a gloss map, you just have to do it manually (ie: metalic areas in your spec map will have the appropriate color, and non-metalic areas will have gray spec). Going with 8bit spec over 24bit/full color is generally a good way to save memory, so this is common in a lot of implementations. You can also drop the base reflectance texture input all together, which it looks like they've done in UE4, though personally I like to have it for the extra control it gives when working with complex, multi-surface materials.

    Also sort of related: Gamma correct rendering. A big reason for having full color specular content previously was engines that were not Gamma corrected. This meant you often had to use the opposite of the diffuse color in your specular content to get a white highlight. If your engine has gamma correct rendering (and TB1 and TB2 do) the need to have those bright blue spec maps goes away for the most part, and you can get by with grayscale spec much more reliably.
  • almighty_gir
    Offline / Send Message
    almighty_gir ngon master
    prefacing statement: obviously each team/studio/engine will have it's own way of handling PBR. they will have their own stylistic choices and they will choose which way round they want certain variables to go.

    there's no problem with that.

    what i've learned, through trying to make this shader is that yes, there is a shift in thought that an artist needs to take. a lot of the values we used to plug in are now extremely over-saturated, and the biggest shift is going to be in specularity. you've used the term "fudging values" before EQ, and that's exactly what artists do currently... it's something that will (hopefully) be gone with this new system.

    i can also see art pipelines becoming extremely streamlined by this process. combining PBR material presets with tools like substance designer to generate the masks is going to give an incredibly consistent look across an entire game. this, in my opinion is going to have two effects:
    1. it allows artists to spend more time on actual artistic and creative things.
    2. hopefully bring budgets down, as dev time is more evenly spread over creative endeavors and less time is dedicated to trying to unify the look of a game.

    aaaanyway, progress time!
    i managed to fix the issue i was having in unity, but i'm still not entirely happy with the way unity handles certain things, so instead i rewrote the shader in UDK and here are the results!

    currently only have the roughness value working. roughness is clamped between 0.05 and 1, as any value lower than 0.05 leads to a weird "dead" spot in the highlight, and values over 1 lead to a strange halo.

    pics:
    glossy
    JLg7DAI.jpg


    rough
    fFM1eS7.jpg
  • EarthQuake
    i can also see art pipelines becoming extremely streamlined by this process. combining PBR material presets with tools like substance designer to generate the masks is going to give an incredibly consistent look across an entire game. this, in my opinion is going to have two effects:
    1. it allows artists to spend more time on actual artistic and creative things.
    2. hopefully bring budgets down, as dev time is more evenly spread over creative endeavors and less time is dedicated to trying to unify the look of a game.

    Yeah absolutely, that is one of the biggest benefits, standardizing the whole production process. dDo's preset reflectance values are a great example, which are tailor made to work well with Marmoset shaders (though disclaimer: I'm not sure if those are "measured" values or how the Quixel guys came up with them, I just know they generally look nice). So I use those a lot. =D
    JLg7DAI.jpg


    rough
    fFM1eS7.jpg
    Looking nice!
  • Ace-Angel
    Offline / Send Message
    Ace-Angel polycounter lvl 12
    Earthquake: Can I ask a question? If you guys are making a Gold material (something like a piece of conductive material that it's reflection hue/spec color is gold as well reflected back to the viewer), in a PBR setup, what would be the best way to go about it, what would be the most physically golden solution (pun intended) for this way?

    I know plenty of people use Strauss for the Metalness function, decrease the Diffuse term to lower value, and increase the tint given to the Spec/Refl. through a single parameter change.

    However, I was wonder if there is something more (or you peeps would do something different) in that regard? Would it be simpler to tint your Spec Map or use a Float3 and call it a day? Is Strauss wrong? Etc.
  • joeriv
    Offline / Send Message
    joeriv polycounter lvl 7
    Something I am curious about:
    When reading some articles it's clear that putting AO in your diffuse/spec is a no-go in PBR (but it can be added later on for ao for small details that engines can't do).
    And kodde's shader has a input for that.

    But is that something that gets done in the "upcoming" engines (cryengine 3.5/ue4/TB2/etc).
    I never seen it mentioned in relation to UE4, So what is happening with that in general + it leads me to wondering how certain "tricks" we use today such as not actually putting in a hole, but faking it in the normal map + black in the ao.
  • iniside
    Offline / Send Message
    iniside polycounter lvl 6
    Well, you still need texture maps for the various inputs to create any sort of variation, wear, or natural texture that a surface type will have. Not to mention any material that has multiple surface types.
    Well I've been talking from my perspective as I (to be honest), have hardly any other experience other than UE4 in that regard.
    Instead of painting entire map what you do is:
    1. Paint mask that define where what materials are going.
    2. Create simple materials, that covers exactly one case (steel, copper, plastic, paint etc).
    3. Assign materials based on mask.
    4. If you need more varation, you slap another masks on top of it. Either unique of tileable.

    The end result is usually very good, and it's much easier that way instead of going trough painting textures. No to mention you can add some variation on top of it by procedurally adjusting masks inside editor.

    I even managed to get quite nice Skin this way (masks for everything, no color map) (but I can't show it).

    In general it might not always look as good as unique textures (but Infiltrator demo was done using above workflow), but it's huge time saver.

    Can't really go into details, but we can discuss about materials since they showed it already to some degree.
    Creating content based on... The name of the input?
    Hm look at it this way.
    Glossines as the name impiles define how glossy the surface is. And it's logical to assume that 0 no gloss at all and 1 is mirror.
    Roughness define how rough surface is. 0 is not rough at all (mirror) and 1 it's completly rough.
    Yes it's pretty much means the same, it's opposite in values input. It's just matter of being consistent with naming and what the name impiles.
    When reading some articles it's clear that putting AO in your diffuse/spec is a no-go in PBR (but it can be added later on for ao for small details that engines can't do).
    No. Putting AO map in your color is fine. BUT. You should do it only for microdetails that can't be handled by engine (from normal map and geometry). Which is honestly rare case. You will be better of just blending another detailed color texture on top of your base color inside material (I like to do it for stucco plaster as in general normal map for stucco looks balnd regardless of how high res you get).
  • EarthQuake
    Ace-Angel wrote: »
    Earthquake: Can I ask a question? If you guys are making a Gold material (something like a piece of conductive material that it's reflection hue/spec color is gold as well reflected back to the viewer), in a PBR setup, what would be the best way to go about it, what would be the most physically golden solution (pun intended) for this way?

    I know plenty of people use Strauss for the Metalness function, decrease the Diffuse term to lower value, and increase the tint given to the Spec/Refl. through a single parameter change.

    However, I was wonder if there is something more (or you peeps would do something different) in that regard? Would it be simpler to tint your Spec Map or use a Float3 and call it a day? Is Strauss wrong? Etc.

    Ace: Sorry the specifics of the technical implementation are a little over my head, but here is a shot of the Gold preset we have, which was created by tinting the specular color with a measured value for gold, and by using a black diffuse (in this case not having a diffuse input at all in the material). These: https://twitter.com/marmosetco/status/365547872730611712/photo/1 were created in a similar manner.

    tb2gold.jpg

    Though I asked Jeff Russell (https://twitter.com/j3ffdr), one of our graphics programmers and he said strauss is similar to the shading model that we use for TB2.
  • EarthQuake
    iniside wrote: »
    Well I've been talking from my perspective as I (to be honest), have hardly any other experience other than UE4 in that regard.
    Instead of painting entire map what you do is:
    1. Paint mask that define where what materials are going.
    2. Create simple materials, that covers exactly one case (steel, copper, plastic, paint etc).
    3. Assign materials based on mask.
    4. If you need more varation, you slap another masks on top of it. Either unique of tileable.

    The end result is usually very good, and it's much easier that way instead of going trough painting textures. No to mention you can add some variation on top of it by procedurally adjusting masks inside editor.

    I even managed to get quite nice Skin this way (masks for everything, no color map) (but I can't show it).

    In general it might not always look as good as unique textures (but Infiltrator demo was done using above workflow), but it's huge time saver.

    Can't really go into details, but we can discuss about materials since they showed it already to some degree.

    Ok cool, that sounds really awesome. I don't have any experience with UE4 unfortunately.
    Hm look at it this way.
    Glossines as the name impiles define how glossy the surface is. And it's logical to assume that 0 no gloss at all and 1 is mirror.
    Roughness define how rough surface is. 0 is not rough at all (mirror) and 1 it's completly rough.
    Yes it's pretty much means the same, it's opposite in values input. It's just matter of being consistent with naming and what the name impiles.
    Sure, I get what you're saying. I guess I'm just ranting a bit, it seems like every PBR shader renames all of the inputs, just because. Which can be very confusing to less experienced artists. "You mean I have a roughness mask and a substance mask now? How do I make those?", when in reality its basically the same input types we've been using for years.
  • RogelioD
    Offline / Send Message
    RogelioD polycounter lvl 12
    EarthQuake wrote: »
    OSure, I get what you're saying. I guess I'm just ranting a bit, it seems like every PBR shader renames all of the inputs, just because. Which can be very confusing to less experienced artists. "You mean I have a roughness mask and a substance mask now? How do I make those?", when in reality its basically the same input types we've been using for years.

    I can attest to this. I have friends who are 3D artists who get extremely confused when names change like that. Granted, I think I may be a little more ambitious than most of my 3D Art friends, so jumping onto the PBR bandwagon early generally meant that I was open to change, knew what I was getting into, etc. But some of them kinda shrug it off as something too advanced to learn now when in reality it's not THAT much different than the current system. It's things like unnecessary name changes that make PBR confusing rather than make it encouraging to learn.

    Hope that made sense =P
13567
Sign In or Register to comment.