Request: Help with modernizing Elementalism's shaders

Ask about editing graphics, sounds, models, music, etc here!
Shaders (GLSL) and SNDINFO questions also go here!

Moderators: GZDoom Developers, Raze Developers

Forum rules
Before asking on how to use a ZDoom feature, read the ZDoom wiki first. If you still don't understand how to use a feature, then ask here.

Request: Help with modernizing Elementalism's shaders

Postby Bauul » Wed Mar 16, 2022 7:41 pm

Hello lovely people,

With the RC1 release of Elementalism, it's been pointed out that the shaders I have been using are out of date, to the extent that they might not even work properly with 4.8 when it releases.

I know basically nothing about writing shaders, and had cobbled most of these together from bits and pieces I found online back in 2018. Apparently these use some rather old approaches that are not future proof, but I don't know what exactly. So I was hoping that a kind soul here might have a few minutes to look through these and update them where anything is out of date?

The shaders are:

https://pastebin.com/iM5q4hLs - a sort of bump mappy, parallax-mappy thingy for icky flesh textures
https://pastebin.com/yjpfmMJq - an environment-mapping warpy shader for water textures
https://pastebin.com/UAEbGZSj - a simple warping shader I use on some flesh-sprites
https://pastebin.com/91bNHMY9 and https://pastebin.com/r7mDCtGR - two halves of a screenspace blur shader, used to accompany a couple of big explosions
https://pastebin.com/wTZQ0PqT and https://pastebin.com/dHTDxtKz - two halves of an screenspace warping shader, used when the player goes underwater

All of these currently work in 4.7.1, and I don't want the end result changed at all. I would just forever be grateful if anyone was able to review the syntax and post any modernization changes that would need to be made to make the future proof.

Thank you in advance to anyone who is able to help!
Last edited by Bauul on Thu Mar 17, 2022 12:04 am, edited 1 time in total.
Bauul
 
Joined: 29 Aug 2016

Re: Request: Help with modernizing Elementalism's shaders

Postby Rachael » Wed Mar 16, 2022 10:22 pm

That is not correct at all. The shaders will work perfectly fine in 4.8, I don't know where you got that information but it is absolutely dead false. The shaders you have will not stop working.

The thing that has changed with post-process shaders is how they are changed in ZScript. Material shaders (i.e. object/texture shaders) are unchanged. However if you have tried out the OpenGL ES backend at some point they might accidentally be disabled. (They can be reenabled again by typing gl_customshader true in the console)

Instead of: playermobj.player.shader.SetEnabled("ShaderName") for example - change the playermobj.player.shader part to ppshader. So - ppShader.SetEnabled("ShaderName") Also this means the effects are global and affect every player. Uniforms undergo a similar change, with the exact same syntactic adjustment.

The player.shader.command functions in ZScript will also continue to work as long as your ZScript is set to an older version. Once you use 4.8 however, then the deprecation takes hold and you will have to use the new method.
User avatar
Rachael
^ walking stack of unfinished projects ^
Admin
 
Joined: 13 Jan 2004
Discord: Rachael#3767
Twitch ID: madamerachelle
Github ID: madame-rachelle

Re: Request: Help with modernizing Elementalism's shaders

Postby Bauul » Wed Mar 16, 2022 11:58 pm

That's fantastic news, thanks for reviewing them Rachael! That's a big relief!

To confirm it was Graf who suggested the shaders needed updating, he said:

"A technical note: While looking at the shaders I noticed that there's still several that use the broken and deprecated ProcessMaterial function instead of the future-proof SetupMaterial replacement. I strongly recommend to rewrite those shaders to the new interface to ensure that they continue working in the future. ProcessMaterial has a serious design flaw that is not fixable, so it should be restricted to old mods that are done and not updated anymore."

