mirror of
https://github.com/XProger/OpenLara.git
synced 2025-08-13 16:44:50 +02:00
#23 uber-shaders
This commit is contained in:
@@ -17,6 +17,7 @@ struct IGame {
|
|||||||
virtual ~IGame() {}
|
virtual ~IGame() {}
|
||||||
virtual TR::Level* getLevel() { return NULL; }
|
virtual TR::Level* getLevel() { return NULL; }
|
||||||
virtual void waterDrop(const vec3 &pos, float radius, float strength) {}
|
virtual void waterDrop(const vec3 &pos, float radius, float strength) {}
|
||||||
|
virtual void setShader(Core::Pass pass, Shader::Type type, bool caustics) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Controller {
|
struct Controller {
|
||||||
@@ -54,7 +55,7 @@ struct Controller {
|
|||||||
|
|
||||||
Controller(IGame *game, int entity) : game(game), level(game->getLevel()), entity(entity), animation(level, getModel()), state(animation.state), layers(NULL), actionCommand(NULL) {
|
Controller(IGame *game, int entity) : game(game), level(game->getLevel()), entity(entity), animation(level, getModel()), state(animation.state), layers(NULL), actionCommand(NULL) {
|
||||||
TR::Entity &e = getEntity();
|
TR::Entity &e = getEntity();
|
||||||
pos = vec3((float)e.x, (float)e.y, (float)e.z);
|
pos = vec3(float(e.x), float(e.y), float(e.z));
|
||||||
angle = vec3(0.0f, e.rotation, 0.0f);
|
angle = vec3(0.0f, e.rotation, 0.0f);
|
||||||
TR::Model *m = getModel();
|
TR::Model *m = getModel();
|
||||||
joints = m ? new Basis[m->mCount] : NULL;
|
joints = m ? new Basis[m->mCount] : NULL;
|
||||||
@@ -493,7 +494,7 @@ struct Controller {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
virtual void render(Frustum *frustum, MeshBuilder *mesh) { // TODO: animation.calcJoints
|
virtual void render(Frustum *frustum, MeshBuilder *mesh, Shader::Type type, bool caustics) { // TODO: animation.calcJoints
|
||||||
mat4 matrix = getMatrix();
|
mat4 matrix = getMatrix();
|
||||||
|
|
||||||
Box box = animation.getBoundingBox(vec3(0, 0, 0), 0);
|
Box box = animation.getBoundingBox(vec3(0, 0, 0), 0);
|
||||||
|
169
src/core.h
169
src/core.h
@@ -6,6 +6,30 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <gl/GL.h>
|
#include <gl/GL.h>
|
||||||
#include <gl/glext.h>
|
#include <gl/glext.h>
|
||||||
|
#elif ANDROID
|
||||||
|
#define MOBILE
|
||||||
|
#include <GLES2/gl2.h>
|
||||||
|
#include <GLES2/gl2ext.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
|
||||||
|
#define GL_TEXTURE_COMPARE_MODE 0x884C
|
||||||
|
#define GL_TEXTURE_COMPARE_FUNC 0x884D
|
||||||
|
#define GL_COMPARE_REF_TO_TEXTURE 0x884E
|
||||||
|
|
||||||
|
#undef GL_RGBA32F
|
||||||
|
#undef GL_RGBA16F
|
||||||
|
#undef GL_HALF_FLOAT
|
||||||
|
|
||||||
|
#define GL_RGBA32F GL_RGBA
|
||||||
|
#define GL_RGBA16F GL_RGBA
|
||||||
|
#define GL_HALF_FLOAT GL_HALF_FLOAT_OES
|
||||||
|
|
||||||
|
#define PFNGLGENVERTEXARRAYSPROC PFNGLGENVERTEXARRAYSOESPROC
|
||||||
|
#define PFNGLDELETEVERTEXARRAYSPROC PFNGLDELETEVERTEXARRAYSOESPROC
|
||||||
|
#define PFNGLBINDVERTEXARRAYPROC PFNGLBINDVERTEXARRAYOESPROC
|
||||||
|
#define glGenVertexArrays glGenVertexArraysOES
|
||||||
|
#define glDeleteVertexArrays glDeleteVertexArraysOES
|
||||||
|
#define glBindVertexArray glBindVertexArrayOES
|
||||||
#elif __linux__
|
#elif __linux__
|
||||||
#define LINUX 1
|
#define LINUX 1
|
||||||
#include <GL/gl.h>
|
#include <GL/gl.h>
|
||||||
@@ -18,16 +42,11 @@
|
|||||||
#include <OpenGL/gl.h>
|
#include <OpenGL/gl.h>
|
||||||
#include <OpenGL/glext.h>
|
#include <OpenGL/glext.h>
|
||||||
#include <AGL/agl.h>
|
#include <AGL/agl.h>
|
||||||
/*
|
#define glGenVertexArrays glGenVertexArraysAPPLE
|
||||||
* In compatibility mode, Mac OS X only supports OpenGL 2 (no VAO), but it does
|
#define glDeleteVertexArrays glDeleteVertexArraysAPPLE
|
||||||
* support the Apple-specific VAO extension which is older and in all relevant
|
#define glBindVertexArray glBindVertexArrayAPPLE
|
||||||
* parts 100% compatible. So use those functions instead.
|
|
||||||
*/
|
|
||||||
#define glBindVertexArray glBindVertexArrayAPPLE
|
|
||||||
#define glGenVertexArrays glGenVertexArraysAPPLE
|
|
||||||
#define glDeleteVertexArrays glDeleteVertexArraysAPPLE
|
|
||||||
#elif __EMSCRIPTEN__
|
#elif __EMSCRIPTEN__
|
||||||
#define MOBILE 1
|
#define MOBILE
|
||||||
#include <emscripten.h>
|
#include <emscripten.h>
|
||||||
#include <html5.h>
|
#include <html5.h>
|
||||||
#include <GLES3/gl3.h>
|
#include <GLES3/gl3.h>
|
||||||
@@ -46,7 +65,11 @@
|
|||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include "sound.h"
|
#include "sound.h"
|
||||||
|
|
||||||
#if defined(WIN32) || defined(LINUX)
|
#if defined(WIN32) || defined(LINUX) || defined(ANDROID)
|
||||||
|
|
||||||
|
#ifdef ANDROID
|
||||||
|
#define GetProc(x) dlsym(libGL, x);
|
||||||
|
#else
|
||||||
void* GetProc(const char *name) {
|
void* GetProc(const char *name) {
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
return (void*)wglGetProcAddress(name);
|
return (void*)wglGetProcAddress(name);
|
||||||
@@ -54,6 +77,7 @@
|
|||||||
return (void*)glXGetProcAddress((GLubyte*)name);
|
return (void*)glXGetProcAddress((GLubyte*)name);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#define GetProcOGL(x) x=(decltype(x))GetProc(#x);
|
#define GetProcOGL(x) x=(decltype(x))GetProc(#x);
|
||||||
|
|
||||||
@@ -61,7 +85,15 @@
|
|||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
PFNGLACTIVETEXTUREPROC glActiveTexture;
|
PFNGLACTIVETEXTUREPROC glActiveTexture;
|
||||||
#endif
|
#endif
|
||||||
// Shader
|
|
||||||
|
#if defined(WIN32) || defined(LINUX)
|
||||||
|
// Profiling
|
||||||
|
#ifdef PROFILE
|
||||||
|
PFNGLOBJECTLABELPROC glObjectLabel;
|
||||||
|
PFNGLPUSHDEBUGGROUPPROC glPushDebugGroup;
|
||||||
|
PFNGLPOPDEBUGGROUPPROC glPopDebugGroup;
|
||||||
|
#endif
|
||||||
|
// Shader
|
||||||
PFNGLCREATEPROGRAMPROC glCreateProgram;
|
PFNGLCREATEPROGRAMPROC glCreateProgram;
|
||||||
PFNGLDELETEPROGRAMPROC glDeleteProgram;
|
PFNGLDELETEPROGRAMPROC glDeleteProgram;
|
||||||
PFNGLLINKPROGRAMPROC glLinkProgram;
|
PFNGLLINKPROGRAMPROC glLinkProgram;
|
||||||
@@ -84,15 +116,7 @@
|
|||||||
PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray;
|
PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray;
|
||||||
PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray;
|
PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray;
|
||||||
PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer;
|
PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer;
|
||||||
// Mesh
|
// Render to texture
|
||||||
PFNGLGENBUFFERSARBPROC glGenBuffers;
|
|
||||||
PFNGLDELETEBUFFERSARBPROC glDeleteBuffers;
|
|
||||||
PFNGLBINDBUFFERARBPROC glBindBuffer;
|
|
||||||
PFNGLBUFFERDATAARBPROC glBufferData;
|
|
||||||
PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
|
|
||||||
PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays;
|
|
||||||
PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
|
|
||||||
// Render to texture
|
|
||||||
PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers;
|
PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers;
|
||||||
PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer;
|
PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer;
|
||||||
PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers;
|
PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers;
|
||||||
@@ -101,13 +125,20 @@
|
|||||||
PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer;
|
PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer;
|
||||||
PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage;
|
PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage;
|
||||||
PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus;
|
PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus;
|
||||||
PFNGLDRAWBUFFERSPROC glDrawBuffers;
|
// Mesh
|
||||||
// Profiling
|
PFNGLGENBUFFERSARBPROC glGenBuffers;
|
||||||
#ifdef PROFILE
|
PFNGLDELETEBUFFERSARBPROC glDeleteBuffers;
|
||||||
PFNGLOBJECTLABELPROC glObjectLabel;
|
PFNGLBINDBUFFERARBPROC glBindBuffer;
|
||||||
PFNGLPUSHDEBUGGROUPPROC glPushDebugGroup;
|
PFNGLBUFFERDATAARBPROC glBufferData;
|
||||||
PFNGLPOPDEBUGGROUPPROC glPopDebugGroup;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
|
||||||
|
PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays;
|
||||||
|
PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MOBILE
|
||||||
|
PFNGLDISCARDFRAMEBUFFEREXTPROC glDiscardFramebufferEXT;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MAX_LIGHTS 3
|
#define MAX_LIGHTS 3
|
||||||
@@ -152,7 +183,7 @@ namespace Core {
|
|||||||
|
|
||||||
Texture *blackTex, *whiteTex;
|
Texture *blackTex, *whiteTex;
|
||||||
|
|
||||||
enum Pass { passCompose, passShadow, passAmbient, passFilter, passWater } pass;
|
enum Pass { passCompose, passShadow, passAmbient, passFilter, passWater, passMAX } pass;
|
||||||
|
|
||||||
GLuint FBO;
|
GLuint FBO;
|
||||||
struct RenderTargetCache {
|
struct RenderTargetCache {
|
||||||
@@ -167,6 +198,7 @@ namespace Core {
|
|||||||
struct {
|
struct {
|
||||||
Shader *shader;
|
Shader *shader;
|
||||||
Texture *textures[8];
|
Texture *textures[8];
|
||||||
|
Texture *target;
|
||||||
GLuint VAO;
|
GLuint VAO;
|
||||||
} active;
|
} active;
|
||||||
|
|
||||||
@@ -176,9 +208,10 @@ namespace Core {
|
|||||||
} stats;
|
} stats;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
bool VAO;
|
||||||
bool depthTexture;
|
bool depthTexture;
|
||||||
bool shadowSampler;
|
bool shadowSampler;
|
||||||
bool VAO;
|
bool discardFrame;
|
||||||
bool texFloat, texFloatLinear;
|
bool texFloat, texFloatLinear;
|
||||||
bool texHalf, texHalfLinear;
|
bool texHalf, texHalfLinear;
|
||||||
} support;
|
} support;
|
||||||
@@ -198,10 +231,22 @@ namespace Core {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void init() {
|
void init() {
|
||||||
#if defined(WIN32) || defined(LINUX)
|
#ifdef ANDROID
|
||||||
|
void *libGL = dlopen("libGLESv2.so", RTLD_LAZY);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(WIN32) || defined(LINUX) || defined(ANDROID)
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
GetProcOGL(glActiveTexture);
|
GetProcOGL(glActiveTexture);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(WIN32) || defined(LINUX)
|
||||||
|
#ifdef PROFILE
|
||||||
|
GetProcOGL(glObjectLabel);
|
||||||
|
GetProcOGL(glPushDebugGroup);
|
||||||
|
GetProcOGL(glPopDebugGroup);
|
||||||
|
#endif
|
||||||
|
|
||||||
GetProcOGL(glCreateProgram);
|
GetProcOGL(glCreateProgram);
|
||||||
GetProcOGL(glDeleteProgram);
|
GetProcOGL(glDeleteProgram);
|
||||||
GetProcOGL(glLinkProgram);
|
GetProcOGL(glLinkProgram);
|
||||||
@@ -225,14 +270,6 @@ namespace Core {
|
|||||||
GetProcOGL(glDisableVertexAttribArray);
|
GetProcOGL(glDisableVertexAttribArray);
|
||||||
GetProcOGL(glVertexAttribPointer);
|
GetProcOGL(glVertexAttribPointer);
|
||||||
|
|
||||||
GetProcOGL(glGenBuffers);
|
|
||||||
GetProcOGL(glDeleteBuffers);
|
|
||||||
GetProcOGL(glBindBuffer);
|
|
||||||
GetProcOGL(glBufferData);
|
|
||||||
GetProcOGL(glGenVertexArrays);
|
|
||||||
GetProcOGL(glDeleteVertexArrays);
|
|
||||||
GetProcOGL(glBindVertexArray);
|
|
||||||
|
|
||||||
GetProcOGL(glGenFramebuffers);
|
GetProcOGL(glGenFramebuffers);
|
||||||
GetProcOGL(glBindFramebuffer);
|
GetProcOGL(glBindFramebuffer);
|
||||||
GetProcOGL(glGenRenderbuffers);
|
GetProcOGL(glGenRenderbuffers);
|
||||||
@@ -241,19 +278,29 @@ namespace Core {
|
|||||||
GetProcOGL(glFramebufferRenderbuffer);
|
GetProcOGL(glFramebufferRenderbuffer);
|
||||||
GetProcOGL(glRenderbufferStorage);
|
GetProcOGL(glRenderbufferStorage);
|
||||||
GetProcOGL(glCheckFramebufferStatus);
|
GetProcOGL(glCheckFramebufferStatus);
|
||||||
GetProcOGL(glDrawBuffers);
|
|
||||||
|
|
||||||
#ifdef PROFILE
|
GetProcOGL(glGenBuffers);
|
||||||
GetProcOGL(glObjectLabel);
|
GetProcOGL(glDeleteBuffers);
|
||||||
GetProcOGL(glPushDebugGroup);
|
GetProcOGL(glBindBuffer);
|
||||||
GetProcOGL(glPopDebugGroup);
|
GetProcOGL(glBufferData);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MOBILE
|
||||||
|
GetProcOGL(glDiscardFramebufferEXT);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
GetProcOGL(glGenVertexArrays);
|
||||||
|
GetProcOGL(glDeleteVertexArrays);
|
||||||
|
GetProcOGL(glBindVertexArray);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
char *ext = (char*)glGetString(GL_EXTENSIONS);
|
char *ext = (char*)glGetString(GL_EXTENSIONS);
|
||||||
//LOG("%s\n", ext);
|
|
||||||
support.depthTexture = extSupport(ext, "_depth_texture");
|
|
||||||
support.shadowSampler = extSupport(ext, "EXT_shadow_samplers") || extSupport(ext, "GL_ARB_shadow");
|
|
||||||
support.VAO = extSupport(ext, "_vertex_array_object");
|
support.VAO = extSupport(ext, "_vertex_array_object");
|
||||||
|
support.depthTexture = extSupport(ext, "_depth_texture");
|
||||||
|
support.shadowSampler = false;//extSupport(ext, "_shadow_samplers") || extSupport(ext, "GL_ARB_shadow");
|
||||||
|
support.discardFrame = extSupport(ext, "_discard_framebuffer");
|
||||||
support.texFloatLinear = extSupport(ext, "GL_ARB_texture_float") || extSupport(ext, "_texture_float_linear");
|
support.texFloatLinear = extSupport(ext, "GL_ARB_texture_float") || extSupport(ext, "_texture_float_linear");
|
||||||
support.texFloat = support.texFloatLinear || extSupport(ext, "_texture_float");
|
support.texFloat = support.texFloatLinear || extSupport(ext, "_texture_float");
|
||||||
support.texHalfLinear = extSupport(ext, "GL_ARB_texture_float") || extSupport(ext, "_texture_half_float_linear");
|
support.texHalfLinear = extSupport(ext, "GL_ARB_texture_float") || extSupport(ext, "_texture_half_float_linear");
|
||||||
@@ -265,9 +312,10 @@ namespace Core {
|
|||||||
LOG("Version : %s\n", glGetString(GL_VERSION));
|
LOG("Version : %s\n", glGetString(GL_VERSION));
|
||||||
|
|
||||||
LOG("supports:\n");
|
LOG("supports:\n");
|
||||||
|
LOG(" vertex arrays : %s\n", support.VAO ? "true" : "false");
|
||||||
LOG(" depth texture : %s\n", support.depthTexture ? "true" : "false");
|
LOG(" depth texture : %s\n", support.depthTexture ? "true" : "false");
|
||||||
LOG(" shadow sampler : %s\n", support.shadowSampler ? "true" : "false");
|
LOG(" shadow sampler : %s\n", support.shadowSampler ? "true" : "false");
|
||||||
LOG(" vertex arrays : %s\n", support.VAO ? "true" : "false");
|
LOG(" discard frame : %s\n", support.discardFrame ? "true" : "false");
|
||||||
LOG(" float textures : float = %s, half = %s\n",
|
LOG(" float textures : float = %s, half = %s\n",
|
||||||
support.texFloat ? (support.texFloatLinear ? "linear" : "nearest") : "false",
|
support.texFloat ? (support.texFloatLinear ? "linear" : "nearest") : "false",
|
||||||
support.texHalf ? (support.texHalfLinear ? "linear" : "nearest") : "false");
|
support.texHalf ? (support.texHalfLinear ? "linear" : "nearest") : "false");
|
||||||
@@ -326,9 +374,10 @@ namespace Core {
|
|||||||
return cache.count++;
|
return cache.count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear(const vec4 &color) {
|
void clear(bool clearColor, bool clearDepth, 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);
|
if (GLbitfield mask = (clearColor ? GL_COLOR_BUFFER_BIT : 0) | (clearDepth ? GL_DEPTH_BUFFER_BIT : 0))
|
||||||
|
glClear(mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setViewport(int x, int y, int width, int height) {
|
void setViewport(int x, int y, int width, int height) {
|
||||||
@@ -352,6 +401,7 @@ namespace Core {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setBlending(BlendMode mode) {
|
void setBlending(BlendMode mode) {
|
||||||
|
mode = bmNone;
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case bmNone :
|
case bmNone :
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
@@ -389,14 +439,24 @@ namespace Core {
|
|||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setTarget(Texture *target, int face = 0) {
|
void invalidateTarget(bool color, bool depth) {
|
||||||
|
#ifdef MOBILE
|
||||||
|
if (support.discardFrame && (color || depth)) {
|
||||||
|
int count = 0;
|
||||||
|
GLenum discard[2];
|
||||||
|
if (color) discard[count++] = active.target ? GL_COLOR_ATTACHMENT0 : GL_COLOR_EXT;
|
||||||
|
if (depth) discard[count++] = active.target ? GL_DEPTH_ATTACHMENT : GL_DEPTH_EXT;
|
||||||
|
glDiscardFramebufferEXT(GL_FRAMEBUFFER, count, discard);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void setTarget(Texture *target, bool clear = false, 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);
|
||||||
setViewport(0, 0, Core::width, Core::height);
|
setViewport(0, 0, Core::width, Core::height);
|
||||||
return;
|
} else {
|
||||||
}
|
|
||||||
|
|
||||||
GLenum texTarget = GL_TEXTURE_2D;
|
GLenum texTarget = GL_TEXTURE_2D;
|
||||||
if (target->cube)
|
if (target->cube)
|
||||||
texTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
|
texTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
|
||||||
@@ -412,6 +472,11 @@ namespace Core {
|
|||||||
glColorMask(false, false, false, false);
|
glColorMask(false, false, false, false);
|
||||||
setViewport(0, 0, target->width, target->height);
|
setViewport(0, 0, target->width, target->height);
|
||||||
}
|
}
|
||||||
|
active.target = target;
|
||||||
|
|
||||||
|
if (clear)
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
void copyTarget(Texture *texture, int xOffset, int yOffset, int x, int y, int width, int height) {
|
void copyTarget(Texture *texture, int xOffset, int yOffset, int x, int y, int width, int height) {
|
||||||
texture->bind(sDiffuse);
|
texture->bind(sDiffuse);
|
||||||
|
14
src/format.h
14
src/format.h
@@ -491,7 +491,7 @@ namespace TR {
|
|||||||
} flags;
|
} flags;
|
||||||
// not exists in file
|
// not exists in file
|
||||||
uint16 align;
|
uint16 align;
|
||||||
int16 modelIndex; // index of representation in models (index + 1) or spriteSequences (-(index + 1)) arrays
|
int32 modelIndex; // index of representation in models (index + 1) or spriteSequences (-(index + 1)) arrays
|
||||||
void *controller; // Controller implementation or NULL
|
void *controller; // Controller implementation or NULL
|
||||||
|
|
||||||
bool isEnemy() {
|
bool isEnemy() {
|
||||||
@@ -842,6 +842,7 @@ namespace TR {
|
|||||||
} extra;
|
} extra;
|
||||||
|
|
||||||
Level(Stream &stream, bool demo) {
|
Level(Stream &stream, bool demo) {
|
||||||
|
int startPos = stream.pos;
|
||||||
memset(this, 0, sizeof(*this));
|
memset(this, 0, sizeof(*this));
|
||||||
cutEntity = -1;
|
cutEntity = -1;
|
||||||
Tile8 *tiles8 = NULL;
|
Tile8 *tiles8 = NULL;
|
||||||
@@ -863,14 +864,13 @@ namespace TR {
|
|||||||
|
|
||||||
if (version == VER_TR1_PSX) {
|
if (version == VER_TR1_PSX) {
|
||||||
uint32 offsetTexTiles;
|
uint32 offsetTexTiles;
|
||||||
|
|
||||||
stream.seek(8);
|
stream.seek(8);
|
||||||
stream.read(offsetTexTiles);
|
stream.read(offsetTexTiles);
|
||||||
// sound offsets
|
// sound offsets
|
||||||
uint16 numSounds;
|
uint16 numSounds;
|
||||||
stream.setPos(22);
|
stream.setPos(startPos + 22);
|
||||||
stream.read(numSounds);
|
stream.read(numSounds);
|
||||||
stream.setPos(2086 + numSounds * 512);
|
stream.setPos(startPos + 2086 + numSounds * 512);
|
||||||
soundOffsetsCount = numSounds;
|
soundOffsetsCount = numSounds;
|
||||||
soundOffsets = new uint32[soundOffsetsCount];
|
soundOffsets = new uint32[soundOffsetsCount];
|
||||||
soundSize = new uint32[soundOffsetsCount];
|
soundSize = new uint32[soundOffsetsCount];
|
||||||
@@ -882,9 +882,9 @@ namespace TR {
|
|||||||
soundDataSize += soundSize[i] = size * 8;
|
soundDataSize += soundSize[i] = size * 8;
|
||||||
}
|
}
|
||||||
// sound data
|
// sound data
|
||||||
stream.setPos(2600 + numSounds * 512);
|
stream.setPos(startPos + 2600 + numSounds * 512);
|
||||||
stream.read(soundData, soundDataSize);
|
stream.read(soundData, soundDataSize);
|
||||||
stream.setPos(offsetTexTiles + 8);
|
stream.setPos(startPos + offsetTexTiles + 8);
|
||||||
} else if (version == VER_TR1_PC) {
|
} else if (version == VER_TR1_PC) {
|
||||||
// tiles
|
// tiles
|
||||||
stream.read(tiles8, stream.read(tilesCount));
|
stream.read(tiles8, stream.read(tilesCount));
|
||||||
@@ -1580,7 +1580,7 @@ namespace TR {
|
|||||||
info.trigger = Trigger::ACTIVATE;
|
info.trigger = Trigger::ACTIVATE;
|
||||||
info.trigCmdCount = 0;
|
info.trigCmdCount = 0;
|
||||||
|
|
||||||
if (s.floor == -127)
|
if (uint8(s.floor) == TR::NO_ROOM)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Room::Sector *sBelow = &s;
|
Room::Sector *sBelow = &s;
|
||||||
|
19
src/game.h
19
src/game.h
@@ -8,28 +8,27 @@
|
|||||||
namespace Game {
|
namespace Game {
|
||||||
Level *level;
|
Level *level;
|
||||||
|
|
||||||
void startLevel(Stream &stream, const char *sndName, bool demo, bool home) {
|
void startLevel(Stream *lvl, Stream *snd, bool demo, bool home) {
|
||||||
delete level;
|
delete level;
|
||||||
level = new Level(stream, demo, home);
|
level = new Level(*lvl, demo, home);
|
||||||
|
delete lvl;
|
||||||
|
|
||||||
#ifndef __EMSCRIPTEN__
|
#ifndef __EMSCRIPTEN__
|
||||||
//Sound::play(Sound::openWAD("05_Lara's_Themes.wav"), 1, 1, 0);
|
//Sound::play(Sound::openWAD("05_Lara's_Themes.wav"), 1, 1, 0);
|
||||||
Sound::play(new Stream(sndName), vec3(0.0f), 1, 1, Sound::Flags::LOOP);
|
Sound::play(snd, vec3(0.0f), 1, 1, Sound::Flags::LOOP);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void startLevel(const char *lvlName, const char *sndName, bool demo, bool home) {
|
void init(Stream *lvl, Stream *snd) {
|
||||||
Stream stream(lvlName);
|
Core::init();
|
||||||
startLevel(stream, sndName, demo, home);
|
level = NULL;
|
||||||
|
startLevel(lvl, snd, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void init(char *lvlName = NULL, char *sndName = NULL) {
|
void init(char *lvlName = NULL, char *sndName = NULL) {
|
||||||
Core::init();
|
|
||||||
level = NULL;
|
|
||||||
|
|
||||||
if (!lvlName) lvlName = (char*)"LEVEL2.PSX";
|
if (!lvlName) lvlName = (char*)"LEVEL2.PSX";
|
||||||
if (!sndName) sndName = (char*)"05.ogg";
|
if (!sndName) sndName = (char*)"05.ogg";
|
||||||
startLevel(lvlName, sndName, false, false);
|
init(new Stream(lvlName), new Stream(sndName));
|
||||||
}
|
}
|
||||||
|
|
||||||
void free() {
|
void free() {
|
||||||
|
11
src/lara.h
11
src/lara.h
@@ -405,7 +405,7 @@ struct Lara : Character {
|
|||||||
|
|
||||||
if (level->extra.braid > -1)
|
if (level->extra.braid > -1)
|
||||||
braid = new Braid(this, vec3(-4.0f, 24.0f, -48.0f));
|
braid = new Braid(this, vec3(-4.0f, 24.0f, -48.0f));
|
||||||
|
//reset(15, vec3(70067, -256, 29104), -0.68f); // level 2 (pool)
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
//reset(14, vec3(40448, 3584, 60928), PI * 0.5f, true); // gym (pool)
|
//reset(14, vec3(40448, 3584, 60928), PI * 0.5f, true); // gym (pool)
|
||||||
|
|
||||||
@@ -414,7 +414,7 @@ struct Lara : Character {
|
|||||||
//reset(61, vec3(27221, -1024, 29205), PI * 0.5f); // level 2 (blade)
|
//reset(61, vec3(27221, -1024, 29205), PI * 0.5f); // level 2 (blade)
|
||||||
//reset(43, vec3(31400, -2560, 25200), PI); // level 2 (reach)
|
//reset(43, vec3(31400, -2560, 25200), PI); // level 2 (reach)
|
||||||
//reset(16, vec3(60907, 0, 39642), PI * 3 / 2); // level 2 (hang & climb)
|
//reset(16, vec3(60907, 0, 39642), PI * 3 / 2); // level 2 (hang & climb)
|
||||||
reset(19, vec3(60843, 1024, 30557), PI); // level 2 (block)
|
//reset(19, vec3(60843, 1024, 30557), PI); // level 2 (block)
|
||||||
//reset(7, vec3(64108, -512, 16514), -PI * 0.5f); // level 2 (bat trigger)
|
//reset(7, vec3(64108, -512, 16514), -PI * 0.5f); // level 2 (bat trigger)
|
||||||
//reset(15, vec3(70082, -512, 26935), PI * 0.5f); // level 2 (bear)
|
//reset(15, vec3(70082, -512, 26935), PI * 0.5f); // level 2 (bear)
|
||||||
//reset(63, vec3(31390, -2048, 33472), 0.0f); // level 2 (trap floor)
|
//reset(63, vec3(31390, -2048, 33472), 0.0f); // level 2 (trap floor)
|
||||||
@@ -2018,8 +2018,8 @@ struct Lara : Character {
|
|||||||
Core::setBlending(bmNone);
|
Core::setBlending(bmNone);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void render(Frustum *frustum, MeshBuilder *mesh) {
|
virtual void render(Frustum *frustum, MeshBuilder *mesh, Shader::Type type, bool caustics) {
|
||||||
Controller::render(frustum, mesh);
|
Controller::render(frustum, mesh, type, caustics);
|
||||||
chestOffset = animation.getJoints(getMatrix(), 7).pos; // TODO: move to update func
|
chestOffset = animation.getJoints(getMatrix(), 7).pos; // TODO: move to update func
|
||||||
|
|
||||||
if (braid)
|
if (braid)
|
||||||
@@ -2027,10 +2027,9 @@ struct Lara : Character {
|
|||||||
|
|
||||||
if (wpnCurrent != Weapon::SHOTGUN && Core::pass != Core::passShadow && (arms[0].shotTimer < MUZZLE_FLASH_TIME || arms[1].shotTimer < MUZZLE_FLASH_TIME)) {
|
if (wpnCurrent != Weapon::SHOTGUN && Core::pass != Core::passShadow && (arms[0].shotTimer < MUZZLE_FLASH_TIME || arms[1].shotTimer < MUZZLE_FLASH_TIME)) {
|
||||||
mat4 matrix = getMatrix();
|
mat4 matrix = getMatrix();
|
||||||
Core::active.shader->setParam(uType, Shader::FLASH);
|
game->setShader(Core::pass, Shader::FLASH, false);
|
||||||
renderMuzzleFlash(mesh, animation.getJoints(matrix, 10, true), vec3(-10, -50, 150), arms[0].shotTimer);
|
renderMuzzleFlash(mesh, animation.getJoints(matrix, 10, true), vec3(-10, -50, 150), arms[0].shotTimer);
|
||||||
renderMuzzleFlash(mesh, animation.getJoints(matrix, 13, true), vec3( 10, -50, 150), arms[1].shotTimer);
|
renderMuzzleFlash(mesh, animation.getJoints(matrix, 13, true), vec3( 10, -50, 150), arms[1].shotTimer);
|
||||||
Core::active.shader->setParam(uType, Shader::ENTITY);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
242
src/level.h
242
src/level.h
@@ -33,10 +33,7 @@ const char GUI[] =
|
|||||||
#define WATER_FOG_DIST (8 * 1024)
|
#define WATER_FOG_DIST (8 * 1024)
|
||||||
|
|
||||||
struct Level : IGame {
|
struct Level : IGame {
|
||||||
enum { shCompose, shShadow, shAmbient, shFilter, shWater, shGUI, shMAX };
|
|
||||||
|
|
||||||
TR::Level level;
|
TR::Level level;
|
||||||
Shader *shaders[shMAX];
|
|
||||||
Texture *atlas;
|
Texture *atlas;
|
||||||
Texture *cube;
|
Texture *cube;
|
||||||
MeshBuilder *mesh;
|
MeshBuilder *mesh;
|
||||||
@@ -54,6 +51,70 @@ struct Level : IGame {
|
|||||||
float clipHeight;
|
float clipHeight;
|
||||||
} params;
|
} params;
|
||||||
|
|
||||||
|
struct ShaderCache {
|
||||||
|
Shader *shaders[int(Core::passMAX) * Shader::MAX * 2];
|
||||||
|
|
||||||
|
ShaderCache(int animTexRangesCount, int animTexOffsetsCount) {
|
||||||
|
memset(shaders, 0, sizeof(shaders));
|
||||||
|
char def[255], ext[255];
|
||||||
|
|
||||||
|
ext[0] = 0;
|
||||||
|
if (Core::support.shadowSampler) {
|
||||||
|
#ifdef MOBILE
|
||||||
|
strcat(ext, "#extension GL_EXT_shadow_samplers : require\n");
|
||||||
|
#endif
|
||||||
|
strcat(ext, "#define SHADOW_SAMPLER\n");
|
||||||
|
} else
|
||||||
|
if (Core::support.depthTexture)
|
||||||
|
strcat(ext, "#define SHADOW_DEPTH\n");
|
||||||
|
else
|
||||||
|
strcat(ext, "#define SHADOW_COLOR\n");
|
||||||
|
|
||||||
|
{
|
||||||
|
const char *passNames[] = { "COMPOSE", "SHADOW", "AMBIENT" };
|
||||||
|
const char *typeNames[] = { "SPRITE", "FLASH", "ROOM", "ENTITY", "MIRROR" };
|
||||||
|
|
||||||
|
for (int pass = Core::passCompose; pass <= Core::passAmbient; pass++)
|
||||||
|
for (int caustics = 0; caustics < 2; caustics++)
|
||||||
|
for (int type = Shader::SPRITE; type <= Shader::MIRROR; type++) {
|
||||||
|
sprintf(def, "%s#define PASS_%s\n#define TYPE_%s\n#define MAX_LIGHTS %d\n#define MAX_RANGES %d\n#define MAX_OFFSETS %d\n#define FOG_DIST (1.0/%d.0)\n#define WATER_FOG_DIST (1.0/%d.0)\n", ext, passNames[pass], typeNames[type], MAX_LIGHTS, animTexRangesCount, animTexOffsetsCount, FOG_DIST, WATER_FOG_DIST);
|
||||||
|
if (caustics)
|
||||||
|
strcat(def, "#define CAUSTICS\n");
|
||||||
|
shaders[getIndex(Core::Pass(pass), Shader::Type(type), caustics == 1)] = new Shader(SHADER, def);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const char *typeNames[] = { "DROP", "STEP", "CAUSTICS", "MASK", "COMPOSE" };
|
||||||
|
|
||||||
|
for (int type = Shader::WATER_DROP; type <= Shader::WATER_COMPOSE; type++) {
|
||||||
|
sprintf(def, "%s#define WATER_%s\n#define WATER_FOG_DIST (1.0/%d.0)\n", ext, typeNames[type], WATER_FOG_DIST);
|
||||||
|
shaders[getIndex(Core::passWater, Shader::Type(type), false)] = new Shader(WATER, def);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
shaders[getIndex(Core::passFilter, Shader::FILTER_DOWNSAMPLE, false)] = new Shader(FILTER, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
~ShaderCache() {
|
||||||
|
for (int i = 0; i < sizeof(shaders) / sizeof(shaders[0]); i++)
|
||||||
|
delete shaders[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
int getIndex(Core::Pass pass, Shader::Type type, bool caustics) {
|
||||||
|
int index = int(pass) * Shader::MAX * 2 + type * 2 + int(caustics);
|
||||||
|
ASSERT(index < sizeof(shaders) / sizeof(shaders[0]));
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bind(Core::Pass pass, Shader::Type type, bool caustics = false) {
|
||||||
|
Core::pass = pass;
|
||||||
|
int index = getIndex(pass, type, caustics);
|
||||||
|
ASSERT(shaders[index] != NULL);
|
||||||
|
shaders[index]->bind();
|
||||||
|
}
|
||||||
|
|
||||||
|
} *shaderCache;
|
||||||
|
|
||||||
struct AmbientCache {
|
struct AmbientCache {
|
||||||
Level *level;
|
Level *level;
|
||||||
|
|
||||||
@@ -125,8 +186,7 @@ struct Level : IGame {
|
|||||||
// second pass - downsample it
|
// second pass - downsample it
|
||||||
Core::setDepthTest(false);
|
Core::setDepthTest(false);
|
||||||
|
|
||||||
level->setPassShader(Core::passFilter);
|
level->shaderCache->bind(Core::passFilter, Shader::FILTER_DOWNSAMPLE, false);
|
||||||
Core::active.shader->setParam(uType, Shader::FILTER_DOWNSAMPLE);
|
|
||||||
|
|
||||||
for (int i = 1; i < 4; i++) {
|
for (int i = 1; i < 4; i++) {
|
||||||
int size = 64 >> (i << 1);
|
int size = 64 >> (i << 1);
|
||||||
@@ -136,7 +196,7 @@ struct Level : IGame {
|
|||||||
for (int j = 0; j < 6; j++) {
|
for (int j = 0; j < 6; j++) {
|
||||||
Texture *src = textures[j * 4 + i - 1];
|
Texture *src = textures[j * 4 + i - 1];
|
||||||
Texture *dst = textures[j * 4 + i];
|
Texture *dst = textures[j * 4 + i];
|
||||||
Core::setTarget(dst);
|
Core::setTarget(dst, true);
|
||||||
src->bind(sDiffuse);
|
src->bind(sDiffuse);
|
||||||
level->mesh->renderQuad();
|
level->mesh->renderQuad();
|
||||||
}
|
}
|
||||||
@@ -151,7 +211,6 @@ struct Level : IGame {
|
|||||||
colors[j] = vec3(color.r / 255.0f, color.g / 255.0f, color.b / 255.0f);
|
colors[j] = vec3(color.r / 255.0f, color.g / 255.0f, color.b / 255.0f);
|
||||||
colors[j] *= colors[j]; // to "linear" space
|
colors[j] *= colors[j]; // to "linear" space
|
||||||
}
|
}
|
||||||
Core::setTarget(NULL);
|
|
||||||
|
|
||||||
Core::setDepthTest(true);
|
Core::setDepthTest(true);
|
||||||
}
|
}
|
||||||
@@ -273,9 +332,8 @@ struct Level : IGame {
|
|||||||
caustics = new Texture(512, 512, Texture::RGB16, false);
|
caustics = new Texture(512, 512, Texture::RGB16, false);
|
||||||
blank = false;
|
blank = false;
|
||||||
|
|
||||||
Core::setTarget(data[0]);
|
Core::setTarget(data[0], true);
|
||||||
Core::clear(vec4(0.0f));
|
Core::invalidateTarget(false, true);
|
||||||
Core::setTarget(NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void free() {
|
void free() {
|
||||||
@@ -399,9 +457,9 @@ struct Level : IGame {
|
|||||||
void drop(Item &item) {
|
void drop(Item &item) {
|
||||||
if (!dropCount) return;
|
if (!dropCount) return;
|
||||||
|
|
||||||
|
level->setShader(Core::passWater, Shader::WATER_DROP, false);
|
||||||
vec3 rPosScale[2] = { vec3(0.0f), vec3(1.0f) };
|
vec3 rPosScale[2] = { vec3(0.0f), vec3(1.0f) };
|
||||||
Core::active.shader->setParam(uPosScale, rPosScale[0], 2);
|
Core::active.shader->setParam(uPosScale, rPosScale[0], 2);
|
||||||
Core::active.shader->setParam(uType, Shader::WATER_DROP);
|
|
||||||
|
|
||||||
for (int i = 0; i < dropCount; i++) {
|
for (int i = 0; i < dropCount; i++) {
|
||||||
Drop &drop = drops[i];
|
Drop &drop = drops[i];
|
||||||
@@ -412,9 +470,10 @@ struct Level : IGame {
|
|||||||
Core::active.shader->setParam(uParam, vec4(p.x, p.z, drop.radius * DETAIL, drop.strength));
|
Core::active.shader->setParam(uParam, vec4(p.x, p.z, drop.radius * DETAIL, drop.strength));
|
||||||
|
|
||||||
item.data[0]->bind(sDiffuse);
|
item.data[0]->bind(sDiffuse);
|
||||||
Core::setTarget(item.data[1]);
|
Core::setTarget(item.data[1], true);
|
||||||
Core::setViewport(0, 0, int(item.size.x * DETAIL * 2.0f + 0.5f), int(item.size.z * DETAIL * 2.0f + 0.5f));
|
Core::setViewport(0, 0, int(item.size.x * DETAIL * 2.0f + 0.5f), int(item.size.z * DETAIL * 2.0f + 0.5f));
|
||||||
level->mesh->renderQuad();
|
level->mesh->renderQuad();
|
||||||
|
Core::invalidateTarget(false, true);
|
||||||
swap(item.data[0], item.data[1]);
|
swap(item.data[0], item.data[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -422,23 +481,24 @@ struct Level : IGame {
|
|||||||
void step(Item &item) {
|
void step(Item &item) {
|
||||||
if (item.timer < SIMULATE_TIMESTEP) return;
|
if (item.timer < SIMULATE_TIMESTEP) return;
|
||||||
|
|
||||||
Core::active.shader->setParam(uType, Shader::WATER_STEP);
|
level->setShader(Core::passWater, Shader::WATER_STEP, false);
|
||||||
Core::active.shader->setParam(uParam, vec4(0.995f, 1.0f, 0, 0));
|
Core::active.shader->setParam(uParam, vec4(0.995f, 1.0f, 0, 0));
|
||||||
|
|
||||||
while (item.timer >= SIMULATE_TIMESTEP) {
|
while (item.timer >= SIMULATE_TIMESTEP) {
|
||||||
// water step
|
// water step
|
||||||
item.data[0]->bind(sDiffuse);
|
item.data[0]->bind(sDiffuse);
|
||||||
Core::setTarget(item.data[1]);
|
Core::setTarget(item.data[1], 0, true);
|
||||||
Core::setViewport(0, 0, int(item.size.x * DETAIL * 2.0f + 0.5f), int(item.size.z * DETAIL * 2.0f + 0.5f));
|
Core::setViewport(0, 0, int(item.size.x * DETAIL * 2.0f + 0.5f), int(item.size.z * DETAIL * 2.0f + 0.5f));
|
||||||
level->mesh->renderQuad();
|
level->mesh->renderQuad();
|
||||||
|
Core::invalidateTarget(false, true);
|
||||||
swap(item.data[0], item.data[1]);
|
swap(item.data[0], item.data[1]);
|
||||||
item.timer -= SIMULATE_TIMESTEP;
|
item.timer -= SIMULATE_TIMESTEP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// calc caustics
|
// calc caustics
|
||||||
|
level->setShader(Core::passWater, Shader::WATER_CAUSTICS, false);
|
||||||
vec3 rPosScale[2] = { vec3(0.0f), vec3(1.0f / PLANE_DETAIL) };
|
vec3 rPosScale[2] = { vec3(0.0f), vec3(1.0f / PLANE_DETAIL) };
|
||||||
Core::active.shader->setParam(uType, Shader::WATER_CAUSTICS);
|
|
||||||
Core::active.shader->setParam(uPosScale, rPosScale[0], 2);
|
Core::active.shader->setParam(uPosScale, rPosScale[0], 2);
|
||||||
|
|
||||||
float sx = item.size.x * DETAIL / (item.data[0]->width / 2);
|
float sx = item.size.x * DETAIL / (item.data[0]->width / 2);
|
||||||
@@ -448,19 +508,19 @@ struct Level : IGame {
|
|||||||
|
|
||||||
Core::whiteTex->bind(sReflect);
|
Core::whiteTex->bind(sReflect);
|
||||||
item.data[0]->bind(sNormal);
|
item.data[0]->bind(sNormal);
|
||||||
Core::setTarget(item.caustics);
|
Core::setTarget(item.caustics, true);
|
||||||
level->mesh->renderPlane();
|
level->mesh->renderPlane();
|
||||||
|
Core::invalidateTarget(false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void render() {
|
void render() {
|
||||||
if (!visible) return;
|
if (!visible) return;
|
||||||
|
|
||||||
// mask underwater geometry by zero alpha
|
// mask underwater geometry by zero alpha
|
||||||
level->setPassShader(Core::passWater);
|
|
||||||
level->atlas->bind(sNormal);
|
level->atlas->bind(sNormal);
|
||||||
level->atlas->bind(sReflect);
|
level->atlas->bind(sReflect);
|
||||||
|
|
||||||
Core::active.shader->setParam(uType, Shader::WATER_MASK);
|
level->setShader(Core::passWater, Shader::WATER_MASK, false);
|
||||||
Core::active.shader->setParam(uTexParam, vec4(1.0f));
|
Core::active.shader->setParam(uTexParam, vec4(1.0f));
|
||||||
Core::setBlending(bmNone);
|
Core::setBlending(bmNone);
|
||||||
Core::setCulling(cfNone);
|
Core::setCulling(cfNone);
|
||||||
@@ -497,7 +557,7 @@ struct Level : IGame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// render mirror reflection
|
// render mirror reflection
|
||||||
Core::setTarget(reflect);
|
Core::setTarget(reflect, true);
|
||||||
vec3 p = item.pos;
|
vec3 p = item.pos;
|
||||||
vec3 n = vec3(0, 1, 0);
|
vec3 n = vec3(0, 1, 0);
|
||||||
|
|
||||||
@@ -511,6 +571,7 @@ struct Level : IGame {
|
|||||||
level->params.clipSign = underwater ? -1.0f : 1.0f;
|
level->params.clipSign = underwater ? -1.0f : 1.0f;
|
||||||
level->params.clipHeight = item.pos.y * level->params.clipSign;
|
level->params.clipHeight = item.pos.y * level->params.clipSign;
|
||||||
level->renderCompose(underwater ? item.from : item.to);
|
level->renderCompose(underwater ? item.from : item.to);
|
||||||
|
Core::invalidateTarget(false, true);
|
||||||
level->params.clipHeight = 1000000.0f;
|
level->params.clipHeight = 1000000.0f;
|
||||||
level->params.clipSign = 1.0f;
|
level->params.clipSign = 1.0f;
|
||||||
|
|
||||||
@@ -518,8 +579,6 @@ struct Level : IGame {
|
|||||||
level->camera->setup(true);
|
level->camera->setup(true);
|
||||||
|
|
||||||
// simulate water
|
// simulate water
|
||||||
level->setPassShader(Core::passWater);
|
|
||||||
|
|
||||||
Core::setDepthTest(false);
|
Core::setDepthTest(false);
|
||||||
item.mask->bind(sMask);
|
item.mask->bind(sMask);
|
||||||
|
|
||||||
@@ -542,7 +601,7 @@ struct Level : IGame {
|
|||||||
Core::lightColor[0] = vec4(lum, lum, lum, float(light.radius) * float(light.radius));
|
Core::lightColor[0] = vec4(lum, lum, lum, float(light.radius) * float(light.radius));
|
||||||
}
|
}
|
||||||
|
|
||||||
Core::active.shader->setParam(uType, Shader::WATER_COMPOSE);
|
level->setShader(Core::passWater, Shader::WATER_COMPOSE, false);
|
||||||
Core::active.shader->setParam(uViewProj, Core::mViewProj);
|
Core::active.shader->setParam(uViewProj, Core::mViewProj);
|
||||||
Core::active.shader->setParam(uPosScale, item.pos, 2);
|
Core::active.shader->setParam(uPosScale, item.pos, 2);
|
||||||
Core::active.shader->setParam(uViewPos, Core::viewPos);
|
Core::active.shader->setParam(uViewPos, Core::viewPos);
|
||||||
@@ -627,6 +686,9 @@ struct Level : IGame {
|
|||||||
waterCache->addDrop(pos, radius, strength);
|
waterCache->addDrop(pos, radius, strength);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void setShader(Core::Pass pass, Shader::Type type, bool caustics) {
|
||||||
|
shaderCache->bind(pass, type, caustics);
|
||||||
|
}
|
||||||
|
|
||||||
Level(Stream &stream, bool demo, bool home) : level(stream, demo), lara(NULL), waterColor(0.6f, 0.9f, 0.9f) {
|
Level(Stream &stream, bool demo, bool home) : level(stream, demo), lara(NULL), waterColor(0.6f, 0.9f, 0.9f) {
|
||||||
params.time = 0.0f;
|
params.time = 0.0f;
|
||||||
@@ -637,7 +699,7 @@ struct Level : IGame {
|
|||||||
mesh = new MeshBuilder(level);
|
mesh = new MeshBuilder(level);
|
||||||
|
|
||||||
initTextures();
|
initTextures();
|
||||||
initShaders();
|
shaderCache = new ShaderCache(mesh->animTexRangesCount, mesh->animTexOffsetsCount);
|
||||||
initOverrides();
|
initOverrides();
|
||||||
|
|
||||||
for (int i = 0; i < level.entitiesBaseCount; i++) {
|
for (int i = 0; i < level.entitiesBaseCount; i++) {
|
||||||
@@ -756,8 +818,7 @@ struct Level : IGame {
|
|||||||
for (int i = 0; i < level.entitiesCount; i++)
|
for (int i = 0; i < level.entitiesCount; i++)
|
||||||
delete (Controller*)level.entities[i].controller;
|
delete (Controller*)level.entities[i].controller;
|
||||||
|
|
||||||
for (int i = 0; i < shMAX; i++)
|
delete shaderCache;
|
||||||
delete shaders[i];
|
|
||||||
|
|
||||||
delete shadow;
|
delete shadow;
|
||||||
delete ambientCache;
|
delete ambientCache;
|
||||||
@@ -815,33 +876,6 @@ struct Level : IGame {
|
|||||||
level.tiles = NULL;
|
level.tiles = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void initShaders() {
|
|
||||||
char def[255], ext[255];
|
|
||||||
|
|
||||||
ext[0] = 0;
|
|
||||||
if (Core::support.shadowSampler) {
|
|
||||||
#ifdef MOBILE
|
|
||||||
strcat(ext, "#extension GL_EXT_shadow_samplers : require\n");
|
|
||||||
#endif
|
|
||||||
strcat(ext, "#define SHADOW_SAMPLER\n");
|
|
||||||
} else
|
|
||||||
if (Core::support.depthTexture)
|
|
||||||
strcat(ext, "#define SHADOW_DEPTH\n");
|
|
||||||
else
|
|
||||||
strcat(ext, "#define SHADOW_COLOR\n");
|
|
||||||
|
|
||||||
sprintf(def, "%s#define PASS_COMPOSE\n#define MAX_LIGHTS %d\n#define MAX_RANGES %d\n#define MAX_OFFSETS %d\n#define FOG_DIST (1.0/%d.0)\n#define WATER_FOG_DIST (1.0/%d.0)\n", ext, MAX_LIGHTS, mesh->animTexRangesCount, mesh->animTexOffsetsCount, FOG_DIST, WATER_FOG_DIST);
|
|
||||||
shaders[shCompose] = new Shader(SHADER, def);
|
|
||||||
sprintf(def, "%s#define PASS_SHADOW\n", ext);
|
|
||||||
shaders[shShadow] = new Shader(SHADER, def);
|
|
||||||
sprintf(def, "%s#define PASS_AMBIENT\n", ext);
|
|
||||||
shaders[shAmbient] = new Shader(SHADER, def);
|
|
||||||
shaders[shFilter] = new Shader(FILTER, "");
|
|
||||||
sprintf(def, "#define WATER_FOG_DIST (1.0/%d.0)\n", WATER_FOG_DIST);
|
|
||||||
shaders[shWater] = new Shader(WATER, def);
|
|
||||||
shaders[shGUI] = new Shader(GUI, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
void initOverrides() {
|
void initOverrides() {
|
||||||
/*
|
/*
|
||||||
for (int i = 0; i < level.entitiesCount; i++) {
|
for (int i = 0; i < level.entitiesCount; i++) {
|
||||||
@@ -954,15 +988,18 @@ struct Level : IGame {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void setRoomParams(int roomIndex, float intensity) {
|
void setRoomParams(int roomIndex, float intensity, Shader::Type type) {
|
||||||
if (Core::pass == Core::passShadow)
|
if (Core::pass == Core::passShadow) {
|
||||||
|
setShader(Core::pass, type, false);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
TR::Room &room = level.rooms[roomIndex];
|
TR::Room &room = level.rooms[roomIndex];
|
||||||
|
|
||||||
|
setShader(Core::pass, type, room.flags.water);
|
||||||
|
|
||||||
if (room.flags.water) {
|
if (room.flags.water) {
|
||||||
Core::color = vec4(waterColor, intensity);
|
Core::color = vec4(waterColor, intensity);
|
||||||
Core::active.shader->setParam(uCaustics, 1);
|
|
||||||
/*
|
/*
|
||||||
// trace to water surface room
|
// trace to water surface room
|
||||||
int wrIndex = roomIndex;
|
int wrIndex = roomIndex;
|
||||||
@@ -972,10 +1009,9 @@ struct Level : IGame {
|
|||||||
int sx = room.xSectors
|
int sx = room.xSectors
|
||||||
*/
|
*/
|
||||||
waterCache->bindCaustics(roomIndex);
|
waterCache->bindCaustics(roomIndex);
|
||||||
} else {
|
} else
|
||||||
Core::color = vec4(1.0f, 1.0f, 1.0f, intensity);
|
Core::color = vec4(1.0f, 1.0f, 1.0f, intensity);
|
||||||
Core::active.shader->setParam(uCaustics, 0);
|
|
||||||
}
|
|
||||||
Core::active.shader->setParam(uColor, Core::color);
|
Core::active.shader->setParam(uColor, Core::color);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -994,13 +1030,13 @@ struct Level : IGame {
|
|||||||
room.flags.rendered = true;
|
room.flags.rendered = true;
|
||||||
|
|
||||||
if (Core::pass != Core::passShadow) {
|
if (Core::pass != Core::passShadow) {
|
||||||
setRoomParams(roomIndex, intensityf(room.ambient));
|
setRoomParams(roomIndex, intensityf(room.ambient), Shader::ROOM);
|
||||||
|
Shader *sh = Core::active.shader;
|
||||||
|
sh->setParam(uLightColor, Core::lightColor[0], MAX_LIGHTS);
|
||||||
|
sh->setParam(uLightPos, Core::lightPos[0], MAX_LIGHTS);
|
||||||
|
|
||||||
Basis qTemp = Core::basis;
|
Basis qTemp = Core::basis;
|
||||||
Core::basis.translate(offset);
|
Core::basis.translate(offset);
|
||||||
|
|
||||||
Shader *sh = Core::active.shader;
|
|
||||||
sh->setParam(uType, Shader::ROOM);
|
|
||||||
sh->setParam(uBasis, Core::basis);
|
sh->setParam(uBasis, Core::basis);
|
||||||
|
|
||||||
// render room geometry
|
// render room geometry
|
||||||
@@ -1008,9 +1044,11 @@ struct Level : IGame {
|
|||||||
|
|
||||||
// render room sprites
|
// render room sprites
|
||||||
if (mesh->hasRoomSprites(roomIndex)) {
|
if (mesh->hasRoomSprites(roomIndex)) {
|
||||||
Core::color.w = 1.0;
|
setRoomParams(roomIndex, 1.0, Shader::SPRITE);
|
||||||
sh->setParam(uType, Shader::SPRITE);
|
sh = Core::active.shader;
|
||||||
sh->setParam(uColor, Core::color);
|
sh->setParam(uLightColor, Core::lightColor[0], MAX_LIGHTS);
|
||||||
|
sh->setParam(uLightPos, Core::lightPos[0], MAX_LIGHTS);
|
||||||
|
sh->setParam(uBasis, Core::basis);
|
||||||
mesh->renderRoomSprites(roomIndex);
|
mesh->renderRoomSprites(roomIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1108,7 +1146,11 @@ struct Level : IGame {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
int16 lum = entity.intensity == -1 ? room.ambient : entity.intensity;
|
int16 lum = entity.intensity == -1 ? room.ambient : entity.intensity;
|
||||||
setRoomParams(entity.room, isModel ? controller->specular : intensityf(lum));
|
|
||||||
|
Shader::Type type = isModel ? Shader::ENTITY : Shader::SPRITE;
|
||||||
|
if (entity.type == TR::Entity::CRYSTAL)
|
||||||
|
type = Shader::MIRROR;
|
||||||
|
setRoomParams(entity.room, isModel ? controller->specular : intensityf(lum), type);
|
||||||
|
|
||||||
if (isModel) { // model
|
if (isModel) { // model
|
||||||
vec3 pos = controller->getPos();
|
vec3 pos = controller->getPos();
|
||||||
@@ -1119,18 +1161,18 @@ struct Level : IGame {
|
|||||||
memcpy(controller->ambient, cube.colors, sizeof(cube.colors)); // store last calculated ambient into controller
|
memcpy(controller->ambient, cube.colors, sizeof(cube.colors)); // store last calculated ambient into controller
|
||||||
}
|
}
|
||||||
getLight(pos, entity.room);
|
getLight(pos, entity.room);
|
||||||
Core::active.shader->setParam(uType, Shader::ENTITY);
|
|
||||||
Core::active.shader->setParam(uAmbient, controller->ambient[0], 6);
|
Core::active.shader->setParam(uAmbient, controller->ambient[0], 6);
|
||||||
} else { // sprite
|
} else { // sprite
|
||||||
Core::active.shader->setParam(uType, Shader::SPRITE);
|
|
||||||
Core::lightPos[0] = vec3(0);
|
Core::lightPos[0] = vec3(0);
|
||||||
Core::lightColor[0] = vec4(0, 0, 0, 1);
|
Core::lightColor[0] = vec4(0, 0, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Core::active.shader->setParam(uViewProj, Core::mViewProj);
|
||||||
|
Core::active.shader->setParam(uLightProj, Core::mLightProj);
|
||||||
Core::active.shader->setParam(uLightPos, Core::lightPos[0], MAX_LIGHTS);
|
Core::active.shader->setParam(uLightPos, Core::lightPos[0], MAX_LIGHTS);
|
||||||
Core::active.shader->setParam(uLightColor, Core::lightColor[0], MAX_LIGHTS);
|
Core::active.shader->setParam(uLightColor, Core::lightColor[0], MAX_LIGHTS);
|
||||||
|
|
||||||
controller->render(camera->frustum, mesh);
|
controller->render(camera->frustum, mesh, type, room.flags.water);
|
||||||
}
|
}
|
||||||
|
|
||||||
void update() {
|
void update() {
|
||||||
@@ -1155,6 +1197,9 @@ struct Level : IGame {
|
|||||||
waterCache->update();
|
waterCache->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
PROFILE_MARKER("SETUP");
|
PROFILE_MARKER("SETUP");
|
||||||
|
|
||||||
@@ -1168,19 +1213,20 @@ struct Level : IGame {
|
|||||||
|
|
||||||
if (!Core::support.VAO)
|
if (!Core::support.VAO)
|
||||||
mesh->bind();
|
mesh->bind();
|
||||||
|
//Core::mViewProj = Core::mLightProj;
|
||||||
// set frame constants for all shaders
|
// set frame constants for all shaders
|
||||||
Shader *sh = Core::active.shader;
|
for (int i = 0; i < sizeof(shaderCache->shaders) / sizeof(shaderCache->shaders[0]); i++) {
|
||||||
|
Shader *sh = shaderCache->shaders[i];
|
||||||
|
if (!sh) continue;
|
||||||
sh->bind();
|
sh->bind();
|
||||||
sh->setParam(uViewProj, Core::mViewProj);
|
sh->setParam(uViewProj, Core::mViewProj);
|
||||||
sh->setParam(uLightProj, Core::mLightProj);
|
sh->setParam(uLightProj, Core::mLightProj);
|
||||||
sh->setParam(uViewInv, Core::mViewInv);
|
sh->setParam(uViewInv, Core::mViewInv);
|
||||||
sh->setParam(uViewPos, Core::viewPos);
|
sh->setParam(uViewPos, Core::viewPos);
|
||||||
sh->setParam(uParam, *((vec4*)¶ms));
|
sh->setParam(uParam, *((vec4*)¶ms));
|
||||||
sh->setParam(uLightsCount, 3);
|
|
||||||
sh->setParam(uAnimTexRanges, mesh->animTexRanges[0], mesh->animTexRangesCount);
|
sh->setParam(uAnimTexRanges, mesh->animTexRanges[0], mesh->animTexRangesCount);
|
||||||
sh->setParam(uAnimTexOffsets, mesh->animTexOffsets[0], mesh->animTexOffsetsCount);
|
sh->setParam(uAnimTexOffsets, mesh->animTexOffsets[0], mesh->animTexOffsetsCount);
|
||||||
|
}
|
||||||
Core::basis.identity();
|
Core::basis.identity();
|
||||||
|
|
||||||
// clear visibility flag for rooms
|
// clear visibility flag for rooms
|
||||||
@@ -1196,8 +1242,6 @@ struct Level : IGame {
|
|||||||
PROFILE_MARKER("ROOMS");
|
PROFILE_MARKER("ROOMS");
|
||||||
|
|
||||||
getLight(lara->pos, lara->getRoomIndex());
|
getLight(lara->pos, lara->getRoomIndex());
|
||||||
Core::active.shader->setParam(uLightColor, Core::lightColor[0], MAX_LIGHTS);
|
|
||||||
Core::active.shader->setParam(uLightPos, Core::lightPos[0], MAX_LIGHTS);
|
|
||||||
|
|
||||||
#ifdef LEVEL_EDITOR
|
#ifdef LEVEL_EDITOR
|
||||||
for (int i = 0; i < level.roomsCount; i++)
|
for (int i = 0; i < level.roomsCount; i++)
|
||||||
@@ -1264,62 +1308,51 @@ struct Level : IGame {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
case Core::passFilter : sh = shaders[shFilter]; break;
|
|
||||||
case Core::passWater : sh = shaders[shWater]; break;
|
|
||||||
}
|
|
||||||
ASSERT(sh);
|
|
||||||
sh->bind();
|
|
||||||
}
|
|
||||||
|
|
||||||
void renderEnvironment(int roomIndex, const vec3 &pos, Texture **targets, int stride = 0) {
|
void renderEnvironment(int roomIndex, const vec3 &pos, Texture **targets, int stride = 0) {
|
||||||
PROFILE_MARKER("ENVIRONMENT");
|
PROFILE_MARKER("ENVIRONMENT");
|
||||||
// first pass render level into cube faces
|
// first pass render level into cube faces
|
||||||
for (int i = 0; i < 6; i++) {
|
for (int i = 0; i < 6; i++) {
|
||||||
setupCubeCamera(pos, i);
|
setupCubeCamera(pos, i);
|
||||||
setPassShader(Core::passAmbient);
|
Core::pass = Core::passAmbient;
|
||||||
Texture *target = targets[0]->cube ? targets[0] : targets[i * stride];
|
Texture *target = targets[0]->cube ? targets[0] : targets[i * stride];
|
||||||
Core::setTarget(target, i);
|
Core::setTarget(target, true, i);
|
||||||
Core::clear(vec4(0, 0, 0, 1));
|
|
||||||
renderScene(roomIndex);
|
renderScene(roomIndex);
|
||||||
|
Core::invalidateTarget(false, true);
|
||||||
}
|
}
|
||||||
Core::setTarget(NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderShadows(int roomIndex) {
|
void renderShadows(int roomIndex) {
|
||||||
PROFILE_MARKER("PASS_SHADOW");
|
PROFILE_MARKER("PASS_SHADOW");
|
||||||
|
Core::pass = Core::passShadow;
|
||||||
if (!setupLightCamera()) return;
|
if (!setupLightCamera()) return;
|
||||||
shadow->unbind(sShadow);
|
shadow->unbind(sShadow);
|
||||||
setPassShader(Core::passShadow);
|
|
||||||
Core::setBlending(bmNone);
|
Core::setBlending(bmNone);
|
||||||
Core::setTarget(shadow);
|
bool colorShadow = shadow->format == Texture::Format::RGBA ? true : false;
|
||||||
Core::clear(vec4(1.0));
|
if (colorShadow)
|
||||||
|
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
|
||||||
|
Core::setTarget(shadow, true);
|
||||||
Core::setCulling(cfBack);
|
Core::setCulling(cfBack);
|
||||||
renderScene(roomIndex);
|
renderScene(roomIndex);
|
||||||
|
Core::invalidateTarget(!colorShadow, colorShadow);
|
||||||
Core::setCulling(cfFront);
|
Core::setCulling(cfFront);
|
||||||
Core::setTarget(NULL);
|
if (colorShadow)
|
||||||
|
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderCompose(int roomIndex) {
|
void renderCompose(int roomIndex) {
|
||||||
PROFILE_MARKER("PASS_COMPOSE");
|
PROFILE_MARKER("PASS_COMPOSE");
|
||||||
setPassShader(Core::passCompose);
|
Core::pass = Core::passCompose;
|
||||||
|
|
||||||
Core::setBlending(bmAlpha);
|
Core::setBlending(bmAlpha);
|
||||||
Core::setDepthTest(true);
|
Core::setDepthTest(true);
|
||||||
Core::setDepthWrite(true);
|
Core::setDepthWrite(true);
|
||||||
Core::clear(vec4(0.0f, 0.0f, 0.0f, 1.0f));
|
|
||||||
shadow->bind(sShadow);
|
shadow->bind(sShadow);
|
||||||
renderScene(roomIndex);
|
renderScene(roomIndex);
|
||||||
Core::setBlending(bmNone);
|
Core::setBlending(bmNone);
|
||||||
}
|
}
|
||||||
|
|
||||||
void render() {
|
void render() {
|
||||||
|
Core::invalidateTarget(true, true);
|
||||||
params.clipHeight = 1000000.0f;
|
params.clipHeight = 1000000.0f;
|
||||||
params.clipSign = 1.0f;
|
params.clipSign = 1.0f;
|
||||||
params.waterHeight = params.clipHeight;
|
params.waterHeight = params.clipHeight;
|
||||||
@@ -1329,6 +1362,7 @@ struct Level : IGame {
|
|||||||
waterCache->reset();
|
waterCache->reset();
|
||||||
|
|
||||||
renderShadows(lara->getRoomIndex());
|
renderShadows(lara->getRoomIndex());
|
||||||
|
Core::setTarget(NULL, true);
|
||||||
Core::setViewport(0, 0, Core::width, Core::height);
|
Core::setViewport(0, 0, Core::width, Core::height);
|
||||||
|
|
||||||
waterCache->checkVisibility = true;
|
waterCache->checkVisibility = true;
|
||||||
@@ -1410,7 +1444,6 @@ struct Level : IGame {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
@@ -1419,10 +1452,7 @@ struct Level : IGame {
|
|||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
glOrtho(0, Core::width, 0, Core::height, 0, 1);
|
glOrtho(0, Core::width, 0, Core::height, 0, 1);
|
||||||
|
|
||||||
if (waterCache->count)
|
shadow->bind(sDiffuse);
|
||||||
waterCache->items[0].data[0]->bind(sDiffuse);
|
|
||||||
else
|
|
||||||
atlas->bind(sDiffuse);
|
|
||||||
glEnable(GL_TEXTURE_2D);
|
glEnable(GL_TEXTURE_2D);
|
||||||
glDisable(GL_CULL_FACE);
|
glDisable(GL_CULL_FACE);
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
@@ -1448,12 +1478,12 @@ struct Level : IGame {
|
|||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
*/
|
|
||||||
|
|
||||||
Core::setBlending(bmAlpha);
|
Core::setBlending(bmAlpha);
|
||||||
// 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);
|
||||||
// Core::setDepthTest(false);
|
// Core::setDepthTest(false);
|
||||||
// Debug::Level::portals(level);
|
// Debug::Level::portals(level);
|
||||||
// Core::setDepthTest(true);
|
// Core::setDepthTest(true);
|
||||||
|
@@ -437,6 +437,7 @@ struct MeshBuilder {
|
|||||||
iCount += 6;
|
iCount += 6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
LOG("MegaMesh: %d %d %d\n", iCount, vCount, aCount);
|
||||||
|
|
||||||
// compile buffer and ranges
|
// compile buffer and ranges
|
||||||
mesh = new Mesh(indices, iCount, vertices, vCount, aCount);
|
mesh = new Mesh(indices, iCount, vertices, vCount, aCount);
|
||||||
|
@@ -18,8 +18,7 @@ extern "C" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EMSCRIPTEN_KEEPALIVE game_level_load(char *data, int size, int home) {
|
void EMSCRIPTEN_KEEPALIVE game_level_load(char *data, int size, int home) {
|
||||||
Stream stream(data, size);
|
Game::startLevel(new Stream(data, size), NULL, false, home);
|
||||||
Game::startLevel(stream, NULL, false, home);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -149,6 +149,7 @@
|
|||||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
||||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||||
|
<AssemblyDebug>true</AssemblyDebug>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">
|
||||||
|
@@ -119,6 +119,44 @@ void joyUpdate() {
|
|||||||
joyFree();
|
joyFree();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// touch
|
||||||
|
typedef BOOL (__stdcall *PREGISTERTOUCHWINDOW)(HWND, ULONG);
|
||||||
|
typedef BOOL (__stdcall *PGETTOUCHINPUTINFO)(HTOUCHINPUT, UINT, PTOUCHINPUT, int);
|
||||||
|
typedef BOOL (__stdcall *PCLOSETOUCHINPUTHANDLE)(HTOUCHINPUT);
|
||||||
|
|
||||||
|
PREGISTERTOUCHWINDOW RegisterTouchWindowX;
|
||||||
|
PGETTOUCHINPUTINFO GetTouchInputInfoX;
|
||||||
|
PCLOSETOUCHINPUTHANDLE CloseTouchInputHandleX;
|
||||||
|
|
||||||
|
#define MAX_TOUCH_COUNT 10
|
||||||
|
|
||||||
|
void touchInit(HWND hWnd) {
|
||||||
|
int value = GetSystemMetrics(SM_DIGITIZER);
|
||||||
|
if (value) {
|
||||||
|
HMODULE hUser32 = LoadLibrary("user32.dll");
|
||||||
|
RegisterTouchWindowX = (PREGISTERTOUCHWINDOW)GetProcAddress(hUser32, "RegisterTouchWindow");
|
||||||
|
GetTouchInputInfoX = (PGETTOUCHINPUTINFO)GetProcAddress(hUser32, "GetTouchInputInfo");
|
||||||
|
CloseTouchInputHandleX = (PCLOSETOUCHINPUTHANDLE)GetProcAddress(hUser32, "CloseTouchInputHandle");
|
||||||
|
if (RegisterTouchWindowX && GetTouchInputInfoX && CloseTouchInputHandleX)
|
||||||
|
RegisterTouchWindowX(hWnd, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void touchUpdate(HTOUCHINPUT hTouch, int count) {
|
||||||
|
TOUCHINPUT touches[MAX_TOUCH_COUNT];
|
||||||
|
count = min(count, MAX_TOUCH_COUNT);
|
||||||
|
|
||||||
|
if (!GetTouchInputInfoX(hTouch, count, touches, sizeof(TOUCHINPUT)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
LOG("touch [ ", count);
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
LOG("%d (%d, %d) ", i, touches[i].x, touches[i].y);
|
||||||
|
LOG("]\n");
|
||||||
|
|
||||||
|
CloseTouchInputHandleX(hTouch);
|
||||||
|
}
|
||||||
|
|
||||||
// sound
|
// sound
|
||||||
#define SND_SIZE 4704*2
|
#define SND_SIZE 4704*2
|
||||||
|
|
||||||
@@ -242,6 +280,9 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPara
|
|||||||
joyInit();
|
joyInit();
|
||||||
return 1;
|
return 1;
|
||||||
// touch
|
// touch
|
||||||
|
case WM_TOUCH :
|
||||||
|
touchUpdate((HTOUCHINPUT)lParam, wParam);
|
||||||
|
break;
|
||||||
// TODO
|
// TODO
|
||||||
// sound
|
// sound
|
||||||
default :
|
default :
|
||||||
@@ -293,6 +334,7 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
Sound::channelsCount = 0;
|
Sound::channelsCount = 0;
|
||||||
|
|
||||||
|
touchInit(hWnd);
|
||||||
joyInit();
|
joyInit();
|
||||||
sndInit(hWnd);
|
sndInit(hWnd);
|
||||||
|
|
||||||
|
147
src/shader.glsl
147
src/shader.glsl
@@ -1,7 +1,11 @@
|
|||||||
R"====(
|
R"====(
|
||||||
#ifdef GL_ES
|
#ifdef GL_ES
|
||||||
precision highp int;
|
precision lowp int;
|
||||||
precision highp float;
|
precision highp float;
|
||||||
|
#else
|
||||||
|
#define lowp
|
||||||
|
#define mediump
|
||||||
|
#define highp
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
varying vec4 vTexCoord; // xy - atlas coords, zw - caustics coords
|
varying vec4 vTexCoord; // xy - atlas coords, zw - caustics coords
|
||||||
@@ -16,14 +20,6 @@ varying vec4 vTexCoord; // xy - atlas coords, zw - caustics coords
|
|||||||
varying vec4 vColor;
|
varying vec4 vColor;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define TYPE_SPRITE 0
|
|
||||||
#define TYPE_FLASH 1
|
|
||||||
#define TYPE_ROOM 2
|
|
||||||
#define TYPE_ENTITY 3
|
|
||||||
#define TYPE_MIRROR 4
|
|
||||||
|
|
||||||
uniform int uType;
|
|
||||||
|
|
||||||
#ifdef PASS_COMPOSE
|
#ifdef PASS_COMPOSE
|
||||||
uniform vec3 uViewPos;
|
uniform vec3 uViewPos;
|
||||||
uniform int uCaustics;
|
uniform int uCaustics;
|
||||||
@@ -78,7 +74,7 @@ uniform int uType;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef PASS_COMPOSE
|
#ifdef PASS_COMPOSE
|
||||||
if (uType != TYPE_SPRITE) {
|
#ifndef 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
|
||||||
|
|
||||||
@@ -88,16 +84,15 @@ uniform int uType;
|
|||||||
vTexCoord.xy = (aTexCoord.xy + offset) * TEXCOORD_SCALE; // first frame + offset * isAnimated
|
vTexCoord.xy = (aTexCoord.xy + offset) * TEXCOORD_SCALE; // first frame + offset * isAnimated
|
||||||
vNormal = vec4(mulQuat(rBasisRot, aNormal.xyz), aNormal.w);
|
vNormal = vec4(mulQuat(rBasisRot, aNormal.xyz), aNormal.w);
|
||||||
|
|
||||||
if (uCaustics != 0) {
|
#ifdef CAUSTICS
|
||||||
float sum = coord.x + coord.y + coord.z;
|
float sum = coord.x + coord.y + coord.z;
|
||||||
vColor.xyz *= abs(sin(sum / 512.0 + uParam.x)) * 1.5 + 0.5; // color dodge
|
vColor.xyz *= abs(sin(sum / 512.0 + uParam.x)) * 1.5 + 0.5; // color dodge
|
||||||
}
|
#endif
|
||||||
|
#else
|
||||||
} else {
|
|
||||||
coord.xyz += uViewInv[0].xyz * aTexCoord.z - uViewInv[1].xyz * aTexCoord.w;
|
coord.xyz += uViewInv[0].xyz * aTexCoord.z - uViewInv[1].xyz * aTexCoord.w;
|
||||||
vTexCoord.xy = aTexCoord.xy * TEXCOORD_SCALE;
|
vTexCoord.xy = aTexCoord.xy * TEXCOORD_SCALE;
|
||||||
vNormal = vec4(uViewPos.xyz - coord.xyz, 0.0);
|
vNormal = vec4(uViewPos.xyz - coord.xyz, 0.0);
|
||||||
}
|
#endif
|
||||||
|
|
||||||
vTexCoord.zw = clamp((coord.xz - uRoomSize.xy) / (uRoomSize.zw - uRoomSize.xy), vec2(0.0), vec2(1.0));
|
vTexCoord.zw = clamp((coord.xz - uRoomSize.xy) / (uRoomSize.zw - uRoomSize.xy), vec2(0.0), vec2(1.0));
|
||||||
|
|
||||||
@@ -118,7 +113,6 @@ uniform int uType;
|
|||||||
uniform vec4 uColor;
|
uniform vec4 uColor;
|
||||||
#ifdef PASS_COMPOSE
|
#ifdef PASS_COMPOSE
|
||||||
uniform samplerCube sEnvironment;
|
uniform samplerCube sEnvironment;
|
||||||
uniform int uLightsCount;
|
|
||||||
uniform vec3 uLightPos[MAX_LIGHTS];
|
uniform vec3 uLightPos[MAX_LIGHTS];
|
||||||
uniform vec4 uLightColor[MAX_LIGHTS];
|
uniform vec4 uLightColor[MAX_LIGHTS];
|
||||||
uniform vec3 uAmbient[6];
|
uniform vec3 uAmbient[6];
|
||||||
@@ -140,14 +134,14 @@ uniform int uType;
|
|||||||
|
|
||||||
#ifdef SHADOW_SAMPLER
|
#ifdef SHADOW_SAMPLER
|
||||||
uniform sampler2DShadow sShadow;
|
uniform sampler2DShadow sShadow;
|
||||||
#ifdef MOBILE
|
#ifdef GL_ES
|
||||||
#define SHADOW(V) (shadow2DEXT(sShadow, V))
|
#define SHADOW(V) (shadow2DEXT(sShadow, V))
|
||||||
#else
|
#else
|
||||||
#define SHADOW(V) (shadow2D(sShadow, V).x)
|
#define SHADOW(V) (shadow2D(sShadow, V).x)
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
uniform sampler2D sShadow;
|
uniform sampler2D sShadow;
|
||||||
#define CMP(a,b) float(a > b)
|
#define CMP(a,b) step(b, a)
|
||||||
|
|
||||||
#ifdef SHADOW_DEPTH
|
#ifdef SHADOW_DEPTH
|
||||||
#define compare(p, z) CMP(texture2D(sShadow, (p)).x, (z));
|
#define compare(p, z) CMP(texture2D(sShadow, (p)).x, (z));
|
||||||
@@ -160,6 +154,8 @@ uniform int uType;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
float SHADOW(vec3 p) {
|
float SHADOW(vec3 p) {
|
||||||
|
return compare(p.xy, p.z);
|
||||||
|
/*
|
||||||
vec2 t = vec2(0.0, 1.0 / 1024.0);
|
vec2 t = vec2(0.0, 1.0 / 1024.0);
|
||||||
vec2 c = floor(p.xy * 1024.0 + 0.5) / 1024.0;
|
vec2 c = floor(p.xy * 1024.0 + 0.5) / 1024.0;
|
||||||
vec4 s;
|
vec4 s;
|
||||||
@@ -169,40 +165,55 @@ uniform int uType;
|
|||||||
s.w = compare(c + t.yy, p.z);
|
s.w = compare(c + t.yy, p.z);
|
||||||
vec2 f = fract(p.xy * 1024.0 + 0.5);
|
vec2 f = fract(p.xy * 1024.0 + 0.5);
|
||||||
return mix(mix(s.x, s.y, f.y), mix(s.z, s.w, f.y), f.x);
|
return mix(mix(s.x, s.y, f.y), mix(s.z, s.w, f.y), f.x);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
float getShadow(vec4 lightProj) {
|
float getShadow(vec4 lightProj) {
|
||||||
vec3 p = lightProj.xyz / lightProj.w;
|
vec3 poissonDisk[16];
|
||||||
if (lightProj.w < 0.0) return 1.0;
|
poissonDisk[ 0] = vec3(-0.94201624, -0.39906216, 0.0) * (1.5 / 1024.0);
|
||||||
|
poissonDisk[ 1] = vec3( 0.94558609, -0.76890725, 0.0) * (1.5 / 1024.0);
|
||||||
vec2 poissonDisk[16];
|
poissonDisk[ 2] = vec3(-0.09418410, -0.92938870, 0.0) * (1.5 / 1024.0);
|
||||||
poissonDisk[ 0] = vec2( -0.94201624, -0.39906216 );
|
poissonDisk[ 3] = vec3( 0.34495938, 0.29387760, 0.0) * (1.5 / 1024.0);
|
||||||
poissonDisk[ 1] = vec2( 0.94558609, -0.76890725 );
|
poissonDisk[ 4] = vec3(-0.91588581, 0.45771432, 0.0) * (1.5 / 1024.0);
|
||||||
poissonDisk[ 2] = vec2( -0.09418410, -0.92938870 );
|
poissonDisk[ 5] = vec3(-0.81544232, -0.87912464, 0.0) * (1.5 / 1024.0);
|
||||||
poissonDisk[ 3] = vec2( 0.34495938, 0.29387760 );
|
poissonDisk[ 6] = vec3(-0.38277543, 0.27676845, 0.0) * (1.5 / 1024.0);
|
||||||
poissonDisk[ 4] = vec2( -0.91588581, 0.45771432 );
|
poissonDisk[ 7] = vec3( 0.97484398, 0.75648379, 0.0) * (1.5 / 1024.0);
|
||||||
poissonDisk[ 5] = vec2( -0.81544232, -0.87912464 );
|
poissonDisk[ 8] = vec3( 0.44323325, -0.97511554, 0.0) * (1.5 / 1024.0);
|
||||||
poissonDisk[ 6] = vec2( -0.38277543, 0.27676845 );
|
poissonDisk[ 9] = vec3( 0.53742981, -0.47373420, 0.0) * (1.5 / 1024.0);
|
||||||
poissonDisk[ 7] = vec2( 0.97484398, 0.75648379 );
|
poissonDisk[10] = vec3(-0.26496911, -0.41893023, 0.0) * (1.5 / 1024.0);
|
||||||
poissonDisk[ 8] = vec2( 0.44323325, -0.97511554 );
|
poissonDisk[11] = vec3( 0.79197514, 0.19090188, 0.0) * (1.5 / 1024.0);
|
||||||
poissonDisk[ 9] = vec2( 0.53742981, -0.47373420 );
|
poissonDisk[12] = vec3(-0.24188840, 0.99706507, 0.0) * (1.5 / 1024.0);
|
||||||
poissonDisk[10] = vec2( -0.26496911, -0.41893023 );
|
poissonDisk[13] = vec3(-0.81409955, 0.91437590, 0.0) * (1.5 / 1024.0);
|
||||||
poissonDisk[11] = vec2( 0.79197514, 0.19090188 );
|
poissonDisk[14] = vec3( 0.19984126, 0.78641367, 0.0) * (1.5 / 1024.0);
|
||||||
poissonDisk[12] = vec2( -0.24188840, 0.99706507 );
|
poissonDisk[15] = vec3( 0.14383161, -0.14100790, 0.0) * (1.5 / 1024.0);
|
||||||
poissonDisk[13] = vec2( -0.81409955, 0.91437590 );
|
|
||||||
poissonDisk[14] = vec2( 0.19984126, 0.78641367 );
|
|
||||||
poissonDisk[15] = vec2( 0.14383161, -0.14100790 );
|
|
||||||
|
|
||||||
float rShadow = 0.0;
|
float rShadow = 0.0;
|
||||||
for (int i = 0; i < 16; i += 1)
|
vec3 p = lightProj.xyz / lightProj.w;
|
||||||
rShadow += SHADOW(p + vec3(poissonDisk[i] * 1.5, 0.0) * (1.0 / 1024.0));
|
|
||||||
|
rShadow += SHADOW(p + poissonDisk[0]);
|
||||||
|
rShadow += SHADOW(p + poissonDisk[1]);
|
||||||
|
rShadow += SHADOW(p + poissonDisk[2]);
|
||||||
|
rShadow += SHADOW(p + poissonDisk[3]);
|
||||||
|
rShadow += SHADOW(p + poissonDisk[4]);
|
||||||
|
rShadow += SHADOW(p + poissonDisk[5]);
|
||||||
|
rShadow += SHADOW(p + poissonDisk[6]);
|
||||||
|
rShadow += SHADOW(p + poissonDisk[7]);
|
||||||
|
rShadow += SHADOW(p + poissonDisk[8]);
|
||||||
|
rShadow += SHADOW(p + poissonDisk[9]);
|
||||||
|
rShadow += SHADOW(p + poissonDisk[10]);
|
||||||
|
rShadow += SHADOW(p + poissonDisk[11]);
|
||||||
|
rShadow += SHADOW(p + poissonDisk[12]);
|
||||||
|
rShadow += SHADOW(p + poissonDisk[13]);
|
||||||
|
rShadow += SHADOW(p + poissonDisk[14]);
|
||||||
|
rShadow += SHADOW(p + poissonDisk[15]);
|
||||||
|
|
||||||
rShadow /= 16.0;
|
rShadow /= 16.0;
|
||||||
|
|
||||||
vec3 lv = uLightPos[0].xyz - vCoord.xyz;
|
vec3 lv = uLightPos[0].xyz - vCoord.xyz;
|
||||||
float fade = clamp(dot(lv, lv) / uLightColor[0].w, 0.0, 1.0);
|
float fade = clamp(dot(lv, lv) / uLightColor[0].w, 0.0, 1.0);
|
||||||
|
|
||||||
return mix(rShadow, 1.0, fade);
|
return clamp(mix(rShadow, 1.0, fade), -lightProj.w, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 calcLight(vec3 normal, vec3 pos, vec4 color) {
|
vec3 calcLight(vec3 normal, vec3 pos, vec4 color) {
|
||||||
@@ -227,13 +238,12 @@ uniform int uType;
|
|||||||
sqr.z * mix(uAmbient[5], uAmbient[4], pos.z);
|
sqr.z * mix(uAmbient[5], uAmbient[4], pos.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CAUSTICS
|
||||||
float calcCaustics(vec3 n) {
|
float calcCaustics(vec3 n) {
|
||||||
if (uCaustics != 0) {
|
|
||||||
vec2 fade = smoothstep(uRoomSize.xy, uRoomSize.xy + vec2(256.0), vCoord.xz) * (1.0 - smoothstep(uRoomSize.zw - vec2(256.0), uRoomSize.zw, vCoord.xz));
|
vec2 fade = smoothstep(uRoomSize.xy, uRoomSize.xy + vec2(256.0), vCoord.xz) * (1.0 - smoothstep(uRoomSize.zw - vec2(256.0), uRoomSize.zw, vCoord.xz));
|
||||||
return texture2D(sReflect, vTexCoord.zw).r * (max(0.0, -n.y)) * fade.x * fade.y;
|
return texture2D(sReflect, vTexCoord.zw).r * (max(0.0, -n.y)) * fade.x * fade.y;
|
||||||
} else
|
|
||||||
return 0.0;
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
vec3 applyFog(vec3 color, vec3 fogColor, float factor) {
|
vec3 applyFog(vec3 color, vec3 fogColor, float factor) {
|
||||||
float fog = clamp(1.0 / exp(factor), 0.0, 1.0);
|
float fog = clamp(1.0 / exp(factor), 0.0, 1.0);
|
||||||
@@ -268,9 +278,10 @@ uniform int uType;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
vec4 color = texture2D(sDiffuse, vTexCoord.xy);
|
vec4 color = texture2D(sDiffuse, vTexCoord.xy);
|
||||||
if (color.w <= 0.6) {
|
|
||||||
discard;
|
// if (color.w <= 0.6) {
|
||||||
}
|
// discard;
|
||||||
|
// }
|
||||||
|
|
||||||
#ifdef PASS_SHADOW
|
#ifdef PASS_SHADOW
|
||||||
#ifdef SHADOW_COLOR
|
#ifdef SHADOW_COLOR
|
||||||
@@ -288,7 +299,7 @@ uniform int uType;
|
|||||||
color.xyz *= vColor.w;
|
color.xyz *= vColor.w;
|
||||||
#else
|
#else
|
||||||
// calc point lights
|
// calc point lights
|
||||||
if (uType != TYPE_FLASH) {
|
#ifndef TYPE_FLASH
|
||||||
vec3 normal = normalize(vNormal.xyz);
|
vec3 normal = normalize(vNormal.xyz);
|
||||||
|
|
||||||
//vec3 n = getNormal();;
|
//vec3 n = getNormal();;
|
||||||
@@ -299,50 +310,62 @@ uniform int uType;
|
|||||||
vec3 viewVec = normalize(vViewVec);
|
vec3 viewVec = normalize(vViewVec);
|
||||||
vec3 light = vec3(0.0);
|
vec3 light = vec3(0.0);
|
||||||
|
|
||||||
for (int i = 1; i < MAX_LIGHTS; i++) // additional lights
|
// for (int i = 1; i < 3; i++) // additional lights
|
||||||
light += calcLight(normal, uLightPos[i], uLightColor[i]);
|
light += calcLight(normal, uLightPos[1], uLightColor[1]);
|
||||||
|
light += calcLight(normal, uLightPos[2], uLightColor[2]);
|
||||||
|
|
||||||
// apply lighting
|
// apply lighting
|
||||||
if (uType == TYPE_SPRITE) {
|
#ifdef TYPE_SPRITE
|
||||||
light += vColor.w * uColor.w;
|
light += vColor.w * uColor.w;
|
||||||
}
|
#endif
|
||||||
|
|
||||||
if (uType == TYPE_ROOM) {
|
#ifdef TYPE_ROOM
|
||||||
float rShadow = dot(normal, uLightPos[0].xyz - vCoord) > 0.0 ? getShadow(vLightProj) : 1.0;
|
float rShadow = dot(normal, uLightPos[0].xyz - vCoord) > 0.0 ? getShadow(vLightProj) : 1.0;
|
||||||
//light += calcLight(normal, uLightPos[0], uLightColor[0]);
|
//light += calcLight(normal, uLightPos[0], uLightColor[0]);
|
||||||
light += mix(min(uColor.w, vColor.w), vColor.w, rShadow);
|
light += mix(min(uColor.w, vColor.w), vColor.w, rShadow);
|
||||||
|
#ifdef CAUSTICS
|
||||||
light += calcCaustics(normal);
|
light += calcCaustics(normal);
|
||||||
}
|
#endif
|
||||||
|
//color.xyz = vec3(rShadow);
|
||||||
|
//light.xyz = vec3(1.0);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (uType == TYPE_ENTITY) {
|
#ifdef TYPE_ENTITY
|
||||||
vec3 rAmbient = calcAmbient(normal);
|
vec3 rAmbient = calcAmbient(normal);
|
||||||
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;
|
||||||
color.xyz += calcSpecular(normal, viewVec, uLightPos[0], uLightColor[0], uColor.w * rShadow + 0.03);
|
color.xyz += calcSpecular(normal, viewVec, uLightPos[0], uLightColor[0], uColor.w * rShadow + 0.03);
|
||||||
|
#ifdef CAUSTICS
|
||||||
light += calcCaustics(normal);
|
light += calcCaustics(normal);
|
||||||
}
|
#endif
|
||||||
|
//color.xyz = vec3(rShadow);
|
||||||
|
//light.xyz = vec3(1.0);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (uType == TYPE_MIRROR) {
|
#ifdef TYPE_MIRROR
|
||||||
vec3 rv = reflect(-viewVec, normal);
|
vec3 rv = reflect(-viewVec, normal);
|
||||||
color.xyz = uColor.xyz * pow(abs(textureCube(sEnvironment, normalize(rv)).xyz), vec3(2.2));
|
color.xyz = uColor.xyz * pow(abs(textureCube(sEnvironment, normalize(rv)).xyz), vec3(2.2));
|
||||||
light.xyz = vec3(1.0);
|
light.xyz = vec3(1.0);
|
||||||
}
|
#endif
|
||||||
|
|
||||||
color.xyz *= light;
|
color.xyz *= light;
|
||||||
} else {
|
|
||||||
|
#else // ifndef TYPE_FLASH
|
||||||
|
|
||||||
color.w = uColor.w;
|
color.w = uColor.w;
|
||||||
}
|
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
color = sqrt(color); // back to "gamma" space
|
color = sqrt(color); // back to "gamma" space
|
||||||
|
|
||||||
#ifdef PASS_COMPOSE
|
#ifdef PASS_COMPOSE
|
||||||
color.xyz = applyFog(color.xyz, vec3(0.0), length(vViewVec) * FOG_DIST);
|
color.xyz = applyFog(color.xyz, vec3(0.0), length(vViewVec) * FOG_DIST);
|
||||||
if (uCaustics != 0) {
|
#ifdef CAUSTICS
|
||||||
float d = abs((vCoord.y - max(uViewPos.y, uParam.y)) / normalize(vViewVec).y);
|
float d = abs((vCoord.y - max(uViewPos.y, uParam.y)) / normalize(vViewVec).y);
|
||||||
d *= step(0.0, vCoord.y - uParam.y);
|
d *= step(0.0, vCoord.y - uParam.y);
|
||||||
color.xyz = applyFog(color.xyz, uColor.xyz * 0.2, d * WATER_FOG_DIST);
|
color.xyz = applyFog(color.xyz, uColor.xyz * 0.2, d * WATER_FOG_DIST);
|
||||||
}
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
gl_FragColor = color;
|
gl_FragColor = color;
|
||||||
|
@@ -5,20 +5,22 @@
|
|||||||
|
|
||||||
enum AttribType { aCoord, aTexCoord, aNormal, aColor, aMAX };
|
enum AttribType { aCoord, aTexCoord, aNormal, aColor, aMAX };
|
||||||
enum SamplerType { sDiffuse, sNormal, sReflect, sShadow, sEnvironment, sMask, sMAX };
|
enum SamplerType { sDiffuse, sNormal, sReflect, sShadow, sEnvironment, sMask, sMAX };
|
||||||
enum UniformType { uType, uCaustics, uParam, uTexParam, uViewProj, uViewInv, uBasis, uLightProj, uColor, uAmbient, uViewPos, uLightsCount, uLightPos, uLightColor, uAnimTexRanges, uAnimTexOffsets, uRoomSize, uPosScale, uMAX };
|
enum UniformType { uParam, uTexParam, uViewProj, uViewInv, uBasis, uLightProj, uColor, uAmbient, uViewPos, uLightPos, uLightColor, uAnimTexRanges, uAnimTexOffsets, uRoomSize, uPosScale, uMAX };
|
||||||
|
|
||||||
const char *AttribName[aMAX] = { "aCoord", "aTexCoord", "aNormal", "aColor" };
|
const char *AttribName[aMAX] = { "aCoord", "aTexCoord", "aNormal", "aColor" };
|
||||||
const char *SamplerName[sMAX] = { "sDiffuse", "sNormal", "sReflect", "sShadow", "sEnvironment", "sMask" };
|
const char *SamplerName[sMAX] = { "sDiffuse", "sNormal", "sReflect", "sShadow", "sEnvironment", "sMask" };
|
||||||
const char *UniformName[uMAX] = { "uType", "uCaustics", "uParam", "uTexParam", "uViewProj", "uViewInv", "uBasis", "uLightProj", "uColor", "uAmbient", "uViewPos", "uLightsCount", "uLightPos", "uLightColor", "uAnimTexRanges", "uAnimTexOffsets", "uRoomSize", "uPosScale" };
|
const char *UniformName[uMAX] = { "uParam", "uTexParam", "uViewProj", "uViewInv", "uBasis", "uLightProj", "uColor", "uAmbient", "uViewPos", "uLightPos", "uLightColor", "uAnimTexRanges", "uAnimTexOffsets", "uRoomSize", "uPosScale" };
|
||||||
|
|
||||||
struct Shader {
|
struct Shader {
|
||||||
GLuint ID;
|
GLuint ID;
|
||||||
GLint uID[uMAX];
|
GLint uID[uMAX];
|
||||||
|
|
||||||
enum : GLint {
|
enum Type : GLint {
|
||||||
|
NONE = 0,
|
||||||
/* shader */ SPRITE = 0, FLASH = 1, ROOM = 2, ENTITY = 3, MIRROR = 4,
|
/* shader */ SPRITE = 0, FLASH = 1, ROOM = 2, ENTITY = 3, MIRROR = 4,
|
||||||
/* filter */ FILTER_DOWNSAMPLE = 0,
|
/* filter */ FILTER_DOWNSAMPLE = 0,
|
||||||
/* water */ WATER_DROP = 0, WATER_STEP = 1, WATER_CAUSTICS = 2, WATER_MASK = 3, WATER_COMPOSE = 4,
|
/* water */ WATER_DROP = 0, WATER_STEP = 1, WATER_CAUSTICS = 2, WATER_MASK = 3, WATER_COMPOSE = 4,
|
||||||
|
MAX = 5
|
||||||
};
|
};
|
||||||
|
|
||||||
Shader(const char *text, const char *defines = "") {
|
Shader(const char *text, const char *defines = "") {
|
||||||
|
@@ -61,7 +61,7 @@ struct Sprite : Controller {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void render(Frustum *frustum, MeshBuilder *mesh) {
|
virtual void render(Frustum *frustum, MeshBuilder *mesh, Shader::Type type, bool caustics) {
|
||||||
Basis basis(Core::basis);
|
Basis basis(Core::basis);
|
||||||
basis.translate(pos);
|
basis.translate(pos);
|
||||||
Core::active.shader->setParam(uBasis, basis);
|
Core::active.shader->setParam(uBasis, basis);
|
||||||
|
@@ -299,13 +299,11 @@ struct Crystal : Controller {
|
|||||||
delete environment;
|
delete environment;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void render(Frustum *frustum, MeshBuilder *mesh) {
|
virtual void render(Frustum *frustum, MeshBuilder *mesh, Shader::Type type, bool caustics) {
|
||||||
Shader *sh = Core::active.shader;
|
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
|
sh->setParam(uColor, vec4(0.4f, 0.4f, 16.0f, 1.0f)); // blue color dodge
|
||||||
environment->bind(sEnvironment);
|
environment->bind(sEnvironment);
|
||||||
Controller::render(frustum, mesh);
|
Controller::render(frustum, mesh, type, caustics);
|
||||||
sh->setParam(uType, Shader::ENTITY);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
16
src/utils.h
16
src/utils.h
@@ -12,9 +12,6 @@
|
|||||||
|
|
||||||
#ifndef ANDROID
|
#ifndef ANDROID
|
||||||
#define LOG(...) printf(__VA_ARGS__)
|
#define LOG(...) printf(__VA_ARGS__)
|
||||||
#else
|
|
||||||
#include <android/log.h>
|
|
||||||
#define LOG(...) __android_log_print(ANDROID_LOG_INFO,"X5",__VA_ARGS__)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
@@ -26,6 +23,13 @@
|
|||||||
// #endif
|
// #endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef ANDROID
|
||||||
|
#include <android/log.h>
|
||||||
|
#undef LOG
|
||||||
|
#define LOG(...) __android_log_print(ANDROID_LOG_INFO,"OpenLara",__VA_ARGS__)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define EPS FLT_EPSILON
|
#define EPS FLT_EPSILON
|
||||||
#define INF INFINITY
|
#define INF INFINITY
|
||||||
#define PI 3.14159265358979323846f
|
#define PI 3.14159265358979323846f
|
||||||
@@ -34,9 +38,9 @@
|
|||||||
#define RAD2DEG (180.0f / PI)
|
#define RAD2DEG (180.0f / PI)
|
||||||
#define randf() ((float)rand()/RAND_MAX)
|
#define randf() ((float)rand()/RAND_MAX)
|
||||||
|
|
||||||
typedef char int8;
|
typedef signed char int8;
|
||||||
typedef short int16;
|
typedef signed short int16;
|
||||||
typedef int int32;
|
typedef signed int int32;
|
||||||
typedef unsigned char uint8;
|
typedef unsigned char uint8;
|
||||||
typedef unsigned short uint16;
|
typedef unsigned short uint16;
|
||||||
typedef unsigned int uint32;
|
typedef unsigned int uint32;
|
||||||
|
@@ -1,24 +1,23 @@
|
|||||||
R"====(
|
R"====(
|
||||||
#ifdef GL_ES
|
#ifdef GL_ES
|
||||||
precision highp int;
|
precision lowp int;
|
||||||
precision highp float;
|
precision highp float;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
varying vec3 vCoord;
|
varying vec3 vCoord;
|
||||||
varying vec2 vTexCoord;
|
varying vec2 vTexCoord;
|
||||||
varying vec4 vProjCoord;
|
varying vec4 vProjCoord;
|
||||||
varying vec3 vRefPos1;
|
varying vec4 vOldPos;
|
||||||
varying vec3 vRefPos2;
|
varying vec4 vNewPos;
|
||||||
varying vec3 vViewVec;
|
varying vec3 vViewVec;
|
||||||
varying vec3 vLightVec;
|
varying vec3 vLightVec;
|
||||||
|
/*
|
||||||
#define WATER_DROP 0
|
#define WATER_DROP 0
|
||||||
#define WATER_STEP 1
|
#define WATER_STEP 1
|
||||||
#define WATER_CAUSTICS 2
|
#define WATER_CAUSTICS 2
|
||||||
#define WATER_MASK 3
|
#define WATER_MASK 3
|
||||||
#define WATER_COMPOSE 4
|
#define WATER_COMPOSE 4
|
||||||
|
*/
|
||||||
uniform int uType;
|
|
||||||
uniform vec3 uViewPos;
|
uniform vec3 uViewPos;
|
||||||
uniform mat4 uViewProj;
|
uniform mat4 uViewProj;
|
||||||
uniform vec3 uLightPos;
|
uniform vec3 uLightPos;
|
||||||
@@ -39,14 +38,14 @@ uniform sampler2D sNormal;
|
|||||||
void main() {
|
void main() {
|
||||||
vTexCoord = (aCoord.xy * 0.5 + 0.5) * uTexParam.zw;
|
vTexCoord = (aCoord.xy * 0.5 + 0.5) * uTexParam.zw;
|
||||||
|
|
||||||
if (uType >= WATER_MASK) {
|
#if defined(WATER_MASK) || defined(WATER_COMPOSE)
|
||||||
|
|
||||||
float height = 0.0;
|
float height = 0.0;
|
||||||
|
|
||||||
if (uType == WATER_COMPOSE) {
|
#ifdef WATER_COMPOSE
|
||||||
vTexCoord = (aCoord.xy * (1.0 / 48.0) * 0.5 + 0.5) * uTexParam.zw;
|
vTexCoord = (aCoord.xy * (1.0 / 48.0) * 0.5 + 0.5) * uTexParam.zw;
|
||||||
height = texture2D(sNormal, vTexCoord).x;
|
height = texture2D(sNormal, vTexCoord).x;
|
||||||
}
|
#endif
|
||||||
|
|
||||||
vCoord = vec3(aCoord.x, height, aCoord.y) * uPosScale[1] + uPosScale[0];
|
vCoord = vec3(aCoord.x, height, aCoord.y) * uPosScale[1] + uPosScale[0];
|
||||||
|
|
||||||
@@ -54,28 +53,28 @@ uniform sampler2D sNormal;
|
|||||||
|
|
||||||
vProjCoord = cp;
|
vProjCoord = cp;
|
||||||
gl_Position = cp;
|
gl_Position = cp;
|
||||||
} else {
|
#else
|
||||||
vProjCoord = vec4(0.0);
|
vProjCoord = vec4(0.0);
|
||||||
vCoord = vec3(aCoord.xy, 0.0);
|
vCoord = vec3(aCoord.xy, 0.0);
|
||||||
if (uType == WATER_CAUSTICS) {
|
#ifdef WATER_CAUSTICS
|
||||||
vec3 rCoord = vec3(aCoord.x, 0.0, aCoord.y) * uPosScale[1];
|
vec3 rCoord = vec3(aCoord.x, aCoord.y, 0.0) * uPosScale[1].xzy;
|
||||||
|
|
||||||
vec4 info = texture2D(sNormal, (rCoord.xz * 0.5 + 0.5) * uTexParam.zw);
|
vec4 info = texture2D(sNormal, (rCoord.xy * 0.5 + 0.5) * uTexParam.zw);
|
||||||
vec3 normal = vec3(info.z, -sqrt(1.0 - dot(info.zw, info.zw)), info.w);
|
vec3 normal = vec3(info.z, info.w, sqrt(1.0 - dot(info.zw, info.zw)));
|
||||||
|
|
||||||
vec3 light = vec3(0.0, -1.0, 0.0);
|
vec3 light = vec3(0.0, 0.0, 1.0);
|
||||||
vec3 refractedLight = refract(-light, vec3(0.0, 1.0, 0.0), ETA_AIR / ETA_WATER);
|
vec3 refOld = refract(-light, vec3(0.0, 0.0, 1.0), 0.75);
|
||||||
vec3 ray = refract(-light, normal, ETA_AIR / ETA_WATER);
|
vec3 refNew = refract(-light, normal, 0.75);
|
||||||
|
|
||||||
vRefPos1 = rCoord + vec3(0.0, 0.0, 0.0);
|
vOldPos = vec4(rCoord + refOld * (-0.25 / refOld.z) + refOld * ((-refOld.z - 1.0) / refOld.z), 1.0);
|
||||||
vRefPos2 = rCoord + vec3(0.0, info.r, 0.0) + ray / ray.y;
|
vNewPos = vec4(rCoord + refNew * ((info.r - 0.25) / refNew.z) + refOld * ((-refNew.z - 1.0) / refOld.z), 1.0);
|
||||||
|
|
||||||
gl_Position = vec4((vRefPos2.xz + 0.0 * refractedLight.xz / refractedLight.y), 0.0, 1.0);
|
gl_Position = vec4(vNewPos.xy + refOld.xy / refOld.z, 0.0, 1.0);
|
||||||
} else {
|
#else
|
||||||
vRefPos1 = vRefPos2 = vec3(0.0);
|
vOldPos = vNewPos = vec4(0.0);
|
||||||
gl_Position = vec4(aCoord.xyz, 1.0);
|
gl_Position = vec4(aCoord.xyz, 1.0);
|
||||||
}
|
#endif
|
||||||
}
|
#endif
|
||||||
vViewVec = uViewPos - vCoord.xyz;
|
vViewVec = uViewPos - vCoord.xyz;
|
||||||
vLightVec = uLightPos - vCoord.xyz;
|
vLightVec = uLightPos - vCoord.xyz;
|
||||||
}
|
}
|
||||||
@@ -137,9 +136,10 @@ uniform sampler2D sNormal;
|
|||||||
}
|
}
|
||||||
|
|
||||||
vec4 caustics() {
|
vec4 caustics() {
|
||||||
float area1 = length(dFdx(vRefPos1)) * length(dFdy(vRefPos1));
|
float rOldArea = length(dFdx(vOldPos.xyz)) * length(dFdy(vOldPos.xyz));
|
||||||
float area2 = length(dFdx(vRefPos2)) * length(dFdy(vRefPos2));
|
float rNewArea = length(dFdx(vNewPos.xyz)) * length(dFdy(vNewPos.xyz));
|
||||||
return vec4(vec3(area1 / area2 * 0.2), 1.0);
|
float value = clamp(rOldArea / rNewArea * 0.2, 0.0, 1.0) * vOldPos.w;
|
||||||
|
return vec4(vec3(value), 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
vec4 mask() {
|
vec4 mask() {
|
||||||
@@ -178,12 +178,28 @@ uniform sampler2D sNormal;
|
|||||||
}
|
}
|
||||||
|
|
||||||
vec4 pass() {
|
vec4 pass() {
|
||||||
if (uType == WATER_DROP) return drop();
|
return
|
||||||
if (uType == WATER_STEP) return calc();
|
#ifdef WATER_DROP
|
||||||
if (uType == WATER_CAUSTICS) return caustics();
|
drop();
|
||||||
if (uType == WATER_MASK) return mask();
|
#endif
|
||||||
if (uType == WATER_COMPOSE) return compose();
|
|
||||||
return vec4(1.0, 0.0, 0.0, 1.0);
|
#ifdef WATER_STEP
|
||||||
|
calc();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WATER_CAUSTICS
|
||||||
|
caustics();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WATER_MASK
|
||||||
|
mask();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WATER_COMPOSE
|
||||||
|
compose();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
vec4(1.0, 0.0, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
Reference in New Issue
Block a user