<div dir="ltr"><div>My experience with freewrl mixing appearance.material / backMaterial types:</div><div>- the old TwoSidedMaterial already implemented and working paved the way</div><div>- I just needed a bit of tinkering, and presto, I can do any combination of (front/back) no material, Material, UnlitMaterial and PhycalMaterial. I can even have no front material and assign something to backMaterial - and do it all in one pass in one shader:</div><a href="http://dug9.users.sourceforge.net/web3d/tests/PBR/sidedness.x3dv">http://dug9.users.sourceforge.net/web3d/tests/PBR/sidedness.x3dv</a><div><a href="http://dug9.users.sourceforge.net/web3d/tests/PBR/screenshot_sidedness.jpg">http://dug9.users.sourceforge.net/web3d/tests/PBR/screenshot_sidedness.jpg</a></div><div>- in the frag shader, first thing in main() I check gl_FrontFacing and mat = frontmat else mat = backmat, then use mat for all the getters like getDiffuse() getEmissive() and have a mat.type int for non,unlit,material,physical so I can do some if-else.</div><div><br></div><div>Before doing that, I tried two pass -a loop on the CPU side, with only one material, and switching the cull face -, but in freewrl I was making a mess, but I did see a bit of unlit on one side, and regular on the other side, proving it can be done if necessary:<br><a href="http://dug9.users.sourceforge.net/web3d/tests/PBR/lit_unlit_2_pass.jpg">http://dug9.users.sourceforge.net/web3d/tests/PBR/lit_unlit_2_pass.jpg</a><br></div><div><br></div><div>Hypothesis: for distributions with limited texture units, one idea is to use a textureArray sampler type. I haven't studied it but if something like that would save textureUnits then there might be no need for 2-pass.</div><div>-Doug Sanden</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Mar 19, 2020 at 9:33 AM Michalis Kamburelis <<a href="mailto:michalis.kambi@gmail.com">michalis.kambi@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Many, many thanks for this work, and for writing a detailed report<br>
summarizing the implementation experience. This is great! Very<br>
valuable to me, and I'm sure to other implementors too. And I'm very<br>
happy that you got these results so quickly (16 days for PBR rendering<br>
implementation is very quick, IMHO :) ).<br>
<br>
I looked at your code and I only noticed one thing:<br>
<a href="https://sourceforge.net/p/freewrl/git/ci/develop/tree/freex3d/src/lib/scenegraph/Component_Shape.c" rel="noreferrer" target="_blank">https://sourceforge.net/p/freewrl/git/ci/develop/tree/freex3d/src/lib/scenegraph/Component_Shape.c</a><br>
calls "baseColorTexture", but the node field should be just<br>
"baseTexture". This naming (without additional "Color" in the middle)<br>
looks a bit simpler, and is consistent with CommonSurfaceShader too.<br>
<br>
Regards,<br>
Michalis<br>
<br>
czw., 19 mar 2020 o 16:03 GPU Group <<a href="mailto:gpugroup@gmail.com" target="_blank">gpugroup@gmail.com</a>> napisał(a):<br>
><br>
> My experience implementing some of the PBR v4 features in freewrl:<br>
> - took 16 days<br>
> - I started by defining the PhysicalMaterial, UnlitMaterial and extending the Material node fields, using Michalis's documetation.<br>
> <a href="https://github.com/michaliskambi/x3d-tests/wiki/X3D-version-4:-New-features-of-materials,-lights-and-textures#new-x3dmaterialnode-node-with-emissive-and-normalmap-textures" rel="noreferrer" target="_blank">https://github.com/michaliskambi/x3d-tests/wiki/X3D-version-4:-New-features-of-materials,-lights-and-textures#new-x3dmaterialnode-node-with-emissive-and-normalmap-textures</a><br>
> - and internally extended structs in program and shader to hold all the new fields<br>
> - then most of the 2 weeks was getting the information flowing to the shader without breaking current functionality,<br>
> -- appearance.backMaterial - I spent a few days harmonizing TwoMaterialShader and this new approach<br>
> -- for the texture maps I found there ware lots of issues with old code assuming certain scenarios, and I spent about a week refactoring messy old code<br>
> - I found the khronos glTF sample had some interesting hints beyond physical, for example they use getter() functions in frag code that hides/abstracts the issue of whether or not there's a texture map.<br>
><br>
> <a href="https://github.com/KhronosGroup/glTF-Sample-Viewer/tree/master/src/shaders" rel="noreferrer" target="_blank">https://github.com/KhronosGroup/glTF-Sample-Viewer/tree/master/src/shaders</a><br>
><br>
> - see the metallic-roughness.frag<br>
><br>
> normal = getNormal();<br>
><br>
> And I refactored the frag shader to use getters like they do.<br>
><br>
> - I spent a few extra hours reading up on normal maps (which I learned are in 'tangent space' so need a transform matrix called TBN applied):<br>
><br>
> <a href="https://learnopengl.com/Advanced-Lighting/Normal-Mapping" rel="noreferrer" target="_blank">https://learnopengl.com/Advanced-Lighting/Normal-Mapping</a><br>
><br>
> - normal map normals are expressed in tangent space<br>
><br>
><br>
> Once I had getters, and had all the info flowing to the frag shader, then it only took a few days to do the metalic-roughness functionality.<br>
><br>
> If you have a loop where you are applying the lights, you probably have something like:<br>
><br>
> diffuse += ...<br>
><br>
> specular +=<br>
><br>
> ambient +=<br>
><br>
> inside the loop.<br>
><br>
> For metalic-roughness, I found I could replace those 3 with<br>
><br>
> shade = getPointShade(pointToLight, materialInfo, normal, view);<br>
><br>
> from the khronos example to make a PBR equivalent light loop.<br>
><br>
><br>
> So in hindsight, it would have been easy to start with the scalar PhyscialMaterial fields, and I could have added the texturemaps to the getters() later.<br>
><br>
> For those implementing for GLES < 3.0 where texture units are in short supply, the scalar part of PhysicalMaterial should be no problem.<br>
><br>
><br>
> I still have some minor tinkiering to do -when to apply gamma or its inverse, Michalis has given some answers. And field naming, textureTransform/textureCoordinate 'channel' field conventions, and I haven't attempted EnvironmentLight.<br>
><br>
> Results:<br>
><br>
> 1) PBR physics based rendering via PhysicalMaterial node<br>
>  - the lighting equations use roughness and metallic with baseColor<br>
> - (instead of specular, shininess and diffuseColor)<br>
> - and constrain to physics principle of 'conservation of energy'<br>
> <a href="http://dug9.users.sourceforge.net/web3d/tests/PBR/screenshot_pbr_teapots_view3dscene_freewrl.jpg" rel="noreferrer" target="_blank">http://dug9.users.sourceforge.net/web3d/tests/PBR/screenshot_pbr_teapots_view3dscene_freewrl.jpg</a><br>
> <a href="http://dug9.users.sourceforge.net/web3d/tests/PBR/metallic_roughness.x3dv" rel="noreferrer" target="_blank">http://dug9.users.sourceforge.net/web3d/tests/PBR/metallic_roughness.x3dv</a><br>
><br>
> 2) extended Material node - supports texture maps for normals, emissive, diffuse, specularShininess, ambient<br>
> <a href="http://dug9.users.sourceforge.net/web3d/tests/PBR/screenshot_e_mat_sphere240_view3dscene_freewrl.jpg" rel="noreferrer" target="_blank">http://dug9.users.sourceforge.net/web3d/tests/PBR/screenshot_e_mat_sphere240_view3dscene_freewrl.jpg</a><br>
> <a href="http://dug9.users.sourceforge.net/web3d/tests/PBR/sphere_240_fw.x3dv" rel="noreferrer" target="_blank">http://dug9.users.sourceforge.net/web3d/tests/PBR/sphere_240_fw.x3dv</a><br>
><br>
> The PhysicalMaterial node also supports texturemap for metallicRoughness although I haven't tested.<br>
><br>
> 3) UnlitMaterial - roughed in plumbing but haven't tested thoroughly - should work and support normal and emissive texture maps<br>
><br>
> freewrl code samples:<br>
> <a href="https://sourceforge.net/p/freewrl/git/ci/develop/tree/freex3d/src/lib/opengl/Compositing_Shaders.c" rel="noreferrer" target="_blank">https://sourceforge.net/p/freewrl/git/ci/develop/tree/freex3d/src/lib/opengl/Compositing_Shaders.c</a><br>
> L.1106 MaterialInfo and gamma functions from Khronos glTF example<br>
> L.1155 getNormal() and getter() farm starts<br>
> L.1300-1340 getting ready for apply_lights_physical<br>
> L.1806 apply_lights_physical code with khronos glTF sample functions, followed by freewrl light loop calling shade = pointShade(...) L.1917<br>
>  <a href="https://sourceforge.net/p/freewrl/git/ci/develop/tree/freex3d/src/lib/scenegraph/Component_Shape.c" rel="noreferrer" target="_blank">https://sourceforge.net/p/freewrl/git/ci/develop/tree/freex3d/src/lib/scenegraph/Component_Shape.c</a><br>
> L.1417 compile_PhysicalMaterial - organizes into internal structs and flags for sending to shader<br>
> _______________________________________________<br>
> x3d-public mailing list<br>
> <a href="mailto:x3d-public@web3d.org" target="_blank">x3d-public@web3d.org</a><br>
> <a href="http://web3d.org/mailman/listinfo/x3d-public_web3d.org" rel="noreferrer" target="_blank">http://web3d.org/mailman/listinfo/x3d-public_web3d.org</a><br>
</blockquote></div>