diff --git a/Minecraft.Client/Minecraft.Client.vcxproj b/Minecraft.Client/Minecraft.Client.vcxproj index 078a606..18154a8 100644 --- a/Minecraft.Client/Minecraft.Client.vcxproj +++ b/Minecraft.Client/Minecraft.Client.vcxproj @@ -1293,7 +1293,7 @@ if not exist "$(TargetDir)\savedata" mkdir "$(TargetDir)\savedata" true $(OutDir)$(ProjectName).pdb - d3d11.lib;..\Minecraft.World\x64_Debug\Minecraft.World.lib;%(AdditionalDependencies);XInput9_1_0.lib;..\Minecraft.Client\Windows64\Miles\Lib\mss64.lib + d3d11.lib;d3dcompiler.lib;..\Minecraft.World\x64_Debug\Minecraft.World.lib;%(AdditionalDependencies);XInput9_1_0.lib;..\Minecraft.Client\Windows64\Miles\Lib\mss64.lib NotSet false @@ -1432,7 +1432,7 @@ xcopy /q /y /i /s /e $(ProjectDir)Durango\CU $(LayoutDir)Image\Loose\CU true $(OutDir)$(ProjectName).pdb - d3d11.lib;..\Minecraft.World\x64_Release\Minecraft.World.lib;XInput9_1_0.lib;Windows64\Iggy\lib\iggy_w64.lib;..\Minecraft.Client\Windows64\Miles\Lib\mss64.lib;%(AdditionalDependencies) + d3d11.lib;d3dcompiler.lib;..\Minecraft.World\x64_Release\Minecraft.World.lib;XInput9_1_0.lib;Windows64\Iggy\lib\iggy_w64.lib;..\Minecraft.Client\Windows64\Miles\Lib\mss64.lib;%(AdditionalDependencies) NotSet false @@ -1484,7 +1484,7 @@ copy /Y "$(ProjectDir)Durango\Sound\Minecraft.msscmp" "$(OutDir)Durango\Sound\"< true $(OutDir)$(ProjectName).pdb - d3d11.lib;..\Minecraft.World\x64_Release\Minecraft.World.lib;XInput9_1_0.lib;Windows64\Iggy\lib\iggy_w64.lib;%(AdditionalDependencies) + d3d11.lib;d3dcompiler.lib;..\Minecraft.World\x64_Release\Minecraft.World.lib;XInput9_1_0.lib;Windows64\Iggy\lib\iggy_w64.lib;%(AdditionalDependencies) NotSet false @@ -16657,6 +16657,37 @@ xcopy /q /y /i /s /e $(ProjectDir)Durango\CU $(LayoutDir)Image\Loose\CUtrue true + + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + false + false + false + false + false + false + false + true + true + true + true + true + true + true + true true @@ -29116,6 +29147,51 @@ xcopy /q /y /i /s /e $(ProjectDir)Durango\CU $(LayoutDir)Image\Loose\CUtrue true + + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + false + false + false + false + false + false + false + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true true diff --git a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp index 1e52a16..f17d698 100644 --- a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp +++ b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp @@ -37,8 +37,11 @@ #include "Resource.h" #include "..\..\Minecraft.World\compression.h" #include "..\..\Minecraft.World\OldChunkStorage.h" + #include "Network\WinsockNetLayer.h" +#include "Windows64_PostProcess.h" + #include "Xbox/resource.h" HINSTANCE hMyInst; @@ -343,54 +346,23 @@ ID3D11Device* g_pd3dDevice = NULL; ID3D11DeviceContext* g_pImmediateContext = NULL; IDXGISwapChain* g_pSwapChain = NULL; -static WORD g_originalGammaRamp[3][256]; -static bool g_gammaRampSaved = false; +ID3D11RenderTargetView* g_pRenderTargetView = NULL; +ID3D11DepthStencilView* g_pDepthStencilView = NULL; +ID3D11Texture2D* g_pDepthStencilBuffer = NULL; void Windows64_UpdateGamma(unsigned short usGamma) { - if (!g_hWnd) return; - - HDC hdc = GetDC(g_hWnd); - if (!hdc) return; - - if (!g_gammaRampSaved) - { - GetDeviceGammaRamp(hdc, g_originalGammaRamp); - g_gammaRampSaved = true; - } - float gamma = (float)usGamma / 32768.0f; - if (gamma < 0.01f) gamma = 0.01f; + if (gamma < 0.0f) gamma = 0.0f; if (gamma > 1.0f) gamma = 1.0f; - float invGamma = 1.0f / (0.5f + gamma * 0.5f); - - WORD ramp[3][256]; - for (int i = 0; i < 256; i++) - { - float normalized = (float)i / 255.0f; - float corrected = powf(normalized, invGamma); - WORD val = (WORD)(corrected * 65535.0f + 0.5f); - ramp[0][i] = val; - ramp[1][i] = val; - ramp[2][i] = val; - } - - SetDeviceGammaRamp(hdc, ramp); - ReleaseDC(g_hWnd, hdc); + SetGammaValue(0.5f * powf(4.0f, gamma)); } void Windows64_RestoreGamma() { - if (!g_gammaRampSaved || !g_hWnd) return; - HDC hdc = GetDC(g_hWnd); - if (!hdc) return; - SetDeviceGammaRamp(hdc, g_originalGammaRamp); - ReleaseDC(g_hWnd, hdc); + } -ID3D11RenderTargetView* g_pRenderTargetView = NULL; -ID3D11DepthStencilView* g_pDepthStencilView = NULL; -ID3D11Texture2D* g_pDepthStencilBuffer = NULL; // // FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM) @@ -712,6 +684,7 @@ app.DebugPrintf("width: %d, height: %d\n", width, height); // Create a depth stencil buffer D3D11_TEXTURE2D_DESC descDepth; + ZeroMemory(&descDepth, sizeof(descDepth)); descDepth.Width = width; descDepth.Height = height; @@ -727,11 +700,10 @@ app.DebugPrintf("width: %d, height: %d\n", width, height); hr = g_pd3dDevice->CreateTexture2D(&descDepth, NULL, &g_pDepthStencilBuffer); D3D11_DEPTH_STENCIL_VIEW_DESC descDSView; + ZeroMemory(&descDSView, sizeof(descDSView)); descDSView.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; descDSView.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; descDSView.Texture2D.MipSlice = 0; - // when would this ever be a non-garbage value? - descDSView.Flags = 0; hr = g_pd3dDevice->CreateDepthStencilView(g_pDepthStencilBuffer, &descDSView, &g_pDepthStencilView); @@ -777,6 +749,8 @@ void CleanupDevice() extern void Windows64_RestoreGamma(); Windows64_RestoreGamma(); + CleanupGammaPostProcess(); + if( g_pImmediateContext ) g_pImmediateContext->ClearState(); if( g_pRenderTargetView ) g_pRenderTargetView->Release(); @@ -861,6 +835,8 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, return 0; } + InitGammaPostProcess(); + #if 0 // Main message loop MSG msg = {0}; @@ -1337,6 +1313,8 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, RenderManager.Set_matrixDirty(); #endif + ApplyGammaPostProcess(); + // Present the frame. RenderManager.Present(); diff --git a/Minecraft.Client/Windows64/Windows64_PostProcess.cpp b/Minecraft.Client/Windows64/Windows64_PostProcess.cpp new file mode 100644 index 0000000..1d06ec8 --- /dev/null +++ b/Minecraft.Client/Windows64/Windows64_PostProcess.cpp @@ -0,0 +1,251 @@ +#include "stdafx.h" +#include "Windows64_PostProcess.h" +#include +#pragma comment(lib, "d3dcompiler.lib") + +extern ID3D11Device* g_pd3dDevice; +extern ID3D11DeviceContext* g_pImmediateContext; +extern IDXGISwapChain* g_pSwapChain; +extern ID3D11RenderTargetView* g_pRenderTargetView; + +static ID3D11Texture2D* g_pGammaOffscreenTex = NULL; +static ID3D11ShaderResourceView* g_pGammaOffscreenSRV = NULL; +static ID3D11RenderTargetView* g_pGammaOffscreenRTV = NULL; +static ID3D11VertexShader* g_pGammaVS = NULL; +static ID3D11PixelShader* g_pGammaPS = NULL; +static ID3D11Buffer* g_pGammaCB = NULL; +static ID3D11SamplerState* g_pGammaSampler = NULL; +static ID3D11RasterizerState* g_pGammaRastState = NULL; +static ID3D11DepthStencilState* g_pGammaDepthState = NULL; +static ID3D11BlendState* g_pGammaBlendState = NULL; +static bool g_gammaPostProcessReady = false; +static float g_gammaValue = 1.0f; + +struct GammaCBData +{ + float gamma; + float pad[3]; +}; + +static const char* g_gammaVSCode = + "void main(uint id : SV_VertexID, out float4 pos : SV_Position, out float2 uv : TEXCOORD0)\n" + "{\n" + " uv = float2((id << 1) & 2, id & 2);\n" + " pos = float4(uv * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0);\n" + "}\n"; + +static const char* g_gammaPSCode = + "cbuffer GammaCB : register(b0)\n" + "{\n" + " float gamma;\n" + " float3 pad;\n" + "};\n" + "Texture2D sceneTex : register(t0);\n" + "SamplerState sceneSampler : register(s0);\n" + "float4 main(float4 pos : SV_Position, float2 uv : TEXCOORD0) : SV_Target\n" + "{\n" + " float4 color = sceneTex.Sample(sceneSampler, uv);\n" + " color.rgb = pow(max(color.rgb, 0.0), 1.0 / gamma);\n" + " return color;\n" + "}\n"; + + +void SetGammaValue(float gamma) +{ + g_gammaValue = gamma; +} + +bool InitGammaPostProcess() +{ + if (!g_pd3dDevice || !g_pSwapChain) return false; + + HRESULT hr; + + ID3D11Texture2D* pBackBuffer = NULL; + hr = g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer); + if (FAILED(hr)) return false; + + D3D11_TEXTURE2D_DESC bbDesc; + pBackBuffer->GetDesc(&bbDesc); + pBackBuffer->Release(); + + D3D11_TEXTURE2D_DESC texDesc; + ZeroMemory(&texDesc, sizeof(texDesc)); + texDesc.Width = bbDesc.Width; + texDesc.Height = bbDesc.Height; + texDesc.MipLevels = 1; + texDesc.ArraySize = 1; + texDesc.Format = bbDesc.Format; + texDesc.SampleDesc.Count = 1; + texDesc.SampleDesc.Quality = 0; + texDesc.Usage = D3D11_USAGE_DEFAULT; + texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + hr = g_pd3dDevice->CreateTexture2D(&texDesc, NULL, &g_pGammaOffscreenTex); + if (FAILED(hr)) return false; + + hr = g_pd3dDevice->CreateShaderResourceView(g_pGammaOffscreenTex, NULL, &g_pGammaOffscreenSRV); + if (FAILED(hr)) return false; + + hr = g_pd3dDevice->CreateRenderTargetView(g_pGammaOffscreenTex, NULL, &g_pGammaOffscreenRTV); + if (FAILED(hr)) return false; + + ID3DBlob* vsBlob = NULL; + ID3DBlob* errBlob = NULL; + hr = D3DCompile(g_gammaVSCode, strlen(g_gammaVSCode), "GammaVS", NULL, NULL, "main", "vs_4_0", 0, 0, &vsBlob, &errBlob); + if (FAILED(hr)) + { + if (errBlob) errBlob->Release(); + return false; + } + hr = g_pd3dDevice->CreateVertexShader(vsBlob->GetBufferPointer(), vsBlob->GetBufferSize(), NULL, &g_pGammaVS); + vsBlob->Release(); + if (errBlob) errBlob->Release(); + if (FAILED(hr)) return false; + + errBlob = NULL; + ID3DBlob* psBlob = NULL; + hr = D3DCompile(g_gammaPSCode, strlen(g_gammaPSCode), "GammaPS", NULL, NULL, "main", "ps_4_0", 0, 0, &psBlob, &errBlob); + if (FAILED(hr)) + { + if (errBlob) errBlob->Release(); + return false; + } + hr = g_pd3dDevice->CreatePixelShader(psBlob->GetBufferPointer(), psBlob->GetBufferSize(), NULL, &g_pGammaPS); + psBlob->Release(); + if (errBlob) errBlob->Release(); + if (FAILED(hr)) return false; + + D3D11_BUFFER_DESC cbDesc; + ZeroMemory(&cbDesc, sizeof(cbDesc)); + cbDesc.ByteWidth = sizeof(GammaCBData); + cbDesc.Usage = D3D11_USAGE_DYNAMIC; + cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + GammaCBData initData = { 1.0f, {0, 0, 0} }; + D3D11_SUBRESOURCE_DATA srData; + srData.pSysMem = &initData; + srData.SysMemPitch = 0; + srData.SysMemSlicePitch = 0; + hr = g_pd3dDevice->CreateBuffer(&cbDesc, &srData, &g_pGammaCB); + if (FAILED(hr)) return false; + + D3D11_SAMPLER_DESC sampDesc; + ZeroMemory(&sampDesc, sizeof(sampDesc)); + sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; + sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; + sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; + sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + hr = g_pd3dDevice->CreateSamplerState(&sampDesc, &g_pGammaSampler); + if (FAILED(hr)) return false; + + D3D11_RASTERIZER_DESC rasDesc; + ZeroMemory(&rasDesc, sizeof(rasDesc)); + rasDesc.FillMode = D3D11_FILL_SOLID; + rasDesc.CullMode = D3D11_CULL_NONE; + rasDesc.DepthClipEnable = FALSE; + hr = g_pd3dDevice->CreateRasterizerState(&rasDesc, &g_pGammaRastState); + if (FAILED(hr)) return false; + + // Depth stencil state (disabled) + D3D11_DEPTH_STENCIL_DESC dsDesc; + ZeroMemory(&dsDesc, sizeof(dsDesc)); + dsDesc.DepthEnable = FALSE; + dsDesc.StencilEnable = FALSE; + hr = g_pd3dDevice->CreateDepthStencilState(&dsDesc, &g_pGammaDepthState); + if (FAILED(hr)) return false; + + D3D11_BLEND_DESC blendDesc; + ZeroMemory(&blendDesc, sizeof(blendDesc)); + blendDesc.RenderTarget[0].BlendEnable = FALSE; + blendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; + hr = g_pd3dDevice->CreateBlendState(&blendDesc, &g_pGammaBlendState); + if (FAILED(hr)) return false; + + g_gammaPostProcessReady = true; + return true; +} + +void ApplyGammaPostProcess() +{ + if (!g_gammaPostProcessReady) return; + + if (g_gammaValue > 0.99f && g_gammaValue < 1.01f) return; + + ID3D11DeviceContext* ctx = g_pImmediateContext; + + ID3D11Texture2D* pBackBuffer = NULL; + HRESULT hr = g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer); + if (FAILED(hr)) return; + ctx->CopyResource(g_pGammaOffscreenTex, pBackBuffer); + + D3D11_MAPPED_SUBRESOURCE mapped; + hr = ctx->Map(g_pGammaCB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped); + if (SUCCEEDED(hr)) + { + GammaCBData* cb = (GammaCBData*)mapped.pData; + cb->gamma = g_gammaValue; + ctx->Unmap(g_pGammaCB, 0); + } + + ID3D11RenderTargetView* oldRTV = NULL; + ID3D11DepthStencilView* oldDSV = NULL; + ctx->OMGetRenderTargets(1, &oldRTV, &oldDSV); + + UINT numViewports = 1; + D3D11_VIEWPORT oldViewport; + ctx->RSGetViewports(&numViewports, &oldViewport); + + ID3D11RenderTargetView* bbRTV = g_pRenderTargetView; + ctx->OMSetRenderTargets(1, &bbRTV, NULL); + + // Set viewport to full screen + D3D11_TEXTURE2D_DESC bbDesc; + pBackBuffer->GetDesc(&bbDesc); + pBackBuffer->Release(); + + D3D11_VIEWPORT vp; + vp.Width = (FLOAT)bbDesc.Width; + vp.Height = (FLOAT)bbDesc.Height; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = 0; + vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); + + ctx->IASetInputLayout(NULL); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pGammaVS, NULL, 0); + ctx->PSSetShader(g_pGammaPS, NULL, 0); + ctx->PSSetShaderResources(0, 1, &g_pGammaOffscreenSRV); + ctx->PSSetSamplers(0, 1, &g_pGammaSampler); + ctx->PSSetConstantBuffers(0, 1, &g_pGammaCB); + ctx->RSSetState(g_pGammaRastState); + ctx->OMSetDepthStencilState(g_pGammaDepthState, 0); + float blendFactor[4] = { 0, 0, 0, 0 }; + ctx->OMSetBlendState(g_pGammaBlendState, blendFactor, 0xFFFFFFFF); + + ctx->Draw(3, 0); + + ID3D11ShaderResourceView* nullSRV = NULL; + ctx->PSSetShaderResources(0, 1, &nullSRV); + + ctx->OMSetRenderTargets(1, &oldRTV, oldDSV); + ctx->RSSetViewports(1, &oldViewport); + if (oldRTV) oldRTV->Release(); + if (oldDSV) oldDSV->Release(); +} + +void CleanupGammaPostProcess() +{ + if (g_pGammaBlendState) { g_pGammaBlendState->Release(); g_pGammaBlendState = NULL; } + if (g_pGammaDepthState) { g_pGammaDepthState->Release(); g_pGammaDepthState = NULL; } + if (g_pGammaRastState) { g_pGammaRastState->Release(); g_pGammaRastState = NULL; } + if (g_pGammaSampler) { g_pGammaSampler->Release(); g_pGammaSampler = NULL; } + if (g_pGammaCB) { g_pGammaCB->Release(); g_pGammaCB = NULL; } + if (g_pGammaPS) { g_pGammaPS->Release(); g_pGammaPS = NULL; } + if (g_pGammaVS) { g_pGammaVS->Release(); g_pGammaVS = NULL; } + if (g_pGammaOffscreenRTV) { g_pGammaOffscreenRTV->Release(); g_pGammaOffscreenRTV = NULL; } + if (g_pGammaOffscreenSRV) { g_pGammaOffscreenSRV->Release(); g_pGammaOffscreenSRV = NULL; } + if (g_pGammaOffscreenTex) { g_pGammaOffscreenTex->Release(); g_pGammaOffscreenTex = NULL; } + g_gammaPostProcessReady = false; +} diff --git a/Minecraft.Client/Windows64/Windows64_PostProcess.h b/Minecraft.Client/Windows64/Windows64_PostProcess.h new file mode 100644 index 0000000..27d209c --- /dev/null +++ b/Minecraft.Client/Windows64/Windows64_PostProcess.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +bool InitGammaPostProcess(); +void ApplyGammaPostProcess(); +void CleanupGammaPostProcess(); +void SetGammaValue(float gamma);