perf: replace pow(x, 5.0) with multiplies in Schlick Fresnel#8774
Open
willeastcott wants to merge 6 commits into
Open
perf: replace pow(x, 5.0) with multiplies in Schlick Fresnel#8774willeastcott wants to merge 6 commits into
willeastcott wants to merge 6 commits into
Conversation
pow(x, 5.0) compiles to log2 + mul + exp2 on most hardware (two transcendentals); the four multiplies that compute x^5 directly are bit-exact and consistently cheaper, especially on mobile GPUs where transcendentals are slower. Applied to both the main getFresnel and clearcoat getFresnelCC, in both GLSL and WGSL chunks. Output is mathematically identical to the prior implementation; no visual change. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add an inline comment at each call site so a future reader does not "clean up" the manual multiply chain back into pow(x, 5.0). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Mirrors the pre-existing square() helper. Collapses the four duplicated x*x*x*x*x expansions in fresnelSchlick into single pow5() calls and keeps the rationale comment in one place. Same idea as Filament's common_math.glsl pow5 helper. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Optimizes the Schlick Fresnel term in the lit fragment shader chunks by replacing pow(x, 5) with an x^5 multiply chain, reducing reliance on transcendental ops in both GLSL and WGSL shader paths.
Changes:
- Added a
pow5helper to the lit fragmentbasechunk (GLSL + WGSL). - Updated
getFresnelandgetFresnelCCinfresnelSchlickchunks to usepow5(...)(GLSL + WGSL).
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/scene/shader-lib/wgsl/chunks/lit/frag/fresnelSchlick.js | Switch Fresnel exponent from pow(..., 5) to pow5(...). |
| src/scene/shader-lib/wgsl/chunks/lit/frag/base.js | Introduce pow5 helper in WGSL base chunk. |
| src/scene/shader-lib/glsl/chunks/lit/frag/fresnelSchlick.js | Switch Fresnel exponent from pow(..., 5) to pow5(...). |
| src/scene/shader-lib/glsl/chunks/lit/frag/base.js | Introduce pow5 helper in GLSL base chunk. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Per review feedback: basePS is user-overridable, so adding a required symbol to it would silently break any project that overrides basePS when fresnelSchlickPS calls into it. pow5 has only two callers and they are both in fresnelSchlickPS, so it belongs there. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
pow5 lives in fresnelSchlickPS now, so base.js no longer needs to be touched. Reverting the operator-spacing tidy keeps this PR scoped to the Fresnel perf change. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
pow(1.0 - saturate(cosTheta), 5.0)as a manual chain of multiplies (x2 = x*x; fresnel = x2*x2*x) in bothgetFresnelandgetFresnelCC.fresnelSchlickchunk.pow(x, 5.0)compiles toexp2(5.0 * log2(x))on most hardware — two transcendental ops. The four multiplies that computex^5directly are bit-exact and consistently cheaper, especially on mobile GPUs where transcendentals run at a lower throughput. With clearcoat enabled both Fresnel functions are invoked per light per fragment, so the saving compounds in lit scenes.This is a standard industry optimization — Unreal, Unity, and Filament all use the same form for Schlick.
Test plan
graphics_clustered-lightingand a clearcoat material — pixel diff should be zero modulo last-bit FP noise.npm testandnpm run lintpass (only pre-existing unrelated lint error inutils/esbuild-build-target.mjs).WEBGL_debug_shaders/ Mali Offline Compiler to confirmpowis gone from the translated source / cycle count drops.🤖 Generated with Claude Code