30 void Print(
const char* msg, ...);
35 static bool surface_has_tangent_data =
false;
36 static Light* main_light;
37 static Light* back_light;
38 static D3DXMATRIX matrixWorld;
39 static D3DXMATRIX matrixView;
40 static D3DXMATRIX matrixProj;
41 static D3DXMATRIX matrixWorldInverse;
46 #define RELEASE(x) if (x) { x->Release(); x=NULL; }
50 #define F2DW(x) (*(DWORD*)(&x))
54 #define DW2I(x) (*(int*)(&x))
59 typedef HRESULT (WINAPI *
LPDDCE)(GUID FAR *, LPVOID *, REFIID , IUnknown FAR *);
61 static D3DMATRIX identity_matrix = {
62 FLOAT(1.0), FLOAT(0.0), FLOAT(0.0), FLOAT(0.0),
63 FLOAT(0.0), FLOAT(1.0), FLOAT(0.0), FLOAT(0.0),
64 FLOAT(0.0), FLOAT(0.0), FLOAT(1.0), FLOAT(0.0),
65 FLOAT(0.0), FLOAT(0.0), FLOAT(0.0), FLOAT(1.0)
112 static int d3dstate_table[] = {
121 D3DRS_SPECULARENABLE,
130 static const int NUM_SCREEN_VERTS = 1024;
131 static const int NUM_SCREEN_INDICES = NUM_SCREEN_VERTS * 2;
165 { 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
166 { 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 },
167 { 0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
168 { 0, 32, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1 },
169 { 0, 40, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 2 },
170 { 0, 52, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BINORMAL, 3 },
186 D3DFVF_TEXCOORDSIZE2(0);
200 D3DFVF_TEXCOORDSIZE2(0);
242 static VideoDX9* video_dx9_instance = 0;
245 : width(0), height(0), bpp(0), hwnd(window), surface(0),
246 d3d(0), d3ddevice(0), device_lost(false), fade(0),
247 zdepth(0), gamma(128), num_verts(0), first_vert(0),
248 current_texture(0), screen_vbuf(0), screen_ibuf(0),
249 font_verts(0), font_indices(0), font_nverts(0),
250 nlights(0), use_material(0), d3dx_font(0),
251 segment_material(0), strategy(0), passes(0),
252 screen_line_verts(0), line_verts(0),
253 vertex_declaration(0),
254 magic_fx(0), magic_fx_code(0), magic_fx_code_len(0)
256 video_dx9_instance =
this;
258 Print(
"\n********************************\n");
259 Print(
"* Direct 3D version 9 *\n");
260 Print(
"********************************\n\n");
263 HRESULT
err = E_OUTOFMEMORY;
265 d3d = Direct3DCreate9(D3D_SDK_VERSION);
268 if (d3d && dx9enum) {
285 VideoDX9Error(
"(ctor) could not enumerate dx9 properties", err);
305 Print(
"\nD3DPRESENT_PARAMETERS:\n");
306 Print(
" BackBufferWidth: %d\n", d3dparams.BackBufferWidth);
307 Print(
" BackBufferHeight: %d\n", d3dparams.BackBufferHeight);
308 Print(
" BackBufferCount: %d\n", d3dparams.BackBufferCount);
310 Print(
" Multisample Type: %d\n", d3dparams.MultiSampleType);
311 Print(
" Multisample Qual: %d\n", d3dparams.MultiSampleQuality);
312 Print(
" Swap Effect: %d\n", d3dparams.SwapEffect);
313 Print(
" Device Window: %08X\n", d3dparams.hDeviceWindow);
314 Print(
" Windowed: %s\n", d3dparams.Windowed ?
"true" :
"false");
315 Print(
" Enable Depth/Stencil: %s\n", d3dparams.EnableAutoDepthStencil ?
"true" :
"false");
317 Print(
" Flags: %08X\n", d3dparams.Flags);
318 Print(
" Fullscreen Refresh: %d Hz\n", d3dparams.FullScreen_RefreshRateInHz);
320 switch (d3dparams.PresentationInterval) {
321 case D3DPRESENT_INTERVAL_IMMEDIATE:
322 Print(
" Present Interval: IMMEDIATE\n");
325 case D3DPRESENT_INTERVAL_DEFAULT:
326 Print(
" Present Interval: DEFAULT\n");
329 case D3DPRESENT_INTERVAL_ONE:
330 Print(
" Present Interval: ONE\n");
333 case D3DPRESENT_INTERVAL_TWO:
334 Print(
" Present Interval: TWO\n");
337 case D3DPRESENT_INTERVAL_THREE:
338 Print(
" Present Interval: THREE\n");
341 case D3DPRESENT_INTERVAL_FOUR:
342 Print(
" Present Interval: FOUR\n");
346 Print(
" Present Interval: Unknown (%d)\n", d3dparams.PresentationInterval);
353 Print(
" Creating Video Device for HWND = %08x\n", window);
355 err = d3d->CreateDevice(D3DADAPTER_DEFAULT,
358 D3DCREATE_HARDWARE_VERTEXPROCESSING,
390 ZeroMemory(&rect,
sizeof(rect));
393 texcache =
new(__FILE__,__LINE__)
TexCacheDX9(
this);
400 Print(
" Available Texture Memory: %d MB\n\n", vmf);
403 if (CreateBuffers()) {
404 d3ddevice->SetRenderState(D3DRS_ALPHATESTENABLE,
false);
405 d3ddevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
407 d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
408 d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
409 d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
410 d3ddevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
411 d3ddevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
412 d3ddevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
417 ZeroMemory(font_name, 64);
430 if (!texcache->
count) {
435 delete environment_cube;
443 delete [] magic_fx_code;
445 Print(
" VideoDX9: shutdown\n");
446 video_dx9_instance = 0;
452 if (video_dx9_instance)
453 return video_dx9_instance->d3ddevice;
470 if (adapter_index < 0 || adapter_index >= dx9enum->
NumAdapters()) {
471 ::Print(
"WARNING: VideoDX9 could not select adapter %d (max=%d)\n",
479 d3dparams.Windowed = video_settings.
IsWindowed();
480 d3dparams.BackBufferCount = 2;
481 d3dparams.MultiSampleType = D3DMULTISAMPLE_NONE;
482 d3dparams.MultiSampleQuality = 0;
483 d3dparams.SwapEffect = D3DSWAPEFFECT_DISCARD;
485 d3dparams.hDeviceWindow = hwnd;
488 d3dparams.Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;
495 d3dparams.Flags |= D3DPRESENTFLAG_DEVICECLIP;
498 d3dparams.BackBufferWidth = video_settings.
window_width;
501 d3dparams.FullScreen_RefreshRateInHz = 0;
502 d3dparams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
505 d3dparams.BackBufferWidth = video_settings.
GetWidth();
506 d3dparams.BackBufferHeight = video_settings.
GetHeight();
508 d3dparams.FullScreen_RefreshRateInHz = video_settings.
GetRefreshRate();
509 d3dparams.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
530 if (vs != &video_settings)
554 bool using_x_font = (d3dx_font != 0);
561 HRESULT hr = d3ddevice->Reset(&d3dparams);
570 IDirect3DSurface9* back_buffer;
571 d3ddevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &back_buffer);
572 back_buffer->GetDesc(&back_buffer_desc);
584 if (CreateBuffers()) {
585 d3ddevice->SetRenderState(D3DRS_ALPHATESTENABLE,
false);
586 d3ddevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
588 d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
589 d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
590 d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
591 d3ddevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
592 d3ddevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
593 d3ddevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
597 hr = d3ddevice->GetViewport(&view);
602 rect.
h = view.Height;
606 UseXFont(font_name, font_size, font_bold, font_ital);
617 VideoDX9::CreateBuffers()
621 UINT index_size =
sizeof(WORD);
629 D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY);
636 D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY);
643 LPD3DXBUFFER code_buffer = 0;
648 &vertex_declaration);
651 if (video_settings.
use_effects && !magic_fx_code) {
653 ::fopen_s(&f,
"magic.fx",
"rb");
656 ::fseek(f, 0, SEEK_END);
657 magic_fx_code_len = ftell(f);
658 ::fseek(f, 0, SEEK_SET);
660 magic_fx_code =
new(__FILE__,__LINE__) BYTE[magic_fx_code_len+1];
662 ::fread(magic_fx_code, magic_fx_code_len, 1, f);
663 magic_fx_code[magic_fx_code_len] = 0;
666 magic_fx_code_len = loader->
LoadBuffer(
"magic.fx", magic_fx_code,
true,
true);
672 if (video_settings.
use_effects && magic_fx_code && magic_fx_code_len) {
673 hr = D3DXCreateEffect(d3ddevice,
681 ::Print(
"ERROR - Failed to compile 'magic.fx'\n");
682 ::Print((
const char*) code_buffer->GetBufferPointer());
689 return screen_vbuf && screen_ibuf;
693 VideoDX9::DestroyBuffers()
700 if (screen_line_verts) {
701 delete screen_line_verts;
702 screen_line_verts = 0;
716 delete [] font_verts;
721 delete [] font_indices;
741 result = d3ddevice->GetAvailableTextureMem();
753 return (
int) dev_info->
caps.MaxTextureWidth;
767 return (
int) dev_info->
caps.MaxTextureAspectRatio;
779 Print(
"VideoDX9::RecoverSurfaces()\n");
785 hr = d3ddevice->TestCooperativeLevel();
787 if (hr == D3DERR_DEVICELOST) {
790 Print(
"D3DERR_DEVICELOST\n");
794 hr = d3ddevice->TestCooperativeLevel();
795 }
while (hr == D3DERR_DEVICELOST);
798 if (hr == D3DERR_DEVICENOTRESET) {
799 if (
Reset(&video_settings))
804 Print(
"* Invalidating Texture Cache\n");
812 Print(
"* Recover Surfaces Complete.\n\n");
833 return (WORD) (65535.0 * fade * pow((
double)i/255.f, recip_gamma));
844 return logf(i/255.f)/logf(0.5f);
855 return logf(0.5f)/logf(i/255.f);
864 if (gamma != g || fade != f) {
872 for (UINT i = 0; i < 256; i++) {
875 gamma_ramp.red[i] = val;
876 gamma_ramp.green[i] = val;
877 gamma_ramp.blue[i] = val;
880 d3ddevice->SetGammaRamp(0, D3DSGR_NO_CALIBRATION, &gamma_ramp);
888 return SUCCEEDED(hr);
897 D3DMATRIX world_matrix;
899 hr = d3ddevice->SetTransform(D3DTS_WORLD, &world_matrix);
901 matrixWorld = world_matrix;
902 D3DXMatrixInverse(&matrixWorldInverse, 0, &matrixWorld);
905 return SUCCEEDED(hr);
915 err = d3ddevice->Clear(0,
917 D3DCLEAR_TARGET | D3DCLEAR_STENCIL | D3DCLEAR_ZBUFFER,
923 static int report = 10;
938 err = d3ddevice->Clear(0,
940 D3DCLEAR_STENCIL | D3DCLEAR_ZBUFFER,
946 static int report = 10;
962 HRESULT
err = d3ddevice->Present( NULL, NULL, NULL, NULL );
965 if (err == D3DERR_DEVICELOST) {
970 static int report = 10;
1009 if (texcache && tex)
1035 result._11 = (float) m.
elem[0][0];
1036 result._12 = (
float) m.
elem[1][0];
1037 result._13 = (float) m.
elem[2][0];
1040 result._21 = (
float) m.
elem[0][1];
1041 result._22 = (float) m.
elem[1][1];
1042 result._23 = (
float) m.
elem[2][1];
1045 result._31 = (float) m.
elem[0][2];
1046 result._32 = (
float) m.
elem[1][2];
1047 result._33 = (float) m.
elem[2][2];
1050 result._41 = (
float) p.
x;
1051 result._42 = (float) p.
y;
1052 result._43 = (
float) p.
z;
1059 result._11 = (float) m.
elem[0][0];
1060 result._12 = (
float) m.
elem[1][0];
1061 result._13 = (float) m.
elem[2][0];
1064 result._21 = (
float) m.
elem[0][1];
1065 result._22 = (float) m.
elem[1][1];
1066 result._23 = (
float) m.
elem[2][1];
1069 result._31 = (float) m.
elem[0][2];
1070 result._32 = (
float) m.
elem[1][2];
1071 result._33 = (float) m.
elem[2][2];
1083 CopyMemory(&result.Diffuse, &mtl.
Kd,
sizeof(D3DCOLORVALUE));
1084 CopyMemory(&result.Ambient, &mtl.
Ka,
sizeof(D3DCOLORVALUE));
1085 CopyMemory(&result.Specular, &mtl.
Ks,
sizeof(D3DCOLORVALUE));
1086 CopyMemory(&result.Emissive, &mtl.
Ke,
sizeof(D3DCOLORVALUE));
1088 result.Power = mtl.
power;
1098 HRESULT hr = E_FAIL;
1099 LPDIRECT3DSURFACE9 pSurf=NULL, pTempSurf=NULL;
1100 D3DSURFACE_DESC desc;
1105 hr = d3ddevice->GetDisplayMode(0, &dm);
1108 VideoDX9Error(
"VideoDX9::Capture - Can't get display mode!", hr);
1110 desc.Width = dm.Width;
1111 desc.Height = dm.Height;
1112 desc.Format = D3DFMT_A8R8G8B8;
1114 hr = d3ddevice->CreateOffscreenPlainSurface(
1123 VideoDX9Error(
"VideoDX9::Capture - Cannot create offscreen buffer 1", hr);
1127 hr = d3ddevice->GetFrontBufferData(0, pTempSurf);
1131 VideoDX9Error(
"VideoDX9::Capture - Can't get front buffer", hr);
1141 ::GetClientRect(hwnd, &srcRect);
1142 ::ClientToScreen(hwnd, (LPPOINT) &srcRect);
1143 srcRect.right += srcRect.left;
1144 srcRect.bottom += srcRect.top;
1146 desc.Width = srcRect.right - srcRect.left;
1147 desc.Height = srcRect.bottom - srcRect.top;
1148 desc.Format = D3DFMT_A8R8G8B8;
1153 hr = d3ddevice->CreateOffscreenPlainSurface(
1163 VideoDX9Error(
"VideoDX9::Capture - Cannot create offscreen buffer 2", hr);
1168 hr = d3ddevice->UpdateSurface(pTempSurf, &srcRect, pSurf, &pt);
1173 VideoDX9Error(
"VideoDX9::Capture - Cannot update surface", hr);
1182 D3DLOCKED_RECT lockedRect;
1183 hr = pTempSurf->LockRect(&lockedRect, NULL,
1184 D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK);
1193 DWORD* buffer =
new DWORD[desc.Width * desc.Height];
1194 BYTE* src = (BYTE*) lockedRect.pBits;
1195 BYTE* dst = (BYTE*) buffer;
1198 for (DWORD y = 0; y < desc.Height; y++) {
1201 for (DWORD x = 0; x < desc.Width; x++) {
1202 switch(desc.Format) {
1206 *dst++ = (BYTE) clr.
Red();
1207 *dst++ = (BYTE) clr.
Green();
1208 *dst++ = (BYTE) clr.
Blue();
1212 case D3DFMT_A8R8G8B8:
1213 case D3DFMT_X8R8G8B8:
1234 src += lockedRect.Pitch;
1244 return SUCCEEDED(hr);
1255 if (d3ddevice && (rect.
w < 1 || rect.
h < 1)) {
1257 HRESULT hr = d3ddevice->GetViewport(&view);
1258 if (SUCCEEDED(hr)) {
1261 rect.
w = view.Width;
1262 rect.
h = view.Height;
1283 if (!d3d || !d3ddevice)
1298 hr = d3ddevice->SetViewport(&view);
1306 if (d3dstate_table[i]) {
1307 d3ddevice->SetRenderState((D3DRENDERSTATETYPE) d3dstate_table[i], render_state[i]);
1311 d3ddevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
1344 D3DLIGHT9 d3d_light;
1345 ZeroMemory(&d3d_light,
sizeof(d3d_light));
1346 d3d_light.Type = (D3DLIGHTTYPE) light->
Type();
1349 d3d_light.Direction.x = (float) (-light->
Location().
x);
1350 d3d_light.Direction.y = (float) (-light->
Location().
y);
1351 d3d_light.Direction.z = (float) (-light->
Location().
z);
1353 if (d3d_light.Direction.x == 0 &&
1354 d3d_light.Direction.y == 0 &&
1355 d3d_light.Direction.z == 0) {
1357 d3d_light.Direction.y = -1;
1364 else if (!back_light) {
1369 d3d_light.Position.x = (float) ( light->
Location().
x);
1370 d3d_light.Position.y = (float) ( light->
Location().
y);
1371 d3d_light.Position.z = (float) ( light->
Location().
z);
1378 d3d_light.Diffuse.r = r;
1379 d3d_light.Diffuse.g = g;
1380 d3d_light.Diffuse.b = b;
1382 d3d_light.Specular.r = r;
1383 d3d_light.Specular.g = g;
1384 d3d_light.Specular.b = b;
1386 d3d_light.Range = light->
Intensity() * 10.0f;
1387 d3d_light.Attenuation0 = 0.1f;
1388 d3d_light.Attenuation1 = 0.7f;
1389 d3d_light.Attenuation2 = 0.0f;
1392 d3ddevice->SetLight(index, &d3d_light);
1393 d3ddevice->LightEnable(index, TRUE);
1398 while (nlights > index+1) {
1399 d3ddevice->LightEnable(--nlights, FALSE);
1402 nlights = index + 1;
1418 d3ddevice->SetTransform(D3DTS_VIEW, &m);
1430 if (d3ddevice && zfar > znear) {
1434 double width = (float) (rect.
w);
1435 double height = (float) (rect.
h);
1436 ZeroMemory(&m,
sizeof(m));
1443 double xscale = width / fov;
1444 double yscale = height / fov;
1446 double maxscale = xscale;
1447 if (yscale > xscale) maxscale = yscale;
1449 double xangle = atan(fov/2 * maxscale/xscale);
1451 w = (float) (2/tan(xangle));
1452 h = (float) (w * width/height);
1453 Q = zfar/(zfar - znear);
1467 m._11 = (float) (fov/width);
1468 m._22 = (float) (fov/height);
1469 m._33 = (float) (1/(zfar-znear));
1470 m._43 = (float) (znear/(znear-zfar));
1471 m._44 = (float) (1);
1478 d3ddevice->SetTransform(D3DTS_PROJECTION, &m);
1492 if (environment_cube && !faces) {
1493 delete environment_cube;
1494 environment_cube = 0;
1498 if (!environment_cube) {
1499 environment_cube =
new(__FILE__,__LINE__)
TexCubeDX9(
this);
1502 if (environment_cube) {
1504 for (
int i = 0; i < 6; i++)
1505 ok = ok && environment_cube->
LoadTexture(faces[i], i);
1520 if (render_state[state] == value || d3dstate_table[state] == 0) {
1521 render_state[state] = value;
1525 HRESULT hr = E_FAIL;
1529 DWORD wrap = D3DTADDRESS_CLAMP;
1532 wrap = D3DTADDRESS_WRAP;
1534 hr = d3ddevice->SetSamplerState(0, D3DSAMP_ADDRESSU, wrap);
1535 hr = d3ddevice->SetSamplerState(0, D3DSAMP_ADDRESSV, wrap);
1541 hr = d3ddevice->SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_EXP);
1542 hr = d3ddevice->SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_NONE);
1545 hr = d3ddevice->SetRenderState(D3DRS_FOGENABLE, value);
1549 else if (state ==
Z_BIAS) {
1551 FLOAT bias_scale = 1.0f;
1552 FLOAT depth_bias = (FLOAT) (
DW2I(value) / -10000.0);
1554 hr = d3ddevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS,
F2DW(bias_scale));
1555 hr = d3ddevice->SetRenderState(D3DRS_DEPTHBIAS,
F2DW(depth_bias));
1558 hr = d3ddevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0);
1559 hr = d3ddevice->SetRenderState(D3DRS_DEPTHBIAS, 0);
1565 hr = d3ddevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
1566 hr = d3ddevice->SetRenderState(D3DRS_ZENABLE, value);
1571 hr = d3ddevice->SetRenderState((D3DRENDERSTATETYPE) d3dstate_table[state], value);
1579 render_state[state] = value;
1588 if (blend_type == current_blend_state)
1591 switch (blend_type) {
1599 d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE,
false);
1603 d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE,
true);
1604 d3ddevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
1605 d3ddevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
1609 d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE,
true);
1610 d3ddevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
1611 d3ddevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
1615 current_blend_state = blend_type;
1634 static int frame_number = 1;
1635 static int report_errs = 100;
1645 err = d3ddevice->BeginScene();
1648 if (report_errs > 0) {
1657 current_blend_state = -1;
1673 err = d3ddevice->EndScene();
1687 static DWORD ColorModulate(DWORD a, DWORD b)
1689 float a0 = (float) ((a ) & 0xff)/255.0f;
1690 float a1 = (float) ((a>> 8) & 0xff)/255.0f;
1691 float a2 = (float) ((a>>16) & 0xff)/255.0f;
1692 float a3 = (float) ((a>>24) & 0xff)/255.0f;
1694 float b0 = (float) ((b ) & 0xff)/255.0f;
1695 float b1 = (float) ((b>> 8) & 0xff)/255.0f;
1696 float b2 = (float) ((b>>16) & 0xff)/255.0f;
1697 float b3 = (float) ((b>>24) & 0xff)/255.0f;
1699 return (DWORD) ((BYTE)(a3*b3*255.0f) << 24) |
1700 ((BYTE)(a2*b2*255.0f) << 16) |
1701 ((BYTE)(a1*b1*255.0f) << 8) |
1702 ((BYTE)(a0*b0*255.0f));
1708 VideoDX9::PopulateScreenVerts(
VertexSet* vset)
1710 if (!vset || !screen_vbuf)
1713 num_verts = vset->
nverts;
1720 for (
int i = 0; i < num_verts; i++) {
1724 v->
rhw = vset->
rw[i];
1728 v->
tu = vset->
tu[i];
1729 v->
tv = vset->
tv[i];
1738 Print(
" VideoDX9: could not lock screen vbuf for %d verts.\n", num_verts);
1747 bool result =
false;
1749 if (d3ddevice && polys && npolys > 0) {
1758 int nverts = vset->
nverts;
1759 bool luminous =
false;
1760 bool detail =
false;
1764 WORD* indices =
new(__FILE__,__LINE__) WORD[npolys*6];
1770 if (vset->
tu1 != 0) {
1776 for (
int i = 0; i < nverts; i++) {
1777 v->
x = vset->
loc[i].
x;
1778 v->
y = vset->
loc[i].
y;
1779 v->
z = vset->
loc[i].
z;
1784 v->
tu = vset->
tu[i];
1785 v->
tv = vset->
tv[i];
1793 else if (luminous) {
1799 for (
int i = 0; i < nverts; i++) {
1800 v->
x = vset->
loc[i].
x;
1801 v->
y = vset->
loc[i].
y;
1802 v->
z = vset->
loc[i].
z;
1806 v->
tu = vset->
tu[i];
1807 v->
tv = vset->
tv[i];
1819 for (
int i = 0; i < nverts; i++) {
1820 v->
x = vset->
loc[i].
x;
1821 v->
y = vset->
loc[i].
y;
1822 v->
z = vset->
loc[i].
z;
1828 v->
tu = vset->
tu[i];
1829 v->
tv = vset->
tv[i];
1835 if (verts && indices) {
1836 HRESULT hr = E_FAIL;
1839 int num_indices = 0;
1845 for (
int i = 0; i < npolys; i++) {
1855 else if (p->
nverts == 4) {
1871 hr = d3ddevice->SetTransform(D3DTS_WORLD, &identity_matrix);
1872 hr = d3ddevice->SetVertexShader(NULL);
1873 hr = d3ddevice->SetFVF(fvf);
1877 IDirect3DTexture9* texture = 0;
1883 if (current_texture != texture) {
1884 hr = d3ddevice->SetTexture(0, texture);
1885 current_texture = texture;
1890 hr = d3ddevice->SetTexture(1, texture);
1893 if (mtl && !luminous) {
1894 D3DMATERIAL9 d3dmtl;
1897 hr = d3ddevice->SetMaterial(&d3dmtl);
1898 hr = d3ddevice->SetRenderState(D3DRS_AMBIENT, ambient.
Value());
1906 d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
1907 d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
1908 d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
1909 d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
1910 d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
1911 d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
1913 d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
1916 hr = d3ddevice->DrawIndexedPrimitiveUP(
1927 static int report = 10;
1935 if (SUCCEEDED(hr)) {
1951 bool result =
false;
1952 HRESULT hr = E_FAIL;
1954 if (d3ddevice && polys && npolys > 0 && screen_vbuf && screen_ibuf) {
1962 int num_indices = 0;
1966 for (
int i = 0; i < npolys; i++) {
1967 Poly* p = polys + i;
1974 else if (p->
nverts == 4) {
1980 WORD* screen_indices = screen_ibuf->
Lock(num_indices);
1983 if (!screen_indices) {
1984 Print(
" VideoDX9: could not lock screen ibuf for %d indices.\n", num_indices);
1989 WORD* s = screen_indices;
1992 for (
int i = 0; i < npolys; i++) {
1994 *s++ = p->
verts[0] + first_vert;
1995 *s++ = p->
verts[1] + first_vert;
1996 *s++ = p->
verts[2] + first_vert;
1998 else if (p->
nverts == 4) {
1999 *s++ = p->
verts[0] + first_vert;
2000 *s++ = p->
verts[1] + first_vert;
2001 *s++ = p->
verts[2] + first_vert;
2003 *s++ = p->
verts[0] + first_vert;
2004 *s++ = p->
verts[2] + first_vert;
2005 *s++ = p->
verts[3] + first_vert;
2020 d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
2021 d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
2022 d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
2023 d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
2024 d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
2025 d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
2027 d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
2031 IDirect3DTexture9* texture = 0;
2037 if (current_texture != texture) {
2038 hr = d3ddevice->SetTexture(0, texture);
2039 current_texture = texture;
2044 hr = d3ddevice->SetVertexShader(NULL);
2047 hr = d3ddevice->DrawIndexedPrimitive(
2056 static int report = 10;
2075 bool result =
false;
2076 HRESULT hr = E_FAIL;
2078 if (d3ddevice && s && s->
GetModel()) {
2083 D3DMATRIX world_matrix;
2085 d3ddevice->SetTransform(D3DTS_WORLD, &world_matrix);
2086 matrixWorld = world_matrix;
2087 D3DXMatrixInverse(&matrixWorldInverse, 0, &matrixWorld);
2090 while (++surf_iter) {
2096 if (PrepareSurface(surf)) {
2104 while (++seg_iter) {
2108 if (mtl && (blend_modes & mtl->
blend)) {
2109 result = result && DrawSegment(segment);
2116 surface_has_tangent_data =
false;
2122 VideoDX9::DrawSegment(
Segment* segment)
2124 bool result =
false;
2125 bool detail =
false;
2126 bool luminous =
false;
2127 HRESULT hr = E_FAIL;
2142 d3ddevice->SetRenderState(D3DRS_AMBIENT, ambient.
Value());
2154 hr = d3ddevice->SetVertexShader(NULL);
2158 else if (luminous) {
2159 hr = d3ddevice->SetVertexShader(NULL);
2163 else if (surface_has_tangent_data && vertex_declaration) {
2164 hr = d3ddevice->SetVertexDeclaration(vertex_declaration);
2165 hr = d3ddevice->SetVertexShader(NULL);
2169 hr = d3ddevice->SetVertexShader(NULL);
2174 PrepareMaterial(mtl);
2177 for (
int i = 0; i < segment->
npolys; i++) {
2182 else if (luminous) {
2183 PrepareMaterial(mtl);
2189 for (
int pass = 0; pass < passes; pass++) {
2192 hr = d3ddevice->DrawIndexedPrimitive(
2201 d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
2205 PrepareMaterial(mtl);
2212 DWORD vs_version = 0;
2213 DWORD ps_version = 0;
2214 bool shaders_ok =
false;
2219 vs_version = video_settings.
enable_vs ? dev_info->
caps.VertexShaderVersion : 0;
2220 ps_version = video_settings.
enable_ps ? dev_info->
caps.PixelShaderVersion : 0;
2222 if (vs_version >= D3DVS_VERSION(1,1))
2226 if (surface_has_tangent_data && vertex_declaration) {
2227 hr = d3ddevice->SetVertexShader(NULL);
2228 hr = d3ddevice->SetVertexDeclaration(vertex_declaration);
2232 hr = d3ddevice->SetVertexShader(NULL);
2240 bool do_pix = will_bump && render_state[
LIGHTING_PASS] == 0;
2241 bool do_bump = will_bump && render_state[
LIGHTING_PASS] > 0;
2243 D3DXMATRIX matrixWVP = matrixWorld * matrixView * matrixProj;
2245 D3DXVECTOR4 eyePos( (
float) camera->Pos().x, (float) camera->Pos().y, (float) camera->Pos().z, 1.0f);
2248 D3DXVec4Transform(&eyeObj, &eyePos, &matrixWorldInverse);
2250 D3DXVECTOR4 lightPos(100.0f, 100.0f, 100.0f, 1.0f);
2251 D3DXVECTOR4 lightColor(1,1,1,1);
2252 D3DXVECTOR4 ambientColor(0,0,0,1);
2254 ambientColor.x = ambient.
fRed();
2255 ambientColor.y = ambient.
fGreen();
2256 ambientColor.z = ambient.
fBlue();
2259 lightPos.x = (float) main_light->
Location().
x;
2260 lightPos.y = (float) main_light->
Location().
y;
2261 lightPos.z = (float) main_light->
Location().
z;
2264 D3DXVec4Transform(&lightPos, &lightPos, &matrixWorldInverse);
2269 lightColor.w = 1.0f;
2273 lightPos.x = (float) back_light->
Location().
x;
2274 lightPos.y = (float) back_light->
Location().
y;
2275 lightPos.z = (float) back_light->
Location().
z;
2280 lightColor.w = 1.0f;
2283 D3DXVECTOR4 lightDir = D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f) - lightPos;
2284 D3DXVec4Normalize(&lightDir, &lightDir);
2286 magic_fx->SetMatrix(
"wvp", &matrixWVP);
2287 magic_fx->SetMatrix(
"world", &matrixWorld);
2288 magic_fx->SetMatrix(
"view", &matrixView);
2289 magic_fx->SetMatrix(
"proj", &matrixProj);
2290 magic_fx->SetMatrix(
"worldInv", &matrixWorldInverse);
2292 magic_fx->SetVector(
"light1Pos", &lightPos);
2293 magic_fx->SetVector(
"light1Dir", &lightDir);
2294 magic_fx->SetVector(
"light1Color", &lightColor);
2295 magic_fx->SetVector(
"ambientColor", &ambientColor);
2296 magic_fx->SetVector(
"eyeObj", &eyeObj);
2298 FLOAT base_bias = (FLOAT) (
DW2I(render_state[
Z_BIAS]) / -10000.0);
2299 magic_fx->SetFloat(
"bias", base_bias + video_settings.
depth_bias);
2304 mtl->
Ks = mtl->
Ks * 0.3;
2306 magic_fx->SetValue(
"Ka", &mtl->
Ka,
sizeof(
ColorValue));
2307 magic_fx->SetValue(
"Kd", &mtl->
Kd,
sizeof(
ColorValue));
2308 magic_fx->SetValue(
"Ke", &mtl->
Ke,
sizeof(
ColorValue));
2309 magic_fx->SetValue(
"Ks", &mtl->
Ks,
sizeof(
ColorValue));
2310 magic_fx->SetFloat(
"Ns", mtl->
power);
2317 magic_fx->SetTexture(
"tex_d", texture);
2319 magic_fx->SetTexture(
"tex_d", 0);
2324 magic_fx->SetTexture(
"tex_e", texture);
2326 magic_fx->SetTexture(
"tex_e", 0);
2331 magic_fx->SetTexture(
"tex_s", texture);
2333 magic_fx->SetTexture(
"tex_s", 0);
2338 magic_fx->SetTexture(
"tex_n", texture);
2342 magic_fx->SetTexture(
"tex_x", texture);
2344 magic_fx->SetTexture(
"tex_x", 0);
2348 D3DXHANDLE hnd_shader = 0;
2351 if (!strcmp(mtl_shader,
"null"))
2354 hnd_shader = magic_fx->GetTechniqueByName(mtl_shader);
2358 hr = magic_fx->SetTechnique(hnd_shader);
2363 if (ps_version >= D3DPS_VERSION(2,0))
2364 hr = magic_fx->SetTechnique(
"BumpSpecMapPix");
2366 hr = magic_fx->SetTechnique(
"BumpSpecMap");
2367 }
else if (mtl->
tex_emissive && render_state[LIGHTING_PASS] == 0) {
2368 if (ps_version >= D3DPS_VERSION(2,0))
2369 hr = magic_fx->SetTechnique(
"EmissiveSpecMapPix");
2371 hr = magic_fx->SetTechnique(
"EmissiveSpecularTexture");
2373 if (ps_version >= D3DPS_VERSION(2,0))
2374 hr = magic_fx->SetTechnique(
"SpecMapPix");
2376 hr = magic_fx->SetTechnique(
"SpecularTexture");
2380 if (ps_version >= D3DPS_VERSION(2,0))
2381 hr = magic_fx->SetTechnique(
"BumpMapPix");
2383 hr = magic_fx->SetTechnique(
"BumpMap");
2384 }
else if (mtl->
tex_emissive && render_state[LIGHTING_PASS] == 0) {
2385 if (ps_version >= D3DPS_VERSION(2,0))
2386 hr = magic_fx->SetTechnique(
"EmissivePix");
2388 hr = magic_fx->SetTechnique(
"EmissiveTexture");
2390 if (ps_version >= D3DPS_VERSION(2,0))
2391 hr = magic_fx->SetTechnique(
"SimplePix");
2393 hr = magic_fx->SetTechnique(
"SimpleTexture");
2400 if (mtl->
tex_emissive && render_state[LIGHTING_PASS] == 0) {
2401 hr = magic_fx->SetTechnique(
"EmissiveSpecularTexture");
2403 hr = magic_fx->SetTechnique(
"SpecularTexture");
2408 if (mtl->
tex_emissive && render_state[LIGHTING_PASS] == 0) {
2409 hr = magic_fx->SetTechnique(
"EmissiveTexture");
2411 hr = magic_fx->SetTechnique(
"SimpleTexture");
2415 hr = magic_fx->SetTechnique(
"SimpleMaterial");
2419 if (environment_cube != 0 && magic_fx->IsParameterUsed(
"env_cube", hnd_shader)) {
2420 D3DXMATRIX env_matrix;
2421 D3DXMatrixIdentity(&env_matrix);
2423 magic_fx->SetMatrix(
"env_matrix", &env_matrix);
2424 magic_fx->SetTexture(
"env_cube", environment_cube->
GetTexture());
2428 d3ddevice->SetRenderState(D3DRS_STENCILENABLE, TRUE);
2429 d3ddevice->SetRenderState(D3DRS_STENCILREF, 0x01);
2430 d3ddevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_GREATER);
2432 d3ddevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
2435 if (render_state[LIGHTING_PASS] > 0) {
2436 current_blend_state = 100;
2440 current_blend_state = 100;
2446 hr = magic_fx->Begin(&nPasses, 0);
2448 for (UINT i = 0; i < nPasses; i++) {
2449 hr = magic_fx->BeginPass(i);
2451 hr = d3ddevice->DrawIndexedPrimitive(
2459 hr = magic_fx->EndPass();
2462 hr = magic_fx->End();
2464 for (
int pass = 0; pass < passes; pass++) {
2467 hr = d3ddevice->DrawIndexedPrimitive(
2476 hr = d3ddevice->SetVertexShader(NULL);
2478 }
else if (luminous) {
2479 hr = d3ddevice->SetVertexShader(NULL);
2481 }
else if (surface_has_tangent_data && vertex_declaration) {
2482 hr = d3ddevice->SetVertexShader(NULL);
2483 hr = d3ddevice->SetVertexDeclaration(vertex_declaration);
2485 hr = d3ddevice->SetVertexShader(NULL);
2493 static int report = 10;
2509 if (d3ddevice && p && p->
nverts >= 3) {
2516 HRESULT hr = E_FAIL;
2518 ZeroMemory(verts,
sizeof(verts));
2523 for (
int i = 0; i < p->
nverts; i++) {
2524 index = p->
verts[i];
2526 verts[i].
x = vset->
loc[index].
x;
2527 verts[i].
y = vset->
loc[index].
y;
2528 verts[i].
z = vset->
loc[index].
z;
2533 index = p->
verts[0];
2536 verts[i].
x = vset->
loc[index].
x;
2537 verts[i].
y = vset->
loc[index].
y;
2538 verts[i].
z = vset->
loc[index].
z;
2541 current_texture = 0;
2543 hr = d3ddevice->SetVertexShader(NULL);
2545 hr = d3ddevice->SetTexture(0, 0);
2546 hr = d3ddevice->DrawPrimitiveUP(
2562 bool result =
false;
2563 HRESULT hr = E_FAIL;
2569 D3DMATRIX world_matrix;
2571 d3ddevice->SetTransform(D3DTS_WORLD, &world_matrix);
2572 matrixWorld = world_matrix;
2578 d3ddevice->SetRenderState(D3DRS_ZENABLE, TRUE);
2579 d3ddevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
2580 d3ddevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
2581 d3ddevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT);
2582 d3ddevice->SetRenderState(D3DRS_LIGHTING, FALSE);
2583 d3ddevice->SetVertexShader(NULL);
2585 d3ddevice->SetTexture(0, 0);
2589 for (
int i = 0; i < nverts; i+=3) {
2590 DWORD c = 0xa0ffff80;
2592 verts[0].
x = shadow_verts[i+0].
x;
2593 verts[0].
y = shadow_verts[i+0].
y;
2594 verts[0].
z = shadow_verts[i+0].
z;
2597 verts[1].
x = shadow_verts[i+1].
x;
2598 verts[1].
y = shadow_verts[i+1].
y;
2599 verts[1].
z = shadow_verts[i+1].
z;
2602 verts[2].
x = shadow_verts[i+2].
x;
2603 verts[2].
y = shadow_verts[i+2].
y;
2604 verts[2].
z = shadow_verts[i+2].
z;
2607 verts[3].
x = shadow_verts[i+0].
x;
2608 verts[3].
y = shadow_verts[i+0].
y;
2609 verts[3].
z = shadow_verts[i+0].
z;
2612 hr = d3ddevice->DrawPrimitiveUP(
2620 d3ddevice->SetRenderState(D3DRS_LIGHTING, render_state[
LIGHTING_ENABLE]);
2627 d3ddevice->SetRenderState(D3DRS_ZENABLE, TRUE);
2628 d3ddevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
2629 d3ddevice->SetRenderState(D3DRS_STENCILENABLE, TRUE);
2632 d3ddevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT);
2638 d3ddevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS );
2639 d3ddevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP );
2640 d3ddevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP );
2643 d3ddevice->SetRenderState(D3DRS_STENCILREF, 0x1 );
2644 d3ddevice->SetRenderState(D3DRS_STENCILMASK, 0xff );
2645 d3ddevice->SetRenderState(D3DRS_STENCILWRITEMASK, 0xff );
2646 d3ddevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_INCR );
2649 d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE );
2650 d3ddevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO );
2651 d3ddevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE );
2653 d3ddevice->SetVertexShader(NULL);
2654 d3ddevice->SetFVF(D3DFVF_XYZ);
2657 hr = d3ddevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, nverts/3, shadow_verts,
sizeof(
Vec3));
2660 d3ddevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW );
2663 d3ddevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_DECR );
2666 hr = d3ddevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, nverts/3, shadow_verts,
sizeof(
Vec3));
2669 d3ddevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
2670 d3ddevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
2671 d3ddevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
2672 d3ddevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
2675 int type = current_blend_state;
2676 current_blend_state = 100;
2679 result = SUCCEEDED(hr);
2690 bool result =
false;
2692 if (d3ddevice && points && nlines > 0 && nlines <= 256) {
2698 HRESULT hr = E_FAIL;
2700 for (
int i = 0; i < 2*nlines; i++) {
2702 Vec3* p = points + i;
2710 hr = d3ddevice->SetTransform(D3DTS_WORLD, &identity_matrix);
2711 hr = d3ddevice->SetVertexShader(NULL);
2717 if (current_texture) {
2718 d3ddevice->SetTexture(0, 0);
2719 current_texture = 0;
2725 hr = d3ddevice->DrawPrimitiveUP(
2732 static int report = 10;
2739 if (SUCCEEDED(hr)) {
2755 bool result =
false;
2757 if (d3ddevice && points && nlines > 0 && nlines <= 64) {
2763 HRESULT hr = E_FAIL;
2765 for (
int i = 0; i < 2*nlines; i++) {
2768 v->
sx = points[2*i + 0];
2769 v->
sy = points[2*i + 1];
2777 hr = d3ddevice->SetVertexShader(NULL);
2781 static int report = 10;
2787 if (current_texture != 0) {
2788 hr = d3ddevice->SetTexture(0, 0);
2789 current_texture = 0;
2797 hr = d3ddevice->DrawPrimitiveUP(
2804 static int report = 10;
2810 if (SUCCEEDED(hr)) {
2826 if (vset && vset->
nverts) {
2827 HRESULT hr = E_FAIL;
2829 int nverts = vset->
nverts;
2833 for (
int i = 0; i < nverts; i++) {
2845 hr = d3ddevice->SetTransform(D3DTS_WORLD, &identity_matrix);
2846 hr = d3ddevice->SetVertexShader(NULL);
2848 hr = d3ddevice->SetTexture(0, 0);
2849 hr = d3ddevice->DrawPrimitiveUP(
2877 if (d3ddevice && name && *name && size > 4) {
2880 strcpy_s(font_name, name);
2885 HRESULT hr = E_FAIL;
2886 HDC hdc = GetDC(NULL);
2887 int nLogPixelsY = GetDeviceCaps(hdc, LOGPIXELSY);
2889 ReleaseDC(NULL, hdc);
2891 int nHeight = -size * nLogPixelsY / 72;
2893 hr = D3DXCreateFont(d3ddevice,
2896 bold ? FW_BOLD : FW_NORMAL,
2902 DEFAULT_PITCH | FF_DONTCARE,
2906 if (SUCCEEDED(hr)) {
2918 if (d3ddevice && text && *text && d3dx_font) {
2922 r.right = rect.
x + rect.
w;
2923 r.bottom = rect.
y + rect.
h;
2925 d3dx_font->DrawText(0, text, count, &r, format, c.
Value());
2934 VideoDX9::PrepareSurface(
Surface* surf)
2940 bool luminous =
false;
2955 surface_has_tangent_data =
false;
2958 surface_has_tangent_data =
true;
2964 dynamic | D3DUSAGE_WRITEONLY);
2973 dynamic | D3DUSAGE_WRITEONLY);
2976 else if (luminous) {
2982 dynamic | D3DUSAGE_WRITEONLY);
2991 dynamic | D3DUSAGE_WRITEONLY);
2997 dynamic | D3DUSAGE_WRITEONLY);
2999 if (!surf_data->vertex_buffer || !surf_data->index_buffer) {
3000 Print(
"VideoDX9: Unable to prepare surface '%s'\n", surf->
Name());
3008 if (surf_data && !surf_data->IsValid()) {
3014 for (
int i = 0; i < nverts; i++) {
3015 v->
x = vset->
loc[i].
x;
3016 v->
y = vset->
loc[i].
y;
3017 v->
z = vset->
loc[i].
z;
3022 v->
tu = vset->
tu[i];
3023 v->
tv = vset->
tv[i];
3030 surf_data->vertex_buffer->Unlock();
3034 else if (luminous) {
3039 for (
int i = 0; i < nverts; i++) {
3040 v->
x = vset->
loc[i].
x;
3041 v->
y = vset->
loc[i].
y;
3042 v->
z = vset->
loc[i].
z;
3046 v->
tu = vset->
tu[i];
3047 v->
tv = vset->
tv[i];
3052 surf_data->vertex_buffer->Unlock();
3056 else if (surface_has_tangent_data) {
3061 for (
int i = 0; i < nverts; i++) {
3062 v->
x = vset->
loc[i].
x;
3063 v->
y = vset->
loc[i].
y;
3064 v->
z = vset->
loc[i].
z;
3070 v->
t0u = vset->
tu[i];
3071 v->
t0v = vset->
tv[i];
3072 v->
t1u = vset->
tu[i];
3073 v->
t1v = vset->
tv[i];
3086 surf_data->vertex_buffer->Unlock();
3095 for (
int i = 0; i < nverts; i++) {
3096 v->
x = vset->
loc[i].
x;
3097 v->
y = vset->
loc[i].
y;
3098 v->
z = vset->
loc[i].
z;
3104 v->
tu = vset->
tu[i];
3105 v->
tv = vset->
tv[i];
3110 surf_data->vertex_buffer->Unlock();
3114 WORD* indices = surf_data->index_buffer->Lock(nindices);
3121 for (
int i = 0; i < surf->
NumPolys(); i++) {
3127 else if (p->
nverts == 4) {
3140 surf_data->index_buffer->Unlock();
3143 surf_data->Validate();
3146 int first_index = 0;
3149 while (++seg_iter) {
3156 for (
int i = 0; i < segment->
npolys; i++)
3166 first_index += num_tris * 3;
3177 VideoDX9::PrepareMaterial(
Material* m)
3179 segment_material = m;
3185 int max_textures = 1;
3186 bool multiply_add =
false;
3187 bool dotproduct3 =
false;
3188 bool vertexshader =
false;
3189 bool pixelshader =
false;
3190 DWORD vs_version = 0;
3191 DWORD ps_version = 0;
3196 max_stages = (int) dev_info->
caps.MaxTextureBlendStages;
3197 max_textures = (
int) dev_info->
caps.MaxSimultaneousTextures;
3198 multiply_add = (dev_info->
caps.TextureOpCaps & D3DTEXOPCAPS_MULTIPLYADD) ?
true :
false;
3199 dotproduct3 = (dev_info->
caps.TextureOpCaps & D3DTEXOPCAPS_DOTPRODUCT3) ?
true :
false;
3201 vs_version = video_settings.
enable_vs ? dev_info->
caps.VertexShaderVersion : 0;
3202 ps_version = video_settings.
enable_ps ? dev_info->
caps.PixelShaderVersion : 0;
3204 vertexshader = vs_version >= D3DVS_VERSION(1,1);
3205 pixelshader = ps_version >= D3DPS_VERSION(2,0);
3212 if (m->
tex_detail && max_textures > 2 && max_stages > 4)
3215 else if (max_textures > 1 && max_stages > 3)
3226 if (max_textures < 2 || max_stages < 2 || !multiply_add)
3233 if (max_textures < 2 || max_stages < 2)
3240 if (max_textures < 2 || max_stages < 2)
3243 else if (max_textures < 3 || max_stages < 3 || !multiply_add)
3252 VideoDX9::SetupPass(
int pass)
3254 if (pass < 0 || pass >= passes)
3258 D3DMATERIAL9 d3dmtl;
3259 IDirect3DTexture9* texture_0 = 0;
3260 IDirect3DTexture9* texture_1 = 0;
3261 IDirect3DTexture9* texture_2 = 0;
3266 HRESULT hr = E_FAIL;
3272 segment_material->
Ks = orig_spec;
3274 hr = d3ddevice->SetMaterial(&d3dmtl);
3316 if (texcache && tex_bmp_0) {
3319 hr = d3ddevice->SetTexture(0, texture_0);
3320 current_texture = texture_0;
3324 hr = d3ddevice->SetTexture(1, texture_1);
3328 hr = d3ddevice->SetTexture(2, texture_2);
3333 hr = d3ddevice->SetTexture(0, 0);
3334 current_texture = 0;
3340 d3ddevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
3341 d3ddevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
3342 d3ddevice->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
3344 d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
3345 d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
3346 d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
3347 d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
3349 d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_BLENDCURRENTALPHA);
3350 d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT);
3351 d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_TEXTURE);
3352 d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
3353 d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
3354 d3ddevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0);
3356 d3ddevice->SetTextureStageState(2, D3DTSS_COLOROP, D3DTOP_MODULATE);
3357 d3ddevice->SetTextureStageState(2, D3DTSS_COLORARG1, D3DTA_CURRENT);
3358 d3ddevice->SetTextureStageState(2, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
3359 d3ddevice->SetTextureStageState(2, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
3360 d3ddevice->SetTextureStageState(2, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
3362 d3ddevice->SetTextureStageState(3, D3DTSS_COLOROP, D3DTOP_DISABLE);
3366 d3ddevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
3367 d3ddevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
3368 d3ddevice->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
3369 d3ddevice->SetSamplerState(2, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
3370 d3ddevice->SetSamplerState(2, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
3371 d3ddevice->SetSamplerState(2, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
3373 d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
3374 d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
3375 d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
3376 d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
3377 d3ddevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0);
3379 d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_BLENDCURRENTALPHA);
3380 d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT);
3381 d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_TEXTURE);
3382 d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
3383 d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
3384 d3ddevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0);
3386 d3ddevice->SetTextureStageState(2, D3DTSS_COLOROP, D3DTOP_BLENDTEXTUREALPHA);
3387 d3ddevice->SetTextureStageState(2, D3DTSS_COLORARG1, D3DTA_TEXTURE);
3388 d3ddevice->SetTextureStageState(2, D3DTSS_COLORARG2, D3DTA_CURRENT);
3389 d3ddevice->SetTextureStageState(2, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
3390 d3ddevice->SetTextureStageState(2, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
3391 d3ddevice->SetTextureStageState(2, D3DTSS_TEXCOORDINDEX, 1);
3393 d3ddevice->SetTextureStageState(3, D3DTSS_COLOROP, D3DTOP_MODULATE);
3394 d3ddevice->SetTextureStageState(3, D3DTSS_COLORARG1, D3DTA_CURRENT);
3395 d3ddevice->SetTextureStageState(3, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
3396 d3ddevice->SetTextureStageState(3, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
3397 d3ddevice->SetTextureStageState(3, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
3401 d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
3402 d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
3403 d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT);
3404 d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
3405 d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
3408 else if (texture_0) {
3409 d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
3410 d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
3411 d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT);
3412 d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
3413 d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
3417 d3ddevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
3418 d3ddevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
3419 d3ddevice->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
3421 d3ddevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0);
3422 d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MULTIPLYADD);
3423 d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
3424 d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_SPECULAR);
3425 d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
3426 d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
3430 d3ddevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
3431 d3ddevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
3432 d3ddevice->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
3434 d3ddevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0);
3435 d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_ADD);
3436 d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
3437 d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
3438 d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
3439 d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
3443 d3ddevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
3444 d3ddevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
3445 d3ddevice->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
3447 d3ddevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0);
3448 d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_ADD);
3449 d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
3450 d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
3451 d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
3452 d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
3456 d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
3460 else if (pass == 1) {
3461 D3DMATERIAL9 d3dmtl;
3462 IDirect3DTexture9* texture = 0;
3466 HRESULT hr = E_FAIL;
3475 segment_material->
Ka = orig_Ka;
3476 segment_material->
Kd = orig_Kd;
3478 hr = d3ddevice->SetMaterial(&d3dmtl);
3483 d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
3484 d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
3485 d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_SPECULAR);
3490 d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
3491 d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
3494 d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
3496 if (texcache && tex_bmp) {
3498 hr = d3ddevice->SetTexture(0, texture);
3499 current_texture = texture;
3505 if (render_state[STENCIL_ENABLE]) {
3506 d3ddevice->SetRenderState(D3DRS_STENCILENABLE, TRUE);
3507 d3ddevice->SetRenderState(D3DRS_STENCILREF, 0x01);
3508 d3ddevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_GREATER);
3511 d3ddevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
3514 if (render_state[LIGHTING_PASS] > 0) {
3533 static char errstrbuf[128];
3537 sprintf_s(errstrbuf,
"Unrecognized error value = %08x.", hr);
3543 case D3DERR_WRONGTEXTUREFORMAT:
3544 return "Wrong texture format.";
3546 case D3DERR_UNSUPPORTEDCOLOROPERATION:
3547 return "Unsupported color operation.";
3549 case D3DERR_UNSUPPORTEDCOLORARG:
3550 return "Unsupported color argument.";
3552 case D3DERR_UNSUPPORTEDALPHAOPERATION:
3553 return "Unsupported alpha operation.";
3555 case D3DERR_UNSUPPORTEDALPHAARG:
3556 return "Unsupported alpha argument.";
3558 case D3DERR_TOOMANYOPERATIONS:
3559 return "Too many operations.";
3561 case D3DERR_CONFLICTINGTEXTUREFILTER:
3562 return "Conflicting texture filter.";
3564 case D3DERR_UNSUPPORTEDFACTORVALUE:
3565 return "Unsupported factor value.";
3567 case D3DERR_CONFLICTINGRENDERSTATE:
3568 return "Conflicting render state.";
3570 case D3DERR_UNSUPPORTEDTEXTUREFILTER:
3571 return "Unsupported texture filter.";
3573 case D3DERR_CONFLICTINGTEXTUREPALETTE:
3574 return "Conflicting texture palette.";
3576 case D3DERR_DRIVERINTERNALERROR:
3577 return "Driver internal error.";
3580 case D3DERR_NOTFOUND:
3581 return "Resource was not found.";
3583 case D3DERR_MOREDATA:
3584 return "More data?";
3586 case D3DERR_DEVICELOST:
3587 return "Device lost.";
3589 case D3DERR_DEVICENOTRESET:
3590 return "Device is not reset.";
3592 case D3DERR_NOTAVAILABLE:
3593 return "Not available.";
3595 case D3DERR_OUTOFVIDEOMEMORY:
3596 return "Out of video memory.";
3599 return "Out of system memory.";
3601 case D3DERR_INVALIDDEVICE:
3602 return "Invalid device selection.";
3604 case D3DERR_INVALIDCALL:
3605 return "Invalid call or parameter.";
3607 case D3DERR_DRIVERINVALIDCALL:
3608 return "Driver invalid call.";
3610 case D3DERR_WASSTILLDRAWING:
3611 return "The device was still drawing.";
3613 case D3DOK_NOAUTOGEN:
3614 return "Autogeneration is not supported by this device.";