diff --git a/Makefile b/Makefile index b6eca17..fd08b35 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,8 @@ all: $(BUILD_TYPE)/d3d10.exe SHADERS = \ main.fxo \ - font.fxo + font.fxo \ + bloom.fxo $(BUILD_TYPE)/%.res: %.rc $(SHADERS) rc.exe /d "_UNICODE" /d "UNICODE" /fo $@ $< diff --git a/bloom.fx b/bloom.fx new file mode 100644 index 0000000..815d067 --- /dev/null +++ b/bloom.fx @@ -0,0 +1,74 @@ +float2 vInvScreenSize; +float2 vDir; + +Texture2D txDiffuse; +SamplerState samPoint { + Filter = MIN_MAG_MIP_POINT; + AddressU = Wrap; + AddressV = Wrap; +}; + +struct VS_INPUT +{ + float4 Pos : POSITION; +}; + +struct PS_INPUT +{ + float4 Pos : SV_POSITION; + float2 Tex : TEXCOORD0; +}; + +PS_INPUT VS(VS_INPUT input) +{ + PS_INPUT output; + + output.Pos = input.Pos; + output.Tex = input.Pos.xy * float2(0.5, -0.5) + float2(0.5, 0.5); + + return output; +} + +static const float offset[] = {0.0, 1.0, 2.0, 3.0, 4.0}; +static const float weight[] = { // sigma 1.75, radius 4 + 0.22720403874968215, + 0.19382872916158458, + 0.12033793944552469, + 0.05436431541122633, + 0.01786699660682331, +}; + +float4 PS(PS_INPUT input) : SV_Target +{ + float4 texColor = txDiffuse.Sample(samPoint, input.Tex) * weight[0]; + for (int i = 1; i < 5; i++) { + float2 texOffset = vDir * offset[i] * vInvScreenSize; + texColor += txDiffuse.Sample(samPoint, input.Tex + texOffset) * weight[i]; + texColor += txDiffuse.Sample(samPoint, input.Tex - texOffset) * weight[i]; + } + + return texColor; +} + +BlendState Blending +{ + BlendEnable[0] = FALSE; +}; + +DepthStencilState DisableDepth +{ + DepthEnable = FALSE; + DepthWriteMask = ZERO; +}; + +technique10 Bloom +{ + pass P0 + { + SetVertexShader(CompileShader(vs_4_0, VS())); + SetGeometryShader(NULL); + SetPixelShader(CompileShader(ps_4_0, PS())); + SetBlendState(Blending, float4(0.0, 0.0, 0.0, 0.0), 0xffffffff); + SetDepthStencilState(DisableDepth, 0); + } +} diff --git a/font.fx b/font.fx index f900bbd..b45bd5e 100644 --- a/font.fx +++ b/font.fx @@ -81,6 +81,12 @@ BlendState Blending BlendOpAlpha = ADD; }; +DepthStencilState DisableDepth +{ + DepthEnable = FALSE; + DepthWriteMask = ZERO; +}; + technique10 Font { pass P0 @@ -89,5 +95,6 @@ technique10 Font SetGeometryShader(CompileShader(gs_4_0, GS())); SetPixelShader(CompileShader(ps_4_0, PS())); SetBlendState(Blending, float4(0.0, 0.0, 0.0, 0.0), 0xffffffff); + SetDepthStencilState(DisableDepth, 0); } } diff --git a/include/render_state.hpp b/include/render_state.hpp index a1ed81e..cf69a6e 100644 --- a/include/render_state.hpp +++ b/include/render_state.hpp @@ -8,4 +8,14 @@ HRESULT LoadTexture(const wchar_t * resourceName, const DXGI_FORMAT format, ID3D10ShaderResourceView ** pTextureShaderResourceView); +HRESULT CreateTextureRenderTargetView(const int width, + const int height, + ID3D10Texture2D ** pTexture, + ID3D10RenderTargetView ** pRenderTargetView); + +HRESULT CreateTextureRenderTargetView(const int width, + const int height, + ID3D10RenderTargetView ** pRenderTargetView, + ID3D10ShaderResourceView ** pTextureShaderResourceView); + #endif _RENDER_STATE_HPP_ diff --git a/main.fx b/main.fx index 300cb94..84dea12 100644 --- a/main.fx +++ b/main.fx @@ -53,8 +53,8 @@ PS_INPUT VS(VS_INPUT input) output.Joint = input.Joint; output.Tex = input.Tex; - output.Normal = mul(input.Normal, mSkin); - output.Normal = mul(output.Normal, World); + output.Normal = mul(input.Normal, mSkin).xyz; + output.Normal = mul(output.Normal, World).xyz; return output; } @@ -72,17 +72,17 @@ float4 PS(PS_INPUT input) : SV_Target return texColor * intensityColor; } -float4 PSSolid(PS_INPUT input) : SV_Target -{ - //return vOutputColor; - return float4(input.Weight.xyz, 1); -} - BlendState Blending { BlendEnable[0] = FALSE; }; +DepthStencilState EnableDepth +{ + DepthEnable = TRUE; + DepthWriteMask = ALL; +}; + technique10 Render { pass P0 @@ -91,15 +91,6 @@ technique10 Render SetGeometryShader(NULL); SetPixelShader(CompileShader(ps_4_0, PS())); SetBlendState(Blending, float4(0.0, 0.0, 0.0, 0.0), 0xffffffff); - } -} - -technique10 RenderLight -{ - pass P0 - { - SetVertexShader(CompileShader(vs_4_0, VS())); - SetGeometryShader(NULL); - SetPixelShader(CompileShader(ps_4_0, PSSolid())); + SetDepthStencilState(EnableDepth, 0); } } diff --git a/main.rc b/main.rc index dcf670c..aed84c2 100644 --- a/main.rc +++ b/main.rc @@ -1,4 +1,5 @@ RES_MAIN_FXO RCDATA "main.fxo" RES_FONT_FXO RCDATA "font.fxo" +RES_BLOOM_FXO RCDATA "bloom.fxo" RES_ROBOT_PLAYER RCDATA "robot_player.data" RES_FONT_TERMINUS_6X12 RCDATA "font/terminus_128x64_6x12.data" \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 1921013..5915d06 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -45,6 +45,21 @@ D3DXMATRIX g_World2; D3DXMATRIX g_View; D3DXMATRIX g_Projection; +// bloom +ID3D10RenderTargetView * g_pRenderTargetViewTexture[2] = { NULL, NULL }; +ID3D10ShaderResourceView * g_pRenderTargetShaderResourceView[2] = { NULL, NULL }; + +ID3D10Effect * g_pEffectBloom = NULL; +ID3D10EffectTechnique * g_pTechniqueBloom = NULL; +ID3D10InputLayout * g_pVertexLayoutBloom = NULL; +const DWORD g_dwVertexBufferCountBloom = 1; +ID3D10Buffer * g_pVertexBuffersBloom[g_dwVertexBufferCountBloom]; +ID3D10EffectShaderResourceVariable * g_pDiffuseVariableBloom = NULL; +ID3D10EffectVectorVariable * g_pInvScreenSizeVariableBloom = NULL; +ID3D10EffectVectorVariable * g_pDirVariableBloom = NULL; + +typedef D3DXVECTOR2 BloomVertex; + // font ID3D10Effect * g_pEffectFont = NULL; @@ -58,6 +73,11 @@ ID3D10EffectVectorVariable * g_pGlyphScaleVariableFont = NULL; ID3D10EffectVectorVariable * g_pTexScaleVariableFont = NULL; ID3D10EffectShaderResourceVariable * g_pDiffuseVariableFont = NULL; +const int g_iFontBufferLength = 512; +typedef D3DXVECTOR4 FontVertex; + +// forward declarations + HRESULT InitWindow(HINSTANCE hInstance, int nCmdShow); LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); HRESULT InitDirect3DDevice(); @@ -134,7 +154,7 @@ HRESULT InitWindow(HINSTANCE hInstance, int nCmdShow) return E_FAIL; // create window - RECT rc = { 0, 0, 320, 240 }; + RECT rc = { 0, 0, 160, 120 }; AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE); UINT width = rc.right - rc.left; UINT height = rc.bottom - rc.top; @@ -195,7 +215,7 @@ HRESULT InitDirect3DViews() hr = g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, &g_pRenderTargetView); pBackBuffer->Release(); if (FAILED(hr)) { - print("g_pSwapChain->CreateRenderTargetView\n"); + print("g_pd3dDevice->CreateRenderTargetView(pBackBuffer)\n"); return hr; } @@ -212,6 +232,7 @@ HRESULT InitDirect3DViews() descDepth.BindFlags = D3D10_BIND_DEPTH_STENCIL; descDepth.CPUAccessFlags = 0; descDepth.MiscFlags = 0; + hr = g_pd3dDevice->CreateTexture2D(&descDepth, NULL, &g_pDepthStencil); if (FAILED(hr)) { print("CreateTexture2D\n"); @@ -222,13 +243,23 @@ HRESULT InitDirect3DViews() descDSV.Format = descDepth.Format; descDSV.ViewDimension = D3D10_DSV_DIMENSION_TEXTURE2D; descDSV.Texture2D.MipSlice = 0; + hr = g_pd3dDevice->CreateDepthStencilView(g_pDepthStencil, &descDSV, &g_pDepthStencilView); if (FAILED(hr)) { print("CreateDepthStencilView\n"); return hr; } - g_pd3dDevice->OMSetRenderTargets(1, &g_pRenderTargetView, g_pDepthStencilView); + // intermediate render targets + for (int i = 0; i < 2; i++) { + hr = CreateTextureRenderTargetView(backBufferSurfaceDesc.Width, + backBufferSurfaceDesc.Height, + &g_pRenderTargetViewTexture[i], + &g_pRenderTargetShaderResourceView[i]); + if (FAILED(hr)) { + return hr; + } + } // viewport D3D10_VIEWPORT vp; @@ -259,7 +290,7 @@ HRESULT LoadMesh() const Mesh * mesh = ROOT_MESH_NODE.mesh; // position - bd.Usage = D3D10_USAGE_DEFAULT; + bd.Usage = D3D10_USAGE_IMMUTABLE; bd.ByteWidth = mesh->position_size; bd.BindFlags = D3D10_BIND_VERTEX_BUFFER; bd.CPUAccessFlags = 0; @@ -272,7 +303,7 @@ HRESULT LoadMesh() } // weights - bd.Usage = D3D10_USAGE_DEFAULT; + bd.Usage = D3D10_USAGE_IMMUTABLE; bd.ByteWidth = mesh->weights_0_size; bd.BindFlags = D3D10_BIND_VERTEX_BUFFER; bd.CPUAccessFlags = 0; @@ -285,7 +316,7 @@ HRESULT LoadMesh() } // joints - bd.Usage = D3D10_USAGE_DEFAULT; + bd.Usage = D3D10_USAGE_IMMUTABLE; bd.ByteWidth = mesh->joints_0_size; bd.BindFlags = D3D10_BIND_VERTEX_BUFFER; bd.CPUAccessFlags = 0; @@ -298,7 +329,7 @@ HRESULT LoadMesh() } // normals - bd.Usage = D3D10_USAGE_DEFAULT; + bd.Usage = D3D10_USAGE_IMMUTABLE; bd.ByteWidth = mesh->normal_size; bd.BindFlags = D3D10_BIND_VERTEX_BUFFER; bd.CPUAccessFlags = 0; @@ -311,7 +342,7 @@ HRESULT LoadMesh() } // texcoords - bd.Usage = D3D10_USAGE_DEFAULT; + bd.Usage = D3D10_USAGE_IMMUTABLE; bd.ByteWidth = mesh->texcoord_0_size; bd.BindFlags = D3D10_BIND_VERTEX_BUFFER; bd.CPUAccessFlags = 0; @@ -327,7 +358,7 @@ HRESULT LoadMesh() // index buffer ////////////////////////////////////////////////////////////////////// - bd.Usage = D3D10_USAGE_DEFAULT; + bd.Usage = D3D10_USAGE_IMMUTABLE; bd.ByteWidth = mesh->indices_size; bd.BindFlags = D3D10_BIND_INDEX_BUFFER; bd.CPUAccessFlags = 0; @@ -368,9 +399,6 @@ HRESULT LoadMesh() return S_OK; } -const int g_iFontBufferLength = 512; -typedef D3DXVECTOR4 FontVertex; - HRESULT InitFontBuffers() { HRESULT hr; @@ -448,6 +476,92 @@ HRESULT InitFontBuffers() return S_OK; } +// +Y is up +D3DXVECTOR2 vtxBloom[] = { + D3DXVECTOR2(-1, -1), // top left + D3DXVECTOR2(-1, 1), // top right + D3DXVECTOR2( 1, -1), // bottom left + D3DXVECTOR2( 1, 1), // bottom right +}; + +HRESULT InitBloomBuffers() +{ + HRESULT hr; + + ////////////////////////////////////////////////////////////////////// + // effect + ////////////////////////////////////////////////////////////////////// + + HRSRC hRes = FindResource(NULL, L"RES_BLOOM_FXO", RT_RCDATA); + if (hRes == NULL) { + print("FindResource RES_BLOOM_FXO\n"); + return E_FAIL; + } + DWORD dwResSize = SizeofResource(NULL, hRes); + HGLOBAL hData = LoadResource(NULL, hRes); + void * pData = LockResource(hData); + hr = D3D10CreateEffectFromMemory(pData, + dwResSize, + 0, + g_pd3dDevice, + NULL, + &g_pEffectBloom + ); + if (FAILED(hr)) { + print("D3D10CreateEffectFromMemory\n"); + return hr; + } + + g_pTechniqueBloom = g_pEffectBloom->GetTechniqueByName("Bloom"); + g_pInvScreenSizeVariableBloom = g_pEffectBloom->GetVariableByName("vInvScreenSize")->AsVector(); + g_pDirVariableBloom = g_pEffectBloom->GetVariableByName("vDir")->AsVector(); + g_pDiffuseVariableBloom = g_pEffectBloom->GetVariableByName("txDiffuse")->AsShaderResource(); + + ////////////////////////////////////////////////////////////////////// + // layout + ////////////////////////////////////////////////////////////////////// + + D3D10_INPUT_ELEMENT_DESC layout[] = { + {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0 , D3D10_INPUT_PER_VERTEX_DATA, 0}, + }; + UINT numElements = (sizeof (layout)) / (sizeof (layout[0])); + + D3D10_PASS_DESC passDesc; + g_pTechniqueBloom->GetPassByIndex(0)->GetDesc(&passDesc); + + hr = g_pd3dDevice->CreateInputLayout(layout, numElements, + passDesc.pIAInputSignature, + passDesc.IAInputSignatureSize, + &g_pVertexLayoutBloom); + if (FAILED(hr)) { + print("CreateInputLayout\n"); + return hr; + } + + ////////////////////////////////////////////////////////////////////// + // vertex buffers + ////////////////////////////////////////////////////////////////////// + + D3D10_BUFFER_DESC bd; + D3D10_SUBRESOURCE_DATA initData; + + // position + bd.Usage = D3D10_USAGE_IMMUTABLE; + bd.ByteWidth = (sizeof (vtxBloom)); + bd.BindFlags = D3D10_BIND_VERTEX_BUFFER; + bd.CPUAccessFlags = 0; + bd.MiscFlags = 0; + initData.pSysMem = vtxBloom; + + hr = g_pd3dDevice->CreateBuffer(&bd, &initData, &g_pVertexBuffersBloom[0]); + if (FAILED(hr)) { + print("CreateBuffer\n"); + return hr; + } + + return S_OK; +} + HRESULT InitDirect3DDevice() { RECT rc; @@ -602,6 +716,12 @@ HRESULT InitDirect3DDevice() return hr; } + hr = InitBloomBuffers(); + if (FAILED(hr)) { + print("InitBloomBuffers\n"); + return hr; + } + ////////////////////////////////////////////////////////////////////// // transform matrices ////////////////////////////////////////////////////////////////////// @@ -641,7 +761,7 @@ BOOL Resize() if (width == g_ViewportSize.Width && height == g_ViewportSize.Height) return true; - //g_pd3dDevice->OMSetRenderTargets(1, NULL, NULL); + g_pd3dDevice->OMSetRenderTargets(0, NULL, NULL); g_pRenderTargetView->Release(); g_pDepthStencil->Release(); g_pDepthStencilView->Release(); @@ -886,7 +1006,6 @@ void RenderModel(float t) void RenderFont() { - ////////////////////////////////////////////////////////////////////// // dynamic vertex buffer ////////////////////////////////////////////////////////////////////// @@ -916,7 +1035,6 @@ void RenderFont() c -= 0x20; cx = (float)(c % charStride); cy = (float)(c / charStride); - print("%c %f %f\n", c + 0x20, cx, cy); } pData[ix++] = FontVertex(px, py, cx, cy); @@ -945,6 +1063,8 @@ void RenderFont() g_pTexScaleVariableFont->SetFloatVector((float *)&texScale); g_pDiffuseVariableFont->SetResource(g_pTextureShaderResourceViewFont); + ////////////////////////////////////////////////////////////////////// + UINT stride[] = { (sizeof (FontVertex)), }; @@ -962,6 +1082,54 @@ void RenderFont() } } +void RenderBloom() +{ + ////////////////////////////////////////////////////////////////////// + // effect variables + ////////////////////////////////////////////////////////////////////// + + D3DXVECTOR2 invScreenSize = D3DXVECTOR2(1.0f / (float)g_ViewportSize.Width, + 1.0f / (float)g_ViewportSize.Height); + + g_pInvScreenSizeVariableBloom->SetFloatVector((float *)&invScreenSize); + + ////////////////////////////////////////////////////////////////////// + + UINT stride[] = { + (sizeof (BloomVertex)), + }; + UINT offset[] = { 0 }; + g_pd3dDevice->IASetInputLayout(g_pVertexLayoutBloom); + g_pd3dDevice->IASetVertexBuffers(0, g_dwVertexBufferCountBloom, g_pVertexBuffersBloom, stride, offset); + g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + + D3D10_TECHNIQUE_DESC techDesc; + g_pTechniqueBloom->GetDesc(&techDesc); + + // horizontal + + D3DXVECTOR2 dirHorizontal = D3DXVECTOR2(1.0, 0.0); + g_pDirVariableBloom->SetFloatVector((float *)dirHorizontal); + g_pDiffuseVariableBloom->SetResource(g_pRenderTargetShaderResourceView[0]); + g_pd3dDevice->OMSetRenderTargets(1, &g_pRenderTargetViewTexture[1], NULL); + + for (UINT p = 0; p < techDesc.Passes; p++) { + g_pTechniqueBloom->GetPassByIndex(p)->Apply(0); + g_pd3dDevice->Draw(4, 0); + } + + // vertical + D3DXVECTOR2 dirVertical = D3DXVECTOR2(0.0, 1.0); + g_pDirVariableBloom->SetFloatVector((float *)dirVertical); + g_pDiffuseVariableBloom->SetResource(g_pRenderTargetShaderResourceView[1]); + g_pd3dDevice->OMSetRenderTargets(1, &g_pRenderTargetView, NULL); + + for (UINT p = 0; p < techDesc.Passes; p++) { + g_pTechniqueBloom->GetPassByIndex(p)->Apply(0); + g_pd3dDevice->Draw(4, 0); + } +} + void Render() { static float t = 0.0f; @@ -977,35 +1145,16 @@ void Render() // clear + g_pd3dDevice->OMSetRenderTargets(1, &g_pRenderTargetViewTexture[0], g_pDepthStencilView); float ClearColor[4] = { 0.0f, 0.125f, 0.6f, 1.0f }; - g_pd3dDevice->ClearRenderTargetView(g_pRenderTargetView, ClearColor); + g_pd3dDevice->ClearRenderTargetView(g_pRenderTargetViewTexture[0], ClearColor); g_pd3dDevice->ClearDepthStencilView(g_pDepthStencilView, D3D10_CLEAR_DEPTH, 1.0f, 0); // render - RenderModel(t); RenderFont(); - // render the lights - /* - for (int m = 0; m < 2; m++) { - D3DXMATRIX mLight; - D3DXMATRIX mLightScale; - D3DXVECTOR3 vLightPos = vLightDirs[m] * 4.0f; - D3DXMatrixTranslation( &mLight, vLightPos.x, vLightPos.y, vLightPos.z ); - D3DXMatrixScaling( &mLightScale, 0.2f, 0.2f, 0.2f ); - mLight = mLightScale * mLight; - - g_pWorldVariable->SetMatrix((float *)&mLight); - g_pOutputColorVariable->SetFloatVector((float *)&vLightColors[m]); - - g_pTechniqueRenderLight->GetDesc( &techDesc ); - for (UINT p = 0; p < techDesc.Passes; p++) { - g_pTechniqueRenderLight->GetPassByIndex(p)->Apply(0); - g_pd3dDevice->DrawIndexed(indices_length, 0, 0); - } - } - */ + RenderBloom(); // present g_pSwapChain->Present(0, 0); diff --git a/src/render_state.cpp b/src/render_state.cpp index c8ed5a3..554d12b 100644 --- a/src/render_state.cpp +++ b/src/render_state.cpp @@ -39,7 +39,7 @@ HRESULT LoadTexture(const wchar_t * resourceName, textureDesc.Format = format; textureDesc.SampleDesc.Count = 1; textureDesc.SampleDesc.Quality = 0; - textureDesc.Usage = D3D10_USAGE_DEFAULT; + textureDesc.Usage = D3D10_USAGE_IMMUTABLE; textureDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; textureDesc.CPUAccessFlags = 0; textureDesc.MiscFlags = 0; @@ -65,3 +65,51 @@ HRESULT LoadTexture(const wchar_t * resourceName, return S_OK; } + +HRESULT CreateTextureRenderTargetView(const int width, + const int height, + ID3D10RenderTargetView ** pRenderTargetView, + ID3D10ShaderResourceView ** pTextureShaderResourceView) +{ + HRESULT hr; + + D3D10_TEXTURE2D_DESC textureDesc; + textureDesc.Width = width; + textureDesc.Height = height; + textureDesc.MipLevels = 1; + textureDesc.ArraySize = 1; + textureDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; + textureDesc.SampleDesc.Count = 1; + textureDesc.SampleDesc.Quality = 0; + textureDesc.Usage = D3D10_USAGE_DEFAULT; + textureDesc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE; + textureDesc.CPUAccessFlags = 0; + textureDesc.MiscFlags = 0; + + ID3D10Texture2D * pTexture; + + hr = g_pd3dDevice->CreateTexture2D(&textureDesc, NULL, &pTexture); + if (FAILED(hr)) { + print("CreateTexture2D\n"); + return hr; + } + + hr = g_pd3dDevice->CreateRenderTargetView(pTexture, NULL, pRenderTargetView); + if (FAILED(hr)) { + print("g_pd3dDevice->CreateRenderTargetView(pTexture)\n"); + return hr; + } + + D3D10_SHADER_RESOURCE_VIEW_DESC descSRV; + descSRV.Format = textureDesc.Format; + descSRV.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + descSRV.Texture2D.MostDetailedMip = 0; + descSRV.Texture2D.MipLevels = 1; + hr = g_pd3dDevice->CreateShaderResourceView(pTexture, &descSRV, pTextureShaderResourceView); + if (FAILED(hr)) { + print("CreateShaderResourceView\n"); + return hr; + } + + return S_OK; +}