Skip to content

Commit

Permalink
Implemented loading of baked sunlight ambient occlusion textures.
Browse files Browse the repository at this point in the history
Implemented pre-bake shader.
  • Loading branch information
jarmonik committed Nov 13, 2023
1 parent 6397e1b commit 8f77cee
Show file tree
Hide file tree
Showing 7 changed files with 171 additions and 31 deletions.
47 changes: 24 additions & 23 deletions OVP/D3D9Client/D3D9Surface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ void NatCheckFlags(DWORD &flags)
// ===============================================================================================
// Load a simple plain texture
//
LPDIRECT3DTEXTURE9 NatLoadTexture(const char* path)
LPDIRECT3DTEXTURE9 NatLoadTexture(const char* path, bool bNoMips)
{
LPDIRECT3DTEXTURE9 pTex = NULL;
D3DXIMAGE_INFO info;
Expand All @@ -70,6 +70,7 @@ LPDIRECT3DTEXTURE9 NatLoadTexture(const char* path)

if (Config->TextureMips == 2) Mips = 0; // Autogen all
if (Config->TextureMips == 1 && info.MipLevels == 1) Mips = 0; // Autogen missing
if (bNoMips) Mips = 1;

if (S_OK == D3DXCreateTextureFromFileExA(g_client->GetDevice(), path, info.Width, info.Height, Mips, 0, D3DFMT_FROM_FILE, D3DPOOL_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, &pTex))
{
Expand All @@ -85,11 +86,11 @@ LPDIRECT3DTEXTURE9 NatLoadTexture(const char* path)
// ===============================================================================================
// Load a simple plain texture with map type extension
//
LPDIRECT3DTEXTURE9 NatLoadSpecialTexture(const char* path, const char* ext)
LPDIRECT3DTEXTURE9 NatLoadSpecialTexture(const char* path, const char* ext, bool bNoMips)
{
char name[MAX_PATH];
NatCreateName(name, ARRAYSIZE(name), path, ext);
return NatLoadTexture(name);
return NatLoadTexture(name, bNoMips);
}


Expand All @@ -98,16 +99,16 @@ LPDIRECT3DTEXTURE9 NatLoadSpecialTexture(const char* path, const char* ext)
//
void NatLoadMaps(SurfNative *pNat, const char* path)
{
pNat->AddMap(MAP_HEAT, NatLoadSpecialTexture(path, "heat"));
pNat->AddMap(MAP_NORMAL, NatLoadSpecialTexture(path, "norm"));
pNat->AddMap(MAP_SPECULAR, NatLoadSpecialTexture(path, "spec"));
pNat->AddMap(MAP_EMISSION, NatLoadSpecialTexture(path, "emis"));
pNat->AddMap(MAP_ROUGHNESS, NatLoadSpecialTexture(path, "rghn"));
pNat->AddMap(MAP_METALNESS, NatLoadSpecialTexture(path, "metal"));
pNat->AddMap(MAP_REFLECTION, NatLoadSpecialTexture(path, "refl"));
pNat->AddMap(MAP_TRANSLUCENCE, NatLoadSpecialTexture(path, "transl"));
pNat->AddMap(MAP_TRANSMITTANCE, NatLoadSpecialTexture(path, "transm"));
pNat->AddMap(MAP_AMBIENT, NatLoadSpecialTexture(path, "bkao"));
pNat->AddMap(MAP_HEAT, NatLoadSpecialTexture(path, "_heat"));
pNat->AddMap(MAP_NORMAL, NatLoadSpecialTexture(path, "_norm"));
pNat->AddMap(MAP_SPECULAR, NatLoadSpecialTexture(path, "_spec"));
pNat->AddMap(MAP_EMISSION, NatLoadSpecialTexture(path, "_emis"));
pNat->AddMap(MAP_ROUGHNESS, NatLoadSpecialTexture(path, "_rghn"));
pNat->AddMap(MAP_METALNESS, NatLoadSpecialTexture(path, "_metal"));
pNat->AddMap(MAP_REFLECTION, NatLoadSpecialTexture(path, "_refl"));
pNat->AddMap(MAP_TRANSLUCENCE, NatLoadSpecialTexture(path, "_transl"));
pNat->AddMap(MAP_TRANSMITTANCE, NatLoadSpecialTexture(path, "_transm"));
pNat->AddMap(MAP_AMBIENT, NatLoadSpecialTexture(path, "_bkao"));
}


Expand Down Expand Up @@ -1067,15 +1068,15 @@ void SurfNative::Reload()
if (S_OK == D3DXCreateTextureFromFileExA(g_client->GetDevice(), path, info.Width, info.Height, Mips, 0,
D3DFMT_FROM_FILE, D3DPOOL_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, (LPDIRECT3DTEXTURE9 *)&pResource))
{
AddMap(MAP_HEAT, NatLoadSpecialTexture(name, "heat"));
AddMap(MAP_NORMAL, NatLoadSpecialTexture(name, "norm"));
AddMap(MAP_SPECULAR, NatLoadSpecialTexture(name, "spec"));
AddMap(MAP_EMISSION, NatLoadSpecialTexture(name, "emis"));
AddMap(MAP_ROUGHNESS, NatLoadSpecialTexture(name, "rghn"));
AddMap(MAP_METALNESS, NatLoadSpecialTexture(name, "metal"));
AddMap(MAP_REFLECTION, NatLoadSpecialTexture(name, "refl"));
AddMap(MAP_TRANSLUCENCE, NatLoadSpecialTexture(name, "transl"));
AddMap(MAP_TRANSMITTANCE, NatLoadSpecialTexture(name, "transm"));
AddMap(MAP_HEAT, NatLoadSpecialTexture(name, "_heat"));
AddMap(MAP_NORMAL, NatLoadSpecialTexture(name, "_norm"));
AddMap(MAP_SPECULAR, NatLoadSpecialTexture(name, "_spec"));
AddMap(MAP_EMISSION, NatLoadSpecialTexture(name, "_emis"));
AddMap(MAP_ROUGHNESS, NatLoadSpecialTexture(name, "_rghn"));
AddMap(MAP_METALNESS, NatLoadSpecialTexture(name, "_metal"));
AddMap(MAP_REFLECTION, NatLoadSpecialTexture(name, "_refl"));
AddMap(MAP_TRANSLUCENCE, NatLoadSpecialTexture(name, "_transl"));
AddMap(MAP_TRANSMITTANCE, NatLoadSpecialTexture(name, "_transm"));
}
}
}
Expand Down Expand Up @@ -1182,7 +1183,7 @@ bool NatCreateName(char* out, int mlen, const char* fname, const char* id)
char* p = strrchr(buffe, '.');
if (p != NULL) {
*p = '\0';
sprintf_s(out, mlen, "%s_%s.%s", buffe, id, ++p);
sprintf_s(out, mlen, "%s%s.%s", buffe, id, ++p);
}
return (p != NULL);
}
Expand Down
3 changes: 2 additions & 1 deletion OVP/D3D9Client/D3D9Surface.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@

