I am trying to implement a simple shader. A round ball object is rendered with uniform albedo and I noticed some strange white spots on the outputs.
I perform importance sampling with 512 light directions on the cosine-weighted hemisphere to render the scene. For debugging purposes, I dropped the specular component from the visualization and only show the albedo*light
component:
The spots roughly align with the position of the sun in the env map. From what I have understood the issue is that some values in the hdr are very high (up to ~8384
, 12% of the environment map pixels have a value over 1
). So if one of the very high values is sampled, then the resulting average light intensity will be very high. However, I don't see why the resulting diffuse color is sparse like this.
From this render, I expect to see a uniform color with a bright side on the left of the sphere. Could this issue be fixed with a more advanced sampling method based on the env map intensity, or am I missing something with the current approach?
For additional reference, I use the following python code to query the env map:
def get_light(self, incident_dir, envir_map):
"""
envir_map: shape (1, 3, H, W)
incident_dir: (3, point_num*samples_num)
"""
# convert from cartesian to spherical
x,y,z = incident_dir
phi = torch.arccos(z).flatten() - 1e-6
theta = torch.atan2(y, x).flatten()
# normalize to [-1, 1]
query_y = (phi / np.pi) * 2 - 1
query_x = - theta / np.pi
# sampling grid is shaped (1, 1, pn*sn, 2)
grid = torch.stack((query_x, query_y)).permute(1, 0).unsqueeze(0).unsqueeze(0)
# interpolate to query env map,
sampled = F.grid_sample(envir_map, grid, align_corners=True) # [1, 3, 1, pn*sn]
light_rgbs = sampled.squeeze().permute(1, 0).reshape(pn, -1, 3) # [pn, sn, 3]
return light_rgbs
The environment map looks like so: