forked from LeenkxTeam/LNXSDK
Update Files
This commit is contained in:
17
leenkx/Shaders/blend_pass/blend_pass.json
Normal file
17
leenkx/Shaders/blend_pass/blend_pass.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"contexts": [
|
||||
{
|
||||
"name": "blend_pass",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"blend_source": "blend_one",
|
||||
"blend_destination": "blend_one",
|
||||
"blend_operation": "add",
|
||||
"links": [],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass.vert.glsl",
|
||||
"fragment_shader": "../include/pass_copy.frag.glsl"
|
||||
}
|
||||
]
|
||||
}
|
62
leenkx/Shaders/bloom_pass/bloom_pass.json
Normal file
62
leenkx/Shaders/bloom_pass/bloom_pass.json
Normal file
@ -0,0 +1,62 @@
|
||||
{
|
||||
"contexts": [
|
||||
{
|
||||
"name": "downsample_pass",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [
|
||||
{
|
||||
"name": "screenSizeInv",
|
||||
"link": "_screenSizeInv"
|
||||
},
|
||||
{
|
||||
"name": "currentMipLevel",
|
||||
"link": "_downsampleCurrentMip"
|
||||
},
|
||||
{
|
||||
"name": "BloomThresholdData",
|
||||
"link": "_BloomThresholdData",
|
||||
"ifdef": ["_CPostprocess"]
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass.vert.glsl",
|
||||
"fragment_shader": "downsample_pass.frag.glsl"
|
||||
},
|
||||
{
|
||||
"name": "upsample_pass",
|
||||
"blend_source": "blend_one",
|
||||
"blend_destination": "blend_one",
|
||||
"blend_operation": "add",
|
||||
"alpha_blend_source": "blend_zero",
|
||||
"alpha_blend_destination": "blend_one",
|
||||
"alpha_blend_operation": "add",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [
|
||||
{
|
||||
"name": "screenSizeInv",
|
||||
"link": "_screenSizeInv"
|
||||
},
|
||||
{
|
||||
"name": "currentMipLevel",
|
||||
"link": "_upsampleCurrentMip"
|
||||
},
|
||||
{
|
||||
"name": "sampleScale",
|
||||
"link": "_bloomSampleScale"
|
||||
},
|
||||
{
|
||||
"name": "PPComp11",
|
||||
"link": "_PPComp11",
|
||||
"ifdef": ["_CPostprocess"]
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass.vert.glsl",
|
||||
"fragment_shader": "upsample_pass.frag.glsl"
|
||||
}
|
||||
]
|
||||
}
|
79
leenkx/Shaders/bloom_pass/downsample_pass.frag.glsl
Normal file
79
leenkx/Shaders/bloom_pass/downsample_pass.frag.glsl
Normal file
@ -0,0 +1,79 @@
|
||||
#version 450
|
||||
|
||||
#include "compiled.inc" // bloomKnee, bloomThreshold
|
||||
#include "std/resample.glsl"
|
||||
|
||||
uniform sampler2D tex;
|
||||
uniform vec2 screenSizeInv;
|
||||
uniform int currentMipLevel;
|
||||
|
||||
#ifdef _CPostprocess
|
||||
uniform vec4 BloomThresholdData; // Only filled with data if currentMipLevel == 0
|
||||
#endif
|
||||
|
||||
in vec2 texCoord;
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
const float epsilon = 6.2e-5; // see https://github.com/keijiro/KinoBloom/issues/15
|
||||
|
||||
#ifdef _BloomAntiFlicker
|
||||
const bool antiFlicker = true;
|
||||
#else
|
||||
const bool antiFlicker = false;
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
if (antiFlicker && currentMipLevel == 0) {
|
||||
#ifdef _BloomQualityHigh
|
||||
fragColor.rgb = downsample_13_tap_anti_flicker(tex, texCoord, screenSizeInv);
|
||||
#else
|
||||
#ifdef _BloomQualityMedium
|
||||
fragColor.rgb = downsample_dual_filter_anti_flicker(tex, texCoord, screenSizeInv);
|
||||
#else // _BloomQualityLow
|
||||
fragColor.rgb = downsample_box_filter_anti_flicker(tex, texCoord, screenSizeInv);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
#ifdef _BloomQualityHigh
|
||||
fragColor.rgb = downsample_13_tap(tex, texCoord, screenSizeInv);
|
||||
#else
|
||||
#ifdef _BloomQualityMedium
|
||||
fragColor.rgb = downsample_dual_filter(tex, texCoord, screenSizeInv);
|
||||
#else // _BloomQualityLow
|
||||
fragColor.rgb = downsample_box_filter(tex, texCoord, screenSizeInv);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
if (currentMipLevel == 0) {
|
||||
// https://catlikecoding.com/unity/tutorials/advanced-rendering/bloom/#3.2
|
||||
// https://catlikecoding.com/unity/tutorials/advanced-rendering/bloom/#3.4
|
||||
|
||||
float brightness = max(fragColor.r, max(fragColor.g, fragColor.b));
|
||||
|
||||
#ifdef _CPostprocess
|
||||
// Only apply precalculation optimization if _CPostprocess, otherwise
|
||||
// the compiler is able to do the same optimization for the constant
|
||||
// values from compiled.inc without the need to pass a uniform
|
||||
float softeningCurve = brightness - BloomThresholdData.y;
|
||||
softeningCurve = clamp(softeningCurve, 0.0, BloomThresholdData.z); // "connect" to hard knee curve
|
||||
softeningCurve = softeningCurve * softeningCurve * BloomThresholdData.w;
|
||||
|
||||
float contributionFactor = max(softeningCurve, brightness - BloomThresholdData.x);
|
||||
#else
|
||||
float softeningCurve = brightness - bloomThreshold + bloomKnee;
|
||||
softeningCurve = clamp(softeningCurve, 0.0, 2.0 * bloomKnee);
|
||||
softeningCurve = softeningCurve * softeningCurve / (4 * bloomKnee + epsilon);
|
||||
|
||||
float contributionFactor = max(softeningCurve, brightness - bloomThreshold);
|
||||
#endif
|
||||
|
||||
contributionFactor /= max(epsilon, brightness);
|
||||
|
||||
fragColor.rgb *= contributionFactor;
|
||||
}
|
||||
|
||||
fragColor.a = 1.0;
|
||||
}
|
39
leenkx/Shaders/bloom_pass/upsample_pass.frag.glsl
Normal file
39
leenkx/Shaders/bloom_pass/upsample_pass.frag.glsl
Normal file
@ -0,0 +1,39 @@
|
||||
#version 450
|
||||
|
||||
#include "compiled.inc" // bloomStrength
|
||||
#include "std/resample.glsl"
|
||||
|
||||
uniform sampler2D tex;
|
||||
uniform vec2 screenSizeInv;
|
||||
uniform int currentMipLevel;
|
||||
uniform float sampleScale;
|
||||
|
||||
#ifdef _CPostprocess
|
||||
uniform vec3 PPComp11;
|
||||
#endif
|
||||
|
||||
in vec2 texCoord;
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
void main() {
|
||||
#ifdef _BloomQualityHigh
|
||||
fragColor.rgb = upsample_tent_filter_3x3(tex, texCoord, screenSizeInv, sampleScale);
|
||||
#else
|
||||
#ifdef _BloomQualityMedium
|
||||
fragColor.rgb = upsample_dual_filter(tex, texCoord, screenSizeInv, sampleScale);
|
||||
#else // _BloomQualityLow
|
||||
fragColor.rgb = upsample_4tap_bilinear(tex, texCoord, screenSizeInv, sampleScale);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (currentMipLevel == 0) {
|
||||
#ifdef _CPostprocess
|
||||
fragColor.rgb *= PPComp11.x;
|
||||
#else
|
||||
fragColor.rgb *= bloomStrength;
|
||||
#endif
|
||||
}
|
||||
|
||||
fragColor.a = 1.0;
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
// Exclusive to SSR for now
|
||||
#version 450
|
||||
|
||||
#include "compiled.inc"
|
||||
#include "std/gbuffer.glsl"
|
||||
|
||||
uniform sampler2D tex;
|
||||
uniform sampler2D gbuffer0; // Roughness
|
||||
|
||||
uniform vec2 dirInv;
|
||||
|
||||
in vec2 texCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
void main() {
|
||||
float roughness = textureLod(gbuffer0, texCoord, 0.0).b;
|
||||
// if (roughness == 0.0) { // Always blur for now, non blured output can produce noise
|
||||
// fragColor.rgb = textureLod(tex, texCoord).rgb;
|
||||
// return;
|
||||
// }
|
||||
if (roughness >= 0.8) { // No reflections
|
||||
fragColor.rgb = textureLod(tex, texCoord, 0.0).rgb;
|
||||
return;
|
||||
}
|
||||
|
||||
fragColor.rgb = textureLod(tex, texCoord + dirInv * 2.5, 0.0).rgb;
|
||||
fragColor.rgb += textureLod(tex, texCoord + dirInv * 1.5, 0.0).rgb;
|
||||
fragColor.rgb += textureLod(tex, texCoord, 0.0).rgb;
|
||||
fragColor.rgb += textureLod(tex, texCoord - dirInv * 1.5, 0.0).rgb;
|
||||
fragColor.rgb += textureLod(tex, texCoord - dirInv * 2.5, 0.0).rgb;
|
||||
fragColor.rgb /= vec3(5.0);
|
||||
}
|
84
leenkx/Shaders/blur_adaptive_pass/blur_adaptive_pass.json
Normal file
84
leenkx/Shaders/blur_adaptive_pass/blur_adaptive_pass.json
Normal file
@ -0,0 +1,84 @@
|
||||
{
|
||||
"contexts": [
|
||||
{
|
||||
"name": "blur_adaptive_pass_x",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [
|
||||
{
|
||||
"name": "dirInv",
|
||||
"link": "_vec2xInv"
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass.vert.glsl",
|
||||
"fragment_shader": "blur_adaptive_pass.frag.glsl"
|
||||
},
|
||||
{
|
||||
"name": "blur_adaptive_pass_y",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [
|
||||
{
|
||||
"name": "dirInv",
|
||||
"link": "_vec2yInv"
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass.vert.glsl",
|
||||
"fragment_shader": "blur_adaptive_pass.frag.glsl"
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
"name": "blur_adaptive_pass_x2",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [
|
||||
{
|
||||
"name": "dirInv",
|
||||
"link": "_vec2x2Inv"
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass.vert.glsl",
|
||||
"fragment_shader": "blur_adaptive_pass.frag.glsl"
|
||||
},
|
||||
{
|
||||
"name": "blur_adaptive_pass_y3",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [
|
||||
{
|
||||
"name": "dirInv",
|
||||
"link": "_vec2y3Inv"
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass.vert.glsl",
|
||||
"fragment_shader": "blur_adaptive_pass.frag.glsl"
|
||||
},
|
||||
{
|
||||
"name": "blur_adaptive_pass_y3_blend",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"blend_source": "blend_one",
|
||||
"blend_destination": "blend_one",
|
||||
"blend_operation": "add",
|
||||
"links": [
|
||||
{
|
||||
"name": "dirInv",
|
||||
"link": "_vec2y3Inv"
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass.vert.glsl",
|
||||
"fragment_shader": "blur_adaptive_pass.frag.glsl"
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
// Exclusive to volumetric light for now
|
||||
#version 450
|
||||
|
||||
#include "compiled.inc"
|
||||
|
||||
uniform sampler2D tex;
|
||||
uniform vec2 dir;
|
||||
uniform vec2 screenSize;
|
||||
|
||||
in vec2 texCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
const float weight[10] = float[] (0.132572, 0.125472, 0.106373, 0.08078, 0.05495, 0.033482, 0.018275, 0.008934, 0.003912, 0.001535);
|
||||
|
||||
float normpdf(float x, float sigma) {
|
||||
return 0.39894 * exp(-0.5 * x * x / (sigma * sigma)) / sigma;
|
||||
}
|
||||
|
||||
float normpdf3(vec3 v, float sigma) {
|
||||
return 0.39894 * exp(-0.5 * dot(v, v) / (sigma * sigma)) / sigma;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 step = (dir / screenSize.xy);
|
||||
vec3 colf = textureLod(tex, texCoord, 0.0).rgb * weight[0];
|
||||
|
||||
float col;
|
||||
float res = 0.0;
|
||||
float sumfactor = 0.0;
|
||||
float factor;
|
||||
float f = 1.0 / normpdf(0.0, 1.0);
|
||||
|
||||
for (int i = 1; i < 10; i++) {
|
||||
float fw = f * weight[i];
|
||||
vec2 s = step * (float(i) + 0.5);
|
||||
|
||||
col = textureLod(tex, texCoord + s, 0.0).r;
|
||||
factor = normpdf3(col - colf, 1.0) * fw;
|
||||
sumfactor += factor;
|
||||
res += factor * col;
|
||||
|
||||
col = textureLod(tex, texCoord - s, 0.0).r;
|
||||
factor = normpdf3(col - colf, 1.0) * fw;
|
||||
sumfactor += factor;
|
||||
res += factor * col;
|
||||
}
|
||||
|
||||
res /= sumfactor;
|
||||
fragColor = vec4(volumAirColor * res, 1.0);
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
{
|
||||
"contexts": [
|
||||
{
|
||||
"name": "blur_bilat_blend_pass_y",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"blend_source": "blend_one",
|
||||
"blend_destination": "blend_one",
|
||||
"blend_operation": "add",
|
||||
"alpha_blend_source": "blend_one",
|
||||
"alpha_blend_destination": "blend_one",
|
||||
"alpha_blend_operation": "add",
|
||||
"links": [
|
||||
{
|
||||
"name": "dir",
|
||||
"link": "_vec2y"
|
||||
},
|
||||
{
|
||||
"name": "screenSize",
|
||||
"link": "_screenSize"
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass.vert.glsl",
|
||||
"fragment_shader": "blur_bilat_blend_pass.frag.glsl"
|
||||
}
|
||||
]
|
||||
}
|
49
leenkx/Shaders/blur_bilat_pass/blur_bilat_pass.frag.glsl
Normal file
49
leenkx/Shaders/blur_bilat_pass/blur_bilat_pass.frag.glsl
Normal file
@ -0,0 +1,49 @@
|
||||
// Exclusive to volumetric light for now
|
||||
#version 450
|
||||
|
||||
#include "compiled.inc"
|
||||
|
||||
uniform sampler2D tex;
|
||||
uniform vec2 dir;
|
||||
uniform vec2 screenSize;
|
||||
|
||||
in vec2 texCoord;
|
||||
out float fragColor;
|
||||
|
||||
const float weight[10] = float[] (0.132572, 0.125472, 0.106373, 0.08078, 0.05495, 0.033482, 0.018275, 0.008934, 0.003912, 0.001535);
|
||||
|
||||
float normpdf(float x, float sigma) {
|
||||
return 0.39894 * exp(-0.5 * x * x / (sigma * sigma)) / sigma;
|
||||
}
|
||||
|
||||
float normpdf3(vec3 v, float sigma) {
|
||||
return 0.39894 * exp(-0.5 * dot(v, v) / (sigma * sigma)) / sigma;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 step = (dir / screenSize.xy);
|
||||
vec3 colf = textureLod(tex, texCoord, 0.0).rgb * weight[0];
|
||||
|
||||
float col;
|
||||
float sumfactor = 0.0;
|
||||
float factor;
|
||||
float f = 1.0 / normpdf(0.0, 1.0);
|
||||
fragColor = 0.0;
|
||||
|
||||
for (int i = 1; i < 10; i++) {
|
||||
float fw = f * weight[i];
|
||||
vec2 s = step * (float(i) + 0.5);
|
||||
|
||||
col = textureLod(tex, texCoord + s, 0.0).r;
|
||||
factor = normpdf3(col - colf, 1.0) * fw;
|
||||
sumfactor += factor;
|
||||
fragColor += factor * col;
|
||||
|
||||
col = textureLod(tex, texCoord - s, 0.0).r;
|
||||
factor = normpdf3(col - colf, 1.0) * fw;
|
||||
sumfactor += factor;
|
||||
fragColor += factor * col;
|
||||
}
|
||||
|
||||
fragColor /= sumfactor;
|
||||
}
|
67
leenkx/Shaders/blur_bilat_pass/blur_bilat_pass.json
Normal file
67
leenkx/Shaders/blur_bilat_pass/blur_bilat_pass.json
Normal file
@ -0,0 +1,67 @@
|
||||
{
|
||||
"contexts": [
|
||||
{
|
||||
"name": "blur_bilat_pass_x",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [
|
||||
{
|
||||
"name": "dir",
|
||||
"link": "_vec2x"
|
||||
},
|
||||
{
|
||||
"name": "screenSize",
|
||||
"link": "_screenSize"
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass.vert.glsl",
|
||||
"fragment_shader": "blur_bilat_pass.frag.glsl"
|
||||
},
|
||||
{
|
||||
"name": "blur_bilat_pass_y",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [
|
||||
{
|
||||
"name": "dir",
|
||||
"link": "_vec2y"
|
||||
},
|
||||
{
|
||||
"name": "screenSize",
|
||||
"link": "_screenSize"
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass.vert.glsl",
|
||||
"fragment_shader": "blur_bilat_pass.frag.glsl"
|
||||
},
|
||||
{
|
||||
"name": "blur_bilat_pass_y_blend",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"blend_source": "blend_one",
|
||||
"blend_destination": "blend_one",
|
||||
"blend_operation": "add",
|
||||
"alpha_blend_source": "blend_one",
|
||||
"alpha_blend_destination": "blend_one",
|
||||
"alpha_blend_operation": "add",
|
||||
"links": [
|
||||
{
|
||||
"name": "dir",
|
||||
"link": "_vec2y"
|
||||
},
|
||||
{
|
||||
"name": "screenSize",
|
||||
"link": "_screenSize"
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass.vert.glsl",
|
||||
"fragment_shader": "blur_bilat_pass.frag.glsl"
|
||||
}
|
||||
]
|
||||
}
|
44
leenkx/Shaders/blur_edge_pass/blur_edge_pass.frag.glsl
Normal file
44
leenkx/Shaders/blur_edge_pass/blur_edge_pass.frag.glsl
Normal file
@ -0,0 +1,44 @@
|
||||
// Exclusive to SSAO for now
|
||||
#version 450
|
||||
|
||||
#include "compiled.inc"
|
||||
#include "std/gbuffer.glsl"
|
||||
|
||||
uniform sampler2D tex;
|
||||
uniform sampler2D gbuffer0;
|
||||
|
||||
uniform vec2 dirInv; // texStep
|
||||
|
||||
in vec2 texCoord;
|
||||
out float fragColor;
|
||||
|
||||
// const float blurWeights[5] = float[] (0.227027, 0.1945946, 0.1216216, 0.054054, 0.016216);
|
||||
const float blurWeights[10] = float[] (0.132572, 0.125472, 0.106373, 0.08078, 0.05495, 0.033482, 0.018275, 0.008934, 0.003912, 0.001535);
|
||||
const float discardThreshold = 0.95;
|
||||
|
||||
void main() {
|
||||
vec3 nor = getNor(textureLod(gbuffer0, texCoord, 0.0).rg);
|
||||
|
||||
fragColor = textureLod(tex, texCoord, 0.0).r * blurWeights[0];
|
||||
float weight = blurWeights[0];
|
||||
|
||||
for (int i = 1; i < 8; ++i) {
|
||||
float posadd = i;// + 0.5;
|
||||
|
||||
vec3 nor2 = getNor(textureLod(gbuffer0, texCoord + i * dirInv, 0.0).rg);
|
||||
float influenceFactor = step(discardThreshold, dot(nor2, nor));
|
||||
float col = textureLod(tex, texCoord + posadd * dirInv, 0.0).r;
|
||||
float w = blurWeights[i] * influenceFactor;
|
||||
fragColor += col * w;
|
||||
weight += w;
|
||||
|
||||
nor2 = getNor(textureLod(gbuffer0, texCoord - i * dirInv, 0.0).rg);
|
||||
influenceFactor = step(discardThreshold, dot(nor2, nor));
|
||||
col = textureLod(tex, texCoord - posadd * dirInv, 0.0).r;
|
||||
w = blurWeights[i] * influenceFactor;
|
||||
fragColor += col * w;
|
||||
weight += w;
|
||||
}
|
||||
|
||||
fragColor = fragColor / weight;
|
||||
}
|
74
leenkx/Shaders/blur_edge_pass/blur_edge_pass.json
Normal file
74
leenkx/Shaders/blur_edge_pass/blur_edge_pass.json
Normal file
@ -0,0 +1,74 @@
|
||||
{
|
||||
"contexts": [
|
||||
{
|
||||
"name": "blur_edge_pass_x",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [
|
||||
{
|
||||
"name": "dirInv",
|
||||
"link": "_vec2xInv"
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass.vert.glsl",
|
||||
"fragment_shader": "blur_edge_pass.frag.glsl"
|
||||
},
|
||||
{
|
||||
"name": "blur_edge_pass_y",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [
|
||||
{
|
||||
"name": "dirInv",
|
||||
"link": "_vec2yInv"
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass.vert.glsl",
|
||||
"fragment_shader": "blur_edge_pass.frag.glsl"
|
||||
},
|
||||
{
|
||||
"name": "blur_edge_pass_y_blend",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"blend_source": "destination_color",
|
||||
"blend_destination": "blend_zero",
|
||||
"blend_operation": "add",
|
||||
"links": [
|
||||
{
|
||||
"name": "dirInv",
|
||||
"link": "_vec2yInv"
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass.vert.glsl",
|
||||
"fragment_shader": "blur_edge_pass.frag.glsl"
|
||||
},
|
||||
|
||||
{
|
||||
"name": "blur_edge_pass_y_blend_add",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"blend_source": "blend_one",
|
||||
"blend_destination": "blend_one",
|
||||
"blend_operation": "add",
|
||||
"alpha_blend_source": "blend_one",
|
||||
"alpha_blend_destination": "blend_one",
|
||||
"alpha_blend_operation": "add",
|
||||
"links": [
|
||||
{
|
||||
"name": "dirInv",
|
||||
"link": "_vec2yInv"
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass.vert.glsl",
|
||||
"fragment_shader": "blur_edge_pass.frag.glsl"
|
||||
}
|
||||
]
|
||||
}
|
23
leenkx/Shaders/blur_pass/blur_pass.frag.glsl
Normal file
23
leenkx/Shaders/blur_pass/blur_pass.frag.glsl
Normal file
@ -0,0 +1,23 @@
|
||||
#version 450
|
||||
|
||||
uniform sampler2D tex;
|
||||
|
||||
uniform vec2 dirInv;
|
||||
|
||||
in vec2 texCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
void main() {
|
||||
fragColor.rgb = textureLod(tex, texCoord + dirInv * 5.5, 0.0).rgb;
|
||||
fragColor.rgb += textureLod(tex, texCoord + dirInv * 4.5, 0.0).rgb;
|
||||
fragColor.rgb += textureLod(tex, texCoord + dirInv * 3.5, 0.0).rgb;
|
||||
fragColor.rgb += textureLod(tex, texCoord + dirInv * 2.5, 0.0).rgb;
|
||||
fragColor.rgb += textureLod(tex, texCoord + dirInv * 1.5, 0.0).rgb;
|
||||
fragColor.rgb += textureLod(tex, texCoord, 0.0).rgb;
|
||||
fragColor.rgb += textureLod(tex, texCoord - dirInv * 1.5, 0.0).rgb;
|
||||
fragColor.rgb += textureLod(tex, texCoord - dirInv * 2.5, 0.0).rgb;
|
||||
fragColor.rgb += textureLod(tex, texCoord - dirInv * 3.5, 0.0).rgb;
|
||||
fragColor.rgb += textureLod(tex, texCoord - dirInv * 4.5, 0.0).rgb;
|
||||
fragColor.rgb += textureLod(tex, texCoord - dirInv * 5.5, 0.0).rgb;
|
||||
fragColor.rgb /= vec3(11.0);
|
||||
}
|
66
leenkx/Shaders/blur_pass/blur_pass.json
Normal file
66
leenkx/Shaders/blur_pass/blur_pass.json
Normal file
@ -0,0 +1,66 @@
|
||||
{
|
||||
"contexts": [
|
||||
{
|
||||
"name": "blur_pass_x",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [
|
||||
{
|
||||
"name": "dirInv",
|
||||
"link": "_vec2xInv"
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass.vert.glsl",
|
||||
"fragment_shader": "blur_pass.frag.glsl"
|
||||
},
|
||||
{
|
||||
"name": "blur_pass_y",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [
|
||||
{
|
||||
"name": "dirInv",
|
||||
"link": "_vec2yInv"
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass.vert.glsl",
|
||||
"fragment_shader": "blur_pass.frag.glsl"
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
"name": "blur_pass_x2",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [
|
||||
{
|
||||
"name": "dirInv",
|
||||
"link": "_vec2x2Inv"
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass.vert.glsl",
|
||||
"fragment_shader": "blur_pass.frag.glsl"
|
||||
},
|
||||
{
|
||||
"name": "blur_pass_y2",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [
|
||||
{
|
||||
"name": "dirInv",
|
||||
"link": "_vec2y2Inv"
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass.vert.glsl",
|
||||
"fragment_shader": "blur_pass.frag.glsl"
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
#version 450
|
||||
|
||||
#include "compiled.inc"
|
||||
|
||||
uniform sampler2D tex;
|
||||
|
||||
#ifdef _CPostprocess
|
||||
uniform vec3 PPComp13;
|
||||
#endif
|
||||
|
||||
in vec2 texCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
vec2 barrelDistortion(vec2 coord, float amt) {
|
||||
vec2 cc = coord - 0.5;
|
||||
float dist = dot(cc, cc);
|
||||
return coord + cc * dist * amt;
|
||||
}
|
||||
float sat(float value)
|
||||
{
|
||||
return clamp(value, 0.0, 1.0);
|
||||
}
|
||||
float linterp(float t) {
|
||||
return sat(1.0 - abs(2.0 * t - 1.0) );
|
||||
}
|
||||
float remap(float t, float a, float b ) {
|
||||
return sat((t - a) / (b - a));
|
||||
}
|
||||
vec4 spectrum_offset(float t) {
|
||||
vec4 ret;
|
||||
float low = step(t,0.5);
|
||||
float high = 1.0 - low;
|
||||
float minMap = 1.0;
|
||||
float maxMap = 6.0;
|
||||
float w = linterp( remap(t, minMap/maxMap, 5.0/maxMap ) );
|
||||
ret = vec4(low, 1.0, high, 1.) * vec4(1.0-w, w, 1.0-w, 1.0);
|
||||
|
||||
return pow(ret, vec4(1.0/2.2) );
|
||||
}
|
||||
|
||||
void main() {
|
||||
|
||||
#ifdef _CPostprocess
|
||||
float max_distort = PPComp13.x;
|
||||
int num_iter = int(PPComp13.y);
|
||||
#else
|
||||
float max_distort = compoChromaticStrength;
|
||||
int num_iter = compoChromaticSamples;
|
||||
#endif
|
||||
|
||||
// Spectral
|
||||
if (compoChromaticType == 1) {
|
||||
float reci_num_iter_f = 1.0 / float(num_iter);
|
||||
|
||||
vec2 resolution = vec2(1,1);
|
||||
vec2 uv = (texCoord.xy/resolution.xy);
|
||||
vec4 sumcol = vec4(0.0);
|
||||
vec4 sumw = vec4(0.0);
|
||||
for (int i=0; i < num_iter; ++i)
|
||||
{
|
||||
float t = float(i) * reci_num_iter_f;
|
||||
vec4 w = spectrum_offset(t);
|
||||
sumw += w;
|
||||
sumcol += w * texture(tex, barrelDistortion(uv, 0.6 * max_distort * t));
|
||||
}
|
||||
|
||||
fragColor = sumcol / sumw;
|
||||
}
|
||||
|
||||
// Simple
|
||||
else {
|
||||
vec3 col = vec3(0.0);
|
||||
col.x = texture(tex, texCoord + ((vec2(0.0, 1.0) * max_distort) / vec2(1000.0))).x;
|
||||
col.y = texture(tex, texCoord + ((vec2(-0.85, -0.5) * max_distort) / vec2(1000.0))).y;
|
||||
col.z = texture(tex, texCoord + ((vec2(0.85, -0.5) * max_distort) / vec2(1000.0))).z;
|
||||
fragColor = vec4(col.x, col.y, col.z, fragColor.w);
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
{
|
||||
"contexts": [
|
||||
{
|
||||
"name": "chromatic_aberration_pass",
|
||||
"depth_write": false,
|
||||
"color_write_alpha": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [
|
||||
{
|
||||
"name": "PPComp13",
|
||||
"link": "_PPComp13",
|
||||
"ifdef": ["_CPostprocess"]
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass.vert.glsl",
|
||||
"fragment_shader": "chromatic_aberration_pass.frag.glsl"
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
#version 450
|
||||
|
||||
in vec2 texCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
void main() {
|
||||
fragColor = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
gl_FragDepth = 1.0;
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
{
|
||||
"contexts": [
|
||||
{
|
||||
"name": "clear_color_depth_pass",
|
||||
"depth_write": true,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass.vert.glsl",
|
||||
"fragment_shader": "clear_color_depth_pass.frag.glsl",
|
||||
"color_attachments": ["_HDR"]
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
#version 450
|
||||
|
||||
in vec2 texCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
void main() {
|
||||
fragColor = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
}
|
15
leenkx/Shaders/clear_color_pass/clear_color_pass.json
Normal file
15
leenkx/Shaders/clear_color_pass/clear_color_pass.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"contexts": [
|
||||
{
|
||||
"name": "clear_color_pass",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass.vert.glsl",
|
||||
"fragment_shader": "clear_color_pass.frag.glsl",
|
||||
"color_attachments": ["_HDR"]
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
#version 450
|
||||
|
||||
in vec2 texCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
void main() {
|
||||
gl_FragDepth = 1.0;
|
||||
}
|
19
leenkx/Shaders/clear_depth_pass/clear_depth_pass.json
Normal file
19
leenkx/Shaders/clear_depth_pass/clear_depth_pass.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"contexts": [
|
||||
{
|
||||
"name": "clear_depth_pass",
|
||||
"depth_write": true,
|
||||
"color_write_red": false,
|
||||
"color_write_green": false,
|
||||
"color_write_blue": false,
|
||||
"color_write_alpha": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass.vert.glsl",
|
||||
"fragment_shader": "clear_depth_pass.frag.glsl",
|
||||
"color_attachments": ["_HDR"]
|
||||
}
|
||||
]
|
||||
}
|
617
leenkx/Shaders/compositor_pass/compositor_pass.frag.glsl
Normal file
617
leenkx/Shaders/compositor_pass/compositor_pass.frag.glsl
Normal file
@ -0,0 +1,617 @@
|
||||
#version 450
|
||||
|
||||
#include "compiled.inc"
|
||||
#include "std/tonemap.glsl"
|
||||
#include "std/math.glsl"
|
||||
#ifdef _CDOF
|
||||
#include "std/dof.glsl"
|
||||
#endif
|
||||
#ifdef _CPostprocess
|
||||
#include "std/colorgrading.glsl"
|
||||
#endif
|
||||
|
||||
uniform sampler2D tex;
|
||||
#ifdef _CDepth
|
||||
uniform sampler2D gbufferD;
|
||||
#endif
|
||||
|
||||
#ifdef _CLensTex
|
||||
uniform sampler2D lensTexture;
|
||||
#endif
|
||||
|
||||
#ifdef _CLUT
|
||||
uniform sampler2D lutTexture;
|
||||
#endif
|
||||
|
||||
#ifdef _AutoExposure
|
||||
uniform sampler2D histogram;
|
||||
#endif
|
||||
|
||||
#ifdef _CPostprocess
|
||||
uniform vec3 globalWeight;
|
||||
uniform vec3 globalTint;
|
||||
uniform vec3 globalSaturation;
|
||||
uniform vec3 globalContrast;
|
||||
uniform vec3 globalGamma;
|
||||
uniform vec3 globalGain;
|
||||
uniform vec3 globalOffset;
|
||||
|
||||
uniform vec3 shadowSaturation;
|
||||
uniform vec3 shadowContrast;
|
||||
uniform vec3 shadowGamma;
|
||||
uniform vec3 shadowGain;
|
||||
uniform vec3 shadowOffset;
|
||||
|
||||
uniform vec3 midtoneSaturation;
|
||||
uniform vec3 midtoneContrast;
|
||||
uniform vec3 midtoneGamma;
|
||||
uniform vec3 midtoneGain;
|
||||
uniform vec3 midtoneOffset;
|
||||
|
||||
uniform vec3 highlightSaturation;
|
||||
uniform vec3 highlightContrast;
|
||||
uniform vec3 highlightGamma;
|
||||
uniform vec3 highlightGain;
|
||||
uniform vec3 highlightOffset;
|
||||
|
||||
uniform vec3 PPComp1;
|
||||
uniform vec3 PPComp2;
|
||||
uniform vec3 PPComp3;
|
||||
uniform vec3 PPComp4;
|
||||
uniform vec3 PPComp5;
|
||||
uniform vec3 PPComp6;
|
||||
uniform vec3 PPComp7;
|
||||
uniform vec3 PPComp8;
|
||||
uniform vec3 PPComp14;
|
||||
uniform vec4 PPComp15;
|
||||
#endif
|
||||
|
||||
// #ifdef _CPos
|
||||
// uniform vec3 eye;
|
||||
// uniform vec3 eyeLook;
|
||||
// #endif
|
||||
|
||||
#ifdef _CGlare
|
||||
uniform vec3 light;
|
||||
uniform mat4 VP;
|
||||
uniform vec3 eye;
|
||||
uniform vec3 eyeLook;
|
||||
uniform float aspectRatio;
|
||||
#endif
|
||||
|
||||
#ifdef _CTexStep
|
||||
uniform vec2 texStep;
|
||||
#endif
|
||||
|
||||
#ifdef _CDistort
|
||||
uniform float time;
|
||||
#else
|
||||
#ifdef _CGrain
|
||||
uniform float time;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _DynRes
|
||||
uniform float dynamicScale;
|
||||
#endif
|
||||
|
||||
#ifdef _CCameraProj
|
||||
uniform vec2 cameraProj;
|
||||
#endif
|
||||
|
||||
in vec2 texCoord;
|
||||
// #ifdef _CPos
|
||||
// in vec3 viewRay;
|
||||
// #endif
|
||||
out vec4 fragColor;
|
||||
|
||||
#ifdef _CFog
|
||||
// const vec3 compoFogColor = vec3(0.5, 0.6, 0.7);
|
||||
// const float compoFogAmountA = 1.0; // b = 0.01
|
||||
// const float compoFogAmountB = 1.0; // c = 0.1
|
||||
// vec3 applyFog(vec3 rgb, // original color of the pixel
|
||||
// float distance, // camera to point distance
|
||||
// vec3 rayOri, // camera position
|
||||
// vec3 rayDir) { // camera to point vector
|
||||
// float fogAmount = compoFogAmountB * exp(-rayOri.y * compoFogAmountA) * (1.0 - exp(-distance * rayDir.y * compoFogAmountA)) / rayDir.y;
|
||||
// return mix(rgb, compoFogColor, fogAmount);
|
||||
// }
|
||||
vec3 applyFog(vec3 rgb, float distance) {
|
||||
// float fogAmount = 1.0 - exp(-distance * compoFogAmountA);
|
||||
float fogAmount = 1.0 - exp(-distance * (compoFogAmountA / 100));
|
||||
return mix(rgb, compoFogColor, fogAmount);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _CPostprocess
|
||||
float ComputeEV100(const float aperture2, const float shutterTime, const float ISO) {
|
||||
return log2(aperture2 / shutterTime * 100.0 / ISO);
|
||||
}
|
||||
float ConvertEV100ToExposure(float EV100) {
|
||||
return 1/0.8 * exp2(-EV100);
|
||||
}
|
||||
float ComputeEV(float avgLuminance) {
|
||||
const float sqAperture = PPComp1[0].x * PPComp1.x;
|
||||
const float shutterTime = 1.0 / PPComp1.y;
|
||||
const float ISO = PPComp1.z;
|
||||
const float EC = PPComp2.x;
|
||||
|
||||
float EV100 = ComputeEV100(sqAperture, shutterTime, ISO);
|
||||
|
||||
return ConvertEV100ToExposure(EV100 - EC) * PI;
|
||||
}
|
||||
#endif
|
||||
|
||||
vec4 LUTlookup(in vec4 textureColor, in sampler2D lookupTable) {
|
||||
|
||||
//Clamp to prevent weird results
|
||||
textureColor = clamp(textureColor, 0.0, 1.0);
|
||||
|
||||
mediump float blueColor = textureColor.b * 63.0;
|
||||
mediump vec2 quad1;
|
||||
|
||||
quad1.y = floor(floor(blueColor) / 8.0);
|
||||
quad1.x = floor(blueColor) - (quad1.y * 8.0);
|
||||
|
||||
mediump vec2 quad2;
|
||||
quad2.y = floor(ceil(blueColor) / 8.0);
|
||||
quad2.x = ceil(blueColor) - (quad2.y * 8.0);
|
||||
|
||||
highp vec2 texelPosition1;
|
||||
texelPosition1.x = (quad1.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);
|
||||
texelPosition1.y = (quad1.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g);
|
||||
|
||||
highp vec2 texelPosition2;
|
||||
texelPosition2.x = (quad2.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);
|
||||
texelPosition2.y = (quad2.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g);
|
||||
|
||||
lowp vec4 newColor1 = textureLod(lookupTable, texelPosition1, 0.0);
|
||||
lowp vec4 newColor2 = textureLod(lookupTable, texelPosition2, 0.0);
|
||||
|
||||
lowp vec4 colorGradedResult = mix(newColor1, newColor2, fract(blueColor));
|
||||
|
||||
return colorGradedResult;
|
||||
|
||||
}
|
||||
|
||||
#ifdef _CVignette
|
||||
float vignette() {
|
||||
#ifdef _CPostprocess
|
||||
float strengthVignette = PPComp14.z;
|
||||
#else
|
||||
float strengthVignette = compoVignetteStrength;
|
||||
#endif
|
||||
return (1.0 - strengthVignette) + strengthVignette * pow(16.0 * texCoord.x * texCoord.y * (1.0 - texCoord.x) * (1.0 - texCoord.y), 0.2);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _CGlare
|
||||
// Based on lense flare implementation by musk
|
||||
// https://www.shadertoy.com/view/4sX3Rs
|
||||
vec3 lensflare(vec2 uv, vec2 pos) {
|
||||
vec2 uvd = uv * (length(uv));
|
||||
float f2 = max(1.0/(1.0+32.0*pow(length(uvd+0.8*pos),2.0)),0.0)*0.25;
|
||||
float f22 = max(1.0/(1.0+32.0*pow(length(uvd+0.85*pos),2.0)),0.0)*0.23;
|
||||
float f23 = max(1.0/(1.0+32.0*pow(length(uvd+0.9*pos),2.0)),0.0)*0.21;
|
||||
|
||||
vec2 uvx = mix(uv, uvd, -0.5);
|
||||
float f4 = max(0.01-pow(length(uvx+0.4*pos),2.4),0.0)*6.0;
|
||||
float f42 = max(0.01-pow(length(uvx+0.45*pos),2.4),0.0)*5.0;
|
||||
float f43 = max(0.01-pow(length(uvx+0.5*pos),2.4),0.0)*3.0;
|
||||
|
||||
uvx = mix(uv, uvd, -0.4);
|
||||
float f5 = max(0.01-pow(length(uvx+0.2*pos),5.5),0.0)*2.0;
|
||||
float f52 = max(0.01-pow(length(uvx+0.4*pos),5.5),0.0)*2.0;
|
||||
float f53 = max(0.01-pow(length(uvx+0.6*pos),5.5),0.0)*2.0;
|
||||
|
||||
uvx = mix(uv, uvd, -0.5);
|
||||
float f6 = max(0.01-pow(length(uvx-0.3*pos),1.6),0.0)*6.0;
|
||||
float f62 = max(0.01-pow(length(uvx-0.325*pos),1.6),0.0)*3.0;
|
||||
float f63 = max(0.01-pow(length(uvx-0.35*pos),1.6),0.0)*5.0;
|
||||
|
||||
vec3 c = vec3(0.0);
|
||||
c.r += f2 + f4 + f5 + f6;
|
||||
c.g += f22 + f42 + f52 + f62;
|
||||
c.b += f23 + f43 + f53 + f63;
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
vec2 texCo = texCoord;
|
||||
#ifdef _DynRes
|
||||
texCo *= dynamicScale;
|
||||
#endif
|
||||
|
||||
#ifdef _CLetterbox
|
||||
#ifdef _CPostprocess
|
||||
vec3 uColor = vec3(PPComp15.x, PPComp15.y, PPComp15.z);
|
||||
float uSize = PPComp15.w;
|
||||
#else
|
||||
vec3 uColor = compoLetterboxColor;
|
||||
float uSize = compoLetterboxSize;
|
||||
#endif
|
||||
if (texCo.y < uSize || texCo.y > (1.0 - uSize)) {
|
||||
fragColor.rgb = uColor;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _CFishEye
|
||||
#ifdef _CPostprocess
|
||||
const float fishEyeStrength = -(PPComp2.y);
|
||||
#else
|
||||
const float fishEyeStrength = -0.01;
|
||||
#endif
|
||||
const vec2 m = vec2(0.5, 0.5);
|
||||
vec2 d = texCo - m;
|
||||
float r = sqrt(dot(d, d));
|
||||
float power = (2.0 * PI / (2.0 * sqrt(dot(m, m)))) * fishEyeStrength;
|
||||
float bind;
|
||||
if (power > 0.0) { bind = sqrt(dot(m, m)); }
|
||||
else { bind = m.x; }
|
||||
if (power > 0.0) {
|
||||
texCo = m + normalize(d) * tan(r * power) * bind / tan(bind * power);
|
||||
}
|
||||
else {
|
||||
texCo = m + normalize(d) * atan(r * -power * 10.0) * bind / atan(-power * bind * 10.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _CDistort
|
||||
#ifdef _CPostprocess
|
||||
float strengthDistort = PPComp14.x;
|
||||
#else
|
||||
float strengthDistort = compoDistortStrength;
|
||||
#endif
|
||||
float uX = time * strengthDistort;
|
||||
texCo.y = texCo.y + (sin(texCo.x*4.0+uX*2.0)*0.01);
|
||||
texCo.x = texCo.x + (cos(texCo.y*4.0+uX*2.0)*0.01);
|
||||
#endif
|
||||
|
||||
#ifdef _CDepth
|
||||
float depth = textureLod(gbufferD, texCo, 0.0).r * 2.0 - 1.0;
|
||||
#endif
|
||||
|
||||
#ifdef _CFXAA
|
||||
const float FXAA_REDUCE_MIN = 1.0 / 128.0;
|
||||
const float FXAA_REDUCE_MUL = 1.0 / 8.0;
|
||||
const float FXAA_SPAN_MAX = 8.0;
|
||||
|
||||
vec2 tcrgbNW = (texCo + vec2(-1.0, -1.0) * texStep);
|
||||
vec2 tcrgbNE = (texCo + vec2(1.0, -1.0) * texStep);
|
||||
vec2 tcrgbSW = (texCo + vec2(-1.0, 1.0) * texStep);
|
||||
vec2 tcrgbSE = (texCo + vec2(1.0, 1.0) * texStep);
|
||||
vec2 tcrgbM = vec2(texCo);
|
||||
|
||||
vec3 rgbNW = textureLod(tex, tcrgbNW, 0.0).rgb;
|
||||
vec3 rgbNE = textureLod(tex, tcrgbNE, 0.0).rgb;
|
||||
vec3 rgbSW = textureLod(tex, tcrgbSW, 0.0).rgb;
|
||||
vec3 rgbSE = textureLod(tex, tcrgbSE, 0.0).rgb;
|
||||
vec3 rgbM = textureLod(tex, tcrgbM, 0.0).rgb;
|
||||
vec3 luma = vec3(0.299, 0.587, 0.114);
|
||||
float lumaNW = dot(rgbNW, luma);
|
||||
float lumaNE = dot(rgbNE, luma);
|
||||
float lumaSW = dot(rgbSW, luma);
|
||||
float lumaSE = dot(rgbSE, luma);
|
||||
float lumaM = dot(rgbM, luma);
|
||||
float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
|
||||
float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
|
||||
|
||||
vec2 dir;
|
||||
dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));
|
||||
dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));
|
||||
|
||||
float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) *
|
||||
(0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN);
|
||||
|
||||
float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce);
|
||||
dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX),
|
||||
max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),
|
||||
dir * rcpDirMin)) * texStep;
|
||||
|
||||
vec3 rgbA = 0.5 * (
|
||||
textureLod(tex, texCo + dir * (1.0 / 3.0 - 0.5), 0.0).rgb +
|
||||
textureLod(tex, texCo + dir * (2.0 / 3.0 - 0.5), 0.0).rgb);
|
||||
vec3 rgbB = rgbA * 0.5 + 0.25 * (
|
||||
textureLod(tex, texCo + dir * -0.5, 0.0).rgb +
|
||||
textureLod(tex, texCo + dir * 0.5, 0.0).rgb);
|
||||
|
||||
float lumaB = dot(rgbB, luma);
|
||||
if ((lumaB < lumaMin) || (lumaB > lumaMax)) fragColor = vec4(rgbA, 1.0);
|
||||
else fragColor = vec4(rgbB, 1.0);
|
||||
|
||||
#else
|
||||
|
||||
#ifdef _CDOF
|
||||
#ifdef _CPostprocess
|
||||
|
||||
bool compoAutoFocus = false;
|
||||
float compoDistance = PPComp3.x;
|
||||
float compoLength = PPComp3.y;
|
||||
float compoStop = PPComp3.z;
|
||||
|
||||
if (PPComp2.z == 1){
|
||||
compoAutoFocus = true;
|
||||
} else {
|
||||
compoAutoFocus = false;
|
||||
}
|
||||
|
||||
fragColor.rgb = dof(texCo, depth, tex, gbufferD, texStep, cameraProj, compoAutoFocus, compoDistance, compoLength, compoStop);
|
||||
#else
|
||||
fragColor.rgb = dof(texCo, depth, tex, gbufferD, texStep, cameraProj, true, compoDOFDistance, compoDOFLength, compoDOFFstop);
|
||||
#endif
|
||||
#else
|
||||
fragColor = textureLod(tex, texCo, 0.0);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef _CSharpen
|
||||
#ifdef _CPostprocess
|
||||
float strengthSharpen = PPComp14.y;
|
||||
#else
|
||||
float strengthSharpen = compoSharpenStrength;
|
||||
#endif
|
||||
vec3 col1 = textureLod(tex, texCo + vec2(-texStep.x, -texStep.y) * 1.5, 0.0).rgb;
|
||||
vec3 col2 = textureLod(tex, texCo + vec2(texStep.x, -texStep.y) * 1.5, 0.0).rgb;
|
||||
vec3 col3 = textureLod(tex, texCo + vec2(-texStep.x, texStep.y) * 1.5, 0.0).rgb;
|
||||
vec3 col4 = textureLod(tex, texCo + vec2(texStep.x, texStep.y) * 1.5, 0.0).rgb;
|
||||
vec3 colavg = (col1 + col2 + col3 + col4) * 0.25;
|
||||
fragColor.rgb += (fragColor.rgb - colavg) * strengthSharpen;
|
||||
#endif
|
||||
|
||||
#ifdef _CFog
|
||||
// if (depth < 1.0) {
|
||||
// vec3 pos = getPos(depth, cameraProj);
|
||||
// float dist = distance(pos, eye);
|
||||
float dist = linearize(depth, cameraProj);
|
||||
// vec3 eyedir = eyeLook;// normalize(eye + pos);
|
||||
// fragColor.rgb = applyFog(fragColor.rgb, dist, eye, eyedir);
|
||||
fragColor.rgb = applyFog(fragColor.rgb, dist);
|
||||
// }
|
||||
#endif
|
||||
|
||||
#ifdef _CGlare
|
||||
if (dot(light, eyeLook) > 0.0) { // Facing light
|
||||
vec4 lndc = VP * vec4(light, 1.0);
|
||||
lndc.xy /= lndc.w;
|
||||
vec2 lss = lndc.xy * 0.5 + 0.5;
|
||||
float lssdepth = linearize(textureLod(gbufferD, lss, 0.0).r * 2.0 - 1.0, cameraProj);
|
||||
float lightDistance = distance(eye, light);
|
||||
if (lightDistance <= lssdepth) {
|
||||
vec2 lensuv = texCo * 2.0 - 1.0;
|
||||
lensuv.x *= aspectRatio;
|
||||
vec3 lensflarecol = vec3(1.4, 1.2, 1.0) * lensflare(lensuv, lndc.xy);
|
||||
fragColor.rgb += lensflarecol;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _CGrain
|
||||
float x = (texCo.x + 4.0) * (texCo.y + 4.0) * (time * 10.0);
|
||||
#ifdef _CPostprocess
|
||||
fragColor.rgb += vec3(mod((mod(x, 13.0) + 1.0) * (mod(x, 123.0) + 1.0), 0.01) - 0.005) * PPComp4.y;
|
||||
#else
|
||||
fragColor.rgb += vec3(mod((mod(x, 13.0) + 1.0) * (mod(x, 123.0) + 1.0), 0.01) - 0.005) * compoGrainStrength;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _CGrainStatic
|
||||
float x = (texCo.x + 4.0) * (texCo.y + 4.0) * 10.0;
|
||||
fragColor.rgb += vec3(mod((mod(x, 13.0) + 1.0) * (mod(x, 123.0) + 1.0), 0.01) - 0.005) * 0.09;
|
||||
#endif
|
||||
|
||||
#ifdef _CVignette
|
||||
fragColor.rgb *= vignette();
|
||||
#endif
|
||||
|
||||
#ifdef _CExposure
|
||||
fragColor.rgb += fragColor.rgb * compoExposureStrength;
|
||||
#endif
|
||||
|
||||
#ifdef _CPostprocess
|
||||
fragColor.rgb *= ComputeEV(0.0);
|
||||
#endif
|
||||
|
||||
#ifdef _AutoExposure
|
||||
float expo = 2.0 - clamp(length(textureLod(histogram, vec2(0.5, 0.5), 0).rgb), 0.0, 1.0);
|
||||
fragColor.rgb *= pow(expo, autoExposureStrength * 2.0);
|
||||
#endif
|
||||
|
||||
// Clamp color to get rid of INF values that don't work for the tone mapping below
|
||||
// The max value is kind of arbitrary (16 bit float max * 0.5), but it should be large enough
|
||||
fragColor.rgb = min(fragColor.rgb, 65504 * 0.5);
|
||||
|
||||
#ifdef _CPostprocess
|
||||
|
||||
#ifdef _CToneCustom
|
||||
fragColor.rgb = clamp((fragColor.rgb * (PPComp4.z * fragColor.rgb + PPComp5.x)) / (fragColor.rgb * (PPComp5.y * fragColor.rgb + PPComp5.z) + PPComp6.x), 0.0, 1.0);
|
||||
#else
|
||||
if(PPComp4.x == 0){ //Filmic 1
|
||||
fragColor.rgb = tonemapFilmic(fragColor.rgb); // With gamma
|
||||
} else if (PPComp4.x == 1){ //Filmic 2
|
||||
fragColor.rgb = acesFilm(fragColor.rgb);
|
||||
fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2));
|
||||
} else if (PPComp4.x == 2){ //Reinhard
|
||||
fragColor.rgb = tonemapReinhard(fragColor.rgb);
|
||||
fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2));
|
||||
} else if (PPComp4.x == 3){ //Uncharted2
|
||||
fragColor.rgb = tonemapUncharted2(fragColor.rgb);
|
||||
fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2)); // To gamma
|
||||
fragColor.rgb = clamp(fragColor.rgb, 0.0, 1.0);
|
||||
} else if (PPComp4.x == 4){ //None
|
||||
fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2)); // To gamma
|
||||
} else if (PPComp4.x == 5){ //Non-Gamma / Linear
|
||||
fragColor.rgb = fragColor.rgb;
|
||||
} else if (PPComp4.x == 6){ //HDP
|
||||
vec3 x = fragColor.rgb - 0.004;
|
||||
//vec3 x = max(0, fragColor.rgb - 0.004);
|
||||
fragColor.rgb = (x*(6.2*x+.5))/(x*(6.2*x+1.7)+0.06);
|
||||
} else if (PPComp4.x == 7){ //Raw
|
||||
vec4 vh = vec4(fragColor.rgb, 1);
|
||||
vec4 va = (1.425 * vh) + 0.05;
|
||||
vec4 vf = ((vh * va + 0.004) / ((vh * (va + 0.55) + 0.0491))) - 0.0821;
|
||||
fragColor.rgb = vf.rgb / vf.www;
|
||||
} else if (PPComp4.x == 8){ //False Colors for luminance control
|
||||
|
||||
vec4 c = vec4(fragColor.r,fragColor.g,fragColor.b,0); //Linear without gamma
|
||||
|
||||
vec3 luminanceVector = vec3(0.2125, 0.7154, 0.0721); //Relative Luminance Vector
|
||||
float luminance = dot(luminanceVector, c.xyz);
|
||||
|
||||
vec3 maxLumColor = vec3(1,0,0); //High values (> 1.0)
|
||||
//float maxLum = 2.0; Needs to read the highest pixel, but I don't know how to yet
|
||||
//Probably easier with a histogram too, once it's it in place?
|
||||
|
||||
vec3 midLumColor = vec3(0,1,0); //Mid values (< 1.0)
|
||||
float midLum = 1.0;
|
||||
|
||||
vec3 minLumColor = vec3(0,0,1); //Low values (< 1.0)
|
||||
float minLum = 0.0;
|
||||
|
||||
if(luminance < midLum){
|
||||
fragColor.rgb = mix(minLumColor, midLumColor, luminance);
|
||||
} else {
|
||||
fragColor.rgb = mix(midLumColor, maxLumColor, luminance);
|
||||
}
|
||||
|
||||
} else {
|
||||
fragColor.rgb = vec3(0,1,0); //ERROR
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
#ifdef _CToneFilmic
|
||||
fragColor.rgb = tonemapFilmic(fragColor.rgb); // With gamma
|
||||
#endif
|
||||
#ifdef _CToneFilmic2
|
||||
fragColor.rgb = acesFilm(fragColor.rgb);
|
||||
fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2));
|
||||
#endif
|
||||
#ifdef _CToneReinhard
|
||||
fragColor.rgb = tonemapReinhard(fragColor.rgb);
|
||||
fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2));
|
||||
#endif
|
||||
#ifdef _CToneUncharted
|
||||
fragColor.rgb = tonemapUncharted2(fragColor.rgb);
|
||||
fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2)); // To gamma
|
||||
fragColor.rgb = clamp(fragColor.rgb, 0.0, 2.2);
|
||||
#endif
|
||||
#ifdef _CToneNone
|
||||
fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2)); // To gamma
|
||||
#endif
|
||||
#ifdef _CToneCustom
|
||||
fragColor.rgb = clamp((fragColor.rgb * (1 * fragColor.rgb + 1)) / (fragColor.rgb * (1 * fragColor.rgb + 1 ) + 1), 0.0, 1.0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _CBW
|
||||
// fragColor.rgb = vec3(clamp(dot(fragColor.rgb, fragColor.rgb), 0.0, 1.0));
|
||||
fragColor.rgb = vec3((fragColor.r * 0.3 + fragColor.g * 0.59 + fragColor.b * 0.11) / 3.0) * 2.5;
|
||||
#endif
|
||||
|
||||
// #ifdef _CContrast
|
||||
// -0.5 - 0.5
|
||||
// const float compoContrast = 0.2;
|
||||
// fragColor.rgb = ((fragColor.rgb - 0.5) * max(compoContrast + 1.0, 0.0)) + 0.5;
|
||||
// #endif
|
||||
|
||||
// #ifdef _CBrighness
|
||||
// fragColor.rgb += compoBrightness;
|
||||
// #endif
|
||||
|
||||
#ifdef _CPostprocess
|
||||
//Global Values
|
||||
|
||||
float factor = 1;
|
||||
float colorTempK = globalWeight.x;
|
||||
vec3 ColorTempRGB = ColorTemperatureToRGB(colorTempK);
|
||||
|
||||
float originalLuminance = Luminance(fragColor.rgb);
|
||||
vec3 blended = mix(fragColor.rgb, fragColor.rgb * ColorTempRGB, factor);
|
||||
vec3 resultHSL = RGBtoHSL(blended);
|
||||
vec3 luminancePreservedRGB = HSLtoRGB(vec3(resultHSL.x, resultHSL.y, originalLuminance));
|
||||
fragColor = vec4(mix(blended, luminancePreservedRGB, LUMINANCE_PRESERVATION), 1.0);
|
||||
|
||||
mat3 CCSaturation = mat3 ( //Saturation
|
||||
globalSaturation.r * shadowSaturation.r, globalSaturation.g * shadowSaturation.g, globalSaturation.b * shadowSaturation.b, //Shadows + Global
|
||||
globalSaturation.r * midtoneSaturation.r, globalSaturation.g * midtoneSaturation.g, globalSaturation.b * midtoneSaturation.b, //Midtones + Global
|
||||
globalSaturation.r * highlightSaturation.r, globalSaturation.g * highlightSaturation.g, globalSaturation.b * highlightSaturation.b //Highlights + Global
|
||||
);
|
||||
|
||||
mat3 CCContrast = mat3 (
|
||||
globalContrast.r * shadowContrast.r, globalContrast.g * shadowContrast.g, globalContrast.b * shadowContrast.b, //Shadows + Global
|
||||
globalContrast.r * midtoneContrast.r, globalContrast.g * midtoneContrast.g, globalContrast.b * midtoneContrast.b, //Midtones + Global
|
||||
globalContrast.r * highlightContrast.r, globalContrast.g * highlightContrast.g, globalContrast.b * highlightContrast.b //Highlights + Global
|
||||
);
|
||||
|
||||
mat3 CCGamma = mat3 (
|
||||
globalGamma.r * shadowGamma.r, globalGamma.g * shadowGamma.g, globalGamma.b * shadowGamma.b, //Shadows + Global
|
||||
globalGamma.r * midtoneGamma.r, globalGamma.g * midtoneGamma.g, globalGamma.b * midtoneGamma.b, //Midtones + Global
|
||||
globalGamma.r * highlightGamma.r, globalGamma.g * highlightGamma.g, globalGamma.b * highlightGamma.b //Highlights + Global
|
||||
);
|
||||
|
||||
mat3 CCGain = mat3 (
|
||||
globalGain.r * shadowGain.r, globalGain.g * shadowGain.g, globalGain.b * shadowGain.b, //Shadows + Global
|
||||
globalGain.r * midtoneGain.r, globalGain.g * midtoneGain.g, globalGain.b * midtoneGain.b, //Midtones + Global
|
||||
globalGain.r * highlightGain.r, globalGain.g * highlightGain.g, globalGain.b * highlightGain.b //Highlights + Global
|
||||
);
|
||||
|
||||
mat3 CCOffset = mat3 (
|
||||
globalOffset.r * shadowOffset.r, globalOffset.g * shadowOffset.g, globalOffset.b * shadowOffset.b, //Shadows + Global
|
||||
globalOffset.r * midtoneOffset.r, globalOffset.g * midtoneOffset.g, globalOffset.b * midtoneOffset.b, //Midtones + Global
|
||||
globalOffset.r * highlightOffset.r, globalOffset.g * highlightOffset.g, globalOffset.b * highlightOffset.b //Highlights + Global
|
||||
);
|
||||
|
||||
vec2 ToneWeights = vec2(globalWeight.y, globalWeight.z);
|
||||
|
||||
fragColor.rgb = FinalizeColorCorrection(
|
||||
fragColor.rgb,
|
||||
CCSaturation,
|
||||
CCContrast,
|
||||
CCGamma,
|
||||
CCGain,
|
||||
CCOffset,
|
||||
ToneWeights
|
||||
);
|
||||
|
||||
//Tint
|
||||
fragColor.rgb *= vec3(globalTint.r,globalTint.g,globalTint.b);
|
||||
#endif
|
||||
|
||||
#ifdef _CLensTex
|
||||
#ifdef _CLensTexMasking
|
||||
vec4 scratches = texture(lensTexture, texCo);
|
||||
vec3 scratchBlend = fragColor.rgb + scratches.rgb;
|
||||
|
||||
#ifdef _CPostprocess
|
||||
float centerMaxClip = PPComp6.y;
|
||||
float centerMinClip = PPComp6.z;
|
||||
float luminanceMax = PPComp7.x;
|
||||
float luminanceMin = PPComp7.y;
|
||||
float brightnessExp = PPComp7.z;
|
||||
#else
|
||||
float centerMaxClip = compoCenterMaxClip;
|
||||
float centerMinClip = compoCenterMinClip;
|
||||
float luminanceMax = compoLuminanceMax;
|
||||
float luminanceMin = compoLuminanceMin;
|
||||
float brightnessExp = compoBrightnessExponent;
|
||||
#endif
|
||||
|
||||
float center = smoothstep(centerMaxClip, centerMinClip, length(texCo - 0.5));
|
||||
float luminance = dot(fragColor.rgb, vec3(0.299, 0.587, 0.114));
|
||||
float brightnessMap = smoothstep(luminanceMax, luminanceMin, luminance * center);
|
||||
fragColor.rgb = clamp(mix(fragColor.rgb, scratchBlend, brightnessMap * brightnessExp), 0, 1);
|
||||
#else
|
||||
fragColor.rgb += textureLod(lensTexture, texCo, 0.0).rgb;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//3D LUT Implementation from GPUGems 2 by Nvidia
|
||||
//https://developer.nvidia.com/gpugems/GPUGems2/gpugems2_chapter24.html
|
||||
|
||||
#ifdef _CLUT
|
||||
fragColor = LUTlookup(fragColor, lutTexture);
|
||||
#endif
|
||||
}
|
245
leenkx/Shaders/compositor_pass/compositor_pass.json
Normal file
245
leenkx/Shaders/compositor_pass/compositor_pass.json
Normal file
@ -0,0 +1,245 @@
|
||||
{
|
||||
"contexts": [
|
||||
{
|
||||
"name": "compositor_pass",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [
|
||||
{
|
||||
"name": "eye",
|
||||
"link": "_cameraPosition",
|
||||
"ifdef": ["_CGlare"]
|
||||
},
|
||||
{
|
||||
"name": "eye",
|
||||
"link": "_cameraPosition",
|
||||
"ifdef": ["_Disabled_CPos"]
|
||||
},
|
||||
{
|
||||
"name": "eyeLook",
|
||||
"link": "_cameraLook",
|
||||
"ifdef": ["_CGlare"]
|
||||
},
|
||||
{
|
||||
"name": "eyeLook",
|
||||
"link": "_cameraLook",
|
||||
"ifdef": ["_Disabled_CPos"]
|
||||
},
|
||||
{
|
||||
"name": "invVP",
|
||||
"link": "_inverseViewProjectionMatrix",
|
||||
"ifdef": ["_Disabled_CPos"]
|
||||
},
|
||||
{
|
||||
"name": "light",
|
||||
"link": "_lightPosition",
|
||||
"ifdef": ["_CGlare"]
|
||||
},
|
||||
{
|
||||
"name": "VP",
|
||||
"link": "_viewProjectionMatrix",
|
||||
"ifdef": ["_CGlare"]
|
||||
},
|
||||
{
|
||||
"name": "time",
|
||||
"link": "_time",
|
||||
"ifdef": ["_CDistort", "_CGrain"]
|
||||
},
|
||||
{
|
||||
"name": "texStep",
|
||||
"link": "_screenSizeInv",
|
||||
"ifdef": ["_CTexStep"]
|
||||
},
|
||||
{
|
||||
"name": "dynamicScale",
|
||||
"link": "_dynamicScale",
|
||||
"ifdef": ["_DynRes"]
|
||||
},
|
||||
{
|
||||
"name": "aspectRatio",
|
||||
"link": "_aspectRatioF",
|
||||
"ifdef": ["_CGlare"]
|
||||
},
|
||||
{
|
||||
"name": "lensTexture",
|
||||
"link": "$lenstexture.jpg",
|
||||
"ifdef": ["_CLensTex"]
|
||||
},
|
||||
{
|
||||
"name": "cameraProj",
|
||||
"link": "_cameraPlaneProj",
|
||||
"ifdef": ["_CCameraProj"]
|
||||
},
|
||||
{
|
||||
"name": "lutTexture",
|
||||
"link": "$luttexture.jpg",
|
||||
"ifdef": ["_CLUT"]
|
||||
},
|
||||
{
|
||||
"name": "globalWeight",
|
||||
"link": "_globalWeight",
|
||||
"ifdef": ["_CPostprocess"]
|
||||
},
|
||||
{
|
||||
"name": "globalTint",
|
||||
"link": "_globalTint",
|
||||
"ifdef": ["_CPostprocess"]
|
||||
},
|
||||
{
|
||||
"name": "globalSaturation",
|
||||
"link": "_globalSaturation",
|
||||
"ifdef": ["_CPostprocess"]
|
||||
},
|
||||
{
|
||||
"name": "globalContrast",
|
||||
"link": "_globalContrast",
|
||||
"ifdef": ["_CPostprocess"]
|
||||
},
|
||||
{
|
||||
"name": "globalGamma",
|
||||
"link": "_globalGamma",
|
||||
"ifdef": ["_CPostprocess"]
|
||||
},
|
||||
{
|
||||
"name": "globalGain",
|
||||
"link": "_globalGain",
|
||||
"ifdef": ["_CPostprocess"]
|
||||
},
|
||||
{
|
||||
"name": "globalOffset",
|
||||
"link": "_globalOffset",
|
||||
"ifdef": ["_CPostprocess"]
|
||||
},
|
||||
{
|
||||
"name": "shadowSaturation",
|
||||
"link": "_shadowSaturation",
|
||||
"ifdef": ["_CPostprocess"]
|
||||
},
|
||||
{
|
||||
"name": "shadowContrast",
|
||||
"link": "_shadowContrast",
|
||||
"ifdef": ["_CPostprocess"]
|
||||
},
|
||||
{
|
||||
"name": "shadowGamma",
|
||||
"link": "_shadowGamma",
|
||||
"ifdef": ["_CPostprocess"]
|
||||
},
|
||||
{
|
||||
"name": "shadowGain",
|
||||
"link": "_shadowGain",
|
||||
"ifdef": ["_CPostprocess"]
|
||||
},
|
||||
{
|
||||
"name": "shadowOffset",
|
||||
"link": "_shadowOffset",
|
||||
"ifdef": ["_CPostprocess"]
|
||||
},
|
||||
{
|
||||
"name": "midtoneSaturation",
|
||||
"link": "_midtoneSaturation",
|
||||
"ifdef": ["_CPostprocess"]
|
||||
},
|
||||
{
|
||||
"name": "midtoneContrast",
|
||||
"link": "_midtoneContrast",
|
||||
"ifdef": ["_CPostprocess"]
|
||||
},
|
||||
{
|
||||
"name": "midtoneGamma",
|
||||
"link": "_midtoneGamma",
|
||||
"ifdef": ["_CPostprocess"]
|
||||
},
|
||||
{
|
||||
"name": "midtoneGain",
|
||||
"link": "_midtoneGain",
|
||||
"ifdef": ["_CPostprocess"]
|
||||
},
|
||||
{
|
||||
"name": "midtoneOffset",
|
||||
"link": "_midtoneOffset",
|
||||
"ifdef": ["_CPostprocess"]
|
||||
},
|
||||
{
|
||||
"name": "highlightSaturation",
|
||||
"link": "_highlightSaturation",
|
||||
"ifdef": ["_CPostprocess"]
|
||||
},
|
||||
{
|
||||
"name": "highlightContrast",
|
||||
"link": "_highlightContrast",
|
||||
"ifdef": ["_CPostprocess"]
|
||||
},
|
||||
{
|
||||
"name": "highlightGamma",
|
||||
"link": "_highlightGamma",
|
||||
"ifdef": ["_CPostprocess"]
|
||||
},
|
||||
{
|
||||
"name": "highlightGain",
|
||||
"link": "_highlightGain",
|
||||
"ifdef": ["_CPostprocess"]
|
||||
},
|
||||
{
|
||||
"name": "highlightOffset",
|
||||
"link": "_highlightOffset",
|
||||
"ifdef": ["_CPostprocess"]
|
||||
},
|
||||
{
|
||||
"name": "PPComp1",
|
||||
"link": "_PPComp1",
|
||||
"ifdef": ["_CPostprocess"]
|
||||
},
|
||||
{
|
||||
"name": "PPComp2",
|
||||
"link": "_PPComp2",
|
||||
"ifdef": ["_CPostprocess"]
|
||||
},
|
||||
{
|
||||
"name": "PPComp3",
|
||||
"link": "_PPComp3",
|
||||
"ifdef": ["_CPostprocess"]
|
||||
},
|
||||
{
|
||||
"name": "PPComp4",
|
||||
"link": "_PPComp4",
|
||||
"ifdef": ["_CPostprocess"]
|
||||
},
|
||||
{
|
||||
"name": "PPComp5",
|
||||
"link": "_PPComp5",
|
||||
"ifdef": ["_CPostprocess"]
|
||||
},
|
||||
{
|
||||
"name": "PPComp6",
|
||||
"link": "_PPComp6",
|
||||
"ifdef": ["_CPostprocess"]
|
||||
},
|
||||
{
|
||||
"name": "PPComp7",
|
||||
"link": "_PPComp7",
|
||||
"ifdef": ["_CPostprocess"]
|
||||
},
|
||||
{
|
||||
"name": "PPComp8",
|
||||
"link": "_PPComp8",
|
||||
"ifdef": ["_CPostprocess"]
|
||||
},
|
||||
{
|
||||
"name": "PPComp14",
|
||||
"link": "_PPComp14",
|
||||
"ifdef": ["_CPostprocess"]
|
||||
},
|
||||
{
|
||||
"name": "PPComp15",
|
||||
"link": "_PPComp15",
|
||||
"ifdef": ["_CPostprocess"]
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "compositor_pass.vert.glsl",
|
||||
"fragment_shader": "compositor_pass.frag.glsl"
|
||||
}
|
||||
]
|
||||
}
|
34
leenkx/Shaders/compositor_pass/compositor_pass.vert.glsl
Normal file
34
leenkx/Shaders/compositor_pass/compositor_pass.vert.glsl
Normal file
@ -0,0 +1,34 @@
|
||||
#version 450
|
||||
|
||||
#include "compiled.inc"
|
||||
|
||||
// #ifdef _CPos
|
||||
// uniform mat4 invVP;
|
||||
// uniform vec3 eye;
|
||||
// #endif
|
||||
|
||||
in vec2 pos;
|
||||
|
||||
out vec2 texCoord;
|
||||
// #ifdef _CPos
|
||||
// out vec3 viewRay;
|
||||
// #endif
|
||||
|
||||
void main() {
|
||||
// Scale vertex attribute to [0-1] range
|
||||
const vec2 madd = vec2(0.5, 0.5);
|
||||
texCoord = pos.xy * madd + madd;
|
||||
#ifdef _InvY
|
||||
texCoord.y = 1.0 - texCoord.y;
|
||||
#endif
|
||||
|
||||
gl_Position = vec4(pos.xy, 0.0, 1.0);
|
||||
|
||||
// #ifdef _CPos
|
||||
// NDC (at the back of cube)
|
||||
// vec4 v = vec4(pos.xy, 1.0, 1.0);
|
||||
// v = vec4(invVP * v);
|
||||
// v.xyz /= v.w;
|
||||
// viewRay = v.xyz - eye;
|
||||
// #endif
|
||||
}
|
12
leenkx/Shaders/copy_mrt2_pass/copy_mrt2_pass.frag.glsl
Normal file
12
leenkx/Shaders/copy_mrt2_pass/copy_mrt2_pass.frag.glsl
Normal file
@ -0,0 +1,12 @@
|
||||
#version 450
|
||||
|
||||
uniform sampler2D tex0;
|
||||
uniform sampler2D tex1;
|
||||
|
||||
in vec2 texCoord;
|
||||
out vec4 fragColor[2];
|
||||
|
||||
void main() {
|
||||
fragColor[0] = textureLod(tex0, texCoord, 0.0);
|
||||
fragColor[1] = textureLod(tex1, texCoord, 0.0);
|
||||
}
|
14
leenkx/Shaders/copy_mrt2_pass/copy_mrt2_pass.json
Normal file
14
leenkx/Shaders/copy_mrt2_pass/copy_mrt2_pass.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"contexts": [
|
||||
{
|
||||
"name": "copy_mrt2_pass",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass.vert.glsl",
|
||||
"fragment_shader": "copy_mrt2_pass.frag.glsl"
|
||||
}
|
||||
]
|
||||
}
|
14
leenkx/Shaders/copy_mrt3_pass/copy_mrt3_pass.frag.glsl
Normal file
14
leenkx/Shaders/copy_mrt3_pass/copy_mrt3_pass.frag.glsl
Normal file
@ -0,0 +1,14 @@
|
||||
#version 450
|
||||
|
||||
uniform sampler2D tex0;
|
||||
uniform sampler2D tex1;
|
||||
uniform sampler2D tex2;
|
||||
|
||||
in vec2 texCoord;
|
||||
out vec4 fragColor[3];
|
||||
|
||||
void main() {
|
||||
fragColor[0] = textureLod(tex0, texCoord, 0.0);
|
||||
fragColor[1] = textureLod(tex1, texCoord, 0.0);
|
||||
fragColor[2] = textureLod(tex2, texCoord, 0.0);
|
||||
}
|
14
leenkx/Shaders/copy_mrt3_pass/copy_mrt3_pass.json
Normal file
14
leenkx/Shaders/copy_mrt3_pass/copy_mrt3_pass.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"contexts": [
|
||||
{
|
||||
"name": "copy_mrt3_pass",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass.vert.glsl",
|
||||
"fragment_shader": "copy_mrt3_pass.frag.glsl"
|
||||
}
|
||||
]
|
||||
}
|
14
leenkx/Shaders/copy_pass/copy_pass.json
Normal file
14
leenkx/Shaders/copy_pass/copy_pass.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"contexts": [
|
||||
{
|
||||
"name": "copy_pass",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass.vert.glsl",
|
||||
"fragment_shader": "../include/pass_copy.frag.glsl"
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
#version 450
|
||||
|
||||
#include "../compiled.inc"
|
||||
|
||||
// Include functions for gbuffer operations (packFloat2() etc.)
|
||||
#include "../std/gbuffer.glsl"
|
||||
|
||||
// World-space normal from the vertex shader stage
|
||||
in vec3 wnormal;
|
||||
|
||||
/*
|
||||
The G-Buffer output. Deferred rendering uses the following render target layout:
|
||||
|
||||
| Index | Needs #define || R | G | B | A |
|
||||
+===================+=================++==============+==============+=================+====================+
|
||||
| GBUF_IDX_0 | || normal (XY) | roughness | metallic/matID |
|
||||
+-------------------+-----------------++--------------+--------------+-----------------+--------------------+
|
||||
| GBUF_IDX_1 | || base color (RGB) | occlusion/specular |
|
||||
+-------------------+-----------------++--------------+--------------+-----------------+--------------------+
|
||||
| GBUF_IDX_2 | _gbuffer2 || velocity (XY) | ignore radiance | unused |
|
||||
+-------------------+-----------------++--------------+--------------+-----------------+--------------------+
|
||||
| GBUF_IDX_EMISSION | _EmissionShaded || emission color (RGB) | unused |
|
||||
+-------------------+-----------------++--------------+--------------+-----------------+--------------------+
|
||||
|
||||
The indices as well as the GBUF_SIZE define are defined in "compiled.inc".
|
||||
*/
|
||||
out vec4 fragColor[GBUF_SIZE];
|
||||
|
||||
void main() {
|
||||
// Pack normals into 2 components to fit into the gbuffer
|
||||
vec3 n = normalize(wnormal);
|
||||
n /= (abs(n.x) + abs(n.y) + abs(n.z));
|
||||
n.xy = n.z >= 0.0 ? n.xy : octahedronWrap(n.xy);
|
||||
|
||||
// Define PBR material values
|
||||
vec3 basecol = vec3(1.0);
|
||||
float roughness = 0.0;
|
||||
float metallic = 0.0;
|
||||
float occlusion = 1.0;
|
||||
float specular = 1.0;
|
||||
uint materialId = 0;
|
||||
vec3 emissionCol = vec3(0.0);
|
||||
float ior = 1.450;
|
||||
float opacity = 1.0;
|
||||
|
||||
// Store in gbuffer (see layout table above)
|
||||
fragColor[GBUF_IDX_0] = vec4(n.xy, roughness, packFloatInt16(metallic, materialId));
|
||||
fragColor[GBUF_IDX_1] = vec4(basecol.rgb, packFloat2(occlusion, specular));
|
||||
|
||||
#ifdef _EmissionShaded
|
||||
fragColor[GBUF_IDX_EMISSION] = vec4(emissionCol, 0.0);
|
||||
#endif
|
||||
|
||||
#ifdef _SSRefraction
|
||||
fragColor[GBUF_IDX_REFRACTION] = vec4(ior, opacity, 0.0, 0.0);
|
||||
#endif
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
#version 450
|
||||
|
||||
// World to view projection matrix to correctly position the vertex on screen
|
||||
uniform mat4 WVP;
|
||||
// Matrix to transform normals from local into world space
|
||||
uniform mat3 N;
|
||||
|
||||
// Position and normal vectors of the current vertex in local space
|
||||
// Leenkx packs the vertex data to preserve memory, so nor.z values are
|
||||
// saved in pos.w
|
||||
in vec4 pos; // pos.xyz, nor.w
|
||||
in vec2 nor; // nor.xy
|
||||
|
||||
// Normal vector in world space
|
||||
out vec3 wnormal;
|
||||
|
||||
void main() {
|
||||
wnormal = normalize(N * vec3(nor.xy, pos.w));
|
||||
gl_Position = WVP * vec4(pos.xyz, 1.0);
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
#version 450
|
||||
|
||||
// Color of each fragment on the screen
|
||||
out vec4 fragColor;
|
||||
|
||||
void main() {
|
||||
// Shadeless white color
|
||||
fragColor = vec4(1.0);
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
#version 450
|
||||
|
||||
// World to view projection matrix to correctly position the vertex on screen
|
||||
uniform mat4 WVP;
|
||||
|
||||
// Position vector of the current vertex in local space
|
||||
in vec3 pos;
|
||||
|
||||
void main() {
|
||||
gl_Position = WVP * vec4(pos, 1.0);
|
||||
}
|
8
leenkx/Shaders/debug_draw/line.frag.glsl
Normal file
8
leenkx/Shaders/debug_draw/line.frag.glsl
Normal file
@ -0,0 +1,8 @@
|
||||
#version 450
|
||||
|
||||
in vec3 color;
|
||||
out vec4 fragColor;
|
||||
|
||||
void main() {
|
||||
fragColor = vec4(color, 1.0);
|
||||
}
|
12
leenkx/Shaders/debug_draw/line.vert.glsl
Normal file
12
leenkx/Shaders/debug_draw/line.vert.glsl
Normal file
@ -0,0 +1,12 @@
|
||||
#version 450
|
||||
|
||||
in vec3 pos;
|
||||
in vec3 col;
|
||||
|
||||
uniform mat4 ViewProjection;
|
||||
out vec3 color;
|
||||
|
||||
void main() {
|
||||
color = col;
|
||||
gl_Position = ViewProjection * vec4(pos, 1.0);
|
||||
}
|
15
leenkx/Shaders/debug_draw/line_deferred.frag.glsl
Normal file
15
leenkx/Shaders/debug_draw/line_deferred.frag.glsl
Normal file
@ -0,0 +1,15 @@
|
||||
#version 450
|
||||
|
||||
#include "compiled.inc"
|
||||
|
||||
in vec3 color;
|
||||
out vec4 fragColor[GBUF_SIZE];
|
||||
|
||||
void main() {
|
||||
fragColor[GBUF_IDX_0] = vec4(1.0, 1.0, 0.0, 1.0);
|
||||
fragColor[GBUF_IDX_1] = vec4(color, 1.0);
|
||||
|
||||
#ifdef _EmissionShaded
|
||||
fragColor[GBUF_IDX_EMISSION] = vec4(0.0);
|
||||
#endif
|
||||
}
|
527
leenkx/Shaders/deferred_light/deferred_light.frag.glsl
Normal file
527
leenkx/Shaders/deferred_light/deferred_light.frag.glsl
Normal file
@ -0,0 +1,527 @@
|
||||
#version 450
|
||||
|
||||
#include "compiled.inc"
|
||||
#include "std/gbuffer.glsl"
|
||||
#ifdef _Clusters
|
||||
#include "std/clusters.glsl"
|
||||
#endif
|
||||
#ifdef _Irr
|
||||
#include "std/shirr.glsl"
|
||||
#endif
|
||||
#ifdef _SSS
|
||||
#include "std/sss.glsl"
|
||||
#endif
|
||||
#ifdef _SSRS
|
||||
#include "std/ssrs.glsl"
|
||||
#endif
|
||||
|
||||
uniform sampler2D gbufferD;
|
||||
uniform sampler2D gbuffer0;
|
||||
uniform sampler2D gbuffer1;
|
||||
|
||||
#ifdef _gbuffer2
|
||||
uniform sampler2D gbuffer2;
|
||||
#endif
|
||||
#ifdef _EmissionShaded
|
||||
uniform sampler2D gbufferEmission;
|
||||
#endif
|
||||
|
||||
#ifdef _VoxelGI
|
||||
uniform sampler2D voxels_diffuse;
|
||||
uniform sampler2D voxels_specular;
|
||||
#endif
|
||||
#ifdef _VoxelAOvar
|
||||
uniform sampler2D voxels_ao;
|
||||
#endif
|
||||
#ifdef _VoxelShadow
|
||||
uniform sampler3D voxels;
|
||||
uniform sampler3D voxelsSDF;
|
||||
uniform float clipmaps[10 * voxelgiClipmapCount];
|
||||
#endif
|
||||
|
||||
uniform float envmapStrength;
|
||||
#ifdef _Irr
|
||||
uniform vec4 shirr[7];
|
||||
#endif
|
||||
#ifdef _Brdf
|
||||
uniform sampler2D senvmapBrdf;
|
||||
#endif
|
||||
#ifdef _Rad
|
||||
uniform sampler2D senvmapRadiance;
|
||||
uniform int envmapNumMipmaps;
|
||||
#endif
|
||||
#ifdef _EnvCol
|
||||
uniform vec3 backgroundCol;
|
||||
#endif
|
||||
|
||||
#ifdef _SSAO
|
||||
uniform sampler2D ssaotex;
|
||||
#endif
|
||||
|
||||
#ifdef _SSS
|
||||
uniform vec2 lightPlane;
|
||||
#endif
|
||||
|
||||
#ifdef _SSRS
|
||||
//!uniform mat4 VP;
|
||||
uniform mat4 invVP;
|
||||
#endif
|
||||
|
||||
#ifdef _LightIES
|
||||
//!uniform sampler2D texIES;
|
||||
#endif
|
||||
|
||||
#ifdef _SMSizeUniform
|
||||
//!uniform vec2 smSizeUniform;
|
||||
#endif
|
||||
|
||||
#ifdef _LTC
|
||||
//!uniform vec3 lightArea0;
|
||||
//!uniform vec3 lightArea1;
|
||||
//!uniform vec3 lightArea2;
|
||||
//!uniform vec3 lightArea3;
|
||||
//!uniform sampler2D sltcMat;
|
||||
//!uniform sampler2D sltcMag;
|
||||
#ifdef _ShadowMap
|
||||
#ifdef _SinglePoint
|
||||
//!uniform sampler2DShadow shadowMapSpot[1];
|
||||
//!uniform sampler2D shadowMapSpotTransparent[1];
|
||||
//!uniform mat4 LWVPSpot[1];
|
||||
#endif
|
||||
#ifdef _Clusters
|
||||
//!uniform sampler2DShadow shadowMapSpot[4];
|
||||
//!uniform sampler2D shadowMapSpotTransparent[4];
|
||||
//!uniform mat4 LWVPSpotArray[4];
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
uniform vec2 cameraProj;
|
||||
uniform vec3 eye;
|
||||
uniform vec3 eyeLook;
|
||||
|
||||
#ifdef _Clusters
|
||||
uniform vec4 lightsArray[maxLights * 3];
|
||||
#ifdef _Spot
|
||||
uniform vec4 lightsArraySpot[maxLights * 2];
|
||||
#endif
|
||||
uniform sampler2D clustersData;
|
||||
uniform vec2 cameraPlane;
|
||||
#endif
|
||||
|
||||
#ifdef _ShadowMap
|
||||
#ifdef _SinglePoint
|
||||
#ifdef _Spot
|
||||
//!uniform sampler2DShadow shadowMapSpot[1];
|
||||
//!uniform sampler2D shadowMapSpotTransparent[1];
|
||||
//!uniform mat4 LWVPSpot[1];
|
||||
#else
|
||||
//!uniform samplerCubeShadow shadowMapPoint[1];
|
||||
//!uniform samplerCube shadowMapPointTransparent[1];
|
||||
//!uniform vec2 lightProj;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef _Clusters
|
||||
#ifdef _ShadowMapAtlas
|
||||
#ifdef _SingleAtlas
|
||||
uniform sampler2DShadow shadowMapAtlas;
|
||||
uniform sampler2D shadowMapAtlasTransparent;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef _ShadowMapAtlas
|
||||
#ifndef _SingleAtlas
|
||||
//!uniform sampler2DShadow shadowMapAtlasPoint;
|
||||
//!uniform sampler2D shadowMapAtlasPointTransparent;
|
||||
#endif
|
||||
//!uniform vec4 pointLightDataArray[4];
|
||||
#else
|
||||
//!uniform samplerCubeShadow shadowMapPoint[4];
|
||||
//!uniform samplerCube shadowMapPointTransparent[4];
|
||||
#endif
|
||||
//!uniform vec2 lightProj;
|
||||
#ifdef _Spot
|
||||
#ifdef _ShadowMapAtlas
|
||||
#ifndef _SingleAtlas
|
||||
//!uniform sampler2DShadow shadowMapAtlasSpot;
|
||||
//!uniform sampler2D shadowMapAtlasSpotTransparent;
|
||||
#endif
|
||||
#else
|
||||
//!uniform sampler2DShadow shadowMapSpot[4];
|
||||
//!uniform sampler2D shadowMapSpotTransparent[4];
|
||||
#endif
|
||||
//!uniform mat4 LWVPSpotArray[maxLightsCluster];
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _Sun
|
||||
uniform vec3 sunDir;
|
||||
uniform vec3 sunCol;
|
||||
#ifdef _ShadowMap
|
||||
#ifdef _ShadowMapAtlas
|
||||
#ifndef _SingleAtlas
|
||||
uniform sampler2DShadow shadowMapAtlasSun;
|
||||
uniform sampler2D shadowMapAtlasSunTransparent;
|
||||
#endif
|
||||
#else
|
||||
uniform sampler2DShadow shadowMap;
|
||||
uniform sampler2D shadowMapTransparent;
|
||||
#endif
|
||||
uniform float shadowsBias;
|
||||
#ifdef _CSM
|
||||
//!uniform vec4 casData[shadowmapCascades * 4 + 4];
|
||||
#else
|
||||
uniform mat4 LWVP;
|
||||
#endif
|
||||
#endif // _ShadowMap
|
||||
#endif
|
||||
|
||||
#ifdef _SinglePoint // Fast path for single light
|
||||
uniform vec3 pointPos;
|
||||
uniform vec3 pointCol;
|
||||
#ifdef _ShadowMap
|
||||
uniform float pointBias;
|
||||
#endif
|
||||
#ifdef _Spot
|
||||
uniform vec3 spotDir;
|
||||
uniform vec3 spotRight;
|
||||
uniform vec4 spotData;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _LightClouds
|
||||
uniform sampler2D texClouds;
|
||||
uniform float time;
|
||||
#endif
|
||||
|
||||
#include "std/light.glsl"
|
||||
|
||||
in vec2 texCoord;
|
||||
in vec3 viewRay;
|
||||
out vec4 fragColor;
|
||||
|
||||
void main() {
|
||||
vec4 g0 = textureLod(gbuffer0, texCoord, 0.0); // Normal.xy, roughness, metallic/matid
|
||||
|
||||
vec3 n;
|
||||
n.z = 1.0 - abs(g0.x) - abs(g0.y);
|
||||
n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy);
|
||||
n = normalize(n);
|
||||
|
||||
float roughness = g0.b;
|
||||
float metallic;
|
||||
uint matid;
|
||||
unpackFloatInt16(g0.a, metallic, matid);
|
||||
|
||||
vec4 g1 = textureLod(gbuffer1, texCoord, 0.0); // Basecolor.rgb, spec/occ
|
||||
vec2 occspec = unpackFloat2(g1.a);
|
||||
vec3 albedo = surfaceAlbedo(g1.rgb, metallic); // g1.rgb - basecolor
|
||||
vec3 f0 = surfaceF0(g1.rgb, metallic);
|
||||
|
||||
float depth = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0;
|
||||
vec3 p = getPos(eye, eyeLook, normalize(viewRay), depth, cameraProj);
|
||||
vec3 v = normalize(eye - p);
|
||||
float dotNV = max(dot(n, v), 0.0);
|
||||
|
||||
#ifdef _gbuffer2
|
||||
vec4 g2 = textureLod(gbuffer2, texCoord, 0.0);
|
||||
#endif
|
||||
|
||||
#ifdef _MicroShadowing
|
||||
occspec.x = mix(1.0, occspec.x, dotNV); // AO Fresnel
|
||||
#endif
|
||||
|
||||
#ifdef _Brdf
|
||||
vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy;
|
||||
#endif
|
||||
|
||||
// Envmap
|
||||
#ifdef _Irr
|
||||
|
||||
vec3 envl = shIrradiance(n, shirr);
|
||||
|
||||
#ifdef _gbuffer2
|
||||
if (g2.b < 0.5) {
|
||||
envl = envl;
|
||||
} else {
|
||||
envl = vec3(0.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _EnvTex
|
||||
envl /= PI;
|
||||
#endif
|
||||
#else
|
||||
vec3 envl = vec3(0.0);
|
||||
#endif
|
||||
|
||||
#ifdef _Rad
|
||||
vec3 reflectionWorld = reflect(-v, n);
|
||||
float lod = getMipFromRoughness(roughness, envmapNumMipmaps);
|
||||
vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb;
|
||||
#endif
|
||||
|
||||
#ifdef _EnvLDR
|
||||
envl.rgb = pow(envl.rgb, vec3(2.2));
|
||||
#ifdef _Rad
|
||||
prefilteredColor = pow(prefilteredColor, vec3(2.2));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
envl.rgb *= albedo;
|
||||
|
||||
#ifdef _Brdf
|
||||
envl.rgb *= 1.0 - (f0 * envBRDF.x + envBRDF.y); //LV: We should take refracted light into account
|
||||
#endif
|
||||
|
||||
#ifdef _Rad // Indirect specular
|
||||
envl.rgb += prefilteredColor * (f0 * envBRDF.x + envBRDF.y); //LV: Removed "1.5 * occspec.y". Specular should be weighted only by FV LUT
|
||||
#else
|
||||
#ifdef _EnvCol
|
||||
envl.rgb += backgroundCol * (f0 * envBRDF.x + envBRDF.y); //LV: Eh, what's the point of weighting it only by F0?
|
||||
#endif
|
||||
#endif
|
||||
|
||||
envl.rgb *= envmapStrength * occspec.x;
|
||||
|
||||
#ifdef _VoxelGI
|
||||
vec4 indirect_diffuse = textureLod(voxels_diffuse, texCoord, 0.0);
|
||||
fragColor.rgb = (indirect_diffuse.rgb * albedo + envl.rgb * (1.0 - indirect_diffuse.a)) * voxelgiDiff;
|
||||
if(roughness < 1.0 && occspec.y > 0.0)
|
||||
fragColor.rgb += textureLod(voxels_specular, texCoord, 0.0).rgb * occspec.y * voxelgiRefl;
|
||||
#endif
|
||||
|
||||
#ifdef _VoxelAOvar
|
||||
envl.rgb *= textureLod(voxels_ao, texCoord, 0.0).r;
|
||||
#endif
|
||||
|
||||
#ifndef _VoxelGI
|
||||
fragColor.rgb = envl;
|
||||
#endif
|
||||
// Show voxels
|
||||
// vec3 origin = vec3(texCoord * 2.0 - 1.0, 0.99);
|
||||
// vec3 direction = vec3(0.0, 0.0, -1.0);
|
||||
// vec4 color = vec4(0.0f);
|
||||
// for(uint step = 0; step < 400 && color.a < 0.99f; ++step) {
|
||||
// vec3 point = origin + 0.005 * step * direction;
|
||||
// color += (1.0f - color.a) * textureLod(voxels, point * 0.5 + 0.5, 0);
|
||||
// }
|
||||
// fragColor.rgb += color.rgb;
|
||||
|
||||
// Show SSAO
|
||||
// fragColor.rgb = texture(ssaotex, texCoord).rrr;
|
||||
|
||||
#ifdef _SSAO
|
||||
// #ifdef _RTGI
|
||||
// fragColor.rgb *= textureLod(ssaotex, texCoord, 0.0).rgb;
|
||||
// #else
|
||||
fragColor.rgb *= textureLod(ssaotex, texCoord, 0.0).r;
|
||||
// #endif
|
||||
#endif
|
||||
|
||||
#ifdef _EmissionShadeless
|
||||
if (matid == 1) { // pure emissive material, color stored in basecol
|
||||
fragColor.rgb += g1.rgb;
|
||||
fragColor.a = 1.0; // Mark as opaque
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#ifdef _EmissionShaded
|
||||
#ifdef _EmissionShadeless
|
||||
else {
|
||||
#endif
|
||||
vec3 emission = textureLod(gbufferEmission, texCoord, 0.0).rgb;
|
||||
fragColor.rgb += emission;
|
||||
#ifdef _EmissionShadeless
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _Sun
|
||||
vec3 sh = normalize(v + sunDir);
|
||||
float sdotNH = max(0.0, dot(n, sh));
|
||||
float sdotVH = max(0.0, dot(v, sh));
|
||||
float sdotNL = max(0.0, dot(n, sunDir));
|
||||
vec3 svisibility = vec3(1.0);
|
||||
vec3 sdirect = lambertDiffuseBRDF(albedo, sdotNL) +
|
||||
specularBRDF(f0, roughness, sdotNL, sdotNH, dotNV, sdotVH) * occspec.y;
|
||||
|
||||
#ifdef _ShadowMap
|
||||
#ifdef _CSM
|
||||
svisibility = shadowTestCascade(
|
||||
#ifdef _ShadowMapAtlas
|
||||
#ifndef _SingleAtlas
|
||||
shadowMapAtlasSun, shadowMapAtlasSunTransparent
|
||||
#else
|
||||
shadowMapAtlas, shadowMapAtlasTransparent
|
||||
#endif
|
||||
#else
|
||||
shadowMap, shadowMapTransparent
|
||||
#endif
|
||||
, eye, p + n * shadowsBias * 10, shadowsBias, false
|
||||
);
|
||||
#else
|
||||
vec4 lPos = LWVP * vec4(p + n * shadowsBias * 100, 1.0);
|
||||
if (lPos.w > 0.0) {
|
||||
svisibility = shadowTest(
|
||||
#ifdef _ShadowMapAtlas
|
||||
#ifndef _SingleAtlas
|
||||
shadowMapAtlasSun, shadowMapAtlasSunTransparent
|
||||
#else
|
||||
shadowMapAtlas, shadowMapAtlasTransparent
|
||||
#endif
|
||||
#else
|
||||
shadowMap, shadowMapTransparent
|
||||
#endif
|
||||
, lPos.xyz / lPos.w, shadowsBias, false
|
||||
);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _VoxelShadow
|
||||
svisibility *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, sunDir, clipmaps, gl_FragCoord.xy).r) * voxelgiShad;
|
||||
#endif
|
||||
|
||||
#ifdef _SSRS
|
||||
// vec2 coords = getProjectedCoord(hitCoord);
|
||||
// vec2 deltaCoords = abs(vec2(0.5, 0.5) - coords.xy);
|
||||
// float screenEdgeFactor = clamp(1.0 - (deltaCoords.x + deltaCoords.y), 0.0, 1.0);
|
||||
svisibility *= traceShadowSS(sunDir, p, gbufferD, invVP, eye);
|
||||
#endif
|
||||
|
||||
#ifdef _LightClouds
|
||||
svisibility *= textureLod(texClouds, vec2(p.xy / 100.0 + time / 80.0), 0.0).r * dot(n, vec3(0,0,1));
|
||||
#endif
|
||||
|
||||
#ifdef _MicroShadowing
|
||||
// See https://advances.realtimerendering.com/other/2016/naughty_dog/NaughtyDog_TechArt_Final.pdf
|
||||
svisibility *= clamp(sdotNL + 2.0 * occspec.x * occspec.x - 1.0, 0.0, 1.0);
|
||||
#endif
|
||||
|
||||
fragColor.rgb += sdirect * sunCol * svisibility;
|
||||
|
||||
// #ifdef _Hair // Aniso
|
||||
// if (matid == 2) {
|
||||
// const float shinyParallel = roughness;
|
||||
// const float shinyPerpendicular = 0.1;
|
||||
// const vec3 v = vec3(0.99146, 0.11664, 0.05832);
|
||||
// vec3 T = abs(dot(n, v)) > 0.99999 ? cross(n, vec3(0.0, 1.0, 0.0)) : cross(n, v);
|
||||
// fragColor.rgb = orenNayarDiffuseBRDF(albedo, roughness, dotNV, dotNL, dotVH) + wardSpecular(n, h, dotNL, dotNV, dotNH, T, shinyParallel, shinyPerpendicular) * spec;
|
||||
// }
|
||||
// #endif
|
||||
|
||||
#ifdef _SSS
|
||||
if (matid == 2) {
|
||||
#ifdef _CSM
|
||||
int casi, casindex;
|
||||
mat4 LWVP = getCascadeMat(distance(eye, p), casi, casindex);
|
||||
#endif
|
||||
fragColor.rgb += fragColor.rgb * SSSSTransmittance(
|
||||
LWVP, p, n, sunDir, lightPlane.y,
|
||||
#ifdef _ShadowMapAtlas
|
||||
#ifndef _SingleAtlas
|
||||
shadowMapAtlasSun
|
||||
#else
|
||||
shadowMapAtlas
|
||||
#endif
|
||||
#else
|
||||
shadowMap
|
||||
#endif
|
||||
);//TODO implement transparent shadowmaps into the SSSSTransmittance()
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _Sun
|
||||
|
||||
#ifdef _SinglePoint
|
||||
|
||||
fragColor.rgb += sampleLight(
|
||||
p, n, v, dotNV, pointPos, pointCol, albedo, roughness, occspec.y, f0
|
||||
#ifdef _ShadowMap
|
||||
, 0, pointBias, true, false
|
||||
#endif
|
||||
#ifdef _Spot
|
||||
, true, spotData.x, spotData.y, spotDir, spotData.zw, spotRight
|
||||
#endif
|
||||
#ifdef _VoxelShadow
|
||||
, voxels, voxelsSDF, clipmaps
|
||||
#endif
|
||||
#ifdef _MicroShadowing
|
||||
, occspec.x
|
||||
#endif
|
||||
#ifdef _SSRS
|
||||
, gbufferD, invVP, eye
|
||||
#endif
|
||||
);
|
||||
|
||||
#ifdef _Spot
|
||||
#ifdef _SSS
|
||||
if (matid == 2) fragColor.rgb += fragColor.rgb * SSSSTransmittance(LWVPSpot[0], p, n, normalize(pointPos - p), lightPlane.y, shadowMapSpot[0]);//TODO implement transparent shadowmaps into the SSSSTransmittance()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef _Clusters
|
||||
float viewz = linearize(depth * 0.5 + 0.5, cameraProj);
|
||||
int clusterI = getClusterI(texCoord, viewz, cameraPlane);
|
||||
int numLights = int(texelFetch(clustersData, ivec2(clusterI, 0), 0).r * 255);
|
||||
|
||||
#ifdef HLSL
|
||||
viewz += textureLod(clustersData, vec2(0.0), 0.0).r * 1e-9; // TODO: krafix bug, needs to generate sampler
|
||||
#endif
|
||||
|
||||
#ifdef _Spot
|
||||
int numSpots = int(texelFetch(clustersData, ivec2(clusterI, 1 + maxLightsCluster), 0).r * 255);
|
||||
int numPoints = numLights - numSpots;
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < min(numLights, maxLightsCluster); i++) {
|
||||
int li = int(texelFetch(clustersData, ivec2(clusterI, i + 1), 0).r * 255);
|
||||
fragColor.rgb += sampleLight(
|
||||
p,
|
||||
n,
|
||||
v,
|
||||
dotNV,
|
||||
lightsArray[li * 3].xyz, // lp
|
||||
lightsArray[li * 3 + 1].xyz, // lightCol
|
||||
albedo,
|
||||
roughness,
|
||||
occspec.y,
|
||||
f0
|
||||
#ifdef _ShadowMap
|
||||
// light index, shadow bias, cast_shadows
|
||||
, li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0, false
|
||||
#endif
|
||||
#ifdef _Spot
|
||||
, lightsArray[li * 3 + 2].y != 0.0
|
||||
, lightsArray[li * 3 + 2].y // spot size (cutoff)
|
||||
, lightsArraySpot[li * 2].w // spot blend (exponent)
|
||||
, lightsArraySpot[li * 2].xyz // spotDir
|
||||
, vec2(lightsArray[li * 3].w, lightsArray[li * 3 + 1].w) // scale
|
||||
, lightsArraySpot[li * 2 + 1].xyz // right
|
||||
#endif
|
||||
#ifdef _VoxelShadow
|
||||
, voxels, voxelsSDF, clipmaps
|
||||
#endif
|
||||
#ifdef _MicroShadowing
|
||||
, occspec.x
|
||||
#endif
|
||||
#ifdef _SSRS
|
||||
, gbufferD, invVP, eye
|
||||
#endif
|
||||
);
|
||||
}
|
||||
#endif // _Clusters
|
||||
|
||||
/*
|
||||
#ifdef _VoxelRefract
|
||||
if(opac < 1.0) {
|
||||
vec3 refraction = traceRefraction(p, n, voxels, v, ior, roughness, eye) * voxelgiRefr;
|
||||
fragColor.rgb = mix(refraction, fragColor.rgb, opac);
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
fragColor.a = 1.0; // Mark as opaque
|
||||
}
|
246
leenkx/Shaders/deferred_light/deferred_light.json
Normal file
246
leenkx/Shaders/deferred_light/deferred_light.json
Normal file
@ -0,0 +1,246 @@
|
||||
{
|
||||
"variants": ["_VoxelAOvar"],
|
||||
"contexts": [
|
||||
{
|
||||
"name": "deferred_light",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [
|
||||
{
|
||||
"name": "eye",
|
||||
"link": "_cameraPosition"
|
||||
},
|
||||
{
|
||||
"name": "voxelBlend",
|
||||
"link": "_voxelBlend",
|
||||
"ifdef": ["_VoxelTemporal"]
|
||||
},
|
||||
{
|
||||
"name": "eyeLook",
|
||||
"link": "_cameraLook"
|
||||
},
|
||||
{
|
||||
"name": "clipmaps",
|
||||
"link": "_clipmaps",
|
||||
"ifdef": ["_VoxelShadow"]
|
||||
},
|
||||
{
|
||||
"name": "invVP",
|
||||
"link": "_inverseViewProjectionMatrix"
|
||||
},
|
||||
{
|
||||
"name": "shirr",
|
||||
"link": "_envmapIrradiance",
|
||||
"ifdef": ["_Irr"]
|
||||
},
|
||||
{
|
||||
"name": "senvmapRadiance",
|
||||
"link": "_envmapRadiance",
|
||||
"ifdef": ["_Rad"]
|
||||
},
|
||||
{
|
||||
"name": "envmapNumMipmaps",
|
||||
"link": "_envmapNumMipmaps",
|
||||
"ifdef": ["_Rad"]
|
||||
},
|
||||
{
|
||||
"name": "senvmapBrdf",
|
||||
"link": "$brdf.png",
|
||||
"ifdef": ["_Brdf"]
|
||||
},
|
||||
{
|
||||
"name": "cameraProj",
|
||||
"link": "_cameraPlaneProj"
|
||||
},
|
||||
{
|
||||
"name": "envmapStrength",
|
||||
"link": "_envmapStrength"
|
||||
},
|
||||
{
|
||||
"name": "backgroundCol",
|
||||
"link": "_backgroundCol",
|
||||
"ifdef": ["_EnvCol"]
|
||||
},
|
||||
{
|
||||
"name": "lightsArray",
|
||||
"link": "_lightsArray",
|
||||
"ifdef": ["_Clusters"]
|
||||
},
|
||||
{
|
||||
"name": "lightsArraySpot",
|
||||
"link": "_lightsArraySpot",
|
||||
"ifdef": ["_Clusters", "_Spot"]
|
||||
},
|
||||
{
|
||||
"name": "clustersData",
|
||||
"link": "_clustersData",
|
||||
"ifdef": ["_Clusters"]
|
||||
},
|
||||
{
|
||||
"name": "cameraPlane",
|
||||
"link": "_cameraPlane",
|
||||
"ifdef": ["_Clusters"]
|
||||
},
|
||||
{
|
||||
"name": "sunDir",
|
||||
"link": "_sunDirection",
|
||||
"ifdef": ["_Sun"]
|
||||
},
|
||||
{
|
||||
"name": "sunCol",
|
||||
"link": "_sunColor",
|
||||
"ifdef": ["_Sun"]
|
||||
},
|
||||
{
|
||||
"name": "shadowsBias",
|
||||
"link": "_sunShadowsBias",
|
||||
"ifdef": ["_Sun", "_ShadowMap"]
|
||||
},
|
||||
{
|
||||
"name": "LWVP",
|
||||
"link": "_biasLightWorldViewProjectionMatrixSun",
|
||||
"ifndef": ["_CSM"],
|
||||
"ifdef": ["_Sun", "_ShadowMap"]
|
||||
},
|
||||
{
|
||||
"name": "casData",
|
||||
"link": "_cascadeData",
|
||||
"ifdef": ["_Sun", "_ShadowMap", "_CSM"]
|
||||
},
|
||||
{
|
||||
"name": "lightPlane",
|
||||
"link": "_lightPlane",
|
||||
"ifdef": ["_SSS"]
|
||||
},
|
||||
{
|
||||
"name": "VP",
|
||||
"link": "_viewProjectionMatrix",
|
||||
"ifdef": ["_SSRS"]
|
||||
},
|
||||
{
|
||||
"name": "texClouds",
|
||||
"link": "$cloudstexture.png",
|
||||
"ifdef": ["_LightClouds"]
|
||||
},
|
||||
{
|
||||
"name": "time",
|
||||
"link": "_time",
|
||||
"ifdef": ["_LightClouds"]
|
||||
},
|
||||
{
|
||||
"name": "texIES",
|
||||
"link": "$iestexture.png",
|
||||
"ifdef": ["_LightIES"]
|
||||
},
|
||||
{
|
||||
"name": "lightArea0",
|
||||
"link": "_lightArea0",
|
||||
"ifdef": ["_LTC"]
|
||||
},
|
||||
{
|
||||
"name": "lightArea1",
|
||||
"link": "_lightArea1",
|
||||
"ifdef": ["_LTC"]
|
||||
},
|
||||
{
|
||||
"name": "lightArea2",
|
||||
"link": "_lightArea2",
|
||||
"ifdef": ["_LTC"]
|
||||
},
|
||||
{
|
||||
"name": "lightArea3",
|
||||
"link": "_lightArea3",
|
||||
"ifdef": ["_LTC"]
|
||||
},
|
||||
{
|
||||
"name": "sltcMat",
|
||||
"link": "_ltcMat",
|
||||
"ifdef": ["_LTC"]
|
||||
},
|
||||
{
|
||||
"name": "sltcMag",
|
||||
"link": "_ltcMag",
|
||||
"ifdef": ["_LTC"]
|
||||
},
|
||||
{
|
||||
"name": "smSizeUniform",
|
||||
"link": "_shadowMapSize",
|
||||
"ifdef": ["_SMSizeUniform"]
|
||||
},
|
||||
{
|
||||
"name": "lightProj",
|
||||
"link": "_lightPlaneProj",
|
||||
"ifdef": ["_ShadowMap"]
|
||||
},
|
||||
{
|
||||
"name": "pointPos",
|
||||
"link": "_pointPosition",
|
||||
"ifdef": ["_SinglePoint"]
|
||||
},
|
||||
{
|
||||
"name": "pointCol",
|
||||
"link": "_pointColor",
|
||||
"ifdef": ["_SinglePoint"]
|
||||
},
|
||||
{
|
||||
"name": "pointBias",
|
||||
"link": "_pointShadowsBias",
|
||||
"ifdef": ["_SinglePoint", "_ShadowMap"]
|
||||
},
|
||||
{
|
||||
"name": "spotDir",
|
||||
"link": "_spotDirection",
|
||||
"ifdef": ["_SinglePoint", "_Spot"]
|
||||
},
|
||||
{
|
||||
"name": "spotData",
|
||||
"link": "_spotData",
|
||||
"ifdef": ["_SinglePoint", "_Spot"]
|
||||
},
|
||||
{
|
||||
"name": "spotRight",
|
||||
"link": "_spotRight",
|
||||
"ifdef": ["_SinglePoint", "_Spot"]
|
||||
},
|
||||
{
|
||||
"name": "LWVPSpotArray",
|
||||
"link": "_biasLightWorldViewProjectionMatrixSpotArray",
|
||||
"ifdef": ["_Clusters", "_ShadowMap", "_Spot"]
|
||||
},
|
||||
{
|
||||
"name": "pointLightDataArray",
|
||||
"link": "_pointLightsAtlasArray",
|
||||
"ifdef": ["_Clusters", "_ShadowMap", "_ShadowMapAtlas"]
|
||||
},
|
||||
{
|
||||
"name": "LWVPSpot[0]",
|
||||
"link": "_biasLightWorldViewProjectionMatrixSpot0",
|
||||
"ifndef": ["_ShadowMapAtlas"],
|
||||
"ifdef": ["_LTC", "_ShadowMap"]
|
||||
},
|
||||
{
|
||||
"name": "LWVPSpot[1]",
|
||||
"link": "_biasLightWorldViewProjectionMatrixSpot1",
|
||||
"ifndef": ["_ShadowMapAtlas"],
|
||||
"ifdef": ["_LTC", "_ShadowMap"]
|
||||
},
|
||||
{
|
||||
"name": "LWVPSpot[2]",
|
||||
"link": "_biasLightWorldViewProjectionMatrixSpot2",
|
||||
"ifndef": ["_ShadowMapAtlas"],
|
||||
"ifdef": ["_LTC", "_ShadowMap"]
|
||||
},
|
||||
{
|
||||
"name": "LWVPSpot[3]",
|
||||
"link": "_biasLightWorldViewProjectionMatrixSpot3",
|
||||
"ifndef": ["_ShadowMapAtlas"],
|
||||
"ifdef": ["_LTC", "_ShadowMap"]
|
||||
}
|
||||
],
|
||||
"vertex_shader": "../include/pass_viewray.vert.glsl",
|
||||
"fragment_shader": "deferred_light.frag.glsl",
|
||||
"color_attachments": ["RGBA64"]
|
||||
}
|
||||
]
|
||||
}
|
283
leenkx/Shaders/deferred_light_mobile/deferred_light.frag.glsl
Normal file
283
leenkx/Shaders/deferred_light_mobile/deferred_light.frag.glsl
Normal file
@ -0,0 +1,283 @@
|
||||
#version 450
|
||||
|
||||
#include "compiled.inc"
|
||||
#include "std/gbuffer.glsl"
|
||||
#include "std/math.glsl"
|
||||
#ifdef _Clusters
|
||||
#include "std/clusters.glsl"
|
||||
#endif
|
||||
#ifdef _Irr
|
||||
#include "std/shirr.glsl"
|
||||
#endif
|
||||
|
||||
uniform sampler2D gbufferD;
|
||||
uniform sampler2D gbuffer0;
|
||||
uniform sampler2D gbuffer1;
|
||||
|
||||
uniform float envmapStrength;
|
||||
#ifdef _Irr
|
||||
uniform vec4 shirr[7];
|
||||
#endif
|
||||
#ifdef _Brdf
|
||||
uniform sampler2D senvmapBrdf;
|
||||
#endif
|
||||
#ifdef _Rad
|
||||
uniform sampler2D senvmapRadiance;
|
||||
uniform int envmapNumMipmaps;
|
||||
#endif
|
||||
#ifdef _EnvCol
|
||||
uniform vec3 backgroundCol;
|
||||
#endif
|
||||
|
||||
#ifdef _SMSizeUniform
|
||||
//!uniform vec2 smSizeUniform;
|
||||
#endif
|
||||
uniform vec2 cameraProj;
|
||||
uniform vec3 eye;
|
||||
uniform vec3 eyeLook;
|
||||
|
||||
#ifdef _Clusters
|
||||
uniform vec4 lightsArray[maxLights * 3];
|
||||
#ifdef _Spot
|
||||
uniform vec4 lightsArraySpot[maxLights * 2];
|
||||
#endif
|
||||
uniform sampler2D clustersData;
|
||||
uniform vec2 cameraPlane;
|
||||
#endif
|
||||
|
||||
#ifdef _ShadowMap
|
||||
#ifdef _SinglePoint
|
||||
#ifdef _Spot
|
||||
//!uniform sampler2DShadow shadowMapSpot[1];
|
||||
//!uniform mat4 LWVPSpot[1];
|
||||
#else
|
||||
//!uniform samplerCubeShadow shadowMapPoint[1];
|
||||
//!uniform vec2 lightProj;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef _Clusters
|
||||
#ifdef _ShadowMapAtlas
|
||||
#ifdef _SingleAtlas
|
||||
uniform sampler2DShadow shadowMapAtlas;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef _ShadowMapAtlas
|
||||
#ifndef _SingleAtlas
|
||||
//!uniform sampler2DShadow shadowMapAtlasPoint;
|
||||
#endif
|
||||
//!uniform vec4 pointLightDataArray[4];
|
||||
#else
|
||||
//!uniform samplerCubeShadow shadowMapPoint[4];
|
||||
#endif
|
||||
//!uniform vec2 lightProj;
|
||||
#ifdef _Spot
|
||||
#ifdef _ShadowMapAtlas
|
||||
#ifndef _SingleAtlas
|
||||
//!uniform sampler2DShadow shadowMapAtlasSpot;
|
||||
#endif
|
||||
#else
|
||||
//!uniform sampler2DShadow shadowMapSpot[4];
|
||||
#endif
|
||||
//!uniform mat4 LWVPSpotArray[4];
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _Sun
|
||||
uniform vec3 sunDir;
|
||||
uniform vec3 sunCol;
|
||||
#ifdef _ShadowMap
|
||||
#ifdef _ShadowMapAtlas
|
||||
#ifndef _SingleAtlas
|
||||
uniform sampler2DShadow shadowMapAtlasSun;
|
||||
#endif
|
||||
#else
|
||||
uniform sampler2DShadow shadowMap;
|
||||
#endif
|
||||
uniform float shadowsBias;
|
||||
#ifdef _CSM
|
||||
//!uniform vec4 casData[shadowmapCascades * 4 + 4];
|
||||
#else
|
||||
uniform mat4 LWVP;
|
||||
#endif
|
||||
#endif // _ShadowMap
|
||||
#endif
|
||||
|
||||
#ifdef _SinglePoint // Fast path for single light
|
||||
uniform vec3 pointPos;
|
||||
uniform vec3 pointCol;
|
||||
uniform float pointBias;
|
||||
#ifdef _Spot
|
||||
uniform vec3 spotDir;
|
||||
uniform vec3 spotRight;
|
||||
uniform vec4 spotData;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "std/light_mobile.glsl"
|
||||
|
||||
in vec2 texCoord;
|
||||
in vec3 viewRay;
|
||||
out vec4 fragColor;
|
||||
|
||||
void main() {
|
||||
vec4 g0 = textureLod(gbuffer0, texCoord, 0.0); // Normal.xy, roughness, metallic/matid
|
||||
|
||||
vec3 n;
|
||||
n.z = 1.0 - abs(g0.x) - abs(g0.y);
|
||||
n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy);
|
||||
n = normalize(n);
|
||||
|
||||
float roughness = g0.b;
|
||||
float metallic;
|
||||
uint matid;
|
||||
unpackFloatInt16(g0.a, metallic, matid);
|
||||
|
||||
vec4 g1 = textureLod(gbuffer1, texCoord, 0.0); // Basecolor.rgb, spec/occ
|
||||
vec2 occspec = unpackFloat2(g1.a);
|
||||
vec3 albedo = surfaceAlbedo(g1.rgb, metallic); // g1.rgb - basecolor
|
||||
vec3 f0 = surfaceF0(g1.rgb, metallic);
|
||||
|
||||
float depth = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0;
|
||||
vec3 p = getPos(eye, eyeLook, normalize(viewRay), depth, cameraProj);
|
||||
vec3 v = normalize(eye - p);
|
||||
float dotNV = max(dot(n, v), 0.0);
|
||||
|
||||
#ifdef _Brdf
|
||||
vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy;
|
||||
#endif
|
||||
|
||||
// Envmap
|
||||
#ifdef _Irr
|
||||
vec3 envl = shIrradiance(n, shirr);
|
||||
#ifdef _EnvTex
|
||||
envl /= PI;
|
||||
#endif
|
||||
#else
|
||||
vec3 envl = vec3(1.0);
|
||||
#endif
|
||||
|
||||
#ifdef _Rad
|
||||
vec3 reflectionWorld = reflect(-v, n);
|
||||
float lod = getMipFromRoughness(roughness, envmapNumMipmaps);
|
||||
vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb;
|
||||
#endif
|
||||
|
||||
#ifdef _EnvLDR
|
||||
envl.rgb = pow(envl.rgb, vec3(2.2));
|
||||
#ifdef _Rad
|
||||
prefilteredColor = pow(prefilteredColor, vec3(2.2));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
envl.rgb *= albedo;
|
||||
|
||||
#ifdef _Rad // Indirect specular
|
||||
envl.rgb += prefilteredColor * (f0 * envBRDF.x + envBRDF.y) * 1.5 * occspec.y;
|
||||
#else
|
||||
#ifdef _EnvCol
|
||||
envl.rgb += backgroundCol * surfaceF0(g1.rgb, metallic); // f0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
envl.rgb *= envmapStrength * occspec.x;
|
||||
fragColor.rgb = envl;
|
||||
|
||||
#ifdef _Sun
|
||||
vec3 sh = normalize(v + sunDir);
|
||||
float sdotNH = max(0.0, dot(n, sh));
|
||||
float sdotVH = max(0.0, dot(v, sh));
|
||||
float sdotNL = max(0.0, dot(n, sunDir));
|
||||
float svisibility = 1.0;
|
||||
vec3 sdirect = lambertDiffuseBRDF(albedo, sdotNL) +
|
||||
specularBRDF(f0, roughness, sdotNL, sdotNH, dotNV, sdotVH) * occspec.y;
|
||||
|
||||
#ifdef _ShadowMap
|
||||
#ifdef _CSM
|
||||
svisibility = shadowTestCascade(
|
||||
#ifdef _ShadowMapAtlas
|
||||
#ifndef _SingleAtlas
|
||||
shadowMapAtlasSun
|
||||
#else
|
||||
shadowMapAtlas
|
||||
#endif
|
||||
#else
|
||||
shadowMap
|
||||
#endif
|
||||
, eye, p + n * shadowsBias * 10, shadowsBias
|
||||
);
|
||||
#else
|
||||
vec4 lPos = LWVP * vec4(p + n * shadowsBias * 100, 1.0);
|
||||
if (lPos.w > 0.0) svisibility = shadowTest(
|
||||
#ifdef _ShadowMapAtlas
|
||||
#ifndef _SingleAtlas
|
||||
shadowMapAtlasSun
|
||||
#else
|
||||
shadowMapAtlas
|
||||
#endif
|
||||
#else
|
||||
shadowMap
|
||||
#endif
|
||||
, lPos.xyz / lPos.w, shadowsBias
|
||||
);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
fragColor.rgb += sdirect * svisibility * sunCol;
|
||||
#endif
|
||||
|
||||
#ifdef _SinglePoint
|
||||
fragColor.rgb += sampleLight(
|
||||
p, n, v, dotNV, pointPos, pointCol, albedo, roughness, occspec.y, f0
|
||||
#ifdef _ShadowMap
|
||||
, 0, pointBias, true
|
||||
#endif
|
||||
#ifdef _Spot
|
||||
, true, spotData.x, spotData.y, spotDir, spotData.zw, spotRight // TODO: Test!
|
||||
#endif
|
||||
);
|
||||
#endif
|
||||
|
||||
#ifdef _Clusters
|
||||
float viewz = linearize(depth * 0.5 + 0.5, cameraProj);
|
||||
int clusterI = getClusterI(texCoord, viewz, cameraPlane);
|
||||
int numLights = int(texelFetch(clustersData, ivec2(clusterI, 0), 0).r * 255);
|
||||
|
||||
#ifdef HLSL
|
||||
viewz += textureLod(clustersData, vec2(0.0), 0.0).r * 1e-9; // TODO: krafix bug, needs to generate sampler
|
||||
#endif
|
||||
|
||||
#ifdef _Spot
|
||||
int numSpots = int(texelFetch(clustersData, ivec2(clusterI, 1 + maxLightsCluster), 0).r * 255);
|
||||
int numPoints = numLights - numSpots;
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < min(numLights, maxLightsCluster); i++) {
|
||||
int li = int(texelFetch(clustersData, ivec2(clusterI, i + 1), 0).r * 255);
|
||||
fragColor.rgb += sampleLight(
|
||||
p,
|
||||
n,
|
||||
v,
|
||||
dotNV,
|
||||
lightsArray[li * 3].xyz, // lp
|
||||
lightsArray[li * 3 + 1].xyz, // lightCol
|
||||
albedo,
|
||||
roughness,
|
||||
occspec.y,
|
||||
f0
|
||||
#ifdef _ShadowMap
|
||||
// light index, shadow bias, cast_shadows
|
||||
, li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0
|
||||
#endif
|
||||
#ifdef _Spot
|
||||
, lightsArray[li * 3 + 2].y != 0.0
|
||||
, lightsArray[li * 3 + 2].y // spot size (cutoff)
|
||||
, lightsArraySpot[li].w // spot blend (exponent)
|
||||
, lightsArraySpot[li].xyz // spotDir
|
||||
, vec2(lightsArray[li * 3].w, lightsArray[li * 3 + 1].w) // scale
|
||||
, lightsArraySpot[li * 2 + 1].xyz // right
|
||||
#endif
|
||||
);
|
||||
}
|
||||
#endif // _Clusters
|
||||
}
|
190
leenkx/Shaders/deferred_light_mobile/deferred_light_mobile.json
Normal file
190
leenkx/Shaders/deferred_light_mobile/deferred_light_mobile.json
Normal file
@ -0,0 +1,190 @@
|
||||
{
|
||||
"contexts": [
|
||||
{
|
||||
"name": "deferred_light",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [
|
||||
{
|
||||
"name": "eye",
|
||||
"link": "_cameraPosition"
|
||||
},
|
||||
{
|
||||
"name": "eyeLook",
|
||||
"link": "_cameraLook"
|
||||
},
|
||||
{
|
||||
"name": "invVP",
|
||||
"link": "_inverseViewProjectionMatrix"
|
||||
},
|
||||
{
|
||||
"name": "shirr",
|
||||
"link": "_envmapIrradiance",
|
||||
"ifdef": ["_Irr"]
|
||||
},
|
||||
{
|
||||
"name": "senvmapRadiance",
|
||||
"link": "_envmapRadiance",
|
||||
"ifdef": ["_Rad"]
|
||||
},
|
||||
{
|
||||
"name": "envmapNumMipmaps",
|
||||
"link": "_envmapNumMipmaps",
|
||||
"ifdef": ["_Rad"]
|
||||
},
|
||||
{
|
||||
"name": "senvmapBrdf",
|
||||
"link": "$brdf.png",
|
||||
"ifdef": ["_Brdf"]
|
||||
},
|
||||
{
|
||||
"name": "cameraProj",
|
||||
"link": "_cameraPlaneProj"
|
||||
},
|
||||
{
|
||||
"name": "envmapStrength",
|
||||
"link": "_envmapStrength"
|
||||
},
|
||||
{
|
||||
"name": "backgroundCol",
|
||||
"link": "_backgroundCol",
|
||||
"ifdef": ["_EnvCol"]
|
||||
},
|
||||
{
|
||||
"name": "lightsArray",
|
||||
"link": "_lightsArray",
|
||||
"ifdef": ["_Clusters"]
|
||||
},
|
||||
{
|
||||
"name": "lightsArraySpot",
|
||||
"link": "_lightsArraySpot",
|
||||
"ifdef": ["_Clusters", "_Spot"]
|
||||
},
|
||||
{
|
||||
"name": "clustersData",
|
||||
"link": "_clustersData",
|
||||
"ifdef": ["_Clusters"]
|
||||
},
|
||||
{
|
||||
"name": "cameraPlane",
|
||||
"link": "_cameraPlane",
|
||||
"ifdef": ["_Clusters"]
|
||||
},
|
||||
{
|
||||
"name": "sunDir",
|
||||
"link": "_sunDirection",
|
||||
"ifdef": ["_Sun"]
|
||||
},
|
||||
{
|
||||
"name": "sunCol",
|
||||
"link": "_sunColor",
|
||||
"ifdef": ["_Sun"]
|
||||
},
|
||||
{
|
||||
"name": "shadowsBias",
|
||||
"link": "_sunShadowsBias",
|
||||
"ifdef": ["_Sun", "_ShadowMap"]
|
||||
},
|
||||
{
|
||||
"name": "LWVP",
|
||||
"link": "_biasLightWorldViewProjectionMatrixSun",
|
||||
"ifndef": ["_CSM"],
|
||||
"ifdef": ["_Sun", "_ShadowMap"]
|
||||
},
|
||||
{
|
||||
"name": "casData",
|
||||
"link": "_cascadeData",
|
||||
"ifdef": ["_Sun", "_ShadowMap", "_CSM"]
|
||||
},
|
||||
{
|
||||
"name": "lightPlane",
|
||||
"link": "_lightPlane",
|
||||
"ifdef": ["_SSS"]
|
||||
},
|
||||
{
|
||||
"name": "VP",
|
||||
"link": "_viewProjectionMatrix",
|
||||
"ifdef": ["_SSRS"]
|
||||
},
|
||||
{
|
||||
"name": "smSizeUniform",
|
||||
"link": "_shadowMapSize",
|
||||
"ifdef": ["_SMSizeUniform"]
|
||||
},
|
||||
{
|
||||
"name": "lightProj",
|
||||
"link": "_lightPlaneProj",
|
||||
"ifdef": ["_ShadowMap"]
|
||||
},
|
||||
{
|
||||
"name": "pointPos",
|
||||
"link": "_pointPosition",
|
||||
"ifdef": ["_SinglePoint"]
|
||||
},
|
||||
{
|
||||
"name": "pointCol",
|
||||
"link": "_pointColor",
|
||||
"ifdef": ["_SinglePoint"]
|
||||
},
|
||||
{
|
||||
"name": "pointBias",
|
||||
"link": "_pointShadowsBias",
|
||||
"ifdef": ["_SinglePoint"]
|
||||
},
|
||||
{
|
||||
"name": "spotDir",
|
||||
"link": "_spotDirection",
|
||||
"ifdef": ["_SinglePoint", "_Spot"]
|
||||
},
|
||||
{
|
||||
"name": "spotData",
|
||||
"link": "_spotData",
|
||||
"ifdef": ["_SinglePoint", "_Spot"]
|
||||
},
|
||||
{
|
||||
"name": "spotRight",
|
||||
"link": "_spotRight",
|
||||
"ifdef": ["_SinglePoint", "_Spot"]
|
||||
},
|
||||
{
|
||||
"name": "LWVPSpotArray",
|
||||
"link": "_biasLightWorldViewProjectionMatrixSpotArray",
|
||||
"ifdef": ["_Clusters", "_ShadowMap", "_Spot"]
|
||||
},
|
||||
{
|
||||
"name": "pointLightDataArray",
|
||||
"link": "_pointLightsAtlasArray",
|
||||
"ifdef": ["_Clusters", "_ShadowMap", "_ShadowMapAtlas"]
|
||||
},
|
||||
{
|
||||
"name": "LWVPSpot[0]",
|
||||
"link": "_biasLightWorldViewProjectionMatrixSpot0",
|
||||
"ifndef": ["_ShadowMapAtlas"],
|
||||
"ifdef": ["_LTC", "_ShadowMap"]
|
||||
},
|
||||
{
|
||||
"name": "LWVPSpot[1]",
|
||||
"link": "_biasLightWorldViewProjectionMatrixSpot1",
|
||||
"ifndef": ["_ShadowMapAtlas"],
|
||||
"ifdef": ["_LTC", "_ShadowMap"]
|
||||
},
|
||||
{
|
||||
"name": "LWVPSpot[2]",
|
||||
"link": "_biasLightWorldViewProjectionMatrixSpot2",
|
||||
"ifndef": ["_ShadowMapAtlas"],
|
||||
"ifdef": ["_LTC", "_ShadowMap"]
|
||||
},
|
||||
{
|
||||
"name": "LWVPSpot[3]",
|
||||
"link": "_biasLightWorldViewProjectionMatrixSpot3",
|
||||
"ifndef": ["_ShadowMapAtlas"],
|
||||
"ifdef": ["_LTC", "_ShadowMap"]
|
||||
}
|
||||
],
|
||||
"vertex_shader": "../include/pass_viewray.vert.glsl",
|
||||
"fragment_shader": "deferred_light.frag.glsl",
|
||||
"color_attachments": ["RGBA64"]
|
||||
}
|
||||
]
|
||||
}
|
13
leenkx/Shaders/deferred_light_solid/deferred_light.frag.glsl
Normal file
13
leenkx/Shaders/deferred_light_solid/deferred_light.frag.glsl
Normal file
@ -0,0 +1,13 @@
|
||||
#version 450
|
||||
|
||||
#include "compiled.inc"
|
||||
#include "std/gbuffer.glsl"
|
||||
|
||||
uniform sampler2D gbuffer1;
|
||||
|
||||
in vec2 texCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
void main() {
|
||||
fragColor.rgb = textureLod(gbuffer1, texCoord, 0.0).rgb; // Basecolor.rgb
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
{
|
||||
"contexts": [
|
||||
{
|
||||
"name": "deferred_light",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [],
|
||||
"vertex_shader": "../include/pass.vert.glsl",
|
||||
"fragment_shader": "deferred_light.frag.glsl",
|
||||
"color_attachments": ["RGBA64"]
|
||||
}
|
||||
]
|
||||
}
|
18
leenkx/Shaders/downsample_depth/downsample_depth.frag.glsl
Normal file
18
leenkx/Shaders/downsample_depth/downsample_depth.frag.glsl
Normal file
@ -0,0 +1,18 @@
|
||||
#version 450
|
||||
|
||||
#include "compiled.inc"
|
||||
|
||||
uniform sampler2D texdepth;
|
||||
uniform vec2 screenSizeInv;
|
||||
|
||||
in vec2 texCoord;
|
||||
|
||||
out float fragColor;
|
||||
|
||||
void main() {
|
||||
float d0 = textureLod(texdepth, texCoord, 0.0).r;
|
||||
float d1 = textureLod(texdepth, texCoord + vec2(screenSizeInv.x, 0.0), 0.0).r;
|
||||
float d2 = textureLod(texdepth, texCoord + vec2(0.0, screenSizeInv.y), 0.0).r;
|
||||
float d3 = textureLod(texdepth, texCoord + vec2(screenSizeInv.x, screenSizeInv.y), 0.0).r;
|
||||
fragColor = max(max(d0, d1), max(d2, d3));
|
||||
}
|
19
leenkx/Shaders/downsample_depth/downsample_depth.json
Normal file
19
leenkx/Shaders/downsample_depth/downsample_depth.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"contexts": [
|
||||
{
|
||||
"name": "downsample_depth",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [
|
||||
{
|
||||
"name": "screenSizeInv",
|
||||
"link": "_screenSizeInv"
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass.vert.glsl",
|
||||
"fragment_shader": "downsample_depth.frag.glsl"
|
||||
}
|
||||
]
|
||||
}
|
58
leenkx/Shaders/fxaa_pass/fxaa_pass.frag.glsl
Normal file
58
leenkx/Shaders/fxaa_pass/fxaa_pass.frag.glsl
Normal file
@ -0,0 +1,58 @@
|
||||
#version 450
|
||||
|
||||
uniform sampler2D tex;
|
||||
uniform vec2 screenSizeInv;
|
||||
|
||||
in vec2 texCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
void main() {
|
||||
const float FXAA_REDUCE_MIN = 1.0 / 128.0;
|
||||
const float FXAA_REDUCE_MUL = 1.0 / 8.0;
|
||||
const float FXAA_SPAN_MAX = 8.0;
|
||||
|
||||
vec2 tcrgbNW = (texCoord + vec2(-1.0, -1.0) * screenSizeInv);
|
||||
vec2 tcrgbNE = (texCoord + vec2(1.0, -1.0) * screenSizeInv);
|
||||
vec2 tcrgbSW = (texCoord + vec2(-1.0, 1.0) * screenSizeInv);
|
||||
vec2 tcrgbSE = (texCoord + vec2(1.0, 1.0) * screenSizeInv);
|
||||
vec2 tcrgbM = vec2(texCoord);
|
||||
|
||||
vec3 rgbNW = textureLod(tex, tcrgbNW, 0.0).rgb;
|
||||
vec3 rgbNE = textureLod(tex, tcrgbNE, 0.0).rgb;
|
||||
vec3 rgbSW = textureLod(tex, tcrgbSW, 0.0).rgb;
|
||||
vec3 rgbSE = textureLod(tex, tcrgbSE, 0.0).rgb;
|
||||
vec4 texColor = textureLod(tex, tcrgbM, 0.0);
|
||||
vec3 rgbM = texColor.rgb;
|
||||
vec3 luma = vec3(0.299, 0.587, 0.114);
|
||||
float lumaNW = dot(rgbNW, luma);
|
||||
float lumaNE = dot(rgbNE, luma);
|
||||
float lumaSW = dot(rgbSW, luma);
|
||||
float lumaSE = dot(rgbSE, luma);
|
||||
float lumaM = dot(rgbM, luma);
|
||||
float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
|
||||
float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
|
||||
|
||||
vec2 dir;
|
||||
dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));
|
||||
dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));
|
||||
|
||||
float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) *
|
||||
(0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN);
|
||||
|
||||
float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce);
|
||||
dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX),
|
||||
max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),
|
||||
dir * rcpDirMin)) * screenSizeInv;
|
||||
|
||||
vec3 rgbA = 0.5 * (
|
||||
textureLod(tex, texCoord + dir * (1.0 / 3.0 - 0.5), 0.0).rgb +
|
||||
textureLod(tex, texCoord + dir * (2.0 / 3.0 - 0.5), 0.0).rgb);
|
||||
fragColor.rgb = rgbA * 0.5 + 0.25 * ( // vec3 rgbB
|
||||
textureLod(tex, texCoord + dir * -0.5, 0.0).rgb +
|
||||
textureLod(tex, texCoord + dir * 0.5, 0.0).rgb);
|
||||
|
||||
// float lumaB = dot(rgbB, luma);
|
||||
float lumaB = dot(fragColor.rgb, luma);
|
||||
if ((lumaB < lumaMin) || (lumaB > lumaMax)) fragColor.rgb = rgbA;
|
||||
// else fragColor.rgb = rgbB;
|
||||
}
|
19
leenkx/Shaders/fxaa_pass/fxaa_pass.json
Normal file
19
leenkx/Shaders/fxaa_pass/fxaa_pass.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"contexts": [
|
||||
{
|
||||
"name": "fxaa_pass",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [
|
||||
{
|
||||
"name": "screenSizeInv",
|
||||
"link": "_screenSizeInv"
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass.vert.glsl",
|
||||
"fragment_shader": "fxaa_pass.frag.glsl"
|
||||
}
|
||||
]
|
||||
}
|
18
leenkx/Shaders/histogram_pass/histogram_pass.frag.glsl
Normal file
18
leenkx/Shaders/histogram_pass/histogram_pass.frag.glsl
Normal file
@ -0,0 +1,18 @@
|
||||
#version 450
|
||||
|
||||
#include "compiled.inc"
|
||||
|
||||
uniform sampler2D tex;
|
||||
|
||||
in vec2 texCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
void main() {
|
||||
fragColor.a = 0.01 * autoExposureSpeed;
|
||||
fragColor.rgb = textureLod(tex, vec2(0.5, 0.5), 0.0).rgb +
|
||||
textureLod(tex, vec2(0.2, 0.2), 0.0).rgb +
|
||||
textureLod(tex, vec2(0.8, 0.2), 0.0).rgb +
|
||||
textureLod(tex, vec2(0.2, 0.8), 0.0).rgb +
|
||||
textureLod(tex, vec2(0.8, 0.8), 0.0).rgb;
|
||||
fragColor.rgb /= 5.0;
|
||||
}
|
17
leenkx/Shaders/histogram_pass/histogram_pass.json
Normal file
17
leenkx/Shaders/histogram_pass/histogram_pass.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"contexts": [
|
||||
{
|
||||
"name": "histogram_pass",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"blend_source": "source_alpha",
|
||||
"blend_destination": "inverse_source_alpha",
|
||||
"blend_operation": "add",
|
||||
"links": [],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass.vert.glsl",
|
||||
"fragment_shader": "histogram_pass.frag.glsl"
|
||||
}
|
||||
]
|
||||
}
|
18
leenkx/Shaders/include/pass.vert.glsl
Normal file
18
leenkx/Shaders/include/pass.vert.glsl
Normal file
@ -0,0 +1,18 @@
|
||||
#version 450
|
||||
|
||||
#include "compiled.inc"
|
||||
|
||||
in vec2 pos;
|
||||
|
||||
out vec2 texCoord;
|
||||
|
||||
void main() {
|
||||
// Scale vertex attribute to 0-1 range
|
||||
const vec2 madd = vec2(0.5, 0.5);
|
||||
texCoord = pos.xy * madd + madd;
|
||||
#ifdef _InvY
|
||||
texCoord.y = 1.0 - texCoord.y;
|
||||
#endif
|
||||
|
||||
gl_Position = vec4(pos.xy, 0.0, 1.0);
|
||||
}
|
10
leenkx/Shaders/include/pass_copy.frag.glsl
Normal file
10
leenkx/Shaders/include/pass_copy.frag.glsl
Normal file
@ -0,0 +1,10 @@
|
||||
#version 450
|
||||
|
||||
uniform sampler2D tex;
|
||||
|
||||
in vec2 texCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
void main() {
|
||||
fragColor = textureLod(tex, texCoord, 0.0);
|
||||
}
|
31
leenkx/Shaders/include/pass_viewray.vert.glsl
Normal file
31
leenkx/Shaders/include/pass_viewray.vert.glsl
Normal file
@ -0,0 +1,31 @@
|
||||
#version 450
|
||||
|
||||
#include "compiled.inc"
|
||||
|
||||
uniform mat4 invVP;
|
||||
uniform vec3 eye;
|
||||
|
||||
in vec2 pos;
|
||||
|
||||
out vec2 texCoord;
|
||||
out vec3 viewRay;
|
||||
|
||||
void main() {
|
||||
// Scale vertex attribute to [0-1] range
|
||||
const vec2 madd = vec2(0.5, 0.5);
|
||||
texCoord = pos.xy * madd + madd;
|
||||
#ifdef _InvY
|
||||
texCoord.y = 1.0 - texCoord.y;
|
||||
#endif
|
||||
|
||||
gl_Position = vec4(pos.xy, 0.0, 1.0);
|
||||
|
||||
// fullscreen triangle: http://de.slideshare.net/DevCentralAMD/vertex-shader-tricks-bill-bilodeau
|
||||
// gl_Position = vec4((gl_VertexID % 2) * 4.0 - 1.0, (gl_VertexID / 2) * 4.0 - 1.0, 0.0, 1.0);
|
||||
|
||||
// NDC (at the back of cube)
|
||||
vec4 v = vec4(pos.x, pos.y, 1.0, 1.0);
|
||||
v = vec4(invVP * v);
|
||||
v.xyz /= v.w;
|
||||
viewRay = v.xyz - eye;
|
||||
}
|
26
leenkx/Shaders/include/pass_viewray2.vert.glsl
Normal file
26
leenkx/Shaders/include/pass_viewray2.vert.glsl
Normal file
@ -0,0 +1,26 @@
|
||||
#version 450
|
||||
|
||||
#include "compiled.inc"
|
||||
|
||||
uniform mat4 invP;
|
||||
|
||||
in vec2 pos;
|
||||
|
||||
out vec2 texCoord;
|
||||
out vec3 viewRay;
|
||||
|
||||
void main() {
|
||||
// Scale vertex attribute to [0-1] range
|
||||
const vec2 madd = vec2(0.5, 0.5);
|
||||
texCoord = pos.xy * madd + madd;
|
||||
#ifdef _InvY
|
||||
texCoord.y = 1.0 - texCoord.y;
|
||||
#endif
|
||||
|
||||
gl_Position = vec4(pos.xy, 0.0, 1.0);
|
||||
|
||||
// NDC (at the back of cube)
|
||||
vec4 v = vec4(pos.x, pos.y, 1.0, 1.0);
|
||||
v = vec4(invP * v);
|
||||
viewRay = vec3(v.xy / v.z, 1.0);
|
||||
}
|
12
leenkx/Shaders/include/pass_volume.vert.glsl
Normal file
12
leenkx/Shaders/include/pass_volume.vert.glsl
Normal file
@ -0,0 +1,12 @@
|
||||
#version 450
|
||||
|
||||
uniform mat4 VWVP;
|
||||
|
||||
in vec3 pos;
|
||||
|
||||
out vec4 wvpposition;
|
||||
|
||||
void main() {
|
||||
wvpposition = VWVP * vec4(pos, 1.0);
|
||||
gl_Position = wvpposition;
|
||||
}
|
54
leenkx/Shaders/motion_blur_pass/motion_blur_pass.frag.glsl
Normal file
54
leenkx/Shaders/motion_blur_pass/motion_blur_pass.frag.glsl
Normal file
@ -0,0 +1,54 @@
|
||||
// Based on GPU Gems 3
|
||||
// http://http.developer.nvidia.com/GPUGems3/gpugems3_ch27.html
|
||||
#version 450
|
||||
|
||||
#include "compiled.inc"
|
||||
#include "std/gbuffer.glsl"
|
||||
|
||||
uniform sampler2D gbufferD;
|
||||
uniform sampler2D tex;
|
||||
uniform mat4 prevVP;
|
||||
uniform vec3 eye;
|
||||
uniform vec3 eyeLook;
|
||||
uniform vec2 cameraProj;
|
||||
uniform float frameScale;
|
||||
|
||||
in vec2 texCoord;
|
||||
in vec3 viewRay;
|
||||
out vec4 fragColor;
|
||||
|
||||
vec2 getVelocity(vec2 coord, float depth) {
|
||||
#ifdef _InvY
|
||||
coord.y = 1.0 - coord.y;
|
||||
#endif
|
||||
vec4 currentPos = vec4(coord.xy * 2.0 - 1.0, depth, 1.0);
|
||||
vec4 worldPos = vec4(getPos(eye, eyeLook, normalize(viewRay), depth, cameraProj), 1.0);
|
||||
vec4 previousPos = prevVP * worldPos;
|
||||
previousPos /= previousPos.w;
|
||||
vec2 velocity = (currentPos - previousPos).xy / 40.0;
|
||||
#ifdef _InvY
|
||||
velocity.y = -velocity.y;
|
||||
#endif
|
||||
return velocity;
|
||||
}
|
||||
|
||||
void main() {
|
||||
fragColor.rgb = textureLod(tex, texCoord, 0.0).rgb;
|
||||
|
||||
float depth = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0;
|
||||
if (depth == 1.0) {
|
||||
return;
|
||||
}
|
||||
|
||||
float blurScale = motionBlurIntensity * frameScale;
|
||||
vec2 velocity = getVelocity(texCoord, depth) * blurScale;
|
||||
|
||||
vec2 offset = texCoord;
|
||||
int processed = 1;
|
||||
for(int i = 0; i < 8; ++i) {
|
||||
offset += velocity;
|
||||
fragColor.rgb += textureLod(tex, offset, 0.0).rgb;
|
||||
processed++;
|
||||
}
|
||||
fragColor.rgb /= processed;
|
||||
}
|
39
leenkx/Shaders/motion_blur_pass/motion_blur_pass.json
Normal file
39
leenkx/Shaders/motion_blur_pass/motion_blur_pass.json
Normal file
@ -0,0 +1,39 @@
|
||||
{
|
||||
"contexts": [
|
||||
{
|
||||
"name": "motion_blur_pass",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [
|
||||
{
|
||||
"name": "prevVP",
|
||||
"link": "_prevViewProjectionMatrix"
|
||||
},
|
||||
{
|
||||
"name": "invVP",
|
||||
"link": "_inverseViewProjectionMatrix"
|
||||
},
|
||||
{
|
||||
"name": "eye",
|
||||
"link": "_cameraPosition"
|
||||
},
|
||||
{
|
||||
"name": "eyeLook",
|
||||
"link": "_cameraLook"
|
||||
},
|
||||
{
|
||||
"name": "cameraProj",
|
||||
"link": "_cameraPlaneProj"
|
||||
},
|
||||
{
|
||||
"name": "frameScale",
|
||||
"link": "_frameScale"
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass_viewray.vert.glsl",
|
||||
"fragment_shader": "motion_blur_pass.frag.glsl"
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
// Per-Object Motion Blur
|
||||
// http://john-chapman-graphics.blogspot.com/2013/01/per-object-motion-blur.html
|
||||
#version 450
|
||||
|
||||
#include "compiled.inc"
|
||||
|
||||
uniform sampler2D sveloc;
|
||||
uniform sampler2D tex;
|
||||
// uniform vec2 texStep;
|
||||
uniform float frameScale;
|
||||
|
||||
in vec2 texCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
void main() {
|
||||
vec2 velocity = textureLod(sveloc, texCoord, 0.0).rg * motionBlurIntensity * frameScale;
|
||||
|
||||
#ifdef _InvY
|
||||
velocity.y = -velocity.y;
|
||||
#endif
|
||||
|
||||
fragColor.rgb = textureLod(tex, texCoord, 0.0).rgb;
|
||||
|
||||
// float speed = length(velocity / texStep);
|
||||
// const int MAX_SAMPLES = 8;
|
||||
// int samples = clamp(int(speed), 1, MAX_SAMPLES);
|
||||
const int samples = 8;
|
||||
for (int i = 0; i < samples; ++i) {
|
||||
vec2 offset = velocity * (float(i) / float(samples - 1) - 0.5);
|
||||
fragColor.rgb += textureLod(tex, texCoord + offset, 0.0).rgb;
|
||||
}
|
||||
fragColor.rgb /= float(samples + 1);
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
{
|
||||
"contexts": [
|
||||
{
|
||||
"name": "motion_blur_veloc_pass",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [
|
||||
{
|
||||
"name": "frameScale",
|
||||
"link": "_frameScale"
|
||||
},
|
||||
{
|
||||
"name": "texStep",
|
||||
"link": "_screenSizeInv",
|
||||
"ifdef": ["_Disabled"]
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass.vert.glsl",
|
||||
"fragment_shader": "motion_blur_veloc_pass.frag.glsl"
|
||||
}
|
||||
]
|
||||
}
|
54
leenkx/Shaders/probe_cubemap/probe_cubemap.frag.glsl
Normal file
54
leenkx/Shaders/probe_cubemap/probe_cubemap.frag.glsl
Normal file
@ -0,0 +1,54 @@
|
||||
#version 450
|
||||
|
||||
#include "compiled.inc"
|
||||
#include "std/gbuffer.glsl"
|
||||
|
||||
uniform samplerCube probeTex;
|
||||
uniform sampler2D gbufferD;
|
||||
uniform sampler2D gbuffer0;
|
||||
uniform sampler2D gbuffer1;
|
||||
uniform mat4 invVP;
|
||||
uniform vec3 probep;
|
||||
uniform vec3 eye;
|
||||
|
||||
in vec4 wvpposition;
|
||||
out vec4 fragColor;
|
||||
|
||||
void main() {
|
||||
vec2 texCoord = wvpposition.xy / wvpposition.w;
|
||||
texCoord = texCoord * 0.5 + 0.5;
|
||||
#ifdef _InvY
|
||||
texCoord.y = 1.0 - texCoord.y;
|
||||
#endif
|
||||
|
||||
vec4 g0 = textureLod(gbuffer0, texCoord, 0.0); // Normal.xy, roughness, metallic/matid
|
||||
|
||||
float roughness = g0.b;
|
||||
if (roughness > 0.95) {
|
||||
fragColor.rgb = vec3(0.0);
|
||||
return;
|
||||
}
|
||||
|
||||
float spec = fract(textureLod(gbuffer1, texCoord, 0.0).a);
|
||||
if (spec == 0.0) {
|
||||
fragColor.rgb = vec3(0.0);
|
||||
return;
|
||||
}
|
||||
|
||||
float depth = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0;
|
||||
vec3 wp = getPos2(invVP, depth, texCoord);
|
||||
|
||||
vec2 enc = g0.rg;
|
||||
vec3 n;
|
||||
n.z = 1.0 - abs(enc.x) - abs(enc.y);
|
||||
n.xy = n.z >= 0.0 ? enc.xy : octahedronWrap(enc.xy);
|
||||
n = normalize(n);
|
||||
|
||||
vec3 v = wp - eye;
|
||||
vec3 r = reflect(v, n);
|
||||
#ifdef _InvY
|
||||
r.y = -r.y;
|
||||
#endif
|
||||
float intensity = clamp((1.0 - roughness) * dot(wp - probep, n), 0.0, 1.0);
|
||||
fragColor.rgb = texture(probeTex, r).rgb * intensity;
|
||||
}
|
36
leenkx/Shaders/probe_cubemap/probe_cubemap.json
Normal file
36
leenkx/Shaders/probe_cubemap/probe_cubemap.json
Normal file
@ -0,0 +1,36 @@
|
||||
{
|
||||
"contexts": [
|
||||
{
|
||||
"name": "probe_cubemap",
|
||||
"depth_write": false,
|
||||
"compare_mode": "less",
|
||||
"cull_mode": "clockwise",
|
||||
"blend_source": "blend_one",
|
||||
"blend_destination": "blend_one",
|
||||
"blend_operation": "add",
|
||||
"alpha_blend_source": "blend_one",
|
||||
"alpha_blend_destination": "blend_one",
|
||||
"alpha_blend_operation": "add",
|
||||
"links": [
|
||||
{
|
||||
"name": "VWVP",
|
||||
"link": "_worldViewProjectionMatrix"
|
||||
},
|
||||
{
|
||||
"name": "invVP",
|
||||
"link": "_inverseViewProjectionMatrix"
|
||||
},
|
||||
{
|
||||
"name": "probep",
|
||||
"link": "_probePosition"
|
||||
},
|
||||
{
|
||||
"name": "eye",
|
||||
"link": "_cameraPosition"
|
||||
}
|
||||
],
|
||||
"vertex_shader": "../include/pass_volume.vert.glsl",
|
||||
"fragment_shader": "probe_cubemap.frag.glsl"
|
||||
}
|
||||
]
|
||||
}
|
54
leenkx/Shaders/probe_planar/probe_planar.frag.glsl
Normal file
54
leenkx/Shaders/probe_planar/probe_planar.frag.glsl
Normal file
@ -0,0 +1,54 @@
|
||||
#version 450
|
||||
|
||||
#include "compiled.inc"
|
||||
#include "std/gbuffer.glsl"
|
||||
|
||||
uniform sampler2D probeTex;
|
||||
uniform sampler2D gbufferD;
|
||||
uniform sampler2D gbuffer0;
|
||||
uniform sampler2D gbuffer1;
|
||||
uniform mat4 probeVP;
|
||||
uniform mat4 invVP;
|
||||
uniform vec3 proben;
|
||||
|
||||
in vec4 wvpposition;
|
||||
out vec4 fragColor;
|
||||
|
||||
void main() {
|
||||
vec2 texCoord = wvpposition.xy / wvpposition.w;
|
||||
texCoord = texCoord * 0.5 + 0.5;
|
||||
#ifdef _InvY
|
||||
texCoord.y = 1.0 - texCoord.y;
|
||||
#endif
|
||||
|
||||
vec4 g0 = textureLod(gbuffer0, texCoord, 0.0); // Normal.xy, roughness, metallic/matid
|
||||
|
||||
float roughness = g0.b;
|
||||
if (roughness > 0.95) {
|
||||
fragColor.rgb = vec3(0.0);
|
||||
return;
|
||||
}
|
||||
|
||||
float spec = fract(textureLod(gbuffer1, texCoord, 0.0).a);
|
||||
if (spec == 0.0) {
|
||||
fragColor.rgb = vec3(0.0);
|
||||
return;
|
||||
}
|
||||
|
||||
float depth = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0;
|
||||
vec3 wp = getPos2(invVP, depth, texCoord);
|
||||
vec4 pp = probeVP * vec4(wp.xyz, 1.0);
|
||||
vec2 tc = (pp.xy / pp.w) * 0.5 + 0.5;
|
||||
#ifdef _InvY
|
||||
tc.y = 1.0 - tc.y;
|
||||
#endif
|
||||
|
||||
vec2 enc = g0.rg;
|
||||
vec3 n;
|
||||
n.z = 1.0 - abs(enc.x) - abs(enc.y);
|
||||
n.xy = n.z >= 0.0 ? enc.xy : octahedronWrap(enc.xy);
|
||||
n = normalize(n);
|
||||
|
||||
float intensity = clamp((1.0 - roughness) * dot(n, proben), 0.0, 1.0);
|
||||
fragColor.rgb = texture(probeTex, tc).rgb * intensity;
|
||||
}
|
36
leenkx/Shaders/probe_planar/probe_planar.json
Normal file
36
leenkx/Shaders/probe_planar/probe_planar.json
Normal file
@ -0,0 +1,36 @@
|
||||
{
|
||||
"contexts": [
|
||||
{
|
||||
"name": "probe_planar",
|
||||
"depth_write": false,
|
||||
"compare_mode": "less",
|
||||
"cull_mode": "clockwise",
|
||||
"blend_source": "blend_one",
|
||||
"blend_destination": "blend_one",
|
||||
"blend_operation": "add",
|
||||
"alpha_blend_source": "blend_one",
|
||||
"alpha_blend_destination": "blend_one",
|
||||
"alpha_blend_operation": "add",
|
||||
"links": [
|
||||
{
|
||||
"name": "VWVP",
|
||||
"link": "_worldViewProjectionMatrix"
|
||||
},
|
||||
{
|
||||
"name": "invVP",
|
||||
"link": "_inverseViewProjectionMatrix"
|
||||
},
|
||||
{
|
||||
"name": "probeVP",
|
||||
"link": "_probeViewProjectionMatrix"
|
||||
},
|
||||
{
|
||||
"name": "proben",
|
||||
"link": "_probeNormal"
|
||||
}
|
||||
],
|
||||
"vertex_shader": "../include/pass_volume.vert.glsl",
|
||||
"fragment_shader": "probe_planar.frag.glsl"
|
||||
}
|
||||
]
|
||||
}
|
457
leenkx/Shaders/smaa_blend_weight/smaa_blend_weight.frag.glsl
Normal file
457
leenkx/Shaders/smaa_blend_weight/smaa_blend_weight.frag.glsl
Normal file
@ -0,0 +1,457 @@
|
||||
#version 450
|
||||
|
||||
#include "compiled.inc"
|
||||
#define SMAA_MAX_SEARCH_STEPS_DIAG 8
|
||||
#define SMAA_AREATEX_MAX_DISTANCE 16
|
||||
#define SMAA_AREATEX_MAX_DISTANCE_DIAG 20
|
||||
#define SMAA_AREATEX_PIXEL_SIZE (1.0 / vec2(160.0, 560.0))
|
||||
#define SMAA_AREATEX_SUBTEX_SIZE (1.0 / 7.0)
|
||||
#define SMAA_SEARCHTEX_SIZE vec2(66.0, 33.0)
|
||||
#define SMAA_SEARCHTEX_PACKED_SIZE vec2(64.0, 16.0)
|
||||
#define SMAA_CORNER_ROUNDING 25
|
||||
#define SMAA_CORNER_ROUNDING_NORM (float(SMAA_CORNER_ROUNDING) / 100.0)
|
||||
#define SMAA_AREATEX_SELECT(sample) sample.rg
|
||||
#define SMAA_SEARCHTEX_SELECT(sample) sample.r
|
||||
#define mad(a, b, c) (a * b + c)
|
||||
#define saturate(a) clamp(a, 0.0, 1.0)
|
||||
#define round(a) floor(a + 0.5)
|
||||
|
||||
uniform sampler2D edgesTex;
|
||||
uniform sampler2D areaTex;
|
||||
uniform sampler2D searchTex;
|
||||
|
||||
uniform vec2 screenSize;
|
||||
uniform vec2 screenSizeInv;
|
||||
|
||||
in vec2 texCoord;
|
||||
in vec2 pixcoord;
|
||||
in vec4 offset0;
|
||||
in vec4 offset1;
|
||||
in vec4 offset2;
|
||||
out vec4 fragColor;
|
||||
|
||||
// Blending Weight Calculation Pixel Shader (Second Pass)
|
||||
vec2 cdw_end;
|
||||
|
||||
vec4 textureLodA(sampler2D tex, vec2 coord, float lod) {
|
||||
#ifdef _InvY
|
||||
coord.y = 1.0 - coord.y;
|
||||
#endif
|
||||
return textureLod(tex, coord, lod);
|
||||
}
|
||||
|
||||
#define SMAASampleLevelZeroOffset(tex, coord, offset) textureLodA(tex, coord + offset * screenSizeInv.xy, 0.0)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Diagonal Search Functions
|
||||
|
||||
// #if !defined(SMAA_DISABLE_DIAG_DETECTION)
|
||||
/**
|
||||
* Allows to decode two binary values from a bilinear-filtered access.
|
||||
*/
|
||||
vec2 SMAADecodeDiagBilinearAccess(vec2 e) {
|
||||
// Bilinear access for fetching 'e' have a 0.25 offset, and we are
|
||||
// interested in the R and G edges:
|
||||
//
|
||||
// +---G---+-------+
|
||||
// | x o R x |
|
||||
// +-------+-------+
|
||||
//
|
||||
// Then, if one of these edge is enabled:
|
||||
// Red: (0.75 * X + 0.25 * 1) => 0.25 or 1.0
|
||||
// Green: (0.75 * 1 + 0.25 * X) => 0.75 or 1.0
|
||||
//
|
||||
// This function will unpack the values (mad + mul + round):
|
||||
// wolframalpha.com: round(x * abs(5 * x - 5 * 0.75)) plot 0 to 1
|
||||
e.r = e.r * abs(5.0 * e.r - 5.0 * 0.75);
|
||||
return round(e);
|
||||
}
|
||||
|
||||
vec4 SMAADecodeDiagBilinearAccess(vec4 e) {
|
||||
e.rb = e.rb * abs(5.0 * e.rb - 5.0 * 0.75);
|
||||
return round(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* These functions allows to perform diagonal pattern searches.
|
||||
*/
|
||||
vec2 SMAASearchDiag1(vec2 texcoord, vec2 dir/*, out vec2 e*/) {
|
||||
vec4 coord = vec4(texcoord, -1.0, 1.0);
|
||||
vec3 t = vec3(screenSizeInv.xy, 1.0);
|
||||
float cw = coord.w; // TODO: krafix hlsl bug
|
||||
while (coord.z < float(SMAA_MAX_SEARCH_STEPS_DIAG - 1) && cw > 0.9) {
|
||||
coord.xyz = mad(t, vec3(dir, 1.0), coord.xyz);
|
||||
cdw_end /*e*/ = textureLodA(edgesTex, coord.xy, 0.0).rg;
|
||||
cw = dot(cdw_end /*e*/, vec2(0.5, 0.5));
|
||||
}
|
||||
coord.w = cw;
|
||||
return coord.zw;
|
||||
}
|
||||
|
||||
vec2 SMAASearchDiag2(vec2 texcoord, vec2 dir) {
|
||||
vec4 coord = vec4(texcoord, -1.0, 1.0);
|
||||
coord.x += 0.25 * screenSizeInv.x; // See @SearchDiag2Optimization
|
||||
vec3 t = vec3(screenSizeInv.xy, 1.0);
|
||||
float cw = coord.w; // TODO: krafix hlsl bug
|
||||
while (coord.z < float(SMAA_MAX_SEARCH_STEPS_DIAG - 1) && cw > 0.9) {
|
||||
coord.xyz = mad(t, vec3(dir, 1.0), coord.xyz);
|
||||
// @SearchDiag2Optimization
|
||||
// Fetch both edges at once using bilinear filtering:
|
||||
cdw_end /*e*/ = textureLodA(edgesTex, coord.xy, 0.0).rg;
|
||||
cdw_end /*e*/ = SMAADecodeDiagBilinearAccess(cdw_end /*e*/);
|
||||
cw = dot(cdw_end /*e*/, vec2(0.5, 0.5));
|
||||
}
|
||||
coord.w = cw;
|
||||
return coord.zw;
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to SMAAArea, this calculates the area corresponding to a certain
|
||||
* diagonal distance and crossing edges 'e'.
|
||||
*/
|
||||
vec2 SMAAAreaDiag(vec2 dist, vec2 e, float offset) {
|
||||
vec2 texcoord = mad(vec2(SMAA_AREATEX_MAX_DISTANCE_DIAG, SMAA_AREATEX_MAX_DISTANCE_DIAG), e, dist);
|
||||
|
||||
// We do a scale and bias for mapping to texel space:
|
||||
texcoord = mad(SMAA_AREATEX_PIXEL_SIZE, texcoord, 0.5 * SMAA_AREATEX_PIXEL_SIZE);
|
||||
|
||||
// Diagonal areas are on the second half of the texture:
|
||||
texcoord.x += 0.5;
|
||||
|
||||
// Move to proper place, according to the subpixel offset:
|
||||
texcoord.y += SMAA_AREATEX_SUBTEX_SIZE * offset;
|
||||
|
||||
// Do it!
|
||||
return SMAA_AREATEX_SELECT(textureLod(areaTex, texcoord, 0.0));
|
||||
}
|
||||
|
||||
/**
|
||||
* This searches for diagonal patterns and returns the corresponding weights.
|
||||
*/
|
||||
vec2 SMAACalculateDiagWeights(vec2 texcoord, vec2 e, vec4 subsampleIndices) {
|
||||
vec2 weights = vec2(0.0, 0.0);
|
||||
|
||||
// Search for the line ends:
|
||||
vec4 d;
|
||||
if (e.r > 0.0) {
|
||||
d.xz = SMAASearchDiag1(texcoord, vec2(-1.0, 1.0)/*, cdw_end*/);
|
||||
float dadd = cdw_end.y > 0.9 ? 1.0 : 0.0;
|
||||
d.x += dadd;
|
||||
}
|
||||
else {
|
||||
d.xz = vec2(0.0, 0.0);
|
||||
}
|
||||
d.yw = SMAASearchDiag1(texcoord, vec2(1.0, -1.0)/*, cdw_end*/);
|
||||
|
||||
//SMAA_BRANCH
|
||||
if (d.x + d.y > 2.0) { // d.x + d.y + 1 > 3
|
||||
// Fetch the crossing edges:
|
||||
vec4 coords = mad(vec4(-d.x + 0.25, d.x, d.y, -d.y - 0.25), screenSizeInv.xyxy, texcoord.xyxy);
|
||||
vec4 c;
|
||||
|
||||
c.xy = SMAASampleLevelZeroOffset(edgesTex, coords.xy, ivec2(-1, 0)).rg;
|
||||
c.zw = SMAASampleLevelZeroOffset(edgesTex, coords.zw, ivec2( 1, 0)).rg;
|
||||
c.yxwz = SMAADecodeDiagBilinearAccess(c.xyzw);
|
||||
|
||||
// Merge crossing edges at each side into a single value:
|
||||
vec2 cc = mad(vec2(2.0, 2.0), c.xz, c.yw);
|
||||
|
||||
// Remove the crossing edge if we didn't found the end of the line:
|
||||
// SMAAMovc(bvec2(step(0.9, d.zw)), cc, vec2(0.0, 0.0));
|
||||
float a1condx = step(0.9, d.z);
|
||||
float a1condy = step(0.9, d.w);
|
||||
if (a1condx == 1.0) cc.x = 0.0;
|
||||
if (a1condy == 1.0) cc.y = 0.0;
|
||||
|
||||
// Fetch the areas for this line:
|
||||
weights += SMAAAreaDiag(d.xy, cc, subsampleIndices.z);
|
||||
}
|
||||
|
||||
// Search for the line ends:
|
||||
d.xz = SMAASearchDiag2(texcoord, vec2(-1.0, -1.0)/*, cdw_end*/);
|
||||
if (SMAASampleLevelZeroOffset(edgesTex, texcoord, ivec2(1, 0)).r > 0.0) {
|
||||
d.yw = SMAASearchDiag2(texcoord, vec2(1.0, 1.0)/*, cdw_end*/);
|
||||
float dadd = cdw_end.y > 0.9 ? 1.0 : 0.0;
|
||||
d.y += dadd;
|
||||
}
|
||||
else {
|
||||
d.yw = vec2(0.0, 0.0);
|
||||
}
|
||||
|
||||
// SMAA_BRANCH
|
||||
if (d.x + d.y > 2.0) { // d.x + d.y + 1 > 3
|
||||
// Fetch the crossing edges:
|
||||
vec4 coords = mad(vec4(-d.x, -d.x, d.y, d.y), screenSizeInv.xyxy, texcoord.xyxy);
|
||||
vec4 c;
|
||||
c.x = SMAASampleLevelZeroOffset(edgesTex, coords.xy, ivec2(-1, 0)).g;
|
||||
c.y = SMAASampleLevelZeroOffset(edgesTex, coords.xy, ivec2( 0, -1)).r;
|
||||
c.zw = SMAASampleLevelZeroOffset(edgesTex, coords.zw, ivec2( 1, 0)).gr;
|
||||
vec2 cc = mad(vec2(2.0, 2.0), c.xz, c.yw);
|
||||
|
||||
// Remove the crossing edge if we didn't found the end of the line:
|
||||
// SMAAMovc(bvec2(step(0.9, d.zw)), cc, vec2(0.0, 0.0));
|
||||
float a1condx = step(0.9, d.z);
|
||||
float a1condy = step(0.9, d.w);
|
||||
if (a1condx == 1.0) cc.x = 0.0;
|
||||
if (a1condy == 1.0) cc.y = 0.0;
|
||||
|
||||
// Fetch the areas for this line:
|
||||
weights += SMAAAreaDiag(d.xy, cc, subsampleIndices.w).gr;
|
||||
}
|
||||
|
||||
return weights;
|
||||
}
|
||||
// #endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Horizontal/Vertical Search Functions
|
||||
|
||||
/**
|
||||
* This allows to determine how much length should we add in the last step
|
||||
* of the searches. It takes the bilinearly interpolated edge (see
|
||||
* @PSEUDO_GATHER4), and adds 0, 1 or 2, depending on which edges and
|
||||
* crossing edges are active.
|
||||
*/
|
||||
float SMAASearchLength(vec2 e, float offset) {
|
||||
// The texture is flipped vertically, with left and right cases taking half
|
||||
// of the space horizontally:
|
||||
vec2 scale = SMAA_SEARCHTEX_SIZE * vec2(0.5, -1.0);
|
||||
vec2 bias = SMAA_SEARCHTEX_SIZE * vec2(offset, 1.0);
|
||||
|
||||
// Scale and bias to access texel centers:
|
||||
scale += vec2(-1.0, 1.0);
|
||||
bias += vec2( 0.5, -0.5);
|
||||
|
||||
// Convert from pixel coordinates to texcoords:
|
||||
// (We use SMAA_SEARCHTEX_PACKED_SIZE because the texture is cropped)
|
||||
scale *= 1.0 / SMAA_SEARCHTEX_PACKED_SIZE;
|
||||
bias *= 1.0 / SMAA_SEARCHTEX_PACKED_SIZE;
|
||||
|
||||
vec2 coord = mad(scale, e, bias);
|
||||
|
||||
// Lookup the search texture:
|
||||
return SMAA_SEARCHTEX_SELECT(textureLod(searchTex, coord, 0.0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Horizontal/vertical search functions for the 2nd pass.
|
||||
*/
|
||||
float SMAASearchXLeft(vec2 texcoord, float end) {
|
||||
/**
|
||||
* @PSEUDO_GATHER4
|
||||
* This texcoord has been offset by (-0.25, -0.125) in the vertex shader to
|
||||
* sample between edge, thus fetching four edges in a row.
|
||||
* Sampling with different offsets in each direction allows to disambiguate
|
||||
* which edges are active from the four fetched ones.
|
||||
*/
|
||||
vec2 e = vec2(0.0, 1.0);
|
||||
while (texcoord.x > end &&
|
||||
e.g > 0.8281 && // Is there some edge not activated?
|
||||
e.r == 0.0) { // Or is there a crossing edge that breaks the line?
|
||||
e = textureLodA(edgesTex, texcoord, 0.0).rg;
|
||||
texcoord = mad(-vec2(2.0, 0.0), screenSizeInv.xy, texcoord);
|
||||
}
|
||||
|
||||
float offset = mad(-(255.0 / 127.0), SMAASearchLength(e, 0.0), 3.25);
|
||||
return mad(screenSizeInv.x, offset, texcoord.x);
|
||||
}
|
||||
|
||||
float SMAASearchXRight(vec2 texcoord, float end) {
|
||||
vec2 e = vec2(0.0, 1.0);
|
||||
while (texcoord.x < end &&
|
||||
e.g > 0.8281 && // Is there some edge not activated?
|
||||
e.r == 0.0) { // Or is there a crossing edge that breaks the line?
|
||||
e = textureLodA(edgesTex, texcoord, 0.0).rg;
|
||||
texcoord = mad(vec2(2.0, 0.0), screenSizeInv.xy, texcoord);
|
||||
}
|
||||
|
||||
float offset = mad(-(255.0 / 127.0), SMAASearchLength(e, 0.5), 3.25);
|
||||
return mad(-screenSizeInv.x, offset, texcoord.x);
|
||||
}
|
||||
|
||||
float SMAASearchYUp(vec2 texcoord, float end) {
|
||||
vec2 e = vec2(1.0, 0.0);
|
||||
while (texcoord.y > end &&
|
||||
e.r > 0.8281 && // Is there some edge not activated?
|
||||
e.g == 0.0) { // Or is there a crossing edge that breaks the line?
|
||||
e = textureLodA(edgesTex, texcoord, 0.0).rg;
|
||||
texcoord = mad(-vec2(0.0, 2.0), screenSizeInv.xy, texcoord);
|
||||
}
|
||||
float offset = mad(-(255.0 / 127.0), SMAASearchLength(e.gr, 0.0), 3.25);
|
||||
return mad(screenSizeInv.y, offset, texcoord.y);
|
||||
}
|
||||
|
||||
float SMAASearchYDown(vec2 texcoord, float end) {
|
||||
vec2 e = vec2(1.0, 0.0);
|
||||
while (texcoord.y < end &&
|
||||
e.r > 0.8281 && // Is there some edge not activated?
|
||||
e.g == 0.0) { // Or is there a crossing edge that breaks the line?
|
||||
e = textureLodA(edgesTex, texcoord, 0.0).rg;
|
||||
texcoord = mad(vec2(0.0, 2.0), screenSizeInv.xy, texcoord);
|
||||
}
|
||||
float offset = mad(-(255.0 / 127.0), SMAASearchLength(/*searchTex,*/ e.gr, 0.5), 3.25);
|
||||
return mad(-screenSizeInv.y, offset, texcoord.y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ok, we have the distance and both crossing edges. So, what are the areas
|
||||
* at each side of current edge?
|
||||
*/
|
||||
vec2 SMAAArea(vec2 dist, float e1, float e2, float offset) {
|
||||
// Rounding prevents precision errors of bilinear filtering:
|
||||
vec2 texcoord = mad(vec2(SMAA_AREATEX_MAX_DISTANCE, SMAA_AREATEX_MAX_DISTANCE), round(4.0 * vec2(e1, e2)), dist);
|
||||
|
||||
// We do a scale and bias for mapping to texel space:
|
||||
texcoord = mad(SMAA_AREATEX_PIXEL_SIZE, texcoord, 0.5 * SMAA_AREATEX_PIXEL_SIZE);
|
||||
|
||||
// Move to proper place, according to the subpixel offset:
|
||||
texcoord.y = mad(SMAA_AREATEX_SUBTEX_SIZE, offset, texcoord.y);
|
||||
|
||||
// Do it!
|
||||
return SMAA_AREATEX_SELECT(textureLod(areaTex, texcoord, 0.0));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Corner Detection Functions
|
||||
|
||||
vec2 SMAADetectHorizontalCornerPattern(vec2 weights, vec4 texcoord, vec2 d) {
|
||||
// #if !defined(SMAA_DISABLE_CORNER_DETECTION)
|
||||
vec2 leftRight = step(d.xy, d.yx);
|
||||
vec2 rounding = (1.0 - SMAA_CORNER_ROUNDING_NORM) * leftRight;
|
||||
|
||||
rounding /= leftRight.x + leftRight.y; // Reduce blending for pixels in the center of a line.
|
||||
|
||||
vec2 factor = vec2(1.0, 1.0);
|
||||
factor.x -= rounding.x * SMAASampleLevelZeroOffset(edgesTex, texcoord.xy, ivec2(0, 1)).r;
|
||||
factor.x -= rounding.y * SMAASampleLevelZeroOffset(edgesTex, texcoord.zw, ivec2(1, 1)).r;
|
||||
factor.y -= rounding.x * SMAASampleLevelZeroOffset(edgesTex, texcoord.xy, ivec2(0, -2)).r;
|
||||
factor.y -= rounding.y * SMAASampleLevelZeroOffset(edgesTex, texcoord.zw, ivec2(1, -2)).r;
|
||||
|
||||
weights *= saturate(factor);
|
||||
return weights; //
|
||||
// #endif
|
||||
}
|
||||
|
||||
vec2 SMAADetectVerticalCornerPattern(vec2 weights, vec4 texcoord, vec2 d) {
|
||||
//#if !defined(SMAA_DISABLE_CORNER_DETECTION)
|
||||
vec2 leftRight = step(d.xy, d.yx);
|
||||
vec2 rounding = (1.0 - SMAA_CORNER_ROUNDING_NORM) * leftRight;
|
||||
|
||||
rounding /= leftRight.x + leftRight.y;
|
||||
|
||||
vec2 factor = vec2(1.0, 1.0);
|
||||
factor.x -= rounding.x * SMAASampleLevelZeroOffset(edgesTex, texcoord.xy, ivec2( 1, 0)).g;
|
||||
factor.x -= rounding.y * SMAASampleLevelZeroOffset(edgesTex, texcoord.zw, ivec2( 1, 1)).g;
|
||||
factor.y -= rounding.x * SMAASampleLevelZeroOffset(edgesTex, texcoord.xy, ivec2(-2, 0)).g;
|
||||
factor.y -= rounding.y * SMAASampleLevelZeroOffset(edgesTex, texcoord.zw, ivec2(-2, 1)).g;
|
||||
|
||||
weights *= saturate(factor);
|
||||
return weights; //
|
||||
// #endif
|
||||
}
|
||||
|
||||
|
||||
vec4 SMAABlendingWeightCalculationPS(vec2 texcoord, vec2 pixcoord,
|
||||
vec4 subsampleIndices) { // Just pass zero for SMAA 1x, see @SUBSAMPLE_INDICES.
|
||||
vec4 weights = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
|
||||
vec2 e = textureLodA(edgesTex, texcoord, 0.0).rg;
|
||||
|
||||
//SMAA_BRANCH
|
||||
if (e.g > 0.0) { // Edge at north
|
||||
//#if !defined(SMAA_DISABLE_DIAG_DETECTION)
|
||||
// Diagonals have both north and west edges, so searching for them in
|
||||
// one of the boundaries is enough.
|
||||
weights.rg = SMAACalculateDiagWeights(texcoord, e, subsampleIndices);
|
||||
|
||||
// We give piority to diagonals, so if we find a diagonal we skip
|
||||
// horizontal/vertical processing.
|
||||
//SMAA_BRANCH
|
||||
if (weights.r == -weights.g) { // weights.r + weights.g == 0.0
|
||||
//#endif
|
||||
|
||||
vec2 d;
|
||||
|
||||
// Find the distance to the left:
|
||||
vec3 coords;
|
||||
coords.x = SMAASearchXLeft(offset0.xy, offset2.x);
|
||||
coords.y = offset1.y; // offset[1].y = texcoord.y - 0.25 * screenSizeInv.y (@CROSSING_OFFSET)
|
||||
d.x = coords.x;
|
||||
|
||||
// Now fetch the left crossing edges, two at a time using bilinear
|
||||
// filtering. Sampling at -0.25 (see @CROSSING_OFFSET) enables to
|
||||
// discern what value each edge has:
|
||||
float e1 = textureLodA(edgesTex, coords.xy, 0.0).r;
|
||||
|
||||
// Find the distance to the right:
|
||||
coords.z = SMAASearchXRight(offset0.zw, offset2.y);
|
||||
d.y = coords.z;
|
||||
|
||||
// We want the distances to be in pixel units (doing this here allow to
|
||||
// better interleave arithmetic and memory accesses):
|
||||
d = abs(round(mad(screenSize.xx, d, -pixcoord.xx)));
|
||||
|
||||
// SMAAArea below needs a sqrt, as the areas texture is compressed
|
||||
// quadratically:
|
||||
vec2 sqrt_d = sqrt(d);
|
||||
|
||||
// Fetch the right crossing edges:
|
||||
float e2 = SMAASampleLevelZeroOffset(edgesTex, coords.zy, ivec2(1, 0)).r;
|
||||
|
||||
// Ok, we know how this pattern looks like, now it is time for getting
|
||||
// the actual area:
|
||||
weights.rg = SMAAArea(sqrt_d, e1, e2, subsampleIndices.y);
|
||||
|
||||
// Fix corners:
|
||||
coords.y = texcoord.y;
|
||||
weights.rg = SMAADetectHorizontalCornerPattern(weights.rg, coords.xyzy, d);
|
||||
|
||||
//#if !defined(SMAA_DISABLE_DIAG_DETECTION)
|
||||
}
|
||||
else {
|
||||
e.r = 0.0; // Skip vertical processing.
|
||||
}
|
||||
//#endif
|
||||
}
|
||||
|
||||
//SMAA_BRANCH
|
||||
if (e.r > 0.0) { // Edge at west
|
||||
vec2 d;
|
||||
|
||||
// Find the distance to the top:
|
||||
vec3 coords;
|
||||
coords.y = SMAASearchYUp(/*edgesTex, searchTex,*/ offset1.xy, offset2.z);
|
||||
coords.x = offset0.x; // offset[1].x = texcoord.x - 0.25 * screenSizeInv.x;
|
||||
d.x = coords.y;
|
||||
|
||||
// Fetch the top crossing edges:
|
||||
float e1 = textureLodA(edgesTex, coords.xy, 0.0).g;
|
||||
|
||||
// Find the distance to the bottom:
|
||||
coords.z = SMAASearchYDown(offset1.zw, offset2.w);
|
||||
d.y = coords.z;
|
||||
|
||||
// We want the distances to be in pixel units:
|
||||
d = abs(round(mad(screenSize.yy, d, -pixcoord.yy)));
|
||||
|
||||
// SMAAArea below needs a sqrt, as the areas texture is compressed
|
||||
// quadratically:
|
||||
vec2 sqrt_d = sqrt(d);
|
||||
|
||||
// Fetch the bottom crossing edges:
|
||||
float e2 = SMAASampleLevelZeroOffset(edgesTex, coords.xz, ivec2(0, 1)).g;
|
||||
|
||||
// Get the area for this direction:
|
||||
weights.ba = SMAAArea(sqrt_d, e1, e2, subsampleIndices.x);
|
||||
|
||||
// Fix corners:
|
||||
coords.x = texcoord.x;
|
||||
weights.ba = SMAADetectVerticalCornerPattern(weights.ba, coords.xyxz, d);
|
||||
}
|
||||
|
||||
return weights;
|
||||
}
|
||||
|
||||
void main() {
|
||||
fragColor = SMAABlendingWeightCalculationPS(texCoord, pixcoord, vec4(0.0));
|
||||
}
|
31
leenkx/Shaders/smaa_blend_weight/smaa_blend_weight.json
Normal file
31
leenkx/Shaders/smaa_blend_weight/smaa_blend_weight.json
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
"contexts": [
|
||||
{
|
||||
"name": "smaa_blend_weight",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [
|
||||
{
|
||||
"name": "areaTex",
|
||||
"link": "$smaa_area.png"
|
||||
},
|
||||
{
|
||||
"name": "searchTex",
|
||||
"link": "$smaa_search.png"
|
||||
},
|
||||
{
|
||||
"name": "screenSize",
|
||||
"link": "_screenSize"
|
||||
},
|
||||
{
|
||||
"name": "screenSizeInv",
|
||||
"link": "_screenSizeInv"
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "smaa_blend_weight.vert.glsl",
|
||||
"fragment_shader": "smaa_blend_weight.frag.glsl"
|
||||
}
|
||||
]
|
||||
}
|
36
leenkx/Shaders/smaa_blend_weight/smaa_blend_weight.vert.glsl
Normal file
36
leenkx/Shaders/smaa_blend_weight/smaa_blend_weight.vert.glsl
Normal file
@ -0,0 +1,36 @@
|
||||
#version 450
|
||||
|
||||
#include "compiled.inc"
|
||||
|
||||
in vec2 pos;
|
||||
|
||||
uniform vec2 screenSize;
|
||||
uniform vec2 screenSizeInv;
|
||||
|
||||
out vec2 texCoord;
|
||||
out vec2 pixcoord;
|
||||
out vec4 offset0;
|
||||
out vec4 offset1;
|
||||
out vec4 offset2;
|
||||
|
||||
const int SMAA_MAX_SEARCH_STEPS = 16;
|
||||
|
||||
void main() {
|
||||
// Scale vertex attribute to [0-1] range
|
||||
const vec2 madd = vec2(0.5, 0.5);
|
||||
texCoord = pos.xy * madd + madd;
|
||||
|
||||
// Blend Weight Calculation Vertex Shader
|
||||
pixcoord = texCoord * screenSize;
|
||||
|
||||
// We will use these offsets for the searches later on (see @PSEUDO_GATHER4):
|
||||
offset0 = screenSizeInv.xyxy * vec4(-0.25, -0.125, 1.25, -0.125) + texCoord.xyxy;
|
||||
offset1 = screenSizeInv.xyxy * vec4(-0.125, -0.25, -0.125, 1.25) + texCoord.xyxy;
|
||||
|
||||
// And these for the searches, they indicate the ends of the loops:
|
||||
offset2 = screenSizeInv.xxyy *
|
||||
(vec4(-2.0, 2.0, -2.0, 2.0) * float(SMAA_MAX_SEARCH_STEPS)) +
|
||||
vec4(offset0.xz, offset1.yw);
|
||||
|
||||
gl_Position = vec4(pos.xy, 0.0, 1.0);
|
||||
}
|
207
leenkx/Shaders/smaa_edge_detect/smaa_edge_detect.frag.glsl
Normal file
207
leenkx/Shaders/smaa_edge_detect/smaa_edge_detect.frag.glsl
Normal file
@ -0,0 +1,207 @@
|
||||
/**
|
||||
* Copyright (C) 2013 Jorge Jimenez (jorge@iryoku.com)
|
||||
* Copyright (C) 2013 Jose I. Echevarria (joseignacioechevarria@gmail.com)
|
||||
* Copyright (C) 2013 Belen Masia (bmasia@unizar.es)
|
||||
* Copyright (C) 2013 Fernando Navarro (fernandn@microsoft.com)
|
||||
* Copyright (C) 2013 Diego Gutierrez (diegog@unizar.es)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is furnished to
|
||||
* do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software. As clarification, there
|
||||
* is no requirement that the copyright notice and permission be included in
|
||||
* binary distributions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* _______ ___ ___ ___ ___
|
||||
* / || \/ | / \ / \
|
||||
* | (---- | \ / | / ^ \ / ^ \
|
||||
* \ \ | |\/| | / /_\ \ / /_\ \
|
||||
* ----) | | | | | / _____ \ / _____ \
|
||||
* |_______/ |__| |__| /__/ \__\ /__/ \__\
|
||||
*
|
||||
* E N H A N C E D
|
||||
* S U B P I X E L M O R P H O L O G I C A L A N T I A L I A S I N G
|
||||
*
|
||||
* http://www.iryoku.com/smaa/
|
||||
*/
|
||||
#version 450
|
||||
|
||||
#define SMAA_THRESHOLD 0.1
|
||||
#define SMAA_DEPTH_THRESHOLD (0.1 * SMAA_THRESHOLD) // For depth edge detection, depends on the depth range of the scene
|
||||
#define SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR 2.0
|
||||
|
||||
uniform sampler2D colorTex;
|
||||
|
||||
in vec2 texCoord;
|
||||
in vec4 offset0;
|
||||
in vec4 offset1;
|
||||
in vec4 offset2;
|
||||
out vec4 fragColor;
|
||||
|
||||
// Misc functions
|
||||
// Gathers current pixel, and the top-left neighbors.
|
||||
// vec3 SMAAGatherNeighbours(vec2 texcoord/*, vec4 offset[3], sampler2D tex*/) {
|
||||
// float P = textureLod(tex, texcoord, 0.0).r;
|
||||
// float Pleft = textureLod(tex, offset0.xy, 0.0).r;
|
||||
// float Ptop = textureLod(tex, offset0.zw, 0.0).r;
|
||||
// return vec3(P, Pleft, Ptop);
|
||||
// }
|
||||
|
||||
// Edge Detection Pixel Shaders (First Pass)
|
||||
// Adjusts the threshold by means of predication.
|
||||
// vec2 SMAACalculatePredicatedThreshold(vec2 texcoord, vec4 offset[3], sampler2D predicationTex) {
|
||||
// vec3 neighbours = SMAAGatherNeighbours(texcoord, offset, predicationTex);
|
||||
// vec2 delta = abs(neighbours.xx - neighbours.yz);
|
||||
// vec2 edges = step(SMAA_PREDICATION_THRESHOLD, delta);
|
||||
// return SMAA_PREDICATION_SCALE * SMAA_THRESHOLD * (1.0 - SMAA_PREDICATION_STRENGTH * edges);
|
||||
// }
|
||||
|
||||
// Luma Edge Detection
|
||||
// IMPORTANT NOTICE: luma edge detection requires gamma-corrected colors, and
|
||||
// thus 'colorTex' should be a non-sRGB texture.
|
||||
vec2 SMAALumaEdgeDetectionPS(vec2 texcoord
|
||||
//#if SMAA_PREDICATION
|
||||
//, sampler2D predicationTex
|
||||
//#endif
|
||||
) {
|
||||
// Calculate the threshold:
|
||||
//#if SMAA_PREDICATION
|
||||
//vec2 threshold = SMAACalculatePredicatedThreshold(texcoord, offset, SMAATexturePass2D(predicationTex));
|
||||
//#else
|
||||
vec2 threshold = vec2(SMAA_THRESHOLD, SMAA_THRESHOLD);
|
||||
//#endif
|
||||
|
||||
// Calculate lumas:
|
||||
vec3 weights = vec3(0.2126, 0.7152, 0.0722);
|
||||
float L = dot(textureLod(colorTex, texcoord, 0.0).rgb, weights);
|
||||
|
||||
float Lleft = dot(textureLod(colorTex, offset0.xy, 0.0).rgb, weights);
|
||||
float Ltop = dot(textureLod(colorTex, offset0.zw, 0.0).rgb, weights);
|
||||
|
||||
// We do the usual threshold:
|
||||
vec4 delta;
|
||||
delta.xy = abs(L - vec2(Lleft, Ltop));
|
||||
vec2 edges = step(threshold, delta.xy);
|
||||
|
||||
// Then discard if there is no edge:
|
||||
if (dot(edges, vec2(1.0, 1.0)) == 0.0)
|
||||
discard;
|
||||
|
||||
// Calculate right and bottom deltas:
|
||||
float Lright = dot(textureLod(colorTex, offset1.xy, 0.0).rgb, weights);
|
||||
float Lbottom = dot(textureLod(colorTex, offset1.zw, 0.0).rgb, weights);
|
||||
delta.zw = abs(L - vec2(Lright, Lbottom));
|
||||
|
||||
// Calculate the maximum delta in the direct neighborhood:
|
||||
vec2 maxDelta = max(delta.xy, delta.zw);
|
||||
|
||||
// Calculate left-left and top-top deltas:
|
||||
float Lleftleft = dot(textureLod(colorTex, offset2.xy, 0.0).rgb, weights);
|
||||
float Ltoptop = dot(textureLod(colorTex, offset2.zw, 0.0).rgb, weights);
|
||||
delta.zw = abs(vec2(Lleft, Ltop) - vec2(Lleftleft, Ltoptop));
|
||||
|
||||
// Calculate the final maximum delta:
|
||||
maxDelta = max(maxDelta.xy, delta.zw);
|
||||
float finalDelta = max(maxDelta.x, maxDelta.y);
|
||||
|
||||
// Local contrast adaptation:
|
||||
edges.xy *= step(finalDelta, SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR * delta.xy);
|
||||
|
||||
return edges;
|
||||
}
|
||||
|
||||
// Color Edge Detection
|
||||
// IMPORTANT NOTICE: color edge detection requires gamma-corrected colors, and
|
||||
// thus 'colorTex' should be a non-sRGB texture.
|
||||
vec2 SMAAColorEdgeDetectionPS(vec2 texcoord
|
||||
//#if SMAA_PREDICATION
|
||||
//, sampler2D predicationTex
|
||||
//#endif
|
||||
) {
|
||||
// Calculate the threshold:
|
||||
//#if SMAA_PREDICATION
|
||||
//vec2 threshold = SMAACalculatePredicatedThreshold(texcoord, offset, predicationTex);
|
||||
//#else
|
||||
vec2 threshold = vec2(SMAA_THRESHOLD, SMAA_THRESHOLD);
|
||||
//#endif
|
||||
|
||||
// Calculate color deltas:
|
||||
vec4 delta;
|
||||
vec3 C = textureLod(colorTex, texcoord, 0.0).rgb;
|
||||
|
||||
vec3 Cleft = textureLod(colorTex, offset0.xy, 0.0).rgb;
|
||||
vec3 t = abs(C - Cleft);
|
||||
delta.x = max(max(t.r, t.g), t.b);
|
||||
|
||||
vec3 Ctop = textureLod(colorTex, offset0.zw, 0.0).rgb;
|
||||
t = abs(C - Ctop);
|
||||
delta.y = max(max(t.r, t.g), t.b);
|
||||
|
||||
// We do the usual threshold:
|
||||
vec2 edges = step(threshold, delta.xy);
|
||||
|
||||
// Then discard if there is no edge:
|
||||
if (dot(edges, vec2(1.0, 1.0)) == 0.0)
|
||||
discard;
|
||||
|
||||
// Calculate right and bottom deltas:
|
||||
vec3 Cright = textureLod(colorTex, offset1.xy, 0.0).rgb;
|
||||
t = abs(C - Cright);
|
||||
delta.z = max(max(t.r, t.g), t.b);
|
||||
|
||||
vec3 Cbottom = textureLod(colorTex, offset1.zw, 0.0).rgb;
|
||||
t = abs(C - Cbottom);
|
||||
delta.w = max(max(t.r, t.g), t.b);
|
||||
|
||||
// Calculate the maximum delta in the direct neighborhood:
|
||||
vec2 maxDelta = max(delta.xy, delta.zw);
|
||||
|
||||
// Calculate left-left and top-top deltas:
|
||||
vec3 Cleftleft = textureLod(colorTex, offset2.xy, 0.0).rgb;
|
||||
t = abs(C - Cleftleft);
|
||||
delta.z = max(max(t.r, t.g), t.b);
|
||||
|
||||
vec3 Ctoptop = textureLod(colorTex, offset2.zw, 0.0).rgb;
|
||||
t = abs(C - Ctoptop);
|
||||
delta.w = max(max(t.r, t.g), t.b);
|
||||
|
||||
// Calculate the final maximum delta:
|
||||
maxDelta = max(maxDelta.xy, delta.zw);
|
||||
float finalDelta = max(maxDelta.x, maxDelta.y);
|
||||
|
||||
// Local contrast adaptation:
|
||||
edges.xy *= step(finalDelta, SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR * delta.xy);
|
||||
|
||||
return edges;
|
||||
}
|
||||
|
||||
// Depth Edge Detection
|
||||
// vec2 SMAADepthEdgeDetectionPS(vec2 texcoord, /*vec4 offset[3],*/ sampler2D depthTex) {
|
||||
// vec3 neighbours = SMAAGatherNeighbours(texcoord, /*offset,*/ depthTex);
|
||||
// vec2 delta = abs(neighbours.xx - vec2(neighbours.y, neighbours.z));
|
||||
// vec2 edges = step(SMAA_DEPTH_THRESHOLD, delta);
|
||||
|
||||
// if (dot(edges, vec2(1.0, 1.0)) == 0.0)
|
||||
// discard;
|
||||
|
||||
// return edges;
|
||||
// }
|
||||
|
||||
void main() {
|
||||
fragColor.rg = SMAAColorEdgeDetectionPS(texCoord);
|
||||
}
|
19
leenkx/Shaders/smaa_edge_detect/smaa_edge_detect.json
Normal file
19
leenkx/Shaders/smaa_edge_detect/smaa_edge_detect.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"contexts": [
|
||||
{
|
||||
"name": "smaa_edge_detect",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [
|
||||
{
|
||||
"name": "screenSizeInv",
|
||||
"link": "_screenSizeInv"
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "smaa_edge_detect.vert.glsl",
|
||||
"fragment_shader": "smaa_edge_detect.frag.glsl"
|
||||
}
|
||||
]
|
||||
}
|
33
leenkx/Shaders/smaa_edge_detect/smaa_edge_detect.vert.glsl
Normal file
33
leenkx/Shaders/smaa_edge_detect/smaa_edge_detect.vert.glsl
Normal file
@ -0,0 +1,33 @@
|
||||
#version 450
|
||||
|
||||
#include "compiled.inc"
|
||||
|
||||
in vec2 pos;
|
||||
|
||||
uniform vec2 screenSizeInv;
|
||||
|
||||
out vec2 texCoord;
|
||||
out vec4 offset0;
|
||||
out vec4 offset1;
|
||||
out vec4 offset2;
|
||||
|
||||
#ifdef _InvY
|
||||
#define V_DIR(v) -(v)
|
||||
#else
|
||||
#define V_DIR(v) v
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
// Scale vertex attribute to [0-1] range
|
||||
const vec2 madd = vec2(0.5, 0.5);
|
||||
texCoord = pos.xy * madd + madd;
|
||||
#ifdef _InvY
|
||||
texCoord.y = 1.0 - texCoord.y;
|
||||
#endif
|
||||
|
||||
offset0 = screenSizeInv.xyxy * vec4(-1.0, 0.0, 0.0, V_DIR(-1.0)) + texCoord.xyxy;
|
||||
offset1 = screenSizeInv.xyxy * vec4( 1.0, 0.0, 0.0, V_DIR(1.0)) + texCoord.xyxy;
|
||||
offset2 = screenSizeInv.xyxy * vec4(-2.0, 0.0, 0.0, V_DIR(-2.0)) + texCoord.xyxy;
|
||||
|
||||
gl_Position = vec4(pos.xy, 0.0, 1.0);
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
#version 450
|
||||
|
||||
#include "compiled.inc"
|
||||
|
||||
uniform sampler2D colorTex;
|
||||
uniform sampler2D blendTex;
|
||||
#ifdef _Veloc
|
||||
uniform sampler2D sveloc;
|
||||
#endif
|
||||
|
||||
uniform vec2 screenSizeInv;
|
||||
|
||||
in vec2 texCoord;
|
||||
in vec4 offset;
|
||||
out vec4 fragColor;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Neighborhood Blending Pixel Shader (Third Pass)
|
||||
|
||||
vec4 textureLodA(sampler2D tex, vec2 coords, float lod) {
|
||||
#ifdef _InvY
|
||||
coords.y = 1.0 - coords.y;
|
||||
#endif
|
||||
return textureLod(tex, coords, lod);
|
||||
}
|
||||
|
||||
vec4 SMAANeighborhoodBlendingPS(vec2 texcoord, vec4 offset) {
|
||||
// Fetch the blending weights for current pixel:
|
||||
vec4 a;
|
||||
a.x = textureLod(blendTex, offset.xy, 0.0).a; // Right
|
||||
a.y = textureLod(blendTex, offset.zw, 0.0).g; // Top
|
||||
a.wz = textureLod(blendTex, texcoord, 0.0).xz; // Bottom / Left
|
||||
|
||||
// Is there any blending weight with a value greater than 0.0?
|
||||
//SMAA_BRANCH
|
||||
if (dot(a, vec4(1.0, 1.0, 1.0, 1.0)) < 1e-5) {
|
||||
vec4 color = textureLod(colorTex, texcoord, 0.0);
|
||||
|
||||
#ifdef _Veloc
|
||||
vec2 velocity = textureLod(sveloc, texCoord, 0.0).rg;
|
||||
// Pack velocity into the alpha channel:
|
||||
color.a = sqrt(5.0 * length(velocity));
|
||||
#endif
|
||||
return color;
|
||||
}
|
||||
else {
|
||||
bool h = max(a.x, a.z) > max(a.y, a.w); // max(horizontal) > max(vertical)
|
||||
|
||||
// Calculate the blending offsets:
|
||||
vec4 blendingOffset = vec4(0.0, a.y, 0.0, a.w);
|
||||
vec2 blendingWeight = a.yw;
|
||||
|
||||
if (h) {
|
||||
blendingOffset.x = a.x;
|
||||
blendingOffset.y = 0.0;
|
||||
blendingOffset.z = a.z;
|
||||
blendingOffset.w = 0.0;
|
||||
blendingWeight.x = a.x;
|
||||
blendingWeight.y = a.z;
|
||||
}
|
||||
|
||||
blendingWeight /= dot(blendingWeight, vec2(1.0, 1.0));
|
||||
|
||||
// Calculate the texture coordinates:
|
||||
#ifdef _InvY
|
||||
vec2 tc = vec2(texcoord.x, 1.0 - texcoord.y);
|
||||
#else
|
||||
vec2 tc = texcoord;
|
||||
#endif
|
||||
vec4 blendingCoord = blendingOffset * vec4(screenSizeInv.xy, -screenSizeInv.xy) + tc.xyxy;
|
||||
|
||||
// We exploit bilinear filtering to mix current pixel with the chosen
|
||||
// neighbor:
|
||||
vec4 color = blendingWeight.x * textureLodA(colorTex, blendingCoord.xy, 0.0);
|
||||
color += blendingWeight.y * textureLodA(colorTex, blendingCoord.zw, 0.0);
|
||||
|
||||
#ifdef _Veloc
|
||||
// Antialias velocity for proper reprojection in a later stage:
|
||||
vec2 velocity = blendingWeight.x * textureLodA(sveloc, blendingCoord.xy, 0.0).rg;
|
||||
velocity += blendingWeight.y * textureLodA(sveloc, blendingCoord.zw, 0.0).rg;
|
||||
|
||||
// Pack velocity into the alpha channel:
|
||||
color.a = sqrt(5.0 * length(velocity));
|
||||
#endif
|
||||
return color;
|
||||
}
|
||||
return vec4(0.0);
|
||||
}
|
||||
|
||||
void main() {
|
||||
fragColor = SMAANeighborhoodBlendingPS(texCoord, offset);
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
{
|
||||
"contexts": [
|
||||
{
|
||||
"name": "smaa_neighborhood_blend",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [
|
||||
{
|
||||
"name": "screenSizeInv",
|
||||
"link": "_screenSizeInv"
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "smaa_neighborhood_blend.vert.glsl",
|
||||
"fragment_shader": "smaa_neighborhood_blend.frag.glsl"
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
#version 450
|
||||
|
||||
#include "compiled.inc"
|
||||
|
||||
in vec2 pos;
|
||||
|
||||
uniform vec2 screenSizeInv;
|
||||
|
||||
out vec2 texCoord;
|
||||
out vec4 offset;
|
||||
|
||||
#ifdef _InvY
|
||||
#define V_DIR(v) -(v)
|
||||
#else
|
||||
#define V_DIR(v) v
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
// Scale vertex attribute to [0-1] range
|
||||
const vec2 madd = vec2(0.5, 0.5);
|
||||
texCoord = pos.xy * madd + madd;
|
||||
#ifdef _InvY
|
||||
texCoord.y = 1.0 - texCoord.y;
|
||||
#endif
|
||||
|
||||
// Neighborhood Blending Vertex Shader
|
||||
offset = screenSizeInv.xyxy * vec4(1.0, 0.0, 0.0, V_DIR(1.0)) + texCoord.xyxy;
|
||||
gl_Position = vec4(pos.xy, 0.0, 1.0);
|
||||
}
|
64
leenkx/Shaders/ssao_pass/ssao_pass.frag.glsl
Normal file
64
leenkx/Shaders/ssao_pass/ssao_pass.frag.glsl
Normal file
@ -0,0 +1,64 @@
|
||||
// Alchemy AO / Scalable Ambient Obscurance
|
||||
#version 450
|
||||
|
||||
#include "compiled.inc"
|
||||
#include "std/gbuffer.glsl"
|
||||
|
||||
uniform sampler2D gbufferD;
|
||||
uniform sampler2D gbuffer0;
|
||||
uniform vec2 cameraProj;
|
||||
uniform vec3 eye;
|
||||
uniform vec3 eyeLook;
|
||||
uniform vec2 screenSize;
|
||||
uniform mat4 invVP;
|
||||
|
||||
#ifdef _CPostprocess
|
||||
uniform vec3 PPComp12;
|
||||
#endif
|
||||
|
||||
in vec2 texCoord;
|
||||
in vec3 viewRay;
|
||||
out float fragColor;
|
||||
|
||||
void main() {
|
||||
float depth = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0;
|
||||
if (depth == 1.0) { fragColor = 1.0; return; }
|
||||
|
||||
vec2 enc = textureLod(gbuffer0, texCoord, 0.0).rg;
|
||||
vec3 n;
|
||||
n.z = 1.0 - abs(enc.x) - abs(enc.y);
|
||||
n.xy = n.z >= 0.0 ? enc.xy : octahedronWrap(enc.xy);
|
||||
n = normalize(n);
|
||||
|
||||
vec3 vray = normalize(viewRay);
|
||||
vec3 currentPos = getPosNoEye(eyeLook, vray, depth, cameraProj);
|
||||
// vec3 currentPos = getPos2NoEye(eye, invVP, depth, texCoord);
|
||||
float currentDistance = length(currentPos);
|
||||
#ifdef _CPostprocess
|
||||
float currentDistanceA = currentDistance * PPComp12.z * (1.0 / PPComp12.y);
|
||||
#else
|
||||
float currentDistanceA = currentDistance * ssaoScale * (1.0 / ssaoRadius);
|
||||
#endif
|
||||
float currentDistanceB = currentDistance * 0.0005;
|
||||
ivec2 px = ivec2(texCoord * screenSize);
|
||||
float phi = (3 * px.x ^ px.y + px.x * px.y) * 10;
|
||||
|
||||
fragColor = 0;
|
||||
const int samples = 8;
|
||||
const float samplesInv = PI2 * (1.0 / samples);
|
||||
for (int i = 0; i < samples; ++i) {
|
||||
float theta = samplesInv * (i + 0.5) + phi;
|
||||
vec2 k = vec2(cos(theta), sin(theta)) / currentDistanceA;
|
||||
depth = textureLod(gbufferD, texCoord + k, 0.0).r * 2.0 - 1.0;
|
||||
// vec3 pos = getPosNoEye(eyeLook, vray, depth, cameraProj) - currentPos;
|
||||
vec3 pos = getPos2NoEye(eye, invVP, depth, texCoord + k) - currentPos;
|
||||
fragColor += max(0, dot(pos, n) - currentDistanceB) / (dot(pos, pos) + 0.015);
|
||||
}
|
||||
|
||||
#ifdef _CPostprocess
|
||||
fragColor *= (PPComp12.x * 0.3) / samples;
|
||||
#else
|
||||
fragColor *= (ssaoStrength * 0.3) / samples;
|
||||
#endif
|
||||
fragColor = 1.0 - fragColor;
|
||||
}
|
40
leenkx/Shaders/ssao_pass/ssao_pass.json
Normal file
40
leenkx/Shaders/ssao_pass/ssao_pass.json
Normal file
@ -0,0 +1,40 @@
|
||||
{
|
||||
"contexts": [
|
||||
{
|
||||
"name": "ssao_pass",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [
|
||||
{
|
||||
"name": "invVP",
|
||||
"link": "_inverseViewProjectionMatrix"
|
||||
},
|
||||
{
|
||||
"name": "eye",
|
||||
"link": "_cameraPosition"
|
||||
},
|
||||
{
|
||||
"name": "eyeLook",
|
||||
"link": "_cameraLook"
|
||||
},
|
||||
{
|
||||
"name": "cameraProj",
|
||||
"link": "_cameraPlaneProj"
|
||||
},
|
||||
{
|
||||
"name": "screenSize",
|
||||
"link": "_screenSize"
|
||||
},
|
||||
{
|
||||
"name": "PPComp12",
|
||||
"link": "_PPComp12",
|
||||
"ifdef": ["_CPostprocess"]
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass_viewray.vert.glsl",
|
||||
"fragment_shader": "ssao_pass.frag.glsl"
|
||||
}
|
||||
]
|
||||
}
|
61
leenkx/Shaders/ssao_pass/ssgi_pass_.frag.glsl
Normal file
61
leenkx/Shaders/ssao_pass/ssgi_pass_.frag.glsl
Normal file
@ -0,0 +1,61 @@
|
||||
// Alchemy AO / Scalable Ambient Obscurance
|
||||
#version 450
|
||||
|
||||
#include "compiled.inc"
|
||||
#include "std/gbuffer.glsl"
|
||||
|
||||
uniform sampler2D gbufferD;
|
||||
uniform sampler2D gbuffer0;
|
||||
uniform vec2 cameraProj;
|
||||
uniform vec3 eye;
|
||||
uniform vec3 eyeLook;
|
||||
uniform vec2 screenSize;
|
||||
uniform mat4 invVP;
|
||||
|
||||
in vec2 texCoord;
|
||||
in vec3 viewRay;
|
||||
out float fragColor;
|
||||
|
||||
void main() {
|
||||
float depth = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0;
|
||||
if (depth == 1.0) { fragColor = 1.0; return; }
|
||||
|
||||
vec2 enc = textureLod(gbuffer0, texCoord, 0.0).rg;
|
||||
vec3 n;
|
||||
n.z = 1.0 - abs(enc.x) - abs(enc.y);
|
||||
n.xy = n.z >= 0.0 ? enc.xy : octahedronWrap(enc.xy);
|
||||
n = normalize(n);
|
||||
|
||||
vec3 vray = normalize(viewRay);
|
||||
vec3 currentPos = getPosNoEye(eyeLook, vray, depth, cameraProj);
|
||||
// vec3 currentPos = getPos2NoEye(eye, invVP, depth, texCoord);
|
||||
float currentDistance = length(currentPos);
|
||||
float currentDistanceA = currentDistance * ssaoScale * (1.0 / ssaoRadius);
|
||||
float currentDistanceB = currentDistance * 0.0005;
|
||||
float currentDistanceC = currentDistance * 5.0;
|
||||
ivec2 px = ivec2(texCoord * screenSize);
|
||||
float phi = (3 * px.x ^ px.y + px.x * px.y) * 10;
|
||||
|
||||
fragColor = 0;
|
||||
const int samples = 8;
|
||||
const float samplesInv = PI2 * (1.0 / samples);
|
||||
for (int i = 0; i < samples; ++i) {
|
||||
float theta = samplesInv * (i + 0.5) + phi;
|
||||
vec2 k = vec2(cos(theta), sin(theta)) / currentDistanceA;
|
||||
depth = textureLod(gbufferD, texCoord + k, 0.0).r * 2.0 - 1.0;
|
||||
// vec3 pos = getPosNoEye(eyeLook, vray, depth, cameraProj) - currentPos;
|
||||
vec3 pos = getPos2NoEye(eye, invVP, depth, texCoord + k) - currentPos;
|
||||
fragColor += (max(0, dot(pos, n) - currentDistanceB) / (dot(pos, pos) + 0.015));
|
||||
}
|
||||
|
||||
for (int i = 0; i < samples; ++i) {
|
||||
float theta = samplesInv * (i + 0.5) + phi;
|
||||
vec2 k = vec2(cos(theta), sin(theta)) / currentDistanceC;
|
||||
depth = textureLod(gbufferD, texCoord + k, 0.0).r * 2.0 - 1.0;
|
||||
vec3 pos = getPos2NoEye(eye, invVP, depth, texCoord + k) - currentPos;
|
||||
fragColor += (max(0, dot(pos, n) - currentDistanceB) / (dot(pos, pos) + 0.015));
|
||||
}
|
||||
|
||||
fragColor *= (ssaoStrength * 0.4) / samples;
|
||||
fragColor = 1.0 - fragColor;
|
||||
}
|
35
leenkx/Shaders/ssao_pass/ssgi_pass_.json
Normal file
35
leenkx/Shaders/ssao_pass/ssgi_pass_.json
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"contexts": [
|
||||
{
|
||||
"name": "ssgi_pass",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [
|
||||
{
|
||||
"name": "invVP",
|
||||
"link": "_inverseViewProjectionMatrix"
|
||||
},
|
||||
{
|
||||
"name": "eye",
|
||||
"link": "_cameraPosition"
|
||||
},
|
||||
{
|
||||
"name": "eyeLook",
|
||||
"link": "_cameraLook"
|
||||
},
|
||||
{
|
||||
"name": "cameraProj",
|
||||
"link": "_cameraPlaneProj"
|
||||
},
|
||||
{
|
||||
"name": "screenSize",
|
||||
"link": "_screenSize"
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass_viewray.vert.glsl",
|
||||
"fragment_shader": "ssgi_pass.frag.glsl"
|
||||
}
|
||||
]
|
||||
}
|
46
leenkx/Shaders/ssgi_blur_pass/ssgi_blur_pass.frag.glsl
Normal file
46
leenkx/Shaders/ssgi_blur_pass/ssgi_blur_pass.frag.glsl
Normal file
@ -0,0 +1,46 @@
|
||||
#version 450
|
||||
|
||||
#include "compiled.inc"
|
||||
#include "std/gbuffer.glsl"
|
||||
|
||||
uniform sampler2D tex;
|
||||
uniform sampler2D gbuffer0;
|
||||
|
||||
uniform vec2 dirInv; // texStep
|
||||
|
||||
in vec2 texCoord;
|
||||
out float fragColor;
|
||||
|
||||
const float blurWeights[5] = float[] (0.227027, 0.1945946, 0.1216216, 0.054054, 0.016216);
|
||||
// const float blurWeights[10] = float[] (0.132572, 0.125472, 0.106373, 0.08078, 0.05495, 0.033482, 0.018275, 0.008934, 0.003912, 0.001535);
|
||||
const float discardThreshold = 0.95;
|
||||
|
||||
float doBlur(const float blurWeight, const int pos, const vec3 nor, const vec2 texCoord) {
|
||||
const float posadd = pos + 0.5;
|
||||
|
||||
vec3 nor2 = getNor(textureLod(gbuffer0, texCoord + pos * dirInv, 0.0).rg);
|
||||
float influenceFactor = step(discardThreshold, dot(nor2, nor));
|
||||
float col = textureLod(tex, texCoord + posadd * dirInv, 0.0).r;
|
||||
fragColor += col * blurWeight * influenceFactor;
|
||||
float weight = blurWeight * influenceFactor;
|
||||
|
||||
nor2 = getNor(textureLod(gbuffer0, texCoord - pos * dirInv, 0.0).rg);
|
||||
influenceFactor = step(discardThreshold, dot(nor2, nor));
|
||||
col = textureLod(tex, texCoord - posadd * dirInv, 0.0).r;
|
||||
fragColor += col * blurWeight * influenceFactor;
|
||||
weight += blurWeight * influenceFactor;
|
||||
|
||||
return weight;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec3 nor = getNor(textureLod(gbuffer0, texCoord, 0.0).rg);
|
||||
|
||||
fragColor = textureLod(tex, texCoord, 0.0).r * blurWeights[0];
|
||||
float weight = blurWeights[0];
|
||||
for (int i = 1; i < 5; i++) {
|
||||
weight += doBlur(blurWeights[i], i, nor, texCoord);
|
||||
}
|
||||
|
||||
fragColor = fragColor / weight;
|
||||
}
|
74
leenkx/Shaders/ssgi_blur_pass/ssgi_blur_pass.json
Normal file
74
leenkx/Shaders/ssgi_blur_pass/ssgi_blur_pass.json
Normal file
@ -0,0 +1,74 @@
|
||||
{
|
||||
"contexts": [
|
||||
{
|
||||
"name": "ssgi_blur_pass_x",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [
|
||||
{
|
||||
"name": "dirInv",
|
||||
"link": "_vec2xInv"
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass.vert.glsl",
|
||||
"fragment_shader": "ssgi_blur_pass.frag.glsl"
|
||||
},
|
||||
{
|
||||
"name": "ssgi_blur_pass_y",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [
|
||||
{
|
||||
"name": "dirInv",
|
||||
"link": "_vec2yInv"
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass.vert.glsl",
|
||||
"fragment_shader": "ssgi_blur_pass.frag.glsl"
|
||||
},
|
||||
{
|
||||
"name": "ssgi_blur_pass_y_blend",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"blend_source": "destination_color",
|
||||
"blend_destination": "blend_zero",
|
||||
"blend_operation": "add",
|
||||
"links": [
|
||||
{
|
||||
"name": "dirInv",
|
||||
"link": "_vec2yInv"
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass.vert.glsl",
|
||||
"fragment_shader": "ssgi_blur_pass.frag.glsl"
|
||||
},
|
||||
|
||||
{
|
||||
"name": "ssgi_blur_pass_y_blend_add",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"blend_source": "blend_one",
|
||||
"blend_destination": "blend_one",
|
||||
"blend_operation": "add",
|
||||
"alpha_blend_source": "blend_one",
|
||||
"alpha_blend_destination": "blend_one",
|
||||
"alpha_blend_operation": "add",
|
||||
"links": [
|
||||
{
|
||||
"name": "dirInv",
|
||||
"link": "_vec2yInv"
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass.vert.glsl",
|
||||
"fragment_shader": "ssgi_blur_pass.frag.glsl"
|
||||
}
|
||||
]
|
||||
}
|
107
leenkx/Shaders/ssgi_pass/ssgi_pass.frag.glsl
Normal file
107
leenkx/Shaders/ssgi_pass/ssgi_pass.frag.glsl
Normal file
@ -0,0 +1,107 @@
|
||||
#version 450
|
||||
|
||||
#include "compiled.inc"
|
||||
#include "std/math.glsl"
|
||||
#include "std/gbuffer.glsl"
|
||||
|
||||
uniform sampler2D gbufferD;
|
||||
uniform sampler2D gbuffer0; // Normal
|
||||
// #ifdef _RTGI
|
||||
// uniform sampler2D gbuffer1; // Basecol
|
||||
// #endif
|
||||
uniform mat4 P;
|
||||
uniform mat3 V3;
|
||||
|
||||
uniform vec2 cameraProj;
|
||||
|
||||
const float angleMix = 0.5f;
|
||||
#ifdef _SSGICone9
|
||||
const float strength = 2.0 * (1.0 / ssgiStrength);
|
||||
#else
|
||||
const float strength = 2.0 * (1.0 / ssgiStrength) * 1.8;
|
||||
#endif
|
||||
|
||||
in vec3 viewRay;
|
||||
in vec2 texCoord;
|
||||
out float fragColor;
|
||||
|
||||
vec3 hitCoord;
|
||||
vec2 coord;
|
||||
float depth;
|
||||
// #ifdef _RTGI
|
||||
// vec3 col = vec3(0.0);
|
||||
// #endif
|
||||
vec3 vpos;
|
||||
|
||||
vec2 getProjectedCoord(vec3 hitCoord) {
|
||||
vec4 projectedCoord = P * vec4(hitCoord, 1.0);
|
||||
projectedCoord.xy /= projectedCoord.w;
|
||||
projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5;
|
||||
#ifdef _InvY
|
||||
projectedCoord.y = 1.0 - projectedCoord.y;
|
||||
#endif
|
||||
return projectedCoord.xy;
|
||||
}
|
||||
|
||||
float getDeltaDepth(vec3 hitCoord) {
|
||||
coord = getProjectedCoord(hitCoord);
|
||||
depth = textureLod(gbufferD, coord, 0.0).r * 2.0 - 1.0;
|
||||
vec3 p = getPosView(viewRay, depth, cameraProj);
|
||||
return p.z - hitCoord.z;
|
||||
}
|
||||
|
||||
void rayCast(vec3 dir) {
|
||||
hitCoord = vpos;
|
||||
dir *= ssgiRayStep * 2;
|
||||
float dist = 0.15;
|
||||
for (int i = 0; i < ssgiMaxSteps; i++) {
|
||||
hitCoord += dir;
|
||||
float delta = getDeltaDepth(hitCoord);
|
||||
if (delta > 0.0 && delta < 0.2) {
|
||||
dist = distance(vpos, hitCoord);
|
||||
break;
|
||||
}
|
||||
}
|
||||
fragColor += dist;
|
||||
// #ifdef _RTGI
|
||||
// col += textureLod(gbuffer1, coord, 0.0).rgb * ((ssgiRayStep * ssgiMaxSteps) - dist);
|
||||
// #endif
|
||||
}
|
||||
|
||||
vec3 tangent(const vec3 n) {
|
||||
vec3 t1 = cross(n, vec3(0, 0, 1));
|
||||
vec3 t2 = cross(n, vec3(0, 1, 0));
|
||||
if (length(t1) > length(t2)) return normalize(t1);
|
||||
else return normalize(t2);
|
||||
}
|
||||
|
||||
void main() {
|
||||
fragColor = 0;
|
||||
vec4 g0 = textureLod(gbuffer0, texCoord, 0.0);
|
||||
float d = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0;
|
||||
|
||||
vec2 enc = g0.rg;
|
||||
vec3 n;
|
||||
n.z = 1.0 - abs(enc.x) - abs(enc.y);
|
||||
n.xy = n.z >= 0.0 ? enc.xy : octahedronWrap(enc.xy);
|
||||
n = normalize(V3 * n);
|
||||
|
||||
vpos = getPosView(viewRay, d, cameraProj);
|
||||
|
||||
rayCast(n);
|
||||
vec3 o1 = normalize(tangent(n));
|
||||
vec3 o2 = (cross(o1, n));
|
||||
vec3 c1 = 0.5f * (o1 + o2);
|
||||
vec3 c2 = 0.5f * (o1 - o2);
|
||||
rayCast(mix(n, o1, angleMix));
|
||||
rayCast(mix(n, o2, angleMix));
|
||||
rayCast(mix(n, -c1, angleMix));
|
||||
rayCast(mix(n, -c2, angleMix));
|
||||
|
||||
#ifdef _SSGICone9
|
||||
rayCast(mix(n, -o1, angleMix));
|
||||
rayCast(mix(n, -o2, angleMix));
|
||||
rayCast(mix(n, c1, angleMix));
|
||||
rayCast(mix(n, c2, angleMix));
|
||||
#endif
|
||||
}
|
31
leenkx/Shaders/ssgi_pass/ssgi_pass.json
Normal file
31
leenkx/Shaders/ssgi_pass/ssgi_pass.json
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
"contexts": [
|
||||
{
|
||||
"name": "ssgi_pass",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [
|
||||
{
|
||||
"name": "P",
|
||||
"link": "_projectionMatrix"
|
||||
},
|
||||
{
|
||||
"name": "V3",
|
||||
"link": "_viewMatrix3"
|
||||
},
|
||||
{
|
||||
"name": "invP",
|
||||
"link": "_inverseProjectionMatrix"
|
||||
},
|
||||
{
|
||||
"name": "cameraProj",
|
||||
"link": "_cameraPlaneProj"
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass_viewray2.vert.glsl",
|
||||
"fragment_shader": "ssgi_pass.frag.glsl"
|
||||
}
|
||||
]
|
||||
}
|
121
leenkx/Shaders/ssr_pass/ssr_pass.frag.glsl
Normal file
121
leenkx/Shaders/ssr_pass/ssr_pass.frag.glsl
Normal file
@ -0,0 +1,121 @@
|
||||
#version 450
|
||||
|
||||
#include "compiled.inc"
|
||||
#include "std/math.glsl"
|
||||
#include "std/gbuffer.glsl"
|
||||
|
||||
uniform sampler2D tex;
|
||||
uniform sampler2D gbufferD;
|
||||
uniform sampler2D gbuffer0; // Normal, roughness
|
||||
uniform sampler2D gbuffer1; // basecol, spec
|
||||
uniform mat4 P;
|
||||
uniform mat3 V3;
|
||||
uniform vec2 cameraProj;
|
||||
|
||||
#ifdef _CPostprocess
|
||||
uniform vec3 PPComp9;
|
||||
uniform vec3 PPComp10;
|
||||
#endif
|
||||
|
||||
in vec3 viewRay;
|
||||
in vec2 texCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
vec3 hitCoord;
|
||||
float depth;
|
||||
|
||||
const int numBinarySearchSteps = 7;
|
||||
const int maxSteps = int(ceil(1.0 / ssrRayStep) * ssrSearchDist);
|
||||
|
||||
vec2 getProjectedCoord(const vec3 hit) {
|
||||
vec4 projectedCoord = P * vec4(hit, 1.0);
|
||||
projectedCoord.xy /= projectedCoord.w;
|
||||
projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5;
|
||||
#ifdef _InvY
|
||||
projectedCoord.y = 1.0 - projectedCoord.y;
|
||||
#endif
|
||||
return projectedCoord.xy;
|
||||
}
|
||||
|
||||
float getDeltaDepth(const vec3 hit) {
|
||||
depth = textureLod(gbufferD, getProjectedCoord(hit), 0.0).r * 2.0 - 1.0;
|
||||
vec3 viewPos = getPosView(viewRay, depth, cameraProj);
|
||||
return viewPos.z - hit.z;
|
||||
}
|
||||
|
||||
vec4 binarySearch(vec3 dir) {
|
||||
float ddepth;
|
||||
for (int i = 0; i < numBinarySearchSteps; i++) {
|
||||
dir *= 0.5;
|
||||
hitCoord -= dir;
|
||||
ddepth = getDeltaDepth(hitCoord);
|
||||
if (ddepth < 0.0) hitCoord += dir;
|
||||
}
|
||||
// Ugly discard of hits too far away
|
||||
#ifdef _CPostprocess
|
||||
if (abs(ddepth) > PPComp9.z / 500) return vec4(0.0);
|
||||
#else
|
||||
if (abs(ddepth) > ssrSearchDist / 500) return vec4(0.0);
|
||||
#endif
|
||||
return vec4(getProjectedCoord(hitCoord), 0.0, 1.0);
|
||||
}
|
||||
|
||||
vec4 rayCast(vec3 dir) {
|
||||
#ifdef _CPostprocess
|
||||
dir *= PPComp9.x;
|
||||
#else
|
||||
dir *= ssrRayStep;
|
||||
#endif
|
||||
for (int i = 0; i < maxSteps; i++) {
|
||||
hitCoord += dir;
|
||||
if (getDeltaDepth(hitCoord) > 0.0) return binarySearch(dir);
|
||||
}
|
||||
return vec4(0.0);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec4 g0 = textureLod(gbuffer0, texCoord, 0.0);
|
||||
float roughness = unpackFloat(g0.b).y;
|
||||
if (roughness == 1.0) { fragColor.rgb = vec3(0.0); return; }
|
||||
|
||||
float spec = fract(textureLod(gbuffer1, texCoord, 0.0).a);
|
||||
if (spec == 0.0) { fragColor.rgb = vec3(0.0); return; }
|
||||
|
||||
float d = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0;
|
||||
if (d == 1.0) { fragColor.rgb = vec3(0.0); return; }
|
||||
|
||||
vec2 enc = g0.rg;
|
||||
vec3 n;
|
||||
n.z = 1.0 - abs(enc.x) - abs(enc.y);
|
||||
n.xy = n.z >= 0.0 ? enc.xy : octahedronWrap(enc.xy);
|
||||
n = normalize(n);
|
||||
|
||||
vec3 viewNormal = V3 * n;
|
||||
vec3 viewPos = getPosView(viewRay, d, cameraProj);
|
||||
vec3 reflected = reflect(viewPos, viewNormal);
|
||||
hitCoord = viewPos;
|
||||
|
||||
#ifdef _CPostprocess
|
||||
vec3 dir = reflected * (1.0 - rand(texCoord) * PPComp10.y * roughness) * 2.0;
|
||||
#else
|
||||
vec3 dir = reflected * (1.0 - rand(texCoord) * ssrJitter * roughness) * 2.0;
|
||||
#endif
|
||||
|
||||
// * max(ssrMinRayStep, -viewPos.z)
|
||||
vec4 coords = rayCast(dir);
|
||||
|
||||
vec2 deltaCoords = abs(vec2(0.5, 0.5) - coords.xy);
|
||||
float screenEdgeFactor = clamp(1.0 - (deltaCoords.x + deltaCoords.y), 0.0, 1.0);
|
||||
|
||||
float reflectivity = 1.0 - roughness;
|
||||
#ifdef _CPostprocess
|
||||
float intensity = pow(reflectivity, PPComp10.x) * screenEdgeFactor * clamp(-reflected.z, 0.0, 1.0) * clamp((PPComp9.z - length(viewPos - hitCoord)) * (1.0 / PPComp9.z), 0.0, 1.0) * coords.w;
|
||||
#else
|
||||
float intensity = pow(reflectivity, ssrFalloffExp) * screenEdgeFactor * clamp(-reflected.z, 0.0, 1.0) * clamp((ssrSearchDist - length(viewPos - hitCoord)) * (1.0 / ssrSearchDist), 0.0, 1.0) * coords.w;
|
||||
#endif
|
||||
|
||||
intensity = clamp(intensity, 0.0, 1.0);
|
||||
vec3 reflCol = textureLod(tex, coords.xy, 0.0).rgb;
|
||||
reflCol = clamp(reflCol, 0.0, 1.0);
|
||||
fragColor.rgb = reflCol * intensity * 0.5;
|
||||
}
|
41
leenkx/Shaders/ssr_pass/ssr_pass.json
Normal file
41
leenkx/Shaders/ssr_pass/ssr_pass.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"contexts": [
|
||||
{
|
||||
"name": "ssr_pass",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [
|
||||
{
|
||||
"name": "P",
|
||||
"link": "_projectionMatrix"
|
||||
},
|
||||
{
|
||||
"name": "V3",
|
||||
"link": "_viewMatrix3"
|
||||
},
|
||||
{
|
||||
"name": "invP",
|
||||
"link": "_inverseProjectionMatrix"
|
||||
},
|
||||
{
|
||||
"name": "cameraProj",
|
||||
"link": "_cameraPlaneProj"
|
||||
},
|
||||
{
|
||||
"name": "PPComp9",
|
||||
"link": "_PPComp9",
|
||||
"ifdef": ["_CPostprocess"]
|
||||
},
|
||||
{
|
||||
"name": "PPComp10",
|
||||
"link": "_PPComp10",
|
||||
"ifdef": ["_CPostprocess"]
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass_viewray2.vert.glsl",
|
||||
"fragment_shader": "ssr_pass.frag.glsl"
|
||||
}
|
||||
]
|
||||
}
|
106
leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl
Normal file
106
leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl
Normal file
@ -0,0 +1,106 @@
|
||||
//https://lettier.github.io/3d-game-shaders-for-beginners/screen-space-refraction.html
|
||||
//Implemented by Yvain Douard.
|
||||
|
||||
#version 450
|
||||
|
||||
#include "compiled.inc"
|
||||
#include "std/math.glsl"
|
||||
#include "std/gbuffer.glsl"
|
||||
|
||||
uniform sampler2D tex;
|
||||
uniform sampler2D tex1;
|
||||
uniform sampler2D gbufferD;
|
||||
uniform sampler2D gbuffer0;
|
||||
uniform sampler2D gbufferD1;
|
||||
|
||||
uniform sampler2D gbuffer_refraction; // ior\opacity
|
||||
uniform mat4 P;
|
||||
uniform mat3 V3;
|
||||
uniform vec2 cameraProj;
|
||||
|
||||
in vec3 viewRay;
|
||||
in vec2 texCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
vec3 hitCoord;
|
||||
float depth;
|
||||
|
||||
const int numBinarySearchSteps = 7;
|
||||
const int maxSteps = int(ceil(1.0 / ss_refractionRayStep) * ss_refractionSearchDist);
|
||||
|
||||
vec2 getProjectedCoord(const vec3 hit) {
|
||||
vec4 projectedCoord = P * vec4(hit, 1.0);
|
||||
projectedCoord.xy /= projectedCoord.w;
|
||||
projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5;
|
||||
#ifdef _InvY
|
||||
projectedCoord.y = 1.0 - projectedCoord.y;
|
||||
#endif
|
||||
return projectedCoord.xy;
|
||||
}
|
||||
|
||||
float getDeltaDepth(const vec3 hit) {
|
||||
depth = textureLod(gbufferD1, getProjectedCoord(hit), 0.0).r * 2.0 - 1.0;
|
||||
vec3 viewPos = getPosView(viewRay, depth, cameraProj);
|
||||
return viewPos.z - hit.z;
|
||||
}
|
||||
|
||||
vec4 binarySearch(vec3 dir) {
|
||||
float ddepth;
|
||||
for (int i = 0; i < numBinarySearchSteps; i++) {
|
||||
dir *= 0.5;
|
||||
hitCoord -= dir;
|
||||
ddepth = getDeltaDepth(hitCoord);
|
||||
if (ddepth < 0.0) hitCoord += dir;
|
||||
}
|
||||
if (abs(ddepth) > ss_refractionSearchDist) return vec4(0.0);
|
||||
return vec4(getProjectedCoord(hitCoord), 0.0, 1.0);
|
||||
}
|
||||
|
||||
vec4 rayCast(vec3 dir) {
|
||||
float ddepth;
|
||||
dir *= ss_refractionRayStep;
|
||||
for (int i = 0; i < maxSteps; i++) {
|
||||
hitCoord += dir;
|
||||
ddepth = getDeltaDepth(hitCoord);
|
||||
if (ddepth > 0.0) return binarySearch(dir);
|
||||
}
|
||||
return vec4(texCoord, 0.0, 1.0);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec4 g0 = textureLod(gbuffer0, texCoord, 0.0);
|
||||
float roughness = g0.z;
|
||||
vec4 gr = textureLod(gbuffer_refraction, texCoord, 0.0);
|
||||
float ior = gr.x;
|
||||
float opac = gr.y;
|
||||
float d = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0;
|
||||
if (d == 0.0 || d == 1.0 || opac == 1.0 || ior == 1.0) {
|
||||
fragColor.rgb = textureLod(tex1, texCoord, 0.0).rgb;
|
||||
return;
|
||||
}
|
||||
vec2 enc = g0.rg;
|
||||
vec3 n;
|
||||
n.z = 1.0 - abs(enc.x) - abs(enc.y);
|
||||
n.xy = n.z >= 0.0 ? enc.xy : octahedronWrap(enc.xy);
|
||||
n = normalize(n);
|
||||
|
||||
vec3 viewNormal = V3 * n;
|
||||
vec3 viewPos = getPosView(viewRay, d, cameraProj);
|
||||
vec3 refracted = refract(viewPos, viewNormal, 1.0 / ior);
|
||||
hitCoord = viewPos;
|
||||
|
||||
vec3 dir = refracted * (1.0 - rand(texCoord) * ss_refractionJitter * roughness) * 2.0;
|
||||
vec4 coords = rayCast(dir);
|
||||
vec2 deltaCoords = abs(vec2(0.5, 0.5) - coords.xy);
|
||||
float screenEdgeFactor = clamp(1.0 - (deltaCoords.x + deltaCoords.y), 0.0, 1.0);
|
||||
float refractivity = 1.0 - roughness;
|
||||
float intensity = pow(refractivity, ss_refractionFalloffExp) * screenEdgeFactor * \
|
||||
clamp(-refracted.z, 0.0, 1.0) * clamp((length(viewPos - hitCoord)), 0.0, 1.0) * coords.w;
|
||||
intensity = clamp(intensity, 0.0, 1.0);
|
||||
|
||||
vec3 refractionCol = textureLod(tex1, coords.xy, 0.0).rgb;
|
||||
refractionCol *= intensity;
|
||||
vec3 color = textureLod(tex, texCoord.xy, 0.0).rgb;
|
||||
|
||||
fragColor.rgb = mix(refractionCol, color, opac);
|
||||
}
|
38
leenkx/Shaders/ssrefr_pass/ssrefr_pass.json
Normal file
38
leenkx/Shaders/ssrefr_pass/ssrefr_pass.json
Normal file
@ -0,0 +1,38 @@
|
||||
{
|
||||
"contexts": [
|
||||
{
|
||||
"name": "ssrefr_pass",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [
|
||||
{
|
||||
"name": "P",
|
||||
"link": "_projectionMatrix"
|
||||
},
|
||||
{
|
||||
"name": "V3",
|
||||
"link": "_viewMatrix3"
|
||||
},
|
||||
{
|
||||
"name": "eye",
|
||||
"link": "_cameraPosition"
|
||||
},
|
||||
{
|
||||
"name": "eyeLook",
|
||||
"link": "_cameraLook"
|
||||
},
|
||||
{
|
||||
"name": "invP",
|
||||
"link": "_inverseProjectionMatrix"
|
||||
},
|
||||
{
|
||||
"name": "cameraProj",
|
||||
"link": "_cameraPlaneProj"
|
||||
}
|
||||
],
|
||||
"vertex_shader": "../include/pass_viewray2.vert.glsl",
|
||||
"fragment_shader": "ssrefr_pass.frag.glsl"
|
||||
}
|
||||
]
|
||||
}
|
115
leenkx/Shaders/sss_pass/sss_pass.frag.glsl
Normal file
115
leenkx/Shaders/sss_pass/sss_pass.frag.glsl
Normal file
@ -0,0 +1,115 @@
|
||||
//
|
||||
// Copyright (C) 2012 Jorge Jimenez (jorge@iryoku.com)
|
||||
// Copyright (C) 2012 Diego Gutierrez (diegog@unizar.es)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution:
|
||||
//
|
||||
// "Uses Separable SSS. Copyright (C) 2012 by Jorge Jimenez and Diego
|
||||
// Gutierrez."
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 COPYRIGHT HOLDERS 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.
|
||||
//
|
||||
// The views and conclusions contained in the software and documentation are
|
||||
// those of the authors and should not be interpreted as representing official
|
||||
// policies, either expressed or implied, of the copyright holders.
|
||||
//
|
||||
|
||||
#version 450
|
||||
|
||||
#include "compiled.inc"
|
||||
|
||||
uniform sampler2D gbufferD;
|
||||
uniform sampler2D gbuffer0;
|
||||
uniform sampler2D tex;
|
||||
|
||||
uniform vec2 dir;
|
||||
uniform vec2 cameraProj;
|
||||
|
||||
in vec2 texCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
const float SSSS_FOVY = 108.0;
|
||||
|
||||
// Separable SSS Reflectance
|
||||
// const float sssWidth = 0.005;
|
||||
vec4 SSSSBlur() {
|
||||
// Quality = 0
|
||||
const int SSSS_N_SAMPLES = 11;
|
||||
vec4 kernel[SSSS_N_SAMPLES];
|
||||
kernel[0] = vec4(0.560479, 0.669086, 0.784728, 0);
|
||||
kernel[1] = vec4(0.00471691, 0.000184771, 5.07566e-005, -2);
|
||||
kernel[2] = vec4(0.0192831, 0.00282018, 0.00084214, -1.28);
|
||||
kernel[3] = vec4(0.03639, 0.0130999, 0.00643685, -0.72);
|
||||
kernel[4] = vec4(0.0821904, 0.0358608, 0.0209261, -0.32);
|
||||
kernel[5] = vec4(0.0771802, 0.113491, 0.0793803, -0.08);
|
||||
kernel[6] = vec4(0.0771802, 0.113491, 0.0793803, 0.08);
|
||||
kernel[7] = vec4(0.0821904, 0.0358608, 0.0209261, 0.32);
|
||||
kernel[8] = vec4(0.03639, 0.0130999, 0.00643685, 0.72);
|
||||
kernel[9] = vec4(0.0192831, 0.00282018, 0.00084214, 1.28);
|
||||
kernel[10] = vec4(0.00471691, 0.000184771, 5.07565e-005, 2);
|
||||
|
||||
vec4 colorM = textureLod(tex, texCoord, 0.0);
|
||||
|
||||
// Fetch linear depth of current pixel
|
||||
float depth = textureLod(gbufferD, texCoord, 0.0).r;
|
||||
float depthM = cameraProj.y / (depth - cameraProj.x);
|
||||
|
||||
// Calculate the sssWidth scale (1.0 for a unit plane sitting on the projection window)
|
||||
float distanceToProjectionWindow = 1.0 / tan(0.5 * radians(SSSS_FOVY));
|
||||
float scale = distanceToProjectionWindow / depthM;
|
||||
|
||||
// Calculate the final step to fetch the surrounding pixels
|
||||
vec2 finalStep = sssWidth * scale * dir;
|
||||
finalStep *= 1.0;//SSSS_STREGTH_SOURCE; // Modulate it using the alpha channel.
|
||||
finalStep *= 1.0 / 3.0; // Divide by 3 as the kernels range from -3 to 3.
|
||||
finalStep *= 0.05; //
|
||||
|
||||
// Accumulate the center sample:
|
||||
vec4 colorBlurred = colorM;
|
||||
colorBlurred.rgb *= kernel[0].rgb;
|
||||
|
||||
// Accumulate the other samples
|
||||
for (int i = 1; i < SSSS_N_SAMPLES; i++) {
|
||||
// Fetch color and depth for current sample
|
||||
vec2 offset = texCoord + kernel[i].a * finalStep;
|
||||
vec4 color = textureLod(tex, offset, 0.0);
|
||||
//#if SSSS_FOLLOW_SURFACE == 1
|
||||
// If the difference in depth is huge, we lerp color back to "colorM":
|
||||
//float depth = textureLod(tex, offset, 0.0).r;
|
||||
//float s = clamp(300.0f * distanceToProjectionWindow * sssWidth * abs(depthM - depth),0.0,1.0);
|
||||
//color.rgb = mix(color.rgb, colorM.rgb, s);
|
||||
//#endif
|
||||
// Accumulate
|
||||
colorBlurred.rgb += kernel[i].rgb * color.rgb;
|
||||
}
|
||||
|
||||
return colorBlurred;
|
||||
}
|
||||
|
||||
void main() {
|
||||
if (textureLod(gbuffer0, texCoord, 0.0).a == 8192.0) {
|
||||
fragColor = clamp(SSSSBlur(), 0.0, 1.0);
|
||||
}
|
||||
else {
|
||||
fragColor = textureLod(tex, texCoord, 0.0);
|
||||
}
|
||||
}
|
42
leenkx/Shaders/sss_pass/sss_pass.json
Normal file
42
leenkx/Shaders/sss_pass/sss_pass.json
Normal file
@ -0,0 +1,42 @@
|
||||
{
|
||||
"contexts": [
|
||||
{
|
||||
"name": "sss_pass_x",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [
|
||||
{
|
||||
"name": "dir",
|
||||
"link": "_vec2x"
|
||||
},
|
||||
{
|
||||
"name": "cameraProj",
|
||||
"link": "_cameraPlaneProj"
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass.vert.glsl",
|
||||
"fragment_shader": "sss_pass.frag.glsl"
|
||||
},
|
||||
{
|
||||
"name": "sss_pass_y",
|
||||
"depth_write": false,
|
||||
"compare_mode": "always",
|
||||
"cull_mode": "none",
|
||||
"links": [
|
||||
{
|
||||
"name": "dir",
|
||||
"link": "_vec2y"
|
||||
},
|
||||
{
|
||||
"name": "cameraProj",
|
||||
"link": "_cameraPlaneProj"
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "../include/pass.vert.glsl",
|
||||
"fragment_shader": "sss_pass.frag.glsl"
|
||||
}
|
||||
]
|
||||
}
|
140
leenkx/Shaders/std/brdf.glsl
Normal file
140
leenkx/Shaders/std/brdf.glsl
Normal file
@ -0,0 +1,140 @@
|
||||
#ifndef _BRDF_GLSL_
|
||||
#define _BRDF_GLSL_
|
||||
|
||||
// http://xlgames-inc.github.io/posts/improvedibl/
|
||||
// http://blog.selfshadow.com/publications/s2013-shading-course/
|
||||
vec3 f_schlick(const vec3 f0, const float vh) {
|
||||
return f0 + (1.0 - f0) * exp2((-5.55473 * vh - 6.98316) * vh);
|
||||
}
|
||||
|
||||
float v_smithschlick(const float nl, const float nv, const float a) {
|
||||
return 1.0 / ((nl * (1.0 - a) + a) * (nv * (1.0 - a) + a));
|
||||
}
|
||||
|
||||
//Uncorrelated masking/shadowing (info below) function
|
||||
//Because it is uncorrelated, G1(NdotL, a) gives us shadowing, and G1(NdotV, a) gives us masking function.
|
||||
//Approximation from: https://ubm-twvideo01.s3.amazonaws.com/o1/vault/gdc2017/Presentations/Hammon_Earl_PBR_Diffuse_Lighting.pdf
|
||||
float g1_approx(const float NdotX, const float alpha)
|
||||
{
|
||||
return (2.0 * NdotX) * (1.0 / (NdotX * (2.0 - alpha) + alpha));
|
||||
}
|
||||
|
||||
//Uncorrelated masking-shadowing function
|
||||
//Approximation from: https://ubm-twvideo01.s3.amazonaws.com/o1/vault/gdc2017/Presentations/Hammon_Earl_PBR_Diffuse_Lighting.pdf
|
||||
float g2_approx(const float NdotL, const float NdotV, const float alpha)
|
||||
{
|
||||
vec2 helper = (2.0 * vec2(NdotL, NdotV)) * (1.0 / (vec2(NdotL, NdotV) * (2.0 - alpha) + alpha));
|
||||
return max(helper.x * helper.y, 0.0); //This can go negative, let's fix that
|
||||
}
|
||||
|
||||
float d_ggx(const float nh, const float a) {
|
||||
float a2 = a * a;
|
||||
float denom = nh * nh * (a2 - 1.0) + 1.0;
|
||||
denom = max(denom * denom, 0.00006103515625 /* 2^-14 = smallest possible half float value, prevent div by zero */);
|
||||
return a2 * (1.0 / 3.1415926535) / denom;
|
||||
}
|
||||
|
||||
vec3 specularBRDF(const vec3 f0, const float roughness, const float nl, const float nh, const float nv, const float vh) {
|
||||
float a = roughness * roughness;
|
||||
return d_ggx(nh, a) * g2_approx(nl, nv, a) * f_schlick(f0, vh) / max(4.0 * nv, 1e-5); //NdotL cancels out later
|
||||
}
|
||||
|
||||
// John Hable - Optimizing GGX Shaders
|
||||
// http://filmicworlds.com/blog/optimizing-ggx-shaders-with-dotlh/
|
||||
vec3 specularBRDFb(const vec3 f0, const float roughness, const float dotNL, const float dotNH, const float dotLH) {
|
||||
// D
|
||||
const float pi = 3.1415926535;
|
||||
float alpha = roughness * roughness;
|
||||
float alphaSqr = alpha * alpha;
|
||||
float denom = dotNH * dotNH * (alphaSqr - 1.0) + 1.0;
|
||||
float D = alphaSqr / (pi * denom * denom);
|
||||
// F
|
||||
const float F_a = 1.0;
|
||||
float F_b = pow(1.0 - dotLH, 5.0);
|
||||
// V
|
||||
float vis;
|
||||
float k = alpha / 2.0;
|
||||
float k2 = k * k;
|
||||
float invK2 = 1.0 - k2;
|
||||
vis = 1.0 / (dotLH * dotLH * invK2 + k2);
|
||||
vec2 FV_helper = vec2((F_a - F_b) * vis, F_b * vis);
|
||||
|
||||
vec3 FV = f0 * FV_helper.x + FV_helper.y;
|
||||
vec3 specular = clamp(dotNL, 0.0, 1.0) * D * FV;
|
||||
return specular / 4.0; // TODO: get rid of / 4.0
|
||||
}
|
||||
|
||||
vec3 orenNayarDiffuseBRDF(const vec3 albedo, const float roughness, const float nv, const float nl, const float vh) {
|
||||
float a = roughness * roughness;
|
||||
float s = a;
|
||||
float s2 = s * s;
|
||||
float vl = 2.0 * vh * vh - 1.0; // Double angle identity
|
||||
float Cosri = vl - nv * nl;
|
||||
float C1 = 1.0 - 0.5 * s2 / (s2 + 0.33);
|
||||
float test = 1.0;
|
||||
if (Cosri >= 0.0) test = (1.0 / (max(nl, nv)));
|
||||
float C2 = 0.45 * s2 / (s2 + 0.09) * Cosri * test;
|
||||
return albedo * max(0.0, nl) * (C1 + C2) * (1.0 + roughness * 0.5);
|
||||
}
|
||||
|
||||
vec3 lambertDiffuseBRDF(const vec3 albedo, const float nl) {
|
||||
return albedo * nl;
|
||||
}
|
||||
|
||||
vec3 surfaceAlbedo(const vec3 baseColor, const float metalness) {
|
||||
return mix(baseColor, vec3(0.0), metalness);
|
||||
}
|
||||
|
||||
vec3 surfaceF0(const vec3 baseColor, const float metalness) {
|
||||
return mix(vec3(0.04), baseColor, metalness);
|
||||
}
|
||||
|
||||
float getMipFromRoughness(const float roughness, const float numMipmaps) {
|
||||
// First mipmap level = roughness 0, last = roughness = 1
|
||||
return roughness * numMipmaps;
|
||||
}
|
||||
|
||||
float wardSpecular(vec3 N, vec3 H, float dotNL, float dotNV, float dotNH, vec3 fiberDirection, float shinyParallel, float shinyPerpendicular) {
|
||||
if(dotNL < 0.0 || dotNV < 0.0) {
|
||||
return 0.0;
|
||||
}
|
||||
// fiberDirection - parse from rotation
|
||||
// shinyParallel - roughness
|
||||
// shinyPerpendicular - anisotropy
|
||||
|
||||
vec3 fiberParallel = normalize(fiberDirection);
|
||||
vec3 fiberPerpendicular = normalize(cross(N, fiberDirection));
|
||||
float dotXH = dot(fiberParallel, H);
|
||||
float dotYH = dot(fiberPerpendicular, H);
|
||||
const float PI = 3.1415926535;
|
||||
float coeff = sqrt(dotNL/dotNV) / (4.0 * PI * shinyParallel * shinyPerpendicular);
|
||||
float theta = (pow(dotXH/shinyParallel, 2.0) + pow(dotYH/shinyPerpendicular, 2.0)) / (1.0 + dotNH);
|
||||
return clamp(coeff * exp(-2.0 * theta), 0.0, 1.0);
|
||||
}
|
||||
|
||||
// https://www.unrealengine.com/en-US/blog/physically-based-shading-on-mobile
|
||||
// vec3 EnvBRDFApprox(vec3 SpecularColor, float Roughness, float NoV) {
|
||||
// const vec4 c0 = { -1, -0.0275, -0.572, 0.022 };
|
||||
// const vec4 c1 = { 1, 0.0425, 1.04, -0.04 };
|
||||
// vec4 r = Roughness * c0 + c1;
|
||||
// float a004 = min( r.x * r.x, exp2( -9.28 * NoV ) ) * r.x + r.y;
|
||||
// vec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;
|
||||
// return SpecularColor * AB.x + AB.y;
|
||||
// }
|
||||
// float EnvBRDFApproxNonmetal(float Roughness, float NoV) {
|
||||
// // Same as EnvBRDFApprox( 0.04, Roughness, NoV )
|
||||
// const vec2 c0 = { -1, -0.0275 };
|
||||
// const vec2 c1 = { 1, 0.0425 };
|
||||
// vec2 r = Roughness * c0 + c1;
|
||||
// return min( r.x * r.x, exp2( -9.28 * NoV ) ) * r.x + r.y;
|
||||
// }
|
||||
float D_Approx(const float Roughness, const float RoL) {
|
||||
float a = Roughness * Roughness;
|
||||
float a2 = a * a;
|
||||
float rcp_a2 = 1.0 / a2;//rcp(a2);
|
||||
// 0.5 / ln(2), 0.275 / ln(2)
|
||||
float c = 0.72134752 * rcp_a2 + 0.39674113;
|
||||
return rcp_a2 * exp2( c * RoL - c );
|
||||
}
|
||||
|
||||
#endif
|
18
leenkx/Shaders/std/clusters.glsl
Normal file
18
leenkx/Shaders/std/clusters.glsl
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
const vec3 clusterSlices = vec3(16, 16, 16);
|
||||
|
||||
int getClusterI(vec2 tc, float viewz, vec2 cameraPlane) {
|
||||
int sliceZ = 0;
|
||||
float cnear = clusterNear + cameraPlane.x;
|
||||
if (viewz >= cnear) {
|
||||
float z = log(viewz - cnear + 1.0) / log(cameraPlane.y - cnear + 1.0);
|
||||
sliceZ = int(z * (clusterSlices.z - 1)) + 1;
|
||||
}
|
||||
// address gap between near plane and cluster near offset
|
||||
else if (viewz >= cameraPlane.x) {
|
||||
sliceZ = 1;
|
||||
}
|
||||
return int(tc.x * clusterSlices.x) +
|
||||
int(int(tc.y * clusterSlices.y) * clusterSlices.x) +
|
||||
int(sliceZ * clusterSlices.x * clusterSlices.y);
|
||||
}
|
144
leenkx/Shaders/std/colorgrading.glsl
Normal file
144
leenkx/Shaders/std/colorgrading.glsl
Normal file
@ -0,0 +1,144 @@
|
||||
// Colorgrading library functions - Inspired by UE4
|
||||
//No specific license (maybe zlib), but just do whatever
|
||||
|
||||
#define LUMINANCE_PRESERVATION 0.75
|
||||
#define EPSILON 1e-10
|
||||
#define LUMA1 0.2722287168
|
||||
#define LUMA2 0.6740817658
|
||||
#define LUMA3 0.0536895174
|
||||
|
||||
float saturate(float v) { return clamp(v, 0.0, 1.0); }
|
||||
vec2 saturate(vec2 v) { return clamp(v, vec2(0.0), vec2(1.0)); }
|
||||
vec3 saturate(vec3 v) { return clamp(v, vec3(0.0), vec3(1.0)); }
|
||||
vec4 saturate(vec4 v) { return clamp(v, vec4(0.0), vec4(1.0)); }
|
||||
|
||||
float LumaKey (vec3 color) {
|
||||
return dot(color, vec3(LUMA1, LUMA2, LUMA3));
|
||||
}
|
||||
|
||||
vec3 ColorTemperatureToRGB(float temperatureInKelvins)
|
||||
{
|
||||
vec3 retColor;
|
||||
|
||||
temperatureInKelvins = clamp(temperatureInKelvins, 1000.0, 40000.0) / 100.0;
|
||||
|
||||
if (temperatureInKelvins <= 66.0)
|
||||
{
|
||||
retColor.r = 1.0;
|
||||
retColor.g = saturate(0.39008157876901960784 * log(temperatureInKelvins) - 0.63184144378862745098);
|
||||
}
|
||||
else
|
||||
{
|
||||
float t = temperatureInKelvins - 60.0;
|
||||
retColor.r = saturate(1.29293618606274509804 * pow(t, -0.1332047592));
|
||||
retColor.g = saturate(1.12989086089529411765 * pow(t, -0.0755148492));
|
||||
}
|
||||
|
||||
if (temperatureInKelvins >= 66.0)
|
||||
retColor.b = 1.0;
|
||||
else if(temperatureInKelvins <= 19.0)
|
||||
retColor.b = 0.0;
|
||||
else
|
||||
retColor.b = saturate(0.54320678911019607843 * log(temperatureInKelvins - 10.0) - 1.19625408914);
|
||||
|
||||
return retColor;
|
||||
}
|
||||
|
||||
float Luminance(vec3 color)
|
||||
{
|
||||
float fmin = min(min(color.r, color.g), color.b);
|
||||
float fmax = max(max(color.r, color.g), color.b);
|
||||
return (fmax + fmin) / 2.0;
|
||||
}
|
||||
|
||||
vec3 HUEtoRGB(float H)
|
||||
{
|
||||
float R = abs(H * 6.0 - 3.0) - 1.0;
|
||||
float G = 2.0 - abs(H * 6.0 - 2.0);
|
||||
float B = 2.0 - abs(H * 6.0 - 4.0);
|
||||
return saturate(vec3(R,G,B));
|
||||
}
|
||||
|
||||
vec3 HSLtoRGB(in vec3 HSL)
|
||||
{
|
||||
vec3 RGB = HUEtoRGB(HSL.x);
|
||||
float C = (1.0 - abs(2.0 * HSL.z - 1.0)) * HSL.y;
|
||||
return (RGB - 0.5) * C + vec3(HSL.z);
|
||||
}
|
||||
|
||||
vec3 RGBtoHCV(vec3 RGB)
|
||||
{
|
||||
vec4 P = (RGB.g < RGB.b) ? vec4(RGB.bg, -1.0, 2.0/3.0) : vec4(RGB.gb, 0.0, -1.0/3.0);
|
||||
vec4 Q = (RGB.r < P.x) ? vec4(P.xyw, RGB.r) : vec4(RGB.r, P.yzx);
|
||||
float C = Q.x - min(Q.w, Q.y);
|
||||
float H = abs((Q.w - Q.y) / (6.0 * C + EPSILON) + Q.z);
|
||||
return vec3(H, C, Q.x);
|
||||
}
|
||||
|
||||
vec3 RGBtoHSL(vec3 RGB)
|
||||
{
|
||||
vec3 HCV = RGBtoHCV(RGB);
|
||||
float L = HCV.z - HCV.y * 0.5;
|
||||
float S = HCV.y / (1.0 - abs(L * 2.0 - 1.0) + EPSILON);
|
||||
return vec3(HCV.x, S, L);
|
||||
}
|
||||
|
||||
|
||||
vec3 ToneColorCorrection(vec3 Color, vec3 ColorSaturation, vec3 ColorContrast, vec3 ColorGamma, vec3 ColorGain, vec3 ColorOffset) {
|
||||
//First initialize the colorluma key
|
||||
float ColorLuma = LumaKey(Color);
|
||||
//Add the saturation with the above key
|
||||
Color = max(vec3(0,0,0), mix(ColorLuma.xxx, Color, ColorSaturation));
|
||||
//Contrast with slight color correction (0.18 coefficient)
|
||||
float ContrastCorrectionCoefficient = 0.18;
|
||||
Color = pow(Color * (1.0 / ContrastCorrectionCoefficient), ColorContrast) * ContrastCorrectionCoefficient;
|
||||
//Gamma
|
||||
Color = pow(Color, 1.0 / ColorGamma);
|
||||
//Gain and Offset
|
||||
Color = Color.rgb * ColorGain + (ColorOffset - 1);
|
||||
//Return the color corrected profile
|
||||
return Color;
|
||||
}
|
||||
|
||||
vec3 FinalizeColorCorrection(vec3 Color, mat3 ColorSaturation, mat3 ColorContrast, mat3 ColorGamma, mat3 ColorGain, mat3 ColorOffset, vec2 Toneweights) {
|
||||
|
||||
float CCShadowsMax = Toneweights.x;
|
||||
float CCHighlightsMin = Toneweights.y;
|
||||
|
||||
//First initialize the colorluma key and set color correction weights
|
||||
float ColorLuma = LumaKey(Color);
|
||||
float CCWeightShadows = 1 - smoothstep(0, CCShadowsMax, ColorLuma);
|
||||
float CCWeightHighlights = smoothstep(CCHighlightsMin, 1, ColorLuma);
|
||||
float CCWeightMidtones = 1 - CCWeightShadows - CCWeightHighlights;
|
||||
|
||||
vec3 CCColorShadows = ToneColorCorrection (
|
||||
Color,
|
||||
ColorSaturation[0],
|
||||
ColorContrast[0],
|
||||
ColorGamma[0],
|
||||
ColorGain[0],
|
||||
ColorOffset[0]
|
||||
);
|
||||
|
||||
vec3 CCColorMidtones = ToneColorCorrection (
|
||||
Color,
|
||||
ColorSaturation[1],
|
||||
ColorContrast[1],
|
||||
ColorGamma[1],
|
||||
ColorGain[1],
|
||||
ColorOffset[1]
|
||||
);
|
||||
|
||||
vec3 CCColorHighlights = ToneColorCorrection (
|
||||
Color,
|
||||
ColorSaturation[2],
|
||||
ColorContrast[2],
|
||||
ColorGamma[2],
|
||||
ColorGain[2],
|
||||
ColorOffset[2]
|
||||
);
|
||||
|
||||
vec3 CombinedCCProfile = CCColorShadows * CCWeightShadows + CCColorMidtones * CCWeightMidtones + CCColorHighlights * CCWeightHighlights;
|
||||
|
||||
return vec3(CombinedCCProfile);
|
||||
}
|
338
leenkx/Shaders/std/conetrace.glsl
Normal file
338
leenkx/Shaders/std/conetrace.glsl
Normal file
@ -0,0 +1,338 @@
|
||||
/*
|
||||
Copyright (c) 2024 Turánszki János
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
#ifndef _CONETRACE_GLSL_
|
||||
#define _CONETRACE_GLSL_
|
||||
|
||||
#include "std/voxels_constants.glsl"
|
||||
|
||||
// References
|
||||
// https://github.com/Friduric/voxel-cone-tracing
|
||||
// https://github.com/Cigg/Voxel-Cone-Tracing
|
||||
// https://github.com/GreatBlambo/voxel_cone_tracing/
|
||||
// http://simonstechblog.blogspot.com/2013/01/implementing-voxel-cone-tracing.html
|
||||
// http://leifnode.com/2015/05/voxel-cone-traced-global-illumination/
|
||||
// http://www.seas.upenn.edu/%7Epcozzi/OpenGLInsights/OpenGLInsights-SparseVoxelization.pdf
|
||||
// https://research.nvidia.com/sites/default/files/publications/GIVoxels-pg2011-authors.pdf
|
||||
|
||||
const float MAX_DISTANCE = voxelgiRange;
|
||||
|
||||
#ifdef _VoxelGI
|
||||
uniform sampler3D dummy;
|
||||
|
||||
vec4 sampleVoxel(sampler3D voxels, vec3 P, const float clipmaps[voxelgiClipmapCount * 10], const float clipmap_index, const float step_dist, const int precomputed_direction, const vec3 face_offset, const vec3 direction_weight) {
|
||||
vec4 col = vec4(0.0);
|
||||
vec3 tc = (P - vec3(clipmaps[int(clipmap_index * 10 + 4)], clipmaps[int(clipmap_index * 10 + 5)], clipmaps[int(clipmap_index * 10 + 6)])) / (float(clipmaps[int(clipmap_index * 10)]) * voxelgiResolution);
|
||||
vec3 half_texel = vec3(0.5) / voxelgiResolution;
|
||||
tc = tc * 0.5 + 0.5;
|
||||
tc = clamp(tc, half_texel, 1.0 - half_texel);
|
||||
tc.x = (tc.x + precomputed_direction) / (6 + DIFFUSE_CONE_COUNT);
|
||||
tc.y = (tc.y + clipmap_index) / voxelgiClipmapCount;
|
||||
|
||||
if (precomputed_direction == 0) {
|
||||
col = direction_weight.x * textureLod(voxels, vec3(tc.x + face_offset.x, tc.y, tc.z), 0)
|
||||
+ direction_weight.y * textureLod(voxels, vec3(tc.x + face_offset.y, tc.y, tc.z), 0)
|
||||
+ direction_weight.z * textureLod(voxels, vec3(tc.x + face_offset.z, tc.y, tc.z), 0);
|
||||
}
|
||||
else
|
||||
col = textureLod(voxels, tc, 0);
|
||||
|
||||
col *= step_dist / float(clipmaps[int(clipmap_index * 10)]);
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
#endif
|
||||
#ifdef _VoxelAOvar
|
||||
float sampleVoxel(sampler3D voxels, vec3 P, const float clipmaps[voxelgiClipmapCount * 10], const float clipmap_index, const float step_dist, const int precomputed_direction, const vec3 face_offset, const vec3 direction_weight) {
|
||||
float opac = 0.0;
|
||||
vec3 tc = (P - vec3(clipmaps[int(clipmap_index * 10 + 4)], clipmaps[int(clipmap_index * 10 + 5)], clipmaps[int(clipmap_index * 10 + 6)])) / (float(clipmaps[int(clipmap_index * 10)]) * voxelgiResolution);
|
||||
vec3 half_texel = vec3(0.5) / voxelgiResolution;
|
||||
tc = tc * 0.5 + 0.5;
|
||||
tc = clamp(tc, half_texel, 1.0 - half_texel);
|
||||
tc.x = (tc.x + precomputed_direction) / (6 + DIFFUSE_CONE_COUNT);
|
||||
tc.y = (tc.y + clipmap_index) / voxelgiClipmapCount;
|
||||
|
||||
if (precomputed_direction == 0) {
|
||||
opac = direction_weight.x * textureLod(voxels, vec3(tc.x + face_offset.x, tc.y, tc.z), 0).r
|
||||
+ direction_weight.y * textureLod(voxels, vec3(tc.x + face_offset.y, tc.y, tc.z), 0).r
|
||||
+ direction_weight.z * textureLod(voxels, vec3(tc.x + face_offset.z, tc.y, tc.z), 0).r;
|
||||
}
|
||||
else
|
||||
opac = textureLod(voxels, tc, 0).r;
|
||||
|
||||
opac *= step_dist / float(clipmaps[int(clipmap_index * 10)]);
|
||||
|
||||
return opac;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _VoxelGI
|
||||
vec4 traceCone(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 origin, const vec3 n, const vec3 dir, const int precomputed_direction, const bool use_sdf, const float aperture, const float step_size, const float clipmaps[voxelgiClipmapCount * 10]) {
|
||||
vec4 sampleCol = vec4(0.0);
|
||||
float voxelSize0 = float(clipmaps[0]) * 2.0;
|
||||
float dist = voxelSize0;
|
||||
float step_dist = dist;
|
||||
vec3 samplePos;
|
||||
vec3 start_pos = origin + n * voxelSize0 * voxelgiOffset;
|
||||
int clipmap_index0 = 0;
|
||||
|
||||
vec3 aniso_direction = -dir;
|
||||
vec3 face_offset = vec3(
|
||||
aniso_direction.x > 0.0 ? 0 : 1,
|
||||
aniso_direction.y > 0.0 ? 2 : 3,
|
||||
aniso_direction.z > 0.0 ? 4 : 5
|
||||
) / (6 + DIFFUSE_CONE_COUNT);
|
||||
vec3 direction_weight = abs(dir);
|
||||
|
||||
float coneCoefficient = 2.0 * tan(aperture * 0.5);
|
||||
|
||||
while (sampleCol.a < 1.0 && dist < MAX_DISTANCE && clipmap_index0 < voxelgiClipmapCount) {
|
||||
vec4 mipSample = vec4(0.0);
|
||||
float diam = max(voxelSize0, dist * coneCoefficient);
|
||||
float lod = clamp(log2(diam / voxelSize0), clipmap_index0, voxelgiClipmapCount - 1);
|
||||
float clipmap_index = floor(lod);
|
||||
float clipmap_blend = fract(lod);
|
||||
vec3 p0 = start_pos + dir * dist;
|
||||
|
||||
samplePos = (p0 - vec3(clipmaps[int(clipmap_index * 10 + 4)], clipmaps[int(clipmap_index * 10 + 5)], clipmaps[int(clipmap_index * 10 + 6)])) / (float(clipmaps[int(clipmap_index * 10)]) * voxelgiResolution);
|
||||
samplePos = samplePos * 0.5 + 0.5;
|
||||
|
||||
if (any(notEqual(samplePos, clamp(samplePos, 0.0, 1.0)))) {
|
||||
clipmap_index0++;
|
||||
continue;
|
||||
}
|
||||
|
||||
mipSample = sampleVoxel(voxels, p0, clipmaps, clipmap_index, step_dist, precomputed_direction, face_offset, direction_weight);
|
||||
|
||||
if(clipmap_blend > 0.0 && clipmap_index < voxelgiClipmapCount - 1) {
|
||||
vec4 mipSampleNext = sampleVoxel(voxels, p0, clipmaps, clipmap_index + 1.0, step_dist, precomputed_direction, face_offset, direction_weight);
|
||||
mipSample = mix(mipSample, mipSampleNext, smoothstep(0.0, 1.0, clipmap_blend));
|
||||
}
|
||||
|
||||
sampleCol += (1.0 - sampleCol.a) * mipSample;
|
||||
|
||||
float stepSizeCurrent = step_size;
|
||||
if (use_sdf) {
|
||||
// half texel correction is applied to avoid sampling over current clipmap:
|
||||
const vec3 half_texel = vec3(0.5) / voxelgiResolution;
|
||||
vec3 tc0 = clamp(samplePos, half_texel, 1 - half_texel);
|
||||
tc0.y = (tc0.y + clipmap_index) / voxelgiClipmapCount; // remap into clipmap
|
||||
float sdf = textureLod(voxelsSDF, tc0, 0).r;
|
||||
stepSizeCurrent = max(step_size, sdf - diam);
|
||||
}
|
||||
step_dist = diam * stepSizeCurrent;
|
||||
dist += step_dist;
|
||||
}
|
||||
return sampleCol;
|
||||
}
|
||||
|
||||
vec4 traceDiffuse(const vec3 origin, const vec3 normal, const sampler3D voxels, const float clipmaps[voxelgiClipmapCount * 10]) {
|
||||
float sum = 0.0;
|
||||
vec4 amount = vec4(0.0);
|
||||
for (int i = 0; i < DIFFUSE_CONE_COUNT; ++i) {
|
||||
vec3 coneDir = DIFFUSE_CONE_DIRECTIONS[i];
|
||||
const float cosTheta = dot(normal, coneDir);
|
||||
if (cosTheta <= 0)
|
||||
continue;
|
||||
int precomputed_direction = 6 + i;
|
||||
amount += traceCone(voxels, dummy, origin, normal, coneDir, precomputed_direction, false, DIFFUSE_CONE_APERTURE, 1.0, clipmaps) * cosTheta;
|
||||
sum += cosTheta;
|
||||
}
|
||||
|
||||
amount /= sum;
|
||||
amount.rgb = max(amount.rgb, vec3(0.0));
|
||||
amount.a = clamp(amount.a, 0.0, 1.0);
|
||||
|
||||
return amount * voxelgiOcc;
|
||||
}
|
||||
|
||||
vec4 traceSpecular(const vec3 origin, const vec3 normal, const sampler3D voxels, const sampler3D voxelsSDF, const vec3 viewDir, const float roughness, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity) {
|
||||
vec3 specularDir = reflect(-viewDir, normal);
|
||||
vec3 P = origin + specularDir * ((BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5)) * voxelgiStep;
|
||||
vec4 amount = traceCone(voxels, voxelsSDF, P, normal, specularDir, 0, true, roughness, voxelgiStep, clipmaps);
|
||||
|
||||
amount.rgb = max(vec3(0.0), amount.rgb);
|
||||
amount.a = clamp(amount.a, 0.0, 1.0);
|
||||
|
||||
return amount * voxelgiOcc;
|
||||
}
|
||||
|
||||
vec4 traceRefraction(const vec3 origin, const vec3 normal, sampler3D voxels, sampler3D voxelsSDF, const vec3 viewDir, const float ior, const float roughness, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity) {
|
||||
const float transmittance = 1.0;
|
||||
vec3 refractionDir = refract(-viewDir, normal, 1.0 / ior);
|
||||
vec3 P = origin + refractionDir * (BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5) * voxelgiStep;
|
||||
vec4 amount = transmittance * traceCone(voxels, voxelsSDF, P, normal, refractionDir, 0, true, roughness, voxelgiStep, clipmaps);
|
||||
|
||||
amount.rgb = max(vec3(0.0), amount.rgb);
|
||||
amount.a = clamp(amount.a, 0.0, 1.0);
|
||||
|
||||
return amount * voxelgiOcc;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _VoxelAOvar
|
||||
float traceConeAO(const sampler3D voxels, const vec3 origin, const vec3 n, const vec3 dir, const int precomputed_direction, const float aperture, const float step_size, const float clipmaps[voxelgiClipmapCount * 10]) {
|
||||
float sampleCol = 0.0;
|
||||
float voxelSize0 = float(clipmaps[0]) * 2.0;
|
||||
float dist = voxelSize0;
|
||||
float step_dist = dist;
|
||||
vec3 samplePos;
|
||||
vec3 start_pos = origin + n * voxelSize0 * voxelgiOffset;
|
||||
int clipmap_index0 = 0;
|
||||
|
||||
vec3 aniso_direction = -dir;
|
||||
vec3 face_offset = vec3(
|
||||
aniso_direction.x > 0.0 ? 0 : 1,
|
||||
aniso_direction.y > 0.0 ? 2 : 3,
|
||||
aniso_direction.z > 0.0 ? 4 : 5
|
||||
) / (6 + DIFFUSE_CONE_COUNT);
|
||||
vec3 direction_weight = abs(dir);
|
||||
|
||||
float coneCoefficient = 2.0 * tan(aperture * 0.5);
|
||||
|
||||
while (sampleCol < 1.0 && dist < MAX_DISTANCE && clipmap_index0 < voxelgiClipmapCount) {
|
||||
float mipSample = 0.0;
|
||||
float diam = max(voxelSize0, dist * coneCoefficient);
|
||||
float lod = clamp(log2(diam / voxelSize0), clipmap_index0, voxelgiClipmapCount - 1);
|
||||
float clipmap_index = floor(lod);
|
||||
float clipmap_blend = fract(lod);
|
||||
vec3 p0 = start_pos + dir * dist;
|
||||
|
||||
samplePos = (p0 - vec3(clipmaps[int(clipmap_index * 10 + 4)], clipmaps[int(clipmap_index * 10 + 5)], clipmaps[int(clipmap_index * 10 + 6)])) / (float(clipmaps[int(clipmap_index * 10)]) * voxelgiResolution.x);
|
||||
samplePos = samplePos * 0.5 + 0.5;
|
||||
|
||||
if ((any(notEqual(clamp(samplePos, 0.0, 1.0), samplePos)))) {
|
||||
clipmap_index0++;
|
||||
continue;
|
||||
}
|
||||
|
||||
mipSample = sampleVoxel(voxels, p0, clipmaps, clipmap_index, step_dist, precomputed_direction, face_offset, direction_weight);
|
||||
|
||||
if(clipmap_blend > 0.0 && clipmap_index < voxelgiClipmapCount - 1) {
|
||||
float mipSampleNext = sampleVoxel(voxels, p0, clipmaps, clipmap_index + 1.0, step_dist, precomputed_direction, face_offset, direction_weight);
|
||||
mipSample = mix(mipSample, mipSampleNext, clipmap_blend);
|
||||
}
|
||||
|
||||
sampleCol += (1.0 - sampleCol) * mipSample;
|
||||
|
||||
step_dist = diam * step_size;
|
||||
dist += step_dist;
|
||||
}
|
||||
return sampleCol;
|
||||
}
|
||||
|
||||
|
||||
float traceAO(const vec3 origin, const vec3 normal, const sampler3D voxels, const float clipmaps[voxelgiClipmapCount * 10]) {
|
||||
float sum = 0.0;
|
||||
float amount = 0.0;
|
||||
for (int i = 0; i < DIFFUSE_CONE_COUNT; i++) {
|
||||
vec3 coneDir = DIFFUSE_CONE_DIRECTIONS[i];
|
||||
int precomputed_direction = 6 + i;
|
||||
const float cosTheta = dot(normal, coneDir);
|
||||
if (cosTheta <= 0)
|
||||
continue;
|
||||
amount += traceConeAO(voxels, origin, normal, coneDir, precomputed_direction, DIFFUSE_CONE_APERTURE, 1.0, clipmaps) * cosTheta;
|
||||
sum += cosTheta;
|
||||
}
|
||||
amount /= sum;
|
||||
amount = clamp(amount, 0.0, 1.0);
|
||||
return amount * voxelgiOcc;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef _VoxelShadow
|
||||
float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 origin, const vec3 n, const vec3 dir, const float aperture, const float step_size, const float clipmaps[voxelgiClipmapCount * 10]) {
|
||||
float sampleCol = 0.0;
|
||||
float voxelSize0 = float(clipmaps[0]) * 2.0;
|
||||
float dist = voxelSize0;
|
||||
float step_dist = dist;
|
||||
vec3 samplePos;
|
||||
vec3 start_pos = origin + n * voxelSize0 * voxelgiOffset;
|
||||
int clipmap_index0 = 0;
|
||||
|
||||
vec3 aniso_direction = -dir;
|
||||
vec3 face_offset = vec3(
|
||||
aniso_direction.x > 0.0 ? 0 : 1,
|
||||
aniso_direction.y > 0.0 ? 2 : 3,
|
||||
aniso_direction.z > 0.0 ? 4 : 5
|
||||
) / (6 + DIFFUSE_CONE_COUNT);
|
||||
vec3 direction_weight = abs(dir);
|
||||
float coneCoefficient = 2.0 * tan(aperture * 0.5);
|
||||
|
||||
while (sampleCol < 1.0 && dist < MAX_DISTANCE && clipmap_index0 < voxelgiClipmapCount) {
|
||||
float mipSample = 0.0;
|
||||
float diam = max(voxelSize0, dist * coneCoefficient);
|
||||
float lod = clamp(log2(diam / voxelSize0), clipmap_index0, voxelgiClipmapCount - 1);
|
||||
float clipmap_index = floor(lod);
|
||||
float clipmap_blend = fract(lod);
|
||||
vec3 p0 = start_pos + dir * dist;
|
||||
|
||||
samplePos = (p0 - vec3(clipmaps[int(clipmap_index * 10 + 4)], clipmaps[int(clipmap_index * 10 + 5)], clipmaps[int(clipmap_index * 10 + 6)])) / (float(clipmaps[int(clipmap_index * 10)]) * voxelgiResolution.x);
|
||||
samplePos = samplePos * 0.5 + 0.5;
|
||||
|
||||
if ((any(notEqual(samplePos, clamp(samplePos, 0.0, 1.0))))) {
|
||||
clipmap_index0++;
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef _VoxelAOvar
|
||||
mipSample = sampleVoxel(voxels, p0, clipmaps, clipmap_index, step_dist, 0, face_offset, direction_weight);
|
||||
#else
|
||||
mipSample = sampleVoxel(voxels, p0, clipmaps, clipmap_index, step_dist, 0, face_offset, direction_weight).a;
|
||||
#endif
|
||||
|
||||
if(clipmap_blend > 0.0 && clipmap_index < voxelgiClipmapCount - 1) {
|
||||
#ifdef _VoxelAOvar
|
||||
float mipSampleNext = sampleVoxel(voxels, p0, clipmaps, clipmap_index + 1.0, step_dist, 0, face_offset, direction_weight);
|
||||
#else
|
||||
float mipSampleNext = sampleVoxel(voxels, p0, clipmaps, clipmap_index + 1.0, step_dist, 0, face_offset, direction_weight).a;
|
||||
#endif
|
||||
mipSample = mix(mipSample, mipSampleNext, clipmap_blend);
|
||||
}
|
||||
|
||||
sampleCol += (1.0 - sampleCol) * mipSample;
|
||||
|
||||
float stepSizeCurrent = step_size;
|
||||
|
||||
// half texel correction is applied to avoid sampling over current clipmap:
|
||||
const vec3 half_texel = vec3(0.5) / voxelgiResolution;
|
||||
vec3 tc0 = clamp(samplePos, half_texel, 1 - half_texel);
|
||||
tc0.y = (tc0.y + clipmap_index) / voxelgiClipmapCount; // remap into clipmap
|
||||
float sdf = textureLod(voxelsSDF, tc0, 0.0).r;
|
||||
stepSizeCurrent = max(step_size, sdf - diam);
|
||||
|
||||
step_dist = diam * stepSizeCurrent;
|
||||
dist += step_dist;
|
||||
}
|
||||
return sampleCol;
|
||||
}
|
||||
|
||||
|
||||
float traceShadow(const vec3 origin, const vec3 normal, const sampler3D voxels, const sampler3D voxelsSDF, const vec3 dir, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel) {
|
||||
vec3 P = origin + dir * (BayerMatrix8[int(pixel.x) % 8][int(pixel.y) % 8] - 0.5) * voxelgiStep;
|
||||
float amount = traceConeShadow(voxels, voxelsSDF, P, normal, dir, DIFFUSE_CONE_APERTURE, voxelgiStep, clipmaps);
|
||||
amount = clamp(amount, 0.0, 1.0);
|
||||
return amount * voxelgiOcc;
|
||||
}
|
||||
#endif
|
||||
#endif // _CONETRACE_GLSL_
|
56
leenkx/Shaders/std/denoise.glsl
Normal file
56
leenkx/Shaders/std/denoise.glsl
Normal file
@ -0,0 +1,56 @@
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Copyright (c) 2018-2019 Michele Morrone
|
||||
// All rights reserved.
|
||||
//
|
||||
// https://michelemorrone.eu - https://BrutPitt.com
|
||||
//
|
||||
// me@michelemorrone.eu - brutpitt@gmail.com
|
||||
// twitter: @BrutPitt - github: BrutPitt
|
||||
//
|
||||
// https://github.com/BrutPitt/glslSmartDeNoise/
|
||||
//
|
||||
// This software is distributed under the terms of the BSD 2-Clause license
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
#ifndef _DENOISE_GLSL_
|
||||
#define _DENOISE_GLSL_
|
||||
|
||||
#define INV_SQRT_OF_2PI 0.39894228040143267793994605993439
|
||||
#define INV_PI 0.31830988618379067153776752674503
|
||||
|
||||
vec4 smartDeNoise(sampler2D tex, vec2 uv, float sigma, float kSigma, float threshold) {
|
||||
float radius = round(kSigma*sigma);
|
||||
float radQ = radius * radius;
|
||||
|
||||
float invSigmaQx2 = .5 / (sigma * sigma); // 1.0 / (sigma^2 * 2.0)
|
||||
float invSigmaQx2PI = INV_PI * invSigmaQx2; // 1.0 / (sqrt(PI) * sigma)
|
||||
|
||||
float invThresholdSqx2 = .5 / (threshold * threshold); // 1.0 / (sigma^2 * 2.0)
|
||||
float invThresholdSqrt2PI = INV_SQRT_OF_2PI / threshold; // 1.0 / (sqrt(2*PI) * sigma)
|
||||
|
||||
vec4 centrPx = texture(tex,uv);
|
||||
|
||||
float zBuff = 0.0;
|
||||
vec4 aBuff = vec4(0.0);
|
||||
vec2 size = vec2(textureSize(tex, 0));
|
||||
|
||||
for(float x=-radius; x <= radius; x++) {
|
||||
float pt = sqrt(radQ-x*x); // pt = yRadius: have circular trend
|
||||
for(float y=-pt; y <= pt; y++) {
|
||||
vec2 d = vec2(x,y)/size;
|
||||
|
||||
float blurFactor = exp( -dot(d , d) * invSigmaQx2 ) * invSigmaQx2;
|
||||
|
||||
vec4 walkPx = texture(tex,uv+d);
|
||||
|
||||
vec4 dC = walkPx-centrPx;
|
||||
float deltaFactor = exp( -dot(dC, dC) * invThresholdSqx2) * invThresholdSqrt2PI * blurFactor;
|
||||
|
||||
zBuff += deltaFactor;
|
||||
aBuff += deltaFactor*walkPx;
|
||||
}
|
||||
}
|
||||
return aBuff/zBuff;
|
||||
}
|
||||
|
||||
#endif
|
92
leenkx/Shaders/std/dof.glsl
Normal file
92
leenkx/Shaders/std/dof.glsl
Normal file
@ -0,0 +1,92 @@
|
||||
// DoF with bokeh GLSL shader by Martins Upitis (martinsh) (devlog-martinsh.blogspot.com)
|
||||
// Creative Commons Attribution 3.0 Unported License
|
||||
|
||||
#include "compiled.inc"
|
||||
#include "std/math.glsl"
|
||||
|
||||
// const float compoDOFDistance = 10.0; // Focal distance value in meters
|
||||
// const float compoDOFLength = 160.0; // Focal length in mm 18-200
|
||||
// const float compoDOFFstop = 128.0; // F-stop value
|
||||
|
||||
const int samples = 6; // Samples on the first ring
|
||||
const int rings = 6; // Ring count
|
||||
const vec2 focus = vec2(0.5, 0.5);
|
||||
const float coc = 0.11; // Circle of confusion size in mm (35mm film = 0.03mm)
|
||||
const float maxblur = 1.0;
|
||||
const float threshold = 0.5; // Highlight threshold
|
||||
const float gain = 2.0; // Highlight gain
|
||||
const float bias = 0.5; // Bokeh edge bias
|
||||
const float fringe = 0.7; // Bokeh chromatic aberration/fringing
|
||||
const float namount = 0.0001; // Dither amount
|
||||
|
||||
vec3 color(vec2 coords, const float blur, const sampler2D tex, const vec2 texStep) {
|
||||
vec3 col = vec3(0.0);
|
||||
col.r = textureLod(tex, coords + vec2(0.0, 1.0) * texStep * fringe * blur, 0.0).r;
|
||||
col.g = textureLod(tex, coords + vec2(-0.866, -0.5) * texStep * fringe * blur, 0.0).g;
|
||||
col.b = textureLod(tex, coords + vec2(0.866, -0.5) * texStep * fringe * blur, 0.0).b;
|
||||
|
||||
const vec3 lumcoeff = vec3(0.299, 0.587, 0.114);
|
||||
float lum = dot(col.rgb, lumcoeff);
|
||||
float thresh = max((lum - threshold) * gain, 0.0);
|
||||
return col + mix(vec3(0.0), col, thresh * blur);
|
||||
}
|
||||
|
||||
vec3 dof(
|
||||
const vec2 texCoord,
|
||||
const float gdepth,
|
||||
const sampler2D tex,
|
||||
const sampler2D gbufferD,
|
||||
const vec2 texStep,
|
||||
const vec2 cameraProj,
|
||||
const bool autoFocus,
|
||||
const float DOFDistance,
|
||||
const float DOFLength,
|
||||
const float DOFFStop) {
|
||||
|
||||
float depth = linearize(gdepth, cameraProj);
|
||||
float fDepth = 0.0;
|
||||
|
||||
if(autoFocus) {
|
||||
fDepth = linearize(textureLod(gbufferD, focus, 0.0).r * 2.0 - 1.0, cameraProj);
|
||||
} else {
|
||||
fDepth = DOFDistance;
|
||||
}
|
||||
|
||||
float f = DOFLength; // Focal length in mm
|
||||
float d = fDepth * 1000.0; // Focal plane in mm
|
||||
float o = depth * 1000.0; // Depth in mm
|
||||
float a = (o * f) / (o - f);
|
||||
float b = (d * f) / (d - f);
|
||||
float c = (d - f) / (d * DOFFStop * coc);
|
||||
float blur = abs(a - b) * c;
|
||||
blur = clamp(blur, 0.0, 1.0);
|
||||
|
||||
vec2 noise = rand2(texCoord) * namount * blur;
|
||||
float w = (texStep.x) * blur * maxblur + noise.x;
|
||||
float h = (texStep.y) * blur * maxblur + noise.y;
|
||||
vec3 col = vec3(0.0);
|
||||
if (blur < 0.05) {
|
||||
col = textureLod(tex, texCoord, 0.0).rgb;
|
||||
}
|
||||
else {
|
||||
col = textureLod(tex, texCoord, 0.0).rgb;
|
||||
float s = 1.0;
|
||||
int ringsamples;
|
||||
|
||||
for (int i = 1; i <= rings; ++i) {
|
||||
ringsamples = i * samples;
|
||||
for (int j = 0 ; j < ringsamples; ++j) {
|
||||
float step = PI2 / float(ringsamples);
|
||||
float pw = (cos(float(j) * step) * float(i));
|
||||
float ph = (sin(float(j) * step) * float(i));
|
||||
float p = 1.0;
|
||||
// if (pentagon) p = penta(vec2(pw, ph));
|
||||
col += color(texCoord + vec2(pw * w, ph * h), blur, tex, texStep) * mix(1.0, (float(i)) / (float(rings)), bias) * p;
|
||||
s += 1.0 * mix(1.0, (float(i)) / (float(rings)), bias) * p;
|
||||
}
|
||||
}
|
||||
col /= s;
|
||||
}
|
||||
return col;
|
||||
}
|
||||
|
60
leenkx/Shaders/std/filters.glsl
Normal file
60
leenkx/Shaders/std/filters.glsl
Normal file
@ -0,0 +1,60 @@
|
||||
|
||||
vec4 cubicCatmullrom(float x) {
|
||||
const float s = 0.5;
|
||||
float x2 = x * x;
|
||||
float x3 = x2 * x;
|
||||
vec4 w;
|
||||
w.x = -s*x3 + 2*s*x2 - s*x + 0;
|
||||
w.y = (2-s)*x3 + (s-3)*x2 + 1;
|
||||
w.z = (s-2)*x3 + (3-2*s)*x2 + s*x + 0;
|
||||
w.w = s*x3 - s*x2 + 0;
|
||||
return w;
|
||||
}
|
||||
|
||||
vec4 cubic(float v) {
|
||||
vec4 n = vec4(1.0, 2.0, 3.0, 4.0) - v;
|
||||
vec4 s = n * n * n;
|
||||
float x = s.x;
|
||||
float y = s.y - 4.0 * s.x;
|
||||
float z = s.z - 4.0 * s.y + 6.0 * s.x;
|
||||
float w = 6.0 - x - y - z;
|
||||
return vec4(x, y, z, w) * (1.0/6.0);
|
||||
}
|
||||
|
||||
vec3 textureBicubic(sampler2D tex, vec2 tc, vec2 texStep) {
|
||||
// http://www.java-gaming.org/index.php?topic=35123.0
|
||||
vec2 texSize = 1.0 / texStep;
|
||||
tc = tc * texSize - 0.5;
|
||||
|
||||
vec2 fxy = fract(tc);
|
||||
tc -= fxy;
|
||||
vec4 xcubic = cubic(fxy.x);
|
||||
vec4 ycubic = cubic(fxy.y);
|
||||
|
||||
vec4 c = tc.xxyy + vec2(-0.5, 1.5).xyxy;
|
||||
vec4 s = vec4(xcubic.xz + xcubic.yw, ycubic.xz + ycubic.yw);
|
||||
vec4 offset = c + vec4 (xcubic.yw, ycubic.yw) / s;
|
||||
offset *= texStep.xxyy;
|
||||
vec3 sample0 = texture(tex, offset.xz).rgb;
|
||||
vec3 sample1 = texture(tex, offset.yz).rgb;
|
||||
vec3 sample2 = texture(tex, offset.xw).rgb;
|
||||
vec3 sample3 = texture(tex, offset.yw).rgb;
|
||||
|
||||
float sx = s.x / (s.x + s.y);
|
||||
float sy = s.z / (s.z + s.w);
|
||||
|
||||
return mix(mix(sample3, sample2, sx), mix(sample1, sample0, sx), sy);
|
||||
}
|
||||
|
||||
vec4 textureSS(sampler2D tex, vec2 tc, vec2 texStep) {
|
||||
vec4 col = texture(tex, tc);
|
||||
col += texture(tex, tc + vec2(1.5, 0.0) * texStep);
|
||||
col += texture(tex, tc + vec2(-1.5, 0.0) * texStep);
|
||||
col += texture(tex, tc + vec2(0.0, 1.5) * texStep);
|
||||
col += texture(tex, tc + vec2(0.0, -1.5) * texStep);
|
||||
col += texture(tex, tc + vec2(1.5, 1.5) * texStep);
|
||||
col += texture(tex, tc + vec2(-1.5, -1.5) * texStep);
|
||||
col += texture(tex, tc + vec2(1.5, -1.5) * texStep);
|
||||
col += texture(tex, tc + vec2(-1.5, 1.5) * texStep);
|
||||
return col / 9.0;
|
||||
}
|
173
leenkx/Shaders/std/gbuffer.glsl
Normal file
173
leenkx/Shaders/std/gbuffer.glsl
Normal file
@ -0,0 +1,173 @@
|
||||
#ifndef _GBUFFER_GLSL_
|
||||
#define _GBUFFER_GLSL_
|
||||
|
||||
vec2 octahedronWrap(const vec2 v) {
|
||||
return (1.0 - abs(v.yx)) * (vec2(v.x >= 0.0 ? 1.0 : -1.0, v.y >= 0.0 ? 1.0 : -1.0));
|
||||
}
|
||||
|
||||
vec3 getNor(const vec2 enc) {
|
||||
vec3 n;
|
||||
n.z = 1.0 - abs(enc.x) - abs(enc.y);
|
||||
n.xy = n.z >= 0.0 ? enc.xy : octahedronWrap(enc.xy);
|
||||
n = normalize(n);
|
||||
return n;
|
||||
}
|
||||
|
||||
vec3 getPosView(const vec3 viewRay, const float depth, const vec2 cameraProj) {
|
||||
float linearDepth = cameraProj.y / (cameraProj.x - depth);
|
||||
//float linearDepth = cameraProj.y / ((depth * 0.5 + 0.5) - cameraProj.x);
|
||||
return viewRay * linearDepth;
|
||||
}
|
||||
|
||||
vec3 getPos(const vec3 eye, const vec3 eyeLook, const vec3 viewRay, const float depth, const vec2 cameraProj) {
|
||||
// eyeLook, viewRay should be normalized
|
||||
float linearDepth = cameraProj.y / ((depth * 0.5 + 0.5) - cameraProj.x);
|
||||
float viewZDist = dot(eyeLook, viewRay);
|
||||
vec3 wposition = eye + viewRay * (linearDepth / viewZDist);
|
||||
return wposition;
|
||||
}
|
||||
|
||||
vec3 getPosNoEye(const vec3 eyeLook, const vec3 viewRay, const float depth, const vec2 cameraProj) {
|
||||
// eyeLook, viewRay should be normalized
|
||||
float linearDepth = cameraProj.y / ((depth * 0.5 + 0.5) - cameraProj.x);
|
||||
float viewZDist = dot(eyeLook, viewRay);
|
||||
vec3 wposition = viewRay * (linearDepth / viewZDist);
|
||||
return wposition;
|
||||
}
|
||||
|
||||
#if defined(HLSL) || defined(METAL)
|
||||
vec3 getPos2(const mat4 invVP, const float depth, vec2 coord) {
|
||||
coord.y = 1.0 - coord.y;
|
||||
#else
|
||||
vec3 getPos2(const mat4 invVP, const float depth, const vec2 coord) {
|
||||
#endif
|
||||
vec4 pos = vec4(coord * 2.0 - 1.0, depth, 1.0);
|
||||
pos = invVP * pos;
|
||||
pos.xyz /= pos.w;
|
||||
return pos.xyz;
|
||||
}
|
||||
|
||||
#if defined(HLSL) || defined(METAL)
|
||||
vec3 getPosView2(const mat4 invP, const float depth, vec2 coord) {
|
||||
coord.y = 1.0 - coord.y;
|
||||
#else
|
||||
vec3 getPosView2(const mat4 invP, const float depth, const vec2 coord) {
|
||||
#endif
|
||||
vec4 pos = vec4(coord * 2.0 - 1.0, depth, 1.0);
|
||||
pos = invP * pos;
|
||||
pos.xyz /= pos.w;
|
||||
return pos.xyz;
|
||||
}
|
||||
|
||||
#if defined(HLSL) || defined(METAL)
|
||||
vec3 getPos2NoEye(const vec3 eye, const mat4 invVP, const float depth, vec2 coord) {
|
||||
coord.y = 1.0 - coord.y;
|
||||
#else
|
||||
vec3 getPos2NoEye(const vec3 eye, const mat4 invVP, const float depth, const vec2 coord) {
|
||||
#endif
|
||||
vec4 pos = vec4(coord * 2.0 - 1.0, depth, 1.0);
|
||||
pos = invVP * pos;
|
||||
pos.xyz /= pos.w;
|
||||
return pos.xyz - eye;
|
||||
}
|
||||
|
||||
float packFloat(const float f1, const float f2) {
|
||||
return floor(f1 * 100.0) + min(f2, 1.0 - 1.0 / 100.0);
|
||||
}
|
||||
|
||||
vec2 unpackFloat(const float f) {
|
||||
return vec2(floor(f) / 100.0, fract(f));
|
||||
}
|
||||
|
||||
float packFloat2(const float f1, const float f2) {
|
||||
// Higher f1 = less precise f2
|
||||
return floor(f1 * 255.0) + min(f2, 1.0 - 1.0 / 100.0);
|
||||
}
|
||||
|
||||
vec2 unpackFloat2(const float f) {
|
||||
return vec2(floor(f) / 255.0, fract(f));
|
||||
}
|
||||
|
||||
vec4 encodeRGBM(const vec3 rgb) {
|
||||
const float maxRange = 6.0;
|
||||
float maxRGB = max(rgb.x, max(rgb.g, rgb.b));
|
||||
float m = maxRGB / maxRange;
|
||||
m = ceil(m * 255.0) / 255.0;
|
||||
return vec4(rgb / (m * maxRange), m);
|
||||
}
|
||||
|
||||
vec3 decodeRGBM(const vec4 rgbm) {
|
||||
const float maxRange = 6.0;
|
||||
return rgbm.rgb * rgbm.a * maxRange;
|
||||
}
|
||||
|
||||
vec2 signNotZero(vec2 v)
|
||||
{
|
||||
return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);
|
||||
}
|
||||
|
||||
vec2 encode_oct(vec3 v)
|
||||
{
|
||||
// Project the sphere onto the octahedron, and then onto the xy plane
|
||||
vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));
|
||||
// Reflect the folds of the lower hemisphere over the diagonals
|
||||
return (v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p;
|
||||
}
|
||||
|
||||
vec3 decode_oct(vec2 e)
|
||||
{
|
||||
vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));
|
||||
if (v.z < 0) v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);
|
||||
return normalize(v);
|
||||
}
|
||||
|
||||
uint encNor(vec3 n) {
|
||||
ivec3 nor = ivec3(n * 255.0f);
|
||||
uvec3 norSigns;
|
||||
norSigns.x = (nor.x >> 5) & 0x04000000;
|
||||
norSigns.y = (nor.y >> 14) & 0x00020000;
|
||||
norSigns.z = (nor.z >> 23) & 0x00000100;
|
||||
nor = abs(nor);
|
||||
uint val = norSigns.x | (nor.x << 18) | norSigns.y | (nor.y << 9) | norSigns.z | nor.z;
|
||||
return val;
|
||||
}
|
||||
|
||||
vec3 decNor(uint val) {
|
||||
uvec3 nor;
|
||||
nor.x = (val >> 18) & 0x000000ff;
|
||||
nor.y = (val >> 9) & 0x000000ff;
|
||||
nor.z = val & 0x000000ff;
|
||||
uvec3 norSigns;
|
||||
norSigns.x = (val >> 25) & 0x00000002;
|
||||
norSigns.y = (val >> 16) & 0x00000002;
|
||||
norSigns.z = (val >> 7) & 0x00000002;
|
||||
norSigns = 1 - norSigns;
|
||||
vec3 normal = vec3(nor) / 255.0f;
|
||||
normal *= norSigns;
|
||||
return normal;
|
||||
}
|
||||
|
||||
/**
|
||||
Packs a float in [0, 1] and an integer in [0..15] into a single 16 bit float value.
|
||||
**/
|
||||
float packFloatInt16(const float f, const uint i) {
|
||||
const uint numBitFloat = 12;
|
||||
const float maxValFloat = float((1 << numBitFloat) - 1);
|
||||
|
||||
const uint bitsInt = i << numBitFloat;
|
||||
const uint bitsFloat = uint(f * maxValFloat);
|
||||
|
||||
return float(bitsInt | bitsFloat);
|
||||
}
|
||||
|
||||
void unpackFloatInt16(const float val, out float f, out uint i) {
|
||||
const uint numBitFloat = 12;
|
||||
const float maxValFloat = float((1 << numBitFloat) - 1);
|
||||
|
||||
const uint bitsValue = uint(val);
|
||||
|
||||
i = bitsValue >> numBitFloat;
|
||||
f = (bitsValue & ~(0xF << numBitFloat)) / maxValFloat;
|
||||
}
|
||||
|
||||
#endif
|
32
leenkx/Shaders/std/ies.glsl
Normal file
32
leenkx/Shaders/std/ies.glsl
Normal file
@ -0,0 +1,32 @@
|
||||
|
||||
uniform sampler2D texIES;
|
||||
|
||||
float iesAttenuation(vec3 l) {
|
||||
|
||||
const float PI = 3.1415926535;
|
||||
// https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
|
||||
// Sample direction into light space
|
||||
// vec3 iesSampleDirection = mul(light.worldToLight , -L);
|
||||
// Cartesian to spherical
|
||||
// Texture encoded with cos( phi ), scale from -1 - >1 to 0 - >1
|
||||
// float phiCoord = (iesSampleDirection.z * 0.5f) + 0.5f;
|
||||
// float theta = atan2 (iesSampleDirection.y , iesSampleDirection .x);
|
||||
// float thetaCoord = theta * (1.0 / (PI * 2.0));
|
||||
// float iesProfileScale = texture(texIES, vec2(thetaCoord, phiCoord)).r;
|
||||
// return iesProfileScale;
|
||||
|
||||
// 1D texture
|
||||
// vec3 pl = normalize(p - lightPos);
|
||||
// float f = asin(dot(pl, l)) / PI + 0.5;
|
||||
// return texture(texIES, vec2(f, 0.0)).r;
|
||||
|
||||
// 1D texture
|
||||
// float cosTheta = dot(lightToPos, lightDir);
|
||||
// float angle = acos(cosTheta) * (1.0 / PI);
|
||||
// return texture(texIES, vec2(angle, 0.0), 0.0).r;
|
||||
|
||||
// Based on https://github.com/tobspr/RenderPipeline
|
||||
float hor = acos(l.z) / PI;
|
||||
float vert = atan(l.x, l.y) * (1.0 / (PI * 2.0)) + 0.5;
|
||||
return texture(texIES, vec2(hor, vert)).r;
|
||||
}
|
84
leenkx/Shaders/std/imageatomic.glsl
Normal file
84
leenkx/Shaders/std/imageatomic.glsl
Normal file
@ -0,0 +1,84 @@
|
||||
|
||||
// Courtesy of
|
||||
// https://github.com/GreatBlambo/voxel_cone_tracing
|
||||
// https://www.seas.upenn.edu/~pcozzi/OpenGLInsights/OpenGLInsights-SparseVoxelization.pdf
|
||||
|
||||
|
||||
uint convVec4ToRGBA8(vec4 val) {
|
||||
vec4 col = vec4(val) * 255;
|
||||
return (uint(col.w) & 0x000000FF) << 24U
|
||||
| (uint(col.z) & 0x000000FF) << 16U
|
||||
| (uint(col.y) & 0x000000FF) << 8U
|
||||
| (uint(col.x) & 0x000000FF);
|
||||
}
|
||||
|
||||
vec4 convRGBA8ToVec4(uint val) {
|
||||
uvec4 col = uvec4(
|
||||
float((val & 0x000000FF)),
|
||||
float((val & 0x0000FF00) >> 8U),
|
||||
float((val & 0x00FF0000) >> 16U),
|
||||
float((val & 0xFF000000) >> 24U));
|
||||
return vec4(col) / 255;
|
||||
}
|
||||
|
||||
// uint encUnsignedNibble(uint m, uint n) {
|
||||
// return (m & 0xFEFEFEFE)
|
||||
// | (n & 0x00000001)
|
||||
// | (n & 0x00000002) << 7U
|
||||
// | (n & 0x00000004) << 14U
|
||||
// | (n & 0x00000008) << 21U;
|
||||
// }
|
||||
|
||||
// uint decUnsignedNibble(uint m) {
|
||||
// return (m & 0x00000001)
|
||||
// | (m & 0x00000100) >> 7U
|
||||
// | (m & 0x00010000) >> 14U
|
||||
// | (m & 0x01000000) >> 21U;
|
||||
// }
|
||||
|
||||
// void imageAtomicRGBA8Avg(layout(r32ui) uimage3D img, ivec3 coords, vec4 val) {
|
||||
// // LSBs are used for the sample counter of the moving average.
|
||||
// val *= 255.0;
|
||||
// uint newVal = encUnsignedNibble(convVec4ToRGBA8(val), 1);
|
||||
// uint prevStoredVal = 0;
|
||||
// uint currStoredVal;
|
||||
// int counter = 0;
|
||||
// // Loop as long as destination value gets changed by other threads
|
||||
// while ((currStoredVal = imageAtomicCompSwap(img, coords, prevStoredVal, newVal)) != prevStoredVal && counter < 16) {
|
||||
// vec4 rval = convRGBA8ToVec4(currStoredVal & 0xFEFEFEFE);
|
||||
// uint n = decUnsignedNibble(currStoredVal);
|
||||
// rval = rval * n + val;
|
||||
// rval /= ++n;
|
||||
// rval = round(rval / 2) * 2;
|
||||
// newVal = encUnsignedNibble(convVec4ToRGBA8(rval), n);
|
||||
// prevStoredVal = currStoredVal;
|
||||
// counter++;
|
||||
// }
|
||||
// }
|
||||
|
||||
// void imageAtomicFloatAdd(layout(r32ui) coherent volatile uimage3D imgUI, ivec3 coords, float val) {
|
||||
// uint newVal = floatBitsToUint(val);
|
||||
// uint prevVal = 0;
|
||||
// uint curVal;
|
||||
// // Loop as long as destination value gets changed by other threads
|
||||
// while ((curVal = imageAtomicCompSwap(imgUI, coords, prevVal, newVal)) != prevVal) {
|
||||
// prevVal = curVal;
|
||||
// newVal = floatBitsToUint((val + uintBitsToFloat(curVal)));
|
||||
// }
|
||||
// }
|
||||
|
||||
// void imageAtomicRGBA8Avg( layout ( r32ui ) coherent volatile uimage3D imgUI , ivec3 coords , vec4 val ) {
|
||||
// val.rgb *= 255.0f; // Optimise following calculations
|
||||
// uint newVal = convVec4ToRGBA8(val);
|
||||
// uint prevStoredVal = 0;
|
||||
// uint curStoredVal;
|
||||
// // Loop as long as destination value gets changed by other threads
|
||||
// while ((curStoredVal = imageAtomicCompSwap(imgUI, coords, prevStoredVal, newVal)) != prevStoredVal) {
|
||||
// prevStoredVal = curStoredVal;
|
||||
// vec4 rval = convRGBA8ToVec4(curStoredVal);
|
||||
// rval.xyz = (rval.xyz * rval.w) ; // Denormalize
|
||||
// vec4 curValF = rval + val; // Add new value
|
||||
// curValF.xyz /= (curValF.w); // Renormalize
|
||||
// newVal = convVec4ToRGBA8(curValF);
|
||||
// }
|
||||
// }
|
239
leenkx/Shaders/std/light.glsl
Normal file
239
leenkx/Shaders/std/light.glsl
Normal file
@ -0,0 +1,239 @@
|
||||
#ifndef _LIGHT_GLSL_
|
||||
#define _LIGHT_GLSL_
|
||||
|
||||
#include "compiled.inc"
|
||||
#include "std/brdf.glsl"
|
||||
#include "std/math.glsl"
|
||||
#ifdef _ShadowMap
|
||||
#include "std/shadows.glsl"
|
||||
#endif
|
||||
#ifdef _VoxelShadow
|
||||
#include "std/conetrace.glsl"
|
||||
//!uniform sampler2D voxels_shadows;
|
||||
#endif
|
||||
#ifdef _LTC
|
||||
#include "std/ltc.glsl"
|
||||
#endif
|
||||
#ifdef _LightIES
|
||||
#include "std/ies.glsl"
|
||||
#endif
|
||||
#ifdef _SSRS
|
||||
#include "std/ssrs.glsl"
|
||||
#endif
|
||||
#ifdef _Spot
|
||||
#include "std/light_common.glsl"
|
||||
#endif
|
||||
|
||||
#ifdef _ShadowMap
|
||||
#ifdef _SinglePoint
|
||||
#ifdef _Spot
|
||||
#ifndef _LTC
|
||||
uniform sampler2DShadow shadowMapSpot[1];
|
||||
uniform sampler2D shadowMapSpotTransparent[1];
|
||||
uniform mat4 LWVPSpot[1];
|
||||
#endif
|
||||
#else
|
||||
uniform samplerCubeShadow shadowMapPoint[1];
|
||||
uniform samplerCube shadowMapPointTransparent[1];
|
||||
uniform vec2 lightProj;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef _Clusters
|
||||
#ifdef _SingleAtlas
|
||||
//!uniform sampler2DShadow shadowMapAtlas;
|
||||
//!uniform sampler2D shadowMapAtlasTransparent;
|
||||
#endif
|
||||
uniform vec2 lightProj;
|
||||
#ifdef _ShadowMapAtlas
|
||||
#ifndef _SingleAtlas
|
||||
uniform sampler2DShadow shadowMapAtlasPoint;
|
||||
uniform sampler2D shadowMapAtlasPointTransparent;
|
||||
#endif
|
||||
#else
|
||||
uniform samplerCubeShadow shadowMapPoint[4];
|
||||
uniform samplerCube shadowMapPointTransparent[4];
|
||||
#endif
|
||||
#ifdef _Spot
|
||||
#ifdef _ShadowMapAtlas
|
||||
#ifndef _SingleAtlas
|
||||
uniform sampler2DShadow shadowMapAtlasSpot;
|
||||
uniform sampler2D shadowMapAtlasSpotTransparent;
|
||||
#endif
|
||||
#else
|
||||
uniform sampler2DShadow shadowMapSpot[4];
|
||||
uniform sampler2D shadowMapSpotTransparent[4];
|
||||
#endif
|
||||
uniform mat4 LWVPSpotArray[maxLightsCluster];
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _LTC
|
||||
uniform vec3 lightArea0;
|
||||
uniform vec3 lightArea1;
|
||||
uniform vec3 lightArea2;
|
||||
uniform vec3 lightArea3;
|
||||
uniform sampler2D sltcMat;
|
||||
uniform sampler2D sltcMag;
|
||||
#ifdef _ShadowMap
|
||||
#ifndef _Spot
|
||||
#ifdef _SinglePoint
|
||||
uniform sampler2DShadow shadowMapSpot[1];
|
||||
uniform sampler2D shadowMapSpotTransparent[1];
|
||||
uniform mat4 LWVPSpot[1];
|
||||
#endif
|
||||
#ifdef _Clusters
|
||||
uniform sampler2DShadow shadowMapSpot[maxLightsCluster];
|
||||
uniform sampler2D shadowMapSpotTransparent[maxLightsCluster];
|
||||
uniform mat4 LWVPSpotArray[maxLightsCluster];
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol,
|
||||
const vec3 albedo, const float rough, const float spec, const vec3 f0
|
||||
#ifdef _ShadowMap
|
||||
, int index, float bias, bool receiveShadow, bool transparent
|
||||
#endif
|
||||
#ifdef _Spot
|
||||
, const bool isSpot, const float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right
|
||||
#endif
|
||||
#ifdef _VoxelShadow
|
||||
, sampler3D voxels, sampler3D voxelsSDF, float clipmaps[10 * voxelgiClipmapCount]
|
||||
#endif
|
||||
#ifdef _MicroShadowing
|
||||
, float occ
|
||||
#endif
|
||||
#ifdef _SSRS
|
||||
, sampler2D gbufferD, mat4 invVP, vec3 eye
|
||||
#endif
|
||||
) {
|
||||
vec3 ld = lp - p;
|
||||
vec3 l = normalize(ld);
|
||||
vec3 h = normalize(v + l);
|
||||
float dotNH = max(0.0, dot(n, h));
|
||||
float dotVH = max(0.0, dot(v, h));
|
||||
float dotNL = max(0.0, dot(n, l));
|
||||
|
||||
#ifdef _LTC
|
||||
float theta = acos(dotNV);
|
||||
vec2 tuv = vec2(rough, theta / (0.5 * PI));
|
||||
tuv = tuv * LUT_SCALE + LUT_BIAS;
|
||||
vec4 t = textureLod(sltcMat, tuv, 0.0);
|
||||
mat3 invM = mat3(
|
||||
vec3(1.0, 0.0, t.y),
|
||||
vec3(0.0, t.z, 0.0),
|
||||
vec3(t.w, 0.0, t.x));
|
||||
float ltcspec = ltcEvaluate(n, v, dotNV, p, invM, lightArea0, lightArea1, lightArea2, lightArea3);
|
||||
ltcspec *= textureLod(sltcMag, tuv, 0.0).a;
|
||||
float ltcdiff = ltcEvaluate(n, v, dotNV, p, mat3(1.0), lightArea0, lightArea1, lightArea2, lightArea3);
|
||||
vec3 direct = albedo * ltcdiff + ltcspec * spec * 0.05;
|
||||
#else
|
||||
vec3 direct = lambertDiffuseBRDF(albedo, dotNL) +
|
||||
specularBRDF(f0, rough, dotNL, dotNH, dotNV, dotVH) * spec;
|
||||
#endif
|
||||
|
||||
direct *= attenuate(distance(p, lp));
|
||||
direct *= lightCol;
|
||||
|
||||
#ifdef _MicroShadowing
|
||||
direct *= clamp(dotNL + 2.0 * occ * occ - 1.0, 0.0, 1.0);
|
||||
#endif
|
||||
|
||||
#ifdef _SSRS
|
||||
direct *= traceShadowSS(l, p, gbufferD, invVP, eye);
|
||||
#endif
|
||||
|
||||
#ifdef _VoxelShadow
|
||||
direct *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, l, clipmaps, gl_FragCoord.xy).r) * voxelgiShad;
|
||||
#endif
|
||||
|
||||
#ifdef _LTC
|
||||
#ifdef _ShadowMap
|
||||
if (receiveShadow) {
|
||||
#ifdef _SinglePoint
|
||||
vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 10, 1.0);
|
||||
direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent);
|
||||
#endif
|
||||
#ifdef _Clusters
|
||||
vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0);
|
||||
if (index == 0) direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent);
|
||||
else if (index == 1) direct *= shadowTest(shadowMapSpot[1], shadowMapSpotTransparent[1], lPos.xyz / lPos.w, bias, transparent);
|
||||
else if (index == 2) direct *= shadowTest(shadowMapSpot[2], shadowMapSpotTransparent[2], lPos.xyz / lPos.w, bias, transparent);
|
||||
else if (index == 3) direct *= shadowTest(shadowMapSpot[3], shadowMapSpotTransparent[3], lPos.xyz / lPos.w, bias, transparent);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
return direct;
|
||||
#endif
|
||||
|
||||
#ifdef _Spot
|
||||
if (isSpot) {
|
||||
direct *= spotlightMask(l, spotDir, right, scale, spotSize, spotBlend);
|
||||
|
||||
#ifdef _ShadowMap
|
||||
if (receiveShadow) {
|
||||
#ifdef _SinglePoint
|
||||
vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0);
|
||||
direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent);
|
||||
#endif
|
||||
#ifdef _Clusters
|
||||
vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0);
|
||||
#ifdef _ShadowMapAtlas
|
||||
direct *= shadowTest(
|
||||
#ifndef _SingleAtlas
|
||||
shadowMapAtlasSpot, shadowMapAtlasSpotTransparent
|
||||
#else
|
||||
shadowMapAtlas, shadowMapAtlasTransparent
|
||||
#endif
|
||||
, lPos.xyz / lPos.w, bias, transparent
|
||||
);
|
||||
#else
|
||||
if (index == 0) direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent);
|
||||
else if (index == 1) direct *= shadowTest(shadowMapSpot[1], shadowMapSpotTransparent[1], lPos.xyz / lPos.w, bias, transparent);
|
||||
else if (index == 2) direct *= shadowTest(shadowMapSpot[2], shadowMapSpotTransparent[2], lPos.xyz / lPos.w, bias, transparent);
|
||||
else if (index == 3) direct *= shadowTest(shadowMapSpot[3], shadowMapSpotTransparent[3], lPos.xyz / lPos.w, bias, transparent);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
return direct;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _LightIES
|
||||
direct *= iesAttenuation(-l);
|
||||
#endif
|
||||
|
||||
#ifdef _ShadowMap
|
||||
if (receiveShadow) {
|
||||
#ifdef _SinglePoint
|
||||
#ifndef _Spot
|
||||
direct *= PCFCube(shadowMapPoint[0], shadowMapPointTransparent[0], ld, -l, bias, lightProj, n, transparent);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef _Clusters
|
||||
#ifdef _ShadowMapAtlas
|
||||
direct *= PCFFakeCube(
|
||||
#ifndef _SingleAtlas
|
||||
shadowMapAtlasPoint, shadowMapAtlasPointTransparent
|
||||
#else
|
||||
shadowMapAtlas, shadowMapAtlasTransparent
|
||||
#endif
|
||||
, ld, -l, bias, lightProj, n, index, transparent
|
||||
);
|
||||
#else
|
||||
if (index == 0) direct *= PCFCube(shadowMapPoint[0], shadowMapPointTransparent[0], ld, -l, bias, lightProj, n, transparent);
|
||||
else if (index == 1) direct *= PCFCube(shadowMapPoint[1], shadowMapPointTransparent[1], ld, -l, bias, lightProj, n, transparent);
|
||||
else if (index == 2) direct *= PCFCube(shadowMapPoint[2], shadowMapPointTransparent[2], ld, -l, bias, lightProj, n, transparent);
|
||||
else if (index == 3) direct *= PCFCube(shadowMapPoint[3], shadowMapPointTransparent[3], ld, -l, bias, lightProj, n, transparent);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
return direct;
|
||||
}
|
||||
|
||||
#endif
|
31
leenkx/Shaders/std/light_common.glsl
Normal file
31
leenkx/Shaders/std/light_common.glsl
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef _LIGHT_COMMON_GLSL_
|
||||
#define _LIGHT_COMMON_GLSL_
|
||||
|
||||
#ifdef _Spot
|
||||
float spotlightMask(const vec3 dir, const vec3 spotDir, const vec3 right, const vec2 scale, const float spotSize, const float spotBlend) {
|
||||
// Project the fragment's light dir to the z axis in the light's local space
|
||||
float localZ = dot(spotDir, dir);
|
||||
|
||||
if (localZ < 0) {
|
||||
return 0.0; // Discard opposite cone
|
||||
}
|
||||
|
||||
vec3 up = cross(spotDir, right);
|
||||
|
||||
// Scale the incoming light direction to treat the spotlight's ellipse as if
|
||||
// it was 1 unit away from the light source, this way the smoothstep below
|
||||
// works independently of the distance
|
||||
vec3 scaledDir = dir.xyz / localZ;
|
||||
|
||||
// Project to right and up vectors to apply axis scale
|
||||
float localX = dot(scaledDir, right) / scale.x;
|
||||
float localY = dot(scaledDir, up) / scale.y;
|
||||
|
||||
// Inverse of length of vector from ellipse to light (scaledDir.z == 1.0)
|
||||
float ellipse = inversesqrt(localX * localX + localY * localY + 1.0);
|
||||
|
||||
return smoothstep(0.0, 1.0, (ellipse - spotSize) / spotBlend);
|
||||
}
|
||||
#endif // _Spot
|
||||
|
||||
#endif // _LIGHT_COMMON_GLSL_
|
135
leenkx/Shaders/std/light_mobile.glsl
Normal file
135
leenkx/Shaders/std/light_mobile.glsl
Normal file
@ -0,0 +1,135 @@
|
||||
#ifndef _LIGHT_MOBILE_GLSL_
|
||||
#define _LIGHT_MOBILE_GLSL_
|
||||
|
||||
#include "compiled.inc"
|
||||
#include "std/brdf.glsl"
|
||||
#ifdef _ShadowMap
|
||||
#include "std/shadows.glsl"
|
||||
#endif
|
||||
#ifdef _Spot
|
||||
#include "std/light_common.glsl"
|
||||
#endif
|
||||
|
||||
#ifdef _ShadowMap
|
||||
#ifdef _SinglePoint
|
||||
#ifdef _Spot
|
||||
uniform sampler2DShadow shadowMapSpot[1];
|
||||
uniform mat4 LWVPSpot[1];
|
||||
#else
|
||||
uniform samplerCubeShadow shadowMapPoint[1];
|
||||
uniform vec2 lightProj;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef _Clusters
|
||||
#ifdef _SingleAtlas
|
||||
//!uniform sampler2DShadow shadowMapAtlas;
|
||||
#endif
|
||||
uniform vec2 lightProj;
|
||||
#ifdef _ShadowMapAtlas
|
||||
#ifndef _SingleAtlas
|
||||
uniform sampler2DShadow shadowMapAtlasPoint;
|
||||
#endif
|
||||
#else
|
||||
uniform samplerCubeShadow shadowMapPoint[4];
|
||||
#endif
|
||||
#ifdef _Spot
|
||||
#ifdef _ShadowMapAtlas
|
||||
#ifndef _SingleAtlas
|
||||
uniform sampler2DShadow shadowMapAtlasSpot;
|
||||
#endif
|
||||
#else
|
||||
uniform sampler2DShadow shadowMapSpot[maxLightsCluster];
|
||||
#endif
|
||||
uniform mat4 LWVPSpotArray[maxLightsCluster];
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol,
|
||||
const vec3 albedo, const float rough, const float spec, const vec3 f0
|
||||
#ifdef _ShadowMap
|
||||
, int index, float bias, bool receiveShadow
|
||||
#endif
|
||||
#ifdef _Spot
|
||||
, bool isSpot, float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right
|
||||
#endif
|
||||
) {
|
||||
vec3 ld = lp - p;
|
||||
vec3 l = normalize(ld);
|
||||
vec3 h = normalize(v + l);
|
||||
float dotNH = max(0.0, dot(n, h));
|
||||
float dotVH = max(0.0, dot(v, h));
|
||||
float dotNL = max(0.0, dot(n, l));
|
||||
|
||||
vec3 direct = lambertDiffuseBRDF(albedo, dotNL) +
|
||||
specularBRDF(f0, rough, dotNL, dotNH, dotNV, dotVH) * spec;
|
||||
|
||||
direct *= lightCol;
|
||||
direct *= attenuate(distance(p, lp));
|
||||
|
||||
#ifdef _Spot
|
||||
if (isSpot) {
|
||||
direct *= spotlightMask(l, spotDir, right, scale, spotSize, spotBlend);
|
||||
|
||||
#ifdef _ShadowMap
|
||||
if (receiveShadow) {
|
||||
#ifdef _SinglePoint
|
||||
vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0);
|
||||
direct *= shadowTest(shadowMapSpot[0], lPos.xyz / lPos.w, bias);
|
||||
#endif
|
||||
#ifdef _Clusters
|
||||
vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0);
|
||||
#ifdef _ShadowMapAtlas
|
||||
direct *= shadowTest(
|
||||
#ifndef _SingleAtlas
|
||||
shadowMapAtlasSpot
|
||||
#else
|
||||
shadowMapAtlas
|
||||
#endif
|
||||
, lPos.xyz / lPos.w, bias
|
||||
);
|
||||
#else
|
||||
if (index == 0) direct *= shadowTest(shadowMapSpot[0], lPos.xyz / lPos.w, bias);
|
||||
else if (index == 1) direct *= shadowTest(shadowMapSpot[1], lPos.xyz / lPos.w, bias);
|
||||
else if (index == 2) direct *= shadowTest(shadowMapSpot[2], lPos.xyz / lPos.w, bias);
|
||||
else if (index == 3) direct *= shadowTest(shadowMapSpot[3], lPos.xyz / lPos.w, bias);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
return direct;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _ShadowMap
|
||||
|
||||
if (receiveShadow) {
|
||||
#ifdef _SinglePoint
|
||||
#ifndef _Spot
|
||||
direct *= PCFCube(shadowMapPoint[0], ld, -l, bias, lightProj, n);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef _Clusters
|
||||
#ifdef _ShadowMapAtlas
|
||||
direct *= PCFFakeCube(
|
||||
#ifndef _SingleAtlas
|
||||
shadowMapAtlasPoint
|
||||
#else
|
||||
shadowMapAtlas
|
||||
#endif
|
||||
, ld, -l, bias, lightProj, n, index
|
||||
);
|
||||
#else
|
||||
if (index == 0) direct *= PCFCube(shadowMapPoint[0], ld, -l, bias, lightProj, n);
|
||||
else if (index == 1) direct *= PCFCube(shadowMapPoint[1], ld, -l, bias, lightProj, n);
|
||||
else if (index == 2) direct *= PCFCube(shadowMapPoint[2], ld, -l, bias, lightProj, n);
|
||||
else if (index == 3) direct *= PCFCube(shadowMapPoint[3], ld, -l, bias, lightProj, n);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
return direct;
|
||||
}
|
||||
|
||||
#endif
|
157
leenkx/Shaders/std/ltc.glsl
Normal file
157
leenkx/Shaders/std/ltc.glsl
Normal file
@ -0,0 +1,157 @@
|
||||
// Linearly Transformed Cosines
|
||||
// https://eheitzresearch.wordpress.com/415-2/
|
||||
|
||||
const float LUT_SIZE = 64.0;
|
||||
const float LUT_SCALE = (LUT_SIZE - 1.0) / LUT_SIZE;
|
||||
const float LUT_BIAS = 0.5 / LUT_SIZE;
|
||||
|
||||
vec3 L0;
|
||||
vec3 L1;
|
||||
vec3 L2;
|
||||
vec3 L3;
|
||||
vec3 L4;
|
||||
|
||||
float integrateEdge(vec3 v1, vec3 v2) {
|
||||
float cosTheta = dot(v1, v2);
|
||||
float theta = acos(cosTheta);
|
||||
float res = cross(v1, v2).z * ((theta > 0.001) ? theta / sin(theta) : 1.0);
|
||||
return res;
|
||||
}
|
||||
|
||||
int clipQuadToHorizon(/*inout vec3 L[5], out int n*/) {
|
||||
int n = 0;
|
||||
// Detect clipping config
|
||||
int config = 0;
|
||||
if (L0.z > 0.0) config += 1;
|
||||
if (L1.z > 0.0) config += 2;
|
||||
if (L2.z > 0.0) config += 4;
|
||||
if (L3.z > 0.0) config += 8;
|
||||
|
||||
// Clip
|
||||
if (config == 0) {
|
||||
// Clip all
|
||||
}
|
||||
else if (config == 1) { // V1 clip V2 V3 V4
|
||||
n = 3;
|
||||
L1 = -L1.z * L0 + L0.z * L1;
|
||||
L2 = -L3.z * L0 + L0.z * L3;
|
||||
}
|
||||
else if (config == 2) { // V2 clip V1 V3 V4
|
||||
n = 3;
|
||||
L0 = -L0.z * L1 + L1.z * L0;
|
||||
L2 = -L2.z * L1 + L1.z * L2;
|
||||
}
|
||||
else if (config == 3) { // V1 V2 clip V3 V4
|
||||
n = 4;
|
||||
L2 = -L2.z * L1 + L1.z * L2;
|
||||
L3 = -L3.z * L0 + L0.z * L3;
|
||||
}
|
||||
else if (config == 4) { // V3 clip V1 V2 V4
|
||||
n = 3;
|
||||
L0 = -L3.z * L2 + L2.z * L3;
|
||||
L1 = -L1.z * L2 + L2.z * L1;
|
||||
}
|
||||
else if (config == 5) { // V1 V3 clip V2 V4) impossible
|
||||
n = 0;
|
||||
}
|
||||
else if (config == 6) { // V2 V3 clip V1 V4
|
||||
n = 4;
|
||||
L0 = -L0.z * L1 + L1.z * L0;
|
||||
L3 = -L3.z * L2 + L2.z * L3;
|
||||
}
|
||||
else if (config == 7) { // V1 V2 V3 clip V4
|
||||
n = 5;
|
||||
L4 = -L3.z * L0 + L0.z * L3;
|
||||
L3 = -L3.z * L2 + L2.z * L3;
|
||||
}
|
||||
else if (config == 8) { // V4 clip V1 V2 V3
|
||||
n = 3;
|
||||
L0 = -L0.z * L3 + L3.z * L0;
|
||||
L1 = -L2.z * L3 + L3.z * L2;
|
||||
L2 = L3;
|
||||
}
|
||||
else if (config == 9) { // V1 V4 clip V2 V3
|
||||
n = 4;
|
||||
L1 = -L1.z * L0 + L0.z * L1;
|
||||
L2 = -L2.z * L3 + L3.z * L2;
|
||||
}
|
||||
else if (config == 10) { // V2 V4 clip V1 V3) impossible
|
||||
n = 0;
|
||||
}
|
||||
else if (config == 11) { // V1 V2 V4 clip V3
|
||||
n = 5;
|
||||
L4 = L3;
|
||||
L3 = -L2.z * L3 + L3.z * L2;
|
||||
L2 = -L2.z * L1 + L1.z * L2;
|
||||
}
|
||||
else if (config == 12) { // V3 V4 clip V1 V2
|
||||
n = 4;
|
||||
L1 = -L1.z * L2 + L2.z * L1;
|
||||
L0 = -L0.z * L3 + L3.z * L0;
|
||||
}
|
||||
else if (config == 13) { // V1 V3 V4 clip V2
|
||||
n = 5;
|
||||
L4 = L3;
|
||||
L3 = L2;
|
||||
L2 = -L1.z * L2 + L2.z * L1;
|
||||
L1 = -L1.z * L0 + L0.z * L1;
|
||||
}
|
||||
else if (config == 14) { // V2 V3 V4 clip V1
|
||||
n = 5;
|
||||
L4 = -L0.z * L3 + L3.z * L0;
|
||||
L0 = -L0.z * L1 + L1.z * L0;
|
||||
}
|
||||
else if (config == 15) { // V1 V2 V3 V4
|
||||
n = 4;
|
||||
}
|
||||
|
||||
if (n == 3) L3 = L0;
|
||||
if (n == 4) L4 = L0;
|
||||
return n;
|
||||
}
|
||||
|
||||
float ltcEvaluate(vec3 N, vec3 V, float dotNV, vec3 P, mat3 Minv, vec3 points0, vec3 points1, vec3 points2, vec3 points3) {
|
||||
// Construct orthonormal basis around N
|
||||
vec3 T1, T2;
|
||||
T1 = normalize(V - N * dotNV);
|
||||
T2 = cross(N, T1);
|
||||
|
||||
// Rotate area light in (T1, T2, R) basis
|
||||
Minv = Minv * transpose(mat3(T1, T2, N));
|
||||
|
||||
// Polygon (allocate 5 vertices for clipping)
|
||||
// vec3 L[5];
|
||||
L0 = Minv * (points0 - P);
|
||||
L1 = Minv * (points1 - P);
|
||||
L2 = Minv * (points2 - P);
|
||||
L3 = Minv * (points3 - P);
|
||||
L4 = vec3(0.0);
|
||||
|
||||
// int n;
|
||||
int n = clipQuadToHorizon(/*L, n*/);
|
||||
|
||||
if (n == 0) return 0.0;
|
||||
|
||||
// Project onto sphere
|
||||
L0 = normalize(L0);
|
||||
L1 = normalize(L1);
|
||||
L2 = normalize(L2);
|
||||
L3 = normalize(L3);
|
||||
L4 = normalize(L4);
|
||||
|
||||
// Integrate
|
||||
float sum = 0.0;
|
||||
|
||||
sum += integrateEdge(L0, L1);
|
||||
sum += integrateEdge(L1, L2);
|
||||
sum += integrateEdge(L2, L3);
|
||||
|
||||
if (n >= 4) sum += integrateEdge(L3, L4);
|
||||
if (n == 5) sum += integrateEdge(L4, L0);
|
||||
|
||||
#ifdef _TwoSidedAreaLight
|
||||
return abs(sum);
|
||||
#else
|
||||
return max(0.0, -sum);
|
||||
#endif
|
||||
}
|
41
leenkx/Shaders/std/mapping.glsl
Normal file
41
leenkx/Shaders/std/mapping.glsl
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
https://github.com/JonasFolletete/glsl-triplanar-mapping
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 Jonas Folletête
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
vec3 blendNormal(vec3 normal) {
|
||||
vec3 blending = abs(normal);
|
||||
blending = normalize(max(blending, 0.00001));
|
||||
blending /= vec3(blending.x + blending.y + blending.z);
|
||||
return blending;
|
||||
}
|
||||
|
||||
vec3 triplanarMapping (sampler2D ImageTexture, vec3 normal, vec3 position) {
|
||||
vec3 normalBlend = blendNormal(normal);
|
||||
vec3 xColor = texture(ImageTexture, position.yz).rgb;
|
||||
vec3 yColor = texture(ImageTexture, position.xz).rgb;
|
||||
vec3 zColor = texture(ImageTexture, position.xy).rgb;
|
||||
|
||||
return (xColor * normalBlend.x + yColor * normalBlend.y + zColor * normalBlend.z);
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user