#define OAPISURF_SKP_GDI_WARN 0x00000001

LPDIRECT3DTEXTURE9 NatLoadSpecialTexture(const char* fname, const char* ext);
LPDIRECT3DTEXTURE9 NatLoadTexture(const char* path, bool bNoMips = false);
LPDIRECT3DTEXTURE9 NatLoadSpecialTexture(const char* fname, const char* ext, bool bNoMips = false);
SURFHANDLE NatLoadSurface(const char* file, DWORD flags, bool bPath = false);
bool NatSaveSurface(const char* file, LPDIRECT3DRESOURCE9 pResource);
SURFHANDLE NatCreateSurface(int width, int height, DWORD flags);
Expand Down
127 changes: 121 additions & 6 deletions OVP/D3D9Client/Mesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,8 @@ void D3D9Mesh::Null(const char *meshName /* = NULL */)
bMtrlModidied = false;
bMustRebake = true;

bli = BakedLights.begin();

Locals = new LightStruct[Config->MaxLights()];

for (int i = 0; i < SHM_CASCADE_COUNT; i++) {
Expand Down Expand Up @@ -399,6 +401,13 @@ void D3D9Mesh::Release()
SAFE_DELETEA(pGrpTF);

if (pBuf) if (pBuf->IsLocalTo(this)) delete pBuf;

for (auto x : BakedLights) {
for (auto y : x.second.pMap) SAFE_RELEASE(y);
for (auto y : x.second.pSunAO) SAFE_RELEASE(y);
SAFE_RELEASE(x.second.pCombined);
SAFE_RELEASE(x.second.pSunAOComb);
}
}


Expand Down Expand Up @@ -465,6 +474,40 @@ void D3D9Mesh::ReLoadMeshFromHandle(MESHHANDLE hMesh)
pBuf->Map(pDev);
}

// ===========================================================================================
//
const char* D3D9Mesh::GetDirName(int i, int v)
{
static const char* names[] = { "up", "down", "left", "right", "fwd", "aft" };
static const char* named[] = { "+y", "-y", "-x", "+x", "+z", "-z" };
if (v == 0) return names[i];
return named[i];
}

// ===========================================================================================
//
FVECTOR3 D3D9Mesh::GetDir(int i)
{
switch (i) {
case 0: return FVECTOR3(0, 1, 0); // Up
case 1: return FVECTOR3(0, -1, 0); // Down
case 2: return FVECTOR3(-1, 0, 0); // Left
case 3: return FVECTOR3( 1, 0, 0); // Right
case 4: return FVECTOR3(0, 0, 1); // Fwd
case 5: return FVECTOR3(0, 0, -1); // Aft
}
return FVECTOR3(0, 0, 1);
}

// ===========================================================================================
//
void D3D9Mesh::ClearBake(int i)
{
for (int k = 0; k < 16; k++) BakedLights[i].pMap[k] = NULL;
for (int k = 0; k < 6; k++) BakedLights[i].pSunAO[k] = NULL;
BakedLights[i].pCombined = NULL;
BakedLights[i].pSunAOComb = NULL;
}

// ===========================================================================================
//
Expand All @@ -473,32 +516,53 @@ void D3D9Mesh::LoadBakedLights()
if (BakedLights.size()) return; // Already Loaded, skip the rest

bMustRebake = true;
char id[8];
char id[32];

for (int i = 0; i < nTex; i++)
{
if (!Tex[i]) continue; // No base texture, pick next

for (int j = 0; j < 16; j++)
{
sprintf_s(id, "bkl%d", j);
LPDIRECT3DTEXTURE9 pTex = NatLoadSpecialTexture(Tex[i]->GetPath(), id);
sprintf_s(id, "_bkl%d", j);
LPDIRECT3DTEXTURE9 pTex = NatLoadSpecialTexture(Tex[i]->GetPath(), id, true);
if (pTex) {
if (BakedLights.find(i) == BakedLights.end()) for (int k = 0; k < 16; k++) BakedLights[i].pMap[k] = NULL;
if (BakedLights.find(i) == BakedLights.end()) ClearBake(i);
BakedLights[i].pMap[j] = pTex;
}
}

for (int j = 0; j < 6; j++)
{
sprintf_s(id, " baked sunlight %s", GetDirName(j, 0));
LPDIRECT3DTEXTURE9 pTex = NatLoadSpecialTexture(Tex[i]->GetPath(), id, true);
if (pTex) {
if (BakedLights.find(i) == BakedLights.end()) ClearBake(i);
BakedLights[i].pSunAO[j] = pTex;
}
else {
sprintf_s(id, "_bs%s", GetDirName(j, 1));
LPDIRECT3DTEXTURE9 pTex = NatLoadSpecialTexture(Tex[i]->GetPath(), id, true);
if (pTex) {
if (BakedLights.find(i) == BakedLights.end()) ClearBake(i);
BakedLights[i].pSunAO[j] = pTex;
}
}
}
}

// Construct render surface for all combined maps
for (auto& a : BakedLights) {
int i = a.first;
if (Tex[i]) {
HR(D3DXCreateTexture(pDev, Tex[i]->GetWidth(), Tex[i]->GetHeight(), 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &a.second.pCombined));
HR(D3DXCreateTexture(pDev, Tex[i]->GetWidth(), Tex[i]->GetHeight(), 0, D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &a.second.pCombined));
HR(D3DXCreateTexture(pDev, Tex[i]->GetWidth(), Tex[i]->GetHeight(), 0, D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &a.second.pSunAOComb));
}
}

for (int i = 0; i < 16; i++) BakedLightsControl[i] = FVECTOR3(0.5, 0.5, 0.5);
for (int i = 0; i < 16; i++) BakedLightsControl[i] = FVECTOR3(1.0f, 1.0f, 1.0f);

bli = BakedLights.begin();
}


Expand Down Expand Up @@ -563,6 +627,57 @@ void D3D9Mesh::BakeLights(ImageProcessing* pBaker)
}


// ===========================================================================================
//
void D3D9Mesh::BakeAO(ImageProcessing* pBaker, const FVECTOR3 &vSun)
{
if (!pBaker->IsOK()) return; // Baker not initialized
if (DefShader != SHADER_BAKED_VC) return; // Not supported by shader
if (BakedLights.size() == 0) return; // Nothing to bake

DWORD flags = IPF_POINT | IPF_CLAMP;
FVECTOR3 control[6];
bool bSE[6];

pBaker->Activate("PSSunAO");

for (int i = 0; i < 6; i++)
{
auto y = bli->second.pSunAO[i];
bSE[i] = (y != NULL);
if (y)
{
pBaker->SetTextureNative(i, y, flags);
control[i] = saturate(dot(GetDir(i), vSun));
control[i] *= control[i];
if (i == 4) D3D9DebugLog("Fwd %f", control[i].x);
if (i == 0) D3D9DebugLog("Up %f", control[i].x);
}
else {
control[i] = 0.0f;
}
}

pBaker->SetFloat("fControl", control, sizeof(control));
pBaker->SetBool("bEnabled", bSE, sizeof(bSE));

LPDIRECT3DSURFACE9 pSrf = NULL;

if (bli->second.pSunAOComb)
{
if (bli->second.pSunAOComb->GetSurfaceLevel(0, &pSrf) == S_OK)
{
pBaker->SetOutputNative(0, pSrf);
pBaker->Execute(true);
SAFE_RELEASE(pSrf);
}
}

bli++;
if (bli == BakedLights.end()) bli = BakedLights.begin();
}


// ===========================================================================================
//
LPDIRECT3DTEXTURE9 D3D9Mesh::GetCombinedMap(int tex_idx)
Expand Down
8 changes: 7 additions & 1 deletion OVP/D3D9Client/Mesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,9 @@ struct _LightList {

struct _BakedLights {
LPDIRECT3DTEXTURE9 pMap[16];
LPDIRECT3DTEXTURE9 pSunAO[6];
LPDIRECT3DTEXTURE9 pCombined;
LPDIRECT3DTEXTURE9 pSunAOComb;
};

class MeshShader : public ShaderClass
Expand Down Expand Up @@ -209,9 +211,10 @@ class D3D9Mesh : private D3D9Effect
bool IsOK() const { return pBuf != NULL; }

void Release();

void ClearBake(int i);
void LoadBakedLights();
void BakeLights(ImageProcessing *pBaker);
void BakeAO(ImageProcessing* pBaker, const FVECTOR3 &vSun);
void SetBakedLightLevel(int idx, const FVECTOR3 &level);
void LoadMeshFromHandle(MESHHANDLE hMesh, D3DXVECTOR3 *reorig = NULL, float *scale = NULL);
void ReLoadMeshFromHandle(MESHHANDLE hMesh);
Expand All @@ -220,6 +223,8 @@ class D3D9Mesh : private D3D9Effect
void SetName(const char *name);
void SetName(UINT idx);
const char * GetName() const { return name; }
const char * GetDirName(int i, int v);
FVECTOR3 GetDir(int i);

void SetDefaultShader(WORD shader);
WORD GetDefaultShader() const { return DefShader; }
Expand Down Expand Up @@ -364,6 +369,7 @@ class D3D9Mesh : private D3D9Effect
D3D9MatExt *Mtrl; // list of mesh materials
SurfNative **Tex; // list of mesh textures
std::map<int, _BakedLights> BakedLights;
std::map<int, _BakedLights>::const_iterator bli;
FVECTOR3 BakedLightsControl[16];
D3DXMATRIX mTransform;
D3DXMATRIX mTransformInv;
Expand Down
1 change: 1 addition & 0 deletions OVP/D3D9Client/Scene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,7 @@ Scene::Scene(D3D9Client *_gc, DWORD w, DWORD h)
}

pBakeLights = new ImageProcessing(pDevice, "Modules/D3D9Client/PreBakeLights.hlsl", "PSMain");
pBakeLights->CompileShader("PSSunAO");

LogAlw("================ Scene Created ===============");
}
Expand Down
2 changes: 2 additions & 0 deletions OVP/D3D9Client/VVessel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -679,7 +679,9 @@ void vVessel::BakeLights(ImageProcessing *pBaker)
if (!meshlist[i].mesh) continue;
if (meshlist[i].vismode & MESHVIS_VC)
{
auto vSun = tmul(FVECTOR4(sundir, 0), oapi::FMATRIX4(mWorld));
meshlist[i].mesh->BakeLights(pBaker);
meshlist[i].mesh->BakeAO(pBaker, vSun.xyz);
}
}
}
Expand Down
14 changes: 14 additions & 0 deletions OVP/D3D9Client/shaders/PreBakeLights.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

uniform extern float3 fControl[16];
uniform extern int iCount;
uniform extern bool bEnabled[6];

sampler tMap[16] : register(s0);

Expand All @@ -27,3 +28,16 @@ float4 PSMain(float x : TEXCOORD0, float y : TEXCOORD1) : COLOR
[unroll] for (int i = 0; i < iCount; i++) color += tex2D(tMap[i], float2(x, y)).rgb * fControl[i];
return float4(LightFX(color), 1.0f);
}

// Combine multiple baked lightmaps into a single map
//
float4 PSSunAO(float x : TEXCOORD0, float y : TEXCOORD1) : COLOR
{
float3 color = 0;
[unroll] for (int i = 0; i < 6; i++) {
if (bEnabled[i]) {
color += tex2D(tMap[i], float2(x, y)).rgb * fControl[i];
}
}
return float4(LightFX(color), 1.0f);
}

0 comments on commit 8f77cee

Please sign in to comment.