@@ -158,7 +158,7 @@ bool BDPTRenderer::computePath(BDPTPathPart* P, int max_n, fvec3 O, fvec3 R, fve
158158 mat->modifyFrame (&P[i].m_surfPoint );
159159 mat->getRayAndBrdf (P[i-1 ].m_outRay ,&P[i].m_surfPoint ,P[i].m_outRay ,brdf,erad,inv);
160160
161- ct=std::abs (inv? dot3 (P[i]. m_outRay ,P[i]. m_surfPoint . m_normal ): dot3 (P[i- 1 ].m_outRay ,P[i].m_surfPoint .m_normal ));
161+ ct=std::abs (dot3 (P[i].m_outRay ,P[i].m_surfPoint .m_normal ));
162162 assignVector (P[i].m_outFactor ,P[i-1 ].m_outFactor [0 ]*brdf[0 ]*ct,P[i-1 ].m_outFactor [1 ]*brdf[1 ]*ct,P[i-1 ].m_outFactor [2 ]*brdf[2 ]*ct);
163163 if (inv) // Tracing from camera, adding emission directly to Rad
164164 {
@@ -265,21 +265,55 @@ void BDPTRenderer::computePaths(fvec3 O, fvec3 R, fvec3 radiance, RenderRay &cam
265265 RenderMaterial* mat;
266266 for (int i=0 ; i<lp_len; ++i)
267267 {
268- assignVector3 (lRad,m_ppLPBuf[tid][i].m_outRad );
269268 lPos=m_ppLPBuf[tid][i].m_surfPoint .m_position ;
269+ // For i > 0: precompute light sub-path radiance arriving at vertex i (before vertex i's BRDF)
270+ fvec3 lRadBase;
271+ RenderMaterial* lightMat=nullptr ;
272+ if (i>0 )
273+ {
274+ if (i==1 )
275+ {
276+ float dToLight=distance3 (m_ppLPBuf[tid][1 ].m_surfPoint .m_position ,
277+ m_ppLPBuf[tid][0 ].m_surfPoint .m_position );
278+ float rDterm=computeLightAttenuation (dToLight,lpsource->getAttenuationDistance ());
279+ assignVector (lRadBase,m_ppLPBuf[tid][0 ].m_outRad [0 ]*rDterm,
280+ m_ppLPBuf[tid][0 ].m_outRad [1 ]*rDterm,
281+ m_ppLPBuf[tid][0 ].m_outRad [2 ]*rDterm);
282+ }
283+ else
284+ {
285+ assignVector3 (lRadBase,m_ppLPBuf[tid][i-1 ].m_outRad );
286+ }
287+ lightMat=m_pScene->getMaterials ()[m_ppLPBuf[tid][i].m_surfPoint .m_pMesh ->m_iMatId ];
288+ }
270289 for (int j=1 ; j<cp_len && i+j<=m_pParams->maxPathLength ; ++j)
271290 {
272291 cPos=m_ppCPBuf[tid][j].m_surfPoint .m_position ;
273292 assignVector (LC_dir,cPos[0 ]-lPos[0 ],cPos[1 ]-lPos[1 ],cPos[2 ]-lPos[2 ]);
274- normalize3 (LC_dir);
293+ float connDist=length3 (LC_dir);
294+ if (connDist<fEpsilon ) continue ;
295+ LC_dir[0 ]/=connDist; LC_dir[1 ]/=connDist; LC_dir[2 ]/=connDist;
275296 if (i==0 )
276297 {
277298 lpsource->getRadianceAlongRay (LC_dir,lpdf,lRad);
278- float lsc=computeLightAttenuation (distance3 (cPos,lPos) ,lpsource->getAttenuationDistance ());
299+ float lsc=computeLightAttenuation (connDist ,lpsource->getAttenuationDistance ());
279300 lRad[0 ]*=m_pParams->lightScaleValue *lsc;
280301 lRad[1 ]*=m_pParams->lightScaleValue *lsc;
281302 lRad[2 ]*=m_pParams->lightScaleValue *lsc;
282303 }
304+ else
305+ {
306+ assignVector3 (lRad,lRadBase);
307+ // Evaluate BRDF at light vertex for connection direction
308+ fvec3 lightBrdf;
309+ lightMat->getBrdf (m_ppLPBuf[tid][i-1 ].m_outRay ,&m_ppLPBuf[tid][i].m_surfPoint ,LC_dir,lightBrdf,false );
310+ // Geometry term: cos at light vertex * 1/d²
311+ float cLight=std::abs (dot3 (LC_dir,m_ppLPBuf[tid][i].m_surfPoint .m_normal ));
312+ float invD2=1 .0f /(connDist*connDist);
313+ lRad[0 ]*=lightBrdf[0 ]*cLight*invD2;
314+ lRad[1 ]*=lightBrdf[1 ]*cLight*invD2;
315+ lRad[2 ]*=lightBrdf[2 ]*cLight*invD2;
316+ }
283317 c=std::abs (dot3 (LC_dir,m_ppCPBuf[tid][j].m_surfPoint .m_normal ));
284318 assignVector (lcRad,lRad[0 ]*c*m_ppCPBuf[tid][j-1 ].m_outFactor [0 ],lRad[1 ]*c*m_ppCPBuf[tid][j-1 ].m_outFactor [1 ],lRad[2 ]*c*m_ppCPBuf[tid][j-1 ].m_outFactor [2 ]);
285319 if (intensity (lcRad)<m_pParams->rayCutPixValue ) continue ; // Max possible radiance through path is less than threshold
0 commit comments