I could find at least one of the above shaders (the first one) that uses "ProcessMaterial" (to the extent those words appear in the shader - I don't know what they do exactly). There was also one shader, the second one in the list above, that someone told me a few weeks ago was using outdated methods and needed to be updated. Additionally at least one shader (not one above, I've since gotten rid of it) was non-functional in a 4.8 dev build, so in light if all this feedback I thought it was safer to just post all of them and hopefully someone could review and let me know what needed updating.

So do I not need to worry about ProcessMaterial? That's fantastic news if so! And the others look good too? That's a great weight off my shoulders!

I did look at the ZScript you mentioned. I do have a couple of post-process shaders being called through it, specifically:

Code: Select allExpand view
class WaterHandler : StaticEventHandler {
   override void RenderOverlay(RenderEvent e) {
      // set the player's timer up correctly (more-than-1-tick precision)
      PlayerInfo p = players[consoleplayer];
      Shader.SetUniform1f(p, "watershader", "timer", gametic + e.FracTic);
      
      if (p.mo.waterlevel >= 3) {
         Shader.SetEnabled(p, "watershader", true);
         Shader.SetEnabled(p, "waterzoomshader", true);
         double effectSize = CVar.GetCVar("uw_effectsize", p).GetFloat();
         Shader.SetUniform1f(p, "watershader", "waterFactor", effectSize);
         Shader.SetUniform1f(p, "waterzoomshader", "zoomFactor", 1 - (effectSize * 2));
      }
      else {
         Shader.SetEnabled(p, "watershader", false);
         Shader.SetEnabled(p, "waterzoomshader", false);
      }
   }
}


and

Code: Select allExpand view
class RoarController {
   static void setRoarSize(Actor mo, int size) {
      if (mo != NULL && mo.player != NULL) {
         if (size != 0) {
            Shader.setEnabled(mo.player, "Roar_RadialBlurShader", true);
            Shader.setEnabled(mo.player, "Roar_ZoomShader", true);
         }
         else {
            Shader.setEnabled(mo.player, "Roar_RadialBlurShader", false);
            Shader.setEnabled(mo.player, "Roar_ZoomShader", false);
         }
         
         Shader.setUniform1i(mo.player, "Roar_RadialBlurShader", "blurSize", size);
         Shader.setUniform1i(mo.player, "Roar_ZoomShader", "blurSize", size);
      }
   }
}


Are these using the old method you outlined above? I can't see "player.shader" anywhere but I appreciate it's not always a 1-1 in terms of the coding.

Thanks again for your help!
Bauul
 
Joined: 29 Aug 2016

Re: Request: Help with modernizing Elementalism's shaders

Postby Rachael » Thu Mar 17, 2022 12:42 am

Oh, I see - well if Graf says ProcessMaterial is being deprecated, then yeah, it does need to be updated. I'll take a look when I get a chance to see if I can update it as per his specs that he gave you.
User avatar
Rachael
^ walking stack of unfinished projects ^
Admin
 
Joined: 13 Jan 2004
Discord: Rachael#3767
Twitch ID: madamerachelle
Github ID: madame-rachelle

Re: Request: Help with modernizing Elementalism's shaders

Postby Nash » Thu Mar 17, 2022 12:55 am

Converting ProcessMaterial to SetupMaterial should be very easy. It's just a matter of changing the function signature (returning void instead of Material), and then assigning the values of each member of the material inside the function itself.

Here's an example I posted in #materials in the Discord server.

Code: Select allExpand view

void SetupMaterial
(inout Material mat)
{
    vec2 texCoord = vTexCoord.st;
    mat.Base = getTexel(texCoord);
    mat.Normal = ApplyNormalMap(texCoord);
#if defined(SPECULAR)
    mat.Specular = texture(speculartexture, texCoord).rgb;
    mat.Glossiness = uSpecularMaterial.x;
    mat.SpecularLevel = uSpecularMaterial.y;
#endif
#if defined(PBR)
    mat.Metallic = texture(metallictexture, texCoord).r;
    mat.Roughness = texture(roughnesstexture, texCoord).r;
    mat.AO = texture(aotexture, texCoord).r;
#endif
    mat.Bright = texture(brighttexture, texCoord);
}
 


