Next Event Estimation for Triangle-based Light Sources

I have a question regarding the NEE for light sources that are composed from triangles. I implemented the next event estimation (explicit light source sampling) for spherical light sources but after all of the trials, the output is always noisy and not even close to spherical luminaries.

else if(const Triangle* tr=dynamic_cast<const Triangle*>(prim))
{
double ran1=rand01();
double ran2=rand01();

double alpha=1-sqrt(ran1);
double beta=(1-ran2)*sqrt(ran1);
double gamma=ran2*sqrt(ran1);

while(alpha+beta>1)
{
ran1=rand01();
ran2=rand01();
alpha=1-sqrt(ran1);
beta=(1-ran2)*sqrt(ran1);
}

Vec firstEdge=tr->vertex1-tr->vertex0;
Vec secondEdge=tr->vertex2-tr->vertex0;
Vec nPrime=secondEdge.cross(firstEdge);
double A=nPrime.length()*1/2;

Vec xPrime = tr->vertex0*alpha+tr->vertex1*beta+tr->vertex2*gamma;

Vec omega=(xPrime-x).normalize();
Vec inverseOmega=(x-xPrime).normalize();

double cosTheta=clamp(((n-x).normalize()).dot(inverseOmega))/(n-x).length()*inverseOmega.length();
double cosThetaPrime=abs(((nPrime-xPrime).normalize()).dot(omega))/(nPrime-xPrime).length()*omega.length();
double magOfxPrimeToX=(xPrime-x).dot(xPrime-x);

{
L_direct = L_direct + (f.mult(tr->e))*(cosTheta)*(cosThetaPrime/magOfxPrimeToX) /(1/A);
}

}

After the loop ends for the light sources, I add direct contribution and indirect contribution in the return statement: return obj.e * emissive + L_direct + f.mult(radiance(Ray(x, d), depth, 0));

The result with 150 sample with 750x500 resolution: However spherical light sources are quite succesful in same specifications (150 sample with 750x500 resolution): What could be wrong in this case ? Thanks a lot.

• It doesn't give a wrong answer if you implement it correctly, your code was simply not computing visibility between two points but rather expected a point and direction. There is a difference between the ray-tracing function $r(x, \omega)$ and the visibility function $V(x,y)$. Another pitfall you may run into is floating point precision. So typically one uses instead $V(x+\epsilon N_x, y + \epsilon N_y)$ instead of $V(x,y)$ in order to avoid self-intersection. $N_x, N_y$ being the normals such that $N_x\cdot (y-x)>0$ and $N_y \cdot (x-y)>0$. Jan 8 at 12:52