# Brightness of specular reflections

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

## Recommended Posts

Once upon time I stumbled across some example code I guess from MS or something like that where they claimed that specular reflections have to be multiplied by 39.78 with HDRI because:

"A light which illuminates objects at 80 lum/sr should be drawn at 3183 lumens/meter^2/steradian, which equates to a multiplier of 39.78 per lumen."

Somehow this never got me anywhere but I'm still curious to know if there is some real logic behind this of if this is a brutal hack that works only in one specific scenario. What is the correct brightness of a specular reflection anyways? The typical game specular reflection code doesn't take much of geometry (distance to light source, size of light source) into account so it can't look anything good at all.

##### Share on other sites
It doesn't take distance into account explicitly, but it does implicitly via angles. Think of a cone that has an apex at the centre of the Sun, a height equal to the (average) Sun-Earth distance, and a base that is the same radius as the (average) radius of the Earth. If you moved the Earth closer or further away from the Sun, the angle obviously changes. See tan/arctan functions http://www.gamedev.net/topic/623633-camera-position-in-spotlight-cone/page__p__4932588#entry4932588, see http://en.wikipedia....et_and_its_star

But yeah, you're right that the simplest models of specular reflection don't take area lights into account.

As for the value 3813, see the Lambert unit for a hint (it's 10000/pi candelas per square metre).

I don't know if I understand your direct question about the brightness of a specular reflection, so sorry.

##### Share on other sites
In that example I found back then the light color has been multiplied by 39.78 for the specular reflection term only with the quoted explanation above. So they sort of intensified specular highlights by factor 40 in contrary to diffuse light contribution. Sounds heavy to me even for HDRI.

##### Share on other sites
Yeah, that seems odd (that they would only multiply one term rather than all terms, but I'm no expert). Do you have a link to the example?

##### Share on other sites
Can you post the actual code in question? This sounds like it's got more to do with IBL/HDRI than it does with specular reflections in particular.

When performing regular (arithmetic) lighting, you have to 'normalize' your specular reflection math to ensure that the output light cone contains the same energy or less than the input light ray. This involves different magic numbers, such as 8*pi...

##### Share on other sites
I can't seem to find the source code right now. It definitely had been out of an MS DX SDK of some kind. It had been a HDR example with some brick wall room, one large light source and some images on the wall. I think DX9 but I'm really not sure.

Concerning the math I'm experimenting now with a more physically based rendering which contains this normalization you mentioned. It seems to help the cause but it's not fully working yet. Something causes banding. I have though the feeling it's an FP16 precision problem the tone mapper somehow exaggerates. More testing required.

##### Share on other sites
The sample you're talking about is the HDRLighting sample in the DirectX SDK. The multiplier to which you're referring to has nothing to with specular reflections, and is instead used to determine the emissive lighting when rendering the actual light source itself. Basically they're saying that if a light causes 80 lumens of light to be reflected off a surface towards the eye, then the same light will emit 3183 lumens directly towards the eye. I have no idea where the numbers come from, or if they're accurate. It seems awfully simplistic to me.

##### Share on other sites
No idea myself so I asked. Using a normalization trick though seems to do the trick. The entire PBR looks strange so far. Some stuff looks very good but for my taste there's a bit much reflection going on. But the specular highlight seems to work... more or less. If one doesn't count the banding. I'm suspecting though some numerical imprecision from the depth reconstruction. Due to compatibility this is encoded depth (float => RGBA). Used a packing code I found on the net but I suspect it causes banding with PBR. Stupid depth textures not working properly <.=.<

##### Share on other sites
Some stuff looks very good but for my taste there's a bit much reflection going on.
What kind of specular mask values are you using? Physical values tend to be very low, e.g. 0.05 / 5%

Due to compatibility this is encoded depth (float => RGBA). Used a packing code I found on the net but I suspect it causes banding with PBR. Stupid depth textures not working properly <.=.<
I've come across a lot of broken ways to pack/unpack floats to/from RGBA textures, so it's possible :/

##### Share on other sites
What kind of specular mask values are you using? Physical values tend to be very low, e.g. 0.05 / 5%

I'm using 0.02 as lowest value so this should be very low. Using a PBR as mentioned in some SIGGRAPH course notes. The specular reflection is okay and looks good but the env-map reflection is off. Using the fresnel factor as mentioned there Fschlick(Cspec, view, normal) but for some reason the reflection from the env-map is bright as hell. So if you have a road stretching ahead of you the specular reflection is toned down well enough to be plausible but the env-map reflection is going to 100% reflection half-way through to the far point. I presume the problem is with the lack of normalization factor there (as the specular part has one) but I could not find any information on what kind of normalization factor to use for an env-map. Maybe the fresnel one is off too.

I've come across a lot of broken ways to pack/unpack floats to/from RGBA textures, so it's possible :/[/quote]
The encoding/decoding I'm using right now is this one:

encode depth:
const vec3 packShift = vec3( 1.0, 256.0, 65536.0 );
const vec3 packMask = vec3( 1.0 / 256.0, 1.0 / 256.0, 0.0 );
vec3 encoded = fract( packShift * vec3( gl_FragCoord.z ) );
outDepth = encoded - ( encoded.yzz * packMask );

decode depth:
const vec3 unpackGeomDepth = vec3( 1.0, 1.0 / 256.0, 1.0 / 65536.0 );
depth = dot( texelFetch( texDepth, tc, 0 ).rgb, unpackGeomDepth ) );

1. 1
2. 2
Rutin
21
3. 3
4. 4
frob
17
5. 5

• 9
• 33
• 13
• 13
• 10
• ### Forum Statistics

• Total Topics
632582
• Total Posts
3007208

×