This is a base template custom shader that does nothing (in other words, it's exactly what GZDoom is doing by default). It's a good starting point for a custom material shader. What you do from here on is up to you.

It should be self explanatory and straight-forward. Do whatever you want with mat's members to manipulate the various material parameters


Finally, here's some documentation by dpJudas from back in the day:

Code: Select allExpand view

    SPECULAR will be defined if the shader is being compiled for a specular material
.
    PBR will be defined for PBR materials.
    BRIGHTMAP will also be defined if it is using a brightmap texture.

    The following textures will be defined depending on the type of material:
        tex
        brighttexture
        speculartexture
        metallictexture
        roughnesstexture
        aotexture

    The helper functions getTexel and ApplyNormalMap can also be used
.

    The material struct looks like this:

    struct Material
    
{
        vec4 Base;
        vec4 Bright;
        vec3 Normal;
        vec3 Specular;
        float Glossiness;
        float SpecularLevel;
        float Metallic;
        float Roughness;
        float AO;
    };
 

User avatar
Nash
AKA Nash Muhandes! Twitter/Facebook/Youtube: nashmuhandes
 
 
 
Joined: 27 Oct 2003
Location: Kuala Lumpur, Malaysia
Twitch ID: nashmuhandes
Github ID: nashmuhandes

Re: Request: Help with modernizing Elementalism's shaders

Postby Nash » Thu Mar 17, 2022 12:59 am

Code: Select allExpand view
//===========================================================================
//
// BEFORE
//
//===========================================================================

Material ProcessMaterial()
{
    mat3 tbn = GetTBN();
    vec2 texCoord = ParallaxMap(tbn);

    Material material;
    material.Base = getTexel(texCoord);
    material.Normal = GetBumpedNormal(tbn, texCoord);
#if defined(SPECULAR)
    material.Specular = texture(speculartexture, texCoord).rgb;
    material.Glossiness = uSpecularMaterial.x;
    material.SpecularLevel = uSpecularMaterial.y;
#endif
#if defined(PBR)
    material.Metallic = texture(metallictexture, texCoord).r;
    material.Roughness = texture(roughnesstexture, texCoord).r;
    material.AO = texture(aotexture, texCoord).r;
#endif
#if defined(BRIGHTMAP)
    material.Bright = texture(brighttexture, texCoord);
#endif
    return material;
}

//===========================================================================
//
// AFTER
//
//===========================================================================

void SetupMaterial(inout Material mat)
{
    mat3 tbn = GetTBN();
    vec2 texCoord = ParallaxMap(tbn);

    mat.Base = getTexel(texCoord);
    mat.Normal = GetBumpedNormal(tbn, texCoord);
#if defined(SPECULAR)
    mat.Specular = texture(speculartexture, texCoord).rgb;
    mat.Glossiness = uSpecularMaterial.x;
    mat.SpecularLevel = uSpecularMaterial.y;
#endif
#if defined(PBR)
    mat.Metallic = texture(metallictexture, texCoord).r;
    mat.Roughness = texture(roughnesstexture, texCoord).r;
    mat.AO = texture(aotexture, texCoord).r;
#endif
#if defined(BRIGHTMAP)
    mat.Bright = texture(brighttexture, texCoord);
#endif
}
 


Before/after conversion. Very simple. I apologize in advance though that I can't commit to doing the entire thing, but hopefully this serves to demonstrate how it can be done by anyone regardless of experience. :)
Last edited by Nash on Sat Mar 19, 2022 12:55 pm, edited 1 time in total.
User avatar
Nash
AKA Nash Muhandes! Twitter/Facebook/Youtube: nashmuhandes
 
 
 
Joined: 27 Oct 2003
Location: Kuala Lumpur, Malaysia
Twitch ID: nashmuhandes
Github ID: nashmuhandes

Re: Request: Help with modernizing Elementalism's shaders

Postby SanyaWaffles » Thu Mar 17, 2022 8:04 pm

Rachael wrote:Instead of: playermobj.player.shader.SetEnabled("ShaderName") for example - change the playermobj.player.shader part to ppshader. So - ppShader.SetEnabled("ShaderName") Also this means the effects are global and affect every player.


What if you want a postprocessing shader to only affect one player? Some post-processing shaders should not affect all players, like colorblind shaders. Seems kind of counter intuitive for things like that.
User avatar
SanyaWaffles
Certified Heretic and Grill Champion
 
Joined: 25 Apr 2013
Location: Disappointment Island
Discord: SanyaWaffles#0950
Twitch ID: sanyawaffles
Operating System: Windows 11
OS Test Version: No (Using Stable Public Version)
Graphics Processor: nVidia with Vulkan support

Re: Request: Help with modernizing Elementalism's shaders

Postby Rachael » Thu Mar 17, 2022 8:29 pm

The old way of handling that was not quite the proper way. All it did was check to see if the calling player number was the same as consoleplayer. A more preferred way to do it would have been to create uniform copies for each player actor - that way the correct uniform set can be activated when F12 spy-camming to each one in a multiplayer game - but that is not how it works currently.

If you really want you can make a wrapper function (incidentally, doing what the deprecated support functions in the player info class do), which adds that same check - but - consider it unsupported and likely to be problematic.

It might be safe to export the playerpawn's spytarget as a native pointer so that the preferred method can be done manually on the zscript side. From my observations that is sent over network games anyhow.
User avatar
Rachael
^ walking stack of unfinished projects ^
Admin
 
Joined: 13 Jan 2004
Discord: Rachael#3767
Twitch ID: madamerachelle
Github ID: madame-rachelle

Re: Request: Help with modernizing Elementalism's shaders

Postby Bauul » Fri Mar 18, 2022 9:26 am

Nash wrote:
Code: Select allExpand view
//===========================================================================
//
// BEFORE
//
//===========================================================================

Material ProcessMaterial()
{
    mat3 tbn = GetTBN();
    vec2 texCoord = ParallaxMap(tbn);

    Material material;
    material.Base = getTexel(texCoord);
    material.Normal = GetBumpedNormal(tbn, texCoord);
#if defined(SPECULAR)
    material.Specular = texture(speculartexture, texCoord).rgb;
    material.Glossiness = uSpecularMaterial.x;
    material.SpecularLevel = uSpecularMaterial.y;
#endif
#if defined(PBR)
    material.Metallic = texture(metallictexture, texCoord).r;
    material.Roughness = texture(roughnesstexture, texCoord).r;
    material.AO = texture(aotexture, texCoord).r;
#endif
#if defined(BRIGHTMAP)
    material.Bright = texture(brighttexture, texCoord);
#endif
    return material;
}

//===========================================================================
//
// AFTER
//
//===========================================================================

void ProcessMaterial(inout Material mat)
{
    mat3 tbn = GetTBN();
    vec2 texCoord = ParallaxMap(tbn);

    mat.Base = getTexel(texCoord);
    mat.Normal = GetBumpedNormal(tbn, texCoord);
#if defined(SPECULAR)
    mat.Specular = texture(speculartexture, texCoord).rgb;
    mat.Glossiness = uSpecularMaterial.x;
    mat.SpecularLevel = uSpecularMaterial.y;
#endif
#if defined(PBR)
    mat.Metallic = texture(metallictexture, texCoord).r;
    mat.Roughness = texture(roughnesstexture, texCoord).r;
    mat.AO = texture(aotexture, texCoord).r;
#endif
#if defined(BRIGHTMAP)
    mat.Bright = texture(brighttexture, texCoord);
#endif
}
 


Before/after conversion. Very simple. I apologize in advance though that I can't commit to doing the entire thing, but hopefully this serves to demonstrate how it can be done by anyone regardless of experience. :)


Thanks for outlining the required changes Nash, this was incredibly helpful for someone with very little coding skill. I needed to swap out "void ProcessMaterial" for "void SetupMaterial" in the first line of your fixed version, but otherwise it works like a charm.

Looking through the rest of the shaders I think that was the only instance where ProcessMaterial appeared, so unless there's any other instances of older syntax in the above shaders (which based on the discussion so far it doesn't seem there is) I think we're all set!

