Jump to content

  • Log In with Google      Sign In   
  • Create Account

#ActualChris_F

Posted 13 March 2013 - 09:50 AM

OK, I'm bumping this thread because I'm revisiting the Fresnel equation, this time using complex IOR values. I'm having a hard time converting this to complex numbers.

 

 

float Fresnel(float CosThetaI, float n)
{
    float CosThetaT = sqrt(max(0, 1 - (1 - CosThetaI * CosThetaI) / (n * n)));
    float NCosThetaT = n * CosThetaT;
    float NCosThetaI = n * CosThetaI;
    float Rs = pow(abs((CosThetaI - NCosThetaT) / (CosThetaI + NCosThetaT)), 2);
    float Rp = pow(abs((CosThetaT - NCosThetaI) / (CosThetaT + NCosThetaI)), 2);
    return (Rs + Rp) / 2;
}

 

This is the basic formula, but I need to re-write it so that it looks like:

 

 

float Fresnel(float CosThetaI, vec3 n, vec3 k)
{
    ...
}

 

Where n and k make up the complex IOR (n + ki). I've taken a few stabs at it, but it's gotten me nowhere. Here is my train wreck of an attempt:

 

 

vec3 Fresnel(float CosThetaI, vec3 n, vec3 k)
{
    float temp = 1 - CosThetaI * CosThetaI;

    vec3 NKSqr_real = n * n - k * k;
    vec3 NKSqr_imag = n * k * 2;

    vec3 temp2_real = (temp * NKSqr_real) / (NKSqr_real * NKSqr_real + NKSqr_imag * NKSqr_imag);
    vec3 temp2_imag = -(temp * NKSqr_imag) / (NKSqr_real * NKSqr_real + NKSqr_imag * NKSqr_imag);

    temp2_real = 1 - temp2_real;
    temp2_imag = -temp2_imag;

    vec3 CosThetaT_real = sqrt((temp2_real + sqrt(temp2_real * temp2_real + temp2_imag * temp2_imag)) / 2);
    vec3 CosThetaT_imag = sign(temp2_imag) * sqrt((-temp2_real + sqrt(temp2_real * temp2_real + temp2_imag * temp2_imag)) / 2);

    vec3 NCosThetaT_real = n * CosThetaT_real - k * CosThetaT_imag;
    vec3 NCosThetaT_imag = k * CosThetaT_real + n * CosThetaT_imag;

    vec3 NCosThetaI_real = n * CosThetaI;
    vec3 NCosThetaI_imag = k * CosThetaI;

    vec3 CosThetaI_minus_NCosThetaT_real = CosThetaI - NCosThetaT_real;
    vec3 CosThetaI_minus_NCosThetaT_imag = -NCosThetaT_imag;

    vec3 CosThetaI_plus_NCosThetaT_real = CosThetaI + NCosThetaT_real;
    vec3 CosThetaI_plus_NCosThetaT_imag = NCosThetaT_imag;

    vec3 a, b, c, d;

    a = CosThetaI_minus_NCosThetaT_real;
    b = CosThetaI_minus_NCosThetaT_imag;
    c = CosThetaI_plus_NCosThetaT_real;
    d = CosThetaI_plus_NCosThetaT_imag;

    vec3 Rs_real = (a * c + b * d) / (c * c + d * d);
    vec3 Rs_imag = (b * c + a * d) / (c * c + d * d);

    vec3 Rs = sqrt(Rs_real * Rs_real + Rs_imag * Rs_imag);
    Rs = Rs * Rs;

    vec3 CosThetaT_minus_NCosThetaI_real = CosThetaT_real - NCosThetaI_real;
    vec3 CosThetaT_minus_NCosThetaI_imag = CosThetaT_imag - NCosThetaI_imag;

    vec3 CosThetaT_plus_NCosThetaI_real = CosThetaT_real + NCosThetaI_real;
    vec3 CosThetaT_plus_NCosThetaI_imag = CosThetaT_imag + NCosThetaI_imag;

    a = CosThetaT_minus_NCosThetaI_real;
    b = CosThetaT_minus_NCosThetaI_imag;
    c = CosThetaT_plus_NCosThetaI_real;
    d = CosThetaT_plus_NCosThetaI_imag;

    vec3 Rp_real = (a * c + b * d) / (c * c + d * d);
    vec3 Rp_imag = (b * c + a * d) / (c * c + d * d);

    vec3 Rp = sqrt(Rp_real * Rp_real + Rp_imag * Rp_imag);
    Rp = Rp * Rp;

    return (Rs + Rp) / 2;
}

 

It would be so much easier if HLSL/GLSL had first class support for complex values. wacko.png

 

EDIT:

 

Never mind. I managed to come up with this.

 

 

vec2 CADD(vec2 a, vec2 b) {    return a + b; }
vec2 CSUB(vec2 a, vec2 b) {    return a - b; }
vec2 CMUL(vec2 a, vec2 b) {    return vec2(a.x * b.x - a.y * b.y, a.y * b.x + a.x * b.y); }
vec2 CDIV(vec2 a, vec2 b) {    return vec2((a.x * b.x + a.y * b.y) / (b.x * b.x + b.y * b.y), (a.y * b.x - a.x * b.y) / (b.x * b.x + b.y * b.y)); }
float CABS(vec2 a) { return sqrt(a.x * a.x + a.y * a.y); }
vec2 CSQRT(vec2 a) { return vec2(sqrt((a.x + sqrt(a.x * a.x + a.y * a.y)) / 2), sign(a.y) * sqrt((-a.x + sqrt(a.x * a.x + a.y * a.y)) / 2)); }

float _Fresnel(float _CosThetaI, vec2 n)
{
    vec2 CosThetaI = vec2(_CosThetaI, 0);
    vec2 CosThetaT = CSQRT(CSUB(vec2(1.0, 0), CDIV(CSUB(vec2(1.0, 0), CMUL(CosThetaI, CosThetaI)), CMUL(n, n))));
    vec2 NCosThetaI = CMUL(n, CosThetaI);
    vec2 NCosThetaT = CMUL(n, CosThetaT);
    float Rs = pow(CABS(CDIV(CSUB(CosThetaI, NCosThetaT), CADD(CosThetaI, NCosThetaT))), 2);
    float Rp = pow(CABS(CDIV(CSUB(CosThetaT, NCosThetaI), CADD(CosThetaT, NCosThetaI))), 2);
    return (Rs + Rp) / 2;
}
 
vec3 Fresnel(float CosThetaI, vec3 n, vec3 k)
{
    return vec3(
            _Fresnel(CosThetaI, vec2(n.r, k.r)),
            _Fresnel(CosThetaI, vec2(n.g, k.g)),
            _Fresnel(CosThetaI, vec2(n.b, k.b))
        );
}

#4Chris_F

Posted 12 March 2013 - 07:58 PM

OK, I'm bumping this thread because I'm revisiting the Fresnel equation, this time using complex IOR values. I'm having a hard time converting this to complex numbers.

 

 

float Fresnel(float CosThetaI, float n)
{
    float CosThetaT = sqrt(1 - (1 - CosThetaI * CosThetaI) / (n * n));
    float NCosThetaT = n * CosThetaT;
    float NCosThetaI = n * CosThetaI;
    float Rs = pow(abs((CosThetaI - NCosThetaT) / (CosThetaI + NCosThetaT)), 2);
    float Rp = pow(abs((CosThetaT - NCosThetaI) / (CosThetaT + NCosThetaI)), 2);
    return (Rs + Rp) / 2;
}

 

This is the basic formula, but I need to re-write it so that it looks like:

 

 

float Fresnel(float CosThetaI, vec3 n, vec3 k)
{
    ...
}

 

Where n and k make up the complex IOR (n + ki). I've taken a few stabs at it, but it's gotten me nowhere. Here is my train wreck of an attempt:

 

 

vec3 Fresnel(float CosThetaI, vec3 n, vec3 k)
{
    float temp = 1 - CosThetaI * CosThetaI;

    vec3 NKSqr_real = n * n - k * k;
    vec3 NKSqr_imag = n * k * 2;

    vec3 temp2_real = (temp * NKSqr_real) / (NKSqr_real * NKSqr_real + NKSqr_imag * NKSqr_imag);
    vec3 temp2_imag = -(temp * NKSqr_imag) / (NKSqr_real * NKSqr_real + NKSqr_imag * NKSqr_imag);

    temp2_real = 1 - temp2_real;
    temp2_imag = -temp2_imag;

    vec3 CosThetaT_real = sqrt((temp2_real + sqrt(temp2_real * temp2_real + temp2_imag * temp2_imag)) / 2);
    vec3 CosThetaT_imag = sign(temp2_imag) * sqrt((-temp2_real + sqrt(temp2_real * temp2_real + temp2_imag * temp2_imag)) / 2);

    vec3 NCosThetaT_real = n * CosThetaT_real - k * CosThetaT_imag;
    vec3 NCosThetaT_imag = k * CosThetaT_real + n * CosThetaT_imag;

    vec3 NCosThetaI_real = n * CosThetaI;
    vec3 NCosThetaI_imag = k * CosThetaI;

    vec3 CosThetaI_minus_NCosThetaT_real = CosThetaI - NCosThetaT_real;
    vec3 CosThetaI_minus_NCosThetaT_imag = -NCosThetaT_imag;

    vec3 CosThetaI_plus_NCosThetaT_real = CosThetaI + NCosThetaT_real;
    vec3 CosThetaI_plus_NCosThetaT_imag = NCosThetaT_imag;

    vec3 a, b, c, d;

    a = CosThetaI_minus_NCosThetaT_real;
    b = CosThetaI_minus_NCosThetaT_imag;
    c = CosThetaI_plus_NCosThetaT_real;
    d = CosThetaI_plus_NCosThetaT_imag;

    vec3 Rs_real = (a * c + b * d) / (c * c + d * d);
    vec3 Rs_imag = (b * c + a * d) / (c * c + d * d);

    vec3 Rs = sqrt(Rs_real * Rs_real + Rs_imag * Rs_imag);
    Rs = Rs * Rs;

    vec3 CosThetaT_minus_NCosThetaI_real = CosThetaT_real - NCosThetaI_real;
    vec3 CosThetaT_minus_NCosThetaI_imag = CosThetaT_imag - NCosThetaI_imag;

    vec3 CosThetaT_plus_NCosThetaI_real = CosThetaT_real + NCosThetaI_real;
    vec3 CosThetaT_plus_NCosThetaI_imag = CosThetaT_imag + NCosThetaI_imag;

    a = CosThetaT_minus_NCosThetaI_real;
    b = CosThetaT_minus_NCosThetaI_imag;
    c = CosThetaT_plus_NCosThetaI_real;
    d = CosThetaT_plus_NCosThetaI_imag;

    vec3 Rp_real = (a * c + b * d) / (c * c + d * d);
    vec3 Rp_imag = (b * c + a * d) / (c * c + d * d);

    vec3 Rp = sqrt(Rp_real * Rp_real + Rp_imag * Rp_imag);
    Rp = Rp * Rp;

    return (Rs + Rp) / 2;
}

 

It would be so much easier if HLSL/GLSL had first class support for complex values. wacko.png

 

EDIT:

 

Never mind. I managed to come up with this.

 

vec2 CADD(vec2 a, vec2 b) {    return a + b; }
vec2 CSUB(vec2 a, vec2 b) {    return a - b; }
vec2 CMUL(vec2 a, vec2 b) {    return vec2(a.x * b.x - a.y * b.y, a.y * b.x + a.x * b.y); }
vec2 CDIV(vec2 a, vec2 b) {    return vec2((a.x * b.x + a.y * b.y) / (b.x * b.x + b.y * b.y), (a.y * b.x - a.x * b.y) / (b.x * b.x + b.y * b.y)); }
float CABS(vec2 a) { return sqrt(a.x * a.x + a.y * a.y); }
vec2 CSQRT(vec2 a) { return vec2(sqrt((a.x + sqrt(a.x * a.x + a.y * a.y)) / 2), sign(a.y) * sqrt((-a.x + sqrt(a.x * a.x + a.y * a.y)) / 2)); }

