Line data Source code
1 : /*
2 : * GPAC - Multimedia Framework C SDK
3 : *
4 : * Authors: Jean Le Feuvre
5 : * Copyright (c) Telecom ParisTech 2000-2020
6 : * All rights reserved
7 : *
8 : * This file is part of GPAC / Scene Compositor sub-project
9 : *
10 : * GPAC is free software; you can redistribute it and/or modify
11 : * it under the terms of the GNU Lesser General Public License as published by
12 : * the Free Software Foundation; either version 2, or (at your option)
13 : * any later version.
14 : *
15 : * GPAC is distributed in the hope that it will be useful,
16 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : * GNU Lesser General Public License for more details.
19 : *
20 : * You should have received a copy of the GNU Lesser General Public
21 : * License along with this library; see the file COPYING. If not, write to
22 : * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23 : *
24 : */
25 :
26 : #include "visual_manager.h"
27 : #include "texturing.h"
28 :
29 : #ifndef GPAC_DISABLE_3D
30 :
31 : #include <gpac/options.h>
32 : #include <gpac/nodes_mpeg4.h>
33 : #include "gl_inc.h"
34 :
35 : #if (defined(WIN32) || defined(_WIN32_WCE)) && !defined(__GNUC__)
36 : # if defined(GPAC_USE_TINYGL)
37 : # pragma comment(lib, "TinyGL")
38 :
39 : # elif defined(GPAC_USE_GLES1X)
40 :
41 : # if 0
42 : # pragma message("Using OpenGL-ES Common Lite Profile")
43 : # pragma comment(lib, "libGLES_CL")
44 : # define GL_ES_CL_PROFILE
45 : # else
46 : # pragma message("Using OpenGL-ES Common Profile")
47 : # pragma comment(lib, "libGLES_CM")
48 : # endif
49 :
50 : # elif defined(GPAC_USE_GLES2)
51 : # pragma comment(lib, "libGLESv2")
52 :
53 : # else
54 : # pragma comment(lib, "opengl32")
55 : # endif
56 :
57 : #ifdef GPAC_HAS_GLU
58 : # pragma comment(lib, "glu32")
59 : #endif
60 :
61 : #endif
62 :
63 : /*!! HORRIBLE HACK, but on my test devices, it seems that glClipPlanex is missing on the device but not in the SDK lib !!*/
64 : #if defined(GL_MAX_CLIP_PLANES) && defined(__SYMBIAN32__)
65 : #undef GL_MAX_CLIP_PLANES
66 : #endif
67 :
68 : #define CHECK_GL_EXT(name) ((strstr(ext, name) != NULL) ? 1 : 0)
69 :
70 :
71 872 : void gf_sc_load_opengl_extensions(GF_Compositor *compositor, Bool has_gl_context)
72 : {
73 : #ifdef GPAC_USE_TINYGL
74 : /*let TGL handle texturing*/
75 : compositor->gl_caps.rect_texture = 1;
76 : compositor->gl_caps.npot_texture = 1;
77 : #else
78 : const char *ext = NULL;
79 :
80 872 : if (has_gl_context)
81 267 : ext = (const char *) glGetString(GL_EXTENSIONS);
82 :
83 267 : if (!ext) ext = gf_opts_get_key("core", "glext");
84 : /*store OGL extension to config for app usage*/
85 267 : else if (gf_opts_get_key("core", "glext")==NULL)
86 128 : gf_opts_set_key("core", "glext", ext ? ext : "None");
87 :
88 872 : if (!ext) return;
89 :
90 300 : memset(&compositor->gl_caps, 0, sizeof(GLCaps));
91 :
92 300 : if (CHECK_GL_EXT("GL_ARB_multisample") || CHECK_GL_EXT("GLX_ARB_multisample") || CHECK_GL_EXT("WGL_ARB_multisample"))
93 300 : compositor->gl_caps.multisample = 1;
94 300 : if (CHECK_GL_EXT("GL_ARB_texture_non_power_of_two"))
95 300 : compositor->gl_caps.npot_texture = 1;
96 300 : if (CHECK_GL_EXT("GL_EXT_abgr"))
97 300 : compositor->gl_caps.abgr_texture = 1;
98 300 : if (CHECK_GL_EXT("GL_EXT_bgra"))
99 300 : compositor->gl_caps.bgra_texture = 1;
100 300 : if (CHECK_GL_EXT("GL_EXT_framebuffer_object") || CHECK_GL_EXT("GL_ARB_framebuffer_object"))
101 300 : compositor->gl_caps.fbo = 1;
102 300 : if (CHECK_GL_EXT("GL_ARB_texture_non_power_of_two"))
103 300 : compositor->gl_caps.npot = 1;
104 :
105 :
106 300 : if (CHECK_GL_EXT("GL_ARB_point_parameters")) {
107 300 : compositor->gl_caps.point_sprite = 1;
108 300 : if (CHECK_GL_EXT("GL_ARB_point_sprite") || CHECK_GL_EXT("GL_NV_point_sprite")) {
109 300 : compositor->gl_caps.point_sprite = 2;
110 : }
111 : }
112 :
113 : #ifdef GPAC_USE_GLES2
114 : compositor->gl_caps.vbo = 1;
115 : #else
116 300 : if (CHECK_GL_EXT("GL_ARB_vertex_buffer_object")) {
117 300 : compositor->gl_caps.vbo = 1;
118 : }
119 : #endif
120 :
121 :
122 : #ifndef GPAC_USE_GLES1X
123 300 : if (CHECK_GL_EXT("GL_EXT_texture_rectangle") || CHECK_GL_EXT("GL_NV_texture_rectangle")) {
124 300 : compositor->gl_caps.rect_texture = 1;
125 : }
126 : #endif
127 :
128 300 : if (CHECK_GL_EXT("EXT_unpack_subimage") ) {
129 0 : compositor->gl_caps.gles2_unpack = 1;
130 : }
131 :
132 300 : if (!has_gl_context) return;
133 :
134 :
135 : /*we have a GL context, init the rest (proc addresses & co)*/
136 267 : glGetIntegerv(GL_MAX_TEXTURE_SIZE, &compositor->gl_caps.max_texture_size);
137 :
138 267 : if (CHECK_GL_EXT("GL_ARB_pixel_buffer_object")) {
139 267 : compositor->gl_caps.pbo=1;
140 : }
141 :
142 : #ifdef LOAD_GL_2_0
143 : if (glCreateProgram != NULL) {
144 : compositor->gl_caps.has_shaders = 1;
145 :
146 : #ifndef GPAC_CONFIG_ANDROID
147 : if (glGetAttribLocation == NULL) {
148 : compositor->shader_mode_disabled = GF_TRUE;
149 : }
150 : #endif
151 :
152 : } else {
153 : GF_LOG(GF_LOG_WARNING, GF_LOG_COMPOSE, ("[Compositor] OpenGL shaders not supported\n"));
154 : }
155 : #endif //LOAD_GL_2_0
156 :
157 : #endif //GPAC_USE_TINYGL
158 :
159 : #ifdef GPAC_USE_GLES2
160 : compositor->gl_caps.has_shaders = GF_TRUE;
161 : #elif defined (GL_VERSION_2_0)
162 267 : compositor->gl_caps.has_shaders = GF_TRUE;
163 : #endif
164 : if (!compositor->gl_caps.has_shaders) {
165 : #if !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES1X)
166 : compositor->shader_mode_disabled = GF_TRUE;
167 : #endif
168 : if (compositor->visual->autostereo_type > GF_3D_STEREO_LAST_SINGLE_BUFFER) {
169 : GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] OpenGL shaders not supported - disabling auto-stereo output\n"));
170 : compositor->visual->nb_views=1;
171 : compositor->visual->autostereo_type = GF_3D_STEREO_NONE;
172 : compositor->visual->camlay = GF_3D_CAMERA_STRAIGHT;
173 : }
174 : }
175 :
176 : #if !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES1X)
177 267 : if (!compositor->shader_mode_disabled && compositor->vertshader && compositor->fragshader) {
178 265 : if (!gf_file_exists(compositor->vertshader)) {
179 2 : GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] GLES Vertex shader %s not found, disabling shaders\n", compositor->vertshader));
180 2 : compositor->shader_mode_disabled = GF_TRUE;
181 : }
182 :
183 265 : if (!gf_file_exists(compositor->fragshader)) {
184 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] GLES Fragment shader %s not found, disabling shaders\n", compositor->fragshader));
185 0 : compositor->shader_mode_disabled = GF_TRUE;
186 : }
187 : }
188 : #endif
189 : }
190 :
191 :
192 : #if !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES1X)
193 :
194 : #ifdef GPAC_USE_GLES2
195 : #define GLES_VERSION_STRING "#version 100 \n"
196 : #else
197 : #define GLES_VERSION_STRING "#version 120 \n"
198 : #endif
199 :
200 : #define GLSL_PREFIX GLES_VERSION_STRING \
201 : "#ifdef GL_ES\n"\
202 : "#ifdef GL_FRAGMENT_PRECISION_HIGH\n"\
203 : "precision highp float;\n"\
204 : "#else\n"\
205 : "precision mediump float;\n"\
206 : "#endif\n" \
207 : "#endif\n"
208 :
209 : static char *glsl_autostereo_vertex = GLSL_PREFIX "\
210 : attribute vec4 gfVertex;\
211 : attribute vec2 gfTextureCoordinates;\
212 : uniform mat4 gfProjectionMatrix;\
213 : varying vec2 TexCoord;\
214 : void main(void)\
215 : {\
216 : TexCoord = gfTextureCoordinates;\
217 : gl_Position = gfProjectionMatrix * gfVertex;\
218 : }";
219 :
220 : static char *glsl_view_anaglyph = GLSL_PREFIX "\
221 : uniform sampler2D gfView1;\
222 : uniform sampler2D gfView2;\
223 : varying vec2 TexCoord;\
224 : void main(void) \
225 : {\
226 : vec4 col1 = texture2D(gfView1, TexCoord.st); \
227 : vec4 col2 = texture2D(gfView2, TexCoord.st); \
228 : gl_FragColor.r = col1.r;\
229 : gl_FragColor.g = col2.g;\
230 : gl_FragColor.b = col2.b;\
231 : }";
232 :
233 : #ifdef GPAC_UNUSED_FUNC
234 : static char *glsl_view_anaglyph_optimize = GLSL_PREFIX "\
235 : uniform sampler2D gfView1;\
236 : uniform sampler2D gfView2;\
237 : varying vec2 TexCoord;\
238 : void main(void) \
239 : {\
240 : vec4 col1 = texture2D(gfView1, TexCoord.st); \
241 : vec4 col2 = texture2D(gfView2, TexCoord.st); \
242 : gl_FragColor.r = 0.7*col1.g + 0.3*col1.b;\
243 : gl_FragColor.r = pow(gl_FragColor.r, 1.5);\
244 : gl_FragColor.g = col2.g;\
245 : gl_FragColor.b = col2.b;\
246 : }";
247 : #endif /*GPAC_UNUSED_FUNC*/
248 :
249 : static char *glsl_view_columns = GLSL_PREFIX "\
250 : uniform sampler2D gfView1;\
251 : uniform sampler2D gfView2;\
252 : varying vec2 TexCoord;\
253 : void main(void) \
254 : {\
255 : if ( int( mod(gl_FragCoord.x, 2.0) ) == 0) \
256 : gl_FragColor = texture2D(gfView1, TexCoord.st); \
257 : else \
258 : gl_FragColor = texture2D(gfView2, TexCoord.st); \
259 : }";
260 :
261 : static char *glsl_view_rows = GLSL_PREFIX "\
262 : uniform sampler2D gfView1;\
263 : uniform sampler2D gfView2;\
264 : varying vec2 TexCoord;\
265 : void main(void) \
266 : {\
267 : if ( int( mod(gl_FragCoord.y, 2.0) ) == 0) \
268 : gl_FragColor = texture2D(gfView1, TexCoord.st); \
269 : else \
270 : gl_FragColor = texture2D(gfView2, TexCoord.st); \
271 : }";
272 :
273 : static char *glsl_view_5VSP19 = GLSL_PREFIX "\
274 : uniform sampler2D gfView1;\
275 : uniform sampler2D gfView2;\
276 : uniform sampler2D gfView3;\
277 : uniform sampler2D gfView4;\
278 : uniform sampler2D gfView5;\
279 : varying vec2 TexCoord;\
280 : \
281 : void getTextureSample(in int texID, out vec4 color) { \
282 : if (texID == 0 ) color = texture2D(gfView1, TexCoord.st); \
283 : else if (texID == 1 ) color = texture2D(gfView2, TexCoord.st); \
284 : else if (texID == 2 ) color = texture2D(gfView3, TexCoord.st); \
285 : else if (texID == 3 ) color = texture2D(gfView4, TexCoord.st); \
286 : else if (texID == 4 ) color = texture2D(gfView5, TexCoord.st); \
287 : } \
288 : \
289 : void main(void) {\
290 : vec4 color;\
291 : float pitch = 5.0 + 1.0 - mod(gl_FragCoord.y , 5.0);\
292 : int col = int( mod(pitch + 3.0 * (gl_FragCoord.x), 5.0 ) );\
293 : int Vr = int(col);\
294 : int Vg = int(col) + 1;\
295 : int Vb = int(col) + 2;\
296 : if (Vg >= 5) Vg -= 5;\
297 : if (Vb >= 5) Vb -= 5;\
298 : getTextureSample(Vr, color); \
299 : gl_FragColor.r = color.r;\
300 : getTextureSample(Vg, color); \
301 : gl_FragColor.g = color.g;\
302 : getTextureSample(Vb, color); \
303 : gl_FragColor.b = color.b;\
304 : }";
305 :
306 : static char *glsl_view_8VAlio = GLSL_PREFIX "\
307 : uniform sampler2D gfView1; \
308 : uniform sampler2D gfView2; \
309 : uniform sampler2D gfView3; \
310 : uniform sampler2D gfView4; \
311 : uniform sampler2D gfView5; \
312 : uniform sampler2D gfView6; \
313 : uniform sampler2D gfView7; \
314 : uniform sampler2D gfView8; \
315 : varying vec2 TexCoord;\
316 : \
317 : void getTextureSample(in int texID, out vec4 color) { \
318 : if (texID == 0 ) color = texture2D(gfView1, TexCoord.st); \
319 : else if (texID == 1 ) color = texture2D(gfView2, TexCoord.st); \
320 : else if (texID == 2 ) color = texture2D(gfView3, TexCoord.st); \
321 : else if (texID == 3 ) color = texture2D(gfView4, TexCoord.st); \
322 : else if (texID == 4 ) color = texture2D(gfView5, TexCoord.st); \
323 : else if (texID == 5 ) color = texture2D(gfView6, TexCoord.st); \
324 : else if (texID == 6 ) color = texture2D(gfView7, TexCoord.st); \
325 : else if (texID == 7 ) color = texture2D(gfView8, TexCoord.st); \
326 : } \
327 : \
328 : void main() \
329 : { \
330 : int x = int(gl_FragCoord.x + 0.5); \
331 : int y = int(gl_FragCoord.y + 0.5); \
332 : int modulox = x/8; \
333 : int moduloy = y/8; \
334 : modulox = x - 8 * modulox; \
335 : moduloy = y - 8 * moduloy; \
336 : \
337 : int viewLine = 7 - moduloy; \
338 : int viewPix = viewLine + 3 * modulox; \
339 : int viewR = viewPix - 8*(viewPix/8); \
340 : int viewG = viewPix + 1 - 8*((viewPix +1)/8); \
341 : int viewB = viewPix + 2 - 8*((viewPix +2)/8); \
342 : \
343 : vec4 color; \
344 : getTextureSample(viewR, color); \
345 : gl_FragColor.r = color.r; \
346 : getTextureSample(viewG, color); \
347 : gl_FragColor.g = color.g; \
348 : getTextureSample(viewB, color); \
349 : gl_FragColor.b = color.b; \
350 : }";
351 :
352 :
353 : /**
354 : parses (glShaderSource) and compiles (glCompileShader) shader source
355 : \return GF_TRUE if successful
356 : */
357 1896 : Bool visual_3d_compile_shader(GF_SHADERID shader_id, const char *name, const char *source)
358 : {
359 1896 : GLint blen = 0;
360 1896 : GLsizei slen = 0;
361 : s32 len;
362 1896 : GLint is_compiled=0;
363 1896 : if (!source || !shader_id) return 0;
364 1896 : len = (u32) strlen(source);
365 1896 : glShaderSource(shader_id, 1, &source, &len);
366 1896 : glCompileShader(shader_id);
367 :
368 1896 : glGetShaderiv(shader_id, GL_COMPILE_STATUS, &is_compiled);
369 1896 : if (is_compiled == GL_TRUE) return GF_TRUE;
370 0 : glGetShaderiv(shader_id, GL_INFO_LOG_LENGTH , &blen);
371 0 : if (blen > 1) {
372 0 : char* compiler_log = (char*) gf_malloc(blen);
373 : #ifdef CONFIG_DARWIN_GL
374 : glGetInfoLogARB((GLhandleARB) shader_id, blen, &slen, compiler_log);
375 : #elif defined(GPAC_USE_GLES2)
376 : glGetShaderInfoLog(shader_id, blen, &slen, compiler_log);
377 : #else
378 0 : glGetInfoLogARB(shader_id, blen, &slen, compiler_log);
379 : #endif
380 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[GLSL] Failed to compile %s shader: %s\n", name, compiler_log));
381 0 : GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[GLSL] ***** faulty shader code ****\n%s\n**********************\n", source));
382 0 : gf_free (compiler_log);
383 0 : return 0;
384 : }
385 : return 1;
386 : }
387 0 : static GF_SHADERID visual_3d_shader_from_source_file(const char *src_path, u32 shader_type)
388 : {
389 : GF_SHADERID shader = 0;
390 : u32 size;
391 : char *shader_src;
392 :
393 0 : GF_Err e = gf_file_load_data(src_path, (u8 **) &shader_src, &size);
394 0 : if (e) {
395 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to open shader file %s: %s\n", src_path, gf_error_to_string(e) ));
396 : } else {
397 0 : shader = glCreateShader(shader_type);
398 0 : if (visual_3d_compile_shader(shader, (shader_type == GL_FRAGMENT_SHADER) ? "fragment" : "vertex", shader_src)==GF_FALSE) {
399 0 : glDeleteShader(shader);
400 : shader = 0;
401 : }
402 0 : gf_free(shader_src);
403 : }
404 0 : return shader;
405 : }
406 :
407 : #ifdef GPAC_CONFIG_IOS
408 : #include <errno.h>
409 : #include <sys/sysctl.h>
410 : #endif
411 :
412 :
413 1894 : static GF_SHADERID visual_3d_shader_with_flags(const char *src_path, u32 shader_type, u32 flags, u32 pixfmt) {
414 :
415 : GF_SHADERID shader = 0;
416 : char *defs, szKey[100];
417 : size_t str_size;
418 :
419 1894 : defs = (char *) gf_strdup(GLES_VERSION_STRING);
420 1894 : str_size = strlen(defs) + 1; //+1 for trailing \0
421 :
422 1894 : if (flags & GF_GL_HAS_LIGHT) {
423 : sprintf(szKey, "#define GF_GL_HAS_LIGHT\n#define LIGHTS_MAX %d\n", GF_MAX_GL_LIGHTS);
424 142 : str_size += strlen(szKey);
425 142 : defs = (char *) gf_realloc(defs, sizeof(char)*str_size);
426 : strcat(defs, szKey);
427 : }
428 :
429 1894 : if(flags & GF_GL_HAS_COLOR) {
430 36 : str_size += strlen("#define GF_GL_HAS_COLOR \n");
431 36 : defs = (char *) gf_realloc(defs, sizeof(char)*str_size);
432 : strcat(defs,"#define GF_GL_HAS_COLOR \n");
433 : }
434 :
435 1894 : if(flags & GF_GL_HAS_TEXTURE) {
436 256 : str_size += strlen("#define GF_GL_HAS_TEXTURE \n");
437 256 : defs = (char *) gf_realloc(defs, sizeof(char)*str_size);
438 : strcat(defs,"#define GF_GL_HAS_TEXTURE \n");
439 : }
440 :
441 1894 : if(flags & GF_GL_HAS_CLIP) {
442 : /*clipping is always enabled*/
443 : sprintf(szKey, "#define CLIPS_MAX %d\n#define GF_GL_HAS_CLIP\n", GF_MAX_GL_CLIPS);
444 4 : str_size += strlen(szKey);
445 4 : defs = (char *) gf_realloc(defs, sizeof(char)*str_size);
446 : strcat(defs, szKey);
447 : }
448 :
449 1894 : if (shader_type==GL_FRAGMENT_SHADER) {
450 947 : if(flags & GF_GL_IS_YUV) {
451 0 : str_size += strlen("#define GF_GL_IS_YUV \n");
452 0 : defs = (char *) gf_realloc(defs, sizeof(char)*str_size);
453 : strcat(defs,"#define GF_GL_IS_YUV \n");
454 : }
455 947 : if(flags & GF_GL_IS_ExternalOES) {
456 0 : str_size += strlen("#define GF_GL_IS_ExternalOES \n");
457 0 : defs = (char *) gf_realloc(defs, sizeof(char)*str_size);
458 : strcat(defs,"#define GF_GL_IS_ExternalOES \n");
459 : }
460 : }
461 :
462 : char *shader_src;
463 : u32 size;
464 1894 : GF_Err e = gf_file_load_data(src_path ,(u8 **) &shader_src, &size);
465 :
466 1894 : if (e) {
467 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to open shader file %s: %s\n", src_path, gf_error_to_string(e)));
468 : } else {
469 1894 : char *final_src = NULL;
470 :
471 1894 : gf_dynstrcat(&final_src, defs, NULL);
472 :
473 1894 : if ((shader_type==GL_FRAGMENT_SHADER) && (flags & GF_GL_HAS_TEXTURE)) {
474 128 : char *sep = strstr(shader_src, "void main(");
475 128 : if (sep) sep[0] = 0;
476 128 : gf_dynstrcat(&final_src, shader_src, NULL);
477 :
478 : //add texture code
479 128 : gf_gl_txw_insert_fragment_shader(pixfmt, "maintx", &final_src);
480 :
481 : //append the rest
482 128 : if (sep) {
483 128 : sep[0] = 'v';
484 128 : gf_dynstrcat(&final_src, sep, "\n");
485 : }
486 : } else {
487 1766 : gf_dynstrcat(&final_src, shader_src, "\n");
488 : }
489 1894 : shader = glCreateShader(shader_type);
490 :
491 1894 : if (visual_3d_compile_shader(shader, (shader_type == GL_FRAGMENT_SHADER) ? "fragment" : "vertex", final_src)==GF_FALSE) {
492 0 : glDeleteShader(shader);
493 : shader = 0;
494 : }
495 :
496 1894 : gf_free(shader_src);
497 1894 : gf_free(final_src);
498 1894 : gf_free(defs);
499 : }
500 1894 : return shader;
501 : }
502 :
503 1 : void visual_3d_init_stereo_shaders(GF_VisualManager *visual)
504 : {
505 : GLint linked;
506 : Bool res;
507 1 : if (!visual->compositor->gl_caps.has_shaders) return;
508 :
509 1 : if (visual->autostereo_glsl_program) return;
510 :
511 1 : visual->autostereo_glsl_program = glCreateProgram();
512 :
513 : res = GF_TRUE;
514 1 : if (!visual->base_glsl_vertex) {
515 1 : visual->base_glsl_vertex = glCreateShader(GL_VERTEX_SHADER);
516 1 : res = visual_3d_compile_shader(visual->base_glsl_vertex, "vertex", glsl_autostereo_vertex);
517 : }
518 1 : if (res) {
519 1 : switch (visual->autostereo_type) {
520 0 : case GF_3D_STEREO_COLUMNS:
521 0 : visual->autostereo_glsl_fragment = glCreateShader(GL_FRAGMENT_SHADER);
522 0 : res = visual_3d_compile_shader(visual->autostereo_glsl_fragment, "fragment", glsl_view_columns);
523 0 : break;
524 0 : case GF_3D_STEREO_ROWS:
525 0 : visual->autostereo_glsl_fragment = glCreateShader(GL_FRAGMENT_SHADER);
526 0 : res = visual_3d_compile_shader(visual->autostereo_glsl_fragment, "fragment", glsl_view_rows);
527 0 : break;
528 0 : case GF_3D_STEREO_ANAGLYPH:
529 0 : visual->autostereo_glsl_fragment = glCreateShader(GL_FRAGMENT_SHADER);
530 0 : res = visual_3d_compile_shader(visual->autostereo_glsl_fragment, "fragment", glsl_view_anaglyph);
531 0 : break;
532 1 : case GF_3D_STEREO_5VSP19:
533 1 : visual->autostereo_glsl_fragment = glCreateShader(GL_FRAGMENT_SHADER);
534 1 : res = visual_3d_compile_shader(visual->autostereo_glsl_fragment, "fragment", glsl_view_5VSP19);
535 1 : break;
536 0 : case GF_3D_STEREO_8VALIO:
537 0 : visual->autostereo_glsl_fragment = glCreateShader(GL_FRAGMENT_SHADER);
538 0 : res = visual_3d_compile_shader(visual->autostereo_glsl_fragment, "fragment", glsl_view_8VAlio);
539 0 : break;
540 :
541 0 : case GF_3D_STEREO_CUSTOM:
542 0 : visual->autostereo_glsl_fragment = visual_3d_shader_from_source_file(visual->compositor->mvshader, GL_FRAGMENT_SHADER);
543 0 : if (visual->autostereo_glsl_fragment) res = GF_TRUE;
544 : break;
545 : }
546 : }
547 :
548 1 : if (res) {
549 1 : glAttachShader(visual->autostereo_glsl_program, visual->base_glsl_vertex);
550 1 : glAttachShader(visual->autostereo_glsl_program, visual->autostereo_glsl_fragment);
551 1 : glLinkProgram(visual->autostereo_glsl_program);
552 :
553 1 : glGetProgramiv(visual->autostereo_glsl_program, GL_LINK_STATUS, &linked);
554 1 : if (!linked) {
555 : int i32CharsWritten, i32InfoLogLength;
556 : char pszInfoLog[2048];
557 0 : glGetProgramiv(visual->autostereo_glsl_program, GL_INFO_LOG_LENGTH, &i32InfoLogLength);
558 0 : glGetProgramInfoLog(visual->autostereo_glsl_program, i32InfoLogLength, &i32CharsWritten, pszInfoLog);
559 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, (pszInfoLog));
560 : res = GF_FALSE;
561 : }
562 : GL_CHECK_ERR()
563 : }
564 :
565 1 : if (!res) {
566 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[V3D:GLSL] Autostereo vertex shader failed - disabling stereo support\n"));
567 0 : visual->autostereo_type = 0;
568 0 : visual->nb_views = 1;
569 : }
570 : }
571 :
572 : #define DEL_SHADER(_a) if (_a) { glDeleteShader(_a); _a = 0; }
573 : #define DEL_PROGRAM(_a) if (_a) { glDeleteProgram(_a); _a = 0; }
574 :
575 :
576 :
577 : #if 0
578 : static GLint gf_glGetUniformLocation(GF_SHADERID glsl_program, const char *uniform_name)
579 : {
580 : GLint loc = glGetUniformLocation(glsl_program, uniform_name);
581 : if (loc<0) {
582 : GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[V3D:GLSL] Cannot find uniform \"%s\" in GLSL program\n", uniform_name));
583 : }
584 : return loc;
585 : }
586 : #endif
587 :
588 :
589 : #if 0
590 : static GLint gf_glGetAttribLocation(GF_SHADERID glsl_program, const char *attrib_name)
591 : {
592 : GLint loc = glGetAttribLocation(glsl_program, attrib_name);
593 : if (loc<0) {
594 : GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[V3D:GLSL] Cannot find attrib \"%s\" in GLSL program\n", attrib_name));
595 : }
596 : return loc;
597 : }
598 : #endif
599 :
600 : //The following functions were used for shader testing [in ES2.0]
601 : #if 0
602 : static void gf_glQueryProgram(GF_SHADERID progObj)
603 : {
604 : GLint err_log = -10;
605 : GL_CHECK_ERR()
606 : glValidateProgram(progObj);
607 : GL_CHECK_ERR()
608 : glGetProgramiv(progObj, GL_VALIDATE_STATUS, &err_log);
609 : printf("GL_VALIDATE_STATUS: %d \n ",err_log);
610 : glGetProgramiv(progObj, GL_LINK_STATUS, &err_log);
611 : printf("GL_LINK_STATUS: %d \n ",err_log);
612 : glGetProgramiv(progObj, GL_ATTACHED_SHADERS, &err_log);
613 : printf("GL_ATTACHED_SHADERS: %d \n ",err_log);
614 : glGetProgramiv(progObj, GL_ACTIVE_UNIFORMS, &err_log);
615 : printf("GL_ACTIVE_UNIFORMS: %d \n ",err_log);
616 : }
617 :
618 : static void gf_glQueryUniform(GF_SHADERID progObj, const char *name, int index)
619 : {
620 : GLint loc, i;
621 : GLfloat res[16];
622 :
623 : loc = glGetUniformLocation(progObj, name);
624 : if(loc<0) {
625 : GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("failed to locate uniform. exiting\n"));
626 : return;
627 : }
628 : glGetUniformfv(progObj, loc, (GLfloat *) res);
629 : GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("uniform %s has value of: ", name));
630 : for (i =0; i<index; i++)
631 : GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("%f ", res[i]));
632 : }
633 :
634 : //same here
635 : static void gf_glQueryAttrib(GF_SHADERID progObj, const char *name, int index, GLenum param)
636 : {
637 : GLint loc, i;
638 : GLfloat res[16];
639 :
640 : loc = glGetAttribLocation(progObj, name);
641 : if (loc<0) {
642 : GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("failed to locate attribute. exiting\n"));
643 : return;
644 : }
645 : glGetVertexAttribfv(loc, param, (GLfloat *) res);
646 : GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("attribute %s has value of: ", name));
647 : for( i =0; i<index; i++)
648 : GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("%f ", res[i]));
649 : }
650 :
651 : static void gf_glQueryUniforms(GF_SHADERID progObj)
652 : {
653 : GLint maxUniformLen;
654 : GLint numUniforms;
655 : char *uniformName;
656 : GLint index;
657 :
658 : glGetProgramiv(progObj, GL_ACTIVE_UNIFORMS, &numUniforms);
659 : glGetProgramiv(progObj, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformLen);
660 : uniformName = gf_malloc(sizeof(char) * maxUniformLen);
661 : for(index = 0; index < numUniforms; index++) {
662 : GLint size;
663 : GLenum type;
664 : GLint location;
665 : // Get the Uniform Info
666 : glGetActiveUniform(progObj, index, maxUniformLen, NULL, &size, &type, uniformName);
667 : // Get the uniform location
668 : location = glGetUniformLocation(progObj, uniformName);
669 : if(location) printf("uniform %s is: ",uniformName);
670 : switch(type) {
671 : case GL_FLOAT:
672 : printf("float \n");
673 : break;
674 : case GL_FLOAT_VEC2:
675 : printf("floatvec2 \n");
676 : break;
677 : case GL_FLOAT_VEC3:
678 : printf("floatvec3 \n");
679 : break;
680 : case GL_FLOAT_VEC4:
681 : printf("floatvec4 \n");
682 : break;
683 : case GL_INT:
684 : printf("int \n");
685 : break;
686 : case GL_INT_VEC2:
687 : case GL_INT_VEC3:
688 : case GL_INT_VEC4:
689 : printf("intVec \n");
690 : break;
691 : case GL_FLOAT_MAT2:
692 : case GL_FLOAT_MAT3:
693 : case GL_FLOAT_MAT4:
694 : printf("fmat \n");
695 : break;
696 : case GL_SAMPLER_2D:
697 : printf("samp2D \n");
698 : break;
699 : case GL_SAMPLER_CUBE:
700 : printf("sampCube \n");
701 : break;
702 : default:
703 : printf("other \n");
704 : break;
705 : }
706 : }
707 : gf_free(uniformName);
708 : }
709 :
710 : static void gf_glQueryAttributes(GF_SHADERID progObj)
711 : {
712 : GLint maxAttributeLen;
713 : GLint numAttributes;
714 : char *attributeName;
715 : GLint index;
716 :
717 : printf("Listing Attribs... \n");
718 : glGetProgramiv(progObj, GL_ACTIVE_ATTRIBUTES, &numAttributes);
719 : glGetProgramiv(progObj, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxAttributeLen);
720 : attributeName = gf_malloc(sizeof(char) * maxAttributeLen);
721 : for(index = 0; index < numAttributes; index++) {
722 : GLint size;
723 : GLenum type;
724 : GLint location;
725 : // Get the Attribute Info
726 : glGetActiveAttrib(progObj, index, maxAttributeLen, NULL, &size, &type, attributeName);
727 : // Get the attribute location
728 : location = glGetAttribLocation(progObj, attributeName);
729 : if(location) printf("attrib %s is: ",attributeName);
730 : switch(type) {
731 : case GL_FLOAT:
732 : printf("float \n");
733 : break;
734 : case GL_FLOAT_VEC2:
735 : printf("floatvec2 \n");
736 : break;
737 : case GL_FLOAT_VEC3:
738 : printf("floatvec3 \n");
739 : break;
740 : case GL_FLOAT_VEC4:
741 : printf("floatvec4 \n");
742 : break;
743 : case GL_INT:
744 : printf("int \n");
745 : break;
746 : case GL_INT_VEC2:
747 : case GL_INT_VEC3:
748 : case GL_INT_VEC4:
749 : printf("intVec \n");
750 : break;
751 : case GL_FLOAT_MAT2:
752 : case GL_FLOAT_MAT3:
753 : case GL_FLOAT_MAT4:
754 : printf("fmat \n");
755 : break;
756 : case GL_SAMPLER_2D:
757 : printf("samp2D \n");
758 : break;
759 : case GL_SAMPLER_CUBE:
760 : printf("sampCube \n");
761 : break;
762 : default:
763 : printf("other \n");
764 : break;
765 : }
766 : }
767 : gf_free(attributeName);
768 : }
769 : #endif
770 :
771 947 : static GF_GLProgInstance *visual_3d_build_program(GF_VisualManager *visual, u32 flags, u32 pix_fmt)
772 : {
773 : s32 linked;
774 : GF_GLProgInstance *pi;
775 :
776 947 : GF_SAFEALLOC(pi, GF_GLProgInstance);
777 947 : if (!pi) return NULL;
778 947 : pi->flags = flags;
779 947 : pi->pix_fmt = pix_fmt;
780 :
781 947 : glGetError();
782 947 : pi->prog = glCreateProgram();
783 947 : if (!pi->prog) {
784 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to create program\n"));
785 0 : gf_free(pi);
786 : return NULL;
787 : }
788 947 : pi->vertex = visual_3d_shader_with_flags(visual->compositor->vertshader , GL_VERTEX_SHADER, flags, 0);
789 947 : if (!pi->vertex) {
790 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to compile vertex shader\n"));
791 0 : DEL_PROGRAM(pi->prog)
792 0 : gf_free(pi);
793 : return NULL;
794 : }
795 947 : if (pix_fmt == GF_PIXEL_GL_EXTERNAL) {
796 0 : flags |= GF_GL_IS_ExternalOES;
797 : }
798 947 : pi->fragment = visual_3d_shader_with_flags(visual->compositor->fragshader , GL_FRAGMENT_SHADER, flags, pix_fmt);
799 947 : if (!pi->fragment) {
800 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to compile fragment shader\n"));
801 0 : DEL_PROGRAM(pi->prog)
802 0 : DEL_SHADER(pi->vertex);
803 0 : gf_free(pi);
804 : return NULL;
805 : }
806 947 : glAttachShader(pi->prog, pi->vertex);
807 : GL_CHECK_ERR();
808 947 : glAttachShader(pi->prog, pi->fragment);
809 : GL_CHECK_ERR();
810 :
811 947 : glLinkProgram(pi->prog);
812 : GL_CHECK_ERR();
813 :
814 947 : glGetProgramiv(pi->prog, GL_LINK_STATUS, &linked);
815 947 : if (!linked) {
816 : int i32CharsWritten, i32InfoLogLength;
817 : char pszInfoLog[2048];
818 0 : glGetProgramiv(pi->prog, GL_INFO_LOG_LENGTH, &i32InfoLogLength);
819 0 : glGetProgramInfoLog(pi->prog, i32InfoLogLength, &i32CharsWritten, pszInfoLog);
820 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, (pszInfoLog));
821 0 : DEL_PROGRAM(pi->prog)
822 0 : DEL_SHADER(pi->vertex);
823 0 : DEL_SHADER(pi->fragment);
824 0 : gf_free(pi);
825 : return NULL;
826 : }
827 947 : GF_LOG(GF_LOG_INFO, GF_LOG_COMPOSE, ("[Compositor] fragment shader compiled fine\n"));
828 : return pi;
829 : }
830 :
831 6627 : static Bool visual_3d_init_generic_shaders(GF_VisualManager *visual)
832 : {
833 : GF_GLProgInstance *pi;
834 6627 : if (gf_list_count(visual->compiled_programs))
835 : return GF_TRUE;
836 708 : if (!gf_file_exists(visual->compositor->vertshader))
837 : return GF_FALSE;
838 708 : if (!gf_file_exists(visual->compositor->fragshader))
839 : return GF_FALSE;
840 :
841 :
842 708 : pi = visual_3d_build_program(visual, 0, 0);
843 708 : if (!pi) return GF_FALSE;
844 :
845 708 : glDeleteShader(pi->vertex);
846 708 : glDeleteShader(pi->fragment);
847 708 : glDeleteProgram(pi->prog);
848 708 : gf_free(pi);
849 708 : return GF_TRUE;
850 : }
851 :
852 6806 : void visual_3d_init_shaders(GF_VisualManager *visual)
853 : {
854 6806 : if (visual->compositor->visual != visual)
855 : return;
856 :
857 6806 : if (!visual->compositor->gl_caps.has_shaders)
858 : return;
859 :
860 6806 : if (!visual->compositor->shader_mode_disabled) {
861 : //If we fail to configure shaders, force 2D mode
862 6627 : if (! visual_3d_init_generic_shaders(visual)) {
863 0 : visual->compositor->hybrid_opengl = GF_FALSE;
864 0 : visual->compositor->force_opengl_2d = GF_FALSE;
865 : /*force resetup*/
866 0 : visual->compositor->root_visual_setup = 0;
867 : /*force texture setup when switching to OpenGL*/
868 0 : gf_sc_reset_graphics(visual->compositor);
869 : /*force redraw*/
870 0 : gf_sc_next_frame_state(visual->compositor, GF_SC_DRAW_FRAME);
871 : }
872 : }
873 : }
874 :
875 : #endif // !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES1X)
876 :
877 :
878 651 : void visual_3d_reset_graphics(GF_VisualManager *visual)
879 : {
880 : #if !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES1X)
881 651 : if (visual->compositor->visual != visual)
882 : return;
883 :
884 604 : DEL_SHADER(visual->base_glsl_vertex);
885 604 : DEL_SHADER(visual->autostereo_glsl_fragment);
886 604 : DEL_PROGRAM(visual->autostereo_glsl_program );
887 :
888 604 : if (visual->gl_textures) {
889 1 : glDeleteTextures(visual->nb_views, visual->gl_textures);
890 1 : gf_free(visual->gl_textures);
891 1 : visual->gl_textures = NULL;
892 : }
893 604 : if (visual->autostereo_mesh) {
894 1 : mesh_free(visual->autostereo_mesh);
895 1 : visual->autostereo_mesh = NULL;
896 : }
897 :
898 841 : while (gf_list_count(visual->compiled_programs)) {
899 237 : GF_GLProgInstance *gi = gf_list_pop_back(visual->compiled_programs);
900 237 : DEL_SHADER(gi->vertex);
901 237 : DEL_SHADER(gi->fragment);
902 237 : DEL_PROGRAM(gi->prog);
903 237 : gf_free(gi);
904 : }
905 : #endif
906 : }
907 :
908 63607 : void visual_3d_set_clipper_scissor(GF_VisualManager *visual, GF_TraverseState *tr_state)
909 : {
910 : #ifndef GPAC_USE_TINYGL
911 63607 : if (visual->has_clipper_2d) {
912 : u32 x, y;
913 : u32 dw, dh;
914 3179 : glEnable(GL_SCISSOR_TEST);
915 :
916 3179 : if (visual->offscreen) {
917 0 : dw = visual->width;
918 0 : dh = visual->height;
919 : } else {
920 3179 : dw = visual->compositor->display_width;
921 3179 : dh = visual->compositor->display_height;
922 : }
923 :
924 3179 : if (visual->center_coords) {
925 3173 : x = visual->clipper_2d.x + dw / 2;
926 3173 : y = dh / 2 + visual->clipper_2d.y - visual->clipper_2d.height;
927 : } else {
928 6 : x = visual->clipper_2d.x;
929 6 : y = dh - visual->clipper_2d.y;
930 : }
931 3179 : glScissor(x, y, visual->clipper_2d.width, visual->clipper_2d.height);
932 : } else {
933 60428 : glDisable(GL_SCISSOR_TEST);
934 : }
935 : #endif
936 63607 : }
937 :
938 :
939 : #if !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES1X)
940 :
941 94940 : static void visual_3d_load_matrix_shaders(GF_SHADERID program, Fixed *mat, const char *name)
942 : {
943 : GLint loc;
944 : #ifdef GPAC_FIXED_POINT
945 : Float _mat[16];
946 : u32 i;
947 : #endif
948 :
949 94940 : loc = glGetUniformLocation(program, name);
950 94940 : if(loc<0) {
951 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("GL Error (file %s line %d): Invalid matrix name", __FILE__, __LINE__));
952 : return;
953 : }
954 : GL_CHECK_ERR()
955 :
956 : #ifdef GPAC_FIXED_POINT
957 : for (i=0; i<16; i++) _mat[i] = FIX2FLT(mat[i]);
958 : glUniformMatrix4fv(loc, 1, GL_FALSE, (GLfloat *) _mat);
959 : #else
960 94940 : glUniformMatrix4fv(loc, 1, GL_FALSE, mat);
961 : #endif
962 : GL_CHECK_ERR()
963 : }
964 :
965 : #endif
966 :
967 166 : GF_Err visual_3d_init_autostereo(GF_VisualManager *visual)
968 : {
969 : #if !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES1X)
970 : u32 bw, bh;
971 : SFVec2f s;
972 166 : Bool use_npot = visual->compositor->gl_caps.npot_texture;
973 166 : if (visual->gl_textures) return GF_OK;
974 :
975 1 : visual->gl_textures = gf_malloc(sizeof(GLuint) * visual->nb_views);
976 1 : glGenTextures(visual->nb_views, visual->gl_textures);
977 :
978 1 : bw = visual->width;
979 1 : bh = visual->height;
980 : /*main (not offscreen) visual*/
981 1 : if (visual->compositor->visual==visual) {
982 1 : bw = visual->compositor->output_width;
983 1 : bh = visual->compositor->output_height;
984 : }
985 :
986 : #ifdef GPAC_USE_GLES2
987 : use_npot = GF_TRUE;
988 : #endif
989 :
990 1 : if (use_npot) {
991 1 : visual->auto_stereo_width = bw;
992 1 : visual->auto_stereo_height = bh;
993 : } else {
994 0 : visual->auto_stereo_width = 2;
995 0 : while (visual->auto_stereo_width < bw) visual->auto_stereo_width *= 2;
996 0 : visual->auto_stereo_height = 2;
997 0 : while (visual->auto_stereo_height < bh) visual->auto_stereo_height *= 2;
998 : }
999 :
1000 1 : visual->autostereo_mesh = new_mesh();
1001 1 : s.x = INT2FIX(bw);
1002 1 : s.y = INT2FIX(bh);
1003 1 : mesh_new_rectangle(visual->autostereo_mesh, s, NULL, 0);
1004 :
1005 1 : if (! use_npot) {
1006 : u32 i;
1007 0 : Fixed max_u = INT2FIX(bw) / visual->auto_stereo_width;
1008 0 : Fixed max_v = INT2FIX(bh) / visual->auto_stereo_height;
1009 0 : for (i=0; i<visual->autostereo_mesh->v_count; i++) {
1010 0 : if (visual->autostereo_mesh->vertices[i].texcoords.x == FIX_ONE) {
1011 0 : visual->autostereo_mesh->vertices[i].texcoords.x = max_u;
1012 : }
1013 0 : if (visual->autostereo_mesh->vertices[i].texcoords.y == FIX_ONE) {
1014 0 : visual->autostereo_mesh->vertices[i].texcoords.y = max_v;
1015 : }
1016 : }
1017 : }
1018 :
1019 1 : GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Visual3D] AutoStereo initialized - width %d height %d\n", visual->auto_stereo_width, visual->auto_stereo_height) );
1020 :
1021 1 : visual_3d_init_stereo_shaders(visual);
1022 : #endif // !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES1X)
1023 :
1024 1 : return GF_OK;
1025 : }
1026 :
1027 830 : void visual_3d_end_auto_stereo_pass(GF_VisualManager *visual)
1028 : {
1029 : #if !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES1X)
1030 : u32 i;
1031 : GLint loc, loc_vertex_attrib, loc_texcoord_attrib;
1032 : Fixed hw, hh;
1033 : GF_Matrix mx;
1034 :
1035 :
1036 830 : glFlush();
1037 :
1038 : GL_CHECK_ERR()
1039 :
1040 : #ifndef GPAC_USE_GLES2
1041 830 : glEnable(GL_TEXTURE_2D);
1042 : #endif
1043 :
1044 830 : glBindTexture(GL_TEXTURE_2D, visual->gl_textures[visual->current_view]);
1045 :
1046 : #ifndef GPAC_USE_GLES2
1047 830 : glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
1048 830 : glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
1049 830 : glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
1050 830 : glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
1051 830 : glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1052 830 : glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1053 : #else
1054 : glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1055 : glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1056 : glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1057 : glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1058 : glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1059 : #endif
1060 :
1061 830 : glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, visual->auto_stereo_width, visual->auto_stereo_height, 0);
1062 : GL_CHECK_ERR()
1063 :
1064 : #ifndef GPAC_USE_GLES2
1065 830 : glDisable(GL_TEXTURE_2D);
1066 : #endif
1067 :
1068 830 : glClear(GL_DEPTH_BUFFER_BIT);
1069 : GL_CHECK_ERR()
1070 :
1071 1494 : if (visual->current_view+1<visual->nb_views) return;
1072 166 : hw = INT2FIX(visual->width);
1073 166 : hh = INT2FIX(visual->height);
1074 : /*main (not offscreen) visual*/
1075 166 : if (visual->compositor->visual==visual) {
1076 166 : hw = INT2FIX(visual->compositor->output_width);
1077 166 : hh = INT2FIX(visual->compositor->output_height);
1078 : }
1079 :
1080 166 : glViewport(0, 0, (GLsizei) hw, (GLsizei) hh );
1081 :
1082 166 : hw /= 2;
1083 166 : hh /= 2;
1084 :
1085 : /*use our program*/
1086 166 : glUseProgram(visual->autostereo_glsl_program);
1087 :
1088 : //load projection
1089 166 : gf_mx_ortho(&mx, -hw, hw, -hh, hh, -10, 100);
1090 166 : visual_3d_load_matrix_shaders(visual->autostereo_glsl_program, mx.m, "gfProjectionMatrix");
1091 :
1092 : //no need for modelview (identifty)
1093 :
1094 : /*push number of views if shader uses it*/
1095 166 : loc = glGetUniformLocation(visual->autostereo_glsl_program, "gfViewCount");
1096 166 : if (loc != -1) glUniform1i(loc, visual->nb_views);
1097 :
1098 : loc_texcoord_attrib = -1;
1099 : //setup vertex attrib
1100 166 : loc_vertex_attrib = glGetAttribLocation(visual->autostereo_glsl_program, "gfVertex");
1101 166 : if (loc_vertex_attrib>=0) {
1102 166 : glVertexAttribPointer(loc_vertex_attrib, 3, GL_FLOAT, GL_FALSE, sizeof(GF_Vertex), &visual->autostereo_mesh->vertices[0].pos);
1103 166 : glEnableVertexAttribArray(loc_vertex_attrib);
1104 :
1105 : GL_CHECK_ERR()
1106 :
1107 : //setup texcoord location
1108 166 : loc_texcoord_attrib = glGetAttribLocation(visual->autostereo_glsl_program, "gfTextureCoordinates");
1109 166 : if (loc_texcoord_attrib>=0) {
1110 : char szTex[100];
1111 166 : glVertexAttribPointer(loc_texcoord_attrib, 2, GL_FLOAT, GL_FALSE, sizeof(GF_Vertex), &visual->autostereo_mesh->vertices[0].texcoords);
1112 166 : glEnableVertexAttribArray(loc_texcoord_attrib);
1113 :
1114 : GL_CHECK_ERR()
1115 :
1116 : /*bind all our textures*/
1117 1162 : for (i=0; i<visual->nb_views; i++) {
1118 830 : sprintf(szTex, "gfView%d", i+1);
1119 830 : loc = glGetUniformLocation(visual->autostereo_glsl_program, szTex);
1120 830 : if (loc == -1) continue;
1121 :
1122 830 : glActiveTexture(GL_TEXTURE0 + i);
1123 :
1124 : #ifndef GPAC_USE_GLES2
1125 830 : glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1126 830 : glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1127 830 : glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1128 830 : glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1129 830 : glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
1130 : #endif
1131 :
1132 : GL_CHECK_ERR()
1133 :
1134 830 : glBindTexture(GL_TEXTURE_2D, visual->gl_textures[i]);
1135 :
1136 : GL_CHECK_ERR()
1137 :
1138 830 : glUniform1i(loc, i);
1139 :
1140 : GL_CHECK_ERR()
1141 : }
1142 :
1143 : //draw
1144 : #if defined(GPAC_USE_GLES2)
1145 : glDrawElements(GL_TRIANGLES, visual->autostereo_mesh->i_count, GL_UNSIGNED_SHORT, visual->autostereo_mesh->indices);
1146 : #else
1147 166 : glDrawElements(GL_TRIANGLES, visual->autostereo_mesh->i_count, GL_UNSIGNED_INT, visual->autostereo_mesh->indices);
1148 : #endif
1149 :
1150 : GL_CHECK_ERR()
1151 : }
1152 : }
1153 :
1154 :
1155 166 : if (loc_vertex_attrib>=0) glDisableVertexAttribArray(loc_vertex_attrib);
1156 166 : if (loc_texcoord_attrib>=0) glDisableVertexAttribArray(loc_texcoord_attrib);
1157 : GL_CHECK_ERR()
1158 :
1159 166 : glUseProgram(0);
1160 :
1161 : #ifndef GPAC_USE_GLES2
1162 : /*not sure why this is needed but it prevents a texturing bug on XP on parallels*/
1163 166 : glActiveTexture(GL_TEXTURE0);
1164 : GL_CHECK_ERR()
1165 :
1166 166 : glBindTexture(GL_TEXTURE_2D, 0);
1167 166 : glDisable(GL_TEXTURE_2D);
1168 : #endif
1169 :
1170 : GL_CHECK_ERR()
1171 : #endif // !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES1X)
1172 :
1173 : }
1174 :
1175 :
1176 12541 : static void visual_3d_setup_quality(GF_VisualManager *visual)
1177 : {
1178 : #ifndef GPAC_USE_GLES2
1179 :
1180 12541 : if (visual->compositor->fast) {
1181 0 : glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
1182 0 : glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
1183 0 : glHint(GL_LINE_SMOOTH_HINT, GL_FASTEST);
1184 : #ifdef GL_POLYGON_SMOOTH_HINT
1185 0 : glHint(GL_POLYGON_SMOOTH_HINT, GL_FASTEST);
1186 : #endif
1187 : } else {
1188 12541 : glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
1189 12541 : glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
1190 12541 : glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
1191 : #ifdef GL_POLYGON_SMOOTH_HINT
1192 12541 : glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
1193 : #endif
1194 : }
1195 :
1196 12541 : if (visual->compositor->aa == GF_ANTIALIAS_FULL) {
1197 12541 : glEnable(GL_LINE_SMOOTH);
1198 : #ifndef GPAC_USE_GLES1X
1199 12541 : if (visual->compositor->paa)
1200 0 : glEnable(GL_POLYGON_SMOOTH);
1201 : else
1202 12541 : glDisable(GL_POLYGON_SMOOTH);
1203 : #endif
1204 : } else {
1205 0 : glDisable(GL_LINE_SMOOTH);
1206 : #ifndef GPAC_USE_GLES1X
1207 0 : glDisable(GL_POLYGON_SMOOTH);
1208 : #endif
1209 : }
1210 :
1211 : #endif
1212 :
1213 12541 : }
1214 :
1215 8025 : void visual_3d_setup(GF_VisualManager *visual)
1216 : {
1217 : //in non-player mode, we might not be the only ones using the gl context !!
1218 8025 : if (visual->compositor->player && visual->gl_setup) {
1219 237 : visual->has_fog = GF_FALSE;
1220 237 : glClear(GL_DEPTH_BUFFER_BIT);
1221 237 : return;
1222 : }
1223 :
1224 : #ifndef GPAC_USE_TINYGL
1225 7788 : glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1226 7788 : glDepthFunc(GL_LEQUAL);
1227 : #endif
1228 7788 : glEnable(GL_DEPTH_TEST);
1229 7788 : glFrontFace(GL_CCW);
1230 7788 : glCullFace(GL_BACK);
1231 :
1232 : #ifdef GPAC_USE_GLES1X
1233 : glClearDepthx(FIX_ONE);
1234 : glLightModelx(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
1235 : glMaterialx(GL_FRONT_AND_BACK, GL_SHININESS, FLT2FIX(0.2f * 128) );
1236 : glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1237 : #elif defined(GPAC_USE_GLES2)
1238 : glClearDepthf(1.0f);
1239 : #else
1240 7788 : glClearDepth(1.0f);
1241 7788 : glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE);
1242 7788 : glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
1243 7788 : glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, (float) (0.2 * 128));
1244 : #endif
1245 :
1246 :
1247 : #ifndef GPAC_USE_GLES2
1248 7788 : glDisable(GL_TEXTURE_2D);
1249 7788 : glShadeModel(GL_SMOOTH);
1250 7788 : glGetIntegerv(GL_MAX_LIGHTS, (GLint*)&visual->max_lights);
1251 7788 : if (visual->max_lights>GF_MAX_GL_LIGHTS)
1252 7788 : visual->max_lights=GF_MAX_GL_LIGHTS;
1253 :
1254 : #ifdef GL_MAX_CLIP_PLANES
1255 7788 : glGetIntegerv(GL_MAX_CLIP_PLANES, (GLint*)&visual->max_clips);
1256 7788 : if (visual->max_clips>GF_MAX_GL_CLIPS)
1257 7788 : visual->max_clips=GF_MAX_GL_CLIPS;
1258 : #endif
1259 :
1260 7788 : glDisable(GL_POINT_SMOOTH);
1261 7788 : glDisable(GL_COLOR_MATERIAL);
1262 7788 : glDisable(GL_LIGHTING);
1263 7788 : glDisable(GL_BLEND);
1264 7788 : glDisable(GL_TEXTURE_2D);
1265 7788 : glDisable(GL_CULL_FACE);
1266 7788 : glDisable(GL_FOG);
1267 : /*Note: we cannot enable/disable normalization on the fly, because we have no clue when the GL implementation
1268 : will actually compute the related fragments. Since a typical world always use scaling, we always turn normalization on
1269 : to avoid tracking scale*/
1270 7788 : glEnable(GL_NORMALIZE);
1271 : #endif //GLES2
1272 :
1273 7788 : visual_3d_setup_quality(visual);
1274 :
1275 7788 : glDisable(GL_BLEND);
1276 7788 : glDisable(GL_CULL_FACE);
1277 7788 : visual->has_fog = GF_FALSE;
1278 7788 : visual->max_lights=GF_MAX_GL_LIGHTS;
1279 7788 : visual->max_clips=GF_MAX_GL_CLIPS;
1280 :
1281 7788 : visual->gl_setup = GF_TRUE;
1282 :
1283 7788 : glClear(GL_DEPTH_BUFFER_BIT);
1284 : }
1285 :
1286 9506 : void visual_3d_set_background_state(GF_VisualManager *visual, Bool on)
1287 : {
1288 : #ifndef GPAC_USE_GLES2
1289 9506 : if (on) {
1290 4753 : glDisable(GL_LIGHTING);
1291 4753 : glDisable(GL_FOG);
1292 4753 : glDisable(GL_LINE_SMOOTH);
1293 :
1294 4753 : glDisable(GL_BLEND);
1295 : #ifndef GPAC_USE_GLES1X
1296 4753 : glDisable(GL_POLYGON_SMOOTH);
1297 : #endif
1298 4753 : glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
1299 4753 : glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
1300 : } else {
1301 4753 : visual_3d_setup_quality(visual);
1302 : }
1303 : #endif
1304 :
1305 : visual_3d_enable_depth_buffer(visual, ! on);
1306 9506 : }
1307 :
1308 :
1309 :
1310 18728 : void visual_3d_enable_antialias(GF_VisualManager *visual, Bool bOn)
1311 : {
1312 : #ifndef GPAC_USE_GLES2
1313 :
1314 18728 : if (bOn) {
1315 15027 : glEnable(GL_LINE_SMOOTH);
1316 : #ifndef GPAC_USE_GLES1X
1317 15027 : if (visual->compositor->paa)
1318 0 : glEnable(GL_POLYGON_SMOOTH);
1319 : else
1320 15027 : glDisable(GL_POLYGON_SMOOTH);
1321 : #endif
1322 : } else {
1323 3701 : glDisable(GL_LINE_SMOOTH);
1324 : #ifndef GPAC_USE_GLES1X
1325 3701 : glDisable(GL_POLYGON_SMOOTH);
1326 : #endif
1327 :
1328 : /* glDisable(GL_DITHER);
1329 : glDisable(GL_POINT_SMOOTH);
1330 : glHint(GL_POINT_SMOOTH, GL_DONT_CARE);
1331 : glHint(GL_LINE_SMOOTH, GL_DONT_CARE);
1332 : glHint(GL_POLYGON_SMOOTH_HINT, GL_DONT_CARE);
1333 :
1334 : glDisable( GL_MULTISAMPLE_ARB);
1335 : */
1336 : }
1337 :
1338 : #endif
1339 18728 : }
1340 :
1341 8742 : void visual_3d_enable_depth_buffer(GF_VisualManager *visual, Bool on)
1342 : {
1343 18248 : if (on) {
1344 11854 : glEnable(GL_DEPTH_TEST);
1345 : } else {
1346 6394 : glDisable(GL_DEPTH_TEST);
1347 : }
1348 8742 : }
1349 :
1350 9936 : void visual_3d_set_viewport(GF_VisualManager *visual, GF_Rect vp)
1351 : {
1352 9936 : glViewport(FIX2INT(vp.x), FIX2INT(vp.y), FIX2INT(vp.width), FIX2INT(vp.height));
1353 9936 : }
1354 :
1355 8742 : void visual_3d_set_scissor(GF_VisualManager *visual, GF_Rect *vp)
1356 : {
1357 : #ifndef GPAC_USE_TINYGL
1358 8742 : if (vp) {
1359 0 : glEnable(GL_SCISSOR_TEST);
1360 0 : glScissor(FIX2INT(vp->x), FIX2INT(vp->y), FIX2INT(vp->width), FIX2INT(vp->height));
1361 : } else {
1362 8742 : glDisable(GL_SCISSOR_TEST);
1363 : }
1364 : #endif
1365 8742 : }
1366 :
1367 1945 : void visual_3d_clear_depth(GF_VisualManager *visual)
1368 : {
1369 1945 : glClear(GL_DEPTH_BUFFER_BIT);
1370 1945 : }
1371 :
1372 367016 : static void visual_3d_draw_aabb_node(GF_TraverseState *tr_state, GF_Mesh *mesh, u32 prim_type, GF_Plane *fplanes, u32 *p_indices, AABBNode *n, void *idx_addr)
1373 : {
1374 : u32 i;
1375 :
1376 : /*if not leaf do cull*/
1377 367016 : if (n->pos) {
1378 : u32 p_idx, cull;
1379 : SFVec3f vertices[8];
1380 : /*get box vertices*/
1381 229550 : gf_bbox_get_vertices(n->min, n->max, vertices);
1382 : cull = CULL_INSIDE;
1383 1060798 : for (i=0; i<6; i++) {
1384 1018479 : p_idx = p_indices[i];
1385 : /*check p-vertex: if not in plane, we're out (since p-vertex is the closest point to the plane)*/
1386 1018479 : if (gf_plane_get_distance(&fplanes[i], &vertices[p_idx])<0) {
1387 : cull = CULL_OUTSIDE;
1388 : break;
1389 : }
1390 : /*check n-vertex: if not in plane, we're intersecting*/
1391 1011346 : if (gf_plane_get_distance(&fplanes[i], &vertices[7-p_idx])<0) {
1392 : cull = CULL_INTERSECTS;
1393 : break;
1394 : }
1395 : }
1396 :
1397 416781 : if (cull==CULL_OUTSIDE) return;
1398 :
1399 222417 : if (cull==CULL_INTERSECTS) {
1400 180098 : visual_3d_draw_aabb_node(tr_state, mesh, prim_type, fplanes, p_indices, n->pos, idx_addr);
1401 180098 : visual_3d_draw_aabb_node(tr_state, mesh, prim_type, fplanes, p_indices, n->neg, idx_addr);
1402 180098 : return;
1403 : }
1404 : }
1405 :
1406 : /*the good thing about the structure of the aabb tree is that the primitive idx is valid for both
1407 : leaf and non-leaf nodes, so we can use it as soon as we have a CULL_INSIDE.
1408 : However we must push triangles one by one since primitive order may have been swapped when
1409 : building the AABB tree*/
1410 3509026 : for (i=0; i<n->nb_idx; i++) {
1411 3509026 : u32 idx = 3*n->indices[i];
1412 : void *vbi_addr;
1413 3509026 : if (!idx_addr) vbi_addr = (void *) PTR_TO_U_CAST ( sizeof(IDX_TYPE) * idx );
1414 0 : else vbi_addr = &mesh->indices[idx];
1415 :
1416 : #if defined(GPAC_USE_GLES1X) || defined(GPAC_USE_GLES2)
1417 : glDrawElements(prim_type, 3, GL_UNSIGNED_SHORT, vbi_addr);
1418 : #else
1419 3509026 : glDrawElements(prim_type, 3, GL_UNSIGNED_INT, vbi_addr);
1420 : #endif
1421 : }
1422 : }
1423 :
1424 : #ifndef GPAC_USE_GLES2
1425 :
1426 : static void visual_3d_matrix_load(GF_VisualManager *visual, Fixed *mat)
1427 : {
1428 : #if defined(GPAC_FIXED_POINT)
1429 : Float _mat[16];
1430 : u32 i;
1431 : #endif
1432 :
1433 314 : if (!mat) {
1434 0 : glLoadIdentity();
1435 : return;
1436 : }
1437 : #if defined(GPAC_USE_GLES1X) && defined(GPAC_FIXED_POINT)
1438 : glLoadMatrixx(mat);
1439 : #elif defined(GPAC_FIXED_POINT)
1440 : for (i=0; i<16; i++) _mat[i] = FIX2FLT(mat[i]);
1441 : glLoadMatrixf(_mat);
1442 : #else
1443 784 : glLoadMatrixf(mat);
1444 : #endif
1445 : }
1446 :
1447 316 : static void visual_3d_update_matrices(GF_TraverseState *tr_state)
1448 : {
1449 : GF_Matrix mx;
1450 316 : if (!tr_state || !tr_state->camera) return;
1451 316 : if (tr_state->visual->needs_projection_matrix_reload) {
1452 314 : tr_state->visual->needs_projection_matrix_reload = 0;
1453 314 : glMatrixMode(GL_PROJECTION);
1454 314 : visual_3d_matrix_load(tr_state->visual, tr_state->camera->projection.m);
1455 314 : glMatrixMode(GL_MODELVIEW);
1456 : }
1457 :
1458 316 : gf_mx_copy(mx, tr_state->camera->modelview.m);
1459 316 : gf_mx_add_matrix(&mx, &tr_state->model_matrix);
1460 : visual_3d_matrix_load(tr_state->visual, (Fixed *) &mx);
1461 : }
1462 :
1463 :
1464 164 : static void visual_3d_set_clippers(GF_VisualManager *visual, GF_TraverseState *tr_state)
1465 : {
1466 : #ifdef GL_MAX_CLIP_PLANES
1467 : u32 i;
1468 : GF_Matrix inv_mx;
1469 :
1470 164 : if (!visual->num_clips)
1471 164 : return;
1472 :
1473 0 : gf_mx_copy(inv_mx, tr_state->model_matrix);
1474 0 : gf_mx_inverse(&inv_mx);
1475 :
1476 0 : for (i=0; i<visual->num_clips; i++) {
1477 0 : u32 idx = GL_CLIP_PLANE0 + i;
1478 : #ifdef GPAC_USE_GLES1X
1479 : Fixed g[4];
1480 : #else
1481 : Double g[4];
1482 : #endif
1483 : GF_Matrix mx;
1484 0 : GF_Plane p = visual->clippers[i].p;
1485 :
1486 0 : if (visual->clippers[i].is_2d_clip) {
1487 0 : visual_3d_matrix_load(tr_state->visual, tr_state->camera->modelview.m);
1488 : } else {
1489 : gf_mx_copy(mx, inv_mx);
1490 0 : if (visual->clippers[i].mx_clipper != NULL) {
1491 0 : gf_mx_add_matrix(&mx, visual->clippers[i].mx_clipper);
1492 : }
1493 0 : gf_mx_apply_plane(&mx, &p);
1494 : }
1495 :
1496 : #if defined(GPAC_USE_GLES1X) && defined(GPAC_FIXED_POINT)
1497 : g[0] = p.normal.x;
1498 : g[1] = p.normal.y;
1499 : g[2] = p.normal.z;
1500 : g[3] = p.d;
1501 : glClipPlanex(idx, g);
1502 : #else
1503 0 : g[0] = FIX2FLT(p.normal.x);
1504 0 : g[1] = FIX2FLT(p.normal.y);
1505 0 : g[2] = FIX2FLT(p.normal.z);
1506 0 : g[3] = FIX2FLT(p.d);
1507 :
1508 : #if defined(GPAC_USE_GLES1X)
1509 : glClipPlanef(idx, g);
1510 : #else
1511 0 : glClipPlane(idx, g);
1512 : #endif
1513 :
1514 : #endif
1515 0 : glEnable(idx);
1516 :
1517 0 : if (visual->clippers[i].is_2d_clip) {
1518 0 : visual_3d_update_matrices(tr_state);
1519 : }
1520 :
1521 : }
1522 : #endif
1523 :
1524 : }
1525 :
1526 : static void visual_3d_reset_clippers(GF_VisualManager *visual)
1527 : {
1528 : #ifdef GL_MAX_CLIP_PLANES
1529 : u32 i;
1530 0 : for (i=0; i<visual->num_clips; i++) {
1531 0 : glDisable(GL_CLIP_PLANE0 + i);
1532 : }
1533 : #endif
1534 : }
1535 :
1536 :
1537 164 : void visual_3d_reset_lights(GF_VisualManager *visual)
1538 : {
1539 : u32 i;
1540 164 : if (!visual->num_lights) return;
1541 152 : for (i=0; i<visual->num_lights; i++) {
1542 152 : glDisable(GL_LIGHT0 + i);
1543 : }
1544 152 : glDisable(GL_LIGHTING);
1545 : }
1546 :
1547 :
1548 164 : static void visual_3d_set_lights(GF_VisualManager *visual)
1549 : {
1550 : u32 i;
1551 : #if defined(GPAC_USE_GLES1X) && defined(GPAC_FIXED_POINT)
1552 : Fixed vals[4], exp;
1553 : #else
1554 : Float vals[4], intensity, cutOffAngle, beamWidth, ambientIntensity, exp;
1555 : #endif
1556 :
1557 176 : if (!visual->num_lights) return;
1558 :
1559 152 : for (i=0; i<visual->num_lights; i++) {
1560 : GF_Matrix mx;
1561 : GF_LightInfo *li = &visual->lights[i];
1562 152 : GLint iLight = GL_LIGHT0 + i;
1563 152 : if(li->type==3) {
1564 152 : gf_mx_init(mx);
1565 : } else {
1566 0 : gf_mx_copy(mx, visual->camera.modelview.m);
1567 0 : gf_mx_add_matrix(&mx, &li->light_mx);
1568 : }
1569 : visual_3d_matrix_load(visual, mx.m);
1570 :
1571 152 : glEnable(iLight);
1572 :
1573 152 : switch (li->type) {
1574 : //directional light
1575 152 : case 0:
1576 : case 3:
1577 : #if defined(GPAC_USE_GLES1X) && defined(GPAC_FIXED_POINT)
1578 : vals[0] = -li->direction.x;
1579 : vals[1] = -li->direction.y;
1580 : vals[2] = -li->direction.z;
1581 : vals[3] = 0;
1582 : glLightxv(iLight, GL_POSITION, vals);
1583 : vals[0] = gf_mulfix(li->color.red, li->intensity);
1584 : vals[1] = gf_mulfix(li->color.green, li->intensity);
1585 : vals[2] = gf_mulfix(li->color.blue, li->intensity);
1586 : vals[3] = FIX_ONE;
1587 : glLightxv(iLight, GL_DIFFUSE, vals);
1588 : glLightxv(iLight, GL_SPECULAR, vals);
1589 : vals[0] = gf_mulfix(li->color.red, li->ambientIntensity);
1590 : vals[1] = gf_mulfix(li->color.green, li->ambientIntensity);
1591 : vals[2] = gf_mulfix(li->color.blue, li->ambientIntensity);
1592 : vals[3] = FIX_ONE;
1593 : glLightxv(iLight, GL_AMBIENT, vals);
1594 :
1595 : glLightx(iLight, GL_CONSTANT_ATTENUATION, FIX_ONE);
1596 : glLightx(iLight, GL_LINEAR_ATTENUATION, 0);
1597 : glLightx(iLight, GL_QUADRATIC_ATTENUATION, 0);
1598 : glLightx(iLight, GL_SPOT_CUTOFF, INT2FIX(180) );
1599 : #else
1600 152 : ambientIntensity = FIX2FLT(li->ambientIntensity);
1601 152 : intensity = FIX2FLT(li->intensity);
1602 :
1603 152 : vals[0] = -FIX2FLT(li->direction.x);
1604 152 : vals[1] = -FIX2FLT(li->direction.y);
1605 152 : vals[2] = -FIX2FLT(li->direction.z);
1606 152 : vals[3] = 0;
1607 152 : glLightfv(iLight, GL_POSITION, vals);
1608 152 : vals[0] = FIX2FLT(li->color.red)*intensity;
1609 152 : vals[1] = FIX2FLT(li->color.green)*intensity;
1610 152 : vals[2] = FIX2FLT(li->color.blue)*intensity;
1611 152 : vals[3] = 1;
1612 152 : glLightfv(iLight, GL_DIFFUSE, vals);
1613 152 : glLightfv(iLight, GL_SPECULAR, vals);
1614 152 : vals[0] = FIX2FLT(li->color.red)*ambientIntensity;
1615 152 : vals[1] = FIX2FLT(li->color.green)*ambientIntensity;
1616 152 : vals[2] = FIX2FLT(li->color.blue)*ambientIntensity;
1617 152 : vals[3] = 1;
1618 152 : glLightfv(iLight, GL_AMBIENT, vals);
1619 :
1620 152 : glLightf(iLight, GL_CONSTANT_ATTENUATION, 1.0f);
1621 152 : glLightf(iLight, GL_LINEAR_ATTENUATION, 0);
1622 152 : glLightf(iLight, GL_QUADRATIC_ATTENUATION, 0);
1623 152 : glLightf(iLight, GL_SPOT_CUTOFF, 180);
1624 : #endif
1625 152 : break;
1626 :
1627 :
1628 : //spot light
1629 0 : case 1:
1630 : #ifndef GPAC_USE_GLES1X
1631 0 : ambientIntensity = FIX2FLT(li->ambientIntensity);
1632 0 : intensity = FIX2FLT(li->intensity);
1633 0 : cutOffAngle = FIX2FLT(li->cutOffAngle);
1634 0 : beamWidth = FIX2FLT(li->beamWidth);
1635 : #endif
1636 :
1637 : #if defined(GPAC_USE_GLES1X) && defined(GPAC_FIXED_POINT)
1638 : vals[0] = li->direction.x;
1639 : vals[1] = li->direction.y;
1640 : vals[2] = li->direction.z;
1641 : vals[3] = FIX_ONE;
1642 : glLightxv(iLight, GL_SPOT_DIRECTION, vals);
1643 : vals[0] = li->position.x;
1644 : vals[1] = li->position.y;
1645 : vals[2] = li->position.z;
1646 : vals[3] = FIX_ONE;
1647 : glLightxv(iLight, GL_POSITION, vals);
1648 : glLightx(iLight, GL_CONSTANT_ATTENUATION, li->attenuation.x ? li->attenuation.x : FIX_ONE);
1649 : glLightx(iLight, GL_LINEAR_ATTENUATION, li->attenuation.y);
1650 : glLightx(iLight, GL_QUADRATIC_ATTENUATION, li->attenuation.z);
1651 : vals[0] = gf_mulfix(li->color.red, li->intensity);
1652 : vals[1] = gf_mulfix(li->color.green, li->intensity);
1653 : vals[2] = gf_mulfix(li->color.blue, li->intensity);
1654 : vals[3] = FIX_ONE;
1655 : glLightxv(iLight, GL_DIFFUSE, vals);
1656 : glLightxv(iLight, GL_SPECULAR, vals);
1657 : vals[0] = gf_mulfix(li->color.red, li->ambientIntensity);
1658 : vals[1] = gf_mulfix(li->color.green, li->ambientIntensity);
1659 : vals[2] = gf_mulfix(li->color.blue, li->ambientIntensity);
1660 : vals[3] = FIX_ONE;
1661 : glLightxv(iLight, GL_AMBIENT, vals);
1662 :
1663 : if (!li->beamWidth) exp = FIX_ONE;
1664 : else if (li->beamWidth > li->cutOffAngle) exp = 0;
1665 : else {
1666 : exp = FIX_ONE - gf_cos(li->beamWidth);
1667 : if (exp>FIX_ONE) exp = FIX_ONE;
1668 : }
1669 : glLightx(iLight, GL_SPOT_EXPONENT, exp*128);
1670 : glLightx(iLight, GL_SPOT_CUTOFF, gf_divfix(180*li->cutOffAngle, GF_PI) );
1671 : #else
1672 0 : vals[0] = FIX2FLT(li->direction.x);
1673 0 : vals[1] = FIX2FLT(li->direction.y);
1674 0 : vals[2] = FIX2FLT(li->direction.z);
1675 0 : vals[3] = 1;
1676 0 : glLightfv(iLight, GL_SPOT_DIRECTION, vals);
1677 0 : vals[0] = FIX2FLT(li->position.x);
1678 0 : vals[1] = FIX2FLT(li->position.y);
1679 0 : vals[2] = FIX2FLT(li->position.z);
1680 0 : vals[3] = 1;
1681 0 : glLightfv(iLight, GL_POSITION, vals);
1682 0 : glLightf(iLight, GL_CONSTANT_ATTENUATION, li->attenuation.x ? FIX2FLT(li->attenuation.x) : 1.0f);
1683 0 : glLightf(iLight, GL_LINEAR_ATTENUATION, FIX2FLT(li->attenuation.y));
1684 0 : glLightf(iLight, GL_QUADRATIC_ATTENUATION, FIX2FLT(li->attenuation.z));
1685 0 : vals[0] = FIX2FLT(li->color.red)*intensity;
1686 0 : vals[1] = FIX2FLT(li->color.green)*intensity;
1687 0 : vals[2] = FIX2FLT(li->color.blue)*intensity;
1688 0 : vals[3] = 1;
1689 0 : glLightfv(iLight, GL_DIFFUSE, vals);
1690 0 : glLightfv(iLight, GL_SPECULAR, vals);
1691 0 : vals[0] = FIX2FLT(li->color.red)*ambientIntensity;
1692 0 : vals[1] = FIX2FLT(li->color.green)*ambientIntensity;
1693 0 : vals[2] = FIX2FLT(li->color.blue)*ambientIntensity;
1694 0 : vals[3] = 1;
1695 0 : glLightfv(iLight, GL_AMBIENT, vals);
1696 :
1697 : //glLightf(iLight, GL_SPOT_EXPONENT, 0.5f * (beamWidth+0.001f) /*(Float) (0.5 * log(0.5) / log(cos(beamWidth)) ) */);
1698 0 : if (!beamWidth) exp = 1;
1699 0 : else if (beamWidth>cutOffAngle) exp = 0;
1700 : else {
1701 0 : exp = 1.0f - (Float) cos(beamWidth);
1702 0 : if (exp>1) exp = 1;
1703 : }
1704 0 : glLightf(iLight, GL_SPOT_EXPONENT, exp*128);
1705 0 : glLightf(iLight, GL_SPOT_CUTOFF, 180*cutOffAngle/FIX2FLT(GF_PI));
1706 : #endif
1707 0 : break;
1708 :
1709 :
1710 : //point light
1711 0 : case 2:
1712 : #if defined(GPAC_USE_GLES1X) && defined(GPAC_FIXED_POINT)
1713 : vals[0] = li->position.x;
1714 : vals[1] = li->position.y;
1715 : vals[2] = li->position.z;
1716 : vals[3] = FIX_ONE;
1717 : glLightxv(iLight, GL_POSITION, vals);
1718 : glLightx(iLight, GL_CONSTANT_ATTENUATION, li->attenuation.x ? li->attenuation.x : FIX_ONE);
1719 : glLightx(iLight, GL_LINEAR_ATTENUATION, li->attenuation.y);
1720 : glLightx(iLight, GL_QUADRATIC_ATTENUATION, li->attenuation.z);
1721 : vals[0] = gf_mulfix(li->color.red, li->intensity);
1722 : vals[1] = gf_mulfix(li->color.green, li->intensity);
1723 : vals[2] = gf_mulfix(li->color.blue, li->intensity);
1724 : vals[3] = FIX_ONE;
1725 : glLightxv(iLight, GL_DIFFUSE, vals);
1726 : glLightxv(iLight, GL_SPECULAR, vals);
1727 : vals[0] = gf_mulfix(li->color.red, li->ambientIntensity);
1728 : vals[1] = gf_mulfix(li->color.green, li->ambientIntensity);
1729 : vals[2] = gf_mulfix(li->color.blue, li->ambientIntensity);
1730 : vals[3] = FIX_ONE;
1731 : glLightxv(iLight, GL_AMBIENT, vals);
1732 :
1733 : glLightx(iLight, GL_SPOT_EXPONENT, 0);
1734 : glLightx(iLight, GL_SPOT_CUTOFF, INT2FIX(180) );
1735 : #else
1736 0 : ambientIntensity = FIX2FLT(li->ambientIntensity);
1737 0 : intensity = FIX2FLT(li->intensity);
1738 :
1739 0 : vals[0] = FIX2FLT(li->position.x);
1740 0 : vals[1] = FIX2FLT(li->position.y);
1741 0 : vals[2] = FIX2FLT(li->position.z);
1742 0 : vals[3] = 1;
1743 0 : glLightfv(iLight, GL_POSITION, vals);
1744 0 : glLightf(iLight, GL_CONSTANT_ATTENUATION, li->attenuation.x ? FIX2FLT(li->attenuation.x) : 1.0f);
1745 0 : glLightf(iLight, GL_LINEAR_ATTENUATION, FIX2FLT(li->attenuation.y));
1746 0 : glLightf(iLight, GL_QUADRATIC_ATTENUATION, FIX2FLT(li->attenuation.z));
1747 0 : vals[0] = FIX2FLT(li->color.red)*intensity;
1748 0 : vals[1] = FIX2FLT(li->color.green)*intensity;
1749 0 : vals[2] = FIX2FLT(li->color.blue)*intensity;
1750 0 : vals[3] = 1;
1751 0 : glLightfv(iLight, GL_DIFFUSE, vals);
1752 0 : glLightfv(iLight, GL_SPECULAR, vals);
1753 0 : vals[0] = FIX2FLT(li->color.red)*ambientIntensity;
1754 0 : vals[1] = FIX2FLT(li->color.green)*ambientIntensity;
1755 0 : vals[2] = FIX2FLT(li->color.blue)*ambientIntensity;
1756 0 : vals[3] = 1;
1757 0 : glLightfv(iLight, GL_AMBIENT, vals);
1758 :
1759 0 : glLightf(iLight, GL_SPOT_EXPONENT, 0);
1760 0 : glLightf(iLight, GL_SPOT_CUTOFF, 180);
1761 : #endif
1762 0 : break;
1763 : }
1764 : }
1765 :
1766 152 : glEnable(GL_LIGHTING);
1767 :
1768 : }
1769 :
1770 151 : void visual_3d_enable_fog(GF_VisualManager *visual)
1771 : {
1772 :
1773 : #ifndef GPAC_USE_TINYGL
1774 :
1775 : #if defined(GPAC_USE_GLES1X) && defined(GPAC_FIXED_POINT)
1776 : Fixed vals[4];
1777 : glEnable(GL_FOG);
1778 : if (!visual->fog_type) glFogx(GL_FOG_MODE, GL_LINEAR);
1779 : else if (visual->fog_type==1) glFogx(GL_FOG_MODE, GL_EXP);
1780 : else if (visual->fog_type==2) glFogx(GL_FOG_MODE, GL_EXP2);
1781 : glFogx(GL_FOG_DENSITY, visual->fog_density);
1782 : glFogx(GL_FOG_START, 0);
1783 : glFogx(GL_FOG_END, visual->fog_visibility);
1784 : vals[0] = visual->fog_color.red;
1785 : vals[1] = visual->fog_color.green;
1786 : vals[2] = visual->fog_color.blue;
1787 : vals[3] = FIX_ONE;
1788 : glFogxv(GL_FOG_COLOR, vals);
1789 : glHint(GL_FOG_HINT, visual->compositor->fast ? GL_FASTEST : GL_NICEST);
1790 : #else
1791 : Float vals[4];
1792 151 : glEnable(GL_FOG);
1793 :
1794 : #if defined(GPAC_USE_GLES1X)
1795 : if (!visual->fog_type) glFogf(GL_FOG_MODE, GL_LINEAR);
1796 : else if (visual->fog_type==1) glFogf(GL_FOG_MODE, GL_EXP);
1797 : else if (visual->fog_type==2) glFogf(GL_FOG_MODE, GL_EXP2);
1798 : #else
1799 151 : if (!visual->fog_type) glFogi(GL_FOG_MODE, GL_LINEAR);
1800 0 : else if (visual->fog_type==1) glFogi(GL_FOG_MODE, GL_EXP);
1801 0 : else if (visual->fog_type==2) glFogi(GL_FOG_MODE, GL_EXP2);
1802 : #endif
1803 :
1804 151 : glFogf(GL_FOG_DENSITY, FIX2FLT(visual->fog_density));
1805 151 : glFogf(GL_FOG_START, 0);
1806 151 : glFogf(GL_FOG_END, FIX2FLT(visual->fog_visibility));
1807 151 : vals[0] = FIX2FLT(visual->fog_color.red);
1808 151 : vals[1] = FIX2FLT(visual->fog_color.green);
1809 151 : vals[2] = FIX2FLT(visual->fog_color.blue);
1810 151 : vals[3] = 1;
1811 151 : glFogfv(GL_FOG_COLOR, vals);
1812 151 : glHint(GL_FOG_HINT, visual->compositor->fast ? GL_FASTEST : GL_NICEST);
1813 : #endif
1814 :
1815 : #endif
1816 :
1817 151 : }
1818 :
1819 : #endif // ! GPAC_USE_GLES2
1820 :
1821 :
1822 63607 : static void visual_3d_do_draw_mesh(GF_TraverseState *tr_state, GF_Mesh *mesh)
1823 : {
1824 : u32 prim_type;
1825 : GF_Matrix mx;
1826 : u32 i, p_idx[6];
1827 : void *idx_addr = NULL;
1828 : GF_Plane fplanes[6];
1829 :
1830 :
1831 63607 : switch (mesh->mesh_type) {
1832 : case MESH_LINESET:
1833 : prim_type = GL_LINES;
1834 : break;
1835 282 : case MESH_POINTSET:
1836 : prim_type = GL_POINTS;
1837 282 : break;
1838 28238 : default:
1839 : prim_type = GL_TRIANGLES;
1840 28238 : break;
1841 : }
1842 :
1843 63607 : if (mesh->vbo_idx) {
1844 53238 : glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->vbo_idx);
1845 : } else {
1846 10369 : idx_addr = mesh->indices;
1847 : }
1848 :
1849 :
1850 : /*if inside or no aabb for the mesh draw vertex array*/
1851 63607 : if (!tr_state->visual->compositor->cull || (tr_state->cull_flag==CULL_INSIDE) || !mesh->aabb_root || !mesh->aabb_root->pos) {
1852 : #if defined(GPAC_USE_GLES1X) || defined(GPAC_USE_GLES2)
1853 : glDrawElements(prim_type, mesh->i_count, GL_UNSIGNED_SHORT, idx_addr);
1854 : #else
1855 60197 : glDrawElements(prim_type, mesh->i_count, GL_UNSIGNED_INT, idx_addr);
1856 : #endif
1857 :
1858 : } else {
1859 :
1860 : /*otherwise cull aabb against frustum - after some testing it appears (as usual) that there must
1861 : be a compromise: we're slowing down the compositor here, however the gain is really appreciable for
1862 : large meshes, especially terrains/elevation grids*/
1863 :
1864 : /*first get transformed frustum in local space*/
1865 3410 : gf_mx_copy(mx, tr_state->model_matrix);
1866 3410 : gf_mx_inverse(&mx);
1867 23870 : for (i=0; i<6; i++) {
1868 20460 : fplanes[i] = tr_state->camera->planes[i];
1869 20460 : gf_mx_apply_plane(&mx, &fplanes[i]);
1870 20460 : p_idx[i] = gf_plane_get_p_vertex_idx(&fplanes[i]);
1871 : }
1872 : /*then recursively cull & draw AABB tree*/
1873 3410 : visual_3d_draw_aabb_node(tr_state, mesh, prim_type, fplanes, p_idx, mesh->aabb_root->pos, idx_addr);
1874 3410 : visual_3d_draw_aabb_node(tr_state, mesh, prim_type, fplanes, p_idx, mesh->aabb_root->neg, idx_addr);
1875 : }
1876 :
1877 63607 : if (mesh->vbo_idx) {
1878 53238 : glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1879 : }
1880 63607 : }
1881 :
1882 63607 : static Bool visual_3d_bind_buffer(GF_Compositor *compositor, GF_Mesh *mesh, void **base_address)
1883 : {
1884 63607 : *base_address = NULL;
1885 63607 : if ((compositor->reset_graphics==2) && mesh->vbo) {
1886 : /*we lost OpenGL context at previous frame, recreate VBO*/
1887 0 : mesh->vbo = 0;
1888 0 : mesh->vbo_idx = 0;
1889 : }
1890 : /*rebuild VBO for large ojects only (we basically filter quads out)*/
1891 63607 : if (!mesh->vbo && compositor->gl_caps.vbo
1892 : #ifndef GPAC_USE_GLES2
1893 11667 : && (mesh->v_count>4)
1894 : #endif
1895 : ) {
1896 1298 : glGenBuffers(1, &mesh->vbo);
1897 1298 : if (mesh->vbo) {
1898 1298 : glBindBuffer(GL_ARRAY_BUFFER, mesh->vbo);
1899 1298 : glBufferData(GL_ARRAY_BUFFER, mesh->v_count * sizeof(GF_Vertex) , mesh->vertices, (mesh->vbo_dynamic) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
1900 1298 : mesh->vbo_dirty = 0;
1901 : } else {
1902 : return GF_FALSE;
1903 : }
1904 :
1905 1298 : glGenBuffers(1, &mesh->vbo_idx);
1906 1298 : if (mesh->vbo_idx) {
1907 1298 : glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->vbo_idx);
1908 1298 : glBufferData(GL_ELEMENT_ARRAY_BUFFER, mesh->i_count*sizeof(IDX_TYPE), mesh->indices, (mesh->vbo_dynamic) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
1909 : } else {
1910 : return GF_FALSE;
1911 : }
1912 : }
1913 :
1914 63607 : if (mesh->vbo) {
1915 53238 : *base_address = NULL;
1916 53238 : glBindBuffer(GL_ARRAY_BUFFER, mesh->vbo);
1917 : } else {
1918 10369 : *base_address = &mesh->vertices[0].pos;
1919 : }
1920 :
1921 63607 : if (mesh->vbo_dirty) {
1922 0 : glBufferSubData(GL_ARRAY_BUFFER, 0, mesh->v_count * sizeof(GF_Vertex) , mesh->vertices);
1923 :
1924 0 : if (mesh->vbo_idx) {
1925 0 : glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->vbo_idx);
1926 0 : glBufferData(GL_ELEMENT_ARRAY_BUFFER, mesh->i_count*sizeof(IDX_TYPE), mesh->indices, (mesh->vbo_dynamic) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
1927 :
1928 0 : glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1929 : }
1930 :
1931 0 : mesh->vbo_dirty = 0;
1932 : }
1933 : return GF_TRUE;
1934 : }
1935 :
1936 :
1937 : #if !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES1X)
1938 :
1939 63443 : static void visual_3d_update_matrices_shaders(GF_TraverseState *tr_state)
1940 : {
1941 : GF_Matrix mx;
1942 :
1943 63443 : if (tr_state->visual->needs_projection_matrix_reload) {
1944 18096 : tr_state->visual->needs_projection_matrix_reload = 0;
1945 18096 : visual_3d_load_matrix_shaders(tr_state->visual->glsl_program, (Fixed *) tr_state->camera->projection.m, "gfProjectionMatrix");
1946 : }
1947 :
1948 : //calculate ModelView matix (camera.view * model)
1949 63443 : gf_mx_copy(mx, tr_state->camera->modelview);
1950 63443 : gf_mx_add_matrix(&mx, &tr_state->model_matrix);
1951 63443 : visual_3d_load_matrix_shaders(tr_state->visual->glsl_program, (Fixed *) &mx.m, "gfModelViewMatrix");
1952 63443 : }
1953 :
1954 13235 : static void visual_3d_set_lights_shaders(GF_TraverseState *tr_state)
1955 : {
1956 : u32 i;
1957 : GF_LightInfo *li;
1958 : GF_Vec pt;
1959 : Float ambientIntensity, intensity, vals[4];
1960 : GLint loc;
1961 : GF_Matrix mx;
1962 13235 : GF_VisualManager *visual = tr_state->visual;
1963 : char szName[100];
1964 :
1965 13235 : loc = glGetUniformLocation(visual->glsl_program, "gfNumLights");
1966 13235 : if (loc>=0)
1967 13235 : glUniform1i(loc, visual->num_lights);
1968 : GL_CHECK_ERR()
1969 :
1970 : /*
1971 : * Equivalent to glLightModel(GL_LIGHTMODEL_TWO_SIDE, GL_TRUE);
1972 : */
1973 13235 : loc = glGetUniformLocation(visual->glsl_program, "gfLightTwoSide");
1974 13235 : if (loc>=0)
1975 13235 : glUniform1i(loc, 1);
1976 : GL_CHECK_ERR()
1977 :
1978 13235 : li = &visual->lights[0];
1979 :
1980 13235 : pt = li->direction;
1981 13235 : gf_vec_norm(&pt);
1982 13235 : vals[0] = -FIX2FLT(pt.x);
1983 13235 : vals[1] = -FIX2FLT(pt.y);
1984 13235 : vals[2] = -FIX2FLT(pt.z);
1985 13235 : vals[3] = 0;
1986 :
1987 13235 : ambientIntensity = FIX2FLT(li->ambientIntensity);
1988 13235 : intensity = FIX2FLT(li->intensity);
1989 :
1990 13265 : for (i = 0; i < (int) visual->num_lights; i++) {
1991 : GF_Vec orig;
1992 13265 : li = &visual->lights[i];
1993 :
1994 13265 : if (li->type==3) { //we have a headlight
1995 10392 : gf_mx_init(mx);
1996 : } else {
1997 : //update mx according to the light mx
1998 2873 : gf_mx_copy(mx, visual->camera.modelview);
1999 2873 : gf_mx_add_matrix(&mx, &li->light_mx);
2000 : }
2001 :
2002 : sprintf(szName, "%s%d%s", "lights[", i, "].type");
2003 13265 : loc = glGetUniformLocation(visual->glsl_program, szName); //Uniform name lights[i].type
2004 13265 : if (loc>=0) {
2005 13265 : if (li->type==3) {
2006 10392 : glUniform1i(loc, 0); //headlight; Set type 0-directional
2007 : } else {
2008 2873 : glUniform1i(loc, (GLint) li->type); //Set type 0-directional 1-spot 2-point
2009 : }
2010 : }
2011 :
2012 : //set for light direction (assuming origin = 0,0,0)
2013 13265 : pt = li->direction;
2014 13265 : orig.x = orig.y = orig.z = 0;
2015 13265 : gf_mx_apply_vec(&mx, &pt);
2016 13265 : gf_mx_apply_vec(&mx, &orig);
2017 13265 : gf_vec_diff(pt, pt, orig);
2018 13265 : gf_vec_norm(&pt);
2019 :
2020 13265 : vals[0] = -FIX2FLT(pt.x);
2021 13265 : vals[1] = -FIX2FLT(pt.y);
2022 13265 : vals[2] = -FIX2FLT(pt.z);
2023 13265 : vals[3] = 0;
2024 : sprintf(szName, "%s%d%s", "lights[", i, "].direction");
2025 13265 : loc = glGetUniformLocation(visual->glsl_program, szName);
2026 13265 : if (loc>=0)
2027 13265 : glUniform4fv(loc, 1, vals); //Set direction
2028 :
2029 13265 : if ((li->type==0) || (li->type==3) ) {
2030 10547 : pt = li->direction;
2031 10547 : vals[0] = -FIX2FLT(pt.x);
2032 10547 : vals[1] = -FIX2FLT(pt.y);
2033 10547 : vals[2] = -FIX2FLT(pt.z);
2034 10547 : vals[3] = 0;
2035 : } else { //we have a spot or point light
2036 2718 : pt = li->position;
2037 2718 : gf_mx_apply_vec(&mx, &pt);
2038 2718 : vals[0] = FIX2FLT(pt.x);
2039 2718 : vals[1] = FIX2FLT(pt.y);
2040 2718 : vals[2] = FIX2FLT(pt.z);
2041 2718 : vals[3] = 1.0;
2042 : }
2043 : sprintf(szName, "%s%d%s", "lights[", i, "].position");
2044 13265 : loc = glGetUniformLocation(visual->glsl_program, szName);
2045 13265 : if (loc>=0)
2046 13265 : glUniform4fv(loc, 1, vals);
2047 :
2048 13265 : pt = li->attenuation;
2049 13265 : if (li->type && !li->attenuation.x) {
2050 10392 : vals[0]=1.0;
2051 : } else {
2052 2873 : vals[0] = FIX2FLT(pt.x);
2053 : }
2054 13265 : vals[1] = FIX2FLT(pt.y);
2055 13265 : vals[2] = FIX2FLT(pt.z);
2056 : sprintf(szName, "%s%d%s", "lights[", i, "].attenuation");
2057 13265 : loc = glGetUniformLocation(visual->glsl_program, szName);
2058 13265 : if (loc>=0)
2059 13265 : glUniform3fv(loc, 1, vals);
2060 :
2061 13265 : vals[0] = FIX2FLT(li->color.red);
2062 13265 : vals[1] = FIX2FLT(li->color.green);
2063 13265 : vals[2] = FIX2FLT(li->color.blue);
2064 13265 : vals[3] = 0;
2065 : sprintf(szName, "%s%d%s", "lights[", i, "].color");
2066 13265 : loc = glGetUniformLocation(visual->glsl_program, szName);
2067 13265 : if (loc>=0)
2068 13265 : glUniform4fv(loc, 1, vals);
2069 :
2070 : sprintf(szName, "%s%d%s", "lights[", i, "].intensity");
2071 13265 : loc = glGetUniformLocation(visual->glsl_program, szName);
2072 13265 : if (loc>=0)
2073 13265 : glUniform1f(loc, li->intensity);
2074 :
2075 : sprintf(szName, "%s%d%s", "lights[", i, "].cutOffAngle");
2076 13265 : loc = glGetUniformLocation(visual->glsl_program, szName);
2077 13265 : if (loc>=0)
2078 13265 : glUniform1f(loc, li->cutOffAngle);
2079 :
2080 : }
2081 :
2082 :
2083 13235 : vals[0] = FIX2FLT(li->color.red)*intensity;
2084 13235 : vals[1] = FIX2FLT(li->color.green)*intensity;
2085 13235 : vals[2] = FIX2FLT(li->color.blue)*intensity;
2086 13235 : vals[3] = 1;
2087 13235 : loc = glGetUniformLocation(visual->glsl_program, "gfLightDiffuse");
2088 13235 : if (loc>=0) glUniform4fv(loc, 1, vals);
2089 :
2090 13235 : loc = glGetUniformLocation(visual->glsl_program, "gfLightSpecular");
2091 13235 : if (loc>=0) glUniform4fv(loc, 1, vals);
2092 :
2093 13235 : vals[0] = FIX2FLT(li->color.red)*ambientIntensity;
2094 13235 : vals[1] = FIX2FLT(li->color.green)*ambientIntensity;
2095 13235 : vals[2] = FIX2FLT(li->color.blue)*ambientIntensity;
2096 13235 : vals[3] = 1;
2097 13235 : loc = glGetUniformLocation(visual->glsl_program, "gfLightAmbient");
2098 13235 : if (loc>=0) glUniform4fv(loc, 1, vals);
2099 :
2100 : GL_CHECK_ERR()
2101 13235 : }
2102 :
2103 13235 : static void visual_3d_set_fog_shaders(GF_VisualManager *visual)
2104 : {
2105 : GLint loc;
2106 13235 : if (visual->has_fog) {
2107 1021 : loc = glGetUniformLocation(visual->glsl_program, "gfFogEnabled");
2108 1021 : if(loc>=0)
2109 1021 : glUniform1i(loc, GL_TRUE);
2110 :
2111 1021 : loc = glGetUniformLocation(visual->glsl_program, "gfFogColor");
2112 1021 : if(loc>=0)
2113 1021 : glUniform3fv(loc, 1, (GLfloat *) &visual->fog_color);
2114 :
2115 1021 : loc = glGetUniformLocation(visual->glsl_program, "gfFogDensity");
2116 1021 : if(loc>=0)
2117 1021 : glUniform1f(loc, visual->fog_density );
2118 :
2119 1021 : loc = glGetUniformLocation(visual->glsl_program, "gfFogType");
2120 1021 : if(loc>=0)
2121 1021 : glUniform1i(loc, (GLuint) visual->fog_type );
2122 :
2123 1021 : loc = glGetUniformLocation(visual->glsl_program, "gfFogVisibility");
2124 1021 : if(loc>=0)
2125 1021 : glUniform1f(loc, visual->fog_visibility);
2126 : } else {
2127 12214 : loc = glGetUniformLocation(visual->glsl_program, "gfFogEnabled");
2128 12214 : if(loc>=0)
2129 12214 : glUniform1i(loc, GL_FALSE);
2130 :
2131 : }
2132 : GL_CHECK_ERR()
2133 13235 : }
2134 :
2135 63443 : static void visual_3d_set_clippers_shaders(GF_VisualManager *visual, GF_TraverseState *tr_state)
2136 : {
2137 : Fixed vals[4];
2138 : char szName[100];
2139 : GLint loc;
2140 : u32 i;
2141 : GF_Matrix inv_mx, eye_mx;
2142 :
2143 126587 : if (!visual->num_clips) return;
2144 :
2145 299 : gf_mx_copy(inv_mx, tr_state->model_matrix);
2146 299 : gf_mx_inverse(&inv_mx);
2147 :
2148 299 : gf_mx_copy(eye_mx, tr_state->camera->modelview);
2149 299 : gf_mx_add_matrix(&eye_mx, &tr_state->model_matrix);
2150 :
2151 299 : loc = glGetUniformLocation(visual->glsl_program, "gfNumClippers");
2152 299 : if (loc>=0)
2153 299 : glUniform1i(loc, visual->num_clips);
2154 :
2155 299 : for (i = 0; i < visual->num_clips; i++) {
2156 : GF_Matrix mx;
2157 : GF_Plane p;
2158 :
2159 299 : p = visual->clippers[i].p;
2160 : //compute clip plane in eye coordinates
2161 299 : if (! visual->clippers[i].is_2d_clip) {
2162 : gf_mx_copy(mx, inv_mx);
2163 299 : if (visual->clippers[i].mx_clipper != NULL) {
2164 299 : gf_mx_add_matrix(&mx, visual->clippers[i].mx_clipper);
2165 : }
2166 : //plane in local coordinates
2167 299 : gf_mx_apply_plane(&mx, &p);
2168 : //plane in eye coordinates
2169 299 : gf_mx_apply_plane(&eye_mx, &p);
2170 : }
2171 :
2172 : sprintf(szName, "%s%d%s", "clipPlane[", i, "]"); //parse plane values
2173 299 : loc = glGetUniformLocation(visual->glsl_program, szName);
2174 299 : if (loc>=0) {
2175 299 : vals[0] = p.normal.x;
2176 299 : vals[1] = p.normal.y;
2177 299 : vals[2] = p.normal.z;
2178 299 : vals[3] = p.d;
2179 299 : glUniform4fv(loc, 1, vals); //Set Plane (w = distance)
2180 : }
2181 : }
2182 : }
2183 :
2184 76927 : GF_GLProgInstance *visual_3d_check_program_exists(GF_VisualManager *root_visual, u32 flags, u32 pix_fmt)
2185 : {
2186 : u32 i, count;
2187 : GF_GLProgInstance *prog = NULL;
2188 76927 : if (root_visual->compositor->shader_mode_disabled)
2189 : return NULL;
2190 :
2191 76925 : count = gf_list_count(root_visual->compiled_programs);
2192 148667 : for (i=0; i<count; i++) {
2193 148428 : prog = gf_list_get(root_visual->compiled_programs, i);
2194 148428 : if ((prog->flags==flags) && (prog->pix_fmt==pix_fmt)) break;
2195 : prog = NULL;
2196 : }
2197 :
2198 76925 : if (!prog) {
2199 239 : prog = visual_3d_build_program(root_visual, flags, pix_fmt);
2200 239 : if (!prog) return NULL;
2201 239 : gf_list_add(root_visual->compiled_programs, prog);
2202 : }
2203 : return prog;
2204 : }
2205 :
2206 63443 : static void visual_3d_draw_mesh_shader_only(GF_TraverseState *tr_state, GF_Mesh *mesh)
2207 : {
2208 : void *vertex_buffer_address;
2209 63443 : GF_VisualManager *visual = tr_state->visual;
2210 63443 : GF_VisualManager *root_visual = visual->compositor->visual;
2211 : GLint loc, loc_vertex_array, loc_color_array, loc_normal_array, loc_textcoord_array;
2212 : u32 flags;
2213 63443 : u32 num_lights = visual->num_lights;
2214 : Bool is_debug_bounds = GF_FALSE;
2215 : GF_GLProgInstance *prog = NULL;
2216 :
2217 63443 : flags = root_visual->active_glsl_flags;
2218 :
2219 63443 : if (!mesh) {
2220 : is_debug_bounds = GF_TRUE;
2221 34803 : mesh = tr_state->visual->compositor->unit_bbox;
2222 : flags = 0;
2223 : }
2224 :
2225 63443 : if (visual->has_material_2d) {
2226 : num_lights = 0;
2227 : }
2228 :
2229 63443 : if (!tr_state->mesh_num_textures && (mesh->flags & MESH_HAS_COLOR)) {
2230 331 : flags |= GF_GL_HAS_COLOR;
2231 331 : visual->has_material_2d = GF_FALSE;
2232 : }
2233 63112 : else if (tr_state->mesh_num_textures && (mesh->mesh_type==MESH_TRIANGLES) && !(mesh->flags & MESH_NO_TEXTURE)) {
2234 13385 : flags |= GF_GL_HAS_TEXTURE;
2235 : } else {
2236 : flags &= ~GF_GL_HAS_TEXTURE;
2237 : flags &= ~GF_GL_IS_YUV;
2238 49727 : flags &= ~GF_GL_IS_ExternalOES;
2239 :
2240 : }
2241 :
2242 63443 : if (num_lights && !is_debug_bounds) {
2243 13235 : flags |= GF_GL_HAS_LIGHT;
2244 : } else {
2245 50208 : flags &= ~GF_GL_HAS_LIGHT;
2246 : }
2247 :
2248 63443 : if (visual->num_clips) {
2249 299 : flags |= GF_GL_HAS_CLIP;
2250 : } else {
2251 63144 : flags &= ~GF_GL_HAS_CLIP;
2252 : }
2253 :
2254 63443 : root_visual->active_glsl_flags = visual->active_glsl_flags = flags;
2255 :
2256 63443 : prog = visual_3d_check_program_exists(root_visual, flags, root_visual->bound_tx_pix_fmt);
2257 63443 : if (!prog) return;
2258 :
2259 : //check if we are using a different program than last time, if so force matrices updates
2260 63443 : if (visual->glsl_program != prog->prog) {
2261 13900 : tr_state->visual->needs_projection_matrix_reload = GF_TRUE;
2262 : }
2263 :
2264 : GL_CHECK_ERR()
2265 63443 : visual->glsl_program = prog->prog;
2266 :
2267 63443 : glUseProgram(visual->glsl_program);
2268 : GL_CHECK_ERR()
2269 :
2270 63443 : if (! visual_3d_bind_buffer(visual->compositor, mesh, &vertex_buffer_address)) {
2271 0 : glUseProgram(0);
2272 0 : return;
2273 : }
2274 :
2275 63443 : if (visual->state_blend_on)
2276 1749 : glEnable(GL_BLEND);
2277 :
2278 63443 : visual_3d_update_matrices_shaders(tr_state);
2279 :
2280 : loc_color_array = loc_normal_array = loc_textcoord_array = -1;
2281 :
2282 : //setup vertext array location (always true)
2283 63443 : loc_vertex_array = glGetAttribLocation(visual->glsl_program, "gfVertex");
2284 63443 : if (loc_vertex_array<0)
2285 : return;
2286 :
2287 63443 : glEnableVertexAttribArray(loc_vertex_array);
2288 : GL_CHECK_ERR()
2289 : #if defined(GPAC_FIXED_POINT)
2290 : glVertexAttribPointer(loc_vertex_array, 3, GL_FIXED, GL_TRUE, sizeof(GF_Vertex), vertex_buffer_address);
2291 : #else
2292 63443 : glVertexAttribPointer(loc_vertex_array, 3, GL_FLOAT, GL_FALSE, sizeof(GF_Vertex), vertex_buffer_address);
2293 : #endif
2294 :
2295 : //setup scissor
2296 63443 : visual_3d_set_clipper_scissor(visual, tr_state);
2297 :
2298 : //setup clippers
2299 63443 : visual_3d_set_clippers_shaders(visual, tr_state);
2300 :
2301 63443 : if (is_debug_bounds) {
2302 : Float cols[4];
2303 34803 : loc = glGetUniformLocation(visual->glsl_program, "gfEmissionColor");
2304 34803 : cols[0] = 1.0f - FIX2FLT(visual->mat_2d.red);
2305 34803 : cols[1] = 1.0f - FIX2FLT(visual->mat_2d.green);
2306 34803 : cols[2] = 1.0f - FIX2FLT(visual->mat_2d.blue);
2307 34803 : cols[3] = 1.0f;
2308 34803 : if (loc>=0)
2309 34803 : glUniform4fv(loc, 1, (GLfloat *) cols);
2310 : GL_CHECK_ERR()
2311 :
2312 34803 : loc = glGetUniformLocation(visual->glsl_program, "hasMaterial2D");
2313 34803 : if (loc>=0)
2314 34803 : glUniform1i(loc, 1);
2315 : GL_CHECK_ERR()
2316 : }
2317 : /* Material2D does not have any lights, color used is "gfEmissionColor" uniform */
2318 28640 : else if (visual->has_material_2d) {
2319 : //for YUV manually set alpha
2320 9994 : if (flags & GF_GL_IS_YUV) {
2321 0 : loc = glGetUniformLocation(visual->glsl_program, "alpha");
2322 0 : if(loc>=0)
2323 0 : glUniform1f(loc, FIX2FLT(visual->mat_2d.alpha));
2324 : }
2325 : //otherwise handle alpha with blend if no texture
2326 9994 : else if (!tr_state->mesh_num_textures) {
2327 5707 : if (visual->mat_2d.alpha < FIX_ONE) {
2328 480 : glEnable(GL_BLEND);
2329 : } else {
2330 5227 : glDisable(GL_BLEND);
2331 : }
2332 : }
2333 :
2334 9994 : loc = glGetUniformLocation(visual->glsl_program, "gfEmissionColor");
2335 9994 : if (loc>=0)
2336 9994 : glUniform4fv(loc, 1, (GLfloat *) & visual->mat_2d);
2337 : GL_CHECK_ERR()
2338 :
2339 9994 : loc = glGetUniformLocation(visual->glsl_program, "hasMaterial2D");
2340 9994 : if (loc>=0)
2341 9994 : glUniform1i(loc, 1);
2342 : GL_CHECK_ERR()
2343 :
2344 : } else {
2345 :
2346 18646 : loc = glGetUniformLocation(visual->glsl_program, "hasMaterial2D");
2347 18646 : if (loc>=0)
2348 18646 : glUniform1i(loc, 0);
2349 : GL_CHECK_ERR()
2350 :
2351 : //for YUV manually set alpha
2352 18646 : if (flags & GF_GL_IS_YUV) {
2353 0 : loc = glGetUniformLocation(visual->glsl_program, "alpha");
2354 0 : if(loc>=0)
2355 0 : glUniform1f(loc, 1.0);
2356 : GL_CHECK_ERR()
2357 : }
2358 : }
2359 :
2360 : /* if lighting is on, setup material */
2361 63443 : if ((flags & GF_GL_HAS_LIGHT) && visual->has_material && !visual->has_material_2d) {
2362 : u32 i;
2363 52940 : for(i =0; i<4; i++) {
2364 52940 : Fixed *rgba = (Fixed *) & visual->materials[i];
2365 : #if defined(GPAC_FIXED_POINT)
2366 : Float _rgba[4];
2367 : _rgba[0] = FIX2FLT(rgba[0]);
2368 : _rgba[1] = FIX2FLT(rgba[1]);
2369 : _rgba[2] = FIX2FLT(rgba[2]);
2370 : _rgba[3] = FIX2FLT(rgba[3]);
2371 : #elif defined(GPAC_USE_GLES1X)
2372 : Fixed *_rgba = (Fixed *) rgba;
2373 : #else
2374 : Float *_rgba = (Float *) rgba;
2375 : #endif
2376 52940 : switch (i) {
2377 13235 : case 0:
2378 13235 : loc = glGetUniformLocation(visual->glsl_program, "gfAmbientColor");
2379 13235 : break;
2380 13235 : case 1:
2381 13235 : loc = glGetUniformLocation(visual->glsl_program, "gfDiffuseColor");
2382 13235 : break;
2383 13235 : case 2:
2384 13235 : loc = glGetUniformLocation(visual->glsl_program, "gfSpecularColor");
2385 13235 : break;
2386 13235 : case 3:
2387 13235 : loc = glGetUniformLocation(visual->glsl_program, "gfEmissionColor");
2388 13235 : break;
2389 : }
2390 :
2391 52940 : if (loc>=0)
2392 52940 : glUniform4fv(loc, 1, _rgba);
2393 : }
2394 : //TO CHECK: if this does not work as it is supposed to, try: visual->shininess * 128
2395 13235 : loc = glGetUniformLocation(visual->glsl_program, "gfShininess");
2396 13235 : if (loc>=0)
2397 13235 : glUniform1f(loc, FIX2FLT(visual->shininess));
2398 :
2399 13235 : glDisable(GL_CULL_FACE); //Enable for performance; if so, check glFrontFace()
2400 : }
2401 :
2402 : //setup mesh color vertex attribute - only available for some shaders
2403 63443 : if (!tr_state->mesh_num_textures && (mesh->flags & MESH_HAS_COLOR) && !is_debug_bounds) {
2404 331 : loc_color_array = glGetAttribLocation(visual->glsl_program, "gfMeshColor");
2405 331 : if (loc_color_array >= 0) {
2406 :
2407 : //for now colors are 8bit/comp RGB(A), so used GL_UNSIGNED_BYTE and GL_TRUE for normalizing values
2408 331 : if (mesh->flags & MESH_HAS_ALPHA) {
2409 4 : glEnable(GL_BLEND);
2410 4 : tr_state->mesh_is_transparent = 1;
2411 4 : glVertexAttribPointer(loc_color_array, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(GF_Vertex), ((char *)vertex_buffer_address + MESH_COLOR_OFFSET));
2412 : } else {
2413 327 : glVertexAttribPointer(loc_color_array, 3, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(GF_Vertex), ((char *)vertex_buffer_address + MESH_COLOR_OFFSET));
2414 : }
2415 331 : glEnableVertexAttribArray(loc_color_array);
2416 : }
2417 : GL_CHECK_ERR()
2418 : }
2419 :
2420 63443 : if (flags & GF_GL_HAS_LIGHT) {
2421 13235 : visual_3d_set_fog_shaders(visual);
2422 : }
2423 :
2424 : //setup mesh normal vertex attribute - only available for some shaders
2425 63443 : if (!visual->has_material_2d && num_lights && (mesh->mesh_type==MESH_TRIANGLES) ) {
2426 : GF_Matrix normal_mx;
2427 : assert(flags & GF_GL_HAS_LIGHT);
2428 :
2429 13235 : gf_mx_copy(normal_mx, tr_state->camera->modelview);
2430 13235 : gf_mx_add_matrix(&normal_mx, &tr_state->model_matrix);
2431 13235 : normal_mx.m[12] = normal_mx.m[13] = normal_mx.m[14] = 0;
2432 13235 : gf_mx_inverse(&normal_mx);
2433 :
2434 :
2435 13235 : gf_mx_transpose(&normal_mx);
2436 :
2437 13235 : visual_3d_load_matrix_shaders(tr_state->visual->glsl_program, (Fixed *) &normal_mx.m, "gfNormalMatrix");
2438 :
2439 13235 : loc_normal_array = glGetAttribLocation(visual->glsl_program, "gfNormal");
2440 13235 : if (loc_normal_array>=0) {
2441 : #ifdef MESH_USE_FIXED_NORMAL
2442 : glVertexAttribPointer(loc_normal_array, 3, GL_FLOAT, GL_FALSE, sizeof(GF_Vertex), ((char *)vertex_buffer_address + MESH_NORMAL_OFFSET) );
2443 : #else
2444 13235 : glVertexAttribPointer(loc_normal_array, 3, GL_BYTE, GL_FALSE, sizeof(GF_Vertex), ((char *)vertex_buffer_address + MESH_NORMAL_OFFSET) );
2445 : #endif
2446 13235 : glEnableVertexAttribArray(loc_normal_array);
2447 : }
2448 : GL_CHECK_ERR()
2449 :
2450 13235 : loc = glGetUniformLocation(visual->glsl_program, "gfNumLights");
2451 13235 : if (loc>=0)
2452 13235 : glUniform1i(loc, num_lights);
2453 13235 : visual_3d_set_lights_shaders(tr_state);
2454 : GL_CHECK_ERR()
2455 : }
2456 :
2457 : //setup mesh normal vertex attribute - only available for some shaders
2458 63443 : if (tr_state->mesh_num_textures && (mesh->mesh_type==MESH_TRIANGLES) && !(mesh->flags & MESH_NO_TEXTURE)) {
2459 13385 : if (visual->has_tx_matrix) {
2460 : //parsing texture matrix
2461 7648 : loc = glGetUniformLocation(visual->glsl_program, "gfTextureMatrix");
2462 7648 : if (loc>=0)
2463 7648 : glUniformMatrix4fv(loc, 1, GL_FALSE, visual->tx_matrix.m);
2464 : GL_CHECK_ERR()
2465 :
2466 7648 : loc = glGetUniformLocation(visual->glsl_program, "hasTextureMatrix");
2467 7648 : if (loc>=0) glUniform1i(loc, 1);
2468 : } else {
2469 5737 : loc = glGetUniformLocation(visual->glsl_program, "hasTextureMatrix");
2470 5737 : if (loc>=0) glUniform1i(loc, 0);
2471 : }
2472 :
2473 : //parsing texture coordinates
2474 13385 : loc_textcoord_array = glGetAttribLocation(visual->glsl_program, "gfMultiTexCoord");
2475 13385 : if (loc_textcoord_array>=0) {
2476 13385 : glVertexAttribPointer(loc_textcoord_array, 2, GL_FLOAT, GL_FALSE, sizeof(GF_Vertex), ((char *)vertex_buffer_address + MESH_TEX_OFFSET));
2477 13385 : glEnableVertexAttribArray(loc_textcoord_array);
2478 : GL_CHECK_ERR()
2479 : }
2480 :
2481 13385 : if (flags & GF_GL_IS_YUV) {
2482 0 : loc = glGetUniformLocation(visual->glsl_program, "yuvPixelFormat");
2483 0 : if (loc>=0) {
2484 : int yuv_mode = 0;
2485 0 : switch (visual->yuv_pixelformat_type) {
2486 0 : case GF_PIXEL_NV21:
2487 : yuv_mode = 1;
2488 0 : break;
2489 0 : case GF_PIXEL_NV12:
2490 : yuv_mode = 2;
2491 0 : break;
2492 : }
2493 :
2494 0 : glUniform1i(loc, yuv_mode);
2495 : }
2496 : GL_CHECK_ERR()
2497 : }
2498 : }
2499 :
2500 : //
2501 63443 : if (mesh->mesh_type != MESH_TRIANGLES) {
2502 : //According to the spec we should pass a 0,0,1 Normal and disable lights. we just disable lights
2503 35369 : if(flags & GF_GL_HAS_LIGHT) {
2504 0 : loc = glGetUniformLocation(visual->glsl_program, "gfNumLights");
2505 0 : if (loc>=0) glUniform1i(loc, 0);
2506 :
2507 : }
2508 35369 : glDisable(GL_CULL_FACE);
2509 :
2510 : #if !defined(GPAC_USE_TINYGL) && !defined(GL_ES_CL_PROFILE)
2511 35369 : glLineWidth(1.0f);
2512 : #endif
2513 :
2514 : } else {
2515 28074 : if (visual->compositor->bcull
2516 28074 : && (!tr_state->mesh_is_transparent || (visual->compositor->bcull ==GF_BACK_CULL_ALPHA) )
2517 26557 : && (mesh->flags & MESH_IS_SOLID)) {
2518 10647 : glEnable(GL_CULL_FACE);
2519 10647 : if (tr_state->reverse_backface) {
2520 0 : glFrontFace((mesh->flags & MESH_IS_CW) ? GL_CCW : GL_CW);
2521 : } else {
2522 10647 : glFrontFace((mesh->flags & MESH_IS_CW) ? GL_CW : GL_CCW);
2523 : }
2524 : } else {
2525 17427 : glDisable(GL_CULL_FACE);
2526 : }
2527 : }
2528 :
2529 : GL_CHECK_ERR()
2530 :
2531 : //We have a Colour Matrix to be applied
2532 63443 : if(!tr_state->color_mat.identity) {
2533 : GF_Matrix toBeParsed; //4x4 RGBA Color Matrix
2534 : Fixed translateV[4]; //Vec4 holding translation property of color_mat
2535 : int row,col;
2536 :
2537 136 : gf_mx_init(toBeParsed);
2538 :
2539 : //Copy values from Color Matrix
2540 680 : for(row=0; row<4; row++) {
2541 2176 : for(col=0; col<4; col++) {
2542 2176 : toBeParsed.m[col+(row*4)]=tr_state->color_mat.m[col+(row*5)];
2543 : }
2544 544 : translateV[row] = tr_state->color_mat.m[4+(row*5)];
2545 : }
2546 :
2547 : //the rest of the values form the translation vector
2548 136 : loc = glGetUniformLocation(visual->glsl_program, "gfTranslationVector");
2549 136 : if (loc>=0)
2550 136 : glUniform4fv(loc, 1, (GLfloat *) &translateV);
2551 : GL_CHECK_ERR()
2552 :
2553 136 : loc = glGetUniformLocation(visual->glsl_program, "hasColorMatrix");
2554 136 : if(loc>=0) glUniform1i(loc, 1);
2555 :
2556 136 : loc = glGetUniformLocation(visual->glsl_program, "gfColorMatrix");
2557 136 : if (loc>=0)
2558 136 : glUniformMatrix4fv(loc, 1, GL_FALSE, toBeParsed.m);
2559 : GL_CHECK_ERR()
2560 : } else {
2561 63307 : loc = glGetUniformLocation(visual->glsl_program, "hasColorMatrix");
2562 63307 : if(loc>=0) glUniform1i(loc, 0);
2563 : }
2564 :
2565 :
2566 : //We have a Colour Key to be applied
2567 63443 : if(tr_state->col_key) {
2568 :
2569 : Float vals[3];
2570 : Float eightbit = 255; //used for mapping values between 0.0 and 1.0
2571 :
2572 0 : glEnable(GL_BLEND); //normally we shouldn have to need this, but we do
2573 :
2574 0 : loc = glGetUniformLocation(visual->glsl_program, "hasColorKey");
2575 0 : if(loc>=0) glUniform1i(loc, 1);
2576 :
2577 0 : vals[0] = tr_state->col_key->r/eightbit;
2578 0 : vals[1] = tr_state->col_key->g/eightbit;
2579 0 : vals[2] = tr_state->col_key->b/eightbit;
2580 :
2581 0 : loc = glGetUniformLocation(visual->glsl_program, "gfKeyColor");
2582 0 : if(loc>=0)glUniform3fv(loc, 1, vals);
2583 :
2584 0 : loc = glGetUniformLocation(visual->glsl_program, "gfKeyLow");
2585 0 : if(loc>=0) glUniform1f(loc, tr_state->col_key->low/eightbit);
2586 :
2587 0 : loc = glGetUniformLocation(visual->glsl_program, "gfKeyHigh");
2588 0 : if(loc>=0) glUniform1f(loc, tr_state->col_key->high/eightbit);
2589 :
2590 0 : loc = glGetUniformLocation(visual->glsl_program, "gfKeyAlpha");
2591 0 : if(loc>=0) glUniform1f(loc, tr_state->col_key->alpha/eightbit);
2592 :
2593 : } else {
2594 63443 : loc = glGetUniformLocation(visual->glsl_program, "hasColorKey");
2595 63443 : if(loc>=0) glUniform1i(loc, 0);
2596 : }
2597 :
2598 :
2599 :
2600 :
2601 63443 : visual_3d_do_draw_mesh(tr_state, mesh);
2602 :
2603 : GL_CHECK_ERR()
2604 : //We drawn, now we Reset
2605 :
2606 63443 : if (mesh->vbo)
2607 53086 : glBindBuffer(GL_ARRAY_BUFFER, 0);
2608 :
2609 63443 : if (loc_vertex_array>=0) glDisableVertexAttribArray(loc_vertex_array);
2610 63443 : if (loc_color_array>=0) glDisableVertexAttribArray(loc_color_array);
2611 63443 : if (loc_normal_array>=0) glDisableVertexAttribArray(loc_normal_array);
2612 63443 : if (loc_textcoord_array>=0) glDisableVertexAttribArray(loc_textcoord_array);
2613 :
2614 : //instead of visual_3d_reset_lights(visual);
2615 63443 : if(root_visual->active_glsl_flags & GF_GL_HAS_LIGHT) {
2616 13235 : loc = glGetUniformLocation(visual->glsl_program, "gfNumLights");
2617 13235 : if (loc>=0) glUniform1i(loc, 0);
2618 : GL_CHECK_ERR()
2619 : }
2620 :
2621 63443 : if (visual->has_clipper_2d) {
2622 3179 : glDisable(GL_SCISSOR_TEST);
2623 : }
2624 :
2625 63443 : visual->has_material_2d = GF_FALSE;
2626 63443 : visual->active_glsl_flags = root_visual->active_glsl_flags;
2627 63443 : root_visual->active_glsl_flags &= ~ GF_GL_HAS_COLOR;
2628 63443 : visual->has_material = 0;
2629 63443 : visual->state_color_on = 0;
2630 63443 : if (tr_state->mesh_is_transparent) glDisable(GL_BLEND);
2631 63443 : tr_state->mesh_is_transparent = 0;
2632 : GL_CHECK_ERR()
2633 63443 : glUseProgram(0);
2634 : GL_CHECK_ERR()
2635 : }
2636 :
2637 : #endif // !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES1X)
2638 :
2639 : //#endif //GPAC_USE_GLES2
2640 :
2641 :
2642 63607 : static void visual_3d_draw_mesh(GF_TraverseState *tr_state, GF_Mesh *mesh)
2643 : {
2644 : #ifndef GPAC_USE_GLES2
2645 63607 : GF_Compositor *compositor = tr_state->visual->compositor;
2646 : GF_VisualManager *visual = tr_state->visual;
2647 : Bool has_col, has_tx, has_norm;
2648 63607 : void *base_address = NULL;
2649 : Bool is_debug_bounds = GF_FALSE;
2650 :
2651 : #if defined(GPAC_FIXED_POINT) && !defined(GPAC_USE_GLES1X)
2652 : Float *color_array = NULL;
2653 : Float fix_scale = 1.0f;
2654 : fix_scale /= FIX_ONE;
2655 : #endif
2656 :
2657 : #endif
2658 :
2659 63607 : if (mesh) {
2660 28804 : GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[V3D] Drawing mesh %p\n", mesh));
2661 : }
2662 :
2663 : //clear error
2664 63607 : glGetError();
2665 : GL_CHECK_ERR()
2666 :
2667 : #ifdef GPAC_USE_GLES2
2668 : visual_3d_draw_mesh_shader_only(tr_state, mesh);
2669 : return;
2670 : #else
2671 :
2672 : #if !defined(GPAC_CONFIG_ANDROID) && !defined(GPAC_CONFIG_IOS) && !defined(GPAC_FIXED_POINT)
2673 63607 : if (!visual->compositor->shader_mode_disabled) {
2674 63443 : visual_3d_draw_mesh_shader_only(tr_state, mesh);
2675 63443 : return;
2676 : }
2677 : #endif
2678 :
2679 164 : if (!mesh) {
2680 0 : mesh = tr_state->visual->compositor->unit_bbox;
2681 : is_debug_bounds = GF_TRUE;
2682 : }
2683 :
2684 164 : if (! visual_3d_bind_buffer(compositor, mesh, &base_address)) {
2685 : #if! defined(GPAC_USE_GLES1X) && !defined(GPAC_USE_TINYGL)
2686 0 : glUseProgram(0);
2687 : #endif
2688 0 : return;
2689 : }
2690 : has_col = has_tx = has_norm = 0;
2691 :
2692 164 : if (!is_debug_bounds) {
2693 : //set lights before pushing modelview matrix
2694 164 : visual_3d_set_lights(visual);
2695 : }
2696 :
2697 164 : visual_3d_update_matrices(tr_state);
2698 :
2699 : /*enable states*/
2700 164 : if (!is_debug_bounds) {
2701 164 : if (visual->has_fog) visual_3d_enable_fog(visual);
2702 :
2703 164 : if (visual->state_color_on) glEnable(GL_COLOR_MATERIAL);
2704 162 : else glDisable(GL_COLOR_MATERIAL);
2705 :
2706 164 : if (visual->state_blend_on) glEnable(GL_BLEND);
2707 : }
2708 :
2709 :
2710 : //setup scissor
2711 164 : visual_3d_set_clipper_scissor(visual, tr_state);
2712 :
2713 164 : visual_3d_set_clippers(visual, tr_state);
2714 :
2715 164 : glEnableClientState(GL_VERTEX_ARRAY);
2716 : #if defined(GPAC_USE_GLES1X)
2717 : glVertexPointer(3, GL_FIXED, sizeof(GF_Vertex), base_address);
2718 : #elif defined(GPAC_FIXED_POINT)
2719 : /*scale modelview matrix*/
2720 : glPushMatrix();
2721 : glScalef(fix_scale, fix_scale, fix_scale);
2722 : glVertexPointer(3, GL_INT, sizeof(GF_Vertex), base_address);
2723 : #else
2724 164 : glVertexPointer(3, GL_FLOAT, sizeof(GF_Vertex), base_address);
2725 : #endif
2726 :
2727 :
2728 : /*
2729 : * Enable colors:
2730 : if mat2d is set, use mat2d and no lighting
2731 : */
2732 164 : if (visual->has_material_2d) {
2733 10 : glDisable(GL_LIGHTING);
2734 10 : if (visual->mat_2d.alpha != FIX_ONE) {
2735 0 : glEnable(GL_BLEND);
2736 : visual_3d_enable_antialias(visual, 0);
2737 : } else {
2738 : //disable blending only if no texture !
2739 10 : if (!tr_state->mesh_num_textures)
2740 10 : glDisable(GL_BLEND);
2741 10 : visual_3d_enable_antialias(visual, visual->compositor->aa ? 1 : 0);
2742 : }
2743 : #ifdef GPAC_USE_GLES1X
2744 : glColor4x( FIX2INT(visual->mat_2d.red * 255), FIX2INT(visual->mat_2d.green * 255), FIX2INT(visual->mat_2d.blue * 255), FIX2INT(visual->mat_2d.alpha * 255));
2745 : #elif defined(GPAC_FIXED_POINT)
2746 : glColor4f(FIX2FLT(visual->mat_2d.red), FIX2FLT(visual->mat_2d.green), FIX2FLT(visual->mat_2d.blue), FIX2FLT(visual->mat_2d.alpha));
2747 : #else
2748 10 : glColor4f(visual->mat_2d.red, visual->mat_2d.green, visual->mat_2d.blue, visual->mat_2d.alpha);
2749 : #endif
2750 : }
2751 :
2752 : //setup material color
2753 164 : if (visual->has_material) {
2754 : u32 i;
2755 : GL_CHECK_ERR()
2756 608 : for (i=0; i<4; i++) {
2757 : GLenum mode;
2758 608 : Fixed *rgba = (Fixed *) & visual->materials[i];
2759 : #if defined(GPAC_USE_GLES1X)
2760 : Fixed *_rgba = (Fixed *) rgba;
2761 : #elif defined(GPAC_FIXED_POINT)
2762 : Float _rgba[4];
2763 : _rgba[0] = FIX2FLT(rgba[0]);
2764 : _rgba[1] = FIX2FLT(rgba[1]);
2765 : _rgba[2] = FIX2FLT(rgba[2]);
2766 : _rgba[3] = FIX2FLT(rgba[3]);
2767 : #else
2768 : Float *_rgba = (Float *) rgba;
2769 : #endif
2770 :
2771 : switch (i) {
2772 : case 0:
2773 : mode = GL_AMBIENT;
2774 : break;
2775 : case 1:
2776 : mode = GL_DIFFUSE;
2777 : break;
2778 : case 2:
2779 : mode = GL_SPECULAR;
2780 : break;
2781 : default:
2782 : mode = GL_EMISSION;
2783 : break;
2784 : }
2785 :
2786 : #if defined(GPAC_USE_GLES1X) && defined(GPAC_FIXED_POINT)
2787 : glMaterialxv(GL_FRONT_AND_BACK, mode, _rgba);
2788 : #else
2789 608 : glMaterialfv(GL_FRONT_AND_BACK, mode, _rgba);
2790 : #endif
2791 : GL_CHECK_ERR()
2792 : }
2793 : #ifdef GPAC_USE_GLES1X
2794 : glMaterialx(GL_FRONT_AND_BACK, GL_SHININESS, visual->shininess * 128);
2795 : #else
2796 152 : glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, FIX2FLT(visual->shininess) * 128);
2797 : #endif
2798 : GL_CHECK_ERR()
2799 : }
2800 :
2801 : //otherwise setup mesh color
2802 164 : if (!tr_state->mesh_num_textures && (mesh->flags & MESH_HAS_COLOR)) {
2803 0 : glEnable(GL_COLOR_MATERIAL);
2804 : #if !defined (GPAC_USE_GLES1X)
2805 0 : glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
2806 : #endif
2807 0 : glEnableClientState(GL_COLOR_ARRAY);
2808 : has_col = 1;
2809 :
2810 : #if defined (GPAC_USE_GLES1X)
2811 :
2812 : if (mesh->flags & MESH_HAS_ALPHA) {
2813 : glEnable(GL_BLEND);
2814 : tr_state->mesh_is_transparent = 1;
2815 : }
2816 : #ifdef MESH_USE_SFCOLOR
2817 : /*glES only accepts full RGBA colors*/
2818 : glColorPointer(4, GL_FIXED, sizeof(GF_Vertex), ((char *)base_address + MESH_COLOR_OFFSET));
2819 : #else
2820 : glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(GF_Vertex), ((char *)base_address + MESH_COLOR_OFFSET));
2821 : #endif /*MESH_USE_SFCOLOR*/
2822 :
2823 : #elif defined (GPAC_FIXED_POINT)
2824 :
2825 :
2826 : #ifdef MESH_USE_SFCOLOR
2827 : /*this is a real pain: we cannot "scale" colors through openGL, and our components are 16.16 (32 bytes) ranging
2828 : from [0 to 65536] mapping to [0, 1.0], but openGL assumes for s32 a range from [-2^31 2^31] mapping to [0, 1.0]
2829 : we must thus rebuild a dedicated array...*/
2830 : if (mesh->flags & MESH_HAS_ALPHA) {
2831 : u32 i;
2832 : color_array = gf_malloc(sizeof(Float)*4*mesh->v_count);
2833 : for (i=0; i<mesh->v_count; i++) {
2834 : color_array[4*i] = FIX2FLT(mesh->vertices[i].color.red);
2835 : color_array[4*i+1] = FIX2FLT(mesh->vertices[i].color.green);
2836 : color_array[4*i+2] = FIX2FLT(mesh->vertices[i].color.blue);
2837 : color_array[4*i+3] = FIX2FLT(mesh->vertices[i].color.alpha);
2838 : }
2839 : glEnable(GL_BLEND);
2840 : glColorPointer(4, GL_FLOAT, 4*sizeof(Float), color_array);
2841 : tr_state->mesh_is_transparent = 1;
2842 : } else {
2843 : color_array = gf_malloc(sizeof(Float)*3*mesh->v_count);
2844 : for (i=0; i<mesh->v_count; i++) {
2845 : color_array[3*i] = FIX2FLT(mesh->vertices[i].color.red);
2846 : color_array[3*i+1] = FIX2FLT(mesh->vertices[i].color.green);
2847 : color_array[3*i+2] = FIX2FLT(mesh->vertices[i].color.blue);
2848 : }
2849 : glColorPointer(3, GL_FLOAT, 3*sizeof(Float), color_array);
2850 : }
2851 : #else
2852 : glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(GF_Vertex), ((char *)base_address + MESH_COLOR_OFFSET));
2853 : #endif /*MESH_USE_SFCOLOR*/
2854 :
2855 : #else
2856 :
2857 : #ifdef MESH_USE_SFCOLOR
2858 : if (mesh->flags & MESH_HAS_ALPHA) {
2859 : glEnable(GL_BLEND);
2860 : glColorPointer(4, GL_FLOAT, sizeof(GF_Vertex), ((char *)base_address + MESH_COLOR_OFFSET));
2861 : tr_state->mesh_is_transparent = 1;
2862 : } else {
2863 : glColorPointer(3, GL_FLOAT, sizeof(GF_Vertex), ((char *)base_address + MESH_COLOR_OFFSET));
2864 : }
2865 : #else
2866 0 : if (mesh->flags & MESH_HAS_ALPHA) {
2867 0 : glEnable(GL_BLEND);
2868 0 : tr_state->mesh_is_transparent = 1;
2869 0 : glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(GF_Vertex), ((char *)base_address + MESH_COLOR_OFFSET));
2870 : } else {
2871 0 : glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(GF_Vertex), ((char *)base_address + MESH_COLOR_OFFSET));
2872 : }
2873 : #endif /*MESH_USE_SFCOLOR*/
2874 :
2875 : #endif
2876 : }
2877 :
2878 164 : if (tr_state->mesh_num_textures && (mesh->mesh_type==MESH_TRIANGLES) && !(mesh->flags & MESH_NO_TEXTURE)) {
2879 : has_tx = 1;
2880 :
2881 2 : glMatrixMode(GL_TEXTURE);
2882 2 : if (visual->has_tx_matrix) {
2883 2 : visual_3d_matrix_load(visual, visual->tx_matrix.m);
2884 : } else {
2885 0 : glLoadIdentity();
2886 : }
2887 2 : glMatrixMode(GL_MODELVIEW);
2888 :
2889 :
2890 : #if defined(GPAC_USE_GLES1X)
2891 : glTexCoordPointer(2, GL_FIXED, sizeof(GF_Vertex), ((char *)base_address + MESH_TEX_OFFSET));
2892 : glEnableClientState(GL_TEXTURE_COORD_ARRAY );
2893 : #elif defined(GPAC_FIXED_POINT)
2894 : glMatrixMode(GL_TEXTURE);
2895 : glPushMatrix();
2896 : glScalef(fix_scale, fix_scale, fix_scale);
2897 : glMatrixMode(GL_MODELVIEW);
2898 : glTexCoordPointer(2, GL_INT, sizeof(GF_Vertex), ((char *)base_address + MESH_TEX_OFFSET));
2899 : glEnableClientState(GL_TEXTURE_COORD_ARRAY );
2900 : #else
2901 :
2902 : #ifndef GPAC_USE_TINYGL
2903 2 : if (tr_state->mesh_num_textures>1) {
2904 : u32 i;
2905 0 : for (i=0; i<tr_state->mesh_num_textures; i++) {
2906 0 : glClientActiveTexture(GL_TEXTURE0 + i);
2907 0 : glTexCoordPointer(2, GL_FLOAT, sizeof(GF_Vertex), ((char *)base_address + MESH_TEX_OFFSET));
2908 0 : glEnableClientState(GL_TEXTURE_COORD_ARRAY);
2909 : }
2910 : } else
2911 : #endif //GPAC_USE_TINYGL
2912 : {
2913 2 : glTexCoordPointer(2, GL_FLOAT, sizeof(GF_Vertex), ((char *)base_address + MESH_TEX_OFFSET));
2914 2 : glEnableClientState(GL_TEXTURE_COORD_ARRAY );
2915 : }
2916 : #endif
2917 : }
2918 :
2919 164 : if (mesh->mesh_type != MESH_TRIANGLES) {
2920 : #ifdef GPAC_USE_GLES1X
2921 : glNormal3x(0, 0, FIX_ONE);
2922 : #else
2923 0 : glNormal3f(0, 0, 1.0f);
2924 : #endif
2925 0 : glDisable(GL_CULL_FACE);
2926 0 : glDisable(GL_LIGHTING);
2927 0 : if (mesh->mesh_type==MESH_LINESET) glDisable(GL_LINE_SMOOTH);
2928 0 : else glDisable(GL_POINT_SMOOTH);
2929 :
2930 : #if !defined(GPAC_USE_TINYGL) && !defined(GL_ES_CL_PROFILE)
2931 0 : glLineWidth(1.0f);
2932 : #endif
2933 :
2934 : } else {
2935 : u32 normal_type = GL_FLOAT;
2936 : has_norm = 1;
2937 164 : glEnableClientState(GL_NORMAL_ARRAY );
2938 : #ifdef MESH_USE_FIXED_NORMAL
2939 :
2940 : #if defined(GPAC_USE_GLES1X)
2941 : normal_type = GL_FIXED;
2942 : #elif defined(GPAC_FIXED_POINT)
2943 : normal_type = GL_INT;
2944 : #else
2945 : normal_type = GL_FLOAT;
2946 : #endif
2947 :
2948 : #else /*MESH_USE_FIXED_NORMAL*/
2949 : /*normals are stored on signed bytes*/
2950 : normal_type = GL_BYTE;
2951 : #endif
2952 164 : glNormalPointer(normal_type, sizeof(GF_Vertex), ((char *)base_address + MESH_NORMAL_OFFSET));
2953 :
2954 164 : if (mesh->mesh_type==MESH_TRIANGLES) {
2955 164 : if (compositor->bcull
2956 164 : && (!tr_state->mesh_is_transparent || (compositor->bcull ==GF_BACK_CULL_ALPHA) )
2957 164 : && (mesh->flags & MESH_IS_SOLID)) {
2958 0 : glEnable(GL_CULL_FACE);
2959 0 : glFrontFace((mesh->flags & MESH_IS_CW) ? GL_CW : GL_CCW);
2960 : } else {
2961 164 : glDisable(GL_CULL_FACE);
2962 : }
2963 : }
2964 : }
2965 :
2966 : GL_CHECK_ERR()
2967 164 : visual_3d_do_draw_mesh(tr_state, mesh);
2968 : GL_CHECK_ERR()
2969 :
2970 164 : glDisableClientState(GL_VERTEX_ARRAY);
2971 164 : if (has_col) glDisableClientState(GL_COLOR_ARRAY);
2972 164 : glDisable(GL_COLOR_MATERIAL);
2973 :
2974 164 : if (has_tx) glDisableClientState(GL_TEXTURE_COORD_ARRAY);
2975 164 : if (has_norm) glDisableClientState(GL_NORMAL_ARRAY);
2976 :
2977 164 : if (mesh->vbo)
2978 152 : glBindBuffer(GL_ARRAY_BUFFER, 0);
2979 :
2980 : #if defined(GPAC_FIXED_POINT) && !defined(GPAC_USE_GLES1X)
2981 : if (color_array) gf_free(color_array);
2982 : if (tr_state->mesh_num_textures && (mesh->mesh_type==MESH_TRIANGLES) && !(mesh->flags & MESH_NO_TEXTURE)) {
2983 : glMatrixMode(GL_TEXTURE);
2984 : glPopMatrix();
2985 : glMatrixMode(GL_MODELVIEW);
2986 : }
2987 : glPopMatrix();
2988 : #endif
2989 :
2990 :
2991 164 : if (visual->has_clipper_2d) {
2992 0 : glDisable(GL_SCISSOR_TEST);
2993 : }
2994 164 : visual_3d_reset_lights(visual);
2995 :
2996 164 : glDisable(GL_COLOR_MATERIAL);
2997 :
2998 : //reset all our states
2999 : visual_3d_reset_clippers(visual);
3000 164 : visual->has_material_2d = GF_FALSE;
3001 164 : visual->has_material = 0;
3002 164 : visual->state_color_on = 0;
3003 164 : if (tr_state->mesh_is_transparent) glDisable(GL_BLEND);
3004 164 : tr_state->mesh_is_transparent = 0;
3005 :
3006 : GL_CHECK_ERR()
3007 : #endif
3008 : }
3009 :
3010 0 : static void visual_3d_set_debug_color(u32 col)
3011 : {
3012 : #ifndef GPAC_USE_GLES2
3013 :
3014 : #ifdef GPAC_USE_GLES1X
3015 : glColor4x( (col ? GF_COL_R(col) : 255) , (col ? GF_COL_G(col) : 0) , (col ? GF_COL_B(col) : 255), 255);
3016 : #else
3017 1059 : glColor4f(col ? GF_COL_R(col)/255.0f : 1, col ? GF_COL_G(col)/255.0f : 0, col ? GF_COL_B(col)/255.0f : 1, 1);
3018 : #endif
3019 :
3020 :
3021 : #endif //GPAC_USE_GLES2
3022 0 : }
3023 :
3024 :
3025 : /*note we don't perform any culling for normal drawing...*/
3026 152 : static void visual_3d_draw_normals(GF_TraverseState *tr_state, GF_Mesh *mesh)
3027 : {
3028 : #if !defined( GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES2)
3029 :
3030 : GF_Vec pt, end;
3031 : u32 i, j;
3032 152 : Fixed scale = mesh->bounds.radius / 4;
3033 :
3034 : #ifdef GPAC_USE_GLES1X
3035 : GF_Vec va[2];
3036 : u16 indices[2];
3037 : glEnableClientState(GL_VERTEX_ARRAY);
3038 : #endif
3039 :
3040 : visual_3d_set_debug_color(0);
3041 :
3042 : #if !defined(GPAC_DISABLE_3D) && !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES1X)
3043 : //in shader mode force pushing projection and modelview using fixed pipeline API
3044 152 : if (!tr_state->visual->compositor->shader_mode_disabled) {
3045 152 : tr_state->visual->needs_projection_matrix_reload=GF_TRUE;
3046 152 : visual_3d_update_matrices(tr_state);
3047 : }
3048 : #endif
3049 :
3050 152 : if (tr_state->visual->compositor->norms==GF_NORMALS_VERTEX) {
3051 0 : IDX_TYPE *idx = mesh->indices;
3052 0 : for (i=0; i<mesh->i_count; i+=3) {
3053 0 : for (j=0; j<3; j++) {
3054 0 : pt = mesh->vertices[idx[j]].pos;
3055 0 : MESH_GET_NORMAL(end, mesh->vertices[idx[j]]);
3056 0 : end = gf_vec_scale(end, scale);
3057 0 : gf_vec_add(end, pt, end);
3058 : #ifdef GPAC_USE_GLES1X
3059 : va[0] = pt;
3060 : va[1] = end;
3061 : indices[0] = 0;
3062 : indices[1] = 1;
3063 : glVertexPointer(3, GL_FIXED, 0, va);
3064 : glDrawElements(GL_LINES, 2, GL_UNSIGNED_SHORT, indices);
3065 : #else
3066 0 : glBegin(GL_LINES);
3067 0 : glVertex3f(FIX2FLT(pt.x), FIX2FLT(pt.y), FIX2FLT(pt.z));
3068 0 : glVertex3f(FIX2FLT(end.x), FIX2FLT(end.y), FIX2FLT(end.z));
3069 0 : glEnd();
3070 : #endif
3071 : }
3072 0 : idx+=3;
3073 : }
3074 : } else {
3075 152 : IDX_TYPE *idx = mesh->indices;
3076 190456 : for (i=0; i<mesh->i_count; i+=3) {
3077 190304 : gf_vec_add(pt, mesh->vertices[idx[0]].pos, mesh->vertices[idx[1]].pos);
3078 190304 : gf_vec_add(pt, pt, mesh->vertices[idx[2]].pos);
3079 190304 : pt = gf_vec_scale(pt, FIX_ONE/3);
3080 190304 : MESH_GET_NORMAL(end, mesh->vertices[idx[0]]);
3081 190304 : end = gf_vec_scale(end, scale);
3082 190304 : gf_vec_add(end, pt, end);
3083 :
3084 : #ifdef GPAC_USE_GLES1X
3085 : va[0] = pt;
3086 : va[1] = end;
3087 : indices[0] = 0;
3088 : indices[1] = 1;
3089 : glVertexPointer(3, GL_FIXED, 0, va);
3090 : glDrawElements(GL_LINES, 2, GL_UNSIGNED_SHORT, indices);
3091 : #else
3092 190304 : glBegin(GL_LINES);
3093 190304 : glVertex3f(FIX2FLT(pt.x), FIX2FLT(pt.y), FIX2FLT(pt.z));
3094 190304 : glVertex3f(FIX2FLT(end.x), FIX2FLT(end.y), FIX2FLT(end.z));
3095 190304 : glEnd();
3096 : #endif
3097 190304 : idx += 3;
3098 : }
3099 : }
3100 : #ifdef GPAC_USE_GLES1X
3101 : glDisableClientState(GL_VERTEX_ARRAY);
3102 : #endif
3103 :
3104 : #endif /*GPAC_USE_TINYGL*/
3105 152 : }
3106 :
3107 :
3108 34048 : void visual_3d_draw_aabb_nodeBounds(GF_TraverseState *tr_state, AABBNode *node)
3109 : {
3110 67944 : if (node->pos) {
3111 33896 : visual_3d_draw_aabb_nodeBounds(tr_state, node->pos);
3112 33896 : visual_3d_draw_aabb_nodeBounds(tr_state, node->neg);
3113 : } else {
3114 : GF_Matrix mx;
3115 : SFVec3f c, s;
3116 34048 : gf_vec_diff(s, node->max, node->min);
3117 34048 : c = gf_vec_scale(s, FIX_ONE/2);
3118 34048 : gf_vec_add(c, node->min, c);
3119 :
3120 34048 : gf_mx_copy(mx, tr_state->model_matrix);
3121 34048 : gf_mx_add_translation(&tr_state->model_matrix, c.x, c.y, c.z);
3122 34048 : gf_mx_add_scale(&tr_state->model_matrix, s.x, s.y, s.z);
3123 :
3124 34048 : visual_3d_draw_mesh(tr_state, NULL);
3125 :
3126 : gf_mx_copy(tr_state->model_matrix, mx);
3127 : }
3128 34048 : }
3129 :
3130 755 : void visual_3d_draw_bbox(GF_TraverseState *tr_state, GF_BBox *box, Bool is_debug)
3131 : {
3132 : GF_Matrix mx;
3133 : SFVec3f c, s;
3134 :
3135 755 : if (! is_debug) {
3136 0 : visual_3d_set_debug_color(tr_state->visual->compositor->hlline);
3137 : }
3138 :
3139 755 : gf_vec_diff(s, box->max_edge, box->min_edge);
3140 755 : c.x = box->min_edge.x + s.x/2;
3141 755 : c.y = box->min_edge.y + s.y/2;
3142 755 : c.z = box->min_edge.z + s.z/2;
3143 :
3144 755 : gf_mx_copy(mx, tr_state->model_matrix);
3145 755 : gf_mx_add_translation(&tr_state->model_matrix, c.x, c.y, c.z);
3146 755 : gf_mx_add_scale(&tr_state->model_matrix, s.x, s.y, s.z);
3147 :
3148 755 : visual_3d_draw_mesh(tr_state, NULL);
3149 : gf_mx_copy(tr_state->model_matrix, mx);
3150 755 : }
3151 :
3152 907 : static void visual_3d_draw_bounds(GF_TraverseState *tr_state, GF_Mesh *mesh)
3153 : {
3154 : visual_3d_set_debug_color(0);
3155 :
3156 907 : if (mesh->aabb_root && (tr_state->visual->compositor->bvol==GF_BOUNDS_AABB)) {
3157 152 : visual_3d_draw_aabb_nodeBounds(tr_state, mesh->aabb_root);
3158 : } else {
3159 755 : visual_3d_draw_bbox(tr_state, &mesh->bounds, GF_TRUE);
3160 : }
3161 907 : }
3162 :
3163 28804 : void visual_3d_mesh_paint(GF_TraverseState *tr_state, GF_Mesh *mesh)
3164 : {
3165 : #if !defined(GPAC_USE_GLES2)
3166 : Bool mesh_drawn = 0;
3167 : #endif
3168 :
3169 : GL_CHECK_ERR()
3170 :
3171 28804 : gf_rmt_begin_gl(visual_3d_mesh_paint);
3172 28804 : glGetError();
3173 :
3174 28804 : GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[V3D] Drawing mesh %p\n", mesh));
3175 28804 : if (tr_state->visual->compositor->wire != GF_WIREFRAME_ONLY) {
3176 28804 : visual_3d_draw_mesh(tr_state, mesh);
3177 : #if !defined(GPAC_USE_GLES2)
3178 : mesh_drawn = 1;
3179 : #endif
3180 : }
3181 :
3182 : #if !defined(GPAC_USE_GLES2)
3183 28804 : if (tr_state->visual->compositor->norms) {
3184 152 : if (!mesh_drawn) {
3185 0 : visual_3d_update_matrices(tr_state);
3186 : mesh_drawn=1;
3187 : }
3188 152 : visual_3d_draw_normals(tr_state, mesh);
3189 : }
3190 :
3191 28804 : if ((mesh->mesh_type==MESH_TRIANGLES) && (tr_state->visual->compositor->wire != GF_WIREFRAME_NONE)) {
3192 0 : glDisable(GL_LIGHTING);
3193 : visual_3d_set_debug_color(0xFFFFFFFF);
3194 :
3195 0 : if (!mesh_drawn)
3196 0 : visual_3d_update_matrices(tr_state);
3197 :
3198 :
3199 0 : glEnableClientState(GL_VERTEX_ARRAY);
3200 : #ifdef GPAC_USE_GLES1X
3201 : glVertexPointer(3, GL_FIXED, sizeof(GF_Vertex), &mesh->vertices[0].pos);
3202 : glDrawElements(GL_LINES, mesh->i_count, GL_UNSIGNED_SHORT, mesh->indices);
3203 : #else
3204 0 : glVertexPointer(3, GL_FLOAT, sizeof(GF_Vertex), &mesh->vertices[0].pos);
3205 0 : glDrawElements(GL_LINES, mesh->i_count, GL_UNSIGNED_INT, mesh->indices);
3206 : #endif
3207 0 : glDisableClientState(GL_VERTEX_ARRAY);
3208 : }
3209 :
3210 : #endif
3211 :
3212 28804 : if (tr_state->visual->compositor->bvol)
3213 907 : visual_3d_draw_bounds(tr_state, mesh);
3214 :
3215 28804 : GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[V3D] Done drawing mesh %p\n", mesh));
3216 :
3217 28804 : gf_rmt_end_gl();
3218 28804 : glGetError();
3219 28804 : }
3220 :
3221 : #if !defined(GPAC_USE_GLES1X) && !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES2)
3222 :
3223 :
3224 : static GLubyte hatch_horiz[] = {
3225 : 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
3226 : 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
3227 : 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
3228 : 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
3229 : 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
3230 : 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
3231 : 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
3232 : 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
3233 : 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
3234 : 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
3235 : 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
3236 : 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
3237 : 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
3238 : 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
3239 : 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
3240 : 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff
3241 : };
3242 :
3243 : static GLubyte hatch_vert[] = {
3244 : 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
3245 : 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
3246 : 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
3247 : 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
3248 : 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
3249 : 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
3250 : 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
3251 : 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
3252 : 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
3253 : 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
3254 : 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
3255 : 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
3256 : 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
3257 : 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
3258 : 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
3259 : 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa
3260 : };
3261 :
3262 : static GLubyte hatch_up[] = {
3263 : 0xc0, 0xc0, 0xc0, 0xc0, 0x30, 0x30, 0x30, 0x30,
3264 : 0x0c, 0x0c, 0x0c, 0x0c, 0x03, 0x03, 0x03, 0x03,
3265 : 0xc0, 0xc0, 0xc0, 0xc0, 0x30, 0x30, 0x30, 0x30,
3266 : 0x0c, 0x0c, 0x0c, 0x0c, 0x03, 0x03, 0x03, 0x03,
3267 : 0xc0, 0xc0, 0xc0, 0xc0, 0x30, 0x30, 0x30, 0x30,
3268 : 0x0c, 0x0c, 0x0c, 0x0c, 0x03, 0x03, 0x03, 0x03,
3269 : 0xc0, 0xc0, 0xc0, 0xc0, 0x30, 0x30, 0x30, 0x30,
3270 : 0x0c, 0x0c, 0x0c, 0x0c, 0x03, 0x03, 0x03, 0x03,
3271 : 0xc0, 0xc0, 0xc0, 0xc0, 0x30, 0x30, 0x30, 0x30,
3272 : 0x0c, 0x0c, 0x0c, 0x0c, 0x03, 0x03, 0x03, 0x03,
3273 : 0xc0, 0xc0, 0xc0, 0xc0, 0x30, 0x30, 0x30, 0x30,
3274 : 0x0c, 0x0c, 0x0c, 0x0c, 0x03, 0x03, 0x03, 0x03,
3275 : 0xc0, 0xc0, 0xc0, 0xc0, 0x30, 0x30, 0x30, 0x30,
3276 : 0x0c, 0x0c, 0x0c, 0x0c, 0x03, 0x03, 0x03, 0x03,
3277 : 0xc0, 0xc0, 0xc0, 0xc0, 0x30, 0x30, 0x30, 0x30,
3278 : 0x0c, 0x0c, 0x0c, 0x0c, 0x03, 0x03, 0x03, 0x03
3279 : };
3280 :
3281 : static GLubyte hatch_down[] = {
3282 : 0x03, 0x03, 0x03, 0x03, 0x0c, 0x0c, 0x0c, 0x0c,
3283 : 0x30, 0x30, 0x30, 0x30, 0xc0, 0xc0, 0xc0, 0xc0,
3284 : 0x03, 0x03, 0x03, 0x03, 0x0c, 0x0c, 0x0c, 0x0c,
3285 : 0x30, 0x30, 0x30, 0x30, 0xc0, 0xc0, 0xc0, 0xc0,
3286 : 0x03, 0x03, 0x03, 0x03, 0x0c, 0x0c, 0x0c, 0x0c,
3287 : 0x30, 0x30, 0x30, 0x30, 0xc0, 0xc0, 0xc0, 0xc0,
3288 : 0x03, 0x03, 0x03, 0x03, 0x0c, 0x0c, 0x0c, 0x0c,
3289 : 0x30, 0x30, 0x30, 0x30, 0xc0, 0xc0, 0xc0, 0xc0,
3290 : 0x03, 0x03, 0x03, 0x03, 0x0c, 0x0c, 0x0c, 0x0c,
3291 : 0x30, 0x30, 0x30, 0x30, 0xc0, 0xc0, 0xc0, 0xc0,
3292 : 0x03, 0x03, 0x03, 0x03, 0x0c, 0x0c, 0x0c, 0x0c,
3293 : 0x30, 0x30, 0x30, 0x30, 0xc0, 0xc0, 0xc0, 0xc0,
3294 : 0x03, 0x03, 0x03, 0x03, 0x0c, 0x0c, 0x0c, 0x0c,
3295 : 0x30, 0x30, 0x30, 0x30, 0xc0, 0xc0, 0xc0, 0xc0,
3296 : 0x03, 0x03, 0x03, 0x03, 0x0c, 0x0c, 0x0c, 0x0c,
3297 : 0x30, 0x30, 0x30, 0x30, 0xc0, 0xc0, 0xc0, 0xc0
3298 : };
3299 :
3300 : static GLubyte hatch_cross[] = {
3301 : 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c,
3302 : 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3303 : 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3304 : 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c,
3305 : 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c,
3306 : 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3307 : 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3308 : 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c,
3309 : 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c,
3310 : 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3311 : 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3312 : 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c,
3313 : 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c,
3314 : 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3315 : 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3316 : 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c
3317 : };
3318 :
3319 2 : void visual_3d_mesh_hatch(GF_TraverseState *tr_state, GF_Mesh *mesh, u32 hatchStyle, SFColor hatchColor)
3320 : {
3321 2 : if (mesh->mesh_type != MESH_TRIANGLES) return;
3322 :
3323 2 : glEnableClientState(GL_VERTEX_ARRAY);
3324 2 : glVertexPointer(3, GL_FLOAT, sizeof(GF_Vertex), &mesh->vertices[0].pos);
3325 2 : if (mesh->flags & MESH_IS_2D) {
3326 0 : glDisableClientState(GL_NORMAL_ARRAY);
3327 0 : glNormal3f(0, 0, 1.0f);
3328 0 : glDisable(GL_CULL_FACE);
3329 : } else {
3330 2 : glEnableClientState(GL_NORMAL_ARRAY );
3331 2 : glNormalPointer(GL_FLOAT, sizeof(GF_Vertex), &mesh->vertices[0].normal);
3332 :
3333 : /*if mesh is transparent DON'T CULL*/
3334 2 : if (!tr_state->mesh_is_transparent && (mesh->flags & MESH_IS_SOLID)) {
3335 2 : glEnable(GL_CULL_FACE);
3336 2 : glFrontFace((mesh->flags & MESH_IS_CW) ? GL_CW : GL_CCW);
3337 : } else {
3338 0 : glDisable(GL_CULL_FACE);
3339 : }
3340 : }
3341 :
3342 2 : glEnable(GL_POLYGON_STIPPLE);
3343 2 : glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
3344 : /*can't access ISO International Register of Graphical Items www site :)*/
3345 2 : switch (hatchStyle) {
3346 2 : case 5:
3347 2 : glPolygonStipple(hatch_cross);
3348 2 : break;
3349 0 : case 4:
3350 0 : glPolygonStipple(hatch_up);
3351 0 : break;
3352 0 : case 3:
3353 0 : glPolygonStipple(hatch_down);
3354 0 : break;
3355 0 : case 2:
3356 0 : glPolygonStipple(hatch_vert);
3357 0 : break;
3358 0 : case 1:
3359 0 : glPolygonStipple(hatch_horiz);
3360 0 : break;
3361 0 : default:
3362 0 : glDisable(GL_POLYGON_STIPPLE);
3363 0 : break;
3364 : }
3365 2 : glColor3f(FIX2FLT(hatchColor.red), FIX2FLT(hatchColor.green), FIX2FLT(hatchColor.blue));
3366 2 : glDrawElements(GL_TRIANGLES, mesh->i_count, GL_UNSIGNED_INT, mesh->indices);
3367 :
3368 2 : glDisable(GL_POLYGON_STIPPLE);
3369 : }
3370 : #endif
3371 :
3372 : /*only used for ILS/ILS2D or IFS2D outline*/
3373 0 : void visual_3d_mesh_strike(GF_TraverseState *tr_state, GF_Mesh *mesh, Fixed width, Fixed line_scale, u32 dash_style)
3374 : {
3375 : #if !defined(GPAC_USE_GLES1X) && !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES2)
3376 : u16 style;
3377 : #endif
3378 :
3379 0 : if (mesh->mesh_type != MESH_LINESET) return;
3380 0 : if (line_scale) width = gf_mulfix(width, line_scale);
3381 0 : width/=2;
3382 : #if !defined(GPAC_USE_TINYGL) && !defined(GL_ES_CL_PROFILE)
3383 0 : glLineWidth( FIX2FLT(width));
3384 : #endif
3385 :
3386 : #if !defined(GPAC_USE_GLES1X) && !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES2)
3387 :
3388 0 : switch (dash_style) {
3389 : case GF_DASH_STYLE_DASH:
3390 : style = 0x1F1F;
3391 : break;
3392 : case GF_DASH_STYLE_DOT:
3393 : style = 0x3333;
3394 : break;
3395 : case GF_DASH_STYLE_DASH_DOT:
3396 : style = 0x6767;
3397 : break;
3398 : case GF_DASH_STYLE_DASH_DASH_DOT:
3399 : style = 0x33CF;
3400 : break;
3401 : case GF_DASH_STYLE_DASH_DOT_DOT:
3402 : style = 0x330F;
3403 : break;
3404 : default:
3405 : style = 0;
3406 : break;
3407 : }
3408 : if (style) {
3409 0 : u32 factor = FIX2INT(width);
3410 0 : if (!factor) factor = 1;
3411 0 : glEnable(GL_LINE_STIPPLE);
3412 0 : glLineStipple(factor, style);
3413 0 : visual_3d_mesh_paint(tr_state, mesh);
3414 0 : glDisable (GL_LINE_STIPPLE);
3415 : } else
3416 : #endif
3417 0 : visual_3d_mesh_paint(tr_state, mesh);
3418 : }
3419 :
3420 :
3421 8400 : void visual_3d_clear(GF_VisualManager *visual, SFColor color, Fixed alpha)
3422 : {
3423 : #ifdef GPAC_USE_GLES1X
3424 : glClearColorx(color.red, color.green, color.blue, alpha);
3425 : #else
3426 8400 : glClearColor(FIX2FLT(color.red), FIX2FLT(color.green), FIX2FLT(color.blue), FIX2FLT(alpha));
3427 : #endif
3428 8400 : glClear(GL_COLOR_BUFFER_BIT);
3429 8400 : }
3430 :
3431 :
3432 0 : void visual_3d_fill_rect(GF_VisualManager *visual, GF_Rect rc, SFColorRGBA color)
3433 : {
3434 : //TODOk - code this for GLES2 ?
3435 : #ifdef GPAC_USE_GLES2
3436 : #else
3437 :
3438 0 : glDisable(GL_BLEND | GL_LIGHTING | GL_TEXTURE_2D);
3439 :
3440 : #if defined(GPAC_USE_GLES1X)
3441 : glNormal3x(0, 0, FIX_ONE);
3442 : if (color.alpha!=FIX_ONE) glEnable(GL_BLEND);
3443 : glColor4x(color.red, color.green, color.blue, color.alpha);
3444 : {
3445 : Fixed v[8];
3446 : u16 indices[3];
3447 : indices[0] = 0;
3448 : indices[1] = 1;
3449 : indices[2] = 2;
3450 :
3451 : v[0] = rc.x;
3452 : v[1] = rc.y;
3453 : v[2] = rc.x+rc.width;
3454 : v[3] = rc.y-rc.height;
3455 : v[4] = rc.x+rc.width;
3456 : v[5] = rc.y;
3457 : glEnableClientState(GL_VERTEX_ARRAY);
3458 : glVertexPointer(2, GL_FIXED, 0, v);
3459 : glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, indices);
3460 :
3461 : v[4] = rc.x;
3462 : v[5] = rc.y-rc.height;
3463 : glVertexPointer(2, GL_FIXED, 0, v);
3464 : glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, indices);
3465 :
3466 : glDisableClientState(GL_VERTEX_ARRAY);
3467 : }
3468 : #else
3469 0 : glNormal3f(0, 0, 1);
3470 0 : if (color.alpha!=FIX_ONE) {
3471 0 : glEnable(GL_BLEND);
3472 0 : glColor4f(FIX2FLT(color.red), FIX2FLT(color.green), FIX2FLT(color.blue), FIX2FLT(color.alpha));
3473 : } else {
3474 0 : glColor3f(FIX2FLT(color.red), FIX2FLT(color.green), FIX2FLT(color.blue));
3475 : }
3476 0 : glBegin(GL_QUADS);
3477 0 : glVertex3f(FIX2FLT(rc.x), FIX2FLT(rc.y), 0);
3478 0 : glVertex3f(FIX2FLT(rc.x), FIX2FLT(rc.y-rc.height), 0);
3479 0 : glVertex3f(FIX2FLT(rc.x+rc.width), FIX2FLT(rc.y-rc.height), 0);
3480 0 : glVertex3f(FIX2FLT(rc.x+rc.width), FIX2FLT(rc.y), 0);
3481 0 : glEnd();
3482 :
3483 0 : glDisable(GL_COLOR_MATERIAL | GL_COLOR_MATERIAL_FACE);
3484 : #endif
3485 :
3486 0 : glDisable(GL_BLEND);
3487 : #endif
3488 0 : }
3489 :
3490 : //note that we always use glReadPixel even if the actual rendering target is a texture
3491 : //this is the recommended way by khronos any way
3492 6773 : GF_Err compositor_3d_get_screen_buffer(GF_Compositor *compositor, GF_VideoSurface *fb, u32 depth_dump_mode)
3493 : {
3494 : u32 i;
3495 :
3496 6773 : fb->width = compositor->display_width;
3497 6773 : fb->height = compositor->display_height;
3498 :
3499 : /*depthmap-only dump*/
3500 6773 : if (depth_dump_mode==1) {
3501 : //depth reading not supported on gles <= 1.1
3502 : #ifdef GPAC_USE_GLES1X
3503 : return GF_NOT_SUPPORTED;
3504 : #else
3505 : Float *depthp;
3506 : Float zFar, zNear;
3507 :
3508 0 : fb->pitch_x = 0;
3509 0 : fb->pitch_y = compositor->vp_width;
3510 :
3511 0 : if (compositor->screen_buffer_alloc_size < fb->pitch_y * fb->height) {
3512 0 : compositor->screen_buffer_alloc_size = fb->pitch_y * fb->height;
3513 0 : compositor->screen_buffer = gf_realloc(compositor->screen_buffer, compositor->screen_buffer_alloc_size);
3514 : }
3515 :
3516 0 : fb->video_buffer = compositor->screen_buffer;
3517 :
3518 : //read as float
3519 0 : depthp = (Float*)gf_malloc(sizeof(Float)* fb->pitch_y * fb->height);
3520 0 : fb->pixel_format = GF_PIXEL_GREYSCALE;
3521 :
3522 : #ifndef GPAC_USE_TINYGL
3523 : //glPixelTransferf(GL_DEPTH_SCALE, FIX2FLT(compositor->OGLDepthGain) );
3524 : //glPixelTransferf(GL_DEPTH_BIAS, FIX2FLT(compositor->OGLDepthOffset) );
3525 : #endif
3526 :
3527 0 : glReadPixels(compositor->vp_x, compositor->vp_y, fb->width, fb->height, GL_DEPTH_COMPONENT, GL_FLOAT, depthp);
3528 :
3529 : //linearize z buffer, from 0 (zfar) to 1 (znear)
3530 0 : zFar = FIX2FLT(compositor->visual->camera.z_far);
3531 0 : zNear = FIX2FLT(compositor->visual->camera.z_near);
3532 0 : for (i=0; i<fb->height*fb->width; i++) {
3533 0 : Float res = ( (2.0f * zNear) / (zFar + zNear - depthp[i] * (zFar - zNear)) ) ;
3534 0 : fb->video_buffer[i] = (u8) ( 255.0 * (1.0 - res));
3535 : }
3536 :
3537 0 : gf_free(depthp);
3538 :
3539 : #endif /*GPAC_USE_GLES1X*/
3540 : }
3541 :
3542 : /* RGBDS or RGBD dump*/
3543 6773 : else if (depth_dump_mode==2 || depth_dump_mode==3) {
3544 : #ifdef GPAC_USE_GLES1X
3545 : GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor]: RGB+Depth format not implemented in OpenGL ES\n"));
3546 : return GF_NOT_SUPPORTED;
3547 : #else
3548 : char *depth_data=NULL;
3549 : u32 size;
3550 0 : fb->pitch_x = 4;
3551 0 : fb->pitch_y = compositor->vp_width*4; /* 4 bytes for each rgbds pixel */
3552 :
3553 : #ifndef GPAC_USE_TINYGL
3554 0 : size = fb->pitch_y * fb->height;
3555 : #else
3556 : size = 2 * fb->pitch_y * fb->height;
3557 : #endif
3558 0 : if (compositor->screen_buffer_alloc_size < size) {
3559 0 : compositor->screen_buffer_alloc_size = size;
3560 0 : compositor->screen_buffer = gf_realloc(compositor->screen_buffer, compositor->screen_buffer_alloc_size);
3561 : }
3562 0 : fb->video_buffer = compositor->screen_buffer;
3563 :
3564 : #ifndef GPAC_USE_TINYGL
3565 :
3566 0 : glReadPixels(0, 0, fb->width, fb->height, GL_RGBA, GL_UNSIGNED_BYTE, fb->video_buffer);
3567 :
3568 : /*
3569 : glPixelTransferf(GL_DEPTH_SCALE, FIX2FLT(compositor->OGLDepthGain));
3570 : glPixelTransferf(GL_DEPTH_BIAS, FIX2FLT(compositor->OGLDepthOffset));
3571 : */
3572 :
3573 0 : depth_data = (char*) gf_malloc(sizeof(char)*fb->width*fb->height);
3574 0 : glReadPixels(0, 0, fb->width, fb->height, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, depth_data);
3575 :
3576 0 : if (depth_dump_mode==2) {
3577 0 : fb->pixel_format = GF_PIXEL_RGBDS;
3578 :
3579 : /*this corresponds to the RGBDS ordering*/
3580 0 : for (i=0; i<fb->height*fb->width; i++) {
3581 : u8 ds;
3582 : /* erase lowest-weighted depth bit */
3583 0 : u8 depth = depth_data[i] & 0xfe;
3584 : /*get alpha*/
3585 0 : ds = (fb->video_buffer[i*4 + 3]);
3586 : /* if heaviest-weighted alpha bit is set (>128) , turn on shape bit*/
3587 0 : if (ds & 0x80) depth |= 0x01;
3588 0 : fb->video_buffer[i*4+3] = depth; /*insert depth onto alpha*/
3589 : }
3590 : /*this corresponds to RGBD ordering*/
3591 0 : } else if (depth_dump_mode==3) {
3592 0 : fb->pixel_format = GF_PIXEL_RGBD;
3593 0 : for (i=0; i<fb->height*fb->width; i++)
3594 0 : fb->video_buffer[i*4+3] = depth_data[i];
3595 : }
3596 : #else
3597 : GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor]: RGB+Depth format not implemented in TinyGL\n"));
3598 : return GF_NOT_SUPPORTED;
3599 : #endif
3600 :
3601 : #endif /*GPAC_USE_GLES1X*/
3602 : } else { /*if (compositor->user && (compositor->user->init_flags & GF_TERM_WINDOW_TRANSPARENT))*/
3603 : u32 size;
3604 6773 : fb->pitch_x = 3;
3605 6773 : if (!compositor->opfmt && compositor->dyn_filter_mode) {
3606 0 : fb->pitch_x = 4;
3607 6773 : } else if (compositor->opfmt==GF_PIXEL_RGBA) {
3608 4 : fb->pitch_x = 4;
3609 : }
3610 :
3611 6773 : fb->pitch_y = fb->pitch_x * compositor->vp_width;
3612 6773 : size = fb->pitch_y * fb->height;
3613 6773 : if (compositor->screen_buffer_alloc_size < size) {
3614 121 : compositor->screen_buffer_alloc_size = size;
3615 121 : compositor->screen_buffer = gf_realloc(compositor->screen_buffer, compositor->screen_buffer_alloc_size);
3616 121 : compositor->line_buffer = gf_realloc(compositor->line_buffer, fb->pitch_y);
3617 :
3618 : }
3619 :
3620 6773 : fb->video_buffer = compositor->screen_buffer;
3621 :
3622 6773 : fb->pixel_format = (fb->pitch_x == 4) ? GF_PIXEL_RGBA : GF_PIXEL_RGB;
3623 :
3624 6773 : if (compositor->fbo_id) compositor_3d_enable_fbo(compositor, GF_TRUE);
3625 :
3626 6773 : glReadPixels(0, 0, fb->width, fb->height, (fb->pitch_x == 4) ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, fb->video_buffer);
3627 :
3628 6773 : if (compositor->fbo_id) compositor_3d_enable_fbo(compositor, GF_FALSE);
3629 :
3630 : /* } else {
3631 : fb->pitch_x = 3;
3632 : fb->pitch_y = 3*compositor->vp_width;
3633 : fb->video_buffer = (char*)gf_malloc(sizeof(char) * fb->pitch_y * fb->height);
3634 : fb->pixel_format = GF_PIXEL_RGB;
3635 :
3636 : glReadPixels(compositor->vp_x, compositor->vp_y, fb->width, fb->height, GL_RGB, GL_UNSIGNED_BYTE, fb->video_buffer);
3637 : */
3638 : }
3639 :
3640 : #ifndef GPAC_USE_TINYGL
3641 : /*flip image (openGL always handle image data bottom to top) */
3642 6773 : u32 hy = fb->height/2;
3643 655037 : for (i=0; i<hy; i++) {
3644 648264 : memcpy(compositor->line_buffer, fb->video_buffer+ i*fb->pitch_y, fb->pitch_y);
3645 648264 : memcpy(fb->video_buffer + i*fb->pitch_y, fb->video_buffer + (fb->height - 1 - i) * fb->pitch_y, fb->pitch_y);
3646 648264 : memcpy(fb->video_buffer + (fb->height - 1 - i) * fb->pitch_y, compositor->line_buffer, fb->pitch_y);
3647 : }
3648 : #endif
3649 6773 : return GF_OK;
3650 : }
3651 :
3652 6773 : GF_Err compositor_3d_release_screen_buffer(GF_Compositor *compositor, GF_VideoSurface *framebuffer)
3653 : {
3654 6773 : framebuffer->video_buffer = 0;
3655 6773 : return GF_OK;
3656 : }
3657 :
3658 0 : GF_Err compositor_3d_get_offscreen_buffer(GF_Compositor *compositor, GF_VideoSurface *fb, u32 view_idx, u32 depth_dump_mode)
3659 : {
3660 : //TODOk - habdle offscreen buffers through frameBuffer objects, no read back j
3661 : #if !defined(GPAC_USE_GLES1X) && !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES2)
3662 : char *tmp;
3663 : u32 hy, i;
3664 : /*not implemented yet*/
3665 0 : if (depth_dump_mode) return GF_NOT_SUPPORTED;
3666 :
3667 0 : if (view_idx>=compositor->visual->nb_views) return GF_BAD_PARAM;
3668 0 : fb->width = compositor->visual->auto_stereo_width;
3669 0 : fb->height = compositor->visual->auto_stereo_height;
3670 0 : fb->pixel_format = GF_PIXEL_RGB;
3671 0 : fb->pitch_y = 3*fb->width;
3672 0 : fb->video_buffer = gf_malloc(sizeof(char)*3*fb->width*fb->height);
3673 0 : if (!fb->video_buffer) return GF_OUT_OF_MEM;
3674 :
3675 0 : glEnable(GL_TEXTURE_2D);
3676 0 : glBindTexture(GL_TEXTURE_2D, compositor->visual->gl_textures[view_idx]);
3677 0 : glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, fb->video_buffer);
3678 0 : glDisable(GL_TEXTURE_2D);
3679 :
3680 : /*flip image (openGL always handle image data bottom to top) */
3681 0 : tmp = (char*)gf_malloc(sizeof(char)*fb->pitch_y);
3682 0 : hy = fb->height/2;
3683 0 : for (i=0; i<hy; i++) {
3684 0 : memcpy(tmp, fb->video_buffer+ i*fb->pitch_y, fb->pitch_y);
3685 0 : memcpy(fb->video_buffer + i*fb->pitch_y, fb->video_buffer + (fb->height - 1 - i) * fb->pitch_y, fb->pitch_y);
3686 0 : memcpy(fb->video_buffer + (fb->height - 1 - i) * fb->pitch_y, tmp, fb->pitch_y);
3687 : }
3688 0 : gf_free(tmp);
3689 0 : return GF_OK;
3690 : #else
3691 : return GF_NOT_SUPPORTED;
3692 : #endif
3693 : }
3694 :
3695 0 : void visual_3d_point_sprite(GF_VisualManager *visual, Drawable *stack, GF_TextureHandler *txh, GF_TraverseState *tr_state)
3696 : {
3697 : //todo - allow point sprites for GLES2 ?
3698 : #if !defined(GPAC_USE_GLES1X) && !defined(GPAC_USE_TINYGL) && !defined(GPAC_USE_GLES2)
3699 : u32 w, h;
3700 : u32 pixel_format, stride;
3701 : u8 *data;
3702 : Float r, g, b;
3703 : Fixed x, y;
3704 : Float inc, scale;
3705 : Bool in_strip;
3706 : GF_Node *txtrans = NULL;
3707 :
3708 0 : if ((visual->compositor->depth_gl_type==GF_SC_DEPTH_GL_POINTS) && visual->compositor->gl_caps.point_sprite) {
3709 : Float z;
3710 : static GLfloat none[3] = { 1.0f, 0, 0 };
3711 :
3712 0 : data = (u8 *) gf_sc_texture_get_data(txh, &pixel_format);
3713 0 : if (!data) return;
3714 0 : if (pixel_format!=GF_PIXEL_RGBD) return;
3715 0 : stride = txh->stride;
3716 0 : if (txh->pixelformat==GF_PIXEL_YUVD) stride *= 4;
3717 :
3718 0 : glPointSize(1.0f * visual->compositor->zoom);
3719 0 : glDepthMask(GL_FALSE);
3720 :
3721 0 : glPointParameterfv(GL_DISTANCE_ATTENUATION_EXT, none);
3722 0 : glPointParameterf(GL_POINT_FADE_THRESHOLD_SIZE_EXT, 0.0);
3723 0 : glEnable(GL_POINT_SMOOTH);
3724 0 : glDisable(GL_LIGHTING);
3725 :
3726 : // scale = FIX2FLT(visual->compositor->depth_gl_scale);
3727 : inc = 1;
3728 0 : if (!tr_state->pixel_metrics) inc /= FIX2FLT(tr_state->min_hsize);
3729 : // x = 0;
3730 : y = 1;
3731 0 : y = gf_mulfix(y, INT2FIX(txh->height/2));
3732 0 : if (!tr_state->pixel_metrics) y = gf_divfix(y, tr_state->min_hsize);
3733 :
3734 0 : glBegin(GL_POINTS);
3735 0 : for (h=0; h<txh->height; h++) {
3736 : x = -1;
3737 0 : x = gf_mulfix(x, INT2FIX(txh->width/2));
3738 0 : if (!tr_state->pixel_metrics) x = gf_divfix(x, tr_state->min_hsize);
3739 0 : for (w=0; w<txh->width; w++) {
3740 0 : u8 *p = data + h*stride + w*4;
3741 0 : r = p[0];
3742 0 : r /= 255;
3743 0 : g = p[1];
3744 0 : g /= 255;
3745 0 : b = p[2];
3746 0 : b /= 255;
3747 0 : z = p[3];
3748 0 : z = z / 255;
3749 :
3750 0 : glColor4f(r, g, b, 1.0);
3751 0 : glVertex3f(FIX2FLT(x), FIX2FLT(y), FIX2FLT(-z)*60);
3752 0 : x += FLT2FIX(inc);
3753 : }
3754 0 : y -= FLT2FIX(inc);
3755 : }
3756 0 : glEnd();
3757 :
3758 0 : glDepthMask(GL_TRUE);
3759 0 : return;
3760 : }
3761 :
3762 0 : if (visual->compositor->depth_gl_type==GF_SC_DEPTH_GL_STRIPS) {
3763 : u32 first_pass;
3764 0 : Float delta = FIX2FLT(visual->compositor->depth_gl_strips_filter);
3765 0 : if (!delta) first_pass = 2;
3766 : else first_pass = 1;
3767 :
3768 0 : data = (u8 *) gf_sc_texture_get_data(txh, &pixel_format);
3769 0 : if (!data) return;
3770 0 : if (pixel_format!=GF_PIXEL_RGBD) return;
3771 0 : stride = txh->stride;
3772 0 : if (txh->pixelformat==GF_PIXEL_YUVD) stride *= 4;
3773 :
3774 0 : glDepthMask(GL_FALSE);
3775 0 : glDisable(GL_TEXTURE_2D);
3776 0 : glDisable(GL_LIGHTING);
3777 0 : glDisable(GL_BLEND);
3778 0 : glDisable(GL_CULL_FACE);
3779 0 : glDisable(GL_POINT_SMOOTH);
3780 0 : glDisable(GL_FOG);
3781 :
3782 0 : restart:
3783 0 : scale = FIX2FLT(visual->compositor->depth_gl_scale);
3784 : inc = 1;
3785 0 : if (!tr_state->pixel_metrics) inc /= FIX2FLT(tr_state->min_hsize);
3786 : // x = 0;
3787 : y = 1;
3788 0 : y = gf_mulfix(y, INT2FIX(txh->height/2));
3789 0 : if (!tr_state->pixel_metrics) y = gf_divfix(y, tr_state->min_hsize);
3790 :
3791 : in_strip = 0;
3792 0 : for (h=0; h<txh->height - 1; h++) {
3793 0 : u8 *src = data + h*stride;
3794 : x = -1;
3795 0 : x = gf_mulfix(x, INT2FIX(txh->width/2));
3796 0 : if (!tr_state->pixel_metrics) x = gf_divfix(x, tr_state->min_hsize);
3797 :
3798 0 : for (w=0; w<txh->width; w++) {
3799 0 : u8 *p1 = src + w*4;
3800 0 : u8 *p2 = src + w*4 + stride;
3801 0 : Float z1 = p1[3];
3802 0 : Float z2 = p2[3];
3803 0 : if (first_pass==1) {
3804 0 : if ((z1>delta) || (z2>delta))
3805 : {
3806 : #if 0
3807 : if (in_strip) {
3808 : glEnd();
3809 : in_strip = 0;
3810 : }
3811 : #endif
3812 0 : x += FLT2FIX(inc);
3813 0 : continue;
3814 : }
3815 0 : } else if (first_pass==0) {
3816 0 : if ((z1<=delta) || (z2<=delta))
3817 : {
3818 0 : if (in_strip) {
3819 0 : glEnd();
3820 : in_strip = 0;
3821 : }
3822 0 : x += FLT2FIX(inc);
3823 0 : continue;
3824 : }
3825 : }
3826 0 : z1 = z1 / 255;
3827 0 : z2 = z2 / 255;
3828 :
3829 0 : r = p1[0];
3830 0 : r /= 255;
3831 0 : g = p1[1];
3832 0 : g /= 255;
3833 0 : b = p1[2];
3834 0 : b /= 255;
3835 :
3836 0 : if (!in_strip) {
3837 0 : glBegin(GL_TRIANGLE_STRIP);
3838 : in_strip = 1;
3839 : }
3840 :
3841 0 : glColor3f(r, g, b);
3842 0 : glVertex3f(FIX2FLT(x), FIX2FLT(y), FIX2FLT(z1)*scale);
3843 :
3844 0 : r = p2[0];
3845 0 : r /= 255;
3846 0 : g = p2[1];
3847 0 : g /= 255;
3848 0 : b = p2[2];
3849 0 : b /= 255;
3850 :
3851 0 : glColor3f(r, g, b);
3852 0 : glVertex3f(FIX2FLT(x), FIX2FLT(y)-inc, FIX2FLT(z2)*scale);
3853 :
3854 0 : x += FLT2FIX(inc);
3855 : }
3856 0 : if (in_strip) {
3857 0 : glEnd();
3858 : in_strip = 0;
3859 : }
3860 0 : y -= FLT2FIX(inc);
3861 : }
3862 :
3863 0 : if (first_pass==1) {
3864 : first_pass = 0;
3865 : goto restart;
3866 : }
3867 : return;
3868 : }
3869 :
3870 0 : glColor3f(1.0, 0.0, 0.0);
3871 : /*render using vertex array*/
3872 0 : if (!stack->mesh) {
3873 0 : stack->mesh = new_mesh();
3874 0 : stack->mesh->vbo_dynamic = 1;
3875 : inc = 1;
3876 0 : if (!tr_state->pixel_metrics) inc /= FIX2FLT(tr_state->min_hsize);
3877 : // x = 0;
3878 : y = 1;
3879 0 : y = gf_mulfix(y, FLT2FIX(txh->height/2));
3880 0 : if (!tr_state->pixel_metrics) y = gf_divfix(y, tr_state->min_hsize);
3881 :
3882 0 : if (txh->width>1 && txh->height>1) {
3883 0 : for (h=0; h<txh->height; h++) {
3884 0 : u32 idx_offset = h ? ((h-1)*txh->width) : 0;
3885 : x = -1;
3886 0 : x = gf_mulfix(x, FLT2FIX(txh->width/2));
3887 0 : if (tr_state->min_hsize && !tr_state->pixel_metrics) x = gf_divfix(x, tr_state->min_hsize);
3888 :
3889 0 : for (w=0; w<txh->width; w++) {
3890 0 : mesh_set_vertex(stack->mesh, x, y, 0, 0, 0, -FIX_ONE, INT2FIX(w / (txh->width-1)), INT2FIX((txh->height - h -1) / (txh->height-1)) );
3891 0 : x += FLT2FIX(inc);
3892 :
3893 : /*set triangle*/
3894 0 : if (h && w) {
3895 0 : u32 first_idx = idx_offset + w - 1;
3896 0 : mesh_set_triangle(stack->mesh, first_idx, first_idx+1, txh->width + first_idx +1);
3897 0 : mesh_set_triangle(stack->mesh, first_idx, txh->width + first_idx, txh->width + first_idx +1);
3898 : }
3899 : }
3900 0 : y -= FLT2FIX(inc);
3901 : }
3902 : /*force recompute of Z*/
3903 0 : txh->needs_refresh = 1;
3904 : }
3905 : }
3906 :
3907 : /*texture has been updated, recompute Z*/
3908 0 : if (txh->needs_refresh) {
3909 0 : Fixed f_scale = FLT2FIX(visual->compositor->depth_gl_scale);
3910 0 : txh->needs_refresh = 0;
3911 :
3912 0 : data = (u8 *) gf_sc_texture_get_data(txh, &pixel_format);
3913 0 : if (!data) return;
3914 0 : if (pixel_format!=GF_PIXEL_RGB_DEPTH) return;
3915 0 : data += txh->height*txh->width*3;
3916 :
3917 0 : for (h=0; h<txh->height; h++) {
3918 0 : u8 *src = data + h * txh->width;
3919 0 : for (w=0; w<txh->width; w++) {
3920 0 : u8 d = src[w];
3921 0 : Fixed z = INT2FIX(d);
3922 0 : z = gf_mulfix(z / 255, f_scale);
3923 0 : stack->mesh->vertices[w + h*txh->width].pos.z = z;
3924 : }
3925 : }
3926 0 : stack->mesh->vbo_dirty = 1;
3927 : }
3928 : #ifndef GPAC_DISABLE_VRML
3929 0 : if (tr_state->appear) txtrans = ((M_Appearance *)tr_state->appear)->textureTransform;
3930 : #endif
3931 0 : tr_state->mesh_num_textures = gf_sc_texture_enable(txh, txtrans);
3932 0 : visual_3d_draw_mesh(tr_state, stack->mesh);
3933 0 : visual_3d_disable_texture(tr_state);
3934 :
3935 : #endif //GPAC_USE_GLES1X
3936 :
3937 : }
3938 :
3939 :
3940 :
3941 178 : GF_Err compositor_3d_setup_fbo(u32 width, u32 height, u32 *fbo_id, u32 *tx_id, u32 *depth_id)
3942 : {
3943 : #if defined(GPAC_USE_GLES1X)
3944 : GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to setup FBO object: not supported on OpenGL ES 1.x\n"));
3945 : return GF_NOT_SUPPORTED;
3946 : #else
3947 178 : if (! *tx_id) {
3948 162 : glGenTextures(1, tx_id);
3949 : }
3950 178 : glBindTexture(GL_TEXTURE_2D, *tx_id);
3951 178 : glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
3952 178 : glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
3953 178 : glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3954 178 : glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3955 178 : glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
3956 :
3957 178 : if (! *fbo_id)
3958 162 : glGenFramebuffers(1, fbo_id);
3959 :
3960 178 : glBindFramebuffer(GL_FRAMEBUFFER, *fbo_id);
3961 178 : glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *tx_id, 0);
3962 :
3963 178 : if (! *depth_id)
3964 162 : glGenRenderbuffers(1, depth_id);
3965 :
3966 178 : glBindRenderbuffer(GL_RENDERBUFFER, *depth_id);
3967 : #if defined(GPAC_CONFIG_IOS) || defined(GPAC_CONFIG_ANDROID)
3968 : glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
3969 : #else
3970 178 : glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height);
3971 : #endif
3972 178 : glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, *depth_id);
3973 :
3974 178 : GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
3975 178 : switch (status) {
3976 : case GL_FRAMEBUFFER_COMPLETE:
3977 : break;
3978 0 : default:
3979 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to setup FBO object: FBO status %08x\n", status));
3980 : return GF_NOT_SUPPORTED;
3981 : }
3982 :
3983 178 : glBindFramebuffer(GL_FRAMEBUFFER, 0);
3984 178 : return GF_OK;
3985 : #endif
3986 :
3987 : }
3988 :
3989 2351 : void compositor_3d_delete_fbo(u32 *fbo_id, u32 *fbo_tx_id, u32 *fbo_depth_id, Bool keep_tx_id)
3990 : {
3991 : #ifndef GPAC_USE_GLES1X
3992 2351 : if (*fbo_id) {
3993 162 : glBindFramebuffer(GL_FRAMEBUFFER, 0);
3994 162 : glDeleteFramebuffers(1, fbo_id);
3995 162 : *fbo_id = 0;
3996 : }
3997 2351 : if (*fbo_depth_id) {
3998 162 : glDeleteRenderbuffers(1, fbo_depth_id);
3999 162 : *fbo_depth_id = 0;
4000 : }
4001 2351 : if (*fbo_tx_id && !keep_tx_id) {
4002 162 : glDeleteTextures(1, fbo_tx_id);
4003 162 : *fbo_tx_id = 0;
4004 : }
4005 : #endif
4006 2351 : }
4007 :
4008 122 : u32 compositor_3d_get_fbo_pixfmt()
4009 : {
4010 122 : return GL_TEXTURE_2D;
4011 : }
4012 :
4013 15566 : void compositor_3d_enable_fbo(GF_Compositor *compositor, Bool enable)
4014 : {
4015 : #ifndef GPAC_USE_GLES1X
4016 29108 : glBindFramebuffer(GL_FRAMEBUFFER, enable ? compositor->fbo_id : 0);
4017 15566 : if (!enable)
4018 14554 : glBindTexture(GL_TEXTURE_2D, 0);
4019 : #endif
4020 :
4021 15566 : }
4022 :
4023 1907 : void visual_3d_clean_state(GF_VisualManager *visual)
4024 : {
4025 1907 : glGetError();
4026 1907 : }
4027 :
4028 : #endif // GPAC_DISABLE_3D
|