From 5739de604403f592efed4d2b96ec08b08646ecab Mon Sep 17 00:00:00 2001 From: XProger Date: Thu, 27 Jul 2017 04:09:49 +0300 Subject: [PATCH] #23 room render optimization for mobile devices; contact ambient occlusion (WIP); #11 inventory touch button --- src/cache.h | 4 +- src/core.h | 3 + src/debug.h | 1 + src/game.h | 1 + src/input.h | 24 +++--- src/inventory.h | 10 ++- src/level.h | 164 ++++++++++++++++++++++------------------ src/shader.h | 4 +- src/shaders/shader.glsl | 88 +++++++++++---------- src/sprite.h | 4 +- src/texture.h | 5 +- src/utils.h | 4 +- 12 files changed, 175 insertions(+), 137 deletions(-) diff --git a/src/cache.h b/src/cache.h index 4c884b3..466cb56 100644 --- a/src/cache.h +++ b/src/cache.h @@ -131,7 +131,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#define SHADOW_TEX_SIZE %d.0\n", ext, passNames[pass], typ, MAX_LIGHTS, animTexRangesCount, animTexOffsetsCount, FOG_DIST, WATER_FOG_DIST, SHADOW_TEX_SIZE); + 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 MAX_CONTACTS %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, MAX_CONTACTS, 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"); @@ -139,6 +139,7 @@ struct ShaderCache { if (Core::settings.detail.lighting) strcat(def, "#define OPT_LIGHTING\n"); if (Core::settings.detail.shadows) strcat(def, "#define OPT_SHADOW\n"); if (Core::settings.detail.water) strcat(def, "#define OPT_WATER\n"); + if (Core::settings.detail.contact) strcat(def, "#define OPT_CONTACT\n"); break; } case Core::passWater : { @@ -181,7 +182,6 @@ struct ShaderCache { // TODO: bindable uniform block shader->setParam(uViewProj, Core::mViewProj); shader->setParam(uLightProj, Core::mLightProj); - shader->setParam(uViewInv, Core::mViewInv); shader->setParam(uViewPos, Core::viewPos); shader->setParam(uParam, Core::params); MeshBuilder *mesh = game->getMesh(); diff --git a/src/core.h b/src/core.h index 31b0643..aa10ddd 100644 --- a/src/core.h +++ b/src/core.h @@ -213,6 +213,7 @@ namespace Core { #define MAX_LIGHTS 4 #define MAX_CACHED_LIGHTS 3 #define MAX_RENDER_BUFFERS 32 +#define MAX_CONTACTS 15 struct Shader; struct Texture; @@ -322,6 +323,7 @@ namespace Core { vec3 lightPos[MAX_LIGHTS]; vec4 lightColor[MAX_LIGHTS]; vec4 params; + vec4 contacts[MAX_CONTACTS]; Texture *blackTex, *whiteTex; @@ -391,6 +393,7 @@ namespace Core { bool lighting; bool shadows; bool water; + bool contact; } detail; struct { diff --git a/src/debug.h b/src/debug.h index 4b43cbe..18eef15 100644 --- a/src/debug.h +++ b/src/debug.h @@ -60,6 +60,7 @@ namespace Debug { glUseProgram(0); Core::active.shader = NULL; Core::active.textures[0] = NULL; + Core::validateRenderState(); } void end() { diff --git a/src/game.h b/src/game.h index 6d88517..0fd2ef9 100644 --- a/src/game.h +++ b/src/game.h @@ -23,6 +23,7 @@ namespace Game { Core::settings.detail.lighting = true; Core::settings.detail.shadows = true; Core::settings.detail.water = Core::support.texFloat || Core::support.texHalf; + Core::settings.detail.contact = false; Core::settings.controls.retarget = true; diff --git a/src/input.h b/src/input.h index f6b436b..172eeae 100644 --- a/src/input.h +++ b/src/input.h @@ -111,7 +111,7 @@ namespace Input { } } head; - enum TouchButton { bNone, bWeapon, bWalk, bAction, bJump, bMAX }; + enum TouchButton { bNone, bWeapon, bWalk, bAction, bJump, bInventory, bMAX }; enum TouchZone { zMove, zLook, zButton, zMAX }; float touchTimerVis, touchTimerTap; @@ -245,11 +245,12 @@ namespace Input { float radius = offset; vec2 center = vec2(Core::width - offset * 0.7f, Core::height - offset * 0.7f); - btnPos[bWeapon] = center; - btnPos[bJump] = center + vec2(cosf(-PI * 0.5f), sinf(-PI * 0.5f)) * radius; - btnPos[bAction] = center + vec2(cosf(-PI * 3.0f / 4.0f), sinf(-PI * 3.0f / 4.0f)) * radius; - btnPos[bWalk] = center + vec2(cosf(-PI), sinf(-PI)) * radius; - btnRadius = Core::height * (25.0f / 1080.0f); + btnRadius = Core::height * (25.0f / 1080.0f); + btnPos[bWeapon] = center; + btnPos[bJump] = center + vec2(cosf(-PI * 0.5f), sinf(-PI * 0.5f)) * radius; + btnPos[bAction] = center + vec2(cosf(-PI * 3.0f / 4.0f), sinf(-PI * 3.0f / 4.0f)) * radius; + btnPos[bWalk] = center + vec2(cosf(-PI), sinf(-PI)) * radius; + btnPos[bInventory] = vec2(Core::width - btnRadius * 2.0f, btnRadius * 2.0f); // touch update if (checkTouchZone(zMove)) @@ -305,11 +306,12 @@ namespace Input { } switch (btn) { - case bWeapon : state[cWeapon] = true; break; - case bWalk : state[cWalk] = true; break; - case bAction : state[cAction] = true; break; - case bJump : state[cJump] = true; break; - default : ; + case bWeapon : state[cWeapon] = true; break; + case bWalk : state[cWalk] = true; break; + case bAction : state[cAction] = true; break; + case bJump : state[cJump] = true; break; + case bInventory : state[cInventory] = true; break; + default : ; } } diff --git a/src/inventory.h b/src/inventory.h index e99cd85..7926f0f 100644 --- a/src/inventory.h +++ b/src/inventory.h @@ -383,10 +383,12 @@ struct Inventory { bool ready = active && phaseRing == 1.0f && phasePage == 1.0f; if (index == targetIndex && targetPage == page && ready && !chosen) { - if (Input::state[cLeft]) { phaseSelect = 0.0f; targetIndex = (targetIndex - 1 + count) % count; } - if (Input::state[cRight]) { phaseSelect = 0.0f; targetIndex = (targetIndex + 1) % count; } - if (Input::state[cUp] && page < PAGE_ITEMS && getItemsCount(page + 1)) { phasePage = 0.0f; targetPage = Page(page + 1); } - if (Input::state[cDown] && page > PAGE_OPTION && getItemsCount(page - 1)) { phasePage = 0.0f; targetPage = Page(page - 1); } + float s = Input::touchTimerVis > 0.0f ? -1.0f : 1.0f; + + if (Input::state[cLeft] || Input::joy.L.x < -0.5f || Input::joy.R.x > 0.5f) { phaseSelect = 0.0f; targetIndex = (targetIndex - 1 + count) % count; } + if (Input::state[cRight] || Input::joy.L.x > 0.5f || Input::joy.R.x < -0.5f) { phaseSelect = 0.0f; targetIndex = (targetIndex + 1) % count; } + if ((Input::state[cUp] || Input::joy.L.y < -0.5f || Input::joy.R.y > 0.5f) && page < PAGE_ITEMS && getItemsCount(page + 1)) { phasePage = 0.0f; targetPage = Page(page + 1); } + if ((Input::state[cDown] || Input::joy.L.y > 0.5f || Input::joy.R.y < -0.5f) && page > PAGE_OPTION && getItemsCount(page - 1)) { phasePage = 0.0f; targetPage = Page(page - 1); } if (index != targetIndex) { vec3 p; diff --git a/src/level.h b/src/level.h index 94cf2e5..8ed8c19 100644 --- a/src/level.h +++ b/src/level.h @@ -408,7 +408,7 @@ struct Level : IGame { data[i * 1024 + j].b = data[i * 1024 + j].g = ((i % 8 == 0) || (j % 8 == 0)) ? 0 : 255; */ - atlas = new Texture(1024, 1024, Texture::RGBA, false, data); + atlas = new Texture(1024, 1024, Texture::RGBA, false, data, true, false); // TODO: generate mips PROFILE_LABEL(TEXTURE, atlas->ID, "atlas"); uint32 whitePix = 0xFFFFFFFF; @@ -490,61 +490,97 @@ struct Level : IGame { } Core::active.shader->setParam(uMaterial, vec4(diffuse, ambient, specular, alpha)); + if (Core::settings.detail.contact) + Core::active.shader->setParam(uContacts, Core::contacts[0], MAX_CONTACTS); } - void renderRoom(int roomIndex) { - ASSERT(roomIndex >= 0 && roomIndex < level.roomsCount); - PROFILE_MARKER("ROOM"); - - TR::Room &room = level.rooms[roomIndex]; - vec3 offset = vec3(float(room.info.x), 0.0f, float(room.info.z)); - - room.flags.visible = true; - - // room geometry & sprites - if (Core::pass != Core::passShadow) { - Basis qTemp = Core::basis; - Core::basis.translate(offset); - - MeshBuilder::RoomRange &range = mesh->rooms[roomIndex]; - - for (int transp = 0; transp < 2; transp++) { - if (!range.geometry[transp].iCount) - continue; - - Core::setBlending(transp ? bmAlpha : bmNone); - - setRoomParams(roomIndex, Shader::ROOM, 1.0f, intensityf(room.ambient), 0.0f, 1.0f, transp > 0); - Shader *sh = Core::active.shader; - sh->setParam(uLightColor, Core::lightColor[0], MAX_LIGHTS); - sh->setParam(uLightPos, Core::lightPos[0], MAX_LIGHTS); - sh->setParam(uBasis, Core::basis); - - // render room geometry - mesh->renderRoomGeometry(roomIndex, transp > 0); - } - - // render room sprites - if (range.sprites.iCount) { - Core::setBlending(bmAlpha); - setRoomParams(roomIndex, Shader::SPRITE, 1.0f, 1.0f, 0.0f, 1.0f, true); - Shader *sh = Core::active.shader; - sh->setParam(uLightColor, Core::lightColor[0], MAX_LIGHTS); - sh->setParam(uLightPos, Core::lightPos[0], MAX_LIGHTS); - sh->setParam(uBasis, Core::basis); - mesh->renderRoomSprites(roomIndex); - } - - Core::basis = qTemp; - } - Core::setBlending(bmNone); - } - void setMainLight(Controller *controller) { Core::lightPos[0] = controller->mainLightPos; Core::lightColor[0] = vec4(controller->mainLightColor.xyz, 1.0f / controller->mainLightColor.w); } + void renderRooms(int *roomsList, int roomsCount) { + PROFILE_MARKER("ROOMS"); + + for (int i = 0; i < level.roomsCount; i++) + level.rooms[i].flags.visible = false; + + for (int i = 0; i < roomsCount; i++) + level.rooms[roomsList[i]].flags.visible = true; + + if (Core::pass == Core::passShadow) + return; + + if (Core::settings.detail.contact) { + Sphere spheres[MAX_CONTACTS]; + int spheresCount; + lara->getSpheres(spheres, spheresCount); + + for (int i = 0; i < MAX_CONTACTS; i++) + if (i < spheresCount) + Core::contacts[i] = vec4(spheres[i].center, PI * spheres[i].radius * spheres[i].radius * 0.25f); + else + Core::contacts[i] = vec4(0.0f); + } + + setMainLight(lara); + + bool hasGeom[2], hasSprite; + hasGeom[0] = hasGeom[1] = hasSprite = false; + + Basis basis; + basis.identity(); + + Core::setBlending(bmNone); + for (int transp = 0; transp < 2; transp++) { + for (int i = 0; i < roomsCount; i++) { + int roomIndex = roomsList[i]; + MeshBuilder::RoomRange &range = mesh->rooms[roomIndex]; + + if (!range.geometry[transp].iCount) + continue; + + setRoomParams(roomIndex, Shader::ROOM, 1.0f, intensityf(level.rooms[roomIndex].ambient), 0.0f, 1.0f, transp > 0); + Shader *sh = Core::active.shader; + + if (!hasGeom[transp]) { + hasGeom[transp] = true; + sh->setParam(uLightColor, Core::lightColor[0], MAX_LIGHTS); + sh->setParam(uLightPos, Core::lightPos[0], MAX_LIGHTS); + } + + basis.pos = level.rooms[roomIndex].getOffset(); + sh->setParam(uBasis, basis); + mesh->renderRoomGeometry(roomIndex, transp > 0); + } + Core::setBlending(bmAlpha); + } + + basis.rot = Core::mViewInv.getRot(); + for (int i = 0; i < roomsCount; i++) { + level.rooms[roomsList[i]].flags.visible = true; + + int roomIndex = roomsList[i]; + MeshBuilder::RoomRange &range = mesh->rooms[roomIndex]; + + if (!range.sprites.iCount) + continue; + + setRoomParams(roomIndex, Shader::SPRITE, 1.0f, 1.0f, 0.0f, 1.0f, true); + Shader *sh = Core::active.shader; + if (!hasSprite) { + sh->setParam(uLightColor, Core::lightColor[0], MAX_LIGHTS); + sh->setParam(uLightPos, Core::lightPos[0], MAX_LIGHTS); + } + + basis.pos = level.rooms[roomIndex].getOffset(); + sh->setParam(uBasis, basis); + mesh->renderRoomSprites(roomIndex); + } + + Core::setBlending(bmNone); + } + void renderEntity(const TR::Entity &entity) { //if (entity.room != lara->getRoomIndex()) return; if (entity.type == TR::Entity::NONE || !entity.modelIndex) return; @@ -568,8 +604,6 @@ struct Level : IGame { type = Shader::MIRROR; int roomIndex = entity.room; -// if (entity.type == TR::Entity::LARA && ((Lara*)entity.controller)->state == Lara::STATE_WATER_OUT) -// roomIndex = ((Lara*)entity.controller)->roomPrev; setRoomParams(roomIndex, type, 1.0f, intensityf(lum), controller->specular, 1.0f, isModel ? !mesh->models[entity.modelIndex - 1].opaque : true); @@ -648,27 +682,6 @@ struct Level : IGame { setupBinding(); } - void renderRooms(int *roomsList, int roomsCount) { - PROFILE_MARKER("ROOMS"); - - for (int i = 0; i < level.roomsCount; i++) - level.rooms[i].flags.visible = false; - - setMainLight(lara); - - #ifdef LEVEL_EDITOR - for (int i = 0; i < level.roomsCount; i++) - renderRoom(i); - #else - if (!camera->cutscene) { - for (int i = 0; i < roomsCount; i++) - renderRoom(roomsList[i]); - } else // TODO: use brain (track the camera room) - for (int i = 0; i < level.roomsCount; i++) - renderRoom(i); - #endif - } - void renderEntities() { PROFILE_MARKER("ENTITIES"); for (int i = 0; i < level.entitiesCount; i++) @@ -756,6 +769,13 @@ struct Level : IGame { } void getVisibleRooms(int *roomsList, int &roomsCount, int from, int to, const vec4 &viewPort, bool water, int count = 0) { + if (camera->cutscene) { + roomsCount = level.roomsCount; + for (int i = 0; i < roomsCount; i++) + roomsList[i] = i; + return; + } + if (count > 16) { ASSERT(false); return; diff --git a/src/shader.h b/src/shader.h index ffeb37a..842ea7b 100644 --- a/src/shader.h +++ b/src/shader.h @@ -22,7 +22,6 @@ E( uParam ) \ E( uTexParam ) \ E( uViewProj ) \ - E( uViewInv ) \ E( uBasis ) \ E( uLightProj ) \ E( uMaterial ) \ @@ -33,7 +32,8 @@ E( uAnimTexRanges ) \ E( uAnimTexOffsets ) \ E( uRoomSize ) \ - E( uPosScale ) + E( uPosScale ) \ + E( uContacts ) enum AttribType { SHADER_ATTRIBS(DECL_ENUM) aMAX }; enum SamplerType { SHADER_SAMPLERS(DECL_ENUM) sMAX }; diff --git a/src/shaders/shader.glsl b/src/shaders/shader.glsl index 588ae0a..db9b99f 100644 --- a/src/shaders/shader.glsl +++ b/src/shaders/shader.glsl @@ -4,15 +4,32 @@ R"====( precision highp float; #endif +#ifdef OPT_CONTACT + varying vec3 vCoord; +#endif + varying vec4 vTexCoord; // xy - atlas coords, zw - trapezoidal correction #if defined(OPT_WATER) && defined(UNDERWATER) varying vec2 vCausticsCoord; // - xy caustics texture coord #endif -#ifndef PASS_SHADOW - uniform vec3 uViewPos; +//uniform vec4 data[MAX_RANGES + MAX_OFFSETS + 4 + 4 + 1 + 1 + MAX_LIGHTS + MAX_LIGHTS + 1 + 6 + 1 + 32 * 2]; +uniform vec2 uAnimTexRanges[MAX_RANGES]; +uniform vec2 uAnimTexOffsets[MAX_OFFSETS]; +uniform mat4 uLightProj; +uniform mat4 uViewProj; +uniform vec3 uViewPos; +uniform vec4 uParam; // x - time, y - water height, z - clip plane sign, w - clip plane height +uniform vec3 uLightPos[MAX_LIGHTS]; +uniform vec4 uLightColor[MAX_LIGHTS]; // xyz - color, w - radius * intensity +uniform vec4 uRoomSize; // xy - minXZ, zw - maxXZ +uniform vec3 uAmbient[6]; +uniform vec4 uMaterial; // x - diffuse, y - ambient, z - specular, w - alpha +uniform vec4 uBasis[32 * 2]; + +#ifndef PASS_SHADOW varying vec4 vViewVec; // xyz - dir * dist, w - coord.y varying vec4 vDiffuse; @@ -25,20 +42,11 @@ varying vec4 vTexCoord; // xy - atlas coords, zw - trapezoidal correction #ifdef OPT_SHADOW varying vec3 vAmbient; #endif - - uniform vec3 uLightPos[MAX_LIGHTS]; - uniform vec4 uLightColor[MAX_LIGHTS]; // xyz - color, w - radius * intensity #endif varying vec4 vLight; // lights intensity (MAX_LIGHTS == 4) - #if defined(OPT_WATER) && defined(UNDERWATER) - uniform vec4 uRoomSize; // xy - minXZ, zw - maxXZ - #endif - #if defined(OPT_AMBIENT) && defined(TYPE_ENTITY) - uniform vec3 uAmbient[6]; - vec3 calcAmbient(vec3 n) { vec3 sqr = n * n; vec3 pos = step(0.0, n); @@ -48,31 +56,9 @@ varying vec4 vTexCoord; // xy - atlas coords, zw - trapezoidal correction } #endif #endif - - uniform vec4 uParam; // x - time, y - water height, z - clip plane sign, w - clip plane height - uniform vec4 uMaterial; // x - diffuse, y - ambient, z - specular, w - alpha #endif #ifdef VERTEX - uniform mat4 uViewProj; - - uniform mat4 uViewInv; - - #ifndef PASS_AMBIENT - uniform mat4 uLightProj; - #endif - - #ifdef PASS_COMPOSE - uniform vec2 uAnimTexRanges[MAX_RANGES]; - uniform vec2 uAnimTexOffsets[MAX_OFFSETS]; - #endif - - #ifdef TYPE_ENTITY - uniform vec4 uBasis[32 * 2]; - #else - uniform vec4 uBasis[2]; - #endif - attribute vec4 aCoord; attribute vec4 aTexCoord; attribute vec4 aParam; @@ -85,8 +71,6 @@ varying vec4 vTexCoord; // xy - atlas coords, zw - trapezoidal correction attribute vec4 aColor; #endif - #define TEXCOORD_SCALE 32767.0 - vec3 mulQuat(vec4 q, vec3 v) { return v + 2.0 * cross(q.xyz, cross(q.xyz, v) + v * q.w); } @@ -105,10 +89,12 @@ varying vec4 vTexCoord; // xy - atlas coords, zw - trapezoidal correction vec4 rBasisPos = uBasis[1]; #endif - vec4 coord = vec4(mulBasis(rBasisRot, rBasisPos, aCoord.xyz), rBasisPos.w); - + vec4 coord; + coord.w = rBasisPos.w; // visible flag #ifdef TYPE_SPRITE - coord.xyz += (uViewInv[0].xyz * aTexCoord.z - uViewInv[1].xyz * aTexCoord.w) * TEXCOORD_SCALE; + coord.xyz = mulBasis(rBasisRot, rBasisPos + aCoord.xyz, vec3(aTexCoord.z, -aTexCoord.w, 0.0) * 32767.0); + #else + coord.xyz = mulBasis(rBasisRot, rBasisPos, aCoord.xyz); #endif #ifndef PASS_SHADOW @@ -137,6 +123,9 @@ varying vec4 vTexCoord; // xy - atlas coords, zw - trapezoidal correction vLightVec.w = clamp(1.0 / exp(fog), 0.0, 1.0); #endif + #ifdef OPT_CONTACT + vCoord = coord.xyz; + #endif return coord; } @@ -374,7 +363,7 @@ varying vec4 vTexCoord; // xy - atlas coords, zw - trapezoidal correction #if defined(OPT_WATER) && defined(UNDERWATER) float calcCaustics(vec3 n) { - vec2 cc = vCausticsCoord.xy; + vec2 cc = vCausticsCoord.xy; vec2 border = vec2(256.0) / (uRoomSize.zw - uRoomSize.xy); vec2 fade = smoothstep(vec2(0.0), border, cc) * (1.0 - smoothstep(vec2(1.0) - border, vec2(1.0), cc)); return texture2D(sReflect, cc).g * max(0.0, -n.y) * fade.x * fade.y; @@ -382,6 +371,21 @@ varying vec4 vTexCoord; // xy - atlas coords, zw - trapezoidal correction #endif #endif +#ifdef OPT_CONTACT + uniform vec4 uContacts[MAX_CONTACTS]; + + float getContactAO(vec3 p, vec3 n) { + float res = 1.0; + for (int i = 0; i < MAX_CONTACTS; i++) { + vec3 v = uContacts[i].xyz - p; + float a = uContacts[i].w; + float o = a * clamp(dot(n, v), 0.0, 1.0) / dot(v, v); + res *= clamp(1.0 - o, 0.0, 1.0); + } + return res; + } +#endif + void main() { #ifdef PASS_COMPOSE #ifdef CLIP_PLANE @@ -439,10 +443,16 @@ varying vec4 vTexCoord; // xy - atlas coords, zw - trapezoidal correction #endif #ifdef TYPE_ROOM + light += mix(vAmbient.x, vLight.x, getShadow()); #if defined(OPT_WATER) && defined(UNDERWATER) light += calcCaustics(n); #endif + + #ifdef OPT_CONTACT + light *= getContactAO(vCoord, n) * 0.5 + 0.5; + #endif + #endif #ifdef TYPE_SPRITE diff --git a/src/sprite.h b/src/sprite.h index 5d8f2a0..3bdf41e 100644 --- a/src/sprite.h +++ b/src/sprite.h @@ -62,9 +62,7 @@ struct Sprite : Controller { } virtual void render(Frustum *frustum, MeshBuilder *mesh, Shader::Type type, bool caustics) { - Basis basis(Core::basis); - basis.translate(pos); - Core::active.shader->setParam(uBasis, basis); + Core::active.shader->setParam(uBasis, Basis(Core::mViewInv.getRot(), pos)); mesh->renderSprite(-(getEntity().modelIndex + 1), frame); } }; diff --git a/src/texture.h b/src/texture.h index 3de96df..0183f05 100644 --- a/src/texture.h +++ b/src/texture.h @@ -11,7 +11,7 @@ struct Texture { Format format; bool cube; - Texture(int width, int height, Format format, bool cube, void *data = NULL, bool filter = true) : cube(cube) { + Texture(int width, int height, Format format, bool cube, void *data = NULL, bool filter = true, bool mips = false) : cube(cube) { if (!Core::support.texNPOT) { width = nextPow2(width); height = nextPow2(height); @@ -65,8 +65,9 @@ struct Texture { float color[] = { 1.0f, 1.0f, 1.0f, 1.0f }; glTexParameterfv(target, GL_TEXTURE_BORDER_COLOR, color); } + + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, filter ? (mips ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR ) : ( mips ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST )); glTexParameteri(target, GL_TEXTURE_MAG_FILTER, filter ? GL_LINEAR : GL_NEAREST); - glTexParameteri(target, GL_TEXTURE_MIN_FILTER, filter ? GL_LINEAR : GL_NEAREST); struct FormatDesc { GLuint ifmt, fmt; diff --git a/src/utils.h b/src/utils.h index 6236a08..a8ce1cd 100644 --- a/src/utils.h +++ b/src/utils.h @@ -602,7 +602,7 @@ struct mat4 { quat getRot() const { float t, s; t = 1.0f + e00 + e11 + e22; - if (t > EPS) { + if (t > 0.0001f) { s = 0.5f / sqrtf(t); return quat((e21 - e12) * s, (e02 - e20) * s, (e10 - e01) * s, 0.25f / s); } else @@ -657,7 +657,7 @@ struct mat4 { }; struct Basis { - quat rot; + quat rot; vec3 pos; float w;