1 /**
2  * Mandelbulber v2, a 3D fractal generator       ,=#MKNmMMKmmßMNWy,
3  *                                             ,B" ]L,,p%%%,,,§;, "K
4  * Copyright (C) 2018-21 Mandelbulber Team     §R-==%w["'~5]m%=L.=~5N
5  *                                        ,=mm=§M ]=4 yJKA"/-Nsaj  "Bw,==,,
6  * This file is part of Mandelbulber.    §R.r= jw",M  Km .mM  FW ",§=ß., ,TN
7  *                                     ,4R =%["w[N=7]J '"5=],""]]M,w,-; T=]M
8  * Mandelbulber is free software:     §R.ß~-Q/M=,=5"v"]=Qf,'§"M= =,M.§ Rz]M"Kw
9  * you can redistribute it and/or     §w "xDY.J ' -"m=====WeC=\ ""%""y=%"]"" §
10  * modify it under the terms of the    "§M=M =D=4"N #"%==A%p M§ M6  R' #"=~.4M
11  * GNU General Public License as        §W =, ][T"]C  §  § '§ e===~ U  !§[Z ]N
12  * published by the                    4M",,Jm=,"=e~  §  §  j]]""N  BmM"py=ßM
13  * Free Software Foundation,          ]§ T,M=& 'YmMMpM9MMM%=w=,,=MT]M m§;'§,
14  * either version 3 of the License,    TWw [.j"5=~N[=§%=%W,T ]R,"=="Y[LFT ]N
15  * or (at your option)                   TW=,-#"%=;[  =Q:["V""  ],,M.m == ]N
16  * any later version.                      J§"mr"] ,=,," =="""J]= M"M"]==ß"
17  *                                          §= "=C=4 §"eM "=B:m|4"]#F,§~
18  * Mandelbulber is distributed in            "9w=,,]w em%wJ '"~" ,=,,ß"
19  * the hope that it will be useful,                 . "K=  ,=RMMMßM"""
20  * but WITHOUT ANY WARRANTY;                            .'''
21  * without even the implied warranty
22  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
23  *
24  * See the GNU General Public License for more details.
25  * You should have received a copy of the GNU General Public License
26  * along with Mandelbulber. If not, see <http://www.gnu.org/licenses/>.
27  *
28  * ###########################################################################
29  *
30  * Authors: Krzysztof Marczak (buddhi1980@gmail.com)
31  *
32  * cRenderWorker::LightShading method - calculates auxiliary light sources
33  */
34 #include "common_math.h"
35 #include "fractparams.hpp"
36 #include "lights.hpp"
37 #include "material.h"
38 #include "render_worker.hpp"
39 
LightShading(const sShaderInputData & input,sRGBAfloat surfaceColor,const cLight * light,sGradientsCollection * gradients,sRGBAfloat * outSpecular) const40 sRGBAfloat cRenderWorker::LightShading(const sShaderInputData &input, sRGBAfloat surfaceColor,
41 	const cLight *light, sGradientsCollection *gradients, sRGBAfloat *outSpecular) const
42 {
43 	sRGBAfloat shading;
44 
45 	double distance = 0.0;
46 	CVector3 lightVector = light->CalculateLightVector(
47 		input.point, input.delta, params->resolution, params->viewDistanceMax, distance);
48 
49 	// intensity of lights is divided by 6 because of backward compatibility. There was an error
50 	// where number of light was always 24
51 	// float intensity = 100.0f * light->intensity / light->Decay(distance) / number / 6;
52 	float intensity;
53 	if (light->type == cLight::lightDirectional)
54 	{
55 		intensity = light->intensity;
56 	}
57 	else
58 	{
59 		intensity = 100.0f * light->intensity / light->Decay(distance) / 6.0f;
60 	}
61 
62 	sRGBFloat textureColor;
63 	intensity *= light->CalculateCone(lightVector, textureColor);
64 
65 	float shade = input.normal.Dot(lightVector);
66 	if (shade < 0) shade = 0;
67 	shade = 1.0f - input.material->shading + shade * input.material->shading;
68 
69 	shade = shade * intensity;
70 	if (shade > 500.0f) shade = 500.0f;
71 
72 	// specular
73 	sRGBAfloat specular =
74 		SpecularHighlightCombined(input, lightVector, surfaceColor, gradients->diffuse);
75 	specular.R *= intensity;
76 	specular.G *= intensity;
77 	specular.B *= intensity;
78 
79 	if (input.material->useColorsFromPalette && input.material->specularGradientEnable)
80 	{
81 		specular.R *= gradients->specular.R;
82 		specular.G *= gradients->specular.G;
83 		specular.B *= gradients->specular.B;
84 	}
85 
86 	float specularMax = dMax(specular.R, specular.G, specular.B);
87 
88 	// calculate shadow
89 	sRGBAfloat auxShadow(1.0, 1.0, 1.0, 1.0);
90 	if (light->castShadows)
91 	{
92 		if (shade > 0.001f || specularMax > 0.001f)
93 		{
94 			auxShadow = AuxShadow(input, light, distance, lightVector);
95 			specular.R *= auxShadow.R;
96 			specular.G *= auxShadow.G;
97 			specular.B *= auxShadow.B;
98 		}
99 		else
100 		{
101 			auxShadow = sRGBAfloat();
102 			specular = sRGBAfloat();
103 		}
104 	}
105 
106 	shading.R = shade * light->color.R * auxShadow.R * textureColor.R;
107 	shading.G = shade * light->color.G * auxShadow.G * textureColor.G;
108 	shading.B = shade * light->color.B * auxShadow.B * textureColor.B;
109 
110 	outSpecular->R = specular.R * light->color.R * textureColor.R;
111 	outSpecular->G = specular.G * light->color.G * textureColor.G;
112 	outSpecular->B = specular.B * light->color.B * textureColor.B;
113 
114 	return shading;
115 }
116