1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-11 15:45:05 +02:00

#23 ambient pass, render to ambient texture; #16 one shader per pass

This commit is contained in:
XProger
2016-12-20 03:52:28 +03:00
parent 77f40a95c8
commit b8b201fbc6
5 changed files with 226 additions and 131 deletions

View File

@@ -139,9 +139,9 @@ namespace Core {
vec4 lightColor[MAX_LIGHTS]; vec4 lightColor[MAX_LIGHTS];
vec4 color; vec4 color;
enum { passOpaque, passShadow } pass; enum Pass { passCompose, passShadow, passAmbient } pass;
GLuint RT; GLuint RT, RB;
struct { struct {
Shader *shader; Shader *shader;
@@ -246,6 +246,10 @@ namespace Core {
// support.depthTexture = support.shadowSampler = false; // depth textures is not supported in Safari browser in fact :( // support.depthTexture = support.shadowSampler = false; // depth textures is not supported in Safari browser in fact :(
glGenFramebuffers(1, &RT); glGenFramebuffers(1, &RT);
glGenRenderbuffers(1, &RB);
glBindRenderbuffer(GL_RENDERBUFFER, RB);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, 64, 64);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
Sound::init(); Sound::init();
@@ -258,6 +262,11 @@ namespace Core {
Sound::free(); Sound::free();
} }
void resetStates() {
memset(&active, 0, sizeof(active));
glEnable(GL_DEPTH_TEST);
}
void clear(const vec4 &color) { void clear(const vec4 &color) {
glClearColor(color.x, color.y, color.z, color.w); glClearColor(color.x, color.y, color.z, color.w);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
@@ -316,6 +325,8 @@ namespace Core {
glBindFramebuffer(GL_FRAMEBUFFER, RT); glBindFramebuffer(GL_FRAMEBUFFER, RT);
glFramebufferTexture2D(GL_FRAMEBUFFER, target->depth ? GL_DEPTH_ATTACHMENT : GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, target->ID, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, target->depth ? GL_DEPTH_ATTACHMENT : GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, target->ID, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, target->depth ? GL_COLOR_ATTACHMENT0 : GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, target->dummy ? target->dummy->ID : 0, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, target->depth ? GL_COLOR_ATTACHMENT0 : GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, target->dummy ? target->dummy->ID : 0, 0);
if (!target->depth)
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, RB);
bool mask = !target->depth; bool mask = !target->depth;
glColorMask(mask, mask, mask, mask); glColorMask(mask, mask, mask, mask);

View File

@@ -1559,20 +1559,42 @@ struct Lara : Character {
} }
void move() { void move() {
TR::Entity &e = getEntity();
TR::Level::FloorInfo info;
float f, c;
bool canPassGap = true;
/*
if (velocity != 0.0f) {
vec3 dir = velocity.normal() * 128.0f;
vec3 p = pos + dir;
level->getFloorInfo(e.room, (int)p.x, (int)p.y, (int)p.z, info);
if (info.floor < p.y - (256 + 128) || info.ceiling > p.y - 768) { // wall
vec3 axis = dir.axisXZ();
vec3 normal = (p - vec3(int(p.x / 1024.0f) * 1024.0f + 512.0f, p.y, int(p.z / 1024.0f) * 1024.0f + 512.0f)).axisXZ();
LOG("%f %f = %f %f = %f\n", axis.x, axis.z, normal.x, normal.z, abs(axis.dot(normal)));
if (abs(axis.dot(normal)) > EPS) {
canPassGap = false;
} else {
updateEntity();
checkRoom();
return;
}
}
}
*/
vec3 offset = velocity * Core::deltaTime * 30.0f; vec3 offset = velocity * Core::deltaTime * 30.0f;
vec3 p = pos; vec3 p = pos;
pos = pos + offset; pos = pos + offset;
TR::Entity &e = getEntity(); if (canPassGap) {
TR::Level::FloorInfo info; level->getFloorInfo(e.room, (int)pos.x, (int)pos.y, (int)pos.z, info);
level->getFloorInfo(e.room, (int)pos.x, (int)pos.y, (int)pos.z, info); canPassGap = (info.floor - info.ceiling) >= (stand == STAND_GROUND ? 768 : 512);
}
// get frame to get height
bool canPassGap = (info.floor - info.ceiling) >= (stand == STAND_GROUND ? 768 : 512);
float f = info.floor - pos.y;
float c = pos.y - info.ceiling;
f = info.floor - pos.y;
c = pos.y - info.ceiling;
/* /*
TR::Animation *anim = animation; TR::Animation *anim = animation;
Box eBox = Box(pos - vec3(128.0f, 0.0f, 128.0f), pos + vec3(128.0, getHeight(), 128.0f)); // getBoundingBox(); Box eBox = Box(pos - vec3(128.0f, 0.0f, 128.0f), pos + vec3(128.0, getHeight(), 128.0f)); // getBoundingBox();

View File

@@ -22,7 +22,7 @@ const char GUI[] =
; ;
struct Level { struct Level {
enum { shDefault, shShadow, shGUI, shMAX }; enum { shCompose, shShadow, shAmbient, shGUI, shMAX };
TR::Level level; TR::Level level;
Shader *shaders[shMAX]; Shader *shaders[shMAX];
@@ -32,6 +32,7 @@ struct Level {
Lara *lara; Lara *lara;
Camera *camera; Camera *camera;
Texture *shadow; Texture *shadow;
Texture *ambient[4]; // 64, 16, 4, 1
float time; float time;
@@ -42,6 +43,8 @@ struct Level {
mesh = new MeshBuilder(level); mesh = new MeshBuilder(level);
shadow = new Texture(1024, 1024, true); shadow = new Texture(1024, 1024, true);
for (int i = 0; i < 4; i++)
ambient[i] = new Texture(64 >> (i << 1), 64 >> (i << 1), false);
initAtlas(); initAtlas();
initShaders(); initShaders();
@@ -154,6 +157,9 @@ struct Level {
delete shaders[i]; delete shaders[i];
delete shadow; delete shadow;
for (int i = 0; i < 4; i++)
delete ambient[i];
delete atlas; delete atlas;
delete mesh; delete mesh;
@@ -214,11 +220,12 @@ struct Level {
else else
strcat(ext, "#define SHADOW_COLOR\n"); strcat(ext, "#define SHADOW_COLOR\n");
sprintf(def, "%s#define MAX_LIGHTS %d\n#define MAX_RANGES %d\n#define MAX_OFFSETS %d\n#define MAX_SHADOW_DIST %d.0\n", ext, MAX_LIGHTS, mesh->animTexRangesCount, mesh->animTexOffsetsCount, MAX_SHADOW_DIST); sprintf(def, "%s#define PASS_COMPOSE\n#define MAX_LIGHTS %d\n#define MAX_RANGES %d\n#define MAX_OFFSETS %d\n#define MAX_SHADOW_DIST %d.0\n", ext, MAX_LIGHTS, mesh->animTexRangesCount, mesh->animTexOffsetsCount, MAX_SHADOW_DIST);
shaders[shDefault] = new Shader(SHADER, def); shaders[shCompose] = new Shader(SHADER, def);
sprintf(def, "%s#define PASS_SHADOW\n", ext); sprintf(def, "%s#define PASS_SHADOW\n", ext);
shaders[shShadow] = new Shader(SHADER, def); shaders[shShadow] = new Shader(SHADER, def);
sprintf(ext, "%s#define SPRITE\n", def); sprintf(def, "%s#define PASS_AMBIENT\n", ext);
shaders[shAmbient] = new Shader(SHADER, def);
shaders[shGUI] = new Shader(GUI, ""); shaders[shGUI] = new Shader(GUI, "");
} }
@@ -323,13 +330,10 @@ struct Level {
} }
#endif #endif
void setRoomShader(const TR::Room &room, float intensity) { void setRoomParams(const TR::Room &room, float intensity) {
if (Core::pass == Core::passShadow) { if (Core::pass == Core::passShadow)
shaders[shShadow]->bind();
return; return;
}
shaders[shDefault]->bind();
if (room.flags.water) { if (room.flags.water) {
Core::color = vec4(0.6f, 0.9f, 0.9f, intensity); Core::color = vec4(0.6f, 0.9f, 0.9f, intensity);
Core::active.shader->setParam(uCaustics, 1); Core::active.shader->setParam(uCaustics, 1);
@@ -347,7 +351,7 @@ struct Level {
TR::Room &room = level.rooms[roomIndex]; TR::Room &room = level.rooms[roomIndex];
vec3 offset = vec3(float(room.info.x), 0.0f, float(room.info.z)); vec3 offset = vec3(float(room.info.x), 0.0f, float(room.info.z));
setRoomShader(room, intensityf(room.ambient)); setRoomParams(room, intensityf(room.ambient));
Shader *sh = Core::active.shader; Shader *sh = Core::active.shader;
Core::lightColor[0] = vec4(0, 0, 0, 1); Core::lightColor[0] = vec4(0, 0, 0, 1);
@@ -396,7 +400,7 @@ struct Level {
sh->setParam(uModel, Core::mModel); sh->setParam(uModel, Core::mModel);
// render room geometry // render room geometry
if (Core::pass == Core::passOpaque) { if (Core::pass == Core::passCompose || Core::pass == Core::passAmbient) {
mesh->renderRoomGeometry(roomIndex); mesh->renderRoomGeometry(roomIndex);
} }
@@ -493,7 +497,7 @@ struct Level {
return; return;
int16 lum = entity.intensity == -1 ? room.ambient : entity.intensity; int16 lum = entity.intensity == -1 ? room.ambient : entity.intensity;
setRoomShader(room, intensityf(lum)); setRoomParams(room, intensityf(lum));
if (entity.modelIndex > 0) { // model if (entity.modelIndex > 0) { // model
getLight(((Controller*)entity.controller)->pos, entity.room); getLight(((Controller*)entity.controller)->pos, entity.room);
@@ -512,7 +516,6 @@ struct Level {
((Controller*)entity.controller)->render(camera->frustum, mesh); ((Controller*)entity.controller)->render(camera->frustum, mesh);
} }
void update() { void update() {
time += Core::deltaTime; time += Core::deltaTime;
@@ -529,7 +532,7 @@ struct Level {
void setup() { void setup() {
PROFILE_MARKER("SETUP"); PROFILE_MARKER("SETUP");
camera->setup(Core::pass != Core::passShadow);; camera->setup(Core::pass == Core::passCompose);
atlas->bind(0); atlas->bind(0);
@@ -537,19 +540,16 @@ struct Level {
mesh->bind(); mesh->bind();
// set frame constants for all shaders // set frame constants for all shaders
Core::active.shader = NULL; Shader *sh = Core::active.shader;
for (int i = 0; i < shMAX; i++) { sh->bind();
shaders[i]->bind(); sh->setParam(uViewProj, Core::mViewProj);
shaders[i]->setParam(uViewProj, Core::mViewProj); sh->setParam(uLightProj, Core::mLightProj);
shaders[i]->setParam(uLightProj, Core::mLightProj); sh->setParam(uViewInv, Core::mViewInv);
shaders[i]->setParam(uViewInv, Core::mViewInv); sh->setParam(uViewPos, Core::viewPos);
shaders[i]->setParam(uViewPos, Core::viewPos); sh->setParam(uTime, time);
shaders[i]->setParam(uTime, time); sh->setParam(uLightTarget, lara->pos);
shaders[i]->setParam(uLightTarget, lara->pos); sh->setParam(uAnimTexRanges, mesh->animTexRanges[0], mesh->animTexRangesCount);
shaders[i]->setParam(uAnimTexRanges, mesh->animTexRanges[0], mesh->animTexRangesCount); sh->setParam(uAnimTexOffsets, mesh->animTexOffsets[0], mesh->animTexOffsetsCount);
shaders[i]->setParam(uAnimTexOffsets, mesh->animTexOffsets[0], mesh->animTexOffsetsCount);
}
glEnable(GL_DEPTH_TEST);
Core::mModel.identity(); Core::mModel.identity();
@@ -562,32 +562,50 @@ struct Level {
room.meshes[j].flags.rendered = false; // clear visible flag for room static meshes room.meshes[j].flags.rendered = false; // clear visible flag for room static meshes
} }
for (int i = 0; i < level.entitiesCount; i++) if (Core::pass != Core::passAmbient)
level.entities[i].flags.rendered = false; for (int i = 0; i < level.entitiesCount; i++)
level.entities[i].flags.rendered = false;
} }
void renderRooms() { void renderRooms(int roomIndex) {
PROFILE_MARKER("ROOMS"); PROFILE_MARKER("ROOMS");
#ifdef LEVEL_EDITOR #ifdef LEVEL_EDITOR
for (int i = 0; i < level.roomsCount; i++) for (int i = 0; i < level.roomsCount; i++)
renderRoom(i); renderRoom(i);
#else #else
renderRoom(camera->getRoomIndex()); renderRoom(roomIndex);
#endif #endif
} }
void renderEntities() { void renderEntities() {
PROFILE_MARKER("ENTITIES"); PROFILE_MARKER("ENTITIES");
shaders[Core::pass == Core::passShadow ? shShadow : shDefault]->bind();
for (int i = 0; i < level.entitiesCount; i++) for (int i = 0; i < level.entitiesCount; i++)
renderEntity(level.entities[i]); renderEntity(level.entities[i]);
} }
void renderScene() { void renderScene(int roomIndex) {
PROFILE_MARKER("SCENE"); PROFILE_MARKER("SCENE");
setup(); setup();
renderRooms(); renderRooms(roomIndex);
renderEntities(); if (Core::pass != Core::passAmbient)
renderEntities();
}
void setupCubeCamera(const vec3 &pos, int face) {
vec3 up = vec3(0, 1, 0);
vec3 dir;
switch (face) {
case 0 : dir = vec3( 1, 0, 0); break;
case 1 : dir = vec3(-1, 0, 0); break;
case 2 : dir = vec3( 0, 1, 0); up = vec3(1, 0, 0); break;
case 3 : dir = vec3( 0, -1, 0); up = vec3(1, 0, 0); break;
case 4 : dir = vec3( 0, 0, 1); break;
case 5 : dir = vec3( 0, 0, -1); break;
}
Core::mViewInv = mat4(pos, pos + dir, up);
Core::mView = Core::mViewInv.inverse();
Core::mProj = mat4(90, 1.0f, camera->znear, camera->zfar);
} }
bool setupLightCamera() { bool setupLightCamera() {
@@ -600,48 +618,76 @@ struct Level {
TR::Room::Light &light = level.rooms[room].lights[idx]; TR::Room::Light &light = level.rooms[room].lights[idx];
vec3 shadowLightPos = vec3(float(light.x), float(light.y), float(light.z)); vec3 shadowLightPos = vec3(float(light.x), float(light.y), float(light.z));
Core::mView = mat4(shadowLightPos, pos - vec3(0, 256, 0), vec3(0, -1, 0)).inverse(); Core::mViewInv = mat4(shadowLightPos, pos - vec3(0, 256, 0), vec3(0, -1, 0));
Core::mProj = mat4(120, 1.0f, camera->znear, camera->zfar); Core::mView = Core::mViewInv.inverse();
Core::mProj = mat4(120, 1.0f, camera->znear, camera->zfar);
Core::mViewProj = Core::mProj * Core::mView;
mat4 bias; mat4 bias;
bias.identity(); bias.identity();
bias.e03 = bias.e13 = bias.e23 = bias.e00 = bias.e11 = bias.e22 = 0.5f; bias.e03 = bias.e13 = bias.e23 = bias.e00 = bias.e11 = bias.e22 = 0.5f;
Core::mLightProj = bias * Core::mProj * Core::mView; // * ( * ) ? Core::mLightProj = bias * Core::mProj * Core::mView;
Shader *sh = shaders[shShadow];
sh->bind();
sh->setParam(uViewProj, Core::mViewProj);
sh->setParam(uLightProj, Core::mLightProj);
return true; return true;
} }
void renderShadows() { void setPassShader(Core::Pass pass) {
if (!setupLightCamera()) return; Core::pass = pass;
Shader *sh = NULL;
switch (pass) {
case Core::passCompose : sh = shaders[shCompose]; break;
case Core::passShadow : sh = shaders[shShadow]; break;
case Core::passAmbient : sh = shaders[shAmbient]; break;
}
ASSERT(sh);
sh->bind();
}
void renderAmbient(int roomIndex, const vec3 &pos, vec3 *cube) {
PROFILE_MARKER("PASS_AMBIENT");
setupCubeCamera(pos, 4);
setPassShader(Core::passAmbient);
Core::setBlending(bmAlpha);
Core::setTarget(ambient[0]);
Core::setViewport(0, 0, ambient[0]->width, ambient[0]->height);
Core::clear(vec4(0, 0, 0, 1));
renderScene(roomIndex);
Core::setTarget(NULL);
}
void renderShadows(int roomIndex) {
PROFILE_MARKER("PASS_SHADOW"); PROFILE_MARKER("PASS_SHADOW");
if (!setupLightCamera()) return;
Texture::unbind(sShadow); Texture::unbind(sShadow);
Core::pass = Core::passShadow; setPassShader(Core::passShadow);
Core::setBlending(bmNone); Core::setBlending(bmNone);
Core::setTarget(shadow); Core::setTarget(shadow);
Core::setViewport(0, 0, shadow->width, shadow->height); Core::setViewport(0, 0, shadow->width, shadow->height);
Core::clear(vec4(1.0)); Core::clear(vec4(1.0));
Core::setCulling(cfBack); Core::setCulling(cfBack);
renderScene(); renderScene(roomIndex);
Core::setCulling(cfFront); Core::setCulling(cfFront);
Core::setTarget(NULL); Core::setTarget(NULL);
shadow->bind(sShadow);
} }
void render() { void renderCompose(int roomIndex) {
renderShadows(); PROFILE_MARKER("PASS_COMPOSE");
setPassShader(Core::passCompose);
Core::pass = Core::passOpaque;
Core::setBlending(bmAlpha); Core::setBlending(bmAlpha);
Core::clear(vec4(0.0f)); Core::clear(vec4(0.0f));
Core::setViewport(0, 0, Core::width, Core::height); Core::setViewport(0, 0, Core::width, Core::height);
renderScene(); shadow->bind(sShadow);
renderScene(roomIndex);
}
void render() {
Core::resetStates();
vec3 cube[6];
// renderAmbient(lara->getRoomIndex(), lara->pos - vec3(0, 512, 0), cube);
renderShadows(lara->getRoomIndex());
renderCompose(camera->getRoomIndex());
#ifdef _DEBUG #ifdef _DEBUG
static int modelIndex = 0; static int modelIndex = 0;
@@ -673,29 +719,29 @@ struct Level {
Debug::begin(); Debug::begin();
// Debug::Level::rooms(level, lara->pos, lara->getEntity().room); // Debug::Level::rooms(level, lara->pos, lara->getEntity().room);
Debug::Level::lights(level, lara->getRoomIndex()); // Debug::Level::lights(level, lara->getRoomIndex());
// Debug::Level::sectors(level, lara->getRoomIndex(), (int)lara->pos.y); // Debug::Level::sectors(level, lara->getRoomIndex(), (int)lara->pos.y);
// Debug::Level::portals(level); // Debug::Level::portals(level);
// Debug::Level::meshes(level); // Debug::Level::meshes(level);
// Debug::Level::entities(level); // Debug::Level::entities(level);
/*
glPushMatrix(); glPushMatrix();
glColor3f(1, 1, 1); glColor3f(1, 1, 1);
glTranslatef(lara->pos.x, lara->pos.y, lara->pos.z); glTranslatef(lara->pos.x, lara->pos.y, lara->pos.z);
Texture::unbind(sShadow); Texture::unbind(sShadow);
shadow->bind(sDiffuse); ambient[0]->bind(sDiffuse);
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
glBegin(GL_QUADS); glBegin(GL_QUADS);
glTexCoord2f(0, 0); glVertex3f( 0, 0, 0); glTexCoord2f(1, 1); glVertex3f( 0, 0, 0);
glTexCoord2f(1, 0); glVertex3f(1024, 0, 0); glTexCoord2f(0, 1); glVertex3f(1024, 0, 0);
glTexCoord2f(1, 1); glVertex3f(1024, -1024, 0); glTexCoord2f(0, 0); glVertex3f(1024, -1024, 0);
glTexCoord2f(0, 1); glVertex3f( 0, -1024, 0); glTexCoord2f(1, 0); glVertex3f( 0, -1024, 0);
glEnd(); glEnd();
glPopMatrix(); glPopMatrix();
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_2D);
*/
/* /*
shaders[shGUI]->bind(); shaders[shGUI]->bind();
Core::mViewProj = mat4(0, (float)Core::width, (float)Core::height, 0, 0, 1); Core::mViewProj = mat4(0, (float)Core::width, (float)Core::height, 0, 0, 1);

View File

@@ -2,12 +2,14 @@ R"====(
varying vec2 vTexCoord; varying vec2 vTexCoord;
#ifndef PASS_SHADOW #ifndef PASS_SHADOW
varying vec3 vCoord; #ifndef PASS_AMBIENT
varying vec4 vNormal; varying vec3 vCoord;
varying vec3 vViewVec; varying vec4 vNormal;
varying vec3 vViewVec;
varying vec4 vLightProj;
varying float vLightTargetDist;
#endif
varying vec4 vColor; varying vec4 vColor;
varying vec4 vLightProj;
varying float vLightTargetDist;
#endif #endif
#define TYPE_SPRITE 0 #define TYPE_SPRITE 0
@@ -16,26 +18,34 @@ varying vec2 vTexCoord;
#define TYPE_FLASH 3 #define TYPE_FLASH 3
uniform int uType; uniform int uType;
uniform int uCaustics;
uniform float uTime; #ifdef PASS_COMPOSE
uniform int uCaustics;
uniform float uTime;
#endif
#ifdef VERTEX #ifdef VERTEX
uniform mat4 uViewProj; uniform mat4 uViewProj;
uniform mat4 uModel; uniform mat4 uModel;
uniform mat4 uViewInv;
uniform mat4 uLightProj;
uniform vec3 uLightTarget;
#ifndef PASS_SHADOW #ifndef PASS_AMBIENT
uniform mat4 uViewInv;
uniform mat4 uLightProj;
uniform vec3 uLightTarget;
#endif
#ifdef PASS_COMPOSE
uniform vec3 uViewPos; uniform vec3 uViewPos;
uniform vec2 uAnimTexRanges[MAX_RANGES]; uniform vec2 uAnimTexRanges[MAX_RANGES];
uniform vec2 uAnimTexOffsets[MAX_OFFSETS]; uniform vec2 uAnimTexOffsets[MAX_OFFSETS];
#endif #endif
attribute vec4 aCoord; attribute vec4 aCoord;
attribute vec4 aTexCoord; attribute vec4 aTexCoord;
attribute vec4 aNormal;
#ifndef PASS_AMBIENT
attribute vec4 aNormal;
#endif
#ifndef PASS_SHADOW #ifndef PASS_SHADOW
attribute vec4 aColor; attribute vec4 aColor;
@@ -45,32 +55,31 @@ uniform float uTime;
void main() { void main() {
vec4 coord = uModel * vec4(aCoord.xyz, 1.0); vec4 coord = uModel * vec4(aCoord.xyz, 1.0);
if (uType != TYPE_SPRITE) { #ifdef PASS_COMPOSE
#ifndef PASS_SHADOW if (uType != TYPE_SPRITE) {
// animated texture coordinates // animated texture coordinates
vec2 range = uAnimTexRanges[int(aTexCoord.z)]; // x - start index, y - count vec2 range = uAnimTexRanges[int(aTexCoord.z)]; // x - start index, y - count
float f = fract((aTexCoord.w + uTime * 4.0 - range.x) / range.y) * range.y; float f = fract((aTexCoord.w + uTime * 4.0 - range.x) / range.y) * range.y;
vec2 offset = uAnimTexOffsets[int(range.x + f)]; // texCoord offset from first frame vec2 offset = uAnimTexOffsets[int(range.x + f)]; // texCoord offset from first frame
vTexCoord = (aTexCoord.xy + offset) * TEXCOORD_SCALE; // first frame + offset * isAnimated vTexCoord = (aTexCoord.xy + offset) * TEXCOORD_SCALE; // first frame + offset * isAnimated
vNormal = vec4((uModel * vec4(aNormal.xyz, 0.0)).xyz, aNormal.w); vNormal = vec4((uModel * vec4(aNormal.xyz, 0.0)).xyz, aNormal.w);
#else } else {
vTexCoord = aTexCoord.xy * TEXCOORD_SCALE; coord.xyz += uViewInv[0].xyz * aTexCoord.z - uViewInv[1].xyz * aTexCoord.w;
#endif vTexCoord = aTexCoord.xy * TEXCOORD_SCALE;
} else { vNormal = vec4(uViewPos.xyz - coord.xyz, 0.0);
coord.xyz += uViewInv[0].xyz * aTexCoord.z - uViewInv[1].xyz * aTexCoord.w; }
#ifndef PASS_SHADOW #else
vTexCoord = aTexCoord.xy * TEXCOORD_SCALE; vTexCoord = aTexCoord.xy * TEXCOORD_SCALE;
vNormal = vec4(uViewPos.xyz - coord.xyz, 0.0); #endif
#endif
}
#ifndef PASS_SHADOW #ifndef PASS_SHADOW
vColor = aColor; vColor = aColor;
#endif
#ifdef PASS_COMPOSE
if (uCaustics != 0) { if (uCaustics != 0) {
float sum = coord.x + coord.y + coord.z; float sum = coord.x + coord.y + coord.z;
vColor.xyz *= abs(sin(sum / 512.0 + uTime)) * 1.5 + 0.5; // color dodge vColor.xyz *= abs(sin(sum / 512.0 + uTime)) * 1.5 + 0.5; // color dodge
@@ -91,7 +100,7 @@ uniform float uTime;
#else #else
uniform sampler2D sDiffuse; uniform sampler2D sDiffuse;
uniform vec4 uColor; uniform vec4 uColor;
#ifndef PASS_SHADOW #ifdef PASS_COMPOSE
uniform vec3 uLightPos[MAX_LIGHTS]; uniform vec3 uLightPos[MAX_LIGHTS];
uniform vec4 uLightColor[MAX_LIGHTS]; uniform vec4 uLightColor[MAX_LIGHTS];
#endif #endif
@@ -106,7 +115,9 @@ uniform float uTime;
return res; return res;
} }
#endif #endif
#else #endif
#ifdef PASS_COMPOSE
#ifdef AMBIENT_CUBE #ifdef AMBIENT_CUBE
uniform vec3 uAmbientCube[6]; uniform vec3 uAmbientCube[6];
@@ -180,7 +191,7 @@ uniform float uTime;
poissonDisk[13] = vec2( -0.81409955, 0.91437590 ); poissonDisk[13] = vec2( -0.81409955, 0.91437590 );
poissonDisk[14] = vec2( 0.19984126, 0.78641367 ); poissonDisk[14] = vec2( 0.19984126, 0.78641367 );
poissonDisk[15] = vec2( 0.14383161, -0.14100790 ); poissonDisk[15] = vec2( 0.14383161, -0.14100790 );
//return SHADOW(p);
float rShadow = 0.0; float rShadow = 0.0;
for (int i = 0; i < 16; i += 1) for (int i = 0; i < 16; i += 1)
rShadow += SHADOW(p + vec3(poissonDisk[i] * 1.5, 0.0) * (1.0 / 1024.0)); rShadow += SHADOW(p + vec3(poissonDisk[i] * 1.5, 0.0) * (1.0 / 1024.0));
@@ -215,34 +226,38 @@ uniform float uTime;
color.xyz = pow(abs(color.xyz), vec3(2.2)); // to linear space color.xyz = pow(abs(color.xyz), vec3(2.2)); // to linear space
// calc point lights #ifdef PASS_AMBIENT
if (uType != TYPE_FLASH) { color.xyz *= vColor.w;
vec3 normal = normalize(vNormal.xyz); #else
vec3 viewVec = normalize(vViewVec); // calc point lights
vec3 light = vec3(0.0); if (uType != TYPE_FLASH) {
vec3 normal = normalize(vNormal.xyz);
vec3 viewVec = normalize(vViewVec);
vec3 light = vec3(0.0);
for (int i = 1; i < MAX_LIGHTS; i++) // additional lights for (int i = 1; i < MAX_LIGHTS; i++) // additional lights
light += calcLight(normal, uLightPos[i], uLightColor[i]); light += calcLight(normal, uLightPos[i], uLightColor[i]);
// apply lighting // apply lighting
if (uType == TYPE_SPRITE) { if (uType == TYPE_SPRITE) {
light += vColor.w * uColor.w; light += vColor.w * uColor.w;
}
if (uType == TYPE_ROOM) {
light += mix(min(uColor.w, vColor.w), vColor.w, getShadow(vLightProj));
}
if (uType == TYPE_ENTITY) {
float shadow = getShadow(vLightProj);
vec3 lum = calcLight(normal, uLightPos[0], uLightColor[0]) * shadow + uColor.w;
light += lum;
light *= dot(normal, viewVec) * 0.2 + 0.8; // apply backlight
}
color.xyz *= light;
} else {
color.w = uColor.w;
} }
#endif
if (uType == TYPE_ROOM) {
light += mix(min(uColor.w, vColor.w), vColor.w, getShadow(vLightProj));
}
if (uType == TYPE_ENTITY) {
float shadow = getShadow(vLightProj);
vec3 lum = calcLight(normal, uLightPos[0], uLightColor[0]) * shadow + uColor.w;
light += lum;
light *= dot(normal, viewVec) * 0.2 + 0.8; // apply backlight
}
color.xyz *= light;
} else {
color.w = uColor.w;
}
color.xyz = pow(abs(color.xyz), vec3(1.0/2.2)); // back to gamma space color.xyz = pow(abs(color.xyz), vec3(1.0/2.2)); // back to gamma space

View File

@@ -133,6 +133,7 @@ struct vec3 {
float length2() const { return dot(*this); } float length2() const { return dot(*this); }
float length() const { return sqrtf(length2()); } float length() const { return sqrtf(length2()); }
vec3 normal() const { float s = length(); return s == 0.0f ? (*this) : (*this)*(1.0f/s); } vec3 normal() const { float s = length(); return s == 0.0f ? (*this) : (*this)*(1.0f/s); }
vec3 axisXZ() const { return (fabsf(x) > fabsf(z)) ? vec3(sign(x), 0, 0) : vec3(0, 0, sign(z)); }
vec3 lerp(const vec3 &v, const float t) const { vec3 lerp(const vec3 &v, const float t) const {
if (t <= 0.0f) return *this; if (t <= 0.0f) return *this;