- remaining parts of GLES.

This commit is contained in:
Christoph Oelckers 2021-09-18 13:03:36 +02:00
parent a3d9cd9a68
commit 01e9d8e5e1
53 changed files with 3050 additions and 7 deletions

View file

@ -191,6 +191,7 @@ if( ${TARGET_ARCHITECTURE} MATCHES "x86_64" )
endif()
option (HAVE_VULKAN "Enable Vulkan support" ON)
option (HAVE_GLES2 "Enable GLES2 support" ON)
# no, we're not using external asmjit for now, we made too many modifications to our's.
# if the asmjit author uses our changes then we'll update this.
@ -207,10 +208,14 @@ if( MSVC )
# String pooling
# Function-level linking
# Disable run-time type information
set( ALL_C_FLAGS "/GF /Gy /permissive-" )
if ( HAVE_VULKAN )
set( ALL_C_FLAGS "/GF /Gy /permissive- /DHAVE_VULKAN" )
else()
set( ALL_C_FLAGS "/GF /Gy /permissive-" )
set( ALL_C_FLAGS "${ALL_C_FLAGS} /DHAVE_VULKAN" )
endif()
if ( HAVE_GLES2 )
set( ALL_C_FLAGS "${ALL_C_FLAGS} /DHAVE_GLES2" )
endif()
# Use SSE 2 as minimum always as the true color drawers needs it for __vectorcall
@ -253,12 +258,15 @@ if( MSVC )
string(REPLACE " /GR" " " CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} )
else()
set( REL_LINKER_FLAGS "" )
set( ALL_C_FLAGS "-ffp-contract=off" )
if ( HAVE_VULKAN )
set( ALL_C_FLAGS "-ffp-contract=off -DHAVE_VULKAN" )
else()
set( ALL_C_FLAGS "-ffp-contract=off" )
set( ALL_C_FLAGS "${ALL_C_FLAGS} -DHAVE_VULKAN" )
endif()
if ( HAVE_GLES2 )
set( ALL_C_FLAGS "${ALL_C_FLAGS} -DHAVE_GLES2" )
endif()
set( ALL_C_FLAGS "${ALL_C_FLAGS} -DUSE_OPENGL=1 -DNOASM=1" )
if ( UNIX )
include(CheckSymbolExists)

View file

@ -967,6 +967,26 @@ set (VULKAN_SOURCES
common/rendering/vulkan/thirdparty/vk_mem_alloc/vk_mem_alloc.cpp
)
if (HAVE_GLES2)
set (GLES_SOURCES
common/rendering/gles/gles_system.cpp
common/rendering/gles/gles_renderer.cpp
common/rendering/gles/gles_framebuffer.cpp
common/rendering/gles/gles_renderstate.cpp
common/rendering/gles/gles_renderbuffers.cpp
common/rendering/gles/gles_postprocess.cpp
common/rendering/gles/gles_postprocessstate.cpp
common/rendering/gles/gles_buffers.cpp
common/rendering/gles/gles_hwtexture.cpp
common/rendering/gles/gles_shader.cpp
common/rendering/gles/gles_shaderprogram.cpp
common/rendering/gles/gles_samplers.cpp
common/rendering/gles/glad/src/glad.c
)
set (FASTMATH_SOURCES ${FASTMATH_SOURCES} ${GLES_SOURCES})
endif()
if (HAVE_VULKAN)
set (FASTMATH_SOURCES ${FASTMATH_SOURCES} ${VULKAN_SOURCES})
endif()
@ -1381,6 +1401,9 @@ include_directories(
common/rendering/hwrenderer/data
common/rendering/gl_load
common/rendering/gl
common/rendering/gles
common/rendering/gles/glad/include
common/rendering/gles/Mali_OpenGL_ES_Emulator/include
common/rendering/vulkan/thirdparty
common/rendering/polyrenderer/backend
common/rendering/polyrenderer/drawers
@ -1546,6 +1569,7 @@ source_group("Common\\Rendering\\Hardware Renderer\\Data" REGULAR_EXPRESSION "^$
source_group("Common\\Rendering\\Hardware Renderer\\Postprocessing" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/rendering/hwrenderer/postprocessing/.+")
source_group("Common\\Rendering\\OpenGL Loader" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/rendering/gl_load/.+")
source_group("Common\\Rendering\\OpenGL Backend" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/rendering/gl/.+")
source_group("Common\\Rendering\\GLES Backend" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/rendering/gles/.+")
source_group("Common\\Rendering\\Vulkan Renderer\\System" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/rendering/vulkan/system/.+")
source_group("Common\\Rendering\\Vulkan Renderer\\Renderer" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/rendering/vulkan/renderer/.+")
source_group("Common\\Rendering\\Vulkan Renderer\\Shaders" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/rendering/vulkan/shaders/.+")

View file

@ -27,7 +27,12 @@ BEGIN
DEFPUSHBUTTON "&Play Game!",IDOK,8,228,90,14
PUSHBUTTON "E&xit",IDCANCEL,166,228,50,14
CONTROL "&OpenGL",IDC_WELCOME_VULKAN1,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,13,167,41,10
#ifdef HAVE_VULKAN
CONTROL "&Vulkan",IDC_WELCOME_VULKAN2,"Button",BS_AUTORADIOBUTTON,13,177,37,10
#endif
#ifdef HAVE_GLES2
CONTROL "OpenGL &ES",IDC_WELCOME_VULKAN4,"Button",BS_AUTORADIOBUTTON,13,187,53,10
#endif
END
IDD_CRASHDIALOG DIALOGEX 0, 0, 415, 308

View file

@ -0,0 +1,90 @@
How can I remove the alpha test discard?
MISSING:
All post processing gone
Present shader missing dither
Shadow maps gone
HDR modes gone
Materials gone
gl_satformula does not do anything (remove an 'if' in shader)
Broken to be fixed:
Texture filtering modes, currently fixed to linear mipmap
--------------------------------------
uTextureMode
0xFFFF =
(USES all)
TM_NORMAL = 0, // (r, g, b, a)
TM_STENCIL, // (1, 1, 1, a)
TM_OPAQUE, // (r, g, b, 1)
TM_INVERSE, // (1-r, 1-g, 1-b, a)
TM_ALPHATEXTURE, // (1, 1, 1, r)
TM_CLAMPY, // (r, g, b, (t >= 0.0 && t <= 1.0)? a:0)
TM_INVERTOPAQUE, // (1-r, 1-g, 1-b, 1)
TM_FOGLAYER, // (renders a fog layer in the shape of the active texture)
TM_FIXEDCOLORMAP = TM_FOGLAYER,
0xF0000 =
(USES all)
TEXF_Brightmap = 0x10000,
TEXF_Detailmap = 0x20000,
TEXF_Glowmap = 0x40000,
uPalLightLevels
0xFF =
32 0r 0 or 1
0xFF00 =
gl_fogmode :
(USES 2)
0, "$OPTVAL_OFF"
1, "$OPTVAL_STANDARD"
2, "$OPTVAL_RADIAL"
0xFF0000
gl_lightmode:
(USES 16, 5)
0, "$OPTVAL_STANDARD"
1, "$OPTVAL_BRIGHT"
2, "$OPTVAL_DOOM"
3, "$OPTVAL_DARK"
4, "$OPTVAL_LEGACY"
5, "$OPTVAL_BUILD"
8, "$OPTVAL_SOFTWARE"
16, "$OPTVAL_VANILLA"
uTextureAddColor.a -> blendflags
0x7 =
(USES all)
const int Tex_Blend_Alpha = 1;
const int Tex_Blend_Screen = 2;
const int Tex_Blend_Overlay = 3;
const int Tex_Blend_Hardlight = 4;
0x8 =
Invert blend bit
uDesaturationFactor
> 0

View file

@ -0,0 +1,13 @@
varying vec4 vTexCoord;
varying vec4 vColor;
void main()
{
vec4 frag = vColor;
vec4 t1 = texture2D(tex, vTexCoord.xy);
vec4 t2 = texture2D(texture2, vec2(vTexCoord.x, 1.0-vTexCoord.y));
gl_FragColor = frag * vec4(t1.r, t1.g, t1.b, t2.a);
}

View file

@ -0,0 +1,30 @@
varying vec4 pixelpos;
//===========================================================================
//
// Main shader routine
//
//===========================================================================
void main()
{
float fogdist;
float fogfactor;
//
// calculate fog factor
//
#if (DEF_FOG_ENABLED == 1) && (DEF_FOG_RADIAL == 0) && (DEF_FOG_COLOURED == 1) // This was uFogEnabled = -1,, TODO check this
{
fogdist = pixelpos.w;
}
#else
{
fogdist = max(16.0, distance(pixelpos.xyz, uCameraPos.xyz));
}
#endif
fogfactor = exp2 (uFogDensity * fogdist);
gl_FragColor = vec4(uFogColor.rgb, 1.0 - fogfactor);
}

View file

@ -0,0 +1,5 @@
vec4 ProcessLight(Material material, vec4 color)
{
return color;
}

View file

@ -0,0 +1,7 @@
void SetupMaterial(inout Material material)
{
material.Base = ProcessTexel();
material.Normal = ApplyNormalMap(vTexCoord.st);
material.Bright = texture2D(brighttexture, vTexCoord.st);
}

View file

@ -0,0 +1,6 @@
void SetupMaterial(inout Material material)
{
vec2 texCoord = GetTexCoord();
SetMaterialProps(material, texCoord);
}

View file

@ -0,0 +1,5 @@
void SetupMaterial(inout Material material)
{
SetMaterialProps(material, vTexCoord.st);
}

View file

@ -0,0 +1,6 @@
vec4 ProcessTexel()
{
return desaturate(uObjectColor);
}

View file

@ -0,0 +1,10 @@
vec4 ProcessTexel()
{
float index = getTexel(vTexCoord.st).r;
index = ((index * 255.0) + 0.5) / 256.0;
vec4 tex = texture2D(texture2, vec2(index, 0.5));
tex.a = 1.0;
return tex;
}

View file

@ -0,0 +1,5 @@
void SetupMaterial(inout Material material)
{
SetMaterialProps(material, vTexCoord.st);
}

View file

@ -0,0 +1,8 @@
void SetupMaterial(inout Material material)
{
SetMaterialProps(material, vTexCoord.st);
material.Specular = texture2D(speculartexture, vTexCoord.st).rgb;
material.Glossiness = uSpecularMaterial.x;
material.SpecularLevel = uSpecularMaterial.y;
}

View file

@ -0,0 +1,19 @@
vec2 GetTexCoord()
{
vec2 texCoord = vTexCoord.st;
const float pi = 3.14159265358979323846;
vec2 offset = vec2(0,0);
offset.y = sin(pi * 2.0 * (texCoord.x + timer * 0.125)) * 0.1;
offset.x = sin(pi * 2.0 * (texCoord.y + timer * 0.125)) * 0.1;
return texCoord + offset;
}
vec4 ProcessTexel()
{
return getTexel(GetTexCoord());
}

View file

@ -0,0 +1,20 @@
vec2 GetTexCoord()
{
vec2 texCoord = vTexCoord.st;
const float pi = 3.14159265358979323846;
vec2 offset = vec2(0.0,0.0);
offset.y = 0.5 + sin(pi * 2.0 * (texCoord.y + timer * 0.61 + 900.0/8192.0)) + sin(pi * 2.0 * (texCoord.x * 2.0 + timer * 0.36 + 300.0/8192.0));
offset.x = 0.5 + sin(pi * 2.0 * (texCoord.y + timer * 0.49 + 700.0/8192.0)) + sin(pi * 2.0 * (texCoord.x * 2.0 + timer * 0.49 + 1200.0/8192.0));
return texCoord + offset * 0.025;
}
vec4 ProcessTexel()
{
return getTexel(GetTexCoord());
}

View file

@ -0,0 +1,21 @@
vec2 GetTexCoord()
{
vec2 texCoord = vTexCoord.st;
const float pi = 3.14159265358979323846;
vec2 offset = vec2(0.0,0.0);
float siny = sin(pi * 2.0 * (texCoord.y * 2.0 + timer * 0.75)) * 0.03;
offset.y = siny + sin(pi * 2.0 * (texCoord.x + timer * 0.75)) * 0.03;
offset.x = siny + sin(pi * 2.0 * (texCoord.x + timer * 0.45)) * 0.02;
return texCoord + offset;
}
vec4 ProcessTexel()
{
return getTexel(GetTexCoord());
}

View file

@ -0,0 +1,17 @@
vec2 GetTexCoord()
{
vec2 texCoord = vTexCoord.st;
const float pi = 3.14159265358979323846;
texCoord.x += sin(pi * 2.0 * (texCoord.y + timer * 0.125)) * 0.1;
return texCoord;
}
vec4 ProcessTexel()
{
return getTexel(GetTexCoord());
}

View file

@ -0,0 +1,24 @@
//created by Evil Space Tomato
vec4 ProcessTexel()
{
vec2 texCoord = vTexCoord.st;
vec2 texSplat;
const float pi = 3.14159265358979323846;
texSplat.x = texCoord.x + mod(sin(pi * 2.0 * (texCoord.y + timer * 2.0)),0.1) * 0.1;
texSplat.y = texCoord.y + mod(cos(pi * 2.0 * (texCoord.x + timer * 2.0)),0.1) * 0.1;
vec4 basicColor = getTexel(texSplat);
float texX = sin(texCoord.x * 100.0 + timer*5.0);
float texY = cos(texCoord.x * 100.0 + timer*5.0);
float vX = (texX/texY)*21.0;
float vY = (texY/texX)*13.0;
float test = mod(timer*2.0+(vX + vY), 0.5);
basicColor.a = basicColor.a * test;
return basicColor;
}

View file

@ -0,0 +1,20 @@
//created by Evil Space Tomato
vec4 ProcessTexel()
{
vec2 texCoord = vTexCoord.st;
vec4 basicColor = getTexel(texCoord);
texCoord.x = float( int(texCoord.x * 128.0) ) / 128.0;
texCoord.y = float( int(texCoord.y * 128.0) ) / 128.0;
float texX = sin(mod(texCoord.x * 100.0 + timer*5.0, 3.489)) + texCoord.x / 4.0;
float texY = cos(mod(texCoord.y * 100.0 + timer*5.0, 3.489)) + texCoord.y / 4.0;
float vX = (texX/texY)*21.0;
float vY = (texY/texX)*13.0;
float test = mod(timer*2.0+(vX + vY), 0.5);
basicColor.a = basicColor.a * test;
basicColor.rgb = vec3(0.0,0.0,0.0);
return basicColor;
}

View file

@ -0,0 +1,18 @@
//created by Evil Space Tomato
vec4 ProcessTexel()
{
vec2 texCoord = vTexCoord.st;
vec4 basicColor = getTexel(texCoord);
float texX = texCoord.x / 3.0 + 0.66;
float texY = 0.34 - texCoord.y / 3.0;
float vX = (texX/texY)*21.0;
float vY = (texY/texX)*13.0;
float test = mod(timer*2.0+(vX + vY), 0.5);
basicColor.a = basicColor.a * test;
basicColor.r = basicColor.g = basicColor.b = 0.0;
return basicColor;
}

View file

@ -0,0 +1,19 @@
//created by Evil Space Tomato
vec4 ProcessTexel()
{
vec2 texCoord = vTexCoord.st;
vec4 basicColor = getTexel(texCoord);
float texX = sin(mod(texCoord.x * 100.0 + timer*5.0, 3.489)) + texCoord.x / 4.0;
float texY = cos(mod(texCoord.y * 100.0 + timer*5.0, 3.489)) + texCoord.y / 4.0;
float vX = (texX/texY)*21.0;
float vY = (texY/texX)*13.0;
float test = mod(timer*2.0+(vX + vY), 0.5);
basicColor.a = basicColor.a * test;
basicColor.rgb = vec3(0.0,0.0,0.0);
return basicColor;
}

View file

@ -0,0 +1,18 @@
//created by Evil Space Tomato
vec4 ProcessTexel()
{
vec2 texCoord = vTexCoord.st;
vec4 basicColor = getTexel(texCoord);
float texX = sin(texCoord.x * 100.0 + timer*5.0);
float texY = cos(texCoord.x * 100.0 + timer*5.0);
float vX = (texX/texY)*21.0;
float vY = (texY/texX)*13.0;
float test = mod(timer*2.0+(vX + vY), 0.5);
basicColor.a = basicColor.a * test;
return basicColor;
}

View file

@ -0,0 +1,21 @@
//created by Evil Space Tomato
vec4 ProcessTexel()
{
vec2 texCoord = vTexCoord.st;
vec4 basicColor = getTexel(texCoord);
texCoord.x = float( int(texCoord.x * 128.0) ) / 128.0;
texCoord.y = float( int(texCoord.y * 128.0) ) / 128.0;
float texX = texCoord.x / 3.0 + 0.66;
float texY = 0.34 - texCoord.y / 3.0;
float vX = (texX/texY)*21.0;
float vY = (texY/texX)*13.0;
float test = mod(timer*2.0+(vX + vY), 0.5);
basicColor.a = basicColor.a * test;
basicColor.r = basicColor.g = basicColor.b = 0.0;
return basicColor;
}

View file

@ -0,0 +1,21 @@
//created by Evil Space Tomato
vec4 ProcessTexel()
{
vec2 texCoord = vTexCoord.st;
vec4 basicColor = getTexel(texCoord);
texCoord.x = float( int(texCoord.x * 128.0) ) / 128.0;
texCoord.y = float( int(texCoord.y * 128.0) ) / 128.0;
float texX = texCoord.x / 3.0 + 0.66;
float texY = 0.34 - texCoord.y / 3.0;
float vX = (texX/texY)*21.0;
float vY = (texY/texX)*13.0;
float test = mod(timer*2.0+(vX + vY), 0.5);
basicColor.a = basicColor.a * test;
basicColor.r = basicColor.g = basicColor.b = 0.0;
return basicColor;
}

View file

@ -0,0 +1,18 @@
//created by Evil Space Tomato
vec4 ProcessTexel()
{
vec2 texCoord = vTexCoord.st;
vec4 basicColor = getTexel(texCoord);
float texX = sin(texCoord.x * 100.0 + timer*5.0);
float texY = cos(texCoord.x * 100.0 + timer*5.0);
float vX = (texX/texY)*21.0;
float vY = (texY/texX)*13.0;
float test = mod(timer*2.0+(vX + vY), 0.5);
basicColor.a = basicColor.a * test;
basicColor.r = basicColor.g = basicColor.b = 0.0;
return basicColor;
}

View file

@ -0,0 +1,566 @@
varying vec4 vTexCoord;
varying vec4 vColor;
varying vec4 pixelpos;
varying vec3 glowdist;
varying vec3 gradientdist;
varying vec4 vWorldNormal;
varying vec4 vEyeNormal;
#ifdef NO_CLIPDISTANCE_SUPPORT
varying vec4 ClipDistanceA;
varying vec4 ClipDistanceB;
#endif
struct Material
{
vec4 Base;
vec4 Bright;
vec4 Glow;
vec3 Normal;
vec3 Specular;
float Glossiness;
float SpecularLevel;
};
vec4 Process(vec4 color);
vec4 ProcessTexel();
Material ProcessMaterial(); // note that this is deprecated. Use SetupMaterial!
void SetupMaterial(inout Material mat);
vec4 ProcessLight(Material mat, vec4 color);
vec3 ProcessMaterialLight(Material material, vec3 color);
vec2 GetTexCoord();
// These get Or'ed into uTextureMode because it only uses its 3 lowermost bits.
//const int TEXF_Brightmap = 0x10000;
//const int TEXF_Detailmap = 0x20000;
//const int TEXF_Glowmap = 0x40000;
//===========================================================================
//
// Color to grayscale
//
//===========================================================================
float grayscale(vec4 color)
{
return dot(color.rgb, vec3(0.3, 0.56, 0.14));
}
//===========================================================================
//
// Desaturate a color
//
//===========================================================================
vec4 dodesaturate(vec4 texel, float factor)
{
if (factor != 0.0)
{
float gray = grayscale(texel);
return mix (texel, vec4(gray,gray,gray,texel.a), factor);
}
else
{
return texel;
}
}
//===========================================================================
//
// Desaturate a color
//
//===========================================================================
vec4 desaturate(vec4 texel)
{
#if (DEF_DO_DESATURATE == 1)
return dodesaturate(texel, uDesaturationFactor);
#else
return texel;
#endif
}
//===========================================================================
//
// Texture tinting code originally from JFDuke but with a few more options
//
//===========================================================================
const int Tex_Blend_Alpha = 1;
const int Tex_Blend_Screen = 2;
const int Tex_Blend_Overlay = 3;
const int Tex_Blend_Hardlight = 4;
vec4 ApplyTextureManipulation(vec4 texel)
{
// Step 1: desaturate according to the material's desaturation factor.
texel = dodesaturate(texel, uTextureModulateColor.a);
// Step 2: Invert if requested // TODO FIX
//if ((blendflags & 8) != 0)
//{
// texel.rgb = vec3(1.0 - texel.r, 1.0 - texel.g, 1.0 - texel.b);
//}
// Step 3: Apply additive color
texel.rgb += uTextureAddColor.rgb;
// Step 4: Colorization, including gradient if set.
texel.rgb *= uTextureModulateColor.rgb;
// Before applying the blend the value needs to be clamped to [0..1] range.
texel.rgb = clamp(texel.rgb, 0.0, 1.0);
// Step 5: Apply a blend. This may just be a translucent overlay or one of the blend modes present in current Build engines.
#if (DEF_BLEND_FLAGS != 0)
vec3 tcol = texel.rgb * 255.0; // * 255.0 to make it easier to reuse the integer math.
vec4 tint = uTextureBlendColor * 255.0;
#if (DEF_BLEND_FLAGS == 1)
tcol.b = tcol.b * (1.0 - uTextureBlendColor.a) + tint.b * uTextureBlendColor.a;
tcol.g = tcol.g * (1.0 - uTextureBlendColor.a) + tint.g * uTextureBlendColor.a;
tcol.r = tcol.r * (1.0 - uTextureBlendColor.a) + tint.r * uTextureBlendColor.a;
#elif (DEF_BLEND_FLAGS == 2) // Tex_Blend_Screen:
tcol.b = 255.0 - (((255.0 - tcol.b) * (255.0 - tint.r)) / 256.0);
tcol.g = 255.0 - (((255.0 - tcol.g) * (255.0 - tint.g)) / 256.0);
tcol.r = 255.0 - (((255.0 - tcol.r) * (255.0 - tint.b)) / 256.0);
#elif (DEF_BLEND_FLAGS == 3) // Tex_Blend_Overlay:
tcol.b = tcol.b < 128.0? (tcol.b * tint.b) / 128.0 : 255.0 - (((255.0 - tcol.b) * (255.0 - tint.b)) / 128.0);
tcol.g = tcol.g < 128.0? (tcol.g * tint.g) / 128.0 : 255.0 - (((255.0 - tcol.g) * (255.0 - tint.g)) / 128.0);
tcol.r = tcol.r < 128.0? (tcol.r * tint.r) / 128.0 : 255.0 - (((255.0 - tcol.r) * (255.0 - tint.r)) / 128.0);
#elif (DEF_BLEND_FLAGS == 4) // Tex_Blend_Hardlight:
tcol.b = tint.b < 128.0 ? (tcol.b * tint.b) / 128.0 : 255.0 - (((255.0 - tcol.b) * (255.0 - tint.b)) / 128.0);
tcol.g = tint.g < 128.0 ? (tcol.g * tint.g) / 128.0 : 255.0 - (((255.0 - tcol.g) * (255.0 - tint.g)) / 128.0);
tcol.r = tint.r < 128.0 ? (tcol.r * tint.r) / 128.0 : 255.0 - (((255.0 - tcol.r) * (255.0 - tint.r)) / 128.0);
#endif
texel.rgb = tcol / 255.0;
#endif
return texel;
}
//===========================================================================
//
// This function is common for all (non-special-effect) fragment shaders
//
//===========================================================================
vec4 getTexel(vec2 st)
{
vec4 texel = texture2D(tex, st);
#if (DEF_TEXTURE_MODE == 1)
texel.rgb = vec3(1.0,1.0,1.0);
#elif (DEF_TEXTURE_MODE == 2)// TM_OPAQUE
texel.a = 1.0;
#elif (DEF_TEXTURE_MODE == 3)// TM_INVERSE
texel = vec4(1.0-texel.r, 1.0-texel.b, 1.0-texel.g, texel.a);
#elif (DEF_TEXTURE_MODE == 4)// TM_ALPHATEXTURE
float gray = grayscale(texel);
texel = vec4(1.0, 1.0, 1.0, gray*texel.a);
#elif (DEF_TEXTURE_MODE == 5)// TM_CLAMPY
if (st.t < 0.0 || st.t > 1.0)
{
texel.a = 0.0;
}
#elif (DEF_TEXTURE_MODE == 6)// TM_OPAQUEINVERSE
texel = vec4(1.0-texel.r, 1.0-texel.b, 1.0-texel.g, 1.0);
#elif (DEF_TEXTURE_MODE == 7)//TM_FOGLAYER
return texel;
#endif
// Apply the texture modification colors.
#if (DEF_BLEND_FLAGS != 0)
// only apply the texture manipulation if it contains something.
texel = ApplyTextureManipulation(texel, DEF_BLEND_FLAGS);
#endif
// Apply the Doom64 style material colors on top of everything from the texture modification settings.
// This may be a bit redundant in terms of features but the data comes from different sources so this is unavoidable.
texel.rgb += uAddColor.rgb;
#if (DEF_USE_OBJECT_COLOR_2 == 1)
texel *= mix(uObjectColor, uObjectColor2, gradientdist.z);
#else
texel *= uObjectColor;
#endif
// Last but not least apply the desaturation from the sector's light.
return desaturate(texel);
}
//===========================================================================
//
// Doom software lighting equation
//
//===========================================================================
#define DOOMLIGHTFACTOR 232.0
float R_DoomLightingEquation_OLD(float light)
{
// z is the depth in view space, positive going into the screen
float z = pixelpos.w;
/* L in the range 0 to 63 */
float L = light * 63.0/31.0;
float min_L = clamp(36.0/31.0 - L, 0.0, 1.0);
// Fix objects getting totally black when close.
if (z < 0.0001)
z = 0.0001;
float scale = 1.0 / z;
float index = (59.0/31.0 - L) - (scale * DOOMLIGHTFACTOR/31.0 - DOOMLIGHTFACTOR/31.0);
// Result is the normalized colormap index (0 bright .. 1 dark)
return clamp(index, min_L, 1.0) / 32.0;
}
//===========================================================================
//
// zdoom colormap equation
//
//===========================================================================
float R_ZDoomColormap(float light, float z)
{
float L = light * 255.0;
float vis = min(uGlobVis / z, 24.0 / 32.0);
float shade = 2.0 - (L + 12.0) / 128.0;
float lightscale = shade - vis;
return lightscale * 31.0;
}
//===========================================================================
//
// Doom software lighting equation
//
//===========================================================================
float R_DoomLightingEquation(float light)
{
// z is the depth in view space, positive going into the screen
float z;
#if (DEF_FOG_RADIAL == 1)
z = distance(pixelpos.xyz, uCameraPos.xyz);
#else
z = pixelpos.w;
#endif
#if (DEF_BUILD_LIGHTING == 1) // gl_lightmode 5: Build software lighting emulation.
// This is a lot more primitive than Doom's lighting...
float numShades = float(uPalLightLevels);
float curshade = (1.0 - light) * (numShades - 1.0);
float visibility = max(uGlobVis * uLightFactor * abs(z), 0.0);
float shade = clamp((curshade + visibility), 0.0, numShades - 1.0);
return clamp(shade * uLightDist, 0.0, 1.0);
#endif
float colormap = R_ZDoomColormap(light, z); // ONLY Software mode, vanilla not yet working
#if (DEF_BANDED_SW_LIGHTING == 1)
colormap = floor(colormap) + 0.5;
#endif
// Result is the normalized colormap index (0 bright .. 1 dark)
return clamp(colormap, 0.0, 31.0) / 32.0;
}
float shadowAttenuation(vec4 lightpos, float lightcolorA)
{
return 1.0;
}
float spotLightAttenuation(vec4 lightpos, vec3 spotdir, float lightCosInnerAngle, float lightCosOuterAngle)
{
vec3 lightDirection = normalize(lightpos.xyz - pixelpos.xyz);
float cosDir = dot(lightDirection, spotdir);
return smoothstep(lightCosOuterAngle, lightCosInnerAngle, cosDir);
}
vec3 ApplyNormalMap(vec2 texcoord)
{
return normalize(vWorldNormal.xyz);
}
//===========================================================================
//
// Sets the common material properties.
//
//===========================================================================
void SetMaterialProps(inout Material material, vec2 texCoord)
{
#ifdef NPOT_EMULATION
#if (DEF_NPOT_EMULATION == 1)
float period = floor(texCoord.t / uNpotEmulation.y);
texCoord.s += uNpotEmulation.x * floor(mod(texCoord.t, uNpotEmulation.y));
texCoord.t = period + mod(texCoord.t, uNpotEmulation.y);
#endif
#endif
material.Base = getTexel(texCoord.st);
material.Normal = ApplyNormalMap(texCoord.st);
#if (DEF_TEXTURE_FLAGS & 0x1)
material.Bright = texture2D(brighttexture, texCoord.st);
#endif
#if (DEF_TEXTURE_FLAGS & 0x2)
{
vec4 Detail = texture2D(detailtexture, texCoord.st * uDetailParms.xy) * uDetailParms.z;
material.Base *= Detail;
}
#endif
#if (DEF_TEXTURE_FLAGS & 0x4)
{
material.Glow = texture2D(glowtexture, texCoord.st);
}
#endif
}
//===========================================================================
//
// Calculate light
//
// It is important to note that the light color is not desaturated
// due to ZDoom's implementation weirdness. Everything that's added
// on top of it, e.g. dynamic lights and glows are, though, because
// the objects emitting these lights are also.
//
// This is making this a bit more complicated than it needs to
// because we can't just desaturate the final fragment color.
//
//===========================================================================
vec4 getLightColor(Material material, float fogdist, float fogfactor)
{
vec4 color = vColor;
#if (DEF_USE_U_LIGHT_LEVEL == 1)
{
float newlightlevel = 1.0 - R_DoomLightingEquation(uLightLevel);
color.rgb *= newlightlevel;
}
#else
{
#if (DEF_FOG_ENABLED == 1) && (DEF_FOG_COLOURED == 0)
{
// brightening around the player for light mode 2
if (fogdist < uLightDist)
{
color.rgb *= uLightFactor - (fogdist / uLightDist) * (uLightFactor - 1.0);
}
//
// apply light diminishing through fog equation
//
color.rgb = mix(vec3(0.0, 0.0, 0.0), color.rgb, fogfactor);
}
#endif
}
#endif
//
// handle glowing walls
//
#if (DEF_USE_GLOW_TOP_COLOR)
if (glowdist.x < uGlowTopColor.a)
{
color.rgb += desaturate(uGlowTopColor * (1.0 - glowdist.x / uGlowTopColor.a)).rgb;
}
#endif
#if (DEF_USE_GLOW_BOTTOM_COLOR)
if (glowdist.y < uGlowBottomColor.a)
{
color.rgb += desaturate(uGlowBottomColor * (1.0 - glowdist.y / uGlowBottomColor.a)).rgb;
}
#endif
color = min(color, 1.0);
// these cannot be safely applied by the legacy format where the implementation cannot guarantee that the values are set.
#ifndef LEGACY_USER_SHADER
//
// apply glow
//
color.rgb = mix(color.rgb, material.Glow.rgb, material.Glow.a);
//
// apply brightmaps
//
color.rgb = min(color.rgb + material.Bright.rgb, 1.0);
#endif
//
// apply other light manipulation by custom shaders, default is a NOP.
//
color = ProcessLight(material, color);
//
// apply dynamic lights
//
return vec4(ProcessMaterialLight(material, color.rgb), material.Base.a * vColor.a);
}
//===========================================================================
//
// Applies colored fog
//
//===========================================================================
vec4 applyFog(vec4 frag, float fogfactor)
{
return vec4(mix(uFogColor.rgb, frag.rgb, fogfactor), frag.a);
}
//===========================================================================
//
// Main shader routine
//
//===========================================================================
void main()
{
//if (ClipDistanceA.x < 0.0 || ClipDistanceA.y < 0.0 || ClipDistanceA.z < 0.0 || ClipDistanceA.w < 0.0 || ClipDistanceB.x < 0.0) discard;
#ifndef LEGACY_USER_SHADER
Material material;
material.Base = vec4(0.0);
material.Bright = vec4(0.0);
material.Glow = vec4(0.0);
material.Normal = vec3(0.0);
material.Specular = vec3(0.0);
material.Glossiness = 0.0;
material.SpecularLevel = 0.0;
SetupMaterial(material);
#else
Material material = ProcessMaterial();
#endif
vec4 frag = material.Base;
#ifndef NO_ALPHATEST
if (frag.a <= uAlphaThreshold) discard;
#endif
#if (DEF_FOG_2D == 0) // check for special 2D 'fog' mode.
{
float fogdist = 0.0;
float fogfactor = 0.0;
//
// calculate fog factor
//
#if (DEF_FOG_ENABLED == 1)
{
#if (DEF_FOG_RADIAL == 0)
fogdist = max(16.0, pixelpos.w);
#else
fogdist = max(16.0, distance(pixelpos.xyz, uCameraPos.xyz));
#endif
fogfactor = exp2 (uFogDensity * fogdist);
}
#endif
#if (DEF_TEXTURE_MODE != 7)
{
frag = getLightColor(material, fogdist, fogfactor);
//
// colored fog
//
#if (DEF_FOG_ENABLED == 1) && (DEF_FOG_COLOURED == 1)
{
frag = applyFog(frag, fogfactor);
}
#endif
}
#else
{
frag = vec4(uFogColor.rgb, (1.0 - fogfactor) * frag.a * 0.75 * vColor.a);
}
#endif
}
#else
{
#if (DEF_TEXTURE_MODE == 7)
{
float gray = grayscale(frag);
vec4 cm = (uObjectColor + gray * (uAddColor - uObjectColor)) * 2;
frag = vec4(clamp(cm.rgb, 0.0, 1.0), frag.a);
}
#endif
frag = frag * ProcessLight(material, vColor);
frag.rgb = frag.rgb + uFogColor.rgb;
}
#endif // (DEF_2D_FOG == 0)
#if (DEF_USE_COLOR_MAP == 1) // This mostly works but doesn't look great because of the blending.
{
frag.rgb = clamp(pow(frag.rgb, vec3(uFixedColormapStart.a)), 0.0, 1.0);
if (uFixedColormapRange.a == 0.0)
{
float gray = (frag.r * 0.3 + frag.g * 0.56 + frag.b * 0.14);
vec4 cm = uFixedColormapStart + gray * uFixedColormapRange;
frag.rgb = clamp(cm.rgb, 0.0, 1.0);
}
}
#endif
gl_FragColor = frag;
//gl_FragColor = vec4(0.8, 0.2, 0.5, 1);
}

View file

@ -0,0 +1,134 @@
attribute vec4 aPosition;
attribute vec2 aTexCoord;
attribute vec4 aColor;
varying vec4 vTexCoord;
varying vec4 vColor;
#ifndef SIMPLE // we do not need these for simple shaders
attribute vec4 aVertex2;
attribute vec4 aNormal;
attribute vec4 aNormal2;
varying vec4 pixelpos;
varying vec3 glowdist;
varying vec3 gradientdist;
varying vec4 vWorldNormal;
varying vec4 vEyeNormal;
#endif
#ifdef NO_CLIPDISTANCE_SUPPORT
varying vec4 ClipDistanceA;
varying vec4 ClipDistanceB;
#endif
void main()
{
float ClipDistance0, ClipDistance1, ClipDistance2, ClipDistance3, ClipDistance4;
vec2 parmTexCoord;
vec4 parmPosition;
parmTexCoord = aTexCoord;
parmPosition = aPosition;
#ifndef SIMPLE
vec4 worldcoord = ModelMatrix * mix(parmPosition, aVertex2, uInterpolationFactor);
#else
vec4 worldcoord = ModelMatrix * parmPosition;
#endif
vec4 eyeCoordPos = ViewMatrix * worldcoord;
#ifdef HAS_UNIFORM_VERTEX_DATA
if ((useVertexData & 1) == 0)
vColor = uVertexColor;
else
vColor = aColor;
#else
vColor = aColor;
#endif
#ifndef SIMPLE
pixelpos.xyz = worldcoord.xyz;
pixelpos.w = -eyeCoordPos.z/eyeCoordPos.w;
if (uGlowTopColor.a > 0.0 || uGlowBottomColor.a > 0.0)
{
float topatpoint = (uGlowTopPlane.w + uGlowTopPlane.x * worldcoord.x + uGlowTopPlane.y * worldcoord.z) * uGlowTopPlane.z;
float bottomatpoint = (uGlowBottomPlane.w + uGlowBottomPlane.x * worldcoord.x + uGlowBottomPlane.y * worldcoord.z) * uGlowBottomPlane.z;
glowdist.x = topatpoint - worldcoord.y;
glowdist.y = worldcoord.y - bottomatpoint;
glowdist.z = clamp(glowdist.x / (topatpoint - bottomatpoint), 0.0, 1.0);
}
if (uObjectColor2.a != 0.0)
{
float topatpoint = (uGradientTopPlane.w + uGradientTopPlane.x * worldcoord.x + uGradientTopPlane.y * worldcoord.z) * uGradientTopPlane.z;
float bottomatpoint = (uGradientBottomPlane.w + uGradientBottomPlane.x * worldcoord.x + uGradientBottomPlane.y * worldcoord.z) * uGradientBottomPlane.z;
gradientdist.x = topatpoint - worldcoord.y;
gradientdist.y = worldcoord.y - bottomatpoint;
gradientdist.z = clamp(gradientdist.x / (topatpoint - bottomatpoint), 0.0, 1.0);
}
if (uSplitBottomPlane.z != 0.0)
{
ClipDistance3 = ((uSplitTopPlane.w + uSplitTopPlane.x * worldcoord.x + uSplitTopPlane.y * worldcoord.z) * uSplitTopPlane.z) - worldcoord.y;
ClipDistance4 = worldcoord.y - ((uSplitBottomPlane.w + uSplitBottomPlane.x * worldcoord.x + uSplitBottomPlane.y * worldcoord.z) * uSplitBottomPlane.z);
}
#ifdef HAS_UNIFORM_VERTEX_DATA
if ((useVertexData & 2) == 0)
vWorldNormal = NormalModelMatrix * vec4(uVertexNormal.xyz, 1.0);
else
vWorldNormal = NormalModelMatrix * vec4(normalize(mix(aNormal.xyz, aNormal2.xyz, uInterpolationFactor)), 1.0);
#else
vWorldNormal = NormalModelMatrix * vec4(normalize(mix(aNormal.xyz, aNormal2.xyz, uInterpolationFactor)), 1.0);
#endif
vEyeNormal = NormalViewMatrix * vWorldNormal;
#endif
#ifdef SPHEREMAP
vec3 u = normalize(eyeCoordPos.xyz);
vec4 n = normalize(NormalViewMatrix * vec4(parmTexCoord.x, 0.0, parmTexCoord.y, 0.0));
vec3 r = reflect(u, n.xyz);
float m = 2.0 * sqrt( r.x*r.x + r.y*r.y + (r.z+1.0)*(r.z+1.0) );
vec2 sst = vec2(r.x/m + 0.5, r.y/m + 0.5);
vTexCoord.xy = sst;
#else
vTexCoord = TextureMatrix * vec4(parmTexCoord, 0.0, 1.0);
#endif
if (uClipHeightDirection != 0.0) // clip planes used for reflective flats
{
ClipDistance0 = (worldcoord.y - uClipHeight) * uClipHeightDirection;
}
else if (uClipLine.x > -1000000.0) // and for line portals - this will never be active at the same time as the reflective planes clipping so it can use the same hardware clip plane.
{
ClipDistance0 = -( (worldcoord.z - uClipLine.y) * uClipLine.z + (uClipLine.x - worldcoord.x) * uClipLine.w ) + 1.0/32768.0; // allow a tiny bit of imprecisions for colinear linedefs.
}
else
{
ClipDistance0 = 1.0;
}
// clip planes used for translucency splitting
ClipDistance1 = worldcoord.y - uClipSplit.x;
ClipDistance2 = uClipSplit.y - worldcoord.y;
if (uSplitTopPlane == vec4(0.0))
{
ClipDistance3 = 1.0;
ClipDistance4 = 1.0;
}
ClipDistanceA = vec4(ClipDistance0, ClipDistance1, ClipDistance2, ClipDistance3);
ClipDistanceB = vec4(ClipDistance4, 0.0, 0.0, 0.0);
//gl_PointSize = 1.0;
gl_Position = ProjectionMatrix * eyeCoordPos;
}

View file

@ -0,0 +1,5 @@
vec3 ProcessMaterialLight(Material material, vec3 color)
{
return material.Base.rgb * clamp(color + desaturate(uDynLightColor).rgb, 0.0, 1.4);
}

View file

@ -0,0 +1,130 @@
vec3 lightContribution(int i, vec3 normal)
{
vec4 lightpos = lights[i];
vec4 lightcolor = lights[i+1];
vec4 lightspot1 = lights[i+2];
vec4 lightspot2 = lights[i+3];
float lightdistance = distance(lightpos.xyz, pixelpos.xyz);
//if (lightpos.w < lightdistance)
// return vec3(0.0); // Early out lights touching surface but not this fragment
vec3 lightdir = normalize(lightpos.xyz - pixelpos.xyz);
float dotprod = dot(normal, lightdir);
//if (dotprod < -0.0001) return vec3(0.0); // light hits from the backside. This can happen with full sector light lists and must be rejected for all cases. Note that this can cause precision issues.
float attenuation = clamp((lightpos.w - lightdistance) / lightpos.w, 0.0, 1.0);
// NOTE, all spot light stuff gone
return lightcolor.rgb * attenuation;
/*
if (lightspot1.w == 1.0)
attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y);
if (lightcolor.a < 0.0) // Sign bit is the attenuated light flag
{
attenuation *= clamp(dotprod, 0.0, 1.0);
}
if (attenuation > 0.0) // Skip shadow map test if possible
{
attenuation *= shadowAttenuation(lightpos, lightcolor.a);
return lightcolor.rgb * attenuation;
}
else
{
return vec3(0.0);
}
*/
}
vec3 ProcessMaterialLight(Material material, vec3 color)
{
vec4 dynlight = uDynLightColor;
vec3 normal = material.Normal;
#if (DEF_DYNAMIC_LIGHTS_MOD == 1)
// modulated lights
// Some very old GLES2 hardward does not allow non-constants in a for-loop expression because it can not unroll it.
// However they do allow 'break' and use stupid hack
#if (USE_GLSL_V100 == 1)
for(int i = 0; i < 8; i++) // Max 8 lights
{
if(i == ((uLightRange.y - uLightRange.x) / 4))
break;
dynlight.rgb += lightContribution(i * 4, normal);
}
#else
for(int i=uLightRange.x; i<uLightRange.y; i+=4)
{
dynlight.rgb += lightContribution(i, normal);
}
#endif
#endif
#if (DEF_DYNAMIC_LIGHTS_SUB == 1)
// subtractive lights
#if (USE_GLSL_V100 == 1)
for(int i = 0; i < 4; i++) // Max 4 lights
{
if(i == ((uLightRange.z - uLightRange.y) / 4))
break;
dynlight.rgb -= lightContribution(uLightRange.y + (i * 4), normal);
}
#else
for(int i=uLightRange.y; i<uLightRange.z; i+=4)
{
dynlight.rgb -= lightContribution(i, normal);
}
#endif
#endif
vec3 frag = material.Base.rgb * clamp(color + desaturate(dynlight).rgb, 0.0, 1.4);
#if (DEF_DYNAMIC_LIGHTS_ADD == 1)
vec4 addlight = vec4(0.0,0.0,0.0,0.0);
// additive lights
#if (USE_GLSL_V100 == 1)
for(int i = 0; i < 4; i++) // Max 4 lights
{
if(i == ((uLightRange.w - uLightRange.z) / 4))
break;
addlight.rgb += lightContribution(uLightRange.z + (i * 4), normal);
}
#else
for(int i=uLightRange.z; i<uLightRange.w; i+=4)
{
addlight.rgb += lightContribution(i, normal);
}
#endif
frag = clamp(frag + desaturate(addlight).rgb, 0.0, 1.0);
#endif
return frag;
}

View file

@ -0,0 +1,195 @@
const float PI = 3.14159265359;
float DistributionGGX(vec3 N, vec3 H, float roughness)
{
float a = roughness * roughness;
float a2 = a * a;
float NdotH = max(dot(N, H), 0.0);
float NdotH2 = NdotH*NdotH;
float nom = a2;
float denom = (NdotH2 * (a2 - 1.0) + 1.0);
denom = PI * denom * denom;
return nom / denom;
}
float GeometrySchlickGGX(float NdotV, float roughness)
{
float r = (roughness + 1.0);
float k = (r * r) / 8.0;
float nom = NdotV;
float denom = NdotV * (1.0 - k) + k;
return nom / denom;
}
float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
{
float NdotV = max(dot(N, V), 0.0);
float NdotL = max(dot(N, L), 0.0);
float ggx2 = GeometrySchlickGGX(NdotV, roughness);
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
return ggx1 * ggx2;
}
vec3 fresnelSchlick(float cosTheta, vec3 F0)
{
return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
}
vec3 fresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness)
{
return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0);
}
float quadraticDistanceAttenuation(vec4 lightpos)
{
float strength = (1.0 + lightpos.w * lightpos.w * 0.25) * 0.5;
vec3 distVec = lightpos.xyz - pixelpos.xyz;
float attenuation = strength / (1.0 + dot(distVec, distVec));
if (attenuation <= 1.0 / 256.0) return 0.0;
return attenuation;
}
float linearDistanceAttenuation(vec4 lightpos)
{
float lightdistance = distance(lightpos.xyz, pixelpos.xyz);
return clamp((lightpos.w - lightdistance) / lightpos.w, 0.0, 1.0);
}
vec3 ProcessMaterialLight(Material material, vec3 ambientLight)
{
vec3 worldpos = pixelpos.xyz;
vec3 albedo = pow(material.Base.rgb, vec3(2.2)); // sRGB to linear
ambientLight = pow(ambientLight, vec3(2.2));
float metallic = material.Metallic;
float roughness = material.Roughness;
float ao = material.AO;
vec3 N = material.Normal;
vec3 V = normalize(uCameraPos.xyz - worldpos);
vec3 F0 = mix(vec3(0.04), albedo, metallic);
vec3 Lo = uDynLightColor.rgb;
if (uLightIndex >= 0)
{
ivec4 lightRange = ivec4(lights[uLightIndex]) + ivec4(uLightIndex + 1);
if (lightRange.z > lightRange.x)
{
//
// modulated lights
//
for(int i=lightRange.x; i<lightRange.y; i+=4)
{
vec4 lightpos = lights[i];
vec4 lightcolor = lights[i+1];
vec4 lightspot1 = lights[i+2];
vec4 lightspot2 = lights[i+3];
vec3 L = normalize(lightpos.xyz - worldpos);
vec3 H = normalize(V + L);
float attenuation = linearDistanceAttenuation(lightpos);
if (lightspot1.w == 1.0)
attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y);
if (lightcolor.a < 0.0)
attenuation *= clamp(dot(N, L), 0.0, 1.0); // Sign bit is the attenuated light flag
if (attenuation > 0.0)
{
attenuation *= shadowAttenuation(lightpos, lightcolor.a);
vec3 radiance = lightcolor.rgb * attenuation;
// cook-torrance brdf
float NDF = DistributionGGX(N, H, roughness);
float G = GeometrySmith(N, V, L, roughness);
vec3 F = fresnelSchlick(clamp(dot(H, V), 0.0, 1.0), F0);
vec3 kS = F;
vec3 kD = (vec3(1.0) - kS) * (1.0 - metallic);
vec3 nominator = NDF * G * F;
float denominator = 4.0 * clamp(dot(N, V), 0.0, 1.0) * clamp(dot(N, L), 0.0, 1.0);
vec3 specular = nominator / max(denominator, 0.001);
Lo += (kD * albedo / PI + specular) * radiance;
}
}
//
// subtractive lights
//
for(int i=lightRange.y; i<lightRange.z; i+=4)
{
vec4 lightpos = lights[i];
vec4 lightcolor = lights[i+1];
vec4 lightspot1 = lights[i+2];
vec4 lightspot2 = lights[i+3];
vec3 L = normalize(lightpos.xyz - worldpos);
vec3 H = normalize(V + L);
float attenuation = linearDistanceAttenuation(lightpos);
if (lightspot1.w == 1.0)
attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y);
if (lightcolor.a < 0.0)
attenuation *= clamp(dot(N, L), 0.0, 1.0); // Sign bit is the attenuated light flag
if (attenuation > 0.0)
{
attenuation *= shadowAttenuation(lightpos, lightcolor.a);
vec3 radiance = lightcolor.rgb * attenuation;
// cook-torrance brdf
float NDF = DistributionGGX(N, H, roughness);
float G = GeometrySmith(N, V, L, roughness);
vec3 F = fresnelSchlick(clamp(dot(H, V), 0.0, 1.0), F0);
vec3 kS = F;
vec3 kD = (vec3(1.0) - kS) * (1.0 - metallic);
vec3 nominator = NDF * G * F;
float denominator = 4.0 * clamp(dot(N, V), 0.0, 1.0) * clamp(dot(N, L), 0.0, 1.0);
vec3 specular = nominator / max(denominator, 0.001);
Lo -= (kD * albedo / PI + specular) * radiance;
}
}
}
}
// Pretend we sampled the sector light level from an irradiance map
vec3 F = fresnelSchlickRoughness(clamp(dot(N, V), 0.0, 1.0), F0, roughness);
vec3 kS = F;
vec3 kD = 1.0 - kS;
vec3 irradiance = ambientLight; // texture(irradianceMap, N).rgb
vec3 diffuse = irradiance * albedo;
//kD *= 1.0 - metallic;
//const float MAX_REFLECTION_LOD = 4.0;
//vec3 prefilteredColor = textureLod(prefilterMap, R, roughness * MAX_REFLECTION_LOD).rgb;
//vec2 envBRDF = texture(brdfLUT, vec2(clamp(dot(N, V), 0.0, 1.0), roughness)).rg;
//vec3 specular = prefilteredColor * (F * envBRDF.x + envBRDF.y);
//vec3 ambient = (kD * diffuse + specular) * ao;
vec3 ambient = (kD * diffuse) * ao;
vec3 color = max(ambient + Lo, vec3(0.0));
// Tonemap (reinhard) and apply sRGB gamma
//color = color / (color + vec3(1.0));
return pow(color, vec3(1.0 / 2.2));
}

View file

@ -0,0 +1,95 @@
vec2 lightAttenuation(int i, vec3 normal, vec3 viewdir, float lightcolorA)
{
vec4 lightpos = lights[i];
vec4 lightspot1 = lights[i+2];
vec4 lightspot2 = lights[i+3];
float lightdistance = distance(lightpos.xyz, pixelpos.xyz);
if (lightpos.w < lightdistance)
return vec2(0.0); // Early out lights touching surface but not this fragment
float attenuation = clamp((lightpos.w - lightdistance) / lightpos.w, 0.0, 1.0);
if (lightspot1.w == 1.0)
attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y);
vec3 lightdir = normalize(lightpos.xyz - pixelpos.xyz);
if (lightcolorA < 0.0) // Sign bit is the attenuated light flag
attenuation *= clamp(dot(normal, lightdir), 0.0, 1.0);
if (attenuation > 0.0) // Skip shadow map test if possible
attenuation *= shadowAttenuation(lightpos, lightcolorA);
if (attenuation <= 0.0)
return vec2(0.0);
float glossiness = uSpecularMaterial.x;
float specularLevel = uSpecularMaterial.y;
vec3 halfdir = normalize(viewdir + lightdir);
float specAngle = clamp(dot(halfdir, normal), 0.0, 1.0);
float phExp = glossiness * 4.0;
return vec2(attenuation, attenuation * specularLevel * pow(specAngle, phExp));
}
vec3 ProcessMaterialLight(Material material, vec3 color)
{
vec4 dynlight = uDynLightColor;
vec4 specular = vec4(0.0, 0.0, 0.0, 1.0);
vec3 normal = material.Normal;
vec3 viewdir = normalize(uCameraPos.xyz - pixelpos.xyz);
if (uLightIndex >= 0)
{
ivec4 lightRange = ivec4(lights[uLightIndex]) + ivec4(uLightIndex + 1);
if (lightRange.z > lightRange.x)
{
// modulated lights
for(int i=lightRange.x; i<lightRange.y; i+=4)
{
vec4 lightcolor = lights[i+1];
vec2 attenuation = lightAttenuation(i, normal, viewdir, lightcolor.a);
dynlight.rgb += lightcolor.rgb * attenuation.x;
specular.rgb += lightcolor.rgb * attenuation.y;
}
// subtractive lights
for(int i=lightRange.y; i<lightRange.z; i+=4)
{
vec4 lightcolor = lights[i+1];
vec2 attenuation = lightAttenuation(i, normal, viewdir, lightcolor.a);
dynlight.rgb -= lightcolor.rgb * attenuation.x;
specular.rgb -= lightcolor.rgb * attenuation.y;
}
}
}
dynlight.rgb = clamp(color + desaturate(dynlight).rgb, 0.0, 1.4);
specular.rgb = clamp(desaturate(specular).rgb, 0.0, 1.4);
vec3 frag = material.Base.rgb * dynlight.rgb + material.Specular * specular.rgb;
if (uLightIndex >= 0)
{
ivec4 lightRange = ivec4(lights[uLightIndex]) + ivec4(uLightIndex + 1);
if (lightRange.w > lightRange.z)
{
vec4 addlight = vec4(0.0,0.0,0.0,0.0);
// additive lights
for(int i=lightRange.z; i<lightRange.w; i+=4)
{
vec4 lightcolor = lights[i+1];
vec2 attenuation = lightAttenuation(i, normal, viewdir, lightcolor.a);
addlight.rgb += lightcolor.rgb * attenuation.x;
}
frag = clamp(frag + desaturate(addlight).rgb, 0.0, 1.0);
}
}
return frag;
}

View file

@ -0,0 +1,7 @@
void main()
{
gl_FragColor = vec4(1.0, 1.0, 1.0, 0.0);
}

View file

@ -0,0 +1,10 @@
layout(location=0) in vec2 TexCoord;
layout(location=0) out vec4 FragColor;
layout(binding=0) uniform sampler2D Bloom;
void main()
{
FragColor = vec4(texture(Bloom, TexCoord).rgb, 0.0);
}

View file

@ -0,0 +1,12 @@
layout(location=0) in vec2 TexCoord;
layout(location=0) out vec4 FragColor;
layout(binding=0) uniform sampler2D SceneTexture;
layout(binding=1) uniform sampler2D ExposureTexture;
void main()
{
float exposureAdjustment = texture(ExposureTexture, vec2(0.5)).x;
vec4 color = texture(SceneTexture, Offset + TexCoord * Scale);
FragColor = max(vec4((color.rgb + vec3(0.001)) * exposureAdjustment - 1.0, 1.0), vec4(0));
}

View file

@ -0,0 +1,28 @@
layout(location=0) in vec2 TexCoord;
layout(location=0) out vec4 FragColor;
layout(binding=0) uniform sampler2D SourceTexture;
void main()
{
#if defined(BLUR_HORIZONTAL)
FragColor =
textureOffset(SourceTexture, TexCoord, ivec2( 0, 0)) * SampleWeights0 +
textureOffset(SourceTexture, TexCoord, ivec2( 1, 0)) * SampleWeights1 +
textureOffset(SourceTexture, TexCoord, ivec2(-1, 0)) * SampleWeights2 +
textureOffset(SourceTexture, TexCoord, ivec2( 2, 0)) * SampleWeights3 +
textureOffset(SourceTexture, TexCoord, ivec2(-2, 0)) * SampleWeights4 +
textureOffset(SourceTexture, TexCoord, ivec2( 3, 0)) * SampleWeights5 +
textureOffset(SourceTexture, TexCoord, ivec2(-3, 0)) * SampleWeights6;
#else
FragColor =
textureOffset(SourceTexture, TexCoord, ivec2(0, 0)) * SampleWeights0 +
textureOffset(SourceTexture, TexCoord, ivec2(0, 1)) * SampleWeights1 +
textureOffset(SourceTexture, TexCoord, ivec2(0,-1)) * SampleWeights2 +
textureOffset(SourceTexture, TexCoord, ivec2(0, 2)) * SampleWeights3 +
textureOffset(SourceTexture, TexCoord, ivec2(0,-2)) * SampleWeights4 +
textureOffset(SourceTexture, TexCoord, ivec2(0, 3)) * SampleWeights5 +
textureOffset(SourceTexture, TexCoord, ivec2(0,-3)) * SampleWeights6;
#endif
}

View file

@ -0,0 +1,18 @@
layout(location=0) in vec2 TexCoord;
layout(location=0) out vec4 FragColor;
layout(binding=0) uniform sampler2D SceneTexture;
void main()
{
vec4 frag = texture(SceneTexture, TexCoord);
frag.rgb = clamp(pow(frag.rgb, vec3(uFixedColormapStart.a)), 0.0, 1.0);
if (uFixedColormapRange.a == 0.0)
{
float gray = (frag.r * 0.3 + frag.g * 0.56 + frag.b * 0.14);
vec4 cm = uFixedColormapStart + gray * uFixedColormapRange;
frag.rgb = clamp(cm.rgb, 0.0, 1.0);
}
FragColor = frag;
}

View file

@ -0,0 +1,54 @@
layout(location=0) in vec2 TexCoord;
layout(location=0) out vec4 FragColor;
layout(binding=0) uniform sampler2D AODepthTexture;
#define KERNEL_RADIUS 3.0
void AddSample(vec2 blurSample, float r, float centerDepth, inout float totalAO, inout float totalW)
{
const float blurSigma = KERNEL_RADIUS * 0.5;
const float blurFalloff = 1.0 / (2.0 * blurSigma * blurSigma);
float ao = blurSample.x;
float z = blurSample.y;
float deltaZ = (z - centerDepth) * BlurSharpness;
float w = exp2(-r * r * blurFalloff - deltaZ * deltaZ);
totalAO += w * ao;
totalW += w;
}
void main()
{
vec2 centerSample = textureOffset(AODepthTexture, TexCoord, ivec2( 0, 0)).xy;
float centerDepth = centerSample.y;
float totalAO = centerSample.x;
float totalW = 1.0;
#if defined(BLUR_HORIZONTAL)
AddSample(textureOffset(AODepthTexture, TexCoord, ivec2(-3, 0)).xy, 3.0, centerDepth, totalAO, totalW);
AddSample(textureOffset(AODepthTexture, TexCoord, ivec2(-2, 0)).xy, 2.0, centerDepth, totalAO, totalW);
AddSample(textureOffset(AODepthTexture, TexCoord, ivec2(-1, 0)).xy, 1.0, centerDepth, totalAO, totalW);
AddSample(textureOffset(AODepthTexture, TexCoord, ivec2( 1, 0)).xy, 1.0, centerDepth, totalAO, totalW);
AddSample(textureOffset(AODepthTexture, TexCoord, ivec2( 2, 0)).xy, 2.0, centerDepth, totalAO, totalW);
AddSample(textureOffset(AODepthTexture, TexCoord, ivec2( 3, 0)).xy, 3.0, centerDepth, totalAO, totalW);
#else
AddSample(textureOffset(AODepthTexture, TexCoord, ivec2(0, -3)).xy, 3.0, centerDepth, totalAO, totalW);
AddSample(textureOffset(AODepthTexture, TexCoord, ivec2(0, -2)).xy, 2.0, centerDepth, totalAO, totalW);
AddSample(textureOffset(AODepthTexture, TexCoord, ivec2(0, -1)).xy, 1.0, centerDepth, totalAO, totalW);
AddSample(textureOffset(AODepthTexture, TexCoord, ivec2(0, 1)).xy, 1.0, centerDepth, totalAO, totalW);
AddSample(textureOffset(AODepthTexture, TexCoord, ivec2(0, 2)).xy, 2.0, centerDepth, totalAO, totalW);
AddSample(textureOffset(AODepthTexture, TexCoord, ivec2(0, 3)).xy, 3.0, centerDepth, totalAO, totalW);
#endif
float fragAO = totalAO / totalW;
#if defined(BLUR_HORIZONTAL)
FragColor = vec4(fragAO, centerDepth, 0.0, 1.0);
#else
FragColor = vec4(pow(clamp(fragAO, 0.0, 1.0), PowExponent), 0.0, 0.0, 1.0);
#endif
}

View file

@ -0,0 +1,22 @@
layout(location=0) in vec2 TexCoord;
layout(location=0) out vec4 FragColor;
layout(binding=0) uniform sampler2D ExposureTexture;
void main()
{
#if __VERSION__ < 400
ivec2 size = textureSize(ExposureTexture, 0);
ivec2 tl = max(ivec2(TexCoord * vec2(size) - 0.5), ivec2(0));
ivec2 br = min(tl + ivec2(1), size - ivec2(1));
vec4 values = vec4(
texelFetch(ExposureTexture, tl, 0).x,
texelFetch(ExposureTexture, ivec2(tl.x, br.y), 0).x,
texelFetch(ExposureTexture, ivec2(br.x, tl.y), 0).x,
texelFetch(ExposureTexture, br, 0).x);
#else
vec4 values = textureGather(ExposureTexture, TexCoord);
#endif
FragColor = vec4((values.x + values.y + values.z + values.w) * 0.25, 0.0, 0.0, 1.0);
}

View file

@ -0,0 +1,12 @@
layout(location=0) in vec2 TexCoord;
layout(location=0) out vec4 FragColor;
layout(binding=0) uniform sampler2D ExposureTexture;
void main()
{
float light = texture(ExposureTexture, TexCoord).x;
float exposureAdjustment = 1.0 / max(ExposureBase + light * ExposureScale, ExposureMin);
FragColor = vec4(exposureAdjustment, 0.0, 0.0, ExposureSpeed);
}

View file

@ -0,0 +1,11 @@
layout(location=0) in vec2 TexCoord;
layout(location=0) out vec4 FragColor;
layout(binding=0) uniform sampler2D SceneTexture;
void main()
{
vec4 color = texture(SceneTexture, Offset + TexCoord * Scale);
FragColor = vec4(max(max(color.r, color.g), color.b), 0.0, 0.0, 1.0);
}

View file

@ -0,0 +1,613 @@
//----------------------------------------------------------------------------------
// File: es3-kepler\FXAA/FXAA3_11.h
// SDK Version: v3.00
// Email: gameworks@nvidia.com
// Site: http://developer.nvidia.com/
//
// Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//----------------------------------------------------------------------------------
layout(location=0) in vec2 TexCoord;
layout(location=0) out vec4 FragColor;
layout(binding=0) uniform sampler2D InputTexture;
#ifdef FXAA_LUMA_PASS
void main()
{
vec3 tex = texture(InputTexture, TexCoord).rgb;
vec3 luma = vec3(0.299, 0.587, 0.114);
FragColor = vec4(tex, dot(tex, luma));
}
#else // FXAA itself
//============================================================================
// NVIDIA FXAA 3.11 by TIMOTHY LOTTES
//============================================================================
#define FXAA_DISCARD 0
#define FXAA_GREEN_AS_LUMA 0
#define FxaaBool bool
#define FxaaDiscard discard
#define FxaaFloat float
#define FxaaFloat2 vec2
#define FxaaFloat3 vec3
#define FxaaFloat4 vec4
#define FxaaHalf float
#define FxaaHalf2 vec2
#define FxaaHalf3 vec3
#define FxaaHalf4 vec4
#define FxaaInt2 ivec2
#define FxaaSat(x) clamp(x, 0.0, 1.0)
#define FxaaTex sampler2D
#define FxaaTexTop(t, p) textureLod(t, p, 0.0)
#define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o)
#if (FXAA_GATHER4_ALPHA == 1)
#define FxaaTexAlpha4(t, p) textureGather(t, p, 3)
#define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3)
#define FxaaTexGreen4(t, p) textureGather(t, p, 1)
#define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1)
#endif
#if (FXAA_GREEN_AS_LUMA == 0)
FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.w; }
#else
FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.y; }
#endif
#if (FXAA_QUALITY__PRESET == 10)
#define FXAA_QUALITY__PS 3
#define FXAA_QUALITY__P0 1.5
#define FXAA_QUALITY__P1 3.0
#define FXAA_QUALITY__P2 12.0
#elif (FXAA_QUALITY__PRESET == 11)
#define FXAA_QUALITY__PS 4
#define FXAA_QUALITY__P0 1.0
#define FXAA_QUALITY__P1 1.5
#define FXAA_QUALITY__P2 3.0
#define FXAA_QUALITY__P3 12.0
#elif (FXAA_QUALITY__PRESET == 12)
#define FXAA_QUALITY__PS 5
#define FXAA_QUALITY__P0 1.0
#define FXAA_QUALITY__P1 1.5
#define FXAA_QUALITY__P2 2.0
#define FXAA_QUALITY__P3 4.0
#define FXAA_QUALITY__P4 12.0
#elif (FXAA_QUALITY__PRESET == 13)
#define FXAA_QUALITY__PS 6
#define FXAA_QUALITY__P0 1.0
#define FXAA_QUALITY__P1 1.5
#define FXAA_QUALITY__P2 2.0
#define FXAA_QUALITY__P3 2.0
#define FXAA_QUALITY__P4 4.0
#define FXAA_QUALITY__P5 12.0
#elif (FXAA_QUALITY__PRESET == 14)
#define FXAA_QUALITY__PS 7
#define FXAA_QUALITY__P0 1.0
#define FXAA_QUALITY__P1 1.5
#define FXAA_QUALITY__P2 2.0
#define FXAA_QUALITY__P3 2.0
#define FXAA_QUALITY__P4 2.0
#define FXAA_QUALITY__P5 4.0
#define FXAA_QUALITY__P6 12.0
#elif (FXAA_QUALITY__PRESET == 15)
#define FXAA_QUALITY__PS 8
#define FXAA_QUALITY__P0 1.0
#define FXAA_QUALITY__P1 1.5
#define FXAA_QUALITY__P2 2.0
#define FXAA_QUALITY__P3 2.0
#define FXAA_QUALITY__P4 2.0
#define FXAA_QUALITY__P5 2.0
#define FXAA_QUALITY__P6 4.0
#define FXAA_QUALITY__P7 12.0
#elif (FXAA_QUALITY__PRESET == 20)
#define FXAA_QUALITY__PS 3
#define FXAA_QUALITY__P0 1.5
#define FXAA_QUALITY__P1 2.0
#define FXAA_QUALITY__P2 8.0
#elif (FXAA_QUALITY__PRESET == 21)
#define FXAA_QUALITY__PS 4
#define FXAA_QUALITY__P0 1.0
#define FXAA_QUALITY__P1 1.5
#define FXAA_QUALITY__P2 2.0
#define FXAA_QUALITY__P3 8.0
#elif (FXAA_QUALITY__PRESET == 22)
#define FXAA_QUALITY__PS 5
#define FXAA_QUALITY__P0 1.0
#define FXAA_QUALITY__P1 1.5
#define FXAA_QUALITY__P2 2.0
#define FXAA_QUALITY__P3 2.0
#define FXAA_QUALITY__P4 8.0
#elif (FXAA_QUALITY__PRESET == 23)
#define FXAA_QUALITY__PS 6
#define FXAA_QUALITY__P0 1.0
#define FXAA_QUALITY__P1 1.5
#define FXAA_QUALITY__P2 2.0
#define FXAA_QUALITY__P3 2.0
#define FXAA_QUALITY__P4 2.0
#define FXAA_QUALITY__P5 8.0
#elif (FXAA_QUALITY__PRESET == 24)
#define FXAA_QUALITY__PS 7
#define FXAA_QUALITY__P0 1.0
#define FXAA_QUALITY__P1 1.5
#define FXAA_QUALITY__P2 2.0
#define FXAA_QUALITY__P3 2.0
#define FXAA_QUALITY__P4 2.0
#define FXAA_QUALITY__P5 3.0
#define FXAA_QUALITY__P6 8.0
#elif (FXAA_QUALITY__PRESET == 25)
#define FXAA_QUALITY__PS 8
#define FXAA_QUALITY__P0 1.0
#define FXAA_QUALITY__P1 1.5
#define FXAA_QUALITY__P2 2.0
#define FXAA_QUALITY__P3 2.0
#define FXAA_QUALITY__P4 2.0
#define FXAA_QUALITY__P5 2.0
#define FXAA_QUALITY__P6 4.0
#define FXAA_QUALITY__P7 8.0
#elif (FXAA_QUALITY__PRESET == 26)
#define FXAA_QUALITY__PS 9
#define FXAA_QUALITY__P0 1.0
#define FXAA_QUALITY__P1 1.5
#define FXAA_QUALITY__P2 2.0
#define FXAA_QUALITY__P3 2.0
#define FXAA_QUALITY__P4 2.0
#define FXAA_QUALITY__P5 2.0
#define FXAA_QUALITY__P6 2.0
#define FXAA_QUALITY__P7 4.0
#define FXAA_QUALITY__P8 8.0
#elif (FXAA_QUALITY__PRESET == 27)
#define FXAA_QUALITY__PS 10
#define FXAA_QUALITY__P0 1.0
#define FXAA_QUALITY__P1 1.5
#define FXAA_QUALITY__P2 2.0
#define FXAA_QUALITY__P3 2.0
#define FXAA_QUALITY__P4 2.0
#define FXAA_QUALITY__P5 2.0
#define FXAA_QUALITY__P6 2.0
#define FXAA_QUALITY__P7 2.0
#define FXAA_QUALITY__P8 4.0
#define FXAA_QUALITY__P9 8.0
#elif (FXAA_QUALITY__PRESET == 28)
#define FXAA_QUALITY__PS 11
#define FXAA_QUALITY__P0 1.0
#define FXAA_QUALITY__P1 1.5
#define FXAA_QUALITY__P2 2.0
#define FXAA_QUALITY__P3 2.0
#define FXAA_QUALITY__P4 2.0
#define FXAA_QUALITY__P5 2.0
#define FXAA_QUALITY__P6 2.0
#define FXAA_QUALITY__P7 2.0
#define FXAA_QUALITY__P8 2.0
#define FXAA_QUALITY__P9 4.0
#define FXAA_QUALITY__P10 8.0
#elif (FXAA_QUALITY__PRESET == 29)
#define FXAA_QUALITY__PS 12
#define FXAA_QUALITY__P0 1.0
#define FXAA_QUALITY__P1 1.5
#define FXAA_QUALITY__P2 2.0
#define FXAA_QUALITY__P3 2.0
#define FXAA_QUALITY__P4 2.0
#define FXAA_QUALITY__P5 2.0
#define FXAA_QUALITY__P6 2.0
#define FXAA_QUALITY__P7 2.0
#define FXAA_QUALITY__P8 2.0
#define FXAA_QUALITY__P9 2.0
#define FXAA_QUALITY__P10 4.0
#define FXAA_QUALITY__P11 8.0
#elif (FXAA_QUALITY__PRESET == 39)
#define FXAA_QUALITY__PS 12
#define FXAA_QUALITY__P0 1.0
#define FXAA_QUALITY__P1 1.0
#define FXAA_QUALITY__P2 1.0
#define FXAA_QUALITY__P3 1.0
#define FXAA_QUALITY__P4 1.0
#define FXAA_QUALITY__P5 1.5
#define FXAA_QUALITY__P6 2.0
#define FXAA_QUALITY__P7 2.0
#define FXAA_QUALITY__P8 2.0
#define FXAA_QUALITY__P9 2.0
#define FXAA_QUALITY__P10 4.0
#define FXAA_QUALITY__P11 8.0
#endif
FxaaFloat4 FxaaPixelShader(FxaaFloat2 pos, FxaaTex tex, FxaaFloat2 fxaaQualityRcpFrame,
FxaaFloat fxaaQualitySubpix, FxaaFloat fxaaQualityEdgeThreshold, FxaaFloat fxaaQualityEdgeThresholdMin)
{
FxaaFloat2 posM;
posM.x = pos.x;
posM.y = pos.y;
#if (FXAA_GATHER4_ALPHA == 1)
#if (FXAA_DISCARD == 0)
FxaaFloat4 rgbyM = FxaaTexTop(tex, posM);
#if (FXAA_GREEN_AS_LUMA == 0)
#define lumaM rgbyM.w
#else
#define lumaM rgbyM.y
#endif
#endif
#if (FXAA_GREEN_AS_LUMA == 0)
FxaaFloat4 luma4A = FxaaTexAlpha4(tex, posM);
FxaaFloat4 luma4B = FxaaTexOffAlpha4(tex, posM, FxaaInt2(-1, -1));
#else
FxaaFloat4 luma4A = FxaaTexGreen4(tex, posM);
FxaaFloat4 luma4B = FxaaTexOffGreen4(tex, posM, FxaaInt2(-1, -1));
#endif
#if (FXAA_DISCARD == 1)
#define lumaM luma4A.w
#endif
#define lumaE luma4A.z
#define lumaS luma4A.x
#define lumaSE luma4A.y
#define lumaNW luma4B.w
#define lumaN luma4B.z
#define lumaW luma4B.x
#else
FxaaFloat4 rgbyM = FxaaTexTop(tex, posM);
#if (FXAA_GREEN_AS_LUMA == 0)
#define lumaM rgbyM.w
#else
#define lumaM rgbyM.y
#endif
FxaaFloat lumaS = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0, 1), fxaaQualityRcpFrame.xy));
FxaaFloat lumaE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 0), fxaaQualityRcpFrame.xy));
FxaaFloat lumaN = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0,-1), fxaaQualityRcpFrame.xy));
FxaaFloat lumaW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 0), fxaaQualityRcpFrame.xy));
#endif
/*--------------------------------------------------------------------------*/
FxaaFloat maxSM = max(lumaS, lumaM);
FxaaFloat minSM = min(lumaS, lumaM);
FxaaFloat maxESM = max(lumaE, maxSM);
FxaaFloat minESM = min(lumaE, minSM);
FxaaFloat maxWN = max(lumaN, lumaW);
FxaaFloat minWN = min(lumaN, lumaW);
FxaaFloat rangeMax = max(maxWN, maxESM);
FxaaFloat rangeMin = min(minWN, minESM);
FxaaFloat rangeMaxScaled = rangeMax * fxaaQualityEdgeThreshold;
FxaaFloat range = rangeMax - rangeMin;
FxaaFloat rangeMaxClamped = max(fxaaQualityEdgeThresholdMin, rangeMaxScaled);
FxaaBool earlyExit = range < rangeMaxClamped;
/*--------------------------------------------------------------------------*/
if(earlyExit)
#if (FXAA_DISCARD == 1)
FxaaDiscard;
#else
return rgbyM;
#endif
/*--------------------------------------------------------------------------*/
#if (FXAA_GATHER4_ALPHA == 0)
FxaaFloat lumaNW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1,-1), fxaaQualityRcpFrame.xy));
FxaaFloat lumaSE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 1), fxaaQualityRcpFrame.xy));
FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1,-1), fxaaQualityRcpFrame.xy));
FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy));
#else
FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(1, -1), fxaaQualityRcpFrame.xy));
FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy));
#endif
/*--------------------------------------------------------------------------*/
FxaaFloat lumaNS = lumaN + lumaS;
FxaaFloat lumaWE = lumaW + lumaE;
FxaaFloat subpixRcpRange = 1.0/range;
FxaaFloat subpixNSWE = lumaNS + lumaWE;
FxaaFloat edgeHorz1 = (-2.0 * lumaM) + lumaNS;
FxaaFloat edgeVert1 = (-2.0 * lumaM) + lumaWE;
/*--------------------------------------------------------------------------*/
FxaaFloat lumaNESE = lumaNE + lumaSE;
FxaaFloat lumaNWNE = lumaNW + lumaNE;
FxaaFloat edgeHorz2 = (-2.0 * lumaE) + lumaNESE;
FxaaFloat edgeVert2 = (-2.0 * lumaN) + lumaNWNE;
/*--------------------------------------------------------------------------*/
FxaaFloat lumaNWSW = lumaNW + lumaSW;
FxaaFloat lumaSWSE = lumaSW + lumaSE;
FxaaFloat edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2);
FxaaFloat edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2);
FxaaFloat edgeHorz3 = (-2.0 * lumaW) + lumaNWSW;
FxaaFloat edgeVert3 = (-2.0 * lumaS) + lumaSWSE;
FxaaFloat edgeHorz = abs(edgeHorz3) + edgeHorz4;
FxaaFloat edgeVert = abs(edgeVert3) + edgeVert4;
/*--------------------------------------------------------------------------*/
FxaaFloat subpixNWSWNESE = lumaNWSW + lumaNESE;
FxaaFloat lengthSign = fxaaQualityRcpFrame.x;
FxaaBool horzSpan = edgeHorz >= edgeVert;
FxaaFloat subpixA = subpixNSWE * 2.0 + subpixNWSWNESE;
/*--------------------------------------------------------------------------*/
if(!horzSpan) lumaN = lumaW;
if(!horzSpan) lumaS = lumaE;
if(horzSpan) lengthSign = fxaaQualityRcpFrame.y;
FxaaFloat subpixB = (subpixA * (1.0/12.0)) - lumaM;
/*--------------------------------------------------------------------------*/
FxaaFloat gradientN = lumaN - lumaM;
FxaaFloat gradientS = lumaS - lumaM;
FxaaFloat lumaNN = lumaN + lumaM;
FxaaFloat lumaSS = lumaS + lumaM;
FxaaBool pairN = abs(gradientN) >= abs(gradientS);
FxaaFloat gradient = max(abs(gradientN), abs(gradientS));
if(pairN) lengthSign = -lengthSign;
FxaaFloat subpixC = FxaaSat(abs(subpixB) * subpixRcpRange);
/*--------------------------------------------------------------------------*/
FxaaFloat2 posB;
posB.x = posM.x;
posB.y = posM.y;
FxaaFloat2 offNP;
offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x;
offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y;
if(!horzSpan) posB.x += lengthSign * 0.5;
if( horzSpan) posB.y += lengthSign * 0.5;
/*--------------------------------------------------------------------------*/
FxaaFloat2 posN;
posN.x = posB.x - offNP.x * FXAA_QUALITY__P0;
posN.y = posB.y - offNP.y * FXAA_QUALITY__P0;
FxaaFloat2 posP;
posP.x = posB.x + offNP.x * FXAA_QUALITY__P0;
posP.y = posB.y + offNP.y * FXAA_QUALITY__P0;
FxaaFloat subpixD = ((-2.0)*subpixC) + 3.0;
FxaaFloat lumaEndN = FxaaLuma(FxaaTexTop(tex, posN));
FxaaFloat subpixE = subpixC * subpixC;
FxaaFloat lumaEndP = FxaaLuma(FxaaTexTop(tex, posP));
/*--------------------------------------------------------------------------*/
if(!pairN) lumaNN = lumaSS;
FxaaFloat gradientScaled = gradient * 1.0/4.0;
FxaaFloat lumaMM = lumaM - lumaNN * 0.5;
FxaaFloat subpixF = subpixD * subpixE;
FxaaBool lumaMLTZero = lumaMM < 0.0;
/*--------------------------------------------------------------------------*/
lumaEndN -= lumaNN * 0.5;
lumaEndP -= lumaNN * 0.5;
FxaaBool doneN = abs(lumaEndN) >= gradientScaled;
FxaaBool doneP = abs(lumaEndP) >= gradientScaled;
if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P1;
if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P1;
FxaaBool doneNP = (!doneN) || (!doneP);
if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P1;
if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P1;
/*--------------------------------------------------------------------------*/
if(doneNP) {
if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
doneN = abs(lumaEndN) >= gradientScaled;
doneP = abs(lumaEndP) >= gradientScaled;
if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P2;
if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P2;
doneNP = (!doneN) || (!doneP);
if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P2;
if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P2;
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY__PS > 3)
if(doneNP) {
if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
doneN = abs(lumaEndN) >= gradientScaled;
doneP = abs(lumaEndP) >= gradientScaled;
if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P3;
if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P3;
doneNP = (!doneN) || (!doneP);
if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P3;
if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P3;
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY__PS > 4)
if(doneNP) {
if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
doneN = abs(lumaEndN) >= gradientScaled;
doneP = abs(lumaEndP) >= gradientScaled;
if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P4;
if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P4;
doneNP = (!doneN) || (!doneP);
if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P4;
if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P4;
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY__PS > 5)
if(doneNP) {
if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
doneN = abs(lumaEndN) >= gradientScaled;
doneP = abs(lumaEndP) >= gradientScaled;
if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P5;
if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P5;
doneNP = (!doneN) || (!doneP);
if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P5;
if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P5;
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY__PS > 6)
if(doneNP) {
if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
doneN = abs(lumaEndN) >= gradientScaled;
doneP = abs(lumaEndP) >= gradientScaled;
if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P6;
if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P6;
doneNP = (!doneN) || (!doneP);
if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P6;
if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P6;
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY__PS > 7)
if(doneNP) {
if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
doneN = abs(lumaEndN) >= gradientScaled;
doneP = abs(lumaEndP) >= gradientScaled;
if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P7;
if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P7;
doneNP = (!doneN) || (!doneP);
if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P7;
if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P7;
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY__PS > 8)
if(doneNP) {
if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
doneN = abs(lumaEndN) >= gradientScaled;
doneP = abs(lumaEndP) >= gradientScaled;
if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P8;
if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P8;
doneNP = (!doneN) || (!doneP);
if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P8;
if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P8;
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY__PS > 9)
if(doneNP) {
if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
doneN = abs(lumaEndN) >= gradientScaled;
doneP = abs(lumaEndP) >= gradientScaled;
if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P9;
if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P9;
doneNP = (!doneN) || (!doneP);
if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P9;
if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P9;
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY__PS > 10)
if(doneNP) {
if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
doneN = abs(lumaEndN) >= gradientScaled;
doneP = abs(lumaEndP) >= gradientScaled;
if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P10;
if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P10;
doneNP = (!doneN) || (!doneP);
if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P10;
if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P10;
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY__PS > 11)
if(doneNP) {
if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
doneN = abs(lumaEndN) >= gradientScaled;
doneP = abs(lumaEndP) >= gradientScaled;
if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P11;
if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P11;
doneNP = (!doneN) || (!doneP);
if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P11;
if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P11;
/*--------------------------------------------------------------------------*/
#if (FXAA_QUALITY__PS > 12)
if(doneNP) {
if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
doneN = abs(lumaEndN) >= gradientScaled;
doneP = abs(lumaEndP) >= gradientScaled;
if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P12;
if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P12;
doneNP = (!doneN) || (!doneP);
if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P12;
if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P12;
/*--------------------------------------------------------------------------*/
}
#endif
/*--------------------------------------------------------------------------*/
}
#endif
/*--------------------------------------------------------------------------*/
}
#endif
/*--------------------------------------------------------------------------*/
}
#endif
/*--------------------------------------------------------------------------*/
}
#endif
/*--------------------------------------------------------------------------*/
}
#endif
/*--------------------------------------------------------------------------*/
}
#endif
/*--------------------------------------------------------------------------*/
}
#endif
/*--------------------------------------------------------------------------*/
}
#endif
/*--------------------------------------------------------------------------*/
}
#endif
/*--------------------------------------------------------------------------*/
}
/*--------------------------------------------------------------------------*/
FxaaFloat dstN = posM.x - posN.x;
FxaaFloat dstP = posP.x - posM.x;
if(!horzSpan) dstN = posM.y - posN.y;
if(!horzSpan) dstP = posP.y - posM.y;
/*--------------------------------------------------------------------------*/
FxaaBool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero;
FxaaFloat spanLength = (dstP + dstN);
FxaaBool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero;
FxaaFloat spanLengthRcp = 1.0/spanLength;
/*--------------------------------------------------------------------------*/
FxaaBool directionN = dstN < dstP;
FxaaFloat dst = min(dstN, dstP);
FxaaBool goodSpan = directionN ? goodSpanN : goodSpanP;
FxaaFloat subpixG = subpixF * subpixF;
FxaaFloat pixelOffset = (dst * (-spanLengthRcp)) + 0.5;
FxaaFloat subpixH = subpixG * fxaaQualitySubpix;
/*--------------------------------------------------------------------------*/
FxaaFloat pixelOffsetGood = goodSpan ? pixelOffset : 0.0;
FxaaFloat pixelOffsetSubpix = max(pixelOffsetGood, subpixH);
if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign;
if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign;
#if (FXAA_DISCARD == 1)
return FxaaTexTop(tex, posM);
#else
return FxaaFloat4(FxaaTexTop(tex, posM).xyz, lumaM);
#endif
}
void main()
{
FragColor = FxaaPixelShader(TexCoord, InputTexture, ReciprocalResolution, 0.75f, 0.166f, 0.0833f);
}
#endif // FXAA_LUMA_PASS

View file

@ -0,0 +1,54 @@
/*
Original Lens Distortion Algorithm from SSontech
http://www.ssontech.com/content/lensalg.htm
If (u,v) are the coordinates of a feature in the undistorted perfect
image plane, then (u', v') are the coordinates of the feature on the
distorted image plate, ie the scanned or captured image from the
camera. The distortion occurs radially away from the image center,
with correction for the image aspect ratio (image_aspect = physical
image width/height), as follows:
r2 = image_aspect*image_aspect*u*u + v*v
f = 1 + r2*(k + kcube*sqrt(r2))
u' = f*u
v' = f*v
The constant k is the distortion coefficient that appears on the lens
panel and through Sizzle. It is generally a small positive or negative
number under 1%. The constant kcube is the cubic distortion value found
on the image preprocessor's lens panel: it can be used to undistort or
redistort images, but it does not affect or get computed by the solver.
When no cubic distortion is needed, neither is the square root, saving
time.
Chromatic Aberration example,
using red distord channel with green and blue undistord channel:
k = vec3(-0.15, 0.0, 0.0);
kcube = vec3(0.15, 0.0, 0.0);
*/
layout(location=0) in vec2 TexCoord;
layout(location=0) out vec4 FragColor;
layout(binding=0) uniform sampler2D InputTexture;
void main()
{
vec2 position = (TexCoord - vec2(0.5));
vec2 p = vec2(position.x * Aspect, position.y);
float r2 = dot(p, p);
vec3 f = vec3(1.0) + r2 * (k.rgb + kcube.rgb * sqrt(r2));
vec3 x = f * position.x * Scale + 0.5;
vec3 y = f * position.y * Scale + 0.5;
vec3 c;
c.r = texture(InputTexture, vec2(x.r, y.r)).r;
c.g = texture(InputTexture, vec2(x.g, y.g)).g;
c.b = texture(InputTexture, vec2(x.b, y.b)).b;
FragColor = vec4(c, 1.0);
}

View file

@ -0,0 +1,38 @@
layout(location=0) in vec2 TexCoord;
layout(location=0) out vec4 FragColor;
#if defined(MULTISAMPLE)
layout(binding=0) uniform sampler2DMS DepthTexture;
layout(binding=1) uniform sampler2DMS ColorTexture;
#else
layout(binding=0) uniform sampler2D DepthTexture;
layout(binding=1) uniform sampler2D ColorTexture;
#endif
float normalizeDepth(float depth)
{
float normalizedDepth = clamp(InverseDepthRangeA * depth + InverseDepthRangeB, 0.0, 1.0);
return 1.0 / (normalizedDepth * LinearizeDepthA + LinearizeDepthB);
}
void main()
{
vec2 uv = Offset + TexCoord * Scale;
#if defined(MULTISAMPLE)
ivec2 texSize = textureSize(DepthTexture);
#else
ivec2 texSize = textureSize(DepthTexture, 0);
#endif
ivec2 ipos = ivec2(max(uv * vec2(texSize), vec2(0.0)));
#if defined(MULTISAMPLE)
float depth = normalizeDepth(texelFetch(ColorTexture, ipos, SampleIndex).a != 0.0 ? texelFetch(DepthTexture, ipos, SampleIndex).x : 1.0);
#else
float depth = normalizeDepth(texelFetch(ColorTexture, ipos, 0).a != 0.0 ? texelFetch(DepthTexture, ipos, 0).x : 1.0);
#endif
FragColor = vec4(depth, 0.0, 0.0, 1.0);
}

