mirror of
https://github.com/XProger/OpenLara.git
synced 2025-08-13 08:34:32 +02:00
#23 environment reflections for crystals (cubemaps)
This commit is contained in:
24
src/core.h
24
src/core.h
@@ -246,7 +246,7 @@ namespace Core {
|
|||||||
glGenFramebuffers(1, &RT);
|
glGenFramebuffers(1, &RT);
|
||||||
glGenRenderbuffers(1, &RB);
|
glGenRenderbuffers(1, &RB);
|
||||||
glBindRenderbuffer(GL_RENDERBUFFER, 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);
|
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||||
|
|
||||||
Sound::init();
|
Sound::init();
|
||||||
@@ -262,11 +262,6 @@ 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);
|
||||||
@@ -315,16 +310,20 @@ namespace Core {
|
|||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setTarget(Texture *target) {
|
void setTarget(Texture *target, int face = 0) {
|
||||||
if (!target) {
|
if (!target) {
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
glColorMask(true, true, true, true);
|
glColorMask(true, true, true, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLenum texTarget = GL_TEXTURE_2D;
|
||||||
|
if (target->cube)
|
||||||
|
texTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
|
||||||
|
|
||||||
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, texTarget, 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, texTarget, target->dummy ? target->dummy->ID : 0, 0);
|
||||||
if (!target->depth)
|
if (!target->depth)
|
||||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, RB);
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, RB);
|
||||||
|
|
||||||
@@ -333,6 +332,13 @@ namespace Core {
|
|||||||
// GLenum buffers[] = { GL_COLOR_ATTACHMENT0 };
|
// GLenum buffers[] = { GL_COLOR_ATTACHMENT0 };
|
||||||
// glDrawBuffers(target->depth ? 0 : 1, buffers);
|
// glDrawBuffers(target->depth ? 0 : 1, buffers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void resetStates() {
|
||||||
|
memset(&active, 0, sizeof(active));
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
setCulling(cfFront);
|
||||||
|
setBlending(bmAlpha);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
86
src/level.h
86
src/level.h
@@ -48,10 +48,10 @@ struct Level {
|
|||||||
#endif
|
#endif
|
||||||
mesh = new MeshBuilder(level);
|
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 j = 0; j < 6; j++)
|
||||||
for (int i = 0; i < 4; i++)
|
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();
|
initAtlas();
|
||||||
initShaders();
|
initShaders();
|
||||||
@@ -119,6 +119,9 @@ struct Level {
|
|||||||
case TR::Entity::TRAP_FLOOR :
|
case TR::Entity::TRAP_FLOOR :
|
||||||
entity.controller = new TrapFloor(&level, i);
|
entity.controller = new TrapFloor(&level, i);
|
||||||
break;
|
break;
|
||||||
|
case TR::Entity::CRYSTAL :
|
||||||
|
entity.controller = new Crystal(&level, i);
|
||||||
|
break;
|
||||||
case TR::Entity::TRAP_BLADE :
|
case TR::Entity::TRAP_BLADE :
|
||||||
case TR::Entity::TRAP_SPIKES :
|
case TR::Entity::TRAP_SPIKES :
|
||||||
entity.controller = new Trigger(&level, i, true);
|
entity.controller = new Trigger(&level, i, true);
|
||||||
@@ -151,6 +154,8 @@ struct Level {
|
|||||||
camera = new Camera(&level, lara);
|
camera = new Camera(&level, lara);
|
||||||
|
|
||||||
level.cameraController = camera;
|
level.cameraController = camera;
|
||||||
|
|
||||||
|
initReflections();
|
||||||
}
|
}
|
||||||
|
|
||||||
~Level() {
|
~Level() {
|
||||||
@@ -204,7 +209,7 @@ struct Level {
|
|||||||
fclose(f);
|
fclose(f);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
atlas = new Texture(1024, 1024, false, data);
|
atlas = new Texture(1024, 1024, false, false, data);
|
||||||
PROFILE_LABEL(TEXTURE, atlas->ID, "atlas");
|
PROFILE_LABEL(TEXTURE, atlas->ID, "atlas");
|
||||||
|
|
||||||
delete[] data;
|
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
|
#ifdef LEVEL_EDITOR
|
||||||
struct Light {
|
struct Light {
|
||||||
vec3 pos;
|
vec3 pos;
|
||||||
@@ -601,20 +617,20 @@ struct Level {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setupCubeCamera(const vec3 &pos, int face) {
|
void setupCubeCamera(const vec3 &pos, int face) {
|
||||||
vec3 up = vec3(0, 1, 0);
|
vec3 up = vec3(0, -1, 0);
|
||||||
vec3 dir;
|
vec3 dir;
|
||||||
switch (face) {
|
switch (face) {
|
||||||
case 0 : dir = vec3( 1, 0, 0); break;
|
case 0 : dir = vec3( 1, 0, 0); break;
|
||||||
case 1 : 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 2 : dir = vec3( 0, 1, 0); up = vec3(0, 0, 1); break;
|
||||||
case 3 : dir = vec3( 0, -1, 0); up = vec3(1, 0, 0); break;
|
case 3 : dir = vec3( 0, -1, 0); up = vec3(0, 0, -1); break;
|
||||||
case 4 : dir = vec3( 0, 0, 1); break;
|
case 4 : dir = vec3( 0, 0, 1); break;
|
||||||
case 5 : dir = vec3( 0, 0, -1); break;
|
case 5 : dir = vec3( 0, 0, -1); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Core::mViewInv = mat4(pos, pos + dir, up);
|
Core::mViewInv = mat4(pos, pos + dir, up);
|
||||||
Core::mView = Core::mViewInv.inverse();
|
Core::mView = Core::mViewInv.inverse();
|
||||||
Core::mProj = mat4(90, 1.0f, camera->znear, camera->zfar);
|
Core::mProj = mat4(90, 1.0f, camera->znear, camera->zfar);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool setupLightCamera() {
|
bool setupLightCamera() {
|
||||||
@@ -628,13 +644,13 @@ 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::mViewInv = mat4(shadowLightPos, pos - vec3(0, 256, 0), vec3(0, -1, 0));
|
Core::mViewInv = mat4(shadowLightPos, pos - vec3(0, 256, 0), vec3(0, -1, 0));
|
||||||
Core::mView = Core::mViewInv.inverse();
|
Core::mView = Core::mViewInv.inverse();
|
||||||
Core::mProj = mat4(120, 1.0f, camera->znear, camera->zfar);
|
Core::mProj = mat4(120, 1.0f, camera->znear, camera->zfar);
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -652,20 +668,25 @@ struct Level {
|
|||||||
sh->bind();
|
sh->bind();
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderAmbient(int roomIndex, const vec3 &pos, vec3 *cube) {
|
void renderEnvironment(int roomIndex, const vec3 &pos, Texture **targets, int stride = 0) {
|
||||||
PROFILE_MARKER("PASS_AMBIENT");
|
PROFILE_MARKER("ENVIRONMENT");
|
||||||
|
|
||||||
// first pass render level into cube faces
|
// first pass render level into cube faces
|
||||||
for (int j = 0; j < 6; j++) {
|
for (int i = 0; i < 6; i++) {
|
||||||
setupCubeCamera(pos, j);
|
setupCubeCamera(pos, i);
|
||||||
setPassShader(Core::passAmbient);
|
setPassShader(Core::passAmbient);
|
||||||
Core::setBlending(bmAlpha);
|
Core::setBlending(bmAlpha);
|
||||||
Texture *target = ambient[j * 4 + 0];
|
Texture *target = targets[0]->cube ? targets[0] : targets[i * stride];
|
||||||
Core::setTarget(target);
|
Core::setTarget(target, i);
|
||||||
Core::setViewport(0, 0, target->width, target->height);
|
Core::setViewport(0, 0, target->width, target->height);
|
||||||
Core::clear(vec4(0, 0, 0, 1));
|
Core::clear(vec4(0, 0, 0, 1));
|
||||||
renderScene(roomIndex);
|
renderScene(roomIndex);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void renderAmbient(int roomIndex, const vec3 &pos, vec3 *cube) {
|
||||||
|
PROFILE_MARKER("PASS_AMBIENT");
|
||||||
|
|
||||||
|
renderEnvironment(roomIndex, pos, ambient, 4);
|
||||||
|
|
||||||
// second pass - downsample
|
// second pass - downsample
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
@@ -705,7 +726,7 @@ struct Level {
|
|||||||
void renderShadows(int roomIndex) {
|
void renderShadows(int roomIndex) {
|
||||||
PROFILE_MARKER("PASS_SHADOW");
|
PROFILE_MARKER("PASS_SHADOW");
|
||||||
if (!setupLightCamera()) return;
|
if (!setupLightCamera()) return;
|
||||||
Texture::unbind(sShadow);
|
shadow->unbind(sShadow);
|
||||||
setPassShader(Core::passShadow);
|
setPassShader(Core::passShadow);
|
||||||
Core::setBlending(bmNone);
|
Core::setBlending(bmNone);
|
||||||
Core::setTarget(shadow);
|
Core::setTarget(shadow);
|
||||||
@@ -734,7 +755,6 @@ struct Level {
|
|||||||
renderAmbient(lara->getRoomIndex(), lara->pos - vec3(0, 512, 0), cube);
|
renderAmbient(lara->getRoomIndex(), lara->pos - vec3(0, 512, 0), cube);
|
||||||
renderShadows(lara->getRoomIndex());
|
renderShadows(lara->getRoomIndex());
|
||||||
renderCompose(camera->getRoomIndex());
|
renderCompose(camera->getRoomIndex());
|
||||||
|
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
static int modelIndex = 0;
|
static int modelIndex = 0;
|
||||||
@@ -765,7 +785,7 @@ struct Level {
|
|||||||
// 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);
|
||||||
static int dbg_ambient = 0;
|
static int dbg_ambient = 0;
|
||||||
@@ -781,19 +801,19 @@ struct Level {
|
|||||||
switch (j) {
|
switch (j) {
|
||||||
case 0 : glRotatef( 90, 0, 1, 0); break;
|
case 0 : glRotatef( 90, 0, 1, 0); break;
|
||||||
case 1 : 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 2 : glRotatef(-90, 1, 0, 0); break;
|
||||||
case 3 : glRotatef( 90, 1, 0, 0); glRotatef(-90, 0, 0, 1); break;
|
case 3 : glRotatef( 90, 1, 0, 0); break;
|
||||||
case 4 : glRotatef( 0, 0, 1, 0); break;
|
case 4 : glRotatef( 0, 0, 1, 0); break;
|
||||||
case 5 : glRotatef(180, 0, 1, 0); break;
|
case 5 : glRotatef(180, 0, 1, 0); break;
|
||||||
}
|
}
|
||||||
glTranslatef(0, 0, 256);
|
glTranslatef(0, 0, 256);
|
||||||
Texture::unbind(sShadow);
|
shadow->unbind(sShadow);
|
||||||
ambient[j * 4 + dbg_ambient]->bind(sDiffuse);
|
ambient[j * 4 + dbg_ambient]->bind(sDiffuse);
|
||||||
glBegin(GL_QUADS);
|
glBegin(GL_QUADS);
|
||||||
glTexCoord2f(1, 1); glVertex3f(-256, 256, 0);
|
glTexCoord2f(0, 0); glVertex3f(-256, 256, 0);
|
||||||
glTexCoord2f(0, 1); glVertex3f( 256, 256, 0);
|
glTexCoord2f(1, 0); glVertex3f( 256, 256, 0);
|
||||||
glTexCoord2f(0, 0); glVertex3f( 256, -256, 0);
|
glTexCoord2f(1, 1); glVertex3f( 256, -256, 0);
|
||||||
glTexCoord2f(1, 0); glVertex3f(-256, -256, 0);
|
glTexCoord2f(0, 1); glVertex3f(-256, -256, 0);
|
||||||
glEnd();
|
glEnd();
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
}
|
}
|
||||||
@@ -813,7 +833,7 @@ struct Level {
|
|||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Debug::Level::info(level, lara->getEntity(), lara->animation);
|
// Debug::Level::info(level, lara->getEntity(), lara->animation);
|
||||||
Debug::end();
|
Debug::end();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@@ -13,9 +13,10 @@ varying vec2 vTexCoord;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define TYPE_SPRITE 0
|
#define TYPE_SPRITE 0
|
||||||
#define TYPE_ROOM 1
|
#define TYPE_FLASH 1
|
||||||
#define TYPE_ENTITY 2
|
#define TYPE_ROOM 2
|
||||||
#define TYPE_FLASH 3
|
#define TYPE_ENTITY 3
|
||||||
|
#define TYPE_MIRROR 4
|
||||||
|
|
||||||
uniform int uType;
|
uniform int uType;
|
||||||
|
|
||||||
@@ -103,8 +104,10 @@ uniform int uType;
|
|||||||
uniform sampler2D sDiffuse;
|
uniform sampler2D sDiffuse;
|
||||||
uniform vec4 uColor;
|
uniform vec4 uColor;
|
||||||
#ifdef PASS_COMPOSE
|
#ifdef PASS_COMPOSE
|
||||||
uniform vec3 uLightPos[MAX_LIGHTS];
|
uniform samplerCube sEnvironment;
|
||||||
uniform vec4 uLightColor[MAX_LIGHTS];
|
uniform vec3 uLightPos[MAX_LIGHTS];
|
||||||
|
uniform vec4 uLightColor[MAX_LIGHTS];
|
||||||
|
uniform vec3 uAmbient[6];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef PASS_SHADOW
|
#ifdef PASS_SHADOW
|
||||||
@@ -120,15 +123,6 @@ uniform int uType;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef PASS_COMPOSE
|
#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
|
#ifdef SHADOW_SAMPLER
|
||||||
uniform sampler2DShadow sShadow;
|
uniform sampler2DShadow sShadow;
|
||||||
@@ -201,6 +195,14 @@ uniform int uType;
|
|||||||
float att = max(0.0, 1.0 - dot(lv, lv) / color.w);
|
float att = max(0.0, 1.0 - dot(lv, lv) / color.w);
|
||||||
return color.xyz * (lum * att);
|
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
|
#endif
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
@@ -242,10 +244,17 @@ uniform int uType;
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (uType == TYPE_ENTITY) {
|
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);
|
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;
|
color.xyz *= light;
|
||||||
} else {
|
} else {
|
||||||
color.w = uColor.w;
|
color.w = uColor.w;
|
||||||
|
@@ -4,18 +4,18 @@
|
|||||||
#include "core.h"
|
#include "core.h"
|
||||||
|
|
||||||
enum AttribType { aCoord, aTexCoord, aNormal, aColor, aMAX };
|
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 };
|
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 *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" };
|
const char *UniformName[uMAX] = { "uType", "uCaustics", "uTime", "uViewProj", "uViewInv", "uModel", "uLightProj", "uColor", "uAmbient", "uViewPos", "uLightPos", "uLightColor", "uLightTarget", "uAnimTexRanges", "uAnimTexOffsets" };
|
||||||
|
|
||||||
struct Shader {
|
struct Shader {
|
||||||
GLuint ID;
|
GLuint ID;
|
||||||
GLint uID[uMAX];
|
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 = "") {
|
Shader(const char *text, const char *defines = "") {
|
||||||
#ifdef MOBILE
|
#ifdef MOBILE
|
||||||
|
@@ -7,36 +7,41 @@ struct Texture {
|
|||||||
GLuint ID;
|
GLuint ID;
|
||||||
int width, height;
|
int width, height;
|
||||||
bool depth;
|
bool depth;
|
||||||
|
bool cube;
|
||||||
Texture *dummy;
|
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);
|
glGenTextures(1, &ID);
|
||||||
bind(0);
|
bind(0);
|
||||||
|
|
||||||
int filter = 1;
|
bool filter = true;
|
||||||
if (depth && !Core::support.depthTexture)
|
if (depth && !Core::support.depthTexture)
|
||||||
depth = false;
|
depth = false;
|
||||||
this->depth = depth;
|
this->depth = depth;
|
||||||
|
|
||||||
|
GLenum target = cube ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D;
|
||||||
|
GLint format = depth ? GL_DEPTH_COMPONENT : GL_RGBA;
|
||||||
|
|
||||||
if (depth) {
|
if (depth) {
|
||||||
if (Core::support.shadowSampler) {
|
if (Core::support.shadowSampler) {
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
|
glTexParameteri(target, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
|
glTexParameteri(target, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
|
||||||
} else
|
} 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)
|
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() {
|
virtual ~Texture() {
|
||||||
@@ -46,12 +51,12 @@ struct Texture {
|
|||||||
|
|
||||||
void bind(int sampler) {
|
void bind(int sampler) {
|
||||||
glActiveTexture(GL_TEXTURE0 + 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);
|
glActiveTexture(GL_TEXTURE0 + sampler);
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(cube ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D, 0);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
#ifndef H_TRIGGER
|
#ifndef H_TRIGGER
|
||||||
#define H_TRIGGER
|
#define H_TRIGGER
|
||||||
|
|
||||||
|
#include "core.h"
|
||||||
#include "controller.h"
|
#include "controller.h"
|
||||||
#include "sprite.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
|
#endif
|
Reference in New Issue
Block a user