No sharp shadows using an environment map

Hello everyone,

I am recently working on a project in which I want to render images with cycles standalone. Therefore I am using the C++ API. Sun lights, point lights, spot lights and area lights seem to work fine. But with the lighting of environment maps I get no sharp shadows. Objects throw a diffuse shadow on the ground. However some objects should also cast a shadow on themselves, which is not visible.

I tried the same setup in blender to exclude that the reason is the used hdr file. But in Blender (with using cycles) I get this shadows on the objects. Other things I tried is experimenting with the strength and using different hdr/exr maps but without success.

Here is the code for adding the environment map:

	Shader* shader = state.scene->default_background;

	ShaderGraph* graph = new ShaderGraph();

	XMLReader graph_reader;
	graph_reader.node_map[ustring("output")] = graph->output();

	ShaderNode* environment = NULL;
	ustring node_name_environment("environment_texture");
	const NodeType* node_type_environment = NodeType::find(node_name_environment);
	environment = (ShaderNode*)node_type_environment->create(node_type_environment);

	static_cast<EnvironmentTextureNode*>(environment)->name = "hdri";
	ustring filename("path to environment texture");
	graph_reader.node_map[environment->name] = environment;

	ShaderNode* background = NULL;
	ustring node_name_background("background_shader");
	const NodeType* node_type_background = NodeType::find(node_name_background);
	background = (ShaderNode*)node_type_background->create(node_type_background);

	static_cast<BackgroundNode*>(background)->name = "bg";
	static_cast<BackgroundNode*>(background)->set_color(float3{ 1.f, 1.f, 1.f });
	graph_reader.node_map[background->name] = background;

	CppApiConnection connection1((ustring)"bg", (ustring)"background", (ustring)"output", (ustring)"surface");
	cpp_set_connection(graph_reader, connection1, graph);

	CppApiConnection connection2((ustring)"hdri", (ustring)"Color", (ustring)"bg", (ustring)"Color");
	cpp_set_connection(graph_reader, connection2, graph);


I would be very grateful for your help!

a shot in the dark - and i am not familiar with the cycles source code, but two things come to mind:

  • color space: are you sure the conversions are correct? if set to srgb/raw this can have extreme effects on shadows
  • importance sampling the hdr, this happens automatically under the hood these days, but maybe needs to be explicitly set in code?

Hey Atair,

thanks for your reply and your ideas!

I tried out different color spaces (“Linear”, “raw”, “sRGB”, u_colorspace_raw, u_colorspace_srgb) but it did not change the shadows in this case although the light looked different. To try out the importance sampling I set the volume_samling_method of the shader to “VOLUME_SAMPLING_MULTIPLE_IMPORTANCE” but that did not have an effect either. I don’t know if this is the correct way to enable importance sampling.

Another thing I tried was to set different update tags (LightManager::UPDATE_ALL, ShaderManager::UPDATE_ALL) - no improvement.

i meant this here:
This is always needed to sample localized high values like a sun, otherwise the sampler just overlooks the pixels, or sometimes samples them by chance, resulting in fireflies
Actutally it still is present in blender - world > settings > surface > Sampling

this is the difference:

In Blender I found that option too. Unfortunately I coudn’t find it in Cycles Standalone even after several hours of searching. I only found the option to choose “volume sampling multiple importance” like I described before.

Maybe have a look at the nishita sky texture commits/code - i remember specifically some slowdowns in realtime sun adjustments due to the importance map being rebuilt… its even outputted to the render status bar - importance map rebuilding or something… should make it easier to track down


This works in Cycles by adding a light with type background. Generally if you want to figure out how something in Blender maps to Cycles, look at the code that does the conversion. It’s in BlenderSync::sync_background_light in this case.


Thanks a lot to both of you! It works now :tada:
The solution was the combination of your tips: Adding the environment map with a background light and enabling multiple importance sampling.
And thanks for your tip with looking at BlenderSync, brecht! I already searched in the Blender code but did not find this snippet.

1 Like