Update Files

This commit is contained in:
2025-01-22 16:18:30 +01:00
parent ed4603cf95
commit a36294b518
16718 changed files with 2960346 additions and 0 deletions

View 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"
}
]
}

View 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"
}
]
}

View 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;
}

View 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;
}

View File

@ -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);
}

View 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"
}
]
}

View File

@ -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);
}

View File

@ -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"
}
]
}

View 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;
}

View 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"
}
]
}

View 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;
}

View 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"
}
]
}

View 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);
}

View 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"
}
]
}

View File

@ -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);
}
}

View File

@ -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"
}
]
}

View File

@ -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;
}

View File

@ -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"]
}
]
}

View File

@ -0,0 +1,8 @@
#version 450
in vec2 texCoord;
out vec4 fragColor;
void main() {
fragColor = vec4(0.0, 0.0, 0.0, 1.0);
}

View 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"]
}
]
}

View File

@ -0,0 +1,8 @@
#version 450
in vec2 texCoord;
out vec4 fragColor;
void main() {
gl_FragDepth = 1.0;
}

View 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"]
}
]
}

View 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
}

View 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"
}
]
}

View 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
}

View 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);
}

View 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"
}
]
}

View 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);
}

View 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"
}
]
}

View 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"
}
]
}

View File

@ -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
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -0,0 +1,8 @@
#version 450
in vec3 color;
out vec4 fragColor;
void main() {
fragColor = vec4(color, 1.0);
}

View 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);
}

View 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
}

View 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
}

View 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"]
}
]
}

View 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
}

View 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"]
}
]
}

View 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
}

View File

@ -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"]
}
]
}

View 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));
}

View 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"
}
]
}

View 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;
}

View 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"
}
]
}

View 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;
}

View 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"
}
]
}

View 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);
}

View File

@ -0,0 +1,10 @@
#version 450
uniform sampler2D tex;
in vec2 texCoord;
out vec4 fragColor;
void main() {
fragColor = textureLod(tex, texCoord, 0.0);
}

View 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;
}

View 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);
}

View 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;
}

View 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;
}

View 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"
}
]
}

View File

@ -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);
}

View File

@ -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"
}
]
}

View 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;
}

View 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"
}
]
}

View 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;
}

View 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"
}
]
}

View 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));
}

View 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"
}
]
}

View 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);
}

View 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);
}

View 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"
}
]
}

View 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);
}

View File

@ -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);
}

View File

@ -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"
}
]
}

View File

@ -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);
}

View 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;
}

View 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"
}
]
}

View 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;
}

View 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"
}
]
}

View 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;
}

View 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"
}
]
}

View 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
}

View 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"
}
]
}

View 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;
}

View 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"
}
]
}

View 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);
}

View 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"
}
]
}

View 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);
}
}

View 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"
}
]
}

View 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

View 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);
}

View 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);
}

View 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_

View 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

View 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;
}

View 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;
}

View 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

View 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;
}

View 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);
// }
// }

View 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

View 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_

View 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
View 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
}

View 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