From 0ad35ea26df6031b2747b56a36ac5e06f8a66bde Mon Sep 17 00:00:00 2001 From: XProger Date: Sat, 16 Feb 2019 03:59:52 +0300 Subject: [PATCH] split GLSL uber-shader by passes --- src/cache.h | 9 +- src/core.h | 2 - src/gapi_gl.h | 41 ++- src/level.h | 50 ++- src/platform/win/OpenLara.vcxproj | 4 +- src/platform/win/OpenLara.vcxproj.filters | 10 +- src/shaders/ambient.glsl | 69 ++++ src/shaders/{shader.glsl => compose.glsl} | 412 ++++++++++------------ src/shaders/shadow.glsl | 60 ++++ 9 files changed, 385 insertions(+), 272 deletions(-) create mode 100644 src/shaders/ambient.glsl rename src/shaders/{shader.glsl => compose.glsl} (52%) create mode 100644 src/shaders/shadow.glsl 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 +)===="