Materials (PBR, Specular, Normal maps)

Handy guides on how to do things, written by users for users.

Moderator: GZDoom Developers

Forum rules
Please don't start threads here asking for help. This forum is not for requesting guides, only for posting them. If you need help, the Editing forum is for you.

Re: Materials (PBR, Specular, Normal maps)

Postby Reinchard2 » Sat Sep 01, 2018 5:49 am

@Indecom I tried your new shader for parallax mapping, but I noticed this isn't compatible with pbr I guess? I mean when I use heightmaps with rest of my pbr maps like roughness/ao/normal my materials don't work with lights ingame at all. But when I use "glossines/specular level values in my gldefs my materials start working with lights, but thay don't read rougness map correctly. I mean I have something like this now:

material Texture "stargr1"
{
normal "materials/normalmaps/stargr1.tga"
specular "materials/specular/spec1.png"
metallic "materials/metallic/startan3.tga"
roughness "materials/roughness/stargr1.tga"
specularlevel 3
glossiness 10
Shader "shaders/texture/parallax.fp"

Texture tex_heightmap "materials/heightmaps/startan3.tga"
Define "Foobar"
}
In pbr I don't need specular map, but I noticed that this new shader works only if I specify some specular map for every material. Any tips?
Reinchard2
 
Joined: 21 Sep 2007
Location: Poland - Bytom

Re: Materials (PBR, Specular, Normal maps)

Postby dpJudas » Sat Sep 01, 2018 6:40 am

Here's an updated version of the shader that supports all the various material types (normal, specular, pbr):

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

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;
}

// Tangent/bitangent/normal space to world space transform matrix
mat3 GetTBN()
{
    vec3 n = normalize(vWorldNormal.xyz);
    vec3 p = pixelpos.xyz;
    vec2 uv = vTexCoord.st;

    // get edge vectors of the pixel triangle
    vec3 dp1 = dFdx(p);
    vec3 dp2 = dFdy(p);
    vec2 duv1 = dFdx(uv);
    vec2 duv2 = dFdy(uv);

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

    // construct a scale-invariant frame
    float invmax = inversesqrt(max(dot(t,t), dot(b,b)));
    return mat3(t * 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.; // Math so "odd" because 0.5 cannot be precisely described in an unsigned format
    map.y = -map.y;
    return normalize(tbn * map);
#else
    return normalize(vWorldNormal.xyz);
#endif
}

vec2 ParallaxMap(mat3 tbn)
{
    const float parallaxScale = 0.045;
    const float minLayers = 8.0;
    const float maxLayers = 16.0;

    // Calculate fragment view direction in tangent space
    mat3 invTBN = transpose(tbn);
    vec3 V = normalize(invTBN * (uCameraPos.xyz - pixelpos.xyz));
    vec2 T = vTexCoord.st;

    float numLayers = mix(maxLayers, minLayers, clamp(abs(V.z), 0.0, 1.0)); // clamp is required due to precision loss

    // calculate the size of each layer
    float layerDepth = 1.0 / numLayers;

    // depth of current layer
    float currentLayerDepth = 0.0;

    // the amount to shift the texture coordinates per layer (from vector P)
    vec2 P = V.xy * parallaxScale;
    vec2 deltaTexCoords = P / numLayers;
    vec2 currentTexCoords = T;
    float currentDepthMapValue = texture(tex_heightmap, currentTexCoords).r;

    while (currentLayerDepth < currentDepthMapValue)
    {
        // shift texture coordinates along direction of P
        currentTexCoords -= deltaTexCoords;

        // get depthmap value at current texture coordinates
        currentDepthMapValue = texture(tex_heightmap, currentTexCoords).r;

        // get depth of next layer
        currentLayerDepth += layerDepth;
    }

    // get texture coordinates before collision (reverse operations)
    vec2 prevTexCoords = currentTexCoords + deltaTexCoords;

    // get depth after and before collision for linear interpolation
    float afterDepth  = currentDepthMapValue - currentLayerDepth;
    float beforeDepth = texture(tex_heightmap, prevTexCoords).r - currentLayerDepth + layerDepth;
     
    // interpolation of texture coordinates
    float weight = afterDepth / (afterDepth - beforeDepth);
    vec2 finalTexCoords = prevTexCoords * weight + currentTexCoords * (1.0 - weight);

    return finalTexCoords;
}
Last edited by dpJudas on Sat Sep 08, 2018 3:07 pm, edited 1 time in total.
dpJudas
 
 
 
Joined: 28 May 2016

Re: Materials (PBR, Specular, Normal maps)

Postby Reinchard2 » Sat Sep 01, 2018 7:29 am

Wow, great thanks!
Reinchard2
 
Joined: 21 Sep 2007
Location: Poland - Bytom

Re: Materials (PBR, Specular, Normal maps)

Postby Reinchard2 » Sat Sep 01, 2018 8:22 am

Everything works well excpet brightmaps. I tried using some brightmap with your new shader and GZDoom shows some information about "missing texture7" in error log.
Reinchard2
 
Joined: 21 Sep 2007
Location: Poland - Bytom

Re: Materials (PBR, Specular, Normal maps)

Postby dpJudas » Sat Sep 01, 2018 8:30 am

This is probably a bug/limitation in how gzdoom handles its shaders. Create two copies of the shader (i.e. para.glsl and para_bm.glsl) and then use different name depending on whether the texture has a brightmap or not.
dpJudas
 
 
 
Joined: 28 May 2016

Re: Materials (PBR, Specular, Normal maps)

Postby Reinchard2 » Sun Sep 02, 2018 11:38 am

OK, thanks. Is there any way to increase heightmap strenght/parallax offset via gldefs code?
Reinchard2
 
Joined: 21 Sep 2007
Location: Poland - Bytom

Re: Materials (PBR, Specular, Normal maps)

Postby dpJudas » Sun Sep 02, 2018 4:38 pm

I believe the parallaxScale variable in the shader itself controls this. There's currently no way to set custom uniform values.

You could use a define in the gldefs file, i.e. 'Define "parallaxScale 0.045"' and then remove the 'const float parallaxSacle = 0.045;' line from the shader itself. The catch is that this method will compile a new shader for each different scale you use, which is not good.
dpJudas
 
 
 
Joined: 28 May 2016

Re: Materials (PBR, Specular, Normal maps)

Postby Reinchard2 » Mon Sep 03, 2018 2:57 am

Ok, thanks!
Reinchard2
 
Joined: 21 Sep 2007
Location: Poland - Bytom

Re: Materials (PBR, Specular, Normal maps)

Postby Reinchard2 » Thu Sep 06, 2018 1:47 am

One more question - what about alpha masks?
Reinchard2
 
Joined: 21 Sep 2007
Location: Poland - Bytom

Re: Materials (PBR, Specular, Normal maps)

Postby Samuel Chibberwell » Fri Sep 07, 2018 9:21 am

hey man, thanks for your work

I have found a bug in your code that seems to make it incompatible with some implementations of shader language:

i have a Macbook Air 2012 with intel graphics 4000... os 10.13.6

the error:

ERROR: 0:79: Initializer not allowed

solved by changing:

const float layerDepth = 1.0 / numLayers;

removing "const"


I think that some implementations likely then allow assigning a constant as the result of an expression, i've seen that in some languages. On my card clearly not.
I had this issue with an older version of your shader to.
removing const is unlikely to affect shader performance.

It would be nice if you posted your work to github :)
Samuel Chibberwell
 

