00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00022 #include "AEngine.h"
00023 #include "AState.h"
00024 #include "AUtil.h"
00025
00026 const int MAX_SPRITE_COUNT = 4096;
00027
00028
00029
00031
00032 {
00033 public:
00035 bool operator()(const SpriteRenderRequestEntry &L, const SpriteRenderRequestEntry &R )
00036 {
00037 return L.tex*100+L.blendMode < R.tex*100+R.blendMode;
00038 }
00039 };
00040
00041
00042
00043 void sprite_init()
00044 {
00045 int vbByteSize = MAX_SPRITE_COUNT * sizeof(SpriteVertex);
00046 if( FAILED( AS.pDevice->CreateVertexBuffer( vbByteSize, D3DUSAGE_WRITEONLY|D3DUSAGE_DYNAMIC|D3DUSAGE_POINTS,
00047 0, D3DPOOL_DEFAULT, &AS.sprite_vb ) ))
00048 throw Error("Can't create spriteVB");
00049
00050 AS.sprite_renderList.resize(0);
00051 AS.sprite_startRenderingIndex = 0;
00052
00053 AS.vshader_sprite = util_loadVertexShader( "shaders\\sprite.vso", dwSpriteVertexDecl );
00054 AS.pshader_sprite = util_loadPixelShader( "shaders\\sprite.pso" );
00055 }
00056
00057 void sprite_add( ATexture tex, int blendMode, Vec3D pos, Vec4D multiplier, FLOAT size )
00058 {
00059 AS.sprite_renderList.push_back( SpriteRenderRequestEntry(tex,blendMode,pos,multiplier,size) );
00060 }
00061
00062 void sprite_flush()
00063 {
00064 AS.sprite_renderList.resize(0);
00065 }
00066
00067 void sprite_process()
00068 {
00069 int renderCount = (int) AS.sprite_renderList.size();
00070 if(renderCount==0) return;
00071
00072 sort( AS.sprite_renderList.begin(), AS.sprite_renderList.end(), SpriteRequestEntryComparer() );
00073
00074 SpriteVertex *pVertex;
00075
00076
00077 HRESULT res;
00078 if( AS.sprite_startRenderingIndex + renderCount < MAX_SPRITE_COUNT )
00079 {
00080 res = AS.sprite_vb->Lock( AS.sprite_startRenderingIndex*sizeof(SpriteVertex),
00081 renderCount*sizeof(SpriteVertex),
00082 (BYTE**)&pVertex, D3DLOCK_NOOVERWRITE );
00083 if( FAILED(res)) throw Error("Can't Lock spriteVB");
00084 }
00085 else
00086 {
00087 AS.sprite_startRenderingIndex = 0;
00088 res = AS.sprite_vb->Lock( AS.sprite_startRenderingIndex*sizeof(SpriteVertex),
00089 renderCount*sizeof(SpriteVertex),
00090 (BYTE**)&pVertex, D3DLOCK_DISCARD );
00091 if( FAILED(res)) throw Error("Can't Lock/Renew spriteVB");
00092 }
00093
00094
00095 for( int i=0; i<renderCount; i++ )
00096 {
00097 pVertex[i].pos = AS.sprite_renderList[i].pos;
00098 pVertex[i].colorMultiplier = AS.sprite_renderList[i].multiplier;
00099 pVertex[i].size = AS.sprite_renderList[i].size;
00100 }
00101 AS.sprite_vb->Unlock();
00102
00103
00104 device_setVertexShader( AS.vshader_sprite );
00105 device_setPixelShader( AS.pshader_sprite );
00106 device_setStreamSource( 0, AS.sprite_vb, sizeof(SpriteVertex) );
00107
00108 Matx matx;
00109 FLOAT sizeCalcConst[4] = { 3.0f, 640.0f, 0.0f, 0.0f };
00110 D3DXMatrixTranspose( &matx, &AS.camera_world2projMatrix);
00111 AS.pDevice->SetVertexShaderConstant( 0, &matx, 4 );
00112 AS.pDevice->SetVertexShaderConstant( 4, &AS.camera_pos[0], 1 );
00113 AS.pDevice->SetVertexShaderConstant( 5, &sizeCalcConst, 1 );
00114
00115
00116 device_setRenderState( D3DRS_ZWRITEENABLE, FALSE );
00117 device_setRenderState( D3DRS_POINTSPRITEENABLE, TRUE );
00118 device_setTextureStageState( 3, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
00119 device_setTextureStageState( 3, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
00120 device_setTextureStageState( 3, D3DTSS_MIPFILTER, D3DTEXF_POINT );
00121
00122
00123 ATexture currentTex = AS.sprite_renderList[0].tex;
00124 int currentBlend = AS.sprite_renderList[0].blendMode;
00125
00126 int start = 0;
00127 for( int i=0; i<renderCount; i++ )
00128 {
00129 ATexture newTex = AS.sprite_renderList[i].tex;
00130 int newBlend = AS.sprite_renderList[i].blendMode;
00131 if( newTex!=currentTex || newBlend!=currentBlend )
00132 {
00133 device_setTexture( 3, AS.res_textures[ currentTex ] );
00134 device_setRenderStateBlendMode(currentBlend);
00135
00136
00137 AS.pDevice->DrawPrimitive( D3DPT_POINTLIST, AS.sprite_startRenderingIndex+start, (i-1)-start+1 );
00138
00139 start = i;
00140 currentTex = newTex;
00141 currentBlend = newBlend;
00142 }
00143 }
00144
00145
00146
00147 device_setTexture( 3, AS.res_textures[ currentTex ] );
00148 device_setRenderStateBlendMode(currentBlend);
00149 AS.pDevice->DrawPrimitive( D3DPT_POINTLIST, AS.sprite_startRenderingIndex+start, (renderCount-1)-start+1 );
00150
00151 AS.sprite_startRenderingIndex += renderCount;
00152 device_setRenderState( D3DRS_POINTSPRITEENABLE, FALSE );
00153 }
00154