1 /**
2  * Mandelbulber v2, a 3D fractal generator       ,=#MKNmMMKmmßMNWy,
3  *                                             ,B" ]L,,p%%%,,,§;, "K
4  * Copyright (C) 2014-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 class - worker for rendering image on single CPU core
33  */
34 
35 #ifndef MANDELBULBER2_SRC_RENDER_WORKER_HPP_
36 #define MANDELBULBER2_SRC_RENDER_WORKER_HPP_
37 
38 #include <memory>
39 
40 #include <QObject>
41 #include <QThread>
42 
43 #include "algebra.hpp"
44 #include "color_structures.hpp"
45 #include "texture_enums.hpp"
46 
47 // forward declarations
48 class cMaterial;
49 class cLight;
50 class cCameraTarget;
51 class cImage;
52 struct sRenderData;
53 struct sParamRender;
54 class cNineFractals;
55 class cScheduler;
56 class cPerlinNoiseOctaves;
57 
58 #define MAX_RAYMARCHING 10000
59 
60 // ambient occlusion data
61 struct sVectorsAround
62 {
63 	double alpha;
64 	double beta;
65 	CVector3 v;
66 	sRGBFloat color;
67 };
68 
69 class cRenderWorker : public QObject
70 {
71 	Q_OBJECT
72 
73 public:
74 	struct sThreadData
75 	{
76 		int id;
77 		int startLine;
78 		std::shared_ptr<cScheduler> scheduler;
79 	};
80 
81 	cRenderWorker(std::shared_ptr<const sParamRender> _params,
82 		std::shared_ptr<const cNineFractals> _fractal, std::shared_ptr<sThreadData> _threadData,
83 		std::shared_ptr<sRenderData> _data, std::shared_ptr<cImage> _image);
84 	~cRenderWorker() override;
85 
86 	// PrepareAOVectors() is public because is needed also for OpenCL data
87 	void PrepareAOVectors();
getAOVectorsAround() const88 	const sVectorsAround *getAOVectorsAround() const { return AOVectorsAround.data(); }
getAoVectorsCount() const89 	int getAoVectorsCount() const { return AOVectorsCount; }
90 
91 	QThread workerThread;
92 
93 private:
94 	// ray-marching step data
95 	struct sStep
96 	{
97 		double distance = 0.0;
98 		double step = 0.0;
99 		CVector3 point;
100 		int iters = 0;
101 		double distThresh = 0.0;
102 	};
103 
104 	struct sRayBuffer
105 	{
106 		std::vector<sStep> stepBuff;
107 		int buffCount = 0;
108 	};
109 
110 	struct sRayMarchingIn
111 	{
112 		inline sRayMarchingIn &operator=(const sRayMarchingIn &assign) = default;
113 		CVector3 start;
114 		CVector3 direction;
115 		double minScan = 0.0;
116 		double maxScan = 0.0;
117 		bool binaryEnable = false;
118 		bool invertMode = false;
119 	};
120 
121 	struct sRayMarchingInOut
122 	{
123 		inline sRayMarchingInOut &operator=(const sRayMarchingInOut &assign) = default;
124 		sStep *stepBuff;
125 		int *buffCount;
126 	};
127 
128 	struct sRayMarchingOut
129 	{
130 		CVector3 point;
131 		double lastDist = 0.0;
132 		double depth = 0.0;
133 		double distThresh = 0.0;
134 		int objectId = 0;
135 		bool found = false;
136 		;
137 	};
138 
139 	enum enumRayBranch
140 	{
141 		rayBranchReflection,
142 		rayBranchRefraction,
143 		rayBranchDone,
144 	};
145 
146 	struct sRayRecursionIn
147 	{
148 		sRayMarchingIn rayMarchingIn;
149 		bool calcInside;
150 		sRGBAfloat resultShader;
151 		sRGBAfloat objectColour;
152 		enumRayBranch rayBranch;
153 	};
154 
155 	struct sRayRecursionOut
156 	{
157 		sRayMarchingOut rayMarchingOut;
158 		CVector3 point;
159 		sRGBAfloat resultShader;
160 		sRGBAfloat objectColour;
161 		sRGBAfloat specular;
162 		CVector3 normal;
163 		float fogOpacity;
164 		bool found;
165 	};
166 
167 	struct sRayRecursionInOut
168 	{
169 		sRayMarchingInOut rayMarchingInOut;
170 	};
171 
172 	struct sShaderInputData
173 	{
174 		CVector3 point;
175 		CVector3 viewVector;
176 		CVector3 normal;
177 		double distThresh; // distance threshold depend on 'detailLevel'
178 		double lastDist;
179 		double delta; // initial step distance for shaders based on distance form camera
180 		double depth;
181 		sStep *stepBuff;
182 		int stepCount;
183 		int objectId;
184 		bool invertMode;
185 		cMaterial *material;
186 		sRGBFloat texDiffuse;
187 		sRGBFloat texColor;
188 		sRGBFloat texLuminosity;
189 		sRGBFloat texReflectance;
190 		sRGBFloat texTransparency;
191 	};
192 
193 	struct sRayStack
194 	{
195 		sRayRecursionIn in;
196 		sRayRecursionOut out;
197 		sRGBAfloat reflectShader;
198 		sRGBAfloat transparentShader;
199 		enumRayBranch rayBranch;
200 		bool goDeeper;
201 	};
202 
203 	struct sGradientsCollection
204 	{
205 		sRGBFloat surface;
206 		sRGBFloat specular;
207 		sRGBFloat diffuse;
208 		sRGBFloat luminosity;
209 		sRGBFloat roughness;
210 		sRGBFloat reflectance;
211 		sRGBFloat trasparency;
212 	};
213 
214 	// functions
215 	void PrepareMainVectors();
216 	void PrepareReflectionBuffer();
217 	void RayMarching(sRayMarchingIn &in, sRayMarchingInOut *inOut, sRayMarchingOut *out) const;
218 	double CalcDistThresh(CVector3 point) const;
219 	double CalcDelta(CVector3 point) const;
220 	static double IterOpacity(
221 		double step, double iters, double maxN, double trim, double trimHigh, double opacitySp);
222 	double CloudOpacity(
223 		CVector3 point, double distance, double detailSize, double *distanceOut) const;
224 	sRayRecursionOut RayRecursion(sRayRecursionIn in, sRayRecursionInOut &inOut);
225 	void MonteCarloDOF(CVector3 *startRay, CVector3 *viewVector) const;
226 	double MonteCarloDOFNoiseEstimation(
227 		sRGBFloat pixel, int repeat, sRGBFloat pixelSum, sRGBFloat &StdDevSum);
228 
229 	// shaders
230 	sRGBAfloat ObjectShader(const sShaderInputData &input, sRGBAfloat *surfaceColour,
231 		sRGBAfloat *specularOut, sRGBFloat *iridescence, sGradientsCollection *gradients) const;
232 	CVector3 CalculateNormals(const sShaderInputData &input) const;
233 	sRGBAfloat SpecularHighlight(const sShaderInputData &input, CVector3 lightVector,
234 		float specularWidth, float roughness, sRGBFloat diffuseGradient) const;
235 	sRGBAfloat SpecularHighlightCombined(const sShaderInputData &input, CVector3 lightVector,
236 		sRGBAfloat surfaceColor, sRGBFloat diffuseGradient) const;
237 	sRGBAfloat SurfaceColour(const sShaderInputData &input, sGradientsCollection *gradients) const;
238 	sRGBAfloat FastAmbientOcclusion(const sShaderInputData &input) const;
239 	sRGBAfloat AmbientOcclusion(const sShaderInputData &input) const;
240 	sRGBAfloat EnvMapping(const sShaderInputData &input) const;
241 	sRGBAfloat AuxLightsShader(const sShaderInputData &input, sRGBAfloat surfaceColor,
242 		sGradientsCollection *gradients, sRGBAfloat *specularOut) const;
243 	sRGBAfloat AuxShadow(const sShaderInputData &input, const cLight *light, double distance,
244 		CVector3 lightVector) const;
245 	sRGBAfloat LightShading(const sShaderInputData &input, sRGBAfloat surfaceColor,
246 		const cLight *light, sGradientsCollection *gradients, sRGBAfloat *outSpecular) const;
247 	sRGBAfloat BackgroundShader(const sShaderInputData &input) const;
248 	sRGBAfloat FakeLights(
249 		const sShaderInputData &input, sRGBAfloat surfaceColor, sRGBAfloat *fakeSpec) const;
250 	sRGBAfloat VolumetricShader(
251 		const sShaderInputData &input, sRGBAfloat oldPixel, sRGBAfloat *opacityOut) const;
252 
253 	sRGBFloat TextureShader(
254 		const sShaderInputData &input, texture::enumTextureSelection texSelect, cMaterial *mat) const;
255 	CVector3 NormalMapShader(const sShaderInputData &input) const;
256 	float RoughnessTexture(const sShaderInputData &input) const;
257 	sRGBFloat IridescenceShader(const sShaderInputData &input) const;
258 	sRGBFloat GlobalIlumination(const sShaderInputData &input, sRGBAfloat objectColor) const;
259 
260 	// data got from main thread
261 	const sParamRender *params;
262 	const cNineFractals *fractal;
263 	sRenderData *data;
264 	std::shared_ptr<sThreadData> threadData;
265 	std::shared_ptr<cImage> image;
266 
267 	// internal variables
268 	int maxRaymarchingSteps;
269 	CRotationMatrix mRot;
270 	CRotationMatrix mRotInv;
271 	CVector3 baseX;
272 	CVector3 baseY;
273 	CVector3 baseZ;
274 	CVector3 viewAngle;
275 	// CVector3 shadowVector;
276 	float actualHue;
277 	int AOVectorsCount;
278 	int reflectionsMax;
279 	bool stopRequest;
280 
281 	// allocated objects
282 	std::unique_ptr<cCameraTarget> cameraTarget;
283 	std::vector<sRayBuffer> rayBuffer;
284 	std::vector<sRayStack> rayStack;
285 	std::vector<sVectorsAround> AOVectorsAround;
286 	std::unique_ptr<cPerlinNoiseOctaves> perlinNoise;
287 
288 public slots:
289 	void doWork();
290 
291 signals:
292 	void finished();
293 	void error(const QString &result);
294 };
295 
296 #endif /* MANDELBULBER2_SRC_RENDER_WORKER_HPP_ */
297