Commit 435b7910 authored by Laurent Belcour's avatar Laurent Belcour

Adding the Retro Fresnel plugin

parent 45d4cb58
......@@ -43,17 +43,36 @@ double dot(const vec& a, const vec& b)
vec product(const vec& a, const vec& b)
{
if(a.size() == 1 && b.size() > 1)
{
vec res(b.size());
for(int i=0; i<b.size(); ++i)
{
res[i] = a[0]*b[i];
}
return res;
}
else if(b.size() == 1 && a.size() > 1)
{
vec res(a.size());
for(int i=0; i<a.size(); ++i)
{
res[i] = a[i]*b[0];
}
return res;
}
else
{
#ifdef DEBUG
assert(a.size() == b.size());
assert(a.size() == b.size());
#endif
vec res(a.size());
for(int i=0; i<a.size(); ++i)
{
res[i] = a[i]*b[i];
}
return res;
vec res(b.size());
for(int i=0; i<b.size(); ++i)
{
res[i] = a[0]*b[i];
}
return res;
}
}
std::ostream& operator<<(std::ostream& out, const vec& v)
......
......@@ -25,6 +25,7 @@ std::map<params::input, const param_info> create_map()
_map.insert(std::make_pair<params::input, const param_info>(params::RUSIN_TH_TD_PD, param_info("RUSIN_TH_TD_PD", 3, "Isotropic Half angle parametrization")));
_map.insert(std::make_pair<params::input, const param_info>(params::ISOTROPIC_TV_TL_DPHI, param_info("ISOTROPIC_TV_TL_DPHI", 3, "Isotropic Light/View angle parametrization")));
_map.insert(std::make_pair<params::input, const param_info>(params::RUSIN_VH, param_info("RUSIN_VH", 3, "Vector representation of the Half angle only")));
_map.insert(std::make_pair<params::input, const param_info>(params::SCHLICK_VK, param_info("SCHLICK_VH", 3, "Vector representation of the Back angle only")));
/* 4D Params */
_map.insert(std::make_pair<params::input, const param_info>(params::RUSIN_TH_PH_TD_PD, param_info("RUSIN_TH_PH_TD_PD", 4, "Complete Half angle parametrization")));
......@@ -102,8 +103,17 @@ void params::to_cartesian(const double* invec, params::input intype,
classical_to_cartesian(invec[0], 0.0, invec[1], invec[2], outvec);
break;
case params::RUSIN_VH:
half_to_cartesian(acos(invec[2]), atan2(invec[1], invec[0]), 0.0, 0.0, outvec);
half_to_cartesian(acos(invec[2]), atan2(invec[1], invec[0]), 0.0, 0.0, outvec);
break;
// \todo I should handle the phi_k in the conversion to CARTESIAN
case params::SCHLICK_VK:
outvec[0] = invec[2]*invec[2]-1.0;
outvec[1] = 0.0;
outvec[2] = invec[2];
outvec[3] = 1.0-invec[2]*invec[2];
outvec[4] = 0.0;
outvec[5] = invec[2];
break;
// 4D Parametrization
case params::RUSIN_TH_PH_TD_PD:
......@@ -224,6 +234,18 @@ void params::from_cartesian(const double* invec, params::input outtype,
outvec[1] = half[1];
outvec[2] = half[2];
break;
case params::SCHLICK_VK:
{
const double Kx = invec[0]-invec[3];
const double Ky = invec[1]-invec[4];
const double Kz = invec[2]-invec[5];
const double norm = sqrt(Kx*Kx + Ky*Ky + Kz*Kz);
outvec[0] = Kx / norm;
outvec[1] = Ky / norm;
outvec[2] = Kz / norm;
}
break;
// 4D Parametrization
case params::RUSIN_TH_PH_TD_PD:
......
......@@ -42,8 +42,9 @@ class params
COS_TH_TD,
COS_TH,
SCHLICK_TK_PK, /*!< Schlick's back vector parametrization */
COS_TK, /*!< Schlick's back vector dot product with the normal */
SCHLICK_TK_PK, /*!< Schlick's back vector parametrization */
SCHLICK_VK, /*!< Schlick's back vector */
COS_TK, /*!< Schlick's back vector dot product with the normal */
STEREOGRAPHIC, /*!< Stereographic projection of the Light and View vectors */
......
#include "function.h"
#include <string>
#include <iostream>
#include <fstream>
#include <limits>
#include <algorithm>
#include <cmath>
#include <core/common.h>
ALTA_DLL_EXPORT function* provide_function()
{
return new retro_schlick();
}
vec retro_schlick::fresnelValue(const vec& x) const
{
double xp[3], cart[6];
params::convert(&x[0], input_parametrization(), params::SCHLICK_VK, xp);
params::convert(&x[0], input_parametrization(), params::CARTESIAN, cart);
const double dotRK = -xp[0]*cart[0] -xp[1]*cart[1] + xp[2]*cart[2];
vec res(_nY);
for(int i=0; i<_nY; ++i)
{
res[i] = R[i] + (1.0 - R[i]) * pow(1.0 - clamp(dotRK, 0.0, 1.0), 5.0);
}
return res;
}
//! \brief Number of parameters to this non-linear function
int retro_schlick::nbFresnelParameters() const
{
return dimY();
}
//! \brief Get the vector of parameters for the function
vec retro_schlick::getFresnelParameters() const
{
vec p(dimY());
for(int i=0; i<dimY(); ++i) { p[i] = R[i]; }
return p;
}
//! \brief Update the vector of parameters for the function
void retro_schlick::setFresnelParameters(const vec& p)
{
for(int i=0; i<dimY(); ++i) { R[i] = p[i]; }
}
//! \brief Obtain the derivatives of the function with respect to the
//! parameters.
vec retro_schlick::getFresnelParametersJacobian(const vec& x) const
{
const int nY = dimY();
double xp[3], cart[6];
params::convert(&x[0], input_parametrization(), params::SCHLICK_VK, xp);
params::convert(&x[0], input_parametrization(), params::CARTESIAN, cart);
const double dotRK = -xp[0]*cart[0] -xp[1]*cart[1] + xp[2]*cart[2];
vec jac(nY);
for(int i=0; i<nY; ++i)
for(int j=0; j<nY; ++j)
{
if(i == j)
{
jac[i*nY + j] = 1.0 - pow(1.0 - clamp(dotRK, 0.0, 1.0), 5.0);
}
else
{
jac[i*nY + j] = 0.0;
}
}
return jac;
}
void retro_schlick::fresnelBootstrap(const data* d, const arguments& args)
{
for(int i=0; i<dimY(); ++i) {R[i] = 0.5; }
}
//! Load function specific files
void retro_schlick::load(std::istream& in)
{
fresnel::load(in);
// Parse line until the next comment
while(in.peek() != '#')
{
char line[256];
in.getline(line, 256);
}
// Checking for the comment line #FUNC nonlinear_fresnel_retro_schlick
std::string token;
in >> token;
if(token != "#FUNC") { std::cerr << "<<ERROR>> parsing the stream. The #FUNC is not the next line defined." << std::endl; }
in >> token;
if(token != "nonlinear_fresnel_retro_schlick") { std::cerr << "<<ERROR>> parsing the stream. function name is not the next token." << std::endl; }
// R [double]
for(int i=0; i<dimY(); ++i) {
in >> token >> R[i];
}
}
void retro_schlick::save_call(std::ostream& out, const arguments& args) const
{
bool is_alta = !args.is_defined("export") || args["export"] == "alta";
if(is_alta)
{
f->save_call(out, args);
}
else
{
out << "("; f->save_call(out, args); out << ")";
}
if(is_alta)
{
out << "#FUNC nonlinear_fresnel_retro_schlick" << std::endl ;
out << "R " << R << std::endl;
out << std::endl;
}
else
{
out << " * retro_schlick_fresnel(L, V, N, X, Y, " << R << ")";
}
}
void retro_schlick::save_body(std::ostream& out, const arguments& args) const
{
f->save_body(out, args);
bool is_shader = args["export"] == "shader" || args["export"] == "explorer";
if(is_shader)
{
out << std::endl;
out << "vec3 retro_schlick_fresnel(vec3 L, vec3 V, vec3 N, vec3 X, vec3 Y, float R)" << std::endl;
out << "{" << std::endl;
out << "\tvec3 R = 2.0f*dot(V,N)*N - V;" << std::endl;
out << "\tvec3 K = normalize(L + R);" << std::endl;
out << "\treturn vec3(R + (1.0f - R) * pow(1.0f - clamp(dot(K,R), 0.0f, 1.0f), 5));" << std::endl;
out << "}" << std::endl;
}
}
#pragma once
// Include STL
#include <vector>
#include <string>
// Interface
#include <core/function.h>
#include <core/data.h>
#include <core/fitter.h>
#include <core/args.h>
#include <core/common.h>
class retro_schlick : public fresnel
{
public: // methods
//! \brief Load function specific files
virtual void load(std::istream& in) ;
virtual void save_call(std::ostream& out, const arguments& args) const;
virtual void save_body(std::ostream& out, const arguments& args) const;
protected: // methods
virtual vec fresnelValue(const vec& x) const;
//! \brief Number of parameters to this non-linear function
virtual int nbFresnelParameters() const ;
//! \brief Get the vector of parameters for the function
virtual vec getFresnelParameters() const ;
//! \brief Update the vector of parameters for the function
virtual void setFresnelParameters(const vec& p) ;
//! Get the vector of min parameters for the function
virtual vec getFresnelParametersMin() const
{
vec m = vec::Zero(dimY());
return m;
}
//! Get the vector of min parameters for the function
virtual vec getFresnelParametersMax() const
{
vec M(dimY());
for(int i=0; i<dimY(); ++i) { M[i] = 1.0; }
return M;
}
//! \brief Obtain the derivatives of the function with respect to the
//! parameters.
virtual vec getFresnelParametersJacobian(const vec& x) const ;
//! \brief Boostrap the function by defining the diffuse term
virtual void fresnelBootstrap(const data* d, const arguments& args);
private: // data
//! Unidimensional Fresnel reflectance at theta = 0
vec R;
} ;
TEMPLATE = lib
CONFIG *= plugin \
eigen
DESTDIR = ../../build
INCLUDEPATH += ../..
HEADERS = function.h
SOURCES = function.cpp
LIBS += -L../../build \
-lcore
......@@ -42,14 +42,14 @@ void schlick::save_call(std::ostream& out, const arguments& args) const
{
bool is_alta = !args.is_defined("export") || args["export"] == "alta";
if(is_alta)
{
out << "("; f->save_call(out, args); out << ")";
}
else
{
f->save_call(out, args);
}
if(is_alta)
{
f->save_call(out, args);
}
else
{
out << "("; f->save_call(out, args); out << ")";
}
if(is_alta)
{
......@@ -80,19 +80,21 @@ void schlick::save_body(std::ostream& out, const arguments& args) const
}
vec schlick::fresnelValue(const vec& x) const
{
double xp[2];
params::convert(&x[0], input_parametrization(), params::COS_TH_TD, xp);
double xp[3], cart[6];
params::convert(&x[0], input_parametrization(), params::RUSIN_VH, xp);
params::convert(&x[0], input_parametrization(), params::CARTESIAN, cart);
vec res(_nY);
for(int i=0; i<_nY; ++i)
{
res[i] = R + (1.0 - R) * pow(1.0 - clamp(xp[1], 0.0, 1.0), 5.0);
}
const double dotVH = xp[0]*cart[0] + xp[1]*cart[1] + xp[2]*cart[2];
return res;
vec res(_nY);
for(int i=0; i<_nY; ++i)
{
res[i] = R + (1.0 - R) * pow(1.0 - clamp(dotVH, 0.0, 1.0), 5.0);
}
return res;
}
//! \brief Number of parameters to this non-linear function
......@@ -120,13 +122,16 @@ void schlick::setFresnelParameters(const vec& p)
vec schlick::getFresnelParametersJacobian(const vec& x) const
{
const int nY = dimY();
double xp[2];
params::convert(&x[0], input_parametrization(), params::COS_TH_TD, xp);
double xp[3], cart[6];
params::convert(&x[0], input_parametrization(), params::RUSIN_VH, xp);
params::convert(&x[0], input_parametrization(), params::CARTESIAN, cart);
const double dotVH = xp[0]*cart[0] + xp[1]*cart[1] + xp[2]*cart[2];
vec jac(nY);
for(int i=0; i<nY; ++i)
{
jac[i] = 1.0 - pow(1.0 - clamp(xp[1], 0.0, 1.0), 5.0);
jac[i] = 1.0 - pow(1.0 - clamp(dotVH, 0.0, 1.0), 5.0);
}
return jac;
......
......@@ -14,6 +14,7 @@ SUBDIRS = \
# nonlinear_fitter_ipopt \
# nonlinear_fitter_nlopt \
nonlinear_fresnel_schlick \
nonlinear_fresnel_retroschlick \
nonlinear_function_diffuse \
nonlinear_function_blinn \
nonlinear_function_retroblinn \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment