An environment gives a scene a distant sky and diffuse image-based lighting. It is optional: scenes without one keep their solid background and existing lighting.
sky := nt3d.GradientEnvironment(
color.RGBA{72, 130, 220, 255}, // zenith
color.RGBA{218, 231, 245, 255}, // horizon
color.RGBA{115, 100, 77, 255}, // ground
)
scene.SetEnvironment(sky)The widget picks it up through the scene’s frames. Call view.Refresh() after
changing it when the application is not already scheduling frames. Remove it
with scene.SetEnvironment(nil). Environment objects are immutable and can be
shared between scenes; frames retain the environment they were made with.
Image skies#
Pass a decoded PNG, JPEG, or other Go image to nt3d.NewEnvironment(img).
It snapshots the pixels, so callers may reuse or modify the source afterwards.
The image is an equirectangular panorama, normally twice as wide as it is tall.
The top is +Z, the center faces +X, and increasing U turns toward +Y. Horizontal
sampling wraps at the seam, while the poles clamp. Alpha is ignored. The same
8192-pixel side limit as NewTexture applies. Input colors are sRGB, not HDR.
environment, err := nt3d.NewEnvironment(img)
if err != nil {
return err
}
scene.SetEnvironment(environment)The sky follows camera orientation but stays fixed under translation and zoom.
Perspective views use the camera’s authored field of view and roll. Orthographic
views use a fixed 45-degree field of view, so models have a useful sky instead
of a single constant direction.
For hand-built frames, set Frame.Forward to the camera’s viewing direction.
Scene.Frame does this automatically.
Light from the environment#
Both renderers add the same precomputed diffuse light to Frame.Lighting.
To use the environment alone, clear the usual lights:
frame, err := scene.Frame(camera, 960, 640)
if err != nil {
return err
}
frame.Lighting = nt3d.Lighting{}
frame.EnvironmentStrength = 0.6EnvironmentStrength scales only the lighting; zero means 1, as with the
other lighting intensity fields. EnvironmentBackgroundOnly = true keeps the
sky while disabling its light. Frame.Environment can also override the scene’s
choice for one frame. In a widget, set these fields in a frame decorator; use
SetLighting(nt3d.Lighting{}) to remove its default lights.
Environment lighting uses nine degree-two RGB spherical-harmonic coefficients, with cosine convolution, for broad directional diffuse illumination. It is a cheap, low-frequency approximation: it does not reproduce small bright light sources, cast environment shadows, or capture sharp reflections. Existing directional and point lights still provide highlights and mapped shadows. Unlit materials, points, lines, and overlays remain unlit. Prefer the default linear-light frames for physically meaningful color blending.
Use nt3d.NewSHEnvironment(radiance) to build an environment directly from SH
radiance coefficients, including a generated sky panorama. Environment.DiffuseSH()
returns its nine convolved diffuse coefficients. The shared nt3dsh package
provides projection, evaluation, and rotation; see
spherical-harmonic lighting for an
example and coefficient conventions. Gaussian splats use SH for their own
view-dependent color and remain unlit by the environment.
The GPU uploads the panorama when it changes and draws one fullscreen triangle.
Software samples the same sky and uses the same diffuse coefficients. The sky
writes no depth, so transparency composites over it and it never changes bounds,
culling, picking, or shadow-map fitting. Wireframe uses sky-colored terminal cell
backgrounds and contrasting default strokes. Fog keeps its existing behavior:
set an explicit Fog.Color near the horizon color if you want it to meet the sky.
Try task lights or the Lights web gallery: it starts with sky and key, then
l cycles through the environment and light presets, including SH studio.
Press h to select the SH studio environment and rotate it in 30-degree steps.
The image preset is an original generated warm/cool panorama, with no downloaded
assets. 1, 2, and 3 compare GPU, software, and wireframe; drag to orbit.
Reflections#
Material.Reflectivity samples the panorama along the reflected view direction.
It is the normal-incidence reflectance F0, in [0,1]: zero explicitly disables
reflection, .02 suits water, and 1 is a mirror. Schlick Fresnel increases
reflection toward grazing angles, blending it with the lit base color. Direct
specular highlights are added afterward. Normal maps affect both contributions.
GPU and software share panorama orientation, seam wrapping, pole clamping, and
color-space behavior. EnvironmentStrength scales reflected light too;
EnvironmentBackgroundOnly disables it along with diffuse environment light.
Without an environment, reflectivity has no effect.
This is a sharp distant-sky reflection. It does not reflect nearby geometry
or prefilter rough surfaces. Shininess controls direct highlights only.