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:
24
src/core.h
24
src/core.h
@@ -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
|
||||
|
86
src/level.h
86
src/level.h
@@ -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
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -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
|
Reference in New Issue
Block a user