-
Hi, I am trying to render a normal map, similar to the aov integrator I wrote a custom integrator inspired by normalmap.cpp this line. The issue is the final result looks a little weird to me. I was wondering this is right way to do this? class NormalIntegrator(mi.SamplingIntegrator):
def sample(self: mi.SamplingIntegrator, scene: mi.Scene, sampler, ray: mi.RayDifferential3f, medium: mi.Medium = None, active: bool = True):
si:mi.SurfaceInteraction3f = scene.ray_intersect(ray, mi.RayFlags.All, True, active)
valid_ray = active & si.is_valid()
result = mi.Spectrum(0)
#taken from normalmap.cpp
def frame(si, active):
n = self.normal_map.eval_3(si, active) * 2 -1
result = mi.Frame3f()
result.n = dr.normalize(n)
result.s = dr.normalize(result.n * dr.dot(result.n, si.dp_du) - si.dp_du)
result.t = dr.cross(result.n, result.s)
return result
f = frame(si, si.is_valid())
sh_normal = si.sh_frame.n #shading normal
perturbed_n = f.to_local(sh_normal) #perturb the original normal
mask = dr.eq(si.shape, self.shape_of_interest)
result = dr.select(mask, perturbed_n , sh_normal) #only for the object of interest, show the perturbed, otherwise show the shading normal
return result, valid_ray, []
normal_integrator = NormalIntegrator(mi.Properties())
# ... find the shape of interest using scene.shapes()[index]
normal_map = mi.load_dict({'type': 'bitmap',
'raw': True,
'filename': r'..\data\scenes_mistuba\kitchen\textures\metal\Metal009_4K-PNG_NormalGL.png'
})
normal_integrator.normal_map = normal_map
normal_integrator.shape_of_interest = shape_of_interest
# my integrator result
normal_rendering = mi.render(scene, integrator=normal_integrator, sensor=sensor)/2 + 0.5
mi.Bitmap(normal_rendering).convert(mi.Bitmap.PixelFormat.RGB, mi.Struct.Type.UInt8, True).write('perturbed.png')
|
Beta Was this translation helpful? Give feedback.
Answered by
saeedhd96
Aug 11, 2024
Replies: 1 comment
-
Thanks to @tizian, the correct answer is: class NormalIntegrator(mi.SamplingIntegrator):
def sample(self: mi.SamplingIntegrator, scene: mi.Scene, sampler, ray: mi.RayDifferential3f, medium: mi.Medium = None, active: bool = True):
si:mi.SurfaceInteraction3f = scene.ray_intersect(ray, mi.RayFlags.All, True, active)
valid_ray = active & si.is_valid()
result = mi.Spectrum(0)
def frame(si, active):
n = self.normal_map.eval_3(si, active) * 2 -1
result = mi.Frame3f()
result.n = dr.normalize(n)
result.s = dr.normalize(result.n * dr.dot(result.n, si.dp_du) - si.dp_du)
result.t = dr.cross(result.n, result.s)
return result
f = frame(si, si.is_valid())
perturbed_n = si.sh_frame.to_world(f.n)
sh_normal = si.sh_frame.n
mask = dr.eq(si.shape, self.shape_of_interest)
result = dr.select(mask, perturbed_n, sh_normal)
return result, valid_ray, [] |
Beta Was this translation helpful? Give feedback.
0 replies
Answer selected by
saeedhd96
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks to @tizian, the correct answer is: