From 1bef4286e0d124f864e04e099198aa1693fe106d Mon Sep 17 00:00:00 2001 From: XProger Date: Sun, 23 Apr 2017 02:13:29 +0300 Subject: [PATCH] #23 interpolation between shadow sources --- src/controller.h | 110 ++++--------- src/debug.h | 11 +- src/format.h | 2 +- src/lara.h | 3 +- src/level.h | 333 ++-------------------------------------- src/shaders/shader.glsl | 12 +- src/utils.h | 8 + 7 files changed, 63 insertions(+), 416 deletions(-) diff --git a/src/controller.h b/src/controller.h index a796964..6414a5c 100644 --- a/src/controller.h +++ b/src/controller.h @@ -46,9 +46,9 @@ struct Controller { vec3 ambient[6]; float specular; - TR::Room::Light *lights[MAX_LIGHTS]; - vec3 mainLightPos; - float mainLightRadius; + TR::Room::Light *targetLight; + vec3 mainLightPos; + vec4 mainLightColor; struct MeshLayer { uint32 model; @@ -75,7 +75,8 @@ struct Controller { frameIndex = -1; specular = 0.0f; ambient[0] = ambient[1] = ambient[2] = ambient[3] = ambient[4] = ambient[5] = vec3(intensityf(getRoom().ambient)); - updateLights(); + targetLight = NULL; + updateLights(false); } virtual ~Controller() { @@ -472,92 +473,47 @@ struct Controller { updateAnimation(true); } - struct MaxLight { - TR::Room::Light *light; - float att; - }; + void updateLights(bool lerp = true) { + if (getModel()) { + TR::Room &room = getRoom(); - 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]; + vec3 center = getBoundingBox().center(); + float maxAtt = 0.0f; - 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; + for (int i = 0; i < room.lightsCount; i++) { + TR::Room::Light &light = room.lights[i]; + if (light.intensity > 0x1FFF) 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); + vec3 dir = vec3(float(light.x), float(light.y), float(light.z)) - center; + 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 > maxAtt) { + maxAtt = att; + targetLight = &light; } } + } else + targetLight = NULL; - 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; + if (targetLight == NULL) { + mainLightPos = vec3(0); + mainLightColor = vec4(0, 0, 0, 1); return; } - MaxLight maxLights[MAX_LIGHTS]; + vec3 tpos = vec3(float(targetLight->x), float(targetLight->y), float(targetLight->z)); + vec4 tcolor = vec4(vec3(intensityf(targetLight->intensity)), float(targetLight->radius)); - for (int i = 0; i < MAX_LIGHTS; i++) { - maxLights[i].light = NULL; - maxLights[i].att = 0.0f; + if (lerp) { + float t = Core::deltaTime * 2.0f; + mainLightPos = mainLightPos.lerp(tpos, t); + mainLightColor = mainLightColor.lerp(tcolor, t); + } else { + mainLightPos = tpos; + mainLightColor = tcolor; } - - 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; - MeshBuilder::MeshInfo *mInfo = mesh->meshMap[offsetIndex]; - if (!mInfo) return; // invisible mesh (offsetIndex > 0 && level.meshOffsets[offsetIndex] == 0) camera target entity etc. - mesh->renderMesh(mInfo); - } -*/ + mat4 getMatrix() { mat4 matrix; diff --git a/src/debug.h b/src/debug.h index 3cd8ffc..fbccae7 100644 --- a/src/debug.h +++ b/src/debug.h @@ -353,7 +353,6 @@ namespace Debug { 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++) { @@ -362,18 +361,16 @@ namespace Debug { vec3 p = vec3(l.x, l.y, l.z); vec4 color = vec4(a, a, a, 1); - 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); Debug::Draw::sphere(p, l.radius, color); - } + + vec4 color = vec4(lara->mainLightColor.x, 0.0f, 0.0f, 1.0f); + Debug::Draw::point(lara->mainLightPos, color); + Debug::Draw::sphere(lara->mainLightPos, lara->mainLightColor.w, color); } void meshes(const TR::Level &level) { diff --git a/src/format.h b/src/format.h index 53344bc..9a7a8e4 100644 --- a/src/format.h +++ b/src/format.h @@ -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); diff --git a/src/lara.h b/src/lara.h index 6934967..a04ae17 100644 --- a/src/lara.h +++ b/src/lara.h @@ -407,7 +407,7 @@ struct Lara : Character { if (level->extra.braid > -1) braid = new Braid(this, vec3(-4.0f, 24.0f, -48.0f)); -//reset(15, vec3(70067, -256, 29104), -0.68f); // level 2 (pool) +reset(15, vec3(70067, -256, 29104), -0.68f); // level 2 (pool) #ifdef _DEBUG //reset(14, vec3(40448, 3584, 60928), PI * 0.5f, true); // gym (pool) @@ -444,6 +444,7 @@ struct Lara : Character { animation.setAnim(ANIM_TO_ONWATER); } updateEntity(); + updateLights(false); } void wpnSet(Weapon::Type wType) { diff --git a/src/level.h b/src/level.h index 5f1f4f8..26b77c2 100644 --- a/src/level.h +++ b/src/level.h @@ -459,25 +459,9 @@ 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; - - 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); - } - } - - Core::lightPos[0] = lara->mainLightPos; - if (lara->mainLightRadius > 0.0f) - Core::lightColor[0].w = 1.0f / lara->mainLightRadius; + void setMainLight(Controller *controller) { + Core::lightPos[0] = controller->mainLightPos; + Core::lightColor[0] = vec4(controller->mainLightColor.xyz, 1.0f / controller->mainLightColor.w); } void renderEntity(const TR::Entity &entity) { @@ -520,7 +504,7 @@ struct Level : IGame { Core::active.shader->setParam(uAmbient, controller->ambient[0], 6); } - setLights(controller); + setMainLight(controller); } else { // sprite Core::lightPos[0] = vec3(0); Core::lightColor[0] = vec4(0, 0, 0, 1); @@ -587,7 +571,7 @@ struct Level : IGame { void renderRooms(int roomIndex) { PROFILE_MARKER("ROOMS"); - setLights(lara, true); + setMainLight(lara); #ifdef LEVEL_EDITOR for (int i = 0; i < level.roomsCount; i++) @@ -632,262 +616,12 @@ struct Level : IGame { Core::mProj = mat4(90, 1.0f, camera->znear, camera->zfar); } - - 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 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, 256, 0), vec3(0, -1, 0)); - Core::mView = Core::mViewInv.inverse(); - 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; - - 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; - } - 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); + Core::mProj = mat4(90.0f, 1.0f, camera->znear, lara->mainLightColor.w * 1.5f); mat4 bias; bias.identity(); @@ -898,7 +632,6 @@ struct Level : IGame { return true; } - void renderShadows(int roomIndex) { PROFILE_MARKER("PASS_SHADOW"); Core::eye = 0.0f; @@ -917,48 +650,7 @@ struct Level : IGame { if (colorShadow) Core::setClearColor(vec4(0.0f, 0.0f, 0.0f, 0.0f)); } -/* - void renderShadowVolumes() { - getLight(lara->pos, lara->getRoomIndex()); - - Core::setCulling(cfNone); - Core::setDepthWrite(false); - Core::setColorWrite(false, false, false, false); - Core::setStencilTest(true); - Core::setStencilTwoSide(128, true); - - setShader(Core::passVolume, Shader::DEFAULT, false, false); - vec4 lp(Core::lightPos[0], 1.0f / Core::lightColor[0].w); - Core::active.shader->setParam(uLightPos, lp); - - for (int i = 0; i < level.entitiesCount; i++) { - TR::Entity &e = level.entities[i]; - if (e.flags.rendered && TR::castShadow(e.type)) { - Controller *controller = (Controller*)e.controller; - - mat4 matrix = controller->getMatrix(); - Box box = controller->animation.getBoundingBox(vec3(0.0f), 0); - matrix.translate(box.center()); - - Core::active.shader->setParam(uBasis, Basis(matrix) ); - Core::active.shader->setParam(uPosScale, box.size() * 0.5); - - mesh->renderShadowBox(); - } - } - - Core::setDepthWrite(true); - Core::setColorWrite(true, true, true, true); - - Core::setStencilTwoSide(128, false); - -// setShader(Core::passFilter, Shader::DEFAULT, false, false); -// mesh->renderQuad(); - - Core::setStencilTest(false); - } -*/ void render() { Core::invalidateTarget(true, true); params->clipHeight = NO_CLIP_PLANE; @@ -1062,6 +754,8 @@ struct Level : IGame { glEnd(); Core::setDepthTest(true); */ + + /* glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); @@ -1099,7 +793,7 @@ struct Level : IGame { glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); - + */ Core::setDepthTest(false); @@ -1110,15 +804,10 @@ struct Level : IGame { glEnd(); Core::setDepthTest(true); - Debug::Draw::sphere(lara->mainLightPos, lara->mainLightRadius, vec4(1, 1, 0, 1)); + Debug::Draw::sphere(lara->mainLightPos, lara->mainLightColor.w, 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)); - + Debug::Draw::box(bbox.min, bbox.max, vec4(1, 0, 1, 1)); Core::setBlending(bmAlpha); // Debug::Level::rooms(level, lara->pos, lara->getEntity().room); diff --git a/src/shaders/shader.glsl b/src/shaders/shader.glsl index 5db007c..f724889 100644 --- a/src/shaders/shader.glsl +++ b/src/shaders/shader.glsl @@ -338,17 +338,13 @@ varying vec4 vTexCoord; // xy - atlas coords, zw - caustics coords } else rShadow /= 4.0; - return rShadow; + return rShadow; } float getShadow() { - 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; + // min(dot(vNormal.xyz, lv), vLightProj.w) > 0.0 + // clamp(dot(lv, lv), 2.0), 0.0, 1.0); + return vLightProj.w > 0.0 ? getShadow(vLightProj) : 1.0; } #endif diff --git a/src/utils.h b/src/utils.h index 6075c76..9592c16 100644 --- a/src/utils.h +++ b/src/utils.h @@ -246,8 +246,16 @@ struct vec4 { vec4(const vec3 &xyz, float w) : x(xyz.x), y(xyz.y), z(xyz.z), w(w) {} vec4(const vec2 &xy, const vec2 &zw) : x(xy.x), y(xy.y), z(zw.x), w(zw.y) {} + vec4 operator + (const vec4 &v) const { return vec4(x + v.x, y + v.y, z + v.z, w + v.w); } + vec4 operator - (const vec4 &v) const { return vec4(x - v.x, y - v.y, z - v.z, w - v.w); } vec4 operator * (const vec4 &v) const { return vec4(x*v.x, y*v.y, z*v.z, w*v.w); } vec4& operator *= (const vec4 &v) { x*=v.x; y*=v.y; z*=v.z; w*=v.w; return *this; } + + vec4 lerp(const vec4 &v, const float t) const { + if (t <= 0.0f) return *this; + if (t >= 1.0f) return v; + return *this + (v - *this) * t; + } }; struct quat {