engine/bin/data/shaders/display/deferred/comp/comp.h

361 lines
12 KiB
C

#extension GL_EXT_samplerless_texture_functions : require
#extension GL_EXT_nonuniform_qualifier : enable
#if RT
#extension GL_EXT_ray_tracing : enable
#extension GL_EXT_ray_query : enable
#endif
layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
#define COMPUTE 1
#define DEFERRED 1
#define DEFERRED_SAMPLING 1
#define PBR 1
#define LAMBERT 0
#define FOG 1
#define FOG_RAY_MARCH 1
#include "../../../common/macros.h"
layout (constant_id = 0) const uint TEXTURES = 512;
layout (constant_id = 1) const uint CUBEMAPS = 128;
#if VXGI
layout (constant_id = 2) const uint CASCADES = 16;
#endif
#if !MULTISAMPLING
layout(binding = 0) uniform utexture2D samplerId;
#if BARYCENTRIC
#if !BARYCENTRIC_CALCULATE
layout(binding = 1) uniform texture2D samplerBary;
#endif
#else
layout(binding = 1) uniform texture2D samplerUv;
layout(binding = 2) uniform texture2D samplerNormal;
#endif
layout(binding = 3) uniform texture2D samplerDepth;
#else
layout(binding = 0) uniform utexture2DMS samplerId;
#if BARYCENTRIC
#if !BARYCENTRIC_CALCULATE
layout(binding = 1) uniform texture2DMS samplerBary;
#endif
#else
layout(binding = 1) uniform texture2DMS samplerUv;
layout(binding = 2) uniform texture2DMS samplerNormal;
#endif
layout(binding = 3) uniform texture2DMS samplerDepth;
#endif
layout(binding = 7, rgba16f) uniform volatile coherent image2D imageColor;
layout(binding = 8, rgba16f) uniform volatile coherent image2D imageBright;
layout(binding = 9, rg16f) uniform volatile coherent image2D imageMotion;
layout( push_constant ) uniform PushBlock {
uint pass;
uint draw;
} PushConstant;
#include "../../../common/structs.h"
layout (binding = 10) uniform UBO {
EyeMatrices eyes[2];
Settings settings;
} ubo;
/*
*/
layout (std140, binding = 11) readonly buffer DrawCommands {
DrawCommand drawCommands[];
};
layout (std140, binding = 12) readonly buffer Instances {
Instance instances[];
};
layout (std140, binding = 13) readonly buffer InstanceAddresseses {
InstanceAddresses instanceAddresses[];
};
layout (std140, binding = 14) readonly buffer Objects {
Object objects[];
};
layout (std140, binding = 15) readonly buffer Materials {
Material materials[];
};
layout (std140, binding = 16) readonly buffer Textures {
Texture textures[];
};
layout (std140, binding = 17) readonly buffer Lights {
Light lights[];
};
layout (binding = 18) uniform sampler2D samplerTextures[TEXTURES];
layout (binding = 19) uniform samplerCube samplerCubemaps[CUBEMAPS];
layout (binding = 20) uniform sampler3D samplerNoise;
#if VXGI
layout (binding = 21) uniform usampler3D voxelDrawId[CASCADES];
layout (binding = 22) uniform usampler3D voxelInstanceId[CASCADES];
layout (binding = 23) uniform sampler3D voxelNormalX[CASCADES];
layout (binding = 24) uniform sampler3D voxelNormalY[CASCADES];
layout (binding = 25) uniform sampler3D voxelRadianceR[CASCADES];
layout (binding = 26) uniform sampler3D voxelRadianceG[CASCADES];
layout (binding = 27) uniform sampler3D voxelRadianceB[CASCADES];
layout (binding = 28) uniform sampler3D voxelRadianceA[CASCADES];
layout (binding = 29) uniform sampler3D voxelCount[CASCADES];
layout (binding = 30) uniform sampler3D voxelOutput[CASCADES];
#endif
#if RT
layout (binding = 31) uniform accelerationStructureEXT tlas;
#endif
#if BUFFER_REFERENCE
//layout(buffer_reference, scalar) buffer Vertices { Vertex v[]; };
layout(buffer_reference, scalar) buffer Indices { uint i[]; };
//layout(buffer_reference, scalar) buffer Indices { uvec3 i[]; };
layout(buffer_reference, scalar) buffer Indirects { DrawCommand dc[]; };
//layout(buffer_reference, scalar) buffer VPos { vec3 v[]; };
layout(buffer_reference, scalar) buffer VPos { float v[]; };
layout(buffer_reference, scalar) buffer VUv { vec2 v[]; };
//layout(buffer_reference, scalar) buffer VUv { float v[]; };
layout(buffer_reference, scalar) buffer VColor { uint v[]; };
layout(buffer_reference, scalar) buffer VSt { vec2 v[]; };
//layout(buffer_reference, scalar) buffer VSt { float v[]; };
//layout(buffer_reference, scalar) buffer VNormal { vec3 v[]; };
layout(buffer_reference, scalar) buffer VNormal { float v[]; };
//layout(buffer_reference, scalar) buffer VTangent { vec3 v[]; };
layout(buffer_reference, scalar) buffer VTangent { float v[]; };
layout(buffer_reference, scalar) buffer VID { uint v[]; };
#endif
#include "../../../common/functions.h"
#include "../../../common/fog.h"
#include "../../../common/light.h"
#include "../../../common/shadows.h"
#if VXGI
#include "../../../common/vxgi.h"
#endif
#if RT
#include "../../../common/rt.h"
#endif
#if MULTISAMPLING
#define IMAGE_LOAD(X) texelFetch( X, ivec2(gl_GlobalInvocationID.xy), msaa.currentID )
#else
#define IMAGE_LOAD(X) texelFetch( X, ivec2(gl_GlobalInvocationID.xy), 0 )
#endif
#define IMAGE_STORE(X, Y) imageStore( X, ivec2(gl_GlobalInvocationID.xy), Y )
bool USE_SKYBOX_ON_DIVERGENCE = false;
void postProcess() {
if ( USE_SKYBOX_ON_DIVERGENCE ) {
if ( 0 <= ubo.settings.lighting.indexSkybox && ubo.settings.lighting.indexSkybox < CUBEMAPS ) {
surface.fragment.rgb = texture( samplerCubemaps[ubo.settings.lighting.indexSkybox], surface.ray.direction ).rgb;
}
}
#if FOG
fog( surface.ray, surface.fragment.rgb, surface.fragment.a );
#endif
float brightness = dot(surface.fragment.rgb, vec3(0.2126, 0.7152, 0.0722));
bool bloom = brightness > ubo.settings.bloom.threshold;
//if ( bloom ) toneMap( surface.fragment.rgb, brightness );
vec4 outFragColor = vec4(surface.fragment.rgb, 1.0);
vec4 outFragBright = bloom ? vec4(surface.fragment.rgb, 1.0) : vec4(0, 0, 0, 1);
vec2 outFragMotion = surface.motion;
if ( ubo.settings.mode.type > 0x0000 ) {
uvec2 renderSize = imageSize(imageColor);
vec2 inUv = (vec2(gl_GlobalInvocationID.xy) / vec2(renderSize)) * 2.0f - 1.0f;
if ( true ) {
// if ( ubo.settings.mode.type == 0x0001 ) outFragColor = vec4(surface.barycentric.rgb, 1);
if ( ubo.settings.mode.type == 0x0001 ) outFragColor = vec4(surface.material.albedo.rgb, 1);
else if ( ubo.settings.mode.type == 0x0002 ) outFragColor = vec4(surface.light.rgb, 1);
else if ( ubo.settings.mode.type == 0x0003 ) outFragColor = vec4(vec3(surface.light.a), 1);
else if ( ubo.settings.mode.type == 0x0004 ) outFragColor = vec4(surface.normal.eye.rgb, 1);
else if ( ubo.settings.mode.type == 0x0005 ) outFragColor = vec4(surface.uv.xy, 0, 1);
else if ( ubo.settings.mode.type == 0x0006 ) outFragColor = vec4(surface.st.xy, 0, 1);
else if ( ubo.settings.mode.type == 0x0007 ) outFragColor = vec4(vec3(surface.material.metallic), 1);
else if ( ubo.settings.mode.type == 0x0008 ) outFragColor = vec4(vec3(surface.material.roughness * 4), 1);
else if ( ubo.settings.mode.type == 0x0009 ) outFragColor = vec4(vec3(surface.material.occlusion), 1);
}
}
IMAGE_STORE( imageColor, outFragColor );
IMAGE_STORE( imageBright, outFragBright );
IMAGE_STORE( imageMotion, vec4(outFragMotion, 0, 0) );
}
void populateSurface() {
const uvec2 renderSize = imageSize(imageColor);
if ( gl_GlobalInvocationID.x >= renderSize.x || gl_GlobalInvocationID.y >= renderSize.y || gl_GlobalInvocationID.z > PushConstant.pass ) return;
surface.pass = PushConstant.pass;
surface.fragment = vec4(0);
surface.light = vec4(0);
surface.motion = vec2(0);
surface.material.indirect = vec4(0);
surface.material.metallic = 1;
surface.material.roughness = 0;
surface.material.occlusion = 0;
float depth = 0.0;
{
vec2 inUv = (vec2(gl_GlobalInvocationID.xy) / vec2(renderSize)) * 2.0f - 1.0f;
const mat4 iProjectionView = inverse( ubo.eyes[surface.pass].projection * mat4(mat3(ubo.eyes[surface.pass].view)) );
const vec4 near4 = iProjectionView * (vec4(inUv, -1.0, 1.0));
const vec4 far4 = iProjectionView * (vec4(inUv, 1.0, 1.0));
const vec3 near3 = near4.xyz / near4.w;
const vec3 far3 = far4.xyz / far4.w;
surface.ray.direction = normalize( far3 - near3 );
// surface.ray.origin = near3.xyz;
surface.ray.origin = ubo.eyes[surface.pass].eyePos.xyz;
// surface.ray.origin = vec3( -ubo.eyes[surface.pass].view[0][3], -ubo.eyes[surface.pass].view[1][3], -ubo.eyes[surface.pass].view[2][3] );
depth = IMAGE_LOAD(samplerDepth).r;
vec4 eye = ubo.eyes[surface.pass].iProjection * vec4(inUv, depth, 1.0);
eye /= eye.w;
surface.position.eye = eye.xyz;
surface.position.world = vec3( ubo.eyes[surface.pass].iView * eye );
}
#if !MULTISAMPLING
const uvec2 ID = uvec2(IMAGE_LOAD(samplerId).xy);
#else
const uvec2 ID = msaa.IDs[msaa.currentID];
#endif
if ( ID.x == 0 || ID.y == 0 || depth <= 0.0 ) {
USE_SKYBOX_ON_DIVERGENCE = true;
}
/*
if ( ID.x == 0 || ID.y == 0 || depth <= 0.0 ) {
if ( 0 <= ubo.settings.lighting.indexSkybox && ubo.settings.lighting.indexSkybox < CUBEMAPS ) {
surface.fragment.rgb = texture( samplerCubemaps[ubo.settings.lighting.indexSkybox], surface.ray.direction ).rgb;
}
return;
}
*/
{
const uint triangleID = ID.x == 0 ? 0 : ID.x - 1;
const uint instanceID = ID.y == 0 ? 0 : ID.y - 1;
surface.subID = 1;
#if BARYCENTRIC
#if !BARYCENTRIC_CALCULATE
surface.barycentric = decodeBarycentrics(IMAGE_LOAD(samplerBary).xy).xyz;
#endif
populateSurface( instanceID, triangleID );
#else
vec4 uvst = IMAGE_LOAD(samplerUv);
vec4 normaltangent = IMAGE_LOAD(samplerNormal);
surface.uv.xy = uvst.xy;
surface.uv.z = 0;
surface.st.xy = uvst.zw;
surface.st.z = 0;
surface.normal.world = decodeNormals(normaltangent.xy);
// surface.tangent.world = decodeNormals(normaltangent.zw);
surface.instance = instances[instanceID >= instances.length() ? 0 : instanceID];
surface.object = objects[surface.instance.objectID];
populateSurfaceMaterial();
#endif
}
{
vec4 pNDC = ubo.eyes[surface.pass].previous * surface.object.previous * vec4(surface.position.world, 1);
vec4 cNDC = ubo.eyes[surface.pass].model * surface.object.model * vec4(surface.position.world, 1);
pNDC /= pNDC.w;
cNDC /= cNDC.w;
surface.motion = cNDC.xy - pNDC.xy;
}
}
void directLighting() {
#if VXGI
// to-do: proper "visual" of the VXGI maps (directly pick the pixel instead of just rawdog tracing for it)
if ( ubo.settings.mode.type == 0x000A ) {
Ray ray;
ray.direction = surface.ray.direction;
ray.origin = surface.ray.origin;
ray.origin -= ray.direction;
vec4 radiance = voxelConeTrace( ray, 0 );
surface.material.albedo.rgb = radiance.rgb;
surface.material.indirect.rgb = vec3(0);
surface.fragment.rgb = radiance.rgb;
surface.fragment.a = radiance.a;
//return;
}
#endif
surface.light.rgb += surface.material.albedo.rgb * ubo.settings.lighting.ambient.rgb * surface.material.occlusion; // add ambient lighting
surface.light.rgb += surface.material.indirect.rgb; // add indirect lighting
#if PBR
pbr();
#elif LAMBERT
lambert();
#elif PHONG
phong();
#endif
surface.fragment.rgb += surface.light.rgb;
}
void indirectLighting() {
uint scale = 0;
#if RT
++scale;
indirectLightingRT();
#endif
#if VXGI
++scale;
indirectLightingVXGI();
#endif
// if ( scale > 1 ) surface.material.indirect.rgb /= scale;
}
#if MULTISAMPLING
void resolveSurfaceFragment() {
for ( int i = 0; i < ubo.settings.mode.msaa; ++i ) {
msaa.currentID = i;
msaa.IDs[i] = uvec3(IMAGE_LOAD(samplerId)).xy;
// check if ID is already used
bool unique = true;
for ( int j = msaa.currentID - 1; j >= 0; --j ) {
if ( msaa.IDs[j] == msaa.IDs[i] ) {
surface.fragment = msaa.fragments[j];
unique = false;
break;
}
}
if ( unique ) {
populateSurface();
#if VXGI || RT
indirectLighting();
#endif
directLighting();
}
msaa.fragment += surface.fragment;
msaa.fragments[msaa.currentID] = surface.fragment;
}
surface.fragment = msaa.fragment / ubo.settings.mode.msaa;
}
#endif