//============================================================================= // Return the number of pixels colliding between the two sprites. // Pre: The device supports a stencil buffer and pOcclusionQuery points to // a valid occlusionQuery object. // Post: Returns the number of pixels of overlap //============================================================================= DWORD Graphics::pixelCollision(const SpriteData &sprite1, const SpriteData &sprite2) { if(!stencilSupport) // if no stencil buffer support return 0; beginScene(); // Set up stencil buffer using current entity device3d->SetRenderState(D3DRS_STENCILENABLE, true); device3d->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS); device3d->SetRenderState(D3DRS_STENCILREF, 0x1); device3d->SetRenderState(D3DRS_STENCILMASK, 0xffffffff); device3d->SetRenderState(D3DRS_STENCILWRITEMASK,0xffffffff); device3d->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP); device3d->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE); // Write a 1 into the stencil buffer for each non-transparent pixel in ent spriteBegin(); // Enable stencil buffer (must be after spriteBegin) device3d->SetRenderState(D3DRS_STENCILENABLE, true); drawSprite(sprite2); // write 1s to stencil buffer spriteEnd(); // Change stencil buffer to only allow writes where the stencil value is 1 // (where the ent sprite is colliding with the current sprite) device3d->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_EQUAL); device3d->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP); // Begin occlusion query to count pixels that are drawn pOcclusionQuery->Issue(D3DISSUE_BEGIN); spriteBegin(); // Enable stencil buffer (must be after spriteBegin) device3d->SetRenderState(D3DRS_STENCILENABLE, true); drawSprite(sprite1); // draw current entity spriteEnd(); // End occlusion query pOcclusionQuery->Issue(D3DISSUE_END); // Wait until the GPU is finished. while(S_FALSE == pOcclusionQuery->GetData( &numberOfPixelsColliding, sizeof(DWORD), D3DGETDATA_FLUSH )) {} // Turn off stencil device3d->SetRenderState(D3DRS_STENCILENABLE, false); endScene(); return numberOfPixelsColliding; }
DWORD Graphics::pixelCollision(const SpriteData &sprite1, const SpriteData &sprite2) { if(!stencilSupport) return 0; beginScene(); device3d->SetRenderState(D3DRS_STENCILENABLE, true); device3d->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS); device3d->SetRenderState(D3DRS_STENCILREF, 0x1); device3d->SetRenderState(D3DRS_STENCILMASK, 0xffffffff); device3d->SetRenderState(D3DRS_STENCILWRITEMASK,0xffffffff); device3d->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP); device3d->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE); spriteBegin(); device3d->SetRenderState(D3DRS_STENCILENABLE, true); drawSprite(sprite2); spriteEnd(); device3d->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_EQUAL); device3d->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP); pOcclusionQuery->Issue(D3DISSUE_BEGIN); spriteBegin(); device3d->SetRenderState(D3DRS_STENCILENABLE, true); drawSprite(sprite1); spriteEnd(); pOcclusionQuery->Issue(D3DISSUE_END); while(S_FALSE == pOcclusionQuery->GetData( &numberOfPixelsColliding, sizeof(DWORD), D3DGETDATA_FLUSH )) {} device3d->SetRenderState(D3DRS_STENCILENABLE, false); endScene(); return numberOfPixelsColliding; }