FreeWRL / FreeX3D 4.3.0
Component_VolumeRendering.c
1/*
2
3
4X3D Volume Rendering Component
5
6*/
7
8
9/****************************************************************************
10 This file is part of the FreeWRL/FreeX3D Distribution.
11
12 Copyright 2009 CRC Canada. (http://www.crc.gc.ca)
13
14 FreeWRL/FreeX3D is free software: you can redistribute it and/or modify
15 it under the terms of the GNU Lesser Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
18
19 FreeWRL/FreeX3D is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with FreeWRL/FreeX3D. If not, see <http://www.gnu.org/licenses/>.
26****************************************************************************/
27
28
29
30#include <config.h>
31#include <system.h>
32#include <display.h>
33#include <internal.h>
34
35#include <libFreeWRL.h>
36
37#include "../vrml_parser/Structs.h"
38#include "../main/headers.h"
39#include "../opengl/OpenGL_Utils.h"
40#include "../opengl/Textures.h"
41#include "../scenegraph/Component_Shape.h"
42#include "../scenegraph/RenderFuncs.h"
43#include "../scenegraph/LinearAlgebra.h"
44
45/*
46Volumee Rendering aka voxels
47http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/volume.html
48- VolumeData is like shape node with its own equivalents to appearance, geometry
49- Style nodes - like appearance, except sometimes composable
50
51
52Before starting to implement this there are a few other nodes and components that might be needed:
53- clipPlane - besides transparent voxels, you may want to slice a volumetric image with a clipplane to look inside IMPLEMENTED SEPT 2016
54- we have TextureProperties to get the RST
55- Texturing3D component > for 3D image file format reading:
56 http://paulbourke.net/dataformats/volumetric/
57 - Simplest 3d texture file, if you are writing your own
58 http://www.web3d.org/x3d/content/examples/Basic/VolumeRendering/
59 - these examples use nrrd format, not much harder IMPLEMENTED Oct 2, 2016
60Links:
61 http://http.developer.nvidia.com/GPUGems/gpugems_ch39.html
62 - GpuGems online, ideas about volume rendering
63 http://teem.sourceforge.net/
64 - same place as nrrd file format lib
65 - unu.exe commandline program is handy:
66 print nrrd file header:
67 unu head brain.nrrd
68 resize an image ie from 512x512x512 to 128x128x128:
69 unu resample -s 128 128 128 -i brain.nrrd -o brain128.nrrd
70
71 http://castle-engine.sourceforge.net/compositing_shaders.php
72 - in the "Compositing Shaders in X3D" .pdf, page 9 mentions volume nodes
73 - the VolumeRendering Component has 10 style nodes, and Kambu is suggesting his Plug/hook method
74 http://cs.iupui.edu/~tuceryan/research/Microscopy/vis98.pdf
75 - paper: "Image-Based Transfer Function Design for Data Exploration in Volume Visualization"
76 pain: hard to stay organized with general functions in volume data
77 solution: goal-directed composable steps ie sharpen surface, colorize via 'transfer functions'
78 1. Apply transfer functions
79 A. Gray = F(Gray) or F(F(F(F(Gray)))) ie can chain grayscale functions for each voxel processed
80 a) F() image functions - anything from 2D image processing generalized to 3D
81 b) F() spatial functions - edge sharpening ie sobel or smoothing also from image processing
82 B. Gray to RGBA - lookup table
83 2. do your raycasting on RGBA
84 http://demos.vicomtech.org/
85 - uses webgl and x3dom
86 https://www.slicer.org/
87 - Uses teem
88 http://teem.sourceforge.net/mite/opts.html
89 - teem > Mite - has some transfer tables
90 http://graphicsrunner.blogspot.ca/2009/01/volume-rendering-101.html
91 - shows 'volume raycasting' method, shader (directx) and results
92 http://prideout.net/blog/?tag=volume-rendering
93 - shows volume raycasting shader example
94 https://www.opengl.org/discussion_boards/showthread.php/174814-Save-vertices-to-texture-problem
95 - xyz texture preparation, related to volume raycasting shader technique
96 http://http.developer.nvidia.com/GPUGems3/gpugems3_ch30.html
97 - see 30.3.1 Volume Rendering for raymarching nuances
98
99
100COMPONENT VOLUMERENDERING ISSUES Oct 29, 2016
101http://dug9.users.sourceforge.net/web3d/tests/volume/
102- these sample scenes use max size 128 .nrrd textures
103
104By Node:
105
106VoiumeData
107 - works
108SegmentedVolumeData
109 - no confirmation its working
110 - SegmentedVentricles.x3d - cycles every 3 seconds or so
111IsoSurfaceVolumeData
112 - no confirm
113 - IsoSurfaceSkull.x3d
114
115BlendedVolumeStyle
116 - blackscreens
117 - BlendedBodyInternals.x3d - blackscreens
118 - BlendedComposedVolumes.x3d - blackscreens
119BoundaryEnhancementVolumeStyle
120 - no confirm
121 - BoundaryEnhancementInternals.x3d - blackscreens
122 - BlendedComposedVolumes.x3d - blackscreens
123CartoonVolumeStyle
124 - works
125 - CartoonBackpack.x3d
126 - BlendedComposedVolumes.x3d
127ComposedVolumeStyle
128 - no confirm
129 - ComposedBackpack.x3d
130 - BlendedComposedVolumes.x3d
131EdgeEnhancementVolumeStyle
132 - works
133 - EdgeBrain.x3d
134 - ComposedBackpack.x3d
135 - BlendedComposedVolumes.x3d
136OpacityMapVolumeStyle
137 - no TransferFunction verification
138 - basics (implicit) works, plus explicit:
139 - BlendedComposedVolumes.x3d
140 - SegmentedVentricles.x3d
141ProjectionVolumeStyle
142 - works
143 - ProjectionMaxVentricles.x3d
144ShadedVolumeStyle
145 - no confirm
146 - ShadedBrain.x3d - no evidence of shading
147SillouetteEnhancementVolumeStyle
148 - works but hard to see a difference
149 - SilhouetteSkull.x3d
150 - ComposedBackpack.x3d
151 - BlendedComposedVolumes.x3d
152ToneMappedVolumeStyle
153 - works
154 - BlendedComposedVolumes.x3d
155 - ToneInternal.x3d - blackscreens
156
157
158By Technique:
159
160gradients:
161 IsoSurfaceVolumeData
162
163surfaceNormals:
164 CartoonVolumeStyle
165 EdgeEnhacementVolumeStyle
166 ShadedVolumeStyle
167 SilhouetteEnhancementVolumeStyle
168 ToneMappedVolumeStyle
169
170segmentIdentifiers:
171 SegmentedVolumeData
172
173Texture2D as transfer function:
174 BlendedVolumeStyle > weightTransferFunction1, weightTransferFunction2
175 OpacityMapVolumeStyle > transferFunction
176
177MF list:
178MFNode -renderStyle > ComposedVolumeStyle, IsoSurfaceVolumeData, SegmentedVolumeStyle
179MFFloat -surfaceValues > IsoSurfaceVolumeData
180
181
182*/
183
185 GLuint front_texture;
186 GLuint back_texture;
187 GLint ifbobuffer;
188 GLint idepthbuffer;
189 int width, height;
190 GLfloat *quad;
192void *Component_VolumeRendering_constructor(){
193 void *v = MALLOCV(sizeof(struct pComponent_VolumeRendering));
194 memset(v,0,sizeof(struct pComponent_VolumeRendering));
195 return v;
196}
197void Component_VolumeRendering_init(struct tComponent_VolumeRendering *t){
198 //public
199 //private
200 t->prv = Component_VolumeRendering_constructor();
201 {
203 p->back_texture = 0;
204 p->front_texture = 0;
205 p->ifbobuffer = 0;
206 p->idepthbuffer = 0;
207 p->width = 0;
208 p->height = 0;
209 p->quad = NULL;
210 }
211}
212void Component_VolumeRendering_clear(struct tComponent_VolumeRendering *t){
213 //public
214 //private
215 {
217 //p->front_texture;
218 //p->back_texture;
219 FREE_IF_NZ(p->quad);
220 }
221}
222//ppComponent_VolumeRendering p = (ppComponent_VolumeRendering)gglobal()->Component_VolumeRendering.prv;
223
224
225
226
227//6 faces x 2 triangles per face x 3 vertices per triangle x 3 scalars (xyz) per vertex = 6 x 2 x 3 x 3 = 108
228GLfloat box [108] = {1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, };
229
230// 6 7 //back far z
231// 4 5
232// 2 3 //front near z
233// 0 1
234float boxvert [24] = {
235-.5f,-.5f, .5f, .5f,-.5f, .5f, -.5f,.5f, .5f, .5f,.5f, .5f, //near z LL LR UL UR
236-.5f,-.5f,-.5f, .5f,-.5f,-.5f, -.5f,.5f,-.5f, .5f,.5f,-.5f, //far z
237};
238//ccw tris
239ushort boxtriindccw [48] = {
2400, 1, 3, -1, //near z
2413, 2, 0, -1,
2421, 5, 7, -1, //right
2437, 3, 1, -1,
2445, 4, 6, -1, //back z
2456, 7, 5, -1,
2464, 0, 2, -1, //left
2472, 6, 4, -1,
2482, 3, 7, -1, //top y
2497, 6, 2, -1,
2504, 5, 1, -1, //bottom y
2511, 0, 4, -1,
252};
253ushort boxtriindcw [48] = {
2540, 3, 1, -1, //near z
2553, 0, 2, -1,
2561, 7, 5, -1, //right
2577, 1, 3, -1,
2585, 6, 4, -1, //back z
2596, 5, 7, -1,
2604, 2, 0, -1, //left
2612, 4, 6, -1,
2622, 7, 3, -1, //top y
2637, 2, 6, -1,
2644, 1, 5, -1, //bottom y
2651, 4, 0, -1,
266};
267void compile_VolumeData(struct X3D_VolumeData *node){
268 int i,j,itri, ind, jvert;
269 float *boxtris;
270
271 ConsoleMessage("compile_volumedata\n");
272 if(node->_boxtris == NULL){
273 node->_boxtris = MALLOC(void *,108 * sizeof(float));
274 }
275 boxtris = (float*)node->_boxtris;
276 if(0)
277 for(i=0;i<36;i++){
278 for(j=0;j<3;j++)
279 boxtris[i*3 + j] = .5f * node->dimensions.c[j] * box[i*3 + j]; //raw triangles are -1 to 1, dimensions are absolute
280
281 }
282 if(1)
283 for(itri=0;itri<12;itri++){
284 for(jvert=0;jvert<3;jvert++) {
285 float *vert;
286 ind = boxtriindccw[itri*4 + jvert];
287 vert = &boxvert[ind*3];
288 for(j=0;j<3;j++){
289 boxtris[(itri*3 +jvert)*3 + j] = node->dimensions.c[j]*vert[j];
290 }
291 }
292 }
293 //for(i=0;i<36;i++)
294 // printf("%f %f %f\n",boxtris[i*3 +0],boxtris[i*3 +1],boxtris[i*3 +2]);
295 MARK_NODE_COMPILED
296}
297void pushnset_framebuffer(int ibuffer);
298void popnset_framebuffer();
299
300
301#ifdef OLDCODE
302#ifdef GL_DEPTH_COMPONENT32
303#define FW_GL_DEPTH_COMPONENT GL_DEPTH_COMPONENT32
304#else
305#define FW_GL_DEPTH_COMPONENT GL_DEPTH_COMPONENT16
306#endif
307#endif //OLDCODE
308
309
310void __gluMultMatricesd(const GLDOUBLE a[16], const GLDOUBLE b[16], GLDOUBLE r[16]);
311int __gluInvertMatrixd(const GLDOUBLE m[16], GLDOUBLE invOut[16]);
312ivec4 get_current_viewport();
313textureTableIndexStruct_s *getTableTableFromTextureNode(struct X3D_Node *textureNode);
314
315unsigned int prep_volumestyle(struct X3D_Node *vstyle, unsigned int volflags){
316 struct X3D_OpacityMapVolumeStyle *style0 = (struct X3D_OpacityMapVolumeStyle*)vstyle;
317 if(style0->enabled){
318 switch(vstyle->_nodeType){
319 case NODE_OpacityMapVolumeStyle:
320 volflags = volflags << 4;
321 volflags |= SHADERFLAGS_VOLUME_STYLE_OPACITY;
322 break;
323 case NODE_BlendedVolumeStyle:
324 //volflags = volflags << 4;
325 //volflags |= SHADERFLAGS_VOLUME_STYLE_BLENDED;
326 //do nothing, so parent renders as default, or gets a style via composed
327 break;
328 case NODE_BoundaryEnhancementVolumeStyle:
329 volflags = volflags << 4;
330 volflags |= SHADERFLAGS_VOLUME_STYLE_BOUNDARY;
331 break;
332 case NODE_CartoonVolumeStyle:
333 volflags = volflags << 4;
334 volflags |= SHADERFLAGS_VOLUME_STYLE_CARTOON;
335 break;
336 case NODE_ComposedVolumeStyle:
337 {
338 int i;
339 struct X3D_ComposedVolumeStyle *style = (struct X3D_ComposedVolumeStyle*)vstyle;
340 //volflags = volflags << 4;
341 //volflags |= SHADERFLAGS_VOLUME_STYLE_COMPOSED;
342 // I 'unroll' composed here, into a bit-shifted list with 4 bits per entry
343 for(i=0;i<style->renderStyle.n;i++){
344 volflags = prep_volumestyle(style->renderStyle.p[i], volflags);
345 }
346 }
347 break;
348 case NODE_EdgeEnhancementVolumeStyle:
349 volflags = volflags << 4;
350 volflags |= SHADERFLAGS_VOLUME_STYLE_EDGE;
351 break;
352 case NODE_ProjectionVolumeStyle:
353 volflags = volflags << 4;
354 volflags |= SHADERFLAGS_VOLUME_STYLE_PROJECTION;
355 break;
356 case NODE_ShadedVolumeStyle:
357 volflags = volflags << 4;
358 volflags |= SHADERFLAGS_VOLUME_STYLE_SHADED;
359 break;
360 case NODE_SilhouetteEnhancementVolumeStyle:
361 volflags = volflags << 4;
362 volflags |= SHADERFLAGS_VOLUME_STYLE_SILHOUETTE;
363 break;
364 case NODE_ToneMappedVolumeStyle:
365 volflags = volflags << 4;
366 volflags |= SHADERFLAGS_VOLUME_STYLE_TONE;
367 break;
368 default:
369 break;
370 }
371 }
372 return volflags;
373}
374void render_volume_data(struct X3D_Node *renderStyle, struct X3D_Node *voxels, struct X3D_VolumeData *node);
375struct X3D_Material *get_material_oneSided();
376struct X3D_TwoSidedMaterial *get_material_twoSided();
377void pushnset_viewport(float *vpFraction);
378void popnset_viewport();
379int haveFrameBufferObject();
380void render_volumestyle(struct X3D_Node *vstyle, GLint myProg){
381 struct X3D_OpacityMapVolumeStyle *style0 = (struct X3D_OpacityMapVolumeStyle*)vstyle;
382 if(style0->enabled){
383 switch(vstyle->_nodeType){
384 case NODE_OpacityMapVolumeStyle:
385 {
386 // http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/volume.html#OpacityMapVolumeStyle
387 // Q. how do the transfer function on GPU? its defined like its on the CPU ie
388 // with integers. On GPU the .a will be 0.0 to 1.0. I guess that can be used as 1D texture coordinate.
389 int havetexture;
390 GLint iopactex;
391 struct X3D_OpacityMapVolumeStyle *style = (struct X3D_OpacityMapVolumeStyle*)vstyle;
392 havetexture = 0;
393 if(style->transferFunction){
394 //load texture
395 struct X3D_Node *tmpN;
397 ttglobal tg = gglobal();
398
399 POSSIBLE_PROTO_EXPANSION(struct X3D_Node *, style->transferFunction,tmpN);
400 tg->RenderFuncs.texturenode = (void*)tmpN;
401
402 //problem: I don't want it sending image dimensions to my volume shader,
403 // which could confuse the voxel sampler
404 //render_node(tmpN); //render_node(node->texture);
405 loadTextureNode(tmpN,NULL);
406 tti = getTableTableFromTextureNode(tmpN);
407 if(tti && tti->status >= TEX_LOADED){
408 glActiveTexture(GL_TEXTURE0+3);
409 glBindTexture(GL_TEXTURE_2D,tti->OpenGLTexture);
410 havetexture = 1;
411 }
412 }
413 iopactex = GET_UNIFORM(myProg,"fw_opacTexture");
414 glUniform1i(iopactex,havetexture);
415
416 }
417 break;
418 case NODE_BlendedVolumeStyle:
419 {
420 // http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/volume.html#BlendedVolumeStyle
421 struct X3D_BlendedVolumeStyle *style = (struct X3D_BlendedVolumeStyle*)vstyle;
422 //FBO blending
423 //a) render the parent volumeData to fbo:
424 // - in prep Blended push fbo
425 // - render main to fbo
426 // - in fin Blended: read pixels or save renderbuffer texture 0
427 //b) in fin Blended: render blended (voxels,stye) as VolumeData to fbo
428 // - read pixels or same renderbuffer texture 1
429 //c) pop fbo
430 //d) set 2 pixelsets as textures
431 // and render via a special little shader that blends 2 textures and sends to GL_BACK.
432 #define BLENDED 1
433 #ifdef BLENDED
434 int *fbohandles = style->_fbohandles.p;
435 GLint iviewport[4];
436 float vp[4] = {0.0f,1.0f,0.0f,1.0f}; //arbitrary
437
438 glGetIntegerv(GL_VIEWPORT, iviewport); //xmin,ymin,w,h
439 if(haveFrameBufferObject()){
440 if(fbohandles[0] == 0){
441 GLuint depthrenderbuffer;
442 // https://www.opengl.org/wiki/Framebuffer_Object
443 glGenFramebuffers(1, (GLuint *) &fbohandles[0]);
444 pushnset_framebuffer(fbohandles[0]); //binds framebuffer. we push here, in case higher up we are already rendering the whole scene to an fbo
445
446 // The depth buffer - optional
447 glGenRenderbuffers(1, &depthrenderbuffer);
448 glBindRenderbuffer(GL_RENDERBUFFER, depthrenderbuffer);
449 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, iviewport[2],iviewport[3]);
450 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthrenderbuffer);
451
452
453 glGenTextures(1,(GLuint *) &fbohandles[1]);
454 glBindTexture(GL_TEXTURE_2D, fbohandles[1]);
455 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, iviewport[2], iviewport[3], 0, GL_RGBA , GL_UNSIGNED_BYTE, 0);
456 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
457 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
458
459 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbohandles[1], 0);
460
461
462 glGenTextures(1,(GLuint *)&fbohandles[2]);
463 glBindTexture(GL_TEXTURE_2D, fbohandles[2]);
464 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, iviewport[2], iviewport[3], 0, GL_RGBA , GL_UNSIGNED_BYTE, 0);
465 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
466 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
467
468 //glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+1, GL_TEXTURE_2D, fbohandles[2], 0);
469 //--dont assign the second texture till after the parent VolumeData has drawn itself
470 //glDrawBuffers(1,&fbohandles[1]);
471 if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
472 printf("ouch framebuffer not complete\n");
473 //popnset_framebuffer(); //pop after drawing
474 }else{
475 pushnset_framebuffer(fbohandles[0]);
476 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbohandles[1], 0);
477 }
478 }
479 pushnset_viewport(vp); //something to push so we can pop-and-set below, so any mainloop GL_BACK viewport is restored
480 glViewport(0,0,iviewport[2],iviewport[3]); //viewport we want
481 glClearColor(0.0f,0.0f,0.0f,0.0f); //red, for diagnostics during debugging
482 FW_GL_CLEAR(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
483
484 #endif //BLENDED
485 }
486 break;
487 case NODE_BoundaryEnhancementVolumeStyle:
488 {
489 // http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/volume.html#BoundaryEnhancementVolumeStyle
491 //SFFloat [in,out] boundaryOpacity 0.9 [0,1]
492 //SFFloat [in,out] opacityFactor 2 [0,?)
493 //SFFloat [in,out] retainedOpacity 0.2 [0,1]
494 GLint ibebound, iberetain, ibefactor;
495 ibebound = GET_UNIFORM(myProg,"fw_boundaryOpacity");
496 glUniform1f(ibebound,style->boundaryOpacity);
497 iberetain = GET_UNIFORM(myProg,"fw_retainedOpacity");
498 glUniform1f(iberetain,style->retainedOpacity);
499 ibefactor = GET_UNIFORM(myProg,"fw_opacityFactor");
500 glUniform1f(ibefactor,style->opacityFactor);
501 }
502 break;
503 case NODE_CartoonVolumeStyle:
504 {
505 // http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/volume.html#CartoonVolumeStyle
506 struct X3D_CartoonVolumeStyle *style = (struct X3D_CartoonVolumeStyle*)vstyle;
507 //SFInt32 [in,out] colorSteps 4 [1,64]
508 //SFColorRGBA [in,out] orthogonalColor 1 1 1 1 [0,1]
509 //SFColorRGBA [in,out] parallelColor 0 0 0 1 [0,1]
510 //SFNode [in,out] surfaceNormals NULL [X3DTexture3DNode]
511 GLint itoonsteps, itoonortho, itoonparallel;
512 itoonsteps = GET_UNIFORM(myProg,"fw_colorSteps");
513 glUniform1i(itoonsteps,style->colorSteps);
514 itoonortho = GET_UNIFORM(myProg,"fw_orthoColor");
515 glUniform4fv(itoonortho,1,style->orthogonalColor.c);
516 itoonparallel = GET_UNIFORM(myProg,"fw_paraColor");
517 glUniform4fv(itoonparallel,1,style->parallelColor.c);
518
519 }
520 break;
521 case NODE_ComposedVolumeStyle:
522 {
523 int i;
524 // http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/volume.html#ComposedVolumeStyle
525 struct X3D_ComposedVolumeStyle *style = (struct X3D_ComposedVolumeStyle*)vstyle;
526 for(i=0;i<style->renderStyle.n;i++){
527 render_volumestyle(style->renderStyle.p[i], myProg);
528 }
529 }
530 break;
531 case NODE_EdgeEnhancementVolumeStyle:
532 {
533 // http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/volume.html#EdgeEnhancementVolumeStyle
534 //SFColorRGBA [in,out] edgeColor 0 0 0 1 [0,1]
535 //SFBool [in,out] enabled TRUE
536 //SFFloat [in,out] gradientThreshold 0.4 [0,PI]
537 //SFNode [in,out] metadata NULL [X3DMetadataObject]
538 //SFNode [in,out] surfaceNormals NULL [X3DTexture3DNode]
540 GLint iedgeColor, igradientThreshold;
541 float *rgba;
542 rgba = style->edgeColor.c;
543 iedgeColor = GET_UNIFORM(myProg,"fw_edgeColor");
544 glUniform4fv(iedgeColor,1,rgba);
545 igradientThreshold = GET_UNIFORM(myProg,"fw_cosGradientThreshold");
546 glUniform1f(igradientThreshold,cosf(style->gradientThreshold));
547 //printf("edge uniforms color %d gradthresh %d\n",iedgeColor,igradientThreshold);
548 }
549 break;
550 case NODE_ProjectionVolumeStyle:
551 {
552 // http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/volume.html#ProjectionVolumeStyle
553 struct X3D_ProjectionVolumeStyle *style = (struct X3D_ProjectionVolumeStyle*)vstyle;
554 //SFFloat [in,out] intensityThreshold 0 [0,1]
555 //SFString [in,put] type "MAX" ["MAX", "MIN", "AVERAGE"]
556 GLint iintensity, itype;
557 int ktype = 1; // initialize this to something that makes sense
558 char *ctype;
559 iintensity = GET_UNIFORM(myProg,"fw_intensityThreshold");
560 glUniform1f(iintensity,style->intensityThreshold);
561 itype = GET_UNIFORM(myProg,"fw_projType");
562 if(style->_type == 0){
563 ctype = style->type->strptr;
564 if(!strcmp(ctype,"MIN"))
565 ktype = 1;
566 else if(!strcmp(ctype,"MAX"))
567 ktype = 2;
568 else if(!strcmp(ctype,"AVERAGE"))
569 ktype = 3;
570 style->_type = ktype;
571 }
572 glUniform1i(itype,style->_type);
573 }
574 break;
575 case NODE_ShadedVolumeStyle:
576 {
577 // http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/volume.html#ShadedVolumeStyle
578 GLint iphase, ilite, ishadow;
579 struct X3D_ShadedVolumeStyle *style = (struct X3D_ShadedVolumeStyle*)vstyle;
580 //SFBool [in,out] lighting FALSE
581 //SFNode [in,out] material NULL [X3DMaterialNode]
582 //SFBool [in,out] shadows FALSE
583 //SFNode [in,out] surfaceNormals NULL [X3DTexture3DNode]
584 //SFString [] phaseFunction "Henyey-Greenstein" ["Henyey-Greenstein","NONE",...]
585 //MATERIAL
586 if(style->material){
587 struct fw_MaterialParameters defaultMaterials = {
588 {0.0f, 0.0f, 0.0f, 1.0f}, /* Emission */
589 {0.0f, 0.0f, 0.0f, 1.0f}, /* Ambient */
590 {0.8f, 0.8f, 0.8f, 1.0f}, /* Diffuse */
591 {0.0f, 0.0f, 0.0f, 1.0f}, /* Specular */
592 10.0f}; /* Shininess */
593
594 struct X3D_Material *matone;
595 struct X3D_TwoSidedMaterial *mattwo;
596 struct fw_MaterialParameters *fw_FrontMaterial;
597 struct fw_MaterialParameters *fw_BackMaterial;
598 GLint myMaterialAmbient;
599 GLint myMaterialDiffuse;
600 GLint myMaterialSpecular;
601 GLint myMaterialShininess;
602 GLint myMaterialEmission;
603
604 GLint myMaterialBackAmbient;
605 GLint myMaterialBackDiffuse;
606 GLint myMaterialBackSpecular;
607 GLint myMaterialBackShininess;
608 GLint myMaterialBackEmission;
609 struct matpropstruct *myap = getAppearanceProperties();
610
611 memcpy (&myap->fw_FrontMaterial, &defaultMaterials, sizeof (struct fw_MaterialParameters));
612 memcpy (&myap->fw_BackMaterial, &defaultMaterials, sizeof (struct fw_MaterialParameters));
613
614 RENDER_MATERIAL_SUBNODES(style->material);
615 //struct matpropstruct matprop;
616 //s_shader_capabilities_t mysp;
617 //sendFogToShader(mysp);
618 matone = get_material_oneSided();
619 mattwo = get_material_twoSided();
620 //sendMaterialsToShader(mysp);
621 if (matone != NULL) {
622 memcpy (&myap->fw_FrontMaterial, matone->_verifiedColor.p, sizeof (struct fw_MaterialParameters));
623 memcpy (&myap->fw_BackMaterial, matone->_verifiedColor.p, sizeof (struct fw_MaterialParameters));
624 /* copy the emissive colour over for lines and points */
625 memcpy(&myap->emissionColour,matone->_verifiedColor.p, 3*sizeof(float));
626
627 } else if (mattwo != NULL) {
628 memcpy (&myap->fw_FrontMaterial, mattwo->_verifiedFrontColor.p, sizeof (struct fw_MaterialParameters));
629 memcpy (&myap->fw_BackMaterial, mattwo->_verifiedBackColor.p, sizeof (struct fw_MaterialParameters));
630 /* copy the emissive colour over for lines and points */
631 memcpy(&myap->emissionColour,mattwo->_verifiedFrontColor.p, 3*sizeof(float));
632 } else {
633 /* no materials selected.... */
634 }
635
636
637
638 if (!myap) return;
639 fw_FrontMaterial = &myap->fw_FrontMaterial;
640 fw_BackMaterial = &myap->fw_BackMaterial;
641
642
643 PRINT_GL_ERROR_IF_ANY("BEGIN sendMaterialsToShader");
644
645 /* eventually do this with code blocks in glsl */
646
647
648 myMaterialEmission = GET_UNIFORM(myProg,"fw_FrontMaterial.emission");
649 myMaterialDiffuse = GET_UNIFORM(myProg,"fw_FrontMaterial.diffuse");
650 myMaterialShininess = GET_UNIFORM(myProg,"fw_FrontMaterial.shininess");
651 myMaterialAmbient = GET_UNIFORM(myProg,"fw_FrontMaterial.ambient");
652 myMaterialSpecular = GET_UNIFORM(myProg,"fw_FrontMaterial.specular");
653
654 myMaterialBackEmission = GET_UNIFORM(myProg,"fw_BackMaterial.emission");
655 myMaterialBackDiffuse = GET_UNIFORM(myProg,"fw_BackMaterial.diffuse");
656 myMaterialBackShininess = GET_UNIFORM(myProg,"fw_BackMaterial.shininess");
657 myMaterialBackAmbient = GET_UNIFORM(myProg,"fw_BackMaterial.ambient");
658 myMaterialBackSpecular = GET_UNIFORM(myProg,"fw_BackMaterial.specular");
659
660
661 profile_start("sendvec");
662 GLUNIFORM4FV(myMaterialAmbient,1,fw_FrontMaterial->ambient);
663 GLUNIFORM4FV(myMaterialDiffuse,1,fw_FrontMaterial->diffuse);
664 GLUNIFORM4FV(myMaterialSpecular,1,fw_FrontMaterial->specular);
665 GLUNIFORM4FV(myMaterialEmission,1,fw_FrontMaterial->emission);
666 GLUNIFORM1F(myMaterialShininess,fw_FrontMaterial->shininess);
667
668 GLUNIFORM4FV(myMaterialBackAmbient,1,fw_BackMaterial->ambient);
669 GLUNIFORM4FV(myMaterialBackDiffuse,1,fw_BackMaterial->diffuse);
670 GLUNIFORM4FV(myMaterialBackSpecular,1,fw_BackMaterial->specular);
671 GLUNIFORM4FV(myMaterialBackEmission,1,fw_BackMaterial->emission);
672 GLUNIFORM1F(myMaterialBackShininess,fw_BackMaterial->shininess);
673 profile_end("sendvec");
674
675
676 }
677 if(style->lighting){
678 //LIGHT
679 //FOG
680 //-these are from the scenegraph above the voldata node, and -like clipplane- can/should be
681 //set generically
682 }
683
684 //phasefunc
685 if(style->_phaseFunction == 0){
686 if(!strcmp(style->phaseFunction->strptr,"NONE"))
687 style->_phaseFunction = 1;
688 else if(!strcmp(style->phaseFunction->strptr,"Henyey-Greenstein"))
689 style->_phaseFunction = 2;
690 }
691 iphase = GET_UNIFORM(myProg,"fw_phase");
692 glUniform1i(iphase,style->_phaseFunction);
693 ilite = GET_UNIFORM(myProg,"fw_lighting");
694 glUniform1i(ilite,style->lighting);
695 ishadow = GET_UNIFORM(myProg,"fw_shadows");
696 glUniform1i(ishadow,style->shadows);
697 }
698 break;
699 case NODE_SilhouetteEnhancementVolumeStyle:
700 {
701 // http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/volume.html#SilhouetteEnhancementVolumeStyle
703 //SFFloat [in,out] silhouetteBoundaryOpacity 0 [0,1]
704 //SFFloat [in,out] silhouetteRetainedOpacity 1 [0,1]
705 //SFFloat [in,out] silhouetteSharpness 0.5 [0,8)
706 GLint isilbound, isilretain, isilsharp;
707 isilbound = GET_UNIFORM(myProg,"fw_BoundaryOpacity");
708 glUniform1f(isilbound,style->silhouetteBoundaryOpacity);
709 isilretain = GET_UNIFORM(myProg,"fw_RetainedOpacity");
710 glUniform1f(isilretain,style->silhouetteRetainedOpacity);
711 isilsharp = GET_UNIFORM(myProg,"fw_Sharpness");
712 glUniform1f(isilsharp,style->silhouetteSharpness);
713 }
714 break;
715 case NODE_ToneMappedVolumeStyle:
716 {
717 // http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/volume.html#ToneMappedVolumeStyle
718 //SFColorRGBA [in,out] coolColor 0 0 1 0 [0,1]
719 //SFColorRGBA [in,out] warmColor 1 1 0 0 [0,1]
720 //SFNode [in,out] surfaceNormals NULL [X3DTexture3DNode]
721 struct X3D_ToneMappedVolumeStyle *style = (struct X3D_ToneMappedVolumeStyle*)vstyle;
722 //send warm, cool to shader
723 GLint icool, iwarm;
724 icool = GET_UNIFORM(myProg,"fw_coolColor");
725 glUniform4fv(icool,1,style->coolColor.c);
726 iwarm = GET_UNIFORM(myProg,"fw_warmColor");
727 glUniform4fv(iwarm,1,style->warmColor.c);
728 }
729 break;
730 default:
731 break;
732 }
733 }
734}
735static struct {
736const char *ctype;
737int itype;
738} blendfuncs [] = {
739{"CONSTANT",1},
740{"ALPHA1",2},
741{"ALPHA2",3},
742{"TABLE",4},
743{"ONE_MINUS_ALPHA1",5},
744{"ONE_MINUS_ALPHA2",6},
745{NULL,0},
746};
747int lookup_blendfunc(const char *funcname){
748 int iret, i;
749 i = 0;
750 iret = 0;
751 do{
752 if(!strcmp(blendfuncs[i].ctype,funcname)){
753 iret = blendfuncs[i].itype;
754 break;
755 }
756 i++;
757 }while(blendfuncs[i].ctype);
758 return iret;
759}
760
761void sendExplicitMatriciesToShader (GLint ModelViewMatrix, GLint ProjectionMatrix, GLint NormalMatrix, GLint *TextureMatrix, GLint ModelViewInverseMatrix);
762void render_GENERIC_volume_data(s_shader_capabilities_t *caps, struct X3D_Node **renderStyle, int nstyle, struct X3D_Node *voxels, struct X3D_VolumeData *node );
763s_shader_capabilities_t * getVolumeProgram(struct X3D_Node **renderStyle, int nstyle, int VOLUME_DATA_FLAG);
764void saveImage_web3dit(struct textureTableIndexStruct *tti, char *fname);
765
766void fin_volumestyle(struct X3D_Node *vstyle, struct X3D_VolumeData *dataParent){
767 struct X3D_OpacityMapVolumeStyle *style0 = (struct X3D_OpacityMapVolumeStyle*)vstyle;
768 if(style0->enabled){
769 switch(vstyle->_nodeType){
770 case NODE_OpacityMapVolumeStyle:
771 {
772 ttglobal tg = gglobal();
773 //do I need to do this?
774 tg->RenderFuncs.textureStackTop = 0;
775 tg->RenderFuncs.texturenode = NULL;
776 }
777 break;
778 case NODE_BlendedVolumeStyle:
779 {
780 // http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/volume.html#BlendedVolumeStyle
781 struct X3D_BlendedVolumeStyle *style = (struct X3D_BlendedVolumeStyle*)vstyle;
782 //FBO blending
783 //a) render the parent volumeData to fbo:
784 // - in prep Blended push fbo
785 // - render main to fbo
786 // - in fin Blended: read pixels or save renderbuffer texture 0
787 //b) in fin Blended: render blended (voxels,stye) as VolumeData to fbo
788 // - read pixels or same renderbuffer texture 1
789 //c) pop fbo
790 //d) set 2 pixelsets as textures
791 // and render via a special little shader that blends 2 textures and sends to GL_BACK.
792 #ifdef BLENDED
793 GLuint pixelType = GL_RGBA;
794 int *fbohandles = style->_fbohandles.p;
795 if(fbohandles[0] > 0){
796 //readpixels from parent volumedata render
797 static int iframe = 0;
799 int nsubstyle;
800 //GLuint myProg;
801 int method_draw_cube, method_draw_quad;
802
803 iframe++;
804 //FW_GL_READPIXELS (0,0,isize,isize,pixelType,GL_UNSIGNED_BYTE, ttip->texdata);
805 if(0) if(iframe==500){
806 //write out whats in the framebuffer, and use as texture in test scene, to see fbo rendered OK
807 GLint iviewport[4];
808 char namebuf[100];
809 textureTableIndexStruct_s ttipp, *ttip;
810 ttip = &ttipp;
811 glGetIntegerv(GL_VIEWPORT, iviewport); //xmin,ymin,w,h
812
813 ttip->texdata = MALLOC (GLvoid *, 4*iviewport[2]*iviewport[3]);
814
815 /* grab the data */
816 //FW_GL_PIXELSTOREI (GL_UNPACK_ALIGNMENT, 1);
817 //FW_GL_PIXELSTOREI (GL_PACK_ALIGNMENT, 1);
818
819 // https://www.khronos.org/opengles/sdk/docs/man/xhtml/glReadPixels.xml
820 FW_GL_READPIXELS (iviewport[0],iviewport[1],iviewport[2],iviewport[3],pixelType,GL_UNSIGNED_BYTE, ttip->texdata);
821 ttip->x = iviewport[2];
822 ttip->y = iviewport[3];
823 ttip->z = 1;
824 ttip->hasAlpha = 1;
825 ttip->channels = 4;
826 //write out tti as web3dit image files for diagnostic viewing, can use for BackGround node
827 //void saveImage_web3dit(struct textureTableIndexStruct *tti, char *fname)
828 sprintf(namebuf,"%s%d.web3dit","blended_fbo_",0);
829 saveImage_web3dit(ttip, namebuf);
830 FREE_IF_NZ(ttip->texdata);
831 }
832
833 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbohandles[2], 0);
834 //glDrawBuffers(1,&fbohandles[2]);
835
836 glClearColor(0.0f,0.0f,0.0f,0.0f); //red, for diagnostics during debugging
837 FW_GL_CLEAR(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
838
839 //render blended as volumedata to fbo
840 //render_volume_data(style->renderStyle,style->voxels,dataParent);
841 nsubstyle = style->renderStyle ? 1 : 0;
842 caps = getVolumeProgram(&style->renderStyle,nsubstyle, SHADERFLAGS_VOLUME_DATA_BASIC);
843 //render generic volume
844 render_GENERIC_volume_data(caps,&style->renderStyle,nsubstyle,style->voxels,(struct X3D_VolumeData*)dataParent );
845 //render_GENERIC_volume_data(caps,style->renderStyle,1,style->voxels,(struct X3D_VolumeData*)dataParent );
846
847 //glDrawBuffers(0,NULL);
848
849 //read blended from fbo
850 //FW_GL_READPIXELS (0,0,isize,isize,pixelType,GL_UNSIGNED_BYTE, ttip->texdata);
851 if(0) if(iframe==500){
852 //write out whats in the framebuffer, and use as texture in test scene, to see fbo rendered OK
853 GLint iviewport[4];
854 char namebuf[100];
855 textureTableIndexStruct_s ttipp, *ttip;
856 ttip = &ttipp;
857 glGetIntegerv(GL_VIEWPORT, iviewport); //xmin,ymin,w,h
858
859 ttip->texdata = MALLOC (GLvoid *, 4*iviewport[2]*iviewport[3]);
860
861 /* grab the data */
862 //FW_GL_PIXELSTOREI (GL_UNPACK_ALIGNMENT, 1);
863 //FW_GL_PIXELSTOREI (GL_PACK_ALIGNMENT, 1);
864 // https://www.khronos.org/opengles/sdk/docs/man/xhtml/glReadPixels.xml
865 FW_GL_READPIXELS (iviewport[0],iviewport[1],iviewport[2],iviewport[3],pixelType,GL_UNSIGNED_BYTE, ttip->texdata);
866 ttip->x = iviewport[2];
867 ttip->y = iviewport[3];
868 ttip->z = 1;
869 ttip->hasAlpha = 1;
870 ttip->channels = 4;
871 //write out tti as web3dit image files for diagnostic viewing, can use for BackGround node
872 //void saveImage_web3dit(struct textureTableIndexStruct *tti, char *fname)
873 sprintf(namebuf,"%s%d.web3dit","blended_fbo_",1);
874 saveImage_web3dit(ttip, namebuf);
875 FREE_IF_NZ(ttip->texdata);
876 printf("wrote blended_fbo_.web3dit \n");
877 }
878 popnset_framebuffer();
879 popnset_viewport();
880 //we're now back to rendering to the screen
881 //we should have 2 textures
882
883 //render 2 textures as blended multitexture, or in special shader for blending,
884 //2 textures are fbohandles[0] (parent voldata), fbohandles[1] (blend voldata)
885 //over window-filling quad
886 //Options:
887 //1) draw our cube again, to get the depth (and skip unneeded pixels)
888 // but use gl_fragCoords as texture interpolator
889 //2) draw quad in ortho mode (but where depth buffer?)
890 method_draw_cube = method_draw_quad = 0;
891 method_draw_cube = 1;
892 if(method_draw_cube){
893 GLint myProg;
894 GLint iwtc1, iwtc2, iwtf1, iwtf2;
895 GLint TextureUnit;
896 int havetextures;
897 GLint iopactex, vp;
898 GLint iviewport[4];
899 float viewport[4];
900 shaderflagsstruct shader_requirements; //shaderflags,
902 GLint Vertices, mvm, proj;
903 double modelviewMatrix[16], projMatrix[16]; //, mvp[16]; // mvpinverse[16]; //mvmInverse[16],
904
905
906 memset(&shader_requirements,0,sizeof(shaderflagsstruct));
907 shader_requirements.volume = SHADERFLAGS_VOLUME_STYLE_BLENDED << 4; //send the following through the volume ubershader
908 // by default we'll mash it in: shader_requirements.volume |= TEX3D_SHADER;
909 caps = getMyShaders(shader_requirements);
910 enableGlobalShader(caps);
911 myProg = caps->myShaderProgram;
912
913 //send the usual matrices - same vertex shader as volumedata
914 //but simpler frag shader that uses gl_fragCoords, and does blend
915
916 //set shader flags
917 //build or get shader program
918 //set attributes
919 //SFFloat [in,out] weightConstant1 0.5 [0,1]
920 //SFFloat [in,out] weightConstant2 0.5 [0,1]
921 //BRUTZMAN: ALPHA0,1 here should be ALPHA1,2 to match table 14.1
922 //SFString [in,out] weightFunction1 "CONSTANT" ["CONSTANT", "ALPHA0", "ALPHA1", "TABLE",
923 // "ONE_MINUS_ALPHA0", "ONE_MINUS_ALPHA1" ]
924 //SFString [in,out] weightFunction2 "CONSTANT" ["CONSTANT", "ALPHA0", "ALPHA1", "TABLE",
925 // "ONE_MINUS_ALPHA0", "ONE_MINUS_ALPHA1" ]
926 //SFNode [in,out] weightTransferFunction1 NULL [X3DTexture2DNode]
927 //SFNode [in,out] weightTransferFunction2 NULL [X3DTexture2DNode]
928
929 iwtc1 = GET_UNIFORM(myProg,"fw_iwtc1");
930 iwtc2 = GET_UNIFORM(myProg,"fw_iwtc2");
931 iwtf1 = GET_UNIFORM(myProg,"fw_iwtf1");
932 iwtf2 = GET_UNIFORM(myProg,"fw_iwtf2");
933 glUniform1f(iwtc1,style->weightConstant1);
934 glUniform1f(iwtc2,style->weightConstant2);
935 if(style->_weightFunction1 == 0)
936 style->_weightFunction1 = lookup_blendfunc(style->weightFunction1->strptr);
937 if(style->_weightFunction2 == 0)
938 style->_weightFunction2 = lookup_blendfunc(style->weightFunction2->strptr);
939 glUniform1i(iwtf1,style->_weightFunction1);
940 glUniform1i(iwtf2,style->_weightFunction2);
941
942 //set the 2 textures from the fbo rendering
943 glActiveTexture ( GL_TEXTURE0 );
944 glBindTexture(GL_TEXTURE_2D,style->_fbohandles.p[1]);
945 FW_GL_TEXPARAMETERI( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); //don't interpolate integer segment IDs
946
947 glActiveTexture ( GL_TEXTURE0+1 );
948 glBindTexture(GL_TEXTURE_2D,style->_fbohandles.p[2]);
949 FW_GL_TEXPARAMETERI( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); //don't interpolate integer segment IDs
950
951 TextureUnit= GET_UNIFORM(myProg,"fw_Texture_unit0");
952 glUniform1i(TextureUnit,0);
953 TextureUnit= GET_UNIFORM(myProg,"fw_Texture_unit1");
954 glUniform1i(TextureUnit,1);
955
956 //set the 2 transfer function textures
957 havetextures = 0;
958 if(style->weightTransferFunction1){
959 //load texture
960 struct X3D_Node *tmpN;
962 ttglobal tg = gglobal();
963
964 POSSIBLE_PROTO_EXPANSION(struct X3D_Node *, style->weightTransferFunction1,tmpN);
965 tg->RenderFuncs.texturenode = (void*)tmpN;
966
967 //problem: I don't want it sending image dimensions to my volume shader,
968 // which could confuse the voxel sampler
969 //render_node(tmpN); //render_node(node->texture);
970 loadTextureNode(tmpN,NULL);
971 tti = getTableTableFromTextureNode(tmpN);
972 if(tti && tti->status >= TEX_LOADED){
973 glActiveTexture(GL_TEXTURE0+2);
974 glBindTexture(GL_TEXTURE_2D,tti->OpenGLTexture);
975 havetextures |= 1;
976 }
977 }
978 if(style->weightTransferFunction2){
979 //load texture
980 struct X3D_Node *tmpN;
982 ttglobal tg = gglobal();
983
984 POSSIBLE_PROTO_EXPANSION(struct X3D_Node *, style->weightTransferFunction2,tmpN);
985 tg->RenderFuncs.texturenode = (void*)tmpN;
986
987 //problem: I don't want it sending image dimensions to my volume shader,
988 // which could confuse the voxel sampler
989 //render_node(tmpN); //render_node(node->texture);
990 loadTextureNode(tmpN,NULL);
991 tti = getTableTableFromTextureNode(tmpN);
992 if(tti && tti->status >= TEX_LOADED){
993 glActiveTexture(GL_TEXTURE0+3);
994 glBindTexture(GL_TEXTURE_2D,tti->OpenGLTexture);
995 havetextures |= 2;
996 }
997 }
998 iopactex = GET_UNIFORM(myProg,"fw_haveTransfers");
999 glUniform1i(iopactex,havetextures);
1000
1001
1002 glGetIntegerv(GL_VIEWPORT, iviewport); //xmin,ymin,w,h
1003
1004 vp = GET_UNIFORM(myProg,"fw_viewport");
1005 viewport[0] = (float)iviewport[0]; //xmin
1006 viewport[1] = (float)iviewport[1]; //ymin
1007 viewport[2] = (float)iviewport[2]; //width
1008 viewport[3] = (float)iviewport[3]; //height
1009 GLUNIFORM4F(vp,viewport[0],viewport[1],viewport[2],viewport[3]);
1010
1011 //draw the box
1012
1013 Vertices = GET_ATTRIB(myProg,"fw_Vertex");
1014 mvm = GET_UNIFORM(myProg,"fw_ModelViewMatrix"); //fw_ModelViewMatrix
1015 proj = GET_UNIFORM(myProg,"fw_ProjectionMatrix"); //fw_ProjectionMatrix
1016 sendExplicitMatriciesToShader(mvm,proj,-1,NULL,-1);
1017 FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX, modelviewMatrix);
1018 FW_GL_GETDOUBLEV(GL_PROJECTION_MATRIX, projMatrix);
1019
1020 glEnableVertexAttribArray(Vertices);
1021
1022 glVertexAttribPointer(Vertices, 3, GL_FLOAT, GL_FALSE, 0, dataParent->_boxtris);
1023
1024
1025 glEnable(GL_CULL_FACE);
1026 glFrontFace(GL_CW);
1027 glDrawArrays(GL_TRIANGLES,0,36);
1028 glDisable(GL_CULL_FACE);
1029
1030 }else if(method_draw_quad){
1032 //GLint Vertices = GET_ATTRIB(myProg,"fw_Vertex");
1033 //glEnableVertexAttribArray(Vertices);
1034 //glVertexAttribPointer(Vertices, 3, GL_FLOAT, GL_FALSE, 0, box);
1035 //glDrawArrays(GL_TRIANGLES,0,6); //6 vertices for quad
1036 }
1037
1038 }
1039 #endif //BLENDED
1040 }
1041 case NODE_ComposedVolumeStyle:
1042 {
1043 int i;
1044 // http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/volume.html#ComposedVolumeStyle
1045 struct X3D_ComposedVolumeStyle *style = (struct X3D_ComposedVolumeStyle*)vstyle;
1046 for(i=0;i<style->renderStyle.n;i++){
1047 fin_volumestyle(style->renderStyle.p[i],dataParent);
1048 }
1049 }
1050 break;
1051
1052 default:
1053 break;
1054 }
1055 }
1056}
1057int volstyle_needs_normal(struct X3D_Node *vstyle){
1058 //IDEA: compute image gradient and store in RGB, if a style requests it
1059 // then surfaceNormal = normalize(gradient)
1060 //SFNode [in,out] surfaceNormals NULL [X3DTexture3DNode
1061 // Cartoon
1062 // Edge
1063 // Shaded
1064 // SilhouetteEnhancement
1065 // ToneMappedVolumeStyle
1066 //
1067 //SFNode [in,out] gradients NULL [X3DTexture3DNode]
1068 // IsoSurfaceVolumeData
1069 //
1070 //SFNode [in,out] segmentIdentifiers NULL [X3DTexture3DNode]
1071 // SegmentedVolumeData
1072 int need_normal;
1073 struct X3D_OpacityMapVolumeStyle *style0 = (struct X3D_OpacityMapVolumeStyle*)vstyle;
1074 need_normal = FALSE;
1075 if(style0->enabled){
1076 switch(vstyle->_nodeType){
1077 case NODE_ComposedVolumeStyle:
1078 {
1079 int i;
1080 struct X3D_ComposedVolumeStyle *style = (struct X3D_ComposedVolumeStyle*)vstyle;
1081 for(i=0;i<style->renderStyle.n;i++){
1082 need_normal = need_normal || volstyle_needs_normal(style->renderStyle.p[i]);
1083 }
1084 }
1085 break;
1086 case NODE_CartoonVolumeStyle:
1087 case NODE_EdgeEnhancementVolumeStyle:
1088 case NODE_ShadedVolumeStyle:
1089 case NODE_SilhouetteEnhancementVolumeStyle:
1090 case NODE_ToneMappedVolumeStyle:
1091 {
1092 //in perl structs, for these nodes its all the 3rd field after enabled, metadata, surfacenormals
1093 struct X3D_ToneMappedVolumeStyle *style = (struct X3D_ToneMappedVolumeStyle*)vstyle;
1094 need_normal = need_normal || (style->surfaceNormals == NULL);
1095 }
1096 break;
1097 default:
1098 break;
1099 }
1100 }
1101 return need_normal;
1102}
1103
1104void compile_IsoSurfaceVolumeData(struct X3D_IsoSurfaceVolumeData *node){
1105 // http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/volume.html#IsoSurfaceVolumeData
1106 // VolumeData + 4 fields:
1107 //SFFloat [in,out] contourStepSize 0 (-INF,INF)
1108 //SFNode [in,out] gradients NULL [X3DTexture3DNode]
1109 //SFFloat [in,out] surfaceTolerance 0 [0,INF)
1110 //MFFloat [in,out] surfaceValues [] (-INF,INF)
1111 printf("compile_isosurfacevolumedata not implemented\n");
1112 compile_VolumeData((struct X3D_VolumeData *)node);
1113}
1114
1115
1116
1117void compile_SegmentedVolumeData(struct X3D_SegmentedVolumeData *node){
1118 // http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/volume.html#SegmentedVolumeData
1119 // VolumeData + 2 fields:
1120 //MFBool [in,out] segmentEnabled []
1121 //SFNode [in,out] segmentIdentifiers NULL [X3DTexture3DNode]
1122 printf("compile_segmentedvolumedata \n");
1123 compile_VolumeData((struct X3D_VolumeData *)node);
1124}
1125s_shader_capabilities_t * getVolumeProgram(struct X3D_Node **renderStyle, int nstyle, int VOLUME_DATA_FLAG){
1126 static int once = 0;
1127 unsigned int volflags;
1128 int i;
1130
1131 if(!once)
1132 ConsoleMessage("getVolumeProgram\n");
1133 volflags = 0;
1134 if(nstyle){
1135 for(i=0;i<nstyle;i++){
1136 struct X3D_OpacityMapVolumeStyle *style0 = (struct X3D_OpacityMapVolumeStyle*)renderStyle[i];
1137 if(style0->enabled){
1138 volflags = prep_volumestyle(renderStyle[i], volflags); //get shader flags
1139 }
1140 }
1141 }else{
1142 volflags = SHADERFLAGS_VOLUME_STYLE_DEFAULT;
1143 }
1144
1145 if(!once){
1146 printf("volflags= ");
1147 for(i=0;i<8;i++)
1148 printf("%d ",((volflags >> (8-i-1)*4) & 0xF)); //show 4 int
1149 printf("\n");
1150 }
1151
1152 //render
1153 //Step 1: set the 3D texture
1154 //if(node->voxels)
1155 // render_node(node->voxels);
1156 //Step 2: get rays to cast: start point and direction vector for each ray to cast
1157
1158 //method: use cpu math to compute a few uniforms so frag shader can do box intersections
1159 //http://prideout.net/blog/?p=64
1160 //- one step raycasting using gl_fragCoord
1161 //- we modified this general method to use gluUnproject math instead of focallength
1162
1163 //Step 3: accumulate along rays and render opacity fragment in one step
1164 //GPU VERSION
1165 {
1166 shaderflagsstruct shader_requirements; //shaderflags,
1167 // OLDCODE GLint myProg;
1168
1169 memset(&shader_requirements,0,sizeof(shaderflagsstruct));
1170 //shaderflags = getShaderFlags();
1171 shader_requirements.volume = VOLUME_DATA_FLAG; //SHADERFLAGS_VOLUME_DATA_BASIC; //send the following through the volume ubershader
1172 shader_requirements.volume |= (volflags << 4); //SHADERFLAGS_VOLUME_STYLE_OPACITY;
1173 //CLIPPLANES ?
1174 shader_requirements.base |= getShaderFlags().base & CLIPPLANE_SHADER;
1175 // by default we'll mash it in: shader_requirements.volume |= TEX3D_SHADER;
1176 caps = getMyShaders(shader_requirements);
1177 enableGlobalShader(caps);
1178 // OLDCODE myProg = caps->myShaderProgram;
1179 }
1180 //Step 1: set the 3D texture
1181 once = 1;
1182 //return myProg;
1183 return caps;
1184}
1185
1186void render_SEGMENTED_volume_data(s_shader_capabilities_t *caps, struct X3D_Node *segmentIDs, int itexture, struct X3D_SegmentedVolumeData *node) {
1187 int myProg;
1188 GLint inids, ienable;
1189
1190 int *enabledIDs = node->segmentEnabled.p;
1191 int nIDs = node->segmentEnabled.n;
1192 myProg = caps->myShaderProgram;
1193 if(segmentIDs){
1194 struct X3D_Node *tmpN;
1196 ttglobal tg = gglobal();
1197
1198 POSSIBLE_PROTO_EXPANSION(struct X3D_Node *, segmentIDs,tmpN);
1199 tg->RenderFuncs.texturenode = (void*)tmpN;
1200
1201 render_node(tmpN); //render_node(node->voxels);
1202
1203 tti = getTableTableFromTextureNode(tmpN);
1204 if(tti && tti->status >= TEX_LOADED){
1205 GLint TextureUnit;
1206 if(0){
1207 //in theory these will be set by the main voxel texture but don't match
1208 //here we want NEAREST not LINEAR
1209 GLint tex3dUseVertex, ttiles, repeatSTR, magFilter;
1210 ttiles = GET_UNIFORM(myProg,"tex3dTiles");
1211 GLUNIFORM1IV(ttiles,3,tti->tiles);
1212
1213 //me->tex3dUseVertex = GET_UNIFORM(myProg,"tex3dUseVertex");
1214 tex3dUseVertex = GET_UNIFORM(myProg,"tex3dUseVertex");
1215 glUniform1i(tex3dUseVertex,0);
1216 repeatSTR = GET_UNIFORM(myProg,"repeatSTR");
1217 glUniform1iv(repeatSTR,3,tti->repeatSTR);
1218 magFilter = GET_UNIFORM(myProg,"magFilter");
1219 glUniform1i(magFilter,0); //tti->magFilter); //NEAREST
1220 }
1221 TextureUnit= GET_UNIFORM(myProg,"fw_Texture_unit1");
1222 glUniform1i(TextureUnit,itexture);
1223 glActiveTexture(GL_TEXTURE0+itexture);
1224 glBindTexture(GL_TEXTURE_2D,tti->OpenGLTexture);
1225 FW_GL_TEXPARAMETERI( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); //don't interpolate integer segment IDs
1226 }
1227 }
1228 inids = GET_UNIFORM(myProg,"fw_nIDs");
1229 glUniform1i(inids,nIDs);
1230 ienable = GET_UNIFORM(myProg,"fw_enableIDs");
1231 glUniform1iv(ienable,nIDs,enabledIDs);
1232
1233 //similar to ISO, there are multiple rendering styles
1234 if(node->renderStyle.n){
1235 int i, *styleflags,instyles;
1236 GLint istyles;
1237
1238 styleflags = MALLOC(int*,sizeof(int)*node->renderStyle.n);
1239 for(i=0;i<node->renderStyle.n;i++){
1240 styleflags[i] = prep_volumestyle(node->renderStyle.p[i],0);
1241 }
1242 //printf("%d %d\n",styleflags[0],styleflags[1]);
1243 istyles = GET_UNIFORM(myProg,"fw_surfaceStyles");
1244 glUniform1iv(istyles,node->renderStyle.n,styleflags);
1245 instyles = GET_UNIFORM(myProg,"fw_nStyles");
1246 glUniform1i(instyles,node->renderStyle.n);
1247 }
1248
1249
1250
1251}
1252
1253float *getTransformedClipPlanes();
1254int getClipPlaneCount();
1255void sendFogToShader(s_shader_capabilities_t *me);
1256void render_GENERIC_volume_data(s_shader_capabilities_t *caps, struct X3D_Node **renderStyle, int nstyle, struct X3D_Node *voxels, struct X3D_VolumeData *node ) {
1257 static int once = 0;
1258 int myProg;
1259 //unsigned int volflags;
1260 GLint Vertices, mvm, proj, mvpi;
1261 double modelviewMatrix[16],projMatrix[16], mvp[16], mvpinverse[16]; // mvmInverse[16],
1262 float spmat[16];
1263 int nsend;
1264 GLint iclipplanes, inclipplanes;
1265 float *clipplanes;
1266 GLint iviewport[4];
1267 float viewport[4];
1268 GLint vp, dim;
1269 float *dimensions;
1270
1271 ttglobal tg = gglobal();
1272
1273 myProg = caps->myShaderProgram;
1274
1275 if(voxels){
1276 struct X3D_Node *tmpN;
1278 POSSIBLE_PROTO_EXPANSION(struct X3D_Node *, voxels,tmpN);
1279 tg->RenderFuncs.texturenode = (void*)tmpN;
1280
1281 //gradient > Oct 2016 we compute in textures.c if channels==1 and z>1 and put in rgb
1282 // - saves mallocing another RGBA
1283 // - for scalar images RGB is unused or just 111 anyway
1284 // - takes 1 second on desktop CPU for 17 Mpixel image
1285 //if(node->renderStyle){
1286 // if(volstyle_needs_normal(node->renderStyle)){
1287 // switch(tmpN->_nodeType){
1288 // case NODE_PixelTexture3D:
1289 // ((struct X3D_PixelTexture3D*)tmpN)->_needs_gradient = TRUE; break;
1290 // case NODE_ImageTexture3D:
1291 // ((struct X3D_ImageTexture3D*)tmpN)->_needs_gradient = TRUE; break;
1292 // }
1293 // }
1294 //}
1295 //render_node(voxels) should keep pulling the texture through all stages of loading and opengl
1296 render_node(tmpN); //render_node(node->voxels);
1297
1298 tti = getTableTableFromTextureNode(tmpN);
1299 if(tti && tti->status >= TEX_LOADED){
1300 GLint ttiles, tex3dUseVertex,repeatSTR,magFilter;
1301 ttiles = GET_UNIFORM(myProg,"tex3dTiles");
1302 GLUNIFORM1IV(ttiles,3,tti->tiles);
1303
1304 //me->tex3dUseVertex = GET_UNIFORM(myProg,"tex3dUseVertex");
1305 tex3dUseVertex = GET_UNIFORM(myProg,"tex3dUseVertex");
1306 glUniform1i(tex3dUseVertex,0);
1307 repeatSTR = GET_UNIFORM(myProg,"repeatSTR");
1308 glUniform1iv(repeatSTR,3,tti->repeatSTR);
1309 magFilter = GET_UNIFORM(myProg,"magFilter");
1310 glUniform1i(magFilter,1); //need LINEAR //tti->magFilter);
1311
1312 glActiveTexture(GL_TEXTURE0);
1313 glBindTexture(GL_TEXTURE_2D,tti->OpenGLTexture);
1314 FW_GL_TEXPARAMETERI( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1315
1316 }
1317 }
1318 if(nstyle){
1319 int i;
1320 for(i=0;i<nstyle;i++){
1321 struct X3D_OpacityMapVolumeStyle *style0 = (struct X3D_OpacityMapVolumeStyle*)renderStyle[i];
1322 if(style0->enabled){
1323 render_volumestyle(renderStyle[i],myProg); //send uniforms
1324 // if style uses a texture, it should be the next texture ie GL_TEXTURE0+1,2..
1325 }
1326 }
1327 }
1328 //3.1 set uniforms: dimensions, focal length, fov (field of view), window size, modelview matrix
1329 // set attributes vertices of triangles of bounding box
1330 // set box with vol.dimensions with triangles
1331 Vertices = GET_ATTRIB(myProg,"fw_Vertex");
1332 mvm = GET_UNIFORM(myProg,"fw_ModelViewMatrix"); //fw_ModelViewMatrix
1333 proj = GET_UNIFORM(myProg,"fw_ProjectionMatrix"); //fw_ProjectionMatrix
1334 if(!once)
1335 ConsoleMessage("vertices %d mvm %d proj %d\n",Vertices,mvm,proj);
1336 sendExplicitMatriciesToShader(mvm,proj,-1,NULL,-1);
1337 FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX, modelviewMatrix);
1338 FW_GL_GETDOUBLEV(GL_PROJECTION_MATRIX, projMatrix);
1339 if(1){
1340 //see gluUnproject in Opengl_Utils.c
1341 __gluMultMatricesd(modelviewMatrix, projMatrix, mvp);
1342 if (!__gluInvertMatrixd(mvp, mvpinverse)) return;
1343 }else{
1344 matmultiplyFULL(mvp,modelviewMatrix,projMatrix);
1345 //matmultiplyFULL(mvp,projMatrix,modelviewMatrix);
1346 //if (!__gluInvertMatrixd(mvp, mvpinverse)) return;
1347 matinverseFULL(mvpinverse,mvp); //seems different than glu's. H0: just wrong H1: transopose H2: full inverse vs factorized
1348 }
1349 matdouble2float4(spmat,mvpinverse);
1350
1351 mvpi = GET_UNIFORM(myProg,"fw_ModelViewProjInverse");
1352 GLUNIFORMMATRIX4FV(mvpi,1,GL_FALSE,spmat);
1353
1354
1355//SEND CLIPPLANES?
1356 //sendClipplanesToShader(mysp);
1357 clipplanes = getTransformedClipPlanes();
1358
1359 nsend = getClipPlaneCount();
1360 iclipplanes = GET_UNIFORM(myProg,"fw_clipplanes");
1361 inclipplanes = GET_UNIFORM(myProg,"fw_nclipplanes");
1362
1363 GLUNIFORM4FV(iclipplanes,nsend,clipplanes);
1364 GLUNIFORM1I(inclipplanes,nsend);
1365
1366//SEND LIGHTS IF WE HAVE A SHADER STYLE
1367 //int haveShaderStyle = FALSE;
1368 //if(nstyle){
1369 // for(int i=0;i<nstyle;i++){
1370 // haveShaderStyle = haveShaderStyle || (renderStyle[i]->_nodeType == NODE_ShadedVolumeStyle);
1371 // }
1372 //}
1373 //if(haveShaderStyle){
1374 //send lights
1375 if (caps->haveLightInShader) {
1376 sendLightInfo(caps);
1377 sendFogToShader(caps);
1378 }
1379 //}
1380
1381
1382
1383 //get the current viewport
1384 glGetIntegerv(GL_VIEWPORT, iviewport); //xmin,ymin,w,h
1385 vp = GET_UNIFORM(myProg,"fw_viewport");
1386 viewport[0] = (float)iviewport[0]; //xmin
1387 viewport[1] = (float)iviewport[1]; //ymin
1388 viewport[2] = (float)iviewport[2]; //width
1389 viewport[3] = (float)iviewport[3]; //height
1390 GLUNIFORM4F(vp,viewport[0],viewport[1],viewport[2],viewport[3]);
1391 dim = GET_UNIFORM(myProg,"fw_dimensions");
1392 dimensions = node->dimensions.c;
1393 GLUNIFORM3F(dim,dimensions[0],dimensions[1],dimensions[2]);
1394
1395 if(!once) ConsoleMessage("dim %d vp %d \n",dim,vp );
1396
1397 //3.2 draw with shader
1398 glEnableVertexAttribArray(Vertices);
1399 glVertexAttribPointer(Vertices, 3, GL_FLOAT, GL_FALSE, 0, node->_boxtris);
1400 // https://www.opengl.org/wiki/Face_Culling
1401 glEnable(GL_CULL_FACE);
1402 //we want to draw only either back/far or front/near triangles, not both
1403 //so that we comput a ray only once.
1404 //and because we want to use clipplane (or frustum near side) to slice into
1405 //volumes, we want to make sure we are still getting ray fragments when slicing
1406 //so instead of drawing the front faces (which would slice away fragments/rays)
1407 //we want to draw only the far/back triangles so even when slicing, we'll get
1408 //fragment shader calls, and can compute rays.
1409 //assuming our triangles are defined CCW (normal)
1410 //setting front-face to GL_CW should ensure only the far/back triangles are rendered
1411 glFrontFace(GL_CW);
1412 glDrawArrays(GL_TRIANGLES,0,36);
1413 glDisable(GL_CULL_FACE);
1414 if(voxels){
1415 tg->RenderFuncs.textureStackTop = 0;
1416 tg->RenderFuncs.texturenode = NULL;
1417 }
1418 if(nstyle){
1419 int i;
1420 for(i=0;i<nstyle;i++)
1421 fin_volumestyle(renderStyle[i],node);
1422 }
1423 once = 1;
1424
1425}
1426
1427void child_SegmentedVolumeData(struct X3D_SegmentedVolumeData *node){
1428 // http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/volume.html#SegmentedVolumeData
1429 // VolumeData + 2 fields:
1430 //MFBool [in,out] segmentEnabled []
1431 //SFNode [in,out] segmentIdentifiers NULL [X3DTexture3DNode]
1433 static int once = 0;
1434 COMPILE_IF_REQUIRED
1435
1436 if (renderstate()->render_blend == (node->_renderFlags & VF_Blend)) {
1437 int itexture = 1; //voxels=0,segmentIDs=1
1438
1439 if(!once)
1440 printf("child segmentedvolumedata \n");
1441 //int nstyles = 0;
1442 //if(node->renderStyle) nstyles = 1;
1443
1444 caps = getVolumeProgram(node->renderStyle.p,node->renderStyle.n, SHADERFLAGS_VOLUME_DATA_SEGMENT);
1445 //get and set segment-specific uniforms
1446 itexture = 1; //voxels=0,segmentIDs=1
1447 render_SEGMENTED_volume_data(caps,node->segmentIdentifiers,itexture,node);
1448 //render generic volume
1449 render_GENERIC_volume_data(caps,node->renderStyle.p,node->renderStyle.n,node->voxels,(struct X3D_VolumeData*)node );
1450 once = 1;
1451 } //if VF_Blend
1452
1453}
1454void render_ISO_volume_data(s_shader_capabilities_t *caps,struct X3D_IsoSurfaceVolumeData *node){
1455 // http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/volume.html#IsoSurfaceVolumeData
1456 // VolumeData + 4 fields, minus 1 field
1457 //SFFloat [in,out] contourStepSize 0 (-INF,INF)
1458 //SFNode [in,out] gradients NULL [X3DTexture3DNode]
1459 //SFFloat [in,out] surfaceTolerance 0 [0,INF)
1460 //MFFloat [in,out] surfaceValues [] (-INF,INF)
1461 //MFNode [in,out] renderStyle [] [X3DVolumeRenderStyleNode]
1462 //minus SFNode renderStyle
1463 int myProg;
1464 GLint istep, itol,ivals,invals;
1465 myProg= caps->myShaderProgram;
1466 istep = GET_UNIFORM(myProg,"fw_stepSize");
1467 glUniform1f(istep,node->contourStepSize);
1468 itol = GET_UNIFORM(myProg,"fw_tolerance");
1469 glUniform1f(itol,node->surfaceTolerance);
1470
1471 ivals = GET_UNIFORM(myProg,"fw_surfaceVals");
1472 glUniform1fv(ivals,node->surfaceValues.n,node->surfaceValues.p);
1473 invals = GET_UNIFORM(myProg,"fw_nVals");
1474 glUniform1i(invals,node->surfaceValues.n);
1475 if(node->renderStyle.n){
1476 int i;
1477 // OLDCODE GLint istyles;
1478 GLint instyles;
1479 int *styleflags = MALLOC(int*,sizeof(int)*node->renderStyle.n);
1480 for(i=0;i<node->renderStyle.n;i++){
1481 styleflags[i] = prep_volumestyle(node->renderStyle.p[i],0);
1482 }
1483 // OLDCODE istyles = GET_UNIFORM(myProg,"fw_surfaceStyles");
1484 glUniform1iv(ivals,node->renderStyle.n,styleflags);
1485 instyles = GET_UNIFORM(myProg,"fw_nStyles");
1486 glUniform1i(instyles,node->renderStyle.n);
1487 }
1488
1489 //renderstyle handling?
1490 //Options:
1491 // a) include all renderstyles in the shader
1492 // b) go through the list and |= (multiple times should show up as once?)
1493 // then make a special shader to (equivalent to switch-case) on each voxel/gradient after iso value has been computed
1494}
1495
1496void child_IsoSurfaceVolumeData(struct X3D_IsoSurfaceVolumeData *node){
1497 // http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/volume.html#IsoSurfaceVolumeData
1498 // VolumeData + 4 fields:
1499 //SFFloat [in,out] contourStepSize 0 (-INF,INF)
1500 //SFNode [in,out] gradients NULL [X3DTexture3DNode]
1501 //SFFloat [in,out] surfaceTolerance 0 [0,INF)
1502 //MFFloat [in,out] surfaceValues [] (-INF,INF)
1503 static int once = 0;
1504 COMPILE_IF_REQUIRED
1505 if (renderstate()->render_blend == (node->_renderFlags & VF_Blend)) {
1506 unsigned int voldataflags;
1508 int MODE;
1509
1510 if(!once)
1511 printf("child segmentedvolumedata \n");
1512 voldataflags = SHADERFLAGS_VOLUME_DATA_ISO;
1513
1514 MODE = node->surfaceValues.n == 1 ? 1 : 3;
1515 MODE = node->contourStepSize != 0.0f && MODE == 1 ? 2 : 1;
1516 if(MODE == 3)
1517 voldataflags |= SHADERFLAGS_VOLUME_DATA_ISO_MODE3;
1518 caps = getVolumeProgram(node->renderStyle.p,node->renderStyle.n, voldataflags);
1519 //get and set ISO-specific uniforms
1520 render_ISO_volume_data(caps,node);
1521 //render generic volume
1522 render_GENERIC_volume_data(caps,node->renderStyle.p,node->renderStyle.n,node->voxels,(struct X3D_VolumeData*)node );
1523 once = 1;
1524 } //if VF_Blend
1525}
1526
1527void child_VolumeData(struct X3D_VolumeData *node){
1528 // http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/volume.html#VolumeData
1529 // VolumeData
1531 static int once = 0;
1532 COMPILE_IF_REQUIRED
1533
1534 if (renderstate()->render_blend == (node->_renderFlags & VF_Blend)) {
1535 int nstyles = 0;
1536 if(!once)
1537 printf("child volumedata \n");
1538 if(node->renderStyle) nstyles = 1;
1539 caps = getVolumeProgram(&node->renderStyle,nstyles, SHADERFLAGS_VOLUME_DATA_BASIC);
1540 //render generic volume
1541 render_GENERIC_volume_data(caps,&node->renderStyle,nstyles,node->voxels,(struct X3D_VolumeData*)node );
1542 once = 1;
1543 } //if VF_Blend
1544
1545}