static void dx11_acquire_back_buffer(RenderDevice* dev) { // Get default back buffer D3D_CALL( dev->swap_chain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&dev->backbuffer_tex) ); D3D_CALL( dev->native->CreateRenderTargetView(dev->backbuffer_tex, NULL, &dev->backbuffer_rtv) ); // Create default depth buffer // create depth stencil D3D11_TEXTURE2D_DESC depth_stencil_desc; depth_stencil_desc.Width = dev->window->width(); depth_stencil_desc.Height = dev->window->height(); depth_stencil_desc.MipLevels = 1; depth_stencil_desc.ArraySize = 1; depth_stencil_desc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; depth_stencil_desc.SampleDesc.Count = 1; depth_stencil_desc.SampleDesc.Quality = 0; depth_stencil_desc.Usage = D3D11_USAGE_DEFAULT; depth_stencil_desc.BindFlags = D3D11_BIND_DEPTH_STENCIL; depth_stencil_desc.CPUAccessFlags = 0; depth_stencil_desc.MiscFlags = 0; D3D_CALL( dev->native->CreateTexture2D(&depth_stencil_desc, NULL, &dev->depthstencil_tex) ); // create depth stencil view D3D11_DEPTH_STENCIL_VIEW_DESC depth_stencil_view_desc = CD3D11_DEPTH_STENCIL_VIEW_DESC(); depth_stencil_view_desc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; depth_stencil_view_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; depth_stencil_view_desc.Texture2D.MipSlice = 0; depth_stencil_view_desc.Flags = 0; D3D_CALL( dev->native->CreateDepthStencilView(dev->depthstencil_tex, &depth_stencil_view_desc, &dev->depthstencil_dsv) ); }
// I'm assuming it called with the render states set as they will be during rendering... void CD3D_Device::PreCalcSomeDeviceCaps() { if (!m_pD3DDevice) return; // Fix some issues on ATI cards if( m_pAdapter->AdapterID.VendorId == 0x1002 ) { g_pStruct->RunConsoleString( "Use0WeightsForDisable 1" ); } // Check for TableFog... if ((m_DeviceCaps.RasterCaps & D3DPRASTERCAPS_FOGTABLE) && ((m_DeviceCaps.RasterCaps & D3DPRASTERCAPS_ZFOG) || (m_DeviceCaps.RasterCaps & D3DPRASTERCAPS_WFOG)) && g_CV_TableFog.m_Val) { m_ExtraDevCaps.m_bUsingTableFog = true; } else { m_ExtraDevCaps.m_bUsingTableFog = false; } // Check for stencil buffer & get the format... LPDIRECT3DSURFACE9 pDepthStencilBuffer = NULL; D3D_CALL(m_pD3DDevice->GetDepthStencilSurface(&pDepthStencilBuffer)); if (pDepthStencilBuffer) { D3DSURFACE_DESC SurfDesc; // SurfDesc.Size = sizeof(SurfDesc); D3D_CALL(pDepthStencilBuffer->GetDesc(&SurfDesc)); m_ExtraDevCaps.m_DepthStencilBufferFormat = SurfDesc.Format; uint32 iZDepth,iStencilDepth; d3d_GetDepthStencilBits(m_ExtraDevCaps.m_DepthStencilBufferFormat,iZDepth,iStencilDepth); m_ExtraDevCaps.m_bHasStencilBuffer = (iStencilDepth>0 ? true : false); int iRefCnt = pDepthStencilBuffer->Release(); } }
void Gfx_Context_SetTechnique(RenderContext* rc, TechniqueHandle h) { const TechniqueDX11& t = rc->resources->techniques[h]; rc->native->IASetInputLayout(t.input_layout); rc->native->PSSetShader(rc->resources->pixel_shaders[t.ps].native, NULL, 0); rc->native->VSSetShader(rc->resources->vertex_shaders[t.vs].native, NULL, 0); // set constants in a stupid way, emulating GLES2 behavior Vector4 ps_constant_data[MaxShaderConstants]; Vector4 vs_constant_data[MaxShaderConstants]; int32 psc_dirty_first = MaxShaderConstants; int32 psc_dirty_last = 0; for( uint32 i=0; i<t.ps_bindings.size(); ++i ) { int32 first = (int32)t.ps_bindings[i].index; int32 count = (int32)t.ps_bindings[i].count; int32 last = first+count; rush_memcpy(&ps_constant_data[first], (const float*)t.ps_bindings[i].data, sizeof(Vector4)*count); psc_dirty_first = rush_min(psc_dirty_first, first); psc_dirty_last = rush_max(psc_dirty_last, last); } int32 vsc_dirty_first = MaxShaderConstants; int32 vsc_dirty_last = 0; for( uint32 i=0; i<t.vs_bindings.size(); ++i ) { int32 first = (int32)t.vs_bindings[i].index; int32 count = (int32)t.vs_bindings[i].count; int32 last = first+count; rush_memcpy(&vs_constant_data[first], (const float*)t.vs_bindings[i].data, sizeof(Vector4)*count); vsc_dirty_first = rush_min(vsc_dirty_first, first); vsc_dirty_last = rush_max(vsc_dirty_last, last); } if( psc_dirty_first!=MaxShaderConstants ) { D3D11_MAPPED_SUBRESOURCE mr; D3D_CALL(rc->native->Map(rc->ps_cb, 0, D3D11_MAP_WRITE_DISCARD, 0, &mr)); Vector4* data_v4f = (Vector4*)mr.pData; rush_memcpy(&data_v4f[psc_dirty_first], &ps_constant_data[psc_dirty_first], sizeof(Vector4)*(psc_dirty_last-psc_dirty_first)); rc->native->Unmap(rc->ps_cb, 0); rc->native->PSSetConstantBuffers(0, 1, &rc->ps_cb); } if( vsc_dirty_first!=MaxShaderConstants ) { D3D11_MAPPED_SUBRESOURCE mr; D3D_CALL(rc->native->Map(rc->vs_cb, 0, D3D11_MAP_WRITE_DISCARD, 0, &mr)); Vector4* data_v4f = (Vector4*)mr.pData; rush_memcpy(&data_v4f[vsc_dirty_first], &vs_constant_data[vsc_dirty_first], sizeof(Vector4)*(vsc_dirty_last-vsc_dirty_first)); rc->native->Unmap(rc->vs_cb, 0); rc->native->VSSetConstantBuffers(0, 1, &rc->vs_cb); } }
// Call before you start rendering a frame... bool CD3D_Device::Start3D() { CSAccess cLoadRenderCSLock(&g_Device.GetLoadRenderCS()); if (g_Device.m_bIn3D || !g_Device.m_pD3DDevice) return false; HRESULT hResult = D3D_CALL(g_Device.m_pD3DDevice->BeginScene()); g_Device.m_bIn3D = (hResult == D3D_OK); D3D_CALL(g_Device.m_pD3DDevice->SetVertexShader(NULL)); D3D_CALL(g_Device.m_pD3DDevice->SetFVF(D3DFVF_XYZ)); return g_Device.m_bIn3D; }
// blend state BlendStateHandle Gfx_BlendState_Create(RenderDevice* dev, const BlendStateDescr& descr) { D3D11_BLEND_DESC desc_dx11; desc_dx11.AlphaToCoverageEnable = FALSE; desc_dx11.IndependentBlendEnable = FALSE; desc_dx11.RenderTarget[0].BlendEnable = descr.enable; desc_dx11.RenderTarget[0].SrcBlend = dx11_convert<D3D11_BLEND>(descr.src); desc_dx11.RenderTarget[0].DestBlend = dx11_convert<D3D11_BLEND>(descr.dst); desc_dx11.RenderTarget[0].BlendOp = dx11_convert<D3D11_BLEND_OP>(descr.op); desc_dx11.RenderTarget[0].SrcBlendAlpha = dx11_convert<D3D11_BLEND>(descr.alpha_src); desc_dx11.RenderTarget[0].DestBlendAlpha = dx11_convert<D3D11_BLEND>(descr.alpha_dst); desc_dx11.RenderTarget[0].BlendOpAlpha = dx11_convert<D3D11_BLEND_OP>(descr.alpha_op); desc_dx11.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; // TODO // TODO: support other render targets ID3D11BlendState* native = NULL; D3D_CALL(dev->native->CreateBlendState(&desc_dx11, &native)); BlendStateDX11 res; res.native = native; return dev->resources.blend_states.push(res); }
DepthStencilStateHandle Gfx_DepthStencilState_Create(RenderDevice* dev, const DepthStencilStateDescr& descr) { // TODO D3D11_DEPTH_STENCIL_DESC desc_dx11; desc_dx11.DepthEnable = descr.enable; desc_dx11.DepthWriteMask = descr.write_enable ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO; desc_dx11.DepthFunc = dx11_convert<D3D11_COMPARISON_FUNC>(descr.cmp_func); desc_dx11.StencilEnable = FALSE; desc_dx11.StencilReadMask = 0xFF; desc_dx11.StencilWriteMask = 0xFF; desc_dx11.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; desc_dx11.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; desc_dx11.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; desc_dx11.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; desc_dx11.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; desc_dx11.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; desc_dx11.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; desc_dx11.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; ID3D11DepthStencilState* state_dx11 = NULL; D3D_CALL(dev->native->CreateDepthStencilState(&desc_dx11, &state_dx11)); return dev->resources.depth_stencil_states.push(state_dx11); }
// vertex buffer VertexBufferHandle Gfx_VertexBuffer_Create(RenderDevice* dev, const VertexBufferDescr& vb, const void* data) { D3D11_BUFFER_DESC desc; desc.ByteWidth = vb.size; desc.Usage = dx11_convert<D3D11_USAGE>(vb.mode); desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = dx11_convert<D3D11_CPU_ACCESS_FLAG>(vb.mode); desc.MiscFlags = 0; desc.StructureByteStride = vb.stride; D3D11_SUBRESOURCE_DATA initial_data; initial_data.pSysMem = data; initial_data.SysMemPitch = 0; initial_data.SysMemSlicePitch = 0; ID3D11Buffer* native = NULL; D3D_CALL(dev->native->CreateBuffer(&desc, data?&initial_data:NULL, &native)); VertexBufferDX11 res; res.desc = vb; res.native = native; return dev->resources.vertex_buffers.push(res); }
// sampler state SamplerStateHandle Gfx_SamplerState_Create(RenderDevice* dev, const SamplerStateDescr& descr) { (void)descr; // TODO: convert state correctly D3D11_SAMPLER_DESC desc_dx11; desc_dx11.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; desc_dx11.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; desc_dx11.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; desc_dx11.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; desc_dx11.MipLODBias = 0; desc_dx11.MaxAnisotropy = 1; desc_dx11.ComparisonFunc = D3D11_COMPARISON_ALWAYS; desc_dx11.BorderColor[0] = 0; desc_dx11.BorderColor[1] = 0; desc_dx11.BorderColor[2] = 0; desc_dx11.BorderColor[3] = 0; desc_dx11.MinLOD = 0; desc_dx11.MaxLOD = D3D11_FLOAT32_MAX; ID3D11SamplerState* native = NULL; D3D_CALL(dev->native->CreateSamplerState(&desc_dx11, &native)); SamplerStateDX11 res; res.native = native; return dev->resources.sampler_states.push(res); }
// texture TextureHandle Gfx_Texture_Load(RenderDevice* dev, const char* filename, TextureType::type type) { (void)type; // TODO ID3D11Texture2D* tex_dx11 = NULL; D3DX11_IMAGE_LOAD_INFO image_load_info; D3D_CALL( D3DX11CreateTextureFromFileA(dev->native, filename, &image_load_info, NULL, (ID3D11Resource**)&tex_dx11, NULL) ); if( tex_dx11 == NULL ) return InvalidResourceHandle(); D3D11_TEXTURE2D_DESC desc; tex_dx11->GetDesc(&desc); TextureDescr tex = TextureDescr::create_2D(desc.Width, desc.Height, dx11_convert<PixelFormat::type>(desc.Format), TextureType::Tex2D); R_ASSERT( tex.format!=PixelFormat::Unknown ); TextureDX11 res; res.desc = tex; res.native2D = tex_dx11; res.srv = create_srv(dev->native, tex_dx11); return dev->resources.textures.push(res); }
// index buffer IndexBufferHandle Gfx_IndexBuffer_Create(RenderDevice* dev, const IndexBufferDescr& ib, const void* data) { D3D11_BUFFER_DESC desc; desc.ByteWidth = ib.size; desc.Usage = dx11_convert<D3D11_USAGE>(ib.mode); desc.BindFlags = D3D11_BIND_INDEX_BUFFER; desc.CPUAccessFlags = dx11_convert<D3D11_CPU_ACCESS_FLAG>(ib.mode); desc.MiscFlags = 0; desc.StructureByteStride = ib.stride; D3D11_SUBRESOURCE_DATA initial_data; initial_data.pSysMem = data; initial_data.SysMemPitch = 0; initial_data.SysMemSlicePitch = 0; ID3D11Buffer* native = NULL; D3D_CALL(dev->native->CreateBuffer(&desc, data?&initial_data:NULL, &native)); IndexBufferDX11 res; res.desc = ib; res.native = native; res.native_format = ib.stride == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT; return dev->resources.index_buffers.push(res); }
void Gfx_Present(RenderDevice* dev) { if( dev->resize_listener->size() ) { const WindowEvent::Resize& last_resize = dev->resize_listener->back(); DXGI_SWAP_CHAIN_DESC desc; dev->swap_chain->GetDesc(&desc); dx11_release_back_buffer(dev); D3D_CALL(dev->swap_chain->ResizeBuffers(desc.BufferCount, last_resize.width, last_resize.height, desc.BufferDesc.Format, desc.Flags)); dx11_acquire_back_buffer(dev); dx11_setup_back_buffer(dev); dev->resize_listener->clear(); } D3D_CALL( dev->swap_chain->Present(dev->vsync, 0) ); }
static void d3d_SetEnvMapTextureStates(const ViewParams& Params, uint32 envMapType, LTPolyGrid* pGrid, bool bCubic) { //use the T-Factor for the overall translucency of the polygrid D3D_CALL(PD3DDEVICE->SetRenderState(D3DRS_TEXTUREFACTOR, D3DRGBA_255(255, 255, 255, pGrid->m_ColorA))); PD3DDEVICE->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE2X); PD3DDEVICE->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); PD3DDEVICE->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); PD3DDEVICE->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2); PD3DDEVICE->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_CURRENT); PD3DDEVICE->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); PD3DDEVICE->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE); PD3DDEVICE->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_DIFFUSE); PD3DDEVICE->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_TEXTURE); PD3DDEVICE->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_MODULATE); PD3DDEVICE->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TFACTOR); PD3DDEVICE->SetTextureStageState(1, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); PD3DDEVICE->SetTextureStageState(2, D3DTSS_COLOROP, D3DTOP_DISABLE); PD3DDEVICE->SetTextureStageState(2, D3DTSS_ALPHAOP, D3DTOP_DISABLE); //now we need to set up the environment map transform //get the basis vectors for world space LTVector vRight, vUp, vForward; Params.m_mView.GetBasisVectors(&vRight, &vUp, &vForward); //now setup the transpose, thus converting the normals into worldspace D3DXMATRIX mCamToWorld( vRight.x, vUp.x, vForward.x, 0.0f, vRight.y, vUp.y, vForward.y, 0.0f, vRight.z, vUp.z, vForward.z, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f); if(!bCubic) { //setup our texture channel 1 to generate environment maps D3DXMATRIX mTex1Trans( 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.0f, 1.0f ); mCamToWorld = mCamToWorld * mTex1Trans; } //setup our input parameters for the texture coordinates PD3DDEVICE->SetTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, bCubic ? D3DTTFF_COUNT3 : D3DTTFF_COUNT2); PD3DDEVICE->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR | 1); //setup our texture transform PD3DDEVICE->SetTransform(D3DTS_TEXTURE1, &mCamToWorld); }
static void d3d_SetDefaultBlendStates() { //disable the fancier approach D3D_CALL(PD3DDEVICE->SetRenderState(D3DRS_TEXTUREFACTOR, D3DRGBA_255(255, 255, 255, 255))); PD3DDEVICE->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); PD3DDEVICE->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); PD3DDEVICE->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); PD3DDEVICE->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); PD3DDEVICE->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); PD3DDEVICE->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); PD3DDEVICE->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); PD3DDEVICE->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE); PD3DDEVICE->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT); PD3DDEVICE->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); PD3DDEVICE->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); PD3DDEVICE->SetTextureStageState(1, D3DTSS_ALPHAARG2, D3DTA_CURRENT); }
VertexBufferLock Gfx_VertexBuffer_Lock(RenderDevice* dev, VertexBufferHandle h, uint32 offset, uint32 size) { VertexBufferLock lock; if( h.valid() ) { lock.size = size; lock.handle = h; D3D11_MAP type = dx11_convert<D3D11_MAP>(dev->resources.vertex_buffers[h].desc.mode); uint32 flags = 0; ID3D11Buffer* native = dev->resources.vertex_buffers[h].native; D3D11_MAPPED_SUBRESOURCE res; D3D_CALL(dev->default_context->native->Map(native, 0, type, flags, &res)); lock.data = (char*)res.pData + offset; } return lock; }
void CD3D_Device::SetupViewport(uint32 iLeft, uint32 iRight, uint32 iTop, uint32 iBottom, float fMinZ, float fMaxZ) { if (m_rcViewport.left == (LONG)iLeft && m_rcViewport.right == (LONG)iRight && m_rcViewport.top == (LONG)iTop && m_rcViewport.bottom == (LONG)iBottom) return; m_rcViewport.left = iLeft; m_rcViewport.right = iRight; m_rcViewport.top = iTop; m_rcViewport.bottom = iBottom; D3DVIEWPORT9 viewportData; viewportData.X = m_rcViewport.left; viewportData.Y = m_rcViewport.top; viewportData.Width = m_rcViewport.right - m_rcViewport.left; viewportData.Height = m_rcViewport.bottom - m_rcViewport.top; viewportData.MinZ = fMinZ; viewportData.MaxZ = fMaxZ; HRESULT hResult = D3D_CALL(PD3DDEVICE->SetViewport(&viewportData)); if (FAILED(hResult)) { assert(!"IDirect3DDevice::SetViewport failed."); return; } }
TextureHandle Gfx_Texture_Create(RenderDevice* dev, const TextureDescr& tex, const void* data, size_t /*size*/) { ID3D11Texture2D* tex_dx11 = NULL; DXGI_FORMAT format = dx11_convert<DXGI_FORMAT>(tex.format); D3D11_TEXTURE2D_DESC desc = CD3D11_TEXTURE2D_DESC(format, tex.width, tex.height, 1, 1); UINT pitch = (tex.width * PixelFormat::bits_per_pixel(tex.format))/8; D3D11_SUBRESOURCE_DATA initial_data; initial_data.pSysMem = data; initial_data.SysMemPitch = pitch; initial_data.SysMemSlicePitch = pitch * tex.height; D3D_CALL(dev->native->CreateTexture2D(&desc, data?&initial_data:NULL, &tex_dx11)); TextureDX11 res; res.desc = tex; res.native2D = tex_dx11; res.srv = create_srv(dev->native, tex_dx11); return dev->resources.textures.push(res); }
RenderDevice* Gfx_CreateDevice(Window* window, const RenderDeviceConfig& cfg) { (void)cfg; // TODO RenderDevice* dev = new RenderDevice; dev->window = window; dev->vsync = cfg.use_vertical_sync ? 1 : 0; dev->default_context = new RenderContext; dev->default_context->resources = &dev->resources; // create d3d11 device and essential resources HWND hwnd = *(HWND*)window->native_window_handle(); DXGI_SWAP_CHAIN_DESC sd; ZeroMemory( &sd, sizeof( sd ) ); sd.BufferCount = 1; sd.BufferDesc.Width = window->width(); sd.BufferDesc.Height = window->height(); sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.BufferDesc.RefreshRate.Numerator = 60; sd.BufferDesc.RefreshRate.Denominator = 1; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.OutputWindow = hwnd; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.Windowed = TRUE; uint32 flags = D3D11_CREATE_DEVICE_SINGLETHREADED; #ifdef _DEBUG flags |= D3D11_CREATE_DEVICE_DEBUG; #endif //_DEBUG D3D_DRIVER_TYPE type = D3D_DRIVER_TYPE_HARDWARE; IDXGIAdapter* adapter = NULL; if( cfg.use_nvperfhud ) { IDXGIAdapter* enumerated_adapter = NULL; IDXGIFactory* factory = NULL; D3D_CALL( CreateDXGIFactory(__uuidof(IDXGIFactory),(void**)&factory) ); for( uint32 i=0; factory->EnumAdapters(i,&enumerated_adapter) != DXGI_ERROR_NOT_FOUND; ++i ) { DXGI_ADAPTER_DESC adapter_desc; if(enumerated_adapter->GetDesc(&adapter_desc) != S_OK) { continue; } if(wcsstr(adapter_desc.Description,L"PerfHUD") != 0) { type = D3D_DRIVER_TYPE_REFERENCE; adapter = enumerated_adapter; break; } } SafeRelease(factory); } D3D_FEATURE_LEVEL features[] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_9_3, D3D_FEATURE_LEVEL_9_2, D3D_FEATURE_LEVEL_9_1 }; const uint32 num_features = sizeof(features) / sizeof(features[0]); D3D_FEATURE_LEVEL supported_features = D3D_FEATURE_LEVEL_9_1; // Create device D3D_CALL( D3D11CreateDeviceAndSwapChain( adapter, type, NULL, flags, features, num_features, D3D11_SDK_VERSION, &sd, &dev->swap_chain, &dev->native, &supported_features, &dev->default_context->native) ); // Set-up default Colour and Depth surfaces dx11_acquire_back_buffer(dev); dx11_setup_back_buffer(dev); // create default pixel and vertex constant buffers D3D11_BUFFER_DESC desc; desc.ByteWidth = MaxShaderConstants*sizeof(Vector4); desc.Usage = D3D11_USAGE_DYNAMIC; desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; desc.MiscFlags = 0; desc.StructureByteStride = 0; D3D_CALL(dev->native->CreateBuffer(&desc, NULL, &dev->default_context->ps_cb)); D3D_CALL(dev->native->CreateBuffer(&desc, NULL, &dev->default_context->vs_cb)); // Hack -- enable scissor rect state by default D3D11_RASTERIZER_DESC rasterizer_desc = CD3D11_RASTERIZER_DESC(CD3D11_DEFAULT()); rasterizer_desc.ScissorEnable = TRUE; dev->native->CreateRasterizerState(&rasterizer_desc, &dev->rasterizer_state); dev->default_context->native->RSSetState(dev->rasterizer_state); // all done dev->resize_listener = new WindowResizeListener(window); return dev; }
void d3d_DrawPolyGrid(const ViewParams &Params, LTObject *pObj) { //the global pixel shader to be used for the water bumpmapping and a flag indicating if //creation failed bool s_bPixelShaderFailed = false; //make sure that the polygrid is valid assert(pObj); //get our polygrid LTPolyGrid *pGrid = (LTPolyGrid*)pObj; // Make sure it's initialized. if(!pGrid->m_Data) return; //must have an index buffer if(!pGrid->m_Indices || (pGrid->m_nIndices == 0)) return; //and of course, make sure that the size is reasonable if((pGrid->m_Width < 2) || (pGrid->m_Height < 2)) return; IncFrameStat(eFS_PolyGridTriangles, pGrid->m_nTris); //cache the half dimensions float fHalfGridWidth = ((float)pGrid->m_Width - 1) * 0.5f; float fHalfGridHeight = ((float)pGrid->m_Height - 1) * 0.5f; //now we need to build our color lookup table for this polygrid, this is faster for any //polygrid that is larger than 8x8, and even then we can get a nice tight loop that //should still be rather optimal // Set the blending mode based on the flags. uint32 nSrcBlend, nDestBlend, nFog, nFogColor; d3d_GetBlendStates(pGrid, nSrcBlend, nDestBlend, nFog, nFogColor); StateSet ssSrcBlend(D3DRS_SRCBLEND, nSrcBlend); StateSet ssDestBlend(D3DRS_DESTBLEND, nDestBlend); StateSet ssFog(D3DRS_FOGENABLE, nFog); StateSet ssFogColor(D3DRS_FOGCOLOR, nFogColor); //flag indicating whether or not bool bEnvMap = false; bool bCubicEnvMap = false; bool bBumpMap = false; //vertex information uint32 nVertexSize = sizeof(CPolyGridVertex); uint32 nVertexFVF = POLYGRIDVERTEX_FORMAT; //UV scales to adjust the texture by (defaults to 1, but if we are bump mapping, this will //be set to the detail texture scale) float fPGUScale = 1.0f; float fPGVScale = 1.0f; // Set the texture if necessary. SpriteTracker* pTracker; LTPixelShader *pPixelShader = NULL; if(pGrid->m_pSprite) { pTracker = &pGrid->m_SpriteTracker; if(pTracker->m_pCurFrame) { SharedTexture* pTex = pTracker->m_pCurFrame->m_pTex; if(pTex) { //get the type of this texture ESharedTexType eTexType = pTex->m_eTexType; //the base texture SharedTexture* pBaseTex = NULL; //the environment map SharedTexture* pEnvMapTex = pGrid->m_pEnvMap; //the bumpmap SharedTexture* pBumpMapTex = NULL; //determine our texture data if(pGrid->m_nPGFlags & PG_NORMALMAPSPRITE) { //only use a bump map texture if we actually have an environment map if(pEnvMapTex) pBumpMapTex = pTex; } else { //we have a normal texture pBaseTex = pTex; } // Set up the environment mapping texture if applicable if( pEnvMapTex && g_CV_EnvMapPolyGrids.m_Val) { //see if the is a cubic environment map RTexture *pRenderTexture = (RTexture*)pEnvMapTex->m_pRenderData; if(pRenderTexture && pRenderTexture->IsCubeMap()) { bCubicEnvMap = true; } bEnvMap = true; } if( pBumpMapTex && g_CV_BumpMapPolyGrids.m_Val) { //we now need to make sure that the bump map shader is valid //see if we need to load it if (!s_bPixelShaderFailed) { // Get the pixel shader. pPixelShader = LTPixelShaderMgr::GetSingleton().GetPixelShader(LTPixelShader::PIXELSHADER_ENVBUMPMAP); if (NULL == pPixelShader) { FileRef ref; ref.m_FileType = FILE_ANYFILE; ref.m_pFilename = "ps\\envbumpmap.psh"; // Try to load it. ILTStream *pStream = g_pIClientFileMgr->OpenFile(&ref); if (NULL != pStream) { if (LTPixelShaderMgr::GetSingleton().AddPixelShader(pStream, ref.m_pFilename, LTPixelShader::PIXELSHADER_ENVBUMPMAP, true)) { pPixelShader = LTPixelShaderMgr::GetSingleton().GetPixelShader(LTPixelShader::PIXELSHADER_ENVBUMPMAP); } // Close the file. pStream->Release(); } } } // See if we can continue. if (NULL != pPixelShader && pPixelShader->IsValidShader()) { bBumpMap = true; nVertexSize = sizeof(CPolyGridBumpVertex); nVertexFVF = POLYGRIDBUMPVERTEX_FORMAT; fPGUScale = ((RTexture*)pBumpMapTex->m_pRenderData)->m_DetailTextureScale; fPGVScale = fPGUScale; } else { //we failed to create the shader, the device can't support it s_bPixelShaderFailed = true; } } //setup the textures based upon the configuration if(bBumpMap) { d3d_SetTexture(pBumpMapTex, 0, eFS_PolyGridBumpMapTexMemory); d3d_SetTexture(pEnvMapTex, 3, eFS_PolyGridEnvMapTexMemory); } else { LTEffectImpl* pEffect = (LTEffectImpl*)LTEffectShaderMgr::GetSingleton().GetEffectShader(pGrid->m_nEffectShaderID); if(pEffect) { ID3DXEffect* pD3DEffect = pEffect->GetEffect(); if(pD3DEffect) { nVertexSize = sizeof(CPolyGridEffectVertex); RTexture* pRTexture = (RTexture*)pBaseTex->m_pRenderData; pD3DEffect->SetTexture("texture0", pRTexture->m_pD3DTexture); if(bEnvMap) { pRTexture = (RTexture*)pEnvMapTex->m_pRenderData; pD3DEffect->SetTexture("texture1", pRTexture->m_pD3DTexture); } } }else { d3d_SetTexture(pBaseTex, 0, eFS_PolyGridBaseTexMemory); if(bEnvMap) { d3d_SetTexture(pEnvMapTex, 1, eFS_PolyGridEnvMapTexMemory); } } } } else { //if we didn't set any texture, we need to make sure and clear out the texture //channel d3d_DisableTexture(0); } } } //specify that we were visible pGrid->m_Flags |= FLAG_INTERNAL1; // Build the vertex list. uint32 nBufferSize = pGrid->m_Width * pGrid->m_Height * nVertexSize; if(nBufferSize > g_TriVertListSize) { //we need to reallocate our list of vertices dfree(g_TriVertList); LT_MEM_TRACK_ALLOC(g_TriVertList = dalloc(nBufferSize),LT_MEM_TYPE_RENDERER); //check the allocation if(!g_TriVertList) { g_TriVertListSize = 0; return; } g_TriVertListSize = nBufferSize; } //determine if this polygrid should be lit or not bool bFresnel = (pGrid->m_nPGFlags & PG_FRESNEL) && (g_CV_FresnelPolyGrids.m_Val) ? true : false; //determine what alpha value we should use uint8 nColorAlpha = 0; if(!bEnvMap) nColorAlpha = 255; else if(!bFresnel) nColorAlpha = 128; float fScaledR = pGrid->m_ColorR * MATH_ONE_OVER_255; float fScaledG = pGrid->m_ColorG * MATH_ONE_OVER_255; float fScaledB = pGrid->m_ColorB * MATH_ONE_OVER_255; uint32 nColorTable[256]; for(uint32 nCurrColor = 0; nCurrColor < 256; nCurrColor++) { //Note that the color table is 0..255, object color is 0..255 as well nColorTable[nCurrColor] = D3DRGBA_255( pGrid->m_ColorTable[nCurrColor].x * fScaledR, pGrid->m_ColorTable[nCurrColor].y * fScaledG, pGrid->m_ColorTable[nCurrColor].z * fScaledB, nColorAlpha); } //setup our world matrix to represent a space that holds the orientation of the polygrid //as well as the center position. This allows all operations to take place //as if performed on the XZ plane (note that we don't do the scale as that tends //to mess up normals) LTMatrix mWorldTrans; LTVector vUnitScale(1.0f, 1.0f, 1.0f); d3d_SetupTransformation(&pGrid->GetPos(), (float*)&pGrid->m_Rotation, &vUnitScale, &mWorldTrans); d3d_SetD3DMat(D3DTS_WORLD, &mWorldTrans); //calculate our position increments float fXInc = pGrid->GetDims().x * 2.0f / (pGrid->m_Width - 1); float fZInc = pGrid->GetDims().z * 2.0f / (pGrid->m_Height - 1); float fYScale = pGrid->GetDims().y / 127.0f; float fXStart = -fHalfGridWidth * fXInc; float fCurrX = fXStart; float fCurrZ = -fHalfGridHeight * fZInc; int8* pDataPos = (int8*)pGrid->m_Data; int8* pDataEnd = pDataPos + pGrid->m_Width * pGrid->m_Height; int8* pLineDataEnd = pDataPos + pGrid->m_Width; uint32* pColor = nColorTable + 128; float fXScale = pGrid->m_xScale / ((pGrid->m_Width - 1) * fXInc); float fZScale = pGrid->m_yScale / ((pGrid->m_Height - 1) * fZInc); float fStartU = (float)fmod(pGrid->m_xPan * fPGUScale, 1.0f); float fStartV = (float)fmod(pGrid->m_yPan * fPGVScale, 1.0f); float fCurrU = fStartU; float fCurrV = fStartV; float fUInc = fXInc * fXScale * fPGUScale; float fVInc = fZInc * fZScale * fPGVScale; int32 nWidth = pGrid->m_Width; float fSpacingX = fXInc * 2.0f; float fSpacingZ = fZInc * 2.0f; uint32 nNumVerts; bool bEffect = false; LTEffectImpl* pEffect = (LTEffectImpl*)LTEffectShaderMgr::GetSingleton().GetEffectShader(pGrid->m_nEffectShaderID); if(pEffect) { ID3DXEffect* pD3DEffect = pEffect->GetEffect(); if(pD3DEffect) { bEffect = true; } } if(bBumpMap) { CPolyGridBumpVertex* pVertexPos = (CPolyGridBumpVertex*)g_TriVertList; if(pGrid->m_pValidMask) { //this polygrid has a valid mask, meaning that we need to skip over vertices //as needed uint32* pCurrMask = pGrid->m_pValidMask; //amount to adjust the mask at the end of a line uint32 nMaskLineAdjust = (pGrid->m_Width % 32) ? 1 : 0; uint32 nShift; uint32 nNormalY1 = 0; uint32 nNormalY2 = nWidth; float fWidthTimesHeight = fSpacingX * fSpacingZ; while(pDataPos < pDataEnd) { nShift = 0x1; while(pDataPos < pLineDataEnd) { if(*pCurrMask & nShift) { //this is valid, add this vertex d3d_SetupVertexPos(pVertexPos, fCurrX, *pDataPos * fYScale, fCurrZ, pColor[*pDataPos], fCurrU, fCurrV); //generate a normal for it GenerateBasisSpace(pDataPos, pVertexPos, -1, 1, nNormalY1, nNormalY2, fSpacingX, fSpacingZ, fWidthTimesHeight, fYScale); //move along to the next vertex pVertexPos++; } pDataPos++; fCurrX += fXInc; fCurrU += fUInc; if(nShift == 0x80000000) { pCurrMask++; nShift = 1; } else { nShift <<= 1; } } //reset the line fCurrX = fXStart; //update our threshold for when to move onto the next line pLineDataEnd += pGrid->m_Width; pCurrMask += nMaskLineAdjust; //update our position fCurrZ += fZInc; fCurrU = fStartU; fCurrV += fVInc; //update the normal offsets to ensure we don't go outside of our buffer nNormalY1 = -nWidth; if(pLineDataEnd >= pDataEnd) nNormalY2 = 0; } nNumVerts = pVertexPos - (CPolyGridBumpVertex*)g_TriVertList; } else { nNumVerts = pGrid->m_Width * pGrid->m_Height; while(pDataPos < pDataEnd) { while(pDataPos < pLineDataEnd) { d3d_SetupVertexPos(pVertexPos, fCurrX, *pDataPos * fYScale, fCurrZ, pColor[*pDataPos], fCurrU, fCurrV); pDataPos++; pVertexPos++; fCurrX += fXInc; fCurrU += fUInc; } //reset the line fCurrX = fXStart; //update our threshold for when to move onto the next line pLineDataEnd += pGrid->m_Width; //update our position fCurrZ += fZInc; fCurrU = fStartU; fCurrV += fVInc; } //now we need to generate the normals for the polygrid GeneratePolyGridVectors(pGrid, (CPolyGridBumpVertex*)g_TriVertList, GenerateBasisSpace); } } else if(bEffect) { CPolyGridEffectVertex* pVertexPos = (CPolyGridEffectVertex*)g_TriVertList; if(pGrid->m_pValidMask) { //this polygrid has a valid mask, meaning that we need to skip over vertices //as needed uint32* pCurrMask = pGrid->m_pValidMask; //amount to adjust the mask at the end of a line uint32 nMaskLineAdjust = (pGrid->m_Width % 32) ? 1 : 0; uint32 nShift; uint32 nNormalY1 = 0; uint32 nNormalY2 = nWidth; float fWidthTimesHeight = fSpacingX * fSpacingZ; while(pDataPos < pDataEnd) { nShift = 0x1; while(pDataPos < pLineDataEnd) { if(*pCurrMask & nShift) { //this is valid, add this vertex d3d_SetupVertexPos(pVertexPos, fCurrX, *pDataPos * fYScale, fCurrZ, pColor[*pDataPos], fCurrU, fCurrV); //generate a normal for it GenerateEffectBasisSpace(pDataPos, pVertexPos, -1, 1, nNormalY1, nNormalY2, fSpacingX, fSpacingZ, fWidthTimesHeight, fYScale); //move along to the next vertex pVertexPos++; } pDataPos++; fCurrX += fXInc; fCurrU += fUInc; if(nShift == 0x80000000) { pCurrMask++; nShift = 1; } else { nShift <<= 1; } } //reset the line fCurrX = fXStart; //update our threshold for when to move onto the next line pLineDataEnd += pGrid->m_Width; pCurrMask += nMaskLineAdjust; //update our position fCurrZ += fZInc; fCurrU = fStartU; fCurrV += fVInc; //update the normal offsets to ensure we don't go outside of our buffer nNormalY1 = -nWidth; if(pLineDataEnd >= pDataEnd) nNormalY2 = 0; } nNumVerts = pVertexPos - (CPolyGridEffectVertex*)g_TriVertList; } else { nNumVerts = pGrid->m_Width * pGrid->m_Height; while(pDataPos < pDataEnd) { while(pDataPos < pLineDataEnd) { d3d_SetupVertexPos(pVertexPos, fCurrX, *pDataPos * fYScale, fCurrZ, pColor[*pDataPos], fCurrU, fCurrV); pDataPos++; pVertexPos++; fCurrX += fXInc; fCurrU += fUInc; } //reset the line fCurrX = fXStart; //update our threshold for when to move onto the next line pLineDataEnd += pGrid->m_Width; //update our position fCurrZ += fZInc; fCurrU = fStartU; fCurrV += fVInc; } //now we need to generate the normals for the polygrid LTEffectImpl* pEffect = (LTEffectImpl*)LTEffectShaderMgr::GetSingleton().GetEffectShader(pGrid->m_nEffectShaderID); if(pEffect) { ID3DXEffect* pD3DEffect = pEffect->GetEffect(); if(pD3DEffect) { GeneratePolyGridVectors(pGrid, (CPolyGridEffectVertex*)g_TriVertList, GenerateEffectBasisSpace); } } else { GeneratePolyGridVectors(pGrid, (CPolyGridVertex*)g_TriVertList, GenerateNormal); } } } else //fixed function { CPolyGridVertex* pVertexPos = (CPolyGridVertex*)g_TriVertList; if(pGrid->m_pValidMask) { //this polygrid has a valid mask, meaning that we need to skip over vertices //as needed uint32* pCurrMask = pGrid->m_pValidMask; //amount to adjust the mask at the end of a line uint32 nMaskLineAdjust = (pGrid->m_Width % 32) ? 1 : 0; uint32 nShift; uint32 nNormalY1 = 0; uint32 nNormalY2 = nWidth; float fWidthTimesHeight = fSpacingX * fSpacingZ; while(pDataPos < pDataEnd) { nShift = 0x1; while(pDataPos < pLineDataEnd) { if(*pCurrMask & nShift) { //this is valid, add this vertex d3d_SetupVertexPos(pVertexPos, fCurrX, *pDataPos * fYScale, fCurrZ, pColor[*pDataPos], fCurrU, fCurrV); //generate a normal for it GenerateNormal(pDataPos, pVertexPos, -1, 1, nNormalY1, nNormalY2, fSpacingX, fSpacingZ, fWidthTimesHeight, fYScale); //move along to the next vertex pVertexPos++; } pDataPos++; fCurrX += fXInc; fCurrU += fUInc; if(nShift == 0x80000000) { pCurrMask++; nShift = 1; } else { nShift <<= 1; } } //reset the line fCurrX = fXStart; //update our threshold for when to move onto the next line pLineDataEnd += pGrid->m_Width; pCurrMask += nMaskLineAdjust; //update our position fCurrZ += fZInc; fCurrU = fStartU; fCurrV += fVInc; //update the normal offsets to ensure we don't go outside of our buffer nNormalY1 = -nWidth; if(pLineDataEnd >= pDataEnd) nNormalY2 = 0; } nNumVerts = pVertexPos - (CPolyGridVertex*)g_TriVertList; } else { nNumVerts = pGrid->m_Width * pGrid->m_Height; while(pDataPos < pDataEnd) { while(pDataPos < pLineDataEnd) { d3d_SetupVertexPos(pVertexPos, fCurrX, *pDataPos * fYScale, fCurrZ, pColor[*pDataPos], fCurrU, fCurrV); pDataPos++; pVertexPos++; fCurrX += fXInc; fCurrU += fUInc; } //reset the line fCurrX = fXStart; //update our threshold for when to move onto the next line pLineDataEnd += pGrid->m_Width; //update our position fCurrZ += fZInc; fCurrU = fStartU; fCurrV += fVInc; } //now we need to generate the normals for the polygrid LTEffectImpl* pEffect = (LTEffectImpl*)LTEffectShaderMgr::GetSingleton().GetEffectShader(pGrid->m_nEffectShaderID); if(pEffect) { ID3DXEffect* pD3DEffect = pEffect->GetEffect(); if(pD3DEffect) { GeneratePolyGridVectors(pGrid, (CPolyGridEffectVertex*)g_TriVertList, GenerateEffectBasisSpace); } } else { GeneratePolyGridVectors(pGrid, (CPolyGridVertex*)g_TriVertList, GenerateNormal); } } } // Set environment map texture coordinates. if(bEnvMap && !bBumpMap) { d3d_SetEnvMapTextureStates(Params, pTracker->m_pCurFrame->m_pTex->m_eTexType, pGrid, bCubicEnvMap); } //see if we are just doing a base texture if(!bEnvMap && !bBumpMap) { d3d_SetDefaultBlendStates(); } //generate the alpha if we can use it if(bBumpMap) { GeneratePolyGridFresnelAlphaAndCamera(Params.m_Pos, (CPolyGridBumpVertex*)g_TriVertList, pGrid, nNumVerts); } else if(bFresnel) { GeneratePolyGridFresnelAlpha(Params.m_Pos, (CPolyGridVertex*)g_TriVertList, pGrid, nNumVerts); } //make the backfacing polygons cull StateSet ssCullMode(D3DRS_CULLMODE, (pGrid->m_nPGFlags & PG_NOBACKFACECULL) ? D3DCULL_NONE : D3DCULL_CCW); //setup the pixel shader if we are bumpmapping if(bBumpMap) { assert(NULL != pPixelShader && pPixelShader->IsValidShader()); // Set the pixel shader constants. float *pConstants = pPixelShader->GetConstants(); pConstants[0] = 0.0f; pConstants[1] = 0.0f; pConstants[2] = 0.0f; pConstants[3] = pGrid->m_ColorA / 255.0f; LTPixelShaderMgr::GetSingleton().SetPixelShaderConstants(pPixelShader); // Install the pixel shader. LTPixelShaderMgr::GetSingleton().InstallPixelShader(pPixelShader); //now actually draw the polygrid D3D_CALL(PD3DDEVICE->SetVertexShader(NULL)); D3D_CALL(PD3DDEVICE->SetFVF(nVertexFVF)); int nNumPolies = (pGrid->m_nIndices/3); // Is this polygrid larger than our buffer? If so, break it into smaller patches. if(nNumPolies > g_CV_PolyGridBufferSize) { int32 nRemainingPolies = nNumPolies; uint32 nCurrentVertPosition = 0; while(nRemainingPolies > 0) { uint32 nPoliesThisFrame = (nRemainingPolies > g_CV_PolyGridBufferSize) ? g_CV_PolyGridBufferSize: nRemainingPolies; D3D_CALL(PD3DDEVICE->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST,0,nNumVerts,nPoliesThisFrame,&pGrid->m_Indices[nCurrentVertPosition],D3DFMT_INDEX16,g_TriVertList, nVertexSize)); nCurrentVertPosition += nPoliesThisFrame*3; nRemainingPolies -= nPoliesThisFrame; } } else { D3D_CALL(PD3DDEVICE->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST,0,nNumVerts,(pGrid->m_nIndices)/3,pGrid->m_Indices,D3DFMT_INDEX16,g_TriVertList, nVertexSize)); } // Uninstall the pixel shader. LTPixelShaderMgr::GetSingleton().UninstallPixelShader(); d3d_DisableTexture(0); d3d_DisableTexture(3); } else { //now actually draw the polygrid D3D_CALL(PD3DDEVICE->SetVertexShader(NULL)); D3D_CALL(PD3DDEVICE->SetFVF(nVertexFVF)); int nNumPolies = (pGrid->m_nIndices/3); // Is this polygrid larger than our buffer? If so, break it into smaller patches. if(nNumPolies > g_CV_PolyGridBufferSize) { int32 nRemainingPolies = nNumPolies; uint32 nCurrentVertPosition = 0; while(nRemainingPolies > 0) { uint32 nPoliesThisFrame = (nRemainingPolies > g_CV_PolyGridBufferSize) ? g_CV_PolyGridBufferSize: nRemainingPolies; LTEffectImpl* pEffect = (LTEffectImpl*)LTEffectShaderMgr::GetSingleton().GetEffectShader(pGrid->m_nEffectShaderID); if(pEffect) { pEffect->UploadVertexDeclaration(); ID3DXEffect* pD3DEffect = pEffect->GetEffect(); if(pD3DEffect) { i_client_shell->OnEffectShaderSetParams(pEffect, NULL, NULL, LTShaderDeviceStateImp::GetSingleton()); UINT nPasses = 0; pD3DEffect->Begin(&nPasses, 0); for(UINT i = 0; i < nPasses; ++i) { pD3DEffect->BeginPass(i); D3D_CALL(PD3DDEVICE->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST,0,nNumVerts,nPoliesThisFrame,&pGrid->m_Indices[nCurrentVertPosition],D3DFMT_INDEX16,g_TriVertList, nVertexSize)); pD3DEffect->EndPass(); } pD3DEffect->End(); } } else { D3D_CALL(PD3DDEVICE->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST,0,nNumVerts,nPoliesThisFrame,&pGrid->m_Indices[nCurrentVertPosition],D3DFMT_INDEX16,g_TriVertList, nVertexSize)); } nCurrentVertPosition += nPoliesThisFrame*3; nRemainingPolies -= nPoliesThisFrame; } } else { LTEffectImpl* pEffect = (LTEffectImpl*)LTEffectShaderMgr::GetSingleton().GetEffectShader(pGrid->m_nEffectShaderID); if(pEffect) { pEffect->UploadVertexDeclaration(); ID3DXEffect* pD3DEffect = pEffect->GetEffect(); if(pD3DEffect) { i_client_shell->OnEffectShaderSetParams(pEffect, NULL, NULL, LTShaderDeviceStateImp::GetSingleton()); UINT nPasses = 0; pD3DEffect->Begin(&nPasses, 0); for(UINT i = 0; i < nPasses; ++i) { pD3DEffect->BeginPass(i); D3D_CALL(PD3DDEVICE->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST,0,nNumVerts,(pGrid->m_nIndices)/3,pGrid->m_Indices,D3DFMT_INDEX16,g_TriVertList, nVertexSize)); pD3DEffect->EndPass(); } pD3DEffect->End(); } } else { // No Effect Shader, just fixed function. D3D_CALL(PD3DDEVICE->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST,0,nNumVerts,(pGrid->m_nIndices)/3,pGrid->m_Indices,D3DFMT_INDEX16,g_TriVertList, nVertexSize)); } } d3d_DisableTexture(0); d3d_DisableTexture(1); } if (bEnvMap) d3d_UnsetEnvMapTextureStates(); //reset our world transform so that it won't mess up the rendering of other objects d3d_SetD3DMat(D3DTS_WORLD, &Params.m_mIdentity); }
static void d3d_DrawRotatableSprite(const ViewParams& Params, SpriteInstance *pInstance, SharedTexture *pShared) { if(!d3d_SetTexture(pShared, 0, eFS_SpriteTexMemory)) return; float fWidth = (float)((RTexture*)pShared->m_pRenderData)->GetBaseWidth(); float fHeight = (float)((RTexture*)pShared->m_pRenderData)->GetBaseHeight(); //cache the object position LTVector vPos = pInstance->GetPos(); LTMatrix mRotation; d3d_SetupTransformation(&vPos, (float*)&pInstance->m_Rotation, &pInstance->m_Scale, &mRotation); //get our basis vectors LTVector vRight, vUp, vForward; mRotation.GetBasisVectors(&vRight, &vUp, &vForward); //scale the vectors to be the appropriate size vRight *= fWidth; vUp *= fHeight; // Setup the points. RGBColor Color; d3d_GetSpriteColor(pInstance, &Color); uint32 nColor = Color.color; CSpriteVertex SpriteVerts[4]; SpriteVerts[0].SetupVert(vPos + vUp - vRight, nColor, 0.0f, 0.0f); SpriteVerts[1].SetupVert(vPos + vUp + vRight, nColor, 1.0f, 0.0f); SpriteVerts[2].SetupVert(vPos + vRight - vUp, nColor, 1.0f, 1.0f); SpriteVerts[3].SetupVert(vPos - vRight - vUp, nColor, 0.0f, 1.0f); //figure out our final vertices to use CSpriteVertex *pPoints; uint32 nPoints; CSpriteVertex ClippedSpriteVerts[40 + 5]; if(pInstance->m_ClipperPoly != INVALID_HPOLY) { if(!d3d_ClipSprite(pInstance, pInstance->m_ClipperPoly, &pPoints, &nPoints, ClippedSpriteVerts)) { return; } } else { pPoints = SpriteVerts; nPoints = 4; } if((pInstance->m_Flags & FLAG_SPRITEBIAS) && !(pInstance->m_Flags & FLAG_REALLYCLOSE)) { //adjust the points for(uint32 nCurrPt = 0; nCurrPt < nPoints; nCurrPt++) { //get the sprite vertex that we are modifying LTVector& vPt = SpriteVerts[nCurrPt].m_Vec; //find a point relative to the viewer position LTVector vPtRelCamera = vPt - Params.m_Pos; //determine the distance from the camera float fZ = vPtRelCamera.Dot(Params.m_Forward); if(fZ <= NEARZ) continue; //find the bias, up to, but not including the near plane float fBiasDist = SPRITE_POSITION_ZBIAS; if((fZ + fBiasDist) < NEARZ) fBiasDist = NEARZ - fZ; //now adjust our vectors accordingly so that we can move it forward //but have it be the same size float fScale = 1 + fBiasDist / fZ; vPt = Params.m_Right * vPtRelCamera.Dot(Params.m_Right) * fScale + Params.m_Up * vPtRelCamera.Dot(Params.m_Up) * fScale + (fZ + fBiasDist) * Params.m_Forward + Params.m_Pos; } } LTEffectImpl* pEffect = (LTEffectImpl*)LTEffectShaderMgr::GetSingleton().GetEffectShader(pInstance->m_nEffectShaderID); if(pEffect) { pEffect->UploadVertexDeclaration(); ID3DXEffect* pD3DEffect = pEffect->GetEffect(); if(pD3DEffect) { RTexture* pTexture = (RTexture*)pShared->m_pRenderData; pD3DEffect->SetTexture("texture0", pTexture->m_pD3DTexture); i_client_shell->OnEffectShaderSetParams(pEffect, NULL, NULL, LTShaderDeviceStateImp::GetSingleton()); UINT nPasses = 0; pD3DEffect->Begin(&nPasses, 0); for(UINT i = 0; i < nPasses; ++i) { pD3DEffect->BeginPass(i); D3D_CALL(PD3DDEVICE->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, nPoints-2, pPoints, sizeof(CSpriteVertex))); pD3DEffect->EndPass(); } pD3DEffect->End(); } } else { D3D_CALL(PD3DDEVICE->SetVertexShader(NULL)); D3D_CALL(PD3DDEVICE->SetFVF(SPRITEVERTEX_FORMAT)); D3D_CALL(PD3DDEVICE->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, nPoints-2, pPoints, sizeof(CSpriteVertex))); } d3d_DisableTexture(0); }
static void d3d_DrawSprite(const ViewParams& Params, SpriteInstance *pInstance, SharedTexture *pShared) { //the basis up and right vectors LTVector vBasisRight, vBasisUp, vBasisPos, vBasisForward; // If it's really close, change the near Z and transform it into clipping space if(pInstance->m_Flags & FLAG_REALLYCLOSE) { //we are in camera space, so up and right are always the standard vBasisRight.Init(1.0f, 0.0f, 0.0f); vBasisUp.Init(0.0f, 1.0f, 0.0f); vBasisForward.Init(0.0f, 0.0f, 1.0f); vBasisPos.Init(0.0f, 0.0f, 0.0f); } else { //Otherwise we need to grab the camera's up and right vBasisRight = Params.m_Right; vBasisUp = Params.m_Up; vBasisForward = Params.m_Forward; vBasisPos = Params.m_Pos; } //get the object position LTVector vPos = pInstance->GetPos(); //find the Z distance float fZ = (vPos - vBasisPos).Dot(vBasisForward); //bail if this is too close to even be seen if(!(pInstance->m_Flags & FLAG_REALLYCLOSE) && (fZ < NEARZ)) return; if(!d3d_SetTexture(pShared, 0, eFS_SpriteTexMemory)) return; float fWidth = (float)((RTexture*)pShared->m_pRenderData)->GetBaseWidth(); float fHeight = (float)((RTexture*)pShared->m_pRenderData)->GetBaseHeight(); float fSizeX = fWidth * pInstance->m_Scale.x; float fSizeY = fHeight * pInstance->m_Scale.y; if(pInstance->m_Flags & FLAG_GLOWSPRITE) { //find the scale factor float fFactor = (fZ - SPRITE_MINFACTORDIST) / (SPRITE_MAXFACTORDIST - SPRITE_MINFACTORDIST); fFactor = LTCLAMP(fFactor, 0.0f, 1.0f); fFactor = SPRITE_MINFACTOR + ((SPRITE_MAXFACTOR-SPRITE_MINFACTOR) * fFactor); fSizeX *= fFactor; fSizeY *= fFactor; } //find the color of this sprite RGBColor Color; d3d_GetSpriteColor(pInstance, &Color); uint32 nColor = Color.color; //scale up to be the appropriate half height LTVector vRight = vBasisRight * fSizeX; LTVector vUp = vBasisUp * fSizeY; // Generate our vertices CSpriteVertex SpriteVerts[4]; SpriteVerts[0].SetupVert(vPos + vUp - vRight, nColor, 0.0f, 0.0f); SpriteVerts[1].SetupVert(vPos + vUp + vRight, nColor, 1.0f, 0.0f); SpriteVerts[2].SetupVert(vPos + vRight - vUp, nColor, 1.0f, 1.0f); SpriteVerts[3].SetupVert(vPos - vRight - vUp, nColor, 0.0f, 1.0f); if((pInstance->m_Flags & FLAG_SPRITEBIAS) && !(pInstance->m_Flags & FLAG_REALLYCLOSE)) { //find the bias, up to, but not including the near plane float fBiasDist = SPRITE_POSITION_ZBIAS; if((fZ + fBiasDist) < NEARZ) fBiasDist = NEARZ - fZ; //now adjust our vectors accordingly so that we can move it forward //but have it be the same size float fScale = 1 + fBiasDist / fZ; //adjust the points for(uint32 nCurrPt = 0; nCurrPt < 4; nCurrPt++) { LTVector& vPt = SpriteVerts[nCurrPt].m_Vec; vPt = vBasisRight * (vPt - vBasisPos).Dot(vBasisRight) * fScale + vBasisUp * (vPt - vBasisPos).Dot(vBasisUp) * fScale + (fZ + fBiasDist) * vBasisForward + vBasisPos; } } //Render our lovely verts LTEffectImpl* pEffect = (LTEffectImpl*)LTEffectShaderMgr::GetSingleton().GetEffectShader(pInstance->m_nEffectShaderID); if(pEffect) { pEffect->UploadVertexDeclaration(); ID3DXEffect* pD3DEffect = pEffect->GetEffect(); if(pD3DEffect) { RTexture* pTexture = (RTexture*)pShared->m_pRenderData; pD3DEffect->SetTexture("texture0", pTexture->m_pD3DTexture); i_client_shell->OnEffectShaderSetParams(pEffect, NULL, NULL, LTShaderDeviceStateImp::GetSingleton()); UINT nPasses = 0; pD3DEffect->Begin(&nPasses, 0); for(UINT i = 0; i < nPasses; ++i) { pD3DEffect->BeginPass(i); D3D_CALL(PD3DDEVICE->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, SpriteVerts, sizeof(CSpriteVertex))); pD3DEffect->EndPass(); } pD3DEffect->End(); } } else { D3D_CALL(PD3DDEVICE->SetVertexShader(NULL)); D3D_CALL(PD3DDEVICE->SetFVF(SPRITEVERTEX_FORMAT)); D3D_CALL(PD3DDEVICE->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, SpriteVerts, sizeof(CSpriteVertex))); } d3d_DisableTexture(0); }
void CD3D_Device::SetDefaultRenderStates() { // Basic Render State defaults... if (m_ExtraDevCaps.m_bUsingTableFog) { D3D_CALL(m_pD3DDevice->SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_LINEAR)); D3D_CALL(m_pD3DDevice->SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_NONE)); } else { D3D_CALL(m_pD3DDevice->SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR)); D3D_CALL(m_pD3DDevice->SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_NONE)); } // D3D_CALL(m_pD3DDevice->SetRenderState(D3DRS_EDGEANTIALIAS, FALSE)); D3D_CALL(m_pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE)); D3D_CALL(m_pD3DDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE)); D3D_CALL(m_pD3DDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE)); D3D_CALL(m_pD3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL)); D3D_CALL(m_pD3DDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, F2DW(0.0f))); D3D_CALL(m_pD3DDevice->SetRenderState(D3DRS_DEPTHBIAS, F2DW(0.0f))); D3D_CALL(m_pD3DDevice->SetRenderState(D3DRS_SPECULARENABLE, FALSE)); D3D_CALL(m_pD3DDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD)); D3D_CALL(m_pD3DDevice->SetRenderState(D3DRS_DITHERENABLE, TRUE)); D3D_CALL(m_pD3DDevice->SetRenderState(D3DRS_FILLMODE, g_CV_Wireframe ? D3DFILL_WIREFRAME : D3DFILL_SOLID)); D3D_CALL(m_pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE)); D3D_CALL(m_pD3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE)); D3D_CALL(m_pD3DDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL)); D3D_CALL(m_pD3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA)); D3D_CALL(m_pD3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA)); D3D_CALL(m_pD3DDevice->SetRenderState(D3DRS_COLORVERTEX, FALSE)); D3D_CALL(m_pD3DDevice->SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_DISABLE)); D3D_CALL(m_pD3DDevice->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE)); D3D_CALL(m_pD3DDevice->SetRenderState(D3DRS_NORMALIZENORMALS,FALSE)); D3D_CALL(m_pD3DDevice->SetRenderState(D3DRS_CLIPPING, TRUE)); // HW Transform & Light... D3D_CALL(m_pD3DDevice->SetSoftwareVertexProcessing(((g_Device.GetDeviceCaps()->DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0) ? 1 : 0)); // Setup Material (for D3D lighting)... D3D_CALL(m_pD3DDevice->SetRenderState(D3DRS_LIGHTING,FALSE)); D3D_CALL(m_pD3DDevice->SetRenderState(D3DRS_AMBIENTMATERIALSOURCE,D3DMCS_MATERIAL)); D3D_CALL(m_pD3DDevice->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE,D3DMCS_MATERIAL)); D3D_CALL(m_pD3DDevice->SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE,D3DMCS_MATERIAL)); D3D_CALL(m_pD3DDevice->SetRenderState(D3DRS_SPECULARMATERIALSOURCE,D3DMCS_MATERIAL)); // Texture Stage States... for(uint32 nCurrStage = 0; nCurrStage < 4; nCurrStage++) { D3D_CALL(m_pD3DDevice->SetTextureStageState(nCurrStage, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU | nCurrStage)); D3D_CALL(m_pD3DDevice->SetTextureStageState(nCurrStage, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE)); D3D_CALL(m_pD3DDevice->SetSamplerState(nCurrStage, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP)); D3D_CALL(m_pD3DDevice->SetSamplerState(nCurrStage, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP)); D3D_CALL(PD3DDEVICE->SetSamplerState(nCurrStage, D3DSAMP_MAXANISOTROPY, g_CV_Anisotropic.m_Val ? g_CV_Anisotropic.m_Val : 1)); // check for device caps anisotropic filter for min filter if ((m_DeviceCaps.VertexTextureFilterCaps & D3DPTFILTERCAPS_MINFANISOTROPIC) && (g_CV_Anisotropic.m_Val)) { D3D_CALL(PD3DDEVICE->SetSamplerState(nCurrStage, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC)); } else { D3D_CALL(PD3DDEVICE->SetSamplerState(nCurrStage, D3DSAMP_MINFILTER, g_CV_Bilinear.m_Val ? D3DTEXF_LINEAR : D3DTEXF_POINT)); } // check for device cpas anistropic filter for mag filter if ((m_DeviceCaps.VertexTextureFilterCaps & D3DPTFILTERCAPS_MAGFANISOTROPIC) && (g_CV_Anisotropic.m_Val)) { D3D_CALL(PD3DDEVICE->SetSamplerState(nCurrStage, D3DSAMP_MAGFILTER, D3DTEXF_ANISOTROPIC)); } else { D3D_CALL(PD3DDEVICE->SetSamplerState(nCurrStage, D3DSAMP_MAGFILTER, g_CV_Bilinear.m_Val ? D3DTEXF_LINEAR : D3DTEXF_POINT)); } D3D_CALL(PD3DDEVICE->SetSamplerState(nCurrStage, D3DSAMP_MIPFILTER, g_CV_Trilinear.m_Val ? D3DTEXF_LINEAR : D3DTEXF_POINT)); d3d_DisableTexture(nCurrStage); } //setup a default blend D3D_CALL(m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE)); D3D_CALL(m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE)); D3D_CALL(m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE)); D3D_CALL(m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE)); D3D_CALL(m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE)); D3D_CALL(m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE)); D3D_CALL(m_pD3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE)); D3D_CALL(m_pD3DDevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE)); D3D_CALL(m_pD3DDevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT)); D3D_CALL(m_pD3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE)); D3D_CALL(m_pD3DDevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE)); D3D_CALL(m_pD3DDevice->SetTextureStageState(1, D3DTSS_ALPHAARG2, D3DTA_CURRENT)); //turn off alpha ref D3D_CALL(m_pD3DDevice->SetRenderState(D3DRS_ALPHAREF, 0)); // Setup the Material...This should be set on the per piece basis, but for the fall release I'm just setting it the once and moving on... D3DMATERIAL9 Material; D3DCOLORVALUE MatColor1; MatColor1.r = 1.0f; MatColor1.g = 1.0f; MatColor1.b = 1.0f; MatColor1.a = 1.0f; D3DCOLORVALUE MatColor2; MatColor2.r = 0.0f; MatColor2.g = 0.0f; MatColor2.b = 0.0f; MatColor2.a = 0.0f; Material.Diffuse = MatColor1; Material.Ambient = MatColor1; Material.Specular = MatColor2; Material.Emissive = MatColor2; Material.Power = 0.0f; g_RenderStateMgr.SetMaterial(Material); assert(m_pD3DDevice); }
// technique TechniqueHandle Gfx_Technique_Create(RenderDevice* dev, const TechniqueDescr& descr) { if( descr.ps.valid()==false || descr.vs.valid()==false || descr.vf.valid()==false ) { return InvalidResourceHandle();; } TechniqueDX11 res; res.ps = descr.ps; res.vs = descr.vs; res.vf = descr.vf; const VertexFormatDescr& vf_descr = dev->resources.vertex_formats[descr.vf].descr; const uint32 max_vertex_elements = 32; StaticArray<D3D11_INPUT_ELEMENT_DESC, max_vertex_elements> elements; UINT num_elements = (UINT)vf_descr.num_elements(); for( uint32 i=0; i<num_elements; ++i ) { const VertexFormatDescr::Element& elem = vf_descr.element(i); D3D11_INPUT_ELEMENT_DESC& native_elem = elements[i]; native_elem.SemanticName = dx11_convert<const char*>(elem.usage); native_elem.SemanticIndex = elem.index; native_elem.Format = dx11_convert<DXGI_FORMAT>(elem.type); native_elem.InputSlot = elem.stream; native_elem.AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT; native_elem.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; native_elem.InstanceDataStepRate = 0; elements.current_size++; } const ShaderCode& vsh_code = dev->resources.vertex_shaders[descr.vs].code; D3D_CALL(dev->native->CreateInputLayout(elements.data, num_elements, vsh_code.data(), vsh_code.size(), &res.input_layout)); const ShaderConstantTable& vs_constants = dev->resources.vertex_shaders[descr.vs].constants; const ShaderConstantTable& ps_constants = dev->resources.pixel_shaders[descr.ps].constants; if( descr.bindings ) { for( uint32 i=0; i<descr.bindings->items.size(); ++i ) { const ShaderConstantBindings::Item& item = descr.bindings->items[i]; if( item.type == ShaderConstantBindings::BindingType_Constant ) { ShaderConstantIndex vs_idx = vs_constants.index_from_name(item.name); if( vs_idx.is_valid() ) { TechniqueDX11::Binding b; b.index = vs_idx.index; b.count = rush_min(vs_idx.count, item.count); b.data = item.data; res.vs_bindings.push_back(b); } ShaderConstantIndex ps_idx = ps_constants.index_from_name(item.name); if( ps_idx.is_valid() ) { TechniqueDX11::Binding b; b.index = ps_idx.index; b.count = rush_min(ps_idx.count, item.count); b.data = item.data; res.ps_bindings.push_back(b); } } else if( item.type == ShaderConstantBindings::BindingType_Sampler ) { // TODO } } } return dev->resources.techniques.push(res); }