File size: 7,204 Bytes
5f9d349
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
/*
 * Copyright (C) 2020, Inria
 * GRAPHDECO research group, https://team.inria.fr/graphdeco
 * All rights reserved.
 *
 * This software is free for non-commercial, research and evaluation use 
 * under the terms of the LICENSE.md file.
 *
 * For inquiries contact [email protected] and/or [email protected]
 */


#pragma once

# include "Config.hpp"
# include <core/system/Config.hpp>
# include <core/graphics/Texture.hpp>
# include <core/graphics/Shader.hpp>
# include <core/graphics/Mesh.hpp>
# include <core/renderer/RenderMaskHolder.hpp>
# include <core/scene/BasicIBRScene.hpp>
# include <core/system/SimpleTimer.hpp>

namespace sibr { 
	
	/**
	 * \class ULRV3Renderer
	 * \brief Perform per-pixel Unstructured Lumigraph Rendering (Buehler et al., 2001). No selection is done on the CPU side.
	 * Relies on texture arrays and uniform buffer objects to support a high number of cameras. 
	 */
	class SIBR_EXP_ULR_EXPORT ULRV3Renderer : public RenderMaskHolderArray
	{
		SIBR_CLASS_PTR(ULRV3Renderer);
	
	public:

		/**
		 * Constructor.
		 * \param cameras The input cameras to use.
		 * \param w The width of the internal rendertargets.
		 * \param h The height of the internal rendertargets.
		 * \param fShader An optional name of the fragment shader to use (default to ulr_v3).
		 * \param vShader An optional name of the vertex shader to use (default to ulr_v3).
		 * \param facecull Should the mesh be renderer with backface culling.
		 */
		ULRV3Renderer(const std::vector<InputCamera::Ptr> & cameras, 
			const uint w, const uint h, 
			const std::string & fShader = "ulr/ulr_v3", 
			const std::string & vShader = "ulr/ulr_v3", 
			const bool facecull = true
		);

		/**
		 * Change the shaders used by the ULR renderer.
		 * \param fShader The name of the fragment shader to use.
		 * \param vShader The name of the vertex shader to use.
		 */
		virtual void setupShaders(
			const std::string & fShader = "ulr/ulr_v3",
			const std::string & vShader = "ulr/ulr_v3"
		);

		/**
		 * Performs ULR rendering to a given destination rendertarget.
		 * \param mesh The mesh to use as geometric proxy.
		 * \param eye The novel viewpoint.
		 * \param dst The destination rendertarget.
		 * \param inputRGBs A texture array containing the input RGB images.
		 * \param inputDepths A texture array containing the input depth maps.
		 * \param passthroughDepth If true, depth from the position map will be output to the depth buffer for ulterior passes.
		 */
		virtual void process(
			const sibr::Mesh & mesh,
			const sibr::Camera& eye,
			IRenderTarget& dst,
			const sibr::Texture2DArrayRGB::Ptr & inputRGBs,
			const sibr::Texture2DArrayLum32F::Ptr & inputDepths,
			bool passthroughDepth = false
			);

		/**
		 * Performs ULR rendering to a given destination rendertarget.
		 * \param mesh The mesh to use as geometric proxy.
		 * \param eye The novel viewpoint.
		 * \param dst The destination rendertarget.
		 * \param inputRGBHandle The handle of a texture array containing the input RGB images.
		 * \param inputDepths A texture array containing the input depth maps.
		 * \param passthroughDepth If true, depth from the position map will be output to the depth buffer for ulterior passes.
		 */
		virtual void process(
			const sibr::Mesh & mesh,
			const sibr::Camera& eye,
			IRenderTarget& dst,
			uint inputRGBHandle,
			const sibr::Texture2DArrayLum32F::Ptr & inputDepths,
			bool passthroughDepth = false
		);

		/** 
		 *  Update which cameras should be used for rendering, based on the indices passed.
		 *  \param camIds The indices to enable.
		 **/
		void updateCameras(const std::vector<uint> & camIds);

