在实施Ole Gulbrandsen(http://jcgt.org/published/0003/04/03/paper.pdf)撰写的“ Artist Friendly Metallic Fresnel”论文时,我读到它是完全可逆的: >
(第2.3.2节):对于所有r,g∈(0,1),从(n,k)到(r,g)的映射是双射


但是,似乎不是这样吗?将(r,g)转换为(n,k)并转换回(r,g)时,我没有得到与初始参数匹配的输出。这是预期的吗?

r: 0.7 0.55 0.075
g: 0.8 0.65 0.35
n: 2.39006 2.5479 1.44145
k: 4.98834 3.604 0.537046
r_check: 0.737183 0.601524 0.0773389
g_check: 0.827686 0.699977 0.35995


这里是要验证的实现,请注意,我只实现了get_k(),本文已经提供了其他功能。 get_k()从本文中的以下公式得出:

$$ k(r,n(r,g))= \ sqrt {\ frac {1} {1-r}(r(n (r,g)+1)^ 2-(n(r,g)-1)^ 2)} $$

 #include <iostream>
#include <vector>
#include <cmath>

float n_min(float r) {
  return (1.0-r)/(1.0+r);
}

float n_max(float r) {
  return (1.0 + std::sqrt(r))/(1.0-std::sqrt(r));
}

float get_n(float r, float g) {
  return g*n_min(r) + (1.0-g)*n_max(r);
}

float get_k(float r, float n) {
  return std::sqrt( (1.0/(1.0-r)) * (r * std::pow(n+1.0, 2)) - std::pow(n-1.0, 2) );
}

//float get_k2(float r, float n) {
//  float nr = (n+1.0)*(n+1.0)*r-(n-1.0)*(n-1.0);
//  return nr/(1.0-r);
//}

float get_r(float n, float k) {
  return (std::pow(n-1.0, 2)+std::pow(k, 2)) / (std::pow(n+1.0, 2)+std::pow(k, 2));
}

float get_g(float n, float k) {
  float r = get_r(n, k);
  return (n_max(r)-n)/(n_max(r)-n_min(r));
}



int main() {
  std::vector<float> r = {0.7, 0.55, 0.075};
  std::vector<float> g = {0.8, 0.65, 0.35};
  std::cout << "r: " << r[0] << " " << r[1] << " " << r[2] << std::endl;
  std::cout << "g: " << g[0] << " " << g[1] << " " << g[2] << std::endl;


  std::vector<float> n(3);
  std::vector<float> k(3);
  for (int i = 0; i<3; i++) {
    n[i] = get_n(r[i], g[i]);
    k[i] = get_k(r[i], n[i]);
  }
  std::cout << "n: " << n[0] << " " << n[1] << " " << n[2] << std::endl;
  std::cout << "k: " << k[0] << " " << k[1] << " " << k[2] << std::endl;


  std::vector<float> r_check(3);
  std::vector<float> g_check(3);
  for (int i = 0; i<3; i++) {
    r_check[i] = get_r(n[i], k[i]);
    g_check[i] = get_g(n[i], k[i]);
  }
  std::cout << "r_check: " << r_check[0] << " " << r_check[1] << " " << r_check[2] << std::endl;
  std::cout << "g_check: " << g_check[0] << " " << g_check[1] << " " << g_check[2] << std::endl;
}
 


#1 楼

我不是真的期望如此,不。本文中的公式并不是最优雅的-里面有很多括号。在这种情况下,我认为这只是在get_k实现中对括号进行一点改组的问题-两项均应除以(1-r)

    float get_k(float r, float n) {
        return std::sqrt( 1.0/(1.0-r) * ( r*std::pow(n+1.0, 2) - std::pow(n-1.0, 2) ));
    }


评论


$ \ begingroup $
请论文作者注册并提供答案!
$ \ endgroup $
– Zeno
18/12/4在22:01