mirror of
https://github.com/XProger/OpenLara.git
synced 2025-08-17 18:36:43 +02:00
#23 use all-in-one shadow map method for medium shadow quality settings
This commit is contained in:
13
src/cache.h
13
src/cache.h
@@ -142,7 +142,7 @@ struct ShaderCache {
|
||||
|
||||
src = SHADER;
|
||||
typ = typeNames[type];
|
||||
sprintf(def, "%s#define PASS_%s\n#define TYPE_%s\n#define MAX_LIGHTS %d\n#define MAX_CONTACTS %d\n#define WATER_FOG_DIST (1.0/%d.0)\n#define SHADOW_TEXEL vec3(1.0 / %d.0, 1.0 / %d.0, 0.0)\n#define SHADOW_OBJ_MAX %d\n", ext, passNames[pass], typ, MAX_LIGHTS, MAX_CONTACTS, WATER_FOG_DIST, SHADOW_TEX_WIDTH, SHADOW_TEX_HEIGHT, SHADOW_OBJ_MAX);
|
||||
sprintf(def, "%s#define PASS_%s\n#define TYPE_%s\n#define MAX_LIGHTS %d\n#define MAX_CONTACTS %d\n#define WATER_FOG_DIST (1.0/%d.0)\n", ext, passNames[pass], typ, MAX_LIGHTS, MAX_CONTACTS, WATER_FOG_DIST);
|
||||
#ifdef MERGE_SPRITES
|
||||
if (type == Shader::SPRITE)
|
||||
strcat(def, "#define ALIGN_SPRITES 1\n");
|
||||
@@ -157,8 +157,15 @@ struct ShaderCache {
|
||||
strcat(def, "#define OPT_LIGHTING\n");
|
||||
if (Core::settings.detail.lighting > Core::Settings::MEDIUM && (type == Shader::ENTITY))
|
||||
strcat(def, "#define OPT_AMBIENT\n");
|
||||
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)) {
|
||||
strcat(def, "#define OPT_SHADOW\n");
|
||||
|
||||
if (Core::settings.detail.shadows > Core::Settings::MEDIUM) {
|
||||
strcat(def, "#define OPT_SHADOW_HIGH\n");
|
||||
sprintf(def, "%s#define SHADOW_TEXEL vec3(1.0 / %d.0, 1.0 / %d.0, 0.0)\n#define SHADOW_OBJ_MAX %d\n", def, SHADOW_TEX_WIDTH, SHADOW_TEX_HEIGHT, SHADOW_OBJ_MAX);
|
||||
} else
|
||||
sprintf(def, "%s#define SHADOW_TEXEL vec3(1.0 / %d.0, 1.0 / %d.0, 0.0)\n#define SHADOW_OBJ_MAX %d\n", def, SHADOW_TEX_BIG_WIDTH, SHADOW_TEX_BIG_HEIGHT, 1);
|
||||
}
|
||||
if (Core::settings.detail.shadows > Core::Settings::MEDIUM && (type == Shader::ROOM))
|
||||
strcat(def, "#define OPT_CONTACT\n");
|
||||
if (Core::settings.detail.water > Core::Settings::MEDIUM && (type == Shader::ENTITY || type == Shader::ROOM) && (fx & FX_UNDERWATER))
|
||||
@@ -209,7 +216,7 @@ struct ShaderCache {
|
||||
shader->bind();
|
||||
// TODO: bindable uniform block
|
||||
shader->setParam(uViewProj, Core::mViewProj);
|
||||
shader->setParam(uLightProj, Core::mLightProj[0], SHADOW_OBJ_MAX);
|
||||
shader->setParam(uLightProj, Core::mLightProj[0], Core::settings.detail.shadows > Core::Settings::Quality::MEDIUM ? SHADOW_OBJ_MAX : 1);
|
||||
shader->setParam(uViewPos, Core::viewPos);
|
||||
shader->setParam(uParam, Core::params);
|
||||
shader->setParam(uFogParams, Core::fogParams);
|
||||
|
@@ -195,6 +195,8 @@
|
||||
#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)
|
||||
|
69
src/level.h
69
src/level.h
@@ -223,6 +223,16 @@ struct Level : IGame {
|
||||
}
|
||||
}
|
||||
|
||||
void initShadow() {
|
||||
delete shadow;
|
||||
if (Core::settings.detail.shadows > Core::Settings::MEDIUM)
|
||||
shadow = new Texture(SHADOW_TEX_WIDTH, SHADOW_TEX_HEIGHT, Texture::SHADOW);
|
||||
else if (Core::settings.detail.shadows > Core::Settings::LOW)
|
||||
shadow = new Texture(SHADOW_TEX_BIG_WIDTH, SHADOW_TEX_BIG_HEIGHT, Texture::SHADOW);
|
||||
else
|
||||
shadow = NULL;
|
||||
}
|
||||
|
||||
virtual void applySettings(const Core::Settings &settings) {
|
||||
if (settings.detail.filter != Core::settings.detail.filter)
|
||||
atlas->setFilterQuality(settings.detail.filter);
|
||||
@@ -259,10 +269,8 @@ struct Level : IGame {
|
||||
ambientCache = Core::settings.detail.lighting > Core::Settings::MEDIUM ? new AmbientCache(this) : NULL;
|
||||
}
|
||||
|
||||
if (rebuildShadows) {
|
||||
delete shadow;
|
||||
shadow = Core::settings.detail.shadows > Core::Settings::LOW ? new Texture(SHADOW_TEX_WIDTH, SHADOW_TEX_HEIGHT, Texture::SHADOW) : NULL;
|
||||
}
|
||||
if (rebuildShadows)
|
||||
initShadow();
|
||||
|
||||
if (rebuildWater) {
|
||||
delete waterCache;
|
||||
@@ -681,7 +689,9 @@ struct Level : IGame {
|
||||
zoneCache = new ZoneCache(this);
|
||||
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 = Core::settings.detail.shadows > Core::Settings::LOW ? new Texture(SHADOW_TEX_WIDTH, SHADOW_TEX_HEIGHT, Texture::SHADOW) : NULL;
|
||||
|
||||
shadow = NULL;
|
||||
initShadow();
|
||||
|
||||
initReflections();
|
||||
|
||||
@@ -1931,7 +1941,27 @@ struct Level : IGame {
|
||||
camera->setup(false);
|
||||
}
|
||||
|
||||
void renderEntityShadow(int index, Controller *controller, Controller *player) {
|
||||
void renderShadowView(int roomIndex) {
|
||||
vec3 pos = player->getBoundingBox().center();
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
camera->frustum->pos = Core::viewPos;
|
||||
camera->frustum->calcPlanes(Core::mViewProj);
|
||||
|
||||
setup();
|
||||
renderView(roomIndex, false, false);
|
||||
}
|
||||
|
||||
void renderShadowEntity(int index, Controller *controller, Controller *player) {
|
||||
Box box = controller->getSpheresBox(true);
|
||||
mat4 m = controller->getMatrix();
|
||||
|
||||
@@ -1940,8 +1970,7 @@ struct Level : IGame {
|
||||
Core::mView = Core::mViewInv.inverseOrtho();
|
||||
Core::mProj = mat4(90.0f, 1.0f, 1.0f, 2.0f);
|
||||
|
||||
mat4 mLightProj = Core::mProj * Core::mView * m;
|
||||
Box crop = box * (mLightProj);
|
||||
Box crop = box * (Core::mProj * Core::mView * m);
|
||||
crop.min.z = max(0.0f, crop.min.z);
|
||||
|
||||
float sx = 2.0f / (crop.max.x - crop.min.x);
|
||||
@@ -1960,8 +1989,7 @@ struct Level : IGame {
|
||||
|
||||
mat4 bias;
|
||||
bias.identity();
|
||||
bias.e00 = bias.e11 = bias.e22 = 0.5f;
|
||||
bias.e03 = bias.e13 = bias.e23 = 0.5f;
|
||||
bias.e00 = bias.e11 = bias.e22 = bias.e03 = bias.e13 = bias.e23 = 0.5f;
|
||||
Core::mLightProj[index] = bias * (Core::mProj * Core::mView);
|
||||
|
||||
Core::setBlending(bmNone);
|
||||
@@ -2032,9 +2060,9 @@ struct Level : IGame {
|
||||
void renderShadows(int roomIndex) {
|
||||
PROFILE_MARKER("PASS_SHADOW");
|
||||
|
||||
// get near objects
|
||||
NearObj nearObj[SHADOW_OBJ_MAX];
|
||||
int nearCount = getNearObjects(nearObj, SHADOW_OBJ_MAX);
|
||||
if (Core::settings.detail.shadows == Core::Settings::Quality::LOW)
|
||||
return;
|
||||
ASSERT(shadow);
|
||||
|
||||
// render to shadow map
|
||||
float oldEye = Core::eye;
|
||||
@@ -2050,13 +2078,19 @@ struct Level : IGame {
|
||||
|
||||
Core::setCulling(cfBack);
|
||||
|
||||
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);
|
||||
|
||||
for (int i = 0; i < nearCount; i++) {
|
||||
Core::setViewport((i % SHADOW_OBJ_COLS) * SHADOW_TEX_TILE, (i / SHADOW_OBJ_COLS) * SHADOW_TEX_TILE, SHADOW_TEX_TILE, SHADOW_TEX_TILE);
|
||||
renderEntityShadow(i, (Controller*)level.entities[nearObj[i].index].controller, players[nearObj[i].player]);
|
||||
renderShadowEntity(i, (Controller*)level.entities[nearObj[i].index].controller, players[nearObj[i].player]);
|
||||
}
|
||||
|
||||
for (int i = nearCount; i < SHADOW_OBJ_MAX; i++)
|
||||
Core::mLightProj[i].identity();
|
||||
} else // all-in-one shadow map
|
||||
renderShadowView(roomIndex);
|
||||
|
||||
Core::setCulling(cfFront);
|
||||
if (colorShadow)
|
||||
@@ -2350,7 +2384,12 @@ struct Level : IGame {
|
||||
params->clipSign = 1.0f;
|
||||
params->waterHeight = params->clipHeight;
|
||||
|
||||
if (shadow) shadow->bind(sShadow);
|
||||
if (shadow) {
|
||||
if (view > 0 && Core::settings.detail.shadows < Core::Settings::Quality::HIGH)
|
||||
renderShadows(player->getRoomIndex()); // render shadows for player2 for all-in-one shadow technique
|
||||
shadow->bind(sShadow);
|
||||
}
|
||||
|
||||
Core::pass = Core::passCompose;
|
||||
/*
|
||||
if (view == 0 && Input::hmd.ready) {
|
||||
|
@@ -14,7 +14,10 @@ varying vec4 vTexCoord; // xy - atlas coords, zw - trapezoidal correction
|
||||
uniform vec4 uRoomSize; // xy - minXZ, zw - maxXZ
|
||||
#endif
|
||||
|
||||
uniform mat4 uLightProj[SHADOW_OBJ_MAX];
|
||||
#ifdef OPT_SHADOW
|
||||
uniform mat4 uLightProj[SHADOW_OBJ_MAX];
|
||||
#endif
|
||||
|
||||
uniform mat4 uViewProj;
|
||||
uniform vec3 uViewPos;
|
||||
uniform vec4 uParam; // x - time, y - water height, z - clip plane sign, w - clip plane height
|
||||
@@ -283,28 +286,18 @@ uniform vec4 uMaterial; // x - diffuse, y - ambient, z - specular, w - alpha
|
||||
}
|
||||
#endif
|
||||
|
||||
float random(vec3 seed, float freq) {
|
||||
float dt = dot(floor(seed * freq), vec3(53.1215, 21.1352, 9.1322));
|
||||
return fract(sin(dt) * 2105.2354);
|
||||
}
|
||||
|
||||
float randomAngle(vec3 seed, float freq) {
|
||||
return random(seed, freq) * 6.283285;
|
||||
}
|
||||
|
||||
vec3 rotate(vec2 sc, vec2 v) {
|
||||
return vec3(v.x * sc.y + v.y * sc.x, v.x * -sc.x + v.y * sc.y, 0.0);
|
||||
}
|
||||
|
||||
float getShadow(vec4 lightProj, vec2 tileOffset) {
|
||||
vec3 p = lightProj.xyz / lightProj.w;
|
||||
|
||||
float vis = lightProj.w;
|
||||
#ifdef TYPE_ROOM
|
||||
vis = min(vis, dot(vNormal.xyz, vLightVec.xyz));
|
||||
#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
|
||||
|
||||
float rShadow =(SHADOW(SHADOW_TEXEL * vec3(-0.5, -0.5, 0.0) + p) +
|
||||
SHADOW(SHADOW_TEXEL * vec3( 0.5, -0.5, 0.0) + p) +
|
||||
@@ -315,9 +308,10 @@ uniform vec4 uMaterial; // x - diffuse, y - ambient, z - specular, w - alpha
|
||||
return rShadow + (1.0 - rShadow) * fade;
|
||||
}
|
||||
|
||||
float getShadow() { // hardcoded for 4x2 shadow atlas
|
||||
float getShadow() {
|
||||
vec4 c = vec4(vCoord, 1.0);
|
||||
return min(min(min(min(min(min(min(
|
||||
#ifdef OPT_SHADOW_HIGH
|
||||
return min(min(min(min(min(min(min( // hardcoded for 4x2 shadow atlas
|
||||
getShadow(uLightProj[0] * c, vec2(0.00, 0.0)),
|
||||
getShadow(uLightProj[1] * c, vec2(0.25, 0.0))),
|
||||
getShadow(uLightProj[2] * c, vec2(0.50, 0.0))),
|
||||
@@ -326,6 +320,9 @@ uniform vec4 uMaterial; // x - diffuse, y - ambient, z - specular, w - alpha
|
||||
getShadow(uLightProj[5] * c, vec2(0.25, 0.5))),
|
||||
getShadow(uLightProj[6] * c, vec2(0.50, 0.5))),
|
||||
getShadow(uLightProj[7] * c, vec2(0.75, 0.5)));
|
||||
#else
|
||||
return getShadow(uLightProj[0] * c, vec2(0.0, 0.0));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -457,20 +454,10 @@ uniform vec4 uMaterial; // x - diffuse, y - ambient, z - specular, w - alpha
|
||||
color.xyz = mix(uFogParams.xyz, color.xyz, vLightVec.w);
|
||||
#endif
|
||||
#endif
|
||||
/* catsuit test
|
||||
#elif defined(TYPE_MIRROR)
|
||||
color.xyz += calcSpecular(normalize(vNormal.xyz), vViewVec.xyz, vLightVec.xyz, uLightColor[0], 0.4);
|
||||
color.w = 1.0;
|
||||
*/
|
||||
#endif
|
||||
|
||||
#ifdef TYPE_PARTICLE_SPRITE
|
||||
gl_FragColor = vec4(color.xyz * max(1.0 - vNormal.w, color.w), color.w * vNormal.w); // premultiplied
|
||||
#else
|
||||
gl_FragColor = color;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
)===="
|
Reference in New Issue
Block a user