Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix sun and lens flares #37

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions DSfix.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL</PreprocessorDefinitions>
</ClCompile>
<ClCompile Include="d3d9query.cpp" />
<ClCompile Include="d3dutil.cpp" />
<ClCompile Include="Detouring.cpp" />
<ClCompile Include="dinputWrapper.cpp" />
Expand Down Expand Up @@ -313,6 +314,7 @@
<ItemGroup>
<ClInclude Include="AreaTex.h" />
<ClInclude Include="d3d9.h" />
<ClInclude Include="d3d9query.h" />
<ClInclude Include="d3dutil.h" />
<ClInclude Include="Detouring.h" />
<ClInclude Include="dinput.h" />
Expand Down
172 changes: 165 additions & 7 deletions RenderstateManager.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "RenderstateManager.h"

#include <atlbase.h>
#include <time.h>
#include <intsafe.h>
#include <io.h>
Expand All @@ -15,15 +16,28 @@

RSManager RSManager::instance;

static const char *PIXEL_SHADER_DUMP_DIR = "dsfix/pixelshader_dump";
static const char *PIXEL_SHADER_OVERRIDE_DIR = "dsfix/pixelshader_override";
static const char *VERTEX_SHADER_DUMP_DIR = "dsfix/vertexshader_dump";
static const char *VERTEX_SHADER_OVERRIDE_DIR = "dsfix/vertexshader_override";
namespace {
const char *PIXEL_SHADER_DUMP_DIR = "dsfix/pixelshader_dump";
const char *PIXEL_SHADER_OVERRIDE_DIR = "dsfix/pixelshader_override";
const char *VERTEX_SHADER_DUMP_DIR = "dsfix/vertexshader_dump";
const char *VERTEX_SHADER_OVERRIDE_DIR = "dsfix/vertexshader_override";

unsigned getDOFResolution() {
unsigned setting = Settings::get().getDOFOverrideResolution();
if (setting == 0) {
return 360;
} else {
return setting;
}
}
}

