Original Post
Noticed there is another recent BRDF thread but felt my post did not exactly belong there. So here goes...
I've been thinking of implementing some BRDFs using GLSL these days to be able to simulate the looks of certain materials using a variety of well-known BRDFs. I took my time to read about the subject to get the basics and while I definitely have a much better understanding of it now I still feel like I'm standing on shaky ground. So some help/clarification would be nice.
This is how I think of it, the BRDF function describes the ratio of reflected light to incident light (I'll skip describing this in radiometric terms for simplicity) and one might generally use a combination of two BRDF's together; diffuse BRDF for some diffuse reflection and specular BRDF for some specular reflection. So overall one might have this kind of reflection model written in the fragment/pixel shader (omitting the ambient term):
I[sub]r[/sub] = I[sub]i[/sub]*(brdf[sub]diff[/sub]*dot(n*l)+c[sub]spec[/sub]*brdf[sub]specular[/sub])
where I[sub]r[/sub] is reflected light, I[sub]i[/sub] is the light intensity, c[sub]spec[/sub] is a material property describing the amount of specular reflection from the surface and dot(n*l) is cos for the angle between the surface normal and light direction. I'll focus on the diffuse part here (but my confusion extends to the specular part as well)
So as commonly known, for a BRDF to be at least physically plausible it has a few constraints, among them being conservation of energy. To adhere to the conservation of energy then from what I've understood a normalization factor is often added to the BRDF.
For example a diffuse BRDF that does not conserve energy might just be brdf[sub]diff[/sub] = c[sub]d[/sub] where c[sub]d[/sub] is the material property describing the amount of diffuse reflection (albedo/surface color). A diffuse BRDF that does fullfill the constraint would be brdf[sub]diff[/sub] = c[sub]d[/sub]/pi.
Wanting to make my reflection model at least slightly more physically based I simply performed this in my shader by dividing my diffuse reflection with pi. Of course this gave me nothing but terrible results because the resulting diffuse reflection (for all three color channels) was enough small that my object was quite dark (and sometimes non-visible/black). Obviously the same problem happened when I tried the same for a specular BRDF(normalized Phong and Blinn-Phong), the specular highlights disappeared.
At first I thought that the problem might just lie somewhere in my code but after reading some more about diffuse BRDF I saw some sources showing that when you calculate the reflected light, accounting for light incoming from all directions (integrating over the whole hemisphere), and have a diffuse BRDF which is a constant (albedo) then you'll end up with I[sub]r[/sub] = I[sub]i[/sub]*c[sub]diff[/sub]*pi. This could be problematic in some situations because we could end up producing more light than what we had initially, thus breaking the constraint mentioned earlier.
So in the end, if my whole description above is not wrong (which it could be!), what I'm really confused about is if I SHOULD divide my diffuse BRDF by pi (and thus my problem lies elsewhere) or if I should assume that my diffuse reflection is somehow being implicitly multiplied and divided by pi (cancelling each other out) and thus leaving me with what I already had at first, and then not only making it easier to use but also fulfilling the constraint. Which is the correct approach here? If it's the latter then does the same apply for specular BRDF (assuming things to be multiplied/divided implicitly) as well?
Sorry for the long post, but I felt I needed to write it down myself so I'm sure I understand what might(!) be going on. Hopefully I can get some help on this.
I've been thinking of implementing some BRDFs using GLSL these days to be able to simulate the looks of certain materials using a variety of well-known BRDFs. I took my time to read about the subject to get the basics and while I definitely have a much better understanding of it now I still feel like I'm standing on shaky ground. So some help/clarification would be nice.
This is how I think of it, the BRDF function describes the ratio of reflected light to incident light (I'll skip describing this in radiometric terms for simplicity) and one might generally use a combination of two BRDF's together; diffuse BRDF for some diffuse reflection and specular BRDF for some specular reflection. So overall one might have this kind of reflection model written in the fragment/pixel shader (omitting the ambient term):
I[sub]r[/sub] = I[sub]i[/sub]*(brdf[sub]diff[/sub]*dot(n*l)+c[sub]spec[/sub]*brdf[sub]specular[/sub])
where I[sub]r[/sub] is reflected light, I[sub]i[/sub] is the light intensity, c[sub]spec[/sub] is a material property describing the amount of specular reflection from the surface and dot(n*l) is cos for the angle between the surface normal and light direction. I'll focus on the diffuse part here (but my confusion extends to the specular part as well)
So as commonly known, for a BRDF to be at least physically plausible it has a few constraints, among them being conservation of energy. To adhere to the conservation of energy then from what I've understood a normalization factor is often added to the BRDF.
For example a diffuse BRDF that does not conserve energy might just be brdf[sub]diff[/sub] = c[sub]d[/sub] where c[sub]d[/sub] is the material property describing the amount of diffuse reflection (albedo/surface color). A diffuse BRDF that does fullfill the constraint would be brdf[sub]diff[/sub] = c[sub]d[/sub]/pi.
Wanting to make my reflection model at least slightly more physically based I simply performed this in my shader by dividing my diffuse reflection with pi. Of course this gave me nothing but terrible results because the resulting diffuse reflection (for all three color channels) was enough small that my object was quite dark (and sometimes non-visible/black). Obviously the same problem happened when I tried the same for a specular BRDF(normalized Phong and Blinn-Phong), the specular highlights disappeared.
At first I thought that the problem might just lie somewhere in my code but after reading some more about diffuse BRDF I saw some sources showing that when you calculate the reflected light, accounting for light incoming from all directions (integrating over the whole hemisphere), and have a diffuse BRDF which is a constant (albedo) then you'll end up with I[sub]r[/sub] = I[sub]i[/sub]*c[sub]diff[/sub]*pi. This could be problematic in some situations because we could end up producing more light than what we had initially, thus breaking the constraint mentioned earlier.
So in the end, if my whole description above is not wrong (which it could be!), what I'm really confused about is if I SHOULD divide my diffuse BRDF by pi (and thus my problem lies elsewhere) or if I should assume that my diffuse reflection is somehow being implicitly multiplied and divided by pi (cancelling each other out) and thus leaving me with what I already had at first, and then not only making it easier to use but also fulfilling the constraint. Which is the correct approach here? If it's the latter then does the same apply for specular BRDF (assuming things to be multiplied/divided implicitly) as well?
Sorry for the long post, but I felt I needed to write it down myself so I'm sure I understand what might(!) be going on. Hopefully I can get some help on this.