diff options
author | Aki <please@ignore.pl> | 2021-10-01 23:46:47 +0200 |
---|---|---|
committer | Aki <please@ignore.pl> | 2021-10-01 23:46:47 +0200 |
commit | ddd76aa4e1571c8d5965709db5c3cd47a89c9a38 (patch) | |
tree | 4e07bfaebede6531a70984fdebc855bca52f394a /nGenEx/VideoDX9.cpp | |
parent | 3a507e08b1d4e5970b27401a7e6517570d529400 (diff) | |
parent | c2d2c3551501110fddd78674d5435bfaa70382a3 (diff) | |
download | starshatter-ddd76aa4e1571c8d5965709db5c3cd47a89c9a38.zip starshatter-ddd76aa4e1571c8d5965709db5c3cd47a89c9a38.tar.gz starshatter-ddd76aa4e1571c8d5965709db5c3cd47a89c9a38.tar.bz2 |
Project is now built with CMake
Diffstat (limited to 'nGenEx/VideoDX9.cpp')
-rw-r--r-- | nGenEx/VideoDX9.cpp | 3642 |
1 files changed, 0 insertions, 3642 deletions
diff --git a/nGenEx/VideoDX9.cpp b/nGenEx/VideoDX9.cpp deleted file mode 100644 index 397e628..0000000 --- a/nGenEx/VideoDX9.cpp +++ /dev/null @@ -1,3642 +0,0 @@ -/* Starshatter OpenSource Distribution - Copyright (c) 1997-2004, Destroyer Studios LLC. - All Rights Reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name "Destroyer Studios" nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - - SUBSYSTEM: nGenEx.lib - FILE: VideoDX9.cpp - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Direct3D Video class for DirectX 9 -*/ - -#include "MemDebug.h" -#include "VideoDX9.h" -#include "VideoDX9Enum.h" -#include "VideoDX9VertexBuffer.h" -#include "TexDX9.h" -#include "TexCubeDX9.h" -#include "Camera.h" -#include "Color.h" -#include "DataLoader.h" -#include "Polygon.h" -#include "Light.h" -#include "Solid.h" - -// +--------------------------------------------------------------------+ - -void Print(const char* msg, ...); -char* D3DErrStr(HRESULT dderr); -void VideoDX9Error(const char* msg, HRESULT dderr); -static TexCacheDX9* texcache = 0; -static TexCubeDX9* environment_cube = 0; -static bool surface_has_tangent_data = false; -static Light* main_light; -static Light* back_light; -static D3DXMATRIX matrixWorld; -static D3DXMATRIX matrixView; -static D3DXMATRIX matrixProj; -static D3DXMATRIX matrixWorldInverse; - -extern int VD3D_describe_things; - -#ifndef RELEASE -#define RELEASE(x) if (x) { x->Release(); x=NULL; } -#endif - -#ifndef F2DW -#define F2DW(x) (*(DWORD*)(&x)) -#endif - -#ifndef DW2I -#define DW2I(x) (*(int*)(&x)) -#endif - -// +--------------------------------------------------------------------+ - -typedef HRESULT (WINAPI * LPDDCE)(GUID FAR *, LPVOID *, REFIID , IUnknown FAR *); - -static D3DMATRIX identity_matrix = { - FLOAT(1.0), FLOAT(0.0), FLOAT(0.0), FLOAT(0.0), - FLOAT(0.0), FLOAT(1.0), FLOAT(0.0), FLOAT(0.0), - FLOAT(0.0), FLOAT(0.0), FLOAT(1.0), FLOAT(0.0), - FLOAT(0.0), FLOAT(0.0), FLOAT(0.0), FLOAT(1.0) -}; - -// +--------------------------------------------------------------------+ - -List<Model> model_clients; - -class VideoDX9SurfaceData : public VideoPrivateData -{ -public: - VideoDX9SurfaceData(Model* m) : model(m), vertex_buffer(0), index_buffer(0) { - if (!model_clients.contains(model)) - model_clients.append(model); - } - - virtual ~VideoDX9SurfaceData() { - model_clients.remove(model); - - delete vertex_buffer; - delete index_buffer; - } - - enum { TYPE = 9001 }; - virtual int GetType() const { return TYPE; } - - Model* model; - VideoDX9VertexBuffer* vertex_buffer; - VideoDX9IndexBuffer* index_buffer; -}; - -class VideoDX9SegmentData : public VideoPrivateData -{ -public: - VideoDX9SegmentData() : first_vert(0), num_verts(0), first_index(0), num_tris(0) { } - virtual ~VideoDX9SegmentData() { } - - enum { TYPE = 9002 }; - virtual int GetType() const { return TYPE; } - - int first_vert; - int num_verts; - int first_index; - int num_tris; -}; - -// +--------------------------------------------------------------------+ - -static int d3dstate_table[] = { - D3DRS_FILLMODE, // FILL_MODE - D3DRS_SHADEMODE, // SHADE_MODE - D3DRS_LIGHTING, // LIGHTING_ENABLE - D3DRS_ZENABLE, // Z_ENABLE - D3DRS_ZWRITEENABLE, // Z_WRITE_ENABLE - D3DRS_DEPTHBIAS, // Z_BIAS - 0, // TEXTURE_FILTER - D3DRS_DITHERENABLE, // DITHER_ENABLE - D3DRS_SPECULARENABLE, // SPECULAR_ENABLE - D3DRS_FOGENABLE, // FOG_ENABLE - D3DRS_FOGCOLOR, // FOG_COLOR - D3DRS_FOGDENSITY, // FOG_DENSITY - D3DRS_STENCILENABLE, // STENCIL_ENABLE - 0x11111111, // TEXTURE_WRAP (special case) - 0 // LIGHTING_PASS -}; - -static const int NUM_SCREEN_VERTS = 1024; -static const int NUM_SCREEN_INDICES = NUM_SCREEN_VERTS * 2; - -// +--------------------------------------------------------------------+ - -struct VideoDX9ScreenVertex -{ - FLOAT sx, sy, sz, rhw; - DWORD diffuse; - FLOAT tu, tv; - - static DWORD FVF; -}; - -DWORD VideoDX9ScreenVertex::FVF = D3DFVF_XYZRHW | -D3DFVF_DIFFUSE | -D3DFVF_TEX1; - -struct VideoDX9NormalVertex -{ - FLOAT x, y, z; - FLOAT nx, ny, nz; - FLOAT t0u, t0v; - FLOAT t1u, t1v; - FLOAT tx, ty, tz; - FLOAT bx, by, bz; - - static DWORD FVF; -}; - -DWORD VideoDX9NormalVertex::FVF = 0; - -// Global Vertex Declaration shared by shaders -D3DVERTEXELEMENT9 videoDX9NormalVertexElements[] = -{ - { 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, - { 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 }, - { 0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, - { 0, 32, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1 }, - { 0, 40, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 2 }, - { 0, 52, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BINORMAL, 3 }, - D3DDECL_END() -}; - -struct VideoDX9SolidVertex -{ - FLOAT x, y, z; - FLOAT nx, ny, nz; - FLOAT tu, tv; - - static DWORD FVF; -}; - -DWORD VideoDX9SolidVertex::FVF = D3DFVF_XYZ | -D3DFVF_NORMAL | -D3DFVF_TEX1 | -D3DFVF_TEXCOORDSIZE2(0); - -struct VideoDX9LuminousVertex -{ - FLOAT x, y, z; - DWORD diffuse; - FLOAT tu, tv; - - static DWORD FVF; -}; - -DWORD VideoDX9LuminousVertex::FVF = D3DFVF_XYZ | -D3DFVF_DIFFUSE | -D3DFVF_TEX1 | -D3DFVF_TEXCOORDSIZE2(0); - -struct VideoDX9DetailVertex -{ - FLOAT x, y, z; - DWORD diffuse; - DWORD specular; - FLOAT tu, tv; - FLOAT tu1, tv1; - - static DWORD FVF; -}; - -DWORD VideoDX9DetailVertex::FVF = D3DFVF_XYZ | -D3DFVF_DIFFUSE | -D3DFVF_SPECULAR | -D3DFVF_TEX2; - -struct VideoDX9LineVertex -{ - FLOAT x, y, z; - DWORD diffuse; - - static DWORD FVF; -}; - -DWORD VideoDX9LineVertex::FVF = D3DFVF_XYZ | -D3DFVF_DIFFUSE; - -enum { - DX9_STRATEGY_NONE, - DX9_STRATEGY_SIMPLE, - DX9_STRATEGY_GLOW, - DX9_STRATEGY_SPECMAP, - DX9_STRATEGY_EMISSIVE, - DX9_STRATEGY_SPEC_EMISSIVE, - DX9_STRATEGY_BLEND, - DX9_STRATEGY_BLEND_DETAIL -}; - -// +--------------------------------------------------------------------+ - -static VideoDX9* video_dx9_instance = 0; - -VideoDX9::VideoDX9(const HWND& window, VideoSettings* vs) -: width(0), height(0), bpp(0), hwnd(window), surface(0), -d3d(0), d3ddevice(0), device_lost(false), fade(0), -zdepth(0), gamma(128), num_verts(0), first_vert(0), -current_texture(0), screen_vbuf(0), screen_ibuf(0), -font_verts(0), font_indices(0), font_nverts(0), -nlights(0), use_material(0), d3dx_font(0), -segment_material(0), strategy(0), passes(0), -screen_line_verts(0), line_verts(0), -vertex_declaration(0), -magic_fx(0), magic_fx_code(0), magic_fx_code_len(0) -{ - video_dx9_instance = this; - - Print("\n********************************\n"); - Print("* Direct 3D version 9 *\n"); - Print("********************************\n\n"); - - status = VIDEO_ERR; - HRESULT err = E_OUTOFMEMORY; - - d3d = Direct3DCreate9(D3D_SDK_VERSION); - dx9enum = new(__FILE__,__LINE__) VideoDX9Enum(d3d); - - if (d3d && dx9enum) { - if (vs) { - dx9enum->req_fullscreen = vs->is_windowed ? false : true; - dx9enum->req_windowed = vs->is_windowed ? true : false; - dx9enum->min_stencil_bits = vs->shadows ? 8 : 0; - dx9enum->uses_depth_buffer = true; - } - else { - dx9enum->req_fullscreen = video_settings.is_windowed ? false : true; - dx9enum->req_windowed = video_settings.is_windowed ? true : false; - dx9enum->min_stencil_bits = video_settings.shadows ? 8 : 0; - dx9enum->uses_depth_buffer = true; - } - - err = dx9enum->Enumerate(); - - if (FAILED(err)) { - VideoDX9Error("(ctor) could not enumerate dx9 properties", err); - delete dx9enum; - return; - } - } - else { - VideoDX9Error("(ctor) could not create enumerator", err); - return; - } - - SetVideoSettings(vs); - - if (video_settings.is_windowed) - dx9enum->SuggestWindowSettings(&video_settings); - else - dx9enum->SuggestFullscreenSettings(&video_settings); - - SetupParams(); - - if (VD3D_describe_things > 2) { - Print("\nD3DPRESENT_PARAMETERS:\n"); - Print(" BackBufferWidth: %d\n", d3dparams.BackBufferWidth); - Print(" BackBufferHeight: %d\n", d3dparams.BackBufferHeight); - Print(" BackBufferCount: %d\n", d3dparams.BackBufferCount); - Print(" BackBufferFormat: %s\n", VideoDX9DisplayMode::D3DFormatToString(d3dparams.BackBufferFormat)); - Print(" Multisample Type: %d\n", d3dparams.MultiSampleType); - Print(" Multisample Qual: %d\n", d3dparams.MultiSampleQuality); - Print(" Swap Effect: %d\n", d3dparams.SwapEffect); - Print(" Device Window: %08X\n", d3dparams.hDeviceWindow); - Print(" Windowed: %s\n", d3dparams.Windowed ? "true" : "false"); - Print(" Enable Depth/Stencil: %s\n", d3dparams.EnableAutoDepthStencil ? "true" : "false"); - Print(" Depth/Stencil Format: %s\n", VideoDX9DisplayMode::D3DFormatToString(d3dparams.AutoDepthStencilFormat)); - Print(" Flags: %08X\n", d3dparams.Flags); - Print(" Fullscreen Refresh: %d Hz\n", d3dparams.FullScreen_RefreshRateInHz); - - switch (d3dparams.PresentationInterval) { - case D3DPRESENT_INTERVAL_IMMEDIATE: - Print(" Present Interval: IMMEDIATE\n"); - break; - - case D3DPRESENT_INTERVAL_DEFAULT: - Print(" Present Interval: DEFAULT\n"); - break; - - case D3DPRESENT_INTERVAL_ONE: - Print(" Present Interval: ONE\n"); - break; - - case D3DPRESENT_INTERVAL_TWO: - Print(" Present Interval: TWO\n"); - break; - - case D3DPRESENT_INTERVAL_THREE: - Print(" Present Interval: THREE\n"); - break; - - case D3DPRESENT_INTERVAL_FOUR: - Print(" Present Interval: FOUR\n"); - break; - - default: - Print(" Present Interval: Unknown (%d)\n", d3dparams.PresentationInterval); - break; - } - - Print("\n"); - } - - Print(" Creating Video Device for HWND = %08x\n", window); - - err = d3d->CreateDevice(D3DADAPTER_DEFAULT, - D3DDEVTYPE_HAL, - window, - D3DCREATE_HARDWARE_VERTEXPROCESSING, - &d3dparams, - &d3ddevice); - - if (FAILED(err)) { - VideoDX9Error("(ctor) could not create device", err); - return; - } - - width = video_settings.GetWidth(); - height = video_settings.GetHeight(); - bpp = video_settings.GetDepth(); - - shadow_enabled = vs->shadows; - bump_enabled = vs->bumpmaps; - spec_enabled = vs->specmaps; - - render_state[FILL_MODE] = FILL_SOLID; - render_state[SHADE_MODE] = SHADE_GOURAUD; - render_state[Z_ENABLE] = false; - render_state[Z_WRITE_ENABLE] = false; - render_state[Z_BIAS] = 0; - render_state[TEXTURE_FILTER] = FILTER_LINEAR; - render_state[DITHER_ENABLE] = false; - render_state[SPECULAR_ENABLE] = true; - render_state[FOG_ENABLE] = false; - render_state[FOG_COLOR] = 0; - render_state[FOG_DENSITY] = 0; - render_state[STENCIL_ENABLE] = false; - render_state[TEXTURE_WRAP] = true; - render_state[LIGHTING_PASS] = 0; - - ZeroMemory(&rect, sizeof(rect)); - - if (!texcache) - texcache = new(__FILE__,__LINE__) TexCacheDX9(this); - - if (texcache) - texcache->count++; - - if (VD3D_describe_things > 0) { - DWORD vmf = VidMemFree() / (1024 * 1024); - Print(" Available Texture Memory: %d MB\n\n", vmf); - } - - if (CreateBuffers()) { - d3ddevice->SetRenderState(D3DRS_ALPHATESTENABLE, false); - d3ddevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL); - - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); - d3ddevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); - d3ddevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); - d3ddevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_NONE); - - status = VIDEO_OK; - } - - ZeroMemory(font_name, 64); - font_size = 0; - font_bold = false; - font_ital = false; -} - -// +--------------------------------------------------------------------+ - -VideoDX9::~VideoDX9() -{ - DestroyBuffers(); - - texcache->count--; - if (!texcache->count) { - delete texcache; - texcache = 0; - } - - delete environment_cube; - delete dx9enum; - - RELEASE(d3dx_font); - RELEASE(d3ddevice); - RELEASE(d3d); - - if (magic_fx_code) - delete [] magic_fx_code; - - Print(" VideoDX9: shutdown\n"); - video_dx9_instance = 0; -} - -IDirect3DDevice9* -VideoDX9::GetD3DDevice9() -{ - if (video_dx9_instance) - return video_dx9_instance->d3ddevice; - - return 0; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::SetupParams() -{ - if (!dx9enum || dx9enum->NumAdapters() < 1) { - status = VIDEO_ERR; - return false; - } - - int adapter_index = video_settings.GetAdapterIndex(); - - if (adapter_index < 0 || adapter_index >= dx9enum->NumAdapters()) { - ::Print("WARNING: VideoDX9 could not select adapter %d (max=%d)\n", - adapter_index, dx9enum->NumAdapters()); - - adapter_index = 0; - } - - dx9enum->SelectAdapter(adapter_index); - - d3dparams.Windowed = video_settings.IsWindowed(); - d3dparams.BackBufferCount = 2; - d3dparams.MultiSampleType = D3DMULTISAMPLE_NONE; - d3dparams.MultiSampleQuality = 0; - d3dparams.SwapEffect = D3DSWAPEFFECT_DISCARD; - d3dparams.EnableAutoDepthStencil = dx9enum->uses_depth_buffer; - d3dparams.hDeviceWindow = hwnd; - - if (dx9enum->uses_depth_buffer) { - d3dparams.Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL; - d3dparams.AutoDepthStencilFormat = (D3DFORMAT) video_settings.GetDepthStencilFormat(); - } - else { - d3dparams.Flags = 0; - } - - d3dparams.Flags |= D3DPRESENTFLAG_DEVICECLIP; - - if (video_settings.IsWindowed()) { - d3dparams.BackBufferWidth = video_settings.window_width; - d3dparams.BackBufferHeight = video_settings.window_height; - d3dparams.BackBufferFormat = (D3DFORMAT) video_settings.GetBackBufferFormat(); - d3dparams.FullScreen_RefreshRateInHz = 0; - d3dparams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; - } - else { - d3dparams.BackBufferWidth = video_settings.GetWidth(); - d3dparams.BackBufferHeight = video_settings.GetHeight(); - d3dparams.BackBufferFormat = (D3DFORMAT) video_settings.GetBackBufferFormat(); - d3dparams.FullScreen_RefreshRateInHz = video_settings.GetRefreshRate(); - d3dparams.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; - } - - return true; -} - - -bool -VideoDX9::IsModeSupported(int w, int h, int b) const -{ - if (dx9enum) - return dx9enum->IsModeSupported(w, h, b); - - return false; -} - -bool -VideoDX9::SetVideoSettings(const VideoSettings* vs) -{ - // custom video settings: - if (vs) { - if (vs != &video_settings) - CopyMemory(&video_settings, vs, sizeof(VideoSettings)); - } - - // default video settings: - else { - ZeroMemory(&video_settings, sizeof(VideoSettings)); - - video_settings.fullscreen_mode.width = 800; - video_settings.fullscreen_mode.height = 600; - video_settings.fullscreen_mode.format = VideoMode::FMT_X8R8G8B8; - } - - return true; -} - -bool -VideoDX9::Reset(const VideoSettings* vs) -{ - if (!d3ddevice || !SetVideoSettings(vs)) { - status = VIDEO_ERR; - return false; - } - - bool using_x_font = (d3dx_font != 0); - - RELEASE(d3dx_font); - InvalidateCache(); - DestroyBuffers(); - SetupParams(); - - HRESULT hr = d3ddevice->Reset(&d3dparams); - - if (FAILED(hr)) { - VideoDX9Error("could not reset d3d device", hr); - status = VIDEO_ERR; - return false; - } - - // Store render target surface desc - IDirect3DSurface9* back_buffer; - d3ddevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &back_buffer); - back_buffer->GetDesc(&back_buffer_desc); - RELEASE(back_buffer); - - width = video_settings.GetWidth(); - height = video_settings.GetHeight(); - bpp = video_settings.GetDepth(); - - shadow_enabled = vs->shadows; - bump_enabled = vs->bumpmaps; - spec_enabled = vs->specmaps; - - - if (CreateBuffers()) { - d3ddevice->SetRenderState(D3DRS_ALPHATESTENABLE, false); - d3ddevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL); - - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); - d3ddevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); - d3ddevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); - d3ddevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_NONE); - - D3DVIEWPORT9 view; - - hr = d3ddevice->GetViewport(&view); - if (SUCCEEDED(hr)) { - rect.x = view.X; - rect.y = view.Y; - rect.w = view.Width; - rect.h = view.Height; - } - - if (using_x_font) - UseXFont(font_name, font_size, font_bold, font_ital); - - status = VIDEO_OK; - } - - return status == VIDEO_OK; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::CreateBuffers() -{ - if (d3ddevice) { - UINT vertex_size = sizeof(VideoDX9ScreenVertex); - UINT index_size = sizeof(WORD); - - if (!screen_vbuf) { - screen_vbuf = new(__FILE__,__LINE__) VideoDX9VertexBuffer( - this, - NUM_SCREEN_VERTS, - vertex_size, - VideoDX9ScreenVertex::FVF, - D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY); - } - - if (!screen_ibuf) { - screen_ibuf = new(__FILE__,__LINE__) VideoDX9IndexBuffer( - this, - NUM_SCREEN_INDICES, - D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY); - } - - screen_line_verts = new(__FILE__,__LINE__) VideoDX9ScreenVertex[256]; - line_verts = new(__FILE__,__LINE__) VideoDX9LineVertex[512]; - - // create effects: - LPD3DXBUFFER code_buffer = 0; - DataLoader* loader = DataLoader::GetLoader(); - HRESULT hr = E_FAIL; - - hr = d3ddevice->CreateVertexDeclaration(videoDX9NormalVertexElements, - &vertex_declaration); - - // The E - We want to load our shader from the standard filesystem by default, to allow for better modding. - if (video_settings.use_effects && !magic_fx_code) { - FILE* f; - ::fopen_s(&f, "magic.fx", "rb"); - - if (f) { - ::fseek(f, 0, SEEK_END); - magic_fx_code_len = ftell(f); - ::fseek(f, 0, SEEK_SET); - - magic_fx_code = new(__FILE__,__LINE__) BYTE[magic_fx_code_len+1]; - if (magic_fx_code) { - ::fread(magic_fx_code, magic_fx_code_len, 1, f); - magic_fx_code[magic_fx_code_len] = 0; - } - ::fclose(f); - } else if (loader) { - magic_fx_code_len = loader->LoadBuffer("magic.fx", magic_fx_code, true, true); - } - } - - if (video_settings.use_effects && magic_fx_code && magic_fx_code_len) { - hr = D3DXCreateEffect(d3ddevice, - magic_fx_code, - magic_fx_code_len, - 0, 0, 0, 0, - &magic_fx, - &code_buffer); - - if (code_buffer) { - ::Print("ERROR - Failed to compile 'magic.fx'\n"); - ::Print((const char*) code_buffer->GetBufferPointer()); - ::Print("\n\n"); - RELEASE(code_buffer); - } - } - } - - return screen_vbuf && screen_ibuf; -} - -bool -VideoDX9::DestroyBuffers() -{ - if (line_verts) { - delete line_verts; - line_verts = 0; - } - - if (screen_line_verts) { - delete screen_line_verts; - screen_line_verts = 0; - } - - if (screen_vbuf) { - delete screen_vbuf; - screen_vbuf = 0; - } - - if (screen_ibuf) { - delete screen_ibuf; - screen_ibuf = 0; - } - - if (font_verts) { - delete [] font_verts; - font_verts = 0; - } - - if (font_indices) { - delete [] font_indices; - font_indices = 0; - } - - font_nverts = 0; - - RELEASE(vertex_declaration); - RELEASE(magic_fx); - - return true; -} - -// +--------------------------------------------------------------------+ - -DWORD -VideoDX9::VidMemFree() const -{ - UINT result = 0; - - if (d3ddevice) - result = d3ddevice->GetAvailableTextureMem(); - - return result; -} - -int -VideoDX9::MaxTexSize() const -{ - if (d3d && dx9enum && dx9enum->GetAdapterInfo()) { - VideoDX9DeviceInfo* dev_info = dx9enum->GetDeviceInfo(video_settings.GetDeviceType()); - - if (dev_info) { - return (int) dev_info->caps.MaxTextureWidth; - } - } - - return 0; -} - -int -VideoDX9::MaxTexAspect() const -{ - if (d3d && dx9enum && dx9enum->GetAdapterInfo()) { - VideoDX9DeviceInfo* dev_info = dx9enum->GetDeviceInfo(video_settings.GetDeviceType()); - - if (dev_info) { - return (int) dev_info->caps.MaxTextureAspectRatio; - } - } - - return 0; -} - -// +--------------------------------------------------------------------+ - -void -VideoDX9::RecoverSurfaces() -{ - Print("VideoDX9::RecoverSurfaces()\n"); - - HRESULT hr = D3D_OK; - - surface = 0; - - hr = d3ddevice->TestCooperativeLevel(); - - if (hr == D3DERR_DEVICELOST) { - // This means that some app took exclusive mode access - // we need to sit in a loop till we get back to the right mode. - Print("D3DERR_DEVICELOST\n"); - - do { - Sleep(500); - hr = d3ddevice->TestCooperativeLevel(); - } while (hr == D3DERR_DEVICELOST); - } - - if (hr == D3DERR_DEVICENOTRESET) { - if (Reset(&video_settings)) - hr = S_OK; - } - - if (SUCCEEDED(hr)) { - Print("* Invalidating Texture Cache\n"); - // Re-fill the contents of textures which just got restored: - InvalidateCache(); - - device_lost = false; - } - - Print("* Vid Mem Free: %8d\n", VidMemFree()); - Print("* Recover Surfaces Complete.\n\n"); -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::SetBackgroundColor(Color c) -{ - background = c; - return true; -} - -//----------------------------------------------------------------------------- -// RampValue -// -// The gamma function with inputs in [0,255], scaled to a range with the -// default range appropriate for D3DGAMMARAMP. -// -inline WORD -RampValue(UINT i, double recip_gamma, double fade) -{ - return (WORD) (65535.0 * fade * pow((double)i/255.f, recip_gamma)); -} - -//----------------------------------------------------------------------------- -// ReciprocalGamma -// -// Given a gamma corrected i in [0,255], return 1/gamma -// -inline float -ReciprocalGamma(UINT i) -{ - return logf(i/255.f)/logf(0.5f); -} - -//----------------------------------------------------------------------------- -// GammaValue -// -// Given a gamma corrected color channel value in [0,255], return the gamma. -// -inline float -GammaValue(UINT i) -{ - return logf(0.5f)/logf(i/255.f); -} - -bool -VideoDX9::SetGammaLevel(int g) -{ - HRESULT hr = E_FAIL; - double f = Color::GetFade(); - - if (gamma != g || fade != f) { - if (d3ddevice) { - //::Print("VideoDX9 - SetGammaLevel(%d) fade = %f\n", g, f); - - // compute 1/gamma - float recip_gray = ReciprocalGamma(g); - - // compute i**(1/gamma) for all i and scale to range - for (UINT i = 0; i < 256; i++) { - int val = RampValue(i, recip_gray, f); - - gamma_ramp.red[i] = val; - gamma_ramp.green[i] = val; - gamma_ramp.blue[i] = val; - } - - d3ddevice->SetGammaRamp(0, D3DSGR_NO_CALIBRATION, &gamma_ramp); - hr = D3D_OK; - } - - gamma = g; - fade = f; - } - - return SUCCEEDED(hr); -} - -bool -VideoDX9::SetObjTransform(const Matrix& orient, const Point& loc) -{ - HRESULT hr = E_FAIL; - - if (d3ddevice) { - D3DMATRIX world_matrix; - CreateD3DMatrix(world_matrix, orient, loc); - hr = d3ddevice->SetTransform(D3DTS_WORLD, &world_matrix); - - matrixWorld = world_matrix; - D3DXMatrixInverse(&matrixWorldInverse, 0, &matrixWorld); - } - - return SUCCEEDED(hr); -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::ClearAll() -{ - HRESULT err; - - err = d3ddevice->Clear(0, - NULL, - D3DCLEAR_TARGET | D3DCLEAR_STENCIL | D3DCLEAR_ZBUFFER, - background.Value(), - 1.0f, - 0); - - if (FAILED(err)) { - static int report = 10; - if (report > 0) { - VideoDX9Error("Failed to clear device", err); - report--; - } - } - - return true; -} - -bool -VideoDX9::ClearDepthBuffer() -{ - HRESULT err; - - err = d3ddevice->Clear(0, - NULL, - D3DCLEAR_STENCIL | D3DCLEAR_ZBUFFER, - 0, - 1.0f, - 0); - - if (FAILED(err)) { - static int report = 10; - if (report > 0) { - VideoDX9Error("Failed to clear depth buffer", err); - report--; - } - } - - return true; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::Present() -{ - // Show the frame on the primary surface. - HRESULT err = d3ddevice->Present( NULL, NULL, NULL, NULL ); - - if (FAILED(err)) { - if (err == D3DERR_DEVICELOST) { - device_lost = true; - } - - else { - static int report = 10; - if (report > 0) { - VideoDX9Error("Could not present frame", err); - report--; - } - } - } - - return true; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::Pause() -{ - return true; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::Resume() -{ - return true; -} - -// +--------------------------------------------------------------------+ - -void -VideoDX9::PreloadSurface(Surface* s) -{ - if (s) - PrepareSurface(s); -} - -void -VideoDX9::PreloadTexture(Bitmap* tex) -{ - if (texcache && tex) - texcache->FindTexture(tex); -} - -void -VideoDX9::InvalidateCache() -{ - ListIter<Model> iter = model_clients; - while (++iter) { - // remove each model from the list... - Model* model = iter.removeItem(); - - // ...so that the buffer destructor doesn't - // do it and mess up the iterator. - model->DeletePrivateData(); - } - - if (texcache) - texcache->InvalidateCache(); -} - -// +--------------------------------------------------------------------+ - -void -VideoDX9::CreateD3DMatrix(D3DMATRIX& result, const Matrix& m, const Point& p) -{ - result._11 = (float) m.elem[0][0]; - result._12 = (float) m.elem[1][0]; - result._13 = (float) m.elem[2][0]; - result._14 = 0.0f; - - result._21 = (float) m.elem[0][1]; - result._22 = (float) m.elem[1][1]; - result._23 = (float) m.elem[2][1]; - result._24 = 0.0f; - - result._31 = (float) m.elem[0][2]; - result._32 = (float) m.elem[1][2]; - result._33 = (float) m.elem[2][2]; - result._34 = 0.0f; - - result._41 = (float) p.x; - result._42 = (float) p.y; - result._43 = (float) p.z; - result._44 = 1.0f; -} - -void -VideoDX9::CreateD3DMatrix(D3DMATRIX& result, const Matrix& m, const Vec3& v) -{ - result._11 = (float) m.elem[0][0]; - result._12 = (float) m.elem[1][0]; - result._13 = (float) m.elem[2][0]; - result._14 = 0.0f; - - result._21 = (float) m.elem[0][1]; - result._22 = (float) m.elem[1][1]; - result._23 = (float) m.elem[2][1]; - result._24 = 0.0f; - - result._31 = (float) m.elem[0][2]; - result._32 = (float) m.elem[1][2]; - result._33 = (float) m.elem[2][2]; - result._34 = 0.0f; - - result._41 = v.x; - result._42 = v.y; - result._43 = v.z; - result._44 = 1.0f; -} - -void -VideoDX9::CreateD3DMaterial(D3DMATERIAL9& result, const Material& mtl) -{ - CopyMemory(&result.Diffuse, &mtl.Kd, sizeof(D3DCOLORVALUE)); - CopyMemory(&result.Ambient, &mtl.Ka, sizeof(D3DCOLORVALUE)); - CopyMemory(&result.Specular, &mtl.Ks, sizeof(D3DCOLORVALUE)); - CopyMemory(&result.Emissive, &mtl.Ke, sizeof(D3DCOLORVALUE)); - - result.Power = mtl.power; -} - - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::Capture(Bitmap& bmp) -{ - if (d3ddevice) { - HRESULT hr = E_FAIL; - LPDIRECT3DSURFACE9 pSurf=NULL, pTempSurf=NULL; - D3DSURFACE_DESC desc; - D3DDISPLAYMODE dm; - - // get display dimensions - // this will be the dimensions of the front buffer - hr = d3ddevice->GetDisplayMode(0, &dm); - - if (FAILED(hr)) - VideoDX9Error("VideoDX9::Capture - Can't get display mode!", hr); - - desc.Width = dm.Width; - desc.Height = dm.Height; - desc.Format = D3DFMT_A8R8G8B8; - - hr = d3ddevice->CreateOffscreenPlainSurface( - desc.Width, - desc.Height, - desc.Format, - D3DPOOL_SYSTEMMEM, - &pTempSurf, - NULL); - - if (FAILED(hr)) { - VideoDX9Error("VideoDX9::Capture - Cannot create offscreen buffer 1", hr); - return false; - } - - hr = d3ddevice->GetFrontBufferData(0, pTempSurf); - - if (FAILED(hr)) { - RELEASE(pTempSurf); - VideoDX9Error("VideoDX9::Capture - Can't get front buffer", hr); - return false; - } - - - if (video_settings.IsWindowed()) { - POINT pt={0, 0}; - RECT srcRect; - - // capture only the client area of the screen: - ::GetClientRect(hwnd, &srcRect); - ::ClientToScreen(hwnd, (LPPOINT) &srcRect); - srcRect.right += srcRect.left; - srcRect.bottom += srcRect.top; - - desc.Width = srcRect.right - srcRect.left; - desc.Height = srcRect.bottom - srcRect.top; - desc.Format = D3DFMT_A8R8G8B8; // this is what we get from the screen, so stick with it - - // NB we can't lock the back buffer direct because it's no created that way - // and to do so hits performance, so copy to another surface - // Must be the same format as the source surface - hr = d3ddevice->CreateOffscreenPlainSurface( - desc.Width, - desc.Height, - desc.Format, - D3DPOOL_DEFAULT, - &pSurf, - NULL); - - if (FAILED(hr)) { - RELEASE(pSurf); - VideoDX9Error("VideoDX9::Capture - Cannot create offscreen buffer 2", hr); - return false; - } - - // Copy - hr = d3ddevice->UpdateSurface(pTempSurf, &srcRect, pSurf, &pt); - - if (FAILED(hr)) { - RELEASE(pTempSurf); - RELEASE(pSurf); - VideoDX9Error("VideoDX9::Capture - Cannot update surface", hr); - return false; - } - - RELEASE(pTempSurf); - pTempSurf = pSurf; - pSurf = NULL; - } - - D3DLOCKED_RECT lockedRect; - hr = pTempSurf->LockRect(&lockedRect, NULL, - D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK); - - if (FAILED(hr)) { - VideoDX9Error("VideoDX9::Capture - can't lock rect", hr); - RELEASE(pTempSurf); - return false; - } - - // Allocate color buffer - DWORD* buffer = new DWORD[desc.Width * desc.Height]; - BYTE* src = (BYTE*) lockedRect.pBits; - BYTE* dst = (BYTE*) buffer; - Color clr; - - for (DWORD y = 0; y < desc.Height; y++) { - BYTE *pRow = src; - - for (DWORD x = 0; x < desc.Width; x++) { - switch(desc.Format) { - case D3DFMT_R5G6B5: - clr = Color::Unformat(*((WORD*) (pRow))); - - *dst++ = (BYTE) clr.Red(); - *dst++ = (BYTE) clr.Green(); - *dst++ = (BYTE) clr.Blue(); - *dst++ = 255; - break; - - case D3DFMT_A8R8G8B8: - case D3DFMT_X8R8G8B8: - *dst++ = pRow[0]; // R - *dst++ = pRow[1]; // G - *dst++ = pRow[2]; // B - *dst++ = 255; - - pRow += 4; - break; - - case D3DFMT_R8G8B8: - *dst++ = pRow[0]; // R - *dst++ = pRow[1]; // G - *dst++ = pRow[2]; // B - *dst++ = 255; - - pRow += 3; - break; - } - - } - - src += lockedRect.Pitch; - } - - bmp.CopyHighColorImage(desc.Width, desc.Height, buffer); - - delete [] buffer; - - RELEASE(pTempSurf); - RELEASE(pSurf); - - return SUCCEEDED(hr); - } - - return false; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::GetWindowRect(Rect& r) -{ - if (d3ddevice && (rect.w < 1 || rect.h < 1)) { - D3DVIEWPORT9 view; - HRESULT hr = d3ddevice->GetViewport(&view); - if (SUCCEEDED(hr)) { - rect.x = view.X; - rect.y = view.Y; - rect.w = view.Width; - rect.h = view.Height; - } - } - - r = rect; - return true; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::SetWindowRect(const Rect& r) -{ - return SetViewport(r.x, r.y, r.w, r.h); -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::SetViewport(int x, int y, int w, int h) -{ - if (!d3d || !d3ddevice) - return false; - - HRESULT hr; - - // set up the viewport according to args: - D3DVIEWPORT9 view; - - view.X = x; - view.Y = y; - view.Width = w; - view.Height = h; - view.MinZ = 0.0f; - view.MaxZ = 1.0f; - - hr = d3ddevice->SetViewport(&view); - if (FAILED(hr)) { - VideoDX9Error("could not initialize viewport", hr); - return false; - } - - // set up the render state: - for (int i = FILL_MODE; i < TEXTURE_WRAP; i++) { - if (d3dstate_table[i]) { - d3ddevice->SetRenderState((D3DRENDERSTATETYPE) d3dstate_table[i], render_state[i]); - } - } - - d3ddevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL); - - rect.x = x; - rect.y = y; - rect.w = w; - rect.h = h; - - return true; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::SetAmbient(Color c) -{ - ambient = c; - return true; -} - -bool -VideoDX9::SetLights(const List<Light>& lights) -{ - if (d3ddevice) { - main_light = 0; - back_light = 0; - - ListIter<Light> iter = (List<Light>&) lights; - int index = -1; - - while (++iter) { - Light* light = iter.value(); - - if (light->IsActive()) { - D3DLIGHT9 d3d_light; - ZeroMemory(&d3d_light, sizeof(d3d_light)); - d3d_light.Type = (D3DLIGHTTYPE) light->Type(); - - if (light->Type() == Light::LIGHT_DIRECTIONAL) { - Point light_location = light->Location(); - d3d_light.Direction.x = (float) (-light_location.x); - d3d_light.Direction.y = (float) (-light_location.y); - d3d_light.Direction.z = (float) (-light_location.z); - - if (d3d_light.Direction.x == 0 && - d3d_light.Direction.y == 0 && - d3d_light.Direction.z == 0) { - - d3d_light.Direction.y = -1; - } - - if (light->CastsShadow()) { - if (!main_light || light->Intensity() > main_light->Intensity()) - main_light = light; - } - else if (!back_light) { - back_light = light; - } - } - else { - d3d_light.Position.x = (float) ( light->Location().x); - d3d_light.Position.y = (float) ( light->Location().y); - d3d_light.Position.z = (float) ( light->Location().z); - } - - float r = (light->GetColor().Red() / 255.0f) * light->Intensity(); - float g = (light->GetColor().Green() / 255.0f) * light->Intensity(); - float b = (light->GetColor().Blue() / 255.0f) * light->Intensity(); - - d3d_light.Diffuse.r = r; - d3d_light.Diffuse.g = g; - d3d_light.Diffuse.b = b; - - d3d_light.Specular.r = r; - d3d_light.Specular.g = g; - d3d_light.Specular.b = b; - - d3d_light.Range = light->Intensity() * 10.0f; - d3d_light.Attenuation0 = 0.1f; - d3d_light.Attenuation1 = 0.7f; - d3d_light.Attenuation2 = 0.0f; - - index++; - d3ddevice->SetLight(index, &d3d_light); - d3ddevice->LightEnable(index, TRUE); - } - } - - // turn off any unused lights from before: - while (nlights > index+1) { - d3ddevice->LightEnable(--nlights, FALSE); - } - - nlights = index + 1; - - return true; - } - - return false; -} - -bool -VideoDX9::SetCamera(const Camera* cam) -{ - if (d3ddevice) { - camera = cam; - - D3DMATRIX m; - CreateD3DMatrix(m, cam->Orientation(), cam->Pos()); - d3ddevice->SetTransform(D3DTS_VIEW, &m); - matrixView = m; - - return true; - } - - return false; -} - -bool -VideoDX9::SetProjection(float fov, float znear, float zfar, DWORD type) -{ - if (d3ddevice && zfar > znear) { - D3DMATRIX m; - float h, w, Q; - - double width = (float) (rect.w); - double height = (float) (rect.h); - ZeroMemory(&m, sizeof(m)); - - /*** - *** PERSPECTIVE PROJECTION: - ***/ - - if (type == PROJECTION_PERSPECTIVE) { - double xscale = width / fov; - double yscale = height / fov; - - double maxscale = xscale; - if (yscale > xscale) maxscale = yscale; - - double xangle = atan(fov/2 * maxscale/xscale); - - w = (float) (2/tan(xangle)); // 1/tan(x) == cot(x) - h = (float) (w * width/height); - Q = zfar/(zfar - znear); - - m._11 = w; - m._22 = h; - m._33 = Q; - m._43 = -Q*znear; - m._34 = 1; - } - - /*** - *** ORTHOGONAL PROJECTION: - ***/ - - else if (type == PROJECTION_ORTHOGONAL) { - m._11 = (float) (fov/width); - m._22 = (float) (fov/height); - m._33 = (float) (1/(zfar-znear)); - m._43 = (float) (znear/(znear-zfar)); - m._44 = (float) (1); - } - - else { - return false; - } - - d3ddevice->SetTransform(D3DTS_PROJECTION, &m); - matrixProj = m; - - return true; - } - - return false; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::SetEnvironment(Bitmap** faces) -{ - if (environment_cube && !faces) { - delete environment_cube; - environment_cube = 0; - return true; - } - - if (!environment_cube) { - environment_cube = new(__FILE__,__LINE__) TexCubeDX9(this); - } - - if (environment_cube) { - bool ok = true; - for (int i = 0; i < 6; i++) - ok = ok && environment_cube->LoadTexture(faces[i], i); - return ok; - } - - return false; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::SetRenderState(RENDER_STATE state, DWORD value) -{ - if (!d3ddevice) - return false; - - if (render_state[state] == value || d3dstate_table[state] == 0) { - render_state[state] = value; - return true; - } - - HRESULT hr = E_FAIL; - - // special case for texture wrapping: - if (state == TEXTURE_WRAP) { - DWORD wrap = D3DTADDRESS_CLAMP; - - if (value) - wrap = D3DTADDRESS_WRAP; - - hr = d3ddevice->SetSamplerState(0, D3DSAMP_ADDRESSU, wrap); - hr = d3ddevice->SetSamplerState(0, D3DSAMP_ADDRESSV, wrap); - } - - // special case for fog enable: - else if (state == FOG_ENABLE) { - if (value) { - hr = d3ddevice->SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_EXP); - hr = d3ddevice->SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_NONE); - } - - hr = d3ddevice->SetRenderState(D3DRS_FOGENABLE, value); - } - - // special case for z bias - else if (state == Z_BIAS) { - if (value) { - FLOAT bias_scale = 1.0f; - FLOAT depth_bias = (FLOAT) (DW2I(value) / -10000.0); - - hr = d3ddevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, F2DW(bias_scale)); - hr = d3ddevice->SetRenderState(D3DRS_DEPTHBIAS, F2DW(depth_bias)); - } - else { - hr = d3ddevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0); - hr = d3ddevice->SetRenderState(D3DRS_DEPTHBIAS, 0); - } - } - - // set default z func along with z enable - else if (state == Z_ENABLE) { - hr = d3ddevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL); - hr = d3ddevice->SetRenderState(D3DRS_ZENABLE, value); - } - - // all other render states: - else { - hr = d3ddevice->SetRenderState((D3DRENDERSTATETYPE) d3dstate_table[state], value); - } - - if (FAILED(hr)) { - VideoDX9Error("could not SetRenderState", hr); - return false; - } - else { - render_state[state] = value; - } - - return true; -} - -bool -VideoDX9::SetBlendType(int blend_type) -{ - if (blend_type == current_blend_state) - return true; - - switch (blend_type) { - default: - // map misc blend types to SOLID - // and fall through to that case - - blend_type = BLEND_SOLID; - - case BLEND_SOLID: - d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false); - break; - - case BLEND_ALPHA: - d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true); - d3ddevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); - d3ddevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); - break; - - case BLEND_ADDITIVE: - d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true); - d3ddevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); - d3ddevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); - break; - } - - current_blend_state = blend_type; - return true; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::StartFrame() -{ - if (device_lost) { - RecoverSurfaces(); - - if (status != VIDEO_OK) - return false; - } - - stats.Clear(); - - HRESULT err = 0; - static int frame_number = 1; - static int report_errs = 100; - - stats.nframe = frame_number; - texcache->FrameNumber(frame_number++); - - // update gamma ramp for global fade value: - SetGammaLevel(gamma); - - ClearAll(); - - err = d3ddevice->BeginScene(); - - if (FAILED(err)) { - if (report_errs > 0) { - report_errs--; - VideoDX9Error("could not begin scene", err); - } - - return false; - } - - scene_active = 1; - current_blend_state = -1; - - SetRenderState(LIGHTING_PASS, 0); - SetRenderState(STENCIL_ENABLE, false); - - return true; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::EndFrame() -{ - HRESULT err = 0; - - if (scene_active) { - err = d3ddevice->EndScene(); - - if (FAILED(err)) { - VideoDX9Error("could not end scene", err); - return false; - } - } - - scene_active = 0; - return true; -} - -// +--------------------------------------------------------------------+ - -static DWORD ColorModulate(DWORD a, DWORD b) -{ - float a0 = (float) ((a ) & 0xff)/255.0f; - float a1 = (float) ((a>> 8) & 0xff)/255.0f; - float a2 = (float) ((a>>16) & 0xff)/255.0f; - float a3 = (float) ((a>>24) & 0xff)/255.0f; - - float b0 = (float) ((b ) & 0xff)/255.0f; - float b1 = (float) ((b>> 8) & 0xff)/255.0f; - float b2 = (float) ((b>>16) & 0xff)/255.0f; - float b3 = (float) ((b>>24) & 0xff)/255.0f; - - return (DWORD) ((BYTE)(a3*b3*255.0f) << 24) | - ((BYTE)(a2*b2*255.0f) << 16) | - ((BYTE)(a1*b1*255.0f) << 8) | - ((BYTE)(a0*b0*255.0f)); -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::PopulateScreenVerts(VertexSet* vset) -{ - if (!vset || !screen_vbuf) - return false; - - num_verts = vset->nverts; - - VideoDX9ScreenVertex* v = (VideoDX9ScreenVertex*) screen_vbuf->Lock(num_verts); - - if (v) { - first_vert = screen_vbuf->GetNextVert(); - - for (int i = 0; i < num_verts; i++) { - v->sx = vset->s_loc[i].x; - v->sy = vset->s_loc[i].y; - v->sz = vset->s_loc[i].z; - v->rhw = vset->rw[i]; - - v->diffuse = vset->diffuse[i]; - - v->tu = vset->tu[i]; - v->tv = vset->tv[i]; - - v++; - } - - screen_vbuf->Unlock(); - return true; - } - - Print(" VideoDX9: could not lock screen vbuf for %d verts.\n", num_verts); - return false; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::DrawPolys(int npolys, Poly* polys) -{ - bool result = false; - - if (d3ddevice && polys && npolys > 0) { - // screen space polys: - if (polys->vertex_set->space == VertexSet::SCREEN_SPACE) - return DrawScreenPolys(npolys, polys); - - // world space polys: - stats.ncalls++; - - VertexSet* vset = polys->vertex_set; - int nverts = vset->nverts; - bool luminous = false; - bool detail = false; - DWORD fvf = 0; - void* verts = 0; - int vsize = 0; - WORD* indices = new(__FILE__,__LINE__) WORD[npolys*6]; - - if (polys->material) { - luminous = polys->material->luminous; - } - - if (vset->tu1 != 0) { - VideoDX9DetailVertex* v = new(__FILE__,__LINE__) VideoDX9DetailVertex[nverts]; - verts = v; - vsize = sizeof(VideoDX9DetailVertex); - fvf = VideoDX9DetailVertex::FVF; - - for (int i = 0; i < nverts; i++) { - v->x = vset->loc[i].x; - v->y = vset->loc[i].y; - v->z = vset->loc[i].z; - - v->diffuse = vset->diffuse[i]; - v->specular = vset->specular[i]; - - v->tu = vset->tu[i]; - v->tv = vset->tv[i]; - v->tu1 = vset->tu1[i]; - v->tv1 = vset->tv1[i]; - - v++; - } - } - - else if (luminous) { - VideoDX9LuminousVertex* v = new(__FILE__,__LINE__) VideoDX9LuminousVertex[nverts]; - verts = v; - vsize = sizeof(VideoDX9LuminousVertex); - fvf = VideoDX9LuminousVertex::FVF; - - for (int i = 0; i < nverts; i++) { - v->x = vset->loc[i].x; - v->y = vset->loc[i].y; - v->z = vset->loc[i].z; - - v->diffuse = vset->diffuse[i]; - - v->tu = vset->tu[i]; - v->tv = vset->tv[i]; - - v++; - } - } - - else { - VideoDX9SolidVertex* v = new(__FILE__,__LINE__) VideoDX9SolidVertex[nverts]; - verts = v; - vsize = sizeof(VideoDX9SolidVertex); - fvf = VideoDX9SolidVertex::FVF; - - for (int i = 0; i < nverts; i++) { - v->x = vset->loc[i].x; - v->y = vset->loc[i].y; - v->z = vset->loc[i].z; - - v->nx = vset->nrm[i].x; - v->ny = vset->nrm[i].y; - v->nz = vset->nrm[i].z; - - v->tu = vset->tu[i]; - v->tv = vset->tv[i]; - - v++; - } - } - - if (verts && indices) { - HRESULT hr = E_FAIL; - - // fill index array - int num_indices = 0; - int num_tris = 0; - - WORD* s = indices; - Poly* p = polys; - - for (int i = 0; i < npolys; i++) { - if (p->nverts == 3) { - num_indices += 3; - num_tris += 1; - - *s++ = p->verts[0]; - *s++ = p->verts[1]; - *s++ = p->verts[2]; - } - - else if (p->nverts == 4) { - num_indices += 6; - num_tris += 2; - - *s++ = p->verts[0]; - *s++ = p->verts[1]; - *s++ = p->verts[2]; - - *s++ = p->verts[0]; - *s++ = p->verts[2]; - *s++ = p->verts[3]; - } - - p++; - } - - hr = d3ddevice->SetTransform(D3DTS_WORLD, &identity_matrix); - hr = d3ddevice->SetVertexShader(NULL); - hr = d3ddevice->SetFVF(fvf); - - // send primitives to the device - Material* mtl = polys->material; - IDirect3DTexture9* texture = 0; - - if (mtl && texcache && mtl->tex_diffuse) { - texture = texcache->FindTexture(mtl->tex_diffuse); - } - - if (current_texture != texture) { - hr = d3ddevice->SetTexture(0, texture); - current_texture = texture; - } - - if (mtl && texcache && mtl->tex_detail) { - texture = texcache->FindTexture(mtl->tex_detail); - hr = d3ddevice->SetTexture(1, texture); - } - - if (mtl && !luminous) { - D3DMATERIAL9 d3dmtl; - CreateD3DMaterial(d3dmtl, *mtl); - - hr = d3ddevice->SetMaterial(&d3dmtl); - hr = d3ddevice->SetRenderState(D3DRS_AMBIENT, ambient.Value()); - } - - // set render states and select buffers - SetRenderState(FILL_MODE, D3DFILL_SOLID); - SetRenderState(LIGHTING_ENABLE, luminous ? FALSE : TRUE); - SetBlendType(mtl->blend); - - d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); - d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); - - d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); - - - hr = d3ddevice->DrawIndexedPrimitiveUP( - D3DPT_TRIANGLELIST, - 0, - nverts, - num_tris, - indices, - D3DFMT_INDEX16, - verts, - vsize); - - if (FAILED(hr)) { - static int report = 10; - if (report-- > 0) - VideoDX9Error("Could not draw 3D polys.", hr); - } - - delete [] verts; - delete [] indices; - - if (SUCCEEDED(hr)) { - stats.nverts += nverts; - stats.npolys += num_tris; - result = true; - } - } - } - - return result; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::DrawScreenPolys(int npolys, Poly* polys, int blend) -{ - bool result = false; - HRESULT hr = E_FAIL; - - if (d3ddevice && polys && npolys > 0 && screen_vbuf && screen_ibuf) { - stats.ncalls++; - - // fill screen vertex buffer - if (!PopulateScreenVerts(polys->vertex_set)) - return false; - - // fill screen index buffer - int num_indices = 0; - int num_tris = 0; - - // count the number of indices needed for these polys - for (int i = 0; i < npolys; i++) { - Poly* p = polys + i; - - if (p->nverts == 3) { - num_indices += 3; - num_tris += 1; - } - - else if (p->nverts == 4) { - num_indices += 6; - num_tris += 2; - } - } - - WORD* screen_indices = screen_ibuf->Lock(num_indices); - int first_index = screen_ibuf->GetNextIndex(); - - if (!screen_indices) { - Print(" VideoDX9: could not lock screen ibuf for %d indices.\n", num_indices); - return false; - } - - // copy the indices into the locked index buffer - WORD* s = screen_indices; - Poly* p = polys; - - for (int i = 0; i < npolys; i++) { - if (p->nverts == 3) { - *s++ = p->verts[0] + first_vert; - *s++ = p->verts[1] + first_vert; - *s++ = p->verts[2] + first_vert; - } - else if (p->nverts == 4) { - *s++ = p->verts[0] + first_vert; - *s++ = p->verts[1] + first_vert; - *s++ = p->verts[2] + first_vert; - - *s++ = p->verts[0] + first_vert; - *s++ = p->verts[2] + first_vert; - *s++ = p->verts[3] + first_vert; - } - - p++; - } - - screen_ibuf->Unlock(); - - // set render states and select buffers - SetRenderState(FILL_MODE, D3DFILL_SOLID); - SetRenderState(Z_ENABLE, D3DZB_FALSE); - SetRenderState(Z_WRITE_ENABLE, D3DZB_FALSE); - SetRenderState(LIGHTING_ENABLE, FALSE); - SetBlendType(blend); - - d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); - d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); - - d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); - - // send primitives to the device - Material* mtl = polys->material; - IDirect3DTexture9* texture = 0; - - if (mtl && texcache && mtl->tex_diffuse) { - texture = texcache->FindTexture(mtl->tex_diffuse); - } - - if (current_texture != texture) { - hr = d3ddevice->SetTexture(0, texture); - current_texture = texture; - } - - screen_vbuf->Select(0); - screen_ibuf->Select(); - hr = d3ddevice->SetVertexShader(NULL); - hr = d3ddevice->SetFVF(VideoDX9ScreenVertex::FVF); - - hr = d3ddevice->DrawIndexedPrimitive( - D3DPT_TRIANGLELIST, - 0, - first_vert, - num_verts, - first_index, - num_tris); - - if (FAILED(hr)) { - static int report = 10; - if (report-- > 0) - VideoDX9Error("Could not draw screen polys.", hr); - } - else { - stats.nverts += num_verts; - stats.npolys += num_tris; - result = true; - } - } - - return result; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::DrawSolid(Solid* s, DWORD blend_modes) -{ - bool result = false; - HRESULT hr = E_FAIL; - - if (d3ddevice && s && s->GetModel()) { - Model* model = s->GetModel(); - Matrix orient = s->Orientation(); - orient.Transpose(); - - D3DMATRIX world_matrix; - CreateD3DMatrix(world_matrix, orient, s->Location()); - d3ddevice->SetTransform(D3DTS_WORLD, &world_matrix); - matrixWorld = world_matrix; - D3DXMatrixInverse(&matrixWorldInverse, 0, &matrixWorld); - - ListIter<Surface> surf_iter = model->GetSurfaces(); - while (++surf_iter) { - Surface* surf = surf_iter.value(); - - if (surf->IsHidden() || surf->IsSimplified()) - continue; - - if (PrepareSurface(surf)) { - result = true; - - VideoDX9SurfaceData* surf_data = (VideoDX9SurfaceData*) surf->GetVideoPrivateData(); - surf_data->vertex_buffer->Select(0); - surf_data->index_buffer->Select(); - - ListIter<Segment> seg_iter = surf->GetSegments(); - while (++seg_iter) { - Segment* segment = seg_iter.value(); - Material* mtl = segment->material; - - if (mtl && (blend_modes & mtl->blend)) { - result = result && DrawSegment(segment); - } - } - } - } - } - - surface_has_tangent_data = false; - - return result; -} - -bool -VideoDX9::DrawSegment(Segment* segment) -{ - bool result = false; - bool detail = false; - bool luminous = false; - HRESULT hr = E_FAIL; - - if (segment && segment->video_data) { - stats.ncalls++; - - VideoDX9SegmentData* seg_data = (VideoDX9SegmentData*) segment->video_data; - int first_vert = seg_data->first_vert; - int num_verts = seg_data->num_verts; - int first_index = seg_data->first_index; - int num_tris = seg_data->num_tris; - - if (segment->model) - luminous = segment->model->IsLuminous(); - - // set render states and select buffers - d3ddevice->SetRenderState(D3DRS_AMBIENT, ambient.Value()); - - Material* mtl = segment->material; - - if (use_material) - mtl = use_material; - - if (segment->polys && segment->polys->vertex_set && segment->polys->vertex_set->tu1) - detail = true; - - // send primitives to the device - if (detail) { - hr = d3ddevice->SetVertexShader(NULL); - hr = d3ddevice->SetFVF(VideoDX9DetailVertex::FVF); - } - - else if (luminous) { - hr = d3ddevice->SetVertexShader(NULL); - hr = d3ddevice->SetFVF(VideoDX9LuminousVertex::FVF); - } - - else if (surface_has_tangent_data && vertex_declaration) { - hr = d3ddevice->SetVertexDeclaration(vertex_declaration); - hr = d3ddevice->SetVertexShader(NULL); - } - - else { - hr = d3ddevice->SetVertexShader(NULL); - hr = d3ddevice->SetFVF(VideoDX9SolidVertex::FVF); - } - - if (render_state[FILL_MODE] == FILL_WIREFRAME) { - PrepareMaterial(mtl); - SetupPass(0); - - for (int i = 0; i < segment->npolys; i++) { - DrawPolyOutline(segment->polys + i); - } - } - - else if (luminous) { - PrepareMaterial(mtl); - - SetRenderState(FILL_MODE, D3DFILL_SOLID); - SetRenderState(LIGHTING_ENABLE, FALSE); - SetBlendType(mtl->blend); - - for (int pass = 0; pass < passes; pass++) { - SetupPass(pass); - - hr = d3ddevice->DrawIndexedPrimitive( - D3DPT_TRIANGLELIST, - 0, - first_vert, - num_verts, - first_index, - num_tris); - } - - d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); - } - - else { - PrepareMaterial(mtl); - - if (strategy == DX9_STRATEGY_GLOW && render_state[LIGHTING_PASS] > 0) { - hr = 0; - } - - else if (magic_fx && strategy < DX9_STRATEGY_BLEND && !detail) { - DWORD vs_version = 0; - DWORD ps_version = 0; - bool shaders_ok = false; - - VideoDX9DeviceInfo* dev_info = dx9enum->GetDeviceInfo(video_settings.GetDeviceType()); - - if (dev_info) { - vs_version = video_settings.enable_vs ? dev_info->caps.VertexShaderVersion : 0; - ps_version = video_settings.enable_ps ? dev_info->caps.PixelShaderVersion : 0; - - if (vs_version >= D3DVS_VERSION(1,1)) - shaders_ok = true; - } - - if (surface_has_tangent_data && vertex_declaration) { - hr = d3ddevice->SetVertexShader(NULL); - hr = d3ddevice->SetVertexDeclaration(vertex_declaration); - } - - else { - hr = d3ddevice->SetVertexShader(NULL); - hr = d3ddevice->SetFVF(VideoDX9SolidVertex::FVF); - } - - bool would_bump = !IsBumpMapEnabled() && mtl->bump > 0.5; - - bool will_bump = IsBumpMapEnabled() && surface_has_tangent_data && shaders_ok && camera; - - bool do_pix = will_bump && render_state[LIGHTING_PASS] == 0; - bool do_bump = will_bump && render_state[LIGHTING_PASS] > 0; - - D3DXMATRIX matrixWVP = matrixWorld * matrixView * matrixProj; - - D3DXVECTOR4 eyePos( (float) camera->Pos().x, (float) camera->Pos().y, (float) camera->Pos().z, 1.0f); - - D3DXVECTOR4 eyeObj; - D3DXVec4Transform(&eyeObj, &eyePos, &matrixWorldInverse); - - D3DXVECTOR4 lightPos(100.0f, 100.0f, 100.0f, 1.0f); - D3DXVECTOR4 lightColor(1,1,1,1); - D3DXVECTOR4 ambientColor(0,0,0,1); - - ambientColor.x = ambient.fRed(); - ambientColor.y = ambient.fGreen(); - ambientColor.z = ambient.fBlue(); - - if (main_light && (render_state[LIGHTING_PASS] > 0 || mtl->blend > Material::MTL_SOLID)) { - lightPos.x = (float) main_light->Location().x; - lightPos.y = (float) main_light->Location().y; - lightPos.z = (float) main_light->Location().z; - - if (mtl->tex_bumpmap && do_bump) - D3DXVec4Transform(&lightPos, &lightPos, &matrixWorldInverse); - - lightColor.x = main_light->GetColor().fRed() * main_light->Intensity(); - lightColor.y = main_light->GetColor().fGreen() * main_light->Intensity(); - lightColor.z = main_light->GetColor().fBlue() * main_light->Intensity(); - lightColor.w = 1.0f; - } - - else if (back_light && render_state[LIGHTING_PASS] == 0) { - lightPos.x = (float) back_light->Location().x; - lightPos.y = (float) back_light->Location().y; - lightPos.z = (float) back_light->Location().z; - - lightColor.x = back_light->GetColor().fRed() * back_light->Intensity(); - lightColor.y = back_light->GetColor().fGreen() * back_light->Intensity(); - lightColor.z = back_light->GetColor().fBlue() * back_light->Intensity(); - lightColor.w = 1.0f; - } - - D3DXVECTOR4 lightDir = D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f) - lightPos; - D3DXVec4Normalize(&lightDir, &lightDir); - - magic_fx->SetMatrix("wvp", &matrixWVP); - magic_fx->SetMatrix("world", &matrixWorld); - magic_fx->SetMatrix("view", &matrixView); - magic_fx->SetMatrix("proj", &matrixProj); - magic_fx->SetMatrix("worldInv", &matrixWorldInverse); - - magic_fx->SetVector("light1Pos", &lightPos); - magic_fx->SetVector("light1Dir", &lightDir); - magic_fx->SetVector("light1Color", &lightColor); - magic_fx->SetVector("ambientColor", &ambientColor); - magic_fx->SetVector("eyeObj", &eyeObj); - - FLOAT base_bias = (FLOAT) (DW2I(render_state[Z_BIAS]) / -10000.0); - magic_fx->SetFloat("bias", base_bias + video_settings.depth_bias); - - ColorValue orig_ks = mtl->Ks; - - if (would_bump && mtl->specular_value >= 0.5) - mtl->Ks = mtl->Ks * 0.3; - - magic_fx->SetValue("Ka", &mtl->Ka, sizeof(ColorValue)); - magic_fx->SetValue("Kd", &mtl->Kd, sizeof(ColorValue)); - magic_fx->SetValue("Ke", &mtl->Ke, sizeof(ColorValue)); - magic_fx->SetValue("Ks", &mtl->Ks, sizeof(ColorValue)); - magic_fx->SetFloat("Ns", mtl->power); - - if (would_bump && mtl->specular_value >= 0.5) - mtl->Ks = orig_ks; - - if (mtl->tex_diffuse) { - IDirect3DTexture9* texture = texcache->FindTexture(mtl->tex_diffuse); - magic_fx->SetTexture("tex_d", texture); - } else { - magic_fx->SetTexture("tex_d", 0); - } - - if (mtl->tex_emissive) { - IDirect3DTexture9* texture = texcache->FindTexture(mtl->tex_emissive); - magic_fx->SetTexture("tex_e", texture); - } else { - magic_fx->SetTexture("tex_e", 0); - } - - if (mtl->tex_specular && IsSpecMapEnabled()) { - IDirect3DTexture9* texture = texcache->FindTexture(mtl->tex_specular); - magic_fx->SetTexture("tex_s", texture); - } else { - magic_fx->SetTexture("tex_s", 0); - } - - if (mtl->tex_bumpmap && do_bump) { - IDirect3DTexture9* texture = texcache->FindNormalMap(mtl->tex_bumpmap, mtl->bump); - magic_fx->SetTexture("tex_n", texture); - magic_fx->SetFloat("offsetAmp", mtl->bump / mtl->tex_bumpmap->Height()); - } else if (mtl->tex_bumpmap && !do_bump) { - IDirect3DTexture9* texture = texcache->FindTexture(mtl->tex_bumpmap); - magic_fx->SetTexture("tex_x", texture); - } else { - magic_fx->SetTexture("tex_x", 0); - } - - const char* mtl_shader = mtl->GetShader(render_state[LIGHTING_PASS]); - D3DXHANDLE hnd_shader = 0; - - if (mtl_shader) { - if (!strcmp(mtl_shader, "null")) - return true; - - hnd_shader = magic_fx->GetTechniqueByName(mtl_shader); - } - - if (hnd_shader) { - hr = magic_fx->SetTechnique(hnd_shader); - } else { - if (will_bump) { - if (mtl->tex_specular && IsSpecMapEnabled()) { - if (mtl->tex_bumpmap && do_bump) { - if (ps_version >= D3DPS_VERSION(2,0)) - hr = magic_fx->SetTechnique("BumpSpecMapPix"); - else - hr = magic_fx->SetTechnique("BumpSpecMap"); - } else if (mtl->tex_emissive && render_state[LIGHTING_PASS] == 0) { - if (ps_version >= D3DPS_VERSION(2,0)) - hr = magic_fx->SetTechnique("EmissiveSpecMapPix"); - else - hr = magic_fx->SetTechnique("EmissiveSpecularTexture"); - } else { - if (ps_version >= D3DPS_VERSION(2,0)) - hr = magic_fx->SetTechnique("SpecMapPix"); - else - hr = magic_fx->SetTechnique("SpecularTexture"); - } - } else { - if (mtl->tex_bumpmap && do_bump) { - if (ps_version >= D3DPS_VERSION(2,0)) - hr = magic_fx->SetTechnique("BumpMapPix"); - else - hr = magic_fx->SetTechnique("BumpMap"); - } else if (mtl->tex_emissive && render_state[LIGHTING_PASS] == 0) { - if (ps_version >= D3DPS_VERSION(2,0)) - hr = magic_fx->SetTechnique("EmissivePix"); - else - hr = magic_fx->SetTechnique("EmissiveTexture"); - } else { - if (ps_version >= D3DPS_VERSION(2,0)) - hr = magic_fx->SetTechnique("SimplePix"); - else - hr = magic_fx->SetTechnique("SimpleTexture"); - } - } - } - - else if (texcache && mtl->tex_diffuse) { - if (mtl->tex_specular && IsSpecMapEnabled()) { - if (mtl->tex_emissive && render_state[LIGHTING_PASS] == 0) { - hr = magic_fx->SetTechnique("EmissiveSpecularTexture"); - } else { - hr = magic_fx->SetTechnique("SpecularTexture"); - } - } - - else { - if (mtl->tex_emissive && render_state[LIGHTING_PASS] == 0) { - hr = magic_fx->SetTechnique("EmissiveTexture"); - } else { - hr = magic_fx->SetTechnique("SimpleTexture"); - } - } - } else { - hr = magic_fx->SetTechnique("SimpleMaterial"); - } - } - - if (environment_cube != 0 && magic_fx->IsParameterUsed("env_cube", hnd_shader)) { - D3DXMATRIX env_matrix; - D3DXMatrixIdentity(&env_matrix); - - magic_fx->SetMatrix("env_matrix", &env_matrix); - magic_fx->SetTexture("env_cube", environment_cube->GetTexture()); - } - - if (render_state[STENCIL_ENABLE]) { - d3ddevice->SetRenderState(D3DRS_STENCILENABLE, TRUE); - d3ddevice->SetRenderState(D3DRS_STENCILREF, 0x01); - d3ddevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_GREATER); - } else { - d3ddevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); - } - - if (render_state[LIGHTING_PASS] > 0) { - current_blend_state = 100; - SetBlendType(BLEND_ADDITIVE); - SetRenderState(Z_WRITE_ENABLE, FALSE); - } else { - current_blend_state = 100; - SetBlendType(mtl->blend); - } - - UINT nPasses = 0; - - hr = magic_fx->Begin(&nPasses, 0); - - for (UINT i = 0; i < nPasses; i++) { - hr = magic_fx->BeginPass(i); - - hr = d3ddevice->DrawIndexedPrimitive( - D3DPT_TRIANGLELIST, - 0, - first_vert, - num_verts, - first_index, - num_tris); - - hr = magic_fx->EndPass(); - } - - hr = magic_fx->End(); - } else { - for (int pass = 0; pass < passes; pass++) { - SetupPass(pass); - - hr = d3ddevice->DrawIndexedPrimitive( - D3DPT_TRIANGLELIST, - 0, - first_vert, - num_verts, - first_index, - num_tris); - - if (detail) { - hr = d3ddevice->SetVertexShader(NULL); - hr = d3ddevice->SetFVF(VideoDX9DetailVertex::FVF); - } else if (luminous) { - hr = d3ddevice->SetVertexShader(NULL); - hr = d3ddevice->SetFVF(VideoDX9LuminousVertex::FVF); - } else if (surface_has_tangent_data && vertex_declaration) { - hr = d3ddevice->SetVertexShader(NULL); - hr = d3ddevice->SetVertexDeclaration(vertex_declaration); - } else { - hr = d3ddevice->SetVertexShader(NULL); - hr = d3ddevice->SetFVF(VideoDX9SolidVertex::FVF); - } - } - } - } - - if (FAILED(hr)) { - static int report = 10; - if (report-- > 0) - VideoDX9Error("Could not draw solid polys.", hr); - } else { - stats.nverts += num_verts; - stats.npolys += num_tris; - result = true; - } - } - - return result; -} - -bool -VideoDX9::DrawPolyOutline(Poly* p) -{ - if (d3ddevice && p && p->nverts >= 3) { - static VideoDX9LineVertex verts[8]; - - int nlines = p->nverts; - VertexSet* vset = p->vertex_set; - WORD index = 0; - Color color = Color::Black; - HRESULT hr = E_FAIL; - - ZeroMemory(verts, sizeof(verts)); - - if (p->material) - color = p->material->Kd.ToColor(); - - for (int i = 0; i < p->nverts; i++) { - index = p->verts[i]; - - verts[i].x = vset->loc[index].x; - verts[i].y = vset->loc[index].y; - verts[i].z = vset->loc[index].z; - verts[i].diffuse = color.Value(); - } - - // last vertex, to close the loop - index = p->verts[0]; - int i = p->nverts; - - verts[i].x = vset->loc[index].x; - verts[i].y = vset->loc[index].y; - verts[i].z = vset->loc[index].z; - verts[i].diffuse = color.Value(); - - current_texture = 0; - - hr = d3ddevice->SetVertexShader(NULL); - hr = d3ddevice->SetFVF(VideoDX9LineVertex::FVF); - hr = d3ddevice->SetTexture(0, 0); - hr = d3ddevice->DrawPrimitiveUP( - D3DPT_LINESTRIP, - nlines, - verts, - sizeof(VideoDX9LineVertex)); - return true; - } - - return false; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::DrawShadow(Solid* s, int nverts, Vec3* shadow_verts, bool visible) -{ - bool result = false; - HRESULT hr = E_FAIL; - - if (d3ddevice && s && nverts && shadow_verts && IsShadowEnabled()) { - Matrix orient = s->Orientation(); - orient.Transpose(); - - D3DMATRIX world_matrix; - CreateD3DMatrix(world_matrix, orient, s->Location()); - d3ddevice->SetTransform(D3DTS_WORLD, &world_matrix); - matrixWorld = world_matrix; - - // show shadow outlines: - if (visible) { - static VideoDX9LineVertex verts[4]; - - d3ddevice->SetRenderState(D3DRS_ZENABLE, TRUE); - d3ddevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); - d3ddevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL); - d3ddevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT); - d3ddevice->SetRenderState(D3DRS_LIGHTING, FALSE); - d3ddevice->SetVertexShader(NULL); - d3ddevice->SetFVF(VideoDX9LineVertex::FVF); - d3ddevice->SetTexture(0, 0); - - SetBlendType(BLEND_ALPHA); - - for (int i = 0; i < nverts; i+=3) { - DWORD c = 0xa0ffff80; - - verts[0].x = shadow_verts[i+0].x; - verts[0].y = shadow_verts[i+0].y; - verts[0].z = shadow_verts[i+0].z; - verts[0].diffuse = c; - - verts[1].x = shadow_verts[i+1].x; - verts[1].y = shadow_verts[i+1].y; - verts[1].z = shadow_verts[i+1].z; - verts[1].diffuse = c; - - verts[2].x = shadow_verts[i+2].x; - verts[2].y = shadow_verts[i+2].y; - verts[2].z = shadow_verts[i+2].z; - verts[2].diffuse = c; - - verts[3].x = shadow_verts[i+0].x; - verts[3].y = shadow_verts[i+0].y; - verts[3].z = shadow_verts[i+0].z; - verts[3].diffuse = c; - - hr = d3ddevice->DrawPrimitiveUP( - D3DPT_LINESTRIP, - 3, - verts, - sizeof(VideoDX9LineVertex)); - } - - // restore lighting state - d3ddevice->SetRenderState(D3DRS_LIGHTING, render_state[LIGHTING_ENABLE]); - } - - // render shadows into stencil buffer: - - // Disable z-buffer writes (note: z-testing still occurs), and enable the - // stencil-buffer - d3ddevice->SetRenderState(D3DRS_ZENABLE, TRUE); - d3ddevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); - d3ddevice->SetRenderState(D3DRS_STENCILENABLE, TRUE); - - // Dont bother with interpolating color - d3ddevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT); - - // Set up stencil compare fuction, reference value, and masks. - // Stencil test passes if ((ref & mask) cmpfn (stencil & mask)) is true. - // Note: since we set up the stencil-test to always pass, the STENCILFAIL - // renderstate is really not needed. - d3ddevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS ); - d3ddevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP ); - d3ddevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP ); - - // If z-test passes, inc/decrement stencil buffer value - d3ddevice->SetRenderState(D3DRS_STENCILREF, 0x1 ); - d3ddevice->SetRenderState(D3DRS_STENCILMASK, 0xff ); - d3ddevice->SetRenderState(D3DRS_STENCILWRITEMASK, 0xff ); - d3ddevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_INCR ); - - // Make sure that no pixels get drawn to the frame buffer - d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE ); - d3ddevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO ); - d3ddevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE ); - - d3ddevice->SetVertexShader(NULL); - d3ddevice->SetFVF(D3DFVF_XYZ); - - // Draw front-side of shadow volume in stencil/z only - hr = d3ddevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, nverts/3, shadow_verts, sizeof(Vec3)); - - // Now reverse cull order so back sides of shadow volume are written. - d3ddevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW ); - - // Decrement stencil buffer value - d3ddevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_DECR ); - - // Draw back-side of shadow volume in stencil/z only - hr = d3ddevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, nverts/3, shadow_verts, sizeof(Vec3)); - - // restore render states - d3ddevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD); - d3ddevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); - d3ddevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE); - d3ddevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); - - // force restore of current blend type - int type = current_blend_state; - current_blend_state = 100; - SetBlendType(type); - - result = SUCCEEDED(hr); - } - - return result; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::DrawLines(int nlines, Vec3* points, Color c, int blend) -{ - bool result = false; - - if (d3ddevice && points && nlines > 0 && nlines <= 256) { - stats.ncalls++; - - VideoDX9LineVertex* verts = line_verts; - - if (verts) { - HRESULT hr = E_FAIL; - - for (int i = 0; i < 2*nlines; i++) { - VideoDX9LineVertex* v = verts + i; - Vec3* p = points + i; - - v->x = p->x; - v->y = p->y; - v->z = p->z; - v->diffuse = c.Value(); - } - - hr = d3ddevice->SetTransform(D3DTS_WORLD, &identity_matrix); - hr = d3ddevice->SetVertexShader(NULL); - hr = d3ddevice->SetFVF(VideoDX9LineVertex::FVF); - - DWORD old_lighting = render_state[LIGHTING_ENABLE]; - - // untextured lines: - if (current_texture) { - d3ddevice->SetTexture(0, 0); - current_texture = 0; - } - - SetRenderState(LIGHTING_ENABLE, FALSE); - SetBlendType(blend); - - hr = d3ddevice->DrawPrimitiveUP( - D3DPT_LINELIST, - nlines, - verts, - sizeof(VideoDX9LineVertex)); - - if (FAILED(hr)) { - static int report = 10; - if (report-- > 0) - VideoDX9Error("Could not draw 3D lines.", hr); - } - - SetRenderState(LIGHTING_ENABLE, old_lighting); - - if (SUCCEEDED(hr)) { - stats.nverts += 2*nlines; - stats.nlines += nlines; - result = true; - } - } - } - - return result; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::DrawScreenLines(int nlines, float* points, Color c, int blend) -{ - bool result = false; - - if (d3ddevice && points && nlines > 0 && nlines <= 64) { - stats.ncalls++; - - VideoDX9ScreenVertex* verts = screen_line_verts; - - if (verts) { - HRESULT hr = E_FAIL; - - for (int i = 0; i < 2*nlines; i++) { - VideoDX9ScreenVertex* v = verts + i; - - v->sx = points[2*i + 0]; - v->sy = points[2*i + 1]; - v->sz = 0.0f; - v->rhw = 1.0f; - v->diffuse = c.Value(); - v->tu = 0.0f; - v->tv = 0.0f; - } - - hr = d3ddevice->SetVertexShader(NULL); - hr = d3ddevice->SetFVF(VideoDX9ScreenVertex::FVF); - - if (FAILED(hr)) { - static int report = 10; - if (report-- > 0) - VideoDX9Error("Could not set FVF for screen lines.", hr); - } - - else { - if (current_texture != 0) { - hr = d3ddevice->SetTexture(0, 0); - current_texture = 0; - } - - SetRenderState(FILL_MODE, D3DFILL_SOLID); - SetRenderState(Z_ENABLE, D3DZB_FALSE); - SetRenderState(LIGHTING_ENABLE, FALSE); - SetBlendType(blend); - - hr = d3ddevice->DrawPrimitiveUP( - D3DPT_LINELIST, - nlines, - verts, - sizeof(VideoDX9ScreenVertex)); - - if (FAILED(hr)) { - static int report = 10; - if (report-- > 0) - VideoDX9Error("Could not draw screen lines.", hr); - } - } - - if (SUCCEEDED(hr)) { - stats.nverts += 2*nlines; - stats.nlines += nlines; - result = true; - } - } - } - - return result; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::DrawPoints(VertexSet* vset) -{ - if (vset && vset->nverts) { - HRESULT hr = E_FAIL; - - int nverts = vset->nverts; - VideoDX9LineVertex* verts = new(__FILE__,__LINE__) VideoDX9LineVertex[nverts]; - - if (verts) { - for (int i = 0; i < nverts; i++) { - VideoDX9LineVertex* v = verts + i; - Vec3* p = vset->loc + i; - - v->x = p->x; - v->y = p->y; - v->z = p->z; - v->diffuse = vset->diffuse[i]; - } - - SetRenderState(LIGHTING_ENABLE, FALSE); - - hr = d3ddevice->SetTransform(D3DTS_WORLD, &identity_matrix); - hr = d3ddevice->SetVertexShader(NULL); - hr = d3ddevice->SetFVF(VideoDX9LineVertex::FVF); - hr = d3ddevice->SetTexture(0, 0); - hr = d3ddevice->DrawPrimitiveUP( - D3DPT_POINTLIST, - nverts, - verts, - sizeof(VideoDX9LineVertex)); - - delete [] verts; - return true; - } - } - - return false; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::UseMaterial(Material* m) -{ - use_material = m; - return true; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::UseXFont(const char* name, int size, bool bold, bool ital) -{ - if (d3ddevice && name && *name && size > 4) { - RELEASE(d3dx_font); - - strcpy_s(font_name, name); - font_size = size; - font_bold = bold; - font_ital = ital; - - HRESULT hr = E_FAIL; - HDC hdc = GetDC(NULL); - int nLogPixelsY = GetDeviceCaps(hdc, LOGPIXELSY); - - ReleaseDC(NULL, hdc); - - int nHeight = -size * nLogPixelsY / 72; - - hr = D3DXCreateFont(d3ddevice, // D3D device - nHeight, // Height - 0, // Width - bold ? FW_BOLD : FW_NORMAL, // Weight - 1, // MipLevels, 0 = autogen mipmaps - ital, // Italic - DEFAULT_CHARSET, // CharSet - OUT_DEFAULT_PRECIS, // OutputPrecision - DEFAULT_QUALITY, // Quality - DEFAULT_PITCH | FF_DONTCARE, // PitchAndFamily - name, // pFaceName - &d3dx_font); // ppFont - - if (SUCCEEDED(hr)) { - return true; - } - } - - RELEASE(d3dx_font); - return false; -} - -bool -VideoDX9::DrawText(const char* text, int count, const Rect& rect, DWORD format, Color c) -{ - if (d3ddevice && text && *text && d3dx_font) { - RECT r; - r.left = rect.x; - r.top = rect.y; - r.right = rect.x + rect.w; - r.bottom = rect.y + rect.h; - - d3dx_font->DrawText(0, text, count, &r, format, c.Value()); - } - - return false; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::PrepareSurface(Surface* surf) -{ - if (surf) { - int nverts = surf->NumVerts(); - int nindices = surf->NumIndices(); - bool detail = surf->GetVertexSet()->tu1 != 0; - bool luminous = false; - DWORD dynamic = 0; - - if (surf->GetModel()) { - luminous = surf->GetModel()->IsLuminous(); - dynamic = surf->GetModel()->IsDynamic() ? D3DUSAGE_DYNAMIC : 0; - } - - surface_has_tangent_data = !luminous && (surf->GetVertexSet()->tangent && surf->GetVertexSet()->binormal); - - VideoDX9SurfaceData* surf_data = (VideoDX9SurfaceData*) surf->GetVideoPrivateData(); - - if (!surf_data) { - surf_data = new(__FILE__,__LINE__) VideoDX9SurfaceData(surf->GetModel()); - - surface_has_tangent_data = false; - - if (surf->GetVertexSet()->tangent && surf->GetVertexSet()->binormal) { - surface_has_tangent_data = true; - surf_data->vertex_buffer = new(__FILE__,__LINE__) VideoDX9VertexBuffer( - this, - nverts, - sizeof(VideoDX9NormalVertex), - 0, // not an FVF vertex buffer - dynamic | D3DUSAGE_WRITEONLY); - } - - else if (detail) { - surf_data->vertex_buffer = new(__FILE__,__LINE__) VideoDX9VertexBuffer( - this, - nverts, - sizeof(VideoDX9DetailVertex), - VideoDX9DetailVertex::FVF, - dynamic | D3DUSAGE_WRITEONLY); - } - - else if (luminous) { - surf_data->vertex_buffer = new(__FILE__,__LINE__) VideoDX9VertexBuffer( - this, - nverts, - sizeof(VideoDX9LuminousVertex), - VideoDX9LuminousVertex::FVF, - dynamic | D3DUSAGE_WRITEONLY); - } - - else { - surf_data->vertex_buffer = new(__FILE__,__LINE__) VideoDX9VertexBuffer( - this, - nverts, - sizeof(VideoDX9SolidVertex), - VideoDX9SolidVertex::FVF, - dynamic | D3DUSAGE_WRITEONLY); - } - - surf_data->index_buffer = new(__FILE__,__LINE__) VideoDX9IndexBuffer( - this, - nindices, - dynamic | D3DUSAGE_WRITEONLY); - - if (!surf_data->vertex_buffer || !surf_data->index_buffer) { - Print("VideoDX9: Unable to prepare surface '%s'\n", surf->Name()); - delete surf_data; - return false; - } - - surf->SetVideoPrivateData(surf_data); - } - - if (surf_data && !surf_data->IsValid()) { - if (detail) { - VideoDX9DetailVertex* v = (VideoDX9DetailVertex*) surf_data->vertex_buffer->Lock(nverts); - - if (v) { - const VertexSet* vset = surf->GetVertexSet(); - for (int i = 0; i < nverts; i++) { - v->x = vset->loc[i].x; - v->y = vset->loc[i].y; - v->z = vset->loc[i].z; - - v->diffuse = vset->diffuse[i]; - v->specular = vset->specular[i]; - - v->tu = vset->tu[i]; - v->tv = vset->tv[i]; - v->tu1 = vset->tu1[i]; - v->tv1 = vset->tv1[i]; - - v++; - } - - surf_data->vertex_buffer->Unlock(); - } - } - - else if (luminous) { - VideoDX9LuminousVertex* v = (VideoDX9LuminousVertex*) surf_data->vertex_buffer->Lock(nverts); - - if (v) { - const VertexSet* vset = surf->GetVertexSet(); - for (int i = 0; i < nverts; i++) { - v->x = vset->loc[i].x; - v->y = vset->loc[i].y; - v->z = vset->loc[i].z; - - v->diffuse = vset->diffuse[i]; - - v->tu = vset->tu[i]; - v->tv = vset->tv[i]; - - v++; - } - - surf_data->vertex_buffer->Unlock(); - } - } - - else if (surface_has_tangent_data) { - VideoDX9NormalVertex* v = (VideoDX9NormalVertex*) surf_data->vertex_buffer->Lock(nverts); - - if (v) { - const VertexSet* vset = surf->GetVertexSet(); - for (int i = 0; i < nverts; i++) { - v->x = vset->loc[i].x; - v->y = vset->loc[i].y; - v->z = vset->loc[i].z; - - v->nx = vset->nrm[i].x; - v->ny = vset->nrm[i].y; - v->nz = vset->nrm[i].z; - - v->t0u = vset->tu[i]; - v->t0v = vset->tv[i]; - v->t1u = vset->tu[i]; - v->t1v = vset->tv[i]; - - v->tx = vset->tangent[i].x; - v->ty = vset->tangent[i].y; - v->tz = vset->tangent[i].z; - - v->bx = vset->binormal[i].x; - v->by = vset->binormal[i].y; - v->bz = vset->binormal[i].z; - - v++; - } - - surf_data->vertex_buffer->Unlock(); - } - } - - else { - VideoDX9SolidVertex* v = (VideoDX9SolidVertex*) surf_data->vertex_buffer->Lock(nverts); - - if (v) { - const VertexSet* vset = surf->GetVertexSet(); - for (int i = 0; i < nverts; i++) { - v->x = vset->loc[i].x; - v->y = vset->loc[i].y; - v->z = vset->loc[i].z; - - v->nx = vset->nrm[i].x; - v->ny = vset->nrm[i].y; - v->nz = vset->nrm[i].z; - - v->tu = vset->tu[i]; - v->tv = vset->tv[i]; - - v++; - } - - surf_data->vertex_buffer->Unlock(); - } - } - - WORD* indices = surf_data->index_buffer->Lock(nindices); - - if (indices) { - // copy the indices into the locked index buffer - WORD* s = indices; - Poly* p = surf->GetPolys(); - - for (int i = 0; i < surf->NumPolys(); i++) { - if (p->nverts == 3) { - *s++ = p->verts[0]; - *s++ = p->verts[2]; - *s++ = p->verts[1]; - } - else if (p->nverts == 4) { - *s++ = p->verts[0]; - *s++ = p->verts[2]; - *s++ = p->verts[1]; - - *s++ = p->verts[0]; - *s++ = p->verts[3]; - *s++ = p->verts[2]; - } - - p++; - } - - surf_data->index_buffer->Unlock(); - } - - surf_data->Validate(); - } - - int first_index = 0; - - ListIter<Segment> seg_iter = surf->GetSegments(); - while (++seg_iter) { - Segment* segment = seg_iter.value(); - - if (!segment->video_data) { - VideoDX9SegmentData* seg_data = new(__FILE__,__LINE__) VideoDX9SegmentData; - - int num_tris = 0; - for (int i = 0; i < segment->npolys; i++) - num_tris += segment->polys[i].nverts-2; - - seg_data->first_vert = 0; - seg_data->num_verts = surf->NumVerts(); - seg_data->first_index = first_index; - seg_data->num_tris = num_tris; - - segment->video_data = seg_data; - - first_index += num_tris * 3; - } - } - } - - return true; -} - -// +--------------------------------------------------------------------+ - -int -VideoDX9::PrepareMaterial(Material* m) -{ - segment_material = m; - strategy = 0; - passes = 0; - - if (m) { - int max_stages = 1; - int max_textures = 1; - bool multiply_add = false; - bool dotproduct3 = false; - bool vertexshader = false; - bool pixelshader = false; - DWORD vs_version = 0; - DWORD ps_version = 0; - - VideoDX9DeviceInfo* dev_info = dx9enum->GetDeviceInfo(video_settings.GetDeviceType()); - - if (dev_info) { - max_stages = (int) dev_info->caps.MaxTextureBlendStages; - max_textures = (int) dev_info->caps.MaxSimultaneousTextures; - multiply_add = (dev_info->caps.TextureOpCaps & D3DTEXOPCAPS_MULTIPLYADD) ? true : false; - dotproduct3 = (dev_info->caps.TextureOpCaps & D3DTEXOPCAPS_DOTPRODUCT3) ? true : false; - - vs_version = video_settings.enable_vs ? dev_info->caps.VertexShaderVersion : 0; - ps_version = video_settings.enable_ps ? dev_info->caps.PixelShaderVersion : 0; - - vertexshader = vs_version >= D3DVS_VERSION(1,1); - pixelshader = ps_version >= D3DPS_VERSION(2,0); - } - - strategy = DX9_STRATEGY_SIMPLE; - passes = 1; - - if (m->tex_alternate) { - if (m->tex_detail && max_textures > 2 && max_stages > 4) - strategy = DX9_STRATEGY_BLEND_DETAIL; - - else if (max_textures > 1 && max_stages > 3) - strategy = DX9_STRATEGY_BLEND; - } - - else if (m->tex_emissive && (!m->tex_diffuse || m->tex_diffuse == m->tex_emissive)) { - strategy = DX9_STRATEGY_GLOW; - } - - else if (IsSpecMapEnabled() && m->tex_specular && !m->tex_emissive) { - strategy = DX9_STRATEGY_SPECMAP; - - if (max_textures < 2 || max_stages < 2 || !multiply_add) - passes = 2; - } - - else if ((!IsSpecMapEnabled() || !m->tex_specular) && m->tex_emissive) { - strategy = DX9_STRATEGY_EMISSIVE; - - if (max_textures < 2 || max_stages < 2) - passes = 2; - } - - else if (IsSpecMapEnabled() && m->tex_specular && m->tex_emissive) { - strategy = DX9_STRATEGY_SPEC_EMISSIVE; - - if (max_textures < 2 || max_stages < 2) - passes = 3; - - else if (max_textures < 3 || max_stages < 3 || !multiply_add) - passes = 2; - } - } - - return passes; -} - -bool -VideoDX9::SetupPass(int pass) -{ - if (pass < 0 || pass >= passes) - return false; - - if (pass == 0) { - D3DMATERIAL9 d3dmtl; - IDirect3DTexture9* texture_0 = 0; - IDirect3DTexture9* texture_1 = 0; - IDirect3DTexture9* texture_2 = 0; - Bitmap* tex_bmp_0 = 0; - Bitmap* tex_bmp_1 = 0; - Bitmap* tex_bmp_2 = 0; - ColorValue orig_spec = segment_material->Ks; - HRESULT hr = E_FAIL; - - if (segment_material->tex_specular && passes > 1) - segment_material->Ks = Color::Black; - - CreateD3DMaterial(d3dmtl, *segment_material); - segment_material->Ks = orig_spec; - - hr = d3ddevice->SetMaterial(&d3dmtl); - - if (strategy == DX9_STRATEGY_SIMPLE) { - tex_bmp_0 = segment_material->tex_diffuse; - } - - else if (strategy == DX9_STRATEGY_BLEND) { - tex_bmp_0 = segment_material->tex_diffuse; - tex_bmp_1 = segment_material->tex_alternate; - } - - else if (strategy == DX9_STRATEGY_BLEND_DETAIL) { - tex_bmp_0 = segment_material->tex_diffuse; - tex_bmp_1 = segment_material->tex_alternate; - tex_bmp_2 = segment_material->tex_detail; - } - - else if (strategy == DX9_STRATEGY_SPECMAP) { - if (passes == 1) { - tex_bmp_0 = segment_material->tex_diffuse; - tex_bmp_1 = segment_material->tex_specular; - } - else { - tex_bmp_0 = segment_material->tex_diffuse; - } - } - - else if (strategy == DX9_STRATEGY_EMISSIVE && passes == 1 || - strategy == DX9_STRATEGY_SPEC_EMISSIVE && passes == 2) { - if (segment_material->tex_diffuse) { - tex_bmp_0 = segment_material->tex_diffuse; - tex_bmp_1 = segment_material->tex_emissive; - } - else { - tex_bmp_0 = segment_material->tex_emissive; - } - } - - else { - tex_bmp_0 = segment_material->tex_emissive; - } - - if (texcache && tex_bmp_0) { - texture_0 = texcache->FindTexture(tex_bmp_0); - - hr = d3ddevice->SetTexture(0, texture_0); - current_texture = texture_0; - - if (tex_bmp_1) { - texture_1 = texcache->FindTexture(tex_bmp_1); - hr = d3ddevice->SetTexture(1, texture_1); - - if (tex_bmp_2) { - texture_2 = texcache->FindTexture(tex_bmp_2); - hr = d3ddevice->SetTexture(2, texture_2); - } - } - } - else { - hr = d3ddevice->SetTexture(0, 0); - current_texture = 0; - } - - SetBlendType(segment_material->blend); - - if (texture_0 && texture_1 && strategy == DX9_STRATEGY_BLEND) { - d3ddevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); - d3ddevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); - d3ddevice->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); - - d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); - d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE); - - d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_BLENDCURRENTALPHA); - d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT); - d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_TEXTURE); - d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_CURRENT); - d3ddevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0); - - d3ddevice->SetTextureStageState(2, D3DTSS_COLOROP, D3DTOP_MODULATE); - d3ddevice->SetTextureStageState(2, D3DTSS_COLORARG1, D3DTA_CURRENT); - d3ddevice->SetTextureStageState(2, D3DTSS_COLORARG2, D3DTA_DIFFUSE); - d3ddevice->SetTextureStageState(2, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - d3ddevice->SetTextureStageState(2, D3DTSS_ALPHAARG1, D3DTA_CURRENT); - - d3ddevice->SetTextureStageState(3, D3DTSS_COLOROP, D3DTOP_DISABLE); - } - - else if (texture_0 && texture_1 && texture_2 && strategy == DX9_STRATEGY_BLEND_DETAIL) { - d3ddevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); - d3ddevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); - d3ddevice->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); - d3ddevice->SetSamplerState(2, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); - d3ddevice->SetSamplerState(2, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); - d3ddevice->SetSamplerState(2, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); - - d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); - d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE); - d3ddevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0); - - d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_BLENDCURRENTALPHA); - d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT); - d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_TEXTURE); - d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_CURRENT); - d3ddevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0); - - d3ddevice->SetTextureStageState(2, D3DTSS_COLOROP, D3DTOP_BLENDTEXTUREALPHA); - d3ddevice->SetTextureStageState(2, D3DTSS_COLORARG1, D3DTA_TEXTURE); - d3ddevice->SetTextureStageState(2, D3DTSS_COLORARG2, D3DTA_CURRENT); - d3ddevice->SetTextureStageState(2, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - d3ddevice->SetTextureStageState(2, D3DTSS_ALPHAARG1, D3DTA_CURRENT); - d3ddevice->SetTextureStageState(2, D3DTSS_TEXCOORDINDEX, 1); - - d3ddevice->SetTextureStageState(3, D3DTSS_COLOROP, D3DTOP_MODULATE); - d3ddevice->SetTextureStageState(3, D3DTSS_COLORARG1, D3DTA_CURRENT); - d3ddevice->SetTextureStageState(3, D3DTSS_COLORARG2, D3DTA_DIFFUSE); - d3ddevice->SetTextureStageState(3, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - d3ddevice->SetTextureStageState(3, D3DTSS_ALPHAARG1, D3DTA_CURRENT); - } - - else if (texture_0 && strategy == DX9_STRATEGY_GLOW) { - d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); - d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT); - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); - } - - else if (texture_0) { - d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); - d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT); - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); - } - - if (texture_1 && strategy == DX9_STRATEGY_SPECMAP) { - d3ddevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); - d3ddevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); - d3ddevice->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); - - d3ddevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0); - d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MULTIPLYADD); - d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE); - d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_SPECULAR); - d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); - } - - else if (texture_1 && strategy == DX9_STRATEGY_EMISSIVE) { - d3ddevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); - d3ddevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); - d3ddevice->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); - - d3ddevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0); - d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_ADD); - d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE); - d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT); - d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); - } - - else if (texture_1 && strategy == DX9_STRATEGY_SPEC_EMISSIVE) { - d3ddevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); - d3ddevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); - d3ddevice->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); - - d3ddevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0); - d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_ADD); - d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE); - d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT); - d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); - } - - else if (strategy < DX9_STRATEGY_BLEND) { - d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); - } - } - - else if (pass == 1) { - D3DMATERIAL9 d3dmtl; - IDirect3DTexture9* texture = 0; - Bitmap* tex_bmp = 0; - ColorValue orig_Ka = segment_material->Ka; - ColorValue orig_Kd = segment_material->Kd; - HRESULT hr = E_FAIL; - - if (segment_material->tex_specular) { - segment_material->Ka = Color::Black; - segment_material->Kd = Color::Black; - } - - CreateD3DMaterial(d3dmtl, *segment_material); - - segment_material->Ka = orig_Ka; - segment_material->Kd = orig_Kd; - - hr = d3ddevice->SetMaterial(&d3dmtl); - - if (strategy == DX9_STRATEGY_SPECMAP || - strategy == DX9_STRATEGY_SPEC_EMISSIVE) { - tex_bmp = segment_material->tex_specular; - d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); - d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_SPECULAR); - } - - else if (strategy == DX9_STRATEGY_EMISSIVE) { - tex_bmp = segment_material->tex_emissive; - d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); - d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - } - - d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); - - if (texcache && tex_bmp) { - texture = texcache->FindTexture(tex_bmp); - hr = d3ddevice->SetTexture(0, texture); - current_texture = texture; - - SetBlendType(BLEND_ADDITIVE); - } - } - - if (render_state[STENCIL_ENABLE]) { - d3ddevice->SetRenderState(D3DRS_STENCILENABLE, TRUE); - d3ddevice->SetRenderState(D3DRS_STENCILREF, 0x01); - d3ddevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_GREATER); - } - else { - d3ddevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); - } - - if (render_state[LIGHTING_PASS] > 0) { - SetBlendType(BLEND_ADDITIVE); - SetRenderState(Z_WRITE_ENABLE, FALSE); - } - - return true; -} - - -// +--------------------------------------------------------------------+ - -void -VideoDX9Error(const char* msg, HRESULT err) -{ - Print(" VideoDX9: %s. [%s]\n", msg, D3DErrStr(err)); -} - -char* D3DErrStr(HRESULT hr) -{ - static char errstrbuf[128]; - - switch (hr) { - default: - sprintf_s(errstrbuf, "Unrecognized error value = %08x.", hr); - return errstrbuf; - - case D3D_OK: - return "No error."; - - case D3DERR_WRONGTEXTUREFORMAT: - return "Wrong texture format."; - - case D3DERR_UNSUPPORTEDCOLOROPERATION: - return "Unsupported color operation."; - - case D3DERR_UNSUPPORTEDCOLORARG: - return "Unsupported color argument."; - - case D3DERR_UNSUPPORTEDALPHAOPERATION: - return "Unsupported alpha operation."; - - case D3DERR_UNSUPPORTEDALPHAARG: - return "Unsupported alpha argument."; - - case D3DERR_TOOMANYOPERATIONS: - return "Too many operations."; - - case D3DERR_CONFLICTINGTEXTUREFILTER: - return "Conflicting texture filter."; - - case D3DERR_UNSUPPORTEDFACTORVALUE: - return "Unsupported factor value."; - - case D3DERR_CONFLICTINGRENDERSTATE: - return "Conflicting render state."; - - case D3DERR_UNSUPPORTEDTEXTUREFILTER: - return "Unsupported texture filter."; - - case D3DERR_CONFLICTINGTEXTUREPALETTE: - return "Conflicting texture palette."; - - case D3DERR_DRIVERINTERNALERROR: - return "Driver internal error."; - - - case D3DERR_NOTFOUND: - return "Resource was not found."; - - case D3DERR_MOREDATA: - return "More data?"; - - case D3DERR_DEVICELOST: - return "Device lost."; - - case D3DERR_DEVICENOTRESET: - return "Device is not reset."; - - case D3DERR_NOTAVAILABLE: - return "Not available."; - - case D3DERR_OUTOFVIDEOMEMORY: - return "Out of video memory."; - - case E_OUTOFMEMORY: - return "Out of system memory."; - - case D3DERR_INVALIDDEVICE: - return "Invalid device selection."; - - case D3DERR_INVALIDCALL: - return "Invalid call or parameter."; - - case D3DERR_DRIVERINVALIDCALL: - return "Driver invalid call."; - - case D3DERR_WASSTILLDRAWING: - return "The device was still drawing."; - - case D3DOK_NOAUTOGEN: - return "Autogeneration is not supported by this device."; - - } -} - |