Jump to content

Equirectangular Diffuse Transform

Recommended Posts

Equirectangular Diffuse Transform DLL: Equirectangular Diffuse Transform.zip


The user interface:



Summary: The Texture Shader has a mapping mode called Reflection Map (Equirectangular) which allows a panoramic image stored as an equirectangular (ER) map to be reflected onto a height map. Equirectangular Diffuse Transform  provides a method by which the panoramic image can also be used to apply diffuse lighting consistent with the same image. The basic method is to use the original panoramic image to produce the reflection, then use the same image transformed with Equirectangular Diffuse Transform to produce the diffuse lighting, using the Texture Shader's Gradient Map (Equirectangular) mapping mode. The offset and rotation of the Texture Shader's clipboard image should remain the same for the two steps, and normally the light source should be Ambient, without Directional light.


The Help menu description:


Equirectangular Diffuse Transform transforms an equirectangular environment map into an equirectangular diffuse map that can be used to apply diffuse lighting to a height map. The effect uses the first five bands of spherical harmonics to approximate convolution with a clamped cosine function covering a hemisphere.

The resulting diffuse map map can be used by the Texture Shader effect, with the Clipboard Image Mapping Method set to Gradient Map (Equirectangular). Typically, the Directional Light Intensity should be set to zero, and the Ambient Light Color adjusted to determine the light intensity.

The width of an equirectangular map is normally twice the height, but any image will be treated as though it covers the entire sphere.

The controls are:

Pre-Scale Brightness to Maximum Range: When enabled, the brightness of the diffuse map is automatically adjusted so that the the maximum color is as bright as possible without overflowing. This provides the largest brightness range when shading.

When disabled, if Expansion Gamma equals Compression Gamma Reciprocal, the color of a constant-color map is unchanged when transformed; if Expansion Gamma does not equal Compression Gamma Reciprocal, a constant-white map is unchanged when transformed.

Brightness: Adjusts the brightness of the diffuse map. Brightness values greater than 1.0 should generally not be used when Pre-Scale Brightness to Maximum Range is enabled, since they will result in color overflow, and therefore clamping.

Expansion Gamma: The exponent to which the color components are raised before being transformed. When equal to Compression Gamma Reciprocal, this can be used to compensate for gamma compression. Gamma is typically around 2.2. When used with Compression Gamma Reciprocal set to 1.0, it provides a contrast adjustment for the pre-transformed map; increasing the upper-end contrast when greater than 1.0, and decreasing the upper-end contrast when less than 1.0. This can be useful for emphasizing the lights in the map over the background colors.

Compression Gamma Reciprocal: The reciprocal of the exponent to which the color components of the diffuse map are raised.

Link Expansion and Compression Gammas: When enabled, Expansion Gamma will always match Compression Gamma Reciprocal.




Original equirectangular map:



Transformed map (with gamma of 1.0):



Shading example:



Shading details:


This is one of several possible approaches.


The original height map (the height should be set to 255):



The layers making up the image, from top to bottom.


The topmost layer is the reflection. It was shaded in the Reflection Map (Equirectangular) mode, with the original ER map, using Ambient light at full brightness. The layer opacity is used to determine the brightness.

The Blend Mode for this reflection layer is Additive, with Opacity 80.



This second layer is the color. For simplicity, I used a solid color, but other surface colors could be used. Normally they would be produced by using the Texture Shader to apply a clipboard image with only Ambient light.

Also, if only a solid color is used, this layer can be omitted, and the color of the Ambient light set to achieve the desired surface color for the Diffuse Shading layer.

The Blend Mode for the color layer is Multiply, with Opacity 255.


The third layer is the diffuse lighting layer. It was shaded with the Gradient Map (Equirectangular) mode, with diffuse-transformed ER map, using Ambient light at full brightness (255, 255, 255) and no Directional light. The layer opacity is used to determine the brightness.

The Blend Mode for the diffuse lighting layer is Additive, with Opacity 190.


The lowest layer is the ambient lighting layer. It's always solid colored, whose color and brightness determine the amount of ambient light to add to the diffuse layer.

Adding ambient lighting is often desirable to fill out the shadows. If the transformed ER map is sufficient alone, this layer could either be black, or the diffuse lighting layer could be set to the Normal blending mode, and the brightness adjusted, instead of the Opacity. The advantage to keeping an ambient layer, even if it's black, is that the Opacity adjustment to the diffuse layer is a more flexible method of adjusting brightness.

The Blend Mode is Normal, with opacity 255.





Additional comments:


  • Though I think theoretically using a gamma of 2.2 makes sense, the example above uses a gamma of 1.0. Until recently, I began to doubt the gamma control was very useful, except as a contrast adjustment; but now I'm beginning to think using a gamma of 2.2 might be better.
  • The plugin was originally inspired a a series of articles called Spherical Harmonics and applications in real time graphics. If you compare my transformed image to the article's, you'll see they are different. Part of the difference is that by default I scale the brightness to make the image as bright a possible, without overflowing. There are, however, other differences, and I don't know why. However, I've done many tests that pretty much convince me that my result is correct. The tests include writing a plugin that (very slowly) does a full convolution with a clamped cosine function. Though the algorithm was completely different, the results were almost identical. I wrote a fairly detailed comment about the differences on the article's website, which was flagged as spam by the blankety-blank spam filter. Unfortunately, the article is quite old, so the author hasn't responded to my earlier comments.
  • The ER map used for shading should generally represent light sources, not colored areas. If, for instance, the ER map has a large expanse of grass, the diffuse shading will be very green, even though the grass would actually emit, through reflection, only a limited amount of green light onto an object. In some cases, it would be desirable to adjust the map's contrast to emphasize the lights over other areas. (This can be done by setting the expansion gamma to a larger value than the compression reciprocal.) It may also be useful to decrease the map's color saturation, to reduce the effect when shading colored surfaces.
  • To keep my example simple and direct, and avoid confusing detours, I didn't make any post-shading modifications to the diffuse-shaded layer. However, in most cases I would try adjusting the brightness, contrast, saturation, and such to achieve the best result.
  • On the off chance another programmer wants to use my transform code for some other purpose (such as computing the spherical harmonic coefficients) , as with all my PDN code, I'd be happy to provide it.
  • Like 5
  • Upvote 1
