1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-13 16:44:50 +02:00

#23 experimental shadows (XPSM, crop etc.)

This commit is contained in:
XProger
2017-04-23 00:12:30 +03:00
parent a8d54272cd
commit f55a2839c2
11 changed files with 433 additions and 111 deletions

View File

@@ -8,6 +8,8 @@
#define NO_CLIP_PLANE 1000000.0f
#define SHADOW_TEX_SIZE 1024
#define FOG_DIST (18 * 1024)
#define WATER_FOG_DIST (8 * 1024)
//#define WATER_USE_GRID
@@ -130,7 +132,7 @@ struct ShaderCache {
typ = typeNames[type];
int animTexRangesCount = game->getMesh()->animTexRangesCount;
int animTexOffsetsCount = game->getMesh()->animTexOffsetsCount;
sprintf(def, "%s#define PASS_%s\n#define TYPE_%s\n#define MAX_LIGHTS %d\n#define MAX_RANGES %d\n#define MAX_OFFSETS %d\n#define FOG_DIST (1.0/%d.0)\n#define WATER_FOG_DIST (1.0/%d.0)\n", ext, passNames[pass], typ, MAX_LIGHTS, animTexRangesCount, animTexOffsetsCount, FOG_DIST, WATER_FOG_DIST);
sprintf(def, "%s#define PASS_%s\n#define TYPE_%s\n#define MAX_LIGHTS %d\n#define MAX_RANGES %d\n#define MAX_OFFSETS %d\n#define FOG_DIST (1.0/%d.0)\n#define WATER_FOG_DIST (1.0/%d.0)\n#define SHADOW_TEX_SIZE %d.0\n", ext, passNames[pass], typ, MAX_LIGHTS, animTexRangesCount, animTexOffsetsCount, FOG_DIST, WATER_FOG_DIST, SHADOW_TEX_SIZE);
if (fx & FX_UNDERWATER) strcat(def, "#define UNDERWATER\n" UNDERWATER_COLOR);
if (fx & FX_ALPHA_TEST) strcat(def, "#define ALPHA_TEST\n");
if (fx & FX_CLIP_PLANE) strcat(def, "#define CLIP_PLANE\n");

View File

@@ -133,6 +133,7 @@ struct Character : Controller {
}
virtual void update() {
vec3 p = pos;
lastInput = input;
input = getInput();
stand = getStand();
@@ -140,6 +141,8 @@ struct Character : Controller {
Controller::update();
updateVelocity();
updatePosition();
if (p != pos)
updateLights();
}
virtual void cmdJump(const vec3 &vel) {

View File

@@ -46,6 +46,10 @@ struct Controller {
vec3 ambient[6];
float specular;
TR::Room::Light *lights[MAX_LIGHTS];
vec3 mainLightPos;
float mainLightRadius;
struct MeshLayer {
uint32 model;
uint32 mask;
@@ -71,6 +75,7 @@ struct Controller {
frameIndex = -1;
specular = 0.0f;
ambient[0] = ambient[1] = ambient[2] = ambient[3] = ambient[4] = ambient[5] = vec3(intensityf(getRoom().ambient));
updateLights();
}
virtual ~Controller() {
@@ -130,8 +135,6 @@ struct Controller {
return false;
}
void updateEntity() {
TR::Entity &e = getEntity();
e.x = int(pos.x);
@@ -273,7 +276,11 @@ struct Controller {
}
virtual Box getBoundingBox() {
return animation.getBoundingBox(pos, getEntity().rotation.value / 0x4000);
return getBoundingBoxLocal() * getMatrix();
}
virtual Box getBoundingBoxLocal() {
return animation.getBoundingBox(vec3(0, 0, 0), 0);
}
vec3 trace(int fromRoom, const vec3 &from, const vec3 &to, int &room, bool isCamera) { // TODO: use Bresenham
@@ -464,6 +471,85 @@ struct Controller {
virtual void update() {
updateAnimation(true);
}
struct MaxLight {
TR::Room::Light *light;
float att;
};
void checkRoomLights(int roomIndex, int fromRoom, const vec3 &from, MaxLight *maxLights, vec3 &mainDir, float &mainRad, float &attSum, int deep) {
TR::Room &room = level->rooms[roomIndex];
for (int i = 0; i < room.lightsCount; i++) {
TR::Room::Light &light = room.lights[i];
bool exists = false;
for (int m = 0; m < MAX_LIGHTS; m++)
if (maxLights[m].light == &light) {
exists = true;
break;
}
if (exists) continue;
vec3 dir = vec3(float(light.x), float(light.y), float(light.z)) - from;
float att = max(0.0f, 1.0f - dir.length2() / float(light.radius) / float(light.radius)) * intensityf(light.intensity);
for (int m = 0; m < MAX_LIGHTS; m++) {
if (maxLights[m].att < att) {
for (int n = MAX_LIGHTS - 1; n > m; n--)
maxLights[n] = maxLights[n - 1];
maxLights[m].light = &light;
maxLights[m].att = att;
break;
}
}
if (att > 0.0f) {
// if (dir.y > 0.0f)
// att *= 1.0f - dir.y / float(light.radius);
att = max(0.0f, att - dir.y / 8192.0f);
attSum += att;
mainDir += dir * att;
mainRad += float(light.radius) * att;
}
}
if (--deep > 0)
for (int i = 0; i < room.portalsCount; i++)
if (room.portals[i].roomIndex != fromRoom)
checkRoomLights(room.portals[i].roomIndex, roomIndex, from, maxLights, mainDir, mainRad, attSum, deep);
}
void updateLights() {
if (!getModel()) {
for (int i = 0; i < MAX_LIGHTS; i++)
lights[i] = NULL;
return;
}
MaxLight maxLights[MAX_LIGHTS];
for (int i = 0; i < MAX_LIGHTS; i++) {
maxLights[i].light = NULL;
maxLights[i].att = 0.0f;
}
vec3 p = getBoundingBox().center();
vec3 mainDir(0.0f);
float mainRad = 0.0f;
float attSum = 0.0f;
checkRoomLights(getRoomIndex(), -1, p, maxLights, mainDir, mainRad, attSum, 1);
if (attSum > 0.0f) {
attSum = 1.0f / attSum;
mainLightPos = mainDir * attSum + p;
mainLightRadius = mainRad * attSum;
}
for (int i = 0; i < MAX_LIGHTS; i++)
lights[i] = maxLights[i].light;
}
/*
void renderMesh(MeshBuilder *mesh, uint32 offsetIndex) {
return;

View File

@@ -350,18 +350,24 @@ namespace Debug {
}
}
void lights(const TR::Level &level, int room) {
void lights(const TR::Level &level, int room, Controller *lara) {
// int roomIndex = level.entities[lara->entity].room;
// int lightIndex = getLightIndex(lara->pos, roomIndex);
lara->updateLights();
glPointSize(8);
for (int i = 0; i < level.roomsCount; i++)
for (int j = 0; j < level.rooms[i].lightsCount; j++) {
TR::Room::Light &l = level.rooms[i].lights[j];
float a = l.intensity / 8191.0f;
float a = intensityf(l.intensity);
vec3 p = vec3(l.x, l.y, l.z);
vec4 color = vec4(a, a, a, 1);
if (i == room) color.x = color.z = 0;
if (&l == lara->lights[0]) color.y = color.z = 0; // r
if (&l == lara->lights[1]) color.x = color.z = 0; // g
if (&l == lara->lights[2]) color.x = color.y = 0; // b
if (&l == lara->lights[3]) color.y = 0; // a
// if (i == room) color.x = color.z = 0;
Debug::Draw::point(p, color);
//if (i == roomIndex && j == lightIndex)
// color = vec4(0, 1, 0, 1);

View File

@@ -949,7 +949,7 @@ namespace TR {
stream.read(light.intensity);
stream.read(light.radius);
light.radius *= 2;
// light.radius *= 2;
}
// meshes
stream.read(r.meshesCount);

View File

@@ -1808,6 +1808,9 @@ struct Lara : Character {
break;
}
}
if (state == STATE_DEATH || state == STATE_UNDERWATER_DEATH)
velocity.x = velocity.z = 0.0f;
}
virtual void updatePosition() { // TODO: sphere / bbox collision

View File

@@ -22,7 +22,7 @@ struct Level : IGame {
Lara *lara;
Camera *camera;
Texture *shadow, *shadowMask;
Texture *shadow;
struct Params {
float time;
@@ -221,8 +221,7 @@ struct Level : IGame {
ambientCache = Core::settings.ambient ? new AmbientCache(this) : NULL;
waterCache = Core::settings.water ? new WaterCache(this) : NULL;
shadow = Core::settings.shadows ? new Texture(1024, 1024, Texture::SHADOW, false) : NULL;
shadowMask = NULL;
shadow = Core::settings.shadows ? new Texture(SHADOW_TEX_SIZE, SHADOW_TEX_SIZE, Texture::SHADOW, false) : NULL;
initReflections();
@@ -250,7 +249,6 @@ struct Level : IGame {
delete shaderCache;
delete shadow;
delete shadowMask;
delete ambientCache;
delete waterCache;
@@ -460,48 +458,26 @@ struct Level : IGame {
}
camera->frustum = camFrustum; // pop camera frustum
}
void setLights(Controller *controller, bool onlyFlashes = false) {
for (int i = 0; i < MAX_LIGHTS; i++) {
TR::Room::Light *light = controller->lights[i];
if (onlyFlashes && i && light && light->radius > 0.0f)
light = NULL;
int getLightIndex(const vec3 &pos, int &room, float maxAtt = -1.0f, int depth = 0) {
int idx = -1;
TR::Room &r = level.rooms[room];
for (int i = 0; i < r.lightsCount; i++) {
TR::Room::Light &light = r.lights[i];
if (light.intensity > 0x1FFF) continue;
float att = max(0.0f, 1.0f - (pos - vec3(float(light.x), float(light.y), float(light.z))).length2() / ((float)light.radius * (float)light.radius));
if (att > maxAtt) {
maxAtt = att;
idx = i;
if (light) {
float c = 1.0f - intensityf(light->intensity);
Core::lightPos[i] = vec3(float(light->x), float(light->y), float(light->z));
Core::lightColor[i] = vec4(c, c, c, 1.0f / float(light->radius));
} else {
Core::lightPos[i] = vec3(0);
Core::lightColor[i] = vec4(0, 0, 0, 1);
}
}
if (depth > 0)
for (int i = 0; i < r.portalsCount; i++) {
int nextRoom = r.portals[i].roomIndex;
int nextLight = getLightIndex(pos, nextRoom, maxAtt, depth - 1);
if (nextLight > -1) {
room = nextRoom;
idx = nextLight;
}
}
return idx;
}
void getLight(const vec3 &pos, int roomIndex) {
int room = roomIndex;
int idx = getLightIndex(pos, room);
if (idx > -1) {
TR::Room::Light &light = level.rooms[room].lights[idx];
float c = 1.0f - intensityf(level.rooms[room].lights[idx].intensity);
Core::lightPos[0] = vec3(float(light.x), float(light.y), float(light.z));
Core::lightColor[0] = vec4(c, c, c, 1.0f / (float)light.radius);
} else {
Core::lightPos[0] = vec3(0);
Core::lightColor[0] = vec4(0, 0, 0, 1);
}
Core::lightPos[0] = lara->mainLightPos;
if (lara->mainLightRadius > 0.0f)
Core::lightColor[0].w = 1.0f / lara->mainLightRadius;
}
void renderEntity(const TR::Entity &entity) {
@@ -543,7 +519,8 @@ struct Level : IGame {
}
Core::active.shader->setParam(uAmbient, controller->ambient[0], 6);
}
getLight(pos, entity.room);
setLights(controller);
} else { // sprite
Core::lightPos[0] = vec3(0);
Core::lightColor[0] = vec4(0, 0, 0, 1);
@@ -610,7 +587,7 @@ struct Level : IGame {
void renderRooms(int roomIndex) {
PROFILE_MARKER("ROOMS");
getLight(lara->pos, lara->getRoomIndex());
setLights(lara, true);
#ifdef LEVEL_EDITOR
for (int i = 0; i < level.roomsCount; i++)
@@ -656,20 +633,43 @@ struct Level : IGame {
}
mat4 calcCromMatrix(const mat4 &lightViewProj, const Box *boxes, int count) {
mat4 cameraViewProjInv = (mat4(camera->fov, float(Core::width) / Core::height, 512.0f, 4096.0f) * camera->mViewInv.inverse()).inverse();
Box bRec, bCast, bCrop, bSplit;
/*
mat4 calcCropMatrix(const mat4 &viewProj, const Box &receivers, const Box &casters) {
mat4 cameraViewProjInv = (camera->getProjMatrix() * camera->mViewInv.inverse()).inverse();
// camera->mViewInv (mat4(camera->fov, float(Core::width) / Core::height, camera->znear, camera->zfar) * camera->mViewInv.inverse()).inverse();
Box frustumBox = Box(vec3(-1.0f), vec3(1.0f)) * cameraViewProjInv;
Box casterBox(vec3(+INF), vec3(-INF));
Box caster = casters;// * viewProj;
Box receiver = receivers * viewProj;
Box split = frustumBox * viewProj;
for (int i = 0; i < count; i++)
casterBox += boxes[i] * lightViewProj;
Box crop;
crop.min.x = max(max(caster.min.x, receiver.min.x), split.min.x);
crop.max.x = min(min(caster.max.x, receiver.max.x), split.max.x);
crop.min.y = max(max(caster.min.y, receiver.min.y), split.min.y);
crop.max.y = min(min(caster.max.y, receiver.max.y), split.max.y);
crop.min.z = min(caster.min.z, split.min.z);
crop.max.z = min(receiver.max.z, split.max.z);
casterBox -= frustumBox * lightViewProj;
mat4 m = camera->getProjMatrix();
Box cc = receivers * m;
cc = cc * m.inverse();
vec3 scale = vec3(2.0f, 2.0f, 1.0f) / casterBox.size();
vec3 center = casterBox.center();
vec3 offset = vec3(center.x, center.y, casterBox.min.z) * scale;
if (!Input::down[ikShift]) {
mat4 m = viewProj.inverse();
bRec = receivers;// * m;
bCast = casters;// * m;
bCrop = crop * m;
bSplit = split * m;
}
// casterBox -= frustumBox * viewProj;
// crop.min.z = 0.0f;
vec3 scale = vec3(2.0f, 2.0f, 1.0f) / crop.size();
vec3 center = crop.center();
vec3 offset = vec3(center.x, center.y, crop.min.z) * scale;
return mat4(scale.x, 0.0f, 0.0f, 0.0f,
0.0f, scale.y, 0.0f, 0.0f,
@@ -679,62 +679,241 @@ struct Level : IGame {
bool setupLightCamera() {
vec3 pos = lara->getPos();
// omni-spot light shadows
int room = lara->getRoomIndex();
int idx = getLightIndex(lara->pos, room);
if (idx < 0) return false;
lara->updateLights();
vec3 pos = lara->getBoundingBox().center();
TR::Room::Light &light = level.rooms[room].lights[idx];
vec3 shadowLightPos = vec3(float(light.x), float(light.y), float(light.z));
Core::mViewInv = mat4(shadowLightPos, pos - vec3(0, 256, 0), vec3(0, -1, 0));
Core::mViewInv = mat4(lara->mainLightPos, pos - vec3(0, 256, 0), vec3(0, -1, 0));
Core::mView = Core::mViewInv.inverse();
Core::mProj = mat4(120.0f, 1.0f, camera->znear, camera->zfar);
Core::mProj = mat4(1.0f, 1.0f, camera->znear, camera->zfar);//lara->mainLightRadius * 2.0f);
mat4 mLightProj = Core::mProj * Core::mView;
Box casters = lara->getBoundingBox() * mLightProj;
float rq = lara->mainLightRadius * lara->mainLightRadius;
for (int i = 0; i < level.entitiesCount; i++) {
TR::Entity &e = level.entities[i];
Controller *controller = (Controller*)e.controller;
if (controller && TR::castShadow(e.type) && rq > (lara->mainLightPos - controller->pos).length2())
casters += controller->getBoundingBox() * mLightProj;
}
//casters.expand(vec3(128.0f));
Box lightBox = Box(lara->mainLightPos - vec3(lara->mainLightRadius), lara->mainLightPos + vec3(lara->mainLightRadius));
Core::mProj = calcCropMatrix(mLightProj, lightBox, casters) * Core::mProj;
mat4 bias;
bias.identity();
bias.e03 = bias.e13 = bias.e23 = bias.e00 = bias.e11 = bias.e22 = 0.5f;
/*
Box boxes[32];
int bCount = 0;
float rq = light.radius * light.radius;
for (int i = 0; i < level.entitiesCount; i++) {
TR::Entity &e = level.entities[i];
Controller *controller = (Controller*)e.controller;
if (controller && TR::castShadow(e.type) && rq > (shadowLightPos - controller->pos).length2())
boxes[bCount++] = controller->getBoundingBox();
Core::mLightProj = bias * (Core::mProj * Core::mView);
return true;
}
*/
/* // --> XPSM
Box transformPointsBox(const vec3 *points, int count, const mat4 &matrix, float eps) {
Box box(vec3(+INF), vec3(-INF));
for (int i = 0; i < count; i++) {
vec4 p = matrix * vec4(points[i], 1.0f);
if (p.w > eps)
box += p.xyz / p.w;
}
*/
/*
vec3 shadowBox(1024.0f, 0.0f, 1024.0f);
boxes[0] = lara->getBoundingBox();
boxes[0] += Box(lara->pos - shadowBox, lara->pos + shadowBox);
bCount++;
Core::mProj = calcCromMatrix(Core::mProj * Core::mView, &boxes[0], bCount) * Core::mProj;
*/
return box;
}
bool setupLightCamera() {
lara->updateLights();
vec3 pos = lara->getBoundingBox().center();
mat4 mViewCamera = camera->mViewInv.inverse();
// get shadow casters (bbox corner points)
#define MAX_CASTER_POINTS (32 * 8)
vec3 cPoints[32 * 8];
int cPointsCount = 0;
vec3 rPoints[1 * 8];
int rPointsCount = 0;
float rq = lara->mainLightRadius * lara->mainLightRadius;
for (int i = 0; i < level.entitiesCount; i++) {
if (cPointsCount >= MAX_CASTER_POINTS)
break;
TR::Entity &e = level.entities[i];
Controller *controller = (Controller*)e.controller;
if (!controller || !TR::castShadow(e.type) || rq < (lara->mainLightPos - controller->pos).length2())
continue;
Box box = controller->getBoundingBoxLocal();
mat4 m = mViewCamera * controller->getMatrix();
for (int j = 0; j < 8; j++)
cPoints[cPointsCount++] = m * box[j];
}
#undef MAX_CASTER_POINTS
{
mat4 cameraViewProjInv = (camera->getProjMatrix() * mViewCamera).inverse();
Box box(vec3(-1.0f), vec3(1.0f));
for (int i = 0; i < 8; i++) {
vec4 p = cameraViewProjInv * vec4(box[i], 1.0f);
rPoints[rPointsCount++] = mViewCamera * (p.xyz / p.w);
}
}
mat4 mViewLight = mat4(mViewCamera * pos, mViewCamera * lara->mainLightPos, vec3(0, -1, 0)).inverse();
vec2 uP = mViewLight.dir.xy.normal();
float minCastersProj = 1.0f;
for (int i = 0; i < cPointsCount; i++) {
vec3 p = mViewLight * cPoints[i];
minCastersProj = min(minCastersProj, uP.dot(p.xy));
}
float minReceiversProj = 1.0f;
for (int i = 0; i < rPointsCount; i++) {
vec3 p = mViewLight * rPoints[i];
minReceiversProj = min(minReceiversProj, uP.dot(p.xy));
}
float eps = 0.85f;
float maxLengthP = (eps - 1.0f) / minCastersProj; //max(minCastersProj, minReceiversProj);
float lengthP = (0.05f * 0.06f) / uP.dot(mViewLight.dir.xy);
if (maxLengthP > 0.0f && lengthP > maxLengthP)
lengthP = maxLengthP;
mat4 mLProj(1, 0, 0, uP.x * lengthP,
0, 1, 0, uP.y * lengthP,
0, 0, 1, 0,
0, 0, 0, 1);
mat4 mLZRot(uP.x, uP.y, 0, 0,
uP.y, -uP.x, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1);
mat4 mProjLight = mLZRot * mLProj * mViewLight;
Box casters = transformPointsBox(cPoints, cPointsCount, mProjLight, eps);
Box receivers = transformPointsBox(rPoints, rPointsCount, mProjLight, eps);
Box focus = casters;//.intersection2D(receivers);
//focus.min.z = min(casters.min.z, receivers.min.z);
//focus.max.z = max(casters.max.z, receivers.max.z);
vec3 size = focus.size();
if (size.x < EPS || size.y < EPS || size.z < EPS)
return false;
vec3 u = vec3(1.0f) / size;
mat4 mUnitCube(u.x, 0, 0, 0,
0, u.y, 0, 0,
0, 0, u.z, 0,
-focus.min.x * u.x, -focus.min.y * u.y, -focus.min.z * u.z, 1);
mat4 mUnitSpace( 2, 0, 0, 0,
0, 2, 0, 0,
0, 0, 2, 0,
-1, -1, -1, 1);
Core::mView = mViewLight * mViewCamera;
Core::mProj = mUnitSpace * mUnitCube * mLZRot * mLProj;
Core::mViewProj = Core::mProj * Core::mView;
mat4 bias;
bias.identity();
bias.e03 = bias.e13 = bias.e23 = bias.e00 = bias.e11 = bias.e22 = 0.5f;
Core::mLightProj = bias * Core::mViewProj;
return true;
}
<-- */
mat4 calcCropMatrix(const mat4 &viewProj, const Box &receivers, const Box &casters) {
mat4 cameraViewProjInv = (camera->getProjMatrix() * camera->mViewInv.inverse()).inverse();
// camera->mViewInv (mat4(camera->fov, float(Core::width) / Core::height, camera->znear, camera->zfar) * camera->mViewInv.inverse()).inverse();
Box frustumBox = Box(vec3(-1.0f), vec3(1.0f)) * cameraViewProjInv;
Box caster = casters;// * viewProj;
Box receiver = receivers * viewProj;
Box split = frustumBox * viewProj;
Box crop;
crop.min.x = max(max(caster.min.x, receiver.min.x), split.min.x);
crop.max.x = min(min(caster.max.x, receiver.max.x), split.max.x);
crop.min.y = max(max(caster.min.y, receiver.min.y), split.min.y);
crop.max.y = min(min(caster.max.y, receiver.max.y), split.max.y);
crop.min.z = min(caster.min.z, split.min.z);
crop.max.z = min(receiver.max.z, split.max.z);
mat4 m = camera->getProjMatrix();
Box cc = receivers * m;
cc = cc * m.inverse();
if (!Input::down[ikShift]) {
mat4 m = viewProj.inverse();
bRec = receivers;// * m;
bCast = casters;// * m;
bCrop = crop * m;
bSplit = split * m;
}
// casterBox -= frustumBox * viewProj;
// crop.min.z = 0.0f;
vec3 scale = vec3(2.0f, 2.0f, 1.0f) / crop.size();
vec3 center = crop.center();
vec3 offset = vec3(center.x, center.y, crop.min.z) * scale;
return mat4(scale.x, 0.0f, 0.0f, 0.0f,
0.0f, scale.y, 0.0f, 0.0f,
0.0f, 0.0f, scale.z, 0.0f,
-offset.x, -offset.y, -offset.z, 1.0f);
}
bool setupLightCamera() {
lara->updateLights();
vec3 pos = lara->getBoundingBox().center();
Core::mViewInv = mat4(lara->mainLightPos, pos, vec3(0, -1, 0));
Core::mView = Core::mViewInv.inverse();
Core::mProj = mat4(120.0f, 1.0f, camera->znear, lara->mainLightRadius);
mat4 bias;
bias.identity();
bias.e03 = bias.e13 = bias.e23 = bias.e00 = bias.e11 = bias.e22 = 0.5f;
Core::mLightProj = bias * (Core::mProj * Core::mView);
return true;
}
void renderShadows(int roomIndex) {
PROFILE_MARKER("PASS_SHADOW");
Core::eye = 0.0f;
Core::pass = Core::passShadow;
if (!setupLightCamera()) return;
shadow->unbind(sShadow);
bool colorShadow = shadow->format == Texture::Format::RGBA ? true : false;
if (colorShadow)
Core::setClearColor(vec4(1.0f, 1.0f, 1.0f, 1.0f));
Core::setTarget(shadow);
Core::setTarget(shadow);
if (!setupLightCamera()) return;
Core::clear(true, true);
Core::setCulling(cfBack);
renderScene(roomIndex);
renderScene(roomIndex);
Core::invalidateTarget(!colorShadow, colorShadow);
Core::setCulling(cfFront);
Core::setCulling(cfFront);
if (colorShadow)
Core::setClearColor(vec4(0.0f, 0.0f, 0.0f, 0.0f));
}
@@ -851,7 +1030,7 @@ struct Level : IGame {
// renderModel(level.models[modelIndex], level.entities[4]);
*/
Debug::begin();
/*
lara->updateEntity(); // TODO clip angle while rotating
int q = int(normalizeAngle(lara->angleExt + PI * 0.25f) / (PI * 0.5f));
@@ -882,7 +1061,7 @@ struct Level : IGame {
glColor3f(1, 1, 0); p = lara->pos; glVertex3fv((GLfloat*)&p); p -= vec3(0.0f, LARA_HANG_OFFSET, 0.0f); glVertex3fv((GLfloat*)&p);
glEnd();
Core::setDepthTest(true);
/*
*/
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
@@ -891,8 +1070,8 @@ struct Level : IGame {
glLoadIdentity();
glOrtho(0, Core::width, 0, Core::height, 0, 1);
if (waterCache->visible)
waterCache->reflect->bind(sDiffuse);
if (shadow)
shadow->bind(sDiffuse);
else
atlas->bind(sDiffuse);
glEnable(GL_TEXTURE_2D);
@@ -921,10 +1100,29 @@ struct Level : IGame {
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
Core::setDepthTest(false);
glBegin(GL_LINES);
glColor3f(1, 1, 1);
glVertex3fv((GLfloat*)&lara->pos);
glVertex3fv((GLfloat*)&lara->mainLightPos);
glEnd();
Core::setDepthTest(true);
Debug::Draw::sphere(lara->mainLightPos, lara->mainLightRadius, vec4(1, 1, 0, 1));
Box bbox = lara->getBoundingBox();
Debug::Draw::box(bbox.min, bbox.max , vec4(1, 0, 1, 1));
Debug::Draw::box(bRec.min, bRec.max , vec4(1, 0, 0, 1));
Debug::Draw::box(bCast.min, bCast.max, vec4(0, 0, 1, 1));
Debug::Draw::box(bSplit.min, bSplit.max, vec4(0, 1, 1, 1));
Debug::Draw::box(bCrop.min, bCrop.max, vec4(0, 1, 0, 1));
Core::setBlending(bmAlpha);
// Debug::Level::rooms(level, lara->pos, lara->getEntity().room);
// Debug::Level::lights(level, lara->getRoomIndex());
Debug::Level::lights(level, lara->getRoomIndex(), lara);
// Debug::Level::sectors(level, lara->getRoomIndex(), (int)lara->pos.y);
// Core::setDepthTest(false);
// Debug::Level::portals(level);

View File

@@ -132,8 +132,8 @@ struct Mesh {
n.y = (int)o.y;\
n.z = (int)o.z;
float intensityf(int lighting) {
if (lighting < 0) return 1.0f;
float intensityf(uint16 lighting) {
if (lighting > 0x1FFF) return 1.0f;
float lum = 1.0f - (lighting >> 5) / 255.0f;
//return powf(lum, 2.2f); // gamma to linear space
return lum;// * lum; // gamma to "linear" space

View File

@@ -281,7 +281,7 @@ varying vec4 vTexCoord; // xy - atlas coords, zw - caustics coords
#endif
#else
uniform sampler2D sShadow;
#define CMP(a,b) step(b, a)
#define CMP(a,b) step(min(1.0, b), a)
#ifdef SHADOW_DEPTH
#define compare(p, z) CMP(texture2D(sShadow, (p)).x, (z));
@@ -298,7 +298,7 @@ varying vec4 vTexCoord; // xy - atlas coords, zw - caustics coords
}
#endif
#define SHADOW_TEXEL (2.0 / 1024.0)
#define SHADOW_TEXEL (2.0 / SHADOW_TEX_SIZE)
float random(vec3 seed, float freq) {
float dt = dot(floor(seed * freq), vec3(53.1215, 21.1352, 9.1322));
@@ -338,14 +338,17 @@ varying vec4 vTexCoord; // xy - atlas coords, zw - caustics coords
} else
rShadow /= 4.0;
vec3 lv = vLightVec;
float fade = clamp(dot(lv, lv), 0.0, 1.0);
return mix(rShadow, 1.0, fade);
return rShadow;
}
float getShadow() {
return min(dot(vNormal.xyz, vLightVec), vLightProj.w) > 0.0 ? getShadow(vLightProj) : 1.0;
vec3 p = vLightProj.xyz / vLightProj.w;
float fade = smoothstep(0.0, 0.9, p.z);// * (p.z < 1.0 ? 1.0 : 0.0);
float k = max(abs(p.x), abs(p.y));
fade *= 1.0 - smoothstep(0.5, 1.0, k);
fade *= 1.0 - smoothstep(0.999, 1.0, max(0.0, p.z));
return ( fade > 0.0001 && min(dot(vNormal.xyz, vLightVec), vLightProj.w) > 0.0) ? mix(1.0, getShadow(vLightProj), fade) : 1.0;
}
#endif

View File

@@ -23,6 +23,7 @@ struct Texture {
bind(0);
GLenum target = cube ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D;
bool isShadow = format == SHADOW;
if (format == SHADOW && !Core::support.shadowSampler) {
format = DEPTH;
@@ -57,8 +58,12 @@ struct Texture {
glTexParameteri(target, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
}
glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(target, GL_TEXTURE_WRAP_S, isShadow ? GL_CLAMP_TO_BORDER : GL_CLAMP_TO_EDGE);
glTexParameteri(target, GL_TEXTURE_WRAP_T, isShadow ? GL_CLAMP_TO_BORDER : GL_CLAMP_TO_EDGE);
if (isShadow) {
float color[] = { 1.0f, 1.0f, 1.0f, 1.0f };
glTexParameterfv(target, GL_TEXTURE_BORDER_COLOR, color);
}
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, filter ? GL_LINEAR : GL_NEAREST);
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, filter ? GL_LINEAR : GL_NEAREST);

View File

@@ -725,6 +725,17 @@ struct Box {
return min;
}
Box intersection2D(const Box &b) const {
Box r(vec3(0.0f), vec3(0.0f));
if (max.x < b.min.x || min.x > b.max.x) return r;
if (max.y < b.min.y || min.y > b.max.y) return r;
r.max.x = ::min(max.x, b.max.x);
r.max.y = ::min(max.y, b.max.y);
r.min.x = ::max(min.x, b.min.x);
r.min.y = ::max(min.y, b.min.y);
return r;
}
Box& operator += (const Box &box) {
min.x = ::min(min.x, box.min.x);
min.y = ::min(min.y, box.min.y);
@@ -772,6 +783,11 @@ struct Box {
return max - min;
}
void expand(const vec3 &v) {
min -= v;
max += v;
}
void rotate90(int n) {
switch (n) {
case 0 : break;