View file

@ -0,0 +1,32 @@
varying vec2 TexCoord;
uniform sampler2D InputTexture;
uniform sampler2D DitherTexture;
vec4 ApplyGamma(vec4 c)
{
vec3 valgray;
valgray = mix(vec3(dot(c.rgb, vec3(0.3,0.56,0.14))), c.rgb, Saturation);
vec3 val = valgray * Contrast - (Contrast - 1.0) * 0.5;
val += Brightness * 0.5;
val = pow(max(val, vec3(0.0)), vec3(InvGamma));
return vec4(val, c.a);
}
//vec4 Dither(vec4 c)
//{
// if (ColorScale == 0.0)
// return c;
// vec2 texSize = vec2(textureSize(DitherTexture, 0));
// float threshold = texture2D(DitherTexture, gl_FragCoord.xy / texSize).r;
// return vec4(floor(c.rgb * ColorScale + threshold) / ColorScale, c.a);
//}
void main()
{
gl_FragColor = ApplyGamma(texture2D(InputTexture, UVOffset + TexCoord * UVScale));
}

View file

@ -0,0 +1,33 @@
layout(location=0) in vec2 TexCoord;
layout(location=0) out vec4 FragColor;
layout(binding=0) uniform sampler2D LeftEyeTexture;
layout(binding=1) uniform sampler2D RightEyeTexture;
vec4 ApplyGamma(vec4 c)
{
vec3 val = c.rgb * Contrast - (Contrast - 1.0) * 0.5;
val += Brightness * 0.5;
val = pow(max(val, vec3(0.0)), vec3(InvGamma));
return vec4(val, c.a);
}
void main()
{
int thisVerticalPixel = int(gl_FragCoord.y); // Bottom row is typically the right eye, when WindowHeight is even
int thisHorizontalPixel = int(gl_FragCoord.x); // column
bool isLeftEye = (thisVerticalPixel // because we want to alternate eye view on each row
+ thisHorizontalPixel // and each column
+ WindowPositionParity // because the window might not be aligned to the screen
) % 2 == 0;
vec4 inputColor;
if (isLeftEye) {
inputColor = texture(LeftEyeTexture, UVOffset + TexCoord * UVScale);
}
else {
// inputColor = vec4(0, 1, 0, 1);
inputColor = texture(RightEyeTexture, UVOffset + TexCoord * UVScale);
}
FragColor = ApplyGamma(inputColor);
}

