diff --git a/bin/OpenLara.exe b/bin/OpenLara.exe index 54b450cc..de8cf3ba 100644 Binary files a/bin/OpenLara.exe and b/bin/OpenLara.exe differ diff --git a/src/controller.h b/src/controller.h index aa96ffd8..08340133 100644 --- a/src/controller.h +++ b/src/controller.h @@ -688,6 +688,7 @@ struct Controller { Core::active.shader->setParam(uModel, m); Core::active.shader->setParam(uColor, vec4(0.0f, 0.0f, 0.0f, 0.5f)); + Core::active.shader->setParam(uAmbient, vec3(0.0f)); mesh->renderShadowSpot(); } diff --git a/src/core.h b/src/core.h index 260b53b0..21c35928 100644 --- a/src/core.h +++ b/src/core.h @@ -83,6 +83,8 @@ #endif #endif +#define MAX_LIGHTS 3 + struct Shader; struct Texture; @@ -113,8 +115,8 @@ namespace Core { float deltaTime; mat4 mView, mProj, mViewProj, mViewInv, mModel; vec3 viewPos; - vec3 lightPos; - vec4 lightColor; + vec3 lightPos[MAX_LIGHTS]; + vec4 lightColor[MAX_LIGHTS]; vec3 ambient; vec4 color; @@ -185,6 +187,9 @@ namespace Core { support.VAO = (void*)glBindVertexArray != NULL; Sound::init(); + + for (int i = 0; i < MAX_LIGHTS; i++) + lightColor[i] = vec4(0, 0, 0, 1); } void free() { diff --git a/src/lara.h b/src/lara.h index 4df92e2e..e0806429 100644 --- a/src/lara.h +++ b/src/lara.h @@ -26,6 +26,7 @@ #define DESCENT_SPEED 2048.0f #define MUZZLE_FLASH_TIME 0.1f +#define FLASH_LIGHT_COLOR vec4(0.8f, 0.7f, 0.3f, 2048 * 2048) #define TARGET_MAX_DIST (8.0f * 1024.0f) struct Lara : Controller { @@ -490,12 +491,15 @@ struct Lara : Controller { for (int i = 0; i < count; i++) { Arm *arm; + int armIndex; if (wpnCurrent == Weapon::SHOTGUN) { if (!rightHand) continue; arm = &arms[0]; + armIndex = 0; } else { if (!(i ? leftHand : rightHand)) continue; arm = &arms[i]; + armIndex = i; } arm->shotTimer = 0.0f; @@ -523,6 +527,9 @@ struct Lara : Controller { nearDist = dist; } } + + Core::lightPos[1 + armIndex] = getJoint(armIndex == 0 ? 10 : 13, false).getPos(); + Core::lightColor[1 + armIndex] = FLASH_LIGHT_COLOR; } if (hasShot) { @@ -571,6 +578,9 @@ struct Lara : Controller { for (int i = 0; i < 2; i++){ arms[i].animTime += Core::deltaTime * arms[i].animDir; arms[i].shotTimer += Core::deltaTime; + + float intensity = clamp((0.1f - arms[i].shotTimer) * 20.0f, 0.0f, 1.0f); + Core::lightColor[1 + i] = FLASH_LIGHT_COLOR * vec4(intensity, intensity, intensity, sqrtf(intensity)); } if (isRifle) diff --git a/src/level.h b/src/level.h index cded603b..bebcd311 100644 --- a/src/level.h +++ b/src/level.h @@ -172,11 +172,11 @@ struct Level { void initShaders() { char def[255], ext[255]; - sprintf(def, "#define MAX_RANGES %d\n#define MAX_OFFSETS %d\n", mesh->animTexRangesCount, mesh->animTexOffsetsCount); + sprintf(def, "#define MAX_LIGHTS %d\n#define MAX_RANGES %d\n#define MAX_OFFSETS %d\n", MAX_LIGHTS, mesh->animTexRangesCount, mesh->animTexOffsetsCount); shaders[shStatic] = new Shader(SHADER, def); - sprintf(ext, "%s#define CAUSTICS\n", def); + sprintf(ext, "#define MAX_LIGHTS %d\n%s#define CAUSTICS\n", MAX_LIGHTS, def); shaders[shCaustics] = new Shader(SHADER, ext); - sprintf(ext, "%s#define SPRITE\n", def); + sprintf(ext, "#define MAX_LIGHTS %d\n%s#define SPRITE\n", MAX_LIGHTS, def); shaders[shSprite] = new Shader(SHADER, ext); } @@ -238,11 +238,12 @@ struct Level { sh->bind(); sh->setParam(uColor, Core::color); + sh->setParam(uLightColor, Core::lightColor[0], MAX_LIGHTS); + sh->setParam(uLightPos, Core::lightPos[0], MAX_LIGHTS); + sh->setParam(uAmbient, vec3(0.0f));//Core::ambient); // room static meshes { - PROFILE_MARKER("R_MESH"); - for (int i = 0; i < room.meshesCount; i++) { TR::Room::Mesh &rMesh = room.meshes[i]; if (rMesh.flags.rendered) continue; // skip if already rendered @@ -261,11 +262,17 @@ struct Level { // set light parameters getLight(offset, roomIndex); + if (rMesh.intensity >= 0) { + Core::ambient = vec3(intensity(rMesh.intensity) / 255.0f); + Core::ambient = vec3(0.0); + sh->setParam(uAmbient, Core::ambient); + } + // render static mesh mat4 mTemp = Core::mModel; Core::mModel.translate(offset); Core::mModel.rotateY(rMesh.rotation); - Core::active.shader->setParam(uModel, Core::mModel); + sh->setParam(uModel, Core::mModel); mesh->renderMesh(mesh->meshMap[sMesh->mesh]); Core::mModel = mTemp; } @@ -275,30 +282,30 @@ struct Level { if (!room.flags.rendered) { // skip if already rendered mat4 mTemp = Core::mModel; - { - PROFILE_MARKER("R_GEOM"); + room.flags.rendered = true; - room.flags.rendered = true; + Core::lightColor[0] = vec4(0, 0, 0, 1); + Core::ambient = vec3(0.0); - Core::lightColor = vec4(0.0f, 0.0f, 0.0f, 1.0f); - Core::ambient = vec3(1.0f); - sh->setParam(uLightColor, Core::lightColor); - sh->setParam(uAmbient, Core::ambient); + sh->setParam(uLightColor, Core::lightColor[0], MAX_LIGHTS); + sh->setParam(uLightPos, Core::lightPos[0], MAX_LIGHTS); + sh->setParam(uAmbient, Core::ambient); - Core::mModel.translate(offset); + Core::mModel.translate(offset); - // render room geometry - sh->setParam(uModel, Core::mModel); - mesh->renderRoomGeometry(roomIndex); - } + // render room geometry + sh->setParam(uModel, Core::mModel); + mesh->renderRoomGeometry(roomIndex); // render room sprites if (mesh->hasRoomSprites(roomIndex)) { - PROFILE_MARKER("R_SPR"); sh = shaders[shSprite]; sh->bind(); sh->setParam(uModel, Core::mModel); sh->setParam(uColor, Core::color); + sh->setParam(uLightColor, Core::lightColor[0], MAX_LIGHTS); + sh->setParam(uLightPos, Core::lightPos[0], MAX_LIGHTS); + sh->setParam(uAmbient, vec3(0.0f));//Core::ambient); mesh->renderRoomSprites(roomIndex); } @@ -353,17 +360,17 @@ struct Level { if (idx > -1) { TR::Room::Light &light = level.rooms[room].lights[idx]; float c = level.rooms[room].lights[idx].intensity / 8191.0f; - Core::lightPos = vec3(light.x, light.y, light.z); - Core::lightColor = vec4(c, c, c, (float)light.attenuation * (float)light.attenuation); + Core::lightPos[0] = vec3(light.x, light.y, light.z); + Core::lightColor[0] = vec4(c, c, c, (float)light.attenuation * (float)light.attenuation); } else { - Core::lightPos = vec3(0); - Core::lightColor = vec4(0, 0, 0, 1); + Core::lightPos[0] = vec3(0); + Core::lightColor[0] = vec4(0, 0, 0, 1); } Core::ambient = vec3(1.0f - level.rooms[roomIndex].ambient / 8191.0f); Core::active.shader->setParam(uAmbient, Core::ambient); - Core::active.shader->setParam(uLightPos, Core::lightPos); - Core::active.shader->setParam(uLightColor, Core::lightColor); + Core::active.shader->setParam(uLightPos, Core::lightPos[0], MAX_LIGHTS); + Core::active.shader->setParam(uLightColor, Core::lightColor[0], MAX_LIGHTS); } void renderEntity(const TR::Entity &entity) { diff --git a/src/mesh.h b/src/mesh.h index e579e885..88335a94 100644 --- a/src/mesh.h +++ b/src/mesh.h @@ -106,6 +106,20 @@ struct Mesh { n.z = (int)o.z;\ }\ +#define CHECK_ROOM_NORMAL(n) \ + vec3 o(d.vertices[f.vertices[0]].vertex);\ + vec3 a = o - d.vertices[f.vertices[1]].vertex;\ + vec3 b = o - d.vertices[f.vertices[2]].vertex;\ + o = b.cross(a).normal() * 16300.0f;\ + n.x = (int)o.x;\ + n.y = (int)o.y;\ + n.z = (int)o.z; + + +uint8 intensity(int lighting) { + float a = 1.0f - (lighting >> 5) / 255.0f; + return int(255 * a * a); +} struct MeshBuilder { // rooms @@ -252,13 +266,14 @@ struct MeshBuilder { addQuad(indices, iCount, vCount, vStart, vertices, &t); + TR::Vertex n; + CHECK_ROOM_NORMAL(n); + for (int k = 0; k < 4; k++) { TR::Room::Data::Vertex &v = d.vertices[f.vertices[k]]; - uint8 a = 255 - (v.lighting >> 5); - - vertices[vCount].coord = { v.vertex.x, v.vertex.y, v.vertex.z, 0 }; - vertices[vCount].color = { a, a, a, 255 }; - vertices[vCount].normal = { 0, 0, 0, 1 }; + vertices[vCount].coord = { v.vertex.x, v.vertex.y, v.vertex.z, 0 }; + vertices[vCount].color = { 255, 255, 255, intensity(v.lighting) }; + vertices[vCount].normal = { n.x, n.y, n.z, 0 }; vCount++; } } @@ -269,13 +284,14 @@ struct MeshBuilder { addTriangle(indices, iCount, vCount, vStart, vertices, &t); + TR::Vertex n; + CHECK_ROOM_NORMAL(n); + for (int k = 0; k < 3; k++) { auto &v = d.vertices[f.vertices[k]]; - uint8 a = 255 - (v.lighting >> 5); - - vertices[vCount].coord = { v.vertex.x, v.vertex.y, v.vertex.z, 0 }; - vertices[vCount].color = { a, a, a, 255 }; - vertices[vCount].normal = { 0, 0, 0, 1 }; + vertices[vCount].coord = { v.vertex.x, v.vertex.y, v.vertex.z, 0 }; + vertices[vCount].color = { 255, 255, 255, intensity(v.lighting) }; + vertices[vCount].normal = { n.x, n.y, n.z, 0 }; vCount++; } } @@ -288,8 +304,7 @@ struct MeshBuilder { TR::Room::Data::Vertex &v = d.vertices[f.vertex]; TR::SpriteTexture &sprite = level.spriteTextures[f.texture]; - uint8 intensity = 255 - (v.lighting >> 5); - addSprite(indices, vertices, iCount, vCount, vStart, v.vertex.x, v.vertex.y, v.vertex.z, sprite, intensity); + addSprite(indices, vertices, iCount, vCount, vStart, v.vertex.x, v.vertex.y, v.vertex.z, sprite, intensity(v.lighting)); } } @@ -335,21 +350,26 @@ struct MeshBuilder { addQuad(indices, iCount, vCount, vStart, vertices, &t); + short4 normal; + if (!normals) { + TR::Vertex n = { 0, 0, 0 }; + CHECK_NORMAL(n); + normal = { n.x, n.y, n.z, 0 }; + } + for (int k = 0; k < 4; k++) { - uint16 idx = f.vertices[k]; - TR::Vertex &v = mVertices[idx]; + TR::Vertex &v = mVertices[f.vertices[k]]; vertices[vCount].coord = { v.x, v.y, v.z, 0 }; if (normals) { - TR::Vertex &n = normals[idx]; + TR::Vertex &n = normals[f.vertices[k]]; CHECK_NORMAL(n); vertices[vCount].normal = { n.x, n.y, n.z, 0 }; - vertices[vCount].color = { 255, 255, 255, 255 }; + vertices[vCount].color = { 255, 255, 255, 0 }; } else { - uint8 a = 255 - (lights[idx] >> 5); - vertices[vCount].normal = { 0, 0, 0, 1 }; - vertices[vCount].color = { a, a, a, 255 }; + vertices[vCount].normal = normal; + vertices[vCount].color = { 255, 255, 255, intensity(lights[f.vertices[k]]) }; } vCount++; } @@ -363,19 +383,25 @@ struct MeshBuilder { addTriangle(indices, iCount, vCount, vStart, vertices, &t); + short4 normal; + if (!normals) { + TR::Vertex n = { 0, 0, 0 }; + CHECK_NORMAL(n); + normal = { n.x, n.y, n.z, 0 }; + } + for (int k = 0; k < 3; k++) { auto &v = mVertices[f.vertices[k]]; - vertices[vCount].coord = { v.x, v.y, v.z, 0 }; + vertices[vCount].coord = { v.x, v.y, v.z, 0 }; - if (nCount > 0) { + if (normals) { TR::Vertex &n = normals[f.vertices[k]]; CHECK_NORMAL(n); vertices[vCount].normal = { n.x, n.y, n.z, 0 }; - vertices[vCount].color = { 255, 255, 255, 255 }; + vertices[vCount].color = { 255, 255, 255, 0 }; } else { - uint8 a = 255 - (lights[f.vertices[k]] >> 5); - vertices[vCount].normal = { 0, 0, 0, 1 }; - vertices[vCount].color = { a, a, a, 255 }; + vertices[vCount].normal = normal; + vertices[vCount].color = { 255, 255, 255, intensity(lights[f.vertices[k]]) }; } vCount++; } @@ -389,20 +415,26 @@ struct MeshBuilder { addQuad(indices, iCount, vCount, vStart, vertices, &whiteTileQuad); + short4 normal; + if (!normals) { + TR::Vertex n = { 0, 0, 0 }; + CHECK_NORMAL(n); + normal = { n.x, n.y, n.z, 0 }; + } + for (int k = 0; k < 4; k++) { auto &v = mVertices[f.vertices[k]]; - vertices[vCount].coord = { v.x, v.y, v.z, 0 }; + vertices[vCount].coord = { v.x, v.y, v.z, 0 }; - if (nCount > 0) { + if (normals) { TR::Vertex &n = normals[f.vertices[k]]; CHECK_NORMAL(n); vertices[vCount].normal = { n.x, n.y, n.z, 0 }; - vertices[vCount].color = { c.r, c.g, c.b, 255 }; + vertices[vCount].color = { c.r, c.g, c.b, 0 }; } else { - uint8 a = 255 - (lights[f.vertices[k]] >> 5); - vertices[vCount].normal = { 0, 0, 0, 1 }; - vertices[vCount].color = { a, a, a, 255 }; + vertices[vCount].normal = normal; + vertices[vCount].color = { c.r, c.g, c.b, intensity(lights[f.vertices[k]]) }; } vCount++; } @@ -419,17 +451,23 @@ struct MeshBuilder { for (int k = 0; k < 3; k++) { auto &v = mVertices[f.vertices[k]]; - vertices[vCount].coord = { v.x, v.y, v.z, 0 }; + vertices[vCount].coord = { v.x, v.y, v.z, 0 }; + + short4 normal; + if (!normals) { + TR::Vertex n = { 0, 0, 0 }; + CHECK_NORMAL(n); + normal = { n.x, n.y, n.z, 0 }; + } - if (nCount > 0) { + if (normals) { TR::Vertex &n = normals[f.vertices[k]]; CHECK_NORMAL(n); vertices[vCount].normal = { n.x, n.y, n.z, 0 }; - vertices[vCount].color = { c.r, c.g, c.b, 255 }; + vertices[vCount].color = { c.r, c.g, c.b, 0 }; } else { - uint8 a = 255 - (lights[f.vertices[k]] >> 5); - vertices[vCount].normal = { 0, 0, 0, 1 }; - vertices[vCount].color = { a, a, a, 255 }; + vertices[vCount].normal = normal; + vertices[vCount].color = { c.r, c.g, c.b, intensity(lights[f.vertices[k]]) }; } vCount++; } @@ -450,8 +488,8 @@ struct MeshBuilder { // build shadow spot for (int i = 0; i < 8; i++) { Vertex &v = vertices[vCount + i]; - v.normal = { 0, 0, 0, 1 }; - v.color = { 255, 255, 255, 255 }; + v.normal = { 0, -1, 0, 0 }; + v.color = { 255, 255, 255, 0 }; v.texCoord = { 32688, 32688, 0, 0 }; float a = i * (PI / 4.0f) + (PI / 8.0f); @@ -618,7 +656,7 @@ struct MeshBuilder { quad[0].coord = quad[1].coord = quad[2].coord = quad[3].coord = { x, y, z, 0 }; quad[0].normal = quad[1].normal = quad[2].normal = quad[3].normal = { 0, 0, 0, 0 }; - quad[0].color = quad[1].color = quad[2].color = quad[3].color = { intensity, intensity, intensity, 255 }; + quad[0].color = quad[1].color = quad[2].color = quad[3].color = { 255, 255, 255, intensity }; int tx = (sprite.tile % 4) * 256; int ty = (sprite.tile / 4) * 256; diff --git a/src/shader.glsl b/src/shader.glsl index 82e4d54f..44a87aac 100644 --- a/src/shader.glsl +++ b/src/shader.glsl @@ -1,9 +1,7 @@ R"====( -#ifndef SPRITE - varying vec4 vNormal; - varying vec3 vLightVec; - varying vec3 vViewVec; -#endif +varying vec4 vNormal; +varying vec3 vLightVec[MAX_LIGHTS]; +varying vec3 vViewVec; varying vec2 vTexCoord; varying vec4 vColor; @@ -11,11 +9,10 @@ varying vec4 vColor; uniform mat4 uViewProj; uniform mat4 uModel; uniform mat4 uViewInv; - uniform vec4 uColor; + uniform vec3 uLightPos[MAX_LIGHTS]; + uniform vec3 uViewPos; - #ifndef SPRITE - uniform vec3 uViewPos; - uniform vec3 uLightPos; + #ifndef SPRITE uniform vec2 uAnimTexRanges[MAX_RANGES]; uniform vec2 uAnimTexOffsets[MAX_OFFSETS]; #endif @@ -31,7 +28,7 @@ varying vec4 vColor; void main() { vec4 coord = uModel * vec4(aCoord.xyz, 1.0); - vColor = aColor * uColor; + vColor = aColor; #ifdef CAUSTICS float sum = coord.x + coord.y + coord.z; @@ -46,49 +43,59 @@ varying vec4 vColor; vec2 offset = uAnimTexOffsets[int(range.x + f)]; // texCoord offset from first frame vTexCoord = (aTexCoord.xy + offset) * TEXCOORD_SCALE; // first frame + offset * isAnimated - - vViewVec = uViewPos - coord.xyz; - vLightVec = uLightPos - coord.xyz; vNormal = uModel * aNormal; #else vTexCoord = aTexCoord.xy * TEXCOORD_SCALE; coord.xyz -= uViewInv[0].xyz * aTexCoord.z + uViewInv[1].xyz * aTexCoord.w; + vNormal = vec4(uViewPos.xyz - coord.xyz, 0.0); #endif + vViewVec = uViewPos - coord.xyz; + for (int i = 0; i < MAX_LIGHTS; i++) + vLightVec[i] = uLightPos[i] - coord.xyz; + gl_Position = uViewProj * coord; } #else uniform sampler2D sDiffuse; - - #ifndef SPRITE - uniform vec3 uAmbient; - uniform vec4 uLightColor; - #endif + uniform vec4 uColor; + uniform vec3 uAmbient; + uniform vec4 uLightColor[MAX_LIGHTS]; void main() { vec4 color = texture2D(sDiffuse, vTexCoord); if (color.w < 0.6) discard; - color *= vColor; - #ifndef SPRITE - color.xyz = pow(abs(color.xyz), vec3(2.2)); - vec3 normal = normalize(vNormal.xyz); - vec3 lightVec = normalize(vLightVec); - vec3 viewVec = normalize(vViewVec); - float lum = dot(normal, lightVec); - float att = max(0.0, 1.0 - dot(vLightVec, vLightVec) / uLightColor.w); - vec3 light = uLightColor.xyz * max(vNormal.w, lum * att) + uAmbient; - // apply backlight - light *= max(vNormal.w, dot(normal, viewVec) * 0.5 + 0.5); - color.xyz *= light; - color.xyz = pow(abs(color.xyz), vec3(1.0/2.2)); - #endif + color *= uColor; + color.xyz *= vColor.xyz; + + color.xyz = pow(abs(color.xyz), vec3(2.2)); // to linear space + + // calc point lights + vec3 normal = normalize(vNormal.xyz); + vec3 viewVec = normalize(vViewVec); + vec3 light = uAmbient; + for (int i = 0; i < MAX_LIGHTS; i++) { + vec3 lv = vLightVec[i]; + vec4 lc = uLightColor[i]; + float lum = max(0.0, dot(normal, normalize(lv))); + float att = max(0.0, 1.0 - dot(lv, lv) / lc.w); + light += lc.xyz * (lum * att); + } + // calc backlight + light *= dot(normal, viewVec) * 0.5 + 0.5; + + // apply lighting + color.xyz *= vColor.w + light; + + color.xyz = pow(abs(color.xyz), vec3(1.0/2.2)); // back to gamma space - // fog + // apply fog float fog = clamp(1.0 / exp(gl_FragCoord.z / gl_FragCoord.w * 0.000025), 0.0, 1.0); + color = mix(vec4(0.0, 0.0, 0.0, 1.0), color, fog); - gl_FragColor = mix(vec4(0.0, 0.0, 0.0, 1.0), color, fog); + gl_FragColor = color; } #endif )====" \ No newline at end of file diff --git a/src/utils.h b/src/utils.h index 9b0b1c43..a8d318ae 100644 --- a/src/utils.h +++ b/src/utils.h @@ -158,6 +158,7 @@ struct vec4 { vec4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {} vec4(const vec3 &xyz, float w) : x(xyz.x), y(xyz.y), z(xyz.z), w(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; } };