mirror of
https://github.com/XProger/OpenLara.git
synced 2025-04-22 03:51:58 +02:00
#23 room render optimization for mobile devices; contact ambient occlusion (WIP); #11 inventory touch button
This commit is contained in:
parent
e2643cd78a
commit
5739de6044
@ -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();
|
||||
|
@ -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 {
|
||||
|
@ -60,6 +60,7 @@ namespace Debug {
|
||||
glUseProgram(0);
|
||||
Core::active.shader = NULL;
|
||||
Core::active.textures[0] = NULL;
|
||||
Core::validateRenderState();
|
||||
}
|
||||
|
||||
void end() {
|
||||
|
@ -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;
|
||||
|
||||
|
24
src/input.h
24
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 : ;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
164
src/level.h
164
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;
|
||||
|
@ -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 };
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user