File: subsurface.cpp

package info (click to toggle)
povray 1%3A3.7.0.10-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 147,232 kB
  • sloc: cpp: 845,011; ansic: 122,118; sh: 34,204; pascal: 6,420; asm: 3,355; ada: 1,681; makefile: 1,388; cs: 879; awk: 590; perl: 245; xml: 95
file content (114 lines) | stat: -rw-r--r-- 3,937 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/*******************************************************************************
 * subsurface.cpp
 *
 * This module implements subsurface light transport.
 *
 * Author: Christoph Lipka
 *
 * ---------------------------------------------------------------------------
 * Persistence of Vision Ray Tracer ('POV-Ray') version 3.7.
 * Copyright 1991-2013 Persistence of Vision Raytracer Pty. Ltd.
 *
 * POV-Ray is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * POV-Ray is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * ---------------------------------------------------------------------------
 * POV-Ray is based on the popular DKB raytracer version 2.12.
 * DKBTrace was originally written by David K. Buck.
 * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
 * ---------------------------------------------------------------------------
 * $File: //depot/public/povray/3.x/source/backend/lighting/subsurface.cpp $
 * $Revision: #1 $
 * $Change: 6069 $
 * $DateTime: 2013/11/06 11:59:40 $
 * $Author: chrisc $
 *******************************************************************************/

// frame.h must always be the first POV file included (pulls in platform config)
#include "backend/frame.h"

#include "backend/math/vector.h"
#include "backend/lighting/subsurface.h"

// this must be the last file included
#include "base/povdebug.h"

namespace pov
{

/// Computes the BRDF approximation of the diffuse reflectance term.
inline double DiffuseReflectance(double A, double alphaPrime)
{
	double root = sqrt(3*(1-alphaPrime));
	return (alphaPrime/2) * ( 1 + exp(-(4.0/3.0)*A*root) ) * exp(-root);
}


SubsurfaceInterior::SubsurfaceInterior(double ior) :
	precomputedReducedAlbedo(ior)
{}

SubsurfaceInterior::PrecomputedReducedAlbedo::PrecomputedReducedAlbedo(double ior)
{
	reducedAlbedo[ReducedAlbedoSamples] = 1.0;
	double Fdr = FresnelDiffuseReflectance(ior);
	double A = (1+Fdr)/(1-Fdr);
	double alphaPrime = 1.0;
	double Rd = 1.0;
	int it = 0;
	for (int i = ReducedAlbedoSamples-1; i > 0; i --)
	{
		double Rd0 = 0.0;
		double Rd1 = Rd;
		double diffuseReflectance = double(i)/ReducedAlbedoSamples;
		double alphaPrime0 = 0.0;
		double alphaPrime1 = alphaPrime;
		while(fabs(Rd-diffuseReflectance) >= EPSILON)
		{
			double p = (diffuseReflectance-Rd0)/(Rd1-Rd0);
			alphaPrime = alphaPrime0 + p*(alphaPrime1-alphaPrime0);
			Rd = DiffuseReflectance(A, alphaPrime);
			if (Rd < diffuseReflectance)
			{
				alphaPrime0 = alphaPrime;
				Rd0 = Rd;
			}
			else
			{
				alphaPrime1 = alphaPrime;
				Rd1 = Rd;
			}
			it ++;
		}
		reducedAlbedo[i] = alphaPrime;
	}
	reducedAlbedo[0] = 0.0;
}

double SubsurfaceInterior::PrecomputedReducedAlbedo::operator()(double diffuseReflectance) const
{
	double Rd = clip(diffuseReflectance, 0.0, 1.0);
	double i = diffuseReflectance * ReducedAlbedoSamples;
	int i0 = floor(i);
	int i1 = ceil(i);
	double p = (i-i0);
	return (1-p)*reducedAlbedo[i0] + p*reducedAlbedo[i1];
}

DblRGBColour SubsurfaceInterior::GetReducedAlbedo(const RGBColour& diffuseReflectance) const
{
	return DblRGBColour(((const PrecomputedReducedAlbedo&)precomputedReducedAlbedo)(diffuseReflectance.red()),
	                    ((const PrecomputedReducedAlbedo&)precomputedReducedAlbedo)(diffuseReflectance.green()),
	                    ((const PrecomputedReducedAlbedo&)precomputedReducedAlbedo)(diffuseReflectance.blue()));
}

} // end of namespace