mirror of
https://github.com/XProger/OpenLara.git
synced 2025-08-20 03:41:33 +02:00
D3D reflections and water; hide dummy meshes for fire traps
This commit is contained in:
@@ -120,7 +120,7 @@ struct Animation {
|
||||
// real frame index & lerp delta
|
||||
int fIndex = int(time * 30.0f) / anim->frameRate;
|
||||
int k = fIndex * anim->frameRate;
|
||||
delta = (time * 30.0f - k) / min((int)anim->frameRate, max(1, framesCount - k)); // min is because in some cases framesCount > realFramesCount / frameRate * frameRate
|
||||
delta = (time * 30.0f - k) / max(1, min((int)anim->frameRate, framesCount - k)); // min is because in some cases framesCount > realFramesCount / frameRate * frameRate
|
||||
|
||||
int fIndexA = fIndex % fCount,
|
||||
fIndexB = (fIndex + 1) % fCount;
|
||||
|
28
src/cache.h
28
src/cache.h
@@ -446,8 +446,8 @@ struct WaterCache {
|
||||
|
||||
int *mf = new int[4 * w * 64 * h * 64];
|
||||
memset(mf, 0, sizeof(int) * 4 * w * 64 * h * 64);
|
||||
data[0] = new Texture(w * 64, h * 64, FMT_RGBA_HALF, OPT_TARGET, mf);
|
||||
data[1] = new Texture(w * 64, h * 64, FMT_RGBA_HALF, OPT_TARGET);
|
||||
data[0] = new Texture(w * 64, h * 64, FMT_RGBA_HALF, OPT_TARGET | OPT_VERTEX, mf);
|
||||
data[1] = new Texture(w * 64, h * 64, FMT_RGBA_HALF, OPT_TARGET | OPT_VERTEX);
|
||||
delete[] mf;
|
||||
|
||||
caustics = Core::settings.detail.water > Core::Settings::MEDIUM ? new Texture(512, 512, FMT_RGBA, OPT_TARGET) : NULL;
|
||||
@@ -594,11 +594,13 @@ struct WaterCache {
|
||||
void drop(Item &item) {
|
||||
if (!dropCount) return;
|
||||
|
||||
vec2 s(item.size.x * DETAIL * 2.0f, item.size.z * DETAIL * 2.0f);
|
||||
|
||||
game->setShader(Core::passWater, Shader::WATER_DROP);
|
||||
Core::active.shader->setParam(uTexParam, vec4(1.0f / item.data[0]->width, 1.0f / item.data[0]->height, 1.0f, 1.0f));
|
||||
|
||||
vec4 rPosScale[2] = { vec4(0.0f), vec4(1.0f) };
|
||||
Core::active.shader->setParam(uPosScale, rPosScale[0], 2);
|
||||
Core::active.shader->setParam(uTexParam, vec4(1.0f / item.data[0]->width, 1.0f / item.data[0]->height, s.x / item.data[0]->width, s.y / item.data[0]->height));
|
||||
|
||||
for (int i = 0; i < dropCount; i++) {
|
||||
Drop &drop = drops[i];
|
||||
@@ -606,11 +608,12 @@ struct WaterCache {
|
||||
vec3 p;
|
||||
p.x = (drop.pos.x - (item.pos.x - item.size.x)) * DETAIL;
|
||||
p.z = (drop.pos.z - (item.pos.z - item.size.z)) * DETAIL;
|
||||
|
||||
Core::active.shader->setParam(uParam, vec4(p.x, p.z, drop.radius * DETAIL, -drop.strength));
|
||||
|
||||
item.data[0]->bind(sDiffuse);
|
||||
Core::setTarget(item.data[1], RT_STORE_COLOR);
|
||||
Core::setViewport(0, 0, int(item.size.x * DETAIL * 2.0f + 0.5f), int(item.size.z * DETAIL * 2.0f + 0.5f));
|
||||
Core::setViewport(0, 0, int(s.x + 0.5f), int(s.y + 0.5f));
|
||||
game->getMesh()->renderQuad();
|
||||
swap(item.data[0], item.data[1]);
|
||||
}
|
||||
@@ -619,20 +622,25 @@ struct WaterCache {
|
||||
void step(Item &item) {
|
||||
if (item.timer < SIMULATE_TIMESTEP) return;
|
||||
|
||||
vec2 s(item.size.x * DETAIL * 2.0f, item.size.z * DETAIL * 2.0f);
|
||||
|
||||
game->setShader(Core::passWater, Shader::WATER_STEP);
|
||||
Core::active.shader->setParam(uTexParam, vec4(1.0f / item.data[0]->width, 1.0f / item.data[0]->height, 1.0f, 1.0f));
|
||||
Core::active.shader->setParam(uParam, vec4(0.995f, 1.0f, 0, Core::params.x));
|
||||
Core::active.shader->setParam(uTexParam, vec4(1.0f / item.data[0]->width, 1.0f / item.data[0]->height, s.x / item.data[0]->width, s.y / item.data[0]->height));
|
||||
|
||||
while (item.timer >= SIMULATE_TIMESTEP) {
|
||||
// water step
|
||||
item.data[0]->bind(sDiffuse);
|
||||
Core::setTarget(item.data[1], RT_STORE_COLOR);
|
||||
Core::setViewport(0, 0, int(item.size.x * DETAIL * 2.0f + 0.5f), int(item.size.z * DETAIL * 2.0f + 0.5f));
|
||||
Core::setViewport(0, 0, int(s.x + 0.5f), int(s.y + 0.5f));
|
||||
game->getMesh()->renderQuad();
|
||||
swap(item.data[0], item.data[1]);
|
||||
item.timer -= SIMULATE_TIMESTEP;
|
||||
}
|
||||
|
||||
if (Core::settings.detail.water < Core::Settings::HIGH)
|
||||
return;
|
||||
|
||||
// calc caustics
|
||||
game->setShader(Core::passWater, Shader::WATER_CAUSTICS);
|
||||
vec4 rPosScale[2] = { vec4(0.0f), vec4(32767.0f / PLANE_DETAIL) };
|
||||
@@ -641,7 +649,7 @@ struct WaterCache {
|
||||
float sx = item.size.x * DETAIL / (item.data[0]->width / 2);
|
||||
float sz = item.size.z * DETAIL / (item.data[0]->height / 2);
|
||||
|
||||
Core::active.shader->setParam(uTexParam, vec4(1.0f, 1.0f, sx, sz));
|
||||
Core::active.shader->setParam(uTexParam, vec4(0.0f, 0.0f, sx, sz));
|
||||
|
||||
Core::whiteTex->bind(sReflect);
|
||||
item.data[0]->bind(sNormal);
|
||||
@@ -711,13 +719,11 @@ struct WaterCache {
|
||||
// get refraction texture
|
||||
if (!refract || w != refract->origWidth || h != refract->origHeight) {
|
||||
delete refract;
|
||||
refract = new Texture(w, h, FMT_RGBA);
|
||||
/*
|
||||
refract = new Texture(w, h, FMT_RGBA, OPT_TARGET);
|
||||
Core::setTarget(refract, RT_CLEAR_COLOR | RT_STORE_COLOR);
|
||||
Core::validateRenderState();
|
||||
Core::setTarget(NULL, RT_STORE_COLOR);
|
||||
Core::validateRenderState();
|
||||
*/
|
||||
}
|
||||
Core::copyTarget(refract, 0, 0, int(Core::viewportDef.x), int(Core::viewportDef.y), w, h); // copy framebuffer into refraction texture
|
||||
}
|
||||
@@ -832,7 +838,7 @@ struct WaterCache {
|
||||
float sx = item.size.x * DETAIL / (item.data[0]->width / 2);
|
||||
float sz = item.size.z * DETAIL / (item.data[0]->height / 2);
|
||||
|
||||
Core::active.shader->setParam(uTexParam, vec4(1.0f, 1.0f, sx, sz));
|
||||
Core::active.shader->setParam(uTexParam, vec4(0.0f, 0.0f, sx, sz));
|
||||
|
||||
refract->bind(sDiffuse);
|
||||
reflect->bind(sReflect);
|
||||
|
@@ -350,7 +350,8 @@ enum TexOption {
|
||||
OPT_MIPMAPS = 2,
|
||||
OPT_NEAREST = 4,
|
||||
OPT_TARGET = 8,
|
||||
OPT_PROXY = 16,
|
||||
OPT_VERTEX = 16,
|
||||
OPT_PROXY = 32,
|
||||
};
|
||||
|
||||
// Pipeline State Object
|
||||
|
@@ -4153,7 +4153,10 @@ namespace TR {
|
||||
|
||||
int16 getModelIndex(Entity::Type type) const {
|
||||
//#ifndef _DEBUG
|
||||
if ((type >= Entity::AI_GUARD && type <= Entity::AI_CHECK) || (type >= Entity::GLOW_2 && type <= Entity::ENEMY_BAT_SWARM) || type == Entity::WATERFALL || type == Entity::KILL_ALL_TRIGGERS || type == Entity::VIEW_TARGET || type == Entity::SOUND_DOOR_BELL || type == Entity::SOUND_ALARM_BELL || type == Entity::TRIPWIRE)
|
||||
if ((type >= Entity::AI_GUARD && type <= Entity::AI_CHECK) ||
|
||||
(type >= Entity::GLOW_2 && type <= Entity::ENEMY_BAT_SWARM) ||
|
||||
(type == Entity::TRAP_FLAME_EMITTER || type == Entity::MIDAS_HAND) ||
|
||||
type == Entity::WATERFALL || type == Entity::KILL_ALL_TRIGGERS || type == Entity::VIEW_TARGET || type == Entity::SOUND_DOOR_BELL || type == Entity::SOUND_ALARM_BELL || type == Entity::TRIPWIRE)
|
||||
return 0;
|
||||
//#endif
|
||||
|
||||
|
@@ -229,8 +229,8 @@ namespace GAPI {
|
||||
{ 32, D3DFMT_A8R8G8B8 },
|
||||
{ 16, D3DFMT_R5G6B5 },
|
||||
{ 16, D3DFMT_A1R5G5B5 },
|
||||
{ 64, D3DFMT_A16B16G16R16F },
|
||||
{128, D3DFMT_A32B32G32R32F },
|
||||
{ 64, D3DFMT_A16B16G16R16F },
|
||||
{ 16, D3DFMT_D16 },
|
||||
{ 16, D3DFMT_D24X8 },
|
||||
};
|
||||
@@ -277,9 +277,12 @@ namespace GAPI {
|
||||
|
||||
if (Core::active.textures[sampler] != this) {
|
||||
Core::active.textures[sampler] = this;
|
||||
if (tex2D)
|
||||
if (tex2D) {
|
||||
device->SetTexture(sampler, tex2D);
|
||||
else if (texCube)
|
||||
if (opt & OPT_VERTEX) {
|
||||
device->SetTexture(D3DVERTEXTEXTURESAMPLER0 + sampler, tex2D);
|
||||
}
|
||||
} else if (texCube)
|
||||
device->SetTexture(sampler, texCube);
|
||||
|
||||
bool filter = (Core::settings.detail.filter > Core::Settings::LOW) && !(opt & OPT_NEAREST);
|
||||
@@ -291,7 +294,7 @@ namespace GAPI {
|
||||
|
||||
if (aniso) {
|
||||
device->SetSamplerState(sampler, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC);
|
||||
device->SetSamplerState(sampler, D3DSAMP_MAGFILTER, D3DTEXF_ANISOTROPIC);
|
||||
device->SetSamplerState(sampler, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
|
||||
device->SetSamplerState(sampler, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
|
||||
device->SetSamplerState(sampler, D3DSAMP_MAXANISOTROPY, support.maxAniso);
|
||||
} else {
|
||||
@@ -403,15 +406,15 @@ namespace GAPI {
|
||||
support.depthTexture = false; // SHADOW_DEPTH
|
||||
support.shadowSampler = false;
|
||||
support.discardFrame = false;
|
||||
support.texNPOT = false;
|
||||
support.texNPOT = true;
|
||||
support.texRG = false;
|
||||
support.texBorder = false;
|
||||
support.colorFloat = false;
|
||||
support.colorHalf = false;
|
||||
support.texFloatLinear = false;
|
||||
support.texFloat = false;
|
||||
support.texHalfLinear = false;
|
||||
support.texHalf = false;
|
||||
support.colorFloat = true;
|
||||
support.colorHalf = true;
|
||||
support.texFloatLinear = true;
|
||||
support.texFloat = true;
|
||||
support.texHalfLinear = true;
|
||||
support.texHalf = true;
|
||||
|
||||
#ifdef PROFILE
|
||||
support.profMarker = false;
|
||||
@@ -428,10 +431,14 @@ namespace GAPI {
|
||||
};
|
||||
|
||||
device->CreateVertexDeclaration(VERTEX_DECL, &vertexDecl);
|
||||
|
||||
defRT = defDS = NULL;
|
||||
}
|
||||
|
||||
void deinit() {
|
||||
vertexDecl->Release();
|
||||
if (defRT) defRT->Release();
|
||||
if (defDS) defDS->Release();
|
||||
}
|
||||
|
||||
void resetDevice() {
|
||||
@@ -456,6 +463,9 @@ namespace GAPI {
|
||||
res.texture->deinit();
|
||||
}
|
||||
|
||||
if (defRT) { defRT->Release(); defRT = NULL; }
|
||||
if (defDS) { defDS->Release(); defDS = NULL; }
|
||||
|
||||
D3DCHECK(device->Reset(&d3dpp));
|
||||
|
||||
// reinit texture RTs
|
||||
@@ -466,7 +476,6 @@ namespace GAPI {
|
||||
else
|
||||
res.texture->init(NULL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
mat4 ortho(float l, float r, float b, float t, float znear, float zfar) {
|
||||
@@ -493,16 +502,15 @@ namespace GAPI {
|
||||
return false;
|
||||
}
|
||||
|
||||
device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &defRT);
|
||||
device->GetDepthStencilSurface(&defDS);
|
||||
if (defRT == NULL) device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &defRT);
|
||||
if (defDS == NULL) device->GetDepthStencilSurface(&defDS);
|
||||
|
||||
device->BeginScene();
|
||||
return true;
|
||||
}
|
||||
|
||||
void endFrame() {
|
||||
device->EndScene();
|
||||
defRT->Release();
|
||||
defDS->Release();
|
||||
}
|
||||
|
||||
void resetState() {
|
||||
@@ -561,6 +569,8 @@ namespace GAPI {
|
||||
|
||||
surface->Release();
|
||||
}
|
||||
|
||||
Core::active.viewport = Viewport(0, 0, 0, 0); // forcing viewport reset
|
||||
}
|
||||
|
||||
void discardTarget(bool color, bool depth) {}
|
||||
|
@@ -1444,7 +1444,7 @@ struct Lara : Character {
|
||||
flags.invisible = true;
|
||||
if (!environment)
|
||||
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);
|
||||
game->renderEnvironment(getRoomIndex(), pos - vec3(0.0f, 384.0f, 0.0f), &environment);
|
||||
environment->generateMipMap();
|
||||
flags.invisible = false;
|
||||
}
|
||||
|
26
src/level.h
26
src/level.h
@@ -50,6 +50,7 @@ struct Level : IGame {
|
||||
|
||||
bool lastTitle;
|
||||
bool isEnded;
|
||||
bool isFirstFrame;
|
||||
|
||||
TR::Effect::Type effect;
|
||||
float effectTimer;
|
||||
@@ -686,7 +687,13 @@ struct Level : IGame {
|
||||
|
||||
Sound::listenersCount = 1;
|
||||
|
||||
if (!level.isTitle()) {
|
||||
shadow = NULL;
|
||||
camera = NULL;
|
||||
ambientCache = NULL;
|
||||
waterCache = NULL;
|
||||
zoneCache = NULL;
|
||||
|
||||
if (!(lastTitle = level.isTitle())) {
|
||||
ASSERT(players[0] != NULL);
|
||||
player = players[0];
|
||||
camera = player->camera;
|
||||
@@ -695,11 +702,8 @@ struct Level : IGame {
|
||||
ambientCache = Core::settings.detail.lighting > Core::Settings::MEDIUM ? new AmbientCache(this) : NULL;
|
||||
waterCache = Core::settings.detail.water > Core::Settings::LOW ? new WaterCache(this) : NULL;
|
||||
|
||||
shadow = NULL;
|
||||
initShadow();
|
||||
|
||||
initReflections();
|
||||
|
||||
for (int i = 0; i < level.soundSourcesCount; i++) {
|
||||
TR::SoundSource &src = level.soundSources[i];
|
||||
int flags = Sound::PAN;
|
||||
@@ -708,14 +712,7 @@ struct Level : IGame {
|
||||
playSound(src.id, vec3(float(src.x), float(src.y), float(src.z)), flags);
|
||||
}
|
||||
|
||||
lastTitle = false;
|
||||
} else {
|
||||
camera = NULL;
|
||||
ambientCache = NULL;
|
||||
waterCache = NULL;
|
||||
zoneCache = NULL;
|
||||
shadow = NULL;
|
||||
lastTitle = true;
|
||||
inventory.toggle(0, Inventory::PAGE_OPTION);
|
||||
}
|
||||
|
||||
@@ -726,6 +723,8 @@ struct Level : IGame {
|
||||
|
||||
sndWater = sndTrack = NULL;
|
||||
|
||||
isFirstFrame = true;
|
||||
|
||||
playTrack(0);
|
||||
/*
|
||||
if (level.id == TR::LVL_TR2_RIG) {
|
||||
@@ -2375,6 +2374,11 @@ struct Level : IGame {
|
||||
}
|
||||
|
||||
void renderPrepare() {
|
||||
if (isFirstFrame) {
|
||||
initReflections();
|
||||
isFirstFrame = false;
|
||||
}
|
||||
|
||||
if (ambientCache)
|
||||
ambientCache->processQueue();
|
||||
|
||||
|
@@ -429,7 +429,7 @@ HWND hWnd;
|
||||
memset(&d3dpp, 0, sizeof(d3dpp));
|
||||
d3dpp.Windowed = TRUE;
|
||||
d3dpp.BackBufferCount = 1;
|
||||
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
|
||||
d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
|
||||
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
|
||||
d3dpp.hDeviceWindow = hWnd;
|
||||
d3dpp.EnableAutoDepthStencil = TRUE;
|
||||
|
@@ -1,15 +1,15 @@
|
||||
#include "common.hlsl"
|
||||
|
||||
struct VS_OUTPUT {
|
||||
float4 pos : 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;
|
||||
float4 pos : 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;
|
||||
float4 hpos : TEXCOORD4;
|
||||
};
|
||||
|
||||
@@ -216,7 +216,7 @@ float getContactAO(float3 p, float3 n) {
|
||||
|
||||
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);
|
||||
return tex2D(sReflect, float2(cc.x, 1.0 - cc.y)).x * max(0.0, -n.y);
|
||||
}
|
||||
|
||||
float calcSpecular(float3 normal, float3 viewVec, float3 lightVec, float4 color, float intensity) {
|
||||
|
@@ -2,15 +2,12 @@
|
||||
#define MAX_CONTACTS 15
|
||||
#define WATER_FOG_DIST (1.0 / (6.0 * 1024.0))
|
||||
#define UNDERWATER_COLOR float3(0.6, 0.9, 0.9)
|
||||
#define SHADOW_NORMAL_BIAS 16.0
|
||||
#define SHADOW_CONST_BIAS 0.18
|
||||
#define PI 3.141592653589793
|
||||
|
||||
static const float3 SHADOW_TEXEL = float3(1.0 / 1024.0, 1.0 / 1024.0, 0.0);
|
||||
|
||||
#define SHADOW_NORMAL_BIAS 16.0
|
||||
#define SHADOW_CONST_BIAS 0.12
|
||||
|
||||
#define MAX_LIGHTS 4
|
||||
#define MAX_CONTACTS 15
|
||||
|
||||
struct VS_INPUT {
|
||||
float4 aCoord : POSITION;
|
||||
float4 aNormal : NORMAL;
|
||||
@@ -19,14 +16,12 @@ struct VS_INPUT {
|
||||
float4 aLight : COLOR1;
|
||||
};
|
||||
|
||||
#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
|
||||
sampler sDiffuse : register(s0);
|
||||
sampler sNormal : register(s1);
|
||||
sampler sReflect : register(s2);
|
||||
sampler sShadow : register(s3);
|
||||
sampler sEnvironment : register(s4);
|
||||
sampler sMask : register(s5);
|
||||
|
||||
bool uFlags[16] : register( b0 );
|
||||
float4 uParam : register( c0 );
|
||||
|
@@ -1,13 +1,13 @@
|
||||
@echo off
|
||||
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
|
||||
fxc /nologo /T ps_3_0 /O3 /Vn FILTER_PS /Fh filter_ps.h filter.hlsl /DPIXEL
|
||||
fxc /nologo /T vs_3_0 /O3 /Vn GUI_VS /Fh gui_vs.h gui.hlsl /DVERTEX
|
||||
fxc /nologo /T ps_3_0 /O3 /Vn GUI_PS /Fh gui_ps.h gui.hlsl /DPIXEL
|
||||
fxc /nologo /T vs_3_0 /O3 /Gec /Vn COMPOSE_VS /Fh compose_vs.h base.hlsl /DPASS_COMPOSE /DVERTEX
|
||||
fxc /nologo /T ps_3_0 /O3 /Gec /Vn COMPOSE_PS /Fh compose_ps.h base.hlsl /DPASS_COMPOSE /DPIXEL
|
||||
fxc /nologo /T vs_3_0 /O3 /Gec /Vn SHADOW_VS /Fh shadow_vs.h base.hlsl /DPASS_SHADOW /DVERTEX
|
||||
fxc /nologo /T ps_3_0 /O3 /Gec /Vn SHADOW_PS /Fh shadow_ps.h base.hlsl /DPASS_SHADOW /DPIXEL
|
||||
fxc /nologo /T vs_3_0 /O3 /Gec /Vn AMBIENT_VS /Fh ambient_vs.h base.hlsl /DPASS_AMBIENT /DVERTEX
|
||||
fxc /nologo /T ps_3_0 /O3 /Gec /Vn AMBIENT_PS /Fh ambient_ps.h base.hlsl /DPASS_AMBIENT /DPIXEL
|
||||
fxc /nologo /T vs_3_0 /O3 /Gec /Vn WATER_VS /Fh water_vs.h water.hlsl /DVERTEX
|
||||
fxc /nologo /T ps_3_0 /O3 /Gec /Vn WATER_PS /Fh water_ps.h water.hlsl /DPIXEL
|
||||
fxc /nologo /T vs_3_0 /O3 /Gec /Vn FILTER_VS /Fh filter_vs.h filter.hlsl /DVERTEX
|
||||
fxc /nologo /T ps_3_0 /O3 /Gec /Vn FILTER_PS /Fh filter_ps.h filter.hlsl /DPIXEL
|
||||
fxc /nologo /T vs_3_0 /O3 /Gec /Vn GUI_VS /Fh gui_vs.h gui.hlsl /DVERTEX
|
||||
fxc /nologo /T ps_3_0 /O3 /Gec /Vn GUI_PS /Fh gui_ps.h gui.hlsl /DPIXEL
|
@@ -1,7 +1,7 @@
|
||||
#include "common.hlsl"
|
||||
|
||||
struct VS_OUTPUT {
|
||||
float4 wpos : POSITION;
|
||||
float4 pos : POSITION;
|
||||
float2 texCoord : TEXCOORD0;
|
||||
float4 diffuse : COLOR0;
|
||||
};
|
||||
@@ -9,7 +9,7 @@ struct VS_OUTPUT {
|
||||
#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.pos = 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;
|
||||
|
||||
|
@@ -1,23 +1,23 @@
|
||||
#include "common.hlsl"
|
||||
|
||||
struct VS_OUTPUT {
|
||||
float4 wPos : POSITION;
|
||||
float2 vTexCoord : TEXCOORD0;
|
||||
float4 vDiffuse : COLOR0;
|
||||
float4 pos : POSITION;
|
||||
float2 texCoord : TEXCOORD0;
|
||||
float4 diffuse : COLOR0;
|
||||
};
|
||||
|
||||
#ifdef VERTEX
|
||||
VS_OUTPUT main(VS_INPUT In) {
|
||||
VS_OUTPUT Out;
|
||||
Out.wPos = mul(uViewProj, float4(In.aCoord.xy, 0.0, 1.0));
|
||||
Out.vTexCoord = In.aTexCoord.xy * (1.0 / 32767.0);
|
||||
Out.vDiffuse = In.aLight * uMaterial;
|
||||
Out.pos = mul(uViewProj, float4(In.aCoord.xy, 0.0, 1.0));
|
||||
Out.texCoord = In.aTexCoord.xy * (1.0 / 32767.0);
|
||||
Out.diffuse = In.aLight * uMaterial;
|
||||
return Out;
|
||||
}
|
||||
|
||||
#else // PIXEL
|
||||
|
||||
float4 main(VS_OUTPUT In) : COLOR0 {
|
||||
return (In.vDiffuse * tex2D(sDiffuse, In.vTexCoord.xy)).bgra;
|
||||
return (In.diffuse * tex2D(sDiffuse, In.texCoord.xy)).bgra;
|
||||
}
|
||||
#endif
|
@@ -10,11 +10,14 @@ R"====(
|
||||
varying vec3 vCoord;
|
||||
varying vec2 vTexCoord;
|
||||
varying vec4 vProjCoord;
|
||||
varying vec4 vOldPos;
|
||||
varying vec4 vNewPos;
|
||||
varying vec3 vViewVec;
|
||||
varying vec3 vLightVec;
|
||||
|
||||
#ifdef WATER_CAUSTICS
|
||||
varying vec3 vOldPos;
|
||||
varying vec3 vNewPos;
|
||||
#endif
|
||||
|
||||
uniform vec4 uViewPos;
|
||||
uniform mat4 uViewProj;
|
||||
uniform vec4 uLightPos;
|
||||
@@ -26,9 +29,6 @@ uniform vec4 uParam;
|
||||
uniform sampler2D sNormal;
|
||||
|
||||
#ifdef VERTEX
|
||||
#define ETA_AIR 1.000
|
||||
#define ETA_WATER 1.333
|
||||
|
||||
attribute vec4 aCoord;
|
||||
|
||||
void main() {
|
||||
@@ -59,12 +59,11 @@ uniform sampler2D sNormal;
|
||||
vec3 refOld = refract(-light, vec3(0.0, 0.0, 1.0), 0.75);
|
||||
vec3 refNew = refract(-light, normal, 0.75);
|
||||
|
||||
vOldPos = vec4(rCoord + refOld * (-1.0 / refOld.z) + refOld * ((-refOld.z - 1.0) / refOld.z), 1.0);
|
||||
vNewPos = vec4(rCoord + refNew * ((info.r - 1.0) / refNew.z) + refOld * ((-refNew.z - 1.0) / refOld.z), 1.0);
|
||||
vOldPos = rCoord + refOld * (-1.0 / refOld.z) + refOld * ((-refOld.z - 1.0) / refOld.z);
|
||||
vNewPos = rCoord + refNew * ((info.r - 1.0) / refNew.z) + refOld * ((-refNew.z - 1.0) / refOld.z);
|
||||
|
||||
gl_Position = vec4(vNewPos.xy + refOld.xy / refOld.z, 0.0, 1.0);
|
||||
#else
|
||||
vOldPos = vNewPos = vec4(0.0);
|
||||
gl_Position = vec4(coord.xyz, 1.0);
|
||||
#endif
|
||||
#endif
|
||||
@@ -91,10 +90,9 @@ uniform sampler2D sNormal;
|
||||
}
|
||||
|
||||
vec4 drop() {
|
||||
vec2 tc = gl_FragCoord.xy * uTexParam.xy;
|
||||
vec4 v = texture2D(sDiffuse, tc);
|
||||
vec4 v = texture2D(sDiffuse, vTexCoord);
|
||||
|
||||
float drop = max(0.0, 1.0 - length(uParam.xy - gl_FragCoord.xy) / uParam.z);
|
||||
float drop = max(0.0, 1.0 - length(uParam.xy - vTexCoord / uTexParam.xy) / uParam.z);
|
||||
drop = 0.5 - cos(drop * PI) * 0.5;
|
||||
v.x += drop * uParam.w;
|
||||
|
||||
@@ -133,7 +131,7 @@ uniform sampler2D sNormal;
|
||||
}
|
||||
|
||||
vec4 calc() {
|
||||
vec2 tc = gl_FragCoord.xy * uTexParam.xy;
|
||||
vec2 tc = vTexCoord;
|
||||
|
||||
if (texture2D(sMask, tc).x < 0.5)
|
||||
return vec4(0.0);
|
||||
@@ -160,10 +158,10 @@ uniform sampler2D sNormal;
|
||||
}
|
||||
#ifdef WATER_CAUSTICS
|
||||
vec4 caustics() {
|
||||
float rOldArea = length(dFdx(vOldPos.xyz)) * length(dFdy(vOldPos.xyz));
|
||||
float rNewArea = length(dFdx(vNewPos.xyz)) * length(dFdy(vNewPos.xyz));
|
||||
float rOldArea = length(dFdx(vOldPos)) * length(dFdy(vOldPos));
|
||||
float rNewArea = length(dFdx(vNewPos)) * length(dFdy(vNewPos));
|
||||
rNewArea = max(rNewArea, 0.00002); // WebGL NVIDIA workaround >_<
|
||||
float value = clamp(rOldArea / rNewArea * 0.2, 0.0, 1.0) * vOldPos.w;
|
||||
float value = clamp(rOldArea / rNewArea * 0.2, 0.0, 1.0);
|
||||
return vec4(value, 0.0, 0.0, 0.0);
|
||||
}
|
||||
#endif
|
||||
|
@@ -1,50 +1,213 @@
|
||||
#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 pos : POSITION;
|
||||
float3 coord : TEXCOORD0;
|
||||
float2 texCoord : TEXCOORD1;
|
||||
float3 viewVec : TEXCOORD2;
|
||||
float3 lightVec : TEXCOORD3;
|
||||
float3 oldPos : TEXCOORD4;
|
||||
float3 newPos : TEXCOORD5;
|
||||
float4 hpos : TEXCOORD6;
|
||||
};
|
||||
|
||||
#ifdef VERTEX
|
||||
float3 mulQuat(float4 q, float3 v) {
|
||||
return v + 2.0 * cross(q.xyz, cross(q.xyz, v) + v * q.w);
|
||||
float2 invUV(float2 uv) {
|
||||
return float2(uv.x, 1.0 - uv.y);
|
||||
}
|
||||
|
||||
float3 mulBasis(float4 rot, float3 pos, float3 v) {
|
||||
return mulQuat(rot, v) + pos;
|
||||
float3 getInvUV(float2 uv, float4 param) {
|
||||
return float3((float2(uv.x, -uv.y) * 0.5 + 0.5) * param.zw + 0.5 * param.xy, 0.0);
|
||||
}
|
||||
|
||||
|
||||
#ifdef VERTEX
|
||||
VS_OUTPUT main(VS_INPUT In) {
|
||||
VS_OUTPUT Out;
|
||||
|
||||
float3 coord = In.aCoord.xyz * (1.0 / 32767.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));
|
||||
if (WATER_COMPOSE) {
|
||||
Out.coord = float3(coord.x, 0.0, coord.y) * uPosScale[1].xyz + uPosScale[0].xyz;
|
||||
Out.pos = mul(uViewProj, float4(Out.coord, 1.0));
|
||||
Out.viewVec = uViewPos.xyz - Out.coord.xyz;
|
||||
Out.lightVec = uLightPos[0].xyz - Out.coord.xyz;
|
||||
Out.oldPos = getInvUV(coord.xy, uTexParam);
|
||||
} else if (WATER_DROP) {
|
||||
Out.pos = float4(coord.xyz, 1.0);
|
||||
Out.oldPos = getInvUV(coord.xy, uTexParam);
|
||||
} else if (WATER_STEP) {
|
||||
Out.pos = float4(coord.xyz, 1.0);
|
||||
Out.oldPos = getInvUV(coord.xy, uTexParam);
|
||||
} else if (WATER_CAUSTICS) {
|
||||
float3 rCoord = float3(coord.x, coord.y, 0.0) * uPosScale[1].xzy;
|
||||
float2 uv = getInvUV(rCoord.xy, uTexParam).xy;
|
||||
float4 info = tex2Dlod(sNormal, float4(uv, 0, 0));
|
||||
float3 normal = float3(info.z, info.w, sqrt(1.0 - dot(info.zw, info.zw)));
|
||||
|
||||
Out.vTexCoord = In.aTexCoord * (1.0 / 32767.0);
|
||||
Out.vTexCoord.xy *= Out.vTexCoord.zw;
|
||||
float3 light = float3(0.0, 0.0, 1.0);
|
||||
float3 refOld = refract(-light, float3(0.0, 0.0, 1.0), 0.75);
|
||||
float3 refNew = refract(-light, normal, 0.75);
|
||||
|
||||
Out.vDiffuse = float4(In.aColor.xyz * In.aLight.xyz, 1.0);
|
||||
Out.vNormal = In.aNormal;
|
||||
Out.vViewVec = float4(uViewPos.xyz - Out.vCoord, 0.0);
|
||||
Out.vAmbient = float3(0.2, 0.2, 0.2);
|
||||
Out.vLightMap = float4(1.0, 1.0, 1.0, 0.0);
|
||||
Out.vLight = float4(0.5, 0.5, 0.5, 0.5);
|
||||
Out.oldPos = rCoord + refOld * (-1.0 / refOld.z) + refOld * ((-refOld.z - 1.0) / refOld.z);
|
||||
Out.newPos = rCoord + refNew * ((info.r - 1.0) / refNew.z) + refOld * ((-refNew.z - 1.0) / refOld.z);
|
||||
|
||||
Out.pos = float4(Out.newPos.xy + refOld.xy / refOld.z, 0.0, 1.0);
|
||||
} else if (WATER_MASK) {
|
||||
Out.coord = float3(coord.x, 0.0, coord.y) * uPosScale[1].xyz + uPosScale[0].xyz;
|
||||
Out.pos = mul(uViewProj, float4(Out.coord, 1.0));
|
||||
}
|
||||
|
||||
Out.texCoord = (coord.xy * 0.5 + 0.5) * uTexParam.zw + 0.5 * uTexParam.xy; // + half texel offset
|
||||
Out.hpos = Out.pos;
|
||||
|
||||
return Out;
|
||||
}
|
||||
|
||||
#else // PIXEL
|
||||
|
||||
float calcFresnel(float NdotL, float fbias) {
|
||||
float f = 1.0 - NdotL;
|
||||
return saturate(fbias + (1.0 - fbias) * (f * f));
|
||||
}
|
||||
|
||||
float3 applyFog(float3 color, float3 fogColor, float factor) {
|
||||
float fog = saturate(1.0 / exp(factor));
|
||||
return lerp(fogColor, color, fog);
|
||||
}
|
||||
|
||||
float4 drop(VS_OUTPUT In) {
|
||||
float2 iuv = In.oldPos.xy;
|
||||
|
||||
float4 v = tex2D(sDiffuse, iuv);
|
||||
|
||||
float drop = max(0.0, 1.0 - length(uParam.xy - In.texCoord / uTexParam.xy) / uParam.z);
|
||||
drop = 0.5 - cos(drop * PI) * 0.5;
|
||||
|
||||
v.x += drop * uParam.w;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
float3 hash33(float3 p3) {
|
||||
p3 = frac(p3 * float3(.1031,.11369,.13787));
|
||||
p3 += dot(p3, p3.yxz+19.19);
|
||||
return -1.0 + 2.0 * frac(float3((p3.x + p3.y)*p3.z, (p3.x+p3.z)*p3.y, (p3.y+p3.z)*p3.x));
|
||||
}
|
||||
|
||||
float simplex_noise(float3 p) { // https://www.shadertoy.com/view/4sc3z2
|
||||
const float K1 = 0.333333333;
|
||||
const float K2 = 0.166666667;
|
||||
|
||||
float3 i = floor(p + (p.x + p.y + p.z) * K1);
|
||||
float3 d0 = p - (i - (i.x + i.y + i.z) * K2);
|
||||
|
||||
float3 e = step((float3)0.0, d0 - d0.yzx);
|
||||
float3 i1 = e * (1.0 - e.zxy);
|
||||
float3 i2 = 1.0 - e.zxy * (1.0 - e);
|
||||
|
||||
float3 d1 = d0 - (i1 - 1.0 * K2);
|
||||
float3 d2 = d0 - (i2 - 2.0 * K2);
|
||||
float3 d3 = d0 - (1.0 - 3.0 * K2);
|
||||
|
||||
float4 h = max(0.6 - float4(dot(d0, d0), dot(d1, d1), dot(d2, d2), dot(d3, d3)), 0.0);
|
||||
float4 n = h * h * h * h * float4(dot(d0, hash33(i)), dot(d1, hash33(i + i1)), dot(d2, hash33(i + i2)), dot(d3, hash33(i + 1.0)));
|
||||
|
||||
return dot((float4)31.316, n);
|
||||
}
|
||||
|
||||
float h(float2 tc) {
|
||||
return simplex_noise(float3(tc * 16.0, uParam.w)) * 0.0005;
|
||||
}
|
||||
|
||||
float4 calc(VS_OUTPUT In) {
|
||||
float2 iuv = In.oldPos.xy;
|
||||
float2 uv = In.texCoord;
|
||||
|
||||
if (tex2D(sMask, uv).x < 0.5)
|
||||
return 0.0;
|
||||
|
||||
float4 v = tex2D(sDiffuse, iuv); // height, speed, normal.xz
|
||||
|
||||
float3 d = float3(float2(uTexParam.x, -uTexParam.y), 0.0);
|
||||
float4 f = float4(
|
||||
tex2D(sDiffuse, iuv + d.xz).x, tex2D(sDiffuse, iuv + d.zy).x,
|
||||
tex2D(sDiffuse, iuv - d.xz).x, tex2D(sDiffuse, iuv - d.zy).x
|
||||
);
|
||||
|
||||
float average = dot(f, (float4)0.25);
|
||||
|
||||
// normal
|
||||
v.zw = normalize( float3(f.x - f.z, 64.0 / (1024.0 * 4.0), f.y - f.w) ).xz;
|
||||
|
||||
// integrate
|
||||
const float vel = 1.4;
|
||||
const float vis = 0.995;
|
||||
|
||||
v.y += (average - v.x) * vel;
|
||||
v.y *= vis;
|
||||
v.x += v.y + h(uv);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
float4 caustics(VS_OUTPUT In) {
|
||||
float rOldArea = length(ddx(In.oldPos)) * length(ddy(In.oldPos));
|
||||
float rNewArea = length(ddx(In.newPos)) * length(ddy(In.newPos));
|
||||
rNewArea = max(rNewArea, 0.00002); // WebGL NVIDIA workaround >_<
|
||||
float value = saturate(rOldArea / rNewArea * 0.2);
|
||||
return float4(value, 0.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
float4 mask(VS_OUTPUT In) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
float4 compose(VS_OUTPUT In) {
|
||||
float3 viewVec = normalize(In.viewVec);
|
||||
float2 iuv = In.oldPos.xy;
|
||||
|
||||
float4 value = tex2D(sNormal, iuv);
|
||||
float3 normal = float3(value.z, sqrt(1.0 - dot(value.zw, value.zw)) * sign(viewVec.y), value.w);
|
||||
float2 dudv = mul(uViewProj, float4(normal.x, 0.0, normal.z, 0.0)).xy;
|
||||
|
||||
float3 rv = reflect(-viewVec, normal);
|
||||
float3 lv = normalize(In.lightVec);
|
||||
|
||||
float spec = pow(max(0.0, dot(rv, lv)), 64.0) * 0.5;
|
||||
|
||||
float2 tc = In.hpos.xy / In.hpos.w * 0.5 + 0.5;
|
||||
|
||||
float4 refrA = tex2D(sDiffuse, uParam.xy * invUV(clamp(tc + dudv * uParam.z, 0.0, 0.999)) );
|
||||
float4 refrB = tex2D(sDiffuse, uParam.xy * invUV(tc) );
|
||||
float4 refr = float4(lerp(refrA.xyz, refrB.xyz, refrA.w), 1.0);
|
||||
float4 refl = tex2D(sReflect, tc.xy + dudv * uParam.w);
|
||||
|
||||
float fresnel = calcFresnel(dot(normal, viewVec), 0.04);
|
||||
|
||||
float4 color = lerp(refr, refl, fresnel) + spec * 1.5;
|
||||
|
||||
float d = abs((In.coord.y - uViewPos.y) / normalize(In.viewVec).y);
|
||||
d *= step(0.0, uViewPos.y - In.coord.y); // apply fog only when camera is underwater
|
||||
color.xyz = applyFog(color.xyz, UNDERWATER_COLOR * 0.2, d * WATER_FOG_DIST);
|
||||
color.w *= tex2D(sMask, In.texCoord).x;
|
||||
return color;
|
||||
}
|
||||
|
||||
float4 main(VS_OUTPUT In) : COLOR0 {
|
||||
return (In.vDiffuse * tex2D(sDiffuse, In.vTexCoord.xy / In.vTexCoord.zw)).bgra;
|
||||
if (WATER_DROP)
|
||||
return drop(In);
|
||||
|
||||
if (WATER_STEP)
|
||||
return calc(In);
|
||||
|
||||
if (WATER_CAUSTICS)
|
||||
return caustics(In);
|
||||
|
||||
if (WATER_MASK)
|
||||
return mask(In);
|
||||
|
||||
if (WATER_COMPOSE)
|
||||
return compose(In);
|
||||
|
||||
return float4(1.0, 0.0, 1.0, 1.0);
|
||||
}
|
||||
#endif
|
Reference in New Issue
Block a user