mirror of
https://github.com/XProger/OpenLara.git
synced 2025-08-15 09:34:18 +02:00
#15 D3D9 WIP, port some shaders, handle device reset & lost
This commit is contained in:
@@ -84,6 +84,7 @@ struct ShaderCache {
|
||||
void prepareShadows(int fx) {
|
||||
compile(Core::passShadow, Shader::ENTITY, fx, rsShadow);
|
||||
compile(Core::passShadow, Shader::ENTITY, fx, rsShadow | RS_DISCARD);
|
||||
compile(Core::passShadow, Shader::MIRROR, fx, rsShadow);
|
||||
}
|
||||
|
||||
void prepareWater(int fx) {
|
||||
@@ -169,7 +170,7 @@ struct ShaderCache {
|
||||
#undef SD_ADD
|
||||
|
||||
LOG("shader: %s(%d) %s%s%s\n", Core::passNames[pass], type, (fx & FX_UNDERWATER) ? "u" : "", (fx & FX_ALPHA_TEST) ? "a" : "", (fx & FX_CLIP_PLANE) ? "c" : "");
|
||||
return shaders[pass][type][fx] = new Shader(pass, def, defCount);
|
||||
return shaders[pass][type][fx] = new Shader(pass, type, def, defCount);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
@@ -233,7 +234,7 @@ struct AmbientCache {
|
||||
// init downsample textures
|
||||
for (int j = 0; j < 6; j++)
|
||||
for (int i = 0; i < 4; i++)
|
||||
textures[j * 4 + i] = new Texture(64 >> (i << 1), 64 >> (i << 1), FMT_RGBA, false);
|
||||
textures[j * 4 + i] = new Texture(64 >> (i << 1), 64 >> (i << 1), FMT_RGBA, OPT_TARGET | OPT_NEAREST);
|
||||
}
|
||||
|
||||
~AmbientCache() {
|
||||
@@ -277,7 +278,7 @@ struct AmbientCache {
|
||||
for (int i = 1; i < 4; i++) {
|
||||
int size = 64 >> (i << 1);
|
||||
|
||||
Core::active.shader->setParam(uParam, vec4(float(size << 2), 0.0f, 0.0f, 0.0f));
|
||||
Core::active.shader->setParam(uParam, vec4(1.0f / (size << 2), 0.0f, 0.0f, 0.0f));
|
||||
|
||||
for (int j = 0; j < 6; j++) {
|
||||
Texture *src = textures[j * 4 + i - 1];
|
||||
@@ -300,6 +301,7 @@ struct AmbientCache {
|
||||
|
||||
void processQueue() {
|
||||
game->setupBinding();
|
||||
|
||||
for (int i = 0; i < tasksCount; i++) {
|
||||
Task &task = tasks[i];
|
||||
|
||||
|
@@ -122,6 +122,7 @@ struct Lock {
|
||||
|
||||
#define OS_LOCK(mutex) Lock _lock(mutex)
|
||||
|
||||
/*
|
||||
extern void* osRWLockInit ();
|
||||
extern void osRWLockFree (void *obj);
|
||||
extern void osRWLockRead (void *obj);
|
||||
@@ -156,6 +157,7 @@ struct LockWrite {
|
||||
|
||||
#define OS_LOCK_READ(rwLock) LockRead _rLock(rwLock)
|
||||
#define OS_LOCK_WRITE(rwLock) LockWrite _wLock(rwLock)
|
||||
*/
|
||||
|
||||
enum InputKey { ikNone,
|
||||
// keyboard
|
||||
@@ -926,9 +928,9 @@ namespace Core {
|
||||
validateRenderState();
|
||||
}
|
||||
|
||||
void beginFrame() {
|
||||
bool beginFrame() {
|
||||
Core::stats.start();
|
||||
GAPI::beginFrame();
|
||||
return GAPI::beginFrame();
|
||||
}
|
||||
|
||||
void endFrame() {
|
||||
|
22
src/game.h
22
src/game.h
@@ -169,11 +169,14 @@ namespace Game {
|
||||
return true;
|
||||
}
|
||||
|
||||
void frameBegin() {
|
||||
if (Core::settings.version == SETTINGS_READING) return;
|
||||
bool frameBegin() {
|
||||
if (Core::settings.version == SETTINGS_READING) return false;
|
||||
Core::reset();
|
||||
Core::beginFrame();
|
||||
level->renderPrepare();
|
||||
if (Core::beginFrame()) {
|
||||
level->renderPrepare();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void frameRender() {
|
||||
@@ -195,10 +198,13 @@ namespace Game {
|
||||
Core::endFrame();
|
||||
}
|
||||
|
||||
void render() {
|
||||
frameBegin();
|
||||
frameRender();
|
||||
frameEnd();
|
||||
bool render() {
|
||||
if (frameBegin()) {
|
||||
frameRender();
|
||||
frameEnd();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
362
src/gapi_d3d9.h
362
src/gapi_d3d9.h
@@ -8,12 +8,54 @@
|
||||
#define PROFILE_LABEL(id, name, label)
|
||||
#define PROFILE_TIMING(time)
|
||||
|
||||
extern LPDIRECT3D9 D3D;
|
||||
extern LPDIRECT3DDEVICE9 device;
|
||||
extern LPDIRECT3D9 D3D;
|
||||
extern LPDIRECT3DDEVICE9 device;
|
||||
extern D3DPRESENT_PARAMETERS d3dpp;
|
||||
|
||||
#ifdef _DEBUG
|
||||
void D3DCHECK(HRESULT res) {
|
||||
if (res == D3D_OK) return;
|
||||
|
||||
LOG("! ");
|
||||
switch (res) {
|
||||
case D3DERR_WRONGTEXTUREFORMAT : LOG("D3DERR_WRONGTEXTUREFORMAT"); break;
|
||||
case D3DERR_UNSUPPORTEDCOLOROPERATION : LOG("D3DERR_UNSUPPORTEDCOLOROPERATION"); break;
|
||||
case D3DERR_UNSUPPORTEDCOLORARG : LOG("D3DERR_UNSUPPORTEDCOLORARG"); break;
|
||||
case D3DERR_UNSUPPORTEDALPHAOPERATION : LOG("D3DERR_UNSUPPORTEDALPHAOPERATION"); break;
|
||||
case D3DERR_UNSUPPORTEDALPHAARG : LOG("D3DERR_UNSUPPORTEDALPHAARG"); break;
|
||||
case D3DERR_TOOMANYOPERATIONS : LOG("D3DERR_TOOMANYOPERATIONS"); break;
|
||||
case D3DERR_CONFLICTINGTEXTUREFILTER : LOG("D3DERR_CONFLICTINGTEXTUREFILTER"); break;
|
||||
case D3DERR_UNSUPPORTEDFACTORVALUE : LOG("D3DERR_UNSUPPORTEDFACTORVALUE"); break;
|
||||
case D3DERR_CONFLICTINGRENDERSTATE : LOG("D3DERR_CONFLICTINGRENDERSTATE"); break;
|
||||
case D3DERR_UNSUPPORTEDTEXTUREFILTER : LOG("D3DERR_UNSUPPORTEDTEXTUREFILTER"); break;
|
||||
case D3DERR_CONFLICTINGTEXTUREPALETTE : LOG("D3DERR_CONFLICTINGTEXTUREPALETTE"); break;
|
||||
case D3DERR_DRIVERINTERNALERROR : LOG("D3DERR_DRIVERINTERNALERROR"); break;
|
||||
case D3DERR_NOTFOUND : LOG("D3DERR_NOTFOUND"); break;
|
||||
case D3DERR_MOREDATA : LOG("D3DERR_MOREDATA"); break;
|
||||
case D3DERR_DEVICELOST : LOG("D3DERR_DEVICELOST"); break;
|
||||
case D3DERR_DEVICENOTRESET : LOG("D3DERR_DEVICENOTRESET"); break;
|
||||
case D3DERR_NOTAVAILABLE : LOG("D3DERR_NOTAVAILABLE"); break;
|
||||
case D3DERR_OUTOFVIDEOMEMORY : LOG("D3DERR_OUTOFVIDEOMEMORY"); break;
|
||||
case D3DERR_INVALIDDEVICE : LOG("D3DERR_INVALIDDEVICE"); break;
|
||||
case D3DERR_INVALIDCALL : LOG("D3DERR_INVALIDCALL"); break;
|
||||
case D3DERR_DRIVERINVALIDCALL : LOG("D3DERR_DRIVERINVALIDCALL"); break;
|
||||
case D3DERR_WASSTILLDRAWING : LOG("D3DERR_WASSTILLDRAWING"); break;
|
||||
default : LOG("D3DERR_UNKNOWN"); break;
|
||||
}
|
||||
LOG("\n");
|
||||
ASSERT(false);
|
||||
}
|
||||
#else
|
||||
#define D3DCHECK(res) res
|
||||
#endif
|
||||
|
||||
namespace GAPI {
|
||||
#include "shaders/base_vs.h"
|
||||
#include "shaders/base_ps.h"
|
||||
#include "shaders/compose_vs.h"
|
||||
#include "shaders/compose_ps.h"
|
||||
#include "shaders/shadow_vs.h"
|
||||
#include "shaders/shadow_ps.h"
|
||||
#include "shaders/ambient_vs.h"
|
||||
#include "shaders/ambient_ps.h"
|
||||
#include "shaders/water_vs.h"
|
||||
#include "shaders/water_ps.h"
|
||||
#include "shaders/filter_vs.h"
|
||||
@@ -28,8 +70,39 @@ namespace GAPI {
|
||||
int cullMode, blendMode;
|
||||
uint32 clearColor;
|
||||
|
||||
LPDIRECT3DSURFACE9 defBackBuffer;
|
||||
LPDIRECT3DVERTEXDECLARATION9 vertexDecl;
|
||||
|
||||
|
||||
struct Texture;
|
||||
struct Mesh;
|
||||
|
||||
struct Resource {
|
||||
Texture *texture;
|
||||
Mesh *mesh;
|
||||
} resList[256];
|
||||
int resCount;
|
||||
|
||||
void registerResource(Mesh *mesh) {
|
||||
resList[resCount].mesh = mesh;
|
||||
resList[resCount].texture = NULL;
|
||||
resCount++;
|
||||
}
|
||||
|
||||
void registerResource(Texture *texture) {
|
||||
resList[resCount].mesh = NULL;
|
||||
resList[resCount].texture = texture;
|
||||
resCount++;
|
||||
}
|
||||
|
||||
void unregisterResource(void *res) {
|
||||
for (int i = 0; i < resCount; i++)
|
||||
if (resList[i].mesh == res || resList[i].texture == res) {
|
||||
resList[i] = resList[--resCount];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Shader
|
||||
enum {
|
||||
USAGE_VS,
|
||||
@@ -40,40 +113,58 @@ namespace GAPI {
|
||||
int reg;
|
||||
int usage;
|
||||
} bindings[uMAX] = {
|
||||
{ 1, USAGE_VS | USAGE_PS }, // uParam
|
||||
{ 2, USAGE_VS | USAGE_PS }, // uTexParam
|
||||
{ 3, USAGE_VS | USAGE_PS }, // uViewProj
|
||||
{ 7, USAGE_VS | USAGE_PS }, // uBasis
|
||||
{ 71, USAGE_VS | USAGE_PS }, // uLightProj
|
||||
{ 103, USAGE_VS | USAGE_PS }, // uMaterial
|
||||
{ 104, USAGE_VS | USAGE_PS }, // uAmbient
|
||||
{ 110, USAGE_VS | USAGE_PS }, // uFogParams
|
||||
{ 111, USAGE_VS | USAGE_PS }, // uViewPos
|
||||
{ 112, USAGE_VS | USAGE_PS }, // uLightPos
|
||||
{ 116, USAGE_VS | USAGE_PS }, // uLightColor
|
||||
{ 120, USAGE_VS | USAGE_PS }, // uRoomSize
|
||||
{ 121, USAGE_VS | USAGE_PS }, // uPosScale
|
||||
{ 123, USAGE_VS | USAGE_PS }, // uContacts
|
||||
{ 0, USAGE_VS | USAGE_PS }, // uParam
|
||||
{ 1, USAGE_VS | USAGE_PS }, // uTexParam
|
||||
{ 2, USAGE_VS | USAGE_PS }, // uViewProj
|
||||
{ 6, USAGE_VS | USAGE_PS }, // uBasis
|
||||
{ 70, USAGE_VS | USAGE_PS }, // uLightProj
|
||||
{ 102, USAGE_VS | USAGE_PS }, // uMaterial
|
||||
{ 103, USAGE_VS | USAGE_PS }, // uAmbient
|
||||
{ 109, USAGE_VS | USAGE_PS }, // uFogParams
|
||||
{ 110, USAGE_VS | USAGE_PS }, // uViewPos
|
||||
{ 111, USAGE_VS | USAGE_PS }, // uLightPos
|
||||
{ 115, USAGE_VS | USAGE_PS }, // uLightColor
|
||||
{ 119, USAGE_VS | USAGE_PS }, // uRoomSize
|
||||
{ 120, USAGE_VS | USAGE_PS }, // uPosScale
|
||||
{ 122, USAGE_VS | USAGE_PS }, // uContacts
|
||||
};
|
||||
|
||||
struct Shader {
|
||||
LPDIRECT3DVERTEXSHADER9 VS;
|
||||
LPDIRECT3DPIXELSHADER9 PS;
|
||||
|
||||
BOOL flags[16];
|
||||
|
||||
Shader() : VS(NULL), PS(NULL) {}
|
||||
|
||||
void init(Core::Pass pass, int *def, int defCount) {
|
||||
void init(Core::Pass pass, int type, int *def, int defCount) {
|
||||
const BYTE *vSrc, *pSrc;
|
||||
switch (pass) {
|
||||
case Core::passCompose :
|
||||
case Core::passShadow :
|
||||
case Core::passAmbient : vSrc = BASE_VS; pSrc = BASE_PS; break;
|
||||
case Core::passWater : vSrc = WATER_VS; pSrc = WATER_PS; break;
|
||||
case Core::passFilter : vSrc = FILTER_VS; pSrc = FILTER_PS; break;
|
||||
case Core::passGUI : vSrc = GUI_VS; pSrc = GUI_PS; break;
|
||||
case Core::passCompose : vSrc = COMPOSE_VS; pSrc = COMPOSE_PS; break;
|
||||
case Core::passShadow : vSrc = SHADOW_VS; pSrc = SHADOW_PS; break;
|
||||
case Core::passAmbient : vSrc = AMBIENT_VS; pSrc = AMBIENT_PS; break;
|
||||
case Core::passWater : vSrc = WATER_VS; pSrc = WATER_PS; break;
|
||||
case Core::passFilter : vSrc = FILTER_VS; pSrc = FILTER_PS; break;
|
||||
case Core::passGUI : vSrc = GUI_VS; pSrc = GUI_PS; break;
|
||||
default : ASSERT(false); LOG("! wrong pass id\n"); return;
|
||||
}
|
||||
|
||||
memset(flags, 0, sizeof(flags));
|
||||
flags[type] = TRUE;
|
||||
|
||||
for (int i = 0; i < defCount; i++) {
|
||||
switch (def[i]) {
|
||||
case SD_UNDERWATER : flags[ 5] = TRUE; break;
|
||||
case SD_ALPHA_TEST : flags[ 6] = TRUE; break;
|
||||
case SD_CLIP_PLANE : flags[ 7] = TRUE; break;
|
||||
case SD_OPT_AMBIENT : flags[ 8] = TRUE; break;
|
||||
case SD_OPT_SHADOW : flags[ 9] = TRUE; break;
|
||||
case SD_OPT_SHADOW_HIGH : flags[10] = TRUE; break;
|
||||
case SD_OPT_CONTACT : flags[11] = TRUE; break;
|
||||
case SD_OPT_CAUSTICS : flags[12] = TRUE; break;
|
||||
}
|
||||
}
|
||||
|
||||
device->CreateVertexShader ((DWORD*)vSrc, &VS);
|
||||
device->CreatePixelShader ((DWORD*)pSrc, &PS);
|
||||
}
|
||||
@@ -88,6 +179,9 @@ namespace GAPI {
|
||||
Core::active.shader = this;
|
||||
device->SetVertexShader(VS);
|
||||
device->SetPixelShader(PS);
|
||||
|
||||
device->SetVertexShaderConstantB (0, flags, COUNT(flags));
|
||||
device->SetPixelShaderConstantB (0, flags, COUNT(flags));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,7 +221,9 @@ namespace GAPI {
|
||||
bool filter = (opt & OPT_NEAREST) == 0;
|
||||
bool mipmaps = (opt & OPT_MIPMAPS) != 0;
|
||||
bool cube = (opt & OPT_CUBEMAP) != 0;
|
||||
bool isTarget = (opt & OPT_TARGET) != 0;
|
||||
bool isShadow = fmt == FMT_SHADOW;
|
||||
bool isDepth = fmt == FMT_DEPTH || fmt == FMT_DEPTH_STENCIL || fmt == FMT_SHADOW;
|
||||
|
||||
static const struct FormatDesc {
|
||||
int bpp;
|
||||
@@ -146,26 +242,38 @@ namespace GAPI {
|
||||
|
||||
FormatDesc desc = formats[fmt];
|
||||
|
||||
uint32 usage = 0;
|
||||
if (mipmaps) usage |= D3DUSAGE_AUTOGENMIPMAP;
|
||||
if (isDepth) usage |= D3DUSAGE_DEPTHSTENCIL;
|
||||
if (isTarget) usage |= D3DUSAGE_RENDERTARGET;
|
||||
|
||||
D3DPOOL pool = isTarget ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED;
|
||||
|
||||
if (cube) {
|
||||
device->CreateCubeTexture(width, 1, 0, desc.format, D3DPOOL_MANAGED, &texCube, NULL);
|
||||
D3DCHECK(device->CreateCubeTexture(width, 1, usage, desc.format, pool, &texCube, NULL));
|
||||
} else {
|
||||
device->CreateTexture(width, height, 1, 0, desc.format, D3DPOOL_MANAGED, &tex2D, NULL);
|
||||
if (data) {
|
||||
D3DCHECK(device->CreateTexture(width, height, 1, usage, desc.format, pool, &tex2D, NULL));
|
||||
if (data && !isTarget) {
|
||||
D3DLOCKED_RECT rect;
|
||||
tex2D->LockRect(0, &rect, NULL, 0);
|
||||
D3DCHECK(tex2D->LockRect(0, &rect, NULL, 0));
|
||||
memcpy(rect.pBits, data, width * height * (desc.bpp / 8));
|
||||
tex2D->UnlockRect(0);
|
||||
D3DCHECK(tex2D->UnlockRect(0));
|
||||
}
|
||||
}
|
||||
|
||||
if (pool != D3DPOOL_MANAGED)
|
||||
registerResource(this);
|
||||
}
|
||||
|
||||
void deinit() {
|
||||
unregisterResource(this);
|
||||
if (tex2D) tex2D->Release();
|
||||
if (texCube) texCube->Release();
|
||||
}
|
||||
|
||||
void generateMipMap() {
|
||||
// TODO
|
||||
if (texCube) texCube->GenerateMipSubLevels();
|
||||
if (tex2D) tex2D->GenerateMipSubLevels();
|
||||
}
|
||||
|
||||
void bind(int sampler) {
|
||||
@@ -178,6 +286,25 @@ namespace GAPI {
|
||||
device->SetTexture(sampler, tex2D);
|
||||
else if (texCube)
|
||||
device->SetTexture(sampler, texCube);
|
||||
|
||||
bool filter = (Core::settings.detail.filter > Core::Settings::LOW) && !(opt & OPT_NEAREST);
|
||||
bool mipmaps = (Core::settings.detail.filter > Core::Settings::MEDIUM) && (opt & OPT_MIPMAPS);
|
||||
bool aniso = filter && mipmaps && (Core::support.maxAniso > 0);
|
||||
|
||||
device->SetSamplerState(sampler, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
|
||||
device->SetSamplerState(sampler, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
|
||||
|
||||
if (aniso) {
|
||||
device->SetSamplerState(sampler, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC);
|
||||
device->SetSamplerState(sampler, D3DSAMP_MAGFILTER, D3DTEXF_ANISOTROPIC);
|
||||
device->SetSamplerState(sampler, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
|
||||
device->SetSamplerState(sampler, D3DSAMP_MAXANISOTROPY, support.maxAniso);
|
||||
} else {
|
||||
device->SetSamplerState(sampler, D3DSAMP_MINFILTER, filter ? D3DTEXF_LINEAR : D3DTEXF_POINT);
|
||||
device->SetSamplerState(sampler, D3DSAMP_MAGFILTER, filter ? D3DTEXF_LINEAR : D3DTEXF_POINT);
|
||||
device->SetSamplerState(sampler, D3DSAMP_MIPFILTER, mipmaps ? (filter ? D3DTEXF_LINEAR : D3DTEXF_POINT) : D3DTEXF_NONE);
|
||||
device->SetSamplerState(sampler, D3DSAMP_MAXANISOTROPY, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,18 +315,7 @@ namespace GAPI {
|
||||
}
|
||||
}
|
||||
|
||||
void setFilterQuality(int value) {
|
||||
bool filter = value > Core::Settings::LOW;
|
||||
bool mipmaps = value > Core::Settings::MEDIUM;
|
||||
|
||||
for (int i = 0; i < sMAX; i++) {
|
||||
device->SetSamplerState(i, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
|
||||
device->SetSamplerState(i, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
|
||||
device->SetSamplerState(i, D3DSAMP_ADDRESSW, D3DTADDRESS_CLAMP);
|
||||
device->SetSamplerState(i, D3DSAMP_MAGFILTER, filter ? D3DTEXF_LINEAR : D3DTEXF_POINT);
|
||||
device->SetSamplerState(i, D3DSAMP_MINFILTER, filter ? D3DTEXF_LINEAR : D3DTEXF_POINT);
|
||||
}
|
||||
}
|
||||
void setFilterQuality(int value) {}
|
||||
};
|
||||
|
||||
// Mesh
|
||||
@@ -216,15 +332,22 @@ namespace GAPI {
|
||||
void init(Index *indices, int iCount, ::Vertex *vertices, int vCount, int aCount) {
|
||||
this->iCount = iCount;
|
||||
this->vCount = vCount;
|
||||
|
||||
ASSERT(sizeof(GAPI::Vertex) == sizeof(::Vertex));
|
||||
|
||||
device->CreateIndexBuffer (iCount * sizeof(indices[0]), D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &IB, NULL);
|
||||
device->CreateVertexBuffer (vCount * sizeof(vertices[0]), D3DUSAGE_WRITEONLY, 0, D3DPOOL_MANAGED, &VB, NULL);
|
||||
uint32 usage = D3DUSAGE_WRITEONLY | (dynamic ? D3DUSAGE_DYNAMIC : 0);
|
||||
D3DPOOL pool = dynamic ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED;
|
||||
|
||||
D3DCHECK(device->CreateIndexBuffer (iCount * sizeof(Index), usage, D3DFMT_INDEX16, pool, &IB, NULL));
|
||||
D3DCHECK(device->CreateVertexBuffer (vCount * sizeof(Vertex), usage, D3DFMT_UNKNOWN, pool, &VB, NULL));
|
||||
|
||||
update(indices, iCount, vertices, vCount);
|
||||
|
||||
if (pool != D3DPOOL_MANAGED)
|
||||
registerResource(this);
|
||||
}
|
||||
|
||||
void deinit() {
|
||||
unregisterResource(this);
|
||||
IB->Release();
|
||||
VB->Release();
|
||||
}
|
||||
@@ -236,15 +359,17 @@ namespace GAPI {
|
||||
int size;
|
||||
|
||||
if (indices && iCount) {
|
||||
IB->Lock(0, size = iCount * sizeof(indices[0]), &ptr, 0);
|
||||
size = iCount * sizeof(indices[0]);
|
||||
D3DCHECK(IB->Lock(0, 0, &ptr, dynamic ? D3DLOCK_DISCARD : 0));
|
||||
memcpy(ptr, indices, size);
|
||||
IB->Unlock();
|
||||
D3DCHECK(IB->Unlock());
|
||||
}
|
||||
|
||||
if (vertices && vCount) {
|
||||
VB->Lock(0, size = vCount * sizeof(vertices[0]), &ptr, 0);
|
||||
size = vCount * sizeof(vertices[0]);
|
||||
D3DCHECK(VB->Lock(0, 0, &ptr, dynamic ? D3DLOCK_DISCARD: 0));
|
||||
memcpy(ptr, vertices, size);
|
||||
VB->Unlock();
|
||||
D3DCHECK(VB->Unlock());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -276,7 +401,7 @@ namespace GAPI {
|
||||
LOG("Vendor : %s\n", adapterInfo.Description);
|
||||
LOG("Renderer : Direct3D 9.0c\n");
|
||||
|
||||
support.maxAniso = 16;
|
||||
support.maxAniso = 8;
|
||||
support.maxVectors = 16;
|
||||
support.shaderBinary = false;
|
||||
support.VAO = false;
|
||||
@@ -308,40 +433,61 @@ namespace GAPI {
|
||||
};
|
||||
|
||||
device->CreateVertexDeclaration(VERTEX_DECL, &vertexDecl);
|
||||
/*
|
||||
if (support.maxAniso)
|
||||
glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &support.maxAniso);
|
||||
#ifdef _GAPI_GLES
|
||||
glGetIntegerv(GL_MAX_VARYING_VECTORS, &support.maxVectors);
|
||||
#else
|
||||
support.maxVectors = 16;
|
||||
#endif
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*)&defaultFBO);
|
||||
glGenFramebuffers(1, &FBO);
|
||||
*/
|
||||
}
|
||||
|
||||
void deinit() {
|
||||
/*
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glDeleteFramebuffers(1, &FBO);
|
||||
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
for (int b = 0; b < 2; b++)
|
||||
for (int i = 0; i < rtCache[b].count; i++)
|
||||
glDeleteRenderbuffers(1, &rtCache[b].items[i].ID);
|
||||
*/
|
||||
vertexDecl->Release();
|
||||
}
|
||||
|
||||
void beginFrame() {
|
||||
void resetDevice() {
|
||||
int tmpCount = resCount;
|
||||
Resource tmpList[256];
|
||||
memcpy(tmpList, resList, sizeof(Resource) * tmpCount);
|
||||
|
||||
for (int i = 0; i < tmpCount; i++) {
|
||||
Resource &res = tmpList[i];
|
||||
if (res.mesh)
|
||||
res.mesh->deinit();
|
||||
else
|
||||
res.texture->deinit();
|
||||
}
|
||||
|
||||
D3DCHECK(device->Reset(&d3dpp));
|
||||
|
||||
for (int i = 0; i < tmpCount; i++) {
|
||||
Resource &res = tmpList[i];
|
||||
if (res.mesh)
|
||||
res.mesh->init(NULL, res.mesh->iCount, NULL, res.mesh->vCount, 0);
|
||||
else
|
||||
res.texture->init(NULL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool beginFrame() {
|
||||
switch (device->TestCooperativeLevel()) {
|
||||
case D3D_OK :
|
||||
break;
|
||||
case D3DERR_DEVICELOST :
|
||||
return false;
|
||||
case D3DERR_DEVICENOTRESET :
|
||||
switch (device->Reset(&d3dpp)) {
|
||||
case D3D_OK : break;
|
||||
default : return false;
|
||||
}
|
||||
case D3DERR_DRIVERINTERNALERROR :
|
||||
Core::quit();
|
||||
return false;
|
||||
}
|
||||
|
||||
device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &defBackBuffer);
|
||||
device->BeginScene();
|
||||
return true;
|
||||
}
|
||||
|
||||
void endFrame() {
|
||||
device->EndScene();
|
||||
defBackBuffer->Release();
|
||||
}
|
||||
|
||||
void resetState() {
|
||||
@@ -373,39 +519,46 @@ namespace GAPI {
|
||||
}
|
||||
|
||||
void bindTarget(Texture *target, int face) {
|
||||
/*
|
||||
if (!target) { // may be a null
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO);
|
||||
D3DCHECK(device->SetRenderTarget(0, defBackBuffer));
|
||||
} else {
|
||||
GLenum texTarget = GL_TEXTURE_2D;
|
||||
if (target->opt & OPT_CUBEMAP)
|
||||
texTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
|
||||
ASSERT(target->opt & OPT_TARGET);
|
||||
|
||||
LPDIRECT3DSURFACE9 surface;
|
||||
|
||||
if (target->tex2D)
|
||||
D3DCHECK(target->tex2D->GetSurfaceLevel(0, &surface));
|
||||
else if (target->texCube)
|
||||
D3DCHECK(target->texCube->GetCubeMapSurface(D3DCUBEMAP_FACES(D3DCUBEMAP_FACE_POSITIVE_X + face), 0, &surface));
|
||||
|
||||
D3DCHECK(device->SetRenderTarget(0, surface));
|
||||
|
||||
surface->Release();
|
||||
|
||||
bool depth = target->fmt == FMT_DEPTH || target->fmt == FMT_SHADOW;
|
||||
|
||||
int rtIndex = cacheRenderTarget(depth, target->width, target->height);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, FBO);
|
||||
glFramebufferTexture2D (GL_FRAMEBUFFER, depth ? GL_DEPTH_ATTACHMENT : GL_COLOR_ATTACHMENT0, texTarget, target->ID, 0);
|
||||
glFramebufferRenderbuffer (GL_FRAMEBUFFER, depth ? GL_COLOR_ATTACHMENT0 : GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rtCache[depth].items[rtIndex].ID);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void discardTarget(bool color, bool depth) {}
|
||||
|
||||
void copyTarget(Texture *dst, int xOffset, int yOffset, int x, int y, int width, int height) {
|
||||
Core::active.textures[0] = NULL;
|
||||
/*
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, dst->ID);
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, xOffset, yOffset, x, y, width, height);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
*/
|
||||
ASSERT(dst && dst->tex2D);
|
||||
|
||||
LPDIRECT3DSURFACE9 surface;
|
||||
dst->tex2D->GetSurfaceLevel(0, &surface);
|
||||
|
||||
RECT srcRect = { x, y, x + width, y + height },
|
||||
dstRect = { xOffset, yOffset, xOffset + width, yOffset + height };
|
||||
|
||||
device->StretchRect(defBackBuffer, &srcRect, surface, &dstRect, D3DTEXF_POINT);
|
||||
|
||||
surface->Release();
|
||||
}
|
||||
|
||||
void setVSync(bool enable) {
|
||||
//
|
||||
d3dpp.PresentationInterval = enable ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE;
|
||||
GAPI::resetDevice();
|
||||
}
|
||||
|
||||
void waitVBlank() {}
|
||||
@@ -502,9 +655,24 @@ namespace GAPI {
|
||||
}
|
||||
|
||||
vec4 copyPixel(int x, int y) {
|
||||
ubyte4 c;
|
||||
// glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &c);
|
||||
return vec4(float(c.x), float(c.y), float(c.z), float(c.w)) * (1.0f / 255.0f);
|
||||
GAPI::Texture *t = Core::active.target;
|
||||
ASSERT(t && t->tex2D);
|
||||
|
||||
LPDIRECT3DSURFACE9 surface, texSurface;
|
||||
D3DCHECK(t->tex2D->GetSurfaceLevel(0, &texSurface));
|
||||
D3DCHECK(device->CreateOffscreenPlainSurface(t->width, t->height, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, NULL));
|
||||
D3DCHECK(device->GetRenderTargetData(texSurface, surface));
|
||||
|
||||
RECT r = { x, y, x + 1, y + 1 };
|
||||
D3DLOCKED_RECT rect;
|
||||
surface->LockRect(&rect, &r, D3DLOCK_READONLY);
|
||||
ubyte4 c = *((ubyte4*)rect.pBits);
|
||||
surface->UnlockRect();
|
||||
|
||||
texSurface->Release();
|
||||
surface->Release();
|
||||
|
||||
return vec4(float(c.z), float(c.y), float(c.x), float(c.w)) * (1.0f / 255.0f);
|
||||
}
|
||||
|
||||
void initPSO(PSO *pso) {
|
||||
|
@@ -335,7 +335,7 @@ namespace GAPI {
|
||||
|
||||
struct Shader {
|
||||
#ifdef FFP
|
||||
void init(Core::Pass pass, int *def, int defCount) {}
|
||||
void init(Core::Pass pass, int type, int *def, int defCount) {}
|
||||
void deinit() {}
|
||||
void bind() {}
|
||||
void setParam(UniformType uType, const vec4 &value, int count = 1) {}
|
||||
@@ -345,7 +345,7 @@ namespace GAPI {
|
||||
uint32 ID;
|
||||
int32 uID[uMAX];
|
||||
|
||||
void init(Core::Pass pass, int *def, int defCount) {
|
||||
void init(Core::Pass pass, int type, int *def, int defCount) {
|
||||
const char *source;
|
||||
switch (pass) {
|
||||
case Core::passCompose :
|
||||
@@ -977,7 +977,9 @@ namespace GAPI {
|
||||
glDeleteRenderbuffers(1, &rtCache[b].items[i].ID);
|
||||
}
|
||||
|
||||
void beginFrame() {}
|
||||
bool beginFrame() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void endFrame() {}
|
||||
|
||||
|
@@ -289,7 +289,9 @@ namespace GAPI {
|
||||
delete[] cmdBuf;
|
||||
}
|
||||
|
||||
void beginFrame() {}
|
||||
bool beginFrame() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void endFrame() {}
|
||||
|
||||
|
@@ -1443,7 +1443,7 @@ struct Lara : Character {
|
||||
void bakeEnvironment() {
|
||||
flags.invisible = true;
|
||||
if (!environment)
|
||||
environment = new Texture(256, 256, FMT_RGBA, OPT_CUBEMAP | OPT_MIPMAPS);
|
||||
environment = new Texture(256, 256, FMT_RGBA, OPT_CUBEMAP | OPT_MIPMAPS | OPT_TARGET);
|
||||
game->renderEnvironment(getRoomIndex(), pos - vec3(0.0f, 384.0f, 0.0f), &environment, 0, Core::passCompose);
|
||||
environment->generateMipMap();
|
||||
flags.invisible = false;
|
||||
|
@@ -50,26 +50,6 @@ void osMutexUnlock(void *obj) {
|
||||
}
|
||||
|
||||
/*
|
||||
void* osMutexInit() {
|
||||
HANDLE *mutex = new HANDLE();
|
||||
*mutex = CreateMutex(NULL, FALSE, NULL);
|
||||
return mutex;
|
||||
}
|
||||
|
||||
void osMutexFree(void *obj) {
|
||||
CloseHandle(*(HANDLE*)obj);
|
||||
delete (HANDLE*)obj;
|
||||
}
|
||||
|
||||
void osMutexLock(void *obj) {
|
||||
WaitForSingleObject(*(HANDLE*)obj, INFINITE);
|
||||
}
|
||||
|
||||
void osMutexUnlock(void *obj) {
|
||||
ReleaseMutex(*(HANDLE*)obj);
|
||||
}
|
||||
*/
|
||||
|
||||
void* osRWLockInit() {
|
||||
SRWLOCK *lock = new SRWLOCK();
|
||||
InitializeSRWLock(lock);
|
||||
@@ -95,7 +75,7 @@ void osRWLockWrite(void *obj) {
|
||||
void osRWUnlockWrite(void *obj) {
|
||||
ReleaseSRWLockExclusive((SRWLOCK*)obj);
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
// timing
|
||||
int osStartTime = 0;
|
||||
@@ -441,16 +421,14 @@ HWND hWnd;
|
||||
SwapBuffers(hDC);
|
||||
}
|
||||
#else
|
||||
D3DPRESENT_PARAMETERS d3dpp;
|
||||
LPDIRECT3D9 D3D;
|
||||
LPDIRECT3DDEVICE9 device;
|
||||
D3DPRESENT_PARAMETERS d3dpp;
|
||||
|
||||
void ContextCreate() {
|
||||
memset(&d3dpp, 0, sizeof(d3dpp));
|
||||
d3dpp.Windowed = TRUE;
|
||||
d3dpp.BackBufferCount = 1;
|
||||
d3dpp.BackBufferWidth = 1;
|
||||
d3dpp.BackBufferHeight = 1;
|
||||
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
|
||||
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
|
||||
d3dpp.hDeviceWindow = hWnd;
|
||||
@@ -474,14 +452,16 @@ HWND hWnd;
|
||||
}
|
||||
|
||||
void ContextResize() {
|
||||
d3dpp.BackBufferWidth = Core::width;
|
||||
d3dpp.BackBufferHeight = Core::height;
|
||||
device->Reset(&d3dpp);
|
||||
if (Core::width <= 0 || Core::height <= 0)
|
||||
return;
|
||||
d3dpp.BackBufferWidth = Core::width;
|
||||
d3dpp.BackBufferHeight = Core::height;
|
||||
GAPI::resetDevice();
|
||||
}
|
||||
|
||||
void ContextSwap() {
|
||||
if (device->Present(NULL, NULL, NULL, NULL) == D3DERR_DEVICELOST)
|
||||
ContextResize();
|
||||
GAPI::resetDevice();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@@ -13,8 +13,8 @@ struct Shader : GAPI::Shader {
|
||||
MAX = 6
|
||||
};
|
||||
|
||||
Shader(Core::Pass pass, int *def, int defCount) : GAPI::Shader() {
|
||||
init(pass, def, defCount);
|
||||
Shader(Core::Pass pass, Type type, int *def, int defCount) : GAPI::Shader() {
|
||||
init(pass, type, def, defCount);
|
||||
}
|
||||
|
||||
virtual ~Shader() {
|
||||
|
@@ -1,15 +1,15 @@
|
||||
#include "common.hlsl"
|
||||
|
||||
struct VS_OUTPUT {
|
||||
float4 wPos : POSITION;
|
||||
float3 vCoord : TEXCOORD2;
|
||||
float4 vTexCoord : TEXCOORD0;
|
||||
float4 vDiffuse : COLOR0;
|
||||
float4 vNormal : NORMAL;
|
||||
float4 vViewVec : TEXCOORD1;
|
||||
float3 vAmbient : COLOR1;
|
||||
float4 vLightMap : COLOR2;
|
||||
float4 vLight : COLOR3;
|
||||
float4 wpos : POSITION;
|
||||
float3 coord : TEXCOORD0;
|
||||
float4 texCoord : TEXCOORD1;
|
||||
float4 viewVec : TEXCOORD2;
|
||||
float4 normal : NORMAL;
|
||||
float4 diffuse : COLOR0;
|
||||
float3 ambient : COLOR1;
|
||||
float4 lightMap : COLOR2;
|
||||
float4 light : COLOR3;
|
||||
};
|
||||
|
||||
#ifdef VERTEX
|
||||
@@ -20,38 +20,262 @@ float3 mulQuat(float4 q, float3 v) {
|
||||
float3 mulBasis(float4 rot, float3 pos, float3 v) {
|
||||
return mulQuat(rot, v) + pos;
|
||||
}
|
||||
|
||||
|
||||
float3 calcAmbient(float3 n) {
|
||||
float3 sqr = n * n;
|
||||
float3 pos = step(0.0, n);
|
||||
return sqr.x * lerp(uAmbient[1].xyz, uAmbient[0].xyz, pos.x) +
|
||||
sqr.y * lerp(uAmbient[3].xyz, uAmbient[2].xyz, pos.y) +
|
||||
sqr.z * lerp(uAmbient[5].xyz, uAmbient[4].xyz, pos.z);
|
||||
}
|
||||
|
||||
VS_OUTPUT main(VS_INPUT In) {
|
||||
VS_OUTPUT Out;
|
||||
Out.ambient = 0.0;
|
||||
Out.lightMap = 0.0;
|
||||
Out.light = 0.0;
|
||||
|
||||
int index = int(In.aCoord.w * 2.0);
|
||||
float4 rBasisRot = uBasis[index];
|
||||
float4 rBasisPos = uBasis[index + 1];
|
||||
Out.vCoord = mulBasis(rBasisRot, rBasisPos.xyz, In.aCoord.xyz);
|
||||
Out.wPos = mul(uViewProj, float4(Out.vCoord, rBasisPos.w));
|
||||
|
||||
Out.vTexCoord = In.aTexCoord * (1.0 / 32767.0);
|
||||
Out.vTexCoord.xy *= Out.vTexCoord.zw;
|
||||
Out.texCoord = In.aTexCoord * (1.0 / 32767.0);
|
||||
|
||||
if (TYPE_SPRITE) {
|
||||
Out.coord = mulBasis(rBasisRot, rBasisPos.xyz + In.aCoord.xyz, float3(In.aTexCoord.z, In.aTexCoord.w, 0.0));
|
||||
} else {
|
||||
Out.coord = mulBasis(rBasisRot, rBasisPos.xyz, In.aCoord.xyz);
|
||||
Out.texCoord.xy *= Out.texCoord.zw;
|
||||
}
|
||||
|
||||
#ifdef PASS_SHADOW
|
||||
Out.viewVec = 0.0;
|
||||
Out.normal = 0.0;
|
||||
Out.diffuse = 0.0;
|
||||
#else
|
||||
Out.viewVec = float4((uViewPos.xyz - Out.coord) * uFogParams.w, Out.coord.y * uParam.z);
|
||||
|
||||
#ifdef PASS_COMPOSE
|
||||
|
||||
if (TYPE_SPRITE) {
|
||||
Out.normal.xyz = normalize(Out.viewVec.xyz);
|
||||
} else {
|
||||
Out.normal.xyz = mulQuat(rBasisRot, normalize(In.aNormal.xyz));
|
||||
}
|
||||
|
||||
float fog;
|
||||
|
||||
if (!TYPE_FLASH) {
|
||||
|
||||
float3 lv0 = (uLightPos[0].xyz - Out.coord) * uLightColor[0].w;
|
||||
float3 lv1 = (uLightPos[1].xyz - Out.coord) * uLightColor[1].w;
|
||||
float3 lv2 = (uLightPos[2].xyz - Out.coord) * uLightColor[2].w;
|
||||
float3 lv3 = (uLightPos[3].xyz - Out.coord) * uLightColor[3].w;
|
||||
|
||||
float4 lum, att;
|
||||
if (TYPE_ENTITY) {
|
||||
lum.x = dot(Out.normal.xyz, normalize(lv0));
|
||||
att.x = dot(lv0, lv0);
|
||||
if (OPT_AMBIENT) {
|
||||
Out.ambient = calcAmbient(Out.normal.xyz);
|
||||
} else {
|
||||
Out.ambient = min(uMaterial.yyy, In.aLight.xyz);
|
||||
}
|
||||
} else {
|
||||
if (TYPE_SPRITE) {
|
||||
lum.x = uMaterial.y;
|
||||
} else {
|
||||
lum.x = 1.0;
|
||||
}
|
||||
att.x = 0.0;
|
||||
|
||||
Out.ambient = min(uMaterial.yyy, In.aLight.zyx);
|
||||
}
|
||||
|
||||
float4 light;
|
||||
lum.y = dot(Out.normal.xyz, normalize(lv1)); att.y = dot(lv1, lv1);
|
||||
lum.z = dot(Out.normal.xyz, normalize(lv2)); att.z = dot(lv2, lv2);
|
||||
lum.w = dot(Out.normal.xyz, normalize(lv3)); att.w = dot(lv3, lv3);
|
||||
light = max(0.0, lum) * max(0.0, 1.0 - att);
|
||||
|
||||
if (UNDERWATER) {
|
||||
light.x *= abs(sin(dot(Out.coord.xyz, 1.0 / 512.0) + uParam.x)) * 1.5 + 0.5;
|
||||
|
||||
float d;
|
||||
if (uViewPos.y < uParam.y) {
|
||||
d = abs((Out.coord.y - uParam.y) / normalize(Out.viewVec.xyz).y);
|
||||
} else {
|
||||
d = length(uViewPos.xyz - Out.coord.xyz);
|
||||
}
|
||||
|
||||
fog = d * WATER_FOG_DIST;
|
||||
} else {
|
||||
fog = length(Out.viewVec.xyz);
|
||||
}
|
||||
Out.normal.w = saturate(1.0 / exp(fog));
|
||||
|
||||
if (OPT_SHADOW) {
|
||||
Out.light = light;
|
||||
Out.lightMap = In.aLight.zyxw * light.x;
|
||||
} else {
|
||||
Out.light.xyz = uLightColor[1].xyz * light.y + uLightColor[2].xyz * light.z + uLightColor[3].xyz * light.w;
|
||||
Out.light.w = 0.0;
|
||||
|
||||
if (TYPE_ENTITY) {
|
||||
Out.light.xyz += Out.ambient + uLightColor[0].xyz * light.x;
|
||||
} else {
|
||||
Out.light.xyz += In.aLight.xyz * light.x;
|
||||
}
|
||||
}
|
||||
} else
|
||||
Out.normal.w = 1.0;
|
||||
|
||||
#else
|
||||
Out.normal = In.aNormal;
|
||||
Out.light = float4(In.aLight.xyz, 1.0);
|
||||
#endif
|
||||
|
||||
if (TYPE_MIRROR) {
|
||||
Out.diffuse = uMaterial;
|
||||
} else {
|
||||
Out.diffuse = float4(In.aColor.zyx * (uMaterial.x * 1.8), uMaterial.w);
|
||||
|
||||
if (UNDERWATER) {
|
||||
Out.diffuse.xyz *= UNDERWATER_COLOR;
|
||||
}
|
||||
|
||||
if (TYPE_FLASH) {
|
||||
Out.diffuse.xyz += uMaterial.w;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Out.wpos = mul(uViewProj, float4(Out.coord, rBasisPos.w));
|
||||
|
||||
Out.vDiffuse = float4(In.aColor.xyz * (uMaterial.x), uMaterial.w);
|
||||
Out.vNormal = In.aNormal;
|
||||
Out.vViewVec = float4(uViewPos.xyz - Out.vCoord, 0.0);
|
||||
Out.vAmbient = float3(0.2, 0.2, 0.2);
|
||||
Out.vLightMap = In.aLight;
|
||||
Out.vLight = float4(0.5, 0.5, 0.5, 0.5);
|
||||
return Out;
|
||||
}
|
||||
|
||||
#else // PIXEL
|
||||
|
||||
sampler sDiffuse : register(s0);
|
||||
sampler sNormal : register(s1);
|
||||
sampler sReflect : register(s2);
|
||||
sampler sShadow : register(s3);
|
||||
sampler sEnvironment : register(s4);
|
||||
sampler sMask : register(s5);
|
||||
float getShadow(float3 lightVec) {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
float getContactAO(float3 p, float3 n) {
|
||||
float res = 1.0;
|
||||
for (int i = 0; i < MAX_CONTACTS; i++) {
|
||||
float3 v = uContacts[i].xyz - p;
|
||||
float a = uContacts[i].w;
|
||||
float o = a * saturate(dot(n, v)) / dot(v, v);
|
||||
res *= clamp(1.0 - o, 0.0, 1.0);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
float calcCaustics(float3 coord, float3 n) {
|
||||
float2 cc = saturate((coord.xz - uRoomSize.xy) / uRoomSize.zw);
|
||||
return tex2D(sReflect, cc).x * max(0.0, -n.y);
|
||||
}
|
||||
|
||||
float calcSpecular(float3 normal, float3 viewVec, float3 lightVec, float4 color, float intensity) {
|
||||
float3 vv = normalize(viewVec);
|
||||
float3 rv = reflect(-vv, normal);
|
||||
float3 lv = normalize(lightVec);
|
||||
return pow(max(0.0, dot(rv, lv)), 8.0) * intensity;
|
||||
}
|
||||
|
||||
float4 main(VS_OUTPUT In) : COLOR0 {
|
||||
return (In.vDiffuse * In.vLightMap * tex2D(sDiffuse, In.vTexCoord.xy / In.vTexCoord.zw)).bgra;
|
||||
float2 uv = In.texCoord.xy;
|
||||
|
||||
#ifdef PASS_COMPOSE
|
||||
if (CLIP_PLANE) {
|
||||
if (In.viewVec.w > uParam.w) {
|
||||
discard;
|
||||
}
|
||||
}
|
||||
|
||||
if (!TYPE_SPRITE) {
|
||||
uv /= In.texCoord.zw;
|
||||
}
|
||||
#endif
|
||||
|
||||
float4 color;
|
||||
|
||||
if (TYPE_MIRROR) {
|
||||
float3 rv = reflect(-normalize(In.viewVec.xyz), normalize(In.normal.xyz));
|
||||
color = texCUBE(sEnvironment, normalize(rv));
|
||||
} else {
|
||||
color = tex2D(sDiffuse, uv).bgra;
|
||||
|
||||
if (ALPHA_TEST) {
|
||||
if (color.w <= 0.5)
|
||||
discard;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PASS_SHADOW
|
||||
return 1.0;
|
||||
#else
|
||||
color *= In.diffuse;
|
||||
|
||||
if (TYPE_FLASH) {
|
||||
return color;
|
||||
}
|
||||
|
||||
if (TYPE_MIRROR) {
|
||||
return color;
|
||||
}
|
||||
|
||||
#ifdef PASS_AMBIENT
|
||||
color.xyz *= In.light.xyz;
|
||||
#endif
|
||||
|
||||
#ifdef PASS_COMPOSE
|
||||
float3 lightVec = (uLightPos[0].xyz - In.coord) * uLightColor[0].w;
|
||||
float3 normal = normalize(In.normal.xyz);
|
||||
|
||||
float rSpecular = 0.0;
|
||||
|
||||
float3 light;
|
||||
if (OPT_SHADOW) {
|
||||
light = uLightColor[1].xyz * In.light.y + uLightColor[2].xyz * In.light.z + uLightColor[3].xyz * In.light.w;
|
||||
|
||||
if (TYPE_ENTITY) {
|
||||
float rShadow = getShadow(lightVec);
|
||||
rSpecular = (uMaterial.z + 0.03) * rShadow;
|
||||
light += In.ambient + uLightColor[0].xyz * (In.light.x * rShadow);
|
||||
} else if (TYPE_ROOM) {
|
||||
float rShadow = getShadow(lightVec);
|
||||
light += lerp(In.ambient.xyz, In.lightMap.xyz, rShadow);
|
||||
} else if (TYPE_SPRITE) {
|
||||
light += In.lightMap.xyz;
|
||||
}
|
||||
} else {
|
||||
light = In.light.xyz;
|
||||
}
|
||||
|
||||
if (OPT_CAUSTICS) {
|
||||
light += calcCaustics(In.coord, normal);
|
||||
}
|
||||
|
||||
if (OPT_CONTACT) {
|
||||
light *= getContactAO(In.coord, normal) * 0.5 + 0.5;
|
||||
}
|
||||
|
||||
color.xyz *= light;
|
||||
|
||||
if (TYPE_ENTITY) {
|
||||
color.xyz += calcSpecular(normal, In.viewVec.xyz, lightVec, uLightColor[0], rSpecular);
|
||||
}
|
||||
|
||||
if (UNDERWATER) {
|
||||
color.xyz = lerp(UNDERWATER_COLOR * 0.2, color.xyz, In.normal.w);
|
||||
} else {
|
||||
color.xyz = lerp(uFogParams.xyz, color.xyz, In.normal.w);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return color;
|
||||
}
|
||||
#endif
|
@@ -1,5 +1,7 @@
|
||||
#define MAX_LIGHTS 4
|
||||
#define MAX_CONTACTS 15
|
||||
#define MAX_LIGHTS 4
|
||||
#define MAX_CONTACTS 15
|
||||
#define WATER_FOG_DIST (1.0 / (6.0 * 1024.0))
|
||||
#define UNDERWATER_COLOR float3(0.6, 0.9, 0.9)
|
||||
|
||||
struct VS_INPUT {
|
||||
float4 aCoord : POSITION;
|
||||
@@ -9,18 +11,55 @@ struct VS_INPUT {
|
||||
float4 aLight : COLOR1;
|
||||
};
|
||||
|
||||
int4 uInfo : register( c0 );
|
||||
float4 uParam : register( c1 );
|
||||
float4 uTexParam : register( c2 );
|
||||
float4x4 uViewProj : register( c3 );
|
||||
float4 uBasis[32 * 2] : register( c7 );
|
||||
float4x4 uLightProj : register( c71 );
|
||||
float4 uMaterial : register( c103 );
|
||||
float4 uAmbient[6] : register( c104 );
|
||||
float4 uFogParams : register( c110 );
|
||||
float4 uViewPos : register( c111 );
|
||||
float4 uLightPos[MAX_LIGHTS] : register( c112 );
|
||||
float4 uLightColor[MAX_LIGHTS] : register( c116 );
|
||||
float4 uRoomSize : register( c120 );
|
||||
float4 uPosScale[2] : register( c121 );
|
||||
float4 uContacts[MAX_CONTACTS] : register( c123 );
|
||||
#ifdef PIXEL
|
||||
sampler sDiffuse : register(s0);
|
||||
sampler sNormal : register(s1);
|
||||
sampler sReflect : register(s2);
|
||||
sampler sShadow : register(s3);
|
||||
sampler sEnvironment : register(s4);
|
||||
sampler sMask : register(s5);
|
||||
#endif
|
||||
|
||||
bool uFlags[16] : register( b0 );
|
||||
float4 uParam : register( c0 );
|
||||
float4 uTexParam : register( c1 );
|
||||
float4x4 uViewProj : register( c2 );
|
||||
float4 uBasis[32 * 2] : register( c6 );
|
||||
float4x4 uLightProj : register( c70 );
|
||||
float4 uMaterial : register( c102 );
|
||||
float4 uAmbient[6] : register( c103 );
|
||||
float4 uFogParams : register( c109 );
|
||||
float4 uViewPos : register( c110 );
|
||||
float4 uLightPos[MAX_LIGHTS] : register( c111 );
|
||||
float4 uLightColor[MAX_LIGHTS] : register( c115 );
|
||||
float4 uRoomSize : register( c119 );
|
||||
float4 uPosScale[2] : register( c120 );
|
||||
float4 uContacts[MAX_CONTACTS] : register( c122 );
|
||||
|
||||
#define TYPE_SPRITE uFlags[0]
|
||||
#define TYPE_FLASH uFlags[1]
|
||||
#define TYPE_ROOM uFlags[2]
|
||||
#define TYPE_ENTITY uFlags[3]
|
||||
#define TYPE_MIRROR uFlags[4]
|
||||
|
||||
#define FILTER_DEFAULT uFlags[0]
|
||||
#define FILTER_DOWNSAMPLE uFlags[1]
|
||||
#define FILTER_GRAYSCALE uFlags[2]
|
||||
#define FILTER_BLUR uFlags[3]
|
||||
#define FILTER_EQUIRECTANGULAR uFlags[4]
|
||||
|
||||
#define WATER_DROP uFlags[0]
|
||||
#define WATER_STEP uFlags[1]
|
||||
#define WATER_CAUSTICS uFlags[2]
|
||||
#define WATER_MASK uFlags[3]
|
||||
#define WATER_COMPOSE uFlags[4]
|
||||
|
||||
// options for compose, shadow, ambient passes
|
||||
#define UNDERWATER uFlags[5]
|
||||
#define ALPHA_TEST uFlags[6]
|
||||
#define CLIP_PLANE uFlags[7]
|
||||
#define OPT_AMBIENT uFlags[8]
|
||||
#define OPT_SHADOW uFlags[9]
|
||||
#define OPT_SHADOW_HIGH uFlags[10]
|
||||
#define OPT_CONTACT uFlags[11]
|
||||
#define OPT_CAUSTICS uFlags[12]
|
@@ -1,6 +1,10 @@
|
||||
@echo off
|
||||
fxc /nologo /T vs_3_0 /O3 /Vn BASE_VS /Fh base_vs.h base.hlsl /DVERTEX
|
||||
fxc /nologo /T ps_3_0 /O3 /Vn BASE_PS /Fh base_ps.h base.hlsl /DPIXEL
|
||||
fxc /nologo /T vs_3_0 /O3 /Vn COMPOSE_VS /Fh compose_vs.h base.hlsl /DPASS_COMPOSE /DVERTEX
|
||||
fxc /nologo /T ps_3_0 /O3 /Vn COMPOSE_PS /Fh compose_ps.h base.hlsl /DPASS_COMPOSE /DPIXEL
|
||||
fxc /nologo /T vs_3_0 /O3 /Vn SHADOW_VS /Fh shadow_vs.h base.hlsl /DPASS_SHADOW /DVERTEX
|
||||
fxc /nologo /T ps_3_0 /O3 /Vn SHADOW_PS /Fh shadow_ps.h base.hlsl /DPASS_SHADOW /DPIXEL
|
||||
fxc /nologo /T vs_3_0 /O3 /Vn AMBIENT_VS /Fh ambient_vs.h base.hlsl /DPASS_AMBIENT /DVERTEX
|
||||
fxc /nologo /T ps_3_0 /O3 /Vn AMBIENT_PS /Fh ambient_ps.h base.hlsl /DPASS_AMBIENT /DPIXEL
|
||||
fxc /nologo /T vs_3_0 /O3 /Vn WATER_VS /Fh water_vs.h water.hlsl /DVERTEX
|
||||
fxc /nologo /T ps_3_0 /O3 /Vn WATER_PS /Fh water_ps.h water.hlsl /DPIXEL
|
||||
fxc /nologo /T vs_3_0 /O3 /Vn FILTER_VS /Fh filter_vs.h filter.hlsl /DVERTEX
|
||||
|
@@ -23,13 +23,11 @@ uniform vec4 uParam;
|
||||
uniform sampler2D sNormal;
|
||||
|
||||
vec4 downsample() { // uParam (textureSize, unused, unused, unused)
|
||||
float k = 1.0 / uParam.x; // inverted texture size
|
||||
|
||||
vec4 color = vec4(0.0);
|
||||
for (float y = -1.5; y < 2.0; y++)
|
||||
for (float x = -1.5; x < 2.0; x++) {
|
||||
vec4 p;
|
||||
p.xyz = texture2D(sDiffuse, vTexCoord + vec2(x, y) * k).xyz;
|
||||
p.xyz = texture2D(sDiffuse, vTexCoord + vec2(x, y) * uParam.x).xyz;
|
||||
p.w = dot(p.xyz, vec3(0.299, 0.587, 0.114));
|
||||
p.xyz *= p.w;
|
||||
color += p;
|
||||
|
@@ -1,25 +1,77 @@
|
||||
#include "common.hlsl"
|
||||
|
||||
struct VS_OUTPUT {
|
||||
float4 wPos : POSITION;
|
||||
float2 vTexCoord : TEXCOORD0;
|
||||
float4 vDiffuse : COLOR0;
|
||||
float4 wpos : POSITION;
|
||||
float2 texCoord : TEXCOORD0;
|
||||
float4 diffuse : COLOR0;
|
||||
};
|
||||
|
||||
#ifdef VERTEX
|
||||
VS_OUTPUT main(VS_INPUT In) {
|
||||
VS_OUTPUT Out;
|
||||
Out.wPos = float4(In.aCoord.xy * (1.0 / 32767.0), 0.0, 1.0);
|
||||
Out.vTexCoord = In.aTexCoord.xy * (1.0 / 32767.0);
|
||||
Out.vDiffuse = In.aLight;
|
||||
Out.wpos = float4(In.aCoord.xy * (1.0 / 32767.0), 0.0, 1.0);
|
||||
Out.texCoord = In.aTexCoord.xy * (1.0 / 32767.0);
|
||||
Out.diffuse = In.aLight;
|
||||
|
||||
// D3D9 specific
|
||||
if (FILTER_DOWNSAMPLE) {
|
||||
Out.texCoord += float2(2.0, -2.0) * uParam.x;
|
||||
} else if (FILTER_BLUR) {
|
||||
Out.texCoord += float2(1.0, -1.0) * uParam.z;
|
||||
}
|
||||
|
||||
return Out;
|
||||
}
|
||||
|
||||
#else // PIXEL
|
||||
|
||||
sampler sDiffuse : register(s0);
|
||||
float4 downsample(float2 uv) { // uParam (1 / textureSize, unused, unused, unused)
|
||||
float4 color = 0.0;
|
||||
[unroll]
|
||||
for (float y = -1.5; y < 2.0; y++) {
|
||||
[unroll]
|
||||
for (float x = -1.5; x < 2.0; x++) {
|
||||
float4 p;
|
||||
p.xyz = tex2D(sDiffuse, uv + float2(x, y) * uParam.x).xyz;
|
||||
p.w = dot(p.xyz, float3(0.299, 0.587, 0.114));
|
||||
p.xyz *= p.w;
|
||||
color += p;
|
||||
}
|
||||
}
|
||||
|
||||
return float4(color.xyz / color.w, 1.0);
|
||||
}
|
||||
|
||||
float4 grayscale(float2 uv) { // uParam (factor, unused, unused, unused)
|
||||
float4 color = tex2D(sDiffuse, uv);
|
||||
float3 gray = dot(color, float4(0.299, 0.587, 0.114, 0.0));
|
||||
return float4(lerp(color.xyz, gray, uParam.x), color.w);
|
||||
}
|
||||
|
||||
float4 blur(float2 uv) { // uParam (dirX, dirY, 1 / textureSize, unused)
|
||||
const float3 offset = float3( 0.0, 1.3846153846, 3.2307692308);
|
||||
const float3 weight = float3(0.2270270270, 0.3162162162, 0.0702702703);
|
||||
|
||||
float2 dir = uParam.xy * uParam.z;
|
||||
float4 color = tex2D(sDiffuse, uv) * weight[0];
|
||||
color += tex2D(sDiffuse, uv + dir * offset[1]) * weight[1];
|
||||
color += tex2D(sDiffuse, uv - dir * offset[1]) * weight[1];
|
||||
color += tex2D(sDiffuse, uv + dir * offset[2]) * weight[2];
|
||||
color += tex2D(sDiffuse, uv - dir * offset[2]) * weight[2];
|
||||
return color;
|
||||
}
|
||||
|
||||
float4 main(VS_OUTPUT In) : COLOR0 {
|
||||
return (In.vDiffuse * tex2D(sDiffuse, In.vTexCoord.xy)).bgra;
|
||||
|
||||
if (FILTER_DOWNSAMPLE)
|
||||
return downsample(In.texCoord.xy);
|
||||
|
||||
if (FILTER_GRAYSCALE)
|
||||
return grayscale(In.texCoord.xy);
|
||||
|
||||
if (FILTER_BLUR)
|
||||
return blur(In.texCoord.xy);
|
||||
|
||||
return (tex2D(sDiffuse, In.texCoord.xy) * In.diffuse).bgra;
|
||||
}
|
||||
#endif
|
@@ -17,8 +17,6 @@ VS_OUTPUT main(VS_INPUT In) {
|
||||
|
||||
#else // PIXEL
|
||||
|
||||
sampler sDiffuse : register(s0);
|
||||
|
||||
float4 main(VS_OUTPUT In) : COLOR0 {
|
||||
return (In.vDiffuse * tex2D(sDiffuse, In.vTexCoord.xy)).bgra;
|
||||
}
|
||||
|
@@ -402,7 +402,6 @@ uniform vec4 uFogParams;
|
||||
color *= vDiffuse;
|
||||
|
||||
#if !defined(TYPE_FLASH) && !defined(TYPE_MIRROR)
|
||||
vec3 lightVec = (uLightPos[0].xyz - vCoord) * uLightColor[0].w;
|
||||
|
||||
#ifdef PASS_AMBIENT
|
||||
color.xyz *= vLight.xyz;
|
||||
@@ -410,7 +409,8 @@ uniform vec4 uFogParams;
|
||||
|
||||
#ifdef PASS_COMPOSE
|
||||
|
||||
vec3 n = normalize(vNormal.xyz);
|
||||
vec3 lightVec = (uLightPos[0].xyz - vCoord) * uLightColor[0].w;
|
||||
vec3 normal = normalize(vNormal.xyz);
|
||||
|
||||
#ifdef TYPE_ENTITY
|
||||
float rSpecular = uMaterial.z + 0.03;
|
||||
@@ -441,17 +441,17 @@ uniform vec4 uFogParams;
|
||||
#endif
|
||||
|
||||
#ifdef OPT_CAUSTICS
|
||||
light += calcCaustics(n);
|
||||
light += calcCaustics(normal);
|
||||
#endif
|
||||
|
||||
#ifdef OPT_CONTACT
|
||||
light *= getContactAO(vCoord, n) * 0.5 + 0.5;
|
||||
light *= getContactAO(vCoord, normal) * 0.5 + 0.5;
|
||||
#endif
|
||||
|
||||
color.xyz *= light;
|
||||
|
||||
#ifdef TYPE_ENTITY
|
||||
color.xyz += calcSpecular(n, vViewVec.xyz, lightVec.xyz, uLightColor[0], rSpecular);
|
||||
color.xyz += calcSpecular(normal, vViewVec.xyz, lightVec, uLightColor[0], rSpecular);
|
||||
#endif
|
||||
|
||||
#ifdef UNDERWATER
|
||||
|
@@ -44,13 +44,6 @@ VS_OUTPUT main(VS_INPUT In) {
|
||||
|
||||
#else // PIXEL
|
||||
|
||||
sampler sDiffuse : register(s0);
|
||||
sampler sNormal : register(s1);
|
||||
sampler sReflect : register(s2);
|
||||
sampler sShadow : register(s3);
|
||||
sampler sEnvironment : register(s4);
|
||||
sampler sMask : register(s5);
|
||||
|
||||
float4 main(VS_OUTPUT In) : COLOR0 {
|
||||
return (In.vDiffuse * tex2D(sDiffuse, In.vTexCoord.xy / In.vTexCoord.zw)).bgra;
|
||||
}
|
||||
|
@@ -762,7 +762,7 @@ struct Crystal : Controller {
|
||||
Texture *environment;
|
||||
|
||||
Crystal(IGame *game, int entity) : Controller(game, entity) {
|
||||
environment = new Texture(64, 64, FMT_RGBA, OPT_CUBEMAP | OPT_MIPMAPS);
|
||||
environment = new Texture(64, 64, FMT_RGBA, OPT_CUBEMAP | OPT_MIPMAPS | OPT_TARGET);
|
||||
activate();
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user