GGX model in material editor

Does anyone have UE4’s GGX model with nodes in the material editor? I found a nice blog for different shading models, but for some reason the blog’s version of GGX has weird artifacts when the light is rotated behind the model, and overall it doesn’t behave as well as UE4’s model does. I got lost trying to convert UE4’s GGX document to material nodes. Can someone help me out?

I have some related experience with this. In college I became fascinated with shading and implemented a Cook-Torrance BRDF within UDK’s material editor. A few years later I developed a mobile GGX ubershader for Unity as we were looking for getting much higher quality visuals in Unity 4 at work.

My first question is: What is your motivation for this? You wouldn’t want to waste your time on something so complex just trying to solve a problem, unless you’re doing this as a learning exercise which in that case by all means continue. Don’t take the following as discouraging, it merely attempts to convey the scope of your questions and anticipate your intentions and next questions.

If you’re just learning I would not recommend using the material editor in UE4. I almost hate to drop this on the UE forums, but Unity would be a much easier option as you don’t have to worry about tons of interrelated shader code like the UE4 source just to make your own shading model. You just make a new custom shader and can immediately start playing around with designing single forward pass shader. I recommend this because BRDF code has to be absolutely mathematically perfect or it’s a complete waste. Trying to both learn and fit your work into a very strict, predefined rendering pipeline at the same time is setting an extremely high bar. Being able to prototype with a single shader like with Unity is much more powerful (even if you do then translate that code to UE4 in the end!)

If doing GGX in the material editor is ultimately what you require then I have a number of tips: Do not try to convert UE4’s code from that document (I say this again in a second but I can’t stress enough: It’s old!) At the very least adapt it directly from their source code. But this is still faulty logic for us. A few reasons why are that they make many approximations in the UE4 code from the full proper GGX BRDF, there are more recent advancements from that now old presentation, and implementations always vary for nuanced reasons. You really need to be understanding the structure of a typical realtime BRDF. How the mathematical terms fit together and why they exist in the first place. Understanding the various whitepapers and learning the newest advancements is necessary. Also see how the same shaders are different from engine to engine. I’ll tell you now that Frostbite, Unity, and UE4 all have different implementations of GGX. All approximations, making different tradeoffs and choices for different reasons.

Here’s a good complex example that brings up just a portion of the BRDF. If you can’t tell why the Shadowing-Masking parameter in UE4 doesn’t exactly match the original GGX paper, or the correct method which actually came years later (http://jcgt.org/published/0003/02/03/), you couldn’t derive it for yourself. In other words, trying to create your own GGX implementation would be pointless without fully understanding how GGX works. The entire purpose is to try to correctly conserve energy, which necessitates this kind of full knowledge. You could easily end up making mistakes like double counting your light energy.

Again, I hope to not discourage any experimentation or learning. Just want to give you a place to start because it can be quite overwhelming at first. Look into the rendering equation and run from there :slight_smile: My first PBR shaders were terribly broken and I had no understanding of what they were doing. But I kept at it and eventually I got to the point that I developed a correctly energy conserving ubershader. No less on mobile Unity 4 it’s a gamma correct Lambert/Burley-Diffuse/SSS/Pre-integrated Skin (artist chooses which methods) + GGX specular multipass shader.

If you simply want to recreate a specular highlight on a translucent surface like that blog post does you can also make your life a lot easier. Just add a custom node and call the already defined functions from BRDF.usf to get exactly the same specular as a regular UE4 material.

you could just delve though the deferredshadingcommon.usf files and make custom node snipped out of the various functions there like GGX etc. it should be pretty easy to find and make them.

First of all, I like the material editor because it is very easy to use. I struggle with real code, visual scripting just makes a lot more sense with me. And the refactoring/optimization is fantastic! A lot of the stuff that would be insanely difficult to code by hand the material editor just handles perfectly. In most circumstances, having the shadow environment, GI, and reflection environment built-in to all the materials by default works beautifully, and I wouldn’t have it any other way. It’s just a few small instances where that’s not the case and I need to ask here.

The reason I need GGX in material nodes is because of the lack of specularity on translucent surfaces. I would like to use UE4’s BDRF GGX on the water, but for whatever reason it’s awfully expensive to use per-pixel lighting and forward shading on translucent objects. Hardwiring the specularity to an unlit material costs only half as much, and while there are drawbacks regarding shadows, the bang-for-your-buck simplified version works so well that any other method is just not worth the hassle. I have a GTX 960 and I’m running huge open world water scenes at 1080p 85 FPS in the freaking editor.

I’ll try a custom node, but I would much prefer a material node version if that would help with optimization.

I wish I learned HLSL… It’s having problems identifying the first parentheses and NoH.


float D_GGX( float Roughness, float NoH )
{
	float a = Roughness * Roughness;
	float a2 = a * a;
	float d = ( NoH * a2 - NoH ) * NoH + 1;
	return a2 / ( PI*d*d );
}

To use this in the custom node you simply need to remove the first line of the function. you don’t need the brackets either.

The reason why is that the engine automatically (and quite unhelpfully if you ask me) writes that top line, calling it CustomExpression0 and so on, and automatically fills out the parameter entries based on what you enter on the node as inputs.

So for above you need to make inputs for Roughness and NoH.

In general your concern for using code over nodes due to optimization concerns is a valid concern, but if you are taking a core rendering function like ggx from a common file… you can be fairly certain that it is already well optimized. Of course that may not apply with some various reference implementation for certain code paths.

Wow, that actually worked! Man, I love having access to the source shaders! I actually saved 23 instructions using Unreal’s GGX over the blog’s version!

5cfe74bb7e75083771a376acb8a88dce320b5d8e.jpeg

fd391aa0ecd5ac9a3fceba879a479cb757d0f1c3.jpeg