1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-10 15:14:28 +02:00

#23 environment reflections for crystals (cubemaps)

This commit is contained in:
XProger
2016-12-22 03:37:49 +03:00
parent 69e4f8e962
commit 2cd339138b
6 changed files with 142 additions and 79 deletions

View File

@@ -246,7 +246,7 @@ namespace Core {
glGenFramebuffers(1, &RT);
glGenRenderbuffers(1, &RB);
glBindRenderbuffer(GL_RENDERBUFFER, RB);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, 64, 64);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, 128, 128);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
Sound::init();
@@ -262,11 +262,6 @@ 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);
@@ -315,16 +310,20 @@ namespace Core {
glEnable(GL_BLEND);
}
void setTarget(Texture *target) {
void setTarget(Texture *target, int face = 0) {
if (!target) {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glColorMask(true, true, true, true);
return;
}
GLenum texTarget = GL_TEXTURE_2D;
if (target->cube)
texTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
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);
glFramebufferTexture2D(GL_FRAMEBUFFER, target->depth ? GL_DEPTH_ATTACHMENT : GL_COLOR_ATTACHMENT0, texTarget, target->ID, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, target->depth ? GL_COLOR_ATTACHMENT0 : GL_DEPTH_ATTACHMENT, texTarget, target->dummy ? target->dummy->ID : 0, 0);
if (!target->depth)
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, RB);
@@ -333,6 +332,13 @@ namespace Core {
// GLenum buffers[] = { GL_COLOR_ATTACHMENT0 };
// glDrawBuffers(target->depth ? 0 : 1, buffers);
}
void resetStates() {
memset(&active, 0, sizeof(active));
glEnable(GL_DEPTH_TEST);
setCulling(cfFront);
setBlending(bmAlpha);
}
}
#endif

View File

@@ -48,10 +48,10 @@ struct Level {
#endif
mesh = new MeshBuilder(level);
shadow = new Texture(1024, 1024, true);
shadow = new Texture(1024, 1024, true, false);
for (int j = 0; j < 6; j++)
for (int i = 0; i < 4; i++)
ambient[j * 4 + i] = new Texture(64 >> (i << 1), 64 >> (i << 1), false);
ambient[j * 4 + i] = new Texture(64 >> (i << 1), 64 >> (i << 1), false, false);
initAtlas();
initShaders();
@@ -119,6 +119,9 @@ struct Level {
case TR::Entity::TRAP_FLOOR :
entity.controller = new TrapFloor(&level, i);
break;
case TR::Entity::CRYSTAL :
entity.controller = new Crystal(&level, i);
break;
case TR::Entity::TRAP_BLADE :
case TR::Entity::TRAP_SPIKES :
entity.controller = new Trigger(&level, i, true);
@@ -151,6 +154,8 @@ struct Level {
camera = new Camera(&level, lara);
level.cameraController = camera;
initReflections();
}
~Level() {
@@ -204,7 +209,7 @@ struct Level {
fclose(f);
*/
atlas = new Texture(1024, 1024, false, data);
atlas = new Texture(1024, 1024, false, false, data);
PROFILE_LABEL(TEXTURE, atlas->ID, "atlas");
delete[] data;
@@ -274,6 +279,17 @@ struct Level {
*/
}
void initReflections() {
Core::resetStates();
for (int i = 0; i < level.entitiesBaseCount; i++) {
TR::Entity &e = level.entities[i];
if (e.type == TR::Entity::CRYSTAL) {
Crystal *c = (Crystal*)e.controller;
renderEnvironment(c->getRoomIndex(), c->pos - vec3(0, 512, 0), &c->environment);
}
}
}
#ifdef LEVEL_EDITOR
struct Light {
vec3 pos;
@@ -601,20 +617,20 @@ struct Level {
}
void setupCubeCamera(const vec3 &pos, int face) {
vec3 up = vec3(0, 1, 0);
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 2 : dir = vec3( 0, 1, 0); up = vec3(0, 0, 1); break;
case 3 : dir = vec3( 0, -1, 0); up = vec3(0, 0, -1); 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);
Core::mView = Core::mViewInv.inverse();
Core::mProj = mat4(90, 1.0f, camera->znear, camera->zfar);
}
bool setupLightCamera() {
@@ -628,13 +644,13 @@ struct Level {
TR::Room::Light &light = level.rooms[room].lights[idx];
vec3 shadowLightPos = vec3(float(light.x), float(light.y), float(light.z));
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::mView = Core::mViewInv.inverse();
Core::mProj = mat4(120, 1.0f, camera->znear, camera->zfar);
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;
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;
return true;
}
@@ -652,20 +668,25 @@ struct Level {
sh->bind();
}
void renderAmbient(int roomIndex, const vec3 &pos, vec3 *cube) {
PROFILE_MARKER("PASS_AMBIENT");
void renderEnvironment(int roomIndex, const vec3 &pos, Texture **targets, int stride = 0) {
PROFILE_MARKER("ENVIRONMENT");
// first pass render level into cube faces
for (int j = 0; j < 6; j++) {
setupCubeCamera(pos, j);
for (int i = 0; i < 6; i++) {
setupCubeCamera(pos, i);
setPassShader(Core::passAmbient);
Core::setBlending(bmAlpha);
Texture *target = ambient[j * 4 + 0];
Core::setTarget(target);
Core::setViewport(0, 0, target->width, target->height);
Texture *target = targets[0]->cube ? targets[0] : targets[i * stride];
Core::setTarget(target, i);
Core::setViewport(0, 0, target->width, target->height);
Core::clear(vec4(0, 0, 0, 1));
renderScene(roomIndex);
}
}
void renderAmbient(int roomIndex, const vec3 &pos, vec3 *cube) {
PROFILE_MARKER("PASS_AMBIENT");
renderEnvironment(roomIndex, pos, ambient, 4);
// second pass - downsample
glDisable(GL_DEPTH_TEST);
@@ -705,7 +726,7 @@ struct Level {
void renderShadows(int roomIndex) {
PROFILE_MARKER("PASS_SHADOW");
if (!setupLightCamera()) return;
Texture::unbind(sShadow);
shadow->unbind(sShadow);
setPassShader(Core::passShadow);
Core::setBlending(bmNone);
Core::setTarget(shadow);
@@ -734,7 +755,6 @@ struct Level {
renderAmbient(lara->getRoomIndex(), lara->pos - vec3(0, 512, 0), cube);
renderShadows(lara->getRoomIndex());
renderCompose(camera->getRoomIndex());
#ifdef _DEBUG
static int modelIndex = 0;
@@ -765,7 +785,7 @@ struct Level {
// Debug::Level::rooms(level, lara->pos, lara->getEntity().room);
// Debug::Level::lights(level, lara->getRoomIndex());
// Debug::Level::sectors(level, lara->getRoomIndex(), (int)lara->pos.y);
Debug::Level::portals(level);
// Debug::Level::portals(level);
// Debug::Level::meshes(level);
// Debug::Level::entities(level);
static int dbg_ambient = 0;
@@ -781,19 +801,19 @@ struct Level {
switch (j) {
case 0 : glRotatef( 90, 0, 1, 0); break;
case 1 : glRotatef(-90, 0, 1, 0); break;
case 2 : glRotatef(-90, 1, 0, 0); glRotatef(-90, 0, 0, 1); break;
case 3 : glRotatef( 90, 1, 0, 0); glRotatef(-90, 0, 0, 1); break;
case 2 : glRotatef(-90, 1, 0, 0); break;
case 3 : glRotatef( 90, 1, 0, 0); break;
case 4 : glRotatef( 0, 0, 1, 0); break;
case 5 : glRotatef(180, 0, 1, 0); break;
}
glTranslatef(0, 0, 256);
Texture::unbind(sShadow);
shadow->unbind(sShadow);
ambient[j * 4 + dbg_ambient]->bind(sDiffuse);
glBegin(GL_QUADS);
glTexCoord2f(1, 1); glVertex3f(-256, 256, 0);
glTexCoord2f(0, 1); glVertex3f( 256, 256, 0);
glTexCoord2f(0, 0); glVertex3f( 256, -256, 0);
glTexCoord2f(1, 0); glVertex3f(-256, -256, 0);
glTexCoord2f(0, 0); glVertex3f(-256, 256, 0);
glTexCoord2f(1, 0); glVertex3f( 256, 256, 0);
glTexCoord2f(1, 1); glVertex3f( 256, -256, 0);
glTexCoord2f(0, 1); glVertex3f(-256, -256, 0);
glEnd();
glPopMatrix();
}
@@ -813,7 +833,7 @@ struct Level {
glEnable(GL_DEPTH_TEST);
*/
Debug::Level::info(level, lara->getEntity(), lara->animation);
// Debug::Level::info(level, lara->getEntity(), lara->animation);
Debug::end();
#endif
}

View File

@@ -13,9 +13,10 @@ varying vec2 vTexCoord;
#endif
#define TYPE_SPRITE 0
#define TYPE_ROOM 1
#define TYPE_ENTITY 2
#define TYPE_FLASH 3
#define TYPE_FLASH 1
#define TYPE_ROOM 2
#define TYPE_ENTITY 3
#define TYPE_MIRROR 4
uniform int uType;
@@ -103,8 +104,10 @@ uniform int uType;
uniform sampler2D sDiffuse;
uniform vec4 uColor;
#ifdef PASS_COMPOSE
uniform vec3 uLightPos[MAX_LIGHTS];
uniform vec4 uLightColor[MAX_LIGHTS];
uniform samplerCube sEnvironment;
uniform vec3 uLightPos[MAX_LIGHTS];
uniform vec4 uLightColor[MAX_LIGHTS];
uniform vec3 uAmbient[6];
#endif
#ifdef PASS_SHADOW
@@ -120,15 +123,6 @@ uniform int uType;
#endif
#ifdef PASS_COMPOSE
uniform vec3 uAmbient[6];
vec3 getAmbientLight(vec3 n) {
vec3 sqr = n * n;
vec3 pos = step(0.0, n);
return sqr.x * mix(uAmbient[1], uAmbient[0], pos.x) +
sqr.y * mix(uAmbient[3], uAmbient[2], pos.y) +
sqr.z * mix(uAmbient[5], uAmbient[4], pos.z);
}
#ifdef SHADOW_SAMPLER
uniform sampler2DShadow sShadow;
@@ -201,6 +195,14 @@ uniform int uType;
float att = max(0.0, 1.0 - dot(lv, lv) / color.w);
return color.xyz * (lum * att);
}
vec3 calcAmbient(vec3 n) {
vec3 sqr = n * n;
vec3 pos = step(0.0, n);
return sqr.x * mix(uAmbient[1], uAmbient[0], pos.x) +
sqr.y * mix(uAmbient[3], uAmbient[2], pos.y) +
sqr.z * mix(uAmbient[5], uAmbient[4], pos.z);
}
#endif
void main() {
@@ -242,10 +244,17 @@ uniform int uType;
}
if (uType == TYPE_ENTITY) {
vec3 rAmbient = pow(abs(getAmbientLight(normal)), vec3(2.2));
vec3 rAmbient = pow(abs(calcAmbient(normal)), vec3(2.2));
float rShadow = getShadow(vLightProj);
light += calcLight(normal, uLightPos[0], uLightColor[0]) * rShadow + rAmbient;
light += calcLight(normal, uLightPos[0], uLightColor[0]) * rShadow + rAmbient;
}
if (uType == TYPE_MIRROR) {
vec3 rv = reflect(-viewVec, normal);
color.xyz = uColor.xyz * pow(abs(textureCube(sEnvironment, normalize(rv)).xyz), vec3(2.2));
light.xyz = vec3(1.0);
}
color.xyz *= light;
} else {
color.w = uColor.w;

View File

@@ -4,18 +4,18 @@
#include "core.h"
enum AttribType { aCoord, aTexCoord, aNormal, aColor, aMAX };
enum SamplerType { sDiffuse, sShadow, sMAX };
enum SamplerType { sDiffuse, sShadow, sEnvironment, sMAX };
enum UniformType { uType, uCaustics, uTime, uViewProj, uViewInv, uModel, uLightProj, uColor, uAmbient, uViewPos, uLightPos, uLightColor, uLightTarget, uAnimTexRanges, uAnimTexOffsets, uMAX };
const char *AttribName[aMAX] = { "aCoord", "aTexCoord", "aNormal", "aColor" };
const char *SamplerName[sMAX] = { "sDiffuse", "sShadow" };
const char *SamplerName[sMAX] = { "sDiffuse", "sShadow", "sEnvironment" };
const char *UniformName[uMAX] = { "uType", "uCaustics", "uTime", "uViewProj", "uViewInv", "uModel", "uLightProj", "uColor", "uAmbient", "uViewPos", "uLightPos", "uLightColor", "uLightTarget", "uAnimTexRanges", "uAnimTexOffsets" };
struct Shader {
GLuint ID;
GLint uID[uMAX];
enum : GLint { SPRITE = 0, ROOM = 1, ENTITY = 2, FLASH = 3, DOWNSAMPLE = 10 };
enum : GLint { SPRITE = 0, FLASH = 1, ROOM = 2, ENTITY = 3, MIRROR = 4, DOWNSAMPLE = 10 };
Shader(const char *text, const char *defines = "") {
#ifdef MOBILE

View File

@@ -7,36 +7,41 @@ struct Texture {
GLuint ID;
int width, height;
bool depth;
bool cube;
Texture *dummy;
Texture(int width, int height, bool depth, void *data = NULL) : width(width), height(height), dummy(NULL) {
Texture(int width, int height, bool depth, bool cube, void *data = NULL) : width(width), height(height), cube(cube), dummy(NULL) {
glGenTextures(1, &ID);
bind(0);
int filter = 1;
bool filter = true;
if (depth && !Core::support.depthTexture)
depth = false;
this->depth = depth;
GLenum target = cube ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D;
GLint format = depth ? GL_DEPTH_COMPONENT : GL_RGBA;
if (depth) {
if (Core::support.shadowSampler) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
glTexParameteri(target, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
glTexParameteri(target, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
} else
filter = 0;
filter = false;
}
glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, filter ? GL_LINEAR : GL_NEAREST);
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, filter ? GL_LINEAR : GL_NEAREST);
for (int i = 0; i < 6; i++) {
glTexImage2D(cube ? (GL_TEXTURE_CUBE_MAP_POSITIVE_X + i) : GL_TEXTURE_2D, 0, format, width, height, 0, format, depth ? GL_UNSIGNED_SHORT : GL_UNSIGNED_BYTE, data);
if (!cube) break;
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter ? GL_LINEAR : GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter ? GL_LINEAR : GL_NEAREST);
GLint format = depth ? GL_DEPTH_COMPONENT : GL_RGBA;
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, depth ? GL_UNSIGNED_SHORT : GL_UNSIGNED_BYTE, data);
if (depth)
dummy = new Texture(width, height, false, NULL); // some drivers can't render to texture without color target, create dummy color target for fix it
dummy = new Texture(width, height, false, false, NULL); // some drivers can't render to texture without color target, create dummy color target for fix it
}
virtual ~Texture() {
@@ -46,12 +51,12 @@ struct Texture {
void bind(int sampler) {
glActiveTexture(GL_TEXTURE0 + sampler);
glBindTexture(GL_TEXTURE_2D, ID);
glBindTexture(cube ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D, ID);
}
static void unbind(int sampler) {
void unbind(int sampler) {
glActiveTexture(GL_TEXTURE0 + sampler);
glBindTexture(GL_TEXTURE_2D, 0);
glBindTexture(cube ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D, 0);
}
};

View File

@@ -1,6 +1,7 @@
#ifndef H_TRIGGER
#define H_TRIGGER
#include "core.h"
#include "controller.h"
#include "sprite.h"
@@ -287,4 +288,26 @@ struct Bridge : Trigger {
}
};
struct Crystal : Controller {
Texture *environment;
Crystal(TR::Level *level, int entity) : Controller(level, entity) {
environment = new Texture(128, 128, false, true);
}
virtual ~Crystal() {
delete environment;
}
virtual void render(Frustum *frustum, MeshBuilder *mesh) {
Shader *sh = Core::active.shader;
sh->setParam(uType, Shader::MIRROR);
sh->setParam(uColor, vec4(0.4f, 0.4f, 16.0f, 1.0f)); // blue color dodge
environment->bind(sEnvironment);
Controller::render(frustum, mesh);
environment->unbind(sEnvironment);
sh->setParam(uType, Shader::ENTITY);
}
};
#endif