Q: evaluating multiple brdfs in one go #889
-
Hello,
and it is extremely slow. |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 2 replies
-
You can make vectorized calls to all BSDFs at the same time. import mitsuba as mi
import drjit as dr
mi.set_variant('cuda_ad_rgb')
bsdfs = [
mi.load_dict({
'type': 'roughplastic',
'diffuse_reflectance': {
'type': 'rgb',
'value': param_value
}
}) for param_value in [0.1, 0.4, 0.8]
]
# Build vectorized pointer type of BSDFs
bsdfs_unique_ptr = dr.zeros(mi.BSDFPtr, 3)
for i in range(3): # Use recorded loop if many BSDFs
dr.scatter(bsdfs_unique_ptr, mi.BSDFPtr(bsdfs[i]), i)
direction_pair_count = 2 # Evalutate 2 (wi, wo) pairs per BSDF
direction_pairs = [
(mi.Vector3f(0, 0, 1), mi.Vector3f(0, 0, 1)),
(dr.normalize(mi.Vector3f(0, 0.8, 0.1)), mi.Vector3f(0, 0, 1)),
]
# Duplicate/repeat pointers `direction_pair_count` times
bsdfs_ptr = dr.zeros(mi.BSDFPtr, direction_pair_count * dr.width(bsdfs_unique_ptr))
for i in range(direction_pair_count): # Use recorded loop if many directions
idx = dr.arange(mi.UInt32, dr.width(bsdfs_unique_ptr)) * direction_pair_count + i
dr.scatter(bsdfs_ptr, bsdfs_unique_ptr, idx)
# Write si (duplicate si.wi)
si = dr.zeros(mi.SurfaceInteraction3f, dr.width(bsdfs_ptr))
for i in range(direction_pair_count): # Use recorded loop if many directions
idx = dr.arange(mi.UInt32, dr.width(bsdfs_unique_ptr)) * direction_pair_count + i
dr.scatter(si.wi, direction_pairs[i][0], idx)
# Write wo
wo = dr.zeros(mi.Vector3f, dr.width(bsdfs_ptr))
for i in range(direction_pair_count): # Use recorded loop if many directions
idx = dr.arange(mi.UInt32, dr.width(bsdfs_unique_ptr)) * direction_pair_count + i
dr.scatter(wo, direction_pairs[i][1], idx)
values = bsdfs_ptr.eval(mi.BSDFContext(), si, wo)
print(f"{values=}") |
Beta Was this translation helpful? Give feedback.
-
Thanks @njroussel
|
Beta Was this translation helpful? Give feedback.
Hi,
I can run @njroussel's code with both llvm & cuda.
I think your code should give the correct result in your use case, but it is more like a hack.
diffuse_reflectance
has typergb
, which creates aSRGBReflectanceSpectrum
texture. Since we are not in the spectral mode, the stored value (diffuse_reflectance.value
) is supposed to be a scalar color3f: just 3 scalar numbers, not an array of colors. This is checked in the constructor.However, we expose that value through
traverse
and we do not check the validity of the changed value, which allows us to replace it by a vector of colors. Now the BSDF is in an invalid state: the reflectance color of it is simultaneously color A and color B. It…