Skip to content

Commit b5501a5

Browse files
Add ShaderGen option for Airy Fresnel iterations (AcademySoftwareFoundation#2569)
This changelist adds a ShaderGen option for the number of iterations used to compute Airy Fresnel reflections for iridescent materials in hardware shading languages. The visual difference between iteration counts turns out to be very small for many iridescent materials, and this option should give applications more control over the tradeoff between performance and reference-quality accuracy.
1 parent 9e8ca2e commit b5501a5

File tree

5 files changed

+39
-2
lines changed

5 files changed

+39
-2
lines changed

libraries/pbrlib/genglsl/lib/mx_microfacet_specular.glsl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ vec3 mx_fresnel_airy(float cosTheta, FresnelData fd)
374374

375375
// Reflectance term for m>0 (pairs of diracs)
376376
Cm = Rs - T121.x;
377-
for (int m=1; m<=2; m++)
377+
for (int m = 1; m <= AIRY_FRESNEL_ITERATIONS; m++)
378378
{
379379
Cm *= r123p;
380380
Sm = 2.0 * mx_eval_sensitivity(float(m) * opd, float(m)*(phi23p+vec3(phi21.x)));
@@ -389,7 +389,7 @@ vec3 mx_fresnel_airy(float cosTheta, FresnelData fd)
389389

390390
// Reflectance term for m>0 (pairs of diracs)
391391
Cm = Rp - T121.y;
392-
for (int m=1; m<=2; m++)
392+
for (int m = 1; m <= AIRY_FRESNEL_ITERATIONS; m++)
393393
{
394394
Cm *= r123s;
395395
Sm = 2.0 * mx_eval_sensitivity(float(m) * opd, float(m)*(phi23s+vec3(phi21.y)));

source/MaterialXGenGlsl/GlslShaderGenerator.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,10 @@ void GlslShaderGenerator::emitPixelStage(const ShaderGraph& graph, GenContext& c
404404
emitLineBreak(stage);
405405
}
406406

407+
// Define Airy Fresnel iterations
408+
emitLine("#define AIRY_FRESNEL_ITERATIONS " + std::to_string(context.getOptions().hwAiryFresnelIterations), stage, false);
409+
emitLineBreak(stage);
410+
407411
// Add lighting support
408412
if (lighting)
409413
{

source/MaterialXGenMsl/MslShaderGenerator.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -874,6 +874,10 @@ void MslShaderGenerator::emitPixelStage(const ShaderGraph& graph, GenContext& co
874874
emitLineBreak(stage);
875875
}
876876

877+
// Define Airy Fresnel iterations
878+
emitLine("#define AIRY_FRESNEL_ITERATIONS " + std::to_string(context.getOptions().hwAiryFresnelIterations), stage, false);
879+
emitLineBreak(stage);
880+
877881
// Add lighting support
878882
if (lighting)
879883
{

source/MaterialXGenShader/GenOptions.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ class MX_GENSHADER_API GenOptions
8585
hwSpecularEnvironmentMethod(SPECULAR_ENVIRONMENT_FIS),
8686
hwDirectionalAlbedoMethod(DIRECTIONAL_ALBEDO_ANALYTIC),
8787
hwTransmissionRenderMethod(TRANSMISSION_REFRACTION),
88+
hwAiryFresnelIterations(2),
8889
hwSrgbEncodeOutput(false),
8990
hwWriteDepthMoments(false),
9091
hwShadowMap(false),
@@ -153,6 +154,11 @@ class MX_GENSHADER_API GenOptions
153154
/// for HW shader targets.
154155
HwTransmissionRenderMethod hwTransmissionRenderMethod;
155156

157+
/// Sets the number of iterations for Airy Fresnel reflection calculations.
158+
/// Higher values provide more accurate thin-film interference patterns
159+
/// but increase computational cost. Defaults to 2.
160+
unsigned int hwAiryFresnelIterations;
161+
156162
/// Enables an sRGB encoding for the color output on HW shader targets.
157163
/// Defaults to false.
158164
bool hwSrgbEncodeOutput;

source/MaterialXView/Viewer.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ const bool USE_FLOAT_BUFFER = false;
6565
const int MIN_ENV_SAMPLE_COUNT = 4;
6666
const int MAX_ENV_SAMPLE_COUNT = 1024;
6767

68+
const int MIN_AIRY_FRESNEL_ITERATIONS = 1;
69+
const int MAX_AIRY_FRESNEL_ITERATIONS = 8;
70+
6871
const int SHADOW_MAP_SIZE = 2048;
6972
const int ALBEDO_TABLE_SIZE = 128;
7073
const int IRRADIANCE_MAP_WIDTH = 256;
@@ -892,6 +895,26 @@ void Viewer::createAdvancedSettings(ng::ref<Widget> parent)
892895
_lightHandler->setEnvSampleCount(MIN_ENV_SAMPLE_COUNT * (int) std::pow(4, index));
893896
});
894897

898+
ng::ref<ng::Widget> fresnelGroup = new Widget(settingsGroup);
899+
fresnelGroup->set_layout(new ng::BoxLayout(ng::Orientation::Horizontal));
900+
new ng::Label(fresnelGroup, "Airy Fresnel Iterations:");
901+
mx::StringVec fresnelOptions;
902+
for (int i = MIN_AIRY_FRESNEL_ITERATIONS; i <= MAX_AIRY_FRESNEL_ITERATIONS; i *= 2)
903+
{
904+
fresnelOptions.push_back(std::to_string(i));
905+
}
906+
ng::ref<ng::ComboBox> fresnelBox = new ng::ComboBox(fresnelGroup, fresnelOptions);
907+
fresnelBox->set_chevron_icon(-1);
908+
fresnelBox->set_selected_index((int)std::log2(_genContext.getOptions().hwAiryFresnelIterations / MIN_AIRY_FRESNEL_ITERATIONS));
909+
fresnelBox->set_callback([this](int index)
910+
{
911+
_genContext.getOptions().hwAiryFresnelIterations = MIN_AIRY_FRESNEL_ITERATIONS * (int)std::pow(2, index);
912+
#ifndef MATERIALXVIEW_METAL_BACKEND
913+
_genContextEssl.getOptions().hwAiryFresnelIterations = _genContext.getOptions().hwAiryFresnelIterations;
914+
#endif
915+
reloadShaders();
916+
});
917+
895918
ng::ref<ng::Label> lightingLabel = new ng::Label(settingsGroup, "Lighting Options");
896919
lightingLabel->set_font_size(20);
897920
lightingLabel->set_font("sans-bold");

0 commit comments

Comments
 (0)