diff --git a/src/cache.h b/src/cache.h
index 24d537c..9e0999c 100644
--- a/src/cache.h
+++ b/src/cache.h
@@ -75,12 +75,9 @@ struct ShaderCache {
}
void prepareAmbient(int fx) {
- compile(Core::passAmbient, Shader::ROOM, fx, rsFull);
- compile(Core::passAmbient, Shader::ROOM, fx, rsFull | RS_DISCARD);
- compile(Core::passAmbient, Shader::ROOM, fx | FX_UNDERWATER, rsFull);
- compile(Core::passAmbient, Shader::ROOM, fx | FX_UNDERWATER, rsFull | RS_DISCARD);
- compile(Core::passAmbient, Shader::SPRITE, fx, rsFull | RS_DISCARD);
- compile(Core::passAmbient, Shader::SPRITE, fx | FX_UNDERWATER, rsFull | RS_DISCARD);
+ compile(Core::passAmbient, Shader::ROOM, fx, rsFull);
+ compile(Core::passAmbient, Shader::ROOM, fx, rsFull | RS_DISCARD);
+ compile(Core::passAmbient, Shader::SPRITE, fx, rsFull | RS_DISCARD);
}
void prepareShadows(int fx) {
diff --git a/src/core.h b/src/core.h
index b036c74..8a5c876 100644
--- a/src/core.h
+++ b/src/core.h
@@ -520,8 +520,6 @@ namespace Core {
enum Pass { passCompose, passShadow, passAmbient, passSky, passWater, passFilter, passGUI, passMAX } pass;
- const char *passNames[Core::passMAX] = { "COMPOSE", "SHADOW", "AMBIENT", "SKY", "WATER", "FILTER", "GUI" };
-
GAPI::Texture *defaultTarget;
int32 renderState;
diff --git a/src/gapi_gl.h b/src/gapi_gl.h
index 620c907..49c45a3 100644
--- a/src/gapi_gl.h
+++ b/src/gapi_gl.h
@@ -334,8 +334,16 @@ namespace GAPI {
// Shader
#ifndef FFP
- const char SHADER_BASE[] =
- #include "shaders/shader.glsl"
+ const char SHADER_COMPOSE[] =
+ #include "shaders/compose.glsl"
+ ;
+
+ const char SHADER_SHADOW[] =
+ #include "shaders/shadow.glsl"
+ ;
+
+ const char SHADER_AMBIENT[] =
+ #include "shaders/ambient.glsl"
;
const char SHADER_SKY[] =
@@ -398,26 +406,26 @@ namespace GAPI {
void init(Pass pass, int type, int *def, int defCount) {
const char *source;
switch (pass) {
- case Core::passCompose :
- case Core::passShadow :
- case Core::passAmbient : source = SHADER_BASE; break;
- case Core::passSky : source = SHADER_SKY; break;
- case Core::passWater : source = SHADER_WATER; break;
- case Core::passFilter : source = SHADER_FILTER; break;
- case Core::passGUI : source = SHADER_GUI; break;
+ case Core::passCompose : source = SHADER_COMPOSE; break;
+ case Core::passShadow : source = SHADER_SHADOW; break;
+ case Core::passAmbient : source = SHADER_AMBIENT; break;
+ case Core::passSky : source = SHADER_SKY; break;
+ case Core::passWater : source = SHADER_WATER; break;
+ case Core::passFilter : source = SHADER_FILTER; break;
+ case Core::passGUI : source = SHADER_GUI; break;
default : ASSERT(false); LOG("! wrong pass id\n"); return;
}
#ifdef _DEBUG_SHADERS
Stream *stream = NULL;
switch (pass) {
- case Core::passCompose :
- case Core::passShadow :
- case Core::passAmbient : stream = new Stream("../../src/shaders/shader.glsl"); break;
- case Core::passSky : stream = new Stream("../../src/shaders/sky.glsl"); break;
- case Core::passWater : stream = new Stream("../../src/shaders/water.glsl"); break;
- case Core::passFilter : stream = new Stream("../../src/shaders/filter.glsl"); break;
- case Core::passGUI : stream = new Stream("../../src/shaders/gui.glsl"); break;
+ case Core::passCompose : stream = new Stream("../../src/shaders/compose.glsl"); break;
+ case Core::passShadow : stream = new Stream("../../src/shaders/shadow.glsl"); break;
+ case Core::passAmbient : stream = new Stream("../../src/shaders/ambient.glsl"); break;
+ case Core::passSky : stream = new Stream("../../src/shaders/sky.glsl"); break;
+ case Core::passWater : stream = new Stream("../../src/shaders/water.glsl"); break;
+ case Core::passFilter : stream = new Stream("../../src/shaders/filter.glsl"); break;
+ case Core::passGUI : stream = new Stream("../../src/shaders/gui.glsl"); break;
default : ASSERT(false); return;
}
@@ -448,7 +456,6 @@ namespace GAPI {
for (int i = 0; i < defCount; i++) {
sprintf(defines + strlen(defines), "#define %s\n", DefineName[def[i]]);
}
- sprintf(defines + strlen(defines), "#define PASS_%s\n", passNames[pass]);
#if defined(_OS_RPI) || defined(_OS_CLOVER)
strcat(defines, "#define OPT_VLIGHTPROJ\n");
diff --git a/src/level.h b/src/level.h
index 00b3b7c..c1a6bc2 100644
--- a/src/level.h
+++ b/src/level.h
@@ -71,6 +71,10 @@ struct Level : IGame {
float animTexTimer;
float statsTimeDelta;
+ vec3 underwaterColor;
+ vec4 underwaterFogParams;
+ vec4 levelFogParams;
+
// IGame implementation ========
virtual void loadLevel(TR::LevelID id) {
sndWater = sndTrack = NULL;
@@ -519,17 +523,6 @@ struct Level : IGame {
alphaTest = true;
}
- setShader(Core::pass, type, room.flags.water, alphaTest);
-
- if (room.flags.water) {
- if (waterCache)
- waterCache->bindCaustics(roomIndex);
- setWaterParams(float(room.waterLevel[level.state.flags.flipped]));
- } else
- setWaterParams(NO_CLIP_PLANE);
-
- Core::active.shader->setParam(uParam, Core::params);
-
#ifdef FFP
switch (type) {
case Shader::SPRITE :
@@ -549,7 +542,36 @@ struct Level : IGame {
}
#endif
- Core::setMaterial(diffuse, ambient, specular, alpha);
+ vec4 material;
+
+ if (Core::pass == Core::passAmbient) {
+ if (room.flags.water) {
+ Core::fogParams = underwaterFogParams;
+ material = vec4(underwaterColor, 1.0f);
+ } else {
+ Core::fogParams = levelFogParams;
+ material = vec4(1.0f);
+ }
+ } else {
+ Core::fogParams = levelFogParams;
+ material = vec4(diffuse, ambient, specular, alpha);
+ }
+
+ setShader(Core::pass, type, (Core::pass == Core::passAmbient) ? false : room.flags.water, alphaTest);
+
+ Core::setMaterial(material.x, material.y, material.z, material.w);
+
+ if (room.flags.water) {
+ if (waterCache) {
+ waterCache->bindCaustics(roomIndex);
+ }
+ setWaterParams(float(room.waterLevel[level.state.flags.flipped]));
+ } else {
+ setWaterParams(NO_CLIP_PLANE);
+ }
+
+ Core::active.shader->setParam(uParam, Core::params);
+
Core::updateLights();
if (Core::settings.detail.shadows > Core::Settings::MEDIUM)
@@ -835,7 +857,9 @@ struct Level : IGame {
memset(players, 0, sizeof(players));
player = NULL;
- Core::fogParams = TR::getFogParams(level.id);
+ underwaterColor = vec3(0.6f, 0.9f, 0.9f);
+ underwaterFogParams = vec4(underwaterColor * 0.2f, 1.0f / (6 * 1024));
+ levelFogParams = TR::getFogParams(level.id);
inventory->game = this;
diff --git a/src/platform/win/OpenLara.vcxproj b/src/platform/win/OpenLara.vcxproj
index 7a80b9c..619a929 100644
--- a/src/platform/win/OpenLara.vcxproj
+++ b/src/platform/win/OpenLara.vcxproj
@@ -233,9 +233,11 @@
+
+
-
+
diff --git a/src/platform/win/OpenLara.vcxproj.filters b/src/platform/win/OpenLara.vcxproj.filters
index a3504cf..ed6a0a3 100644
--- a/src/platform/win/OpenLara.vcxproj.filters
+++ b/src/platform/win/OpenLara.vcxproj.filters
@@ -69,10 +69,16 @@
shaders
-
+
shaders
-
+
+ shaders
+
+
+ shaders
+
+
shaders
diff --git a/src/shaders/ambient.glsl b/src/shaders/ambient.glsl
new file mode 100644
index 0000000..bf050af
--- /dev/null
+++ b/src/shaders/ambient.glsl
@@ -0,0 +1,69 @@
+R"====(
+uniform mat4 uViewProj;
+uniform vec4 uViewPos;
+uniform vec4 uFogParams;
+
+varying vec2 vTexCoord;
+varying vec4 vDiffuse;
+
+#ifdef VERTEX
+
+ uniform vec4 uBasis[2];
+ uniform vec4 uMaterial;
+
+ attribute vec4 aCoord;
+ attribute vec4 aTexCoord;
+
+ attribute vec3 aColor;
+ attribute vec3 aLight;
+
+ vec3 mulQuat(vec4 q, vec3 v) {
+ return v + 2.0 * cross(q.xyz, cross(q.xyz, v) + v * q.w);
+ }
+
+ vec3 mulBasis(vec4 rot, vec3 pos, vec3 v) {
+ return mulQuat(rot, v) + pos;
+ }
+
+ void main() {
+ vTexCoord = aTexCoord.xy;
+
+ vec4 rBasisRot = uBasis[0];
+ vec4 rBasisPos = uBasis[1];
+
+ vec3 coord =
+ #ifdef TYPE_SPRITE
+ mulBasis(rBasisRot, rBasisPos.xyz + aCoord.xyz, vec3(aTexCoord.z, aTexCoord.w, 0.0) * 32767.0);
+ #else
+ mulBasis(rBasisRot, rBasisPos.xyz, aCoord.xyz);
+ #endif
+
+ vDiffuse.xyz = aColor.xyz * aLight.xyz * uMaterial.xyz;
+ float fog = length(uViewPos.xyz - coord.xyz) * uFogParams.w;
+ vDiffuse.w = clamp(1.0 / exp(fog), 0.0, 1.0);
+
+ gl_Position = uViewProj * vec4(coord, 1.0);
+ }
+
+#else
+
+ uniform sampler2D sDiffuse;
+
+ void main() {
+ vec4 color = texture2D(sDiffuse, vTexCoord);
+
+ #ifdef ALPHA_TEST
+ if (color.w <= 0.5)
+ discard;
+ #endif
+
+ color.xyz *= vDiffuse.xyz;
+ color.xyz = mix(uFogParams.xyz, color.xyz, vDiffuse.w);
+
+ color.xyz *= color.w;
+
+ fragColor = color;
+ }
+
+#endif
+)===="
diff --git a/src/shaders/shader.glsl b/src/shaders/compose.glsl
similarity index 52%
rename from src/shaders/shader.glsl
rename to src/shaders/compose.glsl
index d9cd2d8..6606ad9 100644
--- a/src/shaders/shader.glsl
+++ b/src/shaders/compose.glsl
@@ -8,16 +8,6 @@ R"====(
#define SHADOW_NORMAL_BIAS 16.0
#define SHADOW_CONST_BIAS 0.05
-#if (defined(PASS_AMBIENT) || defined(PASS_COMPOSE)) && !defined(TYPE_FLASH)
- varying vec3 vCoord;
-#endif
-
-varying vec4 vTexCoord; // xy - atlas coords, zw - trapezoidal correction
-
-#ifdef OPT_VLIGHTVEC
- varying vec3 vLightVec;
-#endif
-
#ifdef OPT_CAUSTICS
uniform vec4 uRoomSize; // xy - minXZ, zw - maxXZ
#endif
@@ -40,21 +30,25 @@ uniform vec4 uLightColor[MAX_LIGHTS]; // xyz - color, w - radius * intensity
uniform vec4 uMaterial; // x - diffuse, y - ambient, z - specular, w - alpha
uniform vec4 uFogParams;
-#ifndef PASS_SHADOW
- varying vec4 vViewVec; // xyz - dir * dist, w - coord.y * clipPlaneSign
- varying vec4 vDiffuse;
+varying vec4 vViewVec; // xyz - dir * dist, w - coord.y * clipPlaneSign
+varying vec4 vDiffuse;
+
+#ifndef TYPE_FLASH
+ varying vec3 vCoord;
varying vec4 vNormal; // xyz - normal dir, w - fog factor
- #ifndef TYPE_FLASH
- #ifdef PASS_COMPOSE
- #ifdef OPT_SHADOW
- varying vec3 vAmbient;
- varying vec3 vLightMap;
- #endif
- #endif
-
- varying vec4 vLight; // lights intensity (MAX_LIGHTS == 4)
+ #ifdef OPT_SHADOW
+ varying vec3 vAmbient;
+ varying vec3 vLightMap;
#endif
+
+ varying vec4 vLight; // lights intensity (MAX_LIGHTS == 4)
+#endif
+
+varying vec4 vTexCoord; // xy - atlas coords, zw - trapezoidal correction
+
+#ifdef OPT_VLIGHTVEC
+ varying vec3 vLightVec;
#endif
#ifdef OPT_SHADOW
@@ -89,10 +83,8 @@ uniform vec4 uFogParams;
attribute vec4 aTexCoord;
attribute vec4 aNormal;
- #ifndef PASS_SHADOW
- attribute vec4 aColor;
- attribute vec4 aLight;
- #endif
+ attribute vec4 aColor;
+ attribute vec4 aLight;
vec3 mulQuat(vec4 q, vec3 v) {
return v + 2.0 * cross(q.xyz, cross(q.xyz, v) + v * q.w);
@@ -112,23 +104,16 @@ uniform vec4 uFogParams;
vec4 rBasisPos = uBasis[1];
#endif
- vec4 coord;
- coord.w = rBasisPos.w; // visible flag
- #if defined(TYPE_SPRITE)
- coord.xyz = mulBasis(rBasisRot, rBasisPos.xyz + aCoord.xyz, vec3(aTexCoord.z, aTexCoord.w, 0.0) * 32767.0);
+ vec3 coord =
+ #ifdef TYPE_SPRITE
+ mulBasis(rBasisRot, rBasisPos.xyz + aCoord.xyz, vec3(aTexCoord.z, aTexCoord.w, 0.0) * 32767.0);
#else
- coord.xyz = mulBasis(rBasisRot, rBasisPos.xyz, aCoord.xyz);
+ mulBasis(rBasisRot, rBasisPos.xyz, aCoord.xyz);
#endif
- #ifndef PASS_SHADOW
- vViewVec = vec4((uViewPos.xyz - coord.xyz) * uFogParams.w, coord.y * uParam.z);
- #endif
+ vViewVec = vec4((uViewPos.xyz - coord) * uFogParams.w, coord.y * uParam.z);
- #ifdef PASS_AMBIENT
- vNormal = aNormal;
- #endif
-
- #if defined(PASS_COMPOSE) && !defined(TYPE_FLASH)
+ #ifndef TYPE_FLASH
#ifdef TYPE_SPRITE
vNormal.xyz = normalize(vViewVec.xyz);
#else
@@ -136,125 +121,115 @@ uniform vec4 uFogParams;
#endif
float fog;
- #if defined(UNDERWATER) && defined(OPT_UNDERWATER_FOG)
+ #if defined(UNDERWATER) && !defined(OPT_UNDERWATER_FOG)
float d;
if (uViewPos.y < uParam.y) // TODO: fix for mediump
- d = abs((coord.y - uParam.y) / normalize(uViewPos.xyz - coord.xyz).y);
+ d = abs((coord.y - uParam.y) / normalize(uViewPos.xyz - coord).y);
else
- d = length(uViewPos.xyz - coord.xyz);
+ d = length(uViewPos.xyz - coord);
fog = d * WATER_FOG_DIST;
fog *= step(uParam.y, coord.y);
- vNormal.w = fog;
+ vNormal.w = clamp(1.0 / exp(fog), 0.0, 1.0);
#else
fog = length(vViewVec.xyz);
vNormal.w = clamp(1.0 / exp(fog), 0.0, 1.0);
#endif
- vCoord = coord.xyz;
+ vCoord = coord;
#endif
- return coord;
+ return vec4(coord, rBasisPos.w);
}
void _diffuse() {
- #ifndef PASS_SHADOW
- vDiffuse = vec4(aColor.xyz * uMaterial.x, 1.0);
- #ifdef PASS_COMPOSE
- vDiffuse.xyz *= 2.0;
- #endif
+ vDiffuse = vec4(aColor.xyz * uMaterial.x, 1.0);
+ vDiffuse.xyz *= 2.0;
- #ifdef TYPE_MIRROR
- vDiffuse.xyz = uMaterial.xyz;
- #endif
+ #ifdef TYPE_MIRROR
+ vDiffuse.xyz = uMaterial.xyz;
+ #endif
- #ifdef TYPE_FLASH
- vDiffuse.xyz += uMaterial.w;
- #else
- vDiffuse *= uMaterial.w;
- #endif
+ #ifdef TYPE_FLASH
+ vDiffuse.xyz += uMaterial.w;
+ #else
+ vDiffuse *= uMaterial.w;
+ #endif
- #ifdef TYPE_SPRITE
- vDiffuse *= aLight.w;
- #endif
+ #ifdef TYPE_SPRITE
+ vDiffuse *= aLight.w;
#endif
}
void _lighting(vec3 coord) {
#ifndef TYPE_FLASH
- #ifdef PASS_COMPOSE
- vec3 lv0 = (uLightPos[0].xyz - coord) * uLightColor[0].w;
- vec3 lv1 = (uLightPos[1].xyz - coord) * uLightColor[1].w;
- vec3 lv2 = (uLightPos[2].xyz - coord) * uLightColor[2].w;
- vec3 lv3 = (uLightPos[3].xyz - coord) * uLightColor[3].w;
+ vec3 lv0 = (uLightPos[0].xyz - coord) * uLightColor[0].w;
+ vec3 lv1 = (uLightPos[1].xyz - coord) * uLightColor[1].w;
+ vec3 lv2 = (uLightPos[2].xyz - coord) * uLightColor[2].w;
+ vec3 lv3 = (uLightPos[3].xyz - coord) * uLightColor[3].w;
- #ifdef OPT_VLIGHTVEC
- vLightVec = lv0;
- #endif
+ #ifdef OPT_VLIGHTVEC
+ vLightVec = lv0;
+ #endif
- vec4 lum, att;
- #ifdef TYPE_ENTITY
- lum.x = dot(vNormal.xyz, normalize(lv0));
- att.x = dot(lv0, lv0);
- #else
- lum.x = 1.0;
- att.x = 0.0;
+ vec4 lum, att;
+ #ifdef TYPE_ENTITY
+ lum.x = dot(vNormal.xyz, normalize(lv0));
+ att.x = dot(lv0, lv0);
+ #else
+ lum.x = 1.0;
+ att.x = 0.0;
- #ifdef TYPE_SPRITE
- lum.x *= uMaterial.y;
- #endif
-
- #endif
-
- lum.y = dot(vNormal.xyz, normalize(lv1)); att.y = dot(lv1, lv1);
- lum.z = dot(vNormal.xyz, normalize(lv2)); att.z = dot(lv2, lv2);
- lum.w = dot(vNormal.xyz, normalize(lv3)); att.w = dot(lv3, lv3);
- vec4 light = max(vec4(0.0), lum) * max(vec4(0.0), vec4(1.0) - att);
-
- #if (defined(TYPE_ENTITY) || defined(TYPE_ROOM)) && defined(UNDERWATER)
- light.x *= 0.5 + abs(sin(dot(coord.xyz, vec3(1.0 / 1024.0)) + uParam.x)) * 0.75;
- #endif
-
- vec3 ambient;
- #ifdef TYPE_ENTITY
- #ifdef OPT_AMBIENT
- ambient = calcAmbient(vNormal.xyz);
- #else
- ambient = vec3(uMaterial.y);
- #endif
- #else
- ambient = min(uMaterial.yyy, aLight.xyz);
- #endif
-
- #ifdef OPT_SHADOW
- vAmbient = ambient;
- vLight = light;
- vLightMap = aLight.xyz * light.x;
-
- #ifdef OPT_VLIGHTPROJ
- vLightProj = calcLightProj(coord, lv0, vNormal.xyz);
- #endif
-
- #else
- vLight.xyz = uLightColor[1].xyz * light.y + uLightColor[2].xyz * light.z + uLightColor[3].xyz * light.w;
- vLight.w = 0.0;
-
- #ifdef TYPE_ENTITY
- vLight.xyz += ambient + uLightColor[0].xyz * light.x;
- #else
- vLight.xyz += aLight.xyz * light.x;
- #endif
+ #ifdef TYPE_SPRITE
+ lum.x *= uMaterial.y;
#endif
#endif
- #ifdef PASS_AMBIENT
- vLight = vec4(aLight.xyz, 1.0);
+ lum.y = dot(vNormal.xyz, normalize(lv1)); att.y = dot(lv1, lv1);
+ lum.z = dot(vNormal.xyz, normalize(lv2)); att.z = dot(lv2, lv2);
+ lum.w = dot(vNormal.xyz, normalize(lv3)); att.w = dot(lv3, lv3);
+ vec4 light = max(vec4(0.0), lum) * max(vec4(0.0), vec4(1.0) - att);
+
+ #if (defined(TYPE_ENTITY) || defined(TYPE_ROOM)) && defined(UNDERWATER)
+ light.x *= 0.5 + abs(sin(dot(coord.xyz, vec3(1.0 / 1024.0)) + uParam.x)) * 0.75;
+ #endif
+
+ vec3 ambient;
+ #ifdef TYPE_ENTITY
+ #ifdef OPT_AMBIENT
+ ambient = calcAmbient(vNormal.xyz);
+ #else
+ ambient = vec3(uMaterial.y);
+ #endif
+ #else
+ ambient = min(uMaterial.yyy, aLight.xyz);
+ #endif
+
+ #ifdef OPT_SHADOW
+ vAmbient = ambient;
+ vLight = light;
+ vLightMap = aLight.xyz * light.x;
+
+ #ifdef OPT_VLIGHTPROJ
+ vLightProj = calcLightProj(coord, lv0, vNormal.xyz);
+ #endif
+
+ #else
+ vLight.xyz = uLightColor[1].xyz * light.y + uLightColor[2].xyz * light.z + uLightColor[3].xyz * light.w;
+ vLight.w = 0.0;
+
+ #ifdef TYPE_ENTITY
+ vLight.xyz += ambient + uLightColor[0].xyz * light.x;
+ #else
+ vLight.xyz += aLight.xyz * light.x;
+ #endif
+
#endif
#endif
}
void _uv(vec3 coord) {
vTexCoord = aTexCoord;
- #if defined(PASS_COMPOSE) && !defined(TYPE_SPRITE)
+ #ifndef TYPE_SPRITE
#ifdef OPT_TRAPEZOID
vTexCoord.xy *= vTexCoord.zw;
#endif
@@ -264,27 +239,22 @@ uniform vec4 uFogParams;
void main() {
vec4 coord = _transform();
- #ifndef PASS_SHADOW
- _diffuse();
- _lighting(coord.xyz);
- #endif
+ _diffuse();
+ _lighting(coord.xyz);
_uv(coord.xyz);
gl_Position = uViewProj * coord;
}
+
#else
+
uniform sampler2D sDiffuse;
- #if defined(PASS_COMPOSE) && defined(TYPE_MIRROR)
+ #ifdef TYPE_MIRROR
uniform samplerCube sEnvironment;
#endif
- vec4 pack(float value) {
- vec4 v = fract(value * vec4(1.0, 255.0, 65025.0, 16581375.0));
- return v - v.yzww * vec4(1.0/255.0, 1.0/255.0, 1.0/255.0, 0.0);
- }
-
float unpack(vec4 value) {
return dot(value, vec4(1.0, 1.0/255.0, 1.0/65025.0, 1.0/16581375.0));
}
@@ -392,14 +362,10 @@ uniform vec4 uFogParams;
vec2 uv = vTexCoord.xy;
vec4 color;
#ifdef TYPE_MIRROR
- #ifdef PASS_COMPOSE
- vec3 rv = reflect(-normalize(vViewVec.xyz), normalize(vNormal.xyz));
- color = textureCube(sEnvironment, normalize(rv));
- #else
- color = vec4(1.0);
- #endif
+ vec3 rv = reflect(-normalize(vViewVec.xyz), normalize(vNormal.xyz));
+ color = textureCube(sEnvironment, normalize(rv));
#else
- #if defined(PASS_COMPOSE) && !defined(TYPE_SPRITE)
+ #ifndef TYPE_SPRITE
#ifdef OPT_TRAPEZOID
uv /= vTexCoord.zw;
#endif
@@ -413,107 +379,91 @@ uniform vec4 uFogParams;
discard;
#endif
- #ifdef PASS_SHADOW
+ color *= vDiffuse;
+
+ #if !defined(TYPE_FLASH) && !defined(TYPE_MIRROR)
+
+ #ifndef OPT_VLIGHTVEC
+ vec3 vLightVec = (uLightPos[0].xyz - vCoord) * uLightColor[0].w;
+ #endif
+
+ vec3 normal = normalize(vNormal.xyz);
+
+ #ifdef TYPE_ENTITY
+ float rSpecular = uMaterial.z;
+ #endif
+
+ #ifdef OPT_SHADOW
+ vec3 light = uLightColor[1].xyz * vLight.y + uLightColor[2].xyz * vLight.z + uLightColor[3].xyz * vLight.w;
+
+ #if defined(TYPE_ENTITY) || defined(TYPE_ROOM)
+ float rShadow = getShadow(vLightVec, normal);
+ #endif
+
+ #ifdef TYPE_ENTITY
+ rSpecular *= rShadow;
+ light += vAmbient + uLightColor[0].xyz * (vLight.x * rShadow);
+ #endif
+
+ #ifdef TYPE_ROOM
+ light += mix(vAmbient, vLightMap, rShadow);
+ #endif
+
+ #ifdef TYPE_SPRITE
+ light += vLightMap;
+ #endif
- #ifdef SHADOW_COLOR
- fragColor = pack(gl_FragCoord.z);
#else
- fragColor = vec4(1.0);
+ vec3 light = vLight.xyz;
#endif
- #else
- color *= vDiffuse;
-
- #if !defined(TYPE_FLASH) && !defined(TYPE_MIRROR)
-
- #ifdef PASS_AMBIENT
- color.xyz *= vLight.xyz;
+ #ifdef UNDERWATER
+ float uwSign = 1.0;
+ #ifdef TYPE_ENTITY
+ uwSign = step(uParam.y, vCoord.y);
#endif
- #ifdef PASS_COMPOSE
-
- #ifndef OPT_VLIGHTVEC
- vec3 vLightVec = (uLightPos[0].xyz - vCoord) * uLightColor[0].w;
- #endif
-
- vec3 normal = normalize(vNormal.xyz);
-
- #ifdef TYPE_ENTITY
- float rSpecular = uMaterial.z;
- #endif
-
- #ifdef OPT_SHADOW
- vec3 light = uLightColor[1].xyz * vLight.y + uLightColor[2].xyz * vLight.z + uLightColor[3].xyz * vLight.w;
-
- #if defined(TYPE_ENTITY) || defined(TYPE_ROOM)
- float rShadow = getShadow(vLightVec, normal);
- #endif
-
- #ifdef TYPE_ENTITY
- rSpecular *= rShadow;
- light += vAmbient + uLightColor[0].xyz * (vLight.x * rShadow);
- #endif
-
- #ifdef TYPE_ROOM
- light += mix(vAmbient, vLightMap, rShadow);
- #endif
-
- #ifdef TYPE_SPRITE
- light += vLightMap;
- #endif
-
- #else
- vec3 light = vLight.xyz;
- #endif
-
- #ifdef UNDERWATER
- float uwSign = 1.0;
- #ifdef TYPE_ENTITY
- uwSign = step(uParam.y, vCoord.y);
- #endif
-
- #ifdef OPT_CAUSTICS
- light += calcCaustics(normal) * uwSign;
- #endif
- #endif
-
- #ifdef OPT_CONTACT
- light *= getContactAO(vCoord, normal) * 0.5 + 0.5;
- #endif
-
- color.xyz *= light;
-
- #if defined(TYPE_ENTITY) && defined(OPT_UNDERWATER_FOG)
- float specular = calcSpecular(normal, vViewVec.xyz, vLightVec, uLightColor[0], rSpecular);
- #ifdef UNDERWATER
- specular *= (1.0 - uwSign);
- #endif
- color.xyz += specular;
- #endif
-
- #ifdef UNDERWATER
- #ifdef OPT_UNDERWATER_FOG
- float dist;
- if (uViewPos.y < uParam.y)
- dist = abs((vCoord.y - uParam.y) / normalize(uViewPos.xyz - vCoord.xyz).y);
- else
- dist = length(uViewPos.xyz - vCoord.xyz);
- float fog = clamp(1.0 / exp(dist * WATER_FOG_DIST * uwSign), 0.0, 1.0);
- dist += vCoord.y - uParam.y;
- color.xyz *= mix(vec3(1.0), UNDERWATER_COLOR, clamp(dist * WATER_COLOR_DIST * uwSign, 0.0, 2.0));
- color.xyz = mix(UNDERWATER_COLOR * 0.2, color.xyz, fog);
- #else
- color.xyz = mix(color.xyz, color.xyz * UNDERWATER_COLOR, uwSign);
- color.xyz = mix(uFogParams.xyz, color.xyz, vNormal.w);
- #endif
- #else
- color.xyz = mix(uFogParams.xyz, color.xyz, vNormal.w);
- #endif
+ #ifdef OPT_CAUSTICS
+ light += calcCaustics(normal) * uwSign;
#endif
#endif
- fragColor = color;
+ #ifdef OPT_CONTACT
+ light *= getContactAO(vCoord, normal) * 0.5 + 0.5;
+ #endif
+
+ color.xyz *= light;
+
+ #if defined(TYPE_ENTITY) && defined(OPT_UNDERWATER_FOG)
+ float specular = calcSpecular(normal, vViewVec.xyz, vLightVec, uLightColor[0], rSpecular);
+ #ifdef UNDERWATER
+ specular *= (1.0 - uwSign);
+ #endif
+ color.xyz += specular;
+ #endif
+
+ #ifdef UNDERWATER
+ #ifdef OPT_UNDERWATER_FOG
+ float dist;
+ if (uViewPos.y < uParam.y)
+ dist = abs((vCoord.y - uParam.y) / normalize(uViewPos.xyz - vCoord.xyz).y);
+ else
+ dist = length(uViewPos.xyz - vCoord.xyz);
+ float fog = clamp(1.0 / exp(dist * WATER_FOG_DIST * uwSign), 0.0, 1.0);
+ dist += vCoord.y - uParam.y;
+ color.xyz *= mix(vec3(1.0), UNDERWATER_COLOR, clamp(dist * WATER_COLOR_DIST * uwSign, 0.0, 2.0));
+ color.xyz = mix(UNDERWATER_COLOR * 0.2, color.xyz, fog);
+ #else
+ color.xyz = mix(color.xyz, color.xyz * UNDERWATER_COLOR, uwSign);
+ color.xyz = mix(UNDERWATER_COLOR * 0.2, color.xyz, vNormal.w);
+ #endif
+ #else
+ color.xyz = mix(uFogParams.xyz, color.xyz, vNormal.w);
+ #endif
#endif
+
+ fragColor = color;
}
+
#endif
)===="
diff --git a/src/shaders/shadow.glsl b/src/shaders/shadow.glsl
new file mode 100644
index 0000000..13b3c04
--- /dev/null
+++ b/src/shaders/shadow.glsl
@@ -0,0 +1,60 @@
+R"====(
+#ifdef ALPHA_TEST
+ varying vec2 vTexCoord;
+#endif
+
+#ifdef VERTEX
+
+ uniform mat4 uViewProj;
+ uniform vec4 uBasis[32 * 2];
+
+ attribute vec4 aCoord;
+ #ifdef ALPHA_TEST
+ attribute vec4 aTexCoord;
+ #endif
+
+ vec3 mulQuat(vec4 q, vec3 v) {
+ return v + 2.0 * cross(q.xyz, cross(q.xyz, v) + v * q.w);
+ }
+
+ vec3 mulBasis(vec4 rot, vec3 pos, vec3 v) {
+ return mulQuat(rot, v) + pos;
+ }
+
+ void main() {
+ int index = int(aCoord.w * 2.0);
+ vec4 rBasisRot = uBasis[index];
+ vec4 rBasisPos = uBasis[index + 1];
+ #ifdef ALPHA_TEST
+ vTexCoord = aTexCoord.xy;
+ #endif
+ vec3 coord = mulBasis(rBasisRot, rBasisPos.xyz, aCoord.xyz);
+ gl_Position = uViewProj * vec4(coord, rBasisPos.w);
+ }
+
+#else
+
+ #ifdef ALPHA_TEST
+ uniform sampler2D sDiffuse;
+ #endif
+
+ vec4 pack(float value) {
+ vec4 v = fract(value * vec4(1.0, 255.0, 65025.0, 16581375.0));
+ return v - v.yzww * vec4(1.0/255.0, 1.0/255.0, 1.0/255.0, 0.0);
+ }
+
+ void main() {
+ #ifdef ALPHA_TEST
+ if (texture2D(sDiffuse, vTexCoord).w <= 0.5)
+ discard;
+ #endif
+
+ #ifdef SHADOW_COLOR
+ fragColor = pack(gl_FragCoord.z);
+ #else
+ fragColor = vec4(1.0);
+ #endif
+ }
+
+#endif
+)===="