Thanks for everyone's help, it's immensely appreciated!
Bauul
 
Joined: 29 Aug 2016

Re: Request: Help with modernizing Elementalism's shaders

Postby Enjay » Fri Mar 18, 2022 12:13 pm

Sorry to piggyback onto the thread with my own question, but it seems relevant/related.

Nash wrote:hopefully this serves to demonstrate how it can be done by anyone regardless of experience. :)

There is a saying that I am fond of: if you make something idiot proof, then someone will just invent a better idiot.

I am that idiot.

The following shader uses ProcessMaterial but all of my attempts to change it result in failed compilations. Can anyone figure out what should be changed to modernise it?


Code: Select allExpand view
mat3 GetTBN();
uniform float timer;
vec3 GetBumpedNormal(mat3 tbn, vec2 texcoord);

Material ProcessMaterial()
{
    mat3 tbn = GetTBN();
    vec2 texCoord = vTexCoord.st;

    Material material;
    vec4 addEnv = texture(glowscan, ((pixelpos.xyz).xy + (timer*30)) * 0.01);
    
    material
.Base = getTexel(texCoord);
    material.Base.+= addEnv.r;
    material.Base.+= addEnv.g;
    material.Base.+= addEnv.b;
    
    material
.Normal = GetBumpedNormal(tbn, texCoord);
    
    
#if defined(SPECULAR)
    material.Specular = texture(speculartexture, texCoord).rgb;
    material.Glossiness = uSpecularMaterial.x;
    material.SpecularLevel = uSpecularMaterial.y;
#endif
#if defined(PBR)
    material.Metallic = texture(metallictexture, texCoord).r;
    material.Roughness = texture(roughnesstexture, texCoord).r;
    material.AO = texture(aotexture, texCoord).r;
#endif
    material.Bright = addEnv;
    return material;

}