		/// Set the epsilon occlusion threshold.
		float & epsilonOcclusion() { return _epsilonOcclusion.get(); }

		/// Enable or disable the masks.
		bool & useMasks() { return _useMasks.get(); }

		/// Flip the RGB images before using them.
		bool & flipRGBs() { return _flipRGBs.get(); }

		/// Enable or diable occlusion testing.
		bool& occTest() { return _occTest.get(); }

		/// Show debug weights.
		bool & showWeights() { return _showWeights.get(); }

		/// Set winner takes all weights strategy
		bool & winnerTakesAll() { return _winnerTakesAll.get(); }

		/// Apply gamma correction to the output.
		bool & gammaCorrection() { return _gammaCorrection.get(); }

		/// Apply backface culling to the mesh.
		bool & backfaceCull() { return _backFaceCulling; }

		/** Resize the internal rendertargets.
		 *\param w the new width
		 *\param h the new height
		 **/
		void resize(const unsigned int w, const unsigned int h);

		/// Should the final RT be cleared or not.
		bool & clearDst() { return _clearDst; }

		/// \return The ID of the first pass position map texture.
		uint depthHandle() const { return _depthRT->texture(); }

		void startProfile() { 
			_profiling = true; 
			_depthCost.clear();
			_blendCost.clear();
		}

		void stopProfile();

		/**
		 * Render the world positions of the proxy points in an intermediate rendertarget.
		 * \param mesh the proxy mesh.
		 * \param eye The novel viewpoint.
		 */
		virtual void renderProxyDepth(const sibr::Mesh & mesh, const sibr::Camera& eye);

		/**
		* Perform ULR blending.
		* \param eye The novel viewpoint.
		* \param dst The destination rendertarget.
		* \param inputRGBHandle The handle to a texture array containing the input RGB images.
		* \param inputDepths A texture array containing the input depth maps.
		* \param passthroughDepth If true, depth from the position map will be output to the depth buffer for ulterior passes.
		*/
		virtual void renderBlending(
			const sibr::Camera& eye,
			IRenderTarget& dst,
			uint inputRGBHandle,
			const sibr::Texture2DArrayLum32F::Ptr & inputDepths,
			bool passthroughDepth
		);


	protected:
		/// Shader names.
		std::string fragString, vertexString;

		sibr::GLShader _ulrShader;
		sibr::GLShader _depthShader;

		sibr::RenderTargetRGBA32F::Ptr		_depthRT;
		GLuniform<Matrix4f>					_nCamProj;
		GLuniform<Vector3f>					_nCamPos;

		GLuniform<bool>
			_occTest = true,
			_useMasks = false,
			_discardBlackPixels = true,
			_areMasksBinary = true,
			_invertMasks = false,
			_flipRGBs = false,
			_showWeights = false,
			_winnerTakesAll = false,
			_gammaCorrection = false;

		size_t _maxNumCams = 0;
		GLuniform<int> _camsCount = 0;

		GLuniform<float>					_epsilonOcclusion = 0.01f;
		bool								_backFaceCulling = true;
		bool								_clearDst = true;

		/** Camera infos data structure shared between the CPU and GPU.
			We have to be careful about alignment if we want to send those struct directly into the UBO. */
		struct CameraUBOInfos {	 
			Matrix4f vp; ///< Matrix viewproj.
			Vector3f pos; ///< Camera position.
			int selected = 0; ///< Is the camera selected (0/1).
			Vector3f dir; ///< Camera direction.
			float dummy = 0.0f; ///< Padding to a multiple of 16 bytes for alignment on the GPU.
		};

		std::vector<CameraUBOInfos> _cameraInfos;
		GLuint _uboIndex;

		bool		_profiling = false;
		sibr::Timer	_depthPassTimer;
		sibr::Timer	_blendPassTimer;
		int											_numFramesProfiling = 100;
		std::string									_profileStr = "";
		std::vector<float>							_depthCost, _blendCost;

	};


} /*namespace sibr*/