gxscene.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618
  1. #include "std.h"
  2. #include "gxscene.h"
  3. #include "gxgraphics.h"
  4. #include "gxruntime.h"
  5. static bool can_wb;
  6. static int hw_tex_stages,tex_stages;
  7. static float BLACK[]={0,0,0};
  8. static float WHITE[]={1,1,1};
  9. static float GRAY[]={.5f,.5f,.5f};
  10. static D3DMATRIX sphere_mat,nullmatrix;
  11. void gxScene::setRS( int n,int t ){
  12. if( d3d_rs[n]==t ) return;
  13. dir3dDev->SetRenderState( (D3DRENDERSTATETYPE)n,t );
  14. d3d_rs[n]=t;
  15. }
  16. void gxScene::setTSS( int n,int s,int t ){
  17. if( d3d_tss[n][s]==t ) return;
  18. dir3dDev->SetTextureStageState( n,(D3DTEXTURESTAGESTATETYPE)s,t );
  19. d3d_tss[n][s]=t;
  20. }
  21. gxScene::gxScene( gxGraphics *g,gxCanvas *t ):
  22. graphics(g),target(t),dir3dDev( g->dir3dDev ),
  23. n_texs(0),tris_drawn(0){
  24. memset( d3d_rs,0x55,sizeof(d3d_rs) );
  25. memset( d3d_tss,0x55,sizeof(d3d_tss) );
  26. //nomalize normals
  27. setRS( D3DRENDERSTATE_NORMALIZENORMALS,TRUE );
  28. //vertex coloring
  29. setRS( D3DRENDERSTATE_COLORVERTEX,FALSE );
  30. setRS( D3DRENDERSTATE_DIFFUSEMATERIALSOURCE,D3DMCS_COLOR1 );
  31. setRS( D3DRENDERSTATE_AMBIENTMATERIALSOURCE,D3DMCS_COLOR1 );
  32. setRS( D3DRENDERSTATE_EMISSIVEMATERIALSOURCE,D3DMCS_MATERIAL );
  33. setRS( D3DRENDERSTATE_SPECULARMATERIALSOURCE,D3DMCS_MATERIAL );
  34. //Alpha test
  35. setRS( D3DRENDERSTATE_ALPHATESTENABLE,false );
  36. setRS( D3DRENDERSTATE_ALPHAFUNC,D3DCMP_GREATER );
  37. setRS( D3DRENDERSTATE_ALPHAREF,128 );
  38. //source/dest blending modes
  39. setRS( D3DRENDERSTATE_SRCBLEND,D3DBLEND_SRCALPHA );
  40. setRS( D3DRENDERSTATE_DESTBLEND,D3DBLEND_INVSRCALPHA );
  41. //suss out caps
  42. can_wb=false;
  43. hw_tex_stages=1;
  44. D3DDEVICEDESC7 devDesc={0};
  45. if( dir3dDev->GetCaps( &devDesc )>=0 ){
  46. DWORD caps=devDesc.dpcTriCaps.dwRasterCaps;
  47. //texture stages
  48. hw_tex_stages=devDesc.wMaxSimultaneousTextures;
  49. //depth buffer mode
  50. if( (caps & D3DPRASTERCAPS_WBUFFER) && graphics->zbuffFmt.dwRGBBitCount==16 ) can_wb=true;
  51. //fog mode
  52. if( (caps&D3DPRASTERCAPS_FOGTABLE)&&(caps&D3DPRASTERCAPS_WFOG) ){
  53. setRS( D3DRENDERSTATE_FOGVERTEXMODE,D3DFOG_NONE );
  54. setRS( D3DRENDERSTATE_FOGTABLEMODE,D3DFOG_LINEAR );
  55. }else{
  56. setRS( D3DRENDERSTATE_FOGTABLEMODE,D3DFOG_NONE );
  57. setRS( D3DRENDERSTATE_FOGVERTEXMODE,D3DFOG_LINEAR );
  58. }
  59. }
  60. tex_stages=hw_tex_stages;
  61. caps_level=100;
  62. if( devDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP ){
  63. caps_level=110;
  64. }
  65. //default texture states
  66. for( int n=0;n<hw_tex_stages;++n ){
  67. setTSS( n,D3DTSS_COLORARG1,D3DTA_TEXTURE );
  68. setTSS( n,D3DTSS_COLORARG2,D3DTA_CURRENT );
  69. setTSS( n,D3DTSS_ALPHAARG1,D3DTA_TEXTURE );
  70. setTSS( n,D3DTSS_ALPHAARG2,D3DTA_CURRENT );
  71. setTSS( n,D3DTSS_MINFILTER,D3DTFN_LINEAR );
  72. setTSS( n,D3DTSS_MAGFILTER,D3DTFG_LINEAR );
  73. setTSS( n,D3DTSS_MIPFILTER,D3DTFP_LINEAR );
  74. }
  75. setHWMultiTex( true );
  76. //ATI lighting hack
  77. dir3dDev->LightEnable( 0,true );
  78. dir3dDev->LightEnable( 0,false );
  79. //globals
  80. sphere_mat._11=.5f;sphere_mat._22=-.5f;sphere_mat._33=.5f;
  81. sphere_mat._41=.5f;sphere_mat._42=.5f;sphere_mat._43=.5f;
  82. nullmatrix._11=nullmatrix._22=nullmatrix._33=nullmatrix._44=1;
  83. //set null renderstate
  84. memset(&material,0,sizeof(material));
  85. shininess=0;blend=BLEND_REPLACE;fx=0;
  86. for( int k=0;k<MAX_TEXTURES;++k ) memset( &texstate[k],0,sizeof(texstate[k]) );
  87. wbuffer=can_wb;
  88. dither=false;setDither( true );
  89. antialias=true;setAntialias( false );
  90. wireframe=true;setWireframe( false );
  91. flipped=true;setFlippedTris( false );
  92. ambient=~0;setAmbient( GRAY );
  93. ambient2=~0;setAmbient2( BLACK );
  94. fogcolor=~0;setFogColor( BLACK );
  95. fogrange_nr=fogrange_fr=0;setFogRange( 1,1000 );
  96. fogmode=FOG_LINEAR;setFogMode( FOG_NONE );
  97. zmode=-1;setZMode( ZMODE_NORMAL );
  98. memset(&projmatrix,0,sizeof(projmatrix));
  99. ortho_proj=true;frustum_nr=frustum_fr=frustum_w=frustum_h=0;setPerspProj( 1,1000,1,1 );
  100. memset(&viewport,0,sizeof(viewport));viewport.dvMaxZ=1;setViewport( 0,0,target->getWidth(),target->getHeight() );
  101. viewmatrix=nullmatrix;setViewMatrix( 0 );
  102. worldmatrix=nullmatrix;setWorldMatrix( 0 );
  103. //set default renderstate
  104. blend=fx=~0;shininess=1;
  105. RenderState state;memset(&state,0,sizeof(state));
  106. state.color[0]=state.color[1]=state.color[2]=state.alpha=1;
  107. state.blend=BLEND_REPLACE;
  108. setRenderState( state );
  109. }
  110. gxScene::~gxScene(){
  111. while( _allLights.size() ) freeLight( *_allLights.begin() );
  112. }
  113. void gxScene::setTexState( int n,const TexState &state,bool tex_blend ){
  114. int flags=state.canvas->getFlags();
  115. int tc_index=state.flags & TEX_COORDS2 ? 1 : 0;
  116. //set canvas
  117. dir3dDev->SetTexture( n,state.canvas->getTexSurface() );
  118. //set addressing modes
  119. setTSS( n,D3DTSS_ADDRESSU,(flags & gxCanvas::CANVAS_TEX_CLAMPU) ? D3DTADDRESS_CLAMP : D3DTADDRESS_WRAP );
  120. setTSS( n,D3DTSS_ADDRESSV,(flags & gxCanvas::CANVAS_TEX_CLAMPV) ? D3DTADDRESS_CLAMP : D3DTADDRESS_WRAP );
  121. //texgen
  122. switch( flags&(
  123. gxCanvas::CANVAS_TEX_SPHERE|
  124. gxCanvas::CANVAS_TEX_CUBE) ){
  125. case gxCanvas::CANVAS_TEX_SPHERE:
  126. setTSS( n,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACENORMAL );//|tc_index );
  127. setTSS( n,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2 );
  128. dir3dDev->SetTransform( (D3DTRANSFORMSTATETYPE)(D3DTRANSFORMSTATE_TEXTURE0+n),&sphere_mat );
  129. break;
  130. case gxCanvas::CANVAS_TEX_CUBE:
  131. switch( state.canvas->cubeMode() & 3 ){
  132. case gxCanvas::CUBEMODE_NORMAL:
  133. setTSS( n,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACENORMAL );//|tc_index );
  134. break;
  135. case gxCanvas::CUBEMODE_POSITION:
  136. setTSS( n,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACEPOSITION );//|tc_index );
  137. break;
  138. default:
  139. setTSS( n,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR );//|tc_index );
  140. break;
  141. }
  142. if( state.canvas->cubeMode() & 4 ){
  143. setTSS( n,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_DISABLE );
  144. }else{
  145. setTSS( n,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT3 );//COUNT4|D3DTTFF_PROJECTED );
  146. dir3dDev->SetTransform( (D3DTRANSFORMSTATETYPE)(D3DTRANSFORMSTATE_TEXTURE0+n),&inv_viewmatrix );
  147. }
  148. break;
  149. default:
  150. setTSS( n,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_PASSTHRU|tc_index );
  151. if( state.mat_valid){
  152. setTSS( n,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2 );
  153. dir3dDev->SetTransform( (D3DTRANSFORMSTATETYPE)(D3DTRANSFORMSTATE_TEXTURE0+n),(D3DMATRIX*)&state.matrix );
  154. }else{
  155. setTSS( n,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_DISABLE );
  156. }
  157. }
  158. if( !tex_blend ) return;
  159. //blending
  160. switch( state.blend ){
  161. case BLEND_ALPHA:
  162. setTSS( n,D3DTSS_COLOROP,D3DTOP_BLENDTEXTUREALPHA );
  163. break;
  164. case BLEND_MULTIPLY:
  165. setTSS( n,D3DTSS_COLOROP,D3DTOP_MODULATE);
  166. break;
  167. case BLEND_ADD:
  168. setTSS( n,D3DTSS_COLOROP,D3DTOP_ADD );
  169. break;
  170. case BLEND_DOT3:
  171. setTSS( n,D3DTSS_COLOROP,D3DTOP_DOTPRODUCT3 );
  172. break;
  173. case BLEND_MULTIPLY2:
  174. setTSS( n,D3DTSS_COLOROP,D3DTOP_MODULATE2X );
  175. break;
  176. }
  177. setTSS( n,D3DTSS_ALPHAOP,(flags & gxCanvas::CANVAS_TEX_ALPHA) ? D3DTOP_MODULATE : D3DTOP_SELECTARG2 );
  178. }
  179. int gxScene::hwTexUnits(){
  180. return tex_stages;
  181. }
  182. int gxScene::gfxDriverCaps3D(){
  183. return caps_level;
  184. }
  185. void gxScene::setZMode(){
  186. switch( zmode ){
  187. case ZMODE_NORMAL:
  188. setRS( D3DRENDERSTATE_ZENABLE,wbuffer ? D3DZB_USEW : D3DZB_TRUE );
  189. setRS( D3DRENDERSTATE_ZWRITEENABLE,true );
  190. break;
  191. case ZMODE_DISABLE:
  192. setRS( D3DRENDERSTATE_ZENABLE,D3DZB_FALSE );
  193. setRS( D3DRENDERSTATE_ZWRITEENABLE,false );
  194. break;
  195. case ZMODE_CMPONLY:
  196. setRS( D3DRENDERSTATE_ZENABLE,wbuffer ? D3DZB_USEW : D3DZB_TRUE );
  197. setRS( D3DRENDERSTATE_ZWRITEENABLE,false );
  198. break;
  199. }
  200. }
  201. void gxScene::setLights(){
  202. if( fx & FX_FULLBRIGHT ){
  203. //no lights on
  204. for( int n=0;n<_curLights.size();++n ) dir3dDev->LightEnable( n,false );
  205. }else if( fx & FX_CONDLIGHT ){
  206. //some lights on
  207. for( int n=0;n<_curLights.size();++n ){
  208. gxLight *light=_curLights[n];
  209. bool enable=light->d3d_light.dltType!=D3DLIGHT_DIRECTIONAL;
  210. dir3dDev->LightEnable( n,enable );
  211. }
  212. }else{
  213. //all lights on
  214. for( int n=0;n<_curLights.size();++n ) dir3dDev->LightEnable( n,true );
  215. }
  216. }
  217. void gxScene::setAmbient(){
  218. int n=(fx & FX_FULLBRIGHT) ? 0xffffff : ((fx & FX_CONDLIGHT) ? ambient2 : ambient);
  219. setRS( D3DRENDERSTATE_AMBIENT,n );
  220. }
  221. void gxScene::setFogMode(){
  222. bool fog= fogmode==FOG_LINEAR && !(fx&FX_NOFOG);
  223. setRS( D3DRENDERSTATE_FOGENABLE,fog );
  224. }
  225. void gxScene::setTriCull(){
  226. if( fx & FX_DOUBLESIDED ){
  227. setRS( D3DRENDERSTATE_CULLMODE,D3DCULL_NONE );
  228. }else if( flipped ){
  229. setRS( D3DRENDERSTATE_CULLMODE,D3DCULL_CW );
  230. }else{
  231. setRS( D3DRENDERSTATE_CULLMODE,D3DCULL_CCW );
  232. }
  233. }
  234. void gxScene::setHWMultiTex( bool e ){
  235. for( int n=0;n<8;++n ){
  236. setTSS( n,D3DTSS_COLOROP,D3DTOP_DISABLE );
  237. setTSS( n,D3DTSS_ALPHAOP,D3DTOP_DISABLE );
  238. dir3dDev->SetTexture( n,0 );
  239. }
  240. for( int k=0;k<MAX_TEXTURES;++k ){
  241. memset( &texstate[k],0,sizeof(texstate[k]) );
  242. }
  243. tex_stages=e ? hw_tex_stages : 1;
  244. n_texs=0;
  245. }
  246. void gxScene::setWBuffer( bool n ){
  247. if( n==wbuffer || !can_wb ) return;
  248. wbuffer=n;setZMode();
  249. }
  250. void gxScene::setDither( bool n ){
  251. if( n==dither ) return;
  252. dither=n;setRS( D3DRENDERSTATE_DITHERENABLE,dither ? true : false );
  253. }
  254. void gxScene::setAntialias( bool n ){
  255. if( n==antialias ) return;
  256. antialias=n;setRS( D3DRENDERSTATE_ANTIALIAS,antialias ? D3DANTIALIAS_SORTINDEPENDENT : D3DANTIALIAS_NONE );
  257. }
  258. void gxScene::setWireframe( bool n ){
  259. if( n==wireframe ) return;
  260. wireframe=n;setRS( D3DRENDERSTATE_FILLMODE,wireframe ? D3DFILL_WIREFRAME : D3DFILL_SOLID );
  261. }
  262. void gxScene::setFlippedTris( bool n ){
  263. if( n==flipped ) return;
  264. flipped=n;setTriCull();
  265. }
  266. void gxScene::setAmbient( const float rgb[] ){
  267. int n=(int(rgb[0]*255.0f)<<16)|(int(rgb[1]*255.0f)<<8)|int(rgb[2]*255.0f);
  268. ambient=n;setAmbient();
  269. }
  270. void gxScene::setAmbient2( const float rgb[] ){
  271. int n=(int(rgb[0]*255.0f)<<16)|(int(rgb[1]*255.0f)<<8)|int(rgb[2]*255.0f);
  272. ambient2=n;setAmbient();
  273. }
  274. void gxScene::setViewport( int x,int y,int w,int h ){
  275. if( x==viewport.dwX && y==viewport.dwY && w==viewport.dwWidth && h==viewport.dwHeight ) return;
  276. viewport.dwX=x;viewport.dwY=y;viewport.dwWidth=w;viewport.dwHeight=h;
  277. dir3dDev->SetViewport( &viewport );
  278. }
  279. void gxScene::setOrthoProj( float nr,float fr,float w,float h ){
  280. if( ortho_proj && nr==frustum_nr && fr==frustum_fr && w==frustum_w && h==frustum_h ) return;
  281. frustum_nr=nr;frustum_fr=fr;frustum_w=w;frustum_h=h;ortho_proj=true;
  282. float W=2/w;
  283. float H=2/h;
  284. float Q=1/(fr-nr);
  285. projmatrix._11=W;
  286. projmatrix._22=H;
  287. projmatrix._33=Q;
  288. projmatrix._34=0;
  289. projmatrix._43=-Q*nr;
  290. projmatrix._44=1;
  291. dir3dDev->SetTransform( D3DTRANSFORMSTATE_PROJECTION,&projmatrix );
  292. }
  293. void gxScene::setPerspProj( float nr,float fr,float w,float h ){
  294. if( !ortho_proj && nr==frustum_nr && fr==frustum_fr && w==frustum_w && h==frustum_h ) return;
  295. frustum_nr=nr;frustum_fr=fr;frustum_w=w;frustum_h=h;ortho_proj=false;
  296. float W=2*nr/w;
  297. float H=2*nr/h;
  298. float Q=fr/(fr-nr);
  299. projmatrix._11=W;
  300. projmatrix._22=H;
  301. projmatrix._33=Q;
  302. projmatrix._34=1;
  303. projmatrix._43=-Q*nr;
  304. projmatrix._44=0;
  305. dir3dDev->SetTransform( D3DTRANSFORMSTATE_PROJECTION,&projmatrix );
  306. }
  307. void gxScene::setFogColor( const float rgb[3] ){
  308. int n=(int(rgb[0]*255.0f)<<16)|(int(rgb[1]*255.0f)<<8)|int(rgb[2]*255.0f);
  309. if( n==fogcolor ) return;
  310. fogcolor=n;setRS( D3DRENDERSTATE_FOGCOLOR,fogcolor );
  311. }
  312. void gxScene::setFogRange( float nr,float fr ){
  313. if( nr==fogrange_nr && fr==fogrange_fr ) return;
  314. fogrange_nr=nr;fogrange_fr=fr;
  315. setRS( D3DRENDERSTATE_FOGSTART,*(DWORD*)&fogrange_nr );
  316. setRS( D3DRENDERSTATE_FOGEND,*(DWORD*)&fogrange_fr );
  317. }
  318. void gxScene::setFogMode( int n ){
  319. if( n==fogmode ) return;
  320. fogmode=n;setFogMode();
  321. }
  322. void gxScene::setZMode( int n ){
  323. if( n==zmode ) return;
  324. zmode=n;setZMode();
  325. }
  326. void gxScene::setViewMatrix( const Matrix *m ){
  327. if( m ){
  328. memcpy( &viewmatrix._11,m->elements[0],12 );
  329. memcpy( &viewmatrix._21,m->elements[1],12 );
  330. memcpy( &viewmatrix._31,m->elements[2],12 );
  331. memcpy( &viewmatrix._41,m->elements[3],12 );
  332. inv_viewmatrix._11=viewmatrix._11;inv_viewmatrix._21=viewmatrix._12;inv_viewmatrix._31=viewmatrix._13;
  333. inv_viewmatrix._12=viewmatrix._21;inv_viewmatrix._22=viewmatrix._22;inv_viewmatrix._32=viewmatrix._23;
  334. inv_viewmatrix._13=viewmatrix._31;inv_viewmatrix._23=viewmatrix._32;inv_viewmatrix._33=viewmatrix._33;
  335. inv_viewmatrix._44=viewmatrix._44;
  336. }else{
  337. viewmatrix=inv_viewmatrix=nullmatrix;
  338. }
  339. dir3dDev->SetTransform( D3DTRANSFORMSTATE_VIEW,&viewmatrix );
  340. }
  341. void gxScene::setWorldMatrix( const Matrix *m ){
  342. if( m ){
  343. memcpy( &worldmatrix._11,m->elements[0],12 );
  344. memcpy( &worldmatrix._21,m->elements[1],12 );
  345. memcpy( &worldmatrix._31,m->elements[2],12 );
  346. memcpy( &worldmatrix._41,m->elements[3],12 );
  347. }else worldmatrix=nullmatrix;
  348. dir3dDev->SetTransform( D3DTRANSFORMSTATE_WORLD,&worldmatrix );
  349. }
  350. void gxScene::setRenderState( const RenderState &rs ){
  351. bool setmat=false;
  352. if( memcmp( rs.color,&material.diffuse.r,12 ) ){
  353. memcpy( &material.diffuse.r,rs.color,12 );
  354. memcpy( &material.ambient.r,rs.color,12 );
  355. setmat=true;
  356. }
  357. if( rs.alpha!=material.diffuse.a ){
  358. material.diffuse.a=rs.alpha;
  359. if( rs.fx&FX_ALPHATEST ){
  360. int alpharef=(rs.fx&FX_VERTEXALPHA)?0:128*rs.alpha;
  361. setRS( D3DRENDERSTATE_ALPHAREF,alpharef );
  362. }
  363. setmat=true;
  364. }
  365. if( rs.shininess!=shininess ){
  366. shininess=rs.shininess;
  367. float t=shininess>0 ? (shininess<1 ? shininess : 1) : 0;
  368. material.specular.r=material.specular.g=material.specular.b=t;
  369. material.power=shininess*128;
  370. setRS( D3DRENDERSTATE_SPECULARENABLE,shininess>0 ? true : false );
  371. setmat=true;
  372. }
  373. if( rs.blend!=blend ){
  374. blend=rs.blend;
  375. switch( blend ){
  376. case BLEND_REPLACE:
  377. setRS( D3DRENDERSTATE_ALPHABLENDENABLE,false );
  378. break;
  379. case BLEND_ALPHA:
  380. setRS( D3DRENDERSTATE_ALPHABLENDENABLE,true );
  381. setRS( D3DRENDERSTATE_SRCBLEND,D3DBLEND_SRCALPHA );
  382. setRS( D3DRENDERSTATE_DESTBLEND,D3DBLEND_INVSRCALPHA );
  383. break;
  384. case BLEND_MULTIPLY:
  385. setRS( D3DRENDERSTATE_ALPHABLENDENABLE,true );
  386. setRS( D3DRENDERSTATE_SRCBLEND,D3DBLEND_DESTCOLOR );
  387. setRS( D3DRENDERSTATE_DESTBLEND,D3DBLEND_ZERO );
  388. break;
  389. case BLEND_ADD:
  390. setRS( D3DRENDERSTATE_ALPHABLENDENABLE,true );
  391. setRS( D3DRENDERSTATE_SRCBLEND,D3DBLEND_SRCALPHA );
  392. setRS( D3DRENDERSTATE_DESTBLEND,D3DBLEND_ONE );
  393. break;
  394. }
  395. }
  396. if( rs.fx!=fx ){
  397. int t=rs.fx^fx;fx=rs.fx;
  398. if( t & (FX_FULLBRIGHT|FX_CONDLIGHT) ){
  399. setLights();
  400. setAmbient();
  401. }
  402. if( t&FX_VERTEXCOLOR ){
  403. setRS( D3DRENDERSTATE_COLORVERTEX,fx & FX_VERTEXCOLOR ? true : false );
  404. }
  405. if( t&FX_FLATSHADED ){
  406. setRS( D3DRENDERSTATE_SHADEMODE,fx & FX_FLATSHADED ? D3DSHADE_FLAT : D3DSHADE_GOURAUD );
  407. }
  408. if( t&FX_NOFOG ){
  409. setFogMode();
  410. }
  411. if( t&FX_DOUBLESIDED ){
  412. setTriCull();
  413. }
  414. if( t&FX_EMISSIVE ){
  415. //Q3 Hack!
  416. int n=fx & FX_EMISSIVE;
  417. setRS( D3DRENDERSTATE_DIFFUSEMATERIALSOURCE,n ? D3DMCS_MATERIAL : D3DMCS_COLOR1 );
  418. setRS( D3DRENDERSTATE_AMBIENTMATERIALSOURCE,n ? D3DMCS_MATERIAL : D3DMCS_COLOR1 );
  419. setRS( D3DRENDERSTATE_EMISSIVEMATERIALSOURCE,n ? D3DMCS_COLOR1 : D3DMCS_MATERIAL );
  420. setRS( D3DRENDERSTATE_COLORVERTEX,n ? true : false );
  421. }
  422. if( t&FX_ALPHATEST ){
  423. if( fx&FX_ALPHATEST ){
  424. int alpharef=(rs.fx&FX_VERTEXALPHA)?0:128*rs.alpha;
  425. setRS( D3DRENDERSTATE_ALPHAREF,alpharef );
  426. }
  427. setRS( D3DRENDERSTATE_ALPHATESTENABLE,fx & FX_ALPHATEST ? true : false );
  428. }
  429. }
  430. if( setmat ){
  431. dir3dDev->SetMaterial( &material );
  432. }
  433. n_texs=0;
  434. TexState *hw=texstate;
  435. for( int k=0;k<MAX_TEXTURES;++k ){
  436. const RenderState::TexState &ts=rs.tex_states[k];
  437. if( !ts.canvas || !ts.blend ) continue;
  438. bool settex=false;
  439. ts.canvas->getTexSurface(); //force mipmap rebuild
  440. if( ts.canvas!=hw->canvas ){ hw->canvas=ts.canvas;settex=true; }
  441. if( ts.blend!=hw->blend ){ hw->blend=ts.blend;settex=true; }
  442. if( ts.flags!=hw->flags ){ hw->flags=ts.flags;settex=true; }
  443. if( ts.matrix || hw->mat_valid ){
  444. if( ts.matrix ){
  445. memcpy( &hw->matrix._11,ts.matrix->elements[0],12 );
  446. memcpy( &hw->matrix._21,ts.matrix->elements[1],12 );
  447. memcpy( &hw->matrix._31,ts.matrix->elements[2],12 );
  448. memcpy( &hw->matrix._41,ts.matrix->elements[3],12 );
  449. hw->mat_valid=true;
  450. }else{
  451. hw->mat_valid=false;
  452. }
  453. settex=true;
  454. }
  455. if( settex && n_texs<tex_stages ){
  456. setTexState( n_texs,*hw,true );
  457. }
  458. ++hw;++n_texs;
  459. }
  460. if( n_texs<tex_stages && hw->canvas ){
  461. hw->canvas=0;
  462. setTSS( n_texs,D3DTSS_COLOROP,D3DTOP_DISABLE );
  463. setTSS( n_texs,D3DTSS_ALPHAOP,D3DTOP_DISABLE );
  464. dir3dDev->SetTexture( n_texs,0 );
  465. }
  466. }
  467. bool gxScene::begin( const vector<gxLight*> &lights ){
  468. if( dir3dDev->BeginScene()!=D3D_OK ) return false;
  469. //clear textures!
  470. int n;
  471. for( n=0;n<tex_stages;++n ){
  472. texstate[n].canvas=0;
  473. setTSS( n,D3DTSS_COLOROP,D3DTOP_DISABLE );
  474. setTSS( n,D3DTSS_ALPHAOP,D3DTOP_DISABLE );
  475. dir3dDev->SetTexture( n,0 );
  476. }
  477. //set light states
  478. _curLights.clear();
  479. for( n=0;n<8;++n ){
  480. if( n<lights.size() ){
  481. _curLights.push_back( lights[n] );
  482. dir3dDev->SetLight( n,&_curLights[n]->d3d_light );
  483. }else{
  484. dir3dDev->LightEnable( n,false );
  485. }
  486. }
  487. setLights();
  488. return true;
  489. }
  490. void gxScene::clear( const float rgb[3],float alpha,float z,bool clear_argb,bool clear_z ){
  491. if( !clear_argb && !clear_z ) return;
  492. int flags=(clear_argb ? D3DCLEAR_TARGET : 0) | (clear_z ? D3DCLEAR_ZBUFFER : 0);
  493. unsigned argb=(int(alpha*255.0f)<<24)|(int(rgb[0]*255.0f)<<16)|(int(rgb[1]*255.0f)<<8)|int(rgb[2]*255.0f);
  494. dir3dDev->Clear( 0,0,flags,argb,z,0 );
  495. }
  496. void gxScene::render( gxMesh *m,int first_vert,int vert_cnt,int first_tri,int tri_cnt ){
  497. m->render( first_vert,vert_cnt,first_tri,tri_cnt );
  498. tris_drawn+=tri_cnt;
  499. if( n_texs<=tex_stages ) return;
  500. setTSS( 0,D3DTSS_COLOROP,D3DTOP_SELECTARG1 );
  501. setTSS( 0,D3DTSS_ALPHAOP,D3DTOP_SELECTARG1 );
  502. if( tex_stages>1 ){
  503. setTSS( 1,D3DTSS_COLOROP,D3DTOP_DISABLE );
  504. setTSS( 1,D3DTSS_ALPHAOP,D3DTOP_DISABLE );
  505. }
  506. setRS( D3DRENDERSTATE_LIGHTING,false );
  507. setRS( D3DRENDERSTATE_ALPHABLENDENABLE,true );
  508. for( int k=tex_stages;k<n_texs;++k ){
  509. const TexState &state=texstate[k];
  510. switch( state.blend ){
  511. case BLEND_ALPHA:
  512. setRS( D3DRENDERSTATE_SRCBLEND,D3DBLEND_SRCALPHA );
  513. setRS( D3DRENDERSTATE_DESTBLEND,D3DBLEND_INVSRCALPHA );
  514. break;
  515. case BLEND_MULTIPLY:case BLEND_DOT3:
  516. setRS( D3DRENDERSTATE_SRCBLEND,D3DBLEND_DESTCOLOR );
  517. setRS( D3DRENDERSTATE_DESTBLEND,D3DBLEND_ZERO );
  518. break;
  519. case BLEND_ADD:
  520. setRS( D3DRENDERSTATE_SRCBLEND,D3DBLEND_ONE );
  521. setRS( D3DRENDERSTATE_DESTBLEND,D3DBLEND_ONE );
  522. break;
  523. }
  524. setTexState( 0,state,false );
  525. m->render( first_vert,vert_cnt,first_tri,tri_cnt );
  526. tris_drawn+=tri_cnt;
  527. }
  528. setRS( D3DRENDERSTATE_ALPHABLENDENABLE,false );
  529. setRS( D3DRENDERSTATE_LIGHTING,true );
  530. if( tex_stages>1 ) setTexState( 1,texstate[1],true );
  531. setTexState( 0,texstate[0],true );
  532. }
  533. void gxScene::end(){
  534. dir3dDev->EndScene();
  535. RECT r={ viewport.dwX,viewport.dwY,viewport.dwX+viewport.dwWidth,viewport.dwY+viewport.dwHeight };
  536. target->damage( r );
  537. }
  538. gxLight *gxScene::createLight( int flags ){
  539. gxLight *l=d_new gxLight( this,flags );
  540. _allLights.insert(l);
  541. return l;
  542. }
  543. void gxScene::freeLight( gxLight *l ){
  544. _allLights.erase(l);
  545. }
  546. int gxScene::getTrianglesDrawn()const{
  547. return tris_drawn;
  548. }