I was trying to do importance sampling on lambertian surface.At first I uniformly choose direction from unit sphere.
vec3 direction = camera->genDirection();
...
direction = random_in_unit_sphere();
float cosine = dotp(direction,surfaceNormal);
/*
float dotp(float val){
val = dot(val);
if(val>0.0001f) return val;
else return 0.0001f;
}
*/
vec3 brdf_result = material->baseColor/Pi;//lambertian
vec3 pdf = 1.0f/(2.0f*Pi);
throughput = throughput * brdf_result * cosine / pdf;
With 10 samples per pixel,yields:
then I choose random direction from the unit hemisphere above the surface
direction = random_in_unit_hemisphere(surfaceNormal);
float cosine = dotp(direction,surfaceNormal);
vec3 brdf_result = material->baseColor/Pi;
vec3 pdf = 1.0f/(1.0f*Pi);
throughput = throughput * brdf_result * cosine / pdf;
the result is very similar,except for less noise
and then I use the importance sampling method from (http://in1weekend.blogspot.com/)
class onb {
public:
vec3 operator[](int i)const { return axis[i]; }
vec3 u()const { return axis[0]; }
vec3 v()const { return axis[1]; }
vec3 w()const { return axis[2]; }
vec3 local(float a, float b, float c) { return a * u() + b * v() + c * w(); }
vec3 local(const vec3& a) { return a.x * u() + a.y * v() + a.z * w(); }
void buildFromNormal(const vec3& n) {
axis[2] = normalize(n);
vec3 a;
if (std::abs(w().x) > 0.9f)
a = vec3(0.0f, 1.0f, 0.0f);
else
a = vec3(1.0f, 0.0f, 0.0f);
axis[1] = normalize(cross(w(), a));
axis[0] = cross(w(), v());
}
private:
vec3 axis[3];
};
vec3 randCosDir() {
float r1 = randFloat01();
float r2 = randFloat01();
float z = sqrt(1.0f - r2);
float phi = 2.0f * Pi * r1;
float x = cos(phi) * 2.0f * sqrt(r2);
float y = sin(phi) * 2.0f * sqrt(r2);
return vec3(x, y, z);
}
,
onb uvw;
uvw.buildFromNormal(surfaceNormal);
direction = normalize(uvw.local(randCosDir()));
float cosine = dotp(direction,surfaceNormal);
vec3 brdf_result = material->baseColor/Pi;
vec3 pdf = dotp(uvw.w(), direction)/Pi;
throughput = throughput * brdf_result * cosine / pdf;
however the result is different:
The baseColor of the wall is vec3(0.8f,0.8f,0.8f),and the color of the dome light is vec3(1.0f,1.0f,1.0f). In some tutorial the cosine item is inside the lambertian brdf,and some are in the render equation,and in http://in1weekend.blogspot.com/ "weekend one" there is no cosine item at all.I really get messed with those concepts.Is there any one help me?thanks so much.
another rendering with baseColor = vec3(1.0f,1.0f,1.0f) and dome color = vec3(0.5f,0.5f,0.5f) (importance sampling)
the average color of the final image over all pixels is vec3(0.470884f,0.470884f,0.470884f).
10,000 samples per pixel with uniform hemisphere sampling: