1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-15 09:34:18 +02:00

remove atlas shadows; add D3D9 shadows; fix water rat and crocodile bug

This commit is contained in:
XProger
2018-05-19 01:34:16 +03:00
parent 2a93b0e911
commit d6e1d42927
16 changed files with 295 additions and 196 deletions

View File

@@ -33,6 +33,7 @@ struct ShaderCache {
prepareFilter(FX_NONE);
prepareGUI(FX_NONE);
Core::resetTime();
LOG("shader: cache is ready\n");
}
@@ -148,12 +149,8 @@ struct ShaderCache {
SD_ADD(CLIP_PLANE);
if (Core::settings.detail.lighting > Core::Settings::MEDIUM && (type == Shader::ENTITY))
SD_ADD(OPT_AMBIENT);
if (Core::settings.detail.shadows > Core::Settings::LOW && (type == Shader::ENTITY || type == Shader::ROOM)) {
if (Core::settings.detail.shadows > Core::Settings::LOW && (type == Shader::ENTITY || type == Shader::ROOM))
SD_ADD(OPT_SHADOW);
if (Core::settings.detail.shadows > Core::Settings::MEDIUM)
SD_ADD(OPT_SHADOW_HIGH);
}
if (Core::settings.detail.shadows > Core::Settings::MEDIUM && (type == Shader::ROOM))
SD_ADD(OPT_CONTACT);
if (Core::settings.detail.water > Core::Settings::MEDIUM && (type == Shader::ENTITY || type == Shader::ROOM) && (fx & FX_UNDERWATER))
@@ -715,11 +712,12 @@ struct WaterCache {
if (!refract || w != refract->origWidth || h != refract->origHeight) {
delete refract;
refract = new Texture(w, h, FMT_RGBA);
/*
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
}

View File

@@ -506,7 +506,7 @@ struct Camera : ICamera {
if (Core::settings.detail.stereo == Core::Settings::STEREO_VR)
Core::mProj = Input::hmd.proj[Core::eye == -1.0f ? 0 : 1];
else
Core::mProj = mat4(fov, aspect, znear, zfar);
Core::mProj = GAPI::perspective(fov, aspect, znear, zfar);
}
Core::setViewProj(Core::mView, Core::mProj);
@@ -531,9 +531,6 @@ struct Camera : ICamera {
fov = firstPerson ? 90.0f : 65.0f;
znear = firstPerson ? 8.0f : 32.0f;
#ifdef _OS_PSP
znear = 256.0f;
#endif
zfar = 45.0f * 1024.0f;
}
};

View File

@@ -85,14 +85,8 @@
#include "utils.h"
// muse be equal with base shader
#define SHADOW_OBJ_COLS 4
#define SHADOW_OBJ_ROWS 2
#define SHADOW_TEX_TILE 128
#define SHADOW_TEX_BIG_WIDTH 1024
#define SHADOW_TEX_BIG_HEIGHT 1024
#define SHADOW_TEX_WIDTH (SHADOW_OBJ_COLS * SHADOW_TEX_TILE)
#define SHADOW_TEX_HEIGHT (SHADOW_OBJ_ROWS * SHADOW_TEX_TILE)
#define SHADOW_OBJ_MAX (SHADOW_OBJ_COLS * SHADOW_OBJ_ROWS)
#define SHADOW_TEX_WIDTH 1024
#define SHADOW_TEX_HEIGHT 1024
extern void* osMutexInit ();
extern void osMutexFree (void *obj);
@@ -340,14 +334,12 @@ enum RenderState {
// Texture image format
enum TexFormat {
FMT_LUMINANCE,
FMT_RGBA,
FMT_RGB16,
FMT_RGBA16,
FMT_RGBA_FLOAT,
FMT_RGBA_HALF,
FMT_DEPTH,
FMT_DEPTH_STENCIL,
FMT_SHADOW,
FMT_MAX,
};
@@ -453,7 +445,6 @@ struct MeshRange {
E( CLIP_PLANE ) \
E( OPT_AMBIENT ) \
E( OPT_SHADOW ) \
E( OPT_SHADOW_HIGH ) \
E( OPT_CONTACT ) \
E( OPT_CAUSTICS )
@@ -490,7 +481,7 @@ namespace Core {
float eye;
Viewport viewport, viewportDef;
mat4 mModel, mView, mProj, mViewProj, mViewInv;
mat4 mLightProj[SHADOW_OBJ_MAX];
mat4 mLightProj;
Basis basis;
vec4 viewPos;
vec4 lightPos[MAX_LIGHTS];

View File

@@ -794,6 +794,11 @@ struct Rat : Enemy {
bool water = getRoom().flags.water;
int modelIndex = water ? modelWater : modelLand;
if (modelIndex == -1) {
water = modelWater != -1;
modelIndex = water ? modelWater : modelLand;
}
ASSERT(modelIndex > -1);
const TR::Model *model = &level->models[modelIndex];
if (animation.model != model) {
@@ -985,6 +990,11 @@ struct Crocodile : Enemy {
bool water = getRoom().flags.water;
int modelIndex = water ? modelWater : modelLand;
if (modelIndex == -1) {
water = modelWater != -1;
modelIndex = water ? modelWater : modelLand;
}
ASSERT(modelIndex > -1);
const TR::Model *model = &level->models[modelIndex];
if (animation.model != model) {

View File

@@ -70,7 +70,7 @@ namespace GAPI {
int cullMode, blendMode;
uint32 clearColor;
LPDIRECT3DSURFACE9 defBackBuffer;
LPDIRECT3DSURFACE9 defRT, defDS;
LPDIRECT3DVERTEXDECLARATION9 vertexDecl;
@@ -118,15 +118,15 @@ namespace GAPI {
{ 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
{ 74, USAGE_VS | USAGE_PS }, // uMaterial
{ 75, USAGE_VS | USAGE_PS }, // uAmbient
{ 81, USAGE_VS | USAGE_PS }, // uFogParams
{ 82, USAGE_VS | USAGE_PS }, // uViewPos
{ 83, USAGE_VS | USAGE_PS }, // uLightPos
{ 87, USAGE_VS | USAGE_PS }, // uLightColor
{ 91, USAGE_VS | USAGE_PS }, // uRoomSize
{ 92, USAGE_VS | USAGE_PS }, // uPosScale
{ 94, USAGE_VS | USAGE_PS }, // uContacts
};
struct Shader {
@@ -159,9 +159,8 @@ namespace GAPI {
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;
case SD_OPT_CONTACT : flags[10] = TRUE; break;
case SD_OPT_CAUSTICS : flags[11] = TRUE; break;
}
}
@@ -218,26 +217,22 @@ namespace GAPI {
void init(void *data) {
ASSERT((opt & OPT_PROXY) == 0);
bool filter = (opt & OPT_NEAREST) == 0;
bool isDepth = fmt == FMT_DEPTH || fmt == FMT_SHADOW;
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;
bool isTarget = (opt & OPT_TARGET) != 0 && !isDepth;
static const struct FormatDesc {
int bpp;
D3DFORMAT format;
} formats[FMT_MAX] = {
{ 8, D3DFMT_L8 },
{ 32, D3DFMT_A8R8G8B8 },
{ 16, D3DFMT_R5G6B5 },
{ 16, D3DFMT_A1R5G5B5 },
{ 64, D3DFMT_A16B16G16R16 },
{ 64, D3DFMT_A16B16G16R16 },
{ 16, D3DFMT_D16 },
{ 32, D3DFMT_D24S8 },
{ 64, D3DFMT_A16B16G16R16F },
{128, D3DFMT_A32B32G32R32F },
{ 16, D3DFMT_D16 },
{ 16, D3DFMT_D24X8 },
};
FormatDesc desc = formats[fmt];
@@ -247,7 +242,7 @@ namespace GAPI {
if (isDepth) usage |= D3DUSAGE_DEPTHSTENCIL;
if (isTarget) usage |= D3DUSAGE_RENDERTARGET;
D3DPOOL pool = isTarget ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED;
D3DPOOL pool = (isTarget || isDepth) ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED;
if (cube) {
D3DCHECK(device->CreateCubeTexture(width, 1, usage, desc.format, pool, &texCube, NULL));
@@ -387,7 +382,7 @@ namespace GAPI {
struct RenderTargetCache {
int count;
struct Item {
// GLuint ID;
LPDIRECT3DSURFACE9 surface;
int width;
int height;
} items[MAX_RENDER_BUFFERS];
@@ -404,8 +399,8 @@ namespace GAPI {
support.maxAniso = 8;
support.maxVectors = 16;
support.shaderBinary = false;
support.VAO = false;
support.depthTexture = false;
support.VAO = false; // SHADOW_COLOR
support.depthTexture = false; // SHADOW_DEPTH
support.shadowSampler = false;
support.discardFrame = false;
support.texNPOT = false;
@@ -440,6 +435,15 @@ namespace GAPI {
}
void resetDevice() {
// release dummy RTs
for (int i = 0; i < 2; i++) {
RenderTargetCache &cache = rtCache[i];
for (int j = 0; j < cache.count; j++)
cache.items[j].surface->Release();
cache.count = 0;
}
// release texture RTs
int tmpCount = resCount;
Resource tmpList[256];
memcpy(tmpList, resList, sizeof(Resource) * tmpCount);
@@ -454,6 +458,7 @@ namespace GAPI {
D3DCHECK(device->Reset(&d3dpp));
// reinit texture RTs
for (int i = 0; i < tmpCount; i++) {
Resource &res = tmpList[i];
if (res.mesh)
@@ -464,6 +469,14 @@ namespace GAPI {
}
mat4 ortho(float l, float r, float b, float t, float znear, float zfar) {
return mat4(mat4::PROJ_ZERO_POS, l, r, b, t, znear, zfar);
}
mat4 perspective(float fov, float aspect, float znear, float zfar) {
return mat4(mat4::PROJ_ZERO_POS, fov, aspect, znear, zfar);
}
bool beginFrame() {
switch (device->TestCooperativeLevel()) {
case D3D_OK :
@@ -480,14 +493,16 @@ namespace GAPI {
return false;
}
device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &defBackBuffer);
device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &defRT);
device->GetDepthStencilSurface(&defDS);
device->BeginScene();
return true;
}
void endFrame() {
device->EndScene();
defBackBuffer->Release();
defRT->Release();
defDS->Release();
}
void resetState() {
@@ -509,34 +524,42 @@ namespace GAPI {
RenderTargetCache::Item &item = cache.items[cache.count];
item.width = width;
item.height = height;
/*
glGenRenderbuffers(1, &item.ID);
glBindRenderbuffer(GL_RENDERBUFFER, item.ID);
glRenderbufferStorage(GL_RENDERBUFFER, depth ? GL_RGB565 : GL_DEPTH_COMPONENT16, width, height);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
*/
if (depth)
device->CreateDepthStencilSurface(width, height, D3DFMT_D16, D3DMULTISAMPLE_NONE, 0, true, &item.surface, NULL);
else
device->CreateRenderTarget(width, height, D3DFMT_R5G6B5, D3DMULTISAMPLE_NONE, 0, false, &item.surface, NULL);
return cache.count++;
}
void bindTarget(Texture *target, int face) {
if (!target) { // may be a null
D3DCHECK(device->SetRenderTarget(0, defBackBuffer));
D3DCHECK(device->SetRenderTarget(0, defRT));
D3DCHECK(device->SetDepthStencilSurface(defDS));
} else {
ASSERT(target->opt & OPT_TARGET);
LPDIRECT3DSURFACE9 surface;
if (target->tex2D)
bool depth = target->fmt == FMT_DEPTH || target->fmt == FMT_SHADOW;
if (target->tex2D) {
D3DCHECK(target->tex2D->GetSurfaceLevel(0, &surface));
else if (target->texCube)
} else if (target->texCube)
D3DCHECK(target->texCube->GetCubeMapSurface(D3DCUBEMAP_FACES(D3DCUBEMAP_FACE_POSITIVE_X + face), 0, &surface));
int rtIndex = cacheRenderTarget(!depth, target->width, target->height);
if (depth) {
D3DCHECK(device->SetRenderTarget(0, rtCache[false].items[rtIndex].surface));
D3DCHECK(device->SetDepthStencilSurface(surface));
} else {
D3DCHECK(device->SetRenderTarget(0, surface));
D3DCHECK(device->SetDepthStencilSurface(rtCache[true].items[rtIndex].surface));
}
surface->Release();
bool depth = target->fmt == FMT_DEPTH || target->fmt == FMT_SHADOW;
int rtIndex = cacheRenderTarget(depth, target->width, target->height);
}
}
@@ -551,7 +574,7 @@ namespace GAPI {
RECT srcRect = { x, y, x + width, y + height },
dstRect = { xOffset, yOffset, xOffset + width, yOffset + height };
device->StretchRect(defBackBuffer, &srcRect, surface, &dstRect, D3DTEXF_POINT);
device->StretchRect(defRT, &srcRect, surface, &dstRect, D3DTEXF_POINT);
surface->Release();
}

View File

@@ -547,14 +547,12 @@ namespace GAPI {
GLuint ifmt, fmt;
GLenum type;
} formats[FMT_MAX] = {
{ GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE }, // LUMINANCE
{ GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE }, // RGBA
{ GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 }, // RGB16
{ GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 }, // RGBA16
{ GL_RGBA32F, GL_RGBA, GL_FLOAT }, // RGBA_FLOAT
{ GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT }, // RGBA_HALF
{ GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT }, // DEPTH
{ GL_DEPTH_STENCIL, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8 }, // DEPTH_STENCIL
{ GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT }, // SHADOW
};
@@ -978,6 +976,14 @@ namespace GAPI {
glDeleteRenderbuffers(1, &rtCache[b].items[i].ID);
}
mat4 ortho(float l, float r, float b, float t, float znear, float zfar) {
return mat4(mat4::PROJ_NEG_POS, l, r, b, t, znear, zfar);
}
mat4 perspective(float fov, float aspect, float znear, float zfar) {
return mat4(mat4::PROJ_NEG_POS, fov, aspect, znear, zfar);
}
bool beginFrame() {
return true;
}
@@ -1008,7 +1014,7 @@ namespace GAPI {
glGenRenderbuffers(1, &item.ID);
glBindRenderbuffer(GL_RENDERBUFFER, item.ID);
glRenderbufferStorage(GL_RENDERBUFFER, depth ? GL_RGB565 : GL_DEPTH_COMPONENT16, width, height);
glRenderbufferStorage(GL_RENDERBUFFER, depth ? GL_DEPTH_COMPONENT16 : GL_RGB565, width, height);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
return cache.count++;
}
@@ -1023,11 +1029,11 @@ namespace GAPI {
bool depth = target->fmt == FMT_DEPTH || target->fmt == FMT_SHADOW;
int rtIndex = cacheRenderTarget(depth, target->width, target->height);
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);
glFramebufferRenderbuffer (GL_FRAMEBUFFER, depth ? GL_COLOR_ATTACHMENT0 : GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rtCache[!depth].items[rtIndex].ID);
}
}

View File

@@ -289,6 +289,14 @@ namespace GAPI {
delete[] cmdBuf;
}
mat4 ortho(float l, float r, float b, float t, float znear, float zfar) {
return mat4(mat4::PROJ_ZERO_POS, l, r, b, t, znear, zfar);
}
mat4 perspective(float fov, float aspect, float znear, float zfar) {
return mat4(mat4::PROJ_ZERO_POS, fov, aspect, znear, zfar);
}
bool beginFrame() {
return true;
}

View File

@@ -1496,7 +1496,7 @@ struct Inventory {
if (Core::settings.detail.stereo == Core::Settings::STEREO_VR)
Core::mProj = Input::hmd.proj[Core::eye == -1.0f ? 0 : 1];
else
Core::mProj = mat4(70.0f, aspect, 32.0f, 2048.0f);
Core::mProj = GAPI::perspective(70.0f, aspect, 32.0f, 2048.0f);
Core::mView = Core::mViewInv.inverseOrtho();
Core::viewPos = Core::mViewInv.getPos();
@@ -1514,8 +1514,7 @@ struct Inventory {
// items
game->setupBinding();
for (int i = 0; i < SHADOW_OBJ_MAX; i++)
Core::mLightProj[i].identity();
Core::mLightProj.identity();
setupCamera(aspect);

View File

@@ -229,10 +229,8 @@ struct Level : IGame {
void initShadow() {
delete shadow;
if (Core::settings.detail.shadows > Core::Settings::MEDIUM)
shadow = new Texture(SHADOW_TEX_WIDTH, SHADOW_TEX_HEIGHT, FMT_SHADOW);
else if (Core::settings.detail.shadows > Core::Settings::LOW)
shadow = new Texture(SHADOW_TEX_BIG_WIDTH, SHADOW_TEX_BIG_HEIGHT, FMT_SHADOW);
if (Core::settings.detail.shadows > Core::Settings::LOW)
shadow = new Texture(SHADOW_TEX_WIDTH, SHADOW_TEX_HEIGHT, FMT_SHADOW, OPT_TARGET);
else
shadow = NULL;
}
@@ -1961,7 +1959,7 @@ struct Level : IGame {
Core::mViewInv = mat4(pos, pos + dir, up);
Core::mView = Core::mViewInv.inverseOrtho();
Core::mProj = mat4(90, 1.0f, camera->znear, camera->zfar);
Core::mProj = GAPI::perspective(90, 1.0f, camera->znear, camera->zfar);
Core::mViewProj = Core::mProj * Core::mView;
Core::viewPos = Core::mViewInv.offset().xyz();
@@ -1971,15 +1969,17 @@ struct Level : IGame {
void renderShadowView(int roomIndex) {
vec3 pos = player->getBoundingBox().center();
float znear = camera->znear;
float zfar = player->mainLightColor.w * 1.5f;
Core::mViewInv = mat4(player->mainLightPos, pos, vec3(0, -1, 0));
Core::mView = Core::mViewInv.inverseOrtho();
Core::mProj = mat4(90.0f, 1.0f, camera->znear, player->mainLightColor.w * 1.5f);
Core::mProj = GAPI::perspective(90.0f, 1.0f, znear, zfar);
mat4 bias;
bias.identity();
bias.e03 = bias.e13 = bias.e23 = bias.e00 = bias.e11 = bias.e22 = 0.5f;
Core::mLightProj[0] = bias * (Core::mProj * Core::mView);
//bias.e03 = bias.e13 = bias.e23 = bias.e00 = bias.e11 = bias.e22 = 0.5f;
Core::mLightProj = bias * (Core::mProj * Core::mView);
camera->frustum->pos = Core::viewPos.xyz();
camera->frustum->calcPlanes(Core::mViewProj);
@@ -1987,7 +1987,7 @@ struct Level : IGame {
setup();
renderView(roomIndex, false, false);
}
/*
void renderShadowEntity(int index, Controller *controller, Controller *player) {
Box box = controller->getSpheresBox(true);
mat4 m = controller->getMatrix();
@@ -2086,7 +2086,7 @@ struct Level : IGame {
return count;
}
*/
void renderShadows(int roomIndex) {
PROFILE_MARKER("PASS_SHADOW");
@@ -2104,10 +2104,10 @@ struct Level : IGame {
if (colorShadow)
Core::setClearColor(vec4(1.0f));
Core::setTarget(shadow, RT_CLEAR_DEPTH | (colorShadow ? (RT_CLEAR_COLOR | RT_STORE_COLOR) : RT_STORE_DEPTH));
//Core::setCullMode(cmBack);
Core::validateRenderState();
Core::setCullMode(cmBack);
/*
if (Core::settings.detail.shadows > Core::Settings::Quality::MEDIUM) { // per-object shadow map (atlas)
NearObj nearObj[SHADOW_OBJ_MAX];
int nearCount = getNearObjects(nearObj, SHADOW_OBJ_MAX);
@@ -2120,9 +2120,10 @@ struct Level : IGame {
for (int i = nearCount; i < SHADOW_OBJ_MAX; i++)
Core::mLightProj[i].identity();
} else // all-in-one shadow map
*/
renderShadowView(roomIndex);
Core::setCullMode(cmFront);
//Core::setCullMode(cmFront);
if (colorShadow)
Core::setClearColor(vec4(0.0f));

View File

@@ -24,7 +24,7 @@ struct Shader : GAPI::Shader {
void setup() {
bind();
setParam(uViewProj, Core::mViewProj);
setParam(uLightProj, Core::mLightProj[0], Core::settings.detail.shadows > Core::Settings::Quality::MEDIUM ? SHADOW_OBJ_MAX : 1);
setParam(uLightProj, Core::mLightProj);
setParam(uViewPos, Core::viewPos);
setParam(uParam, Core::params);
setParam(uFogParams, Core::fogParams);

View File

@@ -1,7 +1,7 @@
#include "common.hlsl"
struct VS_OUTPUT {
float4 wpos : POSITION;
float4 pos : POSITION;
float3 coord : TEXCOORD0;
float4 texCoord : TEXCOORD1;
float4 viewVec : TEXCOORD2;
@@ -10,6 +10,7 @@ struct VS_OUTPUT {
float3 ambient : COLOR1;
float4 lightMap : COLOR2;
float4 light : COLOR3;
float4 hpos : TEXCOORD4;
};
#ifdef VERTEX
@@ -56,7 +57,6 @@ VS_OUTPUT main(VS_INPUT In) {
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 {
@@ -66,7 +66,6 @@ VS_OUTPUT main(VS_INPUT In) {
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;
@@ -150,15 +149,58 @@ VS_OUTPUT main(VS_INPUT In) {
}
#endif
Out.wpos = mul(uViewProj, float4(Out.coord, rBasisPos.w));
Out.pos = mul(uViewProj, float4(Out.coord, rBasisPos.w));
Out.hpos = Out.pos;
return Out;
}
#else // PIXEL
float getShadow(float3 lightVec) {
return 1.0;
float SHADOW(float2 p) {
#ifdef SHADOW_DEPTH
return tex2D(sShadow, p).x;
#else
return unpack(tex2D(sShadow, p));
#endif
}
float getShadow(float3 lightVec, float3 normal, float4 lightProj) {
float3 p = lightProj.xyz / lightProj.w;
p.y = -p.y;
p.xy = p.xy * 0.5 + 0.5;
p.z -= SHADOW_CONST_BIAS * SHADOW_TEXEL.x;
float vis = lightProj.w;
if (TYPE_ROOM) {
vis = min(vis, dot(normal, lightVec));
}
if (vis < 0.0 || p.x < 0.0 || p.y < 0.0 || p.x > 1.0 || p.y > 1.0) return 1.0;
p.z = saturate(p.z);
float4 samples = float4(
SHADOW(p.xy ),
SHADOW(p.xy + SHADOW_TEXEL.xz),
SHADOW(p.xy + SHADOW_TEXEL.zy),
SHADOW(p.xy + SHADOW_TEXEL.xy)
);
samples = step(p.zzzz, samples);
float2 f = frac(p.xy / SHADOW_TEXEL.xy);
samples.xy = lerp(samples.xz, samples.yw, f.xx);
float rShadow = lerp(samples.x, samples.y, f.y);
float fade = saturate(dot(lightVec, lightVec));
return rShadow + (1.0 - rShadow) * fade;
}
float getShadow(float3 coord, float3 lightVec, float3 normal) {
float factor = clamp(1.0 - dot(normalize(lightVec), normal), 0.0, 1.0);
factor *= SHADOW_NORMAL_BIAS;
return getShadow(lightVec, normal, mul(uLightProj, float4(coord + normal * factor, 1.0)));
}
float getContactAO(float3 p, float3 n) {
@@ -167,7 +209,7 @@ float getContactAO(float3 p, float3 n) {
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);
res *= saturate(1.0 - o);
}
return res;
}
@@ -214,7 +256,11 @@ float4 main(VS_OUTPUT In) : COLOR0 {
}
#ifdef PASS_SHADOW
return 1.0;
#ifdef SHADOW_DEPTH
return 0.0;
#else // SHADOW_COLOR
return pack(In.hpos.z / In.hpos.w);
#endif
#else
color *= In.diffuse;
@@ -241,11 +287,11 @@ float4 main(VS_OUTPUT In) : COLOR0 {
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);
float rShadow = getShadow(In.coord, lightVec, normal);
rSpecular = (uMaterial.z + 0.03) * rShadow;
light += In.ambient + uLightColor[0].xyz * (In.light.x * rShadow);
} else if (TYPE_ROOM) {
float rShadow = getShadow(lightVec);
float rShadow = getShadow(In.coord, lightVec, normal);
light += lerp(In.ambient.xyz, In.lightMap.xyz, rShadow);
} else if (TYPE_SPRITE) {
light += In.lightMap.xyz;

View File

@@ -3,6 +3,14 @@
#define WATER_FOG_DIST (1.0 / (6.0 * 1024.0))
#define UNDERWATER_COLOR float3(0.6, 0.9, 0.9)
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;
@@ -26,15 +34,15 @@ 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 );
float4 uMaterial : register( c74 );
float4 uAmbient[6] : register( c75 );
float4 uFogParams : register( c81 );
float4 uViewPos : register( c82 );
float4 uLightPos[MAX_LIGHTS] : register( c83 );
float4 uLightColor[MAX_LIGHTS] : register( c87 );
float4 uRoomSize : register( c91 );
float4 uPosScale[2] : register( c92 );
float4 uContacts[MAX_CONTACTS] : register( c94 );
#define TYPE_SPRITE uFlags[0]
#define TYPE_FLASH uFlags[1]
@@ -60,6 +68,18 @@ float4 uContacts[MAX_CONTACTS] : register( c122 );
#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]
#define OPT_CONTACT uFlags[10]
#define OPT_CAUSTICS uFlags[11]
float4 pack(float value) {
float4 bitSh = float4(256.0*256.0*256.0, 256.0*256.0, 256.0, 1.0);
float4 bitMsk = float4(0.0, 1.0/256.0, 1.0/256.0, 1.0/256.0);
float4 res = frac(value * bitSh);
res -= res.xxyz * bitMsk;
return res;
}
float unpack(float4 value) {
float4 bitSh = float4(1.0/(256.0*256.0*256.0), 1.0/(256.0*256.0), 1.0/256.0, 1.0);
return dot(value, bitSh);
}

View File

@@ -20,14 +20,8 @@ varying vec4 vTexCoord; // xy - atlas coords, zw - trapezoidal correction
#endif
#ifdef OPT_SHADOW
#ifdef OPT_SHADOW_HIGH
#define SHADOW_OBJ_MAX 8
#define SHADOW_TEXEL vec3(1.0 / 512.0, 1.0 / 256.0, 0.0)
#else
#define SHADOW_OBJ_MAX 1
#define SHADOW_TEXEL vec3(1.0 / 1024.0, 1.0 / 1024.0, 0.0)
#endif
uniform mat4 uLightProj[SHADOW_OBJ_MAX];
uniform mat4 uLightProj;
#endif
uniform mat4 uViewProj;
@@ -276,66 +270,55 @@ uniform vec4 uFogParams;
#endif
#else
uniform sampler2D sShadow;
#define CMP(a,b) step(min(1.0, b), a)
#ifdef SHADOW_DEPTH
#define compare(p, z) CMP(texture2D(sShadow, (p)).x, (z));
#elif defined(SHADOW_COLOR)
float unpack(vec4 value) {
vec4 bitSh = vec4(1.0/(256.0*256.0*256.0), 1.0/(256.0*256.0), 1.0/256.0, 1.0);
return dot(value, bitSh);
}
#define compare(p, z) CMP(unpack(texture2D(sShadow, (p))), (z));
#endif
float SHADOW(vec3 p) {
return compare(p.xy, p.z);
float SHADOW(vec2 p) {
#ifdef SHADOW_DEPTH
return texture2D(sShadow, p).x;
#else
return unpack(texture2D(sShadow, p));
#endif
}
#endif
float getShadow(vec3 lightVec, vec4 lightProj, vec2 tileOffset) {
float getShadow(vec3 lightVec, vec3 normal, vec4 lightProj) {
vec3 p = lightProj.xyz / lightProj.w;
p.xyz = p.xyz * 0.5 + 0.5;
p.z -= 0.04 * SHADOW_TEXEL.x;
float vis = lightProj.w;
#ifdef TYPE_ROOM
vis = min(vis, dot(vNormal.xyz, lightVec));
vis = min(vis, dot(normal, lightVec));
#endif
if (vis < 0.0 || p.x < 0.0 || p.y < 0.0 || p.x > 1.0 || p.y > 1.0) return 1.0;
#ifdef OPT_SHADOW_HIGH
p.xy = p.xy * vec2(0.25, 0.5) + tileOffset;
#endif
#ifdef SHADOW_SAMPLER
float rShadow = SHADOW(p);
#else
vec4 samples = vec4(SHADOW(SHADOW_TEXEL * vec3(0.0, 0.0, 0.0) + p),
SHADOW(SHADOW_TEXEL * vec3(1.0, 0.0, 0.0) + p),
SHADOW(SHADOW_TEXEL * vec3(0.0, 1.0, 0.0) + p),
SHADOW(SHADOW_TEXEL * vec3(1.0, 1.0, 0.0) + p));
vec4 samples = vec4(SHADOW( p.xy),
SHADOW(SHADOW_TEXEL.xz + p.xy),
SHADOW(SHADOW_TEXEL.zy + p.xy),
SHADOW(SHADOW_TEXEL.xy + p.xy));
samples = step(vec4(p.z), samples);
vec2 f = fract(p.xy / SHADOW_TEXEL.xy);
float rShadow = mix(mix(samples.x, samples.y, f.x), mix(samples.z, samples.w, f.x), f.y);
samples.xy = mix(samples.xz, samples.yw, f.x);
float rShadow = mix(samples.x, samples.y, f.y);
#endif
float fade = clamp(dot(lightVec, lightVec), 0.0, 1.0);
return rShadow + (1.0 - rShadow) * fade;
}
float getShadow(vec3 lightVec) {
vec4 c = vec4(vCoord, 1.0);
#ifdef OPT_SHADOW_HIGH
return min(min(min(min(min(min(min( // hardcoded for 4x2 shadow atlas
getShadow(lightVec, uLightProj[0] * c, vec2(0.00, 0.0)),
getShadow(lightVec, uLightProj[1] * c, vec2(0.25, 0.0))),
getShadow(lightVec, uLightProj[2] * c, vec2(0.50, 0.0))),
getShadow(lightVec, uLightProj[3] * c, vec2(0.75, 0.0))),
getShadow(lightVec, uLightProj[4] * c, vec2(0.00, 0.5))),
getShadow(lightVec, uLightProj[5] * c, vec2(0.25, 0.5))),
getShadow(lightVec, uLightProj[6] * c, vec2(0.50, 0.5))),
getShadow(lightVec, uLightProj[7] * c, vec2(0.75, 0.5)));
#else
return getShadow(lightVec, uLightProj[0] * c, vec2(0.0, 0.0));
#endif
float getShadow(vec3 lightVec, vec3 normal) {
float factor = clamp(1.0 - dot(normalize(lightVec), normal), 0.0, 1.0);
factor *= 16.0;
return getShadow(lightVec, normal, uLightProj * vec4(vCoord + normal * factor, 1.0));
}
#endif
@@ -414,7 +397,6 @@ uniform vec4 uFogParams;
#endif
#ifdef PASS_COMPOSE
vec3 lightVec = (uLightPos[0].xyz - vCoord) * uLightColor[0].w;
vec3 normal = normalize(vNormal.xyz);
@@ -426,7 +408,7 @@ uniform vec4 uFogParams;
vec3 light = uLightColor[1].xyz * vLight.y + uLightColor[2].xyz * vLight.z + uLightColor[3].xyz * vLight.w;
#if defined(TYPE_ENTITY) || defined(TYPE_ROOM)
float rShadow = getShadow(lightVec);
float rShadow = getShadow(lightVec, normal);
#endif
#ifdef TYPE_ENTITY

View File

@@ -66,16 +66,13 @@ struct Texture : GAPI::Texture {
bool filter = (opt & OPT_NEAREST) == 0;
bool mipmaps = (opt & OPT_MIPMAPS) != 0;
if (format == FMT_SHADOW && !Core::support.shadowSampler) {
if (format == FMT_SHADOW && !Core::support.shadowSampler)
format = FMT_DEPTH;
filter = false;
}
if (format == FMT_DEPTH) {
if (Core::support.depthTexture)
filter = false;
else
if (!Core::support.depthTexture)
format = FMT_RGBA;
filter = false;
}
if (format == FMT_RGBA_HALF) {

View File

@@ -280,7 +280,7 @@ namespace UI {
void updateAspect(float aspect) {
height = 480.0f;
width = height * aspect;
Core::mProj = mat4(0.0f, width, height, 0.0f, 0.0f, 1.0f);
Core::mProj = GAPI::ortho(0.0f, width, height, 0.0f, 0.0f, 1.0f);
Core::setViewProj(Core::mView, Core::mProj);
Core::active.shader->setParam(uViewProj, Core::mViewProj);
}
@@ -493,7 +493,7 @@ namespace UI {
Core::setBlendMode(bmAlpha);
Core::setCullMode(cmNone);
Core::mViewProj = mat4(0.0f, float(Core::width), float(Core::height), 0.0f, 0.0f, 1.0f);
Core::mViewProj = GAPI::ortho(0.0f, float(Core::width), float(Core::height), 0.0f, 0.0f, 1.0f);
game->setShader(Core::passGUI, Shader::DEFAULT);

View File

@@ -466,6 +466,12 @@ struct quat {
};
struct mat4 {
enum ProjRange {
PROJ_NEG_POS,
PROJ_ZERO_POS,
};
float e00, e10, e20, e30,
e01, e11, e21, e31,
e02, e12, e22, e32,
@@ -494,17 +500,24 @@ struct mat4 {
e33 = 1.0f;
}
mat4(float l, float r, float b, float t, float znear, float zfar) {
mat4(ProjRange range, float l, float r, float b, float t, float znear, float zfar) {
identity();
e00 = 2.0f / (r - l);
e11 = 2.0f / (t - b);
e22 = 2.0f / (znear - zfar);
e03 = (l + r) / (l - r);
e13 = (t + b) / (b - t);
switch (range) {
case PROJ_NEG_POS :
e23 = (zfar + znear) / (znear - zfar);
break;
case PROJ_ZERO_POS :
e23 = znear / (znear - zfar);
break;
}
}
mat4(float fov, float aspect, float znear, float zfar) {
mat4(ProjRange range, float fov, float aspect, float znear, float zfar) {
float k = 1.0f / tanf(fov * 0.5f * DEG2RAD);
identity();
if (aspect >= 1.0f) {
@@ -514,10 +527,18 @@ struct mat4 {
e00 = k;
e11 = k * aspect;
}
e22 = (znear + zfar) / (znear - zfar);
e33 = 0.0f;
e32 = -1.0f;
switch (range) {
case PROJ_NEG_POS :
e22 = (znear + zfar) / (znear - zfar);
e23 = 2.0f * zfar * znear / (znear - zfar);
break;
case PROJ_ZERO_POS :
e22 = zfar / (znear - zfar);
e23 = znear * e22;
break;
}
}
mat4(const vec3 &from, const vec3 &at, const vec3 &up) {