Re: Materials (PBR, Specular, Normal maps)

Postby DarkShroom » Sat Sep 08, 2018 9:17 am

my post came up as "Samuel Chibberwell" i think i was logged out er sorry

anyway i was now really interested in figuring the reason for this bug so i meant to leave my username

I hate the idea that you can make and test your mod and it'll work fine on your own system... a user will download it, it won't work, he'll just put it in the recycle bin and move on
DarkShroom
 
Joined: 01 Aug 2018

Re: Materials (PBR, Specular, Normal maps)

Postby dpJudas » Sat Sep 08, 2018 3:06 pm

DarkShroom wrote:anyway i was now really interested in figuring the reason for this bug

One of the biggest problems with OpenGL is that each driver brings its own GLSL compiler. The Intel GLSL compiler thinks that line can't be const, while the Nvidia compiler thinks it can be. One of them is wrong, but to figure out which would require reading the GLSL specification carefully. It doesn't really matter much in the end as you'll need to use a syntax that works for all of them regardless of which is to blame.

If you want to maximize the chance your mod works on everyone's computer, make sure you try run it on at least one Intel, one Nvidia and one AMD card.
dpJudas
 
 
 
Joined: 28 May 2016

Re: Materials (PBR, Specular, Normal maps)

Postby furyweb » Sat Sep 08, 2018 5:28 pm

Me again. dpJudas is it possible to add the option of a glossiness material like specular and normal materials. I know we can control the glossiness through numeric value, but would be nice to use a texture for more control. I would use PBR but until cube map environment has come about so we can have some sort of reflection, i prefer to use specular/normal. Also pbr bugs out with sector lines, as in it cuts off the lighting.

Cheers.
User avatar
furyweb
 
Joined: 30 Aug 2018
Location: UK

Re: Materials (PBR, Specular, Normal maps)

Postby dpJudas » Sat Sep 08, 2018 7:00 pm

Yes, that is possible. Change the following lines in the shader from:

Code: Select allExpand view
material.Glossiness = uSpecularMaterial.x;
material.SpecularLevel = uSpecularMaterial.y;

to this:

Code: Select allExpand view
vec4 glossSpec = texture(tex_gloss, texCoord);
material.Glossiness = glossSpec.r * 100.0;
material.SpecularLevel = glossSpec.g * 100.0;

Then add a 'Texture tex_gloss "materials/gloss/foo.png" to the GLSL material entries. This will make the red channel of that texture the glossiness and the green channel the specular level.

The 100 value I typed into the shader is the scale that maps full red and green to that value. I'm not sure what the reasonable max should be here - feel free to adjust it to what makes sense for the two values.
dpJudas
 
 
 
Joined: 28 May 2016

Re: Materials (PBR, Specular, Normal maps)

Postby dpJudas » Sat Sep 08, 2018 7:09 pm

Thinking about it a bit further the code could use the Glossiness and SpecularLevel parameters in the GLDEFS as the scale factor:

Code: Select allExpand view
vec4 glossSpec = texture(tex_gloss, texCoord);
material.Glossiness = glossSpec.r * uSpecularMaterial.x;
material.SpecularLevel = glossSpec.g * uSpecularMaterial.y;
dpJudas
 
 
 
Joined: 28 May 2016

PreviousNext

Return to Tutorials

Who is online

Users browsing this forum: No registered users and 1 guest