Jump to content
The Dark Mod Forums


  • Posts

  • Joined

  • Last visited

  • Days Won


Everything posted by totallytubular

  1. v 0.93 LdotH used for BRDF Fresnel, too, if PBR_OPTIMIZE switched on Really minor update. Stumbled across a presentation on "Physically Based Lighting for Black Ops" (SIGGRAPH 2011) that made the distinction between Fresnel for mirror/cubemap that uses NdotV or NdotL, and Fresnel for BRDF microfacet that uses VdotH or LdotH. Since the FilmicWorlds optimization already does LdotH, I just added LdotH Fresnel to the optimization path. So... Optimization off... VdotH gets calc'ed Fresnel uses VdotH Visibility calc's 2 arms, one for NdotV, one for NdotL Optimization on... LdotH gets calc'ed Fresnel uses LdotH Visibility calc's 1 arm with LdotH then squares it The LdotH specular is a bit brighter than the VdotH one. glprogs.stages.interaction.093.zip
  2. I wandered through the Bloom / Volumetric Lights thread, and came across the link to your github https://github.com/duzenko/darkmod-experiments I wanted to check out your Volumetric Light shaders, but don't see a "glprogs" folder anywhere (?) When researching volumetric lights, I came across a a lot of different sites talking about various ways to do them and optimize them. Maybe I can stare-n-compare to see if I can find a way to tweak them?
  3. Do they not realize volumetric lighting would make their job easier? It does all the work in creating god rays w/o having to hand-place them. I wanted to try real volumetric lighting via shadowmaps, but that's beyond me. (IE: not sure how to implement it, and reached my level of incompetence trying to wrap my head around it .. kept finding a lot of Unity examples, and not sure how to translate that into non-Unity). That's why I focused on the easier post-processing version. I can understand the performance issue ... Fallout 4 was Nvidia's big "look at our volumetric lighting using shadow maps!" example, and I remember having awful performance with FO4 with that turned on while using a GTX760. As more TDM graphics get offloaded from CPU / game engine to GPU / shaders, maybe there will be a time when there's a performance surplus folks would then be willing to rethink spending on cadillac features like volumetric lighting. Since I've spent time farting with lighting, just thought I'd try to bolt on a cheap version and see how it goes.
  4. So, new challenge... I'm trying to implement simple post-processing volumetric lighting as per Nvidia's GPU Gems... https://developer.nvidia.com/gpugems/gpugems3/part-ii-light-and-shadows/chapter-13-volumetric-light-scattering-post-process It's a simple plug-n-play algorithm to shove into the post-processing pipeline (the /glprogs/tonemap.fs file). My idea is to create very faint god-rays for moonlighting. We already have hand-placed god-rays for direct-lighting. So, just wanted to have very faint highlighting for overhead moon light as well. Issue I'm running into is the algorithm needs a light direction. I got into tonemap.vs, and tried calculating a var_WorldLightDir (like the way interaction.common.vs does for shadowmaps). I removed the parts in the calcs needing model matrix, b/c I just try to get a basic light direction for scene w/o model impact. So.. like this... // var_WorldLightDir = (params[attr_DrawId].modelMatrix * attr_Position).xyz - u_globalLightOrigin; var_WorldLightDir = attr_Position.xyz - u_globalLightOrigin.xyz; I can't pull in params w/o shader crashing. The u_globalLightOrigin uniform doesn't seem set for the post-processing tonemap shader. So, all the god rays just dump into the lower-left corner regardless of view angle. Is there another global light direction that exists for post-proc? Or, is that something the would require fiddling with the game engine?
  5. v 0.92b shadow map texSize pre-calc'ed one time Filmic Worlds LdotH optimization included in PBR (switch it on/off with #define PBR_OPTIMIZE in funcs file) Stared at the shadow map fs shader a little more, and noticed texSize is calculated in the main() for shadowResolution, then calculated in the shadow Atlas functions again. Made it where main() calc's it one time, and passes it to the Atlas functions. Real minor change, but the atlas functions are called over and over in soft shadow loops. So, just in case compiler doesn't notice a one-n-done value is done over and over, pulled it out of the loops. I also forgot that I implemented the Filmic Worlds LdotH Visibility GGX PBR optimization in 0.92. Basically, instead of having to calculate a GGX "arm" for NdotL and for NdotV, it just has to calc one for LdotH then square it. Helps cut down on calculations. It makes the PBR a bit brighter, but the results look acceptable. glprogs.stages.interaction.092b.zip
  6. Can you post a pic of the posterization you're seeing? I need some place to reference to tell if I'm fixing it or not. See if the shadow map tweak I made fixes it. ~~~~~~~~~~~~~~~~~~ v 0.92 fixed puddles tweaked shadow map (not sure if it fixes anything) Puddles were spazzing from the MIN_AMBIENT_LIGHT amount I try to add to diffuse light color to keep it from being pitch black. Not sure why it spazzes out. I commented out that part of the ambient frag shader until I can think of a way to do that w/o spazzes. I looked at shadow maps. I'm not sure where the posterization issue is, but the cubemap facing function seems to be doing the wrong values in a few spots. I added a new version of the function that emulates what khronos has in the OpenGL pdf for cubemaps. I'm not sure if it fixes anything or not. I dont' notice a difference when I flip between it and the original TDM version. glprogs.stages.interaction.092.zip
  7. v 0.91 posterization fixed (?) The "if ( this is 0 and that's 0, etc, etc)" logic branch on GetBRDF() equations seemed to be creating a gating situation causing posterization. When I commented them out, posterization seemed to clear up. (Tested on the statue on Mission 2: Tears of Lucia). When I get time, I may get rid of other branches to see if other stuff clears up, too. (EG: the banners in Training Mission hub that still have chunky coloring splotches). Maybe I'm being too liberal with logic branches. I could try running fake specs as vec3's like real specs, and see if things clear up. I don't know. glprogs.stages.interaction.091.zip
  8. What map is that? I want to be able to see the same statue (to keep that as a constant) while I fiddle with things to see if any results change.
  9. Yeah, noticing the posterization on a few things. Pics of banners in main hub of Training Mission: I fiddled with things in PBR, and didn't get it to change. Then I turned PBR off, and... ... it still shows up. So, it's something else. Not sure what. Haven't had time to test other things yet. It's the same posterization pattern, though, so I wonder if it's specular still.
  10. v 0.90 tweak to BRDF function to factor out some math & optimize a bit Been looking at this person's site... http://filmicworlds.com/blog/optimizing-ggx-shaders-with-dotlh/ He's done work to optimize the Cook-Torrance BRDF. I Implemented it in FUEL (at least the ones that don't require extra texture pulls), but it was super-shiny. His level 3 optimized BRDF merges Fresnel with Visibility to reduce calculations.. but then it's harder to isolate Fresnel to do the kS/kD ratio without having to have a separate one do extra calcualtions to complete just for that. So, I tabled that for now. Might bolt it onto TDM later to see how it looks. But, one thing I noticed was in GGX Visibility / Geometry functions, folks seem to do... 1.0 / (stuff1) * 1.0 / (stuff2) as opposed to the LearnOpenGL & Urho3D way that has NdotV / (stuff1) * NdotL / (stuff2) Then I realized it's probably because they used NdotV & NdotL to cancel out the ones in the denominator of the C-T equation... 4 * NdotV * NdotL we can isolate them as... ( Fresnel * ( NdotV/1 * 1/(stuff1) * NdotL/1 * 1/(stuff2) ) * Distribution ) / ( 4 * NdotV * NdotL ) ... and that reduces down to... ( Fresnel * ( NdotV * 1/(stuff1) * NdotL * 1/(stuff2) ) * Distribution ) / ( 4 * NdotV * NdotL ) .. which just means the NdotV & NdotL are free to cancel the ones from the denom, leaving us with... ( Fresnel * ( 1/(stuff1) * 1/(stuff2) ) * Distrubution ) / 4 Someone might want to double-check me on that, but it looks valid. Attached shader .zip does that. glprogs.stages.interaction.090.zip
  11. v 0.89 fixed posterization of PBR After some testing, turns out the Distribution term really does need to include PI in it's denominator.. or else it causes this posterization issue. glprogs.stages.interaction.089.zip
  12. Oh yeah. I noticed it on doors... There were large, chunky squares. And other textures. (I posted a picture of a ground texture that had what looked like ugly pixelization.) I disabled parts of the PBR code to see what was doing it, but couldn't figure it out. But, when PBR is disabled as-a-whole, it goes away. So, I'm not sure what's doing it. I thought the clamp I had on the distribution term was creating a gating effect, but I disable that and it's fine. Maybe it's a combination of things. I don't know. I have to look into it more. But, it is annoying. There's a lamp on Mission 1, you jump down where the 2 guards talk... the lamp has like really black pixelly spots on it... I thought maybe the Visiblity / Geometry term was doing something. The next thing with the PBR would be to bolt on various sub-routines for Visibility/Geometry and GGX/Distribution to see if they are better. Maybe they'd fix something. I feel it's odd I had to hack in a clamp to keep Distribution term from over-shining things as it is. Ideally, PBR should just take things in and shove them out without any modification. But, it's doing something... The fake roughness & specular might have something to do with it. That's why I've been trying to get better algorithms to produce them. At this point, I just don't know what's causing it. But, at least I'm not the only one seeing it. So, that means it's not a graphics driver issue or something. (I think).
  13. Well, it's more that I'm trying to avoid another project to work on. I'm the type of person that likes to dig in and help out. I started asking questions here, and before I knew it I was staring at PBR tutorials to bolt PBR on the lighting shaders. LOL! No one asked me to. But, it was just interesting experiment. It was also something I felt I could work on and be productive with, because the job hunt has been very demoralizing. I'd ask questions at the RBDoom3 forums, but, since I already know the PBR code I did, I'd want to just bolt it on and test it out. So, if it was a waste of time, it would be my waste of time instead of theirs. I'm trying to practice some "proactive quitting" to re-focus my time on my job hunt. I've already got the FUEL shaders in the back of my mind again; wanting to revisit them to see if I can bolt PBR on them. It's like things I want to go do, but I need to stop myself, since I have something I need to do right now that I need to focus on.
  14. v 0.87 * switched fake roughness over to use RBDoom3's version (seems to smooth things out better). Thanks for pointing me to his github, Peter_Spy. He's got some interesting things going on there that I'm going to look into further. * for surfaces with real specular rgb textures, I have roughness using an avg of the diffuse rgb & specular rgb grayscales. This adds variation in the pattern. EG: instead of a polished marble floor having a uniform shine, it will have variation based on where the veins are. * for non-PBR, I switched it over to use fake spec as a spec light instead of a diffuse boost. This makes lighting look more uniform when switching between non-PBR and PBR instead of "whoa, why does non-PBR color pop more?" (if color boosting / color saturation is wanted, it could be added as a feature in post-processing or something.) glprogs.stages.interaction.087.zip
  15. Can you post a screenshot of that banding / posterization? I'm running bare-bones 16-bit color, no SSAO, etc, etc. Like with the Bloom issue, others are running other options that may be seeing different results.. which could be borked up w/o me knowing.
  16. The metalness equation converts the specular from being a simple R0 value into an F0 metal vs. dielectric value. He's got that done. half3 specularColor = lerp( dielectricColor, baseColor, metallic ); That would be the next step for TDM if there was a way to flag metallic surfaces vs. non-metallic; could use that to branch the shader code and keep pipes semi-glossy without cobblestone streets looking wet n shiny. But, whether it's R0 or F0, it needs to head through a Fresnel equation (like Schlick Fresnel) to account for view angle to the surface to determine what ratio of light is reflected as-is vs. diffuse color reflected. I don't see him doing that anywhere. But, I'm just taking a cursory glance at things. I could be looking at the wrong shader file for all I know. Or, he could be using a different specular BRDF model that does things differently than Cook-Torrance. But, he's got the BRDF sub-equations in a BRDF file that Cook-Torrance typically uses. His interaction.ps file creates the dots needed for Fresnel & Visibility/Geometry (vdotN, vdotH), then never uses them. He just uses distribution to do microfacets. Also, he's using half vars for HLSL (half2, half3, etc). I worked with HLSL to modify the shaders for FUEL. Half vars were originally created by Nvidia to try to get a performance gain over real float variables. They recommended using half vars when precision wasn't needed, like with pixel color calculations. But, modern graphics cards & drivers and such convert halfs to floats behind-the-scenes. AMD cards had to do that in order to run HLSL. Nvidia eventually did that, too, because eventually the performance gain from halfs wasn't there any more as gfx cards keep growing in power. The FUEL shaders (built by Asobo in 2009 for Cg, before Cg became HLSL) were using halfs. But, after I did some performance testing, I didn't notice any difference between halfs and floats. I don't want to start a discussion over on their forum. I sound like an a**hole nit-picking their code. I was wanting to put the PBR stuff to bed until TDM got modified in some way where PBR could get expanded on.. like the game engine flagging basic material types (metal vs. non-metal). I'm still splitting hairs over whether to divide the GGX Visibility function by Pi or not.
  17. Looking at his interaction lighting... https://github.com/RobertBeckebans/RBDOOM-3-BFG/blob/master/base/renderprogs/builtin/lighting/interaction.ps.hlsl He doesn't seem to take Fresnel into account to create the ks / kd ratios needed to follow conservation of light energy, which is a key feature PBR needs to do to be considered a real PBR model. He's using Lambertian for color. I'm not quite sure what model he's using for specular. In his BRDF file, he has equations for the 3 key elements: https://github.com/RobertBeckebans/RBDOOM-3-BFG/blob/master/base/renderprogs/BRDF.inc.hlsl Fresnel (reflection vs. transmission .. also counts as the specular ratio) Distribution (microfacets) Visibility (Geometry) (how much area the specular covers) But, in his interaction.ps lighting file, he skips calling those BRDF functions. Instead, he bolts Disney GGX distribution in, and then uses an outside modifier (rpSpecularModifier) to modify specular further. The goal of PBR is to not have to modify it after-the-fact. If you do PBR correctly, you just shove values in and take the outputs as-is to finish your light. You shouldn't have to tweak them further with multipliers. (That said, I built tweaks into the PBR model I created, because my distrubtion terms were creating super-shines in shadows and such. But, that's probably because my fake roughness algorithm sucks. LOL!) His ( USE_PBR ) part generates roughness & metallic for PBR use. So, it does that. But, he doesn't seem to be doing Fresnel... or Visibility / Geometry. Fresnel is the ks specular ratio. 1 - Fresnel = kd diffuse ratio. So, in his shader, we should be seeing something do that math to determine how much of the total light energy input gets used by specular vs. diffuse. I don't see that in his interaction.ps shader. I was confused about that as well until I finally wrapped my head around it using LearnOpenGL's PBR tutorial. RBDoom3 has all the pieces there, but doesn't seem to be putting them together for a true PBR final result. I wouldn't know that if I hadn't spent time sifting through PBR tutorials and stuff figuring it out on my own. If I took his code, and just bolted it right into TDM, it'd just get the same result he has.. which doesn't seem to be real PBR. And, I'd have no way of knowing, because I wouldn't have really understood PBR in doing that. So, in doing it myself, I learned about PBR, where the pitfalls are, what needs to happen, and what it needs to do to count as real PBR. That's not to say his code is without merit... I'm totally thinking of poaching his roughness algorithms and stuff. LOL! I'm also chuckling, b/c I noticed he had to google about whether things should be divided by Pi or not, too. That has been one of the most confusing parts of all this... what needs to divide by Pi or not. I'm glad you pointed me to his code. I wouldn't have understood it earlier on. But now that I know what PBR does, I can see what I could possibly use from his. Also, I can see that if I got similar results as him, then I was on the right track. But, I can also see where his code gets up to the finish line, but doesn't quite cross over. (I'm not personally attacking him. I'm just noticing what I think are flaws in his code. Maybe that rpSpecularModifier handles the specular ratio, and his rpDiffuseModifier handles the diffuse ratio. I'm not sure. It's piped in as a global. I didn't dig through his game engine source code. I'm a shader code person. Maybe he has the game engine calculate fresnel / ratio? Who knows.)
  18. v 0.86 fake spec is now just mul'ing by light source color, and doesn't add to diffuse lighting or mul by diffuse texture I thought about this for a while, and realized that by adding fake specular float to the diffuse light brightness, it was not keeping with PBR. Here's a drawing I did up to reference for the discussion to follow... In PBR specular equals the light from the light source reflected as-is. diffuse equals the light reflected, but modified by the surface; some colors reflecting, some absorbing Real speculars have an RGB texture. So, they can theoretically modify how the full-light color looks as it's reflected. (Usually in slight amounts. EG: if you look at each of the specular color channels on surfaces, the grayscale doesn't differ drastically. It just helps create subtle variations in shine). Fake speculars are just float grayscales. So, they provide an even amount of reflection along all 3 color channels. This means the light source color is reflected as-is. Our ratio for how much light reflected is specular vs diffuse is based on the Fresnel. The Fresnel is generated as part of the Cook-Torrance specular BRDF in the PBR model. Because the C-T model multiplies the Fresnel into it's equation, specular reflection ratio is already accounted for in the output value from the BRDF... To put it simply.. the C-T BRDF outputs a specular value that accounts for... specular texture specular brightness (spec dot) specular ratio (fresnel) All it needs to do after coming out of the BRDF is multiply by the light source RGB. Regardless of whether we used a real specular or a fake, all it needs to do coming out of the BRDF is multiply by a light source color. It doesn't need to take the diffuse texture into account. By adding the fake spec output to the diffuse brightness instead of treating it like a stand-alone specular light, we're artificially boosting diffuse color reflection... and, we're breaking the PBR model. (IE: the spec has shifted to act as a surface color vibrancy boost instead of as the full light reflection it was meant to be). EG: let's say we had 25% fresnel. That means the specular reflects 25% of the total light energy off the surface. The other 75% is diffuse color. (diffuse ratio is just 1.0 - Fresnel. So, if we had a 25% fresnel, we have a 75% diffuse ratio.. this is keeping with the Conservation of Energy, which is a key point of PBR.. a surface can't reflect more light energy than it was lit with, b/c that would break the laws of physics by it magically creating energy/light out of thin air). Let's say our color surface was bright red... R = 100% G = 0% B = 0% This means red is reflected completely while blue & green are absorbed by the surface completely. If we add in our fake specular to our diffuse brightness dot, then the green & blue channels will get negated, which means the specular won't properly represent the light it's really trying to reflect... R = 100% diffuse color * 75% diffuse ratio * ( surface brightness + spec ) B = 0% diffuse color * 75% diffuse ratio * ( surface brightness + spec ) G = 0% diffuse color * 75% diffuse ratio * ( surface brightness + spec ) In that situation, the specular output has been cut in 1/3 of what it actually should be.. actually. more than that.. b/c the specular at that point already accounts for it's Fresnel ratio (25%). So, we're subjecting it to another 75% after adding to diffuse surface brightness.. and then it gets negated by the diffuse color channels. So, long story short... The specular that comes out of the BRDF needs to just mul by the specular or diffuse light color (spec if it's a real spec, diffuse light color if it's a fake spec since there's no spec light color). So, we get the following... Real specs... // real spec rgb totalColor.rgb += specularPBRreal.rgb * specularLightColor.rgb * vec3( specMulReal * clouddim ); // diffuse totalColor.rgb += diffuseMaterial.rgb * diffuseLightColor.rgb * vec3( diffuseBrightness ) * kd3; // diffuse ratio ... vec3(1.0) - fresnel.rgb Fake Specs get a bit of alteration since they're floats... // fake spec totalColor.rgb += diffuseLightColor.rgb // substitute for spec light color * vec3( specularPBRfake ); // diffuse totalColor.rgb += diffuse.rgb * vec3( diffuseBrightness * kd1 ); // 1-fresnel, fresnel as float This makes the fake specs create a more even specular shine.. but, that's the point.. they're reflecting light as-is instead of acting like artificial surface boosters. This is keeping in line with what PBR is trying to do. But, by doing this, the diffuse colors are not as vibrant, since they are no longer getting the fake boost. If folks want brighter colors, a color saturation setting should get worked in some other place (like as post-processing setting they can adjust). I just want to get the PBR doing what PBR should be doing, even if I'm using fake values as placeholders in parts of it. In reworking this (yet again), I toned down the fake spec roughness amounts so fake spec wouldn't be too shiny. The PBR_RIMLIGHT is off again, so if you like using that you'll need to set it to 1 again. glprogs.stages.interaction.086.zip
  19. v 0.83 fake spec PBR path is back to adding to diffuse brightness again I was playing Now & Then, and the lighting inside the museum was bleached out looking. Wasn't sure why. Then I remembered I had to add diffuse texture to ambient fake spec PBR to keep water from spazzing out. So, I added diffuse texture to direct light fake PBR, and that fixed the lighting. But, then we're back to having... diffuse texture * diffuse light color * fake spec PBR .. and that adds to diffuse color once it's calculated diffuse texture * diffuse light color * diffuse brightness * kd ratio So, basically, it's back to factoring out to... diffuse texture * diffuse color * ( diffuse brightness * kd ratio + fake spec PBR ) Real specs can just multiply by their specular light color and be good to go. But, fake specs need to multiply by diffuse light color (as spec light color replacement) and diffuse texture. Not sure why. The BRDF takes the specular texture in, and generates an output that counts as the specular color texture / map & specular brightness already mul'ed together. So, it just muls by spec light color. But, for fake spec maps, it still wants a diffuse texture to make it look right. So, back to doing that. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ got rid of PBR_FAKESPEC_IS_REALSPEC (b/c of above reason) real speculars use 1-specular.rgb as roughness, fake specs use 1-diffuse.rgb .. this helps real speculars look a bit better added #define PBR_RIMLIGHTS to add TDM's default rimlight/rimshine even when PBR is on in order to punch up lighting more if end-user wants. PBR / BRDF takes rimlighting into account with fresnel. And, it does a decent job (eg: the columns on Training Mission have a nice crisp rimlight / rimshine .. walls tend to rimlight at an angle). But, other places it falls flat, like on ground textures that have fairly flat pavers. So, by adding TDM's default direct light rimlight/rimshine on top of what PBR does, it helps enhance the edge-lighting more to make things pop. This voids the warranty of the PBR being a "Conservation of Energy" model then, though. PBR's goal is to keep make sure the output light energy coming off a surface (as color & shine) doesn't exceed the input light energy coming from the light source hitting it. If we add in extra rimlight & rimshine, it voids that by magically creating more light energy out of thin air. But, there's no rule saying PBR can't get enhanced after-the-fact. This is a fantasy video game, so the lighting can get kicked up a notch to help enhance light & shadow for player immersion. The #define PBR_RIMLIGHTS is off by default (set to 0), so you'll need to change it to 1 if you want to switch that on. glprogs.stages.interaction.083.zip
  20. I'll give that random var a try when I get a chance. Also, wasn't sure if the branching was worthwhile or not, but did it anyways. I see a lot of conflicting info about branching in shaders, mainly b/c stuff I find when I google is from 2010 when branching killed performance. OpenGL and DirectX have matured since then. I'm gonna keep the logic branching in the BRDF, because it's being used to avoid div/0 if NdotV or NdotL are 0 without having to do hacky things like add 0.0001 to them.
  21. v 0.82.c optimized BRDF a bit by skipping over it if 0 value inputs would just generate 0 value output roughness is now ( 1 - grayscale(diffuse texture) ) roughness is now used as a mix/lerp factor to better control the gloss/haze range tweaked roughness to tone down glossy real specs while hazing up fake specs a bit so they don't look wet Noticed some surfaces had too even of a shine, like covered in oil or clear-coat. Had this issue with fake specs when using too similar of a value to the diffuse color. So, I did like the one article said and inverted the diffuse grayscale. This let opposite areas of the diffuse stand-out with specular, creating more variation in the specular on the surface. I standardized it all to do that. It was still a pain using multipliers and other junk to try to coax the roughness into something that looked decent. So, I just switched it to being a lerp factor... roughness = mix( 0.2, 0.7, roughness ) This gives better control of the gloss/haze specular.. so real specs I could make a tad more glossy while fake specs I could make more hazy with better precision. Too narrow of a range, and things get too even-shined again.. so tried to keep at least a 0.5 range between low & high values (eg: 0.2 to 0.7, 0.1 to 0.6, etc) With BRDF going, my FPS has dropped a bit, but game is still playable. So, I looked at the functions, and noticed that if some key variables are 0, they'll just generate a 0 output. So, added some logic branching to skip BRDF and just default to 0 if those key variables are 0. Didn't really help with performance; not many things will be 0. I've seen some BRDF's where folks use the dots (NdotV, NdotL, etc) to see if those are 0 and skip processing. But, the problem is with ambient light, NdotL will be 0 for walls. So, walls and windows and things won't get specular lighting. I pipe in the NdotL*0.5+0.5 half-lambert, and that helps, but then NdotL will never be 0, so no point in testing for that. There's probably other ways to optimize this thing, but for now just trying to keep it simple. (Now that I have a handle on it, I was going to look at Disney's / Burley's github repo again later.. dude has tons of BRDF's. Maybe I can find some interesting tweaks / optimizations to make this basic BRDF better. But, that's for later.) todo: I really want to get a noise generation routine going, because it could be used to tone down the "wet / gloss look" of speculars while preserving the brightness / shine. I can't seem to figure that out, though. glprogs.stages.interaction.082c.zip
  22. v 0.82.b fixed spazzy water Water (eg: in Training Mission rope arrow canal area) was flickering like a disco ball again. The PBR fake specs acting like real specs weren't taking the diffuse color texture into account. So, the math changed from this: diffuseLightColor.rgb * vec3( specularPBRfake ) ... to this ... diffuseMaterial.rgb * diffuseLightColor.rgb * vec3( specularPBRfake ) Crisis averted. glprogs.stages.interaction.082b.zip
  23. v 0.82 .. the "I think I finally got PBR working right" update (knock on wood) ambient surfaces with real speculars do more glossy PBRs now capped the distribution term in specular PBR flow to keep it from barfing white specklies everywhere with glossy outputs, and to help control how bright glossy shines are in lighting got rid of the "divide by Pi" parts in PBR flow, because we're not dividing diffuse color by Pi (instead, dividing by " 4 * NdotV * NdotL" which seems to give better results corrected visibility specular PBR term to use NdotL like it should (not sure how I missed this before) renamed BRDF_SPECULAR to PBR_LIGHTING (PBR is what we're doing, BRDF is how we're doing it) added #define PBR_REALISTIC which (when set to 1) will keep the multipliers usually used to tweak outputs (like speculars) to 1.0 so pure PBR outputs are shown without anything tweaking them after-the-fact (the idea of this is to maybe tweak the PBR outputs in the future to "enhance" the lighting to be more immersive / game-like, but still have a way to quickly switch to pure PBR. PBR is supposed to be a realistic lighting model, so mucking with it after-the-fact can alter the realism). added #define PBR_FAKESPEC_IS_REALSPEC to flip between fake specs acting like real spec lights of diffuse boost in PBR (in PBR, they do better acting like real specular lights, because PBR does direct rimlighting and rimshining w/o having to resort to extra functions. But, when you turn the fake specs into diffuse boosts, a lot of what PBR does disappears w/o much diffuse boost to show for it..unless you muck with the outputs post-PBR.. which defeats the purpose of PBR.. to have algorithms do it all w/o having to mess with too many extra variables). finally understood the whole "conservation of energy" thing, and added ks/kd ratios to balance diffuse vs specular. It's basically taking the specular PBR fresnel term and using it to determine how much light is reflected (specular) vs refracted (diffuse) based on your viewing angle, surface, etc. fake spec maps are used in PBR as speculars, but for roughness maps I went with grayscale diffuse textures. This lets them have full 0 to 1 range instead of the curved range that fake specs do. Basically, I read Epic Game's white paper on how they put PBR into UE4, and they made decisions to just keep using Lambertian Diffuse like they had been doing, and just focus on keeping it simple and where the algorithms they chose do all the work.. as opposed to shader devs or artists having to micro-manage tons of variables to tweak everything. This radically changed my thinking about PBR, and I realized it can be as simple or as complex as folks want it to be. So, I ignored a various diffuse lighting models and just kept what we had, but modified with energy conservation (kd). I realized Torrence-Cook is the main PBR model most folks use, but they swap out various sub-algorithms in it. Once I wrapped my head around that, it made more sense. I switched to using the most common algorithms tuts used, and just kept it simple to get it working. I then figured out the whole "conservation of energy" thing, b/c the ks/kd thing was confusing me for a while. (LearnOpenGL's tutorial was confusing, b/c they kept swapping back-n-forth between code and math.. and I do better when I see just a cohesive chunk of code showing how things are done). Anyways... I got it going. The goal (in my mind was) Get the damn thing working properly If it's working right, we shouldn't have to use any post-PBR multipliers to tweak speculars and brightness and other junk. The PBR algorithms should handle all of that, so we don't waste time mucking around with that. (I kept the multipliers in the code, but they're all set to 1.0 for PBR paths.. so we see a pure PBR output experience.) I had to make a few hackish decisions to get things to look decent, like clamping the distribution term (it was barfing white specks all over the place). Also, not dividing by Pi... The Pi division was confusing the heck out of me...then I came across some forum post (can't remember where) that the person said in the Lambertian Lighting Model, you divide diffuse color by pi. But, it's just assumed that light colors in the game engine piped out to shaders are already divided by pi, so nobody divides diffuse color by pi in shaders. Um.. okay? *head-scratching* But, the PBR code I was looking at (eg: Urdo3D, LearnOpenGL) were dividing the specular PBR output by Pi (learn open gl had one of the spec sub-terms also divide by Pi). I realized they were doing this, b/c it would balance out diffuse color dividing by Pi. But, we don't divide TDM diffuse by Pi. It's a bad assumption to make w/o knowing for sure. All I did was look at the results from the shaders.. if I divided diffuse color by Pi, it got really dark. So, I removed the divide by pi from the specular PBR output, too. Instead, I switched it over to a " / 4 * NdotV * NdotL" that I noticed other folks doing. This worked well to tone the final spec output without having to do Pi. (this is the big PITA about all of this.. it's like herding cats. Everyone's doing their own version of it that works for them, but they don't explain why they do certain things. No code comments or what-not in the code, and white-paper-like-discussions that hit my level of incompetence pretty fast. So, trying to mix-n-match code or using one project's code into ours can lead to funky results w/o knowing why.) Anyways... Issues: Chunky texture seams some surfaces have an ugly, chunky texture situation going on, and not sure why. When I switch PBR off, it resolves itself. So, it's something with the PBR pipeline. Something is acting like a cap or limiter or something to create the stark seams between parts. I tested various terms in the PBR, and these chunkies still occurred. Maybe it's my crappy HD 4600 doing something funky? I don't know. Only certain textures do it. If anyone can verify whether they're also having the issue, I'll be able to know if it's a code issue or gfx driver issue. Dark Spot under Player Ground specular was looking nice... before I got kD (diffuse refractive ratio) built into diffuse. Now there's a dark spot under the player. I know it's the kD value, b/c when I remove that from diffuse lighting equation, the dark spot goes away and ground speculars look better. Not sure what's up with this. I'll have to experiment, or try other formulas or something. I don't know. Speculars get Bright up near walls in Ambient PBR helps ambient specs look better, but they exacerbate the brightness of speculars as you get closer to walls more-so than non-PBR spec. Ambient specular was always a balancing act trying to make it look good both indoors and outdoors, b/c it's controlled mainly by the light color the level designer uses for the room/area. So, if they want brighter specs outside, they use a brighter light color. Darker inside, use a darker color. For PBR, I use the distribution clamp value to try to control how bright the shine is. I set it lower for ambient specs than direct specs. But, we still get cases like this, where looking up a wall in a dark area (Alberic's Curse, the inner church) has an out-of-place shine. The PBR has rim light & rim shine baked into its algorithms, so it does this super-brighting on its own. This would be a situation where spec & roughness maps would control it I guess, so maybe my PBR pipeline isn't using them well enough. Not sure. Screenshot Compares Here's some before & afters with non-PBR vs. PBR. It doesn't make a dramatic difference in scene-wide lighting. It mostly enhances things you're looking closely at by making the lighting act more realistically. PBR does it's own rim lighting and rim shine for direct lighting. (not so much for ambient lighting, so kept that as it's own light in ambient). So, in direct lighting, when PBR is on, the rim light & rim shine turn off to let PBR handle it all. Surfaces with real speculars treat PBR more like glossiness while fake specs do more rough / hazy specular. PBR makes light form around objects more realistically. The metal objects use real speculars, so they do more of a glossy shine instead of hazy/rough shine. The player lantern shines off the metals, reflecting light back. The falloff of the light adds more body/depth to the pipes & boiler. The window light also highlights the boiler more... PBR is handling all the direct rim light / rim shine here. So, no fiddling with variables to try to "get it right". The PBR algorithms have the smarts built into them. PBR enhances the lighting along the camera view. The metal lamp post pops out, because it's using specular as more of a gloss. But, the overall lighting tone has changed. The lighting on the posts to the left follows the falloff of the light source better, so instead of both posts being evenly lit, one is a bit brighter than the other. Mission 2, the weeping statue ... PBR helps the light follow the countours better. The stairs stand-out here, b/c PBR works best on things with more contours. It adds better light falloff and specular shine. The flip back-n-forth is my non-PBR shader vs PBR shader. Since my non-PBR pipe adds fake specs to diffuse brightness, it punches up colors. Since my PBR pipeline is set to do fake specs like real spec lights intead of adding them to diffuse brightness, colors seem to have toned down a bit while lighting has punched up a bit. I can post screenshots, but one of the things that makes PBR nice is how it looks when you move. The light just contours around things better. There are spots where you look straight up and go "why is that wood building super shiny?" But, that's b/c I'm doing the best I can with what I have right now. glprogs.stages.interaction.082.zip
  24. Yeah. My thinking is level designers created their levels based on what they saw at the time. Slapping PBR-like stuff on top now, especially by hacking together a roughness map, isn't going to magically make everything look good. I try to tune the stuff to a specific map (namely Training Mission), then go mess with a few other levels to see if anything looks odd. Inevitably, something will stand-out. So, I'll tone something down, but it gets to the point where things can get so toned down it's like "why bother wasting processing for such a minor result?" But, the performance impact is a bit negligible. I'm still getting 20-30fps on a dinky little HD 4600 integrated graphics. And, my view on enhancement is it's a death of a thousand cuts; little things add up. I''ll probably mess with it more later, but right now I need to re-double my efforts on my job hunt now that I'm vaccinated. 2 yrs w/o a job after graduation. My retirement account has been keeping me afloat, but student loans are coming up. And wife's been watching home reno shows, b/c she wants a house badly. I've been throwing myself into personal projects to keep busy, but job hunt has been depressing.
  25. v 0.79 minor tweak to direct fake spec to brighten it up a bit made "darkerunder" only impact fresnel on ambient again, because it was darkening ceilings and such too much when it impacted diffuse & specular specular BRDF added back in with a toggle (#define BRDF_SPECULAR 0/1) to let you switch it on/off The "darker under" thing was culling light too much on ceilings when applied to all ambient light. It's because there's no way to tell what's an object (like a canvas package) vs a ceiling or such. So, I just have it culling rimlight again. I started staring at PBR again. Trying to make sense of it is a learning curve, because sources talking about it either go into very high-level math / comp sci / academia / white paper discussions about it, or they discuss it piece-meal with code chunks without really showing how everything fits together. But, it breaks down into a diffuse lighting model (eg: Lambertian) mashed up with a specular lighting mode (blinn/phong, schlick, ggx, etc). I was staring at the learnOpenGL PBR page again, and followed the link to the Unreal team's paper talking about their work on PBR into UE4. They said they looked at Disney's stuff, and ignored certain things b/c the cost/benefit wasn't worth it. EG: they ignored using other diffuse lighting models (like Burley model) after doing some tests and realizing Lambertian was good enough. The real benefit comes from the GGX, etc specular stuff. So, I ditched the diffuse stuff in the "interactions.pbr" file, and trimmed down to just some basic specular functions for visibility (geometry), distribution & fresnel. (Mainly GGX, since that seems to be what most folks focus on). I got stuff working, and have the fake spec map doing double-duty as a roughness map as well. Ambient & Direct light do their own thing from there... I forced Ambient light to use 1-fakespec as a roughness to prevent glossiness. For some reason the specular distribution term wants to barf white pixels everywhere when glossiness is high, and the glossiness on real spec mapped surfaces sticks out like a sore thumb. So, I forced it to do rough surfaces. Direct lights... if it has a real spec map, I have it doing glossy. If it has fake spec map, it does rough. This allows shiny surfaces, like the pillars on Training Mission, to look like mirror-finish polished marble, reflecting the torch light more. The results of all of this are ok. The specular seems to even out in ambient lighting better. Metal pipes and such have more body to them as they reflect more light. But, some surfaces look wet. Some surfaces look like they have a bunch of white pixels washing over the place like dust. I think this is the micro-facet algorithm going full-steam with "every facet is reflective". To make it vary in color, it needs like a noise algorithm to go with it. I was reading some coding lab web page where folks were doing monte carlo sims to statistically vary their micro-facets (*cough*).. but they were doing rays and stuff. I'm trying to get a noise function to work, b/c I'd like to use it to tone down the gloss on NPC faces and such. But, I can't seem to get GLSL's built-in noise() func's to work, nor ones I bolt in from other sources. I think I'm missing a random value generator to ensure the seed value changes? I'm not sure. I've hit a dead end with noise generation. Anyways.. here's some screen shots... The pillars have real spec maps, so the fake spec map acts as a gloss map instead of a rough map for them. The BRDF specular obstacle course creates reflections of the candle as if it's polished marble. The metal stands out more with speculars, but in ambient light I use the fake spec map as (1-fakespec) for a roughness map. So, they don't have heavy reflection. But, if you turn on the lantern, you will see the lantern reflect light off the pipes more (like with the marble pillars). The spec brdf hugs the curves of the objects more, creating crisp lines. Invasion of the white, speckly pixels. The spec distribution function loves to over-bright things. I had to hackishly tone down it's results in the glossy brdf branch. Even then... I toned down the specular on the ground, but the ground has a real spec map, so it's using the glossy brdf branch. It has a nice shine, but it's a bit over-done. And, the white speckly pixels start to look like static as you move sometimes. The issue with the PBR is it feels like it needs to get tweaked per-level. On one level the specular shines are too much. On another, not enough. Etc. The idea of the BRDF is that it makes more decisions on things, like spec power, rather than having to fiddle with variables. But, still stuck fiddling with some variables. glprogs.stages.interaction.079.zip
  • Create New...