void FForwardPlusRenderer::DoScenePass(const FCamera& Camera, class IScene* Scene) { // Clear depth buffer ID3D11DeviceContext* DeviceContext = GraphicsContext->GetImmediateContext(); const FLOAT ClearColour[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; ID3D11RenderTargetView* BackBuffer = HighDynamicRangeMSAATarget->GetRenderTarget(); DeviceContext->ClearDepthStencilView(HighDynamicRangeMSAATarget->GetDepthStencil(), D3D11_CLEAR_STENCIL | D3D11_CLEAR_DEPTH, 1.0f, 0); DeviceContext->ClearRenderTargetView(BackBuffer, ClearColour); DeviceContext->OMSetRenderTargets(1, &BackBuffer, HighDynamicRangeMSAATarget->GetDepthStencil()); FViewport Fullscreen(0, 0, GraphicsContext->GetWidth(), GraphicsContext->GetHeight()); D3D11_VIEWPORT Viewport = Fullscreen.CreateRenderViewport(); DeviceContext->RSSetViewports(1, &Viewport); InstanceBuffer->SetWorld(glm::mat4(1.0)); ID3D11RasterizerState* PreviousState = nullptr; if (ForceWireframe.AsBoolean()) { DeviceContext->RSGetState(&PreviousState); DeviceContext->RSSetState(GraphicsContext->GetRenderStates()->WireframeRasterizer); } FDrawCall Params(DeviceContext, InstanceBuffer.Get()); Scene->Draw(Params); if (PreviousState != nullptr) { DeviceContext->RSSetState(PreviousState); } }
bool SkyBox::Render(std::shared_ptr<D3DRenderer> d3d, DirectX::CXMMATRIX world, DirectX::CXMMATRIX view, DirectX::CXMMATRIX projection, std::shared_ptr<Camera> camera, std::shared_ptr<Light> light) { ID3D11DeviceContext *context = d3d->GetDeviceContext(); DirectX::XMMATRIX sphereWorld = DirectX::XMMatrixIdentity(), scale = DirectX::XMMatrixScaling(0.3f, 0.3f, 0.3f), translation; translation = DirectX::XMMatrixTranslationFromVector(camera->GetPosition()); sphereWorld = scale * translation; if (!SetShaderParameters(context, sphereWorld, view, projection, texture->GetTexture())) return false; UINT strides = sizeof(DirectX::VertexPositionNormalTexture), offset = 0; context->IASetInputLayout(m_layout); context->IASetIndexBuffer(sphereIndexBuffer, DXGI_FORMAT_R32_UINT, 0); context->IASetVertexBuffers(0, 1, &sphereVertBuffer, &strides, &offset); context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); context->PSSetShader(pixelShader, NULL, 0); context->VSSetShader(vertexShader, NULL, 0); context->RSSetState(d3d->GetRasterState(1)); d3d->SetDepthLessEqual(); context->DrawIndexed(NumSphereFaces*3, 0, 0); d3d->End2D(); context->RSSetState(d3d->GetRasterState(0)); return true; }
//--------------------------------------------------------------------------- void FontRenderer::FontDrawingBegin( RenderContext* rc ) { assert( m_vertexBuffer != NULL ); assert( m_indexBuffer != NULL ); m_currentRC = rc; m_fontDrawOps.clear(); ID3D11DeviceContext* dc = m_currentRC->Context(); UINT viewportCount = 1; D3D11_VIEWPORT vp; dc->RSGetViewports(&viewportCount, &vp); UINT stride = sizeof(FontTextVertex); UINT offset = 0; dc->IASetInputLayout(m_vertexLayout); dc->IASetIndexBuffer(m_indexBuffer, DXGI_FORMAT_R32_UINT, 0); dc->IASetVertexBuffers(0, 1, &m_vertexBuffer, &stride, &offset); dc->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); dc->VSSetShader( m_vertexShader, 0, 0 ); dc->PSSetShader( m_pixelShader, 0, 0 ); dc->PSSetSamplers( 0, 1, &m_samplerState ); dc->RSSetState(m_rasterState); float blendFactor[4] = {1.0f}; dc->OMSetBlendState(m_blendState, blendFactor, 0xffffffff); m_activeFont = NULL; // needs to be set! }
void PipelineStateCache::setRasterizerState(ID3D11RasterizerState* rasterizerState) { if (rasterizerState != m_currentRasterizerState) { m_currentRasterizerState = rasterizerState; m_deviceContext->RSSetState(m_currentRasterizerState); } }
//----------------------------------------------------------------------------- void CPUTRenderStateBlockDX11::SetRenderStates( CPUTRenderParameters &renderParams ) { ID3D11DeviceContext *pContext = ((CPUTRenderParametersDX*)&renderParams)->mpContext; pContext->OMSetBlendState( mpBlendState, mStateDesc.BlendFactor, mStateDesc.SampleMask ); pContext->OMSetDepthStencilState( mpDepthStencilState, 0 ); // TODO: read stecil ref from config file pContext->RSSetState( mpRasterizerState ); pContext->PSSetSamplers( 0, mNumSamplers, mpSamplerState ); pContext->VSSetSamplers( 0, mNumSamplers, mpSamplerState ); pContext->GSSetSamplers( 0, mNumSamplers, mpSamplerState ); } // CPUTRenderStateBlockDX11::SetRenderState()
~CDX11StateGuard() { ID3D11Device* pDevice = static_cast<ID3D11Device*>( gD3DDevice ); ID3D11DeviceContext* pContext = NULL; pDevice->GetImmediateContext( &pContext ); // Apply saved state pContext->OMSetBlendState( m_pBlendState, m_BlendFactor, m_SampleMask ); pContext->RSSetState( m_pRasterizerState ); pContext->IASetPrimitiveTopology( m_PrimitiveTopology ); pContext->IASetIndexBuffer( m_pIndexBuffer, m_IndexBufferFormat, m_IndexBufferOffset ); pContext->IASetInputLayout( m_pInputLayout ); pContext->IASetVertexBuffers( 0, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT, m_pVertexBuffers, m_pVertexBufferStrides, m_pVertexBufferOffsets ); pContext->VSSetShader( m_pVertexShader, m_ppVertexShaderClassInstances, m_VertexShaderClassInstancesCount ); pContext->PSSetShader( m_pPixelShader, m_ppPixelShaderClassInstances, m_PixelShaderClassInstancesCount ); pContext->PSSetSamplers( 0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, m_ppPixelShaderSamplers ); pContext->PSSetShaderResources( 0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, m_ppPixelShaderResources ); // Release references SAFE_RELEASE( m_pBlendState ); SAFE_RELEASE( m_pRasterizerState ); SAFE_RELEASE( m_pIndexBuffer ); SAFE_RELEASE( m_pInputLayout ); for ( UINT i = 0; i < D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT; ++i ) { SAFE_RELEASE( m_pVertexBuffers[i] ); } SAFE_RELEASE( m_pVertexShader ); for ( UINT i = 0; i < m_VertexShaderClassInstancesCount; ++i ) { SAFE_RELEASE( m_ppVertexShaderClassInstances[i] ); } SAFE_RELEASE( m_pPixelShader ); for ( UINT i = 0; i < m_PixelShaderClassInstancesCount; ++i ) { SAFE_RELEASE( m_ppPixelShaderClassInstances[i] ); } for ( UINT i = 0; i < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; ++i ) { SAFE_RELEASE( m_ppPixelShaderSamplers[i] ); } for ( UINT i = 0; i < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; ++i ) { SAFE_RELEASE( m_ppPixelShaderResources[i] ); } }
static void SetDefaultGraphicsState () { #if SUPPORT_D3D11 // D3D11 case if (s_DeviceType == kUnityGfxRendererD3D11) { ID3D11DeviceContext* ctx = NULL; g_D3D11Device->GetImmediateContext (&ctx); ctx->OMSetDepthStencilState (g_D3D11DepthState, 0); ctx->RSSetState (g_D3D11RasterState); ctx->OMSetBlendState (g_D3D11BlendState, NULL, 0xFFFFFFFF); ctx->Release(); } #endif }
void SkyObject::Render(const ICamera &camera) { camera.GetPosition(transform->position); Matrix objectMatrix; transform->GetTransformMatrixQuaternion(objectMatrix); Matrix wvpMatrix = objectMatrix*camera.GetViewProjectionMatrix(); mSkyShader->SetVertexBufferValues(wvpMatrix, objectMatrix); ID3D11DeviceContext *context = pD3dGraphicsObj->GetDeviceContext(); primitive->Draw(mSkyShader.get(), mSkyShader->GetInputLayout(), false, false, [=] { ID3D11RasterizerState* rasterizeState = pCommonStates->CullNone(); context->RSSetState(rasterizeState); } ); }
/* Renders entity */ void CEntity::Render(unsigned int &prevMeshID) const { if (mRenderEntity) { CRenderManager* rm = CRenderManager::GetInstance(); ID3D11DeviceContext* deviceContext = rm->GetDeviceContext(); geom::CMesh* mesh = mTemplate->mMesh; if (mesh != NULL) { if (mesh->GetUID() != prevMeshID) { /* Sets the buffers */ ID3D11Buffer* vertexBuffer = mesh->GetVertexBuffer(); ID3D11Buffer* indexBuffer = mesh->GetIndexBuffer(); UINT stride = mesh->GetVertexSize(); UINT offset = 0; deviceContext->IASetVertexBuffers( 0, 1, &vertexBuffer, &stride, &offset ); deviceContext->IASetIndexBuffer( indexBuffer, DXGI_FORMAT_R16_UINT, 0 ); deviceContext->IASetPrimitiveTopology( mesh->GetTopology() ); /* Sets texture */ ID3D11ShaderResourceView* texture = mesh->GetTexture(); if (texture != NULL) { ID3D11SamplerState* sample = mesh->GetSample(); int startSlot = mesh->GetStartSlot(); deviceContext->PSSetShaderResources( startSlot, 1, &texture ); deviceContext->PSSetSamplers( startSlot, 1, &sample ); deviceContext->RSSetState( mTemplate->mRasterState ); } } deviceContext->DrawIndexed( mesh->GetNumberOfIndices(), 0, 0 ); prevMeshID = mesh->GetUID(); } } }
void Draw() { ID3D11DeviceContext* context = g_d3d.context_.get(); // Clear float clearColor[] = { 0.3f, 0.3f, 0.3f, 1.0f }; context->ClearRenderTargetView( g_d3d.backBufferRTV_.get(), clearColor ); auto* rtv = g_d3d.backBufferRTV_.get(); context->OMSetRenderTargets( 1, &rtv, nullptr ); // Draw body auto cbModelWVP = DirectX::XMMatrixIdentity(); auto matWorld = DirectX::XMMatrixIdentity(); matWorld = DirectX::XMMatrixRotationRollPitchYaw( g_d3d.jointRot_[ 0 ], g_d3d.jointRot_[ 1 ], g_d3d.jointRot_[ 2 ] ); auto matView = DirectX::XMMatrixLookAtLH( DirectX::XMVectorSet( 0, 0, -3, 0 ), DirectX::XMVectorSet( 0, 0, 5, 0 ), DirectX::XMVectorSet( 0, 1, 0, 0 ) ); auto matProj = DirectX::XMMatrixPerspectiveFovLH( DirectX::XMConvertToRadians( 50 ), (float)g_windowWidth / (float)g_windowHeight, 0.01f, 1000.0f ); cbModelWVP = matWorld * matView * matProj; cbModelWVP = DirectX::XMMatrixTranspose( cbModelWVP ); g_d3d.context_->UpdateSubresource( g_d3d.modelCB_.get(), 0, nullptr, &cbModelWVP, 0, 0 ); auto* vb = g_d3d.modelVB_.get(); unsigned int stride = sizeof( D3D::MeshFormat ); unsigned int offset = 0; auto* cb = g_d3d.modelCB_.get(); D3D11_VIEWPORT viewport = { 0, 0, g_windowWidth, g_windowHeight, 0, 1 }; context->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST ); context->IASetInputLayout( g_d3d.modelIL_.get() ); context->IASetVertexBuffers( 0, 1, &vb, &stride, &offset ); context->VSSetShader( g_d3d.modelVS_.get(), nullptr, 0 ); context->VSSetConstantBuffers( 0, 1, &cb ); context->RSSetState( g_d3d.rasterState_.get() ); context->PSSetShader( g_d3d.modelPS_.get(), nullptr, 0 ); context->RSSetViewports( 1, &viewport ); context->Draw( 18, 0 ); g_d3d.swapChain_->Present( 1, 0 ); }
//--------------------------------------------------------------------------- void ShadowMapGen::Begin(RenderContext* rc, RenderSurface* pSurface, const AABB& bounds ) { m_rc = rc; m_pSurface = pSurface; ID3D11DeviceContext* dc = m_rc->Context(); // set depth-stencil state to default. dc->OMSetDepthStencilState(NULL,0); ShadowMaps::Inst()->UpdateLightCamera(dc, LightingState::Inst()->ProminentDirLight(), bounds); ShadowMaps::Inst()->SetAndClear(dc); dc->RSSetState( m_rasterStateShadow ); const Camera& lightCam = ShadowMaps::Inst()->GetCamera(); // update per frame cb ConstantBufferShadowMapGenPerFrame constBuffer; Matrix::Transpose(lightCam.View() ,constBuffer.view); Matrix::Transpose(lightCam.Proj(),constBuffer.proj); UpdateConstantBuffer(dc,m_pConstantBufferPerFrame,&constBuffer,sizeof(constBuffer)); // set imput layout. dc->IASetInputLayout( m_pVertexLayoutMesh ); // set shaders dc->VSSetShader( m_shaderShadowMapsVS, NULL, 0 ); dc->PSSetShader( NULL, NULL, 0 ); dc->GSSetShader( NULL, NULL, 0 ); ID3D11Buffer* constantBuffers[] = { m_pConstantBufferPerFrame, m_pConstantBufferPerDraw }; // set const buffers for vertex shader. dc->VSSetConstantBuffers( 0, ARRAY_SIZE(constantBuffers), constantBuffers ); }
// parameters should be validated/clamped by caller EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) { if (!mSwapChain) { return EGL_SUCCESS; } ID3D11Device *device = mRenderer->getDevice(); ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); // Set vertices D3D11_MAPPED_SUBRESOURCE mappedResource; HRESULT result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); if (FAILED(result)) { return EGL_BAD_ACCESS; } d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData); // Create a quad in homogeneous coordinates float x1 = (x / float(mWidth)) * 2.0f - 1.0f; float y1 = (y / float(mHeight)) * 2.0f - 1.0f; float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f; float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f; float u1 = x / float(mWidth); float v1 = y / float(mHeight); float u2 = (x + width) / float(mWidth); float v2 = (y + height) / float(mHeight); d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v1); d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2); d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1); d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2); deviceContext->Unmap(mQuadVB, 0); static UINT stride = sizeof(d3d11::PositionTexCoordVertex); static UINT startIdx = 0; deviceContext->IASetVertexBuffers(0, 1, &mQuadVB, &stride, &startIdx); // Apply state deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF); static const float blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; deviceContext->OMSetBlendState(NULL, blendFactor, 0xFFFFFFF); deviceContext->RSSetState(NULL); // Apply shaders deviceContext->IASetInputLayout(mPassThroughIL); deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); deviceContext->VSSetShader(mPassThroughVS, NULL, 0); deviceContext->PSSetShader(mPassThroughPS, NULL, 0); deviceContext->GSSetShader(NULL, NULL, 0); // Apply render targets mRenderer->setOneTimeRenderTarget(mBackBufferRTView); // Set the viewport D3D11_VIEWPORT viewport; viewport.TopLeftX = 0; viewport.TopLeftY = 0; viewport.Width = mWidth; viewport.Height = mHeight; viewport.MinDepth = 0.0f; viewport.MaxDepth = 1.0f; deviceContext->RSSetViewports(1, &viewport); // Apply textures deviceContext->PSSetShaderResources(0, 1, &mOffscreenSRView); deviceContext->PSSetSamplers(0, 1, &mPassThroughSampler); // Draw deviceContext->Draw(4, 0); result = mSwapChain->Present(mSwapInterval, 0); if (result == DXGI_ERROR_DEVICE_REMOVED) { HRESULT removedReason = device->GetDeviceRemovedReason(); ERR("Present failed: the D3D11 device was removed: 0x%08X", removedReason); return EGL_CONTEXT_LOST; } else if (result == DXGI_ERROR_DEVICE_RESET) { ERR("Present failed: the D3D11 device was reset from a bad command."); return EGL_CONTEXT_LOST; } else if (FAILED(result)) { ERR("Present failed with error code 0x%08X", result); } // Unbind static ID3D11ShaderResourceView *const nullSRV = NULL; deviceContext->PSSetShaderResources(0, 1, &nullSRV); mRenderer->unapplyRenderTargets(); mRenderer->markAllStateDirty(); return EGL_SUCCESS; }
void FBXObject::SetupDrawRasterizeShader() { ID3D11DeviceContext* pImmediateContext = DX11App::getInstance()->direct3d.pImmediateContext; pImmediateContext->RSSetState( this->pRastersizerState.second ); }
// parameters should be validated/clamped by caller EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) { if (!mSwapChain) { return EGL_SUCCESS; } if (mRenderToBackBuffer) { // When rendering directly to the backbuffer, we must swap the whole buffer. if (!(x == 0 && y == 0 && width == mWidth && height == mHeight)) { ERR("When rendering directly to the backbuffer, swapRect can only be called on the entire backbuffer."); ASSERT(false); return EGL_FALSE; } } HRESULT result = S_OK; ID3D11Device *device = mRenderer->getDevice(); if (!mRenderToBackBuffer) { ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); // Set vertices D3D11_MAPPED_SUBRESOURCE mappedResource; result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); if (FAILED(result)) { return EGL_BAD_ACCESS; } d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData); // Create a quad in homogeneous coordinates float x1 = (x / float(mWidth)) * 2.0f - 1.0f; float y1 = (y / float(mHeight)) * 2.0f - 1.0f; float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f; float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f; float u1 = x / float(mWidth); float v1 = y / float(mHeight); float u2 = (x + width) / float(mWidth); float v2 = (y + height) / float(mHeight); d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v1); d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2); d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1); d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2); deviceContext->Unmap(mQuadVB, 0); static UINT stride = sizeof(d3d11::PositionTexCoordVertex); static UINT startIdx = 0; deviceContext->IASetVertexBuffers(0, 1, &mQuadVB, &stride, &startIdx); // Apply state deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF); static const float blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; deviceContext->OMSetBlendState(NULL, blendFactor, 0xFFFFFFF); deviceContext->RSSetState(NULL); // Apply shaders deviceContext->IASetInputLayout(mPassThroughIL); deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); deviceContext->VSSetShader(mPassThroughVS, NULL, 0); deviceContext->PSSetShader(mPassThroughPS, NULL, 0); deviceContext->GSSetShader(NULL, NULL, 0); // Apply render targets mRenderer->setOneTimeRenderTarget(mBackBufferRTView); // Set the viewport D3D11_VIEWPORT viewport; viewport.TopLeftX = 0; viewport.TopLeftY = 0; viewport.Width = static_cast<FLOAT>(mWidth); viewport.Height = static_cast<FLOAT>(mHeight); viewport.MinDepth = 0.0f; viewport.MaxDepth = 1.0f; deviceContext->RSSetViewports(1, &viewport); // Apply textures mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, mOffscreenSRView); deviceContext->PSSetSamplers(0, 1, &mPassThroughSampler); // Draw deviceContext->Draw(4, 0); } #if ANGLE_VSYNC == ANGLE_DISABLED result = mSwapChain->Present(0, 0); #else // Use IDXGISwapChain1::Present1 with a dirty rect if DXGI 1.2 is available. if (mSwapChain1 != nullptr) { RECT rect = { static_cast<LONG>(x), static_cast<LONG>(mHeight - y - height), static_cast<LONG>(x + width), static_cast<LONG>(mHeight - y) }; DXGI_PRESENT_PARAMETERS params = { 1, &rect, nullptr, nullptr }; result = mSwapChain1->Present1(mSwapInterval, 0, ¶ms); } else { result = mSwapChain->Present(mSwapInterval, 0); } #endif if (result == DXGI_ERROR_DEVICE_REMOVED) { HRESULT removedReason = device->GetDeviceRemovedReason(); UNUSED_TRACE_VARIABLE(removedReason); ERR("Present failed: the D3D11 device was removed: 0x%08X", removedReason); return EGL_CONTEXT_LOST; } else if (result == DXGI_ERROR_DEVICE_RESET) { ERR("Present failed: the D3D11 device was reset from a bad command."); return EGL_CONTEXT_LOST; } else if (FAILED(result)) { ERR("Present failed with error code 0x%08X", result); } // Unbind mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); mRenderer->unapplyRenderTargets(); mRenderer->markAllStateDirty(); return EGL_SUCCESS; }
void VegetationRendering::draw(ID3D11Device* device, const GameTime& gameTime) { ID3D11DeviceContext* deviceContext; device->GetImmediateContext(&deviceContext); D3D11_VIEWPORT viewport; unsigned numViewports = 1; deviceContext->RSGetViewports(&numViewports, &viewport); camera->setAspectRatio(viewport.Width / viewport.Height); deviceContext->RSSetState(rsCullBack); deviceContext->OMSetBlendState(bsDefault, Vector4(0,0,0,0), 0xFFFFFFFF); terrain->draw(device, gameTime); //tessellationTerrain->draw(device, gameTime); if (complexTreesEnabled) trunk->draw(device, gameTime); deviceContext->RSSetState(rsCullNone); if(treeModelsEnabled) { separateLeafModel->draw(device, gameTime); billboardLeafModel->draw(device, gameTime); } if (defaultTreesEnabled) { for(int i = 0; i < trunk->getDrawInstanceCount(); ++i) { Matrix trunkWorld = Matrix::createTranslation(trunk->getTreePositions()[i]); /*if(defaultDetailedEnabled) { defaultTrunkDetailedModel->setWorld(trunkWorld); defaultTrunkDetailedModel->draw(device, gameTime); } else {*/ defaultTrunkModel->setWorld(trunkWorld); defaultTrunkModel->draw(device, gameTime); //} } } if (complexGrassEnabled) complexGrass->draw(device, gameTime); if (defaultGrassEnabled) { for(int i = 0; i < complexGrass->getDrawInstanceCount(); ++i) { Matrix grassWorld = Matrix::createScale(complexGrass->getScale()) * Matrix::createTranslation(complexGrass->getGrassPatchPositions()[i]); if(defaultDetailedEnabled) { defaultGrassDetailedModel->setWorld(grassWorld); defaultGrassDetailedModel->draw(device, gameTime); } else { defaultGrassModel->setWorld(grassWorld); defaultGrassModel->draw(device, gameTime); } } } deviceContext->OMSetBlendState(bsAlphaToCoverage, Vector4(0,0,0,0), 0xFFFFFFFF); if (gsGrassEnabled) gsGrass->draw(device, gameTime); deviceContext->Release(); }
/// Called by D3D11 device to active this state block. /// @param oldState The current state, used to make sure we don't set redundant states on the device. Pass NULL to reset all states. void GFXD3D11StateBlock::activate(GFXD3D11StateBlock* oldState) { PROFILE_SCOPE( GFXD3D11StateBlock_Activate ); ID3D11DeviceContext* pDevCxt = D3D11DEVICECONTEXT; mBlendDesc.AlphaToCoverageEnable = false; mBlendDesc.IndependentBlendEnable = mDesc.separateAlphaBlendEnable; mBlendDesc.RenderTarget[0].BlendEnable = mDesc.blendEnable; mBlendDesc.RenderTarget[0].BlendOp = GFXD3D11BlendOp[mDesc.blendOp]; mBlendDesc.RenderTarget[0].BlendOpAlpha = GFXD3D11BlendOp[mDesc.separateAlphaBlendOp]; mBlendDesc.RenderTarget[0].DestBlend = GFXD3D11Blend[mDesc.blendDest]; mBlendDesc.RenderTarget[0].DestBlendAlpha = GFXD3D11Blend[mDesc.separateAlphaBlendDest]; mBlendDesc.RenderTarget[0].SrcBlend = GFXD3D11Blend[mDesc.blendSrc]; mBlendDesc.RenderTarget[0].SrcBlendAlpha = GFXD3D11Blend[mDesc.separateAlphaBlendSrc]; mBlendDesc.RenderTarget[0].RenderTargetWriteMask = mColorMask; float blendFactor[] = { 1.0f, 1.0f, 1.0f, 1.0f }; pDevCxt->OMSetBlendState(mBlendState, blendFactor, 0xFFFFFFFF); mDepthStencilDesc.DepthWriteMask = mDesc.zWriteEnable ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO; mDepthStencilDesc.DepthEnable = mDesc.zEnable; mDepthStencilDesc.DepthFunc = GFXD3D11CmpFunc[mDesc.zFunc]; mDepthStencilDesc.StencilWriteMask = mDesc.stencilWriteMask; mDepthStencilDesc.StencilReadMask = mDesc.stencilMask; mDepthStencilDesc.StencilEnable = mDesc.stencilEnable; mDepthStencilDesc.FrontFace.StencilFunc = GFXD3D11CmpFunc[mDesc.stencilFunc]; mDepthStencilDesc.FrontFace.StencilFailOp = GFXD3D11StencilOp[mDesc.stencilFailOp]; mDepthStencilDesc.FrontFace.StencilDepthFailOp = GFXD3D11StencilOp[mDesc.stencilZFailOp]; mDepthStencilDesc.FrontFace.StencilPassOp = GFXD3D11StencilOp[mDesc.stencilPassOp]; if (mDesc.stencilEnable) mDepthStencilDesc.BackFace = mDepthStencilDesc.FrontFace; else { mDepthStencilDesc.BackFace.StencilFunc = GFXD3D11CmpFunc[GFXCmpAlways]; mDepthStencilDesc.BackFace.StencilFailOp = GFXD3D11StencilOp[GFXStencilOpKeep]; mDepthStencilDesc.BackFace.StencilDepthFailOp = GFXD3D11StencilOp[GFXStencilOpKeep]; mDepthStencilDesc.BackFace.StencilPassOp = GFXD3D11StencilOp[GFXStencilOpKeep]; } pDevCxt->OMSetDepthStencilState(mDepthStencilState, mDesc.stencilRef); mRasterizerDesc.CullMode = GFXD3D11CullMode[mDesc.cullMode]; mRasterizerDesc.FillMode = GFXD3D11FillMode[mDesc.fillMode]; mRasterizerDesc.DepthBias = mDesc.zBias; mRasterizerDesc.SlopeScaledDepthBias = mDesc.zSlopeBias; mRasterizerDesc.AntialiasedLineEnable = FALSE; mRasterizerDesc.MultisampleEnable = FALSE; mRasterizerDesc.ScissorEnable = FALSE; if (mDesc.zEnable) mRasterizerDesc.DepthClipEnable = true; else mRasterizerDesc.DepthClipEnable = false; mRasterizerDesc.FrontCounterClockwise = FALSE; mRasterizerDesc.DepthBiasClamp = 0.0f; pDevCxt->RSSetState(mRasterizerState); U32 numSamplers = GFX->getNumSamplers(); for (U32 i = 0; i < numSamplers; i++) { mSamplerDesc[i].AddressU = GFXD3D11TextureAddress[mDesc.samplers[i].addressModeU]; mSamplerDesc[i].AddressV = GFXD3D11TextureAddress[mDesc.samplers[i].addressModeV]; mSamplerDesc[i].AddressW = GFXD3D11TextureAddress[mDesc.samplers[i].addressModeW]; mSamplerDesc[i].MaxAnisotropy = mDesc.samplers[i].maxAnisotropy; mSamplerDesc[i].MipLODBias = mDesc.samplers[i].mipLODBias; mSamplerDesc[i].MinLOD = 0; mSamplerDesc[i].MaxLOD = FLT_MAX; if(mDesc.samplers[i].magFilter == GFXTextureFilterPoint && mDesc.samplers[i].minFilter == GFXTextureFilterPoint && mDesc.samplers[i].mipFilter == GFXTextureFilterPoint) mSamplerDesc[i].Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; else if(mDesc.samplers[i].magFilter == GFXTextureFilterPoint && mDesc.samplers[i].minFilter == GFXTextureFilterPoint && mDesc.samplers[i].mipFilter == GFXTextureFilterLinear) mSamplerDesc[i].Filter = D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR; else if(mDesc.samplers[i].magFilter == GFXTextureFilterLinear && mDesc.samplers[i].minFilter == GFXTextureFilterPoint && mDesc.samplers[i].mipFilter == GFXTextureFilterPoint) mSamplerDesc[i].Filter = D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT; else if(mDesc.samplers[i].magFilter == GFXTextureFilterLinear && mDesc.samplers[i].minFilter == GFXTextureFilterPoint && mDesc.samplers[i].mipFilter == GFXTextureFilterLinear) mSamplerDesc[i].Filter = D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR; else if(mDesc.samplers[i].magFilter == GFXTextureFilterPoint && mDesc.samplers[i].minFilter == GFXTextureFilterLinear && mDesc.samplers[i].mipFilter == GFXTextureFilterPoint) mSamplerDesc[i].Filter = D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT; else if(mDesc.samplers[i].magFilter == GFXTextureFilterPoint && mDesc.samplers[i].minFilter == GFXTextureFilterLinear && mDesc.samplers[i].mipFilter == GFXTextureFilterLinear) mSamplerDesc[i].Filter = D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR; else if(mDesc.samplers[i].magFilter == GFXTextureFilterLinear && mDesc.samplers[i].minFilter == GFXTextureFilterLinear && mDesc.samplers[i].mipFilter == GFXTextureFilterPoint) mSamplerDesc[i].Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT; else if(mDesc.samplers[i].magFilter == GFXTextureFilterLinear && mDesc.samplers[i].minFilter == GFXTextureFilterLinear && mDesc.samplers[i].mipFilter == GFXTextureFilterLinear) mSamplerDesc[i].Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; else mSamplerDesc[i].Filter = D3D11_FILTER_ANISOTROPIC; mSamplerDesc[i].BorderColor[0] = 0.0f; mSamplerDesc[i].BorderColor[1] = 0.0f; mSamplerDesc[i].BorderColor[2] = 0.0f; mSamplerDesc[i].BorderColor[3] = 0.0f; mSamplerDesc[i].ComparisonFunc = D3D11_COMPARISON_NEVER; } //TODO samplers for vertex shader // Set all the samplers with one call //pDevCxt->VSSetSamplers(0, numSamplers, &mSamplerStates[0]); pDevCxt->PSSetSamplers(0, numSamplers, &mSamplerStates[0]); }
void Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) { // First determine if a scissored clear is needed, this will always require drawing a quad. // // Otherwise, iterate over the color buffers which require clearing and determine if they can be // cleared with ID3D11DeviceContext::ClearRenderTargetView... This requires: // 1) The render target is being cleared to a float value (will be cast to integer when clearing integer // render targets as expected but does not work the other way around) // 2) The format of the render target has no color channels that are currently masked out. // Clear the easy-to-clear buffers on the spot and accumulate the ones that require special work. // // Also determine if the depth stencil can be cleared with ID3D11DeviceContext::ClearDepthStencilView // by checking if the stencil write mask covers the entire stencil. // // To clear the remaining buffers, quads must be drawn containing an int, uint or float vertex color // attribute. gl::Extents framebufferSize; if (frameBuffer->getFirstColorbuffer() != NULL) { gl::Renderbuffer *renderBuffer = frameBuffer->getFirstColorbuffer(); framebufferSize.width = renderBuffer->getWidth(); framebufferSize.height = renderBuffer->getHeight(); framebufferSize.depth = 1; } else if (frameBuffer->getDepthOrStencilbuffer() != NULL) { gl::Renderbuffer *renderBuffer = frameBuffer->getDepthOrStencilbuffer(); framebufferSize.width = renderBuffer->getWidth(); framebufferSize.height = renderBuffer->getHeight(); framebufferSize.depth = 1; } else { UNREACHABLE(); return; } if (clearParams.scissorEnabled && (clearParams.scissor.x >= framebufferSize.width || clearParams.scissor.y >= framebufferSize.height || clearParams.scissor.x + clearParams.scissor.width <= 0 || clearParams.scissor.y + clearParams.scissor.height <= 0)) { // Scissor is enabled and the scissor rectangle is outside the renderbuffer return; } bool needScissoredClear = clearParams.scissorEnabled && (clearParams.scissor.x > 0 || clearParams.scissor.y > 0 || clearParams.scissor.x + clearParams.scissor.width < framebufferSize.width || clearParams.scissor.y + clearParams.scissor.height < framebufferSize.height); GLuint clientVersion = mRenderer->getCurrentClientVersion(); std::vector<RenderTarget11*> maskedClearRenderTargets; RenderTarget11* maskedClearDepthStencil = NULL; ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) { if (clearParams.clearColor[colorAttachment] && frameBuffer->isEnabledColorAttachment(colorAttachment)) { gl::Renderbuffer *renderbuffer = frameBuffer->getColorbuffer(colorAttachment); if (renderbuffer) { RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(renderbuffer->getRenderTarget()); if (!renderTarget) { ERR("Render target pointer unexpectedly null."); return; } GLenum internalFormat = renderbuffer->getInternalFormat(); GLenum actualFormat = renderbuffer->getActualFormat(); GLenum componentType = gl::GetComponentType(internalFormat, clientVersion); if (clearParams.colorClearType == GL_FLOAT && !(componentType == GL_FLOAT || componentType == GL_UNSIGNED_NORMALIZED || componentType == GL_SIGNED_NORMALIZED)) { ERR("It is undefined behaviour to clear a render buffer which is not normalized fixed point or floating-" "point to floating point values (color attachment %u has internal format 0x%X).", colorAttachment, internalFormat); } GLuint internalRedBits = gl::GetRedBits(internalFormat, clientVersion); GLuint internalGreenBits = gl::GetGreenBits(internalFormat, clientVersion); GLuint internalBlueBits = gl::GetBlueBits(internalFormat, clientVersion); GLuint internalAlphaBits = gl::GetAlphaBits(internalFormat, clientVersion); if ((internalRedBits == 0 || !clearParams.colorMaskRed) && (internalGreenBits == 0 || !clearParams.colorMaskGreen) && (internalBlueBits == 0 || !clearParams.colorMaskBlue) && (internalAlphaBits == 0 || !clearParams.colorMaskAlpha)) { // Every channel either does not exist in the render target or is masked out continue; } else if (needScissoredClear || clearParams.colorClearType != GL_FLOAT || (internalRedBits > 0 && !clearParams.colorMaskRed) || (internalGreenBits > 0 && !clearParams.colorMaskGreen) || (internalBlueBits > 0 && !clearParams.colorMaskBlue) || (internalAlphaBits > 0 && !clearParams.colorMaskAlpha)) { // A scissored or masked clear is required maskedClearRenderTargets.push_back(renderTarget); } else { // ID3D11DeviceContext::ClearRenderTargetView is possible ID3D11RenderTargetView *framebufferRTV = renderTarget->getRenderTargetView(); if (!framebufferRTV) { ERR("Render target view pointer unexpectedly null."); return; } // Check if the actual format has a channel that the internal format does not and set them to the // default values GLuint actualRedBits = gl::GetRedBits(actualFormat, clientVersion); GLuint actualGreenBits = gl::GetGreenBits(actualFormat, clientVersion); GLuint actualBlueBits = gl::GetBlueBits(actualFormat, clientVersion); GLuint actualAlphaBits = gl::GetAlphaBits(actualFormat, clientVersion); const float clearValues[4] = { ((internalRedBits == 0 && actualRedBits > 0) ? 0.0f : clearParams.colorFClearValue.red), ((internalGreenBits == 0 && actualGreenBits > 0) ? 0.0f : clearParams.colorFClearValue.green), ((internalBlueBits == 0 && actualBlueBits > 0) ? 0.0f : clearParams.colorFClearValue.blue), ((internalAlphaBits == 0 && actualAlphaBits > 0) ? 1.0f : clearParams.colorFClearValue.alpha), }; deviceContext->ClearRenderTargetView(framebufferRTV, clearValues); } } } } if (clearParams.clearDepth || clearParams.clearStencil) { gl::Renderbuffer *renderbuffer = frameBuffer->getDepthOrStencilbuffer(); if (renderbuffer) { RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(renderbuffer->getDepthStencil()); if (!renderTarget) { ERR("Depth stencil render target pointer unexpectedly null."); return; } GLenum actualFormat = renderbuffer->getActualFormat(); unsigned int stencilUnmasked = frameBuffer->hasStencil() ? (1 << gl::GetStencilBits(actualFormat, clientVersion)) - 1 : 0; bool needMaskedStencilClear = clearParams.clearStencil && (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked; if (needScissoredClear || needMaskedStencilClear) { maskedClearDepthStencil = renderTarget; } else { ID3D11DepthStencilView *framebufferDSV = renderTarget->getDepthStencilView(); if (!framebufferDSV) { ERR("Depth stencil view pointer unexpectedly null."); return; } UINT clearFlags = (clearParams.clearDepth ? D3D11_CLEAR_DEPTH : 0) | (clearParams.clearStencil ? D3D11_CLEAR_STENCIL : 0); FLOAT depthClear = gl::clamp01(clearParams.depthClearValue); UINT8 stencilClear = clearParams.stencilClearValue & 0xFF; deviceContext->ClearDepthStencilView(framebufferDSV, clearFlags, depthClear, stencilClear); } } } if (maskedClearRenderTargets.size() > 0 || maskedClearDepthStencil) { // To clear the render targets and depth stencil in one pass: // // Render a quad clipped to the scissor rectangle which draws the clear color and a blend // state that will perform the required color masking. // // The quad's depth is equal to the depth clear value with a depth stencil state that // will enable or disable depth test/writes if the depth buffer should be cleared or not. // // The rasterizer state's stencil is set to always pass or fail based on if the stencil // should be cleared or not with a stencil write mask of the stencil clear value. // // ====================================================================================== // // Luckily, the gl spec (ES 3.0.2 pg 183) states that the results of clearing a render- // buffer that is not normalized fixed point or floating point with floating point values // are undefined so we can just write floats to them and D3D11 will bit cast them to // integers. // // Also, we don't have to worry about attempting to clear a normalized fixed/floating point // buffer with integer values because there is no gl API call which would allow it, // glClearBuffer* calls only clear a single renderbuffer at a time which is verified to // be a compatible clear type. // Bind all the render targets which need clearing ASSERT(maskedClearRenderTargets.size() <= mRenderer->getMaxRenderTargets()); std::vector<ID3D11RenderTargetView*> rtvs(maskedClearRenderTargets.size()); for (unsigned int i = 0; i < maskedClearRenderTargets.size(); i++) { ID3D11RenderTargetView *renderTarget = maskedClearRenderTargets[i]->getRenderTargetView(); if (!renderTarget) { ERR("Render target pointer unexpectedly null."); return; } rtvs[i] = renderTarget; } ID3D11DepthStencilView *dsv = maskedClearDepthStencil ? maskedClearDepthStencil->getDepthStencilView() : NULL; ID3D11BlendState *blendState = getBlendState(clearParams, maskedClearRenderTargets); const FLOAT blendFactors[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; const UINT sampleMask = 0xFFFFFFFF; ID3D11DepthStencilState *dsState = getDepthStencilState(clearParams); const UINT stencilClear = clearParams.stencilClearValue & 0xFF; // Set the vertices UINT vertexStride = 0; const UINT startIdx = 0; const ClearShader* shader = NULL; D3D11_MAPPED_SUBRESOURCE mappedResource; HRESULT result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); if (FAILED(result)) { ERR("Failed to map masked clear vertex buffer, HRESULT: 0x%X.", result); return; } const gl::Rectangle *scissorPtr = clearParams.scissorEnabled ? &clearParams.scissor : NULL; switch (clearParams.colorClearType) { case GL_FLOAT: ApplyVertices(framebufferSize, scissorPtr, clearParams.colorFClearValue, clearParams.depthClearValue, mappedResource.pData); vertexStride = sizeof(d3d11::PositionDepthColorVertex<float>); shader = &mFloatClearShader; break; case GL_UNSIGNED_INT: ApplyVertices(framebufferSize, scissorPtr, clearParams.colorUIClearValue, clearParams.depthClearValue, mappedResource.pData); vertexStride = sizeof(d3d11::PositionDepthColorVertex<unsigned int>); shader = &mUintClearShader; break; case GL_INT: ApplyVertices(framebufferSize, scissorPtr, clearParams.colorIClearValue, clearParams.depthClearValue, mappedResource.pData); vertexStride = sizeof(d3d11::PositionDepthColorVertex<int>); shader = &mIntClearShader; break; default: UNREACHABLE(); break; } deviceContext->Unmap(mVertexBuffer, 0); // Set the viewport to be the same size as the framebuffer D3D11_VIEWPORT viewport; viewport.TopLeftX = 0; viewport.TopLeftY = 0; viewport.Width = framebufferSize.width; viewport.Height = framebufferSize.height; viewport.MinDepth = 0; viewport.MaxDepth = 1; deviceContext->RSSetViewports(1, &viewport); // Apply state deviceContext->OMSetBlendState(blendState, blendFactors, sampleMask); deviceContext->OMSetDepthStencilState(dsState, stencilClear); deviceContext->RSSetState(mRasterizerState); // Apply shaders deviceContext->IASetInputLayout(shader->inputLayout); deviceContext->VSSetShader(shader->vertexShader, NULL, 0); deviceContext->PSSetShader(shader->pixelShader, NULL, 0); deviceContext->GSSetShader(NULL, NULL, 0); // Apply vertex buffer deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &vertexStride, &startIdx); deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); // Apply render targets deviceContext->OMSetRenderTargets(rtvs.size(), (rtvs.empty() ? NULL : &rtvs[0]), dsv); // Draw the clear quad deviceContext->Draw(4, 0); // Clean up mRenderer->markAllStateDirty(); } }
gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, const gl::Framebuffer::Data &fboData) { const auto &colorAttachments = fboData.mColorAttachments; const auto &drawBufferStates = fboData.mDrawBufferStates; const auto *depthAttachment = fboData.mDepthAttachment; const auto *stencilAttachment = fboData.mStencilAttachment; ASSERT(colorAttachments.size() == drawBufferStates.size()); // Iterate over the color buffers which require clearing and determine if they can be // cleared with ID3D11DeviceContext::ClearRenderTargetView or ID3D11DeviceContext1::ClearView. // This requires: // 1) The render target is being cleared to a float value (will be cast to integer when clearing integer // render targets as expected but does not work the other way around) // 2) The format of the render target has no color channels that are currently masked out. // Clear the easy-to-clear buffers on the spot and accumulate the ones that require special work. // // If these conditions are met, and: // - No scissored clear is needed, then clear using ID3D11DeviceContext::ClearRenderTargetView. // - A scissored clear is needed then clear using ID3D11DeviceContext1::ClearView if available. // Otherwise draw a quad. // // Also determine if the depth stencil can be cleared with ID3D11DeviceContext::ClearDepthStencilView // by checking if the stencil write mask covers the entire stencil. // // To clear the remaining buffers, quads must be drawn containing an int, uint or float vertex color // attribute. gl::Extents framebufferSize; auto iter = std::find_if(colorAttachments.begin(), colorAttachments.end(), [](const gl::FramebufferAttachment *attachment) { return attachment != nullptr; }); if (iter != colorAttachments.end()) { framebufferSize.width = (*iter)->getWidth(); framebufferSize.height = (*iter)->getHeight(); framebufferSize.depth = 1; } else if (depthAttachment != nullptr) { framebufferSize.width = depthAttachment->getWidth(); framebufferSize.height = depthAttachment->getHeight(); framebufferSize.depth = 1; } else if (stencilAttachment != nullptr) { framebufferSize.width = stencilAttachment->getWidth(); framebufferSize.height = stencilAttachment->getHeight(); framebufferSize.depth = 1; } else { UNREACHABLE(); return gl::Error(GL_INVALID_OPERATION); } if (clearParams.scissorEnabled && (clearParams.scissor.x >= framebufferSize.width || clearParams.scissor.y >= framebufferSize.height || clearParams.scissor.x + clearParams.scissor.width <= 0 || clearParams.scissor.y + clearParams.scissor.height <= 0)) { // Scissor is enabled and the scissor rectangle is outside the renderbuffer return gl::Error(GL_NO_ERROR); } bool needScissoredClear = clearParams.scissorEnabled && (clearParams.scissor.x > 0 || clearParams.scissor.y > 0 || clearParams.scissor.x + clearParams.scissor.width < framebufferSize.width || clearParams.scissor.y + clearParams.scissor.height < framebufferSize.height); std::vector<MaskedRenderTarget> maskedClearRenderTargets; RenderTarget11* maskedClearDepthStencil = NULL; ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported(); for (size_t colorAttachment = 0; colorAttachment < colorAttachments.size(); colorAttachment++) { if (clearParams.clearColor[colorAttachment] && colorAttachments[colorAttachment] != nullptr && drawBufferStates[colorAttachment] != GL_NONE) { const gl::FramebufferAttachment *attachment = colorAttachments[colorAttachment]; RenderTarget11 *renderTarget = NULL; gl::Error error = d3d11::GetAttachmentRenderTarget(attachment, &renderTarget); if (error.isError()) { return error; } const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(attachment->getInternalFormat()); if (clearParams.colorClearType == GL_FLOAT && !(formatInfo.componentType == GL_FLOAT || formatInfo.componentType == GL_UNSIGNED_NORMALIZED || formatInfo.componentType == GL_SIGNED_NORMALIZED)) { ERR("It is undefined behaviour to clear a render buffer which is not normalized fixed point or floating-" "point to floating point values (color attachment %u has internal format 0x%X).", colorAttachment, attachment->getInternalFormat()); } if ((formatInfo.redBits == 0 || !clearParams.colorMaskRed) && (formatInfo.greenBits == 0 || !clearParams.colorMaskGreen) && (formatInfo.blueBits == 0 || !clearParams.colorMaskBlue) && (formatInfo.alphaBits == 0 || !clearParams.colorMaskAlpha)) { // Every channel either does not exist in the render target or is masked out continue; } else if ((!mSupportsClearView && needScissoredClear) || clearParams.colorClearType != GL_FLOAT || (formatInfo.redBits > 0 && !clearParams.colorMaskRed) || (formatInfo.greenBits > 0 && !clearParams.colorMaskGreen) || (formatInfo.blueBits > 0 && !clearParams.colorMaskBlue) || (formatInfo.alphaBits > 0 && !clearParams.colorMaskAlpha)) { // A masked clear is required, or a scissored clear is required and ID3D11DeviceContext1::ClearView is unavailable MaskedRenderTarget maskAndRt; bool clearColor = clearParams.clearColor[colorAttachment]; maskAndRt.colorMask[0] = (clearColor && clearParams.colorMaskRed); maskAndRt.colorMask[1] = (clearColor && clearParams.colorMaskGreen); maskAndRt.colorMask[2] = (clearColor && clearParams.colorMaskBlue); maskAndRt.colorMask[3] = (clearColor && clearParams.colorMaskAlpha); maskAndRt.renderTarget = renderTarget; maskedClearRenderTargets.push_back(maskAndRt); } else { // ID3D11DeviceContext::ClearRenderTargetView or ID3D11DeviceContext1::ClearView is possible ID3D11RenderTargetView *framebufferRTV = renderTarget->getRenderTargetView(); if (!framebufferRTV) { return gl::Error(GL_OUT_OF_MEMORY, "Internal render target view pointer unexpectedly null."); } const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(renderTarget->getDXGIFormat()); // Check if the actual format has a channel that the internal format does not and set them to the // default values const float clearValues[4] = { ((formatInfo.redBits == 0 && dxgiFormatInfo.redBits > 0) ? 0.0f : clearParams.colorFClearValue.red), ((formatInfo.greenBits == 0 && dxgiFormatInfo.greenBits > 0) ? 0.0f : clearParams.colorFClearValue.green), ((formatInfo.blueBits == 0 && dxgiFormatInfo.blueBits > 0) ? 0.0f : clearParams.colorFClearValue.blue), ((formatInfo.alphaBits == 0 && dxgiFormatInfo.alphaBits > 0) ? 1.0f : clearParams.colorFClearValue.alpha), }; if (needScissoredClear) { // We shouldn't reach here if deviceContext1 is unavailable. ASSERT(deviceContext1); D3D11_RECT rect; rect.left = clearParams.scissor.x; rect.right = clearParams.scissor.x + clearParams.scissor.width; rect.top = clearParams.scissor.y; rect.bottom = clearParams.scissor.y + clearParams.scissor.height; deviceContext1->ClearView(framebufferRTV, clearValues, &rect, 1); } else { deviceContext->ClearRenderTargetView(framebufferRTV, clearValues); } } } } if (clearParams.clearDepth || clearParams.clearStencil) { const gl::FramebufferAttachment *attachment = (depthAttachment != nullptr) ? depthAttachment : stencilAttachment; ASSERT(attachment != nullptr); RenderTarget11 *renderTarget = NULL; gl::Error error = d3d11::GetAttachmentRenderTarget(attachment, &renderTarget); if (error.isError()) { return error; } const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(renderTarget->getDXGIFormat()); unsigned int stencilUnmasked = (stencilAttachment != nullptr) ? (1 << dxgiFormatInfo.stencilBits) - 1 : 0; bool needMaskedStencilClear = clearParams.clearStencil && (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked; if (needScissoredClear || needMaskedStencilClear) { maskedClearDepthStencil = renderTarget; } else { ID3D11DepthStencilView *framebufferDSV = renderTarget->getDepthStencilView(); if (!framebufferDSV) { return gl::Error(GL_OUT_OF_MEMORY, "Internal depth stencil view pointer unexpectedly null."); } UINT clearFlags = (clearParams.clearDepth ? D3D11_CLEAR_DEPTH : 0) | (clearParams.clearStencil ? D3D11_CLEAR_STENCIL : 0); FLOAT depthClear = gl::clamp01(clearParams.depthClearValue); UINT8 stencilClear = clearParams.stencilClearValue & 0xFF; deviceContext->ClearDepthStencilView(framebufferDSV, clearFlags, depthClear, stencilClear); } } if (maskedClearRenderTargets.size() > 0 || maskedClearDepthStencil) { // To clear the render targets and depth stencil in one pass: // // Render a quad clipped to the scissor rectangle which draws the clear color and a blend // state that will perform the required color masking. // // The quad's depth is equal to the depth clear value with a depth stencil state that // will enable or disable depth test/writes if the depth buffer should be cleared or not. // // The rasterizer state's stencil is set to always pass or fail based on if the stencil // should be cleared or not with a stencil write mask of the stencil clear value. // // ====================================================================================== // // Luckily, the gl spec (ES 3.0.2 pg 183) states that the results of clearing a render- // buffer that is not normalized fixed point or floating point with floating point values // are undefined so we can just write floats to them and D3D11 will bit cast them to // integers. // // Also, we don't have to worry about attempting to clear a normalized fixed/floating point // buffer with integer values because there is no gl API call which would allow it, // glClearBuffer* calls only clear a single renderbuffer at a time which is verified to // be a compatible clear type. // Bind all the render targets which need clearing ASSERT(maskedClearRenderTargets.size() <= mRenderer->getRendererCaps().maxDrawBuffers); std::vector<ID3D11RenderTargetView*> rtvs(maskedClearRenderTargets.size()); for (unsigned int i = 0; i < maskedClearRenderTargets.size(); i++) { RenderTarget11 *renderTarget = maskedClearRenderTargets[i].renderTarget; ID3D11RenderTargetView *rtv = renderTarget->getRenderTargetView(); if (!rtv) { return gl::Error(GL_OUT_OF_MEMORY, "Internal render target view pointer unexpectedly null."); } rtvs[i] = rtv; } ID3D11DepthStencilView *dsv = maskedClearDepthStencil ? maskedClearDepthStencil->getDepthStencilView() : NULL; ID3D11BlendState *blendState = getBlendState(maskedClearRenderTargets); const FLOAT blendFactors[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; const UINT sampleMask = 0xFFFFFFFF; ID3D11DepthStencilState *dsState = getDepthStencilState(clearParams); const UINT stencilClear = clearParams.stencilClearValue & 0xFF; // Set the vertices UINT vertexStride = 0; const UINT startIdx = 0; const ClearShader* shader = NULL; D3D11_MAPPED_SUBRESOURCE mappedResource; HRESULT result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); if (FAILED(result)) { return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal masked clear vertex buffer, HRESULT: 0x%X.", result); } const gl::Rectangle *scissorPtr = clearParams.scissorEnabled ? &clearParams.scissor : NULL; switch (clearParams.colorClearType) { case GL_FLOAT: ApplyVertices(framebufferSize, scissorPtr, clearParams.colorFClearValue, clearParams.depthClearValue, mappedResource.pData); vertexStride = sizeof(d3d11::PositionDepthColorVertex<float>); shader = &mFloatClearShader; break; case GL_UNSIGNED_INT: ApplyVertices(framebufferSize, scissorPtr, clearParams.colorUIClearValue, clearParams.depthClearValue, mappedResource.pData); vertexStride = sizeof(d3d11::PositionDepthColorVertex<unsigned int>); shader = &mUintClearShader; break; case GL_INT: ApplyVertices(framebufferSize, scissorPtr, clearParams.colorIClearValue, clearParams.depthClearValue, mappedResource.pData); vertexStride = sizeof(d3d11::PositionDepthColorVertex<int>); shader = &mIntClearShader; break; default: UNREACHABLE(); break; } deviceContext->Unmap(mVertexBuffer, 0); // Set the viewport to be the same size as the framebuffer D3D11_VIEWPORT viewport; viewport.TopLeftX = 0; viewport.TopLeftY = 0; viewport.Width = framebufferSize.width; viewport.Height = framebufferSize.height; viewport.MinDepth = 0; viewport.MaxDepth = 1; deviceContext->RSSetViewports(1, &viewport); // Apply state deviceContext->OMSetBlendState(blendState, blendFactors, sampleMask); deviceContext->OMSetDepthStencilState(dsState, stencilClear); deviceContext->RSSetState(mRasterizerState); // Apply shaders deviceContext->IASetInputLayout(shader->inputLayout); deviceContext->VSSetShader(shader->vertexShader, NULL, 0); deviceContext->PSSetShader(shader->pixelShader, NULL, 0); deviceContext->GSSetShader(NULL, NULL, 0); // Apply vertex buffer deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &vertexStride, &startIdx); deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); // Apply render targets deviceContext->OMSetRenderTargets(rtvs.size(), (rtvs.empty() ? NULL : &rtvs[0]), dsv); // Draw the clear quad deviceContext->Draw(4, 0); // Clean up mRenderer->markAllStateDirty(); } return gl::Error(GL_NO_ERROR); }
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR cmdLine, int cmdShow) { DXTInputHandlerDefault inputHandler; DXTWindowEventHandlerDefault eventHandler; DXTWindow window(hInstance, &inputHandler, &eventHandler); DXTRenderParams params; params.Extent = { 800, 600 }; params.UseVSync = true; params.Windowed = true; HRESULT result; result = window.Initialize(params, "DXT Example (DirectX 11)"); if (SUCCEEDED(result)) { ID3D11Device* device; ID3D11DeviceContext* context; IDXGISwapChain* swapChain; result = DXTInitDevice(params, &window, &swapChain, &device, &context); if (SUCCEEDED(result)) { eventHandler.SetSwapChain(swapChain); FLOAT clearColor[] = { 0.5f, 0.5f, 1.0f, 1.0f }; D3D11_INPUT_ELEMENT_DESC inputDesc[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, sizeof(float) * 3, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, sizeof(float) * 5, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; UINT elementCount = 3; UINT stride = 8 * sizeof(FLOAT); UINT offset = 0; UINT indexCount = 0; FLOAT deltaTime = 0.016f; DXTSphericalCamera camera; DXTFirstPersonCameraController cameraController(&camera, &inputHandler); inputHandler.AddInputInterface(&cameraController); cameraController.Velocity = 40.0f; cameraController.RotationVelocity = 0.005f; camera.Position = DirectX::XMFLOAT3(20.0f, 20.0f, 20.0f); camera.LookAt(DirectX::XMFLOAT3(0.0f, 0.0f, 0.0f)); ID3D11RenderTargetView* renderTargetView; ID3D11Texture2D* depthBuffer; ID3D11DepthStencilView* depthBufferView; ID3D11VertexShader* vertexShader; ID3D11PixelShader* pixelShader; DXTBytecodeBlob vertexBytecode; ID3D11DepthStencilState* depthState; ID3D11RasterizerState* rasterizerState; ID3D11Buffer* vertexBuffer; ID3D11Buffer* indexBuffer; ID3D11InputLayout* inputLayout; ID3D11Buffer* transformBuffer; DXTCreateRenderTargetFromBackBuffer(swapChain, device, &renderTargetView); DXTCreateDepthStencilBuffer(device, params.Extent.Width, params.Extent.Height, DXGI_FORMAT_D24_UNORM_S8_UINT, &depthBuffer, &depthBufferView); DXTVertexShaderFromFile(device, "VertexShader.cso", &vertexShader, &vertexBytecode); DXTPixelShaderFromFile(device, "PixelShader.cso", &pixelShader); DXTCreateDepthStencilStateDepthTestEnabled(device, &depthState); DXTCreateRasterizerStateSolid(device, &rasterizerState); DXTLoadStaticMeshFromFile(device, "mesh.ase", DXTVertexAttributePosition | DXTVertexAttributeUV | DXTVertexAttributeNormal, DXTIndexTypeShort, &vertexBuffer, &indexBuffer, &indexCount); DXTCreateBuffer(device, sizeof(DirectX::XMFLOAT4X4) * 2, D3D11_BIND_CONSTANT_BUFFER, D3D11_CPU_ACCESS_WRITE, D3D11_USAGE_DYNAMIC, &transformBuffer); device->CreateInputLayout(inputDesc, elementCount, vertexBytecode.Bytecode, vertexBytecode.BytecodeLength, &inputLayout); vertexBytecode.Destroy(); window.Present(false); while (!window.QuitMessageReceived()) { window.MessagePump(); if (inputHandler.IsKeyDown(VK_ESCAPE)) break; cameraController.Update(deltaTime); XMFLOAT4X4 ViewProj; XMFLOAT4X4 World; camera.GetViewProjectionMatrix(&ViewProj, params.Extent); XMStoreFloat4x4(&World, XMMatrixIdentity()); D3D11_MAPPED_SUBRESOURCE subres; context->Map(transformBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &subres); XMFLOAT4X4* ptr = (XMFLOAT4X4*)subres.pData; ptr[0] = World; ptr[1] = ViewProj; context->Unmap(transformBuffer, 0); D3D11_VIEWPORT viewport = { 0.0f, 0.0f, (FLOAT)params.Extent.Width, (FLOAT)params.Extent.Height, 0.0f, 1.0f }; context->ClearRenderTargetView(renderTargetView, clearColor); context->ClearDepthStencilView(depthBufferView, D3D11_CLEAR_DEPTH, 1.0f, 0); context->OMSetDepthStencilState(depthState, 0); context->OMSetRenderTargets(1, &renderTargetView, depthBufferView); context->RSSetState(rasterizerState); context->RSSetViewports(1, &viewport); context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); context->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &offset); context->IASetIndexBuffer(indexBuffer, DXGI_FORMAT_R16_UINT, 0); context->IASetInputLayout(inputLayout); context->VSSetShader(vertexShader, nullptr, 0); context->PSSetShader(pixelShader, nullptr, 0); context->VSSetConstantBuffers(0, 1, &transformBuffer); context->DrawIndexed(indexCount, 0, 0); swapChain->Present(1, 0); } swapChain->SetFullscreenState(false, nullptr); transformBuffer->Release(); depthBufferView->Release(); depthBuffer->Release(); inputLayout->Release(); vertexBuffer->Release(); indexBuffer->Release(); depthState->Release(); rasterizerState->Release(); vertexShader->Release(); pixelShader->Release(); renderTargetView->Release(); swapChain->Release(); context->Release(); device->Release(); } window.Destroy(); } }
/** Binds a pipeline-state */ void D3D11GraphicsEngineQueued::BindPipelineState(const PipelineState* state) { D3D11PipelineState* s = (D3D11PipelineState*)state; D3D11PipelineState* b = (D3D11PipelineState*)BoundPipelineStateByThread[GetCurrentThreadId()]; ID3D11DeviceContext* context = GetDeferredContextByThread(); if(!b) b = (D3D11PipelineState*)&DefaultPipelineState; // Bind state if(b->BlendState != s->BlendState) SC_DBG(context->OMSetBlendState(s->BlendState, (float *)&D3DXVECTOR4(0, 0, 0, 0), 0xFFFFFFFF), GothicRendererInfo::SC_BS); if(b->SamplerState != s->SamplerState) SC_DBG(context->PSSetSamplers(0, 1, &s->SamplerState), GothicRendererInfo::SC_SMPL); if(b->DepthStencilState != s->DepthStencilState) SC_DBG(context->OMSetDepthStencilState(s->DepthStencilState, 0), GothicRendererInfo::SC_DSS); if(b->RasterizerState != s->RasterizerState) SC_DBG(context->RSSetState(s->RasterizerState), GothicRendererInfo::SC_RS); // Bind constantbuffers (They are likely to change for every object) if(!s->ConstantBuffersVS.empty() && s->ConstantBuffersVS != b->ConstantBuffersVS)SC_DBG(context->VSSetConstantBuffers(0, s->ConstantBuffersVS.size(), &s->ConstantBuffersVS[0]),GothicRendererInfo::SC_CB); if(!s->ConstantBuffersPS.empty() && s->ConstantBuffersPS != b->ConstantBuffersPS)SC_DBG(context->PSSetConstantBuffers(0, s->ConstantBuffersPS.size(), &s->ConstantBuffersPS[0]),GothicRendererInfo::SC_CB); if(!s->ConstantBuffersHDS.empty() && s->ConstantBuffersHDS != b->ConstantBuffersHDS)SC_DBG(context->HSSetConstantBuffers(0, s->ConstantBuffersHDS.size(), &s->ConstantBuffersHDS[0]),GothicRendererInfo::SC_CB); if(!s->ConstantBuffersHDS.empty() && s->ConstantBuffersHDS != b->ConstantBuffersHDS)SC_DBG(context->DSSetConstantBuffers(0, s->ConstantBuffersHDS.size(), &s->ConstantBuffersHDS[0]),GothicRendererInfo::SC_CB); if(!s->ConstantBuffersGS.empty() && s->ConstantBuffersGS != b->ConstantBuffersGS)SC_DBG(context->GSSetConstantBuffers(0, s->ConstantBuffersGS.size(), &s->ConstantBuffersGS[0]),GothicRendererInfo::SC_CB); // Vertexbuffers UINT off[] = {0,0}; if(memcmp(s->BaseState.VertexBuffers, b->BaseState.VertexBuffers, sizeof(b->BaseState.VertexBuffers)) != 0) SC_DBG(context->IASetVertexBuffers(0, s->VertexBuffers.size(), &s->VertexBuffers[0], s->BaseState.VertexStride, off), GothicRendererInfo::SC_VB); if(!s->StructuredBuffersVS.empty() && memcmp(s->BaseState.StructuredBuffersVS, b->BaseState.StructuredBuffersVS, sizeof(b->BaseState.StructuredBuffersVS)) != 0) SC_DBG(context->VSSetShaderResources(0, 1, &s->StructuredBuffersVS[0]), GothicRendererInfo::SC_VB); if(s->IndexBuffer != b->IndexBuffer) SC_DBG(context->IASetIndexBuffer(s->IndexBuffer, s->BaseState.IndexStride == 4 ? DXGI_FORMAT_R32_UINT : DXGI_FORMAT_R16_UINT, 0), GothicRendererInfo::SC_IB); // Shaders if(s->VertexShader != b->VertexShader) SC_DBG(context->VSSetShader(s->VertexShader, NULL, NULL), GothicRendererInfo::SC_VS); if(s->InputLayout != b->InputLayout) SC_DBG(context->IASetInputLayout(s->InputLayout), GothicRendererInfo::SC_IL); if(s->PixelShader != b->PixelShader) SC_DBG(context->PSSetShader(s->PixelShader, NULL, NULL), GothicRendererInfo::SC_PS); if(s->HullShader != b->HullShader) SC_DBG(context->HSSetShader(s->HullShader, NULL, NULL), GothicRendererInfo::SC_HS); if(s->DomainShader != b->DomainShader) SC_DBG(context->DSSetShader(s->DomainShader, NULL, NULL), GothicRendererInfo::SC_DS); if(s->GeometryShader != b->GeometryShader) SC_DBG(context->GSSetShader(s->GeometryShader, NULL, NULL), GothicRendererInfo::SC_GS); // Rendertargets if(memcmp(s->RenderTargetViews, b->RenderTargetViews, sizeof(void*) * s->NumRenderTargetViews) != 0 || s->DepthStencilView != b->DepthStencilView) SC_DBG(context->OMSetRenderTargets(s->NumRenderTargetViews, s->RenderTargetViews, s->DepthStencilView), GothicRendererInfo::SC_RTVDSV); // Textures if(memcmp(s->Textures, b->Textures, sizeof(void*) * s->BaseState.NumTextures) != 0) SC_DBG(context->PSSetShaderResources(0, s->BaseState.NumTextures, s->Textures), GothicRendererInfo::SC_TX); // Primitive topology //Context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); // Replace old state // FIXME: Might not threadsave BoundPipelineStateByThread[GetCurrentThreadId()] = s; }
/////////////////////////////////////////////////////////////////////////////////////////////////// /// CelShadeApp::CelShadeD3D /// /// @brief /// Render a cel-shading demo using Direct3D /// @return /// N/A /////////////////////////////////////////////////////////////////////////////////////////////////// void CelShadeApp::CelShadeD3D() { ID3D11DeviceContext* pContext = m_pDxData->pD3D11Context; ID3D11Device* pDevice = m_pDxData->pD3D11Device; D3DX11_IMAGE_LOAD_INFO imageLoadInfo; memset( &imageLoadInfo, 0, sizeof(D3DX11_IMAGE_LOAD_INFO) ); imageLoadInfo.BindFlags = D3D11_BIND_SHADER_RESOURCE; imageLoadInfo.Format = DXGI_FORMAT_R8G8B8A8_UNORM; DxTextureCreateInfo shadeTexInfo; memset(&shadeTexInfo, 0, sizeof(DxTextureCreateInfo)); shadeTexInfo.flags.RenderTarget = TRUE; shadeTexInfo.flags.ShaderInput = TRUE; shadeTexInfo.format = DXGI_FORMAT_R8G8B8A8_UNORM; shadeTexInfo.width = m_screenWidth; shadeTexInfo.height = m_screenHeight; DxTexture* pShadeTex = DxTexture::Create(pDevice, &shadeTexInfo); DxTextureCreateInfo edgeTexInfo; memset(&edgeTexInfo, 0, sizeof(DxTextureCreateInfo)); edgeTexInfo.flags.RenderTarget = TRUE; edgeTexInfo.flags.ShaderInput = TRUE; edgeTexInfo.format = DXGI_FORMAT_R8G8B8A8_UNORM; edgeTexInfo.width = m_screenWidth; edgeTexInfo.height = m_screenHeight; DxTexture* pEdgeTex = DxTexture::Create(pDevice, &edgeTexInfo); // Samplers ///////////////////////////////////////////////////////////////////////////// // SamplerState PointSampler : register(s0); D3D11_SAMPLER_DESC pointSamplerDesc; memset(&pointSamplerDesc, 0, sizeof(D3D11_SAMPLER_DESC)); pointSamplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; pointSamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; pointSamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; pointSamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; pointSamplerDesc.MinLOD = -FLT_MAX; pointSamplerDesc.MaxLOD = FLT_MAX; pointSamplerDesc.MipLODBias = 0.0f; pointSamplerDesc.MaxAnisotropy = 16; ID3D11SamplerState* pPointSampler = NULL; pDevice->CreateSamplerState(&pointSamplerDesc, &pPointSampler); // UINT numVertices = 0, numIndices = 0; VertexPTN* pVB = NULL; UINT* pIB = NULL; ImportPly("Content/dragon_vrip_res3.ply", numVertices, &pVB, numIndices, &pIB); //ImportPly("Content/bun_zipper_res4.ply", numVertices, &pVB, numIndices, &pIB); DxMeshCreateInfo meshCreateInfo = {0}; meshCreateInfo.indexCount = numIndices; meshCreateInfo.pIndexArray = pIB; meshCreateInfo.indexFormat = DXGI_FORMAT_R32_UINT; meshCreateInfo.pVertexArray = pVB; meshCreateInfo.vertexCount = numVertices; meshCreateInfo.vertexElementSize = sizeof(VertexPTN); DxMesh* pMesh = DxMesh::Create(pDevice, &meshCreateInfo); Plane p; DxMeshCreateInfo planeMeshInfo; memset(&planeMeshInfo, 0, sizeof(planeMeshInfo)); planeMeshInfo.pVertexArray = p.GetVB(); planeMeshInfo.vertexCount = p.NumVertices(); planeMeshInfo.vertexElementSize = sizeof(VertexPTN); DxMesh* pPlaneMesh = DxMesh::Create(pDevice, &planeMeshInfo); Cube c; DxMeshCreateInfo cubeMeshInfo; memset(&cubeMeshInfo, 0, sizeof(cubeMeshInfo)); cubeMeshInfo.pVertexArray = c.GetVB(); cubeMeshInfo.vertexCount = c.NumVertices(); cubeMeshInfo.vertexElementSize = sizeof(VertexPT); DxMesh* pCubeMesh = DxMesh::Create(pDevice, &cubeMeshInfo); D3D11_SUBRESOURCE_DATA cbInitData; memset(&cbInitData, 0, sizeof(D3D11_SUBRESOURCE_DATA)); // Camera Buffer CameraBufferData cameraData; memset(&cameraData, 0, sizeof(CameraBufferData)); DxBufferCreateInfo cameraBufferCreateInfo = {0}; cameraBufferCreateInfo.flags.cpuWriteable = TRUE; cameraBufferCreateInfo.elemSizeBytes = sizeof(CameraBufferData); cameraBufferCreateInfo.pInitialData = &cameraData; DxBuffer* pCameraBuffer = DxBuffer::Create(pDevice, &cameraBufferCreateInfo); // Shaders //////////////////////////////////////////////////////////////////////////////////// m_pPosTexTriVS = DxShader::CreateFromFile(pDevice, "PosTexTri", "Content/shaders/CelShade.hlsl", PosTexVertexDesc, PosTexElements); m_pPosTexNormVS = DxShader::CreateFromFile(pDevice, "PosTexNorm", "Content/shaders/CelShade.hlsl", PosTexNormVertexDesc, PosTexNormElements); m_pCelShadePS = DxShader::CreateFromFile(pDevice, "CelShade", "Content/shaders/CelShade.hlsl"); DxShader* pDetectEdges = DxShader::CreateFromFile(pDevice, "DetectEdges", "Content/shaders/CelShade.hlsl"); DxShader* pApplyTexPS = DxShader::CreateFromFile(pDevice, "ApplyTex", "Content/shaders/CelShade.hlsl"); DxShader* pCubeVS = DxShader::CreateFromFile(pDevice, "PosTex", "Content/shaders/CelShade.hlsl", PosTexVertexDesc, PosTexElements); DxShader* pCubePS = DxShader::CreateFromFile(pDevice, "CubePS", "Content/shaders/CelShade.hlsl"); //////////////////////////////////////////////////////////////////////////////////////// pContext->ClearState(); // SET RENDER STATE FLOAT clearColor[4]; clearColor[0] = 0.2f; clearColor[1] = 0.2f; clearColor[2] = 0.2f; clearColor[3] = 1.0f; D3D11_RASTERIZER_DESC shadeDesc; shadeDesc.FillMode = D3D11_FILL_SOLID; shadeDesc.CullMode = D3D11_CULL_BACK; shadeDesc.FrontCounterClockwise = FALSE; shadeDesc.DepthBias = 0; shadeDesc.DepthBiasClamp = 0.0f; shadeDesc.SlopeScaledDepthBias = 0; shadeDesc.DepthClipEnable = false; shadeDesc.ScissorEnable = false; shadeDesc.MultisampleEnable = false; shadeDesc.AntialiasedLineEnable = false; ID3D11RasterizerState* pShadeRS = NULL; pDevice->CreateRasterizerState(&shadeDesc, &pShadeRS); pContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); m_pWindow->Show(); BOOL quit = false; FLOAT yRotationAngle = 0.0f; while (!quit) { ProcessUpdates(); BeginFrame(); CameraBufferData* pCameraData = NULL; // new frame, clear state pContext->ClearState(); pContext->RSSetViewports(1, &m_pDxData->viewport); pContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); pContext->RSSetState(pShadeRS); pContext->PSSetSamplers(0, 1, &pPointSampler); pContext->OMSetRenderTargets(1, &m_pDxData->pAppRenderTargetView, m_pDxData->pAppDepthStencilTex->GetDepthStencilView()); pContext->ClearRenderTargetView(m_pDxData->pAppRenderTargetView, clearColor); pContext->ClearDepthStencilView(m_pDxData->pAppDepthStencilTex->GetDepthStencilView(), D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0, 0); ///// Draw Mesh /////////////////////////////////////////////////////////////////////////// FLOAT viewRotationY = (GetMousePos().x - (m_screenWidth / 2.0f)) /(m_screenWidth / 2.0f); viewRotationY *= (3.14159f / 4.0f); FLOAT viewRotationZ = (GetMousePos().y - (m_screenHeight / 2.0f)) /(m_screenHeight / 2.0f); viewRotationZ *= (3.14159f / 4.0f); pCameraData = reinterpret_cast<CameraBufferData*>(pCameraBuffer->Map(pContext)); pCameraData->worldMatrix = XMMatrixScaling(25, 25, 25) * XMMatrixRotationY(yRotationAngle) * XMMatrixTranslation(m_pCamera->Position().x, m_pCamera->Position().y, m_pCamera->Position().z) ; // translate world +6 in Z to position camera -9 from world origin pCameraData->viewMatrix = m_pCamera->W2C(); pCameraData->projectionMatrix = m_pCamera->C2S(); pCameraBuffer->Unmap(pContext); pCameraBuffer->BindVS(pContext, 0); pMesh->Bind(pContext); m_pPosTexNormVS->Bind(pContext); m_pCelShadePS->Bind(pContext); pMesh->Draw(pContext); ///// Detect Edges /////////////////////////////////////////////////////////////////////////// ///// Draw Light Position //////////////////////////////////////////////////////////////////// //yRotationAngle = 0; pCameraData = reinterpret_cast<CameraBufferData*>(pCameraBuffer->Map(pContext)); pCameraData->worldMatrix = XMMatrixScaling(1, 1, 1); // XMMatrixRotationY(yRotationAngle); // XMMatrixTranslation(-10, 10, 10); // translate world +6 in Z to position camera -9 from world origin pCameraData->viewMatrix = XMMatrixTranslation(0, 0, 10) * m_pCamera->W2C(); pCameraData->projectionMatrix = m_pCamera->C2S(); pCameraBuffer->Unmap(pContext); pCameraBuffer->BindVS(pContext, 0); pCubeVS->Bind(pContext); pCubePS->Bind(pContext); pCubeMesh->Bind(pContext); pCubeMesh->Draw(pContext); ///// Draw UI //////////////////////////////////////////////////////////////////////////////// ///@todo Consider moving the following UI drawing to Draw2D() m_pUI->Begin(); // Draw UI stuff m_pUI->RenderRect(); m_pUI->RenderText(); m_pUI->End(); /// Blend UI onto final image DrawUI(); m_pDxData->pDXGISwapChain->Present(0,0); EndFrame(); Sleep(50); yRotationAngle += 3.14159f / 60.0f; } // Shader Resource Views pCameraBuffer->Destroy(); // Shaders m_pCelShadePS->Destroy(); m_pCelShadePS = NULL; m_pPosTexTriVS->Destroy(); m_pPosTexTriVS = NULL; m_pPosTexNormVS->Destroy(); m_pPosTexNormVS = NULL; pApplyTexPS->Destroy(); pApplyTexPS = NULL; pPlaneMesh->Destroy(); pPlaneMesh = NULL; // Samplers pPointSampler->Release(); // Rasterizer State pShadeRS->Release(); m_pDxData->pD3D11Context->ClearState(); m_pDxData->pD3D11Context->Flush(); }
// WinMain int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow ) { HRESULT hr; // ウィンドウクラスを登録 WNDCLASSEX wcex = { sizeof( WNDCLASSEX ), // cbSize CS_HREDRAW | CS_VREDRAW, // style WndProc, // lpfnWndProc 0, // cbClsExtra 0, // cbWndExtra hInstance, // hInstance NULL, // hIcon NULL, // hCursor ( HBRUSH )( COLOR_WINDOW + 1 ), // hbrBackGround NULL, // lpszMenuName g_className, // lpszClassName NULL // hIconSm }; if ( ! RegisterClassEx( &wcex ) ) { MessageBox( NULL, _T( "失敗: RegisterClassEx()" ), _T( "エラー" ), MB_OK | MB_ICONERROR ); return 0; } dtprintf( _T( "RegisterClassEx: ok\n" ) ); // ウィンドウサイズを計算 RECT r = { 0, 0, 800, 450 }; // 800x450 (16:9) if ( ! AdjustWindowRect( &r, WS_OVERLAPPEDWINDOW, FALSE ) ) { MessageBox( NULL, _T( "失敗: AdjustWindowRect()" ), _T( "エラー" ), MB_OK | MB_ICONERROR ); return 0; } dtprintf( _T( "AdjustWindowRect: ok (%d, %d)-(%d, %d)\n" ), r.left, r.top, r.right, r.bottom ); // ウィンドウ生成 HWND hWnd; hWnd = CreateWindow( g_className, g_windowName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, r.right - r.left, r.bottom - r.top, NULL, NULL, hInstance, NULL ); if ( hWnd == NULL ) { MessageBox( NULL, _T( "失敗: CreateWindow()" ), _T( "エラー" ), MB_OK | MB_ICONERROR ); return 0; } dtprintf( _T( "CreateWindow: ok\n" ) ); // ウィンドウ表示 ShowWindow(hWnd, nCmdShow); dtprintf( _T( "ShowWindow: ok\n" ) ); // スワップチェイン設定 DXGI_SWAP_CHAIN_DESC scDesc = { { 1280, // BufferDesc.Width 720, // BufferDesc.Height { 60, // BufferDesc.RefreshRate.Numerator 1 // BufferDesc.RefreshRate.Denominator }, DXGI_FORMAT_R16G16B16A16_FLOAT, // BufferDesc.Format DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED, // BufferDesc.ScanlineOrdering DXGI_MODE_SCALING_CENTERED // BufferDesc.Scaling }, { 1, // SampleDesc.Count 0 // SampleDesc.Quality }, DXGI_USAGE_RENDER_TARGET_OUTPUT, // BufferUsage 1, // BufferCount hWnd, // OutputWindow TRUE, // Windowed DXGI_SWAP_EFFECT_DISCARD, // SwapEffect DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH // Flags }; // Direct3D11 デバイス・デバイスコンテキスト・スワップチェーンを生成 ID3D11Device * pDevice = NULL; ID3D11DeviceContext * pDeviceContext = NULL; IDXGISwapChain * pSwapChain = NULL; D3D_FEATURE_LEVEL feature; hr = D3D11CreateDeviceAndSwapChain( NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, NULL, 0, D3D11_SDK_VERSION, &scDesc, &pSwapChain, &pDevice, &feature, &pDeviceContext ); if ( FAILED( hr ) ) { MessageBox( NULL, _T( "失敗: D3D11CreateDeviceAndSwapChain()" ), _T( "エラー" ), MB_OK | MB_ICONERROR ); return 0; } dtprintf( _T( "D3D11CreateDeviceAndSwapChain: ok (pDevice: 0x%p, pDeviceContext: 0x%p, pSwapChain: 0x%p, feature: 0x%4x)\n" ), pDevice, pDeviceContext, pSwapChain, ( int ) feature ); // バックバッファテクスチャを取得 ID3D11Texture2D * pBackBuffer = NULL; hr = pSwapChain->GetBuffer( 0, __uuidof( pBackBuffer ), reinterpret_cast< void ** >( &pBackBuffer ) ); if ( FAILED( hr ) ) { MessageBox( NULL, _T( "失敗: IDXGISwapChain::GetBuffer()" ), _T( "エラー" ), MB_OK | MB_ICONERROR ); return 0; } dtprintf( _T( "IDXGISwapChain::GetBuffer: ok (pBackBuffer: 0x%p)\n" ), pBackBuffer ); // レンダーターゲットビューを生成 ID3D11RenderTargetView * pRenderTargetView = NULL; hr = pDevice->CreateRenderTargetView( pBackBuffer, NULL, &pRenderTargetView ); if ( FAILED( hr ) ) { MessageBox( NULL, _T( "失敗: ID3D11Device::CreateRenderTargetView()" ), _T( "エラー" ), MB_OK | MB_ICONERROR ); return 0; } dtprintf( _T( "ID3D11Device::CreateRenderTargetView: ok (pRenderTargetView: 0x%p)\n" ), pRenderTargetView ); // デプス・ステンシルバッファとなるテクスチャを生成 D3D11_TEXTURE2D_DESC depthStencilBufferDesc = { 1280, // Width 720, // Height 1, // MipLevels 1, // ArraySize DXGI_FORMAT_D32_FLOAT, // Format { 1, // SampleDesc.Count 0 // SampleDesc.Quality }, D3D11_USAGE_DEFAULT, // Usage D3D11_BIND_DEPTH_STENCIL, // BindFlags 0, // CPUAccessFlags 0 // MiscFlags }; ID3D11Texture2D * pDepthStencilBuffer = NULL; hr = pDevice->CreateTexture2D( &depthStencilBufferDesc, NULL, &pDepthStencilBuffer ); if ( FAILED( hr ) ) { MessageBox( NULL, _T( "失敗: ID3D11Device::CreateTexture2D()" ), _T( "エラー" ), MB_OK | MB_ICONERROR ); return 0; } dtprintf( _T( "ID3D11Device::CreateTexture2D: ok (pDepthStencilBuffer: 0x%p)\n" ), pDepthStencilBuffer ); // デプス・ステンシルビューを生成 ID3D11DepthStencilView * pDepthStencilView = NULL; hr = pDevice->CreateDepthStencilView( pDepthStencilBuffer, NULL, &pDepthStencilView ); if ( FAILED( hr ) ) { MessageBox( NULL, _T( "失敗: ID3D11Device::CreateDepthStencilView()" ), _T( "エラー" ), MB_OK | MB_ICONERROR ); return 0; } dtprintf( _T( "ID3D11Device::CreateDepthStencilView: ok (pDepthStencilView: 0x%p)\n" ), pDepthStencilView ); // レンダーターゲットビューとデプス・ステンシルビューをバインド ID3D11RenderTargetView * pRenderTargetViews[] = { pRenderTargetView }; pDeviceContext->OMSetRenderTargets( 1, pRenderTargetViews, pDepthStencilView ); dtprintf( _T( "ID3D11DeviceContext::OMSetRenderTargets: ok\n" ) ); // バックバッファはもうここでは使わない COM_SAFE_RELEASE( pBackBuffer ); // ビューポートをバインド D3D11_VIEWPORT viewport = { 0.0f, // TopLeftX 0.0f, // TopLeftY 1280.0f, // Width 720.0f, // Height 0.0f, // MinDepth 1.0f // MaxDepth }; pDeviceContext->RSSetViewports( 1, &viewport ); dtprintf( _T( "ID3D11DeviceContext::RSSetViewports: ok\n" ) ); // 頂点データ float vertices[ 8 ][ 7 ] = { // Xaxis Yaxis Zaxis 赤 緑 青 Alpha { -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f }, // 手前左上 { 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f }, // 手前右上 { 0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f }, // 手前右下 { -0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 1.0f }, // 手前左下 { -0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f }, // 奥左上 { 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 1.0f, 1.0f }, // 奥右上 { 0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.0f, 1.0f }, // 奥右下 { -0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f } // 奥左下 }; // 頂点バッファを生成 D3D11_BUFFER_DESC vertexBufferDesc = { sizeof( vertices ), // ByteWidth D3D11_USAGE_DEFAULT, // Usage D3D11_BIND_VERTEX_BUFFER, // BindFlags 0, // CPUAccessFlags 0, // MiscFlags 0 // StructureByteStride }; D3D11_SUBRESOURCE_DATA vertexResourceData = { vertices }; ID3D11Buffer * pVertexBuffer = NULL; hr = pDevice->CreateBuffer( &vertexBufferDesc, &vertexResourceData, &pVertexBuffer ); if ( FAILED( hr ) ) { MessageBox( NULL, _T( "失敗: ID3D11Device::CreateBuffer()" ), _T( "エラー" ), MB_OK | MB_ICONERROR ); return 0; } dtprintf( _T( "ID3D11Device::CreateBuffer: ok (pVertexBuffer: 0x%p)\n" ), pVertexBuffer ); // 頂点バッファをバインド UINT strides[] = { sizeof( float ) * 7 }; UINT offsets[] = { 0 }; pDeviceContext->IASetVertexBuffers( 0, 1, &pVertexBuffer, strides, offsets ); dtprintf( _T( "ID3D11DeviceContext::IASetVertexBuffers: ok\n" ) ); // インデックスデータ unsigned int indices[] = { 0, 1, 2, 0, 2, 3, // 手前 4, 0, 3, 4, 3, 7, // 左 1, 5, 6, 1, 6, 2, // 右 0, 4, 5, 0, 5, 1, // 上 2, 6, 7, 2, 7, 3, // 下 5, 4, 7, 5, 7, 6 }; // 裏 // インデックスバッファを生成 D3D11_BUFFER_DESC indexBufferDesc = { sizeof( indices ), // ByteWidth D3D11_USAGE_DEFAULT, // Usage D3D11_BIND_INDEX_BUFFER, // BindFlags 0, // CPUAccessFlags 0, // MiscFlags 0 // StructureByteStride }; D3D11_SUBRESOURCE_DATA indexResourceData = { indices }; ID3D11Buffer * pIndexBuffer = NULL; hr = pDevice->CreateBuffer( &indexBufferDesc, &indexResourceData, &pIndexBuffer ); if ( FAILED( hr ) ) { MessageBox( NULL, _T( "失敗: ID3D11Device::CreateBuffer()" ), _T( "エラー" ), MB_OK | MB_ICONERROR ); return 0; } dtprintf( _T( "ID3D11Device::CreateBuffer: ok (pIndexBuffer: 0x%p)\n" ), pIndexBuffer ); // インデックスバッファをバインド pDeviceContext->IASetIndexBuffer( pIndexBuffer, DXGI_FORMAT_R32_UINT, 0 ); dtprintf( _T( "ID3D11DeviceContext::IASetIndexBuffer: ok\n" ) ); // プリミティブタイプを設定 pDeviceContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST ); dtprintf( _T( "ID3D11DeviceContext::IASetPrimitiveTopology: ok\n" ) ); // 頂点シェーダ用の定数バッファを作成 D3D11_BUFFER_DESC VSConstantBufferDesc = { sizeof( D3DXMATRIX ) * 3, // ByteWidth D3D11_USAGE_DYNAMIC, // Usage D3D11_BIND_CONSTANT_BUFFER, // BindFlags D3D11_CPU_ACCESS_WRITE, // CPUAccessFlags 0, // MiscFlags 0 // StructureByteStride }; ID3D11Buffer * pVSConstantBuffer = NULL; hr = pDevice->CreateBuffer( &VSConstantBufferDesc, NULL, &pVSConstantBuffer ); if ( FAILED( hr ) ) { MessageBox( NULL, _T( "失敗: ID3D11Device::CreateBuffer()" ), _T( "エラー" ), MB_OK | MB_ICONERROR ); return 0; } dtprintf( _T( "ID3D11Device::CreateBuffer: ok (pVSConstantBuffer: 0x%p)\n" ), pVSConstantBuffer ); // 定数バッファをバインド pDeviceContext->VSSetConstantBuffers( 0, 1, &pVSConstantBuffer ); dtprintf( _T( "ID3D11DeviceContext::VSSetConstantBuffers: ok\n" ) ); // 頂点シェーダを作成 ID3D11VertexShader * pVertexShader = NULL; hr = pDevice->CreateVertexShader( g_vs_perspective, sizeof( g_vs_perspective ), NULL, &pVertexShader ); if ( FAILED( hr ) ) { MessageBox( NULL, _T( "失敗: ID3D11Device::CreateVertexShader()" ), _T( "エラー" ), MB_OK | MB_ICONERROR ); return 0; } dtprintf( _T( "ID3D11Device::CreateVertexShader: ok (pVertexShader: 0x%p)\n" ), pVertexShader ); // ピクセルシェーダを作成 ID3D11PixelShader * pPixelShader = NULL; hr = pDevice->CreatePixelShader( g_ps_constant, sizeof( g_ps_constant ), NULL, &pPixelShader ); if ( FAILED( hr ) ) { MessageBox( NULL, _T( "失敗: ID3D11Device::CreatePixelShader()" ), _T( "エラー" ), MB_OK | MB_ICONERROR ); return 0; } dtprintf( _T( "ID3D11Device::CreatePixelShader: ok (pPixelShader: 0x%p)\n" ), pPixelShader ); // シェーダをバインド pDeviceContext->VSSetShader( pVertexShader, NULL, 0 ); dtprintf( _T( "ID3D11DeviceContext::VSSetShader: ok\n" ) ); pDeviceContext->PSSetShader( pPixelShader, NULL, 0 ); dtprintf( _T( "ID3D11DeviceContext::PSSetShader: ok\n" ) ); pDeviceContext->GSSetShader( NULL, NULL, 0 ); pDeviceContext->HSSetShader( NULL, NULL, 0 ); pDeviceContext->DSSetShader( NULL, NULL, 0 ); // 入力エレメント記述子 D3D11_INPUT_ELEMENT_DESC verticesDesc[] = { { "IN_POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "IN_COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, sizeof(float)*3, D3D11_INPUT_PER_VERTEX_DATA, 0 } }; // 入力レイアウトを生成 ID3D11InputLayout * pInputLayout = NULL; hr = pDevice->CreateInputLayout( verticesDesc, 2, g_vs_perspective, sizeof( g_vs_perspective ), &pInputLayout ); if ( FAILED( hr ) ) { MessageBox( NULL, _T( "失敗: ID3D11Device::CreateInputLayout()" ), _T( "エラー" ), MB_OK | MB_ICONERROR ); return 0; } dtprintf( _T( "ID3D11Device::CreateInputLayout: ok (pInputLayout: 0x%p)\n" ), pInputLayout ); // 入力レイアウトをバインド pDeviceContext->IASetInputLayout( pInputLayout ); dtprintf( _T( "ID3D11DeviceContext::IASetInputLayout: ok\n" ) ); // ラスタライザステートを生成 D3D11_RASTERIZER_DESC rasterizerStateDesc = { D3D11_FILL_SOLID, // FillMode // D3D11_FILL_WIREFRAME, // FillMode (ワイヤーフレーム表示) D3D11_CULL_BACK, // CullMode // D3D11_CULL_NONE, // CullMode (カリングなし) FALSE, // FrontCounterClockwise 0, // DepthBias 0.0f, // DepthBiasClamp 0.0f, // SlopeScaledDepthBias TRUE, // DepthClipEnable FALSE, // ScissorEnable FALSE, // MultisampleEnable FALSE // AntialiasedLineEnable }; ID3D11RasterizerState * pRasterizerState = NULL; hr = pDevice->CreateRasterizerState( &rasterizerStateDesc, &pRasterizerState ); if ( FAILED( hr ) ) { MessageBox( NULL, _T( "失敗: ID3D11Device::CreateRasterizerState()" ), _T( "エラー" ), MB_OK | MB_ICONERROR ); return 0; } dtprintf( _T( "ID3D11Device::CreateRasterizerState: ok (pRasterizerState: 0x%p)\n" ), pRasterizerState ); // ラスタライザステートをバインド pDeviceContext->RSSetState( pRasterizerState ); dtprintf( _T( "ID3D11DeviceContext::RSSetState: ok\n" ) ); // デプス・ステンシルステートを生成 D3D11_DEPTH_STENCIL_DESC depthStencilStateDesc = { TRUE, // DepthEnable D3D11_DEPTH_WRITE_MASK_ALL, // DepthWriteMask D3D11_COMPARISON_LESS, // DepthFunc FALSE, // StencilEnable D3D11_DEFAULT_STENCIL_READ_MASK, // StencilReadMask D3D11_DEFAULT_STENCIL_WRITE_MASK, // StencilWriteMask { D3D11_STENCIL_OP_KEEP, // FrontFace.StencilFailOp D3D11_STENCIL_OP_KEEP, // FrontFace.StencilDepthFailOp D3D11_STENCIL_OP_KEEP, // FrontFace.StencilPassOp D3D11_COMPARISON_ALWAYS // FrontFace.StencilFunc }, { D3D11_STENCIL_OP_KEEP, // BackFace.StencilFailOp D3D11_STENCIL_OP_KEEP, // BackFace.StencilDepthFailOp D3D11_STENCIL_OP_KEEP, // BackFace.StencilPassOp D3D11_COMPARISON_ALWAYS // BackFace.StencilFunc } }; ID3D11DepthStencilState * pDepthStencilState = NULL; hr = pDevice->CreateDepthStencilState( &depthStencilStateDesc, &pDepthStencilState ); if ( FAILED( hr ) ) { MessageBox( NULL, _T( "失敗: ID3D11Device::CreateDepthStencilState()" ), _T( "エラー" ), MB_OK | MB_ICONERROR ); return 0; } dtprintf( _T( "ID3D11Device::CreateDepthStencilState: ok (pDepthStencilState: 0x%p)\n" ), pDepthStencilState ); // デプス・ステンシルステートをバインド pDeviceContext->OMSetDepthStencilState( pDepthStencilState, 0 ); dtprintf( _T( "ID3D11DeviceContext::OMSetDepthStencilState: ok\n" ) ); MSG msg; while ( 1 ) { // メッセージを取得 if ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) { if ( msg.message == WM_QUIT ) { dtprintf( _T( "PeekMessage: WM_QUIT\n" ) ); break; } // メッセージ処理 DispatchMessage( &msg ); } else { HRESULT hr; static unsigned int count = 0; float theta = ( count++ / 200.0f ) * ( 3.141593f / 2.0f ); // World-View-Projection 行列をそれぞれ生成 D3DXMATRIX world, view, projection; D3DXMatrixIdentity( &world ); const D3DXVECTOR3 eye( 1.8f * 1.414214f * -cosf( theta ), 1.8f, 1.8f * 1.414214f * sinf( theta ) ); const D3DXVECTOR3 at( 0.0f, 0.0f, 0.0f ); const D3DXVECTOR3 up( 0.0f, 1.0f, 0.0f ); D3DXMatrixLookAtRH( &view, &eye, &at, &up ); D3DXMatrixPerspectiveFovRH( &projection, 3.141593f / 4.0f, 1280.0f / 720.0f, 1.0f, 10000.0f ); // 頂点シェーダ用定数バッファへアクセス D3D11_MAPPED_SUBRESOURCE mapped; hr = pDeviceContext->Map( pVSConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped ); if ( SUCCEEDED( hr ) ) { D3DXMATRIX * mapped_m = static_cast< D3DXMATRIX * >( mapped.pData ); mapped_m[0] = world; mapped_m[1] = view; mapped_m[2] = projection; // 後始末 pDeviceContext->Unmap( pVSConstantBuffer, 0 ); } // レンダーターゲットビューをクリア const float clear[ 4 ] = { 0.0f, 0.0f, 0.3f, 1.0f }; // RGBA pDeviceContext->ClearRenderTargetView( pRenderTargetView, clear ); // デプス・ステンシルビューをクリア pDeviceContext->ClearDepthStencilView( pDepthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0 ); // 描画 pDeviceContext->DrawIndexed( 36, 0, 0 ); pSwapChain->Present( 1, 0 ); // ちょっとだけ待つ Sleep( 5 ); } } // シェーダをアンバインド pDeviceContext->VSSetShader( NULL, NULL, 0 ); pDeviceContext->PSSetShader( NULL, NULL, 0 ); // デバイス・リソース解放 COM_SAFE_RELEASE( pDepthStencilState ); COM_SAFE_RELEASE( pRasterizerState ); COM_SAFE_RELEASE( pInputLayout ); COM_SAFE_RELEASE( pPixelShader ); COM_SAFE_RELEASE( pVertexShader ); COM_SAFE_RELEASE( pVSConstantBuffer ); COM_SAFE_RELEASE( pIndexBuffer ); COM_SAFE_RELEASE( pVertexBuffer ); COM_SAFE_RELEASE( pDepthStencilView ); COM_SAFE_RELEASE( pDepthStencilBuffer ); COM_SAFE_RELEASE( pRenderTargetView ); COM_SAFE_RELEASE( pSwapChain ); COM_SAFE_RELEASE( pDeviceContext ); COM_SAFE_RELEASE( pDevice ); return msg.wParam; }
EGLint SwapChain11::copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width, EGLint height) { if (!mSwapChain) { return EGL_SUCCESS; } initPassThroughResources(); ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); // Set vertices D3D11_MAPPED_SUBRESOURCE mappedResource; HRESULT result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); if (FAILED(result)) { return EGL_BAD_ACCESS; } d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData); // Create a quad in homogeneous coordinates float x1 = (x / float(mWidth)) * 2.0f - 1.0f; float y1 = (y / float(mHeight)) * 2.0f - 1.0f; float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f; float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f; float u1 = x / float(mWidth); float v1 = y / float(mHeight); float u2 = (x + width) / float(mWidth); float v2 = (y + height) / float(mHeight); // Invert the quad vertices depending on the surface orientation. if ((mOrientation & EGL_SURFACE_ORIENTATION_INVERT_X_ANGLE) != 0) { std::swap(x1, x2); } if ((mOrientation & EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE) != 0) { std::swap(y1, y2); } d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v1); d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2); d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1); d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2); deviceContext->Unmap(mQuadVB, 0); static UINT stride = sizeof(d3d11::PositionTexCoordVertex); static UINT startIdx = 0; deviceContext->IASetVertexBuffers(0, 1, &mQuadVB, &stride, &startIdx); // Apply state deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF); static const float blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; deviceContext->OMSetBlendState(NULL, blendFactor, 0xFFFFFFF); deviceContext->RSSetState(mPassThroughRS); // Apply shaders deviceContext->IASetInputLayout(mPassThroughIL); deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); deviceContext->VSSetShader(mPassThroughVS, NULL, 0); deviceContext->PSSetShader(mPassThroughPS, NULL, 0); deviceContext->GSSetShader(NULL, NULL, 0); auto stateManager = mRenderer->getStateManager(); // Apply render targets stateManager->setOneTimeRenderTarget(mBackBufferRTView, nullptr); // Set the viewport D3D11_VIEWPORT viewport; viewport.TopLeftX = 0; viewport.TopLeftY = 0; viewport.Width = static_cast<FLOAT>(mWidth); viewport.Height = static_cast<FLOAT>(mHeight); viewport.MinDepth = 0.0f; viewport.MaxDepth = 1.0f; deviceContext->RSSetViewports(1, &viewport); // Apply textures stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, mOffscreenSRView); deviceContext->PSSetSamplers(0, 1, &mPassThroughSampler); // Draw deviceContext->Draw(4, 0); // Rendering to the swapchain is now complete. Now we can call Present(). // Before that, we perform any cleanup on the D3D device. We do this before Present() to make sure the // cleanup is caught under the current eglSwapBuffers() PIX/Graphics Diagnostics call rather than the next one. stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); mRenderer->markAllStateDirty(); return EGL_SUCCESS; }
// Render function // (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data) { ID3D11DeviceContext* ctx = g_pd3dDeviceContext; // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } g_VertexBufferSize = draw_data->TotalVtxCount + 5000; D3D11_BUFFER_DESC desc; memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); desc.Usage = D3D11_USAGE_DYNAMIC; desc.ByteWidth = g_VertexBufferSize * sizeof(ImDrawVert); desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; desc.MiscFlags = 0; if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount) { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; D3D11_BUFFER_DESC desc; memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); desc.Usage = D3D11_USAGE_DYNAMIC; desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); desc.BindFlags = D3D11_BIND_INDEX_BUFFER; desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert)); memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx)); vtx_dst += cmd_list->VtxBuffer.Size; idx_dst += cmd_list->IdxBuffer.Size; } ctx->Unmap(g_pVB, 0); ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { D3D11_MAPPED_SUBRESOURCE mapped_resource; if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; float L = 0.0f; float R = ImGui::GetIO().DisplaySize.x; float B = ImGui::GetIO().DisplaySize.y; float T = 0.0f; float mvp[4][4] = { { 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, { 0.0f, 2.0f/(T-B), 0.0f, 0.0f }, { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); ctx->Unmap(g_pVertexConstantBuffer, 0); } // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) struct BACKUP_DX11_STATE { UINT ScissorRectsCount, ViewportsCount; D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; ID3D11RasterizerState* RS; ID3D11BlendState* BlendState; FLOAT BlendFactor[4]; UINT SampleMask; UINT StencilRef; ID3D11DepthStencilState* DepthStencilState; ID3D11ShaderResourceView* PSShaderResource; ID3D11SamplerState* PSSampler; ID3D11PixelShader* PS; ID3D11VertexShader* VS; UINT PSInstancesCount, VSInstancesCount; ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; DXGI_FORMAT IndexBufferFormat; ID3D11InputLayout* InputLayout; }; BACKUP_DX11_STATE old; old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); ctx->RSGetState(&old.RS); ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); ctx->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef); ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); ctx->PSGetSamplers(0, 1, &old.PSSampler); old.PSInstancesCount = old.VSInstancesCount = 256; ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); ctx->IAGetInputLayout(&old.InputLayout); // Setup viewport D3D11_VIEWPORT vp; memset(&vp, 0, sizeof(D3D11_VIEWPORT)); vp.Width = ImGui::GetIO().DisplaySize.x; vp.Height = ImGui::GetIO().DisplaySize.y; vp.MinDepth = 0.0f; vp.MaxDepth = 1.0f; vp.TopLeftX = vp.TopLeftY = 0.0f; ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; ctx->IASetInputLayout(g_pInputLayout); ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); ctx->VSSetShader(g_pVertexShader, NULL, 0); ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); ctx->PSSetShader(g_pPixelShader, NULL, 0); ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); ctx->OMSetDepthStencilState(g_pDepthStencilState, 0); ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; int idx_offset = 0; for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) { const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; if (pcmd->UserCallback) { pcmd->UserCallback(cmd_list, pcmd); } else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); ctx->RSSetScissorRects(1, &r); ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.Size; } // Restore modified DX state ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); ctx->RSSetViewports(old.ViewportsCount, old.Viewports); ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release(); ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); ctx->IASetPrimitiveTopology(old.PrimitiveTopology); ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); }
// Render function // (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data) { // Avoid rendering when minimized if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f) return; ID3D11DeviceContext* ctx = g_pd3dDeviceContext; // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } g_VertexBufferSize = draw_data->TotalVtxCount + 5000; D3D11_BUFFER_DESC desc; memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); desc.Usage = D3D11_USAGE_DYNAMIC; desc.ByteWidth = g_VertexBufferSize * sizeof(ImDrawVert); desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; desc.MiscFlags = 0; if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount) { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; D3D11_BUFFER_DESC desc; memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); desc.Usage = D3D11_USAGE_DYNAMIC; desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); desc.BindFlags = D3D11_BIND_INDEX_BUFFER; desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Upload vertex/index data into a single contiguous GPU buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert)); memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx)); vtx_dst += cmd_list->VtxBuffer.Size; idx_dst += cmd_list->IdxBuffer.Size; } ctx->Unmap(g_pVB, 0); ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). { D3D11_MAPPED_SUBRESOURCE mapped_resource; if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; float L = draw_data->DisplayPos.x; float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x; float T = draw_data->DisplayPos.y; float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y; float mvp[4][4] = { { 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, { 0.0f, 2.0f/(T-B), 0.0f, 0.0f }, { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); ctx->Unmap(g_pVertexConstantBuffer, 0); } // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) struct BACKUP_DX11_STATE { UINT ScissorRectsCount, ViewportsCount; D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; ID3D11RasterizerState* RS; ID3D11BlendState* BlendState; FLOAT BlendFactor[4]; UINT SampleMask; UINT StencilRef; ID3D11DepthStencilState* DepthStencilState; ID3D11ShaderResourceView* PSShaderResource; ID3D11SamplerState* PSSampler; ID3D11PixelShader* PS; ID3D11VertexShader* VS; UINT PSInstancesCount, VSInstancesCount; ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; DXGI_FORMAT IndexBufferFormat; ID3D11InputLayout* InputLayout; }; BACKUP_DX11_STATE old; old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); ctx->RSGetState(&old.RS); ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); ctx->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef); ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); ctx->PSGetSamplers(0, 1, &old.PSSampler); old.PSInstancesCount = old.VSInstancesCount = 256; ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); ctx->IAGetInputLayout(&old.InputLayout); // Setup desired DX state ImGui_ImplDX11_SetupRenderState(draw_data, ctx); // Render command lists // (Because we merged all buffers into a single one, we maintain our own offset into them) int global_idx_offset = 0; int global_vtx_offset = 0; ImVec2 clip_off = draw_data->DisplayPos; for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) { const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; if (pcmd->UserCallback != NULL) { // User callback, registered via ImDrawList::AddCallback() // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.) if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) ImGui_ImplDX11_SetupRenderState(draw_data, ctx); else pcmd->UserCallback(cmd_list, pcmd); } else { // Apply scissor/clipping rectangle const D3D11_RECT r = { (LONG)(pcmd->ClipRect.x - clip_off.x), (LONG)(pcmd->ClipRect.y - clip_off.y), (LONG)(pcmd->ClipRect.z - clip_off.x), (LONG)(pcmd->ClipRect.w - clip_off.y) }; ctx->RSSetScissorRects(1, &r); // Bind texture, Draw ID3D11ShaderResourceView* texture_srv = (ID3D11ShaderResourceView*)pcmd->TextureId; ctx->PSSetShaderResources(0, 1, &texture_srv); ctx->DrawIndexed(pcmd->ElemCount, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset); } } global_idx_offset += cmd_list->IdxBuffer.Size; global_vtx_offset += cmd_list->VtxBuffer.Size; } // Restore modified DX state ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); ctx->RSSetViewports(old.ViewportsCount, old.Viewports); ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release(); ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); ctx->IASetPrimitiveTopology(old.PrimitiveTopology); ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); }
gl::Error PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget, GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) { ANGLE_TRY(loadResources()); gl::Extents destSize = destRenderTarget->getExtents(); ASSERT(destArea.x >= 0 && destArea.x + destArea.width <= destSize.width && destArea.y >= 0 && destArea.y + destArea.height <= destSize.height && destArea.z >= 0 && destArea.z + destArea.depth <= destSize.depth ); const gl::Buffer &sourceBuffer = *unpack.pixelBuffer.get(); ASSERT(mRenderer->supportsFastCopyBufferToTexture(destinationFormat)); ID3D11PixelShader *pixelShader = findBufferToTexturePS(destinationFormat); ASSERT(pixelShader); // The SRV must be in the proper read format, which may be different from the destination format // EG: for half float data, we can load full precision floats with implicit conversion GLenum unsizedFormat = gl::GetInternalFormatInfo(destinationFormat).format; GLenum sourceFormat = gl::GetSizedInternalFormat(unsizedFormat, sourcePixelsType); const d3d11::Format &sourceFormatInfo = d3d11::Format::Get(sourceFormat, mRenderer->getRenderer11DeviceCaps()); DXGI_FORMAT srvFormat = sourceFormatInfo.srvFormat; ASSERT(srvFormat != DXGI_FORMAT_UNKNOWN); Buffer11 *bufferStorage11 = GetAs<Buffer11>(sourceBuffer.getImplementation()); ID3D11ShaderResourceView *bufferSRV = nullptr; ANGLE_TRY_RESULT(bufferStorage11->getSRV(srvFormat), bufferSRV); ASSERT(bufferSRV != nullptr); ID3D11RenderTargetView *textureRTV = GetAs<RenderTarget11>(destRenderTarget)->getRenderTargetView(); ASSERT(textureRTV != nullptr); CopyShaderParams shaderParams; setBufferToTextureCopyParams(destArea, destSize, sourceFormat, unpack, offset, &shaderParams); ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); ID3D11Buffer *nullBuffer = nullptr; UINT zero = 0; // Are we doing a 2D or 3D copy? ID3D11GeometryShader *geometryShader = ((destSize.depth > 1) ? mBufferToTextureGS : NULL); auto stateManager = mRenderer->getStateManager(); deviceContext->VSSetShader(mBufferToTextureVS, NULL, 0); deviceContext->GSSetShader(geometryShader, NULL, 0); deviceContext->PSSetShader(pixelShader, NULL, 0); stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, bufferSRV); deviceContext->IASetInputLayout(NULL); deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero); deviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF); deviceContext->OMSetDepthStencilState(mCopyDepthStencilState, 0xFFFFFFFF); deviceContext->RSSetState(mCopyRasterizerState); stateManager->setOneTimeRenderTarget(textureRTV, nullptr); if (!StructEquals(mParamsData, shaderParams)) { d3d11::SetBufferData(deviceContext, mParamsConstantBuffer, shaderParams); mParamsData = shaderParams; } deviceContext->VSSetConstantBuffers(0, 1, &mParamsConstantBuffer); // Set the viewport D3D11_VIEWPORT viewport; viewport.TopLeftX = 0; viewport.TopLeftY = 0; viewport.Width = static_cast<FLOAT>(destSize.width); viewport.Height = static_cast<FLOAT>(destSize.height); viewport.MinDepth = 0.0f; viewport.MaxDepth = 1.0f; deviceContext->RSSetViewports(1, &viewport); UINT numPixels = (destArea.width * destArea.height * destArea.depth); deviceContext->Draw(numPixels, 0); // Unbind textures and render targets and vertex buffer stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); deviceContext->VSSetConstantBuffers(0, 1, &nullBuffer); mRenderer->markAllStateDirty(); return gl::NoError(); }
void DrawCoordinate() { struct CB { XMMATRIX mWorldViewProj; }; ID3D11Device* pDevice = WE::D3DDevice(); ID3D11DeviceContext* pImmediateContext = WE::ImmediateContext(); static ID3D11VertexShader* g_pVertexShader = NULL; static ID3D11PixelShader* g_pPixelShader = NULL; static ID3D11Buffer* g_pCB = NULL; static const char* g_strBuffer = " cbuffer cbPerObject : register( b0 ) \r\n" " { \r\n" " matrix g_mWorldViewProjection : packoffset( c0 ); \r\n" " }; \r\n" " \r\n" " struct VS_In \r\n" " { \r\n" " uint id : SV_VERTEXID; \r\n" " }; \r\n" " \r\n" " struct VS_Out \r\n" " { \r\n" " float4 pos : SV_POSITION; \r\n" " float4 color : COLOR; \r\n" " }; \r\n" " \r\n" " \r\n" " cbuffer cbImmutable \r\n" " { \r\n" " static float4 g_positions[6] = \r\n" " { \r\n" " float4( 0.0f, 0.0f, 0.0f, 1.0f ), \r\n" " float4( 1.0f, 0.0f, 0.0f, 1.0f ), \r\n" " float4( 0.0f, 0.0f, 0.0f, 1.0f ), \r\n" " float4( 0.0f, 1.0f, 0.0f, 1.0f ), \r\n" " float4( 0.0f, 0.0f, 0.0f, 1.0f ), \r\n" " float4( 0.0f, 0.0f, 1.0f, 1.0f ), \r\n" " }; \r\n" " \r\n" " static float4 g_colors[6] = \r\n" " { \r\n" " float4( 1.0f, 0.0f, 0.0f, 1.0f ), \r\n" " float4( 1.0f, 0.0f, 0.0f, 1.0f ), \r\n" " float4( 0.0f, 1.0f, 0.0f, 1.0f ), \r\n" " float4( 0.0f, 1.0f, 0.0f, 1.0f ), \r\n" " float4( 0.0f, 0.0f, 1.0f, 1.0f ), \r\n" " float4( 0.0f, 0.0f, 1.0f, 1.0f ), \r\n" " }; \r\n" " }; \r\n" " VS_Out VSMain(VS_In input) \r\n" " { \r\n" " VS_Out output; \r\n" " \r\n" " output.pos = mul( g_positions[input.id] * 5, g_mWorldViewProjection ); \r\n" " output.color = g_colors[input.id]; \r\n" " return output; \r\n" " } \r\n" " \r\n" " float4 PSMain(VS_Out input) : SV_Target \r\n" " { \r\n" " return input.color; \r\n" " return float4( 1.0f, 1.0f, 0.0f, 1.0f ); \r\n" " } \r\n" ""; HRESULT hr; if ( g_pVertexShader == NULL ) { // Create shaders ID3DBlob* pVSBlob = NULL; ID3DBlob* pPSBlob = NULL; UINT dwBufferSize = ( UINT )strlen( g_strBuffer ) + 1; V( WE::CompileShaderFromMemory( g_strBuffer, dwBufferSize, NULL, "VSMain", "vs_5_0", &pVSBlob ) ); V( WE::CompileShaderFromMemory( g_strBuffer, dwBufferSize, NULL, "PSMain", "ps_5_0", &pPSBlob ) ); V( pDevice->CreateVertexShader( pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), NULL, &g_pVertexShader ) ); V( pDevice->CreatePixelShader( pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), NULL, &g_pPixelShader ) ); SAFE_RELEASE( pVSBlob ); SAFE_RELEASE( pPSBlob ); // Create the constant buffers D3D11_BUFFER_DESC Desc; Desc.Usage = D3D11_USAGE_DYNAMIC; Desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; Desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; Desc.MiscFlags = 0; Desc.ByteWidth = sizeof( CB ); V( pDevice->CreateBuffer( &Desc, NULL, &g_pCB ) ); } D3D11_MAPPED_SUBRESOURCE MappedResource; V(pImmediateContext->Map( g_pCB, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ) ); CB* pPerFrame = ( CB* )MappedResource.pData; pPerFrame->mWorldViewProj = XMMatrixTranspose( WE::Camera()->GetViewProjMtx() ); pImmediateContext->Unmap( g_pCB, 0 ); pImmediateContext->VSSetConstantBuffers( 0, 1, &g_pCB ); pImmediateContext->OMSetDepthStencilState( NULL, 0 ); float vBlendFactor[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; pImmediateContext->OMSetBlendState( NULL, vBlendFactor, 0xFFFFFFFF ); pImmediateContext->RSSetState( NULL ); pImmediateContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_LINELIST ); pImmediateContext->VSSetShader( g_pVertexShader, NULL, 0 ); pImmediateContext->PSSetShader( g_pPixelShader, NULL, 0 ); pImmediateContext->GSSetShader( NULL, NULL, 0 ); // Draw pImmediateContext->Draw( 6, 0 ); }