filename | src/pvr2/glrender.c |
changeset | 863:a5e5310061e2 |
prev | 856:02ac5f37bfc9 |
next | 864:a90f3d5e57e1 |
author | nkeynes |
date | Sun Sep 28 01:09:51 2008 +0000 (14 years ago) |
permissions | -rw-r--r-- |
last change | Initial shadow volume implementation for opaque polygons (stencil isn't quite right, but we get some kind of shadows now) |
file | annotate | diff | log | raw |
1.1 --- a/src/pvr2/glrender.c Thu Sep 11 22:51:24 2008 +00001.2 +++ b/src/pvr2/glrender.c Sun Sep 28 01:09:51 2008 +00001.3 @@ -24,6 +24,8 @@1.4 #include "pvr2/scene.h"1.5 #include "pvr2/glutil.h"1.7 +#define IS_EMPTY_TILE_LIST(p) ((*((uint32_t *)(video_base+(p))) >> 28) == 0x0F)1.8 +1.9 int pvr2_poly_depthmode[8] = { GL_NEVER, GL_LESS, GL_EQUAL, GL_LEQUAL,1.10 GL_GREATER, GL_NOTEQUAL, GL_GEQUAL,1.11 GL_ALWAYS };1.12 @@ -65,9 +67,13 @@1.13 POLY2_TEX_WIDTH(poly->context[1]),1.14 POLY2_TEX_HEIGHT(poly->context[1]) );1.15 if( poly->mod_vertex_index != -1 ) {1.16 - poly->mod_tex_id = texcache_get_texture( poly->context[4],1.17 - POLY2_TEX_WIDTH(poly->context[3]),1.18 - POLY2_TEX_HEIGHT(poly->context[3]) );1.19 + if( pvr2_scene.shadow_mode == SHADOW_FULL ) {1.20 + poly->mod_tex_id = texcache_get_texture( poly->context[4],1.21 + POLY2_TEX_WIDTH(poly->context[3]),1.22 + POLY2_TEX_HEIGHT(poly->context[3]) );1.23 + } else {1.24 + poly->mod_tex_id = poly->tex_id;1.25 + }1.26 }1.27 } else {1.28 poly->tex_id = -1;1.29 @@ -117,22 +123,11 @@1.30 }1.32 /**1.33 - * Setup the GL context for the supplied polygon context.1.34 - * @param context pointer to 3 or 5 words of polygon context1.35 - * @param modified boolean flag indicating that the modified1.36 - * version should be used, rather than the normal version.1.37 + * Setup the basic context that's shared between normal and modified modes -1.38 + * depth, culling, shade model, and color sum1.39 */1.40 -void render_set_context( uint32_t *context, int render_mode )1.41 +static void render_set_base_context( uint32_t poly1 )1.42 {1.43 - uint32_t poly1 = context[0], poly2, texture;1.44 - if( render_mode == RENDER_FULLMOD ) {1.45 - poly2 = context[3];1.46 - texture = context[4];1.47 - } else {1.48 - poly2 = context[1];1.49 - texture = context[2];1.50 - }1.51 -1.52 glDepthFunc( POLY1_DEPTH_MODE(poly1) );1.53 glDepthMask( POLY1_DEPTH_WRITE(poly1) ? GL_TRUE : GL_FALSE );1.55 @@ -151,60 +146,84 @@1.56 break;1.57 }1.59 + glShadeModel( POLY1_SHADE_MODEL(poly1) );1.60 +1.61 if( POLY1_SPECULAR(poly1) ) {1.62 glEnable(GL_COLOR_SUM);1.63 } else {1.64 glDisable(GL_COLOR_SUM);1.65 }1.66 +}1.68 +/**1.69 + * Setup the texture/shading settings (TSP) which vary between mod/unmod modes.1.70 + */1.71 +static void render_set_tsp_context( uint32_t poly1, uint32_t poly2, uint32_t texture )1.72 +{1.73 + if( POLY1_TEXTURED(poly1) ) {1.74 + glEnable(GL_TEXTURE_2D);1.75 + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, pvr2_poly_texblend[POLY2_TEX_BLEND(poly2)] );1.76 + if( POLY2_TEX_CLAMP_U(poly2) ) {1.77 + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );1.78 + } else if( POLY2_TEX_MIRROR_U(poly2) ) {1.79 + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT_ARB );1.80 + } else {1.81 + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );1.82 + }1.83 + if( POLY2_TEX_CLAMP_V(poly2) ) {1.84 + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );1.85 + } else if( POLY2_TEX_MIRROR_V(poly2) ) {1.86 + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT_ARB );1.87 + } else {1.88 + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );1.89 + }1.90 + } else {1.91 + glDisable( GL_TEXTURE_2D );1.92 + }1.93 +1.94 + switch( POLY2_FOG_MODE(poly2) ) {1.95 + case PVR2_POLY_FOG_LOOKUP:1.96 + glFogfv( GL_FOG_COLOR, pvr2_scene.fog_lut_colour );1.97 + glEnable( GL_FOG );1.98 + break;1.99 + case PVR2_POLY_FOG_VERTEX:1.100 + if( POLY1_SPECULAR(poly1) ) {1.101 + glFogfv( GL_FOG_COLOR, pvr2_scene.fog_vert_colour );1.102 + glEnable( GL_FOG );1.103 + break;1.104 + } /* else fallthrough */1.105 + default:1.106 + glDisable( GL_FOG );1.107 + }1.109 - if( POLY1_TEXTURED(poly1) ) {1.110 - glEnable(GL_TEXTURE_2D);1.111 - glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, pvr2_poly_texblend[POLY2_TEX_BLEND(poly2)] );1.112 - if( POLY2_TEX_CLAMP_U(poly2) ) {1.113 - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );1.114 - } else if( POLY2_TEX_MIRROR_U(poly2) ) {1.115 - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT_ARB );1.116 - } else {1.117 - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );1.118 - }1.119 - if( POLY2_TEX_CLAMP_V(poly2) ) {1.120 - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );1.121 - } else if( POLY2_TEX_MIRROR_V(poly2) ) {1.122 - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT_ARB );1.123 - } else {1.124 - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );1.125 - }1.126 + int srcblend = POLY2_SRC_BLEND(poly2);1.127 + int destblend = POLY2_DEST_BLEND(poly2);1.128 + glBlendFunc( srcblend, destblend );1.129 +1.130 + if( POLY2_SRC_BLEND_TARGET(poly2) || POLY2_DEST_BLEND_TARGET(poly2) ) {1.131 + WARN( "Accumulation buffer not supported" );1.132 + }1.133 +}1.134 +1.135 +/**1.136 + * Setup the GL context for the supplied polygon context.1.137 + * @param context pointer to 3 or 5 words of polygon context1.138 + * @param modified boolean flag indicating that the modified1.139 + * version should be used, rather than the normal version.1.140 + */1.141 +void render_set_context( uint32_t *context, int render_mode )1.142 +{1.143 + uint32_t poly1 = context[0], poly2, texture;1.144 + if( render_mode == RENDER_FULLMOD ) {1.145 + poly2 = context[3];1.146 + texture = context[4];1.147 } else {1.148 - glDisable( GL_TEXTURE_2D );1.149 - }1.150 -1.151 - switch( POLY2_FOG_MODE(poly2) ) {1.152 - case PVR2_POLY_FOG_LOOKUP:1.153 - glFogfv( GL_FOG_COLOR, pvr2_scene.fog_lut_colour );1.154 - glEnable( GL_FOG );1.155 - break;1.156 - case PVR2_POLY_FOG_VERTEX:1.157 - if( POLY1_SPECULAR(poly1) ) {1.158 - glFogfv( GL_FOG_COLOR, pvr2_scene.fog_vert_colour );1.159 - glEnable( GL_FOG );1.160 - break;1.161 - } /* else fallthrough */1.162 - default:1.163 - glDisable( GL_FOG );1.164 - }1.165 -1.166 -1.167 - glShadeModel( POLY1_SHADE_MODEL(poly1) );1.168 -1.169 - int srcblend = POLY2_SRC_BLEND(poly2);1.170 - int destblend = POLY2_DEST_BLEND(poly2);1.171 - glBlendFunc( srcblend, destblend );1.172 -1.173 - if( POLY2_SRC_BLEND_TARGET(poly2) || POLY2_DEST_BLEND_TARGET(poly2) ) {1.174 - ERROR( "Accumulation buffer not supported" );1.175 + poly2 = context[1];1.176 + texture = context[2];1.177 }1.179 + render_set_base_context(poly1);1.180 + render_set_tsp_context(poly1,poly2,texture);1.181 }1.184 @@ -213,11 +232,26 @@1.185 if( poly->tex_id != -1 ) {1.186 glBindTexture(GL_TEXTURE_2D, poly->tex_id);1.187 }1.188 - render_set_context( poly->context, RENDER_NORMAL );1.189 - glDrawArrays(GL_TRIANGLE_STRIP, poly->vertex_index, poly->vertex_count );1.190 + if( poly->mod_vertex_index == -1 ) {1.191 + render_set_context( poly->context, RENDER_NORMAL );1.192 + glDrawArrays(GL_TRIANGLE_STRIP, poly->vertex_index, poly->vertex_count );1.193 + } else {1.194 + render_set_base_context( poly->context[0] );1.195 + render_set_tsp_context( poly->context[0], poly->context[1], poly->context[2] );1.196 + glStencilFunc(GL_EQUAL, 0, 1);1.197 + glDrawArrays(GL_TRIANGLE_STRIP, poly->vertex_index, poly->vertex_count );1.198 +1.199 + if( pvr2_scene.shadow_mode == SHADOW_FULL ) {1.200 + if( poly->mod_tex_id != -1 ) {1.201 + glBindTexture(GL_TEXTURE_2D, poly->mod_tex_id);1.202 + }1.203 + render_set_tsp_context( poly->context[0], poly->context[3], poly->context[4] );1.204 + }1.205 + glStencilFunc(GL_EQUAL, 1, 1);1.206 + glDrawArrays(GL_TRIANGLE_STRIP, poly->mod_vertex_index, poly->vertex_count );1.207 + }1.208 }1.210 -1.211 static void gl_render_bkgnd( struct polygon_struct *poly )1.212 {1.213 if( poly->tex_id != -1 ) {1.214 @@ -232,14 +266,15 @@1.215 glEnable( GL_DEPTH_TEST );1.216 }1.218 -1.219 -1.220 void gl_render_tilelist( pvraddr_t tile_entry )1.221 {1.222 uint32_t *tile_list = (uint32_t *)(video_base+tile_entry);1.223 int strip_count;1.224 struct polygon_struct *poly;1.226 + if( !IS_TILE_PTR(tile_entry) )1.227 + return;1.228 +1.229 while(1) {1.230 uint32_t entry = *tile_list++;1.231 switch( entry >> 28 ) {1.232 @@ -264,7 +299,102 @@1.233 gl_render_poly( poly );1.234 }1.235 }1.236 - }1.237 + }1.238 +}1.239 +1.240 +/**1.241 + * Render the tilelist with depthbuffer updates only.1.242 + */1.243 +void gl_render_tilelist_depthonly( pvraddr_t tile_entry )1.244 +{1.245 + uint32_t *tile_list = (uint32_t *)(video_base+tile_entry);1.246 + int strip_count;1.247 + struct polygon_struct *poly;1.248 +1.249 + if( !IS_TILE_PTR(tile_entry) )1.250 + return;1.251 +1.252 + glDisable( GL_TEXTURE_2D );1.253 + glDisable( GL_FOG );1.254 + glDisable( GL_COLOR_SUM );1.255 +1.256 + while(1) {1.257 + uint32_t entry = *tile_list++;1.258 + switch( entry >> 28 ) {1.259 + case 0x0F:1.260 + return; // End-of-list1.261 + case 0x0E:1.262 + tile_list = (uint32_t *)(video_base + (entry&0x007FFFFF));1.263 + break;1.264 + case 0x08: case 0x09: case 0x0A: case 0x0B:1.265 + strip_count = ((entry >> 25) & 0x0F)+1;1.266 + poly = pvr2_scene.buf_to_poly_map[entry&0x000FFFFF];1.267 + while( strip_count > 0 ) {1.268 + render_set_base_context(poly->context[0]);1.269 + glDrawArrays(GL_TRIANGLE_STRIP, poly->vertex_index, poly->vertex_count );1.270 + poly = poly->next;1.271 + strip_count--;1.272 + }1.273 + break;1.274 + default:1.275 + if( entry & 0x7E000000 ) {1.276 + poly = pvr2_scene.buf_to_poly_map[entry&0x000FFFFF];1.277 + render_set_base_context(poly->context[0]);1.278 + glDrawArrays(GL_TRIANGLE_STRIP, poly->vertex_index, poly->vertex_count );1.279 + }1.280 + }1.281 + }1.282 +}1.283 +1.284 +void gl_render_modifier_tilelist( pvraddr_t tile_entry )1.285 +{1.286 + uint32_t *tile_list = (uint32_t *)(video_base+tile_entry);1.287 + int strip_count;1.288 + struct polygon_struct *poly;1.289 +1.290 + if( !IS_TILE_PTR(tile_entry) )1.291 + return;1.292 +1.293 + glDisable( GL_TEXTURE_2D );1.294 + glDisable( GL_FOG );1.295 + glDisable( GL_COLOR_SUM );1.296 + glDisable( GL_CULL_FACE );1.297 + glEnable( GL_STENCIL_TEST );1.298 + glEnable( GL_DEPTH_TEST );1.299 + glDepthFunc( GL_LEQUAL );1.300 +1.301 + glStencilFunc( GL_ALWAYS, 0, 1 );1.302 + glStencilOp( GL_KEEP,GL_INVERT, GL_KEEP );1.303 +1.304 + glDepthMask( GL_FALSE );1.305 +1.306 + while(1) {1.307 + uint32_t entry = *tile_list++;1.308 + switch( entry >> 28 ) {1.309 + case 0x0F:1.310 + glDepthMask( GL_TRUE );1.311 + glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );1.312 + return; // End-of-list1.313 + case 0x0E:1.314 + tile_list = (uint32_t *)(video_base + (entry&0x007FFFFF));1.315 + break;1.316 + case 0x08: case 0x09: case 0x0A: case 0x0B:1.317 + strip_count = ((entry >> 25) & 0x0F)+1;1.318 + poly = pvr2_scene.buf_to_poly_map[entry&0x000FFFFF];1.319 + while( strip_count > 0 ) {1.320 + glDrawArrays(GL_TRIANGLE_STRIP, poly->vertex_index, poly->vertex_count );1.321 + poly = poly->next;1.322 + strip_count--;1.323 + }1.324 + break;1.325 + default:1.326 + if( entry & 0x7E000000 ) {1.327 + poly = pvr2_scene.buf_to_poly_map[entry&0x000FFFFF];1.328 + glDrawArrays(GL_TRIANGLE_STRIP, poly->vertex_index, poly->vertex_count );1.329 + }1.330 + }1.331 + }1.332 +1.333 }1.336 @@ -336,9 +466,26 @@1.337 /* Clip to the visible part of the tile */1.338 glScissor( tile_bounds[0], pvr2_scene.buffer_height-tile_bounds[3],1.339 tile_bounds[1]-tile_bounds[0], tile_bounds[3] - tile_bounds[2] );1.340 - if( IS_TILE_PTR(segment->opaque_ptr) ) {1.341 - gl_render_tilelist(segment->opaque_ptr);1.342 + if( display_driver->capabilities.stencil_bits != 0 &&1.343 + IS_TILE_PTR(segment->opaquemod_ptr) &&1.344 + !IS_EMPTY_TILE_LIST(segment->opaquemod_ptr) ) {1.345 + /* Don't do this unless there's actually some shadow polygons */1.346 +1.347 + /* Use colormask instead of drawbuffer for simplicity */1.348 + glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );1.349 + gl_render_tilelist_depthonly(segment->opaque_ptr);1.350 + gl_render_modifier_tilelist(segment->opaquemod_ptr);1.351 + glClear( GL_DEPTH_BUFFER_BIT );1.352 + glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );1.353 }1.354 + gl_render_tilelist(segment->opaque_ptr);1.355 + if( IS_TILE_PTR(segment->punchout_ptr) ) {1.356 + glEnable(GL_ALPHA_TEST );1.357 + render_autosort_tile(segment->punchout_ptr, RENDER_NORMAL );1.358 + glDisable(GL_ALPHA_TEST );1.359 + }1.360 + glDisable( GL_STENCIL_TEST );1.361 +1.362 if( IS_TILE_PTR(segment->trans_ptr) ) {1.363 if( pvr2_scene.sort_mode == SORT_NEVER ||1.364 (pvr2_scene.sort_mode == SORT_TILEFLAG && (segment->control&SEGMENT_SORT_TRANS))) {1.365 @@ -347,11 +494,6 @@1.366 render_autosort_tile(segment->trans_ptr, RENDER_NORMAL );1.367 }1.368 }1.369 - if( IS_TILE_PTR(segment->punchout_ptr) ) {1.370 - glEnable(GL_ALPHA_TEST );1.371 - render_autosort_tile(segment->punchout_ptr, RENDER_NORMAL );1.372 - glDisable(GL_ALPHA_TEST );1.373 - }1.374 } while( !IS_LAST_SEGMENT(segment++) );1.375 glDisable( GL_SCISSOR_TEST );
.