mitsuba-renderer / drjit

Dr.Jit — A Just-In-Time-Compiler for Differentiable Rendering
BSD 3-Clause "New" or "Revised" License
563 stars 40 forks source link

How to accelerate the ray intersect calculation? #209

Closed linxxcad closed 8 months ago

linxxcad commented 8 months ago

I want to use drjit to implement a simple ray tracing algorithm. May I ask how to accelerate the intersection of rays and quadrilateral? I packed the information on the direction of rays and placed them in Array3f, intersecting them with the quadrilateral ABCD. Using the Möller Trumcore algorithm, the barycentric coordinate arrays u and v were obtained for all rays. When I determine whether each ray intersects with a triangle, I can only use for, which has a low algorithm efficiency. Is there any other method that can accelerate the operation of determining whether it intersects.

rayDir=Array3f(...)
rayOrigin=Array3f(...)
res=dr.full(Float,0.0,rayNum)
#Get a conclusion about whether each ray intersects or not,0.0 is not intersect, 1.0 is intersect
A, B, and C are the three vertices of a quadrilateral.
AB=B-A
AC=C-A
p=dr.cross(rayDir,AC)
det=dr.dot(AB,p)
#Assuming that there is no case where the ray is parallel to the triangle
T=rayOrigin-A
u=dr.dot(T,p)/det
q=dr.cross(T,AB)
v=dr.dot(rayDir,q)/det `
#got the barycentric coordinates u and v
#Get a conclusion about whether each ray intersects or not 
for i in range(rayNum):
   uu=dr.gather(float,u,i)
   vv=dr.gather(float,v,i)
   if uu<1.0 and uu>0.0 and vv<1.0 and vv>0.0: `
       res[i]=0.

Or is there any other method that I can use to compute the intersection, and I want to accelerate whether the ray intersects with some quadrilateral, and I don't care where the intersection is.

If there are kind people who know, please help me, I would be grateful.

njroussel commented 8 months ago

Hi @linxxcad

You don't need the for loop. You can simply write:

res = dr.select(uu<1.0 &  uu>0.0 & vv<1.0 & vv>0.0, 1.0, 0.0)

I'll close this issue, as it's more of a question than a bug report. But fell free to continue asking questions if this wasn't clear.

linxxcad commented 8 months ago

@njroussel Thank you for your answer!

I tried your advice, but I ran into problems. If I use 'res = dr.select(uu<1.0 & uu>0.0 & vv<1.0 & vv>0.0, 1.0, 0.0)'
it seems wrong, 'drjit.Exception: To convert an Dr.Jit array into a boolean value, use a mask reduction operation such as drjit.all(), drjit.any(), drjit.none(). Special variants (drjit.all_nested(), etc.) are available for nested arrays.'

If I use 'res = dr.select(uu<1.0, 1.0, 0.0)' , no errors. How I can solve this problem? Thanks!

linxxcad commented 8 months ago

I have tried this to solve the above problem, thank you! @njroussel

res1=dr.select(u<1.0,1.0,0.0) res2=dr.select(u>0.0,1.0,0.0) res3=dr.select(v<1.0,1.0,0.0) res4=dr.select(v>0.0,1.0,0.0) res=res1+res2+res3+res4 result=dr.select(dr.eq(res,4.0),0.0,1.0)

njroussel commented 8 months ago

Great !