void Object::renderstencilshadow_fast ( int slot, Light *l, bool reverse ) { int i,j; StartCounter ("10stencil render"); // vertex setup: all original vertices with w=1, followed by all original vertices with w=0 if ( instancebase ) { stencilvarhandle = instancebase->stencilvarhandle; if ( !stencilvarhandle ) { stencilvarhandle = renderer->AllocVarBufferHandle( nv*2*4*4 ); // every vertex twice, four floats per vertex if ( !stencilvarhandle ) return; instancebase->stencilvarhandle = stencilvarhandle; } // is vertex buffer still valid? if ( !renderer->IsVarBufferStillValid( stencilvarhandle ) ) stencilreloadneeded = true; } else { // std behaviour // alloc vertex buffer if ( !stencilvarhandle ) { stencilvarhandle = renderer->AllocVarBufferHandle( nv*2*4*4 ); if ( !stencilvarhandle ) return; } } // is vertex buffer still valid? if ( !renderer->IsVarBufferStillValid( stencilvarhandle ) ) stencilreloadneeded = true; void *vbuffer = renderer->LockVarBuffer( stencilvarhandle ); if ( stencilreloadneeded ) { StartCounter ("92Stencil Geometry reload"); Object *src = instancebase?instancebase:this; float *dest = (float*)vbuffer; for ( i=0; inv; i++ ) { dest[0] = src->v[i].os.longvec[0]; dest[1] = src->v[i].os.longvec[1]; dest[2] = src->v[i].os.longvec[2]; dest[3] = 1.0f; dest+=4; } for ( i=0; inv; i++ ) { dest[0] = src->v[i].os.longvec[0]; dest[1] = src->v[i].os.longvec[1]; dest[2] = src->v[i].os.longvec[2]; dest[3] = 0.0f; dest+=4; } StopCounter ("92Stencil Geometry reload"); stencilreloadneeded = false; } // build indices (or should they be built during object update?) int nind[3]; // slots: extrude, frontfacing, backfacing int indbase[3]; // better use one scratch pool... or combine it with some very clever caching... unsigned short *stencilindexlist = renderer->scratchindices; // unsigned shorts.. humz.. this reduces effective max vertex count down to a mere 32k per object.. if ( nv>=(0x10000>>1) ) { printf ("too many vertices in object for stenciling.\n"); } // built extrusion indices int mask = 1<nindices[slot]; unsigned short *ol_ind = outlines->indices[slot]; j=0; indbase[0] = 0; for ( i=0; ipos * mi; osl.w = 1.0f; glProgramParameter4fvNV ( GL_VERTEX_PROGRAM_NV, 16, osl.longvec ); // setup vertices // vp and matrix tacking assumed to be active... glVertexPointer ( 4, GL_FLOAT, 4*sizeof(float), vbuffer ); #ifdef _DEBUG renderer->CheckVAR(); #endif if ( reverse ) { glCullFace ( GL_BACK ); glStencilOp ( GL_KEEP, GL_INCR_WRAP_EXT, GL_KEEP ); for ( int side=0; side<2; side++ ) { if ( glDrawRangeElementsEXT ) { // todo: maybe make first quad set a quad strip... glDrawRangeElementsEXT (GL_QUADS, 0, nv<<1, nind[0], GL_UNSIGNED_SHORT, stencilindexlist+indbase[0]); glDrawRangeElementsEXT (GL_TRIANGLES, 0, nv<<1, nind[2], GL_UNSIGNED_SHORT, stencilindexlist+indbase[2]); glDisable ( GL_VERTEX_PROGRAM_NV ); glDrawRangeElementsEXT (GL_TRIANGLES, 0, nv, nind[1], GL_UNSIGNED_SHORT, stencilindexlist+indbase[1]); glEnable ( GL_VERTEX_PROGRAM_NV ); } else { glDrawElements (GL_QUADS, nind[0],GL_UNSIGNED_SHORT, stencilindexlist+indbase[0]); glDrawElements (GL_TRIANGLES, nind[2],GL_UNSIGNED_SHORT, stencilindexlist+indbase[2]); glDisable ( GL_VERTEX_PROGRAM_NV ); glDrawElements (GL_TRIANGLES, nind[1],GL_UNSIGNED_SHORT, stencilindexlist+indbase[1]); glEnable ( GL_VERTEX_PROGRAM_NV ); } glCullFace ( GL_FRONT ); glStencilOp ( GL_KEEP, GL_DECR_WRAP_EXT, GL_KEEP ); } } else { glCullFace ( GL_BACK ); glStencilOp ( GL_KEEP, GL_KEEP, GL_INCR_WRAP_EXT ); for ( int side=0; side<2; side++ ) { if ( glDrawRangeElementsEXT ) { glDrawRangeElementsEXT (GL_QUADS, 0, nv, nind[0], GL_UNSIGNED_SHORT, stencilindexlist+indbase[0]); glDisable ( GL_VERTEX_PROGRAM_NV ); glDrawRangeElementsEXT (GL_TRIANGLES, 0, nv, nind[1], GL_UNSIGNED_SHORT, stencilindexlist+indbase[1]); glEnable ( GL_VERTEX_PROGRAM_NV ); } else { glDrawElements (GL_QUADS, nind[0],GL_UNSIGNED_SHORT, stencilindexlist+indbase[0]); glDisable ( GL_VERTEX_PROGRAM_NV ); glDrawElements (GL_TRIANGLES, nind[1],GL_UNSIGNED_SHORT, stencilindexlist+indbase[1]); glEnable ( GL_VERTEX_PROGRAM_NV ); } glCullFace ( GL_FRONT ); glStencilOp ( GL_KEEP, GL_KEEP, GL_DECR_WRAP_EXT ); } } glPopMatrix (); renderer->UnlockVarBuffer( stencilvarhandle ); StopCounter ("10stencil render"); }