Materials (PBR, Specular, Normal maps)
Moderators: GZDoom Developers, Raze 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.
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.
-
- Posts: 310
- Joined: Fri Sep 21, 2007 1:08 am
- Location: Poland - Bytom
Re: Materials (PBR, Specular, Normal maps)
@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?
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?
-
-
- Posts: 3145
- Joined: Sat May 28, 2016 1:01 pm
Re: Materials (PBR, Specular, Normal maps)
Here's an updated version of the shader that supports all the various material types (normal, specular, pbr):
Code: Select all
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 2:07 pm, edited 1 time in total.
-
- Posts: 310
- Joined: Fri Sep 21, 2007 1:08 am
- Location: Poland - Bytom
Re: Materials (PBR, Specular, Normal maps)
Wow, great thanks!
-
- Posts: 310
- Joined: Fri Sep 21, 2007 1:08 am
- Location: Poland - Bytom
Re: Materials (PBR, Specular, Normal maps)
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.
-
-
- Posts: 3145
- Joined: Sat May 28, 2016 1:01 pm
Re: Materials (PBR, Specular, Normal maps)
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.
-
- Posts: 310
- Joined: Fri Sep 21, 2007 1:08 am
- Location: Poland - Bytom
Re: Materials (PBR, Specular, Normal maps)
OK, thanks. Is there any way to increase heightmap strenght/parallax offset via gldefs code?
-
-
- Posts: 3145
- Joined: Sat May 28, 2016 1:01 pm
Re: Materials (PBR, Specular, Normal maps)
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.
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.
-
- Posts: 310
- Joined: Fri Sep 21, 2007 1:08 am
- Location: Poland - Bytom
Re: Materials (PBR, Specular, Normal maps)
Ok, thanks!
-
- Posts: 310
- Joined: Fri Sep 21, 2007 1:08 am
- Location: Poland - Bytom
Re: Materials (PBR, Specular, Normal maps)
One more question - what about alpha masks?
Re: Materials (PBR, Specular, Normal maps)
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
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
-
- Posts: 3
- Joined: Wed Aug 01, 2018 1:15 pm
Re: Materials (PBR, Specular, Normal maps)
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
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
-
-
- Posts: 3145
- Joined: Sat May 28, 2016 1:01 pm
Re: Materials (PBR, Specular, Normal maps)
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.DarkShroom wrote:anyway i was now really interested in figuring the reason for this bug
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.
-
- Posts: 34
- Joined: Thu Aug 30, 2018 3:23 pm
- Location: UK
Re: Materials (PBR, Specular, Normal maps)
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.
Cheers.
-
-
- Posts: 3145
- Joined: Sat May 28, 2016 1:01 pm
Re: Materials (PBR, Specular, Normal maps)
Yes, that is possible. Change the following lines in the shader from:
to this:
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.
Code: Select all
material.Glossiness = uSpecularMaterial.x;
material.SpecularLevel = uSpecularMaterial.y;
Code: Select all
vec4 glossSpec = texture(tex_gloss, texCoord);
material.Glossiness = glossSpec.r * 100.0;
material.SpecularLevel = glossSpec.g * 100.0;
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.
-
-
- Posts: 3145
- Joined: Sat May 28, 2016 1:01 pm
Re: Materials (PBR, Specular, Normal maps)
Thinking about it a bit further the code could use the Glossiness and SpecularLevel parameters in the GLDEFS as the scale factor:
Code: Select all
vec4 glossSpec = texture(tex_gloss, texCoord);
material.Glossiness = glossSpec.r * uSpecularMaterial.x;
material.SpecularLevel = glossSpec.g * uSpecularMaterial.y;