Jump to content
  • Advertisement
Sign in to follow this  
ic0de

gloss mapping?

This topic is 2027 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey I just implemented gloss mapping or at least I think I did. Am I right in thinking that gloss mapping is when you change the specular exponent based on a texture? Also did I implement it right? here is my code (simplified of course):


specular = pow(max(dot(halfvec, finalnormal), 0.0), (texture2D(gloss_texture, transformedTexcoord).r*99.0) + 1.0);


Mostly I was wondering about the range, I want to be pretty conformant to what other engines use as to maximize the portability of my content. right now I noticed that when multiplying it by 99 I start running into the limitations of 8-bit grayscale. Does anyone have an example of how they implemented this effect?

Share this post


Link to post
Share on other sites
Advertisement
Sometimes "gloss" terminology is a bit vague - some engines use it to mean the specular power, while others use it to mean the specular mask. In any case, it's good to fetch both the power and mask values from a texture to give your artists decent control over the materials.
In my engine, I call the specular-power texture the "roughness" texture.

You seem to be using the traditional Blinn-Phong specular function, and the code looks ok. In terms of style, I'd suggest a few more line breaks:
float NdotH = saturate(dot(halfvec, finalnormal)); //prefer saturate over max where able
float specPower = texture2D(gloss_texture, transformedTexcoord).r*99.0 + 1.0;
specular = pow(NdotH, specPower);


As for the "[font=courier new,courier,monospace]x*99+1[/font]" part, there is no right answer for this encoding/decoding function. Any positive value is valid for the specular power -- some materials might need "5" and others might need "50000"... This makes choosing a function that encodes this range into 8-bits particularly difficult.
If the materials in your game only need the values of 1-100, then your encoding is fine.

If you want to move more precision to the lower end, you can do something like:
float specPower = texture2D....
specPower = (specPower*specPower) * range + 1;
Or to move precision to higher values, something like:float specPower = 1.0 - texture2D....
specPower = (1.0-(specPower*specPower)) * range + 1;

Some engines use the log function for a logarithmic distribution, but basically you've just got to choose a mapping that works for you.

Other engines might not even be using Blinn-Phong, so even if you use the same mapping, you'll get different appearances of "gloss" anyway. Edited by Hodgman

Share this post


Link to post
Share on other sites
Sorry to intrude but I'm curious as to why you'd prefer saturate over max ?
I was having some problems using saturate for a dot product before, were it was clamping values to 1 which should not have been.
Isn't a max much safer and precise in that respect ? Edited by lipsryme

Share this post


Link to post
Share on other sites
It is common in game engines now to store the spec power in log space, even with 8 bit precicion.

i.e see how UE4 does it here (slide 30)

http://advances.realtimerendering.com/s2012/Epic/The%20Technology%20Behind%20the%20Elemental%20Demo%2016x9.pptx

Frostbite2 also does it this way too (albeit with maybe a slightly different range)


Also as mentioned above a saturate will be better. Its usually free whereas max is not.

Share this post


Link to post
Share on other sites

Also as mentioned above a saturate will be better. Its usually free whereas max is not.


I'm using glsl, as far as I know saturate doesn't exist there, glsl has clamp() but I'm not sure if that is still "free"

Share this post


Link to post
Share on other sites

[quote name='AliasBinman' timestamp='1354558493' post='5006703']
Also as mentioned above a saturate will be better. Its usually free whereas max is not.


I'm using glsl, as far as I know saturate doesn't exist there, glsl has clamp() but I'm not sure if that is still "free"
[/quote]

In that case do clamp(x,0,1) and the compiler should replace with a saturate.

Share this post


Link to post
Share on other sites

Sorry to intrude but I'm curious as to why you'd prefer saturate over max ?
I was having some problems using saturate for a dot product before, were it was clamping values to 1 which should not have been.
Isn't a max much safer and precise in that respect ?
Yes if the input is possibly > 1, then saturate isn't a valid replacement. A dot product of two normal vectors can't be > 1 though, so it's possible in this case.
Saturate/clamp(x,0,1) is preferable because it's often implemented as an instruction modifier, rather than its own instruction.
E.g. Instead of "mul ...; max ...;", the GPU ASM may just be "mul_clamped ...;"

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!