FreeWRL / FreeX3D 4.3.0
RenderTextures.c
1/*
2
3
4Texturing during Runtime
5texture enabling - works for single texture, for multitexture.
6
7*/
8
9
10/****************************************************************************
11 This file is part of the FreeWRL/FreeX3D Distribution.
12
13 Copyright 2009 CRC Canada. (http://www.crc.gc.ca)
14
15 FreeWRL/FreeX3D is free software: you can redistribute it and/or modify
16 it under the terms of the GNU Lesser Public License as published by
17 the Free Software Foundation, either version 3 of the License, or
18 (at your option) any later version.
19
20 FreeWRL/FreeX3D is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU General Public License for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with FreeWRL/FreeX3D. If not, see <http://www.gnu.org/licenses/>.
27****************************************************************************/
28
29
30
31#include <config.h>
32#include <system.h>
33#include <display.h>
34#include <internal.h>
35
36#include <libFreeWRL.h>
37
38#include "../vrml_parser/Structs.h"
39#include "../main/headers.h"
40#include "../opengl/OpenGL_Utils.h"
41#include "../scenegraph/Component_Shape.h"
42#include "../scenegraph/RenderFuncs.h"
43#include "../scenegraph/LinearAlgebra.h"
44
45#include "Textures.h"
46#include "Material.h"
47
48
50int multitex_mode[2];
51int multitex_source[2];
52int multitex_function;
53};
54
55typedef struct pRenderTextures{
56 struct multiTexParams textureParameterStack[MAX_MULTITEXTURE];
58
59void *RenderTextures_constructor(){
60 void *v = MALLOCV(sizeof(struct pRenderTextures));
61 memset(v,0,sizeof(struct pRenderTextures));
62 return v;
63}
64void RenderTextures_init(struct tRenderTextures *t){
65 t->prv = RenderTextures_constructor();
66 {
68 /* variables for keeping track of status */
69 t->textureParameterStack = (void *)p->textureParameterStack;
70 }
71}
72
73
74/* function params */
75//static void passedInGenTex(struct textureVertexInfo *genTex);
76
77/* which texture unit are we going to use? is this texture not OFF?? Should we set the
78 background coloUr??? Larry the Cucumber, help! */
79
80static int setActiveTexture (int c, GLfloat thisTransparency, GLint *texUnit, GLint *texMode)
81{
83 ttglobal tg = gglobal();
84 p = (ppRenderTextures)tg->RenderTextures.prv;
85
86 /* which texture unit are we working on? */
87
88 /* tie each fw_TextureX uniform into the correct texture unit */
89
90 /* here we assign the texture unit to a specific number. NOTE: in the current code, this will ALWAYS
91 * be [0] = 0, [1] = 1; etc. */
92 texUnit[c] = c;
93
94#ifdef TEXVERBOSE
95 if (getAppearanceProperties()->currentShaderProperties != NULL) {
96 printf ("setActiveTexture %d, boundTextureStack is %d, sending to uniform %d\n",c,
97 tg->RenderFuncs.boundTextureStack[c],
98 getAppearanceProperties()->currentShaderProperties->TextureUnit[c]);
99 } else {
100 printf ("setActiveTexture %d, boundTextureStack is %d, sending to uniform [NULL--No Shader]\n",c,
101 tg->RenderFuncs.boundTextureStack[c]);
102 }
103#endif
104
105 /* is this a MultiTexture, or just a "normal" single texture? When we
106 * bind_image, we store a pointer for the texture parameters. It is
107 * NULL, possibly different for MultiTextures */
108
109 if (p->textureParameterStack[c].multitex_mode[0] == INT_ID_UNDEFINED) {
110
111 #ifdef TEXVERBOSE
112 printf ("setActiveTexture - simple texture NOT a MultiTexture \n");
113 #endif
114
115 /* should we set the coloUr to 1,1,1,1 so that the material does not show
116 * through a RGB texture?? */
117 /* only do for the first texture if MultiTexturing */
118 if (c == 0) {
119 #ifdef TEXVERBOSE
120 printf ("setActiveTexture - firsttexture \n");
121 #endif
122 texMode[c]= GL_MODULATE;
123 } else {
124 texMode[c]=GL_ADD;
125 }
126
127 } else {
128 /* printf ("muititex source for %d is %d\n",c,tg->RenderTextures.textureParameterStack[c].multitex_source); */
129 if (p->textureParameterStack[c].multitex_source[0] != MTMODE_OFF) {
130 } else {
131 //glDisable(GL_TEXTURE_2D); /* DISABLE_TEXTURES */
132 //return FALSE;
133 // we do OFF right in the shader
134 }
135 }
136
137
138 PRINT_GL_ERROR_IF_ANY("");
139
140 return TRUE;
141}
142
143
144/* lets disable texture transforms here */
145void textureTransform_end(void) {
146 int j;
147 ttglobal tg = gglobal();
148
149#ifdef TEXVERBOSE
150 printf ("start of textureDraw_end\n");
151#endif
152
153 /* DISABLE_TEXTURES */
154 /* setting this ENSURES that items, like the HUD, that are not within the normal
155 rendering path do not try and use textures... */
156 FW_GL_MATRIX_MODE(GL_TEXTURE);
157 for(j=0;j<tg->RenderFuncs.textureStackTop;j++)
158 FW_GL_POP_MATRIX(); //pushed in passedInGenTex
159
160 tg->RenderFuncs.textureStackTop = 0;
161 tg->RenderFuncs.texturenode = NULL;
162 FW_GL_MATRIX_MODE(GL_MODELVIEW);
163}
164
165/* did we have a TextureTransform in the Appearance node? */
166void do_textureTransform (struct X3D_Node *textureNode, int ttnum) {
167
168 /* is this a simple TextureTransform? */
169 if (textureNode->_nodeType == NODE_TextureTransform) {
170 //ConsoleMessage ("do_textureTransform, node is indeed a NODE_TextureTransform");
171 struct X3D_TextureTransform *ttt = (struct X3D_TextureTransform *) textureNode;
172 /* Render transformations according to spec.*/
173 //http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/texturing.html#TextureTransform
174 //specs say 'translate, rotate, then scale'
175 FW_GL_TRANSLATE_F(-((ttt->center).c[0]),-((ttt->center).c[1]), 0); /* 5*/
176 FW_GL_SCALE_F(((ttt->scale).c[0]),((ttt->scale).c[1]),1); /* 4*/
177 FW_GL_ROTATE_RADIANS(ttt->rotation,0,0,1); /* 3*/
178 FW_GL_TRANSLATE_F(((ttt->center).c[0]),((ttt->center).c[1]), 0); /* 2*/
179 FW_GL_TRANSLATE_F(((ttt->translation).c[0]), ((ttt->translation).c[1]), 0); /* 1*/
180 /* is this a MultiTextureTransform? */
181 } else if (textureNode->_nodeType == NODE_MultiTextureTransform) {
182 struct X3D_MultiTextureTransform *mtt = (struct X3D_MultiTextureTransform *) textureNode;
183 if (ttnum < mtt->textureTransform.n) {
184 struct X3D_TextureTransform *ttt = (struct X3D_TextureTransform *) mtt->textureTransform.p[ttnum];
185 /* is this a simple TextureTransform? */
186 if (ttt->_nodeType == NODE_TextureTransform) {
187 /* Render transformations according to spec.*/
188 FW_GL_TRANSLATE_F(-((ttt->center).c[0]),-((ttt->center).c[1]), 0); /* 5*/
189 FW_GL_SCALE_F(((ttt->scale).c[0]),((ttt->scale).c[1]),1); /* 4*/
190 FW_GL_ROTATE_RADIANS(ttt->rotation,0,0,1); /* 3*/
191 FW_GL_TRANSLATE_F(((ttt->center).c[0]),((ttt->center).c[1]), 0); /* 2*/
192 FW_GL_TRANSLATE_F(((ttt->translation).c[0]), ((ttt->translation).c[1]), 0); /* 1*/
193 } else {
194 static int once = 0;
195 if(!once){
196 printf ("MultiTextureTransform expected a textureTransform for texture %d, got %d \n",
197 ttnum, ttt->_nodeType);
198 once = 1;
199 }
200 }
201 } else {
202 static int once = 0;
203 if(!once){
204 printf ("not enough transforms in MultiTextureTransform -will fill with Identity matrix\n");
205 once = 1;
206 }
207 }
208 } else if (textureNode->_nodeType == NODE_TextureTransform3D) {
209 //ConsoleMessage ("do_textureTransform, node is indeed a NODE_TextureTransform");
210 struct X3D_TextureTransform3D *ttt = (struct X3D_TextureTransform3D *) textureNode;
211 /* Render transformations according to spec.*/
212 FW_GL_TRANSLATE_F(-((ttt->center).c[0]),-((ttt->center).c[1]), -((ttt->center).c[2])); /* 5*/
213 FW_GL_SCALE_F(((ttt->scale).c[0]),((ttt->scale).c[1]),((ttt->scale).c[2])); /* 4*/
214 FW_GL_ROTATE_RADIANS(ttt->rotation.c[3], ttt->rotation.c[0],ttt->rotation.c[1],ttt->rotation.c[2]);
215 FW_GL_TRANSLATE_F(((ttt->center).c[0]),((ttt->center).c[1]), ((ttt->center).c[2])); /* 2*/
216 FW_GL_TRANSLATE_F(((ttt->translation).c[0]), ((ttt->translation).c[1]), ((ttt->translation).c[2])); /* 1*/
217 } else if (textureNode->_nodeType == NODE_TextureTransformMatrix3D) {
218 //ConsoleMessage ("do_textureTransform, node is indeed a NODE_TextureTransform");
219 int i;
220 double mat[16];
221 struct X3D_TextureTransformMatrix3D *ttt = (struct X3D_TextureTransformMatrix3D *) textureNode;
222 for(i=0;i<16;i++)
223 mat[i] = (double)ttt->matrix.c[i];
224 FW_GL_SETDOUBLEV(GL_TEXTURE_MATRIX,mat);
225 } else {
226 static int once = 0;
227 if(!once){
228 printf ("expected a textureTransform node, got %d\n",textureNode->_nodeType);
229 once = 1;
230 }
231 }
232
233 //FW_GL_MATRIX_MODE(GL_MODELVIEW);
234}
235
236/***********************************************************************************/
237int isMultiTexture(struct X3D_Node *node){
238 int ret = FALSE;
239 if(node && node->_nodeType == NODE_MultiTexture)
240 ret = TRUE;
241 return ret;
242}
243textureTableIndexStruct_s *getTableTableFromTextureNode(struct X3D_Node *textureNode);
244int isTex3D(struct X3D_Node *node);
245
246#ifdef OLDCODE
247OLDCODE static void passedInGenTex_OLD(struct textureVertexInfo *genTex) {
248OLDCODE int c;
249OLDCODE int i, isStrict, isMulti, isIdentity;
250OLDCODE GLint texUnit[MAX_MULTITEXTURE];
251OLDCODE GLint texMode[MAX_MULTITEXTURE];
252OLDCODE s_shader_capabilities_t *me;
253OLDCODE struct textureVertexInfo *genTexPtr;
254OLDCODE struct X3D_Node *tnode;
255OLDCODE
256OLDCODE ppRenderTextures p;
257OLDCODE ttglobal tg = gglobal();
258OLDCODE p = (ppRenderTextures)tg->RenderTextures.prv;
259OLDCODE tnode = tg->RenderFuncs.texturenode;
260OLDCODE
261OLDCODE me = getAppearanceProperties()->currentShaderProperties;
262OLDCODE
263OLDCODE #ifdef TEXVERBOSE
264OLDCODE printf ("passedInGenTex, using passed in genTex, textureStackTop %d\n",tg->RenderFuncs.textureStackTop);
265OLDCODE printf ("passedInGenTex, cubeFace %d\n",getAppearanceProperties()->cubeFace);
266OLDCODE #endif
267OLDCODE
268OLDCODE FW_GL_MATRIX_MODE(GL_TEXTURE);
269OLDCODE
270OLDCODE //printf ("passedInGenTex, B\n");
271OLDCODE isStrict = 1; //web3d specs say if its a multitexture,
272OLDCODE //and you give it a single textureTransform instead of multitexturetransform
273OLDCODE //it should ignore the singleTextureTransform and use identities.
274OLDCODE //strict: This is a change of functionality for freewrl Aug 31, 2016
275OLDCODE genTexPtr = genTex;
276OLDCODE isIdentity = TRUE;
277OLDCODE for (c=0; c<tg->RenderFuncs.textureStackTop; c++) {
278OLDCODE FW_GL_PUSH_MATRIX(); //POPPED in textureDraw_end
279OLDCODE FW_GL_LOAD_IDENTITY();
280OLDCODE //printf ("passedInGenTex, c=%d\n",c);
281OLDCODE /* are we ok with this texture yet? */
282OLDCODE if (tg->RenderFuncs.boundTextureStack[c]!=0) {
283OLDCODE isMulti = isMultiTexture(tg->RenderFuncs.texturenode);
284OLDCODE //printf ("passedInGenTex, C, boundTextureStack %d\n",tg->RenderFuncs.boundTextureStack[c]);
285OLDCODE if (setActiveTexture(c,getAppearanceProperties()->transparency,texUnit,texMode)) {
286OLDCODE //printf ("passedInGenTex, going to bind to texture %d\n",tg->RenderFuncs.boundTextureStack[c]);
287OLDCODE GLuint texture;
288OLDCODE struct X3D_Node *tt = getThis_textureTransform();
289OLDCODE if (tt!=NULL) {
290OLDCODE int match = FALSE;
291OLDCODE match = isMulti && (tt->_nodeType == NODE_MultiTextureTransform);
292OLDCODE match = match || (!isMulti && (tt->_nodeType != NODE_MultiTextureTransform));
293OLDCODE if(isStrict){
294OLDCODE if(match){
295OLDCODE do_textureTransform(tt,c);
296OLDCODE isIdentity = FALSE;
297OLDCODE }
298OLDCODE }else{
299OLDCODE do_textureTransform(tt,c);
300OLDCODE isIdentity = FALSE;
301OLDCODE }
302OLDCODE }
303OLDCODE //TEXTURE 3D
304OLDCODE if(isTex3D(tnode)){
305OLDCODE textureTableIndexStruct_s *tti = getTableTableFromTextureNode(tnode);
306OLDCODE if(tnode->_nodeType != NODE_ComposedTexture3D){
307OLDCODE //pixelTexture3D, imageTexture3D (but not composedTexture3D which uses textureCount above)
308OLDCODE if(me){
309OLDCODE if(tti){
310OLDCODE glUniform1iv(me->tex3dTiles,3,tti->tiles);
311OLDCODE }
312OLDCODE }
313OLDCODE }
314OLDCODE //all texture3d
315OLDCODE if(tg->RenderFuncs.shapenode && isIdentity && genTexPtr->TC_size < 3){
316OLDCODE //_if_ no TextureTransform3D was explicitly specified for Texture3D,
317OLDCODE //_and_ no textureCoordinate3D or textureCoordinate4D was explicilty specified with the goem node
318OLDCODE //_then_ bounding box of shape, in local coordinates, is used to scale/translate
319OLDCODE //geometry vertices into 0-1 range on each axis for re-use as default texture3D coordinates
320OLDCODE float bbox[6], *bmin, *bmax;
321OLDCODE struct X3D_Node *gn;
322OLDCODE struct X3D_Shape *sn = (struct X3D_Shape *)tg->RenderFuncs.shapenode;
323OLDCODE POSSIBLE_PROTO_EXPANSION(struct X3D_Node *,sn->geometry,gn);
324OLDCODE if(gn){
325OLDCODE //first vec3 is minimum xyz
326OLDCODE bmin = bbox;
327OLDCODE bmax = &bbox[3];
328OLDCODE for(i=0;i<3;i++){
329OLDCODE bmin[i] = gn->_extent[i*2 + 1];
330OLDCODE bmax[i] = gn->_extent[i*2];
331OLDCODE }
332OLDCODE //second vec3 is 1/size - so can be applied directly in vertex shader
333OLDCODE vecdif3f(bmax,bmax,bmin);
334OLDCODE for(i=0;i<3;i++){
335OLDCODE if(bmax[i] != 0.0f)
336OLDCODE bmax[i] = 1.0f/bmax[i];
337OLDCODE else
338OLDCODE bmax[i] = 1.0f;
339OLDCODE }
340OLDCODE //if(fabs(bmin[0]) > 10.0f)
341OLDCODE // printf("bbox shift [%f %f %f] scale [%f %f %f]\n",bmin[0],bmin[1],bmin[2],bmax[0],bmax[1],bmax[2]);
342OLDCODE
343OLDCODE //special default texture transform for 3D textures posing as 2D textures
344OLDCODE
345OLDCODE //the order of applying transform elements seems reversed for texture transforms
346OLDCODE //H: related to order of operands in mat * vec in shader:
347OLDCODE // fw_TexCoord[0] = vec3(fw_TextureMatrix0 *vec4(texcoord,1.0));
348OLDCODE // but sign on elements is what you expect
349OLDCODE //flip z from RHS to LHS in fragment shader plug_tex3d apply
350OLDCODE //printf("default tt\n");
351OLDCODE FW_GL_SCALE_F(bmax[0],bmax[1],bmax[2]);
352OLDCODE FW_GL_TRANSLATE_F(-bmin[0],-bmin[1],-bmin[2]);
353OLDCODE }
354OLDCODE }
355OLDCODE if(me){
356OLDCODE if(tg->RenderFuncs.shapenode && genTexPtr->TC_size < 3){
357OLDCODE //3D but no 3D coords supplied - gen from vertex in vertex shader
358OLDCODE glUniform1i(me->tex3dUseVertex,1); //vertex shader flag to over-ride texCoords with vertex
359OLDCODE }else{
360OLDCODE glUniform1i(me->tex3dUseVertex,0);
361OLDCODE }
362OLDCODE if(tti){
363OLDCODE if(me->repeatSTR > -1)
364OLDCODE glUniform1iv(me->repeatSTR,3,tti->repeatSTR);
365OLDCODE if(me->magFilter > -1)
366OLDCODE glUniform1i(me->magFilter,tti->magFilter);
367OLDCODE }
368OLDCODE }
369OLDCODE }
370OLDCODE
371OLDCODE texture = tg->RenderFuncs.boundTextureStack[c];
372OLDCODE
373OLDCODE // SET_TEXTURE_UNIT_AND_BIND
374OLDCODE glActiveTexture(GL_TEXTURE0+c);
375OLDCODE //printf("active texture %d texture %d c %d\n",GL_TEXTURE0+c,texture,c);
376OLDCODE if (getAppearanceProperties()->cubeFace==0) {
377OLDCODE glBindTexture(GL_TEXTURE_2D,texture);
378OLDCODE } else {
379OLDCODE glBindTexture(GL_TEXTURE_CUBE_MAP,texture);
380OLDCODE }
381OLDCODE if(genTexPtr->VBO)
382OLDCODE FW_GL_BINDBUFFER(GL_ARRAY_BUFFER,genTexPtr->VBO);
383OLDCODE
384OLDCODE if (genTexPtr->pre_canned_textureCoords != NULL) {
385OLDCODE /* simple shapes, like Boxes and Cones and Spheres will have pre-canned arrays */
386OLDCODE FW_GL_TEXCOORD_POINTER (2,GL_FLOAT,0,genTexPtr->pre_canned_textureCoords,c);
387OLDCODE }else{
388OLDCODE FW_GL_TEXCOORD_POINTER (genTexPtr->TC_size,
389OLDCODE genTexPtr->TC_type,
390OLDCODE genTexPtr->TC_stride,
391OLDCODE genTexPtr->TC_pointer,c);
392OLDCODE }
393OLDCODE }
394OLDCODE }
395OLDCODE genTexPtr = genTexPtr->next ? genTexPtr->next : genTexPtr; //duplicate the prior coords if not enough for all MultiTextures
396OLDCODE }
397OLDCODE /* set up the selected shader for this texture(s) config */
398OLDCODE if (me != NULL) {
399OLDCODE tnode = tg->RenderFuncs.texturenode;
400OLDCODE //printf ("passedInGenTex, we have tts %d tc %d\n",tg->RenderFuncs.textureStackTop, me->textureCount);
401OLDCODE
402OLDCODE if (me->textureCount != -1) {
403OLDCODE glUniform1i(me->textureCount, tg->RenderFuncs.textureStackTop);
404OLDCODE }
405OLDCODE if(tg->RenderFuncs.textureStackTop){
406OLDCODE if(isMultiTexture(tg->RenderFuncs.texturenode)){
407OLDCODE struct X3D_MultiTexture * mtnode = (struct X3D_MultiTexture *)tg->RenderFuncs.texturenode;
408OLDCODE glUniform4f(me->multitextureColor,mtnode->color.c[0],mtnode->color.c[1],mtnode->color.c[2],mtnode->alpha);
409OLDCODE }
410OLDCODE }
411OLDCODE for (i=0; i<tg->RenderFuncs.textureStackTop; i++) {
412OLDCODE //static int once = 0;
413OLDCODE //if(once < 10) {
414OLDCODE //printf (" sending in i%d tu %d mode %d src %d fnc %d\n",i,i,
415OLDCODE // p->textureParameterStack[i].multitex_mode,
416OLDCODE // p->textureParameterStack[i].multitex_source,
417OLDCODE // p->textureParameterStack[i].multitex_function);
418OLDCODE // once++;
419OLDCODE //}
420OLDCODE glUniform1i(me->TextureUnit[i],i);
421OLDCODE //the 2i wasn't working for me even with ivec2 in shader
422OLDCODE glUniform2i(me->TextureMode[i],p->textureParameterStack[i].multitex_mode[0], p->textureParameterStack[i].multitex_mode[1]);
423OLDCODE glUniform2i(me->TextureSource[i],p->textureParameterStack[i].multitex_source[0], p->textureParameterStack[i].multitex_source[1]);
424OLDCODE //glUniform1i(me->TextureMode[i],p->textureParameterStack[i].multitex_mode[0]);
425OLDCODE //glUniform1i(me->TextureSource[i],p->textureParameterStack[i].multitex_source[0]);
426OLDCODE glUniform1i(me->TextureFunction[i],p->textureParameterStack[i].multitex_function);
427OLDCODE }
428OLDCODE #ifdef TEXVERBOSE
429OLDCODE } else {
430OLDCODE printf (" NOT sending in %d i+tu+mode because currentShaderProperties is NULL\n",tg->RenderFuncs.textureStackTop);
431OLDCODE #endif
432OLDCODE }
433OLDCODE
434OLDCODE FW_GL_MATRIX_MODE(GL_MODELVIEW);
435OLDCODE
436OLDCODE PRINT_GL_ERROR_IF_ANY("");
437OLDCODE }
438#endif //OLDCODE
439
440void textureCoord_send(struct textureVertexInfo *genTex) {
441 // Oct 2016 refactoring before particleSystem
442 // moved texturetransform stuff out of here and into (below) textureTransform_start()
443 int c;
444 //int isIdentity; //isMulti, isStrict,i,
445 //GLint texUnit[MAX_MULTITEXTURE];
446 //GLint texMode[MAX_MULTITEXTURE];
447 // OLDCODE s_shader_capabilities_t *me;
448 struct textureVertexInfo *genTexPtr;
449 // OLDCODE struct X3D_Node *tnode;
450
451 // OLDCODE ppRenderTextures p;
452 ttglobal tg = gglobal();
453 // OLDCODE p = (ppRenderTextures)tg->RenderTextures.prv;
454 // OLDCODE tnode = tg->RenderFuncs.texturenode;
455
456 // OLDCODE me = getAppearanceProperties()->currentShaderProperties;
457
458 genTexPtr = genTex;
459 for (c=0; c<tg->RenderFuncs.textureStackTop; c++) {
460 if(genTexPtr->VBO)
461 FW_GL_BINDBUFFER(GL_ARRAY_BUFFER,genTexPtr->VBO);
462
463 if (genTexPtr->pre_canned_textureCoords != NULL) {
464 /* simple shapes, like Boxes and Cones and Spheres will have pre-canned arrays */
465 FW_GL_TEXCOORD_POINTER (2,GL_FLOAT,0,genTexPtr->pre_canned_textureCoords,c);
466 }else{
467 FW_GL_TEXCOORD_POINTER (genTexPtr->TC_size,
468 genTexPtr->TC_type,
469 genTexPtr->TC_stride,
470 genTexPtr->TC_pointer,c);
471 }
472 genTexPtr = genTexPtr->next ? genTexPtr->next : genTexPtr; //duplicate the prior coords if not enough for all MultiTextures
473 }
474}
475
476
477void textureTransform_start() {
478 int c;
479 int i, isStrict, isMulti, isIdentity;
480 GLint texUnit[MAX_MULTITEXTURE];
481 GLint texMode[MAX_MULTITEXTURE];
483 struct X3D_Node *tnode;
484
486 ttglobal tg = gglobal();
487 p = (ppRenderTextures)tg->RenderTextures.prv;
488 tnode = tg->RenderFuncs.texturenode;
489
490 me = getAppearanceProperties()->currentShaderProperties;
491
492 #ifdef TEXVERBOSE
493 printf ("passedInGenTex, using passed in genTex, textureStackTop %d\n",tg->RenderFuncs.textureStackTop);
494 printf ("passedInGenTex, cubeFace %d\n",getAppearanceProperties()->cubeFace);
495 #endif
496
497 FW_GL_MATRIX_MODE(GL_TEXTURE);
498
499 //printf ("passedInGenTex, B\n");
500 isStrict = 1; //web3d specs say if its a multitexture,
501 //and you give it a single textureTransform instead of multitexturetransform
502 //it should ignore the singleTextureTransform and use identities.
503 //strict: This is a change of functionality for freewrl Aug 31, 2016
504 isIdentity = TRUE;
505 for (c=0; c<tg->RenderFuncs.textureStackTop; c++) {
506 FW_GL_PUSH_MATRIX(); //POPPED in textureDraw_end
507 FW_GL_LOAD_IDENTITY();
508 //printf ("passedInGenTex, c=%d\n",c);
509 /* are we ok with this texture yet? */
510 if (tg->RenderFuncs.boundTextureStack[c]!=0) {
511 isMulti = isMultiTexture(tg->RenderFuncs.texturenode);
512 //printf ("passedInGenTex, C, boundTextureStack %d\n",tg->RenderFuncs.boundTextureStack[c]);
513 if (setActiveTexture(c,getAppearanceProperties()->transparency,texUnit,texMode)) {
514 //printf ("passedInGenTex, going to bind to texture %d\n",tg->RenderFuncs.boundTextureStack[c]);
515 GLuint texture;
516 struct X3D_Node *tt = getThis_textureTransform();
517 if (tt!=NULL) {
518 int match = FALSE;
519 match = isMulti && (tt->_nodeType == NODE_MultiTextureTransform);
520 match = match || (!isMulti && (tt->_nodeType != NODE_MultiTextureTransform));
521 if(isStrict){
522 if(match){
523 do_textureTransform(tt,c);
524 isIdentity = FALSE;
525 }
526 }else{
527 do_textureTransform(tt,c);
528 isIdentity = FALSE;
529 }
530 }
531 //TEXTURE 3D
532 if(isTex3D(tnode)){
533 textureTableIndexStruct_s *tti = getTableTableFromTextureNode(tnode);
534 if(tnode->_nodeType != NODE_ComposedTexture3D){
535 //pixelTexture3D, imageTexture3D (but not composedTexture3D which uses textureCount above)
536 if(me){
537 if(tti){
538 glUniform1iv(me->tex3dTiles,3,tti->tiles);
539 }
540 }
541 }
542 //all texture3d
543 if(tg->RenderFuncs.shapenode && isIdentity ) { //&& genTexPtr->TC_size < 3){
544 //_if_ no TextureTransform3D was explicitly specified for Texture3D,
545 //_and_ no textureCoordinate3D or textureCoordinate4D was explicilty specified with the goem node
546 //_then_ bounding box of shape, in local coordinates, is used to scale/translate
547 //geometry vertices into 0-1 range on each axis for re-use as default texture3D coordinates
548 float bbox[6], *bmin, *bmax;
549 struct X3D_Node *gn;
550 struct X3D_Shape *sn = (struct X3D_Shape *)tg->RenderFuncs.shapenode;
551 POSSIBLE_PROTO_EXPANSION(struct X3D_Node *,sn->geometry,gn);
552 if(gn){
553 //first vec3 is minimum xyz
554 bmin = bbox;
555 bmax = &bbox[3];
556 for(i=0;i<3;i++){
557 bmin[i] = gn->_extent[i*2 + 1];
558 bmax[i] = gn->_extent[i*2];
559 }
560 //second vec3 is 1/size - so can be applied directly in vertex shader
561 vecdif3f(bmax,bmax,bmin);
562 for(i=0;i<3;i++){
563 if(bmax[i] != 0.0f)
564 bmax[i] = 1.0f/bmax[i];
565 else
566 bmax[i] = 1.0f;
567 }
568 //if(fabs(bmin[0]) > 10.0f)
569 // printf("bbox shift [%f %f %f] scale [%f %f %f]\n",bmin[0],bmin[1],bmin[2],bmax[0],bmax[1],bmax[2]);
570
571 //special default texture transform for 3D textures posing as 2D textures
572
573 //the order of applying transform elements seems reversed for texture transforms
574 //H: related to order of operands in mat * vec in shader:
575 // fw_TexCoord[0] = vec3(fw_TextureMatrix0 *vec4(texcoord,1.0));
576 // but sign on elements is what you expect
577 //flip z from RHS to LHS in fragment shader plug_tex3d apply
578 //printf("default tt\n");
579 FW_GL_SCALE_F(bmax[0],bmax[1],bmax[2]);
580 FW_GL_TRANSLATE_F(-bmin[0],-bmin[1],-bmin[2]);
581 }
582 }
583 if(me){
584 if(tg->RenderFuncs.shapenode ) { //&& genTexPtr->TC_size < 3){
585 //3D but no 3D coords supplied - gen from vertex in vertex shader
586 glUniform1i(me->tex3dUseVertex,1); //vertex shader flag to over-ride texCoords with vertex
587 }else{
588 glUniform1i(me->tex3dUseVertex,0);
589 }
590 if(tti){
591 if(me->repeatSTR > -1)
592 glUniform1iv(me->repeatSTR,3,tti->repeatSTR);
593 if(me->magFilter > -1)
594 glUniform1i(me->magFilter,tti->magFilter);
595 }
596 }
597 }
598
599 texture = tg->RenderFuncs.boundTextureStack[c];
600
601 // SET_TEXTURE_UNIT_AND_BIND
602 glActiveTexture(GL_TEXTURE0+c);
603 //printf("active texture %d texture %d c %d\n",GL_TEXTURE0+c,texture,c);
604 if (getAppearanceProperties()->cubeFace==0) {
605 glBindTexture(GL_TEXTURE_2D,texture);
606 } else {
607 glBindTexture(GL_TEXTURE_CUBE_MAP,texture);
608 }
609 }
610 }
611 }
612 /* set up the selected shader for this texture(s) config */
613 if (me != NULL) {
614 tnode = tg->RenderFuncs.texturenode;
615 //printf ("passedInGenTex, we have tts %d tc %d\n",tg->RenderFuncs.textureStackTop, me->textureCount);
616
617 if (me->textureCount != -1) {
618 glUniform1i(me->textureCount, tg->RenderFuncs.textureStackTop);
619 }
620 if(tg->RenderFuncs.textureStackTop){
621 if(isMultiTexture(tg->RenderFuncs.texturenode)){
622 struct X3D_MultiTexture * mtnode = (struct X3D_MultiTexture *)tg->RenderFuncs.texturenode;
623 glUniform4f(me->multitextureColor,mtnode->color.c[0],mtnode->color.c[1],mtnode->color.c[2],mtnode->alpha);
624 }
625 }
626 for (i=0; i<tg->RenderFuncs.textureStackTop; i++) {
627 //static int once = 0;
628 //if(once < 10) {
629 //printf (" sending in i%d tu %d mode %d src %d fnc %d\n",i,i,
630 // p->textureParameterStack[i].multitex_mode,
631 // p->textureParameterStack[i].multitex_source,
632 // p->textureParameterStack[i].multitex_function);
633 // once++;
634 //}
635 glUniform1i(me->TextureUnit[i],i);
636 //the 2i wasn't working for me even with ivec2 in shader
637 glUniform2i(me->TextureMode[i],p->textureParameterStack[i].multitex_mode[0], p->textureParameterStack[i].multitex_mode[1]);
638 glUniform2i(me->TextureSource[i],p->textureParameterStack[i].multitex_source[0], p->textureParameterStack[i].multitex_source[1]);
639 //glUniform1i(me->TextureMode[i],p->textureParameterStack[i].multitex_mode[0]);
640 //glUniform1i(me->TextureSource[i],p->textureParameterStack[i].multitex_source[0]);
641 glUniform1i(me->TextureFunction[i],p->textureParameterStack[i].multitex_function);
642
643 }
644 #ifdef TEXVERBOSE
645 } else {
646 printf (" NOT sending in %d i+tu+mode because currentShaderProperties is NULL\n",tg->RenderFuncs.textureStackTop);
647 #endif
648 }
649
650 FW_GL_MATRIX_MODE(GL_MODELVIEW);
651
652 PRINT_GL_ERROR_IF_ANY("");
653}