Coupure prévue mardi 3 Août au matin pour maintenance du serveur. Nous faisons au mieux pour que celle-ci soit la plus brève possible.

clippingShader.cpp 11.5 KB
Newer Older
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
/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps  *
* version 0.1                                                                  *
* Copyright (C) 2009-2011, IGG Team, LSIIT, University of Strasbourg           *
*                                                                              *
* This library is free software; you can redistribute it and/or modify it      *
* under the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, or (at your     *
* option) any later version.                                                   *
*                                                                              *
* This library 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 Lesser General Public License  *
* for more details.                                                            *
*                                                                              *
* You should have received a copy of the GNU Lesser General Public License     *
* along with this library; if not, write to the Free Software Foundation,      *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.           *
*                                                                              *
* Web site: http://cgogn.u-strasbg.fr/                                         *
* Contact information: cgogn@unistra.fr                                        *
*                                                                              *
*******************************************************************************/

#include "Utils/clippingShader.h"

namespace CGoGN
{

namespace Utils
{

ClippingShader::ClippingShader()
{
35
36
37
	// Initialize clipping planes variables
	m_unif_clipPlanes = 0;
	/*m_clipPlaneQuaternion[0] = 1.0;
38
39
	m_clipPlaneQuaternion[1] = 0.0;
	m_clipPlaneQuaternion[2] = 0.0;
40
	m_clipPlaneQuaternion[3] = 0.0;*/
41
	
42
	// Initialize color attenuation variables
43
44
	m_colorAttenuationFactor = 0.0;
	m_unif_colorAttenuationFactor = 0;
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62

	// Plane Drawer
	float planeSize = 100.0;
	m_planeDrawer = new Drawer();
	m_planeDrawer->newList(GL_COMPILE);
	m_planeDrawer->begin(GL_QUADS);
	m_planeDrawer->color3f(0.7, 0.7, 0.2);
	m_planeDrawer->vertex3f(-planeSize/2.0, -planeSize/2.0, 0.0);
	m_planeDrawer->vertex3f(-planeSize/2.0, planeSize/2.0, 0.0);
	m_planeDrawer->vertex3f(planeSize/2.0, planeSize/2.0, 0.0);
	m_planeDrawer->vertex3f(planeSize/2.0, -planeSize/2.0, 0.0);
	m_planeDrawer->end();
	m_planeDrawer->endList();
}

ClippingShader::~ClippingShader()
{
	delete m_planeDrawer;
63
64
}

65
void ClippingShader::setClippingPlaneEquation(Geom::Vec4f clipPlane, int planeIndex)
66
{
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
	// Check if the given index is not out of range
	if ((planeIndex < 0) || ((4*planeIndex) > ((int)m_clipPlanesEquations.size() - 1)))
	{
		CGoGNerr
		<< "ERROR - "
		<< "ClippingShader::setClippingPlaneEquation"
		<< " - Given plane index is out of range"
		<< CGoGNendl;
		return;
	}

	// Copy the given clipPlane
	int i;
	for (i = 0; i < 4; i++)
		m_clipPlanesEquations[4*planeIndex + i] = clipPlane[i];
82
83

	// Recalculate quaternion rotation
84
	/*float m[4][4];
85
86
87
88
89
90
	build_rotmatrix(m, m_clipPlaneQuaternion);
	Geom::Matrix44f rotMat;
	int i, j;
	for (i = 0; i < 4; i++)
		for (j = 0; j < 4; j++)
			rotMat(i, j) = m[i][j];
91
	Geom::Vec4f rotatedVec = rotMat * m_clipPlaneEquation;*/
92

93
94
	// Send again the whole planes equations array to shader
	sendClippingPlanesUniform();
95
96
}

97
Geom::Vec4f ClippingShader::getClippingPlaneEquation(int planeIndex)
98
{
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
	// Check if the given index is not out of range
	if ((planeIndex < 0) || (4*planeIndex > ((int)m_clipPlanesEquations.size() - 1)))
	{
		CGoGNerr
		<< "ERROR - "
		<< "ClippingShader::setClippingPlaneEquation"
		<< " - Given plane index is out of range"
		<< CGoGNendl;
		return Geom::Vec4f(0.0, 0.0, 0.0, 0.0);
	}
	else
	{
		return Geom::Vec4f(
				m_clipPlanesEquations[4*planeIndex + 0],
				m_clipPlanesEquations[4*planeIndex + 1],
				m_clipPlanesEquations[4*planeIndex + 2],
				m_clipPlanesEquations[4*planeIndex + 3]);
	}
117
118
}

119
/*void ClippingShader::setClippingPlaneQuaternion(float quat[4])
120
121
122
123
124
125
{
	m_clipPlaneQuaternion[0] = quat[0];
	m_clipPlaneQuaternion[1] = quat[1];
	m_clipPlaneQuaternion[2] = quat[2];
	m_clipPlaneQuaternion[3] = quat[3];

126
	// Recalculate and send again the clipping plane equation
127
128
129
130
131
132
	setClippingPlaneEquation(m_clipPlaneEquation);
}

Geom::Vec4f ClippingShader::getClippingPlaneQuaternion()
{
	return Geom::Vec4f (m_clipPlaneQuaternion[0], m_clipPlaneQuaternion[1], m_clipPlaneQuaternion[2], m_clipPlaneQuaternion[3]);
133
}*/
134
135
136

void ClippingShader::setClippingColorAttenuationFactor(float colorAttenuationFactor)
{
137
	// Copy the given value
138
	m_colorAttenuationFactor = colorAttenuationFactor;
139
140
141

	// Send again the uniform to shader
	sendColorAttenuationFactorUniform();
142
143
}

144
145
146
147
148
float ClippingShader::getClippingColorAttenuationFactor()
{
	return m_colorAttenuationFactor;
}

149
void ClippingShader::setPlaneClipping(int planesCount)
150
{
151
152
153
154
155
156
157
158
159
160
161
	// Verify that the given clipping planes count is valid
	if (planesCount < 0)
	{
		CGoGNerr
		<< "ERROR - "
		<< "ClippingShader::setPlanesClipping"
		<< " - Given clipping planes count given is not positive !"
		<< CGoGNendl;
		return;
	}

162
163
164
	// Shader name
	std::string shaderName = m_nameVS + "/" + m_nameFS + "/" + m_nameGS;

165
166
167
168
169
	// Verify that the shader has been well created
	if (!isCreated())
	{
		CGoGNerr
		<< "ERROR - "
170
		<< "ClippingShader::setPlaneClipping"
171
		<< " - Could not process shader "
172
		<< shaderName
173
174
175
176
177
178
179
180
181
182
		<< " source code : shader has not been created or has failed to compile"
		<< CGoGNendl;
		return;
	}
	
	// Verify that the shader does not use a geometry shader
	if (getGeometryShaderSrc() != NULL)
	{
		CGoGNerr
		<< "ERROR - "
183
		<< "ClippingShader::setPlaneClipping"
184
		<< " - Could not process shader "
185
		<< shaderName
186
187
188
189
190
		<< " source code : unable to add clipping to a shader which uses a geometry shader"
		<< CGoGNendl;
		return;
	}

191
192
193
194
195
	// String for clipping planes count
	std::string planesCountStr;
	std::stringstream ss;
	ss << planesCount;
	planesCountStr = ss.str();
196

197
198
199
200
201
202
203
204
205
206
207
208
209
210
	// Strings that will be inserted into the source code

	std::string VS_head_insertion =
	"\n"
	"VARYING_VERT vec3 clip_NonTransformedPos;\n"
	"\n";

	std::string VS_mainBegin_insertion =
	"\n"
	"	// Pass the non transformed vertex position to the fragment shader for clipping\n"
	"	clip_NonTransformedPos = VertexPosition;\n";

	std::string FS_head_insertion =
	"\n"
211
	"#define CLIP_PLANES_COUNT " + planesCountStr + "\n"
212
	"\n"
213
	"uniform vec4 clip_ClipPlanes[CLIP_PLANES_COUNT];\n"
214
215
216
217
218
219
220
	"uniform float clip_ColorAttenuationFactor;\n"
	"\n"
	"VARYING_FRAG vec3 clip_NonTransformedPos;\n"
	"\n";

	std::string FS_mainBegin_insertion =
	"\n"
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
	"	// Distance to the nearest plane, stored for color attenuation\n"
	"	float clip_MinDistanceToPlanes = -1.0;\n"
	"\n"
	"	// Do clipping for each plane\n"
	"	int i;\n"
	"	for (i = 0; i < CLIP_PLANES_COUNT; i++)\n"
	"	{\n"
	"		// Copy the plane to make it modifiable\n"
	"		vec4 clip_CurrClipPlane = clip_ClipPlanes[i];\n"
	"\n"
	"		// If the plane normal is zero, use a default normal vector (0.0, 0.0, 1.0)\n"
	"		float clip_NPlane = length(clip_CurrClipPlane.xyz);\n"
	"		if (clip_NPlane == 0.0)\n"
	"		{\n"
	"			clip_CurrClipPlane.z = 1.0;\n"
	"			clip_NPlane = 1.0;\n"
	"		}\n"
	"\n"
	"		// Signed distance between the point and the plane\n"
	"		float clip_DistanceToPlane = dot(clip_NonTransformedPos, clip_CurrClipPlane.xyz) + clip_CurrClipPlane.w;\n"
241
242
	"		clip_DistanceToPlane /= clip_NPlane;\n"
	"\n"
243
244
245
246
247
248
249
250
251
252
253
254
	"		// Keep the fragment only if it is 'above' the plane\n"
	"		if (clip_DistanceToPlane < 0.0)\n"
	"			discard;\n"
	"		// Else keep the positive distance to the nearest plane\n"
	"		else\n"
	"		{\n"
	"			if (clip_MinDistanceToPlanes < 0.0)\n"
	"				clip_MinDistanceToPlanes = clip_DistanceToPlane;\n"
	"			else\n"
	"				clip_MinDistanceToPlanes = min(clip_MinDistanceToPlanes, clip_DistanceToPlane);\n"
	"		}\n"
	"	}\n";
255
256
257

	std::string FS_mainEnd_insertion =
	"\n"
258
259
260
	"	// Attenuate the final fragment color depending on its distance to the nearest plane\n"
	"	if (clip_MinDistanceToPlanes > 0.0)\n"
	"		gl_FragColor.rgb /= (1.0 + clip_MinDistanceToPlanes*clip_ColorAttenuationFactor);\n";
261

262
263
264

	// If the previous plane count was zero, the previous shader source codes were the original ones. Store them
	if (getClippingPlanesCount() == 0)
265
	{
266
267
		originalVertShaderSrc = getVertexShaderSrc();
		originalFragShaderSrc = getFragmentShaderSrc();
268
	}
269
270
271
272
273
274
275

	// If the given plane count is > 0, modify the original shader sources
	if (planesCount > 0)
	{

		// Use a shader mutator
		ShaderMutator SM(shaderName, originalVertShaderSrc, originalFragShaderSrc, "");
276
	
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
		// First check if the vertex shader contains the VertexPosition attribute
		if (!SM.VS_containsVariableDeclaration("VertexPosition"))
		{
			CGoGNerr
			<< "ERROR - "
			<< "ClippingShader::setPlaneClipping"
			<< " - Could not process shader "
			<< m_nameVS
			<< " source code : no VertexPosition attribute found"
			<< CGoGNendl;
			return;
		}

		// Modify vertex shader source code
		SM.VS_insertCodeBeforeMainFunction(VS_head_insertion);
		SM.VS_insertCodeAtMainFunctionBeginning(VS_mainBegin_insertion);
293
	
294
295
296
297
298
299
300
		// Following code insertions need at least shading language 120 (GLSL arrays)
		SM.VS_FS_GS_setMinShadingLanguageVersion(120);

		// Modify fragment shader source code
		SM.FS_insertCodeBeforeMainFunction(FS_head_insertion);
		SM.FS_insertCodeAtMainFunctionEnd(FS_mainEnd_insertion);
		SM.FS_insertCodeAtMainFunctionBeginning(FS_mainBegin_insertion);
301

302
303
304
		// Reload both shaders
		reloadVertexShaderFromMemory(SM.getModifiedVertexShaderSrc().c_str());
		reloadFragmentShaderFromMemory(SM.getModifiedFragmentShaderSrc().c_str());
305

306
307
308
309
310
311
312
313
	}
	// Else no clipping is wanted anymore, so get back the original shader sources
	else
	{
		// Reload both original shaders
		reloadVertexShaderFromMemory(originalVertShaderSrc.c_str());
		reloadFragmentShaderFromMemory(originalFragShaderSrc.c_str());
	}
314

315
316
317
	// Resize the planes equations uniform to the right size
	m_clipPlanesEquations.resize(4*(size_t)planesCount, 0.0);

318
	// Recompile shaders (automatically calls updateClippingUniforms)
319
320
321
322
323
	recompile();
}

void ClippingShader::updateClippingUniforms()
{
324
325
326
327
	// These uniforms only exist if the clipping planes count is > 0
	if (getClippingPlanesCount() <= 0)
		return;

328
329
330
	// Shader name
	std::string shaderName = m_nameVS + "/" + m_nameFS + "/" + m_nameGS;

331
	// Get uniforms locations
332
333
	m_unif_clipPlanes = glGetUniformLocation(program_handler(), "clip_ClipPlanes");
	if (m_unif_clipPlanes == -1)
334
335
336
	{
		CGoGNerr
		<< "ERROR - "
337
		<< "ClippingShader::updateClippingUniforms"
338
		<< " - uniform 'clip_ClipPlane' not found in shader "
339
		<< shaderName
340
341
342
343
344
345
346
		<< CGoGNendl;
	}
	m_unif_colorAttenuationFactor = glGetUniformLocation(program_handler(), "clip_ColorAttenuationFactor");
	if (m_unif_colorAttenuationFactor == -1)
	{
		CGoGNerr
		<< "ERROR - "
347
		<< "ClippingShader::updateClippingUniforms"
348
		<< " - uniform 'clip_ColorAttenuationFactor' not found in shader "
349
		<< shaderName
350
351
352
		<< CGoGNendl;
	}
	
353
354
355
	// Send again uniforms values
	sendClippingPlanesUniform();
	sendColorAttenuationFactorUniform();
356
357
}

358
359
360
361
362
void ClippingShader::displayClippingPlane()
{
	m_planeDrawer->callList();
}

363
364
365
366
367
368
369
370
371
372
373
374
void ClippingShader::sendClippingPlanesUniform()
{
	bind();
	glUniform4fv(m_unif_clipPlanes, m_clipPlanesEquations.size()/4, &m_clipPlanesEquations.front());
}

void ClippingShader::sendColorAttenuationFactorUniform()
{
	bind();
	glUniform1f(m_unif_colorAttenuationFactor, m_colorAttenuationFactor);
}

375
376
377
378
} // namespace Utils

} // namespace CGoGN