Link to post
Share on other sites
7 hours ago, dipstick said:

This looks a lot like Blender's equirectangular diffuse.


I'd be very interested in any details about Blender's equirectangular diffuse shading. I know very little about Blender, but I was under the impression it uses cube maps for the actual shading instead of working directly from equirectangular maps..

Link to post
Share on other sites

Golly @MJW another amazing Plugin from you.  I have to say you are definitely the sharpest knife in the drawer 💥


I am still studying your steps and instructions and will need to practice a few more times, but I had fun and made this:




I do have a silly question to ask.  When you say " Ambient light at full brightness." does it mean you have this turned up to white?





Link to post
Share on other sites
13 minutes ago, Pixey said:

When you say " Ambient light at full brightness." does it mean you have this turned up to white?


Not a silly question at all. Yes, the Ambient should be 255, 255, 255, and the Directional light should be 0, 0, 0. The lighting in the ER map substitutes for the directional light.


The reason for using the maximum is that increasing brightness afterword causes a loss of precision in the colors, while decreasing brightness doesn't. So it's usually best to start with as bright of an image as possible, without overflowing. The way things work, shading with fully bright ambient light and no directional light should never result in overflow.


For the method I suggested in the example, the layer's Opacity is used to adjust its brightness in the combined image. This assumes the layer has the Additive blend mode, as in the example.

Link to post
Share on other sites
5 hours ago, MJW said:

I'd be very interested in any details about Blender's equirectangular diffuse shading.


Here I used "Principal Shading" in blender on this chain link. I used your environmental image as an environmental map for the "World". It can use either equirectangular or mirror ball.





Link to post
Share on other sites
1 hour ago, dipstick said:

Here I used "Principal Shading" in blender on this chain link. I used your environmental image as an environmental map for the "World". It can use either equirectangular or mirror ball.


Thanks, dipstick. Can Blender produce diffuse shading based on an environment map (like Texture Shader's Gradient Map mode, shown in the third layer of my exampe), or only reflections (like Texture Shader's Reflection Map mode). I'm not quite clear from the images.


(I probably should download Blender, myself.)

Link to post
Share on other sites

If you add some roughness to the shader, it will reduce the reflection. It's a matter of what you want. You can download blender and see for yourself. I can post the blender file if you want. Blender is very hard to learn though and I still know next to nothing about it.


This is actually the first object I've sculpted yet. I have a long way to go. Even on this textured vase, you can see some reflections of your image.



Edited by dipstick
added vase
Link to post
Share on other sites

Great new addition to the Height Map arsenal ... although I should have read your answer to Pixey properly.

One question - does the Texture Height Scale in TS need to be adjusted ?  I did here




... more experimenting needed

  • Like 1
Link to post
Share on other sites
52 minutes ago, welshblue said:

One question - does the Texture Height Scale in TS need to be adjusted ?


No, there should be no need to adjust the texture height.


My reply to Pixie is that the "standard" way to use the equirectangular mapping modes is to use all ambient light, with no directional light. The directional lighting comes from the light sources in the equirectangular maps. The specular (reflection) component comes from the original equirectangular map, using the TS's Reflection Map (Equirectangular) mode, while the directional component (and also some ambient component) comes from the diffuse-transformed map, using the Gradient Map (Equirectangular) mode. The lighting brightness can be adjusted either by changing the brightness of the ambient light when shading, or by shading with the light at maximum brightness, and adjusting the layer Opacity (assuming the layer blending mode is Additive. I generally prefer the second method, which is more flexible.


One bit of advice is to always double check that the TS shading mode is the correct one for the type of shading being done: Reflection Map for the reflections, and Gradient Map for the diffuse lighting. Switching between them can be confusing -- at least to me. I swear, when I was experimenting to make the example, I did it wrong more times than I did it right.

Link to post
Share on other sites

The following two equirectangular maps may be useful for those interested in experimenting with the equirectangular shading modes:






They both represent a (more or less) point-source directional light, similar to the Texture Shader's normal directional light source.  The second map is the first map after applying the Equirectangular Diffuse Transform.


The first map can be used to produce the specular lighting, using the Reflection Map (Equirectangular) shading mode, the second can be used to produce the diffuse lighting, using the Gradient Map (Equirectangular) shading mode. I think starting with this simple lighting situation will give a better idea of how the equirectangular shading modes work.



Link to post
Share on other sites
9 hours ago, MJW said:

Reflection Map for the reflections, and Gradient Map for the diffuse lighting. 


I was forgetting to switch from Reflection to Gradient. I think I've got too much of a 'bulb' going on here and maybe the wrong emap for the lighting, but I'm happier about this version




  • Like 1
Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Create New...