Skip to content

Use IOR to parameterize dielectrics specular reflectance#24552

Open
goodartistscopy wants to merge 2 commits into
bevyengine:mainfrom
goodartistscopy:ior_dielectric_reflectance
Open

Use IOR to parameterize dielectrics specular reflectance#24552
goodartistscopy wants to merge 2 commits into
bevyengine:mainfrom
goodartistscopy:ior_dielectric_reflectance

Conversation

@goodartistscopy
Copy link
Copy Markdown
Contributor

@goodartistscopy goodartistscopy commented Jun 7, 2026

Objective

Currently StandardMaterial specifies F0 (the reflectance at normal incidence) through the reflectance field. This provides artistic control of the color of highlights, but is disconnected from the ior parameter, which is also linked to F0 for dielectrics. The Filament doc acknowledges that reflectance and ior should be used mutually exclusively.

Standard glTF defines a fixed F0 = 4% which corresponds to IOR = 1.5, but brings further control over F0 through extensions KHR_materials_ior and KHR_materials_specular. Initial support for the latter folded both the specular_tint artistic control and the specular strength/weight into reflectance (multiplicating both). This is not the same as multiplying the specular response separately with specular, because it does not touch grazing reflections (F90).

The changes proposed here align Bevy's standard material parameters more closely to glTF. The model itself, having its root in Filament formulation, is still a bit different from the glTF formulation.

This addresses #17382.

Solution

  • Remove the reflectance parameter and use ior as the driving parameter for F0
  • Artistic control over the color of the highlights is still controlled by specular_tint
  • The specular parameter is used to non-physically "extinguish" specular highlights, including e.g. for simulating specular occlusion.
  • The deferred renderer now needs to pack both IOR and specular into the GBuffer. I propose a scheme that seems to work OK from my testing. The available space (4 bits for both!) in WebGL 2 is very limited, so some loss is expected. The renderer still does not support specular tint.
  • StandardMaterialUniform grows by one float
  • Bevy follows Filament in its formulation of the dielectric BRDF, just summing the diffuse and specular contributions without any energy compensation term. This means that we cannot follow KHR_materials_specular to the letter, where specular also modifies the compensation term. This is just for clarification, this PR does not change the current behavior in that respect. This might explain why Bevy renders some settings less bright than glTF reference renderer (see second showcase below).

Testing

  • I tested 2 relevant assets from the glTF samples SpecularTest and IORTestGrid

  • rendered using scene_viewer (setting AmbientLight to 0.0 to better see the differences):

cargo run --example scene_viewer --features="pbr_specular_textures free_camera bevy_dev_tools" <...>

Showcase

IOR
  • Notice the reduction of reflectance with lower IOR

Before:
ior-before
After:
ior-after

Specular control
  • The second row is now identical to the first one
  • The last row is less bright than before, but this is because we currently square the reflectance to obtain F0, meaning that the color factors > 1 are artificially inflated. This is confirmed with the last image which is main but with the reflectance formula changed to F0 = 0.08 * reflectance from F0 = 0.16 * reflectance * reflectance.
  • For reference this is how the glTF Sample Viewer renders this asset.

Before:
specular-before
After:
specular-after
Before, linear reflectance ramp
specular-before-linear-reflectance-ramp

@goodartistscopy goodartistscopy force-pushed the ior_dielectric_reflectance branch 3 times, most recently from 20d5ad4 to d78e0c5 Compare June 7, 2026 19:56
@goodartistscopy goodartistscopy force-pushed the ior_dielectric_reflectance branch from d78e0c5 to 3bba25f Compare June 7, 2026 19:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant