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