📄 vs_gl_draw.c
字号:
/* * GPAC - Multimedia Framework C SDK * * Copyright (c) Jean Le Feuvre 2000-2005 * All rights reserved * * This file is part of GPAC / 3D rendering module * * GPAC is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * GPAC is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * */#include "visual_surface.h"#include <gpac/options.h>#include "gl_inc.h"/*!! HORRIBLE HACK, but on my test devices, it seems that glClipPlanex is missing on the device but not in the SDK lib !!*/#if defined(GL_MAX_CLIP_PLANES) && defined(__SYMBIAN32__)#undef GL_MAX_CLIP_PLANES#endif#define CHECK_GL_EXT(name) ((strstr(ext, name) != NULL) ? 1 : 0)void R3D_LoadExtensions(Render3D *sr){ const char *ext = (const char *) glGetString(GL_EXTENSIONS); /*store OGL extension to config for app usage*/ gf_cfg_set_key(sr->compositor->user->config, "Render3D", "OpenGLExtensions", ext); if (!ext) return; memset(&sr->hw_caps, 0, sizeof(HardwareCaps)); if (CHECK_GL_EXT("GL_ARB_multisample") || CHECK_GL_EXT("GLX_ARB_multisample") || CHECK_GL_EXT("WGL_ARB_multisample")) sr->hw_caps.multisample = 1; if (CHECK_GL_EXT("GL_ARB_texture_non_power_of_two")) sr->hw_caps.npot_texture = 1; if (CHECK_GL_EXT("GL_EXT_abgr")) sr->hw_caps.abgr_texture = 1; if (CHECK_GL_EXT("GL_EXT_bgra")) sr->hw_caps.bgra_texture = 1; if (CHECK_GL_EXT("GL_EXT_texture_rectangle") || CHECK_GL_EXT("GL_NV_texture_rectangle")) sr->hw_caps.rect_texture = 1;}void VS3D_Setup(VisualSurface *surf){ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glEnable(GL_CULL_FACE); glFrontFace(GL_CCW); glCullFace(GL_BACK);#ifdef GPAC_USE_OGL_ES glClearDepthx(FIX_ONE); glLightModelx(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); glMaterialx(GL_FRONT_AND_BACK, GL_SHININESS, FLT2FIX(0.2f * 128) );#else glClearDepth(1.0f); glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, (float) (0.2 * 128));#endif glShadeModel(GL_SMOOTH); glGetIntegerv(GL_MAX_LIGHTS, (GLint*)&surf->max_lights);#ifdef GL_MAX_CLIP_PLANES glGetIntegerv(GL_MAX_CLIP_PLANES, &surf->max_clips);#endif if (surf->render->compositor->high_speed) { glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); glHint(GL_LINE_SMOOTH_HINT, GL_FASTEST); glHint(GL_POINT_SMOOTH_HINT, GL_FASTEST);#ifdef GL_POLYGON_SMOOTH_HINT glHint(GL_POLYGON_SMOOTH_HINT, GL_FASTEST);#endif } else { glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);#ifdef GL_POLYGON_SMOOTH_HINT glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);#endif } if (surf->render->compositor->antiAlias == GF_ANTIALIAS_FULL) { glEnable(GL_LINE_SMOOTH); glEnable(GL_POINT_SMOOTH);#ifndef GPAC_USE_OGL_ES if (surf->render->poly_aa) glEnable(GL_POLYGON_SMOOTH); else glDisable(GL_POLYGON_SMOOTH);#endif } else { glDisable(GL_LINE_SMOOTH); glDisable(GL_POINT_SMOOTH);#ifndef GPAC_USE_OGL_ES glDisable(GL_POLYGON_SMOOTH);#endif } glDisable(GL_COLOR_MATERIAL); glDisable(GL_LIGHTING); glEnable(GL_BLEND); glDisable(GL_TEXTURE_2D); glDisable(GL_CULL_FACE); glDisable(GL_FOG); /*Note: we cannot enable/disable normalization on the fly, because we have no clue when the GL implementation will actually compute the related fragments. Since a typical world always use scaling, we always turn normalization on to avoid tracking scale*/ glEnable(GL_NORMALIZE); glClear(GL_DEPTH_BUFFER_BIT);}void VS3D_SetDepthBuffer(VisualSurface *surf, Bool on){ if (on) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST);}void VS3D_SetHeadlight(VisualSurface *surf, Bool bOn, GF_Camera *cam){ SFVec3f dir; SFColor col; if (!bOn) return; col.blue = col.red = col.green = FIX_ONE; if (cam->is_3D) { dir = camera_get_target_dir(cam); } else { dir.x = dir.y = 0; dir.z = FIX_ONE; } VS3D_AddDirectionalLight(surf, 0, col, FIX_ONE, dir);}void VS3D_SetViewport(VisualSurface *surf, GF_Rect vp){ glViewport(FIX2INT(vp.x), FIX2INT(vp.y), FIX2INT(vp.width), FIX2INT(vp.height));}void VS3D_ClearDepth(VisualSurface *surf){ glClear(GL_DEPTH_BUFFER_BIT);}void VS3D_DrawAABBNode(RenderEffect3D *eff, GF_Mesh *mesh, u32 prim_type, GF_Plane *fplanes, u32 *p_indices, AABBNode *n){ u32 i; /*if not leaf do cull*/ if (n->pos) { u32 p_idx, cull; SFVec3f vertices[8]; /*get box vertices*/ gf_bbox_get_vertices(n->min, n->max, vertices); cull = CULL_INSIDE; for (i=0; i<6; i++) { p_idx = p_indices[i]; /*check p-vertex: if not in plane, we're out (since p-vertex is the closest point to the plane)*/ if (gf_plane_get_distance(&fplanes[i], &vertices[p_idx])<0) { cull = CULL_OUTSIDE; break; } /*check n-vertex: if not in plane, we're intersecting*/ if (gf_plane_get_distance(&fplanes[i], &vertices[7-p_idx])<0) { cull = CULL_INTERSECTS; break;} } if (cull==CULL_OUTSIDE) return; if (cull==CULL_INTERSECTS) { VS3D_DrawAABBNode(eff, mesh, prim_type, fplanes, p_indices, n->pos); VS3D_DrawAABBNode(eff, mesh, prim_type, fplanes, p_indices, n->neg); return; } } /*the good thing about the structure of the aabb tree is that the primitive idx is valid for both leaf and non-leaf nodes, so we can use it as soon as we have a CULL_INSIDE. However we must push triangles one by one since primitive order may have been swapped when building the AABB tree*/ for (i=0; i<n->nb_idx; i++) {#ifdef GPAC_USE_OGL_ES glDrawElements(prim_type, 3, GL_UNSIGNED_SHORT, &mesh->indices[3*n->indices[i]]);#else glDrawElements(prim_type, 3, GL_UNSIGNED_INT, &mesh->indices[3*n->indices[i]]);#endif }}void VS3D_DrawMeshIntern(RenderEffect3D *eff, GF_Mesh *mesh){ Bool has_col, has_tx, has_norm; u32 prim_type;#if defined(GPAC_FIXED_POINT) && !defined(GPAC_USE_OGL_ES) u32 i; Float *color_array = NULL; Float fix_scale = 1.0f; fix_scale /= FIX_ONE;#endif has_col = has_tx = has_norm = 0; glEnableClientState(GL_VERTEX_ARRAY);#if defined(GPAC_USE_OGL_ES) glVertexPointer(3, GL_FIXED, sizeof(GF_Vertex), &mesh->vertices[0].pos);#elif defined(GPAC_FIXED_POINT) /*scale modelview matrix*/ glPushMatrix(); glScalef(fix_scale, fix_scale, fix_scale); glVertexPointer(3, GL_INT, sizeof(GF_Vertex), &mesh->vertices[0].pos);#else glVertexPointer(3, GL_FLOAT, sizeof(GF_Vertex), &mesh->vertices[0].pos);#endif if ((eff->mesh_has_texture != 1) && (mesh->flags & MESH_HAS_COLOR)) { glEnable(GL_COLOR_MATERIAL);#if !defined (GPAC_USE_OGL_ES) glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);#endif glEnableClientState(GL_COLOR_ARRAY); has_col = 1;#if defined (GPAC_USE_OGL_ES) if (mesh->flags & MESH_HAS_ALPHA) { glEnable(GL_BLEND); eff->mesh_is_transparent = 1; } /*glES only accepts full RGBA colors*/ glColorPointer(4, GL_FIXED, sizeof(GF_Vertex), &mesh->vertices[0].color);#elif defined (GPAC_FIXED_POINT) /*this is a real pain: we cannot "scale" colors through openGL, and our components are 16.16 (32 bytes) ranging 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] we must thus rebuild a dedicated array...*/ if (mesh->flags & MESH_HAS_ALPHA) { color_array = malloc(sizeof(Float)*4*mesh->v_count); for (i=0; i<mesh->v_count; i++) { color_array[4*i] = FIX2FLT(mesh->vertices[i].color.red); color_array[4*i+1] = FIX2FLT(mesh->vertices[i].color.green); color_array[4*i+2] = FIX2FLT(mesh->vertices[i].color.blue); color_array[4*i+3] = FIX2FLT(mesh->vertices[i].color.alpha); } glEnable(GL_BLEND); glColorPointer(4, GL_FLOAT, 4*sizeof(Float), color_array); eff->mesh_is_transparent = 1; } else { color_array = malloc(sizeof(Float)*3*mesh->v_count); for (i=0; i<mesh->v_count; i++) { color_array[3*i] = FIX2FLT(mesh->vertices[i].color.red); color_array[3*i+1] = FIX2FLT(mesh->vertices[i].color.green); color_array[3*i+2] = FIX2FLT(mesh->vertices[i].color.blue); } glColorPointer(3, GL_FLOAT, 3*sizeof(Float), color_array); }#else if (mesh->flags & MESH_HAS_ALPHA) { glEnable(GL_BLEND); glColorPointer(4, GL_FLOAT, sizeof(GF_Vertex), &mesh->vertices[0].color); eff->mesh_is_transparent = 1; } else { glColorPointer(3, GL_FLOAT, sizeof(GF_Vertex), &mesh->vertices[0].color); }#endif } if (eff->mesh_has_texture && !mesh->mesh_type && !(mesh->flags & MESH_NO_TEXTURE)) { glEnableClientState(GL_TEXTURE_COORD_ARRAY ); has_tx = 1;#if defined(GPAC_USE_OGL_ES) glTexCoordPointer(2, GL_FIXED, sizeof(GF_Vertex), &mesh->vertices[0].texcoords);#elif defined(GPAC_FIXED_POINT) glMatrixMode(GL_TEXTURE); glPushMatrix(); glScalef(fix_scale, fix_scale, fix_scale); glMatrixMode(GL_MODELVIEW); glTexCoordPointer(2, GL_INT, sizeof(GF_Vertex), &mesh->vertices[0].texcoords);#else glTexCoordPointer(2, GL_FLOAT, sizeof(GF_Vertex), &mesh->vertices[0].texcoords);#endif } if (mesh->mesh_type) { glNormal3f(0, 0, 1.0f); glDisable(GL_CULL_FACE); glDisable(GL_LIGHTING); if (mesh->mesh_type==2) glDisable(GL_LINE_SMOOTH); else glDisable(GL_POINT_SMOOTH); glLineWidth(1.0f); } else { has_norm = 1; glEnableClientState(GL_NORMAL_ARRAY );#if defined(GPAC_USE_OGL_ES) glNormalPointer(GL_FIXED, sizeof(GF_Vertex), &mesh->vertices[0].normal);#elif defined(GPAC_FIXED_POINT) glNormalPointer(GL_INT, sizeof(GF_Vertex), &mesh->vertices[0].normal);#else glNormalPointer(GL_FLOAT, sizeof(GF_Vertex), &mesh->vertices[0].normal);#endif if (!mesh->mesh_type) { if (eff->surface->render->backcull && (!eff->mesh_is_transparent || (eff->surface->render->backcull ==GF_BACK_CULL_ALPHA) ) && (mesh->flags & MESH_IS_SOLID)) { glEnable(GL_CULL_FACE); glFrontFace((mesh->flags & MESH_IS_CW) ? GL_CW : GL_CCW); } else { glDisable(GL_CULL_FACE); } } } switch (mesh->mesh_type) { case MESH_LINESET: prim_type = GL_LINES; break; case MESH_POINTSET: prim_type = GL_POINTS; break; default: prim_type = GL_TRIANGLES; break; } /*if inside or no aabb for the mesh draw vertex array*/ if ((eff->cull_flag==CULL_INSIDE) || !mesh->aabb_root || !mesh->aabb_root->pos) {#ifdef GPAC_USE_OGL_ES glDrawElements(prim_type, mesh->i_count, GL_UNSIGNED_SHORT, mesh->indices);#else glDrawElements(prim_type, mesh->i_count, GL_UNSIGNED_INT, mesh->indices);#endif } else { /*otherwise cull aabb against frustum - after some testing it appears (as usual) that there must be a compromise: we're slowing down the renderer here, however the gain is really appreciable for large meshes, especially terrains/elevation grids*/ /*first get transformed frustum in local space*/ GF_Matrix mx; u32 i, p_idx[6]; GF_Plane fplanes[6]; gf_mx_copy(mx, eff->model_matrix); gf_mx_inverse(&mx); for (i=0; i<6; i++) { fplanes[i] = eff->camera->planes[i]; gf_mx_apply_plane(&mx, &fplanes[i]); p_idx[i] = gf_plane_get_p_vertex_idx(&fplanes[i]); } /*then recursively cull & render AABB tree*/ VS3D_DrawAABBNode(eff, mesh, prim_type, fplanes, p_idx, mesh->aabb_root->pos); VS3D_DrawAABBNode(eff, mesh, prim_type, fplanes, p_idx, mesh->aabb_root->neg); } glDisableClientState(GL_VERTEX_ARRAY); if (has_col) glDisableClientState(GL_COLOR_ARRAY); glDisable(GL_COLOR_MATERIAL); if (has_tx) glDisableClientState(GL_TEXTURE_COORD_ARRAY); if (has_norm) glDisableClientState(GL_NORMAL_ARRAY);#if defined(GPAC_FIXED_POINT) && !defined(GPAC_USE_OGL_ES) if (color_array) free(color_array); if (!mesh->mesh_type && !(mesh->flags & MESH_NO_TEXTURE)) { glMatrixMode(GL_TEXTURE); glPopMatrix(); glMatrixMode(GL_MODELVIEW); } glPopMatrix();#endif if (eff->mesh_is_transparent) glDisable(GL_BLEND); eff->mesh_is_transparent = 0;}#ifdef GPAC_USE_OGL_ESu32 ogles_push_enable(u32 mask){ u32 attrib = 0;#ifndef __SYMBIAN32__ if ((mask & GL_LIGHTING) && glIsEnabled(GL_LIGHTING) ) attrib |= GL_LIGHTING; if ((mask & GL_BLEND) && glIsEnabled(GL_BLEND) ) attrib |= GL_BLEND; if ((mask & GL_COLOR_MATERIAL) && glIsEnabled(GL_COLOR_MATERIAL) ) attrib |= GL_COLOR_MATERIAL; if ((mask & GL_TEXTURE_2D) && glIsEnabled(GL_TEXTURE_2D) ) attrib |= GL_TEXTURE_2D;#endif return attrib;}void ogles_pop_enable(u32 mask){#ifndef __SYMBIAN32__ if (mask & GL_LIGHTING) glEnable(GL_LIGHTING); if (mask & GL_BLEND) glEnable(GL_BLEND); if (mask & GL_COLOR_MATERIAL) glEnable(GL_COLOR_MATERIAL); if (mask & GL_TEXTURE_2D) glEnable(GL_TEXTURE_2D);#endif}#endif/*note we don't perform any culling for normal drawing...*/void VS3D_DrawNormals(RenderEffect3D *eff, GF_Mesh *mesh){ GF_Vec pt, end; u32 i, j; Fixed scale = mesh->bounds.radius / 4;#ifdef GPAC_USE_OGL_ES GF_Vec va[2]; u16 indices[2]; u32 attrib = ogles_push_enable(GL_LIGHTING | GL_BLEND | GL_COLOR_MATERIAL | GL_TEXTURE_2D); glEnableClientState(GL_VERTEX_ARRAY);#else glPushAttrib(GL_ENABLE_BIT);#endif glDisable(GL_LIGHTING | GL_BLEND | GL_COLOR_MATERIAL | GL_TEXTURE_2D);#ifdef GPAC_USE_OGL_ES glColor4x(0, 0, 0, 1);#else glColor3f(1, 1, 1);#endif if (eff->surface->render->draw_normals==GF_NORMALS_VERTEX) { IDX_TYPE *idx = mesh->indices;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -