Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Book1.11.4 Unclear Argument Passing in Schlick's Approximation for Fresnel Reflection #1672

Open
Xlucidator opened this issue Feb 1, 2025 · 0 comments

Comments

@Xlucidator
Copy link

Xlucidator commented Feb 1, 2025

The issue is related to the reflectance function in the dielectric class (material.h, line 86).

Schlick’s approximation for Fresnel reflection is given by:

$$ R(\theta_i) = R_0 + (1 - R_0)(1 - \cos\theta_i)^5 $$

where:

$$ R_0 = \left(\frac{\eta_i - \eta_t}{\eta_i + \eta_t}\right)^2 = \left(\frac{1 - \eta_t / \eta_i}{1 + \eta_t / \eta_i}\right)^2 $$

Here, the refractive index transitions from $\eta_i$ to $\eta_t$.

In the implementation, the variable ri represents etai_over_etat, or $\eta_i / \eta_t$. Given this, the function should ideally be called as reflectance(cos_theta, 1 / ri) rather than reflectance(cos_theta, ri). However, because of the squared term in the formula:

$$ R_0 = \left(\frac{\eta_i - \eta_t}{\eta_i + \eta_t}\right)^2 = \left(\frac{\eta_i / \eta_t - 1}{\eta_i / \eta_t + 1}\right)^2 = \left(\frac{1 - \eta_i / \eta_t}{\eta_i / \eta_t + 1}\right)^2 $$

the original implementation reflectance(cos_theta, ri) also produces the correct result.

That said, this implementation might be confusing for beginners (I must admit, I initially misinterpreted it myself XD). Since the book does not explicitly include the Fresnel reflection equation or Schlick’s approximation, it would be helpful to provide a brief introduction beforehand. Alternatively, the implementation could be made clearer by explicitly passing both refractive indices, like this:

// Usage
reflectance(cos_theta_i, ri, 1.0);

// Function
static double reflectance(double cos_theta_i, double eta_i, double eta_t) {
    double r0 = (eta_i - eta_t) / (eta_i + eta_t);
    r0 *= r0;
    return r0 + (1 - r0) * std::pow(1 - cos_theta_i, 5);
}

Also, I think it would be more helpful to briefly introduce the formulas for Fresnel reflection coefficients $R_s$ and $R_p$, and then explain that $R_0$ is an approximation taken at normal incidence.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant