diff --git a/bin/OpenLara.exe b/bin/OpenLara.exe index c38e489..0930478 100644 Binary files a/bin/OpenLara.exe and b/bin/OpenLara.exe differ diff --git a/src/camera.h b/src/camera.h index 1c74a43..ec07618 100644 --- a/src/camera.h +++ b/src/camera.h @@ -163,8 +163,8 @@ struct Camera { Core::mProj = mat4(fov, (float)Core::width / (float)Core::height, znear, zfar); Core::mViewProj = Core::mProj * Core::mView; - - Core::viewPos = Core::mView.inverse().getPos(); + Core::mViewInv = Core::mView.inverse(); + Core::viewPos = Core::mViewInv.getPos(); frustum->pos = Core::viewPos; frustum->calcPlanes(Core::mViewProj); diff --git a/src/core.h b/src/core.h index fdf3de1..7d09957 100644 --- a/src/core.h +++ b/src/core.h @@ -54,16 +54,24 @@ PFNGLBUFFERDATAARBPROC glBufferData; #endif +struct Shader; +struct Texture; + namespace Core { int width, height; float deltaTime; - mat4 mView, mProj, mViewProj, mModel; + mat4 mView, mProj, mViewProj, mViewInv, mModel; vec3 viewPos; vec3 lightPos; vec4 lightColor; vec3 ambient; vec4 color; + struct { + Shader *shader; + Texture *testures[8]; + } active; + struct { int dips; int tris; diff --git a/src/format.h b/src/format.h index 1a4ff6d..3b40516 100644 --- a/src/format.h +++ b/src/format.h @@ -368,7 +368,7 @@ namespace TR { struct SpriteTexture { uint16 tile; uint8 u, v; - uint16 w, h; // (ActualValue * 256) + 255 + uint16 w, h; int16 l, t, r, b; }; diff --git a/src/level.h b/src/level.h index f5032f9..5b0ae84 100644 --- a/src/level.h +++ b/src/level.h @@ -16,8 +16,10 @@ const char SHADER[] = ; struct Level { + enum { shStatic, shSprite, shMAX }; + TR::Level level; - Shader *shader; + Shader *shaders[shMAX]; Texture *atlas; Mesh *mesh; @@ -25,11 +27,13 @@ struct Level { float time; - MeshRange *rangeRooms; + struct RoomRange { + MeshRange geometry; + MeshRange sprites; + } *roomRanges; Camera camera; - int mCount; struct MeshInfo : MeshRange { int offset; @@ -38,7 +42,8 @@ struct Level { } *meshInfo; Level(Stream &stream) : level{stream}, time(0.0f) { - shader = new Shader(SHADER); + shaders[shStatic] = new Shader(SHADER); + shaders[shSprite] = new Shader(SHADER, "#define SPRITE\n"); initAtlas(); initMesh(); @@ -61,10 +66,11 @@ struct Level { } ~Level() { - delete shader; + for (int i = 0; i < shMAX; i++) + delete shaders[i]; delete atlas; delete mesh; - delete[] rangeRooms; + delete[] roomRanges; delete[] meshInfo; delete lara; @@ -108,18 +114,26 @@ struct Level { void initMesh() { // TODO: sort by texture attribute (t.attribute == 2 ? bmAdd : bmAlpha) - rangeRooms = new MeshRange[level.roomsCount]; + roomRanges = new RoomRange[level.roomsCount]; int iCount = 0, vCount = 0; // get rooms mesh info for (int i = 0; i < level.roomsCount; i++) { - rangeRooms[i].vStart = vCount; - rangeRooms[i].iStart = iCount; TR::Room::Data &d = level.rooms[i].data; + RoomRange &r = roomRanges[i]; + + r.geometry.vStart = vCount; + r.geometry.iStart = iCount; iCount += d.rCount * 6 + d.tCount * 3; vCount += d.rCount * 4 + d.tCount * 3; - rangeRooms[i].iCount = iCount - rangeRooms[i].iStart; + r.geometry.iCount = iCount - r.geometry.iStart; + + r.sprites.vStart = vCount; + r.sprites.iStart = iCount; + iCount += d.sCount * 6; + vCount += d.sCount * 4; + r.sprites.iCount = iCount - r.sprites.iStart; } // get objects mesh info @@ -160,12 +174,11 @@ struct Level { Vertex *vertices = new Vertex[vCount]; iCount = vCount = 0; - // rooms geometry for (int i = 0; i < level.roomsCount; i++) { TR::Room::Data &d = level.rooms[i].data; + // rooms geometry int vStart = vCount; - for (int j = 0; j < d.rCount; j++) { auto &f = d.rectangles[j]; auto &t = level.objectTextures[f.texture]; @@ -192,7 +205,7 @@ struct Level { vertices[vCount].coord = { v.vertex.x, v.vertex.y, v.vertex.z }; vertices[vCount].color = { a, a, a, 255 }; - vertices[vCount].normal = { 0, 0, 0, 0x7FFF }; + vertices[vCount].normal = { 0, 0, 0, 1 }; vertices[vCount].texCoord.x = ((tx + t.vertices[k].Xpixel) << 5) + 16; vertices[vCount].texCoord.y = ((ty + t.vertices[k].Ypixel) << 5) + 16; vCount++; @@ -221,12 +234,61 @@ struct Level { vertices[vCount].coord = { v.vertex.x, v.vertex.y, v.vertex.z }; vertices[vCount].color = { a, a, a, 255 }; - vertices[vCount].normal = { 0, 0, 0, 0x7FFF }; + vertices[vCount].normal = { 0, 0, 0, 1 }; vertices[vCount].texCoord.x = ((tx + t.vertices[k].Xpixel) << 5) + 16; vertices[vCount].texCoord.y = ((ty + t.vertices[k].Ypixel) << 5) + 16; vCount++; } } + + // rooms sprites + TR::Room::Info &info = level.rooms[i].info; + vStart = vCount; + for (int j = 0; j < d.sCount; j++) { + auto &f = d.sprites[j]; + + int vIndex = vCount - vStart; + + indices[iCount + 0] = vIndex + 0; + indices[iCount + 1] = vIndex + 1; + indices[iCount + 2] = vIndex + 2; + + indices[iCount + 3] = vIndex + 0; + indices[iCount + 4] = vIndex + 2; + indices[iCount + 5] = vIndex + 3; + + iCount += 6; + + TR::Room::Data::Vertex &v = d.vertices[f.vertex]; + TR::SpriteTexture &sprite = level.spriteTextures[f.texture]; + + Vertex *quad = &vertices[vCount]; + + quad[0].coord = quad[1].coord = quad[2].coord = quad[3].coord = { v.vertex.x, v.vertex.y, v.vertex.z }; + + int tx = (sprite.tile % 4) * 256; + int ty = (sprite.tile / 4) * 256; + + int16 u0 = ((tx + sprite.u) << 5) + 16; + int16 v0 = ((ty + sprite.v) << 5) + 16; + int16 u1 = u0 + (sprite.w >> 3); + int16 v1 = v0 + (sprite.h >> 3); + + quad[0].texCoord = { u0, v0 }; + quad[1].texCoord = { u1, v0 }; + quad[2].texCoord = { u1, v1 }; + quad[3].texCoord = { u0, v1 }; + + quad[0].normal = { sprite.r, sprite.t, 0, 0 }; + quad[1].normal = { sprite.l, sprite.t, 0, 0 }; + quad[2].normal = { sprite.l, sprite.b, 0, 0 }; + quad[3].normal = { sprite.r, sprite.b, 0, 0 }; + + uint8 a = 255 - (v.lighting >> 5); + quad[0].color = quad[1].color = quad[2].color = quad[3].color = { a, a, a, 255 }; + + vCount += 4; + } } // objects geometry @@ -285,11 +347,11 @@ struct Level { if (nCount > 0) { TR::Vertex &n = normals[f.vertices[k]]; - vertices[vCount].normal = { n.x, n.y, n.z, 0 }; + vertices[vCount].normal = { n.x, n.y, n.z, 0 }; vertices[vCount].color = { 255, 255, 255, 255 }; } else { uint8 a = 255 - (lights[f.vertices[k]] >> 5); - vertices[vCount].normal = { 0, 0, 0, 255 }; + vertices[vCount].normal = { 0, 0, 0, 1 }; vertices[vCount].color = { a, a, a, 255 }; } vertices[vCount].texCoord.x = ((tx + t.vertices[k].Xpixel) << 5) + 16; @@ -322,11 +384,11 @@ struct Level { if (nCount > 0) { TR::Vertex &n = normals[f.vertices[k]]; - vertices[vCount].normal = { n.x, n.y, n.z, 0 }; + vertices[vCount].normal = { n.x, n.y, n.z, 0 }; vertices[vCount].color = { 255, 255, 255, 255 }; } else { uint8 a = 255 - (lights[f.vertices[k]] >> 5); - vertices[vCount].normal = { 0, 0, 0, 255 }; + vertices[vCount].normal = { 0, 0, 0, 1 }; vertices[vCount].color = { a, a, a, 255 }; } vertices[vCount].texCoord.x = ((tx + t.vertices[k].Xpixel) << 5) + 16; @@ -364,7 +426,7 @@ struct Level { vertices[vCount].color = { c.r, c.g, c.b, 255 }; } else { uint8 a = 255 - (lights[f.vertices[k]] >> 5); - vertices[vCount].normal = { 0, 0, 0, 255 }; + vertices[vCount].normal = { 0, 0, 0, 1 }; vertices[vCount].color = { a, a, a, 255 }; // TODO: apply color } vertices[vCount].texCoord = { 1022 << 5, 1022 << 5 }; @@ -393,11 +455,11 @@ struct Level { if (nCount > 0) { TR::Vertex &n = normals[f.vertices[k]]; - vertices[vCount].normal = { n.x, n.y, n.z, 0 }; + vertices[vCount].normal = { n.x, n.y, n.z, 0 }; vertices[vCount].color = { c.r, c.g, c.b, 255 }; } else { uint8 a = 255 - (lights[f.vertices[k]] >> 5); - vertices[vCount].normal = { 0, 0, 0, 255 }; + vertices[vCount].normal = { 0, 0, 0, 1 }; vertices[vCount].color = { a, a, a, 255 }; // TODO: apply color } vertices[vCount].texCoord = { 1022 << 5, 1022 << 5 }; @@ -437,12 +499,22 @@ struct Level { Core::ambient = vec3(1.0f); Core::lightColor = vec4(0.0f, 0.0f, 0.0f, 1.0f); - shader->setParam(uModel, Core::mModel); - shader->setParam(uColor, Core::color); - shader->setParam(uAmbient, Core::ambient); - shader->setParam(uLightColor, Core::lightColor); + Shader *sh = shaders[shStatic]; + sh->bind(); + sh->setParam(uModel, Core::mModel); + sh->setParam(uColor, Core::color); + sh->setParam(uAmbient, Core::ambient); + sh->setParam(uLightColor, Core::lightColor); + + mesh->render(roomRanges[index].geometry); + + if (roomRanges[index].sprites.iCount) { + sh = shaders[shSprite]; + sh->bind(); + sh->setParam(uModel, Core::mModel); + mesh->render(roomRanges[index].sprites); + } - mesh->render(rangeRooms[index]); Core::mModel = m; // meshes @@ -464,7 +536,6 @@ struct Level { Core::mModel = m; } - Camera::Frustum *camFrustum = camera.frustum; // push camera frustum Camera::Frustum frustum = *camFrustum; camera.frustum = &frustum; @@ -485,13 +556,6 @@ struct Level { } } camera.frustum = camFrustum; // pop camera frustum - - /* - // sprites - Core::setBlending(bmAlpha); - for (int j = 0; j < room.data.sCount; j++) - renderSprite(room, room.data.sprites[j]); - */ } @@ -504,58 +568,13 @@ struct Level { MeshInfo &m = meshInfo[i]; if (camera.frustum->isVisible(Core::mModel * m.center, m.radius)) { - shader->setParam(uModel, Core::mModel); + Core::active.shader->setParam(uModel, Core::mModel); mesh->render(m); } break; } } - void renderSprite(const TR::SpriteTexture &sprite) { - float u0 = sprite.u / 256.0f; - float v0 = sprite.v / 255.0f; - float u1 = u0 + sprite.w / (256.0f * 256.0f); - float v1 = v0 + sprite.h / (256.0f * 256.0f); - - mat4 m = Core::mView.inverse(); - vec3 up = m.up.xyz * vec3(-1, -1, 1) * (-1); - vec3 right = m.right.xyz * vec3(-1, -1, 1); - - vec3 p[4]; - p[0] = right * sprite.r + up * sprite.b; - p[1] = right * sprite.l + up * sprite.b; - p[2] = right * sprite.l + up * sprite.t; - p[3] = right * sprite.r + up * sprite.t; - -// bindTexture(sprite.tile); - /* - glBegin(GL_QUADS); - glTexCoord2f(u0, v1); - glVertex3fv((GLfloat*)&p[0]); - glTexCoord2f(u1, v1); - glVertex3fv((GLfloat*)&p[1]); - glTexCoord2f(u1, v0); - glVertex3fv((GLfloat*)&p[2]); - glTexCoord2f(u0, v0); - glVertex3fv((GLfloat*)&p[3]); - glEnd(); - */ - } - - void renderSprite(const TR::Room &room, const TR::Room::Data::Sprite &sprite) { - auto &v = room.data.vertices[sprite.vertex]; - float a = 1.0f - v.lighting / (float)0x1FFF; - /* - glColor3f(a, a, a); - glPushMatrix(); - glTranslatef(v.vertex.x + room.info.x, v.vertex.y, v.vertex.z + room.info.z); - - renderSprite(level.spriteTextures[sprite.texture]); - - glPopMatrix(); - */ - } - vec3 getAngle(TR::AnimFrame *frame, int index) { #define ANGLE_SCALE (2.0f * PI / 1024.0f) @@ -710,9 +729,9 @@ struct Level { Core::lightColor = vec4(0.0f); } Core::ambient = vec3(1.0f - level.rooms[roomIndex].ambient / 8191.0f); - shader->setParam(uAmbient, Core::ambient); - shader->setParam(uLightPos, Core::lightPos); - shader->setParam(uLightColor, Core::lightColor); + Core::active.shader->setParam(uAmbient, Core::ambient); + Core::active.shader->setParam(uLightPos, Core::lightPos); + Core::active.shader->setParam(uLightColor, Core::lightColor); } void renderEntity(const TR::Entity &entity) { @@ -728,7 +747,7 @@ struct Level { float l = 1.0f; Core::color = vec4(c, c, c, 1.0); - shader->setParam(uColor, Core::color); + Core::active.shader->setParam(uColor, Core::color); getLight(vec3(entity.x, entity.y, entity.z), entity.room); @@ -989,12 +1008,16 @@ struct Level { #endif camera.setup();; - shader->bind(); atlas->bind(0); mesh->bind(); - shader->setParam(uViewProj, Core::mViewProj); - + // set frame constants for all shaders + for (int i = 0; i < shMAX; i++) { + shaders[i]->bind(); + shaders[i]->setParam(uViewProj, Core::mViewProj); + shaders[i]->setParam(uViewInv, Core::mViewInv); + shaders[i]->setParam(uViewPos, Core::viewPos); + } glEnable(GL_DEPTH_TEST); Core::setCulling(cfFront); @@ -1010,6 +1033,7 @@ struct Level { //for (int i = 0; i < level.roomsCount; i++) // renderRoom(i); + shaders[shStatic]->bind(); for (int i = 0; i < level.entitiesCount; i++) renderEntity(level.entities[i]); diff --git a/src/mesh.h b/src/mesh.h index bf3c9f3..8e0cb29 100644 --- a/src/mesh.h +++ b/src/mesh.h @@ -48,7 +48,7 @@ struct Mesh { Vertex *v = (Vertex*)(range.vStart * sizeof(Vertex)); glVertexAttribPointer(aCoord, 3, GL_SHORT, false, sizeof(Vertex), &v->coord); glVertexAttribPointer(aTexCoord, 2, GL_SHORT, true, sizeof(Vertex), &v->texCoord); - glVertexAttribPointer(aNormal, 4, GL_SHORT, true, sizeof(Vertex), &v->normal); + glVertexAttribPointer(aNormal, 4, GL_SHORT, false, sizeof(Vertex), &v->normal); glVertexAttribPointer(aColor, 4, GL_UNSIGNED_BYTE, true, sizeof(Vertex), &v->color); glDrawElements(GL_TRIANGLES, range.iCount, GL_UNSIGNED_SHORT, (GLvoid*)(range.iStart * sizeof(Index))); diff --git a/src/shader.glsl b/src/shader.glsl index 351f0e4..a11aa65 100644 --- a/src/shader.glsl +++ b/src/shader.glsl @@ -1,13 +1,21 @@ R"====( -varying vec3 vLightVec; +#ifndef SPRITE + varying vec4 vNormal; + varying vec3 vLightVec; +#endif varying vec2 vTexCoord; -varying vec4 vNormal; varying vec4 vColor; +varying vec3 vViewVec; #ifdef VERTEX uniform mat4 uViewProj; uniform mat4 uModel; - uniform vec3 uLightPos; + #ifndef SPRITE + uniform vec3 uViewPos; + uniform vec3 uLightPos; + #else + uniform mat4 uViewInv; + #endif attribute vec3 aCoord; attribute vec2 aTexCoord; @@ -16,31 +24,39 @@ varying vec4 vColor; void main() { vec4 coord = uModel * vec4(aCoord, 1.0); - vLightVec = uLightPos - coord.xyz; vTexCoord = aTexCoord; - vNormal = uModel * aNormal; vColor = aColor; + #ifndef SPRITE + vViewVec = uViewPos - coord.xyz; + vLightVec = uLightPos - coord.xyz; + vNormal = uModel * aNormal; + #else + coord.xyz -= uViewInv[0].xyz * aNormal.x + uViewInv[1].xyz * aNormal.y; + #endif gl_Position = uViewProj * coord; } #else uniform sampler2D sDiffuse; - uniform vec4 uColor; - uniform vec3 uAmbient; - uniform vec4 uLightColor; - + #ifndef SPRITE + uniform vec4 uColor; + uniform vec3 uAmbient; + uniform vec4 uLightColor; + #endif + void main() { vec4 color = texture2D(sDiffuse, vTexCoord); if (color.w < 0.9) discard; - color *= vColor * uColor; -// #ifdef LIGHTING - color.xyz = pow(abs(color.xyz), vec3(2.2)); - float lum = dot(normalize(vNormal.xyz), normalize(vLightVec)); - float att = max(0.0, 1.0 - dot(vLightVec, vLightVec) / uLightColor.w); - vec3 light = uLightColor.xyz * max(vNormal.w, lum * att) + uAmbient; - color.xyz *= light; - color.xyz = pow(abs(color.xyz), vec3(1.0/2.2)); -// #endif + color *= vColor; + #ifndef SPRITE + color *= uColor; + color.xyz = pow(abs(color.xyz), vec3(2.2)); + float lum = dot(normalize(vNormal.xyz), normalize(vLightVec)); + float att = max(0.0, 1.0 - dot(vLightVec, vLightVec) / uLightColor.w); + vec3 light = uLightColor.xyz * max(vNormal.w, lum * att) + uAmbient; + color.xyz *= light; + color.xyz = pow(abs(color.xyz), vec3(1.0/2.2)); + #endif gl_FragColor = color; } #endif diff --git a/src/shader.h b/src/shader.h index 9233dba..6d9ba6f 100644 --- a/src/shader.h +++ b/src/shader.h @@ -5,17 +5,17 @@ enum AttribType { aCoord, aTexCoord, aNormal, aColor, aMAX }; enum SamplerType { sDiffuse, sMAX }; -enum UniformType { uViewProj, uModel, uColor, uAmbient, uLightPos, uLightColor, uMAX }; +enum UniformType { uViewProj, uViewInv, uModel, uColor, uAmbient, uViewPos, uLightPos, uLightColor, uMAX }; const char *AttribName[aMAX] = { "aCoord", "aTexCoord", "aNormal", "aColor" }; const char *SamplerName[sMAX] = { "sDiffuse" }; -const char *UniformName[uMAX] = { "uViewProj", "uModel", "uColor", "uAmbient", "uLightPos", "uLightColor" }; +const char *UniformName[uMAX] = { "uViewProj", "uViewInv", "uModel", "uColor", "uAmbient", "uViewPos", "uLightPos", "uLightColor" }; struct Shader { GLuint ID; GLint uID[uMAX]; - Shader(const char *text) { + Shader(const char *text, const char *defines = "") { #ifdef MOBILE #define GLSL_DEFINE "precision highp float;\n" "#define MOBILE\n" #else @@ -23,9 +23,9 @@ struct Shader { #endif const int type[2] = { GL_VERTEX_SHADER, GL_FRAGMENT_SHADER }; - const char *code[2][2] = { - { GLSL_DEFINE "#define VERTEX\n", text }, - { GLSL_DEFINE "#define FRAGMENT\n", text } + const char *code[2][3] = { + { GLSL_DEFINE "#define VERTEX\n", defines, text }, + { GLSL_DEFINE "#define FRAGMENT\n", defines, text } }; GLchar info[256]; @@ -33,7 +33,7 @@ struct Shader { ID = glCreateProgram(); for (int i = 0; i < 2; i++) { GLuint obj = glCreateShader(type[i]); - glShaderSource(obj, 2, code[i], NULL); + glShaderSource(obj, 3, code[i], NULL); glCompileShader(obj); glGetShaderInfoLog(obj, sizeof(info), NULL, info); @@ -65,6 +65,7 @@ struct Shader { void bind() { glUseProgram(ID); + Core::active.shader = this; } void setParam(UniformType uType, const vec3 &value, int count = 1) { diff --git a/src/web/main.cpp b/src/web/main.cpp index b38cec3..c80c9a4 100644 --- a/src/web/main.cpp +++ b/src/web/main.cpp @@ -163,7 +163,7 @@ EM_BOOL mouseCallback(int eventType, const EmscriptenMouseEvent *e, void *userDa int main() { initGL(); - emscripten_set_canvas_size(Core::width = 1280, Core::height = 720); + emscripten_set_canvas_size(Core::width = 800, Core::height = 600); emscripten_set_keydown_callback(0, 0, 1, keyCallback); emscripten_set_keyup_callback(0, 0, 1, keyCallback);