From f87a72e7fb903eba5ee587329240b58827fae6c2 Mon Sep 17 00:00:00 2001 From: XProger Date: Thu, 1 Sep 2016 03:21:01 +0300 Subject: [PATCH] #6 add environment sprites --- bin/OpenLara.exe | Bin 34304 -> 35840 bytes src/camera.h | 4 +- src/core.h | 10 ++- src/format.h | 2 +- src/level.h | 198 ++++++++++++++++++++++++++--------------------- src/mesh.h | 2 +- src/shader.glsl | 52 ++++++++----- src/shader.h | 15 ++-- src/web/main.cpp | 2 +- 9 files changed, 167 insertions(+), 118 deletions(-) diff --git a/bin/OpenLara.exe b/bin/OpenLara.exe index c38e48916a290f05a1cbcbf246ccc4a8edb65b75..09304781f2f36c6f38c9e2b7924cc0807bdd654b 100644 GIT binary patch delta 18194 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 delta 16551 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 F{txpos = 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);