float _Fresnel(float _CosThetaI, vec2 n)
{
    vec2 CosThetaI = vec2(_CosThetaI, 0);
    vec2 CosThetaT = CSQRT(CSUB(vec2(1.0, 0), CDIV(CSUB(vec2(1.0, 0), CMUL(CosThetaI, CosThetaI)), CMUL(n, n))));
    vec2 NCosThetaI = CMUL(n, CosThetaI);
    vec2 NCosThetaT = CMUL(n, CosThetaT);
    float Rs = pow(CABS(CDIV(CSUB(CosThetaI, NCosThetaT), CADD(CosThetaI, NCosThetaT))), 2);
    float Rp = pow(CABS(CDIV(CSUB(CosThetaT, NCosThetaI), CADD(CosThetaT, NCosThetaI))), 2);
    return (Rs + Rp) / 2;
}
 
vec3 Fresnel(float CosThetaI, vec3 n, vec3 k)
{
    return vec3(
            _Fresnel(CosThetaI, vec2(n.r, k.r)),
            _Fresnel(CosThetaI, vec2(n.g, k.g)),
            _Fresnel(CosThetaI, vec2(n.b, k.b))
        );
}

#3Chris_F

Posted 12 March 2013 - 05:37 PM

OK, I'm bumping this thread because I'm revisiting the Fresnel equation, this time using complex IOR values. I'm having a hard time converting this to complex numbers.

 

 

float Fresnel(float CosThetaI, float n)
{
    float CosThetaT = sqrt(1 - (1 - CosThetaI * CosThetaI) / (n * n));
    float NCosThetaT = n * CosThetaT;
    float NCosThetaI = n * CosThetaI;
    float Rs = pow(abs((CosThetaI - NCosThetaT) / (CosThetaI + NCosThetaT)), 2);
    float Rp = pow(abs((CosThetaT - NCosThetaI) / (CosThetaT + NCosThetaI)), 2);
    return (Rs + Rp) / 2;
}

 

This is the basic formula, but I need to re-write it so that it looks like:

 

 

float Fresnel(float CosThetaI, vec3 n, vec3 k)
{
    ...
}

 

Where n and k make up the complex IOR (n + ki). I've taken a few stabs at it, but it's gotten me nowhere. Here is my train wreck of an attempt:

 