void RSManager::initResources() {
SDLOG(0, "RenderstateManager resource initialization started\n");
unsigned rw = Settings::get().getRenderWidth(), rh = Settings::get().getRenderHeight();
unsigned dofRes = Settings::get().getDOFOverrideResolution();
haveOcclusionScale = false;
occlusionScale = 1;
unsigned dofRes = getDOFResolution();
if(Settings::get().getAAQuality()) {
if(Settings::get().getAAType() == "SMAA") {
smaa = new SMAA(d3ddev, rw, rh, (SMAA::Preset)(Settings::get().getAAQuality()-1));
Expand Down Expand Up @@ -278,6 +292,9 @@ HRESULT RSManager::redirectSetRenderTarget(DWORD RenderTargetIndex, IDirect3DSur
// store it for later use
mainRT = pRenderTarget;
SDLOG(0, "Storing RT as main RT: %p\n", mainRT);
if (!haveOcclusionScale) {
measureOcclusionScale();
}
}

if(nrts == 11) { // we are switching to the RT used to store the Z value in the 24 RGB bits (among other things)
Expand Down Expand Up @@ -430,6 +447,147 @@ HRESULT RSManager::redirectSetRenderTarget(DWORD RenderTargetIndex, IDirect3DSur
return d3ddev->SetRenderTarget(RenderTargetIndex, pRenderTarget);
}

// Measure the occlusion query result of drawing a square of a known
// size.
//
// The result is affected by the rendering resolution which is
// known, but might also be affected by driver-enforced antialiasing.
// This result is used to scale the result of further occlusion
// queries into the expected range of values.
void RSManager::measureOcclusionScale() {
static const D3DVERTEXELEMENT9 vertexElements[2] = {
{ 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
D3DDECL_END()
};
CComPtr<IDirect3DVertexDeclaration9> vertexDeclaration;
CComPtr<ID3DXBuffer> errorBuffer;
static const char vertexShaderSource[] = "vs_3_0 \n dcl_position v0 \n dcl_position o0 \n mov o0, v0";
CComPtr<ID3DXBuffer> vertexShaderBuffer;
CComPtr<IDirect3DVertexShader9> vertexShader;
static const char pixelShaderSource[] = "ps_3_0 \n def c0, 0, 0, 0, 0 \n mov_pp oC0, c0.x";
CComPtr<ID3DXBuffer> pixelShaderBuffer;
CComPtr<IDirect3DPixelShader9> pixelShader;
CComPtr<IDirect3DQuery9> query;
DWORD pixelsVisible = 0;
HRESULT hr;

haveOcclusionScale = true;

float width = 24.0 / 1024;
float height = 24.0 / 720;
const float vertexData[4][3] = {
{ -width, -height, 0.5 },
{ width, -height, 0.5 },
{ width, height, 0.5 },
{ -width, height, 0.5 },
};

if (FAILED(d3ddev->Clear(0, nullptr, D3DCLEAR_TARGET, 0, 1, 0))) {
SDLOG(0, "measureOcclusionScale: Clear failed\n");
return;
}

if (FAILED(d3ddev->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE))) {
SDLOG(0, "measureOcclusionScale: SetRenderState ZENABLE failed\n");
return;
}

if (FAILED(d3ddev->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL))) {
SDLOG(0, "measureOcclusionScale: SetRenderState ZFUNC failed\n");
return;
}

if (FAILED(d3ddev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE))) {
SDLOG(0, "measureOcclusionScale: SetRenderState CULLMODE failed\n");
return;
}

if (FAILED(d3ddev->CreateVertexDeclaration(vertexElements, &vertexDeclaration))) {
SDLOG(0, "measureOcclusionScale: CreateVertexDeclaration failed\n");
return;
}

if (FAILED(d3ddev->SetVertexDeclaration(vertexDeclaration))) {
SDLOG(0, "measureOcclusionScale: SetVertexDeclaration failed\n");
return;
}

if (FAILED(D3DXAssembleShader(vertexShaderSource, sizeof(vertexShaderSource), nullptr, nullptr, 0, &vertexShaderBuffer, &errorBuffer))) {
SDLOG(0, "measureOcclusionScale: D3DXAssembleShader failed:\n%s\n", errorBuffer->GetBufferPointer());
return;
}

if (FAILED(d3ddev->CreateVertexShader(reinterpret_cast<const DWORD*>(vertexShaderBuffer->GetBufferPointer()), &vertexShader))) {
SDLOG(0, "measureOcclusionScale: CreateVertexShader failed\n");
return;
}

if (FAILED(d3ddev->SetVertexShader(vertexShader))) {
SDLOG(0, "measureOcclusionScale: SetVertexShader failed\n");
return;
}

if (FAILED(D3DXAssembleShader(pixelShaderSource, sizeof(pixelShaderSource), nullptr, nullptr, 0, &pixelShaderBuffer, &errorBuffer))) {
SDLOG(0, "measureOcclusionScale: D3DXAssembleShader failed:\n%s\n", errorBuffer->GetBufferPointer());
return;
}

if (FAILED(d3ddev->CreatePixelShader(reinterpret_cast<const DWORD*>(pixelShaderBuffer->GetBufferPointer()), &pixelShader))) {
SDLOG(0, "measureOcclusionScale: CreatePixelShader failed\n");
return;
}

if (FAILED(d3ddev->SetPixelShader(pixelShader))) {
SDLOG(0, "measureOcclusionScale: SetPixelShader failed\n");
return;
}

if (FAILED(d3ddev->CreateQuery(D3DQUERYTYPE_OCCLUSION, &query))) {
SDLOG(0, "measureOcclusionScale: CreateQuery failed\n");
return;
}

if (FAILED(d3ddev->BeginScene())) {
SDLOG(0, "measureOcclusionScale: BeginScene failed\n");
return;
}

if (FAILED(query->Issue(D3DISSUE_BEGIN))) {
SDLOG(0, "measureOcclusionScale: Issue BEGIN failed\n");
return;
}

if (FAILED(d3ddev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, vertexData, sizeof(vertexData[0])))) {
SDLOG(0, "measureOcclusionScale: DrawPrimitiveUP failed\n");
return;
}

if (FAILED(query->Issue(D3DISSUE_END))) {
SDLOG(0, "measureOcclusionScale: Issue END failed\n");
return;
}

while ((hr = query->GetData(&pixelsVisible, sizeof(pixelsVisible), D3DGETDATA_FLUSH)) == S_FALSE);
if (FAILED(hr)) {
SDLOG(0, "measureOcclusionScale: GetData failed\n");
return;
}

if (pixelsVisible == 0) {
occlusionScale = 1;
} else {
occlusionScale = pixelsVisible / 576.0;
}

SDLOG(2, "measureOcclusionScale: pixelsVisible = %d\n", pixelsVisible);
SDLOG(2, "measureOcclusionScale: occlusionScale = %f\n", occlusionScale);

if (FAILED(d3ddev->EndScene())) {
SDLOG(0, "measureOcclusionScale: EndScene failed\n");
return;
}
}

HRESULT RSManager::redirectStretchRect(IDirect3DSurface9* pSourceSurface, CONST RECT* pSourceRect, IDirect3DSurface9* pDestSurface, CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) {
//SurfSurfMap::iterator it = renderTexSurfTargets.find(pSourceSurface);
//if(it != renderTexSurfTargets.end()) {
Expand Down Expand Up @@ -581,7 +739,7 @@ void RSManager::reloadScao() {

void RSManager::reloadGauss() {
SAFEDELETE(gauss);
gauss = new GAUSS(d3ddev, Settings::get().getDOFOverrideResolution()*16/9, Settings::get().getDOFOverrideResolution());
gauss = new GAUSS(d3ddev, getDOFResolution()*16/9, getDOFResolution());
SDLOG(0, "Reloaded GAUSS\n");
}

Expand Down Expand Up @@ -754,7 +912,7 @@ bool RSManager::isTextureText(IDirect3DBaseTexture9* t) {
}

unsigned RSManager::isDof(unsigned width, unsigned height) {
unsigned topWidth = Settings::get().getDOFOverrideResolution()*16/9, topHeight = Settings::get().getDOFOverrideResolution();
unsigned topWidth = getDOFResolution()*16/9, topHeight = getDOFResolution();
if(width == topWidth && height == topHeight) return 1;
if(width == topWidth/2 && height == topHeight/2) return 2;
return 0;
Expand Down
9 changes: 8 additions & 1 deletion RenderstateManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,11 @@ class RSManager {
void dumpShader(UINT32 hash, const char *directory, LPD3DXBUFFER pBuffer);
bool getOverrideShader(UINT32 hash, const char *directory, LPD3DXBUFFER *ppBuffer);

bool haveOcclusionScale;
float occlusionScale;

void measureOcclusionScale();

private:
~RSManager();

Expand All @@ -127,7 +132,7 @@ class RSManager {

RSManager() : smaa(NULL), fxaa(NULL), ssao(NULL), gauss(NULL), rgbaBuffer1Surf(NULL), rgbaBuffer1Tex(NULL),
inited(false), doAA(true), doSsao(true), doDofGauss(true), doHud(true), captureNextFrame(false), capturing(false), hudStarted(false), takeScreenshot(false), hideHud(false),
mainRenderTexIndex(0), mainRenderSurfIndex(0), dumpCaptureIndex(0), numKnownTextures(0), foundKnownTextures(0), skippedPresents(0) {
mainRenderTexIndex(0), mainRenderSurfIndex(0), dumpCaptureIndex(0), numKnownTextures(0), foundKnownTextures(0), skippedPresents(0), haveOcclusionScale(false), occlusionScale(1) {
#define TEXTURE(_name, _hash) ++numKnownTextures;
#include "Textures.def"
#undef TEXTURE
Expand Down Expand Up @@ -195,4 +200,6 @@ class RSManager {
HRESULT redirectSetRenderState(D3DRENDERSTATETYPE State, DWORD Value);
HRESULT redirectCreatePixelShader(CONST DWORD *pfunction, IDirect3DPixelShader9 **ppShader);
HRESULT redirectCreateVertexShader(CONST DWORD *pfunction, IDirect3DVertexShader9 **ppShader);

float getOcclusionScale() const { return occlusionScale; }
};
1 change: 1 addition & 0 deletions d3d9.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@
#include <d3dx9.h>
#include "d3d9int.h"
#include "d3d9dev.h"
#include "d3d9query.h"

IDirect3D9 *APIENTRY hkDirect3DCreate9(UINT SDKVersion);
7 changes: 6 additions & 1 deletion d3d9dev.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,12 @@ HRESULT APIENTRY hkIDirect3DDevice9::CreatePixelShader(CONST DWORD* pFunction,ID
}

HRESULT APIENTRY hkIDirect3DDevice9::CreateQuery(D3DQUERYTYPE Type,IDirect3DQuery9** ppQuery) {
return m_pD3Ddev->CreateQuery(Type, ppQuery);
auto result = m_pD3Ddev->CreateQuery(Type, ppQuery);
if (Type == D3DQUERYTYPE_OCCLUSION && result == D3D_OK) {
new hkIDirect3DQuery9(ppQuery);
// These instances will leak, but there are only a set number of them created
}
return result;
}

HRESULT APIENTRY hkIDirect3DDevice9::CreateRenderTarget(UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Lockable, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle) {
Expand Down
46 changes: 46 additions & 0 deletions d3d9query.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#include "d3d9.h"
#include "main.h"
#include "RenderstateManager.h"
#include "Settings.h"

hkIDirect3DQuery9::hkIDirect3DQuery9(IDirect3DQuery9 **ppReturnedQueryInterface) {
m_pD3Dquery = *ppReturnedQueryInterface;
*ppReturnedQueryInterface = this;
}

HRESULT APIENTRY hkIDirect3DQuery9::QueryInterface(REFIID riid, void** ppvObj) {
return m_pD3Dquery->QueryInterface(riid, ppvObj);
}

ULONG APIENTRY hkIDirect3DQuery9::AddRef() {
return m_pD3Dquery->AddRef();
}

ULONG APIENTRY hkIDirect3DQuery9::Release() {
return m_pD3Dquery->Release();
}

HRESULT APIENTRY hkIDirect3DQuery9::GetDevice(IDirect3DDevice9** ppDevice) {
return m_pD3Dquery->GetDevice(ppDevice);
}

D3DQUERYTYPE APIENTRY hkIDirect3DQuery9::GetType() {
return m_pD3Dquery->GetType();
}

DWORD APIENTRY hkIDirect3DQuery9::GetDataSize() {
return m_pD3Dquery->GetDataSize();
}

HRESULT APIENTRY hkIDirect3DQuery9::Issue(DWORD dwIssueFlags) {
return m_pD3Dquery->Issue(dwIssueFlags);
}

HRESULT APIENTRY hkIDirect3DQuery9::GetData(void* pData, DWORD dwSize, DWORD dwGetDataFlags) {
auto result = m_pD3Dquery->GetData(pData, dwSize, dwGetDataFlags);
if (SUCCEEDED(result)) {
auto pixelsDrawn = reinterpret_cast<DWORD*>(pData);
pixelsDrawn[0] = static_cast<DWORD>(pixelsDrawn[0] / RSManager::get().getOcclusionScale());
}
return result;
}
19 changes: 19 additions & 0 deletions d3d9query.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#pragma once

#include "d3d9.h"

interface hkIDirect3DQuery9 : public IDirect3DQuery9
{
hkIDirect3DQuery9(IDirect3DQuery9 **ppReturnedQueryInterface);

IDirect3DQuery9* m_pD3Dquery;

STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj);
STDMETHOD_(ULONG, AddRef)(THIS);
STDMETHOD_(ULONG, Release)(THIS);
STDMETHOD(GetDevice)(THIS_ IDirect3DDevice9** ppDevice);
STDMETHOD_(D3DQUERYTYPE, GetType)(THIS);
STDMETHOD_(DWORD, GetDataSize)(THIS);
STDMETHOD(Issue)(THIS_ DWORD dwIssueFlags);
STDMETHOD(GetData)(THIS_ void* pData, DWORD dwSize, DWORD dwGetDataFlags);
};