google / filament

Filament is a real-time physically based rendering engine for Android, iOS, Windows, Linux, macOS, and WebGL2
https://google.github.io/filament/
Apache License 2.0
17.63k stars 1.86k forks source link

Is the inverseTonemap or inverseTonemapSRGB function imprecise? #3804

Closed cjsliuj closed 3 years ago

cjsliuj commented 3 years ago

I write a test case like this(inverseTonemap and Inverse_Tonemap_Unreal is copy from common_graphics.fs):

int main(int argc, char **argv) {
  float step = 0.01;
  printf("Raw,toneMapping,InversedTone,Raw\n");
  for (float r = 0; r < 2; r+=step) {
    float3 ret1 = lj::aces::ACES(float3{r,r,r}, 1.0);
    float3 invRet1 = inverseTonemap(ret1);
    printf("%f,%f,%f,%f\n",r, ret1.r,invRet1.r,r);
  }
}
float3 inverseTonemap(float3 linear) {
  // Linear input
  linear = clamp(linear, 0.0, 1.0);
  return Inverse_Tonemap_Unreal(pow(linear, float3(1.0 / 2.2)));
}

float3 Inverse_Tonemap_Unreal(const float3 x) {
  return (x * -0.155) / (x - 1.019);
}

And the line is : image Obviously, the InversedTone curve does not match the Raw curve?

romainguy commented 3 years ago

As documented it is an approximation. The inverse tonemap operator is only exact for the FILMIC tonemap operator.

romainguy commented 3 years ago

Btw I haven't checked your code but the results should be much close than what you are getting.