1 //////////////////////////////////////////////////////////////////////
2 //
3 //                             Pixie
4 //
5 // Copyright � 1999 - 2003, Okan Arikan
6 //
7 // Contact: okan@cs.utexas.edu
8 //
9 //	This library is free software; you can redistribute it and/or
10 //	modify it under the terms of the GNU Lesser General Public
11 //	License as published by the Free Software Foundation; either
12 //	version 2.1 of the License, or (at your option) any later version.
13 //
14 //	This library is distributed in the hope that it will be useful,
15 //	but WITHOUT ANY WARRANTY; without even the implied warranty of
16 //	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 //	Lesser General Public License for more details.
18 //
19 //	You should have received a copy of the GNU Lesser General Public
20 //	License along with this library; if not, write to the Free Software
21 //	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22 //
23 ///////////////////////////////////////////////////////////////////////
24 ///////////////////////////////////////////////////////////////////////
25 //
26 //  File				:	shaderFunctions.h
27 //  Classes				:	-
28 //  Description			:	Shader language specific buint in functions
29 //
30 ////////////////////////////////////////////////////////////////////////
31 
32 
33 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
34 // debug	"o=v"
35 #define	DEBUGVEXPR		debugFunction((float *) res);
36 
37 
38 DEFFUNC(DebugFloat		,"debug"		,"o=f", FUN1EXPR_PRE, DEBUGVEXPR, FUN1EXPR_UPDATE(1), NULL_EXPR, 0)
39 DEFLINKFUNC(DebugP		,"debug"		,"o=p",	0)
40 DEFLINKFUNC(DebugC		,"debug"		,"o=c",	0)
41 DEFLINKFUNC(DebugN		,"debug"		,"o=n",	0)
42 DEFFUNC(DebugVector		,"debug"		,"o=v", FUN1EXPR_PRE, DEBUGVEXPR, FUN1EXPR_UPDATE(3), NULL_EXPR, 0)
43 
44 
45 
46 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
47 // faceforward "v=vv"
48 #define	FACEFORWARDEXPR_PRE		const float	*Ng	=	varying[VARIABLE_NG];			\
49 								FUN3EXPR_PRE
50 
51 #define	FACEFORWARDEXPR			if (dotvv(op1,Ng) > 0) {							\
52 									if (dotvv(op2,Ng) > 0)							\
53 										mulvf(res,op1,-1);							\
54 									else											\
55 										movvv(res,op1);								\
56 								} else {											\
57 									if (dotvv(op2,Ng) > 0)							\
58 										movvv(res,op1);								\
59 									else											\
60 										mulvf(res,op1,-1);							\
61 								}
62 
63 
64 #define	FACEFORWARDEXPR_UPDATE	FUN3EXPR_UPDATE(3,3,3);								\
65 								Ng		+=	3;
66 
67 DEFFUNC(FaceForward		,"faceforward"			,"v=vv"	,FACEFORWARDEXPR_PRE,FACEFORWARDEXPR,FACEFORWARDEXPR_UPDATE,NULL_EXPR,PARAMETER_NG)
68 
69 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
70 // faceforward "v=vvv"
71 #define	FACEFORWARD2EXPR		if (dotvv(op1,op3) > 0) {							\
72 									if (dotvv(op2,op3) > 0)							\
73 										mulvf(res,op1,-1);							\
74 									else											\
75 										movvv(res,op1);								\
76 								} else {											\
77 									if (dotvv(op2,op3) > 0)							\
78 										movvv(res,op1);								\
79 									else											\
80 										mulvf(res,op1,-1);							\
81 								}
82 
83 
84 DEFFUNC(FaceForward3		,"faceforward"		,"v=vvv",FUN4EXPR_PRE,FACEFORWARD2EXPR,FUN4EXPR_UPDATE(3,3,3,3),NULL_EXPR,0)
85 
86 
87 
88 
89 // The following macros are used to evaluate u and v derivatives using central differencing
90 
91 
92 
93 
94 
95 
96 
97 
98 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
99 // du "f=f"
100 #ifndef INIT_SHADING
101 #define	DUFEXPR_PRE				FUN2EXPR_PRE																		\
102 								duFloat(res,op);
103 #else
104 #undef	DUFEXPR_PRE
105 #define	DUFEXPR_PRE
106 #endif
107 
108 DEFFUNC(Duf		,"Du"			,"f=f"	,DUFEXPR_PRE,NULL_EXPR,NULL_EXPR,NULL_EXPR,PARAMETER_DPDU | PARAMETER_DPDV | PARAMETER_DU | PARAMETER_DV | PARAMETER_DERIVATIVE)
109 
110 #undef	DUVEXPR_PRE
111 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
112 // du "v=v"
113 #ifndef INIT_SHADING
114 #define	DUVEXPR_PRE				FUN2EXPR_PRE																		\
115 								duVector(res,op);
116 
117 #else
118 #undef	DUVEXPR_PRE
119 #define	DUVEXPR_PRE
120 #endif
121 
122 DEFLINKFUNC(Duv1	,"Du"		,"v=c",	PARAMETER_DPDU | PARAMETER_DPDV | PARAMETER_DU | PARAMETER_DV | PARAMETER_DERIVATIVE)
123 DEFLINKFUNC(Duv2	,"Du"		,"v=p",	PARAMETER_DPDU | PARAMETER_DPDV | PARAMETER_DU | PARAMETER_DV | PARAMETER_DERIVATIVE)
124 DEFLINKFUNC(Duv3	,"Du"		,"v=n",	PARAMETER_DPDU | PARAMETER_DPDV | PARAMETER_DU | PARAMETER_DV | PARAMETER_DERIVATIVE)
125 DEFFUNC(Duv			,"Du"		,"v=v"	,DUVEXPR_PRE,NULL_EXPR,NULL_EXPR,NULL_EXPR,PARAMETER_DPDU | PARAMETER_DPDV | PARAMETER_DU | PARAMETER_DV | PARAMETER_DERIVATIVE)
126 
127 #undef	DUVEXPR_PRE
128 
129 
130 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
131 // dv "f=f"
132 #ifndef INIT_SHADING
133 #define	DVFEXPR_PRE				FUN2EXPR_PRE																	\
134 								dvFloat(res,op);
135 #else
136 #undef	DVFEXPR_PRE
137 #define	DVFEXPR_PRE
138 #endif
139 
140 DEFFUNC(Dvf		,"Dv"			,"f=f"	,DVFEXPR_PRE,NULL_EXPR,NULL_EXPR,NULL_EXPR,PARAMETER_DPDU | PARAMETER_DPDV | PARAMETER_DU | PARAMETER_DV | PARAMETER_DERIVATIVE)
141 
142 #undef	DVFEXPR_PRE
143 
144 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
145 // dv "v=v"
146 #ifndef INIT_SHADING
147 #define	DVVEXPR_PRE				FUN2EXPR_PRE																	\
148 								dvVector(res,op);
149 #else
150 #undef	DVVEXPR_PRE
151 #define	DVVEXPR_PRE
152 #endif
153 
154 
155 DEFLINKFUNC(Dvv1	,"Dv"		,"v=c",	PARAMETER_DPDU | PARAMETER_DPDV | PARAMETER_DU | PARAMETER_DV | PARAMETER_DERIVATIVE)
156 DEFLINKFUNC(Dvv2	,"Dv"		,"v=p",	PARAMETER_DPDU | PARAMETER_DPDV | PARAMETER_DU | PARAMETER_DV | PARAMETER_DERIVATIVE)
157 DEFLINKFUNC(Dvv3	,"Dv"		,"v=n",	PARAMETER_DPDU | PARAMETER_DPDV | PARAMETER_DU | PARAMETER_DV | PARAMETER_DERIVATIVE)
158 DEFFUNC(Dvv			,"Dv"		,"v=v"	,DVVEXPR_PRE,NULL_EXPR,NULL_EXPR,NULL_EXPR,PARAMETER_DPDU | PARAMETER_DPDV | PARAMETER_DU | PARAMETER_DV | PARAMETER_DERIVATIVE)
159 
160 #undef	DVVEXPR_PRE
161 
162 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
163 // deriv "f=ff"
164 #ifndef INIT_SHADING
165 #define	DERIVFEXPR_PRE			FUN3EXPR_PRE																\
166 								float	*duTop		=	(float *) ralloc(numVertices*sizeof(float)*4,threadMemory);		\
167 								float	*duBottom	=	duTop + numVertices;								\
168 								float	*dvTop		=	duBottom + numVertices;								\
169 								float	*dvBottom	=	dvTop + numVertices;								\
170 								duFloat(duTop,		op1);													\
171 								duFloat(duBottom,	op2);													\
172 								dvFloat(dvTop,		op1);													\
173 								dvFloat(dvBottom,	op2);
174 
175 #define	DERIVFEXPR				if (duBottom[0] != 0) {														\
176 									res[0]	=	duTop[0] / duBottom[0];										\
177 								} else {																	\
178 									res[0]	=	0;															\
179 								}																			\
180 																											\
181 								if (dvBottom[0] != 0) {														\
182 									res[0]	+=	dvTop[0] / dvBottom[0];										\
183 								}
184 
185 
186 
187 #define	DERIVFEXPR_UPDATE		++res;																		\
188 								++duTop;																	\
189 								++duBottom;																	\
190 								++dvTop;																	\
191 								++dvBottom;
192 
193 #else
194 
195 #define	DERIVFEXPR_PRE
196 #define	DERIVFEXPR
197 #define	DERIVFEXPR_UPDATE
198 
199 #endif
200 
201 DEFFUNC(Derivf		,"Deriv"			,"f=ff"	,DERIVFEXPR_PRE,DERIVFEXPR,DERIVFEXPR_UPDATE,NULL_EXPR,PARAMETER_DPDU | PARAMETER_DPDV | PARAMETER_DU | PARAMETER_DV | PARAMETER_DERIVATIVE)
202 
203 #undef	DERIVFEXPR_PRE
204 #undef	DERIVFEXPR
205 #undef	DERIVFEXPR_UPDATE
206 
207 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
208 // deriv "v=vf"
209 #ifndef INIT_SHADING
210 #define	DERIVVEXPR_PRE			FUN3EXPR_PRE																\
211 								float	*duTop		=	(float *) ralloc(numVertices*sizeof(float)*8,threadMemory);		\
212 								float	*duBottom	=	duTop + numVertices*3;								\
213 								float	*dvTop		=	duBottom + numVertices;								\
214 								float	*dvBottom	=	dvTop + numVertices*3;								\
215 								duVector(duTop,		op1);													\
216 								duFloat(duBottom,	op2);													\
217 								dvVector(dvTop,		op1);													\
218 								dvFloat(dvBottom,	op2);
219 
220 #define	DERIVVEXPR				if (duBottom[0] != 0) {														\
221 									res[0]	=	(float) ((double)duTop[0] / (double)duBottom[0]);			\
222 									res[1]	=	(float) ((double)duTop[1] / (double)duBottom[0]);			\
223 									res[2]	=	(float) ((double)duTop[2] / (double)duBottom[0]);			\
224 								} else {																	\
225 									res[0]	=	0;															\
226 									res[1]	=	0;															\
227 									res[2]	=	0;															\
228 								}																			\
229 																											\
230 								if (dvBottom[0] != 0) {														\
231 									res[0]	+=	(float) ((double)dvTop[0] / (double)dvBottom[0]);			\
232 									res[1]	+=	(float) ((double)dvTop[1] / (double)dvBottom[0]);			\
233 									res[2]	+=	(float) ((double)dvTop[2] / (double)dvBottom[0]);			\
234 								}
235 
236 
237 #define	DERIVVEXPR_UPDATE		res			+=	3;															\
238 								duTop		+=	3;															\
239 								dvTop		+=	3;															\
240 								++duBottom;																	\
241 								++dvBottom;
242 
243 #else
244 #define	DERIVVEXPR_PRE
245 #define	DERIVVEXPR
246 #define	DERIVVEXPR_UPDATE
247 #endif
248 
249 DEFLINKFUNC(Derivv1		,"Deriv"		,"v=cf",	PARAMETER_DPDU | PARAMETER_DPDV | PARAMETER_DU | PARAMETER_DV | PARAMETER_DERIVATIVE)
250 DEFLINKFUNC(Derivv2		,"Deriv"		,"v=pf",	PARAMETER_DPDU | PARAMETER_DPDV | PARAMETER_DU | PARAMETER_DV | PARAMETER_DERIVATIVE)
251 DEFLINKFUNC(Derivv3		,"Deriv"		,"v=nf",	PARAMETER_DPDU | PARAMETER_DPDV | PARAMETER_DU | PARAMETER_DV | PARAMETER_DERIVATIVE)
252 DEFFUNC(Derivv			,"Deriv"		,"v=vf"	,	DERIVVEXPR_PRE,DERIVVEXPR,DERIVVEXPR_UPDATE,NULL_EXPR,PARAMETER_DPDU | PARAMETER_DPDV | PARAMETER_DU | PARAMETER_DV | PARAMETER_DERIVATIVE)
253 
254 #undef	DERIVVEXPR_PRE
255 #undef	DERIVVEXPR
256 #undef	DERIVVEXPR_UPDATE
257 
258 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
259 // area "f=p"
260 #ifndef INIT_SHADING
261 #define	AREAEXPR_PRE			FUN2EXPR_PRE																\
262 								float	*du		=	varying[VARIABLE_DU];									\
263 								float	*dv		=	varying[VARIABLE_DV];									\
264 								float	*dPdu	=	(float *) ralloc(numVertices*6*sizeof(float),threadMemory);			\
265 								float	*dPdv	=	dPdu + numVertices*3;									\
266 								vector	tmp;																\
267 								duVector(dPdu,op);															\
268 								dvVector(dPdv,op);
269 
270 
271 #define	AREAEXPR				mulvf(dPdu,du[0]);															\
272 								mulvf(dPdv,dv[0]);															\
273 								crossvv(tmp,dPdu,dPdv);														\
274 								*res	=	lengthv(tmp);													\
275 								assert(*res >= 0);
276 
277 #define	AREAEXPR_UPDATE			++res;																		\
278 								dPdu	+=	3;																\
279 								dPdv	+=	3;																\
280 								++du;																		\
281 								++dv;
282 #else
283 #define	AREAEXPR_PRE
284 #define	AREAEXPR
285 #define	AREAEXPR_UPDATE
286 #endif
287 
288 // Totally ignore the measure argument for area
289 DEFFUNC(Area		,"area"		,"f=p",		AREAEXPR_PRE,AREAEXPR,AREAEXPR_UPDATE,NULL_EXPR,PARAMETER_DPDU | PARAMETER_DPDV | PARAMETER_DU | PARAMETER_DV | PARAMETER_DERIVATIVE)
290 
291 #undef	AREAEXPR_PRE
292 #undef	AREAEXPR
293 #undef	AREAEXPR_UPDATE
294 
295 
296 
297 
298 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
299 // area "f=pS"
300 #ifndef INIT_SHADING
301 #define	AREAEXPR_PRE			FUN2EXPR_PRE																\
302 								float		*du;															\
303 								float		*dv;															\
304 								float		*dPdu;															\
305 								float		*dPdv;															\
306 								vector		tmp;															\
307 								const char	**measure;														\
308 								int			dicingMeasure;													\
309 								operand(2,measure,const char **);											\
310 								if (strcmp(*measure,"shading") == 0) {										\
311 									du		=	varying[VARIABLE_DU];										\
312 									dv		=	varying[VARIABLE_DV];										\
313 									dPdu	=	(float *) ralloc(numVertices*6*sizeof(float),threadMemory);	\
314 									dPdv	=	dPdu + numVertices*3;										\
315 									duVector(dPdu,op);														\
316 									dvVector(dPdv,op);														\
317 									dicingMeasure	=	FALSE;												\
318 								} else if (strcmp(*measure,"dicing") == 0) {								\
319 									du				=	rayDiff(op);										\
320 									dicingMeasure	=	TRUE;												\
321 								} else {																	\
322 									error(CODE_BADTOKEN,"Unrecognized area measure: \"%s\". Assuming \"dicing\"\n",*measure);					\
323 									du				=	rayDiff(op);										\
324 									dicingMeasure	=	TRUE;												\
325 								}
326 
327 
328 #define	AREAEXPR				if (dicingMeasure) {														\
329 									assert(*du >= 0);														\
330 									*res	=	(*du)*(*du);												\
331 								} else {																	\
332 									mulvf(dPdu,du[0]);														\
333 									mulvf(dPdv,dv[0]);														\
334 									crossvv(tmp,dPdu,dPdv);													\
335 									*res	=	lengthv(tmp);												\
336 								}
337 
338 #define	AREAEXPR_UPDATE			++res;																		\
339 								++du;																		\
340 								if (dicingMeasure == FALSE) {												\
341 									dPdu	+=	3;															\
342 									dPdv	+=	3;															\
343 									++dv;																	\
344 								}
345 #else
346 #define	AREAEXPR_PRE
347 #define	AREAEXPR
348 #define	AREAEXPR_UPDATE
349 #endif
350 
351 // Totally ignore the measure argument for area
352 DEFFUNC(AreaS	,"area"		,"f=pS",	AREAEXPR_PRE,AREAEXPR,AREAEXPR_UPDATE,NULL_EXPR,PARAMETER_DPDU | PARAMETER_DPDV | PARAMETER_DU | PARAMETER_DV | PARAMETER_DERIVATIVE)
353 
354 #undef	AREAEXPR_PRE
355 #undef	AREAEXPR
356 #undef	AREAEXPR_UPDATE
357 
358 
359 
360 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
361 // calculatenormal "p=p"
362 #ifndef INIT_SHADING
363 
364 #define	CALCULATENORMALEXPR_PRE		FUN2EXPR_PRE																		\
365 									float		*dPdu	=	(float *) ralloc(numVertices*6*sizeof(float),threadMemory);	\
366 									float		*dPdv	=	dPdu + numVertices*3;										\
367 									const float	mult	=	((currentShadingState->currentObject->attributes->flags & ATTRIBUTES_FLAGS_INSIDE) ? (float) -1 : (float) 1);	\
368 									duVector(dPdu,op);																	\
369 									dvVector(dPdv,op);
370 
371 #define	CALCULATENORMALEXPR			crossvv(res,dPdu,dPdv);														\
372 									mulvf(res,mult);
373 
374 #define	CALCULATENORMALEXPR_UPDATE	res		+=	3;																\
375 									dPdu	+=	3;																\
376 									dPdv	+=	3;
377 #else
378 #define	CALCULATENORMALEXPR_PRE
379 #define	CALCULATENORMALEXPR
380 #define	CALCULATENORMALEXPR_UPDATE
381 #endif
382 
383 DEFFUNC(CalculateNormal		,"calculatenormal"			,"p=p"	,CALCULATENORMALEXPR_PRE,CALCULATENORMALEXPR,CALCULATENORMALEXPR_UPDATE,NULL_EXPR,PARAMETER_DPDU | PARAMETER_DPDV | PARAMETER_DU | PARAMETER_DV | PARAMETER_DERIVATIVE)
384 
385 #undef	CALCULATENORMALEXPR_PRE
386 #undef	CALCULATENORMALEXPR
387 #undef	CALCULATENORMALEXPR_UPDATE
388 
389 
390 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
391 // noise	"f=f"
392 #define	NOISE1D1EXPR				*res	=	FUNCTION(*op);
393 #define	NOISE1D2EXPR				*res	=	FUNCTION(*op1,*op2);
394 #define	NOISE1D3EXPR				*res	=	FUNCTION(op);
395 #define	NOISE1D4EXPR				*res	=	FUNCTION(op1,*op2);
396 
397 #define	NOISE3D1EXPR				FUNCTION(res,*op);
398 #define	NOISE3D2EXPR				FUNCTION(res,*op1,*op2);
399 #define	NOISE3D3EXPR				FUNCTION(res,op);
400 #define	NOISE3D4EXPR				FUNCTION(res,op1,*op2);
401 
402 #define	FUNCTION	noiseFloat
403 DEFFUNC(Noise1D1			,"noise"		,"f=f"	,FUN2EXPR_PRE,NOISE1D1EXPR,FUN2EXPR_UPDATE(1,1),NULL_EXPR,0)
404 DEFFUNC(Noise1D2			,"noise"		,"f=ff"	,FUN3EXPR_PRE,NOISE1D2EXPR,FUN3EXPR_UPDATE(1,1,1),NULL_EXPR,0)
405 DEFFUNC(Noise1D3			,"noise"		,"f=p"	,FUN2EXPR_PRE,NOISE1D3EXPR,FUN2EXPR_UPDATE(1,3),NULL_EXPR,0)
406 DEFFUNC(Noise1D4			,"noise"		,"f=pf"	,FUN3EXPR_PRE,NOISE1D4EXPR,FUN3EXPR_UPDATE(1,3,1),NULL_EXPR,0)
407 #undef FUNCTION
408 
409 #define	FUNCTION	noiseVector
410 DEFLINKFUNC(Noise1Dv1		,"noise"		,"c=f",	0)
411 DEFLINKFUNC(Noise1Dv2		,"noise"		,"p=f",	0)
412 DEFLINKFUNC(Noise1Dv3		,"noise"		,"n=f",	0)
413 DEFFUNC(Noise3D1			,"noise"		,"v=f"	,FUN2EXPR_PRE,NOISE3D1EXPR,FUN2EXPR_UPDATE(3,1),NULL_EXPR,0)
414 DEFLINKFUNC(Noise2Dv1		,"noise"		,"c=ff",	0)
415 DEFLINKFUNC(Noise2Dv2		,"noise"		,"p=ff",	0)
416 DEFLINKFUNC(Noise2Dv3		,"noise"		,"n=ff",	0)
417 DEFFUNC(Noise3D2			,"noise"		,"v=ff"	,FUN3EXPR_PRE,NOISE3D2EXPR,FUN3EXPR_UPDATE(3,1,1),NULL_EXPR,0)
418 DEFLINKFUNC(Noise3Dv1		,"noise"		,"c=p",	0)
419 DEFLINKFUNC(Noise3Dv2		,"noise"		,"p=p",	0)
420 DEFLINKFUNC(Noise3Dv3		,"noise"		,"n=p",	0)
421 DEFFUNC(Noise3D3			,"noise"		,"v=p"	,FUN2EXPR_PRE,NOISE3D3EXPR,FUN2EXPR_UPDATE(3,3),NULL_EXPR,0)
422 DEFLINKFUNC(Noise4Dv1		,"noise"		,"c=pf",	0)
423 DEFLINKFUNC(Noise4Dv2		,"noise"		,"p=pf",	0)
424 DEFLINKFUNC(Noise4Dv3		,"noise"		,"n=pf",	0)
425 DEFFUNC(Noise3D4			,"noise"		,"v=pf"	,FUN3EXPR_PRE,NOISE3D4EXPR,FUN3EXPR_UPDATE(3,3,1),NULL_EXPR,0)
426 #undef FUNCTION
427 
428 #define	FUNCTION	cellNoiseFloat
429 DEFFUNC(CellNoise1D1			,"cellnoise"		,"f=f"	,FUN2EXPR_PRE,NOISE1D1EXPR,FUN2EXPR_UPDATE(1,1),NULL_EXPR,0)
430 DEFFUNC(CellNoise1D2			,"cellnoise"		,"f=ff"	,FUN3EXPR_PRE,NOISE1D2EXPR,FUN3EXPR_UPDATE(1,1,1),NULL_EXPR,0)
431 DEFFUNC(CellNoise1D3			,"cellnoise"		,"f=p"	,FUN2EXPR_PRE,NOISE1D3EXPR,FUN2EXPR_UPDATE(1,3),NULL_EXPR,0)
432 DEFFUNC(CellNoise1D4			,"cellnoise"		,"f=pf"	,FUN3EXPR_PRE,NOISE1D4EXPR,FUN3EXPR_UPDATE(1,3,1),NULL_EXPR,0)
433 #undef FUNCTION
434 
435 #define	FUNCTION	cellNoiseVector
436 DEFLINKFUNC(CellNoise1Dv1		,"cellnoise"		,"c=f",	0)
437 DEFLINKFUNC(CellNoise1Dv2		,"cellnoise"		,"p=f",	0)
438 DEFLINKFUNC(CellNoise1Dv3		,"cellnoise"		,"n=f",	0)
439 DEFFUNC(CellNoise3D1			,"cellnoise"		,"v=f"	,FUN2EXPR_PRE,NOISE3D1EXPR,FUN2EXPR_UPDATE(3,1),NULL_EXPR,0)
440 DEFLINKFUNC(CellNoise2Dv1		,"cellnoise"		,"c=ff",	0)
441 DEFLINKFUNC(CellNoise2Dv2		,"cellnoise"		,"p=ff",	0)
442 DEFLINKFUNC(CellNoise2Dv3		,"cellnoise"		,"n=ff",	0)
443 DEFFUNC(CellNoise3D2			,"cellnoise"		,"v=ff"	,FUN3EXPR_PRE,NOISE3D2EXPR,FUN3EXPR_UPDATE(3,1,1),NULL_EXPR,0)
444 DEFLINKFUNC(CellNoise3Dv1		,"cellnoise"		,"c=p",	0)
445 DEFLINKFUNC(CellNoise3Dv2		,"cellnoise"		,"p=p",	0)
446 DEFLINKFUNC(CellNoise3Dv3		,"cellnoise"		,"n=p",	0)
447 DEFFUNC(CellNoise3D3			,"cellnoise"		,"v=p"	,FUN2EXPR_PRE,NOISE3D3EXPR,FUN2EXPR_UPDATE(3,3),NULL_EXPR,0)
448 DEFLINKFUNC(CellNoise4Dv1		,"cellnoise"		,"c=pf",	0)
449 DEFLINKFUNC(CellNoise4Dv2		,"cellnoise"		,"p=pf",	0)
450 DEFLINKFUNC(CellNoise4Dv3		,"cellnoise"		,"n=pf",	0)
451 DEFFUNC(CellNoise3D4			,"cellnoise"		,"v=pf"	,FUN3EXPR_PRE,NOISE3D4EXPR,FUN3EXPR_UPDATE(3,3,1),NULL_EXPR,0)
452 #undef FUNCTION
453 
454 
455 #define	PNOISE1D1EXPR				*res	=	FUNCTION(*op1,*op2);
456 #define	PNOISE1D2EXPR				*res	=	FUNCTION(*op1,*op2,*op3,*op4);
457 #define	PNOISE1D3EXPR				*res	=	FUNCTION(op1,op2);
458 #define	PNOISE1D4EXPR				*res	=	FUNCTION(op1,*op2,op3,*op4);
459 
460 #define	PNOISE3D1EXPR				FUNCTION(res,*op1,*op2);
461 #define	PNOISE3D2EXPR				FUNCTION(res,*op1,*op2,*op3,*op4);
462 #define	PNOISE3D3EXPR				FUNCTION(res,op1,op2);
463 #define	PNOISE3D4EXPR				FUNCTION(res,op1,*op2,op3,*op4);
464 
465 #define	FUNCTION	pnoiseFloat
466 DEFFUNC(PNoise1D1			,"pnoise"		,"f=ff"		,FUN3EXPR_PRE,PNOISE1D1EXPR,FUN3EXPR_UPDATE(1,1,1),NULL_EXPR,0)
467 DEFFUNC(PNoise1D2			,"pnoise"		,"f=ffff"	,FUN5EXPR_PRE,PNOISE1D2EXPR,FUN5EXPR_UPDATE(1,1,1,1,1),NULL_EXPR,0)
468 DEFFUNC(PNoise1D3			,"pnoise"		,"f=pp"		,FUN3EXPR_PRE,PNOISE1D3EXPR,FUN3EXPR_UPDATE(1,3,3),NULL_EXPR,0)
469 DEFFUNC(PNoise1D4			,"pnoise"		,"f=pfpf"	,FUN5EXPR_PRE,PNOISE1D4EXPR,FUN5EXPR_UPDATE(1,3,1,3,1),NULL_EXPR,0)
470 #undef FUNCTION
471 
472 #define	FUNCTION	pnoiseVector
473 DEFLINKFUNC(PNoise1Dv1		,"pnoise"		,"c=ff",	0)
474 DEFLINKFUNC(PNoise1Dv2		,"pnoise"		,"p=ff",	0)
475 DEFLINKFUNC(PNoise1Dv3		,"pnoise"		,"n=ff",	0)
476 DEFFUNC(PNoise3D1			,"pnoise"		,"v=ff"	,	FUN3EXPR_PRE,PNOISE3D1EXPR,FUN3EXPR_UPDATE(3,1,1),NULL_EXPR,0)
477 DEFLINKFUNC(PNoise2Dv1		,"pnoise"		,"c=ffff",	0)
478 DEFLINKFUNC(PNoise2Dv2		,"pnoise"		,"p=ffff",	0)
479 DEFLINKFUNC(PNoise2Dv3		,"pnoise"		,"n=ffff",	0)
480 DEFFUNC(PNoise3D2			,"pnoise"		,"v=ffff",	FUN5EXPR_PRE,PNOISE3D2EXPR,FUN5EXPR_UPDATE(3,1,1,1,1),NULL_EXPR,0)
481 DEFLINKFUNC(PNoise3Dv1		,"pnoise"		,"c=pp",	0)
482 DEFLINKFUNC(PNoise3Dv2		,"pnoise"		,"p=pp",	0)
483 DEFLINKFUNC(PNoise3Dv3		,"pnoise"		,"n=pp",	0)
484 DEFFUNC(PNoise3D3			,"pnoise"		,"v=pp"	,	FUN3EXPR_PRE,PNOISE3D3EXPR,FUN3EXPR_UPDATE(3,3,3),NULL_EXPR,0)
485 DEFLINKFUNC(PNoise4Dv1		,"pnoise"		,"c=pfpf",	0)
486 DEFLINKFUNC(PNoise4Dv2		,"pnoise"		,"p=pfpf",	0)
487 DEFLINKFUNC(PNoise4Dv3		,"pnoise"		,"n=pfpf",	0)
488 DEFFUNC(PNoise3D4			,"pnoise"		,"v=pfpf",	FUN5EXPR_PRE,PNOISE3D4EXPR,FUN5EXPR_UPDATE(3,3,1,3,1),NULL_EXPR,0)
489 #undef FUNCTION
490 
491 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
492 // ctransform "c=Sc"
493 #define	CTRANSFORMEXPR_PRE	const float			*from,*to;											\
494 							float				*res;												\
495 							const char			**op1;												\
496 							const float			*op2;												\
497 							operand(0,res,float *);													\
498 							operand(1,op1,const char **);											\
499 							operand(2,op2,const float *);											\
500 							ECoordinateSystem	cSystem;											\
501 							findCoordinateSystem(*op1,from,to,cSystem);
502 
503 #define	CTRANSFORMEXPR		convertColorTo(res,op2,cSystem);
504 
505 DEFFUNC(CTransform		,"ctransform"			,"c=Sc"	,CTRANSFORMEXPR_PRE,CTRANSFORMEXPR,FUN3EXPR_UPDATE(3,0,3),NULL_EXPR,0)
506 
507 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
508 // ctransform "c=SSc"
509 #define	CTRANSFORMSEXPR_PRE	const float			*from,*to;											\
510 							vector				vtmp;												\
511 							ECoordinateSystem	cSystemFrom,cSystemTo;								\
512 							float				*res;												\
513 							const char			**op1;												\
514 							const char			**op2;												\
515 							const float			*op3;												\
516 							operand(0,res,float *);													\
517 							operand(1,op1,const char **);											\
518 							operand(2,op2,const char **);											\
519 							operand(3,op3,const float *);											\
520 							findCoordinateSystem(*op1,from,to,cSystemFrom);							\
521 							findCoordinateSystem(*op2,from,to,cSystemTo);
522 
523 #define CTRANSFORMSEXPR		convertColorFrom(vtmp,op3,cSystemFrom);									\
524 							convertColorTo(res,vtmp,cSystemTo);
525 
526 
527 DEFFUNC(CTransforms		,"ctransform"			,"c=SSc"	,CTRANSFORMSEXPR_PRE,CTRANSFORMSEXPR,FUN4EXPR_UPDATE(3,0,0,3),NULL_EXPR,0)
528 
529 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
530 // transform "p=Sp
531 #define	TRANSFORM1EXPR_PRE	ECoordinateSystem	cSystem;											\
532 							const float			*from,*to;											\
533 							float				*res;												\
534 							const char			**op1;												\
535 							const float			*op2;												\
536 							operand(0,res,float *);													\
537 							operand(1,op1,const char **);											\
538 							operand(2,op2,const float *);											\
539 							findCoordinateSystem(*op1,from,to,cSystem);
540 
541 
542 #define	TRANSFORM1EXPR		mulmp(res,to,op2);
543 
544 
545 #define	TRANSFORM1EXPR_UPDATE	FUN3EXPR_UPDATE(3,0,3);
546 
547 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
548 // transform "p=SSp"
549 #define	TRANSFORM2EXPR_PRE	ECoordinateSystem	cSystemFrom,cSystemTo;								\
550 							const float			*from1,*to1,*from2,*to2;							\
551 							vector				vtmp;												\
552 							float				*res;												\
553 							const char			**op1;												\
554 							const char			**op2;												\
555 							const float			*op3;												\
556 							operand(0,res,float *);													\
557 							operand(1,op1,const char **);											\
558 							operand(2,op2,const char **);											\
559 							operand(3,op3,const float *);											\
560 							findCoordinateSystem(*op1,from1,to1,cSystemFrom);						\
561 							findCoordinateSystem(*op2,from2,to2,cSystemTo);
562 
563 #define	TRANSFORM2EXPR		mulmp(vtmp,from1,op3);													\
564 							mulmp(res,to2,vtmp);
565 
566 #define	TRANSFORM2EXPR_UPDATE	FUN4EXPR_UPDATE(3,0,0,3);
567 
568 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
569 // transform "p=mp"
570 #define	TRANSFORM3EXPR		mulmp(res,op1,op2);
571 
572 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
573 // transform "p=Smp"
574 #define	TRANSFORM4EXPR_PRE	ECoordinateSystem	cSystem;											\
575 							const float			*from,*to;											\
576 							vector				vtmp;												\
577 							float				*res;												\
578 							const char			**op1;												\
579 							const float			*op2;												\
580 							const float			*op3;												\
581 							operand(0,res,float *);													\
582 							operand(1,op1,const char **);											\
583 							operand(2,op2,const float *);											\
584 							operand(3,op3,const float *);											\
585 							findCoordinateSystem(*op1,from,to,cSystem);
586 
587 #define	TRANSFORM4EXPR		mulmp(vtmp,from,op3);													\
588 							mulmp(res,op2,vtmp);
589 
590 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
591 // vtransform "p=Sp
592 #define	VTRANSFORM1EXPR_PRE	ECoordinateSystem	cSystem;											\
593 							const float			*from,*to;											\
594 							float				*res;												\
595 							const char			**op1;												\
596 							const float			*op2;												\
597 							operand(0,res,float *);													\
598 							operand(1,op1,const char **);											\
599 							operand(2,op2,const float *);											\
600 							findCoordinateSystem(*op1,from,to,cSystem);
601 
602 #define	VTRANSFORM1EXPR		mulmv(res,to,op2);
603 
604 
605 #define	VTRANSFORM1EXPR_UPDATE	FUN3EXPR_UPDATE(3,0,3);
606 
607 
608 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
609 // ntransform "p=Sp
610 #define	NTRANSFORM1EXPR_PRE	ECoordinateSystem	cSystem;											\
611 							const float			*from,*to;											\
612 							float				*res;												\
613 							const char			**op1;												\
614 							const float			*op2;												\
615 							operand(0,res,float *);													\
616 							operand(1,op1,const char **);											\
617 							operand(2,op2,const float *);											\
618 							findCoordinateSystem(*op1,from,to,cSystem);								\
619 
620 #define	NTRANSFORM1EXPR		mulmn(res,from,op2);
621 
622 #define	NTRANSFORM1EXPR_UPDATE	FUN3EXPR_UPDATE(3,0,3);												\
623 
624 
625 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
626 // vtransform "p=SSp"
627 #define VTRANSFORM2EXPR_PRE	ECoordinateSystem	cSystemFrom,cSystemTo;								\
628 							const float			*from1,*to1,*from2,*to2;							\
629 							vector				vtmp;												\
630 							float				*res;												\
631 							const char			**op1;												\
632 							const char			**op2;												\
633 							const float			*op3;												\
634 							operand(0,res,float *);													\
635 							operand(1,op1,const char **);											\
636 							operand(2,op2,const char **);											\
637 							operand(3,op3,const float *);											\
638 							findCoordinateSystem(*op1,from1,to1,cSystemFrom);						\
639 							findCoordinateSystem(*op2,from2,to2,cSystemTo);
640 
641 #define	VTRANSFORM2EXPR		mulmv(vtmp,from1,op3);													\
642 							mulmv(res,to2,vtmp);
643 
644 #define VTRANSFORM2EXPR_UPDATE	FUN4EXPR_UPDATE(3,0,0,3);
645 
646 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
647 // ntransform "p=SSp"
648 #define NTRANSFORM2EXPR_PRE	ECoordinateSystem	cSystemFrom,cSystemTo;								\
649 							const float			*from1,*to1,*from2,*to2;							\
650 							vector				vtmp;												\
651 							float				*res;												\
652 							const char			**op1;												\
653 							const char			**op2;												\
654 							const float			*op3;												\
655 							operand(0,res,float *);													\
656 							operand(1,op1,const char **);											\
657 							operand(2,op2,const char **);											\
658 							operand(3,op3,const float *);											\
659 							findCoordinateSystem(*op1,from1,to1,cSystemFrom);						\
660 							findCoordinateSystem(*op2,from2,to2,cSystemTo);
661 
662 #define	NTRANSFORM2EXPR		mulmn(vtmp,to1,op3);													\
663 							mulmn(res,from2,vtmp);
664 
665 #define NTRANSFORM2EXPR_UPDATE	FUN4EXPR_UPDATE(3,0,0,3);
666 
667 
668 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
669 // vtransform "p=mp"
670 #define	VTRANSFORM3EXPR		mulmv(res,op1,op2);
671 
672 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
673 // ntransform "p=mp"
674 #define	NTRANSFORM3EXPR		matrix	mtmp;							\
675 							invertm(mtmp,op1);						\
676 							mulmn(res,mtmp,op2);
677 
678 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
679 // vtransform "p=Smp"
680 #define	VTRANSFORM4EXPR_PRE	ECoordinateSystem	cSystem;											\
681 							const float			*from,*to;											\
682 							vector				vtmp;												\
683 							float				*res;												\
684 							const char			**op1;												\
685 							const float			*op2;												\
686 							const float			*op3;												\
687 							operand(0,res,float *);													\
688 							operand(1,op1,const char **);											\
689 							operand(2,op2,const float *);											\
690 							operand(3,op3,const float *);											\
691 							findCoordinateSystem(*op1,from,to,cSystem);
692 
693 #define	VTRANSFORM4EXPR		mulmv(vtmp,from,op3);													\
694 							mulmv(res,op2,vtmp);
695 
696 #define	VTRANSFORM4EXPR_UPDATE	FUN4EXPR_UPDATE(3,0,16,3);
697 
698 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
699 // ntransform "p=Smp"
700 #define	NTRANSFORM4EXPR_PRE	ECoordinateSystem	cSystem;											\
701 							const float			*from,*to;											\
702 							matrix				mtmp;												\
703 							vector				vtmp;												\
704 							float				*res;												\
705 							const char			**op1;												\
706 							const float			*op2;												\
707 							const float			*op3;												\
708 							operand(0,res,float *);													\
709 							operand(1,op1,const char **);											\
710 							operand(2,op2,const float *);											\
711 							operand(3,op3,const float *);											\
712 							findCoordinateSystem(*op1,from,to,cSystem);
713 
714 #define	NTRANSFORM4EXPR		invertm(mtmp,op2);														\
715 							mulmn(vtmp,to,op3);														\
716 							mulmn(res,mtmp,vtmp);
717 
718 #define	NTRANSFORM4EXPR_UPDATE	FUN4EXPR_UPDATE(3,0,16,3);
719 
720 
721 DEFFUNC(Transform1		,"transform"			,"p=Sp"		,TRANSFORM1EXPR_PRE,TRANSFORM1EXPR,TRANSFORM1EXPR_UPDATE,NULL_EXPR,0)
722 DEFFUNC(Transform2		,"transform"			,"p=SSp"	,TRANSFORM2EXPR_PRE,TRANSFORM2EXPR,TRANSFORM2EXPR_UPDATE,NULL_EXPR,0)
723 DEFFUNC(Transform3		,"transform"			,"p=mp"		,FUN3EXPR_PRE,TRANSFORM3EXPR,FUN3EXPR_UPDATE(3,16,3),NULL_EXPR,0)
724 DEFFUNC(Transform4		,"transform"			,"p=Smp"	,TRANSFORM4EXPR_PRE,TRANSFORM4EXPR,FUN4EXPR_UPDATE(3,1,16,3),NULL_EXPR,0)
725 DEFFUNC(VTransform1		,"vtransform"			,"v=Sv"		,VTRANSFORM1EXPR_PRE,VTRANSFORM1EXPR,VTRANSFORM1EXPR_UPDATE,NULL_EXPR,0)
726 DEFFUNC(VTransform2		,"vtransform"			,"v=SSv"	,VTRANSFORM2EXPR_PRE,VTRANSFORM2EXPR,VTRANSFORM2EXPR_UPDATE,NULL_EXPR,0)
727 DEFFUNC(VTransform3		,"vtransform"			,"v=mv"		,FUN3EXPR_PRE,VTRANSFORM3EXPR,FUN3EXPR_UPDATE(3,16,3),NULL_EXPR,0)
728 DEFFUNC(VTransform4		,"vtransform"			,"v=Smv"	,VTRANSFORM4EXPR_PRE,VTRANSFORM4EXPR,VTRANSFORM4EXPR_UPDATE,NULL_EXPR,0)
729 DEFFUNC(NTransform1		,"ntransform"			,"n=Sn"		,NTRANSFORM1EXPR_PRE,NTRANSFORM1EXPR,NTRANSFORM1EXPR_UPDATE,NULL_EXPR,0)
730 DEFFUNC(NTransform2		,"ntransform"			,"n=SSn"	,NTRANSFORM2EXPR_PRE,NTRANSFORM2EXPR,NTRANSFORM2EXPR_UPDATE,NULL_EXPR,0)
731 DEFFUNC(NTransform3		,"ntransform"			,"n=mn"		,FUN3EXPR_PRE,NTRANSFORM3EXPR,FUN3EXPR_UPDATE(3,16,3),NULL_EXPR,0)
732 DEFFUNC(NTransform4		,"ntransform"			,"n=Smn"	,NTRANSFORM4EXPR_PRE,NTRANSFORM4EXPR,NTRANSFORM4EXPR_UPDATE,NULL_EXPR,0)
733 
734 
735 
736 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
737 // depth "f=p"
738 #define DEPTHEXPR		*res	=	(op[2] - CRenderer::clipMin) / (CRenderer::clipMax - CRenderer::clipMin);
739 
740 DEFFUNC(Depth		,"depth"			,"f=p"	,FUN2EXPR_PRE,DEPTHEXPR,FUN2EXPR_UPDATE(1,3),NULL_EXPR,0)
741 
742 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
743 // clearlighting	"o="
744 #define	CLEARLIGHTINGEXPR_PRE	clearLighting();
745 
746 DEFFUNC(Clearlighting			,"clearlighting"				,"o="		,CLEARLIGHTINGEXPR_PRE,NULL_EXPR,NULL_EXPR,NULL_EXPR,0)
747 
748 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
749 // ambient	"c="
750 #define	AMBIENTEXPR_PRE		const float		*Clsave;											\
751 							float			*res;												\
752 							operand(0,res,float *);												\
753 							runAmbientLights();													\
754 							Clsave = (*alights)->savedState[1];
755 
756 #define AMBIENTEXPR			movvv(res,Clsave);
757 
758 #define	AMBIENTEXPR_UPDATE	res		+=	3;														\
759 							Clsave	+=	3;
760 
761 DEFFUNC(Ambient			,"ambient"				,"c="		,AMBIENTEXPR_PRE,AMBIENTEXPR,AMBIENTEXPR_UPDATE,NULL_EXPR,0)
762 
763 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
764 // diffuse	"c=n"
765 #define	DIFFUSEEXPR_PRE		float			*costheta	=	(float *) ralloc(numVertices*sizeof(float),threadMemory);	\
766 							float			*res;												\
767 							const float		*op;												\
768 							vector			Ltmp;												\
769 							for (int i=0;i<numVertices;++i) costheta[i]	=	0;					\
770 							operand(0,res,float *);												\
771 							operand(1,op,const float *);										\
772 							const float	*P		=	varying[VARIABLE_P];						\
773 							const float	*N		=	op;											\
774 																								\
775 							runLights(P,N,costheta);											\
776 							/* initialize output appropriately */								\
777 							float *R			=	res;										\
778 							tags				=	tagStart;									\
779 							for (int i=0;i<numVertices;++i) {									\
780 								if (*tags == 0) initv(R,0,0,0);									\
781 								R += 3;															\
782 								++tags;															\
783 							}																	\
784 							/* loop the lighting contributions */								\
785 							*currentLight	=	*lights;										\
786 							while (*currentLight) {												\
787 								int				ndStep;											\
788 								float			_nd = 0;										\
789 								const float		*nd;											\
790 								enterFastLightingConditional();									\
791 								CShaderInstance *_inst = (*currentLight)->instance;				\
792 								if (_inst ->flags & SHADERFLAGS_NONDIFFUSE) {					\
793 									CLightShaderData *lightData = (CLightShaderData*) _inst->data;			\
794 									nd		=	(*currentLight)->savedState[2+lightData->nonDiffuseIndex];	\
795 									ndStep 	=	lightData->nonDiffuseStep;						\
796 								} else {														\
797 									nd		=	&_nd;											\
798 									ndStep	=	0;												\
799 								}																\
800 								const float	*L		=	(*currentLight)->savedState[0];			\
801 								const float	*Cl		=	(*currentLight)->savedState[1];			\
802 								R		=	res;												\
803 								N		=	op;													\
804 								tags	=	tagStart;
805 
806 
807 #define DIFFUSEEXPR			normalizev(Ltmp,L);													\
808 							const float coefficient = (1.0f-nd[0])*dotvv(N,Ltmp);				\
809 							if (coefficient > 0) {												\
810 								R[COMP_R] += coefficient * Cl[COMP_R];							\
811 								R[COMP_G] += coefficient * Cl[COMP_G];							\
812 								R[COMP_B] += coefficient * Cl[COMP_B];							\
813 							}
814 
815 #define	DIFFUSEEXPR_UPDATE	R		+=	3;														\
816 							N		+=	3;														\
817 							Cl		+=	3;														\
818 							L		+=	3;														\
819 							nd		+=	ndStep;
820 
821 #define DIFFUSEEXPR_POST		exitFastLightingConditional();									\
822 								*currentLight=(*currentLight)->next;							\
823 							}
824 
825 DEFLIGHTFUNC(Diffuse				,"diffuse"				,"c=n"		,DIFFUSEEXPR_PRE, DIFFUSEEXPR, DIFFUSEEXPR_UPDATE, DIFFUSEEXPR_POST, PARAMETER_P)
826 
827 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
828 // diffuse	"c=pnf"
829 #define	DIFFUSE2EXPR_PRE	const float		*P,*N;												\
830 							float			*costheta	=	(float *) ralloc(numVertices*sizeof(float),threadMemory); \
831 							const float		*cosangle;											\
832 							const float		*op3;												\
833 							vector			Ltmp;												\
834 							float			*res;												\
835 							const float		*op2;												\
836 							operand(0,res,float *);												\
837 							operand(1,P,const float *);											\
838 							operand(2,op2,const float *);										\
839 							operand(3,op3,const float *);										\
840 							for (int i=0;i<numVertices;++i) costheta[i] = (float) cos(op3[i]);	\
841 							N		=	op2;													\
842 							runLights(P,N,costheta);											\
843 							/* initialize output appropriately */								\
844 							float *R		=	res;											\
845 							tags			=	tagStart;										\
846 							for (int i=0;i<numVertices;++i) {									\
847 								if (*tags==0) initv(R,0,0,0);									\
848 								R += 3;															\
849 								++tags;															\
850 							}																	\
851 							/* loop the lighting contributions */								\
852 							*currentLight = *lights;											\
853 							while (*currentLight) {												\
854 								int				ndStep;											\
855 								float			_nd = 0;										\
856 								const float		*nd;											\
857 								enterFastLightingConditional();									\
858 								CShaderInstance *_inst = (*currentLight)->instance;				\
859 								if (_inst ->flags & SHADERFLAGS_NONDIFFUSE) {					\
860 									CLightShaderData *lightData = (CLightShaderData*) _inst->data;			\
861 									nd		=	(*currentLight)->savedState[2+lightData->nonDiffuseIndex];	\
862 									ndStep 	=	lightData->nonDiffuseStep;						\
863 								} else {														\
864 									nd		=	&_nd;											\
865 									ndStep	=	0;												\
866 								}																\
867 								const float *L	=	(*currentLight)->savedState[0];				\
868 								const float *Cl	=	(*currentLight)->savedState[1];				\
869 								R			=	res;											\
870 								N			=	op2;											\
871 								cosangle	=	costheta;										\
872 								tags		=	tagStart;
873 
874 #define DIFFUSE2EXPR		normalizev(Ltmp,L);													\
875 							const float coefficient = (1.0f-nd[0])*dotvv(N,Ltmp);				\
876 							if (coefficient > *cosangle) {										\
877 								R[COMP_R] += coefficient * Cl[COMP_R];							\
878 								R[COMP_G] += coefficient * Cl[COMP_G];							\
879 								R[COMP_B] += coefficient * Cl[COMP_B];							\
880 							}
881 
882 #define	DIFFUSE2EXPR_UPDATE	R			+=	3;													\
883 							N			+=	3;													\
884 							cosangle	+=	1;													\
885 							Cl			+=	3;													\
886 							L			+=	3;													\
887 							nd			+=	ndStep;
888 
889 
890 #define DIFFUSE2EXPR_POST		exitFastLightingConditional();									\
891 								*currentLight=(*currentLight)->next;							\
892 							}
893 
894 
895 DEFLIGHTFUNC(Diffuse2			,"diffuse"				,"c=pnf"	,DIFFUSE2EXPR_PRE, DIFFUSE2EXPR, DIFFUSE2EXPR_UPDATE, DIFFUSE2EXPR_POST, 0)
896 
897 
898 
899 
900 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
901 // specular	"c=nvf"
902 #define	SPECULAREXPR_PRE		float			*costheta	=	(float *) ralloc(numVertices*sizeof(float),threadMemory);	\
903 								float			*powers		=	(float *) ralloc(numVertices*sizeof(float),threadMemory);	\
904 								const float		*op1,*op2,*op3;										\
905 								float			*res;												\
906 								vector			Ltmp,halfway;										\
907 								operand(0,res,float *);												\
908 								operand(1,op1,const float *);										\
909 								operand(2,op2,const float *);										\
910 								operand(3,op3,const float *);										\
911 								for (int i=0;i<numVertices;++i)	costheta[i]	=	0;					\
912 								const float *P		=	varying[VARIABLE_P];						\
913 								const float *N		=	op1;										\
914 								runLights(P,N,costheta);											\
915 								/* initialize output appropriately */								\
916 								float *R			=	res;										\
917 								float *power		=	powers;										\
918 								tags				=	tagStart;									\
919 								for (int i=0;i<numVertices;++i) {									\
920 									if (*tags==0) {													\
921 										initv(R,0,0,0);												\
922 										*power = 10.0f / *op3;										\
923 									}																\
924 									R			+=	3;												\
925 									op3			+=	1;												\
926 									power		+=	1;												\
927 									++tags;															\
928 								}																	\
929 								/* loop the lighting contributions */								\
930 								*currentLight = *lights;											\
931 								while (*currentLight) {												\
932 									float	_ns = 0;												\
933 									int		nsStep;													\
934 									const float	*ns;												\
935 									enterFastLightingConditional();									\
936 									CShaderInstance *_inst = (*currentLight)->instance;				\
937 									if (_inst ->flags & SHADERFLAGS_NONSPECULAR) {					\
938 										CLightShaderData *lightData = (CLightShaderData*) _inst->data;			\
939 										ns		=	(*currentLight)->savedState[2+lightData->nonSpecularIndex];	\
940 										nsStep 	=	lightData->nonSpecularStep;						\
941 									} else {														\
942 										ns		=	&_ns;											\
943 										nsStep	=	0;												\
944 									}																\
945 									const float *L			=	(*currentLight)->savedState[0];		\
946 									const float *Cl			=	(*currentLight)->savedState[1];		\
947 									const float *V			=	op2;								\
948 									R			=	res;											\
949 									N			=	op1;											\
950 									power		=	powers;											\
951 									tags		=	tagStart;
952 
953 #define SPECULAREXPR			normalizev(Ltmp,L);													\
954 								addvv(halfway,V,Ltmp);												\
955 								normalizev(halfway);												\
956 								const float	tmp	=	((1.0f-ns[0])*dotvv(N,halfway));				\
957 								if (tmp > 0) {														\
958 									const float coefficient = (float) pow(tmp,*power);				\
959 									R[COMP_R] += coefficient * Cl[COMP_R];							\
960 									R[COMP_G] += coefficient * Cl[COMP_G];							\
961 									R[COMP_B] += coefficient * Cl[COMP_B];							\
962 								}
963 
964 #define	SPECULAREXPR_UPDATE		R			+=	3;													\
965 								N			+=	3;													\
966 								V			+=	3;													\
967 								power		+=	1;													\
968 								Cl			+=	3;													\
969 								L			+=	3;													\
970 								ns			+=	nsStep;
971 
972 #define SPECULAREXPR_POST			exitFastLightingConditional();									\
973 									*currentLight=(*currentLight)->next;							\
974 								}
975 
976 DEFLIGHTFUNC(Specular				,"specular"				,"c=nvf"		,SPECULAREXPR_PRE, SPECULAREXPR, SPECULAREXPR_UPDATE, SPECULAREXPR_POST, PARAMETER_P)
977 
978 
979 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
980 // phong	"c=nvf"
981 #define	PHONGEXPR_PRE			float			*costheta	=	(float *) ralloc(numVertices*sizeof(float),threadMemory);	\
982 								float			*refDirs	=	(float *) ralloc(3*numVertices*sizeof(float),threadMemory);	\
983 								const float		*op1,*op2,*op3;										\
984 								float			*res;												\
985 								vector			Ltmp;												\
986 								operand(0,res,float *);												\
987 								operand(1,op1,const float *);										\
988 								operand(2,op2,const float *);										\
989 								operand(3,op3,const float *);										\
990 								for (int i=0;i<numVertices;++i)	costheta[i]	=	0;					\
991 								const float	*P		=	varying[VARIABLE_P];						\
992 								const float	*N		=	op1;										\
993 								runLights(P,N,costheta);											\
994 								/* initialize output appropriately */								\
995 								float		*R		=	res;										\
996 								const float	*V		=	op2;										\
997 								float *refDir		=	refDirs;									\
998 								N					=	op1;										\
999 								tags				=	tagStart;									\
1000 								for (int i=0;i<numVertices;++i) {									\
1001 									if (*tags==0) {													\
1002 										initv(R,0,0,0);												\
1003 										mulvf(refDir,N,2*dotvv(N,V));								\
1004 										subvv(refDir,V);											\
1005 									}																\
1006 									R			+=	3;												\
1007 									N			+=	3;												\
1008 									V			+=	3;												\
1009 									refDir		+=	3;												\
1010 									++tags;															\
1011 								}																	\
1012 								/* loop the lighting contributions */								\
1013 								*currentLight = *lights;											\
1014 								while (*currentLight) {												\
1015 									int				nsStep;											\
1016 									const float		*ns;											\
1017 									float			_ns = 0;										\
1018 									enterFastLightingConditional();									\
1019 									CShaderInstance *_inst = (*currentLight)->instance;				\
1020 									if (_inst ->flags & SHADERFLAGS_NONSPECULAR) {					\
1021 										CLightShaderData *lightData = (CLightShaderData*) _inst->data;			\
1022 										ns		=	(*currentLight)->savedState[2+lightData->nonSpecularIndex];	\
1023 										nsStep 	=	lightData->nonSpecularStep;						\
1024 									} else {														\
1025 										ns		=	&_ns;											\
1026 										nsStep	=	0;												\
1027 									}																\
1028 									const float *L			=	(*currentLight)->savedState[0];		\
1029 									const float *Cl			=	(*currentLight)->savedState[1];		\
1030 									const float *size		=	op3;								\
1031 									R			=	res;											\
1032 									refDir		=	refDirs;										\
1033 									tags		=	tagStart;
1034 
1035 #define PHONGEXPR				normalizev(Ltmp,L);													\
1036 								const float coefficient = (1.0f-ns[0]) * (float) pow(max(0,dotvv(refDir,Ltmp)),*size);			\
1037 								if (coefficient > 0) {												\
1038 									R[COMP_R] += coefficient * Cl[COMP_R];							\
1039 									R[COMP_G] += coefficient * Cl[COMP_G];							\
1040 									R[COMP_B] += coefficient * Cl[COMP_B];							\
1041 								}
1042 
1043 #define	PHONGEXPR_UPDATE		R		+=	3;														\
1044 								size	+=	1;														\
1045 								refDir	+=	3;														\
1046 								Cl		+=	3;														\
1047 								L		+=	3;														\
1048 								ns		+=	nsStep;
1049 
1050 #define PHONGEXPR_POST			exitFastLightingConditional();										\
1051 								*currentLight=(*currentLight)->next;								\
1052 							}
1053 
1054 DEFLIGHTFUNC(Phong				,"phong"				,"c=nvf"		,PHONGEXPR_PRE, PHONGEXPR, PHONGEXPR_UPDATE, PHONGEXPR_POST, PARAMETER_P)
1055 
1056 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1057 // specularBRDF	"c=vnvf"
1058 #define	SPECULARBRDFEXPR_PRE	float			*res;												\
1059 								const float		*op1,*op2,*op3,*op4;								\
1060 								vector			halfway;											\
1061 								operand(0,res,float *);												\
1062 								operand(1,op1,const float *);										\
1063 								operand(2,op2,const float *);										\
1064 								operand(3,op3,const float *);										\
1065 								operand(4,op4,const float *);
1066 
1067 #define SPECULARBRDFEXPR		addvv(halfway,op3,op1);												\
1068 								normalizev(halfway);												\
1069 								res[0]	=	(float) pow(max(0,dotvv(op2,halfway)),(10.0f)/(*op4));	\
1070 								res[1]	=	res[0];													\
1071 								res[2]	=	res[1];													\
1072 
1073 #define	SPECULARBRDFEXPR_UPDATE	res		+=	3;														\
1074 								op1		+=	3;														\
1075 								op2		+=	3;														\
1076 								op3		+=	3;														\
1077 								op4		+=	1;
1078 
1079 
1080 
1081 DEFFUNC(SpecularBRDF			,"specularbrdf"				,"c=vnvf"		,SPECULARBRDFEXPR_PRE,SPECULARBRDFEXPR,SPECULARBRDFEXPR_UPDATE,NULL_EXPR,0)
1082 
1083 
1084 
1085 
1086 
1087 #ifndef INIT_SHADING
1088 
1089 
1090 ////////////////////
1091 // FIXME: Not 64 bit compatible
1092 #define	PARAMETEREXPR_PRE(accessor)																			\
1093 								float		*res;															\
1094 								const char	**op1;															\
1095 								float		*op2;															\
1096 								int			op2Step;														\
1097 								operand(0,res,float *);														\
1098 								operand(1,op1,const char **);												\
1099 								operand(2,op2,float *);														\
1100 								op2Step = operandVaryingStep(2);											\
1101 																											\
1102 								int			globalIndex =	-1;												\
1103 								CVariable	*cVar		=	NULL;											\
1104 								float		found		=	(float) FUNCTION(op2,*op1,&cVar,&globalIndex);	\
1105 								const float	*src		=	op2;											\
1106 								int			srcStep		=	op2Step;										\
1107 																											\
1108 								if (found != 0) {															\
1109 									srcStep					=	0;											\
1110 									if (cVar != NULL) {														\
1111 										if (cVar->storage == STORAGE_PARAMETER || cVar->storage == STORAGE_MUTABLEPARAMETER) { 				\
1112 											src					=	currentShadingState->locals[accessor][cVar->entry];						\
1113 										} else {																							\
1114 											src					=	varying[cVar->entry];													\
1115 										}																									\
1116 										srcStep				=	cVar->numFloats;															\
1117 										if ((cVar->container == CONTAINER_UNIFORM) || (cVar->container == CONTAINER_CONSTANT)) {			\
1118 											srcStep	=	0;													\
1119 										} else if (op2Step == 0) {											\
1120 											/* guard against varying->uniform assignment : nullify copy */	\
1121 											srcStep	=	0;													\
1122 											src		=	op2;												\
1123 											found	=	0;													\
1124 										}																	\
1125 									}																		\
1126 								}
1127 
1128 #define LIGHTPARAMETEREXPR_PRE	float		*res;															\
1129 								const char	**op1;															\
1130 								float		*op2;															\
1131 								int			op2Step;														\
1132 								operand(0,res,float *);														\
1133 								operand(1,op1,const char **);												\
1134 								operand(2,op2,float *);														\
1135 								op2Step = operandVaryingStep(2);											\
1136 																											\
1137 								int			globalIndex =	-1;												\
1138 								CVariable	*cVar		=	NULL;											\
1139 								float		found		=	(float) (*currentLight)->instance->getParameter(*op1,op2,&cVar,&globalIndex);\
1140 								const float	*src		=	op2;											\
1141 								int			srcStep		=	op2Step;										\
1142 																											\
1143 								if (found != 0) {															\
1144 									srcStep				=	0;												\
1145 									if (cVar != NULL) {														\
1146 										src					=	(*currentLight)->savedState[2+globalIndex];								\
1147 										srcStep				=	cVar->numFloats;														\
1148 										if ((cVar->container == CONTAINER_UNIFORM) || (cVar->container == CONTAINER_CONSTANT)) {		\
1149 											srcStep	=	0;													\
1150 										} else if (op2Step == 0) {											\
1151 											/* guard against varying->uniform assignment : nullify copy */	\
1152 											srcStep		=	0;												\
1153 											src			=	op2;											\
1154 											found		=	0;												\
1155 										}																	\
1156 									}																		\
1157 								}
1158 
1159 #define	PARAMETEREXPRF			*res		=	found;												\
1160 								*op2		=	*src;
1161 
1162 #define	PARAMETEREXPRS			*res		=	found;												\
1163 								*op2		=	*src;
1164 
1165 #define	PARAMETEREXPRV			*res		=	found;												\
1166 								op2[0]		=	src[0];												\
1167 								op2[1]		=	src[1];												\
1168 								op2[2]		=	src[2];
1169 
1170 #define	PARAMETEREXPRM			*res		=	found;												\
1171 								op2[0]		=	src[0];												\
1172 								op2[1]		=	src[1];												\
1173 								op2[2]		=	src[2];												\
1174 								op2[3]		=	src[3];												\
1175 								op2[4]		=	src[4];												\
1176 								op2[5]		=	src[5];												\
1177 								op2[6]		=	src[6];												\
1178 								op2[7]		=	src[7];												\
1179 								op2[8]		=	src[8];												\
1180 								op2[9]		=	src[9];												\
1181 								op2[10]		=	src[10];											\
1182 								op2[11]		=	src[11];											\
1183 								op2[12]		=	src[12];											\
1184 								op2[13]		=	src[13];											\
1185 								op2[14]		=	src[14];											\
1186 								op2[15]		=	src[15];
1187 
1188 
1189 #define	PARAMETEREXPR_UPDATE(__r,__o2)																\
1190 								res			+=	__r;												\
1191 								op2			+=	__o2;												\
1192 								src			+=	srcStep;
1193 
1194 #else
1195 #undef PARAMETEREXPR_PRE
1196 #undef LIGHTPARAMETEREXPR_PRE
1197 #undef PARAMETEREXPRF
1198 #undef PARAMETEREXPRS
1199 #undef PARAMETEREXPRV
1200 #undef PARAMETEREXPRM
1201 #undef PARAMETEREXPR_UPDATE
1202 #define PARAMETEREXPR_PRE(a)
1203 #define LIGHTPARAMETEREXPR_PRE
1204 #define PARAMETEREXPRF
1205 #define PARAMETEREXPRS
1206 #define PARAMETEREXPRV
1207 #define PARAMETEREXPRM
1208 #define PARAMETEREXPR_UPDATE
1209 #endif
1210 
1211 #define	FUNCTION	displacementParameter
1212 DEFLINKFUNC(Displacement2			,"displacement"				,"f=SC",	PARAMETER_MESSAGEPASSING)
1213 DEFLINKFUNC(Displacement3			,"displacement"				,"f=SN",	PARAMETER_MESSAGEPASSING)
1214 DEFLINKFUNC(Displacement4			,"displacement"				,"f=SP",	PARAMETER_MESSAGEPASSING)
1215 DEFFUNC(DisplacementV				,"displacement"				,"f=SV"		,PARAMETEREXPR_PRE(ACCESSOR_DISPLACEMENT),PARAMETEREXPRV,PARAMETEREXPR_UPDATE(1,3),NULL_EXPR,PARAMETER_MESSAGEPASSING)
1216 DEFFUNC(Displacement				,"displacement"				,"f=SF"		,PARAMETEREXPR_PRE(ACCESSOR_DISPLACEMENT),PARAMETEREXPRF,PARAMETEREXPR_UPDATE(1,1),NULL_EXPR,PARAMETER_MESSAGEPASSING)
1217 DEFFUNC(DisplacementS				,"displacement"				,"f=SS"		,PARAMETEREXPR_PRE(ACCESSOR_DISPLACEMENT),PARAMETEREXPRS,PARAMETEREXPR_UPDATE(1,1),NULL_EXPR,PARAMETER_MESSAGEPASSING)
1218 DEFFUNC(DisplacementM				,"displacement"				,"f=SM"		,PARAMETEREXPR_PRE(ACCESSOR_DISPLACEMENT),PARAMETEREXPRM,PARAMETEREXPR_UPDATE(1,16),NULL_EXPR,PARAMETER_MESSAGEPASSING)
1219 #undef FUNCTION
1220 
1221 #define	FUNCTION	surfaceParameter
1222 DEFLINKFUNC(Surface2			,"surface"				,"f=SC",	PARAMETER_MESSAGEPASSING)
1223 DEFLINKFUNC(Surface3			,"surface"				,"f=SN",	PARAMETER_MESSAGEPASSING)
1224 DEFLINKFUNC(Surface4			,"surface"				,"f=SP",	PARAMETER_MESSAGEPASSING)
1225 DEFFUNC(SurfaceV				,"surface"				,"f=SV"		,PARAMETEREXPR_PRE(ACCESSOR_SURFACE),PARAMETEREXPRV,PARAMETEREXPR_UPDATE(1,3),NULL_EXPR,PARAMETER_MESSAGEPASSING)
1226 DEFFUNC(Surface					,"surface"				,"f=SF"		,PARAMETEREXPR_PRE(ACCESSOR_SURFACE),PARAMETEREXPRF,PARAMETEREXPR_UPDATE(1,1),NULL_EXPR,PARAMETER_MESSAGEPASSING)
1227 DEFFUNC(SurfaceS				,"surface"				,"f=SS"		,PARAMETEREXPR_PRE(ACCESSOR_SURFACE),PARAMETEREXPRS,PARAMETEREXPR_UPDATE(1,1),NULL_EXPR,PARAMETER_MESSAGEPASSING)
1228 DEFFUNC(SurfaceM				,"surface"				,"f=SM"		,PARAMETEREXPR_PRE(ACCESSOR_SURFACE),PARAMETEREXPRM,PARAMETEREXPR_UPDATE(1,16),NULL_EXPR,PARAMETER_MESSAGEPASSING)
1229 #undef FUNCTION
1230 
1231 DEFLINKFUNC(Lightsource2			,"lightsource"				,"f=SC",	PARAMETER_MESSAGEPASSING)
1232 DEFLINKFUNC(Lightsource3			,"lightsource"				,"f=SN",	PARAMETER_MESSAGEPASSING)
1233 DEFLINKFUNC(Lightsource4			,"lightsource"				,"f=SP",	PARAMETER_MESSAGEPASSING)
1234 DEFFUNC(LightsourceV				,"lightsource"				,"f=SV"		,LIGHTPARAMETEREXPR_PRE,PARAMETEREXPRV,PARAMETEREXPR_UPDATE(1,3),NULL_EXPR,PARAMETER_MESSAGEPASSING)
1235 DEFFUNC(Lightsource					,"lightsource"				,"f=SF"		,LIGHTPARAMETEREXPR_PRE,PARAMETEREXPRF,PARAMETEREXPR_UPDATE(1,1),NULL_EXPR,PARAMETER_MESSAGEPASSING)
1236 DEFFUNC(LightsourceS				,"lightsource"				,"f=SS"		,LIGHTPARAMETEREXPR_PRE,PARAMETEREXPRS,PARAMETEREXPR_UPDATE(1,1),NULL_EXPR,PARAMETER_MESSAGEPASSING)
1237 DEFFUNC(LightsourceM				,"lightsource"				,"f=SM"		,LIGHTPARAMETEREXPR_PRE,PARAMETEREXPRM,PARAMETEREXPR_UPDATE(1,16),NULL_EXPR,PARAMETER_MESSAGEPASSING)
1238 
1239 #define	FUNCTION	atmosphereParameter
1240 DEFLINKFUNC(Atmosphere2			,"atmosphere"				,"f=SC",	PARAMETER_MESSAGEPASSING)
1241 DEFLINKFUNC(Atmosphere3			,"atmosphere"				,"f=SN",	PARAMETER_MESSAGEPASSING)
1242 DEFLINKFUNC(Atmosphere4			,"atmosphere"				,"f=SP",	PARAMETER_MESSAGEPASSING)
1243 DEFFUNC(AtmosphereV				,"atmosphere"				,"f=SV"		,PARAMETEREXPR_PRE(ACCESSOR_ATMOSPHERE),PARAMETEREXPRV,PARAMETEREXPR_UPDATE(1,3),NULL_EXPR,PARAMETER_MESSAGEPASSING)
1244 DEFFUNC(Atmosphere				,"atmosphere"				,"f=SF"		,PARAMETEREXPR_PRE(ACCESSOR_ATMOSPHERE),PARAMETEREXPRF,PARAMETEREXPR_UPDATE(1,1),NULL_EXPR,PARAMETER_MESSAGEPASSING)
1245 DEFFUNC(AtmosphereS				,"atmosphere"				,"f=SS"		,PARAMETEREXPR_PRE(ACCESSOR_ATMOSPHERE),PARAMETEREXPRS,PARAMETEREXPR_UPDATE(1,1),NULL_EXPR,PARAMETER_MESSAGEPASSING)
1246 DEFFUNC(AtmosphereM				,"atmosphere"				,"f=SM"		,PARAMETEREXPR_PRE(ACCESSOR_ATMOSPHERE),PARAMETEREXPRM,PARAMETEREXPR_UPDATE(1,16),NULL_EXPR,PARAMETER_MESSAGEPASSING)
1247 #undef FUNCTION
1248 
1249 /* note that whilst we provide accessors for incident and opposite, they will never be used */
1250 
1251 #define	FUNCTION	incidentParameter
1252 DEFLINKFUNC(Incident2			,"incident"				,"f=SC",	PARAMETER_MESSAGEPASSING)
1253 DEFLINKFUNC(Incident3			,"incident"				,"f=SN",	PARAMETER_MESSAGEPASSING)
1254 DEFLINKFUNC(Incident4			,"incident"				,"f=SP",	PARAMETER_MESSAGEPASSING)
1255 DEFFUNC(IncidentV				,"incident"				,"f=SV"		,PARAMETEREXPR_PRE(ACCESSOR_EXTERIOR),PARAMETEREXPRV,PARAMETEREXPR_UPDATE(1,3),NULL_EXPR,PARAMETER_MESSAGEPASSING)
1256 DEFFUNC(Incident				,"incident"				,"f=SF"		,PARAMETEREXPR_PRE(ACCESSOR_EXTERIOR),PARAMETEREXPRF,PARAMETEREXPR_UPDATE(1,1),NULL_EXPR,PARAMETER_MESSAGEPASSING)
1257 DEFFUNC(IncidentS				,"incident"				,"f=SS"		,PARAMETEREXPR_PRE(ACCESSOR_EXTERIOR),PARAMETEREXPRS,PARAMETEREXPR_UPDATE(1,1),NULL_EXPR,PARAMETER_MESSAGEPASSING)
1258 DEFFUNC(IncidentM				,"incident"				,"f=SM"		,PARAMETEREXPR_PRE(ACCESSOR_EXTERIOR),PARAMETEREXPRM,PARAMETEREXPR_UPDATE(1,16),NULL_EXPR,PARAMETER_MESSAGEPASSING)
1259 #undef FUNCTION
1260 
1261 #define	FUNCTION	oppositeParameter
1262 DEFLINKFUNC(Opposite2			,"opposite"				,"f=SC",	PARAMETER_MESSAGEPASSING)
1263 DEFLINKFUNC(Opposite3			,"opposite"				,"f=SN",	PARAMETER_MESSAGEPASSING)
1264 DEFLINKFUNC(Opposite4			,"opposite"				,"f=SP",	PARAMETER_MESSAGEPASSING)
1265 DEFFUNC(OppositeV				,"opposite"				,"f=SV"		,PARAMETEREXPR_PRE(ACCESSOR_INTERIOR),PARAMETEREXPRV(ACCESSOR_INTERIOR),PARAMETEREXPR_UPDATE(1,3),NULL_EXPR,PARAMETER_MESSAGEPASSING)
1266 DEFFUNC(Opposite				,"opposite"				,"f=SF"		,PARAMETEREXPR_PRE(ACCESSOR_INTERIOR),PARAMETEREXPRF(ACCESSOR_INTERIOR),PARAMETEREXPR_UPDATE(1,1),NULL_EXPR,PARAMETER_MESSAGEPASSING)
1267 DEFFUNC(OppositeS				,"opposite"				,"f=SS"		,PARAMETEREXPR_PRE(ACCESSOR_INTERIOR),PARAMETEREXPRS(ACCESSOR_INTERIOR),PARAMETEREXPR_UPDATE(1,1),NULL_EXPR,PARAMETER_MESSAGEPASSING)
1268 DEFFUNC(OppositeM				,"opposite"				,"f=SM"		,PARAMETEREXPR_PRE(ACCESSOR_INTERIOR),PARAMETEREXPRM(ACCESSOR_INTERIOR),PARAMETEREXPR_UPDATE(1,16),NULL_EXPR,PARAMETER_MESSAGEPASSING)
1269 #undef FUNCTION
1270 
1271 /* note the accessor for the remaining functions is not used */
1272 
1273 #define	FUNCTION	attributes
1274 DEFLINKFUNC(Attributes2			,"attribute"				,"f=SC",	0)
1275 DEFLINKFUNC(Attributes3			,"attribute"				,"f=SN",	0)
1276 DEFLINKFUNC(Attributes4			,"attribute"				,"f=SP",	0)
1277 DEFFUNC(AttributesV				,"attribute"				,"f=SV"		,PARAMETEREXPR_PRE(0),PARAMETEREXPRV,PARAMETEREXPR_UPDATE(1,3),NULL_EXPR,0)
1278 DEFFUNC(Attributes				,"attribute"				,"f=SF"		,PARAMETEREXPR_PRE(0),PARAMETEREXPRF,PARAMETEREXPR_UPDATE(1,1),NULL_EXPR,0)
1279 DEFFUNC(AttributesS				,"attribute"				,"f=SS"		,PARAMETEREXPR_PRE(0),PARAMETEREXPRS,PARAMETEREXPR_UPDATE(1,1),NULL_EXPR,0)
1280 DEFFUNC(AttributesM				,"attribute"				,"f=SM"		,PARAMETEREXPR_PRE(0),PARAMETEREXPRM,PARAMETEREXPR_UPDATE(1,16),NULL_EXPR,0)
1281 #undef FUNCTION
1282 
1283 #define	FUNCTION	options
1284 DEFLINKFUNC(Options2			,"option"				,"f=SC",	0)
1285 DEFLINKFUNC(Options3			,"option"				,"f=SN",	0)
1286 DEFLINKFUNC(Options4			,"option"				,"f=SP",	0)
1287 DEFFUNC(OptionsV				,"option"				,"f=SV"		,PARAMETEREXPR_PRE(0),PARAMETEREXPRV,PARAMETEREXPR_UPDATE(1,3),NULL_EXPR,0)
1288 DEFFUNC(Options					,"option"				,"f=SF"		,PARAMETEREXPR_PRE(0),PARAMETEREXPRF,PARAMETEREXPR_UPDATE(1,1),NULL_EXPR,0)
1289 DEFFUNC(OptionsS				,"option"				,"f=SS"		,PARAMETEREXPR_PRE(0),PARAMETEREXPRS,PARAMETEREXPR_UPDATE(1,1),NULL_EXPR,0)
1290 DEFFUNC(OptionsM				,"option"				,"f=SM"		,PARAMETEREXPR_PRE(0),PARAMETEREXPRM,PARAMETEREXPR_UPDATE(1,16),NULL_EXPR,0)
1291 #undef FUNCTION
1292 
1293 #define	FUNCTION	rendererInfo
1294 DEFLINKFUNC(Rendererinfo2			,"rendererinfo"				,"f=SC",	0)
1295 DEFLINKFUNC(Rendererinfo3			,"rendererinfo"				,"f=SN",	0)
1296 DEFLINKFUNC(Rendererinfo4			,"rendererinfo"				,"f=SP",	0)
1297 DEFFUNC(RendererinfoV				,"rendererinfo"				,"f=SV"		,PARAMETEREXPR_PRE(0),PARAMETEREXPRV,PARAMETEREXPR_UPDATE(1,3),NULL_EXPR,0)
1298 DEFFUNC(Rendererinfo				,"rendererinfo"				,"f=SF"		,PARAMETEREXPR_PRE(0),PARAMETEREXPRF,PARAMETEREXPR_UPDATE(1,1),NULL_EXPR,0)
1299 DEFFUNC(RendererinfoS				,"rendererinfo"				,"f=SS"		,PARAMETEREXPR_PRE(0),PARAMETEREXPRS,PARAMETEREXPR_UPDATE(1,1),NULL_EXPR,0)
1300 DEFFUNC(RendererinfoM				,"rendererinfo"				,"f=SM"		,PARAMETEREXPR_PRE(0),PARAMETEREXPRM,PARAMETEREXPR_UPDATE(1,16),NULL_EXPR,0)
1301 #undef FUNCTION
1302 
1303 
1304 
1305 
1306 #ifndef INIT_SHADING
1307 
1308 #define	TEXTUREINFO_PRE(_t)		plBegin(CMapInfoLookup,4);											\
1309 								float				*res;											\
1310 								const char			**op1;											\
1311 								const char			**op2;											\
1312 								_t					op3;											\
1313 								float				found;											\
1314 								float				out[16*2];										\
1315 								const char			*outS;											\
1316 								_t					src = (_t) out;									\
1317 								int					op3sz;											\
1318 																									\
1319 								operand(0,res,float *);												\
1320 								operand(1,op1,const char **);										\
1321 								operand(2,op2,const char **);										\
1322 								operandSize(3,op3,op3sz,_t);										\
1323 																									\
1324 								CTextureInfoBase	*textureInfo;									\
1325 								if ((textureInfo = lookup->map) == NULL) {							\
1326 									osLock(CRenderer::shaderMutex);									\
1327 									lookup->map = textureInfo	=	CRenderer::getTextureInfo(*op1);\
1328 									osUnlock(CRenderer::shaderMutex);								\
1329 								}																	\
1330 																									\
1331 								if (textureInfo == NULL) {											\
1332 									found		=	0;												\
1333 									src			=	op3;	/* prevent writing result */			\
1334 								} else {															\
1335 																									\
1336 									for (int i=0;i<16*2;++i) out[i] = 0;							\
1337 																									\
1338 									found				=	1;										\
1339 																									\
1340 									if (strcmp(*op2,"resolution") == 0) {							\
1341 										textureInfo->getResolution(out);							\
1342 									} else if (strcmp(*op2,"type") == 0) {							\
1343 										outS		=	textureInfo->getTextureType();				\
1344 										src			=	(_t) &outS;									\
1345 									} else if (strcmp(*op2,"channels") == 0) {						\
1346 										out[0]		=	(float) textureInfo->getNumChannels();		\
1347 									} else if (strcmp(*op2,"viewingmatrix") == 0) {					\
1348 										found		= (float) textureInfo->getViewMatrix(out);		\
1349 									} else if (strcmp(*op2,"projectionmatrix") == 0) {				\
1350 										found		= (float) textureInfo->getProjectionMatrix(out);\
1351 									} else if (strcmp(*op2,"exists") == 0) {						\
1352 										src			=	op3;	/* prevent writing result */		\
1353 									} else {														\
1354 										found	=	0;												\
1355 										src		=	op3;	/* prevent writing result */			\
1356 									}																\
1357 								}
1358 
1359 #define	TEXTUREINFOF			*res		=	found;												\
1360 								*op3		=	src[0];												\
1361 								if (op3sz > 1) op3[1]		=	src[1];
1362 
1363 #define	TEXTUREINFOS			*res		=	found;												\
1364 								*op3		=	src[0];
1365 
1366 #define	TEXTUREINFOV			*res		=	found;												\
1367 								op3[0]		=	src[0];												\
1368 								op3[1]		=	src[1];												\
1369 								op3[2]		=	src[2];
1370 
1371 #define	TEXTUREINFOM			*res		=	found;												\
1372 								op3[0]		=	src[0];												\
1373 								op3[1]		=	src[1];												\
1374 								op3[2]		=	src[2];												\
1375 								op3[3]		=	src[3];												\
1376 								op3[4]		=	src[4];												\
1377 								op3[5]		=	src[5];												\
1378 								op3[6]		=	src[6];												\
1379 								op3[7]		=	src[7];												\
1380 								op3[8]		=	src[8];												\
1381 								op3[9]		=	src[9];												\
1382 								op3[10]		=	src[10];											\
1383 								op3[11]		=	src[11];											\
1384 								op3[12]		=	src[12];											\
1385 								op3[13]		=	src[13];											\
1386 								op3[14]		=	src[14];											\
1387 								op3[15]		=	src[15];
1388 
1389 
1390 #define	TEXTUREINFO_UPDATE(__r,__o2)	FUN4EXPR_UPDATE(__r,0,0,__o2)
1391 
1392 #define	TEXTUREINFO_POST		plEnd();
1393 
1394 
1395 #else
1396 
1397 #undef	TEXTUREINFO_PRE
1398 #undef	TEXTUREINFOF
1399 #undef	TEXTUREINFOS
1400 #undef	TEXTUREINFOV
1401 #undef	TEXTUREINFOM
1402 #undef	TEXTUREINFO_UPDATE
1403 #undef	TEXTUREINFO_POST
1404 
1405 #define	TEXTUREINFO_PRE(__t)
1406 #define	TEXTUREINFOF
1407 #define	TEXTUREINFOS
1408 #define	TEXTUREINFOV
1409 #define	TEXTUREINFOM
1410 #define	TEXTUREINFO_UPDATE
1411 #define	TEXTUREINFO_POST
1412 #endif
1413 
1414 DEFLINKFUNC(Textureinfo2			,"textureinfo"				,"f=SSC!",	0)
1415 DEFLINKFUNC(Textureinfo3			,"textureinfo"				,"f=SSN!",	0)
1416 DEFLINKFUNC(Textureinfo4			,"textureinfo"				,"f=SSP!",	0)
1417 DEFFUNC(TextureinfoV				,"textureinfo"				,"f=SSV!"	,TEXTUREINFO_PRE(float *),TEXTUREINFOV,TEXTUREINFO_UPDATE(1,3),TEXTUREINFO_POST,0)
1418 DEFFUNC(Textureinfo					,"textureinfo"				,"f=SSF!"	,TEXTUREINFO_PRE(float *),TEXTUREINFOF,TEXTUREINFO_UPDATE(1,op3sz),TEXTUREINFO_POST,0)
1419 DEFFUNC(TextureinfoS				,"textureinfo"				,"f=SSS!"	,TEXTUREINFO_PRE(char **),TEXTUREINFOS,TEXTUREINFO_UPDATE(1,1),TEXTUREINFO_POST,0)
1420 DEFFUNC(TextureinfoM				,"textureinfo"				,"f=SSM!"	,TEXTUREINFO_PRE(float *),TEXTUREINFOM,TEXTUREINFO_UPDATE(1,16),TEXTUREINFO_POST,0)
1421 
1422 
1423 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1424 // shadername	"s="
1425 #define SHADERNAMEEXPR_PRE	char	**res;								\
1426 							operand(0,res,char **);
1427 
1428 #define SHADERNAMEEXPR		*res	=	(char *) currentShader->name;
1429 
1430 DEFFUNC(ShaderName				,"shadername"					,"s="		,SHADERNAMEEXPR_PRE,SHADERNAMEEXPR,FUN1EXPR_UPDATE(1),NULL_EXPR,0)
1431 
1432 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1433 // shadername	"s=s"
1434 #ifndef INIT_SHADING
1435 #define SHADERNAMESEXPR_PRE	char	**res,**op;								\
1436 							operand(0,res,char **);							\
1437 							operand(1,op,char **);
1438 
1439 #define SHADERNAMESEXPR		*res	=	(char *) shaderName(*op);
1440 #else
1441 #undef SHADERNAMESEXPR_PRE
1442 #undef SHADERNAMESEXPR
1443 #define SHADERNAMESEXPR_PRE
1444 #define SHADERNAMESEXPR
1445 #endif
1446 
1447 DEFFUNC(ShaderNames				,"shadername"					,"s=s"		,SHADERNAMESEXPR_PRE,SHADERNAMESEXPR,FUN2EXPR_UPDATE(1,1),NULL_EXPR,0)
1448 
1449 
1450 
1451 
1452 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1453 //
1454 //	Texture - Environment - Shadow mapping macros
1455 //
1456 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1457 
1458 
1459 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1460 // texture	"f=SFff"
1461 #ifndef INIT_SHADING
1462 #define	TEXTUREFEXPR_PRE		float			*res;															\
1463 								const float		*s,*t;															\
1464 								const float		*op2;															\
1465 								/* Begin the parameter list */													\
1466 								plBegin(CTextureLookup,5);														\
1467 								/* Fetch the parameters as usual */												\
1468 								operand(0,res,float *);															\
1469 								operand(2,op2,const float *);													\
1470 								operand(3,s,const float *);														\
1471 								operand(4,t,const float *);														\
1472 								/* Get the texture */															\
1473 								CTexture	*tex;																\
1474 								if ((tex = lookup->map) == NULL) {												\
1475 									const char		**op1;														\
1476 									operand(1,op1,const char **);												\
1477 									osLock(CRenderer::shaderMutex);												\
1478 									lookup->map = tex	=	CRenderer::getTexture(*op1);						\
1479 									osUnlock(CRenderer::shaderMutex);											\
1480 								}																				\
1481 								int				i;																\
1482 								float			*dsdu		=	(float *) ralloc(numVertices*4*sizeof(float),threadMemory);	\
1483 								float			*dsdv		=	dsdu + numVertices;								\
1484 								float			*dtdu		=	dsdv + numVertices;								\
1485 								float			*dtdv		=	dtdu + numVertices;								\
1486 								float			cs[4],ct[4];													\
1487 								const float		swidth		=	(scratch->textureParams.width == 0 ? scratch->textureParams.swidth : scratch->textureParams.width);	\
1488 								const float		twidth		=	(scratch->textureParams.width == 0 ? scratch->textureParams.twidth : scratch->textureParams.width);	\
1489 								const float		*du			=	varying[VARIABLE_DU];							\
1490 								const float		*dv			=	varying[VARIABLE_DV];							\
1491 																												\
1492 								scratch->textureParams.filter	=	lookup->filter;								\
1493 																												\
1494 								duFloat(dsdu,s);																\
1495 								duFloat(dtdu,t);																\
1496 								dvFloat(dsdv,s);																\
1497 								dvFloat(dtdv,t);																\
1498 																												\
1499 								i	=	0;
1500 
1501 #define	TEXTUREFEXPR			plReady();																		\
1502 								cs[0]		=	s[i];															\
1503 								cs[1]		=	s[i] + dsdu[i]*du[i]*swidth;									\
1504 								cs[2]		=	s[i] + dsdv[i]*dv[i]*swidth;									\
1505 								cs[3]		=	s[i] + (dsdu[i]*du[i] + dsdv[i]*dv[i])*swidth;					\
1506 								ct[0]		=	t[i];															\
1507 								ct[1]		=	t[i] + dtdu[i]*du[i]*twidth;									\
1508 								ct[2]		=	t[i] + dtdv[i]*dv[i]*twidth;									\
1509 								ct[3]		=	t[i] + (dtdu[i]*du[i] + dtdv[i]*dv[i])*twidth;					\
1510 								vector	tmp;																	\
1511 								tex->lookup4(tmp,cs,ct,this);													\
1512 								res[i]		=	tmp[int(*op2)&3];
1513 
1514 #define	TEXTUREFEXPR_UPDATE		++i;	plStep();
1515 
1516 #define	TEXTUREFEXPR_POST		plEnd();
1517 #else
1518 #define	TEXTUREFEXPR_PRE
1519 #define	TEXTUREFEXPR
1520 #define	TEXTUREFEXPR_UPDATE
1521 #define	TEXTUREFEXPR_POST
1522 #endif
1523 
1524 DEFFUNC(TextureFloat			,"texture"					,"f=SFff!"		,TEXTUREFEXPR_PRE,TEXTUREFEXPR,TEXTUREFEXPR_UPDATE,TEXTUREFEXPR_POST,PARAMETER_DPDU | PARAMETER_DPDV | PARAMETER_DU | PARAMETER_DV | PARAMETER_DERIVATIVE)
1525 
1526 
1527 
1528 
1529 
1530 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1531 // texture	"c=SFff"
1532 #ifndef INIT_SHADING
1533 
1534 #define	TEXTURECEXPR			plReady();																		\
1535 								cs[0]		=	s[i];															\
1536 								cs[1]		=	s[i] + dsdu[i]*du[i]*swidth;											\
1537 								cs[2]		=	s[i] + dsdv[i]*dv[i]*swidth;											\
1538 								cs[3]		=	s[i] + (dsdu[i]*du[i] + dsdv[i]*dv[i])*swidth;								\
1539 								ct[0]		=	t[i];															\
1540 								ct[1]		=	t[i] + dtdu[i]*du[i]*twidth;											\
1541 								ct[2]		=	t[i] + dtdv[i]*dv[i]*twidth;											\
1542 								ct[3]		=	t[i] + (dtdu[i]*du[i] + dtdv[i]*dv[i])*twidth;								\
1543 								tex->lookup4(res,cs,ct,this);
1544 
1545 #define	TEXTURECEXPR_UPDATE		++i;	res	+=	3;	plStep();
1546 
1547 #define	TEXTURECEXPR_POST		plEnd();
1548 
1549 #else
1550 #define	TEXTURECEXPR_PRE
1551 #define	TEXTURECEXPR
1552 #define	TEXTURECEXPR_UPDATE
1553 #define	TEXTURECEXPR_POST
1554 #endif
1555 
1556 DEFFUNC(TextureColor			,"texture"					,"c=SFff!"		,TEXTUREFEXPR_PRE,TEXTURECEXPR,TEXTURECEXPR_UPDATE,TEXTURECEXPR_POST,PARAMETER_DPDU | PARAMETER_DPDV | PARAMETER_DU | PARAMETER_DV | PARAMETER_DERIVATIVE)
1557 
1558 #undef	TEXTURECEXPR_PRE
1559 #undef	TEXTURECEXPR
1560 #undef	TEXTURECEXPR_UPDATE
1561 #undef	TEXTURECEXPR_POST
1562 #undef	TEXTUREFEXPR_PRE
1563 #undef	TEXTUREFEXPR
1564 #undef	TEXTUREFEXPR_UPDATE
1565 #undef	TEXTUREFEXPR_POST
1566 
1567 
1568 
1569 
1570 
1571 
1572 
1573 
1574 
1575 
1576 
1577 
1578 
1579 
1580 
1581 
1582 
1583 
1584 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1585 // texture	"f=SFffffffff"
1586 #ifndef INIT_SHADING
1587 #define	TEXTUREFFULLEXPR_PRE	/* Begin the parameter list */													\
1588 								plBegin(CTextureLookup,11);														\
1589 								/* Fetch the parameters as usual */												\
1590 								float			*res;															\
1591 								const float		*op2,*op3,*op4,*op5,*op6,*op7,*op8,*op9,*op10;					\
1592 								float			cs[4],ct[4];													\
1593 								operand(0,res,float *);															\
1594 								operand(2,op2,const float *);													\
1595 								operand(3,op3,const float *);													\
1596 								operand(4,op4,const float *);													\
1597 								operand(5,op5,const float *);													\
1598 								operand(6,op6,const float *);													\
1599 								operand(7,op7,const float *);													\
1600 								operand(8,op8,const float *);													\
1601 								operand(9,op9,const float *);													\
1602 								operand(10,op10,const float *);													\
1603 								/* Get the texture */															\
1604 								CTexture	*tex;																\
1605 								if ((tex = lookup->map) == NULL) {												\
1606 									const char		**op1;														\
1607 									operand(1,op1,const char **);												\
1608 									osLock(CRenderer::shaderMutex);												\
1609 									lookup->map = tex	=	CRenderer::getTexture(*op1);						\
1610 									osUnlock(CRenderer::shaderMutex);											\
1611 								}																				\
1612 								scratch->textureParams.filter	=	lookup->filter;
1613 
1614 
1615 #define	TEXTUREFFULLEXPR		plReady();																		\
1616 								cs[0]		=	*op3;															\
1617 								cs[1]		=	*op5;															\
1618 								cs[2]		=	*op7;															\
1619 								cs[3]		=	*op9;															\
1620 								ct[0]		=	*op4;															\
1621 								ct[1]		=	*op6;															\
1622 								ct[2]		=	*op8;															\
1623 								ct[3]		=	*op10;															\
1624 								vector	tmp;																	\
1625 								tex->lookup4(tmp,cs,ct,this);													\
1626 								*res		=	tmp[0];
1627 
1628 #define	TEXTUREFFULLEXPR_UPDATE	++res;																			\
1629 								++op3;																			\
1630 								++op4;																			\
1631 								++op5;																			\
1632 								++op6;																			\
1633 								++op7;																			\
1634 								++op8;																			\
1635 								++op9;																			\
1636 								++op10;																			\
1637 								plStep();
1638 
1639 
1640 #define	TEXTUREFFULLEXPR_POST	plEnd();
1641 
1642 #else
1643 #define	TEXTUREFFULLEXPR_PRE
1644 #define	TEXTUREFFULLEXPR
1645 #define	TEXTUREFFULLEXPR_UPDATE
1646 #define	TEXTUREFFULLEXPR_POST
1647 #endif
1648 
1649 DEFFUNC(TextureFloatFull			,"texture"				,"f=SFffffffff!"		,TEXTUREFFULLEXPR_PRE,TEXTUREFFULLEXPR,TEXTUREFFULLEXPR_UPDATE,TEXTUREFFULLEXPR_POST,0)
1650 
1651 
1652 
1653 
1654 
1655 
1656 
1657 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1658 // texture	"c=SFffffffff"
1659 #ifndef INIT_SHADING
1660 #define	TEXTURECFULLEXPR		plReady();																		\
1661 								cs[0]		=	*op3;															\
1662 								cs[1]		=	*op5;															\
1663 								cs[2]		=	*op7;															\
1664 								cs[3]		=	*op9;															\
1665 								ct[0]		=	*op4;															\
1666 								ct[1]		=	*op6;															\
1667 								ct[2]		=	*op8;															\
1668 								ct[3]		=	*op10;															\
1669 								tex->lookup4(res,cs,ct,this);
1670 
1671 #define	TEXTURECFULLEXPR_UPDATE	res	+=	3;																		\
1672 								++op3;																			\
1673 								++op4;																			\
1674 								++op5;																			\
1675 								++op6;																			\
1676 								++op7;																			\
1677 								++op8;																			\
1678 								++op9;																			\
1679 								++op10;																			\
1680 								plStep();
1681 
1682 
1683 #define	TEXTURECFULLEXPR_POST	plEnd();
1684 
1685 #else
1686 #define	TEXTURECFULLEXPR_PRE
1687 #define	TEXTURECFULLEXPR
1688 #define	TEXTURECFULLEXPR_UPDATE
1689 #define	TEXTURECFULLEXPR_POST
1690 #endif
1691 
1692 DEFFUNC(TextureColorFull			,"texture"				,"c=SFffffffff!"		,TEXTUREFFULLEXPR_PRE,TEXTURECFULLEXPR,TEXTURECFULLEXPR_UPDATE,TEXTURECFULLEXPR_POST,0)
1693 
1694 #undef	TEXTURECFULLEXPR_PRE
1695 #undef	TEXTURECFULLEXPR
1696 #undef	TEXTURECFULLEXPR_UPDATE
1697 #undef	TEXTURECFULLEXPR_POST
1698 #undef	TEXTUREFFULLEXPR_PRE
1699 #undef	TEXTUREFFULLEXPR
1700 #undef	TEXTUREFFULLEXPR_UPDATE
1701 #undef	TEXTUREFFULLEXPR_POST
1702 
1703 
1704 
1705 
1706 
1707 
1708 
1709 
1710 
1711 
1712 
1713 
1714 
1715 
1716 
1717 
1718 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1719 //
1720 //	Environment / Shadow mapping macros
1721 //
1722 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1723 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1724 // environment	"f=SFv"
1725 #ifndef INIT_SHADING
1726 #define	ENVIRONMENTEXPR_PRE(__name)																					\
1727 								/* Begin the parameter list */														\
1728 								plBegin(CEnvironmentLookup,4);														\
1729 								float			*res;																\
1730 								const char		**op1;																\
1731 								const float		*op2;																\
1732 								/* Fetch the parameters as usual */													\
1733 								operand(0,res,float *);																\
1734 								operand(1,op1,const char **);														\
1735 								operand(2,op2,const float *);														\
1736 								/* Get the texture */																\
1737 								CEnvironment	*tex = NULL;														\
1738 								if ((strcmp(*op1,"raytrace") != 0) && (strcmp(*op1,__name) != 0)) {					\
1739 									if ((tex = lookup->map) == NULL) {												\
1740 										osLock(CRenderer::shaderMutex);												\
1741 										lookup->map = tex	=	CRenderer::getEnvironment(*op1);					\
1742 										osUnlock(CRenderer::shaderMutex);											\
1743 									}																				\
1744 								}																					\
1745 								CTraceLocation	*rays;																\
1746 								int				numRays;															\
1747 								const float		*P,*N;																\
1748 								float			*dPdu,*dPdv;														\
1749 								if (tex == NULL) {																	\
1750 									rays	=	(CTraceLocation *) ralloc(currentShadingState->numVertices*sizeof(CTraceLocation),threadMemory);	\
1751 									P		=	varying[VARIABLE_P];												\
1752 									N		=	varying[VARIABLE_N];												\
1753 									dPdu	=	varying[VARIABLE_DPDU];												\
1754 									dPdv	=	varying[VARIABLE_DPDV];												\
1755 									numRays	=	0;																	\
1756 								}																					\
1757 																													\
1758 								const float		*D;																	\
1759 								float			*dDdu		=	(float *) ralloc(numVertices*6*sizeof(float),threadMemory);	\
1760 								float			*dDdv		=	dDdu + numVertices*3;								\
1761 								const float		*du			=	varying[VARIABLE_DU];								\
1762 								const float		*dv			=	varying[VARIABLE_DV];								\
1763 								const float		*time		=	varying[VARIABLE_TIME];								\
1764 								const float		swidth		=	(scratch->textureParams.width == 0 ? scratch->textureParams.swidth : scratch->textureParams.width);	\
1765 								const float		twidth		=	(scratch->textureParams.width == 0 ? scratch->textureParams.twidth : scratch->textureParams.width);	\
1766 								operand(3,D,const float *);															\
1767 																													\
1768 								scratch->textureParams.filter				=	lookup->filter;						\
1769 																													\
1770 								duVector(dDdu,D);																	\
1771 								dvVector(dDdv,D);
1772 
1773 #define	ENVIRONMENTEXPR(__float)																					\
1774 								plReady();																			\
1775 								if (tex == NULL) {																	\
1776 									rays->res	=	res;															\
1777 									movvv(rays->D,D);																\
1778 									mulvf(rays->dDdu,dDdu,(*du)*swidth);											\
1779 									mulvf(rays->dDdv,dDdv,(*dv)*twidth);											\
1780 									movvv(rays->P,P);																\
1781 									mulvf(rays->dPdu,dPdu,(*du)*swidth);											\
1782 									mulvf(rays->dPdv,dPdv,(*dv)*twidth);											\
1783 									rays->coneAngle		=	max(scratch->traceParams.coneAngle,scratch->textureParams.blur);	\
1784 									rays->numSamples	=	(int) scratch->traceParams.samples;						\
1785 									rays->bias			=	scratch->traceParams.bias;								\
1786 									rays->sampleBase	=	scratch->traceParams.sampleBase;						\
1787 									rays->maxDist		=	scratch->traceParams.maxDist;							\
1788 									rays->time			=	*time;													\
1789 									++rays;																			\
1790 									++numRays;																		\
1791 								} else {																			\
1792 									vector	D0,D1,D2,D3;															\
1793 									mulvf(dDdu,(*du)*swidth*0.5f);													\
1794 									mulvf(dDdv,(*dv)*twidth*0.5f);													\
1795 									subvv(D0,D,dDdu); subvv(D0,dDdv);												\
1796 									addvv(D1,D,dDdu); subvv(D1,dDdv);												\
1797 									subvv(D2,D,dDdu); addvv(D2,dDdv);												\
1798 									addvv(D3,D,dDdu); addvv(D3,dDdv);												\
1799 									if (__float) {																	\
1800 										vector	color;																\
1801 										tex->lookup(color,D0,D1,D2,D3,this);										\
1802 										*res	=	color[0];														\
1803 									} else {																		\
1804 										tex->lookup(res,D0,D1,D2,D3,this);											\
1805 									}																				\
1806 								}
1807 
1808 #define ENVIRONMENTEXPR_UPDATE(__n)																					\
1809 								res			+=	__n;																\
1810 								D			+=	3;																	\
1811 								dDdu		+=	3;																	\
1812 								dDdv		+=	3;																	\
1813 								++du;																				\
1814 								++dv;																				\
1815 								++time;																				\
1816 								if (tex == NULL) {																	\
1817 									P		+=	3;																	\
1818 									N		+=	3;																	\
1819 									dPdu	+=	3;																	\
1820 									dPdv	+=	3;																	\
1821 								}																					\
1822 								plStep();
1823 
1824 
1825 
1826 #define ENVIRONMENTEXPR_POST(__float)																				\
1827 								if ((tex == NULL) && (numRays > 0))	{												\
1828 									rays	-=	numRays;															\
1829 									traceReflection(numRays,rays,FALSE);											\
1830 									if (__float) {																	\
1831 										for (int i=numRays;i>0;--i,++rays) {										\
1832 											*(rays->res)	=	(rays->C[0] + rays->C[1] + rays->C[2]) / 3.0f;		\
1833 										}																			\
1834 									} else {																		\
1835 										for (int i=numRays;i>0;--i,++rays) movvv(rays->res,rays->C);				\
1836 									}																				\
1837 								}																					\
1838 								plEnd();
1839 
1840 #else
1841 #define	ENVIRONMENTEXPR_PRE
1842 #define	ENVIRONMENTEXPR
1843 #define	ENVIRONMENTEXPR_UPDATE
1844 #define	ENVIRONMENTEXPR_POST(__float)
1845 #endif
1846 
1847 DEFSHORTFUNC(EnvironmentFloat			,"environment"				,"f=SFv!"		,ENVIRONMENTEXPR_PRE("reflection"),ENVIRONMENTEXPR(TRUE),ENVIRONMENTEXPR_UPDATE(1),ENVIRONMENTEXPR_POST(TRUE),PARAMETER_DPDU | PARAMETER_DPDV | PARAMETER_DU | PARAMETER_DV | PARAMETER_TIME | PARAMETER_DERIVATIVE)
1848 DEFSHORTFUNC(EnvironmentColor			,"environment"				,"c=SFv!"		,ENVIRONMENTEXPR_PRE("reflection"),ENVIRONMENTEXPR(FALSE),ENVIRONMENTEXPR_UPDATE(3),ENVIRONMENTEXPR_POST(FALSE),PARAMETER_DPDU | PARAMETER_DPDV | PARAMETER_DU | PARAMETER_DV | PARAMETER_TIME | PARAMETER_DERIVATIVE)
1849 
1850 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1851 // shadow	"f=Sfv"
1852 #ifndef INIT_SHADING
1853 
1854 
1855 // Note: we are swapping dDdu and dDdv with dPdu and dPdv here, because
1856 // the ENVIRONMENT_PRE macro always calculates the dD differentials.
1857 // It is also very impartant that we supply dPdu and dPdv so the ray differentials
1858 // are correct or otherwise we waste time overtesselating
1859 
1860 #define	SHADOWEXPR_PRE			ENVIRONMENTEXPR_PRE("shadow");														\
1861 								const float	*L	=	varying[VARIABLE_L];											\
1862 								if (tex == NULL) {																	\
1863 									float *tmp	= 	(float*) ralloc(currentShadingState->numVertices*sizeof(float)*9,threadMemory);	\
1864 									dPdu		=	tmp		+ currentShadingState->numVertices*3;					\
1865 									dPdv		=	dPdu	+ currentShadingState->numVertices*3;					\
1866 									for(int v=0;v<currentShadingState->numVertices*3;v+=3) {						\
1867 										subvv(tmp+v,D+v,L+v);														\
1868 									}																				\
1869 									duVector(dPdu,tmp);																\
1870 									dvVector(dPdv,tmp);																\
1871 								}
1872 
1873 
1874 #define	SHADOWEXPR(__float)		plReady();																			\
1875 								if (tex == NULL) {																	\
1876 									rays->res	=	res;															\
1877 									movvv(rays->P,D);																\
1878 									mulvf(rays->dPdu,dDdu,(*du)*swidth);											\
1879 									mulvf(rays->dPdv,dDdv,(*dv)*twidth);											\
1880 									subvv(rays->D,D,L);																\
1881 									mulvf(rays->dDdu,dPdu,(*du)*swidth);											\
1882 									mulvf(rays->dDdv,dPdv,(*dv)*twidth);											\
1883 									rays->coneAngle		=	max(scratch->traceParams.coneAngle,scratch->textureParams.blur);	\
1884 									rays->sampleBase	=	scratch->traceParams.sampleBase;						\
1885 									rays->numSamples	=	(int) scratch->traceParams.samples;						\
1886 									rays->bias			=	scratch->traceParams.bias;								\
1887 									rays->maxDist		=	scratch->traceParams.maxDist;							\
1888 									rays->time			=	*time;													\
1889 									++rays;																			\
1890 									++numRays;																		\
1891 								} else {																			\
1892 									vector	D0,D1,D2,D3;															\
1893 									mulvf(dDdu,(*du)*swidth*0.5f);													\
1894 									mulvf(dDdv,(*dv)*twidth*0.5f);													\
1895 									subvv(D0,D,dDdu); subvv(D0,dDdv);												\
1896 									addvv(D1,D,dDdu); subvv(D1,dDdv);												\
1897 									subvv(D2,D,dDdu); addvv(D2,dDdv);												\
1898 									addvv(D3,D,dDdu); addvv(D3,dDdv);												\
1899 									if (__float) {																	\
1900 										vector	color;																\
1901 										tex->lookup(color,D0,D1,D2,D3,this);										\
1902 										*res	=	(color[0] + color[1] + color[2])/3.0f;							\
1903 									} else {																		\
1904 										tex->lookup(res,D0,D1,D2,D3,this);											\
1905 									}																				\
1906 								}
1907 
1908 #define SHADOWEXPR_UPDATE(__n)	res			+=__n;																	\
1909 								D			+=	3;																	\
1910 								dDdu		+=	3;																	\
1911 								dDdv		+=	3;																	\
1912 								++du;																				\
1913 								++dv;																				\
1914 								++time;																				\
1915 								L			+=	3;																	\
1916 								if (tex == NULL) {																	\
1917 									dPdu	+=	3;																	\
1918 									dPdv	+=	3;																	\
1919 								}																					\
1920 								plStep();
1921 
1922 
1923 #define SHADOWEXPR_POST(__float)																					\
1924 							if ((tex == NULL) && (numRays > 0))	{													\
1925 								rays	-=	numRays;																\
1926 								traceTransmission(numRays,rays,FALSE);												\
1927 								if (__float) {																		\
1928 									for (int i=numRays;i>0;--i,++rays) {											\
1929 										*(rays->res)	=	1 - (rays->C[0] + rays->C[1] + rays->C[2]) / 3.0f;		\
1930 									}																				\
1931 								} else {																			\
1932 									for (int i=numRays;i>0;--i,++rays) {											\
1933 										res		=	rays->res;														\
1934 										res[0]	=	1 - rays->C[0];													\
1935 										res[1]	=	1 - rays->C[1];													\
1936 										res[2]	=	1 - rays->C[2];													\
1937 									}																				\
1938 								}																					\
1939 							}																						\
1940 							plEnd();
1941 
1942 #else
1943 #define	SHADOWEXPR_PRE
1944 #define	SHADOWEXPR
1945 #define	SHADOWEXPR_UPDATE
1946 #define	SHADOWEXPR_POST(__float)
1947 #endif
1948 
1949 DEFSHORTFUNC(ShadowFloat			,"shadow"				,"f=SFp!"		,SHADOWEXPR_PRE,SHADOWEXPR(TRUE),SHADOWEXPR_UPDATE(1),SHADOWEXPR_POST(TRUE),PARAMETER_DU | PARAMETER_DV | PARAMETER_TIME | PARAMETER_DERIVATIVE)
1950 DEFSHORTFUNC(ShadowColor			,"shadow"				,"c=SFp!"		,SHADOWEXPR_PRE,SHADOWEXPR(FALSE),SHADOWEXPR_UPDATE(3),SHADOWEXPR_POST(FALSE),PARAMETER_DU | PARAMETER_DV | PARAMETER_TIME | PARAMETER_DERIVATIVE)
1951 
1952 #undef	ENVIRONMENTEXPR_PRE
1953 #undef	ENVIRONMENTEXPR
1954 #undef	ENVIRONMENTEXPR_UPDATE
1955 #undef	ENVIRONMENTEXPR_POST
1956 
1957 #undef	SHADOWEXPR_PRE
1958 #undef	SHADOWEXPR
1959 #undef	SHADOWEXPR_UPDATE
1960 #undef	SHADOWEXPR_POST
1961 
1962 
1963 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1964 // filterstep "f=ff!"
1965 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1966 #ifndef INIT_SHADING
1967 #define	FILTERSTEP2EXPR_PRE		FUN3EXPR_PRE																		\
1968 								plBegin(CFilterLookup,3);															\
1969 								float			*dsdu	=	(float *) ralloc(numVertices*2*sizeof(float),threadMemory);	\
1970 								float			*dsdv	=	dsdu + numVertices;										\
1971 								float			*fwidth	=	dsdu;													\
1972 								const float		*du		=	varying[VARIABLE_DU];									\
1973 								const float		*dv		=	varying[VARIABLE_DV];									\
1974 								const float		*s		=	op2;													\
1975 																													\
1976 								duFloat(dsdu,s);																	\
1977 								dvFloat(dsdv,s);																	\
1978 								for (int i=0;i<numVertices;++i) {													\
1979 									dsdu[i]		=	fabs(dsdu[i]*du[i]);											\
1980 									dsdv[i]		=	fabs(dsdv[i]*dv[i]);											\
1981 									fwidth[i]	=	scratch->textureParams.width*max(dsdu[i] + dsdv[i],C_EPSILON);	\
1982 								}
1983 
1984 #define	FILTERSTEP2EXPR			plReady();																			\
1985 								*res	=	lookup->filter(*op2,*op1,fwidth[0]);
1986 
1987 
1988 #define	FILTERSTEP2EXPR_UPDATE	plStep();																			\
1989 								FUN3EXPR_UPDATE(1,1,1)																\
1990 								++fwidth;
1991 
1992 #else
1993 #define	FILTERSTEP2EXPR_PRE
1994 #define	FILTERSTEP2EXPR
1995 #define	FILTERSTEP2EXPR_UPDATE
1996 #endif
1997 
1998 DEFFUNC(FilterStep2			,"filterstep"				,"f=ff!"		,FILTERSTEP2EXPR_PRE,FILTERSTEP2EXPR,FUN3EXPR_UPDATE(1,1,1),NULL_EXPR,PARAMETER_DPDU | PARAMETER_DPDV | PARAMETER_DU | PARAMETER_DV | PARAMETER_DERIVATIVE)
1999 
2000 
2001 #undef	FILTERSTEP2EXPR_PRE
2002 #undef	FILTERSTEP2EXPR
2003 #undef	FILTERSTEP2EXPR_UPDATE
2004 
2005 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2006 // filterstep "f=fff!"
2007 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2008 #ifndef INIT_SHADING
2009 #define	FILTERSTEP3EXPR_PRE	FUN4EXPR_PRE																		\
2010 							plBegin(CFilterLookup,4);
2011 
2012 #define	FILTERSTEP3EXPR		plReady();																			\
2013 							*res	=	lookup->filter(0.5f*(*op2+*op3),*op1,*op3-*op2);
2014 
2015 
2016 #define	FILTERSTEP3EXPR_UPDATE	plStep();	FUN4EXPR_UPDATE(1,1,1,1)
2017 #else
2018 #define	FILTERSTEP3EXPR_PRE
2019 #define	FILTERSTEP3EXPR
2020 #define	FILTERSTEP3EXPR_UPDATE
2021 #endif
2022 
2023 DEFFUNC(FilterStep3			,"filterstep"				,"f=fff!"		,FILTERSTEP3EXPR_PRE,FILTERSTEP3EXPR,FUN4EXPR_UPDATE(1,1,1,1),NULL_EXPR,0)
2024 
2025 
2026 #undef	FILTERSTEP3EXPR_PRE
2027 #undef	FILTERSTEP3EXPR
2028 #undef	FILTERSTEP3EXPR_UPDATE
2029 
2030 
2031 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2032 // bake3d	"f=SSpn!"
2033 #ifndef INIT_SHADING
2034 #define	BAKE3DEXPR_PRE			plBegin(CTexture3dLookup,5);													\
2035 								CTexture3d	*tex;																\
2036 								if ((tex = lookup->map) == NULL) {												\
2037 									const float		*from,*to;													\
2038 									findCoordinateSystem(scratch->texture3dParams.coordsys,from,to);			\
2039 									const char		**op1,**op2;												\
2040 									operand(1,op1,const char **);												\
2041 									operand(2,op2,const char **);												\
2042 									osLock(CRenderer::shaderMutex);												\
2043 									lookup->map = tex	=	CRenderer::getTexture3d(*op1,TRUE,*op2,from,to);	\
2044 									osUnlock(CRenderer::shaderMutex);											\
2045 									tex->resolve(lookup->numChannels,lookup->channelName,lookup->channelEntry,lookup->channelSize);	\
2046 								}																				\
2047 								float			*res;															\
2048 								const float		*op3,*op4;														\
2049 								operand(0,res,float *);															\
2050 								operand(3,op3,const float *);													\
2051 								operand(4,op4,const float *);													\
2052 								int				curU=0,curV=0;													\
2053 								const int		uVerts		=	currentShadingState->numUvertices;				\
2054 								const int		vVerts		=	currentShadingState->numVvertices;				\
2055 								const int		doInterp	=	((scratch->texture3dParams.interpolate == 1.0f) && currentShadingState->numVertices == currentShadingState->numRealVertices);	\
2056 								float			*dest		=	(float *) ralloc(tex->dataSize*sizeof(float),threadMemory);	\
2057 								const float		**channelValues = (const float **) ralloc(lookup->numChannels*sizeof(const float *),threadMemory);	\
2058 								float			*dPdu		=	(float *) ralloc(numVertices*6*sizeof(float),threadMemory);	\
2059 								float			*dPdv		=	dPdu + numVertices*3;							\
2060 								duVector(dPdu,op3);																\
2061 								dvVector(dPdv,op3);																\
2062 								const float		*du			=	varying[VARIABLE_DU];							\
2063 								const float		*dv			=	varying[VARIABLE_DV];							\
2064 																												\
2065 								for (int channel=0;channel<lookup->numChannels;++channel) {						\
2066 									operand(lookup->channelIndex[channel],channelValues[channel],const float *);\
2067 								}																				\
2068 																												\
2069 								vector	P;																		\
2070 								float	radius;
2071 
2072 #define	BAKE3DEXPR				plReady();																		\
2073 								mulvf(dPdu,*du);																\
2074 								mulvf(dPdv,*dv);																\
2075 								if (scratch->texture3dParams.radius > 0) {										\
2076 									radius	=	scratch->texture3dParams.radius*scratch->texture3dParams.radiusScale;							\
2077 								} else {																		\
2078 									radius	=	(lengthv(dPdu) + lengthv(dPdv))*0.5f*scratch->texture3dParams.radiusScale;		\
2079 								}																				\
2080 																												\
2081 								texture3Dflatten(dest,lookup->numChannels,channelValues,lookup->channelEntry,lookup->channelSize);	\
2082 								if (doInterp == FALSE) {														\
2083 									movvv(P,op3);																\
2084 									tex->store(dest,P,op4,radius);												\
2085 								} else if ((curU < uVerts-1) && (curV < vVerts-1)) {							\
2086 									/* skip the end - do not double-bake seams */								\
2087 									P[0]	=	(dPdu[0] + dPdv[0])*0.5f + op3[0];								\
2088 									P[1]	=	(dPdu[1] + dPdv[1])*0.5f + op3[1];								\
2089 									P[2]	=	(dPdu[2] + dPdv[2])*0.5f + op3[2];								\
2090 									tex->store(dest,P,op4,radius);												\
2091 								}																				\
2092 								*res		=	1;
2093 
2094 #define	BAKE3DEXPR_UPDATE		++res;																			\
2095 								op3		+=	3;																	\
2096 								op4		+=	3;																	\
2097 								dPdu	+=	3;																	\
2098 								dPdv	+=	3;																	\
2099 								++du;	++dv;																	\
2100 								++curU;																			\
2101 								plStep();																		\
2102 								if (curU == uVerts) { curV++; curU = 0; }										\
2103 								for (int channel=0;channel<lookup->numChannels;++channel) {						\
2104 									channelValues[channel]	+=	lookup->channelSize[channel];					\
2105 								}
2106 
2107 #define	BAKE3DEXPR_POST			plEnd();
2108 
2109 #else
2110 #define	BAKE3DEXPR_PRE
2111 #define	BAKE3DEXPR
2112 #define	BAKE3DEXPR_UPDATE
2113 #define	BAKE3DEXPR_POST
2114 #endif
2115 
2116 DEFSHORTFUNC(Bake3d			,"bake3d"					,"f=SSpn!"		,BAKE3DEXPR_PRE,BAKE3DEXPR,BAKE3DEXPR_UPDATE,BAKE3DEXPR_POST,PARAMETER_DPDU | PARAMETER_DPDV | PARAMETER_DU | PARAMETER_DV | PARAMETER_DERIVATIVE)
2117 
2118 #undef	BAKE3DEXPR_PRE
2119 #undef	BAKE3DEXPR
2120 #undef	BAKE3DEXPR_UPDATE
2121 #undef	BAKE3DEXPR_POST
2122 
2123 
2124 
2125 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2126 // texture3d	"f=Spn!"
2127 #ifndef INIT_SHADING
2128 #define	TEXTURE3DEXPR_PRE		plBegin(CTexture3dLookup,4);													\
2129 								CTexture3d	*tex;																\
2130 								if ((tex = lookup->map) == NULL) {												\
2131 									const float			*from,*to;												\
2132 									findCoordinateSystem(scratch->texture3dParams.coordsys,from,to);			\
2133 									const char			**op1;													\
2134 									operand(1,op1,const char **);												\
2135 									osLock(CRenderer::shaderMutex);												\
2136 									lookup->map	=	tex	=	CRenderer::getTexture3d(*op1,FALSE,NULL,from,to);	\
2137 									osUnlock(CRenderer::shaderMutex);											\
2138 									tex->resolve(lookup->numChannels,lookup->channelName,lookup->channelEntry,lookup->channelSize);	\
2139 								}																				\
2140 								float				*res;														\
2141 								const float			*op2,*op3;													\
2142 								operand(0,res,float *);															\
2143 								operand(2,op2,const float *);													\
2144 								operand(3,op3,const float *);													\
2145 								float			*dest		=	(float *) ralloc(tex->dataSize*sizeof(float),threadMemory);	\
2146 								float			**channelValues = (float **) ralloc(lookup->numChannels*sizeof(float*),threadMemory);	\
2147 								float			*dPdu		=	(float *) ralloc(numVertices*6*sizeof(float),threadMemory);	\
2148 								float			*dPdv		=	dPdu + numVertices*3;							\
2149 								duVector(dPdu,op2);																\
2150 								dvVector(dPdv,op2);																\
2151 								const float		*du			=	varying[VARIABLE_DU];							\
2152 								const float		*dv			=	varying[VARIABLE_DV];							\
2153 																												\
2154 								for (int channel=0;channel<lookup->numChannels;++channel) {						\
2155 									operand(lookup->channelIndex[channel],channelValues[channel],float *);		\
2156 								}
2157 
2158 #define	TEXTURE3DEXPR			plReady();																		\
2159 								float radius;																	\
2160 								mulvf(dPdu,*du);																\
2161 								mulvf(dPdv,*dv);																\
2162 								if (scratch->texture3dParams.radius > 0) {										\
2163 									radius	=	scratch->texture3dParams.radius*scratch->texture3dParams.radiusScale;				\
2164 								} else {																		\
2165 									radius	=	(lengthv(dPdu) + lengthv(dPdv))*0.5f*scratch->texture3dParams.radiusScale;			\
2166 								}																				\
2167 								tex->lookup(dest,op2,op3,radius);												\
2168 								texture3Dunpack(dest,lookup->numChannels,channelValues,lookup->channelEntry,lookup->channelSize);	\
2169 								*res		=	1;
2170 
2171 #define	TEXTURE3DEXPR_UPDATE	++res;																			\
2172 								op2		+=	3;																	\
2173 								op3		+=	3;																	\
2174 								dPdu	+=	3;																	\
2175 								dPdv	+=	3;																	\
2176 								++du;	++dv;																	\
2177 								plStep();																		\
2178 								for (int channel=0;channel<lookup->numChannels;++channel) {						\
2179 									channelValues[channel]	+=	lookup->channelSize[channel];					\
2180 								}
2181 
2182 #define	TEXTURE3DEXPR_POST		plEnd();
2183 #else
2184 #define	TEXTURE3DEXPR_PRE
2185 #define	TEXTURE3DEXPR
2186 #define	TEXTURE3DEXPR_UPDATE
2187 #define	TEXTURE3DEXPR_POST
2188 #endif
2189 
2190 DEFFUNC(Texture3d			,"texture3d"					,"f=Spn!"		,TEXTURE3DEXPR_PRE,TEXTURE3DEXPR,TEXTURE3DEXPR_UPDATE,TEXTURE3DEXPR_POST,PARAMETER_DPDU | PARAMETER_DPDV | PARAMETER_DU | PARAMETER_DV | PARAMETER_DERIVATIVE)
2191 
2192 #undef	TEXTURE3DEXPR_PRE
2193 #undef	TEXTURE3DEXPR
2194 #undef	TEXTURE3DEXPR_UPDATE
2195 #undef	TEXTURE3DEXPR_POST
2196 
2197 
2198 ///////////////////////////////////////////////////
2199 //
2200 //	FIXME : missing functions :
2201 //	bump
2202 
2203 
2204 #include "giFunctions.h"
2205 
2206