mat3 GetTBN()
{
    vec3 n = normalize(vWorldNormal.xyz);
    vec3 p = pixelpos.xyz;
    vec2 uv = vTexCoord.st;

    vec3 dp1 = dFdx(p);
    vec3 dp2 = dFdy(p);
    vec2 duv1 = dFdx(uv);
    vec2 duv2 = dFdy(uv);

    vec3 dp2perp = cross(n, dp2);
    vec3 dp1perp = cross(dp1, n);
    vec3 t = dp2perp * duv1.+ dp1perp * duv2.x;
    vec3 b = dp2perp * duv1.+ dp1perp * duv2.y;

    float invmax = inversesqrt(max(dot(t,t), dot(b,b)));
    return mat3(* invmax, b * invmax, n);
}

vec3 GetBumpedNormal(mat3 tbn, vec2 texcoord)
{
#if defined(NORMALMAP)
    vec3 map = texture(normaltexture, texcoord).xyz;
    map = map * 255./127. - 128./127.;
    map.xy *= vec2(0.5, -0.5);
    return normalize(tbn * map);
#else
    return normalize(vWorldNormal.xyz);
#endif
}
User avatar
Enjay
Everyone is a moon, and has a dark side which he never shows to anybody. Twain
 
 
 
Joined: 15 Jul 2003
Location: Scotland

Re: Request: Help with modernizing Elementalism's shaders

Postby Nash » Sat Mar 19, 2022 1:01 pm

Bauul wrote:I needed to swap out "void ProcessMaterial" for "void SetupMaterial" in the first line of your fixed version


