void Sprite::DrawTexture( const TweenState *state ) { Actor::SetGlobalRenderStates(); // set Actor-specified render states RectF crop = state->crop; // bail if cropped all the way if( crop.left + crop.right >= 1 || crop.top + crop.bottom >= 1 ) return; // use m_temp_* variables to draw the object RectF quadVerticies; quadVerticies.left = -m_size.x/2.0f; quadVerticies.right = +m_size.x/2.0f; quadVerticies.top = -m_size.y/2.0f; quadVerticies.bottom = +m_size.y/2.0f; /* Don't draw anything outside of the texture's image area. Texels outside * of the image area aren't guaranteed to be initialized. */ /* HACK: Clamp the crop values. It would be more accurate to clip the * vertices so that the diffuse value is adjusted. */ CLAMP( crop.left, 0, 1 ); CLAMP( crop.right, 0, 1 ); CLAMP( crop.top, 0, 1 ); CLAMP( crop.bottom, 0, 1 ); RectF croppedQuadVerticies = quadVerticies; #define IF_CROP_POS(side,opp_side) \ if(state->crop.side!=0) \ croppedQuadVerticies.side = \ SCALE( crop.side, 0.f, 1.f, quadVerticies.side, quadVerticies.opp_side ) IF_CROP_POS( left, right ); IF_CROP_POS( top, bottom ); IF_CROP_POS( right, left ); IF_CROP_POS( bottom, top ); static RageSpriteVertex v[4]; v[0].p = RageVector3( croppedQuadVerticies.left, croppedQuadVerticies.top, 0 ); // top left v[1].p = RageVector3( croppedQuadVerticies.left, croppedQuadVerticies.bottom, 0 ); // bottom left v[2].p = RageVector3( croppedQuadVerticies.right, croppedQuadVerticies.bottom, 0 ); // bottom right v[3].p = RageVector3( croppedQuadVerticies.right, croppedQuadVerticies.top, 0 ); // top right if( m_bUsingCustomPosCoords ) { for( int i=0; i < 4; ++i) { v[i].p.x+= m_CustomPosCoords[i*2]; v[i].p.y+= m_CustomPosCoords[(i*2)+1]; } } DISPLAY->ClearAllTextures(); DISPLAY->SetTexture( TextureUnit_1, m_pTexture? m_pTexture->GetTexHandle():0 ); // Must call this after setting the texture or else texture // parameters have no effect. Actor::SetTextureRenderStates(); // set Actor-specified render states DISPLAY->SetEffectMode( m_EffectMode ); if( m_pTexture ) { float f[8]; GetActiveTextureCoords( f ); if( state->crop.left || state->crop.right || state->crop.top || state->crop.bottom ) { RageVector2 texCoords[4] = { RageVector2( f[0], f[1] ), // top left RageVector2( f[2], f[3] ), // bottom left RageVector2( f[4], f[5] ), // bottom right RageVector2( f[6], f[7] ) // top right }; for( int i = 0; i < 4; ++i ) { RageSpriteVertex *pVert = &v[i]; float fTopX = SCALE( pVert->p.x, quadVerticies.left, quadVerticies.right, texCoords[0].x, texCoords[3].x ); float fBottomX = SCALE( pVert->p.x, quadVerticies.left, quadVerticies.right, texCoords[1].x, texCoords[2].x ); pVert->t.x = SCALE( pVert->p.y, quadVerticies.top, quadVerticies.bottom, fTopX, fBottomX ); float fLeftY = SCALE( pVert->p.y, quadVerticies.top, quadVerticies.bottom, texCoords[0].y, texCoords[1].y ); float fRightY = SCALE( pVert->p.y, quadVerticies.top, quadVerticies.bottom, texCoords[3].y, texCoords[2].y ); pVert->t.y = SCALE( pVert->p.x, quadVerticies.left, quadVerticies.right, fLeftY, fRightY ); } } else { v[0].t = RageVector2( f[0], f[1] ); // top left v[1].t = RageVector2( f[2], f[3] ); // bottom left v[2].t = RageVector2( f[4], f[5] ); // bottom right v[3].t = RageVector2( f[6], f[7] ); // top right } } else { // Just make sure we don't throw NaN/INF at the renderer: for( unsigned i = 0; i < 4; ++i ) v[i].t.x = v[i].t.y = 0; } // Draw if we're not fully transparent if( state->diffuse[0].a > 0 || state->diffuse[1].a > 0 || state->diffuse[2].a > 0 || state->diffuse[3].a > 0 ) { DISPLAY->SetTextureMode( TextureUnit_1, TextureMode_Modulate ); // render the shadow if( m_fShadowLengthX != 0 || m_fShadowLengthY != 0 ) { DISPLAY->PushMatrix(); DISPLAY->TranslateWorld( m_fShadowLengthX, m_fShadowLengthY, 0 ); // shift by 5 units RageColor c = m_ShadowColor; c.a *= state->diffuse[0].a; v[0].c = v[1].c = v[2].c = v[3].c = c; // semi-transparent black DISPLAY->DrawQuad( v ); DISPLAY->PopMatrix(); } // render the diffuse pass v[0].c = state->diffuse[0]; // top left v[1].c = state->diffuse[2]; // bottom left v[2].c = state->diffuse[3]; // bottom right v[3].c = state->diffuse[1]; // top right DISPLAY->DrawQuad( v ); } // render the glow pass if( state->glow.a > 0.0001f ) { DISPLAY->SetTextureMode( TextureUnit_1, TextureMode_Glow ); v[0].c = v[1].c = v[2].c = v[3].c = state->glow; DISPLAY->DrawQuad( v ); } DISPLAY->SetEffectMode( EffectMode_Normal ); }
void Sprite::DrawTexture( const TweenState *state ) { Actor::SetGlobalRenderStates(); // set Actor-specified render states // bail if cropped all the way if( state->crop.left + state->crop.right >= 1 || state->crop.top + state->crop.bottom >= 1 ) return; // use m_temp_* variables to draw the object RectF quadVerticies; switch( m_HorizAlign ) { case align_left: quadVerticies.left = 0; quadVerticies.right = m_size.x; break; case align_center: quadVerticies.left = -m_size.x/2; quadVerticies.right = m_size.x/2; break; case align_right: quadVerticies.left = -m_size.x; quadVerticies.right = 0; break; default: ASSERT( false ); } switch( m_VertAlign ) { case align_top: quadVerticies.top = 0; quadVerticies.bottom = m_size.y; break; case align_middle: quadVerticies.top = -m_size.y/2; quadVerticies.bottom = m_size.y/2; break; case align_bottom: quadVerticies.top = -m_size.y; quadVerticies.bottom = 0; break; default: ASSERT(0); } /* Don't draw anything outside of the texture's image area. Texels outside * of the image area aren't guaranteed to be initialized. */ /* HACK: Clamp the crop values. It would be more accurate to clip the * vertices to that the diffuse value is adjusted. */ RectF crop = state->crop; CLAMP( crop.left, 0, 1 ); CLAMP( crop.right, 0, 1 ); CLAMP( crop.top, 0, 1 ); CLAMP( crop.bottom, 0, 1 ); RectF croppedQuadVerticies = quadVerticies; #define IF_CROP_POS(side,opp_side) \ if(state->crop.side!=0) \ croppedQuadVerticies.side = \ SCALE( crop.side, 0.f, 1.f, quadVerticies.side, quadVerticies.opp_side ); IF_CROP_POS( left, right ); IF_CROP_POS( top, bottom ); IF_CROP_POS( right, left ); IF_CROP_POS( bottom, top ); static RageSpriteVertex v[4]; v[0].p = RageVector3( croppedQuadVerticies.left, croppedQuadVerticies.top, 0 ); // top left v[1].p = RageVector3( croppedQuadVerticies.left, croppedQuadVerticies.bottom, 0 ); // bottom left v[2].p = RageVector3( croppedQuadVerticies.right, croppedQuadVerticies.bottom, 0 ); // bottom right v[3].p = RageVector3( croppedQuadVerticies.right, croppedQuadVerticies.top, 0 ); // top right DISPLAY->ClearAllTextures(); DISPLAY->SetTexture( 0, m_pTexture ); // Must call this after setting the texture or else texture // parameters have no effect. Actor::SetTextureRenderStates(); // set Actor-specified render states if( m_pTexture ) { float f[8]; GetActiveTextureCoords(f); TexCoordsFromArray(v, f); RageVector2 texCoords[4] = { RageVector2( f[0], f[1] ), // top left RageVector2( f[2], f[3] ), // bottom left RageVector2( f[4], f[5] ), // bottom right RageVector2( f[6], f[7] ) // top right }; if( crop.left!=0 ) { v[0].t.x = SCALE( crop.left, 0.f, 1.f, texCoords[0].x, texCoords[3].x ); v[1].t.x = SCALE( crop.left, 0.f, 1.f, texCoords[1].x, texCoords[2].x ); } if( crop.right!=0 ) { v[2].t.x = SCALE( crop.right, 0.f, 1.f, texCoords[2].x, texCoords[1].x ); v[3].t.x = SCALE( crop.right, 0.f, 1.f, texCoords[3].x, texCoords[0].x ); } if( crop.top!=0 ) { v[0].t.y = SCALE( crop.top, 0.f, 1.f, texCoords[0].y, texCoords[1].y ); v[3].t.y = SCALE( crop.top, 0.f, 1.f, texCoords[3].y, texCoords[2].y ); } if( crop.bottom!=0 ) { v[1].t.y = SCALE( crop.bottom, 0.f, 1.f, texCoords[1].y, texCoords[0].y ); v[2].t.y = SCALE( crop.bottom, 0.f, 1.f, texCoords[2].y, texCoords[3].y ); } } else { // Just make sure we don't throw NaN/INF at the renderer: for( unsigned i = 0; i < 4; ++i ) v[i].t.x = v[i].t.y = 0; } /* Draw if we're not fully transparent */ if( state->diffuse[0].a > 0 || state->diffuse[1].a > 0 || state->diffuse[2].a > 0 || state->diffuse[3].a > 0 ) { DISPLAY->SetTextureModeModulate(); ////////////////////// // render the shadow ////////////////////// if( m_fShadowLength != 0 ) { DISPLAY->PushMatrix(); DISPLAY->TranslateWorld( m_fShadowLength, m_fShadowLength, 0 ); // shift by 5 units v[0].c = v[1].c = v[2].c = v[3].c = RageColor(0,0,0,0.5f*state->diffuse[0].a); // semi-transparent black DISPLAY->DrawQuad( v ); DISPLAY->PopMatrix(); } ////////////////////// // render the diffuse pass ////////////////////// v[0].c = state->diffuse[0]; // top left v[1].c = state->diffuse[2]; // bottom left v[2].c = state->diffuse[3]; // bottom right v[3].c = state->diffuse[1]; // top right DISPLAY->DrawQuad( v ); } ////////////////////// // render the glow pass ////////////////////// if( state->glow.a > 0.0001f ) { DISPLAY->SetTextureModeGlow(); v[0].c = v[1].c = v[2].c = v[3].c = state->glow; DISPLAY->DrawQuad( v ); } }