View file

@ -0,0 +1,31 @@
layout(location=0) in vec2 TexCoord;
layout(location=0) out vec4 FragColor;
layout(binding=0) uniform sampler2D LeftEyeTexture;
layout(binding=1) uniform sampler2D RightEyeTexture;
vec4 ApplyGamma(vec4 c)
{
vec3 val = c.rgb * Contrast - (Contrast - 1.0) * 0.5;
val += Brightness * 0.5;
val = pow(max(val, vec3(0.0)), vec3(InvGamma));
return vec4(val, c.a);
}
void main()
{
int thisHorizontalPixel = int(gl_FragCoord.x); // zero-based column index from left
bool isLeftEye = (thisHorizontalPixel // because we want to alternate eye view on each column
+ WindowPositionParity // because the window might not be aligned to the screen
) % 2 == 0;
vec4 inputColor;
if (isLeftEye) {
inputColor = texture(LeftEyeTexture, UVOffset + TexCoord * UVScale);
}
else {
// inputColor = vec4(0, 1, 0, 1);
inputColor = texture(RightEyeTexture, UVOffset + TexCoord * UVScale);
}
FragColor = ApplyGamma(inputColor);
}

View file

@ -0,0 +1,31 @@
layout(location=0) in vec2 TexCoord;
layout(location=0) out vec4 FragColor;
layout(binding=0) uniform sampler2D LeftEyeTexture;
layout(binding=1) uniform sampler2D RightEyeTexture;
vec4 ApplyGamma(vec4 c)
{
vec3 val = c.rgb * Contrast - (Contrast - 1.0) * 0.5;
val += Brightness * 0.5;
val = pow(max(val, vec3(0.0)), vec3(InvGamma));
return vec4(val, c.a);
}
void main()
{
int thisVerticalPixel = int(gl_FragCoord.y); // Bottom row is typically the right eye, when WindowHeight is even
bool isLeftEye = (thisVerticalPixel // because we want to alternate eye view on each row
+ WindowPositionParity // because the window might not be aligned to the screen
) % 2 == 0;
vec4 inputColor;
if (isLeftEye) {
inputColor = texture(LeftEyeTexture, UVOffset + TexCoord * UVScale);
}
else {
// inputColor = vec4(0, 1, 0, 1);
inputColor = texture(RightEyeTexture, UVOffset + TexCoord * UVScale);
}
FragColor = ApplyGamma(inputColor);
}

