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;
667 magic_fx_code_len = loader->
LoadBuffer(
"magic.fx", magic_fx_code,
true,
true);
671 if (video_settings.
use_effects && magic_fx_code && magic_fx_code_len) {
672 hr = D3DXCreateEffect(d3ddevice,
680 ::Print(
"ERROR - Failed to compile 'magic.fx'\n");
681 ::Print((
const char*) code_buffer->GetBufferPointer());
688 return screen_vbuf && screen_ibuf;
692 VideoDX9::DestroyBuffers()
699 if (screen_line_verts) {
700 delete screen_line_verts;
701 screen_line_verts = 0;
715 delete [] font_verts;
720 delete [] font_indices;
740 result = d3ddevice->GetAvailableTextureMem();
752 return (
int) dev_info->
caps.MaxTextureWidth;
766 return (
int) dev_info->
caps.MaxTextureAspectRatio;
778 Print(
"VideoDX9::RecoverSurfaces()\n");
784 hr = d3ddevice->TestCooperativeLevel();
786 if (hr == D3DERR_DEVICELOST) {
789 Print(
"D3DERR_DEVICELOST\n");
793 hr = d3ddevice->TestCooperativeLevel();
794 }
while (hr == D3DERR_DEVICELOST);
797 if (hr == D3DERR_DEVICENOTRESET) {
798 if (
Reset(&video_settings))
803 Print(
"* Invalidating Texture Cache\n");
811 Print(
"* Recover Surfaces Complete.\n\n");
832 return (WORD) (65535.0 * fade * pow((
double)i/255.f, recip_gamma));
843 return logf(i/255.f)/logf(0.5f);
854 return logf(0.5f)/logf(i/255.f);
863 if (gamma != g || fade != f) {
871 for (UINT i = 0; i < 256; i++) {
874 gamma_ramp.red[i] = val;
875 gamma_ramp.green[i] = val;
876 gamma_ramp.blue[i] = val;
879 d3ddevice->SetGammaRamp(0, D3DSGR_NO_CALIBRATION, &gamma_ramp);
887 return SUCCEEDED(hr);
896 D3DMATRIX world_matrix;
898 hr = d3ddevice->SetTransform(D3DTS_WORLD, &world_matrix);
900 matrixWorld = world_matrix;
901 D3DXMatrixInverse(&matrixWorldInverse, 0, &matrixWorld);
904 return SUCCEEDED(hr);
914 err = d3ddevice->Clear(0,
916 D3DCLEAR_TARGET | D3DCLEAR_STENCIL | D3DCLEAR_ZBUFFER,
922 static int report = 10;
937 err = d3ddevice->Clear(0,
939 D3DCLEAR_STENCIL | D3DCLEAR_ZBUFFER,
945 static int report = 10;
961 HRESULT
err = d3ddevice->Present( NULL, NULL, NULL, NULL );
964 if (err == D3DERR_DEVICELOST) {
969 static int report = 10;
1008 if (texcache && tex)
1034 result._11 = (float) m.
elem[0][0];
1035 result._12 = (
float) m.
elem[1][0];
1036 result._13 = (float) m.
elem[2][0];
1039 result._21 = (
float) m.
elem[0][1];
1040 result._22 = (float) m.
elem[1][1];
1041 result._23 = (
float) m.
elem[2][1];
1044 result._31 = (float) m.
elem[0][2];
1045 result._32 = (
float) m.
elem[1][2];
1046 result._33 = (float) m.
elem[2][2];
1049 result._41 = (
float) p.
x;
1050 result._42 = (float) p.
y;
1051 result._43 = (
float) p.
z;
1058 result._11 = (float) m.
elem[0][0];
1059 result._12 = (
float) m.
elem[1][0];
1060 result._13 = (float) m.
elem[2][0];
1063 result._21 = (
float) m.
elem[0][1];
1064 result._22 = (float) m.
elem[1][1];
1065 result._23 = (
float) m.
elem[2][1];
1068 result._31 = (float) m.
elem[0][2];
1069 result._32 = (
float) m.
elem[1][2];
1070 result._33 = (float) m.
elem[2][2];
1082 CopyMemory(&result.Diffuse, &mtl.
Kd,
sizeof(D3DCOLORVALUE));
1083 CopyMemory(&result.Ambient, &mtl.
Ka,
sizeof(D3DCOLORVALUE));
1084 CopyMemory(&result.Specular, &mtl.
Ks,
sizeof(D3DCOLORVALUE));
1085 CopyMemory(&result.Emissive, &mtl.
Ke,
sizeof(D3DCOLORVALUE));
1087 result.Power = mtl.
power;
1097 HRESULT hr = E_FAIL;
1098 LPDIRECT3DSURFACE9 pSurf=NULL, pTempSurf=NULL;
1099 D3DSURFACE_DESC desc;
1104 hr = d3ddevice->GetDisplayMode(0, &dm);
1107 VideoDX9Error(
"VideoDX9::Capture - Can't get display mode!", hr);
1109 desc.Width = dm.Width;
1110 desc.Height = dm.Height;
1111 desc.Format = D3DFMT_A8R8G8B8;
1113 hr = d3ddevice->CreateOffscreenPlainSurface(
1122 VideoDX9Error(
"VideoDX9::Capture - Cannot create offscreen buffer 1", hr);
1126 hr = d3ddevice->GetFrontBufferData(0, pTempSurf);
1130 VideoDX9Error(
"VideoDX9::Capture - Can't get front buffer", hr);
1140 ::GetClientRect(hwnd, &srcRect);
1141 ::ClientToScreen(hwnd, (LPPOINT) &srcRect);
1142 srcRect.right += srcRect.left;
1143 srcRect.bottom += srcRect.top;
1145 desc.Width = srcRect.right - srcRect.left;
1146 desc.Height = srcRect.bottom - srcRect.top;
1147 desc.Format = D3DFMT_A8R8G8B8;
1152 hr = d3ddevice->CreateOffscreenPlainSurface(
1162 VideoDX9Error(
"VideoDX9::Capture - Cannot create offscreen buffer 2", hr);
1167 hr = d3ddevice->UpdateSurface(pTempSurf, &srcRect, pSurf, &pt);
1172 VideoDX9Error(
"VideoDX9::Capture - Cannot update surface", hr);
1181 D3DLOCKED_RECT lockedRect;
1182 hr = pTempSurf->LockRect(&lockedRect, NULL,
1183 D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK);
1192 DWORD* buffer =
new DWORD[desc.Width * desc.Height];
1193 BYTE* src = (BYTE*) lockedRect.pBits;
1194 BYTE* dst = (BYTE*) buffer;
1197 for (DWORD y = 0; y < desc.Height; y++) {
1200 for (DWORD x = 0; x < desc.Width; x++) {
1201 switch(desc.Format) {
1205 *dst++ = (BYTE) clr.
Red();
1206 *dst++ = (BYTE) clr.
Green();
1207 *dst++ = (BYTE) clr.
Blue();
1211 case D3DFMT_A8R8G8B8:
1212 case D3DFMT_X8R8G8B8:
1233 src += lockedRect.Pitch;
1243 return SUCCEEDED(hr);
1254 if (d3ddevice && (rect.
w < 1 || rect.
h < 1)) {
1256 HRESULT hr = d3ddevice->GetViewport(&view);
1257 if (SUCCEEDED(hr)) {
1260 rect.
w = view.Width;
1261 rect.
h = view.Height;
1282 if (!d3d || !d3ddevice)
1297 hr = d3ddevice->SetViewport(&view);
1305 if (d3dstate_table[i]) {
1306 d3ddevice->SetRenderState((D3DRENDERSTATETYPE) d3dstate_table[i], render_state[i]);
1310 d3ddevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
1343 D3DLIGHT9 d3d_light;
1344 ZeroMemory(&d3d_light,
sizeof(d3d_light));
1345 d3d_light.Type = (D3DLIGHTTYPE) light->
Type();
1348 d3d_light.Direction.x = (float) (-light->
Location().
x);
1349 d3d_light.Direction.y = (float) (-light->
Location().
y);
1350 d3d_light.Direction.z = (float) (-light->
Location().
z);
1352 if (d3d_light.Direction.x == 0 &&
1353 d3d_light.Direction.y == 0 &&
1354 d3d_light.Direction.z == 0) {
1356 d3d_light.Direction.y = -1;
1363 else if (!back_light) {
1368 d3d_light.Position.x = (float) ( light->
Location().
x);
1369 d3d_light.Position.y = (float) ( light->
Location().
y);
1370 d3d_light.Position.z = (float) ( light->
Location().
z);
1377 d3d_light.Diffuse.r = r;
1378 d3d_light.Diffuse.g = g;
1379 d3d_light.Diffuse.b = b;
1381 d3d_light.Specular.r = r;
1382 d3d_light.Specular.g = g;
1383 d3d_light.Specular.b = b;
1385 d3d_light.Range = light->
Intensity() * 10.0f;
1386 d3d_light.Attenuation0 = 0.1f;
1387 d3d_light.Attenuation1 = 0.7f;
1388 d3d_light.Attenuation2 = 0.0f;
1391 d3ddevice->SetLight(index, &d3d_light);
1392 d3ddevice->LightEnable(index, TRUE);
1397 while (nlights > index+1) {
1398 d3ddevice->LightEnable(--nlights, FALSE);
1401 nlights = index + 1;
1417 d3ddevice->SetTransform(D3DTS_VIEW, &m);
1429 if (d3ddevice && zfar > znear) {
1433 double width = (float) (rect.
w);
1434 double height = (float) (rect.
h);
1435 ZeroMemory(&m,
sizeof(m));
1442 double xscale = width / fov;
1443 double yscale = height / fov;
1445 double maxscale = xscale;
1446 if (yscale > xscale) maxscale = yscale;
1448 double xangle = atan(fov/2 * maxscale/xscale);
1450 w = (float) (2/tan(xangle));
1451 h = (float) (w * width/height);
1452 Q = zfar/(zfar - znear);
1466 m._11 = (float) (fov/width);
1467 m._22 = (float) (fov/height);
1468 m._33 = (float) (1/(zfar-znear));
1469 m._43 = (float) (znear/(znear-zfar));
1470 m._44 = (float) (1);
1477 d3ddevice->SetTransform(D3DTS_PROJECTION, &m);
1491 if (environment_cube && !faces) {
1492 delete environment_cube;
1493 environment_cube = 0;
1497 if (!environment_cube) {
1498 environment_cube =
new(__FILE__,__LINE__)
TexCubeDX9(
this);
1501 if (environment_cube) {
1503 for (
int i = 0; i < 6; i++)
1504 ok = ok && environment_cube->
LoadTexture(faces[i], i);
1519 if (render_state[state] == value || d3dstate_table[state] == 0) {
1520 render_state[state] = value;
1524 HRESULT hr = E_FAIL;
1528 DWORD wrap = D3DTADDRESS_CLAMP;
1531 wrap = D3DTADDRESS_WRAP;
1533 hr = d3ddevice->SetSamplerState(0, D3DSAMP_ADDRESSU, wrap);
1534 hr = d3ddevice->SetSamplerState(0, D3DSAMP_ADDRESSV, wrap);
1540 hr = d3ddevice->SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_EXP);
1541 hr = d3ddevice->SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_NONE);
1544 hr = d3ddevice->SetRenderState(D3DRS_FOGENABLE, value);
1548 else if (state ==
Z_BIAS) {
1550 FLOAT bias_scale = 1.0f;
1551 FLOAT depth_bias = (FLOAT) (
DW2I(value) / -10000.0);
1553 hr = d3ddevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS,
F2DW(bias_scale));
1554 hr = d3ddevice->SetRenderState(D3DRS_DEPTHBIAS,
F2DW(depth_bias));
1557 hr = d3ddevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0);
1558 hr = d3ddevice->SetRenderState(D3DRS_DEPTHBIAS, 0);
1564 hr = d3ddevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
1565 hr = d3ddevice->SetRenderState(D3DRS_ZENABLE, value);
1570 hr = d3ddevice->SetRenderState((D3DRENDERSTATETYPE) d3dstate_table[state], value);
1578 render_state[state] = value;
1587 if (blend_type == current_blend_state)
1590 switch (blend_type) {
1598 d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE,
false);
1602 d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE,
true);
1603 d3ddevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
1604 d3ddevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
1608 d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE,
true);
1609 d3ddevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
1610 d3ddevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
1614 current_blend_state = blend_type;
1633 static int frame_number = 1;
1634 static int report_errs = 100;
1644 err = d3ddevice->BeginScene();
1647 if (report_errs > 0) {
1656 current_blend_state = -1;
1672 err = d3ddevice->EndScene();
1686 static DWORD ColorModulate(DWORD a, DWORD b)
1688 float a0 = (float) ((a ) & 0xff)/255.0f;
1689 float a1 = (float) ((a>> 8) & 0xff)/255.0f;
1690 float a2 = (float) ((a>>16) & 0xff)/255.0f;
1691 float a3 = (float) ((a>>24) & 0xff)/255.0f;
1693 float b0 = (float) ((b ) & 0xff)/255.0f;
1694 float b1 = (float) ((b>> 8) & 0xff)/255.0f;
1695 float b2 = (float) ((b>>16) & 0xff)/255.0f;
1696 float b3 = (float) ((b>>24) & 0xff)/255.0f;
1698 return (DWORD) ((BYTE)(a3*b3*255.0f) << 24) |
1699 ((BYTE)(a2*b2*255.0f) << 16) |
1700 ((BYTE)(a1*b1*255.0f) << 8) |
1701 ((BYTE)(a0*b0*255.0f));
1707 VideoDX9::PopulateScreenVerts(
VertexSet* vset)
1709 if (!vset || !screen_vbuf)
1712 num_verts = vset->
nverts;
1719 for (
int i = 0; i < num_verts; i++) {
1723 v->
rhw = vset->
rw[i];
1727 v->
tu = vset->
tu[i];
1728 v->
tv = vset->
tv[i];
1737 Print(
" VideoDX9: could not lock screen vbuf for %d verts.\n", num_verts);
1746 bool result =
false;
1748 if (d3ddevice && polys && npolys > 0) {
1757 int nverts = vset->
nverts;
1758 bool luminous =
false;
1759 bool detail =
false;
1763 WORD* indices =
new(__FILE__,__LINE__) WORD[npolys*6];
1769 if (vset->
tu1 != 0) {
1775 for (
int i = 0; i < nverts; i++) {
1776 v->
x = vset->
loc[i].
x;
1777 v->
y = vset->
loc[i].
y;
1778 v->
z = vset->
loc[i].
z;
1783 v->
tu = vset->
tu[i];
1784 v->
tv = vset->
tv[i];
1792 else if (luminous) {
1798 for (
int i = 0; i < nverts; i++) {
1799 v->
x = vset->
loc[i].
x;
1800 v->
y = vset->
loc[i].
y;
1801 v->
z = vset->
loc[i].
z;
1805 v->
tu = vset->
tu[i];
1806 v->
tv = vset->
tv[i];
1818 for (
int i = 0; i < nverts; i++) {
1819 v->
x = vset->
loc[i].
x;
1820 v->
y = vset->
loc[i].
y;
1821 v->
z = vset->
loc[i].
z;
1827 v->
tu = vset->
tu[i];
1828 v->
tv = vset->
tv[i];
1834 if (verts && indices) {
1835 HRESULT hr = E_FAIL;
1838 int num_indices = 0;
1844 for (
int i = 0; i < npolys; i++) {
1854 else if (p->
nverts == 4) {
1870 hr = d3ddevice->SetTransform(D3DTS_WORLD, &identity_matrix);
1871 hr = d3ddevice->SetVertexShader(NULL);
1872 hr = d3ddevice->SetFVF(fvf);
1876 IDirect3DTexture9* texture = 0;
1882 if (current_texture != texture) {
1883 hr = d3ddevice->SetTexture(0, texture);
1884 current_texture = texture;
1889 hr = d3ddevice->SetTexture(1, texture);
1892 if (mtl && !luminous) {
1893 D3DMATERIAL9 d3dmtl;
1896 hr = d3ddevice->SetMaterial(&d3dmtl);
1897 hr = d3ddevice->SetRenderState(D3DRS_AMBIENT, ambient.
Value());
1905 d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
1906 d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
1907 d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
1908 d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
1909 d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
1910 d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
1912 d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
1915 hr = d3ddevice->DrawIndexedPrimitiveUP(
1926 static int report = 10;
1934 if (SUCCEEDED(hr)) {
1950 bool result =
false;
1951 HRESULT hr = E_FAIL;
1953 if (d3ddevice && polys && npolys > 0 && screen_vbuf && screen_ibuf) {
1961 int num_indices = 0;
1965 for (
int i = 0; i < npolys; i++) {
1966 Poly* p = polys + i;
1973 else if (p->
nverts == 4) {
1979 WORD* screen_indices = screen_ibuf->
Lock(num_indices);
1982 if (!screen_indices) {
1983 Print(
" VideoDX9: could not lock screen ibuf for %d indices.\n", num_indices);
1988 WORD* s = screen_indices;
1991 for (
int i = 0; i < npolys; i++) {
1993 *s++ = p->
verts[0] + first_vert;
1994 *s++ = p->
verts[1] + first_vert;
1995 *s++ = p->
verts[2] + first_vert;
1997 else if (p->
nverts == 4) {
1998 *s++ = p->
verts[0] + first_vert;
1999 *s++ = p->
verts[1] + first_vert;
2000 *s++ = p->
verts[2] + first_vert;
2002 *s++ = p->
verts[0] + first_vert;
2003 *s++ = p->
verts[2] + first_vert;
2004 *s++ = p->
verts[3] + first_vert;
2019 d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
2020 d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
2021 d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
2022 d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
2023 d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
2024 d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
2026 d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
2030 IDirect3DTexture9* texture = 0;
2036 if (current_texture != texture) {
2037 hr = d3ddevice->SetTexture(0, texture);
2038 current_texture = texture;
2043 hr = d3ddevice->SetVertexShader(NULL);
2046 hr = d3ddevice->DrawIndexedPrimitive(
2055 static int report = 10;
2074 bool result =
false;
2075 HRESULT hr = E_FAIL;
2077 if (d3ddevice && s && s->
GetModel()) {
2082 D3DMATRIX world_matrix;
2084 d3ddevice->SetTransform(D3DTS_WORLD, &world_matrix);
2085 matrixWorld = world_matrix;
2086 D3DXMatrixInverse(&matrixWorldInverse, 0, &matrixWorld);
2089 while (++surf_iter) {
2095 if (PrepareSurface(surf)) {
2103 while (++seg_iter) {
2107 if (mtl && (blend_modes & mtl->
blend)) {
2108 result = result && DrawSegment(segment);
2115 surface_has_tangent_data =
false;
2121 VideoDX9::DrawSegment(
Segment* segment)
2123 bool result =
false;
2124 bool detail =
false;
2125 bool luminous =
false;
2126 HRESULT hr = E_FAIL;
2141 d3ddevice->SetRenderState(D3DRS_AMBIENT, ambient.
Value());
2153 hr = d3ddevice->SetVertexShader(NULL);
2157 else if (luminous) {
2158 hr = d3ddevice->SetVertexShader(NULL);
2162 else if (surface_has_tangent_data && vertex_declaration) {
2163 hr = d3ddevice->SetVertexDeclaration(vertex_declaration);
2164 hr = d3ddevice->SetVertexShader(NULL);
2168 hr = d3ddevice->SetVertexShader(NULL);
2173 PrepareMaterial(mtl);
2176 for (
int i = 0; i < segment->
npolys; i++) {
2181 else if (luminous) {
2182 PrepareMaterial(mtl);
2188 for (
int pass = 0; pass < passes; pass++) {
2191 hr = d3ddevice->DrawIndexedPrimitive(
2200 d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
2204 PrepareMaterial(mtl);
2211 DWORD vs_version = 0;
2212 DWORD ps_version = 0;
2213 bool shaders_ok =
false;
2218 vs_version = video_settings.
enable_vs ? dev_info->
caps.VertexShaderVersion : 0;
2219 ps_version = video_settings.
enable_ps ? dev_info->
caps.PixelShaderVersion : 0;
2221 if (vs_version >= D3DVS_VERSION(1,1))
2225 if (surface_has_tangent_data && vertex_declaration) {
2226 hr = d3ddevice->SetVertexShader(NULL);
2227 hr = d3ddevice->SetVertexDeclaration(vertex_declaration);
2231 hr = d3ddevice->SetVertexShader(NULL);
2239 bool do_pix = will_bump && render_state[
LIGHTING_PASS] == 0;
2240 bool do_bump = will_bump && render_state[
LIGHTING_PASS] > 0;
2242 D3DXMATRIX matrixWVP = matrixWorld * matrixView * matrixProj;
2244 D3DXVECTOR4 eyePos( (
float) camera->Pos().x, (float) camera->Pos().y, (float) camera->Pos().z, 1.0f);
2247 D3DXVec4Transform(&eyeObj, &eyePos, &matrixWorldInverse);
2249 D3DXVECTOR4 lightPos(100.0f, 100.0f, 100.0f, 1.0f);
2250 D3DXVECTOR4 lightColor(1,1,1,1);
2251 D3DXVECTOR4 ambientColor(0,0,0,1);
2253 ambientColor.x = ambient.
fRed();
2254 ambientColor.y = ambient.
fGreen();
2255 ambientColor.z = ambient.
fBlue();
2258 lightPos.x = (float) main_light->
Location().
x;
2259 lightPos.y = (float) main_light->
Location().
y;
2260 lightPos.z = (float) main_light->
Location().
z;
2263 D3DXVec4Transform(&lightPos, &lightPos, &matrixWorldInverse);
2268 lightColor.w = 1.0f;
2272 lightPos.x = (float) back_light->
Location().
x;
2273 lightPos.y = (float) back_light->
Location().
y;
2274 lightPos.z = (float) back_light->
Location().
z;
2279 lightColor.w = 1.0f;
2282 D3DXVECTOR4 lightDir = D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f) - lightPos;
2283 D3DXVec4Normalize(&lightDir, &lightDir);
2285 magic_fx->SetMatrix(
"wvp", &matrixWVP);
2286 magic_fx->SetMatrix(
"world", &matrixWorld);
2287 magic_fx->SetMatrix(
"view", &matrixView);
2288 magic_fx->SetMatrix(
"proj", &matrixProj);
2289 magic_fx->SetMatrix(
"worldInv", &matrixWorldInverse);
2291 magic_fx->SetVector(
"light1Pos", &lightPos);
2292 magic_fx->SetVector(
"light1Dir", &lightDir);
2293 magic_fx->SetVector(
"light1Color", &lightColor);
2294 magic_fx->SetVector(
"ambientColor", &ambientColor);
2295 magic_fx->SetVector(
"eyeObj", &eyeObj);
2297 FLOAT base_bias = (FLOAT) (
DW2I(render_state[
Z_BIAS]) / -10000.0);
2298 magic_fx->SetFloat(
"bias", base_bias + video_settings.
depth_bias);
2303 mtl->
Ks = mtl->
Ks * 0.3;
2305 magic_fx->SetValue(
"Ka", &mtl->
Ka,
sizeof(
ColorValue));
2306 magic_fx->SetValue(
"Kd", &mtl->
Kd,
sizeof(
ColorValue));
2307 magic_fx->SetValue(
"Ke", &mtl->
Ke,
sizeof(
ColorValue));
2308 magic_fx->SetValue(
"Ks", &mtl->
Ks,
sizeof(
ColorValue));
2309 magic_fx->SetFloat(
"Ns", mtl->
power);
2316 magic_fx->SetTexture(
"tex_d", texture);
2318 magic_fx->SetTexture(
"tex_d", 0);
2323 magic_fx->SetTexture(
"tex_e", texture);
2325 magic_fx->SetTexture(
"tex_e", 0);
2330 magic_fx->SetTexture(
"tex_s", texture);
2332 magic_fx->SetTexture(
"tex_s", 0);
2337 magic_fx->SetTexture(
"tex_n", texture);
2341 magic_fx->SetTexture(
"tex_x", texture);
2343 magic_fx->SetTexture(
"tex_x", 0);
2347 D3DXHANDLE hnd_shader = 0;
2350 if (!strcmp(mtl_shader,
"null"))
2353 hnd_shader = magic_fx->GetTechniqueByName(mtl_shader);
2357 hr = magic_fx->SetTechnique(hnd_shader);
2362 if (ps_version >= D3DPS_VERSION(2,0))
2363 hr = magic_fx->SetTechnique(
"BumpSpecMapPix");
2365 hr = magic_fx->SetTechnique(
"BumpSpecMap");
2366 }
else if (mtl->
tex_emissive && render_state[LIGHTING_PASS] == 0) {
2367 if (ps_version >= D3DPS_VERSION(2,0))
2368 hr = magic_fx->SetTechnique(
"EmissiveSpecMapPix");
2370 hr = magic_fx->SetTechnique(
"EmissiveSpecularTexture");
2372 if (ps_version >= D3DPS_VERSION(2,0))
2373 hr = magic_fx->SetTechnique(
"SpecMapPix");
2375 hr = magic_fx->SetTechnique(
"SpecularTexture");
2379 if (ps_version >= D3DPS_VERSION(2,0))
2380 hr = magic_fx->SetTechnique(
"BumpMapPix");
2382 hr = magic_fx->SetTechnique(
"BumpMap");
2383 }
else if (mtl->
tex_emissive && render_state[LIGHTING_PASS] == 0) {
2384 if (ps_version >= D3DPS_VERSION(2,0))
2385 hr = magic_fx->SetTechnique(
"EmissivePix");
2387 hr = magic_fx->SetTechnique(
"EmissiveTexture");
2389 if (ps_version >= D3DPS_VERSION(2,0))
2390 hr = magic_fx->SetTechnique(
"SimplePix");
2392 hr = magic_fx->SetTechnique(
"SimpleTexture");
2399 if (mtl->
tex_emissive && render_state[LIGHTING_PASS] == 0) {
2400 hr = magic_fx->SetTechnique(
"EmissiveSpecularTexture");
2402 hr = magic_fx->SetTechnique(
"SpecularTexture");
2407 if (mtl->
tex_emissive && render_state[LIGHTING_PASS] == 0) {
2408 hr = magic_fx->SetTechnique(
"EmissiveTexture");
2410 hr = magic_fx->SetTechnique(
"SimpleTexture");
2414 hr = magic_fx->SetTechnique(
"SimpleMaterial");
2418 if (environment_cube != 0 && magic_fx->IsParameterUsed(
"env_cube", hnd_shader)) {
2419 D3DXMATRIX env_matrix;
2420 D3DXMatrixIdentity(&env_matrix);
2422 magic_fx->SetMatrix(
"env_matrix", &env_matrix);
2423 magic_fx->SetTexture(
"env_cube", environment_cube->
GetTexture());
2427 d3ddevice->SetRenderState(D3DRS_STENCILENABLE, TRUE);
2428 d3ddevice->SetRenderState(D3DRS_STENCILREF, 0x01);
2429 d3ddevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_GREATER);
2431 d3ddevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
2434 if (render_state[LIGHTING_PASS] > 0) {
2435 current_blend_state = 100;
2439 current_blend_state = 100;
2445 hr = magic_fx->Begin(&nPasses, 0);
2447 for (UINT i = 0; i < nPasses; i++) {
2448 hr = magic_fx->BeginPass(i);
2450 hr = d3ddevice->DrawIndexedPrimitive(
2458 hr = magic_fx->EndPass();
2461 hr = magic_fx->End();
2463 for (
int pass = 0; pass < passes; pass++) {
2466 hr = d3ddevice->DrawIndexedPrimitive(
2475 hr = d3ddevice->SetVertexShader(NULL);
2477 }
else if (luminous) {
2478 hr = d3ddevice->SetVertexShader(NULL);
2480 }
else if (surface_has_tangent_data && vertex_declaration) {
2481 hr = d3ddevice->SetVertexShader(NULL);
2482 hr = d3ddevice->SetVertexDeclaration(vertex_declaration);
2484 hr = d3ddevice->SetVertexShader(NULL);
2492 static int report = 10;
2508 if (d3ddevice && p && p->
nverts >= 3) {
2515 HRESULT hr = E_FAIL;
2517 ZeroMemory(verts,
sizeof(verts));
2522 for (
int i = 0; i < p->
nverts; i++) {
2523 index = p->
verts[i];
2525 verts[i].
x = vset->
loc[index].
x;
2526 verts[i].
y = vset->
loc[index].
y;
2527 verts[i].
z = vset->
loc[index].
z;
2532 index = p->
verts[0];
2535 verts[i].
x = vset->
loc[index].
x;
2536 verts[i].
y = vset->
loc[index].
y;
2537 verts[i].
z = vset->
loc[index].
z;
2540 current_texture = 0;
2542 hr = d3ddevice->SetVertexShader(NULL);
2544 hr = d3ddevice->SetTexture(0, 0);
2545 hr = d3ddevice->DrawPrimitiveUP(
2561 bool result =
false;
2562 HRESULT hr = E_FAIL;
2568 D3DMATRIX world_matrix;
2570 d3ddevice->SetTransform(D3DTS_WORLD, &world_matrix);
2571 matrixWorld = world_matrix;
2577 d3ddevice->SetRenderState(D3DRS_ZENABLE, TRUE);
2578 d3ddevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
2579 d3ddevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
2580 d3ddevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT);
2581 d3ddevice->SetRenderState(D3DRS_LIGHTING, FALSE);
2582 d3ddevice->SetVertexShader(NULL);
2584 d3ddevice->SetTexture(0, 0);
2588 for (
int i = 0; i < nverts; i+=3) {
2589 DWORD c = 0xa0ffff80;
2591 verts[0].
x = shadow_verts[i+0].
x;
2592 verts[0].
y = shadow_verts[i+0].
y;
2593 verts[0].
z = shadow_verts[i+0].
z;
2596 verts[1].
x = shadow_verts[i+1].
x;
2597 verts[1].
y = shadow_verts[i+1].
y;
2598 verts[1].
z = shadow_verts[i+1].
z;
2601 verts[2].
x = shadow_verts[i+2].
x;
2602 verts[2].
y = shadow_verts[i+2].
y;
2603 verts[2].
z = shadow_verts[i+2].
z;
2606 verts[3].
x = shadow_verts[i+0].
x;
2607 verts[3].
y = shadow_verts[i+0].
y;
2608 verts[3].
z = shadow_verts[i+0].
z;
2611 hr = d3ddevice->DrawPrimitiveUP(
2619 d3ddevice->SetRenderState(D3DRS_LIGHTING, render_state[
LIGHTING_ENABLE]);
2626 d3ddevice->SetRenderState(D3DRS_ZENABLE, TRUE);
2627 d3ddevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
2628 d3ddevice->SetRenderState(D3DRS_STENCILENABLE, TRUE);
2631 d3ddevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT);
2637 d3ddevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS );
2638 d3ddevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP );
2639 d3ddevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP );
2642 d3ddevice->SetRenderState(D3DRS_STENCILREF, 0x1 );
2643 d3ddevice->SetRenderState(D3DRS_STENCILMASK, 0xff );
2644 d3ddevice->SetRenderState(D3DRS_STENCILWRITEMASK, 0xff );
2645 d3ddevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_INCR );
2648 d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE );
2649 d3ddevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO );
2650 d3ddevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE );
2652 d3ddevice->SetVertexShader(NULL);
2653 d3ddevice->SetFVF(D3DFVF_XYZ);
2656 hr = d3ddevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, nverts/3, shadow_verts,
sizeof(
Vec3));
2659 d3ddevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW );
2662 d3ddevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_DECR );
2665 hr = d3ddevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, nverts/3, shadow_verts,
sizeof(
Vec3));
2668 d3ddevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
2669 d3ddevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
2670 d3ddevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
2671 d3ddevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
2674 int type = current_blend_state;
2675 current_blend_state = 100;
2678 result = SUCCEEDED(hr);
2689 bool result =
false;
2691 if (d3ddevice && points && nlines > 0 && nlines <= 256) {
2697 HRESULT hr = E_FAIL;
2699 for (
int i = 0; i < 2*nlines; i++) {
2701 Vec3* p = points + i;
2709 hr = d3ddevice->SetTransform(D3DTS_WORLD, &identity_matrix);
2710 hr = d3ddevice->SetVertexShader(NULL);
2716 if (current_texture) {
2717 d3ddevice->SetTexture(0, 0);
2718 current_texture = 0;
2724 hr = d3ddevice->DrawPrimitiveUP(
2731 static int report = 10;
2738 if (SUCCEEDED(hr)) {
2754 bool result =
false;
2756 if (d3ddevice && points && nlines > 0 && nlines <= 64) {
2762 HRESULT hr = E_FAIL;
2764 for (
int i = 0; i < 2*nlines; i++) {
2767 v->
sx = points[2*i + 0];
2768 v->
sy = points[2*i + 1];
2776 hr = d3ddevice->SetVertexShader(NULL);
2780 static int report = 10;
2786 if (current_texture != 0) {
2787 hr = d3ddevice->SetTexture(0, 0);
2788 current_texture = 0;
2796 hr = d3ddevice->DrawPrimitiveUP(
2803 static int report = 10;
2809 if (SUCCEEDED(hr)) {
2825 if (vset && vset->
nverts) {
2826 HRESULT hr = E_FAIL;
2828 int nverts = vset->
nverts;
2832 for (
int i = 0; i < nverts; i++) {
2844 hr = d3ddevice->SetTransform(D3DTS_WORLD, &identity_matrix);
2845 hr = d3ddevice->SetVertexShader(NULL);
2847 hr = d3ddevice->SetTexture(0, 0);
2848 hr = d3ddevice->DrawPrimitiveUP(
2876 if (d3ddevice && name && *name && size > 4) {
2879 strcpy_s(font_name, name);
2884 HRESULT hr = E_FAIL;
2885 HDC hdc = GetDC(NULL);
2886 int nLogPixelsY = GetDeviceCaps(hdc, LOGPIXELSY);
2888 ReleaseDC(NULL, hdc);
2890 int nHeight = -size * nLogPixelsY / 72;
2892 hr = D3DXCreateFont(d3ddevice,
2895 bold ? FW_BOLD : FW_NORMAL,
2901 DEFAULT_PITCH | FF_DONTCARE,
2905 if (SUCCEEDED(hr)) {
2917 if (d3ddevice && text && *text && d3dx_font) {
2921 r.right = rect.
x + rect.
w;
2922 r.bottom = rect.
y + rect.
h;
2924 d3dx_font->DrawText(0, text, count, &r, format, c.
Value());
2933 VideoDX9::PrepareSurface(
Surface* surf)
2939 bool luminous =
false;
2954 surface_has_tangent_data =
false;
2957 surface_has_tangent_data =
true;
2963 dynamic | D3DUSAGE_WRITEONLY);
2972 dynamic | D3DUSAGE_WRITEONLY);
2975 else if (luminous) {
2981 dynamic | D3DUSAGE_WRITEONLY);
2990 dynamic | D3DUSAGE_WRITEONLY);
2996 dynamic | D3DUSAGE_WRITEONLY);
2998 if (!surf_data->vertex_buffer || !surf_data->index_buffer) {
2999 Print(
"VideoDX9: Unable to prepare surface '%s'\n", surf->
Name());
3007 if (surf_data && !surf_data->IsValid()) {
3013 for (
int i = 0; i < nverts; i++) {
3014 v->
x = vset->
loc[i].
x;
3015 v->
y = vset->
loc[i].
y;
3016 v->
z = vset->
loc[i].
z;
3021 v->
tu = vset->
tu[i];
3022 v->
tv = vset->
tv[i];
3029 surf_data->vertex_buffer->Unlock();
3033 else if (luminous) {
3038 for (
int i = 0; i < nverts; i++) {
3039 v->
x = vset->
loc[i].
x;
3040 v->
y = vset->
loc[i].
y;
3041 v->
z = vset->
loc[i].
z;
3045 v->
tu = vset->
tu[i];
3046 v->
tv = vset->
tv[i];
3051 surf_data->vertex_buffer->Unlock();
3055 else if (surface_has_tangent_data) {
3060 for (
int i = 0; i < nverts; i++) {
3061 v->
x = vset->
loc[i].
x;
3062 v->
y = vset->
loc[i].
y;
3063 v->
z = vset->
loc[i].
z;
3069 v->
t0u = vset->
tu[i];
3070 v->
t0v = vset->
tv[i];
3071 v->
t1u = vset->
tu[i];
3072 v->
t1v = vset->
tv[i];
3085 surf_data->vertex_buffer->Unlock();
3094 for (
int i = 0; i < nverts; i++) {
3095 v->
x = vset->
loc[i].
x;
3096 v->
y = vset->
loc[i].
y;
3097 v->
z = vset->
loc[i].
z;
3103 v->
tu = vset->
tu[i];
3104 v->
tv = vset->
tv[i];
3109 surf_data->vertex_buffer->Unlock();
3113 WORD* indices = surf_data->index_buffer->Lock(nindices);
3120 for (
int i = 0; i < surf->
NumPolys(); i++) {
3126 else if (p->
nverts == 4) {
3139 surf_data->index_buffer->Unlock();
3142 surf_data->Validate();
3145 int first_index = 0;
3148 while (++seg_iter) {
3155 for (
int i = 0; i < segment->
npolys; i++)
3165 first_index += num_tris * 3;
3176 VideoDX9::PrepareMaterial(
Material* m)
3178 segment_material = m;
3184 int max_textures = 1;
3185 bool multiply_add =
false;
3186 bool dotproduct3 =
false;
3187 bool vertexshader =
false;
3188 bool pixelshader =
false;
3189 DWORD vs_version = 0;
3190 DWORD ps_version = 0;
3195 max_stages = (int) dev_info->
caps.MaxTextureBlendStages;
3196 max_textures = (
int) dev_info->
caps.MaxSimultaneousTextures;
3197 multiply_add = (dev_info->
caps.TextureOpCaps & D3DTEXOPCAPS_MULTIPLYADD) ?
true :
false;
3198 dotproduct3 = (dev_info->
caps.TextureOpCaps & D3DTEXOPCAPS_DOTPRODUCT3) ?
true :
false;
3200 vs_version = video_settings.
enable_vs ? dev_info->
caps.VertexShaderVersion : 0;
3201 ps_version = video_settings.
enable_ps ? dev_info->
caps.PixelShaderVersion : 0;
3203 vertexshader = vs_version >= D3DVS_VERSION(1,1);
3204 pixelshader = ps_version >= D3DPS_VERSION(2,0);
3211 if (m->
tex_detail && max_textures > 2 && max_stages > 4)
3214 else if (max_textures > 1 && max_stages > 3)
3225 if (max_textures < 2 || max_stages < 2 || !multiply_add)
3232 if (max_textures < 2 || max_stages < 2)
3239 if (max_textures < 2 || max_stages < 2)
3242 else if (max_textures < 3 || max_stages < 3 || !multiply_add)
3251 VideoDX9::SetupPass(
int pass)
3253 if (pass < 0 || pass >= passes)
3257 D3DMATERIAL9 d3dmtl;
3258 IDirect3DTexture9* texture_0 = 0;
3259 IDirect3DTexture9* texture_1 = 0;
3260 IDirect3DTexture9* texture_2 = 0;
3265 HRESULT hr = E_FAIL;
3271 segment_material->
Ks = orig_spec;
3273 hr = d3ddevice->SetMaterial(&d3dmtl);
3315 if (texcache && tex_bmp_0) {
3318 hr = d3ddevice->SetTexture(0, texture_0);
3319 current_texture = texture_0;
3323 hr = d3ddevice->SetTexture(1, texture_1);
3327 hr = d3ddevice->SetTexture(2, texture_2);
3332 hr = d3ddevice->SetTexture(0, 0);
3333 current_texture = 0;
3339 d3ddevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
3340 d3ddevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
3341 d3ddevice->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
3343 d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
3344 d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
3345 d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
3346 d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
3348 d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_BLENDCURRENTALPHA);
3349 d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT);
3350 d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_TEXTURE);
3351 d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
3352 d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
3353 d3ddevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0);
3355 d3ddevice->SetTextureStageState(2, D3DTSS_COLOROP, D3DTOP_MODULATE);
3356 d3ddevice->SetTextureStageState(2, D3DTSS_COLORARG1, D3DTA_CURRENT);
3357 d3ddevice->SetTextureStageState(2, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
3358 d3ddevice->SetTextureStageState(2, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
3359 d3ddevice->SetTextureStageState(2, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
3361 d3ddevice->SetTextureStageState(3, D3DTSS_COLOROP, D3DTOP_DISABLE);
3365 d3ddevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
3366 d3ddevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
3367 d3ddevice->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
3368 d3ddevice->SetSamplerState(2, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
3369 d3ddevice->SetSamplerState(2, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
3370 d3ddevice->SetSamplerState(2, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
3372 d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
3373 d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
3374 d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
3375 d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
3376 d3ddevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0);
3378 d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_BLENDCURRENTALPHA);
3379 d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT);
3380 d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_TEXTURE);
3381 d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
3382 d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
3383 d3ddevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0);
3385 d3ddevice->SetTextureStageState(2, D3DTSS_COLOROP, D3DTOP_BLENDTEXTUREALPHA);
3386 d3ddevice->SetTextureStageState(2, D3DTSS_COLORARG1, D3DTA_TEXTURE);
3387 d3ddevice->SetTextureStageState(2, D3DTSS_COLORARG2, D3DTA_CURRENT);
3388 d3ddevice->SetTextureStageState(2, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
3389 d3ddevice->SetTextureStageState(2, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
3390 d3ddevice->SetTextureStageState(2, D3DTSS_TEXCOORDINDEX, 1);
3392 d3ddevice->SetTextureStageState(3, D3DTSS_COLOROP, D3DTOP_MODULATE);
3393 d3ddevice->SetTextureStageState(3, D3DTSS_COLORARG1, D3DTA_CURRENT);
3394 d3ddevice->SetTextureStageState(3, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
3395 d3ddevice->SetTextureStageState(3, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
3396 d3ddevice->SetTextureStageState(3, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
3400 d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
3401 d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
3402 d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT);
3403 d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
3404 d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
3407 else if (texture_0) {
3408 d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
3409 d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
3410 d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT);
3411 d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
3412 d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
3416 d3ddevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
3417 d3ddevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
3418 d3ddevice->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
3420 d3ddevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0);
3421 d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MULTIPLYADD);
3422 d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
3423 d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_SPECULAR);
3424 d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
3425 d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
3429 d3ddevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
3430 d3ddevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
3431 d3ddevice->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
3433 d3ddevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0);
3434 d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_ADD);
3435 d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
3436 d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
3437 d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
3438 d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
3442 d3ddevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
3443 d3ddevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
3444 d3ddevice->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
3446 d3ddevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0);
3447 d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_ADD);
3448 d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
3449 d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
3450 d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
3451 d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
3455 d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
3459 else if (pass == 1) {
3460 D3DMATERIAL9 d3dmtl;
3461 IDirect3DTexture9* texture = 0;
3465 HRESULT hr = E_FAIL;
3474 segment_material->
Ka = orig_Ka;
3475 segment_material->
Kd = orig_Kd;
3477 hr = d3ddevice->SetMaterial(&d3dmtl);
3482 d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
3483 d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
3484 d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_SPECULAR);
3489 d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
3490 d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
3493 d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
3495 if (texcache && tex_bmp) {
3497 hr = d3ddevice->SetTexture(0, texture);
3498 current_texture = texture;
3504 if (render_state[STENCIL_ENABLE]) {
3505 d3ddevice->SetRenderState(D3DRS_STENCILENABLE, TRUE);
3506 d3ddevice->SetRenderState(D3DRS_STENCILREF, 0x01);
3507 d3ddevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_GREATER);
3510 d3ddevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
3513 if (render_state[LIGHTING_PASS] > 0) {
3532 static char errstrbuf[128];
3536 sprintf_s(errstrbuf,
"Unrecognized error value = %08x.", hr);
3542 case D3DERR_WRONGTEXTUREFORMAT:
3543 return "Wrong texture format.";
3545 case D3DERR_UNSUPPORTEDCOLOROPERATION:
3546 return "Unsupported color operation.";
3548 case D3DERR_UNSUPPORTEDCOLORARG:
3549 return "Unsupported color argument.";
3551 case D3DERR_UNSUPPORTEDALPHAOPERATION:
3552 return "Unsupported alpha operation.";
3554 case D3DERR_UNSUPPORTEDALPHAARG:
3555 return "Unsupported alpha argument.";
3557 case D3DERR_TOOMANYOPERATIONS:
3558 return "Too many operations.";
3560 case D3DERR_CONFLICTINGTEXTUREFILTER:
3561 return "Conflicting texture filter.";
3563 case D3DERR_UNSUPPORTEDFACTORVALUE:
3564 return "Unsupported factor value.";
3566 case D3DERR_CONFLICTINGRENDERSTATE:
3567 return "Conflicting render state.";
3569 case D3DERR_UNSUPPORTEDTEXTUREFILTER:
3570 return "Unsupported texture filter.";
3572 case D3DERR_CONFLICTINGTEXTUREPALETTE:
3573 return "Conflicting texture palette.";
3575 case D3DERR_DRIVERINTERNALERROR:
3576 return "Driver internal error.";
3579 case D3DERR_NOTFOUND:
3580 return "Resource was not found.";
3582 case D3DERR_MOREDATA:
3583 return "More data?";
3585 case D3DERR_DEVICELOST:
3586 return "Device lost.";
3588 case D3DERR_DEVICENOTRESET:
3589 return "Device is not reset.";
3591 case D3DERR_NOTAVAILABLE:
3592 return "Not available.";
3594 case D3DERR_OUTOFVIDEOMEMORY:
3595 return "Out of video memory.";
3598 return "Out of system memory.";
3600 case D3DERR_INVALIDDEVICE:
3601 return "Invalid device selection.";
3603 case D3DERR_INVALIDCALL:
3604 return "Invalid call or parameter.";
3606 case D3DERR_DRIVERINVALIDCALL:
3607 return "Driver invalid call.";
3609 case D3DERR_WASSTILLDRAWING:
3610 return "The device was still drawing.";
3612 case D3DOK_NOAUTOGEN:
3613 return "Autogeneration is not supported by this device.";