Woops! That was a copy/paste error on my part. It indeed should have been "void SetupMaterial". I've edited the original post.

@Enjay:

This should be all that's needed:

Code: Select allExpand view

void SetupMaterial
(inout Material mat)
{
    mat3 tbn = GetTBN();
    vec2 texCoord = vTexCoord.st;

    vec4 addEnv = texture(glowscan, ((pixelpos.xyz).xy + (timer*30)) * 0.01);

    mat.Base = getTexel(texCoord);
    mat.Base.+= addEnv.r;
    mat.Base.+= addEnv.g;
    mat.Base.+= addEnv.b;

    mat.Normal = GetBumpedNormal(tbn, texCoord);


#if defined(SPECULAR)
    mat.Specular = texture(speculartexture, texCoord).rgb;
    mat.Glossiness = uSpecularmat.x;
    mat.SpecularLevel = uSpecularmat.y;
#endif
#if defined(PBR)
    mat.Metallic = texture(metallictexture, texCoord).r;
    mat.Roughness = texture(roughnesstexture, texCoord).r;
    mat.AO = texture(aotexture, texCoord).r;
#endif
    mat.Bright = addEnv;
}
 


Here's a comparison shot, for learning purposes. :D

Last edited by Nash on Sat Mar 19, 2022 1:51 pm, edited 1 time in total.
User avatar
Nash
AKA Nash Muhandes! Twitter/Facebook/Youtube: nashmuhandes
 
 
 
Joined: 27 Oct 2003
Location: Kuala Lumpur, Malaysia
Twitch ID: nashmuhandes
Github ID: nashmuhandes

Re: Request: Help with modernizing Elementalism's shaders

Postby Enjay » Sat Mar 19, 2022 1:33 pm

Thanks, but I guess I must be doing something wrong:
Code: Select allExpand view
**** DIED WITH FATAL ERROR:
Shader 'glowscan' could not be compiled:
ERROR: 0:31: 'material' : undeclared identifier
ERROR: 0:31: 'return' : void function cannot return a value
ERROR: 0:31: '' : compilation terminated
ERROR: 3 compilation errors.  No code generated.

I'm pretty sure that my file looks like your screenshot.

edit: I might have figured the material one out. Shaders are case sensitive, right?, and there is Material and material in there.

Making them agree now gives me:
Code: Select allExpand view
**** DIED WITH FATAL ERROR:
Shader 'glowscan' could not be compiled:
ERROR: 0:31: '' :  syntax error, unexpected SEMICOLON, expecting LEFT_PAREN
ERROR: 1 compilation errors.  No code generated.


I've been spoiled by GZDoom's very clear error messages with line numbers. Got to look for that semicolon...
User avatar
Enjay
Everyone is a moon, and has a dark side which he never shows to anybody. Twain
 
 
 
Joined: 15 Jul 2003
Location: Scotland

Re: Request: Help with modernizing Elementalism's shaders

Postby Nash » Sat Mar 19, 2022 1:52 pm

Enjay: sorry, again, copy/paste error strikes again, I've edited the post (and the screenshot).

I forgot to remove the "return" command in the SetupMaterial version.

And yes, GLSL is absolutely case sensitive.
User avatar
Nash
AKA Nash Muhandes! Twitter/Facebook/Youtube: nashmuhandes
 
 
 
Joined: 27 Oct 2003
Location: Kuala Lumpur, Malaysia
Twitch ID: nashmuhandes
Github ID: nashmuhandes

Re: Request: Help with modernizing Elementalism's shaders

Postby Enjay » Sat Mar 19, 2022 1:57 pm

No worries, help is always appreciated and your fixed code works just fine now. Thank you kindly. :)
User avatar
Enjay
Everyone is a moon, and has a dark side which he never shows to anybody. Twain
 
 
 
Joined: 15 Jul 2003
Location: Scotland


Return to Assets (and other stuff)

Who is online

Users browsing this forum: No registered users and 2 guests