From 153f5ea73fafe815aa71d01acf863f32dcae1ab9 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Mon, 27 Oct 2008 14:36:52 +0000 Subject: [PATCH] Bug 1189 - Backface culling * clutter/cogl/gl/cogl-texture.c (cogl_texture_polygon) (_cogl_texture_quad_sw, _cogl_texture_quad_hw): * clutter/cogl/gles/cogl-texture.c (cogl_texture_polygon) (_cogl_texture_quad_sw, _cogl_texture_quad_hw): Enable backface culling in GL if it is requested. * clutter/cogl/gles/cogl-texture.c (_cogl_texture_quad_sw) (_cogl_texture_quad_hw): * clutter/cogl/gl/cogl-texture.c (_cogl_texture_quad_sw) (_cogl_texture_quad_hw): Reorder the vertices so that they are counter-clockwise. * clutter/cogl/gles/cogl-context.h (CoglContext): * clutter/cogl/gl/cogl-context.h (CoglContext): Added a flag to store whether backface culling is currently enabled. * clutter/cogl/gles/cogl.c (cogl_enable_backface_culling): * clutter/cogl/gl/cogl.c (cogl_enable_backface_culling): New function * doc/reference/cogl/cogl-sections.txt: Add cogl_enable_backface_culling --- cogl.h.in | 12 ++++++ doc/reference/cogl/cogl-sections.txt | 1 + gl/cogl-context.h | 2 + gl/cogl-internal.h | 1 + gl/cogl-texture.c | 58 +++++++++++++++++----------- gl/cogl.c | 12 ++++++ gles/cogl-context.h | 2 + gles/cogl-internal.h | 1 + gles/cogl-texture.c | 51 ++++++++++++++---------- gles/cogl.c | 14 ++++++- 10 files changed, 110 insertions(+), 44 deletions(-) diff --git a/cogl.h.in b/cogl.h.in index 814ca33c0..ac3aa3411 100644 --- a/cogl.h.in +++ b/cogl.h.in @@ -579,6 +579,18 @@ void cogl_clip_stack_restore (void); */ void cogl_enable_depth_test (gboolean setting); +/** + * cogl_enable_backface_culling: + * @setting: %TRUE to enable backface culling or %FALSE to disable. + * + * Sets whether textures positioned so that their backface is showing + * should be hidden. This can be used to efficiently draw two-sided + * textures or fully closed cubes without enabling depth testing. Only + * calls to cogl_texture_rectangle() and cogl_texture_polygon() are + * affected. Backface culling is disabled by default. + */ +void cogl_enable_backface_culling (gboolean setting); + /** * cogl_alpha_func: * @func: the comparison function to use, one of CGL_NEVER, CGL_LESS, diff --git a/doc/reference/cogl/cogl-sections.txt b/doc/reference/cogl/cogl-sections.txt index ed873ce32..c7c751f9b 100644 --- a/doc/reference/cogl/cogl-sections.txt +++ b/doc/reference/cogl/cogl-sections.txt @@ -34,6 +34,7 @@ cogl_clip_stack_save cogl_clip_stack_restore cogl_enable_depth_test +cogl_enable_backface_culling cogl_alpha_func cogl_fog_set diff --git a/gl/cogl-context.h b/gl/cogl-context.h index 96b3199df..4b442ecba 100644 --- a/gl/cogl-context.h +++ b/gl/cogl-context.h @@ -40,6 +40,8 @@ typedef struct guint8 color_alpha; COGLenum blend_src_factor; COGLenum blend_dst_factor; + + gboolean enable_backface_culling; /* Primitives */ CoglFixedVec2 path_start; diff --git a/gl/cogl-internal.h b/gl/cogl-internal.h index 19fc37c9d..bfc7cc73f 100644 --- a/gl/cogl-internal.h +++ b/gl/cogl-internal.h @@ -56,6 +56,7 @@ const char *_cogl_error_string(GLenum errorCode); #define COGL_ENABLE_TEXTURE_RECT (1<<4) #define COGL_ENABLE_VERTEX_ARRAY (1<<5) #define COGL_ENABLE_TEXCOORD_ARRAY (1<<6) +#define COGL_ENABLE_BACKFACE_CULLING (1<<7) gint _cogl_get_format_bpp (CoglPixelFormat format); diff --git a/gl/cogl-texture.c b/gl/cogl-texture.c index 3bdf3bd9a..11f91cfe6 100644 --- a/gl/cogl-texture.c +++ b/gl/cogl-texture.c @@ -1949,6 +1949,9 @@ _cogl_texture_quad_sw (CoglTexture *tex, { enable_flags |= COGL_ENABLE_BLEND; } + + if (ctx->enable_backface_culling) + enable_flags |= COGL_ENABLE_BACKFACE_CULLING; cogl_enable (enable_flags); @@ -2050,21 +2053,21 @@ _cogl_texture_quad_sw (CoglTexture *tex, /* Draw textured quad */ glBegin (GL_QUADS); - + glTexCoord2f (CFX_F(slice_tx1), CFX_F(slice_ty1)); glVertex2f (CFX_F(slice_qx1), CFX_F(slice_qy1)); - - glTexCoord2f (CFX_F(slice_tx2), CFX_F(slice_ty1)); - glVertex2f (CFX_F(slice_qx2), CFX_F(slice_qy1)); - - glTexCoord2f (CFX_F(slice_tx2), CFX_F(slice_ty2)); - glVertex2f (CFX_F(slice_qx2), CFX_F(slice_qy2)); - + glTexCoord2f (CFX_F(slice_tx1), CFX_F(slice_ty2)); glVertex2f (CFX_F(slice_qx1), CFX_F(slice_qy2)); - + + glTexCoord2f (CFX_F(slice_tx2), CFX_F(slice_ty2)); + glVertex2f (CFX_F(slice_qx2), CFX_F(slice_qy2)); + + glTexCoord2f (CFX_F(slice_tx2), CFX_F(slice_ty1)); + glVertex2f (CFX_F(slice_qx2), CFX_F(slice_qy1)); + GE( glEnd () ); - + #undef CFX_F } } @@ -2101,6 +2104,9 @@ _cogl_texture_quad_hw (CoglTexture *tex, enable_flags |= COGL_ENABLE_BLEND; } + if (ctx->enable_backface_culling) + enable_flags |= COGL_ENABLE_BACKFACE_CULLING; + cogl_enable (enable_flags); /* Pick and bind opengl texture object */ @@ -2117,24 +2123,24 @@ _cogl_texture_quad_hw (CoglTexture *tex, ty2 = ty2 * (y_span->size - y_span->waste) / y_span->size; #define CFX_F(x) CLUTTER_FIXED_TO_FLOAT(x) - + /* Draw textured quad */ glBegin (GL_QUADS); - + glTexCoord2f (CFX_F(tx1), CFX_F(ty1)); glVertex2f (CFX_F(x1), CFX_F(y1)); - - glTexCoord2f (CFX_F(tx2), CFX_F(ty1)); - glVertex2f (CFX_F(x2), CFX_F(y1)); - - glTexCoord2f (CFX_F(tx2), CFX_F(ty2)); - glVertex2f (CFX_F(x2), CFX_F(y2)); - + glTexCoord2f (CFX_F(tx1), CFX_F(ty2)); glVertex2f (CFX_F(x1), CFX_F(y2)); - + + glTexCoord2f (CFX_F(tx2), CFX_F(ty2)); + glVertex2f (CFX_F(x2), CFX_F(y2)); + + glTexCoord2f (CFX_F(tx2), CFX_F(ty1)); + glVertex2f (CFX_F(x2), CFX_F(y1)); + GE( glEnd () ); - + #undef CFX_F } @@ -2231,6 +2237,9 @@ cogl_texture_polygon (CoglHandle handle, int i, x, y, vnum; GLuint gl_handle; CoglTexSliceSpan *y_span, *x_span; + gulong enable_flags; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); /* Check if valid texture */ if (!cogl_is_texture (handle)) @@ -2261,7 +2270,12 @@ cogl_texture_polygon (CoglHandle handle, tex = _cogl_texture_pointer_from_handle (handle); /* Prepare GL state */ - cogl_enable (COGL_ENABLE_TEXTURE_2D | COGL_ENABLE_BLEND); + enable_flags = COGL_ENABLE_TEXTURE_2D | COGL_ENABLE_BLEND; + + if (ctx->enable_backface_culling) + enable_flags |= COGL_ENABLE_BACKFACE_CULLING; + + cogl_enable (enable_flags); /* Temporarily change the wrapping mode on all of the slices to use a transparent border */ diff --git a/gl/cogl.c b/gl/cogl.c index 690692765..567d292bc 100644 --- a/gl/cogl.c +++ b/gl/cogl.c @@ -314,6 +314,10 @@ cogl_enable (gulong flags) cogl_toggle_flag (ctx, flags, COGL_ENABLE_TEXTURE_2D, GL_TEXTURE_2D); + + cogl_toggle_flag (ctx, flags, + COGL_ENABLE_BACKFACE_CULLING, + GL_CULL_FACE); cogl_toggle_client_flag (ctx, flags, COGL_ENABLE_VERTEX_ARRAY, @@ -367,6 +371,14 @@ cogl_enable_depth_test (gboolean setting) } } +void +cogl_enable_backface_culling (gboolean setting) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + ctx->enable_backface_culling = setting; +} + void cogl_color (const ClutterColor *color) { diff --git a/gles/cogl-context.h b/gles/cogl-context.h index cc2e4cfed..6efa790b2 100644 --- a/gles/cogl-context.h +++ b/gles/cogl-context.h @@ -49,6 +49,8 @@ typedef struct guint8 color_alpha; COGLenum blend_src_factor; COGLenum blend_dst_factor; + + gboolean enable_backface_culling; /* Primitives */ CoglFixedVec2 path_start; diff --git a/gles/cogl-internal.h b/gles/cogl-internal.h index 8a6b63899..9275f4ba0 100644 --- a/gles/cogl-internal.h +++ b/gles/cogl-internal.h @@ -57,6 +57,7 @@ const char *_cogl_error_string(GLenum errorCode); #define COGL_ENABLE_VERTEX_ARRAY (1<<5) #define COGL_ENABLE_TEXCOORD_ARRAY (1<<6) #define COGL_ENABLE_COLOR_ARRAY (1<<7) +#define COGL_ENABLE_BACKFACE_CULLING (1<<8) gint _cogl_get_format_bpp (CoglPixelFormat format); diff --git a/gles/cogl-texture.c b/gles/cogl-texture.c index 97cd258c0..395f98005 100644 --- a/gles/cogl-texture.c +++ b/gles/cogl-texture.c @@ -1924,6 +1924,9 @@ _cogl_texture_quad_sw (CoglTexture *tex, enable_flags |= COGL_ENABLE_BLEND; } + if (ctx->enable_backface_culling) + enable_flags |= COGL_ENABLE_BACKFACE_CULLING; + cogl_enable (enable_flags); GE( cogl_wrap_glTexCoordPointer (2, GL_FIXED, 0, tex_coords) ); @@ -2021,18 +2024,18 @@ _cogl_texture_quad_sw (CoglTexture *tex, GE( cogl_gles2_wrapper_bind_texture (tex->gl_target, gl_handle, tex->gl_intformat) ); - + /* Draw textured quad */ - tex_coords[0] = slice_tx1; tex_coords[1] = slice_ty1; - tex_coords[2] = slice_tx2; tex_coords[3] = slice_ty1; - tex_coords[4] = slice_tx1; tex_coords[5] = slice_ty2; - tex_coords[6] = slice_tx2; tex_coords[7] = slice_ty2; - - quad_coords[0] = slice_qx1; quad_coords[1] = slice_qy1; - quad_coords[2] = slice_qx2; quad_coords[3] = slice_qy1; - quad_coords[4] = slice_qx1; quad_coords[5] = slice_qy2; - quad_coords[6] = slice_qx2; quad_coords[7] = slice_qy2; - + tex_coords[0] = slice_tx1; tex_coords[1] = slice_ty2; + tex_coords[2] = slice_tx2; tex_coords[3] = slice_ty2; + tex_coords[4] = slice_tx1; tex_coords[5] = slice_ty1; + tex_coords[6] = slice_tx2; tex_coords[7] = slice_ty1; + + quad_coords[0] = slice_qx1; quad_coords[1] = slice_qy2; + quad_coords[2] = slice_qx2; quad_coords[3] = slice_qy2; + quad_coords[4] = slice_qx1; quad_coords[5] = slice_qy1; + quad_coords[6] = slice_qx2; quad_coords[7] = slice_qy1; + GE (cogl_wrap_glDrawArrays (GL_TRIANGLE_STRIP, 0, 4) ); } } @@ -2071,6 +2074,9 @@ _cogl_texture_quad_hw (CoglTexture *tex, enable_flags |= COGL_ENABLE_BLEND; } + if (ctx->enable_backface_culling) + enable_flags |= COGL_ENABLE_BACKFACE_CULLING; + cogl_enable (enable_flags); GE( cogl_wrap_glTexCoordPointer (2, GL_FIXED, 0, tex_coords) ); @@ -2090,16 +2096,16 @@ _cogl_texture_quad_hw (CoglTexture *tex, ty2 = ty2 * (y_span->size - y_span->waste) / y_span->size; /* Draw textured quad */ - tex_coords[0] = tx1; tex_coords[1] = ty1; - tex_coords[2] = tx2; tex_coords[3] = ty1; - tex_coords[4] = tx1; tex_coords[5] = ty2; - tex_coords[6] = tx2; tex_coords[7] = ty2; - - quad_coords[0] = x1; quad_coords[1] = y1; - quad_coords[2] = x2; quad_coords[3] = y1; - quad_coords[4] = x1; quad_coords[5] = y2; - quad_coords[6] = x2; quad_coords[7] = y2; - + tex_coords[0] = tx1; tex_coords[1] = ty2; + tex_coords[2] = tx2; tex_coords[3] = ty2; + tex_coords[4] = tx1; tex_coords[5] = ty1; + tex_coords[6] = tx2; tex_coords[7] = ty1; + + quad_coords[0] = x1; quad_coords[1] = y2; + quad_coords[2] = x2; quad_coords[3] = y2; + quad_coords[4] = x1; quad_coords[5] = y1; + quad_coords[6] = x2; quad_coords[7] = y1; + GE (cogl_wrap_glDrawArrays (GL_TRIANGLE_STRIP, 0, 4) ); } @@ -2258,6 +2264,9 @@ cogl_texture_polygon (CoglHandle handle, else if (ctx->color_alpha < 255) enable_flags |= COGL_ENABLE_BLEND; + if (ctx->enable_backface_culling) + enable_flags |= COGL_ENABLE_BACKFACE_CULLING; + if (use_color) { enable_flags |= COGL_ENABLE_COLOR_ARRAY; diff --git a/gles/cogl.c b/gles/cogl.c index 7259680af..82cbeed59 100644 --- a/gles/cogl.c +++ b/gles/cogl.c @@ -222,7 +222,11 @@ cogl_enable (gulong flags) cogl_toggle_flag (ctx, flags, COGL_ENABLE_TEXTURE_2D, GL_TEXTURE_2D); - + + cogl_toggle_flag (ctx, flags, + COGL_ENABLE_BACKFACE_CULLING, + GL_CULL_FACE); + cogl_toggle_client_flag (ctx, flags, COGL_ENABLE_VERTEX_ARRAY, GL_VERTEX_ARRAY); @@ -278,6 +282,14 @@ cogl_enable_depth_test (gboolean setting) } } +void +cogl_enable_backface_culling (gboolean setting) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + ctx->enable_backface_culling = setting; +} + void cogl_color (const ClutterColor *color) {