-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Modularize PBRLighting.frag #2191
base: master
Are you sure you want to change the base?
Conversation
Addresses this issue: jMonkeyEngine#2122 To re-summarize: This PR extracts all of the texture reads and basematParam assignment into a .glslib file (currently named PBRLightingParamReads.glsllib) And then it also extracts all of the lighting calculation into a .glslib file (currently named PBRLighting.glsllib) I also fixed alot of formatting and indentation mistakes, and overall reorganized the shader. This should now make it as easy as possible for jme devs to fork PBRLighting to make changes, and they will no longer have to update the lighting or texReads to stay on par with master, as all future changes will all be in the glsllibs. This also reduces the chances that a lesser-skilled shader dev (or even skilled shader devs on a bad day) mistakenly mess up the lighting calculations when forking the shader. Any feedback and review is greatly appreciated.
Once approved, I will also update the PBRTerrain shaders to create 2 new glsllibs titled "AdvancedPBRTerrainParamReads.glsllibs" and "PBRTerrainParamReads.glsllib" so that those will be modularized as well. Both of those shaders will also be able to use PBRLighting.glslib for the final lighting calculation, ensuring that PBRLighting and PBRTerrain shaders always share the same lighting code and this will greatly reduce code redundancy. It will also make shader development waaay easier for devs like myself who have 10 forks of PBRLighting all with minor differences. |
I have also placed both of the glslllibs in Common/ShaderLib/ for now... However I am not sure if that is the right place for these, as there is also a PBRLighting.glslib that contains the deeper pbr lighting equations (which are referenced and used in the new PBRLighting.glsllib) and the two could be easily confused. So maybe we should make a new shaderLib directory for modular PBR glsllibs? I'm open to hearing others input on this (for now I don't have the correct reference to the glsllib in PbrLighting.frag, but I will update the import to be correct once a final location has been determined for these new glsllibs) I have also removed some ifDefs aroungs things like tbnMat's calculation, so that it will be calculated even if there is no normal map (I also still need to change PBRLighting.vert to remove ifDefs around the passing of the tbnMat and vViewDir varyings) . This will be important so that forks of the shader that do things like splatting normal maps will still be easy to make even if the original model does not have a normal map, without having to go in and change any of these .glsllibs |
Forgot about spec-gloss pipeline
Added spec-gloss vars
add inouts for specularColor and glossiness to account for specGloss pipeline
Just made one more set of changes because I forgot about the spec-gloss pipeilne. I typically only use the metallic pipeline so I overlooked spec gloss yesterday, but I fixed it so both will work now. I've extensively tested my changes with models that use the metallic pipeline, however I have very few spec-gloss models so I didn't get to test that as thoroughly. I've also updated the vert and j3md files, so now this PR should be ready for a full-scale review. (The only reamining error in the code that I am aware of is the incorrect reference to importing PBRLighting.glsllib and PBRLightingParamReads.glsllib, since I am still unsure of where the best place to place these 2 new glslibs is) |
removed ifDef checks around some things (like tangents) that could still be used by other glslibs even if the shader doesn't have a normal map.
add matDefs for indoor sunlight exposure and debugging final output. These features were previously not in PBRLighting.frag, but they are in PBRTerrain.frag which will eventually share the same glslib for lighting (after doing texture reads), so they both should be consistent.
remove unnecessary assignment of norm, as normal will already = norm if a normalMap is not assigned, and norm isn't used anywhere else in this glslib so no need to pass it in
Hi @yaRnMcDonuts , 10X :) |
There shouldn't be any compatibility issues for any existent forks that are already out there. I made sure to not remove any params or defines from the shader, and only added 3 defines that will not have any effect if left undefined. So all files (the .j3md, .frag, and .vert) on master should still be compatible with forked versions of each other.
If any jme devs out there don't want to adapt these changes to their own existing forks of PBRLighting.frag, then they should still be able to keep all of the logic in one big file and manually keep it up to date with master/stable without any newly added trouble. However, the next time someone makes a PR to add a new feature to the new PBRLighting .glsllibs on master, (such as the recent SpecularAA or AOStrength PRs) then, at that point, I'd highly recommend everyone with forks of PBRLighting adapt the changes and have their forks use the new glsllibs, so then they will never have to worry about updating their forks to stay on par with master/stable ever again in the future. But if anyone still chooses not to adapt these changes and doesn't mind manually adding new features to their own custom version of PBRLighting.frag everytime master/stable has an update, then they are still free to keep on doing things the old way without any issues. |
How about renaming the file |
…eader.glsllib renamed to PBRLightingParamsReader.glsllib
That sounds like a good name to me, I updated the PR to rename it to PBRLightingParamsReader.glsllib and also updated the imports in PBRLighting.frag to reflect the change. I also fixed the import path to point to Common/ShaderLib/ in jme-core, so unless anyone objects to having these 2 new .glsllibs in the Common/ShaderLib/ directory in favor of a better place, then I will leave them there. |
jme3-core/src/main/resources/Common/MatDefs/Light/PBRLighting.frag
Outdated
Show resolved
Hide resolved
jme3-core/src/main/resources/Common/MatDefs/Light/PBRLighting.frag
Outdated
Show resolved
Hide resolved
jme3-core/src/main/resources/Common/MatDefs/Light/PBRLighting.frag
Outdated
Show resolved
Hide resolved
I updated the comments to fix the typos you pointed out, thanks for the proofread. I also appeared to have misspelled glsllib as glslib multiple times (missing the second L) in the comments, so I fixed that as well. |
not sure why build failed after last commit that was only changing comments. resubmitting to try again...
The build failed on mac due to a time-out error, however I resubmitted the same file and it worked again... Strange, but at least everything is okay and there were no real problems. |
jme3-core/src/main/resources/Common/MatDefs/Light/PBRLighting.j3md
Outdated
Show resolved
Hide resolved
added missing in/out to readMatParamsAndTextures
added missing uniform to .frag shader
@yaRnMcDonuts , Since this is a change to the way dev. will use the engine and indicates some kind of official best practice approach for using shaders, I would like engine core devs to comment on it before integration. Thanks! |
I don't have the push permissions, i've asked @yaRnMcDonuts for them, maybe worth pinging him here too |
Sorry I didn't see your message on discord, I don't have discord launch by default on my computer so sometimes I miss notifications on there until I manually open it up again. I went into my repo in the "collaborators" section of my repo's settings, and added you as a collaborator. Does that allow you to push to that branch, or is there any other setting/permission I need to change in the repo settings? |
That worked, thanks @yaRnMcDonuts |
I've pushed the changes, the code needs to be fully tested. Struct based modularityThe idea behind this design is to use mutable structs to create data containers that can be passed to functions. uniform sampler2D m_Tex;
uniform vec2 texCoord;
struct Surface {
vec4 baseColor;
vec4 litColor;
}
struct Light {
vec4 lightColor;
}
Surface getSurface(){
Surface s;
s.baseColor=texture2D(m_Tex,texCoord);
return s;
}
Light getLight(){
Light l;
l.lightColor=vec4(1);
return l;
}
void applyLight(inout Surface surface, in Light light){
surface.litColor=surface.baseColor+light.lightColor;
}
void main(){
Surface surface=getSurface();
Light light=getLight();
applyLight(surface,light);
gl_FragColor=surface.litColor;
} From there by strategically splitting the code into multiple libraries and using macros we can create reusable modular shader code. The
|
Hi @riccardobl , WDYT? |
We need to test it and see if the implementation is good enough or if things need to be abstracted further. |
I unfortunately haven't gotten around to testing your changes in my own project yet, although they do look good so far from what I have reviewed. I haven't had as much time as to work on my jme game this year as I have had in the past, and I got pulled into some other non shader related things around the time I last commented about testing this PR, so I haven't had time to shift back into shader-brain to work on this again (and likely won't be able to anytime soon). It does look like the latest updates you made are all okay, and the approach you took is cleaner than my initial proposal for this PR, while still retaining the important benefits from my initial PR. However the functionality between your updated code and my original code is still pretty much the same, so even though your implementation is an improvement on my original code and is cleaner and more extensible, I haven't been able to find the time/motivation to re-refactor all my PBR forks to match your latest update to this PR, and I'm also somewhat burnt out on shader refactoring and this PR since I already refactored multiple forks of PBR lighting and the terrains multiple times while working on this. I do plan to tackle this task and refactor all my shaders to match your changes some time in the future, but, as of right now, doing so unfortunately offers no benefits to my main JME project since it is solely a refactoring task and doesn't change any features/functionality in my game, so I have to prioritize some other tasks first. In the meantime I would say it is probably okay to pass this PR and have the community test it in an alpha/beta release rather than waiting for me to test it on my pbr forks, especially since shaders tend to produce different errors/issues on different devices. |
Hi @riccardobl I finally have time to work on this again, and I just built this fork to test it and implement everything into my main project. The TestPBR case with the tank ran fine, however now that I've built and imported this fork's jme-core jar to my own game, I am getting the following crash related to my usage of the Overaly.j3md filter:
If I remove the filter using Overlay.frag, then my game runs with no errors, and in that case it looks like the new changes are not breaking anything else with my own shaders so far. But some changes we've made appear to have broken that specific filter, I am not sure why though since it looks like a very basic color overlay filter. |
i think we need to exclude
on GLSL < 130 in glslcompat |
I updated it to check for the version before It says there was a conflict with this branch though, it appears a |
Not a correct solution, @yaRnMcDonuts . Try using the web editor. |
I don't quite understand what is incorrect in my 3rd (and most recent) update to GLSLCompat.glsllib I did use the web editor to add a line of code from the current master branch (based on the differences I saw when I clicked "resolve conflict" after my first edit to GLSLCompat.glsllib) but now it still says there is a conflict and i don't understand what the conflict is. I must be misunderstanding something about what github means when it says this branch has conflicts, hopefully someone can let me know what I'm doing wrong. |
nevermind my last post, it looks like I just had to remove the conflict marker characters <<<<<<<, =======, >>>>>>> that it had inserted into the file after the initial conflict. Not sure why github actually added those lines into the file, I thought that was just display-only text in the web editor so I didn't realize I needed to delete it manually. It should be resolved now. So this PR should finally be ready to merge( as long as it looks okay to everyone else). I built this branch and ran my game with these changes and everything appears to be okay. Once everything is approved and this PR is merged, then I'll start working on modularizing PBRTerrain and AdvancedPBRTerrain with the same struct funtionality and shared pbrLighting glsllib, and after that the engine's PBR shaders will be much easier to maintain and update in the future. |
Can any core devs/engine leaders take a look at this PR for a final review? |
@riccardobl do you think this PR is ready to be merged now? I'm hoping that we could get this in for the next beta release for more widespread testing, and then (as long as there are no further issues found) have this modularized version replace the current PBR shader by the next stable release. |
Are there any core devs or engine leaders that could please take a look at this PR and merge it? I am starting to get the feeling that this PR is not wanted in core, and am starting to doubt that it will ever make it to the point that this replace PBRLighting due to the lack of interest any other jme dev has. I guess no one else forks PBRLighting as heavily as I do, so no one else sees the insane benefit and time-saving potential that this PR can bring. This PR is also holding me up in regards to doing important bug-fixes with PBRTerrain and AdvancedPBRTerrain, and it is also holding up my own personal refactoring of PBR forks in my own project. (I already did work refactoring my own shaders and deleted it twice due to changes I was told to make to this PR, so I want to avoid that again and am holding off on working on many things until this PR passes) So if this PR is not acceptable and is no longer something that engine leaders want, then I would apprecaite if someone could tell me and I will close the PR and go back to implementing things in my own projects. It would be a shame if that is the case, but I get the feeling no one else sees the huge benefit in this PR that I see, and feel like I've mostly been commenting into the void in this PR. |
I'll try taking a look at it. I should be able to do it within this week. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've mostly suggested readability changes. The other PBRLighting files are a mess, so it'd be great if this were a bit neater.
Also, I think it'd be a good idea to profile the modular PBRLighting versus the current PBRLighting. There are so many defines added that it may have impacted shader compilation performance.
vec3 worldViewDir = normalize(g_CameraPosition - wpos); | ||
|
||
// Load surface data | ||
PBRSurface surface=PBRLightingUtils_readPBRSurface(worldViewDir); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add spaces around =
PBRSurface surface=PBRLightingUtils_readPBRSurface(worldViewDir); | ||
|
||
// Calculate direct lights | ||
for(int i = 0;i < NB_LIGHTS; i+=3){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add spacing: for (int i = 0; i < NB_LIGHTS; i += 3) {
|
||
// outputs the final value of the selected layer as a color for debug purposes. | ||
#ifdef DEBUG_VALUES_MODE | ||
if(m_DebugValuesMode == 0){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add spaces: if (m_DebugValuesMode == n) {
for each if statement.
// Alpha threshold for fragment discarding | ||
Float AlphaDiscardThreshold (AlphaTestFallOff) | ||
|
||
//metallicity of the material |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See about removing redundant comments to make the parameters more neat and easier to read.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this file any different from Common/MatDefs/Light/PBRLighting.vert
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is identical, all of the changes in this PR are related to modularizing the Fragment shader, so a new .vert shader should not be necessary. I think riccardo added this when he decided to make this into a new shader, rather than modifying the existing PBRLighting shader (although I still disagree with that decision, as creating a new shader it defeats the whole purpose of modularizing things in the first place)
in vec4 lightData1, | ||
in vec4 lightData2, | ||
inout PBRSurface surface | ||
){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One line function declaration.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix indentation in added test methods.
for (int i = 0; i < structBodyLines.length; i++) { | ||
String structBodyLine = structBodyLines[i]; | ||
structBodyLine = structBodyLine.trim(); | ||
if (structBodyLine == "") continue; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
String comparison with ==
is dangerous. Replace with structBodyLine.isEmpty()
.
@@ -1,4 +1,4 @@ | |||
Material Tank : Common/MatDefs/Light/PBRLighting.j3md { | |||
Material Tank : Common/MatDefs/Light/modular/PBRLighting.j3md { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Revert this. It would be better to create a new j3m file specifically for testing the modular PBR matdef.
else if(m_DebugValuesMode == 5){ | ||
gl_FragColor.rgb = vec3(surface.emission.rgb); | ||
} | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this debug block be moved to a glsllib?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately I do not think this code can be moved. I recall trying moving that code in the past, but it appeared that any references to "gl_FragColor" need to be in the main .frag file
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I'll take your word for it. It isn't important anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few more problems I noticed.
newTexCoord = texCoord; | ||
#endif | ||
|
||
#ifdef BASECOLORMAP |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you wanted to further modularize this, perhaps move each texture read type to a seperate function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes that would increase the modularity, although I didn't do this at first because I figured iit would be unlikely that a shader dev would need to write their shader to do an albedo texture read without having code to do the rest of the standard pbr texture reads, since typically you'd just leave the un-wanted textures un-defined to achieve the same thing.
But from a code standpoint, it would certainly look more organized if each texture read were in its own function, so I will update the .glsllibs to put each texture read in its own function.
surface.NdotV = clamp(abs(dot(!surface.frontFacing?-surface.normal:surface.normal, surface.viewDir)), 0.001, 1.0); | ||
// surface.reflectedVec = normalize(reflect(-surface.viewDir, surface.normal)); | ||
|
||
surface.brightestLightStrength=0.0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Insert spaces around =
surface.normal, | ||
light.dir.xyz, | ||
surface.viewDir, | ||
light.color.rgb, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix indentation (lines 458 through 480)
|
||
#if NB_PROBES > 0 | ||
float probeNdfSum=0; | ||
float invProbeNdfSum=0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Insert spaces around =
@codex128 thanks for the review! You are right that extra compilation time is a potential issue with the new struct design riccardo added. I suspect the extra time should be negligible, but I will profile the shader to make sure (do you know if there is a simple jme shader profiler tool I can use to do this?). I also read all of your formatting suggestions, and I will edit the PR to fix all of the formatting mistakes you pointed out once I've checked the compilation time to make sure that the new struct system is not slowing anything down. (I just don't want to start making minor formatting changes again until I am sure that the file being reviewed is indeed going to remain, as I already did some formatting work that got deleted after riccardo's changes) In the event that the struct system is taking a significant amount of extra time to compile, the first half of this PR (the .glsllibs) can still be used and the struct functionality can be put on hold. In hindsight, I also should have had riccardo put the struct functionality in a separate PR and helped him work on that PR after this one gets merged. This PR has become somewhat of a mess trying to combine 2 new loosely related features (the .glsllibs and the struct functionality) into one mega PR. |
Another important thing to note before I do anymore work on this: After more consideration, I am still very firm in my original belief that these changes should be immediately applied to PBRLighting.frag, and an additional PBR shader in a new directory should NOT be created (as is currently the plan after riccardo's last changes to this PR). JME does not need an extra modularized PBR shader that requires extra maintaining. It needs 1 modularized PBR shader that is easy to test and maintain. I specifically made this PR to so that it would be less work to update 10 forks of PBRLighting anytime PBRLighting.frag gets a new feature or bug-fix on core. By making this into a new shader, that just adds one more extra place to make changes, and defeats the whole purpose of a modular system that only requires updates in 1 place. So if this is a deal breaker and others still think this should be a whole new shader, then I will close the PR and make these changes to the main PBRLighting shader the right way in my own project, the way I originally envisioned in order to solve the original issue. I feel that my efforts to share this PR have ended up causing the core point of this PR to be derailed and overlooked. |
I'll wait a few more days for anyone to comment with additional review, and then I will proceed making the final minor changes before I merge this PR. I aim to have this PR merged and ready for the second alpha release of 3.8 (3.8.0-alpha2) |
Addresses this issue: #2122
To re-summarize:
This PR extracts all of the texture reads and base PBR matParam assignment into a .glslib file (currently named PBRLightingParamReads.glsllib)
And then it also extracts all of the lighting calculation into a .glslib file (currently named PBRLighting.glsllib)
I also fixed alot of formatting and indentation mistakes, and overall reorganized the shader.
This should now make it as easy as possible for jme devs to fork PBRLighting to make changes, and they will no longer have to update the lighting or texReads to stay on par with master, as all future changes will all be in the glsllibs. This also reduces the chances that a lesser-skilled shader dev (or even skilled shader devs on a bad day) mistakenly mess up the lighting calculations when forking the shader.
Any feedback and review is greatly appreciated.