Skip to content

Commit be62e3a

Browse files
author
devsh
committed
improve how the resolution of an IES is calculated but also leave a TODO on how to improve it even more
1 parent 1e9138e commit be62e3a

File tree

4 files changed

+20
-8
lines changed

4 files changed

+20
-8
lines changed

examples_tests

include/nbl/builtin/glsl/material_compiler/common.glsl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -601,7 +601,7 @@ vec3 nbl_glsl_MC_oriented_material_t_getEmissive(in nbl_glsl_MC_oriented_materia
601601
if ((floatBitsToInt(emitter.orientation[0])&1u) != 1u) {
602602
right *= -1;
603603
}
604-
vec2 halfMinusHalfPixel = 0.5-0.5/vec2(nbl_glsl_unpackSize(emitter.emissionProfile));
604+
vec2 halfMinusHalfPixel = vec2(0.5)-vec2(0.5)/vec2(nbl_glsl_unpackSize(emitter.emissionProfile));
605605
return emissive * nbl_glsl_vTextureGrad(emitter.emissionProfile, nbl_glsl_IES_convert_dir_to_uv(mat3(right, up, view)*dir,halfMinusHalfPixel), mat2(0.0)).r;
606606
}
607607
#endif

src/nbl/asset/utils/CIESProfile.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,11 @@ core::smart_refctd_ptr<asset::ICPUImageView> CIESProfile::createIESTexture(Execu
118118

119119
// TODO: If no symmetry (no folding in half and abuse of mirror sampler) make dimensions odd-sized so middle texel taps the south pole
120120

121+
// TODO: This is hack because the mitsuba loader and its material compiler use Virtual Texturing, and there's some bug with IES not sampling sub 128x128 mip levels
122+
// don't want to spend time to fix this since we'll be using descriptor indexing for the next iteration
123+
width = core::max(width,128);
124+
height = core::max(height,128);
125+
121126
asset::ICPUImage::SCreationParams imgInfo;
122127
imgInfo.type = asset::ICPUImage::ET_2D;
123128
imgInfo.extent.width = width;

src/nbl/asset/utils/CIESProfileParser.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,6 @@ bool CIESProfileParser::parse(CIESProfile& result)
106106
if (vSize < 2)
107107
return false;
108108

109-
{
110-
const uint32_t maxDimMeasureSize = core::max(hSize, vSize);
111-
result.optimalIESResolution = decltype(result.optimalIESResolution){ maxDimMeasureSize, maxDimMeasureSize };
112-
result.optimalIESResolution *= 2u; // safe bias for our bilinear interpolation to work nicely and increase resolution of a profile
113-
}
114-
115109
auto& vAngles = result.vAngles;
116110
for (int i = 0; i < vSize; i++) {
117111
vAngles[i] = getDouble("vertical angle truncated");
@@ -184,6 +178,7 @@ bool CIESProfileParser::parse(CIESProfile& result)
184178
const auto H_ANGLES_I_RANGE = result.symmetry != CIESProfile::ISOTROPIC ? result.hAngles.size() - 1 : 1;
185179
const auto V_ANGLES_I_RANGE = result.vAngles.size() - 1;
186180

181+
float smallestRangeSolidAngle = FULL_SOLID_ANGLE;
187182
for (size_t j = 0; j < V_ANGLES_I_RANGE; j++)
188183
{
189184
const float thetaRad = core::radians<float>(result.vAngles[j]);
@@ -196,6 +191,11 @@ bool CIESProfileParser::parse(CIESProfile& result)
196191
for (size_t i = 0; i < H_ANGLES_I_RANGE; i++)
197192
{
198193
const float dPhiRad = result.symmetry != CIESProfile::ISOTROPIC ? core::radians<float>(hAngles[i + 1] - hAngles[i]) : (core::PI<float>() * 2.0f);
194+
// TODO: in reality one should transform the 4 vertices (or 3) into octahedral map, work out the dUV/dPhi and dUV/dTheta vectors as-if for Anisotropic Filtering
195+
// then choose the minor axis length, and use that as a pixel size (since looking for smallest thing, dont have to worry about handling discont)
196+
const float solidAngle = dsinTheta * dPhiRad;
197+
if (solidAngle<smallestRangeSolidAngle)
198+
smallestRangeSolidAngle = solidAngle;
199199

200200
const auto candelaValue = result.getCandelaValue(i, j);
201201

@@ -215,6 +215,13 @@ bool CIESProfileParser::parse(CIESProfile& result)
215215
nonZeroEmissionDomainSize += nonZeroStripDomain*dsinTheta;
216216
}
217217

218+
// assuming octahedral map
219+
{
220+
const uint32_t maxDimMeasureSize = core::sqrt(FULL_SOLID_ANGLE/smallestRangeSolidAngle);
221+
result.optimalIESResolution = decltype(result.optimalIESResolution){ maxDimMeasureSize, maxDimMeasureSize };
222+
result.optimalIESResolution *= 2u; // safe bias for our bilinear interpolation to work nicely and increase resolution of a profile
223+
}
224+
218225
assert(nonZeroEmissionDomainSize >= 0.f);
219226
//assert(nonZeroEmissionDomainSize*fluxMultiplier =approx= 2.f*(cosBack-cosFront)*PI);
220227
if (nonZeroEmissionDomainSize <= std::numeric_limits<float>::min()) // protect us from division by small numbers (just in case, we should never hit it)

0 commit comments

Comments
 (0)