• A Guide on Metalness PBR to SFM and Garry's Mod
    25 replies, posted
Remember how I was supposed to write this guide 2 and a half months ago? This is another guide to pseudo-pbr materials for those of us that still use the garbage that is source for whatever reason. If you've gone through the last tutorial I made for this then good news this new method is both better in nearly all aspects and faster to setup. Unlike the last guide this one is not specific to overwatch. This is for metalness pbr materials in general. To quote the last time I wrote a guide: "The term method in the context of this tutorial deserves a short explanation. A method would be a general series of steps followed to get a desired result. The number afterwards represents a complete revision of the previous method that achieved more than marginally better results. It does not increase if the results were equal, worse, or only a slight improvement. This contrived notation exist only because it was no longer feasible to refer to the number of times I've entirely redone individual models." Last thread was 21b. This one is 34c. Vast improvements have been made over the last 2 years. This guide is written under the assumption you already have experience importing models and materials into source. I will not cover anything outside the setup for materials, textures, and stacking. On that note. Stacking (or the colored specular method as we used to call it) is the act of having duplicates of the same model over itself without z-fighting. Sounds complicated. It isn't. To stack a model all you do is export it, change the materials, and export again as a different smd. From there you toss them in your qc depending on what order you want them to draw. Looks a little something like this: $model "Temp" "horntest.smd"    //    Draws first $model "Temp" "horntest2.smd"    //    Draws second $model "Temp" "horntest3.smd"    //    Draws last The only thing you need to watch out for is if the exported smd have enough verts where your compiler will try to split it into multiple models. I don't have an exact number but the compiler tends to do that to smd around or above 18k verts. You'll get z-fighting if this happens so try to split up complicated mesh into their own stacks. If your model is simple enough you can even fit all the stacks in a single smd. Which is how you can get away with bodygroups and flexes. With that said on to the guide itself. Video Guide: The entire guide compressed into 4 minutes pretty much. https://www.youtube.com/watch?v=tzej0FcOeUY Written Guide: For those of you who like walls of text as much as I do. Start this part of the guide once you have you model all setup for export. It may be worth it to do a few test export and compiles just to see if you got the smoothing and such right before you move on to stacking. Once you've ironed that out set up a bunch of dummy image files that you'll assign materials with. The number and names depends on what you're porting to. For SFM: Make 3 stacks. Ordered your base material first, metallic material second, and CH material last. For Garrysmod: Make 5 stacks. Ordered your base material first, metallic material second, R material third, G material fourth, and B material last. R, G, and B stand for red green blue if you're curious. Garrysmod is missing the CH shader so we gotta make do. If you really want to be accurate give it 6 stacks and put a dif material ahead of what would have been your base material. The dif material must draw first with 6 stacks. All 6 stacking does is slightly improve diffuse so it probably isn't worth doing. Especially if you plan on throwing whatever you're making on to the workshop. Go ahead and compile. If you get a 'splitting into multiple models' warning cut your model into more smd and re-export. load up your model in hlmv and give it a few dummy materials in order to check for z-fighting. Make layers invisible using $no_draw 1 in the vmt to help with that. Now that the model part is out of the way it's time to move into photoshop. First you gotta identify all the mask you got on hand. The following are mandatory: -Albedo -Normal -Metalness -Roughness or Gloss The next few maps should be used if you have them: -Ambient Occlusion -Cavity (Extremely uncommon) -Specular (Uncommon) Just for visual reference here's some labeled maps so you have a vague idea what you're looking for. https://files.facepunch.com/forum/upload/107180/78245e67-95cb-4aa2-8f5b-d20f14cbda1f/Mesh 19 Default.jpg Any mask not part of the above 8 won't be touched on so it's up to you to figure out how to use them. Once you've identified them toss them into photoshop and for your own convenience have them opened separately. Find your roughness or gloss. Figure out which it is. If it's a roughness invert it (ctrl+i) so it becomes a gloss map. If it's already a gloss map just leave it as is. Duplicate your gloss. Apply levels (ctrl+L) to one of them. It will have 3 input boxes and 2 output boxes. In the middle input box enter 0.6. In the left output box enter 10. Click ok. If you have a cavity map: Multiply your cavity over the gloss you just leveled. Merge the layers. If you have a specular map: Mask your specular by an inverted metallic map and multiply over the gloss you just leveled. Merge the layers. Now copy your leveled gloss and paste it into your normalmap alpha. Save as normalmap. Copy your metalness. Return to your leveled gloss and paste the metalness, invert it, apply levels, in the middle input box enter 0.4545, click ok, invert again, and mulitply over the gloss. Merge the two layers. *Optional* If you have an ambient occlusion map: Multiply the ao over the gloss. Merge the layers. If you have an opacity map: Multiply the opacity over the gloss. Merge the layers. (This step is only if you have $alphatest bits. See troubleshooting at the bottom) For SFM: Copy the result and paste it into its own red channel. Fill the green and blue channels with pure black. Save as CH. For Garrysmod: Garrysmod can't use a CH mask. Instead copy and paste your albedo overtop and multiply it. Now for the sort of tedious part. Copy the red channel into the alpha and save as R. Copy the green channel into the alpha and save as G. Copy the blue channel into the alpha and save as B. Go back to your other untouched gloss and apply levels. In the middle input box enter 0.24. Click ok. Copy this gloss and paste it into its own red channel. Fill the green and blue channels with pure white. Save as exponent. Copy your metalness again. Paste it in your albedo alpha. If you have an opacity map: Multiply opacity over metalness. Merge the layers. Toss the result in the albedo alpha. (This step is only if you have $alphatest bits. See troubleshooting at the bottom) If you have an ambient occlusion map: Multiply ao over albedo mask by an inverted metalness. Merge the layers. If you have a cavity map: Set cavity to 50% opacity. Multiply over albedo mask by an inverted metalness. Merge the layers. Save as diffuse. You should be left with 4 textures if you're porting for sfm or 6 for garrysmod. Make them into vtf with the following formats: -Save diffuse as DXT5 -Save normalmap as BGRA8888. Or if you normalmap is either flat or incredibly simple save as DXT5 -Save exponent as DXT1. If this ends up looking too poor save instead as BGR888 -Save CH as DXT1 -Save R, G, and B as DXT5 Have generate mipmaps disabled for sfm vtf but enabled for garrysmod ones. Do not save in vtf version 7.5 for garrysmod. The last step is the vmt. Which I've already made so you're pretty much done already. All you have to do with them is rename them and enter the path to vtf. VMT for SFM. Includes the following templates: -Base material -Base material for if you had a specular -Base material ($alphatest) -Base material for if you had a specular ($alphatest) -Metallic material -CH material -A couple cubemaps I like to use VMT for Garrysmod. Includes the following templates: -Base material -Base material for if you had a specular -Base material ($alphatest) -Base material for if you had a specular ($alphatest) -Metallic material -R material -G material -B material -Dif material for 6 stack -Dif material for 6 stack ($alphatest) -Base material for 6 stack -Base material for 6 stack for if you had a specular Once that's all filled in you're done. Congrats. You better not have touched the boost or fresnel parameters. I won't be mad. Just disappointed. Troubleshooting: These steps won't work for everything obviously. So here's some pre-emptive work around for the 2 biggest problems you may run into. Transparency: Or more specifically any transparent portion with a blend of metal and non metal on them. If the two don't mix just modify one of the existing material templates and use that. This is the nasty one since 34 uses translucent for the metal material. This leads to two problems. First. Flashlights (and sfm lights since they're just altered flashlights) will add 2 intersecting translucent layers together rather than occlude one behind the other. Basically if I have a red material behind a blue material it's gonna show up as purple when you throw a light on it. The second problem is our basealpha is using a metalness map. Which makes alphatest materials sort of annoying. If you do run into anything like this make a copy of your basetexture. Toss the transparency mask in the alpha. Paste the metalness overtop the basetexture, invert it, set to mulitply, and merge. Save as diffuse_alpha or something. Just don't replace your old diffuse. Import as DXT5 just like the regular diffuse. Next would be giving the transparent bits (the whole element. Not just the individual tri with alpha) their own unique base material in the first stack. Template for that are already included with the rest. Now ideally the new basetexture and base layer of the stack would have the uv altered as to save memory but that's a beyond just a quick edit. Decals: Transparent cut outs are often used to add details or text to what would usually be mirrored bits of the model or areas otherwise too low res to retain readability. 34 has issues with decals over metallic parts of the model as decals tend to use translucent and thus won't occlude each other if they're intersecting. Fixing this is relatively simple. Just lightly push out the decals sitting on the metal bits so there's a little space between them. Doesn't need to be that much. Next. Make sure the decal smd in the qc are below pretty much every other smd. Problem solved. You've made it to the end of the guide. As with last time I'm supplying the example model used in the guide for reference. Lunarscythe SFM Lunarscythe Garrysmod If you have any questions feel free to ask. Or don't. I'm not a cop. Gallery: We tested the shit out of 34 with resources from a lot of different sources. Including retrofitting it on to older ports that were already stacked. This isn't every one of them mind you. This isn't even a third of them. Just a handful of examples I got permission to show to give you an idea of how 34 holds up. My personal examples: https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/intermediary/f/ee44936a-8a19-4a3b-a10a-c2263997636a/dct0b1o-41defdd8-573b-4b67-8c98-1216df241523.jpg https://orig00.deviantart.net/ae9e/f/2018/289/d/e/zerins_stiletto_34_by_blueflytrap998-dcpkgz0.jpg https://files.facepunch.com/forum/upload/107180/7dce9558-9ee2-429a-81ea-47cbf6ad6ad0/lvnswrd34.jpg https://files.facepunch.com/forum/upload/107180/bf2e16a4-cfca-4874-bc88-4efdd97dbc6e/lnswrd34_xie.jpg Sundown/Ageha's examples: https://files.facepunch.com/forum/upload/107180/19a52c43-2f44-4b3d-84c6-f5f6425b0a53/dcrinyy-6ef2a0e9-9af2-4ddc-98f0-1d0ea60c1047.jpg https://files.facepunch.com/forum/upload/107180/a5175434-719a-4c87-b806-c12a06f80625/mg1736p.jpg https://files.facepunch.com/forum/upload/107180/1f9e5e55-6d7e-43b3-a2b8-03d81b008786/dcufpor-e38e6cde-60f1-4860-a718-b3eb5a5ead92.jpg Edd's examples: https://files.facepunch.com/forum/upload/107180/0934eafb-ee5d-408c-9392-8a2ec909ad69/cocada.jpg https://files.facepunch.com/forum/upload/107180/7ad3aa61-8995-47df-a5e0-ace1a05f74f4/Pescado.jpg https://files.facepunch.com/forum/upload/107180/28ea9b64-e945-48c7-98cd-4d7e47e112f6/preview_B.O.B.jpg https://files.facepunch.com/forum/upload/107180/0ab9e0fc-f8fd-48aa-b0ec-5bb37c531abf/B.O.Bb.jpg https://files.facepunch.com/forum/upload/107180/927adb36-8c0c-42be-8690-c971a4ec2976/doomfist.jpg https://files.facepunch.com/forum/upload/107180/32b1cd8d-2303-4516-9e9f-698c34f068cf/Trooper.jpg https://files.facepunch.com/forum/upload/107180/d30f0dab-020a-42a1-9caa-49c06f4fabc1/Enforcer.jpg https://files.facepunch.com/forum/upload/107180/0012f3b1-ea92-4df2-a4af-d3d7eb4382a1/Reaper_Primary.jpg Tester shots: https://files.facepunch.com/forum/upload/107180/fcf9d9e5-2b05-467b-b04d-f32cedc7ddd2/1583518333_preview_merc_guts000000 zest.jpg https://files.facepunch.com/forum/upload/107180/5a3c6983-654d-4e58-9bbb-61c2264f1d4e/1583518333_preview_falcon_guts000000 zest.jpg Artwork by Zestalicious https://files.facepunch.com/forum/upload/107180/53f9d60b-4e7b-4bd6-bc60-52a840fc93f9/bobs_borger.jpg Artwork by Leg4Me/Legoformer1000 https://files.facepunch.com/forum/upload/107180/1222067a-768b-4100-a0c5-c8cfd32ded55/1565270609_preview_spider_leap_by_its_midnight_reaper-dcqhmlq.jpg https://files.facepunch.com/forum/upload/107180/7bbbd190-41a6-4019-94d6-944bd926ee21/midnight mccree.jpg https://files.facepunch.com/forum/upload/107180/1e051daa-fb54-49ea-a1ce-032d2116c31e/Supercharged.jpg Artwork by Midnight https://files.facepunch.com/forum/upload/107180/83eccc00-f9a2-4bf8-adc0-8e8143ed9a2a/vindicate mccree rsz.jpg Artwork by Vindicate
Cool. Just for the heck of it. The prototype material of the single pass gmod shader. Work in progress? Without roughness? Ugh. pseudo_pbr { $diffuse "dev\white_blk" // transparency in alpha $subsurf "dev\black_blk" // reverse "thickness" in alpha $normals "dev\noise_generic_bmpa" // rgb888 or dxtn $msrf "dev\msrf_test" // metalness, specularity, roughness, fresnel $emission "dev\emi" // emission color and strength $envmap "env_cubemap"// detail envmap with roughness + irradiance in the lod $normalsusedxtn 1 // 0Y0X rgba aka .ag swizzle encoded and renormalized $subsurfdoreverse 1 // do inverse normal shading with "thickness" blend $envmapdoibl 1 // use irradiance lod envmap for direct illumination $alphatestreference 128 $alphatest 0 $translucent 0 }
I'm stuck on this part. Where exactly do i need to paste the albedo? Over the leveled gloss? Can you please specify in this part what exact materials we should work with? (asking because video guide covers the SFM part only)
You'd toss the albedo over the leveled gloss, multiply, and merge as you said. From there you'd copy each individual channel into the alpha and save one by one until you have 3 resulting textures. This is just to get the color of the albedo for envmap reflections since garrysmod has no way of doing that natively. Envmaps lacking color variation is the second biggest reason they tend to look like total garbage in source. For anything with purely grey metals you can get away with just stealing 1 channel and removing the last 2 stacks from the model entirely. That's what I did on the example model if you look at the files. If possible could the roughness be moved to the green channel on that mask? The additional bit under compression would prevent the roughness from being completely mangled. I'd also personally drop the alpha entirely to cut the memory used for compressed textures in half. Fresnel tends to get tied to the roughness anyway.
Well, yes. And i'm still thinking to simplify the math. I had to read a bunch of optics and color theory. I could see roughness as a kinda microfacet that should maybe just balance the incoming light dispersion aka diffuse term and the general reflection formula. The falsely labeled fresnel was meant to be the ior, which may be needed to get a somewhat correct subsurface entry angle. Dunno if that works. The angle being iored seems weird. What i struggle with tho, is the energy levels and what should basicly be the materials relative spectral absorption aka what the color is or what may be transmitted thru it. And i somehow gotta balance that with a 'density something' or translucency to maybe make a somewhat working double sided lighting possible. That may be better suited for another (the vegi) shader tho. Ugh. Lots of stuff to think about. I need a break for today.
This is a really cool workaround! Is that also what the people behind Boryl Alyph do to have PBR working in source on their models, or are they using a different method?
Why did PBR explode in usage just in the past few years? I mean, it's good that the entire industry went this route, but I feel like something as desirable as this came too late. Looking back at the pre-PBR days, attempts to implement visual phenomena we now associate with PBR were often truly awful, yikes. One would think that recent advances in hardware have finally enabled developers to go physical, but even the last-gen consoles were retrofitted with PBR titles during their last years, often with excellent results considering their legacy status at that point (Trials: Fusion comes to mind).
To my knowledge Boryl Alyph as well as a number of other private source projects have implemented physical based shaders rather than what I've done. Their stuff only works in their personal sdk's. This is instead a stupidly convoluted workaround to both Valve locking down custom shaders in the sfm and a Garrysmod developer making it very clear no one is willing to touch what that engine branch already has. Well that and I found it amusing to do. Someone in the digital 3D art thread could probably answer that but I don't know nearly enough to give you an answer. Sorry.
Welp. I think i got some reference issues to think about. No default fresnel in cycles. Hadn't noticed this kinda crap. Metal is always 0 or 1? Is gold 100% smooth? This does not work, does it? We got a 'looking like' gold and a 'looking like' insulator. Both are somewhere inbetween values. No specular at all, still having it and color modulation and the roughness. Gotta love juggling bogus values. The perfect mirror still is a kinda extra. The packplating sure is ~100 silver and the lowest ior. Does that mean it does diffuse less that is the roughness then? A mirror sure looses a lil bit of energy still that is dissipated thru the ior of the air glass transition. That'd be physically correct? https://i.imgur.com/6vzai5p.jpg
Just a note: it's a good idea to save R, G and B textures as A8. Color channels in these are unused anyway ($color2 [0 0 0] and $additive) and result is not being compressed while having exactly same file size as DXT5.
In concept you're right. Problem is we're using source. Loaded in memory they would be the same but DXT5 is slightly smaller on disk even with the doubled filesize from the rgb channels that doesn't even get used. This weird discrepancy only happens with vtf. Blame Valve.
Did some tests with 2x2 pixel 4-color pattern tiled in 4k texture, the filesizes are exactly same. Both with mipmaps generated: https://files.facepunch.com/forum/upload/107163/f9808bf4-dcb0-4b5e-9877-245a3a1d2f78/explorer_2019-01-21_06-55-02.png And without them: https://files.facepunch.com/forum/upload/107163/0be76e8a-ad2a-499c-9966-8e3efe8e6939/explorer_2019-01-21_06-55-21.png
What's the point compressing single color channels into dxt5? You could use dxt1 and be smaller. Or just use all in RGBA8 textures. Easy. In dxt5 you can compress 2 channels. One in the green and one in the alpha for maximum precision. If you want to you can even compress specular and metalness like overwatch kinda does it. Basicly automatic metalness. Core specular range and everything above is 'added' metal logic, since metal is specular anyway. The other channel is simply roughness. None of this matters anyway, for source, cause you can't modify the shaders. You can't plug those seperated texture channels to the input slots.
https://files.facepunch.com/forum/upload/107180/65047444-acd8-47ce-9938-5cb7173c5dcc/image.png I did say there was only a slight difference. Less than 0.01%. But its there. Besides. You can double one of them as the exponent mask if that still holds up under compression which absolutely does save memory over using A8. This isn't that I am against using A8 for pseudo pbr stuff. For anything especially noisy it pretty much has to be used over DXT5. But for nearly everything else the visual difference is negligible and you're given up to 3 free texture to use elsewhere if need be.
Not sure what I did wrong here, but I can't seem to get the CH material to work: https://files.facepunch.com/forum/upload/212800/eb80e2a0-01f7-4a8e-aee2-867ab8e05667/yes.png Left side has CH enabled and shows a checkerboard pattern akin to missing a texture that manipulates the envmap (it doesn't look like the FO4 cubemap). Commenting out the $maskmap2 line (or just replacing the whole thing with nodraw) results in the right side of the image. SFM console output doesn't give me anything useful to start from.
Your $normalmap path is either incorrect or missing entirely. Customhero does not use $bumpmap like vertexlitgeneric does so if you've used that by mistake that would be it.
The VMT for the CH material in the download above uses $bumpmap instead of $normalmap. Changing that line fixed it. Somehow I missed that detail in the video.
So it is. I've updated the template link to fix it. Sorry about that.
Very useful guide. This made my some of my ports look alot nicer! https://files.facepunch.com/forum/upload/413270/0f9fd06e-968e-480d-9eaa-c67fd11f4054/gear4_cogw.png https://files.facepunch.com/forum/upload/413270/25fb64b8-81af-411c-a14a-90ed8c50e98a/gear4_locw.png I have a question as well, do you by chance have a guide for converting specular glossiness pbr to source or would I be better off taking some fundementals from this guide and pairing them with the colored specular method?
It would be pretty difficult to get satisfactory results using this guide as a base. Specifically because you're trying to go spec to metalness rather than metalness to spec. That doesn't work even outside of source. I was in the process of heavily revising the specular pbr to source workflow. But I've been commissioned and need to set it aside for now. No estimate for when I'll be done with either of those things.
Great stuff, are those from GoW4?
A test with some sten variant from cod ww2 https://files.facepunch.com/forum/upload/182239/6641f360-f8dc-4e5b-b1d8-4f267c8ff920/20181216184928_1.jpg
Not sure what I've done wrong here, but this doesn't look quite right... https://snag.gy/YBzVxA.jpg
You look to have referenced your exponent map as the basetexture for your metallic vmt.
Would it be possible to have this work for models that use RGB values for things like paint? Like let's say I have a car and it's default color is the base white color, and I wanted to apply a red paint, green, black, etc (Image related) https://files.facepunch.com/forum/upload/133754/3047cb1a-aa74-498d-a672-5671fcf6185c/scrolled.png Would I have to create different materials for each of paint or is anything possible through material proxies?
Best answer I can give is sort of. A separate guide and setup would be needed for that. Paintable elements would have to be their own material. Each paintable material would be extremely flexible and allow for control of not only color but physical properties. The catch is they would be unable to paint both metal and non metal bits in the same material. I do have a working example that shown below. Top is inengine results and bottom is all proxy disabled. https://cdn.discordapp.com/attachments/301540837764890626/511355359189925905/mxms34.jpg https://files.facepunch.com/forum/upload/107180/d9fa8490-72c3-4740-999e-a6f7733873de/llpxydbld.jpg
Sorry, you need to Log In to post a reply to this thread.