vec3 Fresnel(float CosThetaI, vec3 n, vec3 k)
{
    float temp = 1 - CosThetaI * CosThetaI;

    vec3 NKSqr_real = n * n - k * k;
    vec3 NKSqr_imag = n * k * 2;

    vec3 temp2_real = (temp * NKSqr_real) / (NKSqr_real * NKSqr_real + NKSqr_imag * NKSqr_imag);
    vec3 temp2_imag = -(temp * NKSqr_imag) / (NKSqr_real * NKSqr_real + NKSqr_imag * NKSqr_imag);

    temp2_real = 1 - temp2_real;
    temp2_imag = -temp2_imag;

    vec3 CosThetaT_real = sqrt((temp2_real + sqrt(temp2_real * temp2_real + temp2_imag * temp2_imag)) / 2);
    vec3 CosThetaT_imag = sign(temp2_imag) * sqrt((-temp2_real + sqrt(temp2_real * temp2_real + temp2_imag * temp2_imag)) / 2);

    vec3 NCosThetaT_real = n * CosThetaT_real - k * CosThetaT_imag;
    vec3 NCosThetaT_imag = k * CosThetaT_real + n * CosThetaT_imag;

    vec3 NCosThetaI_real = n * CosThetaI;
    vec3 NCosThetaI_imag = k * CosThetaI;

    vec3 CosThetaI_minus_NCosThetaT_real = CosThetaI - NCosThetaT_real;
    vec3 CosThetaI_minus_NCosThetaT_imag = -NCosThetaT_imag;

    vec3 CosThetaI_plus_NCosThetaT_real = CosThetaI + NCosThetaT_real;
    vec3 CosThetaI_plus_NCosThetaT_imag = NCosThetaT_imag;

    vec3 a, b, c, d;

    a = CosThetaI_minus_NCosThetaT_real;
    b = CosThetaI_minus_NCosThetaT_imag;
    c = CosThetaI_plus_NCosThetaT_real;
    d = CosThetaI_plus_NCosThetaT_imag;

    vec3 Rs_real = (a * c + b * d) / (c * c + d * d);
    vec3 Rs_imag = (b * c + a * d) / (c * c + d * d);

    vec3 Rs = sqrt(Rs_real * Rs_real + Rs_imag * Rs_imag);
    Rs = Rs * Rs;

    vec3 CosThetaT_minus_NCosThetaI_real = CosThetaT_real - NCosThetaI_real;
    vec3 CosThetaT_minus_NCosThetaI_imag = CosThetaT_imag - NCosThetaI_imag;

    vec3 CosThetaT_plus_NCosThetaI_real = CosThetaT_real + NCosThetaI_real;
    vec3 CosThetaT_plus_NCosThetaI_imag = CosThetaT_imag + NCosThetaI_imag;

    a = CosThetaT_minus_NCosThetaI_real;
    b = CosThetaT_minus_NCosThetaI_imag;
    c = CosThetaT_plus_NCosThetaI_real;
    d = CosThetaT_plus_NCosThetaI_imag;

    vec3 Rp_real = (a * c + b * d) / (c * c + d * d);
    vec3 Rp_imag = (b * c + a * d) / (c * c + d * d);

    vec3 Rp = sqrt(Rp_real * Rp_real + Rp_imag * Rp_imag);
    Rp = Rp * Rp;

    return (Rs + Rp) / 2;
}

 

It would be so much easier if HLSL/GLSL had first class support for complex values. wacko.png


#2Chris_F

Posted 12 March 2013 - 05:20 PM

OK, I'm bumping this thread because I'm revisiting the Fresnel equation, this time using complex IOR values. I'm having a hard time converting this to complex numbers.

 

 

float Fresnel(float CosThetaI, float n)
{
    float CosThetaT = sqrt(1 - (1 - CosThetaI * CosThetaI) / (n * n));
    float NCosThetaT = n * CosThetaT;
    float NCosThetaI = n * CosThetaI;
    float Rs = pow(abs((CosThetaI - NCosThetaT) / (CosThetaI + NCosThetaT)), 2);
    float Rp = pow(abs((CosThetaT - NCosThetaI) / (CosThetaT + NCosThetaI)), 2);
    return (Rs + Rp) / 2;
}

 

This is the basic formula, but I need to re-write it so that it looks like:

 

 

float Fresnel(float CosThetaI, vec3 n, vec3 k)
{
    ...
}

 

Where n and k make up the complex IOR (n + ki). I've taken a few stabs at it, but it's gotten me nowhere. It would be so much easier if HLSL/GLSL had first class support for complex values. wacko.png


#1Chris_F

Posted 12 March 2013 - 05:18 PM

OK, I'm bumping this thread because I'm revisiting the Fresnel equation, this time using complex IOR values. I'm having a hard time converting this to complex numbers.

 

float Fresnel(float CosThetaI, float n)

{

    float CosThetaT = sqrt(1 - (1 - CosThetaI * CosThetaI) / (n * n));

    float NCosThetaT = n * CosThetaT;

    float NCosThetaI = n * CosThetaI;

    float Rs = pow(abs((CosThetaI - NCosThetaT) / (CosThetaI + NCosThetaT)), 2);

    float Rp = pow(abs((CosThetaT - NCosThetaI) / (CosThetaT + NCosThetaI)), 2);

    return (Rs + Rp) / 2;

}

 

This is the basic formula, but I need to re-write it so that it looks like:

 

float Fresnel(float CosThetaI, vec3 n, vec3 k)

{

    ...

}

 

Where n and k make up the complex IOR (n + ki). I've taken a few stabs at it, but it's gotten me nowhere.


PARTNERS