View file

@ -0,0 +1,11 @@
attribute vec4 PositionInProjection;
attribute vec2 UV;
varying vec2 TexCoord;
void main()
{
gl_Position = PositionInProjection;
TexCoord = UV;
}

View file

@ -0,0 +1,190 @@
layout(location=0) in vec2 TexCoord;
layout(location=0) out vec4 FragColor;
// A node in an AABB binary tree with lines stored in the leaf nodes
struct GPUNode
{
vec2 aabb_min; // Min xy values for the axis-aligned box containing the node and its subtree
vec2 aabb_max; // Max xy values
int left; // Left subnode index
int right; // Right subnode index
int line_index; // Line index if it is a leaf node, otherwise -1
int padding; // Unused - maintains 16 byte alignment
};
// 2D line segment, referenced by leaf nodes
struct GPULine
{
vec2 pos; // Line start position
vec2 delta; // Line end position - line start position
};
layout(std430, binding = 4) buffer LightNodes
{
GPUNode nodes[];
};
layout(std430, binding = 5) buffer LightLines
{
GPULine lines[];
};
layout(std430, binding = 6) buffer LightList
{
vec4 lights[];
};
// Overlap test between line segment and axis-aligned bounding box. Returns true if they overlap.
bool overlapRayAABB(vec2 ray_start2d, vec2 ray_end2d, vec2 aabb_min2d, vec2 aabb_max2d)
{
// To do: simplify test to use a 2D test
vec3 ray_start = vec3(ray_start2d, 0.0);
vec3 ray_end = vec3(ray_end2d, 0.0);
vec3 aabb_min = vec3(aabb_min2d, -1.0);
vec3 aabb_max = vec3(aabb_max2d, 1.0);
vec3 c = (ray_start + ray_end) * 0.5f;
vec3 w = ray_end - c;
vec3 h = (aabb_max - aabb_min) * 0.5f; // aabb.extents();
c -= (aabb_max + aabb_min) * 0.5f; // aabb.center();
vec3 v = abs(w);
if (abs(c.x) > v.x + h.x || abs(c.y) > v.y + h.y || abs(c.z) > v.z + h.z)
return false; // disjoint;
if (abs(c.y * w.z - c.z * w.y) > h.y * v.z + h.z * v.y ||
abs(c.x * w.z - c.z * w.x) > h.x * v.z + h.z * v.x ||
abs(c.x * w.y - c.y * w.x) > h.x * v.y + h.y * v.x)
return false; // disjoint;
return true; // overlap;
}
// Intersection test between two line segments.
// Returns the intersection point as a value between 0-1 on the ray line segment. 1.0 if there was no hit.
float intersectRayLine(vec2 ray_start, vec2 ray_end, int line_index, vec2 raydelta, float rayd, float raydist2)
{
const float epsilon = 0.0000001;
GPULine line = lines[line_index];
vec2 raynormal = vec2(raydelta.y, -raydelta.x);
float den = dot(raynormal, line.delta);
if (abs(den) > epsilon)
{
float t_line = (rayd - dot(raynormal, line.pos)) / den;
if (t_line >= 0.0 && t_line <= 1.0)
{
vec2 linehitdelta = line.pos + line.delta * t_line - ray_start;
float t = dot(raydelta, linehitdelta) / raydist2;
return t > 0.0 ? t : 1.0;
}
}
return 1.0;
}
// Returns true if an AABB tree node is a leaf node. Leaf nodes contains a line.
bool isLeaf(int node_index)
{
return nodes[node_index].line_index != -1;
}
// Perform ray intersection test between the ray line segment and all the lines in the AABB binary tree.
// Returns the intersection point as a value between 0-1 on the ray line segment. 1.0 if there was no hit.
float rayTest(vec2 ray_start, vec2 ray_end)
{
vec2 raydelta = ray_end - ray_start;
float raydist2 = dot(raydelta, raydelta);
vec2 raynormal = vec2(raydelta.y, -raydelta.x);
float rayd = dot(raynormal, ray_start);
if (raydist2 < 1.0)
return 1.0;
float t = 1.0;
// Walk the AABB binary tree searching for nodes touching the ray line segment's AABB box.
// When it reaches a leaf node, use a line segment intersection test to see if we got a hit.
int stack[32];
int stack_pos = 1;
stack[0] = NodesCount - 1;
while (stack_pos > 0)
{
int node_index = stack[stack_pos - 1];
if (!overlapRayAABB(ray_start, ray_end, nodes[node_index].aabb_min, nodes[node_index].aabb_max))
{
stack_pos--;
}
else if (isLeaf(node_index))
{
t = min(intersectRayLine(ray_start, ray_end, nodes[node_index].line_index, raydelta, rayd, raydist2), t);
stack_pos--;
}
else if (stack_pos == 32)
{
stack_pos--; // stack overflow
}
else
{
stack[stack_pos - 1] = nodes[node_index].left;
stack[stack_pos] = nodes[node_index].right;
stack_pos++;
}
}
return t;
}
void main()
{
// Find the light that belongs to this texel in the shadowmap texture we output to:
int lightIndex = int(gl_FragCoord.y);
vec4 light = lights[lightIndex];
float radius = light.w;
vec2 lightpos = light.xy;
if (radius > 0.0)
{
// We found an active light. Calculate the ray direction for the texel.
//
// The texels are laid out so that there are four projections:
//
// * top-left to top-right
// * top-right to bottom-right
// * bottom-right to bottom-left
// * bottom-left to top-left
//
vec2 raydir;
float u = gl_FragCoord.x / ShadowmapQuality * 4.0;
switch (int(u))
{
case 0: raydir = vec2(u * 2.0 - 1.0, 1.0); break;
case 1: raydir = vec2(1.0, 1.0 - (u - 1.0) * 2.0); break;
case 2: raydir = vec2(1.0 - (u - 2.0) * 2.0, -1.0); break;
case 3: raydir = vec2(-1.0, (u - 3.0) * 2.0 - 1.0); break;
}
// Find the position for the ray starting at the light position and travelling until light contribution is zero:
vec2 pixelpos = lightpos + raydir * radius;
// Check if we hit any line between the light and the end position:
float t = rayTest(lightpos, pixelpos);
// Calculate the square distance for the hit, if any:
vec2 delta = (pixelpos - lightpos) * t;
float dist2 = dot(delta, delta);
FragColor = vec4(dist2, 0.0, 0.0, 1.0);
}
else
{
FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
}

View file

@ -0,0 +1,123 @@
layout(location=0) in vec2 TexCoord;
layout(location=0) out vec4 FragColor;
layout(binding=0) uniform sampler2D DepthTexture;
#if defined(MULTISAMPLE)
layout(binding=1) uniform sampler2DMS NormalTexture;
#else
layout(binding=1) uniform sampler2D NormalTexture;
#endif
#if defined(USE_RANDOM_TEXTURE)
layout(binding=2) uniform sampler2D RandomTexture;
#endif
#define PI 3.14159265358979323846
// Calculate eye space position for the specified texture coordinate
vec3 FetchViewPos(vec2 uv)
{
float z = texture(DepthTexture, uv).x;
return vec3((UVToViewA * uv + UVToViewB) * z, z);
}
#if defined(MULTISAMPLE)
vec3 SampleNormal(vec2 uv)
{
ivec2 texSize = textureSize(NormalTexture);
ivec2 ipos = ivec2(uv * vec2(texSize));
return texelFetch(NormalTexture, ipos, SampleIndex).xyz * 2.0 - 1.0;
}
#else
vec3 SampleNormal(vec2 uv)
{
ivec2 texSize = textureSize(NormalTexture, 0);
ivec2 ipos = ivec2(uv * vec2(texSize));
return texelFetch(NormalTexture, ipos, 0).xyz * 2.0 - 1.0;
}
#endif
// Look up the eye space normal for the specified texture coordinate
vec3 FetchNormal(vec2 uv)
{
vec3 normal = SampleNormal(Offset + uv * Scale);
if (length(normal) > 0.1)
{
normal = normalize(normal);
normal.z = -normal.z;
return normal;
}
else
{
return vec3(0.0);
}
}
// Compute normalized 2D direction
vec2 RotateDirection(vec2 dir, vec2 cossin)
{
return vec2(dir.x * cossin.x - dir.y * cossin.y, dir.x * cossin.y + dir.y * cossin.x);
}
vec4 GetJitter()
{
#if !defined(USE_RANDOM_TEXTURE)
return vec4(1,0,1,1);
//vec3 rand = noise3(TexCoord.x + TexCoord.y);
//float angle = 2.0 * PI * rand.x / NUM_DIRECTIONS;
//return vec4(cos(angle), sin(angle), rand.y, rand.z);
#else
return texture(RandomTexture, gl_FragCoord.xy / RANDOM_TEXTURE_WIDTH);
#endif
}
// Calculates the ambient occlusion of a sample
float ComputeSampleAO(vec3 kernelPos, vec3 normal, vec3 samplePos)
{
vec3 v = samplePos - kernelPos;
float distanceSquare = dot(v, v);
float nDotV = dot(normal, v) * inversesqrt(distanceSquare);
return clamp(nDotV - NDotVBias, 0.0, 1.0) * clamp(distanceSquare * NegInvR2 + 1.0, 0.0, 1.0);
}
// Calculates the total ambient occlusion for the entire fragment
float ComputeAO(vec3 viewPosition, vec3 viewNormal)
{
vec4 rand = GetJitter();
float radiusPixels = RadiusToScreen / viewPosition.z;
float stepSizePixels = radiusPixels / (NUM_STEPS + 1.0);
const float directionAngleStep = 2.0 * PI / NUM_DIRECTIONS;
float ao = 0.0;
for (float directionIndex = 0.0; directionIndex < NUM_DIRECTIONS; ++directionIndex)
{
float angle = directionAngleStep * directionIndex;
vec2 direction = RotateDirection(vec2(cos(angle), sin(angle)), rand.xy);
float rayPixels = (rand.z * stepSizePixels + 1.0);
for (float StepIndex = 0.0; StepIndex < NUM_STEPS; ++StepIndex)
{
vec2 sampleUV = round(rayPixels * direction) * InvFullResolution + TexCoord;
vec3 samplePos = FetchViewPos(sampleUV);
ao += ComputeSampleAO(viewPosition, viewNormal, samplePos);
rayPixels += stepSizePixels;
}
}
ao *= AOMultiplier / (NUM_DIRECTIONS * NUM_STEPS);
return clamp(1.0 - ao * 2.0, 0.0, 1.0);
}
void main()
{
vec3 viewPosition = FetchViewPos(TexCoord);
vec3 viewNormal = FetchNormal(TexCoord);
float occlusion = viewNormal != vec3(0.0) ? ComputeAO(viewPosition, viewNormal) * AOStrength + (1.0 - AOStrength) : 1.0;
FragColor = vec4(occlusion, viewPosition.z, 0.0, 1.0);
}

View file

@ -0,0 +1,41 @@
layout(location=0) in vec2 TexCoord;
layout(location=0) out vec4 FragColor;
layout(binding=0) uniform sampler2D AODepthTexture;
#if defined(MULTISAMPLE)
layout(binding=1) uniform sampler2DMS SceneFogTexture;
#else
layout(binding=1) uniform sampler2D SceneFogTexture;
#endif
void main()
{
vec2 uv = Offset + TexCoord * Scale;
#if defined(MULTISAMPLE)
ivec2 texSize = textureSize(SceneFogTexture);
#else
ivec2 texSize = textureSize(SceneFogTexture, 0);
#endif
ivec2 ipos = ivec2(uv * vec2(texSize));
#if defined(MULTISAMPLE)
vec3 fogColor = texelFetch(SceneFogTexture, ipos, 0).rgb;
#else
vec3 fogColor = texelFetch(SceneFogTexture, ipos, 0).rgb;
#endif
vec4 ssao = texture(AODepthTexture, TexCoord);
float attenutation = ssao.x;
if (DebugMode == 0)
FragColor = vec4(fogColor, 1.0 - attenutation);
else if (DebugMode < 3)
FragColor = vec4(attenutation, attenutation, attenutation, 1.0);
else if (DebugMode == 3)
FragColor = vec4(ssao.yyy / 1000.0, 1.0);
else
FragColor = vec4(ssao.xyz, 1.0);
}

View file

@ -0,0 +1,89 @@
layout(location=0) in vec2 TexCoord;
layout(location=0) out vec4 FragColor;
layout(binding=0) uniform sampler2D InputTexture;
vec3 Linear(vec3 c)
{
//c = max(c, vec3(0.0));
//return pow(c, 2.2);
return c * c; // cheaper, but assuming gamma of 2.0 instead of 2.2
}
vec3 sRGB(vec3 c)
{
c = max(c, vec3(0.0));
//return pow(c, vec3(1.0 / 2.2));
return sqrt(c); // cheaper, but assuming gamma of 2.0 instead of 2.2
}
#if defined(LINEAR)
vec3 Tonemap(vec3 color)
{
return sRGB(color);
}
#elif defined(REINHARD)
vec3 Tonemap(vec3 color)
{
color = color / (1.0 + color);
return sRGB(color);
}
#elif defined(HEJLDAWSON)
vec3 Tonemap(vec3 color)
{
vec3 x = max(vec3(0.0), color - 0.004);
return (x * (6.2 * x + 0.5)) / (x * (6.2 * x + 1.7) + 0.06); // no sRGB needed
}
#elif defined(UNCHARTED2)
vec3 Uncharted2Tonemap(vec3 x)
{
float A = 0.15;
float B = 0.50;
float C = 0.10;
float D = 0.20;
float E = 0.02;
float F = 0.30;
return ((x * (A * x + C * B) + D * E) / (x * (A * x + B) + D * F)) - E / F;
}
vec3 Tonemap(vec3 color)
{
float W = 11.2;
vec3 curr = Uncharted2Tonemap(color);
vec3 whiteScale = vec3(1) / Uncharted2Tonemap(vec3(W));
return sRGB(curr * whiteScale);
}
#elif defined(PALETTE)
layout(binding=1) uniform sampler2D PaletteLUT;
vec3 Tonemap(vec3 color)
{
ivec3 c = ivec3(clamp(color.rgb, vec3(0.0), vec3(1.0)) * 63.0 + 0.5);
int index = (c.r * 64 + c.g) * 64 + c.b;
int tx = index % 512;
int ty = index / 512;
return texelFetch(PaletteLUT, ivec2(tx, ty), 0).rgb;
}
#else
#error Tonemap mode define is missing
#endif
void main()
{
vec3 color = texture(InputTexture, TexCoord).rgb;
#ifndef PALETTE
color = Linear(color); // needed because gzdoom's scene texture is not linear at the moment
#endif
FragColor = vec4(Tonemap(color), 1.0);
}