1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-10 23:24:06 +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 color;
enum { passOpaque, passShadow } pass;
enum Pass { passCompose, passShadow, passAmbient } pass;
GLuint RT;
GLuint RT, RB;
struct {
Shader *shader;
@@ -246,6 +246,10 @@ namespace Core {
// support.depthTexture = support.shadowSampler = false; // depth textures is not supported in Safari browser in fact :(
glGenFramebuffers(1, &RT);
glGenRenderbuffers(1, &RB);
glBindRenderbuffer(GL_RENDERBUFFER, RB);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, 64, 64);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
Sound::init();
@@ -258,6 +262,11 @@ namespace Core {
Sound::free();
}
void resetStates() {
memset(&active, 0, sizeof(active));
glEnable(GL_DEPTH_TEST);
}
void clear(const vec4 &color) {
glClearColor(color.x, color.y, color.z, color.w);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
@@ -316,6 +325,8 @@ namespace Core {
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_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;
glColorMask(mask, mask, mask, mask);

View File

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

View File

@@ -2,13 +2,15 @@ R"====(
varying vec2 vTexCoord;
#ifndef PASS_SHADOW
#ifndef PASS_AMBIENT
varying vec3 vCoord;
varying vec4 vNormal;
varying vec3 vViewVec;
varying vec4 vColor;
varying vec4 vLightProj;
varying float vLightTargetDist;
#endif
varying vec4 vColor;
#endif
#define TYPE_SPRITE 0
#define TYPE_ROOM 1
@@ -16,26 +18,34 @@ varying vec2 vTexCoord;
#define TYPE_FLASH 3
uniform int uType;
#ifdef PASS_COMPOSE
uniform int uCaustics;
uniform float uTime;
#endif
#ifdef VERTEX
uniform mat4 uViewProj;
uniform mat4 uModel;
#ifndef PASS_AMBIENT
uniform mat4 uViewInv;
uniform mat4 uLightProj;
uniform vec3 uLightTarget;
#endif
#ifndef PASS_SHADOW
#ifdef PASS_COMPOSE
uniform vec3 uViewPos;
uniform vec2 uAnimTexRanges[MAX_RANGES];
uniform vec2 uAnimTexOffsets[MAX_OFFSETS];
#endif
attribute vec4 aCoord;
attribute vec4 aTexCoord;
#ifndef PASS_AMBIENT
attribute vec4 aNormal;
#endif
#ifndef PASS_SHADOW
attribute vec4 aColor;
@@ -46,9 +56,8 @@ uniform float uTime;
void main() {
vec4 coord = uModel * vec4(aCoord.xyz, 1.0);
#ifdef PASS_COMPOSE
if (uType != TYPE_SPRITE) {
#ifndef PASS_SHADOW
// animated texture coordinates
vec2 range = uAnimTexRanges[int(aTexCoord.z)]; // x - start index, y - count
@@ -57,20 +66,20 @@ uniform float uTime;
vTexCoord = (aTexCoord.xy + offset) * TEXCOORD_SCALE; // first frame + offset * isAnimated
vNormal = vec4((uModel * vec4(aNormal.xyz, 0.0)).xyz, aNormal.w);
} else {
coord.xyz += uViewInv[0].xyz * aTexCoord.z - uViewInv[1].xyz * aTexCoord.w;
vTexCoord = aTexCoord.xy * TEXCOORD_SCALE;
vNormal = vec4(uViewPos.xyz - coord.xyz, 0.0);
}
#else
vTexCoord = aTexCoord.xy * TEXCOORD_SCALE;
#endif
} else {
coord.xyz += uViewInv[0].xyz * aTexCoord.z - uViewInv[1].xyz * aTexCoord.w;
#ifndef PASS_SHADOW
vTexCoord = aTexCoord.xy * TEXCOORD_SCALE;
vNormal = vec4(uViewPos.xyz - coord.xyz, 0.0);
#endif
}
#ifndef PASS_SHADOW
vColor = aColor;
#endif
#ifdef PASS_COMPOSE
if (uCaustics != 0) {
float sum = coord.x + coord.y + coord.z;
vColor.xyz *= abs(sin(sum / 512.0 + uTime)) * 1.5 + 0.5; // color dodge
@@ -91,7 +100,7 @@ uniform float uTime;
#else
uniform sampler2D sDiffuse;
uniform vec4 uColor;
#ifndef PASS_SHADOW
#ifdef PASS_COMPOSE
uniform vec3 uLightPos[MAX_LIGHTS];
uniform vec4 uLightColor[MAX_LIGHTS];
#endif
@@ -106,7 +115,9 @@ uniform float uTime;
return res;
}
#endif
#else
#endif
#ifdef PASS_COMPOSE
#ifdef AMBIENT_CUBE
uniform vec3 uAmbientCube[6];
@@ -180,7 +191,7 @@ uniform float uTime;
poissonDisk[13] = vec2( -0.81409955, 0.91437590 );
poissonDisk[14] = vec2( 0.19984126, 0.78641367 );
poissonDisk[15] = vec2( 0.14383161, -0.14100790 );
//return SHADOW(p);
float rShadow = 0.0;
for (int i = 0; i < 16; i += 1)
rShadow += SHADOW(p + vec3(poissonDisk[i] * 1.5, 0.0) * (1.0 / 1024.0));
@@ -215,6 +226,9 @@ uniform float uTime;
color.xyz = pow(abs(color.xyz), vec3(2.2)); // to linear space
#ifdef PASS_AMBIENT
color.xyz *= vColor.w;
#else
// calc point lights
if (uType != TYPE_FLASH) {
vec3 normal = normalize(vNormal.xyz);
@@ -243,6 +257,7 @@ uniform float uTime;
} else {
color.w = uColor.w;
}
#endif
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 length() const { return sqrtf(length2()); }
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 {
if (t <= 0.0f) return *this;