FreeWRL / FreeX3D 4.3.0
Component_Texturing3D.c
1/*
2
3
4X3D Texturing3D 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
44/*
45http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/texture3D.html
46
47Texturing3D > Volumetric Image Formats
48http://www.volumesoffun.com/voldat-format/
49https://graphics.stanford.edu/data/voldata/
50http://paulbourke.net/dataformats/pvl/
51http://www.ncbi.nlm.nih.gov/pmc/articles/PMC2954506/#!po=59.5238
52https://www.blender.org/manual/render/blender_render/textures/types/volume/voxel_data.html
53
54http://paulbourke.net/dataformats/volumetric/
55-Simplest 3d texture file if you write your own images
56http://www.web3d.org/x3d/content/examples/Basic/VolumeRendering/
57- Volumetric Rendering Samples use nrrd format
58- http://teem.sourceforge.net/index.html
59- http://teem.sourceforge.net/nrrd/index.html
60-- Nrrd lib LGPL
61https://msdn.microsoft.com/en-us/library/windows/desktop/bb205579(v=vs.85).aspx
62- DDS Volume Texture Example
63
64What is Texturing3D used for? a few links:
65https://msdn.microsoft.com/en-us/library/windows/desktop/ff476906(v=vs.85).aspx
66- difference between composed slices and volume image
67http://docs.nvidia.com/gameworks/content/gameworkslibrary/graphicssamples/opengl_samples/texturearrayterrainsample.htm
68- an application for rendering terrain
69
70
71
72Fuzzy Design:
73- load various ways into a buffer representing contiguous voxels, with width, height, depth available
74- somewhere in geometry rendering - polyrep stuff? - give it 3D or 4D-homogenous texture coordinates
75 instead of regular 2D. Hint: look at per-vertex RGBA floats in polyrep?
76- somewhere in sending geom to shader, send the 3D/4D texture coords (and/or Matrix?)
77- in shader, detect if its 3D texture, and use 3D texture lookup
78
79Q. is Texture3D available in GLES2?
80 https://www.khronos.org/opengles/sdk/docs/reference_cards/OpenGL-ES-2_0-Reference-card.pdf
81 - at bottom shows texture2D etc sampler functions
82 instead of vec3 texture2D(sampler2D,coord2D)
83 it would be vec4 texture3D(sampler3D sampler, vec3 coord) ?
84
85GLES2 texture3D: first edition doesn't have sampler3D/texture3D
86https://www.khronos.org/registry/gles/extensions/OES/OES_texture_3D.txt
87- there's a proposed extension
88-Q.how to test for it at runtime?
89-A. worst case: frag shader has a compile error:
90-- if I put Texture3D uniform, and sampler3D(texture3d,vec3(coords2D,0.0)) then:
91 - desktop windows opengl frag shader compiles
92 x uwp windows (using angle over dx/hlsl) frag shader doesn't compile
93 x android frag shader doesn't compile
94http://stackoverflow.com/questions/14150941/webgl-glsl-emulate-texture3d
95http://stackoverflow.com/questions/16938422/3d-texture-emulation-in-shader-subpixel-related
96- hackers emulating with texture2D tiles and lerps
97https://android.googlesource.com/platform/external/chromium_org/third_party/angle/+/0027fa9%5E!/
98- looks like chromium's ANGLE^ emulates cube as 6 2Ds as of 2014
99 ^(gles2 over DX/HLSL for webgl in windows chrome browser)
100Michalis: "Note that Castle Game Engine does not support 3D textures in
101 OpenGLES now (so we don't use OES_texture_3D), but only on desktop
102 OpenGL now (available through EXT_texture3D, or in standard OpenGL >=
103 1.2). But that's simply due to my lack of time to patch necessary
104 things:) From the first glance, using OES_texture_3D to achieve the
105 same functionality on OpenGLES should be easy."
106 https://github.com/castle-engine/demo-models > texturing_advanced/tex3d_*
107
108Example use: if you have 3 images for terrain - white for mountain peaks, brown for mountain sides, green for valleys
109- then combine them into a nxmx3 volume image?
110- then you can use the terrain height to compute an R value ?
111- cube sampler should in theory interpolate between the 3 layers?
112
113Design:
114Texture coordinates:
115I think the geometry vertices, scaled into the range 0-1 on each axis,
116could/should serve as default 3D texture coordinates.
117algorithm:
118a) interpolate through varying the vertex xyz you want as usual
119b) transform xyz into 0-1 range
120 -would need to know bounding box, or have pre-computed, or assume -1 to 1, or in textureTransform3D
121Option: convert xyz vertex to 0-1 range in vertex shader,
122 and do varying interpolation in 0-1 range for varying textureCoords3D aka tc3d
123c) sample the texture
124A. if have texture3D/sampler3D/EXT_texture3D/OES_texture3D:
125 sample directly tc3d.xyz (0-1): frag = sampler3D(texture3D, vec3 tc3d.xyz)
126B. else emulate texture3D/sampler3D with 2D tiled texture:
127 single texture2D: sample the texture at xy[z] on the 2D image plane, z rounded 'above' and 'below'
128 Q. how many z layers, and does it have to be same as rows & cols?
129 nx,ny,nz = size of image in pixels
130 nz == number of z levels
131 nzr = sqrt(nz) so if 256 z levels, it would be sqrt(256) = 16. 16x16 tiles in 2D plane
132 x,y,z - 0-1 range 3D image texture coords from tc3d.xyz
133 vec2 xyi = xy[i] = f(xyz) = [x/nzr + (i / nzr), y/nzr + (i % nzr)]
134 vec2 xyj = xy[j] ... "
135 where
136 i = floor(z*nz)
137 j = ceil(z*nz)
138 fxyi = sampler2D(texture2D,xyi)
139 fxyj = sampler2D(texture2D,xyj)
140 lerp between layers xy[i],xy[j]: frag = lerp(fxyi,fxyj,(z*nz-i)/(j-i))
141 Note: i,j don't need to be ints, nothing above needs to be int, can all be float
142 Option1: strip of tiles - instead of maintaining square 2D texture,
143 make strip texture nx x (ny * nz)
144 then no re-arranging needed when sending uniform (parsed into strip)
145 and xyi = [x, y + i*nz]
146 xyj = [x, y + j*nz]
147 hack test on windows, uwp, and androidndk/nexus: they can all handle the oblong texture
148 Option2: lerp vs floor effects:
149 lerp - smooth transition between layers, good for 3-layer valley, hillside, mountain peak
150 floor - (frag = fxyi): gives abrupt change between layers, good for brick effects
151 Option3: compute 2D-ized texture coordinates on CPU, and use ordinary texture2D sampling (no lerp)
152 problem: geometry node doesn't know if shape>appearance has texture3D, so would need to pre-compute like flat coords
153
154Sept 13, 2016
155 .web3dit image file format developeed which includes volume L,LA,RGB,RGBA and int/float, Up/Down options
156
1574 scenarios:
158 1. GL has texture3D/EXT_texture3D/OES_texture3D
159 2. GL no texture3D - emulate
160 A. 3D image: source imagery is i) 3D image or ii) composed image with image layers all same size
161 B. 2D layers: source imagery is composed image with z < 7 layers and layers can be different sizes
162 1 2
163 A vol texture3D tiled texture2D
164 B multi texure2D multi texture2D
165
166*/
167
168int isTex3D(struct X3D_Node *node){
169 int ret = 0;
170 if(node)
171 switch(node->_nodeType){
172 case NODE_PixelTexture3D:
173 case NODE_ComposedTexture3D:
174 case NODE_ImageTexture3D:
175 ret = TRUE; break;
176 default:
177 ret = FALSE;break;
178 }
179 return ret;
180}
181
182void render_PixelTexture3D (struct X3D_PixelTexture3D *node) {
183 loadTextureNode(X3D_NODE(node),NULL);
184 gglobal()->RenderFuncs.textureStackTop=1; /* not multitexture - should have saved to boundTextureStack[0] */
185}
186void move_texture_to_opengl(textureTableIndexStruct_s* me);
187void render_ImageTexture3D (struct X3D_ImageTexture3D *node) {
188 /* printf ("render_ImageTexture, global Transparency %f\n",getAppearanceProperties()->transparency); */
189 loadTextureNode(X3D_NODE(node),NULL);
190 gglobal()->RenderFuncs.textureStackTop=1; /* not multitexture - should have saved to boundTextureStack[0] */
191}
192textureTableIndexStruct_s *getTableTableFromTextureNode(struct X3D_Node *textureNode);
193void render_ComposedTexture3D (struct X3D_ComposedTexture3D *node) {
194 /* printf ("render_ComposedTexture, global Transparency %f\n",getAppearanceProperties()->transparency); */
195 if(node && node->_nodeType == NODE_ComposedTexture3D){
196 int i, allLoaded; //ntextures,
197 struct Multi_Node *tex = &node->texture;
198 //Sep 14, 2016 we assume all ComposedTexture3D are 'LAYERED' TEX3D_LAYER_SHADER / TEX3DLAY
199 if(0){
200 //could switch from layered to volume, if layers all same size?
201 //somewhere around here we could detect if all images are loaded,
202 // and if so, check/test:
203 // A. do they all have the same xy size? if same size,
204 // then they could be converted to single volume texture
205 // and i) texture3D or ii) tiled texture2D
206 // and set shader flag TEX3D_VOLUME_SHADER / TEX3D, TEX3DVOL
207 // B. if different sizes, and z < 7, then treat like multi-texture:
208 // ii) do sampler2D on either size of z
209 // and set shader flag TEX3D_LAYER_SHADER / TEX3D, TEX3DLAY
210 // either way if ii) we have 2 values in frag shader: take floor, ceil or lerp between
211 //
212 int nx, ny, nfound, nsamesize;
213 nfound = nsamesize = 0;
214 for(i=0;i<tex->n;i++){
215 if(tex->p[i] ){
217 tti = getTableTableFromTextureNode(tex->p[i]);
218 if(tti){
219 if(tti->status == TEX_LOADED){
220 nfound++;
221 if(nfound == 1){
222 nx = tti->x; ny = tti->y;
223 nsamesize = 1;
224 }else{
225 if(tti->x == nx && tti->y == ny) nsamesize++;
226 }
227 }
228 }
229 }
230 }
231 if(nsamesize == nfound && nfound == tex->n){
232 //all 2D textures are loadded and the same size
233 // -can combine into single volume texture
234 printf("ComposedTexture3D all same size textures n %d x %d y %d\n",tex->n,nx,ny);
235 //COMBINE?
236 //TEX3DVOL
237 }else{
238 //not all loaded (so can't trust all same size) or not all same size
239 //so we'll do up to 6 'layers' or texture2Ds, and lerp between floor/ceil in the shader
240 printf("ComposedTexture3D not all same size textures \n");
241 //TEX3DLAY
242 }
243 }
244 allLoaded = TRUE;
245 gglobal()->RenderFuncs.textureStackTop = 0;
246 for(i=0;i<min(tex->n,MAX_MULTITEXTURE);i++){
247 //doing layers, we can only handle up to MAX_MULTITEXTURE textures in the shader
248 //gglobal()->RenderFuncs.textureStackTop = ntextures; /* not multitexture - should have saved to boundTextureStack[0] */
249 loadTextureNode(X3D_NODE(tex->p[i]),NULL);
250 allLoaded = allLoaded && getTableTableFromTextureNode(X3D_NODE(tex->p[i]))->status >= TEX_LOADED;
251 gglobal()->RenderFuncs.textureStackTop++;
252 //loadMultiTexture(node);
253 }
254 //move_texture_to_opengl(getTableTableFromTextureNode(X3D_NODE(node))); //load composed texture properties
255
256 if(allLoaded){
258 tti = getTableTableFromTextureNode(X3D_NODE(node));
259 tti->status = max(TEX_NEEDSBINDING, tti->status);
260 loadTextureNode(X3D_NODE(node),NULL);
261 }
262 }
263}
264
265//void loadImageTexture3D(struct X3D_ImageTexture3D *node){
266// //we don't seem to call or need this
267//}