FreeWRL / FreeX3D 4.3.0
Component_Texturing.c
1/*
2
3
4X3D Texturing 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/Polyrep.h"
44#include "LinearAlgebra.h"
45
46void pushnset_framebuffer(int ibuffer);
47void popnset_framebuffer();
48void fw_gluPerspective_2(double xcenter, double fovy, double aspect, double zNear, double zFar);
49void push_globalRenderFlags();
50void pop_globalRenderFlags();
51void printFramebufferStatusIfNotComplete(int status);
52void set_debug_quad(int which_debug_shader, int textureID);
53
54void render_GeneratedTexture(struct X3D_GeneratedTexture* node) {
55 // GeneratedTexture doesn't work (not finished) as of Sep 2023
56 // not sure its needed. You could render your sub-scene as a separate scene,
57 // do a screenshot, save, trim and use as imagetexture.
58 // It would take some work to get this working properly.
59 // References:
60 // mainloop > contenttype_fbostage - simple plain method of rendering fbo creation and push/pop
61 // Layout/layering > rendering a subscene with its own bindables stack (viewpoint etc), lights
62 // GeneratedCubeMap - done with whole scene / from rootnode, but manages camera pose in scene
63 // shadow mapping
64
65 int count, iface;
66
67 if (!strcmp(node->update->strptr, "ALWAYS") || !strcmp(node->update->strptr, "NEXT_FRAME_ONLY")) {
68 ttrenderstate rs;
69 rs = renderstate();
70 if (rs->render_geom) {
71 double modelviewmatrix[16];
72 textureTableIndexStruct_s* tti;
73 float vp[4] = { 0.0f,1.0f,0.0f,1.0f }; //arbitrary
74
75 //compile_generatedcubemap - creates framebufferobject fbo
76 tti = getTableIndex(node->__textureTableIndex);
77 //tti->x = node->size.p[0];
78 //tti->y = node->size.p[1];
79 //tti->z = 1;
80 //set in compile_
81 static int once = 0;
82 if (!once) {
83 //loadTextureNode(X3D_NODE(node), NULL);
84 tti->x = node->size.p[0];
85 tti->y = node->size.p[1];
86 glGenTextures(1, &tti->OpenGLTexture);
87 //bind to set some parameters
88 glBindTexture(GL_TEXTURE_2D, tti->OpenGLTexture);
89 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
90 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
91
92 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
93 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
94 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tti->x, tti->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
95 //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
96 //unbind - will rebind during render to reset width, height as needed
97 glBindTexture(GL_TEXTURE_2D, 0);
98
99 glGenFramebuffers(1, &tti->ifbobuffer);
100 glBindFramebuffer(GL_FRAMEBUFFER, tti->ifbobuffer);
101
102 // create a renderbuffer object to store depth info
103 // NOTE: A depth renderable image should be attached the FBO for depth test.
104 // If we don't attach a depth renderable image to the FBO, then
105 // the rendering output will be corrupted because of missing depth test.
106 // If you also need stencil test for your rendering, then you must
107 // attach additional image to the stencil attachement point, too.
108 glGenRenderbuffers(1, &tti->idepthbuffer);
109 //bind to set some parameters
110 glBindRenderbuffer(GL_RENDERBUFFER, tti->idepthbuffer);
111 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, tti->x, tti->y);
112 //unbind
113 glBindRenderbuffer(GL_RENDERBUFFER, 0);
114
115
116 //pushnset_viewport(node->viewpoint); //something to push so we can pop-and-set below, so any mainloop GL_BACK viewport is restored
117 glViewport(0, 0, tti->x, tti->y); //viewport we want
118 glEnable(GL_TEXTURE_GEN_S);
119 glEnable(GL_TEXTURE_GEN_T);
120 //glEnable(GL_TEXTURE_GEN_R);
121 PRINT_GL_ERROR_IF_ANY("render_GeneratedTexture, after set framebuffer");
122
123 //create fbo or fbo tiles collection for generatedcubemap
124 //method: we draw each face to a single framebuffer texture,
125 if (tti->OpenGLTexture == 0) glGenTextures(1, &tti->OpenGLTexture);
126 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tti->OpenGLTexture, 0);
127 // https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glFramebufferTexture.xhtml
128 PRINT_GL_ERROR_IF_ANY("render_GeneratedTexture, after glFramebufferTexture2D");
129
130 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, tti->idepthbuffer);
131 //unbind framebuffer till render
132 glBindFramebuffer(GL_FRAMEBUFFER, 0);
133 once = 1;
134 }
135 pushnset_framebuffer(tti->ifbobuffer); //binds framebuffer. we push here, in case higher up we are already rendering the whole scene to an fbo
136
137 //glClearColor(1.0f,0.0f,0.0f,1.0f); //red, for diagnostics during debugging
138 glClearColor(1.0f, 0.0f, 0.0f, 0.0f); //transparent, so results can be blended
139 FW_GL_CLEAR(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
140
141 //set viewpoint matrix for side
142 //setup_projection();
143 FW_GL_MATRIX_MODE(GL_PROJECTION);
144 FW_GL_LOAD_IDENTITY();
145 //fw_gluPerspective(90.0, 1.0, .1,10000.0);
146 fw_gluPerspective_2(0.0, 90.0, 1.0, .1, 10000.0);
147
148 FW_GL_MATRIX_MODE(GL_MODELVIEW);
149 FW_GL_LOAD_IDENTITY();
150 //fw_glSetDoublev(GL_MODELVIEW_MATRIX, modelviewmatrix);
151 //fw_glRotated(sideangle[j].angle, sideangle[j].x, sideangle[j].y, sideangle[j].z);
152 //fw_glScaled(1.0, -1.0, 1.0);
153 //fw_glGetDoublev(GL_MODELVIEW_MATRIX, bstack->viewmatrix);
154
155// lightTable_clear();
156
157// render_bound_background();
158
159 /* Other lights*/
160 PRINT_GL_ERROR_IF_ANY("render_GeneratedTexture, before render_hier");
161
162 //render_hier(X3D_NODE(node), VF_globalLight);
163 PRINT_GL_ERROR_IF_ANY("XEvents::render, after render_hier(VF_globalLight)");
164 //render_hier(X3D_NODE(node), VF_Other);
165
166 /* 4. Nodes (not the blended ones)*/
167 profile_start("hier_geom");
168 push_globalRenderFlags();
169 //render_hier(X3D_NODE(node), VF_Geom);
170 //render_node(X3D_NODE(node));
171 normalChildren(node->children);
172 pop_globalRenderFlags();
173
174 profile_end("hier_geom");
175 PRINT_GL_ERROR_IF_ANY("render_GeneratedTexture, after render_hier(VF_Geom)");
176
178 //if (tg->RenderFuncs.have_transparency) {
179 // /* render the blended nodes*/
180 // render_hier(rootNode(), VF_Geom | VF_Blend );
181 // PRINT_GL_ERROR_IF_ANY("XEvents::render, render_hier(VF_Geom)");
182 //}
183
184 //popnset_viewport();
185 int status = glCheckNamedFramebufferStatus(tti->ifbobuffer, GL_FRAMEBUFFER);
186 printFramebufferStatusIfNotComplete(status);
187 popnset_framebuffer();
188 if (0) {
189 //set_debug_quad(1, tti->OpenGLTexture);
190 set_debug_quad(2, tti->ifbobuffer);
191 }
192
193 }
194 }
195 //render what we have now
196 gglobal()->RenderFuncs.textureStackTop = 1;
197 gglobal()->RenderFuncs.texturenode = node;
198
199}
200
201
202void render_PixelTexture (struct X3D_PixelTexture *node) {
203 loadTextureNode(X3D_NODE(node),NULL);
204 gglobal()->RenderFuncs.textureStackTop=1; /* not multitexture - should have saved to boundTextureStack[0] */
205}
206void* set_TextureRep(void* _texrep) {
207 struct X3D_TextureRep* texrep = NULL;
208 //to be called from compile_BufferTexture
209 if (!_texrep) {
210 _texrep = MALLOC(struct X3D_TextureRep*, sizeof(struct X3D_TextureRep));
211 memset(_texrep, 0, sizeof(struct X3D_TextureRep));
212 }
213 texrep = (struct X3D_TextureRep*)_texrep;
214 texrep->itype = 4; //0 meshrep 1 linerep 2 polyrep 3 meshrep 4 texturerep
215 return texrep;
216}
217void render_BufferTexture(struct X3D_BufferTexture* node) {
218 //check if buffer loaded
219 if (node->_intern) {
220 struct X3D_TextureRep* tr = (struct X3D_TextureRep*)node->_intern;
221 if (tr->buffer->loaded) {
222 if (1) {
223 loadTextureNode(X3D_NODE(node), NULL);
224 gglobal()->RenderFuncs.textureStackTop = 1; /* not multitexture - should have saved to boundTextureStack[0] */
225 }
226 }
227 }
228}
229
230void render_ImageTexture (struct X3D_ImageTexture *node) {
231 if (node->autoRefresh > 0.0) {
232 double dtime = TickTime();
233 double elapsedTime = dtime - node->__lasttime;
234 double runtime = dtime - BrowserStartTime();
235 if (elapsedTime > node->autoRefresh && runtime < node->autoRefreshTimeLimit) {
236 node->__lasttime = dtime;
237 textureTableIndexStruct_s* tti;
238 tti = getTableTableFromTextureNode(X3D_NODE(node));
239 tti->status = TEX_NOTLOADED;
240 }
241 }
242
243 loadTextureNode(X3D_NODE(node),NULL); //À̹ÌÁö ÅØ½ºÃ³
244
245 gglobal()->RenderFuncs.textureStackTop=1; /* not multitexture - should have saved to boundTextureStack[0] */
246}
247
248void render_MultiTexture (struct X3D_MultiTexture *node) {
249
250 loadMultiTexture(node);
251}
252
253void render_AudioClip(struct X3D_AudioClip * node);
254void render_MovieTexture (struct X3D_MovieTexture *node) {
255 //july 2016 movietexture fields put in same order as audioclip, so can up-caste and delegate
256 struct X3D_AudioClip *anode = (struct X3D_AudioClip*)node;
257 render_AudioClip(anode); //just checks if loaded, schedules if not
258 if (node->autoRefresh > 0.0) {
259 double dtime = TickTime();
260 double elapsedTime = dtime - node->__lasttime;
261 double runtime = dtime - BrowserStartTime();
262 if (elapsedTime > node->autoRefresh && runtime < node->autoRefreshTimeLimit) {
263 node->__lasttime = dtime;
264 textureTableIndexStruct_s* tti;
265 tti = getTableTableFromTextureNode(X3D_NODE(node));
266 tti->status = TEX_NOTLOADED;
267 }
268 }
269
270 loadTextureNode(X3D_NODE(node),NULL);
271 gglobal()->RenderFuncs.textureStackTop=1; /* not multitexture - should have saved to boundTextureStack[0] */
272
273}
274