Commit for 2022.12.21 16-25-26.7z

This commit is contained in:
mrq 2022-12-21 16:25:00 -06:00
parent e816814186
commit de54bcad8f
219 changed files with 14713 additions and 603 deletions

View File

@ -49,6 +49,7 @@ VULKAN_SDK_PATH += /c/VulkanSDK/1.3.224.1/
GLSLC += $(VULKAN_SDK_PATH)/Bin/glslc
SPV_OPTIMIZER += $(VULKAN_SDK_PATH)/Bin/spirv-opt
SPV_LINTER += $(VULKAN_SDK_PATH)/Bin/spirv-lint
# Base Engine's DLL
INC_DIR += $(ENGINE_INC_DIR)
LIB_DIR += $(ENGINE_LIB_DIR)
@ -343,6 +344,7 @@ endif
%.spv: %.glsl
$(GLSLC) --target-env=vulkan1.2 -o $@ $<
$(SPV_LINTER) $@
$(SPV_OPTIMIZER) --preserve-bindings --preserve-spec-constants -O $@ -o $@
shaders: $(TARGET_SHADERS)

383
belly/bin/data/config.json Normal file
View File

@ -0,0 +1,383 @@
{
"engine": {
"scenes": {
"start": "SourceEngine",
"matrix": { "reverseInfinite": true },
"meshes": { "interleaved": false },
"lights": { "enabled": true,
"useLightmaps": false,
"max": 16,
"shadows": {
"enabled": true,
"update": 2,
"max": 4,
"samples": 1
},
"bloom": {
"scale": 1.0,
"strength": 0.125,
"sigma": 0.8,
"samples": 5,
"threshold": 1.0
}
},
"textures": {
"max": {
"2D": 1024,
"cube": 1024,
"3D": 128
}
},
"vxgi": {
"limiter": 0.5,
// "limiter": 0.125,
"size": 192,
"dispatch": 8,
"cascades": 3,
"cascadePower": 1.5,
"granularity": 12,
"voxelizeScale": 1,
"occlusionFalloff": 2,
"traceStartOffsetFactor": 1,
"shadows": 0,
"extents": {
"min": [ -16, -4, -16 ],
"max": [ 16, 4, 16 ]
}
},
"rt": {
// "size": [ 1280, 720 ],
"full": false,
"filter": "nearest",
"defaultRayBounds": [ 0.5, 256.0 ],
"alphaTestOffset": 0.01,
"samples": 1,
"paths": 2,
"frameAccumulationMinimum": 0
}
},
"graph": {
"initial buffer elements": 131072
},
"ext": {
"vulkan": {
"version": 1.3,
"validation": { "enabled": true,
"filters": [
// "0x4dae5635" // UNASSIGNED-CoreValidation-DrawState-InvalidImageLayout
"0x609a13b" // UNASSIGNED-CoreValidation-Shader-OutputNotConsumed (from depth-only calls)
,"0x141cb623" // UNASSIGNED-Threading-MultipleThreads ("false-positive" multithreading)
,"0xe5d1743c" // VUID-vkCmdDispatch-None-02699 (problem when using VXGI)
,"0x71500fba" // VUID-vkDestroyDevice-device-00378 (don't care about a clean cleanup)
,"0x35d7ea98" // VUID-vkUpdateDescriptorSets-None-03047 (bitches without VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT or VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT)
,"0x8e1000ad" // VUID-vkCmdDrawIndexedIndirect-None-04008 (bitches without nullDescriptor)
,"0x9dd97212" // VUID-vkCmdDrawIndexedIndirect-None-02721 (bitches without nullDescriptor)
,"0x36481fcb" // VUID-vkCmdBindVertexBuffers-pBuffers-04001 (bitches without nullDescriptor)
]
},
"framebuffer": {
"msaa": 1,
"size": 1
// "size": [ 640, 480, "NEAREST" ]
// "size": [ 1280, 720 ]
// "size": [ 960, 540 ]
// "size": [ 640, 480 ]
},
"gpu": 1,
"experimental": {
"rebuild on tick begin": false,
"batch queue submissions": true,
"dedicated thread": false,
"memory budget": false
},
"invariant": {
"default stage buffers": true
},
"pipelines": {
"deferred": true,
"vsync": true,
"hdr": false,
"vxgi": false,
"culling": false,
"bloom": false,
"rt": false,
"postProcess": false,
"fsr": false
},
"formats": {
"depth": "D32_SFLOAT",
"color": "R16G16B16A16_SFLOAT", // "R32G32B32A32_SFLOAT",
"normal": "R16G16B16A16_SFLOAT",
"position": "R16G16B16A16_SFLOAT"
},
"versions": {
"1.0": {
"extensions": {
"instance": [],
"device": [
"VK_KHR_swapchain"
]
},
"features": [
"shaderDrawParameters",
"multiDrawIndirect",
"fillModeNonSolid",
"wideLines",
"independentBlend",
"deviceCoherentMemory",
"robustBufferAccess",
"samplerAnisotropy",
"sampleRateShading"
],
"featureChain": []
},
"1.1": {
"extensions": {
"instance": [
"VK_KHR_get_physical_device_properties2"
,"VK_KHR_get_surface_capabilities2"
],
"device": [
"VK_EXT_memory_budget"
,"VK_EXT_descriptor_indexing"
,"VK_KHR_buffer_device_address"
]
},
"features": [
"nullDescriptor"
,"fragmentStoresAndAtomics"
,"geometryShader"
,"multiViewport"
,"shaderInt16"
,"shaderFloat16"
,"shaderInt64"
,"shaderFloat64"
,"shaderSubgroupClock"
,"shaderSampledImageArrayDynamicIndexing"
,"shaderStorageImageArrayDynamicIndexing"
,"shaderStorageImageMultisample"
,"shaderSampledImageArrayNonUniformIndexing"
,"shaderStorageImageArrayNonUniformIndexing"
,"descriptorIndexing"
,"bufferDeviceAddress"
],
"featureChain": [
"physicalDevice2"
,"shaderDrawParameters"
,"robustness"
,"shaderClock"
,"descriptorIndexing"
,"bufferDeviceAddress"
]
},
"1.2": {
"extensions": {
"instance": [
"VK_KHR_get_physical_device_properties2",
"VK_KHR_get_surface_capabilities2"
],
"device": [
"VK_KHR_deferred_host_operations"
,"VK_EXT_shader_viewport_index_layer"
,"VK_KHR_spirv_1_4"
,"VK_KHR_shader_float_controls"
,"VK_KHR_shader_clock"
,"VK_EXT_subgroup_size_control"
,"VK_KHR_acceleration_structure"
,"VK_KHR_ray_tracing_pipeline"
,"VK_KHR_ray_query"
// ,"VK_AMD_shader_explicit_vertex_parameter"
// ,"VK_KHR_fragment_shader_barycentric"
]
},
"features": [
"hostQueryReset",
"runtimeDescriptorArray",
"descriptorBindingVariableDescriptorCount",
"shaderOutputViewportIndex",
"shaderOutputLayer"
],
"featureChain": [
"physicalDeviceVulkan12"
// for ray-tracing
,"fragmentShaderBarycentric"
,"rayTracingPipeline"
,"rayQuery"
,"accelerationStructure"
,"subgroupSizeControl"
]
},
"1.3": {
"extensions": {
"instance": [],
"device": []
},
"features": [],
"featureChain": []
}
}
},
"opengl": {
"validation": { "enabled": false },
"framebuffer": { "size": 1, "msaa": 1 },
"experimental": {
"rebuild on tick begin": true
},
"pipelines": {
"culling": true
},
"experimental": {
"rebuild on tick begin": true
},
"invariant": {
"multithreaded recording": false
},
"formats": {
"depth": "D32_SFLOAT",
"color": "R8G8B8A8_UNORM", // "R32G32B32A32_SFLOAT",
"normal": "R16G16B16A16_SFLOAT",
"position": "R16G16B16A16_SFLOAT"
},
"features": [],
"extensions": { "instance": [], "device": [] }
},
"lua": {
"enabled": true,
"main": "/main.lua",
"modules": {
"json": "/json.lua"
}
},
"json": {
"encoding": "msgpack",
"compression": "gz"
},
"imgui": {
"enabled": false
},
"fsr": {
"enabled": true,
"sharpness": 1,
"jitter scale": 0.0625,
"preset": "ultra" // native (1x), quality (1.5x), balanced (1.7x), performance (2.0x), ultra (3.0x)
},
"reactphysics": {
"timescale": 0.01666666666,
"interpolate": true,
"gravity": {
"mode": "universal",
"constant": 6.67408e-11
},
"debug draw": {
"enabled": false,
"line width": 8,
// "layer": "Gui",
"rate": 0.0125
}
},
"vr" : {
"enable" : false,
"manifest": "./data/openvr_manifest.json",
"swap eyes": false,
"dominant eye": 0,
"scale": 1.0
},
"ultralight": { "enabled": true, "scale": 1.5 },
"discord": { "enabled": false }
},
"audio": {
"mute": false,
"buffers": {
"size": 32768,
"count": 4
},
"volumes": {
"sfx": 0.35,
"bgm": 0.15,
"voice": 1.0
},
"streams by default": true
},
"memory pool": {
"enabled": true,
"subPools": true,
"alignment": 64,
"override": false,
"size": "512 MiB",
"pools": {
"entity": "128 MiB",
"userdata": "128 MiB",
"component": "128 MiB"
}
},
"render modes": { "gui": true, "deferred": true },
"limiters": {
"deltaTime": 5,
"framerate": 0 // "auto"
},
"threads": {
"workers" : "auto",
"frame limiter": 0 // "auto"
},
"debug": {
"framerate": {
"print": true,
"every": 2
},
"garbage collection": {
"enabled": true,
"mode": 1,
"rate": 4,
"announce": true
},
"entity": {
"delete children on destroy": false,
"delete components on destroy": false
},
"userdata": {
"auto destruct": true,
"auto validate": false
},
"loader": {
"assert": true
},
"hooks": {
"defer lazy calls": true
},
"scene": {
"print task calls": false
}
}
},
"window" : {
"terminal" : {
"ncurses" : false,
"visible" : true
},
"keyboard" : {
"repeat" : false
},
"cursor" : {
"visible" : true,
"center" : false,
"sensitivity": [ 0.75, 0.75 ],
"smoothing": [ 4, 4 ]
},
"mode" : "windowed", // fullscreen, borderless, windowed
"icon" : "./data/textures/icon.png",
// "size" : [ 1920, 1080 ],
// "size" : [ 1280, 720 ],
"size" : [ 960, 540 ],
// "size" : [ 640, 480 ],
// "size" : [ 256, 224 ],
"title" : "Grimgram",
"visible" : true
}
}

View File

@ -0,0 +1,13 @@
#version 450
#pragma shader_stage(fragment)
layout (location = 0) in vec3 inPosition;
layout (location = 1) in vec3 inColor;
layout (location = 0) out uvec2 outId;
layout (location = 1) out vec2 outNormals;
layout (location = 2) out vec4 outAlbedo;
void main() {
outAlbedo = vec4(inColor, 1);
}

View File

@ -0,0 +1,29 @@
#version 450
#pragma shader_stage(vertex)
#include "../../common/macros.h"
#include "../../common/structs.h"
layout (constant_id = 0) const uint PASSES = 6;
layout (location = 0) in vec3 inPos;
layout (location = 1) in vec3 inColor;
layout( push_constant ) uniform PushBlock {
uint pass;
uint draw;
} PushConstant;
layout (binding = 0) uniform Camera {
Viewport viewport[PASSES];
} camera;
layout (location = 0) out vec3 outPosition;
layout (location = 1) out vec3 outColor;
void main() {
outPosition = vec3(camera.viewport[PushConstant.pass].view * vec4(inPos.xyz, 1.0));
outColor = inColor;
gl_Position = camera.viewport[PushConstant.pass].projection * camera.viewport[PushConstant.pass].view * vec4(inPos.xyz, 1.0);
}

View File

@ -0,0 +1,56 @@
// Perlin Fog
void fog( in Ray ray, inout vec3 i, float scale ) {
if ( ubo.settings.fog.stepScale <= 0 || ubo.settings.fog.range.x == 0 || ubo.settings.fog.range.y == 0 ) return;
#if FOG_RAY_MARCH
const float range = ubo.settings.fog.range.y;
const vec3 boundsMin = vec3(-range,-range,-range) + ray.origin;
const vec3 boundsMax = vec3(range,range,range) + ray.origin;
const int numSteps = int(length(boundsMax - boundsMin) * ubo.settings.fog.stepScale );
const vec2 rayBoxInfo = rayBoxDst( boundsMin, boundsMax, ray );
const float dstToBox = rayBoxInfo.x;
const float dstInsideBox = rayBoxInfo.y;
const float depth = surface.position.eye.z;
const float aperture = 0; // PI * 0.5;
const float coneCoefficient = 2.0 * tan(aperture * 0.5);
// march
if ( 0 <= dstInsideBox && dstToBox <= depth ) {
float stepSize = dstInsideBox / numSteps;
float dstLimit = min( depth - dstToBox, dstInsideBox );
float totalDensity = 0;
float transmittance = 1;
float lightFactor = scale;
float coneDiameter = coneCoefficient * ray.distance;
float level = aperture > 0 ? log2( coneDiameter ) : 0;
float density = 0;
vec3 uvw;
ray.distance = dstToBox;
while ( ray.distance < dstLimit ) {
ray.distance += stepSize;
ray.position = ray.origin + ray.direction * ray.distance;
coneDiameter = coneCoefficient * ray.distance;
level = aperture > 0 ? log2( coneDiameter ) : 0;
uvw = ray.position * ubo.settings.fog.densityScale * 0.001 + ubo.settings.fog.offset * 0.01;
density = max(0, textureLod(samplerNoise, uvw, level).r - ubo.settings.fog.densityThreshold) * ubo.settings.fog.densityMultiplier;
if ( density > 0 ) {
density = exp(-density * stepSize * ubo.settings.fog.absorbtion);
transmittance *= density;
lightFactor *= density;
if ( transmittance < 0.1 ) break;
}
}
i.rgb = mix(ubo.settings.fog.color.rgb, i.rgb, transmittance );
}
#endif
#if FOG_BASIC
const vec3 color = ubo.settings.fog.color.rgb;
const float inner = ubo.settings.fog.range.x;
const float outer = ubo.settings.fog.range.y * scale;
const float distance = length(-surface.position.eye);
const float factor = clamp( (distance - inner) / (outer - inner), 0.0, 1.0 );
i.rgb = mix(i.rgb, color, factor);
#endif
}

View File

@ -0,0 +1,419 @@
// Helper Functions
float random(vec3 seed, int i){ return fract(sin(dot(vec4(seed,i), vec4(12.9898,78.233,45.164,94.673))) * 43758.5453); }
float rand2(vec2 co){ return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 143758.5453); }
float rand3(vec3 co){ return fract(sin(dot(co.xyz ,vec3(12.9898,78.233, 37.719))) * 143758.5453); }
//
float mipLevel( in vec2 dx_vtc, in vec2 dy_vtc ) {
const float delta_max_sqr = max(dot(dx_vtc, dx_vtc), dot(dy_vtc, dy_vtc));
return 0.5 * log2(delta_max_sqr);
// return max(0.0, 0.5 * log2(delta_max_sqr) - 1.0);
// return 0.5 * log2(max(dot(dx_vtc, dx_vtc), dot(dy_vtc, dy_vtc)));
}
float mipLevels( vec2 size ) {
return floor(log2(max(size.x, size.y)));
}
float mipLevels( ivec2 size ) {
return floor(log2(max(size.x, size.y)));
}
//
void toneMap( inout vec3 color, float exposure ) {
color.rgb = vec3(1.0) - exp(-color.rgb * exposure);
}
void gammaCorrect( inout vec3 color, float gamma ) {
color.rgb = pow(color.rgb, vec3(1.0 / gamma));
}
void toneMap( inout vec4 color, float exposure ) { toneMap(color.rgb, exposure); }
void gammaCorrect( inout vec4 color, float gamma ) { gammaCorrect(color.rgb, gamma); }
//
uint tea(uint val0, uint val1) {
uint v0 = val0;
uint v1 = val1;
uint s0 = 0;
#pragma unroll 16
for(uint n = 0; n < 16; n++) {
s0 += 0x9e3779b9;
v0 += ((v1 << 4) + 0xa341316c) ^ (v1 + s0) ^ ((v1 >> 5) + 0xc8013ea4);
v1 += ((v0 << 4) + 0xad90777d) ^ (v0 + s0) ^ ((v0 >> 5) + 0x7e95761e);
}
return v0;
}
uint lcg(inout uint prev) {
uint LCG_A = 1664525u;
uint LCG_C = 1013904223u;
prev = (LCG_A * prev + LCG_C);
return prev & 0x00FFFFFF;
}
float rnd(inout uint prev) { return (float(lcg(prev)) / float(0x01000000)); }
uint prngSeed;
float rnd() { return rnd(prngSeed); }
//
float ndfGGX(float cosLh, float roughness) {
const float alpha = roughness * roughness;
const float alphaSq = alpha * alpha;
const float denom = (cosLh * cosLh) * (alphaSq - 1.0) + 1.0;
return alphaSq / (PI * denom * denom);
}
float gaSchlickG1(float cosTheta, float k) { return cosTheta / (cosTheta * (1.0 - k) + k); }
float gaSchlickGGX(float cosLi, float cosLo, float roughness) {
const float r = roughness + 1.0;
const float k = (r * r) / 8.0;
return gaSchlickG1(cosLi, k) * gaSchlickG1(cosLo, k);
}
vec3 fresnelSchlick(vec3 F0, float cosTheta) { return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); }
//
void tangentBitangent(in vec3 N, out vec3 Nt, out vec3 Nb) {
if(abs(N.x) > abs(N.y)) Nt = vec3(N.z, 0, -N.x) / sqrt(N.x * N.x + N.z * N.z);
else Nt = vec3(0, -N.z, N.y) / sqrt(N.y * N.y + N.z * N.z);
Nb = cross(N, Nt);
}
vec3 samplingHemisphere(inout uint seed, in vec3 x, in vec3 y, in vec3 z) {
float r1 = rnd(seed);
float r2 = rnd(seed);
float sq = sqrt(1.0 - r2);
vec3 direction = vec3(cos(2 * PI * r1) * sq, sin(2 * PI * r1) * sq, sqrt(r2));
direction = direction.x * x + direction.y * y + direction.z * z;
return direction;
}
vec3 samplingHemisphere(inout uint seed, in vec3 z) {
vec3 x;
vec3 y;
tangentBitangent( z, x, y );
float r1 = rnd(seed);
float r2 = rnd(seed);
float sq = sqrt(1.0 - r2);
vec3 direction = vec3(cos(2 * PI * r1) * sq, sin(2 * PI * r1) * sq, sqrt(r2));
direction = direction.x * x + direction.y * y + direction.z * z;
return direction;
}
//
float max3( vec3 v ) { return max(max(v.x, v.y), v.z); }
float min3( vec3 v ) { return min(min(v.x, v.y), v.z); }
uint biasedRound( float x, float bias ) { return uint( ( x < bias ) ? floor(x) : ceil(x)); }
float wrap( float i ) { return fract(i); }
vec2 wrap( vec2 uv ) { return vec2( wrap( uv.x ), wrap( uv.y ) ); }
vec3 orthogonal(vec3 u){
u = normalize(u);
const vec3 v = vec3(0.99146, 0.11664, 0.05832); // Pick any normalized vector.
return abs(dot(u, v)) > 0.99999f ? cross(u, vec3(0, 1, 0)) : cross(u, v);
}
vec4 blend( vec4 source, vec4 dest, float a ) {
return source * a + dest * (1.0 - a);
}
float gauss( float x, float sigma ) {
return (1.0 / (2.0 * 3.14157 * sigma) * exp(-(x*x) / (2.0 * sigma)));
}
bool enabled( uint flag, uint bit ) {
return (flag & (1 << bit)) != 0;
}
vec3 decodeNormals( vec2 enc ) {
const vec2 ang = enc*2-1;
const vec2 scth = vec2( sin(ang.x * PI), cos(ang.x * PI) );
const vec2 scphi = vec2(sqrt(1.0 - ang.y*ang.y), ang.y);
return normalize( vec3(scth.y*scphi.x, scth.x*scphi.x, scphi.y) );
}
vec2 encodeNormals( vec3 n ) {
// float p = sqrt(n.z*8+8);
// return n.xy/p + 0.5;
return (vec2(atan(n.y,n.x)/PI, n.z)+1.0)*0.5;
}
vec3 encodeSrgb(vec3 rgb) {
const vec3 a = 12.92 * rgb;
const vec3 b = 1.055 * pow(rgb, vec3(1.0 / 2.4)) - 0.055;
const vec3 c = step(vec3(0.0031308), rgb);
return mix(a, b, c);
}
vec3 decodeSrgb(vec3 rgb) {
const vec3 a = rgb / 12.92;
const vec3 b = pow((rgb + 0.055) / 1.055, vec3(2.4));
const vec3 c = step(vec3(0.04045), rgb);
return mix(a, b, c);
}
bool validTextureIndex( int textureIndex ) {
return 0 <= textureIndex && textureIndex < MAX_TEXTURES;
}
#if MAX_CUBEMAPS
bool validCubemapIndex( int textureIndex ) {
return 0 <= textureIndex && textureIndex < MAX_CUBEMAPS;
}
#endif
#if !BLOOM && (DEFERRED || FRAGMENT || COMPUTE || RT)
bool validTextureIndex( uint id ) {
return 0 <= id && id < MAX_TEXTURES;
}
bool validTextureIndex( uint start, int offset ) {
return 0 <= offset && start + offset < MAX_TEXTURES;
}
uint textureIndex( uint start, int offset ) {
return start + offset;
}
vec4 sampleTexture( uint id, vec2 uv ) {
const Texture t = textures[id];
return texture( samplerTextures[nonuniformEXT(t.index)], mix( t.lerp.xy, t.lerp.zw, uv ) );
}
vec4 sampleTexture( uint id, vec2 uv, float mip ) {
#if QUERY_MIPMAP
return sampleTexture( id, uv );
#else
const Texture t = textures[id];
return textureLod( samplerTextures[nonuniformEXT(t.index)], mix( t.lerp.xy, t.lerp.zw, uv ), mip );
#endif
}
vec4 sampleTexture( uint id, vec3 uvm ) { return sampleTexture( id, uvm.xy, uvm.z ); }
vec4 sampleTexture( uint id ) { return sampleTexture( id, surface.uv.xy, surface.uv.z ); }
vec4 sampleTexture( uint id, float mip ) { return sampleTexture( id, surface.uv.xy, mip ); }
#endif
vec2 rayBoxDst( vec3 boundsMin, vec3 boundsMax, in Ray ray ) {
const vec3 t0 = (boundsMin - ray.origin) / ray.direction;
const vec3 t1 = (boundsMax - ray.origin) / ray.direction;
const vec3 tmin = min(t0, t1);
const vec3 tmax = max(t0, t1);
const float tStart = max(0, max( max(tmin.x, tmin.y), tmin.z ));
const float tEnd = max(0, min( tmax.x, min(tmax.y, tmax.z) ) - tStart);
return vec2(tStart, tEnd);
}
#if VXGI
float cascadePower( uint x ) {
return pow(1 + x, ubo.settings.vxgi.cascadePower);
// return max( 1, x * ubo.settings.vxgi.cascadePower );
}
#endif
#if FRAGMENT
void whitenoise(inout vec3 color, const vec4 parameters) {
const float flicker = parameters.x;
const float pieces = parameters.y;
const float blend = parameters.z;
const float time = parameters.w;
if ( blend < 0.0001 ) return;
const float freq = sin(pow(mod(time, flicker) + flicker, 1.9));
const float whiteNoise = rand2( floor(gl_FragCoord.xy / pieces) + mod(time, freq) );
color = mix( color, vec3(whiteNoise), blend );
}
vec4 resolve( subpassInputMS t, const uint samples ) {
vec4 resolved = vec4(0);
for ( int i = 0; i < samples; ++i ) resolved += subpassLoad(t, i);
resolved /= vec4(samples);
return resolved;
}
uvec4 resolve( usubpassInputMS t, const uint samples ) {
uvec4 resolved = uvec4(0);
for ( int i = 0; i < samples; ++i ) resolved += subpassLoad(t, i);
resolved /= uvec4(samples);
return resolved;
}
#endif
vec4 resolve( sampler2DMS t, ivec2 uv ) {
vec4 resolved = vec4(0);
int samples = textureSamples(t);
for ( int i = 0; i < samples; ++i ) {
resolved += texelFetch(t, uv, i);
}
resolved /= float(samples);
return resolved;
}
//
vec2 encodeBarycentrics( vec3 barycentric ) {
return barycentric.yz;
}
vec3 decodeBarycentrics( vec2 attributes ) {
return vec3(
1.0 - attributes.x - attributes.y,
attributes.x,
attributes.y
);
}
#if DEFERRED_SAMPLING
void populateSurfaceMaterial() {
const Material material = materials[surface.instance.materialID];
surface.material.albedo = material.colorBase;
surface.material.metallic = material.factorMetallic;
surface.material.roughness = material.factorRoughness;
surface.material.occlusion = material.factorOcclusion;
surface.light = material.colorEmissive;
if ( validTextureIndex( material.indexAlbedo ) ) {
surface.material.albedo *= sampleTexture( material.indexAlbedo );
}
// OPAQUE
if ( material.modeAlpha == 0 ) {
surface.material.albedo.a = 1;
// BLEND
} else if ( material.modeAlpha == 1 ) {
// MASK
} else if ( material.modeAlpha == 2 ) {
}
// Lightmap
if ( (/*surface.subID++ > 0 ||*/ bool(ubo.settings.lighting.useLightmaps)) && validTextureIndex( surface.instance.lightmapID ) ) {
vec4 light = sampleTexture( surface.instance.lightmapID, surface.st );
/*surface.material.lightmapped = light.a > 0.000000001;
if ( surface.material.lightmapped )*/ surface.light += surface.material.albedo * light;
} else {
surface.material.lightmapped = false;
}
// Emissive textures
if ( validTextureIndex( material.indexEmissive ) ) {
surface.light += sampleTexture( material.indexEmissive );
}
// Occlusion map
if ( validTextureIndex( material.indexOcclusion ) ) {
surface.material.occlusion = sampleTexture( material.indexOcclusion ).r;
}
// Metallic/Roughness map
if ( validTextureIndex( material.indexMetallicRoughness ) ) {
vec4 samp = sampleTexture( material.indexMetallicRoughness );
surface.material.metallic = samp.r;
surface.material.roughness = samp.g;
}
// Normals
if ( validTextureIndex( material.indexNormal ) && surface.tangent.world != vec3(0) ) {
surface.normal.world = surface.tbn * normalize( sampleTexture( material.indexNormal ).xyz * 2.0 - vec3(1.0));
}
{
surface.normal.eye = normalize(vec3( ubo.eyes[surface.pass].view * vec4(surface.normal.world, 0.0) ));
}
surface.light *= surface.material.albedo;
}
bool isValidAddress( uint64_t address ) {
#if UINT64_ENABLED
return bool(address);
#else
return bool(address.x) && bool(address.y);
#endif
}
#if BUFFER_REFERENCE
void populateSurface( InstanceAddresses instanceAddresses, uvec3 indices ) {
Triangle triangle;
Vertex points[3];
if ( isValidAddress(instanceAddresses.vertex) ) {
Vertices vertices = Vertices(nonuniformEXT(instanceAddresses.vertex));
#pragma unroll 3
for ( uint _ = 0; _ < 3; ++_ ) /*triangle.*/points[_] = vertices.v[/*triangle.*/indices[_]];
} else {
if ( isValidAddress(instanceAddresses.position) ) {
VPos buf = VPos(nonuniformEXT(instanceAddresses.position));
#pragma unroll 3
for ( uint _ = 0; _ < 3; ++_ ) /*triangle.*/points[_].position = buf.v[/*triangle.*/indices[_]];
}
if ( isValidAddress(instanceAddresses.uv) ) {
VUv buf = VUv(nonuniformEXT(instanceAddresses.uv));
#pragma unroll 3
for ( uint _ = 0; _ < 3; ++_ ) /*triangle.*/points[_].uv = buf.v[/*triangle.*/indices[_]];
}
if ( isValidAddress(instanceAddresses.st) ) {
VSt buf = VSt(nonuniformEXT(instanceAddresses.st));
#pragma unroll 3
for ( uint _ = 0; _ < 3; ++_ ) /*triangle.*/points[_].st = buf.v[/*triangle.*/indices[_]];
}
if ( isValidAddress(instanceAddresses.normal) ) {
VNormal buf = VNormal(nonuniformEXT(instanceAddresses.normal));
#pragma unroll 3
for ( uint _ = 0; _ < 3; ++_ ) /*triangle.*/points[_].normal = buf.v[/*triangle.*/indices[_]];
}
if ( isValidAddress(instanceAddresses.tangent) ) {
VTangent buf = VTangent(nonuniformEXT(instanceAddresses.tangent));
#pragma unroll 3
for ( uint _ = 0; _ < 3; ++_ ) /*triangle.*/points[_].tangent = buf.v[/*triangle.*/indices[_]];
}
}
#if BARYCENTRIC_CALCULATE
{
const vec3 p = vec3(inverse( surface.instance.model ) * vec4(surface.position.world, 1));
const vec3 a = points[0].position;
const vec3 b = points[1].position;
const vec3 c = points[2].position;
const vec3 v0 = b - a;
const vec3 v1 = c - a;
const vec3 v2 = p - a;
const float d00 = dot(v0, v0);
const float d01 = dot(v0, v1);
const float d11 = dot(v1, v1);
const float d20 = dot(v2, v0);
const float d21 = dot(v2, v1);
const float denom = d00 * d11 - d01 * d01;
const float v = (d11 * d20 - d01 * d21) / denom;
const float w = (d00 * d21 - d01 * d20) / denom;
const float u = 1.0f - v - w;
surface.barycentric = vec3( u, v, w );
}
#endif
triangle.geomNormal = normalize(cross(points[1].position - points[0].position, points[2].position - points[0].position));
triangle.point.normal = /*triangle.*/points[0].normal * surface.barycentric[0] + /*triangle.*/points[1].normal * surface.barycentric[1] + /*triangle.*/points[2].normal * surface.barycentric[2];
triangle.point.position = /*triangle.*/points[0].position * surface.barycentric[0] + /*triangle.*/points[1].position * surface.barycentric[1] + /*triangle.*/points[2].position * surface.barycentric[2];
triangle.point.uv = /*triangle.*/points[0].uv * surface.barycentric[0] + /*triangle.*/points[1].uv * surface.barycentric[1] + /*triangle.*/points[2].uv * surface.barycentric[2];
triangle.point.st = /*triangle.*/points[0].st * surface.barycentric[0] + /*triangle.*/points[1].st * surface.barycentric[1] + /*triangle.*/points[2].st * surface.barycentric[2];
triangle.point.tangent = /*triangle.*/points[0].tangent * surface.barycentric[0] + /*triangle.*/points[1].tangent * surface.barycentric[1] + /*triangle.*/points[2].tangent * surface.barycentric[2];
if ( triangle.point.tangent != vec3(0) ) {
surface.tangent.world = normalize(vec3( surface.instance.model * vec4(triangle.point.tangent, 0.0) ));
vec3 bitangent = normalize(vec3( surface.instance.model * vec4(cross( triangle.point.normal, triangle.point.tangent ), 0.0) ));
surface.tbn = mat3(surface.tangent.world, bitangent, triangle.point.normal);
}
// bind position
#if 1 || BARYCENTRIC_CALCULATE
{
surface.position.world = vec3( surface.instance.model * vec4(triangle.point.position, 1.0 ) );
surface.position.eye = vec3( ubo.eyes[surface.pass].view * vec4(surface.position.world, 1.0) );
}
#endif
// bind normals
{
surface.normal.world = normalize(vec3( surface.instance.model * vec4(triangle.point.normal, 0.0 ) ));
// surface.normal.eye = vec3( ubo.eyes[surface.pass].view * vec4(surface.normal.world, 0.0) );
}
// bind UVs
{
surface.uv.xy = triangle.point.uv;
surface.uv.z = 0;
surface.st.xy = triangle.point.st;
surface.st.z = 0;
}
populateSurfaceMaterial();
}
void populateSurface( uint instanceID, uint primitiveID ) {
surface.fragment = vec4(0);
surface.light = vec4(0);
surface.instance = instances[instanceID];
const InstanceAddresses instanceAddresses = instanceAddresses[instanceID];
if ( !isValidAddress(instanceAddresses.index) ) return;
const DrawCommand drawCommand = Indirects(nonuniformEXT(instanceAddresses.indirect)).dc[instanceAddresses.drawID];
const uint triangleID = primitiveID + (drawCommand.indexID / 3);
uvec3 indices = Indices(nonuniformEXT(instanceAddresses.index)).i[triangleID];
#pragma unroll 3
for ( uint _ = 0; _ < 3; ++_ ) /*triangle.*/indices[_] += drawCommand.vertexID;
populateSurface( instanceAddresses, indices );
}
void populateSurface( RayTracePayload payload ) {
surface.fragment = vec4(0);
surface.light = vec4(0);
surface.instance = instances[payload.instanceID];
if ( !payload.hit ) return;
surface.barycentric = decodeBarycentrics(payload.attributes);
populateSurface( payload.instanceID, payload.primitiveID );
}
#endif
#endif

View File

@ -0,0 +1,66 @@
float shadowFactor( const Light light, float def );
void lambert() {
// outcoming light from surface to eye
const vec3 Lo = normalize( -surface.position.eye );
// angle of outcoming light
const float cosLo = max(0.0, dot(surface.normal.eye, Lo));
for ( uint i = 0, shadows = 0; i < MAX_LIGHTS; ++i ) {
#if BAKING
// skip if surface is a dynamic light, we aren't baking dynamic lights
if ( lights[i].type < 0 ) continue;
#else
// skip if surface is already baked, and this isn't a dynamic light
if ( surface.material.lightmapped && lights[i].type >= 0 ) continue;
#endif
if ( lights[i].power <= LIGHT_POWER_CUTOFF ) continue;
if ( surface.material.lightmapped && lights[i].type >= 0 ) continue;
vec3 Li = vec3(VIEW_MATRIX * vec4(lights[i].position, 1)) - surface.position.eye;
// magnitude of incoming light vector (for inverse-square attenuation)
const float Lmagnitude = dot(Li, Li);
// distance incoming light travels (reuse from above)
const float Ldistance = sqrt(Lmagnitude);
// "free" normalization, since we need to compute the above values anyways
Li = Li / Ldistance;
// attenuation factor
// const float Lattenuation = 1.0 / (1 + (PI * Lmagnitude));
const float Lattenuation = 1.0 / (1 + Lmagnitude);
// skip if attenuation factor is too low
// if ( Lattenuation <= LIGHT_POWER_CUTOFF ) continue;
// ray cast if our surface is occluded from the light
const float Lshadow = 1; // ( shadows++ < MAX_SHADOWS ) ? shadowFactor( lights[i], 0.0 ) : 1;
// skip if our shadow factor is too low
if ( Lshadow <= LIGHT_POWER_CUTOFF ) continue;
// light radiance
const vec3 Lr = lights[i].color.rgb * lights[i].power * Lattenuation * Lshadow;
// skip if our radiance is too low
// if ( Lr <= LIGHT_POWER_CUTOFF ) continue;
// halfway vector
const vec3 Lh = normalize(Li + Lo);
// angle of incoming light
const float cosLi = max(0.0, dot(surface.normal.eye, Li));
// angle of halfway light vector
const float cosLh = max(0.0, dot(surface.normal.eye, Lh));
/*
const vec3 Liu = vec3(VIEW_MATRIX * vec4(lights[i].position, 1)) - surface.position.eye;
const vec3 Li = normalize(Liu);
// const float Lattenuation = 1.0 / (PI * pow(length(Liu), 2.0));
// const float Lattenuation = 1.0 / (1 + (PI * pow(length(Liu), 2.0)));
const float Lattenuation = 1.0 / (1 + pow(length(Liu), 2.0));
const float Lshadow = ( shadows++ < MAX_SHADOWS ) ? shadowFactor( lights[i], 0.0 ) : 1;
if ( lights[i].power * Lattenuation * Lshadow <= LIGHT_POWER_CUTOFF ) continue;
const float cosLi = max(0.0, dot(surface.normal.eye, Li));
const vec3 Lr = lights[i].color.rgb * lights[i].power * Lattenuation * Lshadow;
// const vec3 Lh = normalize(Li + Lo);
// const float cosLh = max(0.0, dot(surface.normal.eye, Lh));
*/
const vec3 diffuse = surface.material.albedo.rgb;
const vec3 specular = vec3(0);
surface.light.rgb += (diffuse + specular) * Lr * cosLi;
surface.light.a += lights[i].power * Lattenuation * Lshadow;
}
}

View File

@ -0,0 +1,11 @@
float shadowFactor( const Light light, float def );
#if PBR
#include "../common/pbr.h"
#endif
#if LAMBERT
#include "../common/lambert.h"
#endif
#if PHONG
#include "../common/phong.h"
#endif

View File

@ -0,0 +1,104 @@
#ifndef NO_NONUNIFORM_EXT
#define NO_NONUNIFORM_EXT 0
// enable if shaderNonUniform is not supported
// Nvidia hardware does not require nonuniformEXT, but AMD does
#endif
// implicit variables
#ifndef MULTISAMPLING
#define MULTISAMPLING 1
#endif
#ifndef MAX_MSAA_SAMPLES
#define MAX_MSAA_SAMPLES 16
#endif
#ifndef MAX_TEXTURES
#define MAX_TEXTURES TEXTURES
#endif
#ifndef MAX_LIGHTS
#define MAX_LIGHTS ubo.settings.lengths.lights
#endif
#ifndef MAX_SHADOWS
#define MAX_SHADOWS ubo.settings.lighting.maxShadows
#endif
#ifndef VIEW_MATRIX
#define VIEW_MATRIX ubo.eyes[surface.pass].view
#endif
// implicit shader settings
#ifndef CAN_DISCARD
#define CAN_DISCARD 1
#endif
#ifndef USE_LIGHTMAP
#define USE_LIGHTMAP 1
#endif
#if VXGI
#define VXGI_NDC 1
#define VXGI_SHADOWS 0
#endif
/*
#ifndef FOG
#define FOG 1
#endif
#ifndef FOG_RAY_MARCH
#define FOG_RAY_MARCH 1
#endif
#ifndef WHITENOISE
#define WHITENOISE 1
#endif
#ifndef GAMMA_CORRECT
#define GAMMA_CORRECT 1
#endif
#ifndef TONE_MAP
#define TONE_MAP 1
#endif
#ifndef PHONG
#define PHONG 0
#endif
#ifndef LAMBERT
#define LAMBERT 0
#endif
#ifndef PBR
#define PBR 1
#endif
*/
#if NO_NONUNIFORM_EXT
#define nonuniformEXT(X) X
#else
#extension GL_EXT_nonuniform_qualifier : enable
#endif
#if !UINT64_ENABLED
#define uint64_t uvec2
#endif
// easy and accessible in one place
#ifndef BARYCENTRIC
#define BARYCENTRIC 0
#endif
#if BARYCENTRIC
#ifndef BARYCENTRIC_CALCULATE
#define BARYCENTRIC_CALCULATE 0
#endif
#endif
#if BUFFER_REFERENCE
#extension GL_EXT_scalar_block_layout : enable
#extension GL_EXT_buffer_reference : enable
#extension GL_EXT_buffer_reference2 : enable
#if UINT64_ENABLED
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : enable
#else
#extension GL_EXT_buffer_reference_uvec2 : enable
#endif
#endif
const float PI = 3.14159265359;
const float EPSILON = 0.00001;
const float SQRT2 = 1.41421356237;
const float LIGHT_POWER_CUTOFF = 0.0005;
const float LIGHTMAP_GAMMA = 1.0;
#define SETTINGS_TYPE_FULLBRIGHT 0x10

View File

@ -0,0 +1,121 @@
// PBR
void pbr() {
// per-surface, not per-light, compute once
// Freslen reflectance for a dieletric
const vec3 F0 = mix(vec3(0.04), surface.material.albedo.rgb, surface.material.metallic);
// outcoming light from surface to eye
const vec3 Lo = normalize( -surface.position.eye );
// angle of outcoming light
const float cosLo = max(0.0, dot(surface.normal.eye, Lo));
const float Rs = 4.0;
for ( uint i = 0, shadows = 0; i < MAX_LIGHTS; ++i ) {
#if BAKING
// skip if surface is a dynamic light, we aren't baking dynamic lights
if ( lights[i].type < 0 ) continue;
#else
// skip if surface is already baked, and this isn't a dynamic light
if ( surface.material.lightmapped && lights[i].type >= 0 ) continue;
#endif
/*
// skip if light power is too low
if ( lights[i].power <= LIGHT_POWER_CUTOFF ) continue;
if ( surface.material.lightmapped && lights[i].type >= 0 ) continue;
const vec3 Liu = vec3(VIEW_MATRIX * vec4(lights[i].position, 1)) - surface.position.eye;
const vec3 Li = normalize(Liu);
const float Lshadow = ( shadows++ < MAX_SHADOWS ) ? shadowFactor( lights[i], 0.0 ) : 1;
// const float Lattenuation = 1.0 / (PI * pow(length(Liu), 2.0));
// const float Lattenuation = 1.0 / (1 + (PI * pow(length(Liu), 2.0)));
const float Lattenuation = 1.0 / (1 + pow(length(Liu), 2.0));
if ( lights[i].power * Lattenuation * Lshadow <= LIGHT_POWER_CUTOFF ) continue;
const float cosLi = max(0.0, dot(surface.normal.eye, Li));
const vec3 Lr = lights[i].color.rgb * lights[i].power * Lattenuation * Lshadow;
const vec3 Lh = normalize(Li + Lo);
const float cosLh = max(0.0, dot(surface.normal.eye, Lh));
*/
// incoming light to surface (non-const to normalize it later)
// vec3 Li = lights[i].position - surface.position.world;
vec3 Li = vec3(VIEW_MATRIX * vec4(lights[i].position, 1)) - surface.position.eye;
// magnitude of incoming light vector (for inverse-square attenuation)
const float Lmagnitude = dot(Li, Li);
// distance incoming light travels (reuse from above)
const float Ldistance = sqrt(Lmagnitude);
// "free" normalization, since we need to compute the above values anyways
Li = Li / Ldistance;
// attenuation factor
// const float Lattenuation = 1.0 / (1 + (PI * Lmagnitude));
const float Lattenuation = 1.0 / (1 + Lmagnitude);
// skip if attenuation factor is too low
// if ( Lattenuation <= LIGHT_POWER_CUTOFF ) continue;
// ray cast if our surface is occluded from the light
const float Lshadow = ( shadows++ < MAX_SHADOWS ) ? shadowFactor( lights[i], 0.0 ) : 1;
// skip if our shadow factor is too low
if ( Lshadow <= LIGHT_POWER_CUTOFF ) continue;
// light radiance
const vec3 Lr = lights[i].color.rgb * lights[i].power * Lattenuation * Lshadow;
// skip if our radiance is too low
// if ( Lr <= LIGHT_POWER_CUTOFF ) continue;
// halfway vector
const vec3 Lh = normalize(Li + Lo);
// angle of incoming light
const float cosLi = max(0.0, dot(surface.normal.eye, Li));
// angle of halfway light vector
const float cosLh = max(0.0, dot(surface.normal.eye, Lh));
// Fresnel term for direct lighting
const vec3 F = fresnelSchlick(F0, max(0.0, dot(Lh, Lo)));
// Distribution for specular lighting
const float D = ndfGGX( cosLh, surface.material.roughness * Rs);
// Geometric attenuation for specular lighting
const float G = gaSchlickGGX(cosLi, cosLo, surface.material.roughness * Rs);
// final lighting
const vec3 diffuse = mix(vec3(1.0) - F, vec3(0), surface.material.metallic) * surface.material.albedo.rgb;
const vec3 specular = ( shadows < MAX_SHADOWS ) ? ((F * D * G) / max(EPSILON, 4.0 * cosLi * cosLo)) : vec3(0);
surface.light.rgb += (diffuse + specular) * Lr * cosLi;
surface.light.a += lights[i].power * Lattenuation * Lshadow;
}
#if 0
const float Rs = 4.0; // specular lighting looks gross without this
uint shadows = 0;
for ( uint i = 0; i < ubo.settings.lengths.lights; ++i ) {
const Light light = lights[i];
if ( light.power <= LIGHT_POWER_CUTOFF ) continue;
if ( surface.material.lightmapped && light.type >= 0 ) continue;
const vec3 Liu = vec3(ubo.eyes[surface.pass].view * vec4(light.position, 1)) - surface.position.eye;
const float Ld = length(Liu);
const float La = 1.0 / (1 + (PI * pow(Ld, 2.0)));
if ( La <= LIGHT_POWER_CUTOFF ) continue;
const vec3 Li = normalize(Liu);
const float Ls = ( shadows++ < ubo.settings.lighting.maxShadows ) ? shadowFactor( light, 0.0 ) : 1;
if ( light.power * La * Ls <= LIGHT_POWER_CUTOFF ) continue;
const float cosLi = max(0.0, dot(surface.normal.eye, Li));
const vec3 Lr = light.color.rgb * light.power * La * Ls;
const vec3 Lh = normalize(Li + Lo);
const float cosLh = max(0.0, dot(surface.normal.eye, Lh));
const vec3 F = fresnelSchlick( F0, max( 0.0, dot(Lh, Lo) ) );
const float D = ndfGGX( cosLh, surface.material.roughness * Rs );
const float G = gaSchlickGGX(cosLi, cosLo, surface.material.roughness);
const vec3 diffuse = mix( vec3(1.0) - F, vec3(0.0), surface.material.metallic ) * surface.material.albedo.rgb;
const vec3 specular = (F * D * G) / max(EPSILON, 4.0 * cosLi * cosLo);
/*
// lightmapped, compute only specular
if ( light.type >= 0 && validTextureIndex( surface.instance.lightmapID ) ) surface.light.rgb += (specular) * Lr * cosLi;
// point light, compute only diffuse
// else if ( abs(light.type) == 1 ) surface.light.rgb += (diffuse) * Lr * cosLi;
else surface.light.rgb += (diffuse + specular) * Lr * cosLi;
*/
surface.light.rgb += (diffuse + specular) * Lr * cosLi;
surface.light.a += light.power * La * Ls;
}
#endif
}

View File

@ -0,0 +1,171 @@
const vec2 poissonDisk[16] = vec2[](
vec2( -0.94201624, -0.39906216 ),
vec2( 0.94558609, -0.76890725 ),
vec2( -0.094184101, -0.92938870 ),
vec2( 0.34495938, 0.29387760 ),
vec2( -0.91588581, 0.45771432 ),
vec2( -0.81544232, -0.87912464 ),
vec2( -0.38277543, 0.27676845 ),
vec2( 0.97484398, 0.75648379 ),
vec2( 0.44323325, -0.97511554 ),
vec2( 0.53742981, -0.47373420 ),
vec2( -0.26496911, -0.41893023 ),
vec2( 0.79197514, 0.19090188 ),
vec2( -0.24188840, 0.99706507 ),
vec2( -0.81409955, 0.91437590 ),
vec2( 0.19984126, 0.78641367 ),
vec2( 0.14383161, -0.14100790 )
);
#ifndef SHADOW_SAMPLES
#define SHADOW_SAMPLES ubo.settings.lighting.shadowSamples
#endif
#if VXGI
float voxelShadowFactor( const Light, float def );
#endif
#if CUBEMAPS
float omniShadowMap( const Light light, float def ) {
return 1.0;
}
#else
float omniShadowMap( const Light light, float def ) {
float factor = 1.0;
const mat4 views[6] = {
mat4( 0, 0, 1, 0, 0, 1, 0, 0,-1, 0, 0, 0, 0, 0, 0, 1 ),
mat4( 0, 0,-1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1 ),
mat4( 1, 0, 0, 0, 0, 0, 1, 0, 0,-1, 0, 0, 0, 0, 0, 1 ),
mat4( 1, 0, 0, 0, 0, 0,-1, 0, 0, 1, 0, 0, 0, 0, 0, 1 ),
mat4( 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ),
mat4(-1, 0, 0, 0, 0, 1, 0, 0, 0, 0,-1, 0, 0, 0, 0, 1 ),
};
const vec3 D = normalize(surface.position.world - light.position);
const vec3 N = abs(D);
uint A = N.y > N.x ? 1 : 0;
A = N.z > N[A] ? 2 : A;
uint index = A * 2;
if ( D[A] < 0.0 ) ++index;
vec4 positionClip = light.projection * views[index] * vec4(surface.position.world - light.position, 1.0);
positionClip.xy /= positionClip.w;
if ( positionClip.x < -1 || positionClip.x >= 1 ) return 0.0;
if ( positionClip.y < -1 || positionClip.y >= 1 ) return 0.0;
if ( positionClip.z < -1 || positionClip.z >= 1 ) return 0.0;
const float eyeDepthScale = 1.0;
const float sampledDepthScale = light.view[1][1]; // light view matricies will incorporate scaling factors for some retarded reason, so we need to rescale it by grabbing from here, hopefully it remains coherent between all light matrices to ever exist in engine
const float bias = light.depthBias;
const float eyeDepth = abs(positionClip.z / positionClip.w) * eyeDepthScale;
const vec3 sampleOffsetDirections[20] = {
vec3( 1, 1, 1), vec3( 1, -1, 1), vec3(-1, -1, 1), vec3(-1, 1, 1),
vec3( 1, 1, -1), vec3( 1, -1, -1), vec3(-1, -1, -1), vec3(-1, 1, -1),
vec3( 1, 1, 0), vec3( 1, -1, 0), vec3(-1, -1, 0), vec3(-1, 1, 0),
vec3( 1, 0, 1), vec3(-1, 0, 1), vec3( 1, 0, -1), vec3(-1, 0, -1),
vec3( 0, 1, 1), vec3( 0, -1, 1), vec3( 0, -1, -1), vec3( 0, 1, -1)
};
float sampled = 0;
const int samples = int(SHADOW_SAMPLES);
// cubemap point light
if ( light.typeMap == 1 ) {
if ( samples < 1 ) {
sampled = texture(samplerCubemaps[nonuniformEXT(light.indexMap)], D).r * sampledDepthScale;
} else {
for ( int i = 0; i < samples; ++i ) {
const int idx = int( float(samples) * random(floor(surface.position.world.xyz * 1000.0), i)) % samples;
vec2 poisson = poissonDisk[idx] / 700.0;
vec3 P = vec3( poisson.xy, (poisson.x + poisson.y) * 0.5 );
sampled = texture(samplerCubemaps[nonuniformEXT(light.indexMap)], D + P ).r * sampledDepthScale;
if ( eyeDepth < sampled - bias ) factor -= 1.0 / samples;
}
return factor;
}
// separated point lights
} else if ( light.typeMap == 2 ) {
const vec2 uv = positionClip.xy * 0.5 + 0.5;
if ( samples < 1 ) {
sampled = texture(samplerTextures[nonuniformEXT(light.indexMap + index)], uv).r * sampledDepthScale;
} else {
for ( int i = 0; i < samples; ++i ) {
const int idx = int( float(samples) * random(floor(surface.position.world.xyz * 1000.0), i)) % samples;
sampled = texture(samplerTextures[nonuniformEXT(light.indexMap + index)], uv + poissonDisk[idx] / 700.0 ).r * sampledDepthScale;
if ( eyeDepth < sampled - bias ) factor -= 1.0 / samples;
}
return factor;
}
}
return eyeDepth < sampled - bias ? 0.0 : factor;
}
#endif
#if RT
float shadowFactorRT( const Light light, float def ) {
Ray ray;
ray.origin = surface.position.world;
ray.direction = light.position - ray.origin;
float tMin = ubo.settings.rt.defaultRayBounds.x;
float tMax = length(ray.direction) - ubo.settings.rt.defaultRayBounds.x;
ray.direction = normalize(ray.direction);
uint rayFlags = gl_RayFlagsOpaqueEXT | gl_RayFlagsTerminateOnFirstHitEXT | gl_RayFlagsSkipClosestHitShaderEXT;
uint cullMask = 0xFF;
rayQueryEXT rayQuery;
rayQueryInitializeEXT(rayQuery, tlas, rayFlags, cullMask, ray.origin, tMin, ray.direction, tMax);
while(rayQueryProceedEXT(rayQuery));
return rayQueryGetIntersectionTypeEXT(rayQuery, true) == gl_RayQueryCommittedIntersectionNoneEXT ? 1.0 : 0.0;
}
#endif
float shadowFactor( const Light light, float def ) {
#if RT
return shadowFactorRT( light, def );
#endif
if ( light.typeMap != 0 ) return omniShadowMap( light, def );
if ( !validTextureIndex(light.indexMap) )
#if VXGI
return voxelShadowFactor( light, def );
#else
return 1.0;
#endif
vec4 positionClip = light.projection * light.view * vec4(surface.position.world, 1.0);
positionClip.xyz /= positionClip.w;
if ( positionClip.x < -1 || positionClip.x >= 1 ) return def; //0.0;
if ( positionClip.y < -1 || positionClip.y >= 1 ) return def; //0.0;
if ( positionClip.z <= 0 || positionClip.z >= 1 ) return def; //0.0;
float factor = 1.0;
// spot light
if ( abs(light.type) == 2 || abs(light.type) == 3 ) {
const float dist = length( positionClip.xy );
if ( dist > 0.5 ) return def; //0.0;
// spot light with attenuation
if ( abs(light.type) == 3 ) {
factor = 1.0 - (pow(dist * 2,2.0));
}
}
const vec2 uv = positionClip.xy * 0.5 + 0.5;
const float bias = light.depthBias;
const float eyeDepth = positionClip.z;
const int samples = int(SHADOW_SAMPLES);
if ( samples < 1 ) return eyeDepth < texture(samplerTextures[nonuniformEXT(light.indexMap)], uv).r - bias ? 0.0 : factor;
for ( int i = 0; i < samples; ++i ) {
const int index = int( float(samples) * random(floor(surface.position.world.xyz * 1000.0), i)) % samples;
const float lightDepth = texture(samplerTextures[nonuniformEXT(light.indexMap)], uv + poissonDisk[index] / 700.0 ).r;
if ( eyeDepth < lightDepth - bias ) factor -= 1.0 / samples;
}
return factor;
}

View File

@ -0,0 +1,308 @@
struct EyeMatrices {
mat4 view;
mat4 projection;
mat4 model;
mat4 previous;
mat4 iView;
mat4 iProjection;
vec4 eyePos;
};
struct Viewport {
mat4 view;
mat4 projection;
};
struct Cursor {
vec2 position;
vec2 radius;
vec4 color;
};
struct Ray {
vec3 origin;
vec3 direction;
vec3 position;
float distance;
};
struct Space {
vec3 eye;
vec3 world;
};
struct Light {
mat4 view;
mat4 projection;
vec3 position;
float radius;
vec3 color;
float power;
int type;
int typeMap;
int indexMap;
float depthBias;
};
struct Material {
vec4 colorBase;
vec4 colorEmissive;
float factorMetallic;
float factorRoughness;
float factorOcclusion;
float factorAlphaCutoff;
int indexAlbedo;
int indexNormal;
int indexEmissive;
int indexOcclusion;
int indexMetallicRoughness;
int padding1;
int padding2;
int modeAlpha;
};
struct Texture {
int index;
int samp;
int remap;
float blend;
vec4 lerp;
};
struct DrawCommand {
uint indices; // triangle count
uint instances; // instance count
uint indexID; // starting triangle position
int vertexID; // starting vertex position
uint instanceID; // starting instance position
float padding1; //
float padding2; // material to use for this draw call
uint vertices; // number of vertices used
};
struct Bounds {
vec3 min;
float padding1;
vec3 max;
float padding2;
};
struct Instance {
mat4 model;
mat4 previous;
vec4 color;
uint materialID;
uint primitiveID;
uint meshID;
uint objectID;
int jointID;
int lightmapID;
uint imageID;
uint auxID;
Bounds bounds;
// InstanceAddresses addresses;
};
struct InstanceAddresses {
uint64_t vertex;
uint64_t index;
uint64_t indirect;
uint drawID;
uint padding0;
uint64_t position;
uint64_t uv;
uint64_t color;
uint64_t st;
uint64_t normal;
uint64_t tangent;
uint64_t joints;
uint64_t weights;
uint64_t id;
uint64_t padding1;
};
struct SurfaceMaterial {
vec4 albedo;
vec4 indirect;
float metallic;
float roughness;
float occlusion;
bool lightmapped;
};
struct Surface {
uint pass;
uint subID;
vec3 uv;
vec3 st;
Space position;
Space normal;
Space tangent;
mat3 tbn;
vec3 barycentric;
vec2 motion;
Ray ray;
SurfaceMaterial material;
Instance instance;
vec4 light;
vec4 fragment;
} surface;
// MSAA info
#if MULTISAMPLING
struct MSAA {
int currentID;
uvec2 IDs[MAX_MSAA_SAMPLES];
vec4 fragment;
vec4 fragments[MAX_MSAA_SAMPLES];
} msaa;
#endif
// UBO settings
struct SettingsLengths {
uint lights;
uint materials;
uint textures;
uint drawCommands;
};
struct SettingsMode {
vec4 parameters;
uint type;
uint scalar;
uint msaa;
uint frameNumber;
};
struct SettingsLighting {
vec3 ambient;
uint indexSkybox;
uint maxShadows;
uint shadowSamples;
uint useLightmaps;
};
struct SettingsFog {
vec3 color;
float stepScale;
vec3 offset;
float densityScale;
vec2 range;
float densityThreshold;
float densityMultiplier;
float absorbtion;
float padding1;
float padding2;
float padding3;
};
struct SettingsBloom {
float exposure;
float gamma;
float threshold;
uint padding;
};
struct SettingsVxgi {
mat4 matrix;
float cascadePower;
float granularity;
float voxelizeScale;
float occlusionFalloff;
float traceStartOffsetFactor;
uint shadows;
uint padding2;
uint padding3;
};
struct SettingsRayTrace {
vec2 defaultRayBounds;
float alphaTestOffset;
float padding1;
uint samples;
uint paths;
uint frameAccumulationMinimum;
uint padding2;
};
struct Settings {
SettingsLengths lengths;
SettingsMode mode;
SettingsLighting lighting;
SettingsFog fog;
SettingsBloom bloom;
SettingsVxgi vxgi;
SettingsRayTrace rt;
};
struct Voxel {
uvec2 id;
vec3 position;
vec3 normal;
vec2 uv;
vec4 color;
};
struct VoxelInfo {
vec3 min;
vec3 max;
float mipmapLevels;
float radianceSize;
float radianceSizeRecip;
} voxelInfo;
// Raytrace stuff
struct Vertex {
vec3 position;
vec2 uv;
uint color;
vec2 st;
vec3 normal;
vec3 tangent;
uvec2 joints;
vec4 weights;
uint id;
};
struct Triangle {
Vertex point;
vec3 geomNormal;
uint instanceID;
};
struct RayTracePayload {
bool hit;
uint instanceID;
uint primitiveID;
vec2 attributes;
// Triangle triangle;
};

View File

@ -0,0 +1,189 @@
// GI
uint cascadeIndex( vec3 v ) {
float x = max3( abs( v ) );
for ( uint cascade = 0; cascade < CASCADES; ++cascade )
if ( x / cascadePower(cascade) < 1 - voxelInfo.radianceSizeRecip ) return cascade;
return CASCADES - 1;
}
vec4 voxelTrace( inout Ray ray, float aperture, float maxDistance ) {
ray.origin += ray.direction * voxelInfo.radianceSizeRecip * 2 * SQRT2;
#if VXGI_NDC
ray.origin = vec3( ubo.settings.vxgi.matrix * vec4( ray.origin, 1.0 ) );
ray.direction = vec3( ubo.settings.vxgi.matrix * vec4( ray.direction, 0.0 ) );
uint cascade = cascadeIndex(ray.origin);
#else
uint cascade = cascadeIndex( vec3( ubo.settings.vxgi.matrix * vec4( ray.origin, 1.0 ) ) );
#endif
const float granularityRecip = ubo.settings.vxgi.granularity; //2.0; // 0.25f * (CASCADES - cascade);
const float granularity = 1.0f / granularityRecip;
const float occlusionFalloff = ubo.settings.vxgi.occlusionFalloff; //128.0f;
const vec3 voxelBounds = voxelInfo.max - voxelInfo.min;
const vec3 voxelBoundsRecip = 1.0f / voxelBounds;
const float coneCoefficient = 2.0 * tan(aperture * 0.5);
const uint maxSteps = uint(voxelInfo.radianceSize * cascadePower(CASCADES-1) * granularityRecip);
// box
const vec2 rayBoxInfoA = rayBoxDst( voxelInfo.min * cascadePower(cascade), voxelInfo.max * cascadePower(cascade), ray );
const vec2 rayBoxInfoB = rayBoxDst( voxelInfo.min * cascadePower(CASCADES-1), voxelInfo.max * cascadePower(CASCADES-1), ray );
const float tStart = rayBoxInfoA.x;
const float tEnd = maxDistance > 0 ? min(maxDistance, rayBoxInfoB.y) : rayBoxInfoB.y;
const float tDelta = voxelInfo.radianceSizeRecip * granularityRecip;
// marcher
ray.distance = tStart + tDelta * ubo.settings.vxgi.traceStartOffsetFactor;
ray.position = vec3(0);
vec4 radiance = vec4(0);
vec3 uvw = vec3(0);
float coneDiameter = coneCoefficient * ray.distance;
float level = aperture > 0 ? log2( coneDiameter ) : 0;
vec4 color = vec4(0);
float occlusion = 0.0;
uint stepCounter = 0;
while ( color.a < 1.0 && occlusion < 1.0 && ray.distance < tEnd && stepCounter++ < maxSteps ) {
ray.distance += tDelta * cascadePower(cascade) * max(1, coneDiameter);
ray.position = ray.origin + ray.direction * ray.distance;
#if VXGI_NDC
uvw = ray.position;
#else
uvw = vec3( ubo.settings.vxgi.matrix * vec4( ray.position, 1.0 ) );
#endif
cascade = cascadeIndex( uvw );
uvw = (uvw / cascadePower(cascade)) * 0.5 + 0.5;
if ( cascade >= CASCADES || uvw.x < 0.0 || uvw.y < 0.0 || uvw.z < 0.0 || uvw.x >= 1.0 || uvw.y >= 1.0 || uvw.z >= 1.0 ) break;
coneDiameter = coneCoefficient * ray.distance;
level = aperture > 0 ? log2( coneDiameter ) : 0;
if ( level >= voxelInfo.mipmapLevels ) break;
radiance = textureLod(voxelRadiance[nonuniformEXT(cascade)], uvw.xzy, level);
color += (1.0 - color.a) * radiance;
occlusion += ((1.0f - occlusion) * radiance.a) / (1.0f + occlusionFalloff * coneDiameter);
}
return maxDistance > 0 ? color : vec4(color.rgb, occlusion);
// return vec4(color.rgb, occlusion);
}
vec4 voxelConeTrace( inout Ray ray, float aperture ) {
return voxelTrace( ray, aperture, 0 );
}
vec4 voxelTrace( inout Ray ray, float maxDistance ) {
return voxelTrace( ray, 0, maxDistance );
}
uint voxelShadowsCount = 0;
float voxelShadowFactor( const Light light, float def ) {
if ( ubo.settings.vxgi.shadows < ++voxelShadowsCount ) return 1.0;
const float SHADOW_APERTURE = 0.2;
const float DEPTH_BIAS = 0.0;
Ray ray;
ray.direction = normalize( light.position - surface.position.world );
ray.origin = surface.position.world + ray.direction * 0.5;
float z = distance( surface.position.world, light.position ) - DEPTH_BIAS;
return 1.0 - voxelTrace( ray, SHADOW_APERTURE, z ).a;
}
void indirectLighting() {
voxelInfo.radianceSize = textureSize( voxelRadiance[0], 0 ).x;
voxelInfo.radianceSizeRecip = 1.0 / voxelInfo.radianceSize;
voxelInfo.mipmapLevels = log2(voxelInfo.radianceSize) + 1;
#if VXGI_NDC
voxelInfo.min = vec3( -1 );
voxelInfo.max = vec3( 1 );
#else
const mat4 inverseOrtho = inverse( ubo.settings.vxgi.matrix );
voxelInfo.min = vec3( inverseOrtho * vec4( -1, -1, -1, 1 ) );
voxelInfo.max = vec3( inverseOrtho * vec4( 1, 1, 1, 1 ) );
#endif
const vec3 P = surface.position.world;
const vec3 N = surface.normal.world;
#if 1
const vec3 right = normalize(orthogonal(N));
const vec3 up = normalize(cross(right, N));
const uint CONES_COUNT = 6;
const vec3 CONES[] = {
N,
normalize(N + 0.0f * right + 0.866025f * up),
normalize(N + 0.823639f * right + 0.267617f * up),
normalize(N + 0.509037f * right + -0.7006629f * up),
normalize(N + -0.50937f * right + -0.7006629f * up),
normalize(N + -0.823639f * right + 0.267617f * up),
};
#else
const vec3 ortho = normalize(orthogonal(N));
const vec3 ortho2 = normalize(cross(ortho, N));
const vec3 corner = 0.5f * (ortho + ortho2);
const vec3 corner2 = 0.5f * (ortho - ortho2);
const uint CONES_COUNT = 9;
const vec3 CONES[] = {
N,
normalize(mix(N, ortho, 0.5)),
normalize(mix(N, -ortho, 0.5)),
normalize(mix(N, ortho2, 0.5)),
normalize(mix(N, -ortho2, 0.5)),
normalize(mix(N, corner, 0.5)),
normalize(mix(N, -corner, 0.5)),
normalize(mix(N, corner2, 0.5)),
normalize(mix(N, -corner2, 0.5)),
};
#endif
const float DIFFUSE_CONE_APERTURE = 2.0 * 0.57735f;
const float DIFFUSE_INDIRECT_FACTOR = 0; // 1.0f / float(CONES_COUNT) * 0.125f;
const float SPECULAR_CONE_APERTURE = clamp(tan(PI * 0.5f * surface.material.roughness), 0.0174533f, PI); // tan( R * PI * 0.5f * 0.1f );
const float SPECULAR_INDIRECT_FACTOR = (1.0 - surface.material.metallic); // * 0.25; // 1.0f;
vec4 indirectDiffuse = vec4(0);
vec4 indirectSpecular = vec4(0);
// outFragColor.rgb = voxelConeTrace( surface.ray, 0 ).rgb; return;
if ( DIFFUSE_INDIRECT_FACTOR > 0.0f ) {
float weight = PI * 0.25f;
for ( uint i = 0; i < CONES_COUNT; ++i ) {
Ray ray;
ray.direction = CONES[i].xyz;
ray.origin = P; // + ray.direction;
indirectDiffuse += voxelConeTrace( ray, DIFFUSE_CONE_APERTURE ) * weight;
weight = PI * 0.15f;
}
// indirectDiffuse.rgb *= surface.material.albedo.rgb;
surface.material.occlusion += 1.0 - clamp(indirectDiffuse.a, 0.0, 1.0);
// outFragColor.rgb = indirectDiffuse.rgb; return;
// outFragColor.rgb = vec3(surface.material.occlusion); return;
}
if ( SPECULAR_INDIRECT_FACTOR > 0.0f ) {
const vec3 R = reflect( normalize(P - surface.ray.origin), N );
Ray ray;
ray.direction = R;
ray.origin = P; // + ray.direction;
indirectSpecular = voxelConeTrace( ray, SPECULAR_CONE_APERTURE );
// indirectSpecular.rgb *= surface.material.albedo.rgb;
// outFragColor.rgb = indirectSpecular.rgb; return;
}
/*
if ( true ) {
gammaCorrect(indirectDiffuse.rgb, 1.0 / ubo.settings.bloom.gamma);
}
*/
indirectDiffuse *= DIFFUSE_INDIRECT_FACTOR;
indirectSpecular *= SPECULAR_INDIRECT_FACTOR;
surface.material.indirect = indirectDiffuse + indirectSpecular;
// outFragColor.rgb = surface.material.indirect.rgb; return;
// deferred sampling doesn't have a blended albedo buffer
// in place we'll just cone trace behind the window
if ( surface.material.albedo.a < 1.0 ) {
Ray ray;
ray.direction = surface.ray.direction;
ray.origin = surface.position.world + ray.direction;
vec4 radiance = voxelConeTrace( ray, surface.material.albedo.a * 0.5 );
surface.fragment.rgb += (1.0 - surface.material.albedo.a) * radiance.rgb;
}
}

View File

@ -0,0 +1,67 @@
#version 450
#pragma shader_stage(compute)
#define COMPUTE 1
#define TEXTURES 0
#define CUBEMAPS 0
#define BLOOM 1
layout (local_size_x = 8, local_size_y = 8, local_size_z = 8) in;
layout( push_constant ) uniform PushBlock {
uint eye;
uint mode;
} PushConstant;
layout (binding = 0) uniform UBO {
float scale;
float strength;
float threshold;
float sigma;
float gamma;
float exposure;
uint samples;
uint padding;
} ubo;
layout (binding = 1, rgba16f) uniform volatile coherent image2D imageColor;
layout (binding = 2, rgba16f) uniform volatile coherent image2D imageBloom;
layout (binding = 3, rgba16f) uniform volatile coherent image2D imagePingPong;
#include "../../common/macros.h"
#include "../../common/structs.h"
#include "../../common/functions.h"
void main() {
const uint mode = PushConstant.mode;
const ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
const ivec2 size = imageSize( imageColor );
if ( texel.x >= size.x || texel.y >= size.y ) return;
if ( mode == 0 ) { // fill bloom
vec3 result = imageLoad( imageColor, texel ).rgb;
float brightness = dot(result, vec3(0.2126, 0.7152, 0.0722));
if ( brightness < ubo.threshold ) result = vec3(0, 0, 0);
imageStore( imageBloom, texel, vec4( result, 1.0 ) );
} else if ( mode == 1 ) { // bloom horizontal
vec3 result = imageLoad( imageBloom, texel ).rgb * gauss( 0, ubo.sigma ) * ubo.strength;
for( int i = 1; i < ubo.samples; ++i ) {
result += imageLoad( imageBloom, texel + ivec2(i * ubo.scale, 0.0)).rgb * gauss( i * ubo.scale / ubo.samples, ubo.sigma ) * ubo.strength;
result += imageLoad( imageBloom, texel - ivec2(i * ubo.scale, 0.0)).rgb * gauss( i * ubo.scale / ubo.samples, ubo.sigma ) * ubo.strength;
}
// write to PingPong
imageStore( imagePingPong, texel, vec4( result, 1.0 ) );
} else if ( mode == 2 ) { // bloom vertical
vec3 result = imageLoad( imagePingPong, texel ).rgb * gauss( 0, ubo.sigma ) * ubo.strength;
for( int i = 1; i < ubo.samples; ++i ) {
result += imageLoad( imagePingPong, texel + ivec2(0.0, i * ubo.scale)).rgb * gauss( i * ubo.scale / ubo.samples, ubo.sigma ) * ubo.strength;
result += imageLoad( imagePingPong, texel - ivec2(0.0, i * ubo.scale)).rgb * gauss( i * ubo.scale / ubo.samples, ubo.sigma ) * ubo.strength;
}
// write to Bloom
imageStore( imageBloom, texel, vec4( result, 1.0 ) );
} else if ( mode == 3 ) { // combine
vec3 result = imageLoad( imageColor, texel ).rgb + imageLoad( imageBloom, texel ).rgb;
imageStore( imageColor, texel, vec4( result, 1.0 ) );
}
}

View File

@ -0,0 +1,13 @@
#version 450
#pragma shader_stage(compute)
#define RT 0
#define VXGI 0
#define MULTISAMPLING 0
#include "./comp.h"
void main() {
populateSurface();
directLighting();
postProcess();
}

View File

@ -0,0 +1,287 @@
#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 = 4, local_size_y = 4, local_size_z = 1) in;
#define COMPUTE 1
#define DEFERRED 1
#define DEFERRED_SAMPLING 1
#define PBR 1
#define LAMBERT 0
#if RT || BARYCENTRIC
#define BUFFER_REFERENCE 0
#define UINT64_ENABLED 0
#endif
#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 Materials {
Material materials[];
};
layout (std140, binding = 15) readonly buffer Textures {
Texture textures[];
};
layout (std140, binding = 16) readonly buffer Lights {
Light lights[];
};
layout (binding = 17) uniform sampler2D samplerTextures[TEXTURES];
layout (binding = 18) uniform samplerCube samplerCubemaps[CUBEMAPS];
layout (binding = 19) uniform sampler3D samplerNoise;
#if VXGI
layout (binding = 20) uniform usampler3D voxelId[CASCADES];
layout (binding = 21) uniform sampler3D voxelNormal[CASCADES];
layout (binding = 22) uniform sampler3D voxelRadiance[CASCADES];
#endif
#if RT
layout (binding = 23) uniform accelerationStructureEXT tlas;
#endif
#if BUFFER_REFERENCE
layout(buffer_reference, scalar) buffer Vertices { Vertex v[]; };
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 VUv { vec2 v[]; };
layout(buffer_reference, scalar) buffer VColor { uint v[]; };
layout(buffer_reference, scalar) buffer VSt { vec2 v[]; };
layout(buffer_reference, scalar) buffer VNormal { vec3 v[]; };
layout(buffer_reference, scalar) buffer VTangent { vec3 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 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 )
void postProcess() {
#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 == 0x0001 ) {
outFragColor = vec4(surface.material.albedo.rgb, 1);
} else if ( ubo.settings.mode.type == 0x0002 ) {
outFragColor = vec4(surface.normal.eye.rgb, 1);
} else if ( ubo.settings.mode.type == 0x0003 ) {
outFragColor = vec4(surface.uv.xy, 0, 1);
} else if ( ubo.settings.mode.type == 0x0004 ) {
outFragColor = vec4(surface.st.xy, 0, 1);
}
IMAGE_STORE( imageColor, outFragColor );
IMAGE_STORE( imageBright, outFragBright );
IMAGE_STORE( imageMotion, vec4(outFragMotion, 0, 0) );
}
void populateSurface() {
uvec2 renderSize = imageSize(imageColor);
if ( gl_GlobalInvocationID.x >= renderSize.x || gl_GlobalInvocationID.y >= renderSize.y || gl_GlobalInvocationID.z > PushConstant.pass ) return;
surface.fragment = vec4(0);
surface.pass = PushConstant.pass;
{
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;*/ ubo.eyes[surface.pass].eyePos.xyz;
const float 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
surface.motion = vec2(0);
if ( ID.x == 0 || ID.y == 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;
}
surface.fragment.a = 0.0;
return;
}
{
const uint triangleID = ID.x - 1;
const uint instanceID = 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.fragment = vec4(0);
surface.light = vec4(0);
surface.instance = instances[instanceID];
populateSurfaceMaterial();
#endif
}
{
vec4 pNDC = ubo.eyes[surface.pass].previous * surface.instance.previous * vec4(surface.position.world, 1);
vec4 cNDC = ubo.eyes[surface.pass].model * surface.instance.model * vec4(surface.position.world, 1);
pNDC /= pNDC.w;
cNDC /= cNDC.w;
surface.motion = cNDC.xy - pNDC.xy;
}
}
void directLighting() {
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;
}
#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
indirectLighting();
#endif
directLighting();
}
msaa.fragment += surface.fragment;
msaa.fragments[msaa.currentID] = surface.fragment;
}
surface.fragment = msaa.fragment / ubo.settings.mode.msaa;
}
#endif

View File

@ -0,0 +1,13 @@
#version 450
#pragma shader_stage(compute)
#define RT 0
#define VXGI 0
#define MULTISAMPLING 1
#include "./comp.h"
void main() {
resolveSurfaceFragment();
postProcess();
}

View File

@ -0,0 +1,13 @@
#version 460
#pragma shader_stage(compute)
#define RT 1
#define VXGI 0
#define MULTISAMPLING 0
#include "./comp.h"
void main() {
populateSurface();
directLighting();
postProcess();
}

View File

@ -0,0 +1,13 @@
#version 460
#pragma shader_stage(compute)
#define RT 1
#define VXGI 0
#define MULTISAMPLING 1
#include "./comp.h"
void main() {
populateSurface();
directLighting();
postProcess();
}

View File

@ -0,0 +1,14 @@
#version 460
#pragma shader_stage(compute)
#define RT 1
#define VXGI 1
#define MULTISAMPLING 0
#include "./comp.h"
void main() {
populateSurface();
indirectLighting();
directLighting();
postProcess();
}

View File

@ -0,0 +1,13 @@
#version 460
#pragma shader_stage(compute)
#define RT 1
#define VXGI 1
#define MULTISAMPLING 1
#include "./comp.h"
void main() {
populateSurface();
directLighting();
postProcess();
}

View File

@ -0,0 +1,14 @@
#version 450
#pragma shader_stage(compute)
#define RT 0
#define VXGI 1
#define MULTISAMPLING 0
#include "./comp.h"
void main() {
populateSurface();
indirectLighting();
directLighting();
postProcess();
}

View File

@ -0,0 +1,12 @@
#version 450
#pragma shader_stage(compute)
#define RT 0
#define VXGI 1
#define MULTISAMPLING 1
#include "./comp.h"
void main() {
resolveSurfaceFragment();
postProcess();
}

View File

@ -0,0 +1,30 @@
#version 450
#pragma shader_stage(compute)
//#extension GL_EXT_nonuniform_qualifier : enable
layout (constant_id = 0) const uint MIPS = 6;
layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
#define COMPUTE 1
#include "../../common/macros.h"
#include "../../common/structs.h"
layout( push_constant ) uniform PushBlock {
uint _;
uint pass;
} PushConstant;
layout (binding = 3) uniform sampler2D inImage[MIPS];
layout (binding = 4, r32f) uniform volatile coherent image2D outImage[MIPS];
void main() {
vec2 imageSize = imageSize(outImage[PushConstant.pass]);
uvec2 pos = gl_GlobalInvocationID.xy;
if ( pos.x >= imageSize.x || pos.y >= imageSize.y ) return;
float depth = texture(inImage[PushConstant.pass], (vec2(pos) + vec2(0.5)) / imageSize).x;
imageStore(outImage[PushConstant.pass], ivec2(pos), vec4(depth));
}

View File

@ -0,0 +1,35 @@
#version 450
#pragma shader_stage(fragment)
#extension GL_EXT_samplerless_texture_functions : require
layout (location = 0) in vec2 inUv;
layout (location = 1) flat in uint inPass;
layout (location = 0) out vec4 outColor;
layout (binding = 0) uniform sampler2D samplerColor;
layout (binding = 1) uniform UBO {
float curTime;
float gamma;
float exposure;
uint padding;
} ubo;
#define TONE_MAP 1
#define GAMMA_CORRECT 1
#define TEXTURES 1
#include "../../common/macros.h"
#include "../../common/structs.h"
#include "../../common/functions.h"
void main() {
outColor = texture( samplerColor, inUv );
#if TONE_MAP
toneMap(outColor, ubo.exposure);
#endif
#if GAMMA_CORRECT
gammaCorrect(outColor, ubo.gamma);
#endif
}

View File

@ -0,0 +1,392 @@
#version 450
#pragma shader_stage(fragment)
#extension GL_EXT_samplerless_texture_functions : require
layout (location = 0) in vec2 inUv;
layout (location = 1) flat in uint inPass;
layout (location = 0) out vec4 outColor;
layout (binding = 0) uniform sampler2D samplerColor;
layout (binding = 1) uniform UBO {
float curTime;
float gamma;
float exposure;
uint padding;
} ubo;
#define TONE_MAP 1
#define GAMMA_CORRECT 1
#define TEXTURES 1
#include "../../common/macros.h"
#include "../../common/structs.h"
#include "../../common/functions.h"
#define M_PI 3.1415926535897932384626433832795
const float u_imgx = 0;
const float u_imgy = 0;
const float u_imgw = 1;
const float u_imgh = 1;
const float u_img_gain = 2;
const float u_img_bias = 0;
const float u_beam_bias = 0.185;
const float u_beam_gain = 0.25;
const float u_corner = 0.05;
const float u_zoom = 1.0;
const float u_shape = 2;
const float u_round = -0.02;
const float u_grain = 0.4;
const float u_vpitch = 936.1;
const float u_hpitch = 1024.6;
const float u_top = 1;
const float u_bot = 1;
void main() {
const vec2 screenResolution = textureSize( samplerColor, 0 );
const float u_lines = screenResolution.y * 0.75;
vec2 uv_orig = (inUv.xy * 2.0 - 1.0);
vec2 uv_mod = uv_orig * pow(1.0-abs(uv_orig),vec2(u_round)) * (u_zoom + u_corner * pow( abs(uv_orig.yx), vec2(u_shape)) );
vec2 uv = uv_mod / 2.0 + 0.5;
if ( abs(uv_mod).x > 1.0 || abs(uv_mod.y) > 1.0 ) {
outColor = vec4(0.0, 0.0, 0.0, 1.0);
return;
}
float spacing = 1.0/u_lines;
uv+=spacing*0.5;
float line_top = ( ceil(uv.y*u_lines)) / u_lines;
float line_bot = line_top - spacing;
vec2 scale = vec2(u_imgw, u_imgh);
vec2 offset = vec2(u_imgx, u_imgy);
vec2 uv_top = (vec2(uv.x, line_top)+offset) * scale - (scale-1.0)*0.5 ;
vec2 uv_bot = (vec2(uv.x, line_bot)+offset) * scale - (scale-1.0)*0.5 ;
uv_top -= spacing * 0.5;
uv_bot -= spacing * 0.5;
vec4 sampled_top = texture(samplerColor, uv_top);
vec4 sampled_bot = texture(samplerColor, uv_bot);
vec3 color_top = sampled_top.xyz * u_img_gain + u_img_bias;
vec3 color_bot = sampled_bot.xyz * u_img_gain + u_img_bias;
float dist_top = pow(abs(uv.y - line_top), 1.0);
float dist_bot = pow(abs(uv.y - line_bot), 1.0);
vec3 beam_top = 1.0 - (dist_top / (spacing * (color_top * u_beam_gain + u_beam_bias)));
vec3 beam_bot = 1.0 - (dist_bot / (spacing * (color_bot * u_beam_gain + u_beam_bias)));
beam_top = clamp(beam_top, 0.0, 1.0) ;
beam_bot = clamp(beam_bot, 0.0, 1.0) ;
vec3 color = (color_top*beam_top)*u_top + (color_bot*beam_bot)*u_bot;
vec2 dot;
dot.y = floor(uv.y * u_vpitch) ;
dot.x = uv.x;
if (mod(dot.y, 2.0) > 0.5)
dot.x += (4.5/3.0) / u_hpitch;
dot.x = (floor(dot.x*u_hpitch)) ;
int fil = int(mod(dot.x, 3.0));
vec3 out_color = color * (1.0-u_grain);
vec3 passthru = vec3(
float(fil == 0),
float(fil == 1),
float(fil == 2)
) * (u_grain);
out_color += color * passthru;
outColor = vec4(out_color, (sampled_top.a + sampled_bot.a) * 0.5 );
#if TONE_MAP
toneMap(outColor, ubo.exposure);
#endif
#if GAMMA_CORRECT
gammaCorrect(outColor, ubo.gamma);
#endif
}
#if 0
float iTime = 0;
float noise(vec2 p) {
float s = (fract(sin(dot(p * sin( iTime * 0.5 ), vec2(12.9898,78.233)*2.0)) * 43758.5453)); // texture(iChannel1,vec2(1.,2.*cos(iTime))*iTime*8. + p*1.).x;
s *= s;
return s;
}
float onOff(float a, float b, float c) {
return step(c, sin(iTime + a*cos(iTime*b)));
}
float ramp(float y, float start, float end) {
float inside = step(start,y) - step(end,y);
float fact = (y-start)/(end-start)*inside;
return (1.-fact) * inside;
}
float stripes(vec2 uv) {
float noi = noise(uv*vec2(0.5,1.) + vec2(1.,3.));
return ramp(mod(uv.y*4. + iTime/2.+sin(iTime + sin(iTime*0.63)),1.),0.5,0.6)*noi;
}
vec4 getVideo(vec2 uv) {
vec2 look = uv;
float window = 1./(1.+20.*(look.y-mod(iTime/4.,1.))*(look.y-mod(iTime/4.,1.)));
look.x = look.x + sin(look.y*10. + iTime)/50.*onOff(4.,4.,.3)*(1.+cos(iTime*80.))*window;
float vShift = 0.4*onOff(2.,3.,.9)*(sin(iTime)*sin(iTime*20.) +
(0.5 + 0.1*sin(iTime*200.)*cos(iTime)));
look.y = mod(look.y + vShift, 1.);
return texture(samplerColor,look);
}
vec2 screenDistort(vec2 uv) {
uv -= vec2(.5,.5);
uv = uv*1.2*(1./1.2+2.*uv.x*uv.x*uv.y*uv.y);
uv += vec2(.5,.5);
return uv;
}
void main() {
vec2 uv = inUv.xy; // fragCoord.xy / iResolution.xy;
iTime = ubo.curTime;
uv = screenDistort(uv);
vec4 video = getVideo(uv);
float vigAmt = 3.+.3*sin(iTime + 5.*cos(iTime*5.));
float vignette = (1.-vigAmt*(uv.y-.5)*(uv.y-.5))*(1.-vigAmt*(uv.x-.5)*(uv.x-.5));
video.rgb += stripes(uv);
video.rgb += noise(uv*2.)/4.;
video.rgb *= vignette;
video.rgb *= (12.+mod(uv.y*30.+iTime,1.))/13.;
outColor = video;
#if TONE_MAP
toneMap(outColor, ubo.exposure);
#endif
#if GAMMA_CORRECT
gammaCorrect(outColor, ubo.gamma);
#endif
}
#endif
#if 0
vec2 curveRemapUV(vec2 uv, vec2 curvature) {
uv = uv * 2.0 - 1.0;
vec2 offset = abs(uv.yx) / vec2(curvature.x, curvature.y);
uv = uv + uv * offset * offset;
uv = uv * 0.5 + 0.5;
return uv;
}
vec4 scanLineIntensity(float uv, float resolution, float opacity) {
float intensity = sin(uv * resolution * PI * 2.0);
intensity = ((0.5 * intensity) + 0.5) * 0.9 + 0.1;
return vec4(vec3(pow(intensity, opacity)), 1.0);
}
vec4 vignetteIntensity(vec2 uv, vec2 resolution, float opacity, float roundness) {
float intensity = uv.x * uv.y * (1.0 - uv.x) * (1.0 - uv.y);
return vec4(vec3(clamp(pow((resolution.x / roundness) * intensity, opacity), 0.0, 1.0)), 1.0);
}
void main(void) {
const vec2 screenResolution = textureSize( samplerColor, 0 );
const vec2 scanLineOpacity = vec2(0.5);
const float brightness = 2;
const float vignetteOpacity = 0.5;
const float vignetteRoundness = 0.5;
const vec2 curvature = vec2(8);
const vec2 remappedUV = curveRemapUV(vec2(inUv.x, inUv.y), curvature);
vec4 baseColor = texture(samplerColor, remappedUV);
baseColor *= vignetteIntensity(remappedUV, screenResolution, vignetteOpacity, vignetteRoundness);
baseColor *= scanLineIntensity(remappedUV.x, screenResolution.y, scanLineOpacity.x);
baseColor *= scanLineIntensity(remappedUV.y, screenResolution.x, scanLineOpacity.y);
baseColor *= vec4(vec3(brightness), 1.0);
if (remappedUV.x < 0.0 || remappedUV.y < 0.0 || remappedUV.x > 1.0 || remappedUV.y > 1.0){
outColor = vec4(0.0, 0.0, 0.0, 1.0);
} else {
outColor = baseColor;
}
#if TONE_MAP
toneMap(outColor, ubo.exposure);
#endif
#if GAMMA_CORRECT
gammaCorrect(outColor, ubo.gamma);
#endif
}
#endif
#if 0
vec2 fragCoord = vec2(0,0);
vec2 iResolution = vec2(640,480);
// Emulated input resolution.
#if 0
// Fix resolution to set amount.
#define res (vec2(320.0/1.0,160.0/1.0))
#else
// Optimize for resize.
#define res (iResolution.xy/6.0)
#endif
// Hardness of scanline.
// -8.0 = soft
// -16.0 = medium
float hardScan=-8.0;
// Hardness of pixels in scanline.
// -2.0 = soft
// -4.0 = hard
float hardPix=-3.0;
// Display warp.
// 0.0 = none
// 1.0/8.0 = extreme
vec2 warp=vec2(1.0/32.0,1.0/24.0);
// Amount of shadow mask.
float maskDark=0.5;
float maskLight=1.5;
//------------------------------------------------------------------------
// sRGB to Linear.
// Assuing using sRGB typed textures this should not be needed.
float ToLinear1(float c){return(c<=0.04045)?c/12.92:pow((c+0.055)/1.055,2.4);}
vec3 ToLinear(vec3 c){return vec3(ToLinear1(c.r),ToLinear1(c.g),ToLinear1(c.b));}
// Linear to sRGB.
// Assuing using sRGB typed textures this should not be needed.
float ToSrgb1(float c){return(c<0.0031308?c*12.92:1.055*pow(c,0.41666)-0.055);}
vec3 ToSrgb(vec3 c){return vec3(ToSrgb1(c.r),ToSrgb1(c.g),ToSrgb1(c.b));}
// Nearest emulated sample given floating point position and texel offset.
// Also zero's off screen.
vec3 Fetch(vec2 pos,vec2 off){
pos=floor(pos*res+off)/res;
if(max(abs(pos.x-0.5),abs(pos.y-0.5))>0.5)return vec3(0.0,0.0,0.0);
return ToLinear(texture(samplerColor,pos.xy,-16.0).rgb);}
// Distance in emulated pixels to nearest texel.
vec2 Dist(vec2 pos){pos=pos*res;return -((pos-floor(pos))-vec2(0.5));}
// 1D Gaussian.
float Gaus(float pos,float scale){return exp2(scale*pos*pos);}
// 3-tap Gaussian filter along horz line.
vec3 Horz3(vec2 pos,float off){
vec3 b=Fetch(pos,vec2(-1.0,off));
vec3 c=Fetch(pos,vec2( 0.0,off));
vec3 d=Fetch(pos,vec2( 1.0,off));
float dst=Dist(pos).x;
// Convert distance to weight.
float scale=hardPix;
float wb=Gaus(dst-1.0,scale);
float wc=Gaus(dst+0.0,scale);
float wd=Gaus(dst+1.0,scale);
// Return filtered sample.
return (b*wb+c*wc+d*wd)/(wb+wc+wd);}
// 5-tap Gaussian filter along horz line.
vec3 Horz5(vec2 pos,float off){
vec3 a=Fetch(pos,vec2(-2.0,off));
vec3 b=Fetch(pos,vec2(-1.0,off));
vec3 c=Fetch(pos,vec2( 0.0,off));
vec3 d=Fetch(pos,vec2( 1.0,off));
vec3 e=Fetch(pos,vec2( 2.0,off));
float dst=Dist(pos).x;
// Convert distance to weight.
float scale=hardPix;
float wa=Gaus(dst-2.0,scale);
float wb=Gaus(dst-1.0,scale);
float wc=Gaus(dst+0.0,scale);
float wd=Gaus(dst+1.0,scale);
float we=Gaus(dst+2.0,scale);
// Return filtered sample.
return (a*wa+b*wb+c*wc+d*wd+e*we)/(wa+wb+wc+wd+we);}
// Return scanline weight.
float Scan(vec2 pos,float off){
float dst=Dist(pos).y;
return Gaus(dst+off,hardScan);}
// Allow nearest three lines to effect pixel.
vec3 Tri(vec2 pos){
vec3 a=Horz3(pos,-1.0);
vec3 b=Horz5(pos, 0.0);
vec3 c=Horz3(pos, 1.0);
float wa=Scan(pos,-1.0);
float wb=Scan(pos, 0.0);
float wc=Scan(pos, 1.0);
return a*wa+b*wb+c*wc;}
// Distortion of scanlines, and end of screen alpha.
vec2 Warp(vec2 pos){
pos=pos*2.0-1.0;
pos*=vec2(1.0+(pos.y*pos.y)*warp.x,1.0+(pos.x*pos.x)*warp.y);
return pos*0.5+0.5;}
// Shadow mask.
vec3 Mask(vec2 pos){
pos.x+=pos.y*3.0;
vec3 mask=vec3(maskDark,maskDark,maskDark);
pos.x=fract(pos.x/6.0);
if(pos.x<0.333)mask.r=maskLight;
else if(pos.x<0.666)mask.g=maskLight;
else mask.b=maskLight;
return mask;}
void main() {
iResolution = textureSize( samplerColor, 0 );
fragCoord = inUv * iResolution;
vec2 pos = Warp(fragCoord.xy / iResolution.xy);
hardScan = -12.0;
maskDark = maskLight = 1.0;
outColor.rgb = Tri(pos) * Mask(fragCoord.xy);
outColor.rgb = ToSrgb(outColor.rgb);
outColor.a = 1.0;
#if TONE_MAP
toneMap(outColor, ubo.exposure);
#endif
#if GAMMA_CORRECT
gammaCorrect(outColor, ubo.gamma);
#endif
}
#endif
#if 0
void main() {
const vec2 uv = 0.025 * sin( ubo.curTime ) * inUv.xy;
const float mdf = 0.5;
const float noise = (fract(sin(dot(uv, vec2(12.9898,78.233)*2.0)) * 43758.5453));
const vec4 sampled = texture( samplerColor, inUv );
outColor = sampled - noise * mdf;
toneMap(outColor, ubo.exposure);
gammaCorrect(outColor, ubo.gamma);
}
#endif

View File

@ -0,0 +1,16 @@
#version 450
#pragma shader_stage(vertex)
layout (location = 0) out vec2 outUv;
layout (location = 1) out flat uint outPass;
layout( push_constant ) uniform PushBlock {
uint pass;
uint draw;
} PushConstant;
void main() {
outUv = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
outPass = PushConstant.pass;
gl_Position = vec4(outUv * 2.0f + -1.0f, 0.0f, 1.0f);
}

View File

@ -0,0 +1,148 @@
#version 450
#pragma shader_stage(compute)
#extension GL_EXT_samplerless_texture_functions : require
#extension GL_EXT_nonuniform_qualifier : enable
layout (local_size_x = 8, local_size_y = 8, local_size_z = 8) in;
#define COMPUTE 1
#define VXGI 1
#define MAX_CUBEMAPS CUBEMAPS
#define GAMMA_CORRECT 1
#define PBR 1
layout (constant_id = 0) const uint TEXTURES = 512;
layout (constant_id = 1) const uint CUBEMAPS = 128;
layout (constant_id = 2) const uint CASCADES = 16;
#include "../../common/macros.h"
#include "../../common/structs.h"
layout (binding = 0) uniform UBO {
EyeMatrices eyes[2];
Settings settings;
} ubo;
layout (std140, binding = 1) readonly buffer DrawCommands {
DrawCommand drawCommands[];
};
layout (std140, binding = 2) readonly buffer Instances {
Instance instances[];
};
layout (std140, binding = 3) readonly buffer InstanceAddresseses {
InstanceAddresses instanceAddresses[];
};
layout (std140, binding = 4) readonly buffer Materials {
Material materials[];
};
layout (std140, binding = 5) readonly buffer Textures {
Texture textures[];
};
layout (std140, binding = 6) readonly buffer Lights {
Light lights[];
};
layout (binding = 7) uniform sampler2D samplerTextures[TEXTURES];
layout (binding = 8) uniform samplerCube samplerCubemaps[CUBEMAPS];
layout (binding = 9) uniform sampler3D samplerNoise;
layout (binding = 10, rg16ui) uniform volatile coherent uimage3D voxelId[CASCADES];
layout (binding = 11, rg16f) uniform volatile coherent image3D voxelNormal[CASCADES];
#if VXGI_HDR
layout (binding = 12, rgba32f) uniform volatile coherent image3D voxelRadiance[CASCADES];
#else
layout (binding = 12, rgba16f) uniform volatile coherent image3D voxelRadiance[CASCADES];
#endif
#include "../../common/functions.h"
#include "../../common/light.h"
#undef VXGI //
#include "../../common/shadows.h"
void main() {
const vec3 tUvw = gl_GlobalInvocationID.xzy;
for ( uint CASCADE = 0; CASCADE < CASCADES; ++CASCADE ) {
surface.normal.world = decodeNormals( vec2(imageLoad(voxelNormal[CASCADE], ivec3(tUvw) ).xy) );
surface.normal.eye = vec3( ubo.settings.vxgi.matrix * vec4( surface.normal.world, 0.0f ) );
surface.position.eye = (vec3(gl_GlobalInvocationID.xyz) / vec3(imageSize(voxelRadiance[CASCADE])) * 2.0f - 1.0f) * cascadePower(CASCADE);
surface.position.world = vec3( inverse(ubo.settings.vxgi.matrix) * vec4( surface.position.eye, 1.0f ) );
const uvec2 ID = uvec2(imageLoad(voxelId[CASCADE], ivec3(tUvw) ).xy);
const uint drawID = ID.x - 1;
const uint instanceID = ID.y - 1;
if ( ID.x == 0 || ID.y == 0 ) {
imageStore(voxelRadiance[CASCADE], ivec3(tUvw), vec4(0));
continue;
}
const DrawCommand drawCommand = drawCommands[drawID];
surface.instance = instances[instanceID];
const Material material = materials[surface.instance.materialID];
surface.material.albedo = material.colorBase;
surface.fragment = material.colorEmissive;
surface.material.albedo = imageLoad(voxelRadiance[CASCADE], ivec3(tUvw) );
surface.material.metallic = material.factorMetallic;
surface.material.roughness = material.factorRoughness;
surface.material.occlusion = material.factorOcclusion;
const vec3 ambient = ubo.settings.lighting.ambient.rgb * surface.material.occlusion;
if ( validTextureIndex( surface.instance.lightmapID ) ) {
surface.fragment.rgb += surface.material.albedo.rgb;
} else {
surface.fragment.rgb += surface.material.albedo.rgb * ambient;
// corrections
surface.position.eye = vec3( ubo.eyes[surface.pass].view * vec4( surface.position.world, 1 ) );
surface.normal.eye = vec3( ubo.eyes[surface.pass].view * vec4(surface.normal.world, 0) );
pbr();
/*
surface.material.roughness *= 4.0;
const vec3 F0 = mix(vec3(0.04), surface.material.albedo.rgb, surface.material.metallic);
const vec3 Lo = normalize( surface.position.world );
const float cosLo = max(0.0, dot(surface.normal.world, Lo));
for ( uint i = 0; i < ubo.settings.lengths.lights; ++i ) {
const Light light = lights[i];
if ( light.power <= LIGHT_POWER_CUTOFF ) continue;
if ( light.type >= 0 && validTextureIndex( surface.instance.lightmapID ) ) continue;
const vec3 Lp = light.position;
const vec3 Liu = light.position - surface.position.world;
const vec3 Li = normalize(Liu);
const float Ls = shadowFactor( light, 0.0 );
const float La = 1.0 / (1 + (PI * pow(length(Liu), 2.0)));
if ( light.power * La * Ls <= LIGHT_POWER_CUTOFF ) continue;
const float cosLi = max(0.0, dot(surface.normal.world, Li));
const vec3 Lr = light.color.rgb * light.power * La * Ls;
#if LAMBERT
const vec3 diffuse = surface.material.albedo.rgb;
const vec3 specular = vec3(0);
#elif PBR
const vec3 Lh = normalize(Li + Lo);
const float cosLh = max(0.0, dot(surface.normal.world, Lh));
const vec3 F = fresnelSchlick( F0, max( 0.0, dot(Lh, Lo) ) );
const float D = ndfGGX( cosLh, surface.material.roughness );
const float G = gaSchlickGGX(cosLi, cosLo, surface.material.roughness);
const vec3 diffuse = mix( vec3(1.0) - F, vec3(0.0), surface.material.metallic ) * surface.material.albedo.rgb;
const vec3 specular = (F * D * G) / max(EPSILON, 4.0 * cosLi * cosLo);
#endif
// lightmapped, compute only specular
surface.light.rgb += (diffuse + specular) * Lr * cosLi;
surface.light.a += light.power * La * Ls;
}
*/
}
surface.fragment.rgb += surface.light.rgb;
#if TONE_MAP
toneMap(surface.fragment.rgb, ubo.settings.bloom.exposure);
#endif
#if GAMMA_CORRECT
gammaCorrect(surface.fragment.rgb, 1.0 / ubo.settings.bloom.gamma);
#endif
imageStore(voxelRadiance[CASCADE], ivec3(tUvw), vec4(surface.fragment.rgb, surface.material.albedo.a));
}
}

View File

@ -0,0 +1,67 @@
#version 450
#pragma shader_stage(compute)
#extension GL_EXT_samplerless_texture_functions : require
layout (local_size_x = 8, local_size_y = 8, local_size_z = 8) in;
layout (constant_id = 0) const uint CASCADES = 16;
layout (constant_id = 1) const uint MIPS = 16;
layout( push_constant ) uniform PushBlock {
uint cascade;
uint mip;
} PushConstant;
layout (binding = 1, rg16f) uniform volatile coherent image3D voxelRadiance[CASCADES * MIPS];
const float gaussianWeights[] = {
//Top slice
1 / 64.0f,
1 / 32.0f,
1 / 64.0f,
1 / 32.0f,
1 / 16.0f,
1 / 32.0f,
1 / 64.0f,
1 / 32.0f,
1 / 64.0f,
//Center slice
1 / 32.0f,
1 / 16.0f,
1 / 32.0f,
1 / 16.0f,
1 / 4.0f,
1 / 16.0f,
1 / 32.0f,
1 / 16.0f,
1 / 32.0f,
//Bottom slice
1 / 64.0f,
1 / 32.0f,
1 / 64.0f,
1 / 32.0f,
1 / 16.0f,
1 / 32.0f,
1 / 64.0f,
1 / 32.0f,
1 / 64.0f,
};
void main() {
const ivec3 inUVW = ivec3(gl_GlobalInvocationID.xyz) * 2;
const ivec3 outUVW = ivec3(gl_GlobalInvocationID.xyz);
const uint CASCADE_IN = PushConstant.cascade * CASCADES + PushConstant.mip;
const uint CASCADE_OUT = PushConstant.cascade * CASCADES + (PushConstant.mip + 1);
vec4 color = vec4(0);
for ( int z = -1; z <= 1; ++z ) {
for ( int y = -1; y <= 1; ++y ) {
for ( int x = -1; x <= 1; ++x ) {
color += imageLoad( voxelRadiance[CASCADE_IN], inUVW + ivec3(x,y,z) ) * gaussianWeights[x + 1 + (y + 1) * 3 + (z + 1) * 9];
}
}
}
imageStore(voxelRadiance[CASCADE_OUT], ivec3(outUVW), vec4(color));
}

View File

@ -0,0 +1,5 @@
#version 450
#pragma shader_stage(fragment)
#define RT 0
#include "./frag.h"

View File

@ -0,0 +1,204 @@
//#extension GL_EXT_nonuniform_qualifier : enable
#if RT
#extension GL_EXT_ray_tracing : enable
#extension GL_EXT_ray_query : enable
#endif
layout (constant_id = 0) const uint TEXTURES = 512;
layout (constant_id = 1) const uint CUBEMAPS = 128;
layout (constant_id = 2) const uint LAYERS = 32;
layout (binding = 5) uniform sampler2D samplerTextures[TEXTURES];
layout (binding = 6) uniform samplerCube samplerCubemaps[CUBEMAPS];
#define SHADOW_SAMPLES 16
#define FRAGMENT 1
#define BAKING 1
#define PBR 1
#define MAX_LIGHTS min(ubo.lights, lights.length())
#define MAX_SHADOWS MAX_LIGHTS
#define VIEW_MATRIX camera.viewport[0].view
#include "../../common/macros.h"
#include "../../common/structs.h"
layout (binding = 7) uniform Camera {
Viewport viewport[6];
} camera;
layout (binding = 8) uniform UBO {
uint lights;
uint currentID;
uint padding1;
uint padding2;
} ubo;
layout (std140, binding = 9) readonly buffer DrawCommands {
DrawCommand drawCommands[];
};
layout (std140, binding = 10) readonly buffer Instances {
Instance instances[];
};
layout (std140, binding = 11) readonly buffer InstanceAddresseses {
InstanceAddresses instanceAddresses[];
};
layout (std140, binding = 12) readonly buffer Materials {
Material materials[];
};
layout (std140, binding = 13) readonly buffer Textures {
Texture textures[];
};
layout (std140, binding = 14) readonly buffer Lights {
Light lights[];
};
layout (binding = 15, rgba8) uniform volatile coherent image3D outAlbedos;
#if RT
layout (binding = 16) uniform accelerationStructureEXT tlas;
#endif
#include "../../common/functions.h"
#if RT
float shadowFactor( const Light light, float def ) {
Ray ray;
ray.origin = surface.position.world;
ray.direction = light.position - ray.origin;
float tMin = 0.001;
float tMax = length(ray.direction) + tMin;
ray.direction = normalize(ray.direction);
uint rayFlags = gl_RayFlagsOpaqueEXT | gl_RayFlagsTerminateOnFirstHitEXT | gl_RayFlagsSkipClosestHitShaderEXT;
uint cullMask = 0xFF;
rayQueryEXT rayQuery;
rayQueryInitializeEXT(rayQuery, tlas, rayFlags, cullMask, ray.origin, tMin, ray.direction, tMax);
while(rayQueryProceedEXT(rayQuery)) {}
return rayQueryGetIntersectionTypeEXT(rayQuery, true) == gl_RayQueryCommittedIntersectionNoneEXT ? 1.0 : 0.0;
}
#else
#include "../../common/shadows.h"
#endif
#include "../../common/light.h"
layout (location = 0) flat in uvec4 inId;
layout (location = 1) flat in vec4 inPOS0;
layout (location = 2) in vec4 inPOS1;
layout (location = 3) in vec3 inPosition;
layout (location = 4) in vec2 inUv;
layout (location = 5) in vec4 inColor;
layout (location = 6) in vec2 inSt;
layout (location = 7) in vec3 inNormal;
layout (location = 8) in vec3 inTangent;
layout (location = 0) out vec4 outAlbedo;
void main() {
const uint triangleID = uint(inId.x); // gl_PrimitiveID
const uint drawID = uint(inId.y);
const uint instanceID = uint(inId.z);
if ( instanceID != ubo.currentID ) discard;
surface.uv.xy = wrap(inUv.xy);
surface.uv.z = mipLevel(dFdx(inUv), dFdy(inUv));
surface.position.world = inPosition;
surface.normal.world = inNormal;
const DrawCommand drawCommand = drawCommands[drawID];
const Instance instance = instances[instanceID];
const Material material = materials[instance.materialID];
const uint mapID = instance.auxID;
vec4 A = material.colorBase;
surface.material.metallic = material.factorMetallic;
surface.material.roughness = material.factorRoughness;
surface.material.occlusion = 1.0f - material.factorOcclusion;
#if 0
vec3 N = inNormal;
vec3 T = inTangent;
T = normalize(T - dot(T, N) * N);
vec3 B = cross(T, N);
mat3 TBN = mat3(T, B, N);
// mat3 TBN = mat3(N, B, T);
if ( T != vec3(0) && validTextureIndex( material.indexNormal ) ) {
surface.normal.world = TBN * normalize( sampleTexture( material.indexNormal ).xyz * 2.0 - 1.0 );
} else {
surface.normal.world = N;
}
#endif
surface.light = material.colorEmissive;
surface.material.albedo = vec4(1);
{
surface.normal.eye = surface.normal.eye;
surface.position.eye = surface.position.eye;
// pbr();
const vec3 F0 = mix(vec3(0.04), surface.material.albedo.rgb, surface.material.metallic);
for ( uint i = 0; i < min(ubo.lights, lights.length()); ++i ) {
const Light light = lights[i];
if ( light.type <= 0 ) continue;
const mat4 mat = light.view; // inverse(light.view);
const vec3 position = surface.position.world;
// const vec3 position = vec3( mat * vec4(surface.position.world, 1.0) );
const vec3 normal = surface.normal.world;
// const vec3 normal = vec3( mat * vec4(surface.normal.world, 0.0) );
if ( light.power <= LIGHT_POWER_CUTOFF ) continue;
const vec3 Lp = light.position;
const vec3 Liu = light.position - surface.position.world;
const float La = 1.0 / (1 + PI * pow(length(Liu), 2.0));
const float Ls = shadowFactor( light, 0.0 );
if ( light.power * La * Ls <= LIGHT_POWER_CUTOFF ) continue;
const vec3 Lo = normalize( -position );
const float cosLo = max(0.0, abs(dot(normal, Lo)));
const vec3 Li = normalize(Liu);
const vec3 Lr = light.color.rgb * light.power * La * Ls;
// const float cosLi = max(0.0, dot(normal, Li));
const float cosLi = abs(dot(normal, Li));
#if LAMBERT
const vec3 diffuse = surface.material.albedo.rgb;
const vec3 specular = vec3(0);
#elif PBR
const vec3 Lh = normalize(Li + Lo);
// const float cosLh = max(0.0, dot(normal, Lh));
const float cosLh = abs(dot(normal, Lh));
const vec3 F = fresnelSchlick( F0, max( 0.0, dot(Lh, Lo) ) );
const float D = 1; // ndfGGX( cosLh, surface.material.roughness );
const float G = gaSchlickGGX(cosLi, cosLo, surface.material.roughness);
const vec3 diffuse = mix( vec3(1.0) - F, vec3(0.0), surface.material.metallic ) * surface.material.albedo.rgb;
const vec3 specular = (F * D * G) / max(EPSILON, 4.0 * cosLi * cosLo);
#endif
surface.light.rgb += (diffuse + specular) * Lr * cosLi;
surface.light.a += light.power * La * Ls;
}
}
#define EXPOSURE 0
#define GAMMA 0
// surface.light.rgb = vec3(1.0) - exp(-surface.light.rgb * EXPOSURE);
// surface.light.rgb = pow(surface.light.rgb, vec3(1.0 / GAMMA));
outAlbedo = vec4(surface.light.rgb, 1);
{
const vec2 st = inSt.xy * imageSize(outAlbedos).xy;
const ivec3 uvw = ivec3(int(st.x), int(st.y), int(mapID));
imageStore(outAlbedos, uvw, vec4(surface.light.rgb, 1) );
}
}

View File

@ -0,0 +1,5 @@
#version 460
#pragma shader_stage(fragment)
#define RT 1
#include "./frag.h"

View File

@ -0,0 +1,8 @@
#version 450
#pragma shader_stage(vertex)
#define INSTANCED 1
#define SKINNED 0
#define BAKING 1
#include "../base/vert.h"

View File

@ -0,0 +1,126 @@
#version 450
#pragma shader_stage(fragment)
//#extension GL_EXT_nonuniform_qualifier : enable
#define FRAGMENT 1
#define CAN_DISCARD 1
#define MAX_TEXTURES textures.length()
layout (constant_id = 0) const uint TEXTURES = 1;
#include "../../common/macros.h"
#include "../../common/structs.h"
#if BARYCENTRIC && !BARYCENTRIC_CALCULATE
#define BARYCENTRIC_STABILIZE 1
// #define BARY_COORD gl_BaryCoordEXT
// #extension GL_EXT_fragment_shader_barycentric : enable
#define BARY_COORD gl_BaryCoordSmoothAMD
#extension GL_AMD_shader_explicit_vertex_parameter : enable
#endif
layout (binding = 5) uniform sampler2D samplerTextures[TEXTURES];
layout (std140, binding = 6) readonly buffer DrawCommands {
DrawCommand drawCommands[];
};
layout (std140, binding = 7) readonly buffer Instances {
Instance instances[];
};
layout (std140, binding = 8) readonly buffer InstanceAddresseses {
InstanceAddresses instanceAddresses[];
};
layout (std140, binding = 9) readonly buffer Materials {
Material materials[];
};
layout (std140, binding = 10) readonly buffer Textures {
Texture textures[];
};
layout (std140, binding = 11) readonly buffer Lights {
Light lights[];
};
#include "../../common/functions.h"
layout (location = 0) flat in uvec4 inId;
layout (location = 1) flat in vec4 inPOS0;
#if BARYCENTRIC_STABILIZE
layout (location = 2) __explicitInterpAMD in vec4 inPOS1;
#else
layout (location = 2) in vec4 inPOS1;
#endif
layout (location = 3) in vec3 inPosition;
layout (location = 4) in vec2 inUv;
layout (location = 5) in vec4 inColor;
layout (location = 6) in vec2 inSt;
layout (location = 7) in vec3 inNormal;
layout (location = 8) in vec3 inTangent;
layout (location = 0) out uvec2 outId;
#if BARYCENTRIC
layout (location = 1) out vec2 outBary;
#else
layout (location = 1) out vec4 outUv;
layout (location = 2) out vec4 outNormal;
#endif
void main() {
const uint triangleID = gl_PrimitiveID; // uint(inId.x);
const uint drawID = uint(inId.y);
const uint instanceID = uint(inId.z);
#if CAN_DISCARD
const DrawCommand drawCommand = drawCommands[drawID];
const Instance instance = instances[instanceID];
const Material material = materials[instance.materialID];
surface.uv.xy = wrap(inUv.xy);
surface.uv.z = mipLevel(dFdx(inUv), dFdy(inUv));
surface.st.xy = wrap(inSt.xy);
surface.st.z = mipLevel(dFdx(inSt), dFdy(inSt));
vec4 A = inColor * material.colorBase;
// sample albedo
if ( validTextureIndex( material.indexAlbedo ) ) {
A = sampleTexture( material.indexAlbedo );
}
// alpha mode OPAQUE
if ( material.modeAlpha == 0 ) {
A.a = 1;
// alpha mode BLEND
} else if ( material.modeAlpha == 1 ) {
// alpha mode MASK
} else if ( material.modeAlpha == 2 ) {
if ( A.a < abs(material.factorAlphaCutoff) ) discard;
A.a = 1;
}
if ( A.a < 0.0001 ) discard;
#if !BARYCENTRIC
outUv = vec4(surface.uv, surface.st);
outNormal = vec4( encodeNormals(inNormal), encodeNormals(inTangent) );
#endif
#endif
outId = uvec2(triangleID + 1, instanceID + 1);
#if BARYCENTRIC && !BARYCENTRIC_CALCULATE
vec3 bary = vec3(gl_BaryCoordSmoothAMD.xy, 1 - gl_BaryCoordSmoothAMD.x - gl_BaryCoordSmoothAMD.y);
bary = bary.yzx;
#if BARYCENTRIC_STABILIZE
vec4 v0 = interpolateAtVertexAMD(inPOS1, 0);
vec4 v1 = interpolateAtVertexAMD(inPOS1, 1);
vec4 v2 = interpolateAtVertexAMD(inPOS1, 2);
if (v0 == inPOS0) outBary = encodeBarycentrics(bary.yzx);
else if (v1 == inPOS0) outBary = encodeBarycentrics(bary.zxy);
else if (v2 == inPOS0) outBary = encodeBarycentrics(bary.xyz);
#else
outBary = encodeBarycentrics(bary.xyz);
#endif
#endif
}

View File

@ -0,0 +1,6 @@
#version 450
#pragma shader_stage(vertex)
#define INSTANCED 1
#define SKINNED 0
#include "./vert.h"

View File

@ -0,0 +1,6 @@
#version 450
#pragma shader_stage(vertex)
#define INSTANCED 1
#define SKINNED 1
#include "./vert.h"

View File

@ -0,0 +1,6 @@
#version 450
#pragma shader_stage(vertex)
#define INSTANCED 0
#define SKINNED 1
#include "./vert.h"

View File

@ -0,0 +1,6 @@
#version 450
#pragma shader_stage(vertex)
#define INSTANCED 0
#define SKINNED 0
#include "./vert.h"

View File

@ -0,0 +1,100 @@
layout (constant_id = 0) const uint PASSES = 6;
#extension GL_ARB_shader_draw_parameters : enable
#include "../../common/macros.h"
#include "../../common/structs.h"
layout (location = 0) in vec3 inPos;
layout (location = 1) in vec2 inUv;
layout (location = 2) in vec4 inColor;
layout (location = 3) in vec2 inSt;
layout (location = 4) in vec3 inNormal;
layout (location = 5) in vec4 inTangent;
layout (location = 6) in uvec2 inId;
#if SKINNED
layout (location = 7) in uvec4 inJoints;
layout (location = 8) in vec4 inWeights;
#endif
layout( push_constant ) uniform PushBlock {
uint pass;
uint draw;
} PushConstant;
#if !BAKING
layout (binding = 0) uniform Camera {
Viewport viewport[PASSES];
} camera;
#endif
layout (std140, binding = 1) readonly buffer DrawCommands {
DrawCommand drawCommands[];
};
layout (std140, binding = 2) readonly buffer Instances {
Instance instances[];
};
#if SKINNED
layout (std140, binding = 3) readonly buffer Joints {
mat4 joints[];
};
#endif
layout (location = 0) out uvec4 outId;
layout (location = 1) flat out vec4 outPOS0;
layout (location = 2) out vec4 outPOS1;
layout (location = 3) out vec3 outPosition;
layout (location = 4) out vec2 outUv;
layout (location = 5) out vec4 outColor;
layout (location = 6) out vec2 outSt;
layout (location = 7) out vec3 outNormal;
layout (location = 8) out vec3 outTangent;
vec4 snap(vec4 vertex, vec2 resolution) {
vec4 snappedPos = vertex;
snappedPos.xyz = vertex.xyz / vertex.w;
snappedPos.xy = floor(resolution * snappedPos.xy) / resolution;
snappedPos.xyz *= vertex.w;
return snappedPos;
}
void main() {
const uint drawID = gl_DrawIDARB;
const uint triangleID = gl_VertexIndex / 3;
const DrawCommand drawCommand = drawCommands[drawID];
const uint instanceID = drawCommand.instanceID; // gl_InstanceIndex;
const Instance instance = instances[instanceID];
const uint jointID = instance.jointID;
#if BAKING
const mat4 view = mat4(1);
const mat4 projection = mat4(1);
#else
const mat4 view = camera.viewport[PushConstant.pass].view;
const mat4 projection = camera.viewport[PushConstant.pass].projection;
#endif
#if SKINNED
const mat4 skinned = joints.length() <= 0 || jointID < 0 ? mat4(1.0) : inWeights.x * joints[jointID + int(inJoints.x)] + inWeights.y * joints[jointID + int(inJoints.y)] + inWeights.z * joints[jointID + int(inJoints.z)] + inWeights.w * joints[jointID + int(inJoints.w)];
#else
const mat4 skinned = mat4(1.0);
#endif
// const mat4 model = instances.length() <= 0 ? skinned : (instance.model * skinned);
const mat4 model = instance.model * skinned;
#if BAKING
gl_Position = vec4(inSt * 2.0 - 1.0, 0.0, 1.0);
#else
gl_Position = projection * view * model * vec4(inPos.xyz, 1.0);
#endif
outPOS0 = gl_Position;
outPOS1 = gl_Position;
outId = uvec4(triangleID, drawID, instanceID, PushConstant.pass);
outPosition = vec3(model * vec4(inPos.xyz, 1.0));
outUv = inUv;
outSt = inSt;
outColor = inColor * instance.color;
outNormal = normalize(vec3(model * vec4(inNormal.xyz, 0.0)));
outTangent = normalize(vec3(view * model * vec4(inTangent.xyz, 0.0)));
}

View File

@ -0,0 +1,369 @@
#version 450
#pragma shader_stage(compute)
//#extension GL_EXT_nonuniform_qualifier : enable
#extension GL_EXT_samplerless_texture_functions : enable
layout (constant_id = 0) const uint PASSES = 6;
layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
#define COMPUTE 1
#define QUERY_MIPMAPS 1
#define DEPTH_BIAS 0.00005
#include "../../common/macros.h"
#include "../../common/structs.h"
float mipLevels( vec2 size ) {
return floor(log2(max(size.x, size.y)));
}
float mipLevels( ivec2 size ) {
return floor(log2(max(size.x, size.y)));
}
vec4 aabbToSphere( Bounds bounds ) {
vec4 sphere;
sphere.xyz = (bounds.max + bounds.min) * 0.5;
sphere.w = length((bounds.max - bounds.min) * 0.5);
return sphere;
}
// 2D Polyhedral Bounds of a Clipped, Perspective-Projected 3D Sphere. Michael Mara, Morgan McGuire. 2013
bool projectSphere(vec3 C, float r, float znear, float P00, float P11, out vec4 aabb)
{
if (C.z < r + znear)
return false;
vec2 cx = -C.xz;
vec2 vx = vec2(sqrt(dot(cx, cx) - r * r), r);
vec2 minx = mat2(vx.x, vx.y, -vx.y, vx.x) * cx;
vec2 maxx = mat2(vx.x, -vx.y, vx.y, vx.x) * cx;
vec2 cy = -C.yz;
vec2 vy = vec2(sqrt(dot(cy, cy) - r * r), r);
vec2 miny = mat2(vy.x, vy.y, -vy.y, vy.x) * cy;
vec2 maxy = mat2(vy.x, -vy.y, vy.y, vy.x) * cy;
aabb = vec4(minx.x / minx.y * P00, miny.x / miny.y * P11, maxx.x / maxx.y * P00, maxy.x / maxy.y * P11);
aabb = aabb.xwzy * vec4(0.5f, -0.5f, 0.5f, -0.5f) + vec4(0.5f); // clip space -> uv space
return true;
}
layout( push_constant ) uniform PushBlock {
uint pass;
uint passes;
} PushConstant;
layout (binding = 0) uniform Camera {
Viewport viewport[PASSES];
} camera;
layout (std140, binding = 1) buffer DrawCommands {
DrawCommand drawCommands[];
};
layout (std140, binding = 2) buffer Instances {
Instance instances[];
};
layout (binding = 3) uniform sampler2D samplerDepth;
struct Frustum {
vec4 planes[6];
};
vec4 normalizePlane( vec4 p ) {
return p / length(p.xyz);
}
bool frustumCull( uint id ) {
if ( PushConstant.passes == 0 ) return true;
const DrawCommand drawCommand = drawCommands[id];
const Instance instance = instances[drawCommand.instanceID];
bool visible = false;
for ( uint pass = 0; pass < PushConstant.passes; ++pass ) {
#if 0
vec4 sphere = aabbToSphere( instance.bounds );
vec3 center = vec3( camera.viewport[pass].view * instance.model * vec4( ) );
#else
mat4 mat = camera.viewport[pass].projection * camera.viewport[pass].view * instance.model;
#if 1
vec4 planes[6]; {
for (int i = 0; i < 3; ++i)
for (int j = 0; j < 2; ++j) {
planes[i*2+j].x = mat[0][3] + (j == 0 ? mat[0][i] : -mat[0][i]);
planes[i*2+j].y = mat[1][3] + (j == 0 ? mat[1][i] : -mat[1][i]);
planes[i*2+j].z = mat[2][3] + (j == 0 ? mat[2][i] : -mat[2][i]);
planes[i*2+j].w = mat[3][3] + (j == 0 ? mat[3][i] : -mat[3][i]);
planes[i*2+j] = normalizePlane( planes[i*2+j] );
}
}
for ( uint p = 0; p < 6; ++p ) {
float d = max(instance.bounds.min.x * planes[p].x, instance.bounds.max.x * planes[p].x)
+ max(instance.bounds.min.y * planes[p].y, instance.bounds.max.y * planes[p].y)
+ max(instance.bounds.min.z * planes[p].z, instance.bounds.max.z * planes[p].z);
if ( d > -planes[p].w ) return true;
}
#else
vec4 corners[8] = {
vec4( instance.bounds.min.x, instance.bounds.min.y, instance.bounds.min.z, 1.0 ),
vec4( instance.bounds.max.x, instance.bounds.min.y, instance.bounds.min.z, 1.0 ),
vec4( instance.bounds.max.x, instance.bounds.max.y, instance.bounds.min.z, 1.0 ),
vec4( instance.bounds.min.x, instance.bounds.max.y, instance.bounds.min.z, 1.0 ),
vec4( instance.bounds.min.x, instance.bounds.min.y, instance.bounds.max.z, 1.0 ),
vec4( instance.bounds.max.x, instance.bounds.min.y, instance.bounds.max.z, 1.0 ),
vec4( instance.bounds.max.x, instance.bounds.max.y, instance.bounds.max.z, 1.0 ),
vec4( instance.bounds.min.x, instance.bounds.max.y, instance.bounds.max.z, 1.0 ),
};
vec4 planes[6]; {
#pragma unroll 3
for (int i = 0; i < 3; ++i)
#pragma unroll 2
for (int j = 0; j < 2; ++j) {
planes[i*2+j].x = mat[0][3] + (j == 0 ? mat[0][i] : -mat[0][i]);
planes[i*2+j].y = mat[1][3] + (j == 0 ? mat[1][i] : -mat[1][i]);
planes[i*2+j].z = mat[2][3] + (j == 0 ? mat[2][i] : -mat[2][i]);
planes[i*2+j].w = mat[3][3] + (j == 0 ? mat[3][i] : -mat[3][i]);
planes[i*2+j] = normalizePlane( planes[i*2+j] );
}
}
#pragma unroll 8
for ( uint p = 0; p < 8; ++p ) corners[p] = mat * corners[p];
#pragma unroll 6
for ( uint p = 0; p < 6; ++p ) {
#pragma unroll 8
for ( uint q = 0; q < 8; ++q ) {
if ( dot( corners[q], planes[p] ) > 0 ) return true;
}
return false;
}
#endif
#endif
}
return visible;
}
bool occlusionCull( uint id ) {
if ( PushConstant.passes == 0 ) return true;
const DrawCommand drawCommand = drawCommands[id];
const Instance instance = instances[drawCommand.instanceID];
bool visible = true;
for ( uint pass = 0; pass < PushConstant.passes; ++pass ) {
#if 1
vec4 aabb;
vec4 sphere = aabbToSphere( instance.bounds );
vec3 center = (camera.viewport[pass].view * instance.model * vec4(sphere.xyz, 1)).xyz;
float radius = (instance.model * vec4(sphere.w, 0, 0, 0)).x;
// center.y *= -1;
mat4 proj = camera.viewport[pass].projection;
float znear = proj[3][2];
float P00 = proj[0][0];
float P11 = proj[1][1];
if (projectSphere(center, radius, znear, P00, P11, aabb)) {
ivec2 pyramidSize = textureSize( samplerDepth, 0 );
float mips = mipLevels( pyramidSize );
float width = (aabb.z - aabb.x) * pyramidSize.x;
float height = (aabb.w - aabb.y) * pyramidSize.y;
//find the mipmap level that will match the screen size of the sphere
float level = floor(log2(max(width, height)));
// if ( level == mips )
--level;
level = clamp( level, 0, mips );
//sample the depth pyramid at that specific level
float depth = textureLod(samplerDepth, (aabb.xy + aabb.zw) * 0.5, level).x;
float depthSphere = znear / (center.z - radius);
instances[drawCommand.instanceID].bounds.padding1 = depth;
instances[drawCommand.instanceID].bounds.padding2 = proj[3][2];
//if the depth of the sphere is in front of the depth pyramid value, then the object is visible
visible = visible && depthSphere >= depth - DEPTH_BIAS;
}
#else
mat4 mat = camera.viewport[pass].projection * camera.viewport[pass].view * instance.model;
vec3 boundsSize = instance.bounds.max - instance.bounds.min;
vec3 points[8] = {
instance.bounds.min.xyz,
instance.bounds.min.xyz + vec3(boundsSize.x,0,0),
instance.bounds.min.xyz + vec3(0, boundsSize.y,0),
instance.bounds.min.xyz + vec3(0, 0, boundsSize.z),
instance.bounds.min.xyz + vec3(boundsSize.xy,0),
instance.bounds.min.xyz + vec3(0, boundsSize.yz),
instance.bounds.min.xyz + vec3(boundsSize.x, 0, boundsSize.z),
instance.bounds.min.xyz + boundsSize.xyz,
};
vec2 minXY = vec2(1);
vec2 maxXY = vec2(0);
float minZ = 1;
float maxZ = 0;
#pragma unroll 8
for ( uint i = 0; i < 8; ++i ) {
vec4 clip = mat * vec4( points[i], 1 );
clip.xyz /= clip.w;
clip.xy = clip.xy * 0.5 + 0.5;
minXY.x = min(minXY.x, clip.x);
minXY.y = min(minXY.y, clip.y);
maxXY.x = max(maxXY.x, clip.x);
maxXY.y = max(maxXY.y, clip.y);
#if INVERSE
clip.z = 1.0 - clip.z;
maxZ = max(maxZ, clip.z);
#else
minZ = min(minZ, clip.z);
#endif
}
if ( maxXY.x <= 0 || maxXY.y <= 0 ) return false;
if ( minXY.x >= 1 || minXY.y >= 1 ) return false;
ivec2 depthSize = textureSize( samplerDepth, 0 );
float mips = mipLevels( depthSize );
vec4 uv = vec4(minXY, maxXY);
ivec2 clipSize = ivec2(maxXY - minXY) * depthSize;
float mip = mipLevels( clipSize );
mip = clamp( mip, 0, mips );
if ( mip == 0 ) {
mip = 1;
} else {
float lower = max(mip - 1, 0);
float scale = exp2(-lower);
vec2 a = floor(uv.xy * scale);
vec2 b = ceil(uv.zw * scale);
vec2 dims = b - a;
// Use the lower level if we only touch <= 2 texels in both dimensions
if (dims.x <= 2 && dims.y <= 2) mip = lower;
}
float depths[4] = {
textureLod( samplerDepth, uv.xy, mip ).r,
textureLod( samplerDepth, uv.zy, mip ).r,
textureLod( samplerDepth, uv.xw, mip ).r,
textureLod( samplerDepth, uv.zw, mip ).r,
};
#if INVERSE
float minDepth = 1.0 - min(min(min(depths[0], depths[1]), depths[2]), depths[3]);
#else
float maxDepth = max(max(max(depths[0], depths[1]), depths[2]), depths[3]);
#endif
instances[drawCommand.instanceID].bounds.padding1 = minZ;
instances[drawCommand.instanceID].bounds.padding2 = maxDepth;
return minZ <= maxDepth;
#endif
}
return visible;
}
void main() {
const uint gID = gl_GlobalInvocationID.x;
if ( !(0 <= gID && gID < drawCommands.length()) ) return;
bool visible = frustumCull( gID );
// if ( visible ) visible = occlusionCull( gID );
// bool visible = occlusionCull( gID );
drawCommands[gID].instances = visible ? 1 : 0;
}
/*
Frustum frustum;
for (int i = 0; i < 3; ++i)
for (int j = 0; j < 2; ++j) {
frustum.planes[i*2+j].x = mat[0][3] + (j == 0 ? mat[0][i] : -mat[0][i]);
frustum.planes[i*2+j].y = mat[1][3] + (j == 0 ? mat[1][i] : -mat[1][i]);
frustum.planes[i*2+j].z = mat[2][3] + (j == 0 ? mat[2][i] : -mat[2][i]);
frustum.planes[i*2+j].w = mat[3][3] + (j == 0 ? mat[3][i] : -mat[3][i]);
frustum.planes[i*2+j]*= length(frustum.planes[i*2+j].xyz);
}
for ( uint i = 0; i < 6; ++i ) {
vec4 plane = frustum.planes[i];
float d = dot(instance.bounds.center, plane.xyz);
float r = dot(instance.bounds.extent, abs(plane.xyz));
bool inside = d + r > -plane.w;
if ( !inside ) return 0;
}
return true;
*/
/*
vec4 plane;
vec4 center = vec4( (max + min) * 0.5, 1 );
vec4 extent = vec4( (max - min) * 0.5, 1 );
center = mat * center;
extent = mat * extent;
center.xyz /= center.w;
extent.xyz /= extent.w;
for (int i = 0; i < 4; ++i ) plane[i] = mat[i][3] + mat[i][0]; // left
visible = dot(center.xyz + extent.xyz * sign(plane.xyz), plane.xyz ) > -plane.w;
if ( visible ) return true;
for (int i = 0; i < 4; ++i ) plane[i] = mat[i][3] - mat[i][0]; // right
visible = dot(center.xyz + extent.xyz * sign(plane.xyz), plane.xyz ) > -plane.w;
if ( visible ) return true;
for (int i = 0; i < 4; ++i ) plane[i] = mat[i][3] + mat[i][1]; // bottom
visible = dot(center.xyz + extent.xyz * sign(plane.xyz), plane.xyz ) > -plane.w;
if ( visible ) return true;
for (int i = 0; i < 4; ++i ) plane[i] = mat[i][3] - mat[i][1]; // top
visible = dot(center.xyz + extent.xyz * sign(plane.xyz), plane.xyz ) > -plane.w;
if ( visible ) return true;
for (int i = 0; i < 4; ++i ) plane[i] = mat[i][3] + mat[i][2]; // near
visible = dot(center.xyz + extent.xyz * sign(plane.xyz), plane.xyz ) > -plane.w;
if ( visible ) return true;
for (int i = 0; i < 4; ++i ) plane[i] = mat[i][3] - mat[i][2]; // far
visible = dot(center.xyz + extent.xyz * sign(plane.xyz), plane.xyz ) > -plane.w;
if ( visible ) return true;
*/
/*
for ( uint p = 0; p < 8; ++p ) {
vec4 t = corners[p];
float w = abs(t.w);
visible = -w <= t.x && t.x <= w && -w <= t.y && t.y <= w && 0 <= t.z && t.z <= w; // && -w <= t.z && t.z <= w;
}
*/
/*
mat4 convert( mat4 proj ) {
float f = -proj[1][1];
float raidou = f / proj[0][0];
float zNear = proj[3][2];
float zFar = 32;
float range = zNear - zFar;
float Sx = f * raidou;
float Sy = f;
float Sz = (-zNear - zFar) / range;
float Pz = 2 * zFar * zNear / range;
mat4 new = mat4(1.0);
new[0][0] = Sx;
new[1][1] = -Sy;
new[2][2] = Sz;
new[3][2] = Pz;
new[2][3] = 1;
return new;
}
*/

View File

@ -0,0 +1,73 @@
#version 450
#pragma shader_stage(fragment)
#define FRAGMENT 1
#define MAX_TEXTURES textures.length()
layout (constant_id = 0) const uint TEXTURES = 1;
#include "../../common/macros.h"
#include "../../common/structs.h"
layout (binding = 5) uniform sampler2D samplerTextures[TEXTURES];
layout (std140, binding = 6) readonly buffer DrawCommands {
DrawCommand drawCommands[];
};
layout (std140, binding = 7) readonly buffer Instances {
Instance instances[];
};
layout (std140, binding = 8) readonly buffer InstanceAddresseses {
InstanceAddresses instanceAddresses[];
};
layout (std140, binding = 9) readonly buffer Materials {
Material materials[];
};
layout (std140, binding = 10) readonly buffer Textures {
Texture textures[];
};
layout (std140, binding = 11) readonly buffer Lights {
Light lights[];
};
#include "../../common/functions.h"
layout (location = 0) flat in uvec4 inId;
layout (location = 1) flat in vec4 inPOS0;
layout (location = 2) in vec4 inPOS1;
layout (location = 3) in vec3 inPosition;
layout (location = 4) in vec2 inUv;
layout (location = 5) in vec4 inColor;
layout (location = 6) in vec2 inSt;
layout (location = 7) in vec3 inNormal;
layout (location = 8) in vec3 inTangent;
void main() {
const uint triangleID = uint(inId.x); // gl_PrimitiveID
const uint drawID = uint(inId.y);
const uint instanceID = uint(inId.z);
const DrawCommand drawCommand = drawCommands[drawID];
const Instance instance = instances[instanceID];
const Material material = materials[instance.materialID];
surface.uv.xy = wrap(inUv.xy);
surface.uv.z = mipLevel(dFdx(inUv), dFdy(inUv));
vec4 A = inColor * material.colorBase;
// sample albedo
if ( validTextureIndex( material.indexAlbedo ) ) {
A = sampleTexture( material.indexAlbedo );
}
// alpha mode OPAQUE
if ( material.modeAlpha == 0 ) {
A.a = 1;
// alpha mode BLEND
} else if ( material.modeAlpha == 1 ) {
// alpha mode MASK
} else if ( material.modeAlpha == 2 ) {
if ( A.a < abs(material.factorAlphaCutoff) ) discard;
A.a = 1;
}
if ( A.a < 1 ) discard;
}

View File

@ -0,0 +1,142 @@
#version 450
#pragma shader_stage(fragment)
// to-do: convert to use functions.h surface population functions
#define FRAGMENT 1
#define DEFERRED_SAMPLING 0
#define CUBEMAPS 1
#define BLEND 1
#define DEPTH_TEST 0
#define USE_LIGHTMAP 1
layout (constant_id = 0) const uint TEXTURES = 512;
layout (constant_id = 1) const uint CASCADES = 16;
#define MAX_TEXTURES textures.length()
#include "../../common/macros.h"
#include "../../common/structs.h"
layout (binding = 5) uniform sampler2D samplerTextures[TEXTURES];
layout (std140, binding = 6) readonly buffer DrawCommands {
DrawCommand drawCommands[];
};
layout (std140, binding = 7) readonly buffer Instances {
Instance instances[];
};
layout (std140, binding = 8) readonly buffer InstanceAddresseses {
InstanceAddresses instanceAddresses[];
};
layout (std140, binding = 9) readonly buffer Materials {
Material materials[];
};
layout (std140, binding = 10) readonly buffer Textures {
Texture textures[];
};
layout (std140, binding = 11) readonly buffer Lights {
Light lights[];
};
layout (binding = 12, rg16ui) uniform volatile coherent uimage3D voxelId[CASCADES];
layout (binding = 13, rg16f) uniform volatile coherent image3D voxelNormal[CASCADES];
#if VXGI_HDR
layout (binding = 14, rgba16f) uniform volatile coherent image3D voxelRadiance[CASCADES];
#else
layout (binding = 14, rgba8) uniform volatile coherent image3D voxelRadiance[CASCADES];
#endif
#if DEPTH_TEST
layout (binding = 15, r16f) uniform volatile coherent image3D voxelDepth[CASCADES];
#endif
layout (location = 0) flat in uvec4 inId;
layout (location = 1) flat in vec4 inPOS0;
layout (location = 2) in vec4 inPOS1;
layout (location = 3) in vec3 inPosition;
layout (location = 4) in vec2 inUv;
layout (location = 5) in vec4 inColor;
layout (location = 6) in vec2 inSt;
layout (location = 7) in vec3 inNormal;
layout (location = 8) in vec3 inTangent;
#include "../../common/functions.h"
void main() {
const uint CASCADE = inId.w;
if ( CASCADES <= CASCADE ) discard;
const vec3 P = inPosition.xzy * 0.5 + 0.5;
if ( abs(P.x) > 1 || abs(P.y) > 1 || abs(P.z) > 1 ) discard;
const uint triangleID = uint(inId.x); // gl_PrimitiveID
const uint drawID = uint(inId.y);
const uint instanceID = uint(inId.z);
surface.uv.xy = wrap(inUv.xy);
surface.uv.z = mipLevel(dFdx(inUv), dFdy(inUv));
surface.st.xy = inSt;
surface.st.z = mipLevel(dFdx(inSt), dFdy(inSt));
const DrawCommand drawCommand = drawCommands[drawID];
const Instance instance = instances[instanceID];
const Material material = materials[instance.materialID];
surface.instance = instance;
vec4 A = material.colorBase;
float M = material.factorMetallic;
float R = material.factorRoughness;
float AO = material.factorOcclusion;
// sample albedo
if ( validTextureIndex( material.indexAlbedo ) ) {
A = sampleTexture( material.indexAlbedo );
}
// alpha mode OPAQUE
if ( material.modeAlpha == 0 ) {
A.a = 1;
// alpha mode BLEND
} else if ( material.modeAlpha == 1 ) {
// alpha mode MASK
} else if ( material.modeAlpha == 2 ) {
if ( A.a < abs(material.factorAlphaCutoff) ) discard;
A.a = 1;
}
if ( A.a == 0 ) discard;
#if USE_LIGHTMAP
if ( validTextureIndex( instance.lightmapID ) ) {
A.rgb *= sampleTexture( instance.lightmapID, inSt ).rgb;
}
#endif
// sample normal
vec3 N = inNormal;
vec3 T = inTangent;
T = normalize(T - dot(T, N) * N);
vec3 B = cross(T, N);
mat3 TBN = mat3(T, B, N);
// mat3 TBN = mat3(N, B, T);
if ( T != vec3(0) && validTextureIndex( material.indexNormal ) ) {
N = TBN * normalize( sampleTexture( material.indexNormal ).xyz * 2.0 - 1.0 );
}
const ivec3 uvw = ivec3(P * imageSize(voxelRadiance[CASCADE]));
#if DEPTH_TEST
const float outDepth = length(inPosition.xzy);
const float inDepth = imageLoad(voxelDepth[CASCADE], uvw).r;
if ( inDepth != 0 && inDepth < outDepth ) discard;
imageStore(voxelDepth[CASCADE], uvw, vec4(inDepth, 0, 0, 0));
#endif
imageStore(voxelId[CASCADE], uvw, uvec4(uvec2(drawID + 1, instanceID + 1), 0, 0));
imageStore(voxelNormal[CASCADE], uvw, vec4(encodeNormals( normalize( N ) ), 0, 0));
#if BLEND
// GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA
const vec4 src = A * inColor;
const vec4 dst = imageLoad(voxelRadiance[CASCADE], uvw);
imageStore(voxelRadiance[CASCADE], uvw, blend( src, dst, src.a ) );
#else
imageStore(voxelRadiance[CASCADE], uvw, A );
#endif
}

View File

@ -0,0 +1,93 @@
#version 450
#pragma shader_stage(geometry)
layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;
layout (location = 0) flat in uvec4 inId[];
layout (location = 1) flat in vec4 inPOS0[];
layout (location = 2) in vec4 inPOS1[];
layout (location = 3) in vec3 inPosition[];
layout (location = 4) in vec2 inUv[];
layout (location = 5) in vec4 inColor[];
layout (location = 6) in vec2 inSt[];
layout (location = 7) in vec3 inNormal[];
layout (location = 8) in vec3 inTangent[];
layout (location = 0) flat out uvec4 outId;
layout (location = 1) flat out vec4 outPOS0;
layout (location = 2) out vec4 outPOS1;
layout (location = 3) out vec3 outPosition;
layout (location = 4) out vec2 outUv;
layout (location = 5) out vec4 outColor;
layout (location = 6) out vec2 outSt;
layout (location = 7) out vec3 outNormal;
layout (location = 8) out vec3 outTangent;
layout (binding = 4) uniform UBO {
mat4 voxel;
float cascadePower;
float granularity;
float voxelizeScale;
float occlusionFalloff;
uint shadows;
uint padding1;
uint padding2;
uint padding3;
} ubo;
float cascadePower( uint x ) {
return pow(1 + x, ubo.cascadePower);
// return max( 1, x * ubo.cascadePower );
}
#define USE_CROSS 0
void main(){
const float HALF_PIXEL = ubo.voxelizeScale;
const vec3 C = ( inPosition[0] + inPosition[1] + inPosition[2] ) / 3.0;
#if USE_CROSS
const vec3 N = abs(cross(inPosition[2] - inPosition[0], inPosition[1] - inPosition[0]));
#else
const vec3 N = abs(inNormal[0] + inNormal[1] + inNormal[2]);
uint A = N.y > N.x ? 1 : 0;
A = N.z > N[A] ? 2 : A;
#endif
const uint CASCADE = inId[0].w;
vec3 P[3] = {
vec3( ubo.voxel * vec4( inPosition[0], 1 ) ) / cascadePower(CASCADE),
vec3( ubo.voxel * vec4( inPosition[1], 1 ) ) / cascadePower(CASCADE),
vec3( ubo.voxel * vec4( inPosition[2], 1 ) ) / cascadePower(CASCADE),
};
#pragma unroll 3
for( uint i = 0; i < 3; ++i ){
const vec3 D = normalize( inPosition[i] - C ) * HALF_PIXEL;
outPosition = P[i] + D;
outPOS0 = inPOS0[i];
outPOS1 = inPOS1[i];
outUv = inUv[i];
outSt = inSt[i];
outColor = inColor[i];
outNormal = inNormal[i];
outTangent = inTangent[i];
outId = inId[i];
const vec3 P = outPosition; // + D;
#if USE_CROSS
if ( N.z > N.x && N.z > N.y ) gl_Position = vec4(P.x, P.y, 0, 1);
else if ( N.x > N.y && N.x > N.z ) gl_Position = vec4(P.y, P.z, 0, 1);
else gl_Position = vec4(P.x, P.z, 0, 1);
#else
if ( A == 0 ) gl_Position = vec4(P.zy, 0, 1 );
else if ( A == 1 ) gl_Position = vec4(P.xz, 0, 1 );
else if ( A == 2 ) gl_Position = vec4(P.xy, 0, 1 );
#endif
EmitVertex();
}
EndPrimitive();
}

View File

@ -0,0 +1,5 @@
#version 450
#pragma shader_stage(fragment)
#define GLYPH 0
#include "../gui/frag.h"

View File

@ -0,0 +1,5 @@
#version 450
#pragma shader_stage(vertex)
#define GLYPH 0
#include "../gui/vert.h"

View File

@ -0,0 +1,45 @@
#define TEXTURES 1
#define CUBEMAPS 1
#include "../../common/macros.h"
#include "../../common/structs.h"
#include "../../common/functions.h"
#include "./gui.h"
layout (binding = 1) uniform sampler2D samplerTexture;
layout (location = 0) in vec2 inUv;
layout (location = 1) in flat Gui inGui;
layout (location = 7) in flat Glyph inGlyph;
layout (location = 0) out vec4 outAlbedo;
void main() {
if ( inUv.x < inGui.offset.x || inUv.y < inGui.offset.y || inUv.x > inGui.offset.z || inUv.y > inGui.offset.w ) discard;
const vec2 uv = inUv.xy;
const float mip = mipLevel(dFdx(inUv), dFdy(inUv));
vec4 C = inGui.color;
#if GLYPH
if ( enabled(inGui.mode, 1) ) {
outAlbedo = inGui.color;
return;
}
const float sampled = texture(samplerTexture, inUv).r;
if ( enabled(inGui.mode, 2) ) {
const float smoothing = ( inGlyph.spread > 0 && inGlyph.scale > 0 ) ? 0.25 / (inGlyph.spread * inGlyph.scale) : 0.25 / (4 * 1.5);
const float outlining = smoothstep(0.5 - smoothing, 0.5 + smoothing, sampled);
const float alpha = smoothstep(inGlyph.weight - smoothing, inGlyph.weight + smoothing, sampled);
if ( alpha < 0.001 || alpha > 1 ) discard;
C = mix(inGlyph.stroke, inGui.color, outlining);
C.a = inGui.color.a * alpha;
} else {
if ( sampled < 0.001 || sampled > 1 ) discard;
C *= sampled;
}
#else
if ( enabled(inGui.mode, 0) ) C = inGui.color;
else C *= textureLod( samplerTexture, uv, mip );
#endif
outAlbedo = C;
}

View File

@ -0,0 +1,18 @@
struct Gui {
vec4 offset;
vec4 color;
int mode;
float depth;
float padding1;
float padding2;
};
struct Glyph {
vec4 stroke;
int spread;
float weight;
float scale;
float padding;
};

View File

@ -0,0 +1,37 @@
layout (constant_id = 0) const uint PASSES = 6;
layout (location = 0) in vec2 inPos;
layout (location = 1) in vec2 inUv;
#include "./gui.h"
layout( push_constant ) uniform PushBlock {
uint pass;
uint draw;
} PushConstant;
struct Matrices {
mat4 model[PASSES];
};
layout (binding = 0) uniform UBO {
Matrices matrices;
Gui gui;
#if GLYPH
Glyph glyph;
#endif
} ubo;
layout (location = 0) out vec2 outUv;
layout (location = 1) out flat Gui outGui;
#if GLYPH
layout (location = 7) out flat Glyph outGlyph;
#endif
void main() {
outUv = inUv;
outGui = ubo.gui;
#if GLYPH
outGlyph = ubo.glyph;
#endif
gl_Position = ubo.matrices.model[PushConstant.pass] * vec4(inPos.xy, ubo.gui.depth, 1.0);
}

View File

@ -0,0 +1,5 @@
#version 450
#pragma shader_stage(fragment)
#define GLYPH 1
#include "../gui/frag.h"

View File

@ -0,0 +1,5 @@
#version 450
#pragma shader_stage(vertex)
#define GLYPH 1
#include "../gui/vert.h"

View File

@ -0,0 +1,401 @@
#version 460
#extension GL_EXT_ray_tracing : enable
#extension GL_ARB_shader_clock : enable
#pragma shader_stage(raygen)
layout (constant_id = 0) const uint PASSES = 2;
layout (constant_id = 1) const uint TEXTURES = 512;
layout (constant_id = 2) const uint CUBEMAPS = 8;
layout (constant_id = 3) const uint CASCADES = 1;
// shader type settings
#define RT 1
#define DEFERRED_SAMPLING 1
#define BUFFER_REFERENCE 1
#define UINT64_ENABLED 1
#define PBR 1
// shader function settings
#define FOG 1
//force it off
#define BARYCENTRIC 0
#define BARYCENTRIC_CALCULATE 0
#include "../common/macros.h"
#include "../common/structs.h"
layout( push_constant ) uniform PushBlock {
uint pass;
uint draw;
} PushConstant;
layout (binding = 0) uniform accelerationStructureEXT tlas;
layout (binding = 1, rgba32f) uniform volatile coherent image2D outImage;
layout (binding = 2) uniform UBO {
EyeMatrices eyes[2];
Settings settings;
} ubo;
layout (std140, binding = 3) readonly buffer Instances {
Instance instances[];
};
layout (std140, binding = 4) readonly buffer InstanceAddresseses {
InstanceAddresses instanceAddresses[];
};
layout (std140, binding = 5) readonly buffer Materials {
Material materials[];
};
layout (std140, binding = 6) readonly buffer Textures {
Texture textures[];
};
layout (std140, binding = 7) readonly buffer Lights {
Light lights[];
};
layout (binding = 8) uniform sampler2D samplerTextures[TEXTURES];
layout (binding = 9) uniform samplerCube samplerCubemaps[CUBEMAPS];
layout (binding = 10) uniform sampler3D samplerNoise;
#if VXGI
layout (binding = 11) uniform usampler3D voxelId[CASCADES];
layout (binding = 12) uniform sampler3D voxelNormal[CASCADES];
layout (binding = 13) uniform sampler3D voxelRadiance[CASCADES];
#endif
layout (location = 0) rayPayloadEXT RayTracePayload payload;
layout(buffer_reference, scalar) buffer Vertices { Vertex v[]; };
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 VUv { vec2 v[]; };
layout(buffer_reference, scalar) buffer VColor { uint v[]; };
layout(buffer_reference, scalar) buffer VSt { vec2 v[]; };
layout(buffer_reference, scalar) buffer VNormal { vec3 v[]; };
layout(buffer_reference, scalar) buffer VTangent { vec3 v[]; };
layout(buffer_reference, scalar) buffer VID { uint v[]; };
#include "../common/functions.h"
#include "../common/light.h"
#include "../common/fog.h"
#if VXGI
#include "../common/vxgi.h"
#endif
void trace( Ray ray, float tMin, float tMax ) {
uint rayFlags = gl_RayFlagsOpaqueEXT;
uint cullMask = 0xFF;
payload.hit = false;
surface.position.eye.z = tMax;
traceRayEXT(tlas, rayFlags, cullMask, 0, 0, 0, ray.origin, tMin, ray.direction, tMax, 0);
}
void trace( Ray ray, float tMin ) {
uint rayFlags = gl_RayFlagsOpaqueEXT;
uint cullMask = 0xFF;
float tMax = ubo.settings.rt.defaultRayBounds.y;
payload.hit = false;
surface.position.eye.z = tMax;
traceRayEXT(tlas, rayFlags, cullMask, 0, 0, 0, ray.origin, tMin, ray.direction, tMax, 0);
}
void trace( Ray ray ) {
trace( ray, ubo.settings.rt.defaultRayBounds.x, ubo.settings.rt.defaultRayBounds.y );
}
float shadowFactor( const Light light, float def ) {
Ray ray;
ray.origin = surface.position.world;
ray.direction = light.position - ray.origin;
float tMin = ubo.settings.rt.defaultRayBounds.x;
float tMax = length(ray.direction) - 0.0001;
ray.direction = normalize(ray.direction);
uint rayFlags = gl_RayFlagsOpaqueEXT | gl_RayFlagsTerminateOnFirstHitEXT | gl_RayFlagsSkipClosestHitShaderEXT;
uint cullMask = 0xFF;
payload.hit = true;
traceRayEXT(tlas, rayFlags, cullMask, 0, 0, 0, ray.origin, tMin, ray.direction, tMax, 0);
return payload.hit ? 0.0 : 1.0;
}
void directLighting() {
#if VXGI
indirectLighting();
#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;
surface.fragment.a = surface.material.albedo.a;
}
vec4 traceStep( Ray ray ) {
Ray fogRay = ray;
float eyeDepth = 0;
vec4 outFrag = vec4(0);
// initial condition
{
trace( ray );
if ( payload.hit ) {
populateSurface( payload );
directLighting();
} else if ( 0 <= ubo.settings.lighting.indexSkybox && ubo.settings.lighting.indexSkybox < CUBEMAPS ) {
surface.fragment = texture( samplerCubemaps[ubo.settings.lighting.indexSkybox], ray.direction );
surface.fragment.a = 4096;
surface.position.eye.z /= 8;
} else {
surface.fragment = vec4(ubo.settings.lighting.ambient.rgb, 0.5);
}
#if FOG
fog( ray, surface.fragment.rgb, surface.fragment.a );
#endif
outFrag = surface.fragment;
eyeDepth = surface.position.eye.z;
}
// "transparency"
if ( payload.hit && surface.material.albedo.a < 0.999 ) {
const vec4 TRANSPARENCY_COLOR = vec4(1.0 - surface.material.albedo.a);
if ( surface.material.albedo.a < 0.001 ) outFrag = vec4(0);
RayTracePayload surfacePayload = payload;
Ray transparency;
transparency.direction = ray.direction;
transparency.origin = surface.position.world;
fogRay = transparency;
trace( transparency, ubo.settings.rt.alphaTestOffset );
if ( payload.hit ) {
populateSurface( payload );
directLighting();
} else if ( 0 <= ubo.settings.lighting.indexSkybox && ubo.settings.lighting.indexSkybox < CUBEMAPS ) {
surface.fragment = texture( samplerCubemaps[ubo.settings.lighting.indexSkybox], ray.direction );
surface.fragment.a = 4096;
surface.position.eye.z /= 8;
}
#if FOG
fog( transparency, surface.fragment.rgb, surface.fragment.a );
#endif
outFrag += TRANSPARENCY_COLOR * surface.fragment;
eyeDepth = surface.position.eye.z;
payload = surfacePayload;
populateSurface( payload );
}
#if FOG
{
// surface.position.eye.z = eyeDepth;
// fog( fogRay, outFrag.rgb, outFrag.a );
// fog( ray, surface.fragment.rgb, surface.fragment.a );
}
#endif
// reflection
if ( payload.hit ) {
const float REFLECTIVITY = 1.0 - surface.material.roughness;
const vec4 REFLECTED_ALBEDO = surface.material.albedo * REFLECTIVITY;
if ( REFLECTIVITY > 0.001 ) {
RayTracePayload surfacePayload = payload;
Ray reflection;
reflection.origin = surface.position.world;
reflection.direction = reflect( ray.direction, surface.normal.world );
trace( reflection );
if ( payload.hit ) {
populateSurface( payload );
directLighting();
} else if ( 0 <= ubo.settings.lighting.indexSkybox && ubo.settings.lighting.indexSkybox < CUBEMAPS ) {
surface.fragment = texture( samplerCubemaps[ubo.settings.lighting.indexSkybox], reflection.direction );
surface.fragment.a = 4096;
}
#if FOG
fog( reflection, surface.fragment.rgb, surface.fragment.a );
#endif
outFrag += REFLECTED_ALBEDO * surface.fragment;
payload = surfacePayload;
populateSurface( payload );
}
}
return outFrag;
}
void main() {
// if ( ubo.settings.mode.frameNumber > 16 ) return;
// prngSeed = tea(gl_LaunchIDEXT.y * gl_LaunchSizeEXT.x + gl_LaunchIDEXT.x, ubo.settings.mode.frameNumber);
prngSeed = tea(gl_LaunchIDEXT.y * gl_LaunchSizeEXT.x + gl_LaunchIDEXT.x, int(clockARB()));
surface.pass = PushConstant.pass;
surface.subID = 0;
vec4 outFrag = vec4(0);
const uint SAMPLES = min(ubo.settings.rt.samples, 4);
const uint NUM_PATHS = min(ubo.settings.rt.paths, 8);
#if 1
const uint FRAME_ACCUMULATION_VALUE = ubo.settings.rt.frameAccumulationMinimum > 0 ? min(ubo.settings.rt.frameAccumulationMinimum, ubo.settings.mode.frameNumber + 1) : ubo.settings.mode.frameNumber + 1;
#else
const uint FRAME_ACCUMULATION_VALUE = min(32, ubo.settings.mode.frameNumber + 1);
#endif
const float BLEND_FACTOR = 1.0f / float(FRAME_ACCUMULATION_VALUE);
uint FRAME_NUMBER = ubo.settings.mode.frameNumber;
#if 0
for ( uint samp = 0; samp < SAMPLES; ++samp, ++FRAME_NUMBER ) {
{
const vec2 center = ( FRAME_NUMBER > 0 ) ? vec2( rnd(), rnd() ) : vec2(0.5);
const vec2 inUv = (vec2(gl_LaunchIDEXT.xy) + center) / vec2(gl_LaunchSizeEXT.xy);
#if 1
vec4 target = ubo.eyes[surface.pass].iProjection * vec4(inUv.x * 2.0f - 1.0f, inUv.y * 2.0f - 1.0f, 1, 1);
vec4 direction = ubo.eyes[surface.pass].iView * vec4(normalize(target.xyz), 0);
surface.ray.direction = vec3(direction);
surface.ray.origin = ubo.eyes[surface.pass].eyePos.xyz;
#else
const mat4 iProjectionView = inverse( ubo.eyes[surface.pass].projection * mat4(mat3(ubo.eyes[surface.pass].view)) );
const vec4 near4 = iProjectionView * (vec4(2.0 * inUv - 1.0, -1.0, 1.0));
const vec4 far4 = iProjectionView * (vec4(2.0 * inUv - 1.0, 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 = ubo.eyes[surface.pass].eyePos.xyz;
#endif
}
{
vec4 curValue = vec4(0);
vec4 curWeight = vec4(1);
for ( uint path = 0; path < NUM_PATHS; ++path ) {
vec4 stepValue = traceStep( surface.ray );
curValue += stepValue * curWeight;
if ( !payload.hit ) break;
surface.ray.origin = surface.position.world;
surface.ray.direction = samplingHemisphere( prngSeed, surface.normal.world );
curWeight *= surface.material.albedo * dot( surface.ray.direction, surface.normal.world );
if ( length(curWeight) < 0.01 ) break;
}
outFrag += curValue;
}
}
{
outFrag /= SAMPLES;
}
#elif 0
{
const vec2 center = ( FRAME_NUMBER > 0 ) ? vec2( rnd(), rnd() ) : vec2(0.5);
const vec2 inUv = (vec2(gl_LaunchIDEXT.xy) + center) / vec2(gl_LaunchSizeEXT.xy);
#if 0
vec4 target = ubo.eyes[surface.pass].iProjection * vec4(inUv.x * 2.0f - 1.0f, inUv.y * 2.0f - 1.0f, 1, 1);
vec4 direction = ubo.eyes[surface.pass].iView * vec4(normalize(target.xyz), 0);
surface.ray.direction = vec3(direction);
surface.ray.origin = ubo.eyes[surface.pass].eyePos.xyz;
#else
const mat4 iProjectionView = inverse( ubo.eyes[surface.pass].projection * mat4(mat3(ubo.eyes[surface.pass].view)) );
const vec4 near4 = iProjectionView * (vec4(2.0 * inUv - 1.0, -1.0, 1.0));
const vec4 far4 = iProjectionView * (vec4(2.0 * inUv - 1.0, 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 = ubo.eyes[surface.pass].eyePos.xyz;
#endif
}
{
vec4 curValue = vec4(0);
vec4 curWeight = vec4(1);
for ( uint path = 0; path < NUM_PATHS; ++path ) {
vec4 stepValue = traceStep( surface.ray );
curValue += stepValue * curWeight;
if ( !payload.hit ) break;
surface.ray.origin = surface.position.world;
surface.ray.direction = samplingHemisphere( prngSeed, surface.normal.world );
curWeight *= surface.material.albedo * dot( surface.ray.direction, surface.normal.world );
if ( length(curWeight) < 0.01 ) break;
}
outFrag += curValue;
}
{
surface.fragment = outFrag;
}
#else
{
const vec2 center = ( FRAME_NUMBER > 0 ) ? vec2( rnd(), rnd() ) : vec2(0.5);
const vec2 inUv = (vec2(gl_LaunchIDEXT.xy) + center) / vec2(gl_LaunchSizeEXT.xy);
#if 0
vec4 target = ubo.eyes[surface.pass].iProjection * vec4(inUv.x * 2.0f - 1.0f, inUv.y * 2.0f - 1.0f, 1, 1);
vec4 direction = ubo.eyes[surface.pass].iView * vec4(normalize(target.xyz), 0);
surface.ray.direction = vec3(direction);
surface.ray.origin = ubo.eyes[surface.pass].eyePos.xyz;
#else
const mat4 iProjectionView = inverse( ubo.eyes[surface.pass].projection * mat4(mat3(ubo.eyes[surface.pass].view)) );
const vec4 near4 = iProjectionView * (vec4(2.0 * inUv - 1.0, -1.0, 1.0));
const vec4 far4 = iProjectionView * (vec4(2.0 * inUv - 1.0, 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 = ubo.eyes[surface.pass].eyePos.xyz;
#endif
}
{
surface.fragment = traceStep( surface.ray );
}
#endif
{
#if BLOOM
float brightness = dot(surface.fragment.rgb, vec3(0.2126, 0.7152, 0.0722));
vec4 outFragBright = brightness > ubo.threshold ? vec4(surface.fragment.rgb, 1.0) : vec4(0, 0, 0, 1);
// imageStore(outImage, ivec2(gl_LaunchIDEXT.xy), outFragBright);
#endif
#if FOG
fog( surface.ray, surface.fragment.rgb, surface.fragment.a );
#endif
}
{
outFrag = surface.fragment;
outFrag.a = 1;
}
if ( ubo.settings.mode.frameNumber == 0 ) {
imageStore(outImage, ivec2(gl_LaunchIDEXT.xy), outFrag);
} else {
// if ( length(outFrag.rgb) < 0.01f ) return;
vec4 blended = mix(imageLoad(outImage, ivec2(gl_LaunchIDEXT.xy)), outFrag, BLEND_FACTOR);
imageStore(outImage, ivec2(gl_LaunchIDEXT.xy), blended);
}
}

View File

@ -0,0 +1,28 @@
#version 460
#extension GL_EXT_ray_tracing : enable
#extension GL_EXT_nonuniform_qualifier : enable
#extension GL_EXT_buffer_reference : enable
#extension GL_EXT_buffer_reference2 : enable
#extension GL_EXT_scalar_block_layout : enable
#pragma shader_stage(anyhit)
layout (constant_id = 0) const uint PASSES = 2;
layout (constant_id = 1) const uint TEXTURES = 512;
layout (constant_id = 2) const uint CUBEMAPS = 128;
#define RT 1
#define COMPUTE 1
#include "../common/macros.h"
#include "../common/structs.h"
layout(location = 0) rayPayloadInEXT RayTracePayload payload;
hitAttributeEXT vec2 attribs;
void main() {
payload.hit = true;
payload.instanceID = gl_InstanceCustomIndexEXT;
payload.primitiveID = gl_PrimitiveID;
payload.attributes = attribs;
}

View File

@ -0,0 +1,25 @@
#version 460
#extension GL_EXT_ray_tracing : enable
#extension GL_EXT_nonuniform_qualifier : enable
#pragma shader_stage(closest)
layout (constant_id = 0) const uint PASSES = 2;
layout (constant_id = 1) const uint TEXTURES = 512;
layout (constant_id = 2) const uint CUBEMAPS = 128;
#define RT 1
#define COMPUTE 1
#include "../common/macros.h"
#include "../common/structs.h"
layout(location = 0) rayPayloadInEXT RayTracePayload payload;
hitAttributeEXT vec2 attribs;
void main() {
payload.hit = true;
payload.instanceID = gl_InstanceCustomIndexEXT;
payload.primitiveID = gl_PrimitiveID;
payload.attributes = attribs;
}

View File

@ -0,0 +1,15 @@
#version 460
#extension GL_EXT_ray_tracing : enable
#pragma shader_stage(miss)
#define RT 1
#define COMPUTE 1
#include "../common/macros.h"
#include "../common/structs.h"
layout(location = 0) rayPayloadInEXT RayTracePayload payload;
void main() {
payload.hit = false;
}

View File

@ -1,7 +1,7 @@
{
"engine": {
"scenes": {
"start": "StartMenu",
"start": "SourceEngine",
"matrix": { "reverseInfinite": true },
"meshes": { "interleaved": false },
"lights": { "enabled": true,
@ -31,10 +31,10 @@
"vxgi": {
"limiter": 0.5,
// "limiter": 0.125,
"size": 128,
"size": 192,
"dispatch": 8,
"cascades": 3,
"cascadePower": 3,
"cascadePower": 1.5,
"granularity": 12,
"voxelizeScale": 1,
"occlusionFalloff": 2,
@ -57,37 +57,23 @@
}
},
"graph": {
"initial buffer elements": 131072
"initial buffer elements": 1024
},
"ext": {
"vulkan": {
"version": 1.3,
"validation": { "enabled": false,
"filters": [
"0x35d7ea98", // VUID-vkUpdateDescriptorSets-None-03047 ()
// "0x4dae5635" // UNASSIGNED-CoreValidation-DrawState-InvalidImageLayout
"0x4dae5635", // UNASSIGNED-CoreValidation-DrawState-InvalidImageLayout (false positive for cubemaps)
"0x609a13b", // UNASSIGNED-CoreValidation-Shader-OutputNotConsumed (from depth-only calls)
"0x23e43bb7", // UNASSIGNED-CoreValidation-Shader-InputNotProduced (from depth-only calls)
"0x71500fba", // VUID-vkDestroyDevice-device-00378 (don't care about a clean cleanup)
"0x7d560045", // VUID-vkCmdPipelineBarrier-dstStageMask-06462 (false positive, pipeline barrier for BLAS)
"0xde55a405", // VUID-VkDescriptorImageInfo-imageLayout-00344 (bitches because )
"0x9410d614", // VUID-vkCmdDrawIndexedIndirect-None-02699 (same as above)
"0x97c889fd", // VUID-VkBufferDeviceAddressInfo-buffer-02601 (false positive, lies about not setting flags when I explicitly set flags for scratch)
"0xea5edaf3" // VUID-vkCmdBuildAccelerationStructuresKHR-pInfos-03674 (same as above)
// "0x9cacd67a" // UNASSIGNED-CoreValidation-DrawState-QueryNotReset (false positive)
// "0xe91b58a0" // VUID-vkCmdDrawIndexed-None-02686 (?)
// "0x124ffb34", // VUID-VkImageMemoryBarrier-oldLayout-01197 (hacky bloom-shit)
// "0x8ab1932c", // VUID-VkImageViewCreateInfo-imageViewType-04973 (hacky bloom-shit)
// "0x8e1000ad", // VUID-vkCmdDrawIndexedIndirect-None-04008 (bitches without nullDescriptor)
// "0x9dd97212", // VUID-vkCmdDrawIndexedIndirect-None-02721 (bitches without nullDescriptor)
// "0x36481fcb", // VUID-vkCmdBindVertexBuffers-pBuffers-04001 (bitches without nullDescriptor)
"0x609a13b" // UNASSIGNED-CoreValidation-Shader-OutputNotConsumed (from depth-only calls)
,"0x141cb623" // UNASSIGNED-Threading-MultipleThreads ("false-positive" multithreading)
,"0xe5d1743c" // VUID-vkCmdDispatch-None-02699 (problem when using VXGI)
,"0x71500fba" // VUID-vkDestroyDevice-device-00378 (don't care about a clean cleanup)
,"0x35d7ea98" // VUID-vkUpdateDescriptorSets-None-03047 (bitches without VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT or VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT)
,"0x8e1000ad" // VUID-vkCmdDrawIndexedIndirect-None-04008 (bitches without nullDescriptor)
,"0x9dd97212" // VUID-vkCmdDrawIndexedIndirect-None-02721 (bitches without nullDescriptor)
,"0x36481fcb" // VUID-vkCmdBindVertexBuffers-pBuffers-04001 (bitches without nullDescriptor)
]
},
"framebuffer": {
@ -98,20 +84,23 @@
// "size": [ 960, 540 ]
// "size": [ 640, 480 ]
},
"gpu": 1,
"gpu": 7817,
"experimental": {
"rebuild on tick begin": false,
"batch queue submissions": true,
"dedicated thread": true
"dedicated thread": false,
"memory budget": false
},
"invariant": {
"default stage buffers": true
},
"invariant": {},
"pipelines": {
"deferred": true,
"vsync": false,
"hdr": false,
"vsync": true,
"hdr": true,
"vxgi": false,
"culling": false,
"bloom": false,
"culling": true,
"bloom": true,
"rt": false,
"postProcess": false,
"fsr": false
@ -122,62 +111,117 @@
"normal": "R16G16B16A16_SFLOAT",
"position": "R16G16B16A16_SFLOAT"
},
"features": [
"shaderDrawParameters",
"multiDrawIndirect",
"fillModeNonSolid",
"wideLines",
"independentBlend",
"deviceCoherentMemory",
"robustBufferAccess",
"samplerAnisotropy",
"sampleRateShading",
"nullDescriptor",
"fragmentStoresAndAtomics",
"geometryShader",
"multiViewport",
"shaderInt16",
"shaderFloat16",
"shaderInt64",
"shaderFloat64",
"shaderSubgroupClock",
"shaderSampledImageArrayDynamicIndexing",
"shaderStorageImageArrayDynamicIndexing",
"shaderStorageImageMultisample",
// 1.2 features
"descriptorIndexing",
"versions": {
"1.0": {
"extensions": {
"instance": [],
"device": [
"VK_KHR_swapchain"
]
},
"features": [
"shaderDrawParameters",
"multiDrawIndirect",
"fillModeNonSolid",
"wideLines",
"independentBlend",
"deviceCoherentMemory",
"robustBufferAccess",
"samplerAnisotropy",
"sampleRateShading"
],
"featureChain": []
},
"1.1": {
"extensions": {
"instance": [
"VK_KHR_get_physical_device_properties2"
,"VK_KHR_get_surface_capabilities2"
],
"device": [
"VK_EXT_memory_budget"
,"VK_EXT_descriptor_indexing"
,"VK_KHR_buffer_device_address"
]
},
"features": [
"nullDescriptor"
,"fragmentStoresAndAtomics"
,"geometryShader"
,"multiViewport"
,"shaderInt16"
,"shaderFloat16"
,"shaderInt64"
,"shaderFloat64"
,"shaderSubgroupClock"
,"shaderSampledImageArrayDynamicIndexing"
,"shaderStorageImageArrayDynamicIndexing"
,"shaderStorageImageMultisample"
,"shaderSampledImageArrayNonUniformIndexing"
,"shaderStorageImageArrayNonUniformIndexing"
"shaderOutputViewportIndex",
"shaderOutputLayer",
,"descriptorIndexing"
,"bufferDeviceAddress"
],
"featureChain": [
"physicalDevice2"
,"shaderDrawParameters"
,"robustness"
,"shaderClock"
"shaderSampledImageArrayNonUniformIndexing",
"shaderStorageImageArrayNonUniformIndexing",
"runtimeDescriptorArray",
"descriptorBindingVariableDescriptorCount",
,"descriptorIndexing"
,"bufferDeviceAddress"
]
},
"1.2": {
"extensions": {
"instance": [
"VK_KHR_get_physical_device_properties2",
"VK_KHR_get_surface_capabilities2"
],
"device": [
"VK_KHR_deferred_host_operations"
,"VK_EXT_shader_viewport_index_layer"
,"VK_KHR_spirv_1_4"
,"VK_KHR_shader_float_controls"
,"VK_KHR_shader_clock"
,"VK_EXT_subgroup_size_control"
,"VK_KHR_acceleration_structure"
,"VK_KHR_ray_tracing_pipeline"
,"VK_KHR_ray_query"
"hostQueryReset",
"bufferDeviceAddress"
],
"extensions": {
"instance": [
"VK_KHR_get_physical_device_properties2",
"VK_KHR_get_surface_capabilities2"
],
"device": [
"VK_KHR_swapchain",
"VK_EXT_shader_viewport_index_layer",
"VK_KHR_acceleration_structure",
"VK_KHR_ray_tracing_pipeline",
"VK_KHR_buffer_device_address",
"VK_KHR_deferred_host_operations",
"VK_EXT_descriptor_indexing",
"VK_KHR_spirv_1_4",
"VK_KHR_shader_float_controls",
"VK_KHR_shader_clock",
"VK_KHR_ray_query",
"VK_EXT_subgroup_size_control",
"VK_AMD_shader_explicit_vertex_parameter" // "VK_KHR_fragment_shader_barycentric"
]
// ,"VK_AMD_shader_explicit_vertex_parameter"
// ,"VK_KHR_fragment_shader_barycentric"
]
},
"features": [
"hostQueryReset",
"runtimeDescriptorArray",
"descriptorBindingVariableDescriptorCount",
"shaderOutputViewportIndex",
"shaderOutputLayer"
],
"featureChain": [
"physicalDeviceVulkan12"
// for ray-tracing
,"fragmentShaderBarycentric"
,"rayTracingPipeline"
,"rayQuery"
,"accelerationStructure"
,"subgroupSizeControl"
]
},
"1.3": {
"extensions": {
"instance": [],
"device": []
},
"features": [],
"featureChain": []
}
}
},
"opengl": {
@ -226,7 +270,7 @@
},
"reactphysics": {
"timescale": 0.01666666666,
"interpolate": false,
"interpolate": true,
"gravity": {
"mode": "universal",
"constant": 6.67408e-11
@ -276,7 +320,7 @@
"render modes": { "gui": true, "deferred": true },
"limiters": {
"deltaTime": 5,
"framerate": "auto"
"framerate": 0 // "auto"
},
"threads": {
"workers" : "auto",
@ -306,18 +350,21 @@
},
"hooks": {
"defer lazy calls": true
},
"scene": {
"print task calls": false
}
}
},
"window" : {
"terminal" : {
"ncurses" : false,
"visible" : false
"visible" : true
},
"keyboard" : {
"repeat" : false
},
"cursor" : {
"mouse" : {
"visible" : true,
"center" : false,
"sensitivity": [ 0.75, 0.75 ],

View File

@ -1,7 +1,7 @@
{
"type": "Object",
"name": "Burger",
"ignore": true,
"ignore": false,
"import": "/model.json",
"assets": [
// "/burger/burger.glb"

View File

@ -28,8 +28,8 @@ if not timer:running() then timer:start() end
local playSound = function( key )
local url = "/ui/" .. key .. ".ogg"
local assetLoader = scene:getComponent("Asset")
assetLoader:cache(ent:formatHookName("asset:Load.%UID%"), string.resolveURI(url))
-- local assetLoader = scene:getComponent("Asset")
-- assetLoader:cache(ent:formatHookName("asset:Load.%UID%"), string.resolveURI(url))
end
local destination = function( obj, x, y, z )
local static = Static.get(obj)

View File

@ -48,8 +48,8 @@ destination(children.quit, -1.5, nil, 0)
local playSound = function( key )
local url = "/ui/" .. key .. ".ogg"
local assetLoader = scene:getComponent("Asset")
assetLoader:cache(soundEmitter:formatHookName("asset:Load.%UID%"), string.resolveURI(url), "")
-- local assetLoader = scene:getComponent("Asset")
-- assetLoader:cache(soundEmitter:formatHookName("asset:Load.%UID%"), string.resolveURI(url), "")
end
ent:addHook("menu:Close.%UID%", function( json )

View File

@ -24,12 +24,12 @@
"power": 100,
"fov": 90,
"bias": {
"constant": 1.25,
"slope": 1.75,
"shader": 0.00000005 // 0.000005 //0.000000005
"constant": 1,
"slope": 1,
"shader": 0.00005 // 0.000005 //0.000000005
},
"radius": [0.25, 0],
"resolution": 256,
"radius": [0.5, 0],
"resolution": 1024,
"shadows": true,
"dynamic": true
}

View File

@ -1,7 +1,7 @@
{
"type": "Object",
"name": "Player: Model",
"ignore": true,
"ignore": false,
"import": "/model.json",
"assets": [
"/player/bear.glb"

View File

@ -16,7 +16,7 @@
[ 0, 0, 0, 0 ]
],
"shader": {
"mode": 1,
"mode": 0,
"scalar": 16,
"parameters": [ 0, 0, 0, "time" ]
}

View File

@ -3,7 +3,7 @@
"metadata": {
"graph": {
// "renderer": { "separate": true },
"baking": { "enabled": false },
"baking": { "enabled": true },
"tags": {
// exact matches
"worldspawn": {
@ -19,6 +19,7 @@
},
"info_player_spawn": { "action": "attach", "filename": "./player.json", "transform": { "orientation": [ 0, 1, 0, 0 ] } },
"light_environment": { "transform": { "orientation": [0,0,0,1] }, "light": {
"color": [0.1, 0.1, 0.1],
"power": 100000,
"global": true,
"bias": {

View File

@ -2,8 +2,8 @@
"import": "./base_sourceengine.json",
"assets": [
// { "filename": "./models/mds_mcdonalds.glb" }
{ "filename": "./models/mds_mcdonalds/graph.json" }
// { "filename": "/burger.json", "delay": 1 }
{ "filename": "./models/mds_mcdonalds/graph.json" },
{ "filename": "/burger.json", "delay": 1 }
],
"metadata": {
"graph": {

View File

@ -2,16 +2,16 @@
"import": "/scene.json",
"assets": [
"./sourceengine.json"
// "./loading.json"
// { "filename": "./loading.json", "delay": 0.5 }
],
"metadata": {
"light": {
"ambient": [ 0, 0, 0 ],
// "ambient": [ 0, 0, 0 ],
// "ambient": [ 0.05, 0.05, 0.05 ],
// "ambient": [ 0.15, 0.15, 0.15 ],
// "ambient": [ 0.5, 0.5, 0.5 ],
// "ambient": [ 0.8, 0.8, 0.8 ],
// "ambient": [ 0.1, 0.1, 0.2 ],
"ambient": [ 0.1, 0.1, 0.2 ],
"exposure": 0.125,
"gamma": 2.2, // 2.2,

View File

@ -8,10 +8,10 @@
// { "filename": "./models/tiny_msci/graph.json" }
// { "filename": "./models/micro_sci.glb" }
{ "filename": "./models/micro_sci/graph.json" }
// { "filename": "./models/micro_sci/graph.json" }
// { "filename": "./models/msci.glb" }
// { "filename": "./models/msci/graph.json" }
{ "filename": "./models/msci/graph.json" }
// { "filename": "./models/medsci.glb" }
// { "filename": "./models/medsci/graph.json" }

View File

@ -0,0 +1,13 @@
#version 450
#pragma shader_stage(fragment)
layout (location = 0) in vec3 inPosition;
layout (location = 1) in vec3 inColor;
layout (location = 0) out uvec2 outId;
layout (location = 1) out vec2 outNormals;
layout (location = 2) out vec4 outAlbedo;
void main() {
outAlbedo = vec4(inColor, 1);
}

View File

@ -0,0 +1,29 @@
#version 450
#pragma shader_stage(vertex)
#include "../../common/macros.h"
#include "../../common/structs.h"
layout (constant_id = 0) const uint PASSES = 6;
layout (location = 0) in vec3 inPos;
layout (location = 1) in vec3 inColor;
layout( push_constant ) uniform PushBlock {
uint pass;
uint draw;
} PushConstant;
layout (binding = 0) uniform Camera {
Viewport viewport[PASSES];
} camera;
layout (location = 0) out vec3 outPosition;
layout (location = 1) out vec3 outColor;
void main() {
outPosition = vec3(camera.viewport[PushConstant.pass].view * vec4(inPos.xyz, 1.0));
outColor = inColor;
gl_Position = camera.viewport[PushConstant.pass].projection * camera.viewport[PushConstant.pass].view * vec4(inPos.xyz, 1.0);
}

View File

@ -0,0 +1,56 @@
// Perlin Fog
void fog( in Ray ray, inout vec3 i, float scale ) {
if ( ubo.settings.fog.stepScale <= 0 || ubo.settings.fog.range.x == 0 || ubo.settings.fog.range.y == 0 ) return;
#if FOG_RAY_MARCH
const float range = ubo.settings.fog.range.y;
const vec3 boundsMin = vec3(-range,-range,-range) + ray.origin;
const vec3 boundsMax = vec3(range,range,range) + ray.origin;
const int numSteps = int(length(boundsMax - boundsMin) * ubo.settings.fog.stepScale );
const vec2 rayBoxInfo = rayBoxDst( boundsMin, boundsMax, ray );
const float dstToBox = rayBoxInfo.x;
const float dstInsideBox = rayBoxInfo.y;
const float depth = surface.position.eye.z;
const float aperture = 0; // PI * 0.5;
const float coneCoefficient = 2.0 * tan(aperture * 0.5);
// march
if ( 0 <= dstInsideBox && dstToBox <= depth ) {
float stepSize = dstInsideBox / numSteps;
float dstLimit = min( depth - dstToBox, dstInsideBox );
float totalDensity = 0;
float transmittance = 1;
float lightFactor = scale;
float coneDiameter = coneCoefficient * ray.distance;
float level = aperture > 0 ? log2( coneDiameter ) : 0;
float density = 0;
vec3 uvw;
ray.distance = dstToBox;
while ( ray.distance < dstLimit ) {
ray.distance += stepSize;
ray.position = ray.origin + ray.direction * ray.distance;
coneDiameter = coneCoefficient * ray.distance;
level = aperture > 0 ? log2( coneDiameter ) : 0;
uvw = ray.position * ubo.settings.fog.densityScale * 0.001 + ubo.settings.fog.offset * 0.01;
density = max(0, textureLod(samplerNoise, uvw, level).r - ubo.settings.fog.densityThreshold) * ubo.settings.fog.densityMultiplier;
if ( density > 0 ) {
density = exp(-density * stepSize * ubo.settings.fog.absorbtion);
transmittance *= density;
lightFactor *= density;
if ( transmittance < 0.1 ) break;
}
}
i.rgb = mix(ubo.settings.fog.color.rgb, i.rgb, transmittance );
}
#endif
#if FOG_BASIC
const vec3 color = ubo.settings.fog.color.rgb;
const float inner = ubo.settings.fog.range.x;
const float outer = ubo.settings.fog.range.y * scale;
const float distance = length(-surface.position.eye);
const float factor = clamp( (distance - inner) / (outer - inner), 0.0, 1.0 );
i.rgb = mix(i.rgb, color, factor);
#endif
}

View File

@ -0,0 +1,419 @@
// Helper Functions
float random(vec3 seed, int i){ return fract(sin(dot(vec4(seed,i), vec4(12.9898,78.233,45.164,94.673))) * 43758.5453); }
float rand2(vec2 co){ return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 143758.5453); }
float rand3(vec3 co){ return fract(sin(dot(co.xyz ,vec3(12.9898,78.233, 37.719))) * 143758.5453); }
//
float mipLevel( in vec2 dx_vtc, in vec2 dy_vtc ) {
const float delta_max_sqr = max(dot(dx_vtc, dx_vtc), dot(dy_vtc, dy_vtc));
return 0.5 * log2(delta_max_sqr);
// return max(0.0, 0.5 * log2(delta_max_sqr) - 1.0);
// return 0.5 * log2(max(dot(dx_vtc, dx_vtc), dot(dy_vtc, dy_vtc)));
}
float mipLevels( vec2 size ) {
return floor(log2(max(size.x, size.y)));
}
float mipLevels( ivec2 size ) {
return floor(log2(max(size.x, size.y)));
}
//
void toneMap( inout vec3 color, float exposure ) {
color.rgb = vec3(1.0) - exp(-color.rgb * exposure);
}
void gammaCorrect( inout vec3 color, float gamma ) {
color.rgb = pow(color.rgb, vec3(1.0 / gamma));
}
void toneMap( inout vec4 color, float exposure ) { toneMap(color.rgb, exposure); }
void gammaCorrect( inout vec4 color, float gamma ) { gammaCorrect(color.rgb, gamma); }
//
uint tea(uint val0, uint val1) {
uint v0 = val0;
uint v1 = val1;
uint s0 = 0;
#pragma unroll 16
for(uint n = 0; n < 16; n++) {
s0 += 0x9e3779b9;
v0 += ((v1 << 4) + 0xa341316c) ^ (v1 + s0) ^ ((v1 >> 5) + 0xc8013ea4);
v1 += ((v0 << 4) + 0xad90777d) ^ (v0 + s0) ^ ((v0 >> 5) + 0x7e95761e);
}
return v0;
}
uint lcg(inout uint prev) {
uint LCG_A = 1664525u;
uint LCG_C = 1013904223u;
prev = (LCG_A * prev + LCG_C);
return prev & 0x00FFFFFF;
}
float rnd(inout uint prev) { return (float(lcg(prev)) / float(0x01000000)); }
uint prngSeed;
float rnd() { return rnd(prngSeed); }
//
float ndfGGX(float cosLh, float roughness) {
const float alpha = roughness * roughness;
const float alphaSq = alpha * alpha;
const float denom = (cosLh * cosLh) * (alphaSq - 1.0) + 1.0;
return alphaSq / (PI * denom * denom);
}
float gaSchlickG1(float cosTheta, float k) { return cosTheta / (cosTheta * (1.0 - k) + k); }
float gaSchlickGGX(float cosLi, float cosLo, float roughness) {
const float r = roughness + 1.0;
const float k = (r * r) / 8.0;
return gaSchlickG1(cosLi, k) * gaSchlickG1(cosLo, k);
}
vec3 fresnelSchlick(vec3 F0, float cosTheta) { return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); }
//
void tangentBitangent(in vec3 N, out vec3 Nt, out vec3 Nb) {
if(abs(N.x) > abs(N.y)) Nt = vec3(N.z, 0, -N.x) / sqrt(N.x * N.x + N.z * N.z);
else Nt = vec3(0, -N.z, N.y) / sqrt(N.y * N.y + N.z * N.z);
Nb = cross(N, Nt);
}
vec3 samplingHemisphere(inout uint seed, in vec3 x, in vec3 y, in vec3 z) {
float r1 = rnd(seed);
float r2 = rnd(seed);
float sq = sqrt(1.0 - r2);
vec3 direction = vec3(cos(2 * PI * r1) * sq, sin(2 * PI * r1) * sq, sqrt(r2));
direction = direction.x * x + direction.y * y + direction.z * z;
return direction;
}
vec3 samplingHemisphere(inout uint seed, in vec3 z) {
vec3 x;
vec3 y;
tangentBitangent( z, x, y );
float r1 = rnd(seed);
float r2 = rnd(seed);
float sq = sqrt(1.0 - r2);
vec3 direction = vec3(cos(2 * PI * r1) * sq, sin(2 * PI * r1) * sq, sqrt(r2));
direction = direction.x * x + direction.y * y + direction.z * z;
return direction;
}
//
float max3( vec3 v ) { return max(max(v.x, v.y), v.z); }
float min3( vec3 v ) { return min(min(v.x, v.y), v.z); }
uint biasedRound( float x, float bias ) { return uint( ( x < bias ) ? floor(x) : ceil(x)); }
float wrap( float i ) { return fract(i); }
vec2 wrap( vec2 uv ) { return vec2( wrap( uv.x ), wrap( uv.y ) ); }
vec3 orthogonal(vec3 u){
u = normalize(u);
const vec3 v = vec3(0.99146, 0.11664, 0.05832); // Pick any normalized vector.
return abs(dot(u, v)) > 0.99999f ? cross(u, vec3(0, 1, 0)) : cross(u, v);
}
vec4 blend( vec4 source, vec4 dest, float a ) {
return source * a + dest * (1.0 - a);
}
float gauss( float x, float sigma ) {
return (1.0 / (2.0 * 3.14157 * sigma) * exp(-(x*x) / (2.0 * sigma)));
}
bool enabled( uint flag, uint bit ) {
return (flag & (1 << bit)) != 0;
}
vec3 decodeNormals( vec2 enc ) {
const vec2 ang = enc*2-1;
const vec2 scth = vec2( sin(ang.x * PI), cos(ang.x * PI) );
const vec2 scphi = vec2(sqrt(1.0 - ang.y*ang.y), ang.y);
return normalize( vec3(scth.y*scphi.x, scth.x*scphi.x, scphi.y) );
}
vec2 encodeNormals( vec3 n ) {
// float p = sqrt(n.z*8+8);
// return n.xy/p + 0.5;
return (vec2(atan(n.y,n.x)/PI, n.z)+1.0)*0.5;
}
vec3 encodeSrgb(vec3 rgb) {
const vec3 a = 12.92 * rgb;
const vec3 b = 1.055 * pow(rgb, vec3(1.0 / 2.4)) - 0.055;
const vec3 c = step(vec3(0.0031308), rgb);
return mix(a, b, c);
}
vec3 decodeSrgb(vec3 rgb) {
const vec3 a = rgb / 12.92;
const vec3 b = pow((rgb + 0.055) / 1.055, vec3(2.4));
const vec3 c = step(vec3(0.04045), rgb);
return mix(a, b, c);
}
bool validTextureIndex( int textureIndex ) {
return 0 <= textureIndex && textureIndex < MAX_TEXTURES;
}
#if MAX_CUBEMAPS
bool validCubemapIndex( int textureIndex ) {
return 0 <= textureIndex && textureIndex < MAX_CUBEMAPS;
}
#endif
#if !BLOOM && (DEFERRED || FRAGMENT || COMPUTE || RT)
bool validTextureIndex( uint id ) {
return 0 <= id && id < MAX_TEXTURES;
}
bool validTextureIndex( uint start, int offset ) {
return 0 <= offset && start + offset < MAX_TEXTURES;
}
uint textureIndex( uint start, int offset ) {
return start + offset;
}
vec4 sampleTexture( uint id, vec2 uv ) {
const Texture t = textures[id];
return texture( samplerTextures[nonuniformEXT(t.index)], mix( t.lerp.xy, t.lerp.zw, uv ) );
}
vec4 sampleTexture( uint id, vec2 uv, float mip ) {
#if QUERY_MIPMAP
return sampleTexture( id, uv );
#else
const Texture t = textures[id];
return textureLod( samplerTextures[nonuniformEXT(t.index)], mix( t.lerp.xy, t.lerp.zw, uv ), mip );
#endif
}
vec4 sampleTexture( uint id, vec3 uvm ) { return sampleTexture( id, uvm.xy, uvm.z ); }
vec4 sampleTexture( uint id ) { return sampleTexture( id, surface.uv.xy, surface.uv.z ); }
vec4 sampleTexture( uint id, float mip ) { return sampleTexture( id, surface.uv.xy, mip ); }
#endif
vec2 rayBoxDst( vec3 boundsMin, vec3 boundsMax, in Ray ray ) {
const vec3 t0 = (boundsMin - ray.origin) / ray.direction;
const vec3 t1 = (boundsMax - ray.origin) / ray.direction;
const vec3 tmin = min(t0, t1);
const vec3 tmax = max(t0, t1);
const float tStart = max(0, max( max(tmin.x, tmin.y), tmin.z ));
const float tEnd = max(0, min( tmax.x, min(tmax.y, tmax.z) ) - tStart);
return vec2(tStart, tEnd);
}
#if VXGI
float cascadePower( uint x ) {
return pow(1 + x, ubo.settings.vxgi.cascadePower);
// return max( 1, x * ubo.settings.vxgi.cascadePower );
}
#endif
#if FRAGMENT
void whitenoise(inout vec3 color, const vec4 parameters) {
const float flicker = parameters.x;
const float pieces = parameters.y;
const float blend = parameters.z;
const float time = parameters.w;
if ( blend < 0.0001 ) return;
const float freq = sin(pow(mod(time, flicker) + flicker, 1.9));
const float whiteNoise = rand2( floor(gl_FragCoord.xy / pieces) + mod(time, freq) );
color = mix( color, vec3(whiteNoise), blend );
}
vec4 resolve( subpassInputMS t, const uint samples ) {
vec4 resolved = vec4(0);
for ( int i = 0; i < samples; ++i ) resolved += subpassLoad(t, i);
resolved /= vec4(samples);
return resolved;
}
uvec4 resolve( usubpassInputMS t, const uint samples ) {
uvec4 resolved = uvec4(0);
for ( int i = 0; i < samples; ++i ) resolved += subpassLoad(t, i);
resolved /= uvec4(samples);
return resolved;
}
#endif
vec4 resolve( sampler2DMS t, ivec2 uv ) {
vec4 resolved = vec4(0);
int samples = textureSamples(t);
for ( int i = 0; i < samples; ++i ) {
resolved += texelFetch(t, uv, i);
}
resolved /= float(samples);
return resolved;
}
//
vec2 encodeBarycentrics( vec3 barycentric ) {
return barycentric.yz;
}
vec3 decodeBarycentrics( vec2 attributes ) {
return vec3(
1.0 - attributes.x - attributes.y,
attributes.x,
attributes.y
);
}
#if DEFERRED_SAMPLING
void populateSurfaceMaterial() {
const Material material = materials[surface.instance.materialID];
surface.material.albedo = material.colorBase;
surface.material.metallic = material.factorMetallic;
surface.material.roughness = material.factorRoughness;
surface.material.occlusion = material.factorOcclusion;
surface.light = material.colorEmissive;
if ( validTextureIndex( material.indexAlbedo ) ) {
surface.material.albedo *= sampleTexture( material.indexAlbedo );
}
// OPAQUE
if ( material.modeAlpha == 0 ) {
surface.material.albedo.a = 1;
// BLEND
} else if ( material.modeAlpha == 1 ) {
// MASK
} else if ( material.modeAlpha == 2 ) {
}
// Lightmap
if ( (/*surface.subID++ > 0 ||*/ bool(ubo.settings.lighting.useLightmaps)) && validTextureIndex( surface.instance.lightmapID ) ) {
vec4 light = sampleTexture( surface.instance.lightmapID, surface.st );
/*surface.material.lightmapped = light.a > 0.000000001;
if ( surface.material.lightmapped )*/ surface.light += surface.material.albedo * light;
} else {
surface.material.lightmapped = false;
}
// Emissive textures
if ( validTextureIndex( material.indexEmissive ) ) {
surface.light += sampleTexture( material.indexEmissive );
}
// Occlusion map
if ( validTextureIndex( material.indexOcclusion ) ) {
surface.material.occlusion = sampleTexture( material.indexOcclusion ).r;
}
// Metallic/Roughness map
if ( validTextureIndex( material.indexMetallicRoughness ) ) {
vec4 samp = sampleTexture( material.indexMetallicRoughness );
surface.material.metallic = samp.r;
surface.material.roughness = samp.g;
}
// Normals
if ( validTextureIndex( material.indexNormal ) && surface.tangent.world != vec3(0) ) {
surface.normal.world = surface.tbn * normalize( sampleTexture( material.indexNormal ).xyz * 2.0 - vec3(1.0));
}
{
surface.normal.eye = normalize(vec3( ubo.eyes[surface.pass].view * vec4(surface.normal.world, 0.0) ));
}
surface.light *= surface.material.albedo;
}
bool isValidAddress( uint64_t address ) {
#if UINT64_ENABLED
return bool(address);
#else
return bool(address.x) && bool(address.y);
#endif
}
#if BUFFER_REFERENCE
void populateSurface( InstanceAddresses instanceAddresses, uvec3 indices ) {
Triangle triangle;
Vertex points[3];
if ( isValidAddress(instanceAddresses.vertex) ) {
Vertices vertices = Vertices(nonuniformEXT(instanceAddresses.vertex));
#pragma unroll 3
for ( uint _ = 0; _ < 3; ++_ ) /*triangle.*/points[_] = vertices.v[/*triangle.*/indices[_]];
} else {
if ( isValidAddress(instanceAddresses.position) ) {
VPos buf = VPos(nonuniformEXT(instanceAddresses.position));
#pragma unroll 3
for ( uint _ = 0; _ < 3; ++_ ) /*triangle.*/points[_].position = buf.v[/*triangle.*/indices[_]];
}
if ( isValidAddress(instanceAddresses.uv) ) {
VUv buf = VUv(nonuniformEXT(instanceAddresses.uv));
#pragma unroll 3
for ( uint _ = 0; _ < 3; ++_ ) /*triangle.*/points[_].uv = buf.v[/*triangle.*/indices[_]];
}
if ( isValidAddress(instanceAddresses.st) ) {
VSt buf = VSt(nonuniformEXT(instanceAddresses.st));
#pragma unroll 3
for ( uint _ = 0; _ < 3; ++_ ) /*triangle.*/points[_].st = buf.v[/*triangle.*/indices[_]];
}
if ( isValidAddress(instanceAddresses.normal) ) {
VNormal buf = VNormal(nonuniformEXT(instanceAddresses.normal));
#pragma unroll 3
for ( uint _ = 0; _ < 3; ++_ ) /*triangle.*/points[_].normal = buf.v[/*triangle.*/indices[_]];
}
if ( isValidAddress(instanceAddresses.tangent) ) {
VTangent buf = VTangent(nonuniformEXT(instanceAddresses.tangent));
#pragma unroll 3
for ( uint _ = 0; _ < 3; ++_ ) /*triangle.*/points[_].tangent = buf.v[/*triangle.*/indices[_]];
}
}
#if BARYCENTRIC_CALCULATE
{
const vec3 p = vec3(inverse( surface.instance.model ) * vec4(surface.position.world, 1));
const vec3 a = points[0].position;
const vec3 b = points[1].position;
const vec3 c = points[2].position;
const vec3 v0 = b - a;
const vec3 v1 = c - a;
const vec3 v2 = p - a;
const float d00 = dot(v0, v0);
const float d01 = dot(v0, v1);
const float d11 = dot(v1, v1);
const float d20 = dot(v2, v0);
const float d21 = dot(v2, v1);
const float denom = d00 * d11 - d01 * d01;
const float v = (d11 * d20 - d01 * d21) / denom;
const float w = (d00 * d21 - d01 * d20) / denom;
const float u = 1.0f - v - w;
surface.barycentric = vec3( u, v, w );
}
#endif
triangle.geomNormal = normalize(cross(points[1].position - points[0].position, points[2].position - points[0].position));
triangle.point.normal = /*triangle.*/points[0].normal * surface.barycentric[0] + /*triangle.*/points[1].normal * surface.barycentric[1] + /*triangle.*/points[2].normal * surface.barycentric[2];
triangle.point.position = /*triangle.*/points[0].position * surface.barycentric[0] + /*triangle.*/points[1].position * surface.barycentric[1] + /*triangle.*/points[2].position * surface.barycentric[2];
triangle.point.uv = /*triangle.*/points[0].uv * surface.barycentric[0] + /*triangle.*/points[1].uv * surface.barycentric[1] + /*triangle.*/points[2].uv * surface.barycentric[2];
triangle.point.st = /*triangle.*/points[0].st * surface.barycentric[0] + /*triangle.*/points[1].st * surface.barycentric[1] + /*triangle.*/points[2].st * surface.barycentric[2];
triangle.point.tangent = /*triangle.*/points[0].tangent * surface.barycentric[0] + /*triangle.*/points[1].tangent * surface.barycentric[1] + /*triangle.*/points[2].tangent * surface.barycentric[2];
if ( triangle.point.tangent != vec3(0) ) {
surface.tangent.world = normalize(vec3( surface.instance.model * vec4(triangle.point.tangent, 0.0) ));
vec3 bitangent = normalize(vec3( surface.instance.model * vec4(cross( triangle.point.normal, triangle.point.tangent ), 0.0) ));
surface.tbn = mat3(surface.tangent.world, bitangent, triangle.point.normal);
}
// bind position
#if 1 || BARYCENTRIC_CALCULATE
{
surface.position.world = vec3( surface.instance.model * vec4(triangle.point.position, 1.0 ) );
surface.position.eye = vec3( ubo.eyes[surface.pass].view * vec4(surface.position.world, 1.0) );
}
#endif
// bind normals
{
surface.normal.world = normalize(vec3( surface.instance.model * vec4(triangle.point.normal, 0.0 ) ));
// surface.normal.eye = vec3( ubo.eyes[surface.pass].view * vec4(surface.normal.world, 0.0) );
}
// bind UVs
{
surface.uv.xy = triangle.point.uv;
surface.uv.z = 0;
surface.st.xy = triangle.point.st;
surface.st.z = 0;
}
populateSurfaceMaterial();
}
void populateSurface( uint instanceID, uint primitiveID ) {
surface.fragment = vec4(0);
surface.light = vec4(0);
surface.instance = instances[instanceID];
const InstanceAddresses instanceAddresses = instanceAddresses[instanceID];
if ( !isValidAddress(instanceAddresses.index) ) return;
const DrawCommand drawCommand = Indirects(nonuniformEXT(instanceAddresses.indirect)).dc[instanceAddresses.drawID];
const uint triangleID = primitiveID + (drawCommand.indexID / 3);
uvec3 indices = Indices(nonuniformEXT(instanceAddresses.index)).i[triangleID];
#pragma unroll 3
for ( uint _ = 0; _ < 3; ++_ ) /*triangle.*/indices[_] += drawCommand.vertexID;
populateSurface( instanceAddresses, indices );
}
void populateSurface( RayTracePayload payload ) {
surface.fragment = vec4(0);
surface.light = vec4(0);
surface.instance = instances[payload.instanceID];
if ( !payload.hit ) return;
surface.barycentric = decodeBarycentrics(payload.attributes);
populateSurface( payload.instanceID, payload.primitiveID );
}
#endif
#endif

View File

@ -0,0 +1,66 @@
float shadowFactor( const Light light, float def );
void lambert() {
// outcoming light from surface to eye
const vec3 Lo = normalize( -surface.position.eye );
// angle of outcoming light
const float cosLo = max(0.0, dot(surface.normal.eye, Lo));
for ( uint i = 0, shadows = 0; i < MAX_LIGHTS; ++i ) {
#if BAKING
// skip if surface is a dynamic light, we aren't baking dynamic lights
if ( lights[i].type < 0 ) continue;
#else
// skip if surface is already baked, and this isn't a dynamic light
if ( surface.material.lightmapped && lights[i].type >= 0 ) continue;
#endif
if ( lights[i].power <= LIGHT_POWER_CUTOFF ) continue;
if ( surface.material.lightmapped && lights[i].type >= 0 ) continue;
vec3 Li = vec3(VIEW_MATRIX * vec4(lights[i].position, 1)) - surface.position.eye;
// magnitude of incoming light vector (for inverse-square attenuation)
const float Lmagnitude = dot(Li, Li);
// distance incoming light travels (reuse from above)
const float Ldistance = sqrt(Lmagnitude);
// "free" normalization, since we need to compute the above values anyways
Li = Li / Ldistance;
// attenuation factor
// const float Lattenuation = 1.0 / (1 + (PI * Lmagnitude));
const float Lattenuation = 1.0 / (1 + Lmagnitude);
// skip if attenuation factor is too low
// if ( Lattenuation <= LIGHT_POWER_CUTOFF ) continue;
// ray cast if our surface is occluded from the light
const float Lshadow = 1; // ( shadows++ < MAX_SHADOWS ) ? shadowFactor( lights[i], 0.0 ) : 1;
// skip if our shadow factor is too low
if ( Lshadow <= LIGHT_POWER_CUTOFF ) continue;
// light radiance
const vec3 Lr = lights[i].color.rgb * lights[i].power * Lattenuation * Lshadow;
// skip if our radiance is too low
// if ( Lr <= LIGHT_POWER_CUTOFF ) continue;
// halfway vector
const vec3 Lh = normalize(Li + Lo);
// angle of incoming light
const float cosLi = max(0.0, dot(surface.normal.eye, Li));
// angle of halfway light vector
const float cosLh = max(0.0, dot(surface.normal.eye, Lh));
/*
const vec3 Liu = vec3(VIEW_MATRIX * vec4(lights[i].position, 1)) - surface.position.eye;
const vec3 Li = normalize(Liu);
// const float Lattenuation = 1.0 / (PI * pow(length(Liu), 2.0));
// const float Lattenuation = 1.0 / (1 + (PI * pow(length(Liu), 2.0)));
const float Lattenuation = 1.0 / (1 + pow(length(Liu), 2.0));
const float Lshadow = ( shadows++ < MAX_SHADOWS ) ? shadowFactor( lights[i], 0.0 ) : 1;
if ( lights[i].power * Lattenuation * Lshadow <= LIGHT_POWER_CUTOFF ) continue;
const float cosLi = max(0.0, dot(surface.normal.eye, Li));
const vec3 Lr = lights[i].color.rgb * lights[i].power * Lattenuation * Lshadow;
// const vec3 Lh = normalize(Li + Lo);
// const float cosLh = max(0.0, dot(surface.normal.eye, Lh));
*/
const vec3 diffuse = surface.material.albedo.rgb;
const vec3 specular = vec3(0);
surface.light.rgb += (diffuse + specular) * Lr * cosLi;
surface.light.a += lights[i].power * Lattenuation * Lshadow;
}
}

View File

@ -0,0 +1,11 @@
float shadowFactor( const Light light, float def );
#if PBR
#include "../common/pbr.h"
#endif
#if LAMBERT
#include "../common/lambert.h"
#endif
#if PHONG
#include "../common/phong.h"
#endif

View File

@ -0,0 +1,102 @@
#ifndef NO_NONUNIFORM_EXT
#define NO_NONUNIFORM_EXT 0
// enable if shaderNonUniform is not supported
// Nvidia hardware does not require nonuniformEXT, but AMD does
#endif
// implicit variables
#ifndef MULTISAMPLING
#define MULTISAMPLING 1
#endif
#ifndef MAX_MSAA_SAMPLES
#define MAX_MSAA_SAMPLES 16
#endif
#ifndef MAX_TEXTURES
#define MAX_TEXTURES TEXTURES
#endif
#ifndef MAX_LIGHTS
#define MAX_LIGHTS ubo.settings.lengths.lights
#endif
#ifndef MAX_SHADOWS
#define MAX_SHADOWS ubo.settings.lighting.maxShadows
#endif
#ifndef VIEW_MATRIX
#define VIEW_MATRIX ubo.eyes[surface.pass].view
#endif
// implicit shader settings
#ifndef CAN_DISCARD
#define CAN_DISCARD 1
#endif
#ifndef USE_LIGHTMAP
#define USE_LIGHTMAP 1
#endif
#if VXGI
#define VXGI_NDC 1
#define VXGI_SHADOWS 0
#endif
/*
#ifndef FOG
#define FOG 1
#endif
#ifndef FOG_RAY_MARCH
#define FOG_RAY_MARCH 1
#endif
#ifndef WHITENOISE
#define WHITENOISE 1
#endif
#ifndef GAMMA_CORRECT
#define GAMMA_CORRECT 1
#endif
#ifndef TONE_MAP
#define TONE_MAP 1
#endif
#ifndef PHONG
#define PHONG 0
#endif
#ifndef LAMBERT
#define LAMBERT 0
#endif
#ifndef PBR
#define PBR 1
#endif
*/
#if NO_NONUNIFORM_EXT
#define nonuniformEXT(X) X
#else
#extension GL_EXT_nonuniform_qualifier : enable
#endif
#if !UINT64_ENABLED
#define uint64_t uvec2
#endif
// easy and accessible in one place
#ifndef BARYCENTRIC
#define BARYCENTRIC 0
#endif
#if BARYCENTRIC
#ifndef BARYCENTRIC_CALCULATE
#define BARYCENTRIC_CALCULATE 0
#endif
#endif
#if BUFFER_REFERENCE
#extension GL_EXT_scalar_block_layout : enable
#extension GL_EXT_buffer_reference : enable
#extension GL_EXT_buffer_reference2 : enable
#if UINT64_ENABLED
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : enable
#else
#extension GL_EXT_buffer_reference_uvec2 : enable
#endif
#endif
const float PI = 3.14159265359;
const float EPSILON = 0.00001;
const float SQRT2 = 1.41421356237;
const float LIGHT_POWER_CUTOFF = 0.0005;
const float LIGHTMAP_GAMMA = 1.0;

View File

@ -0,0 +1,121 @@
// PBR
void pbr() {
// per-surface, not per-light, compute once
// Freslen reflectance for a dieletric
const vec3 F0 = mix(vec3(0.04), surface.material.albedo.rgb, surface.material.metallic);
// outcoming light from surface to eye
const vec3 Lo = normalize( -surface.position.eye );
// angle of outcoming light
const float cosLo = max(0.0, dot(surface.normal.eye, Lo));
const float Rs = 4.0;
for ( uint i = 0, shadows = 0; i < MAX_LIGHTS; ++i ) {
#if BAKING
// skip if surface is a dynamic light, we aren't baking dynamic lights
if ( lights[i].type < 0 ) continue;
#else
// skip if surface is already baked, and this isn't a dynamic light
if ( surface.material.lightmapped && lights[i].type >= 0 ) continue;
#endif
/*
// skip if light power is too low
if ( lights[i].power <= LIGHT_POWER_CUTOFF ) continue;
if ( surface.material.lightmapped && lights[i].type >= 0 ) continue;
const vec3 Liu = vec3(VIEW_MATRIX * vec4(lights[i].position, 1)) - surface.position.eye;
const vec3 Li = normalize(Liu);
const float Lshadow = ( shadows++ < MAX_SHADOWS ) ? shadowFactor( lights[i], 0.0 ) : 1;
// const float Lattenuation = 1.0 / (PI * pow(length(Liu), 2.0));
// const float Lattenuation = 1.0 / (1 + (PI * pow(length(Liu), 2.0)));
const float Lattenuation = 1.0 / (1 + pow(length(Liu), 2.0));
if ( lights[i].power * Lattenuation * Lshadow <= LIGHT_POWER_CUTOFF ) continue;
const float cosLi = max(0.0, dot(surface.normal.eye, Li));
const vec3 Lr = lights[i].color.rgb * lights[i].power * Lattenuation * Lshadow;
const vec3 Lh = normalize(Li + Lo);
const float cosLh = max(0.0, dot(surface.normal.eye, Lh));
*/
// incoming light to surface (non-const to normalize it later)
// vec3 Li = lights[i].position - surface.position.world;
vec3 Li = vec3(VIEW_MATRIX * vec4(lights[i].position, 1)) - surface.position.eye;
// magnitude of incoming light vector (for inverse-square attenuation)
const float Lmagnitude = dot(Li, Li);
// distance incoming light travels (reuse from above)
const float Ldistance = sqrt(Lmagnitude);
// "free" normalization, since we need to compute the above values anyways
Li = Li / Ldistance;
// attenuation factor
// const float Lattenuation = 1.0 / (1 + (PI * Lmagnitude));
const float Lattenuation = 1.0 / (1 + Lmagnitude);
// skip if attenuation factor is too low
// if ( Lattenuation <= LIGHT_POWER_CUTOFF ) continue;
// ray cast if our surface is occluded from the light
const float Lshadow = ( shadows++ < MAX_SHADOWS ) ? shadowFactor( lights[i], 0.0 ) : 1;
// skip if our shadow factor is too low
if ( Lshadow <= LIGHT_POWER_CUTOFF ) continue;
// light radiance
const vec3 Lr = lights[i].color.rgb * lights[i].power * Lattenuation * Lshadow;
// skip if our radiance is too low
// if ( Lr <= LIGHT_POWER_CUTOFF ) continue;
// halfway vector
const vec3 Lh = normalize(Li + Lo);
// angle of incoming light
const float cosLi = max(0.0, dot(surface.normal.eye, Li));
// angle of halfway light vector
const float cosLh = max(0.0, dot(surface.normal.eye, Lh));
// Fresnel term for direct lighting
const vec3 F = fresnelSchlick(F0, max(0.0, dot(Lh, Lo)));
// Distribution for specular lighting
const float D = ndfGGX( cosLh, surface.material.roughness * Rs);
// Geometric attenuation for specular lighting
const float G = gaSchlickGGX(cosLi, cosLo, surface.material.roughness * Rs);
// final lighting
const vec3 diffuse = mix(vec3(1.0) - F, vec3(0), surface.material.metallic) * surface.material.albedo.rgb;
const vec3 specular = ( shadows < MAX_SHADOWS ) ? ((F * D * G) / max(EPSILON, 4.0 * cosLi * cosLo)) : vec3(0);
surface.light.rgb += (diffuse + specular) * Lr * cosLi;
surface.light.a += lights[i].power * Lattenuation * Lshadow;
}
#if 0
const float Rs = 4.0; // specular lighting looks gross without this
uint shadows = 0;
for ( uint i = 0; i < ubo.settings.lengths.lights; ++i ) {
const Light light = lights[i];
if ( light.power <= LIGHT_POWER_CUTOFF ) continue;
if ( surface.material.lightmapped && light.type >= 0 ) continue;
const vec3 Liu = vec3(ubo.eyes[surface.pass].view * vec4(light.position, 1)) - surface.position.eye;
const float Ld = length(Liu);
const float La = 1.0 / (1 + (PI * pow(Ld, 2.0)));
if ( La <= LIGHT_POWER_CUTOFF ) continue;
const vec3 Li = normalize(Liu);
const float Ls = ( shadows++ < ubo.settings.lighting.maxShadows ) ? shadowFactor( light, 0.0 ) : 1;
if ( light.power * La * Ls <= LIGHT_POWER_CUTOFF ) continue;
const float cosLi = max(0.0, dot(surface.normal.eye, Li));
const vec3 Lr = light.color.rgb * light.power * La * Ls;
const vec3 Lh = normalize(Li + Lo);
const float cosLh = max(0.0, dot(surface.normal.eye, Lh));
const vec3 F = fresnelSchlick( F0, max( 0.0, dot(Lh, Lo) ) );
const float D = ndfGGX( cosLh, surface.material.roughness * Rs );
const float G = gaSchlickGGX(cosLi, cosLo, surface.material.roughness);
const vec3 diffuse = mix( vec3(1.0) - F, vec3(0.0), surface.material.metallic ) * surface.material.albedo.rgb;
const vec3 specular = (F * D * G) / max(EPSILON, 4.0 * cosLi * cosLo);
/*
// lightmapped, compute only specular
if ( light.type >= 0 && validTextureIndex( surface.instance.lightmapID ) ) surface.light.rgb += (specular) * Lr * cosLi;
// point light, compute only diffuse
// else if ( abs(light.type) == 1 ) surface.light.rgb += (diffuse) * Lr * cosLi;
else surface.light.rgb += (diffuse + specular) * Lr * cosLi;
*/
surface.light.rgb += (diffuse + specular) * Lr * cosLi;
surface.light.a += light.power * La * Ls;
}
#endif
}

View File

@ -0,0 +1,171 @@
const vec2 poissonDisk[16] = vec2[](
vec2( -0.94201624, -0.39906216 ),
vec2( 0.94558609, -0.76890725 ),
vec2( -0.094184101, -0.92938870 ),
vec2( 0.34495938, 0.29387760 ),
vec2( -0.91588581, 0.45771432 ),
vec2( -0.81544232, -0.87912464 ),
vec2( -0.38277543, 0.27676845 ),
vec2( 0.97484398, 0.75648379 ),
vec2( 0.44323325, -0.97511554 ),
vec2( 0.53742981, -0.47373420 ),
vec2( -0.26496911, -0.41893023 ),
vec2( 0.79197514, 0.19090188 ),
vec2( -0.24188840, 0.99706507 ),
vec2( -0.81409955, 0.91437590 ),
vec2( 0.19984126, 0.78641367 ),
vec2( 0.14383161, -0.14100790 )
);
#ifndef SHADOW_SAMPLES
#define SHADOW_SAMPLES ubo.settings.lighting.shadowSamples
#endif
#if VXGI
float voxelShadowFactor( const Light, float def );
#endif
#if CUBEMAPS
float omniShadowMap( const Light light, float def ) {
return 1.0;
}
#else
float omniShadowMap( const Light light, float def ) {
float factor = 1.0;
const mat4 views[6] = {
mat4( 0, 0, 1, 0, 0, 1, 0, 0,-1, 0, 0, 0, 0, 0, 0, 1 ),
mat4( 0, 0,-1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1 ),
mat4( 1, 0, 0, 0, 0, 0, 1, 0, 0,-1, 0, 0, 0, 0, 0, 1 ),
mat4( 1, 0, 0, 0, 0, 0,-1, 0, 0, 1, 0, 0, 0, 0, 0, 1 ),
mat4( 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ),
mat4(-1, 0, 0, 0, 0, 1, 0, 0, 0, 0,-1, 0, 0, 0, 0, 1 ),
};
const vec3 D = normalize(surface.position.world - light.position);
const vec3 N = abs(D);
uint A = N.y > N.x ? 1 : 0;
A = N.z > N[A] ? 2 : A;
uint index = A * 2;
if ( D[A] < 0.0 ) ++index;
vec4 positionClip = light.projection * views[index] * vec4(surface.position.world - light.position, 1.0);
positionClip.xy /= positionClip.w;
if ( positionClip.x < -1 || positionClip.x >= 1 ) return 0.0;
if ( positionClip.y < -1 || positionClip.y >= 1 ) return 0.0;
if ( positionClip.z < -1 || positionClip.z >= 1 ) return 0.0;
const float eyeDepthScale = 1.0;
const float sampledDepthScale = light.view[1][1]; // light view matricies will incorporate scaling factors for some retarded reason, so we need to rescale it by grabbing from here, hopefully it remains coherent between all light matrices to ever exist in engine
const float bias = light.depthBias;
const float eyeDepth = abs(positionClip.z / positionClip.w) * eyeDepthScale;
const vec3 sampleOffsetDirections[20] = {
vec3( 1, 1, 1), vec3( 1, -1, 1), vec3(-1, -1, 1), vec3(-1, 1, 1),
vec3( 1, 1, -1), vec3( 1, -1, -1), vec3(-1, -1, -1), vec3(-1, 1, -1),
vec3( 1, 1, 0), vec3( 1, -1, 0), vec3(-1, -1, 0), vec3(-1, 1, 0),
vec3( 1, 0, 1), vec3(-1, 0, 1), vec3( 1, 0, -1), vec3(-1, 0, -1),
vec3( 0, 1, 1), vec3( 0, -1, 1), vec3( 0, -1, -1), vec3( 0, 1, -1)
};
float sampled = 0;
const int samples = int(SHADOW_SAMPLES);
// cubemap point light
if ( light.typeMap == 1 ) {
if ( samples < 1 ) {
sampled = texture(samplerCubemaps[nonuniformEXT(light.indexMap)], D).r * sampledDepthScale;
} else {
for ( int i = 0; i < samples; ++i ) {
const int idx = int( float(samples) * random(floor(surface.position.world.xyz * 1000.0), i)) % samples;
vec2 poisson = poissonDisk[idx] / 700.0;
vec3 P = vec3( poisson.xy, (poisson.x + poisson.y) * 0.5 );
sampled = texture(samplerCubemaps[nonuniformEXT(light.indexMap)], D + P ).r * sampledDepthScale;
if ( eyeDepth < sampled - bias ) factor -= 1.0 / samples;
}
return factor;
}
// separated point lights
} else if ( light.typeMap == 2 ) {
const vec2 uv = positionClip.xy * 0.5 + 0.5;
if ( samples < 1 ) {
sampled = texture(samplerTextures[nonuniformEXT(light.indexMap + index)], uv).r * sampledDepthScale;
} else {
for ( int i = 0; i < samples; ++i ) {
const int idx = int( float(samples) * random(floor(surface.position.world.xyz * 1000.0), i)) % samples;
sampled = texture(samplerTextures[nonuniformEXT(light.indexMap + index)], uv + poissonDisk[idx] / 700.0 ).r * sampledDepthScale;
if ( eyeDepth < sampled - bias ) factor -= 1.0 / samples;
}
return factor;
}
}
return eyeDepth < sampled - bias ? 0.0 : factor;
}
#endif
#if RT
float shadowFactorRT( const Light light, float def ) {
Ray ray;
ray.origin = surface.position.world;
ray.direction = light.position - ray.origin;
float tMin = ubo.settings.rt.defaultRayBounds.x;
float tMax = length(ray.direction) - ubo.settings.rt.defaultRayBounds.x;
ray.direction = normalize(ray.direction);
uint rayFlags = gl_RayFlagsOpaqueEXT | gl_RayFlagsTerminateOnFirstHitEXT | gl_RayFlagsSkipClosestHitShaderEXT;
uint cullMask = 0xFF;
rayQueryEXT rayQuery;
rayQueryInitializeEXT(rayQuery, tlas, rayFlags, cullMask, ray.origin, tMin, ray.direction, tMax);
while(rayQueryProceedEXT(rayQuery));
return rayQueryGetIntersectionTypeEXT(rayQuery, true) == gl_RayQueryCommittedIntersectionNoneEXT ? 1.0 : 0.0;
}
#endif
float shadowFactor( const Light light, float def ) {
#if RT
return shadowFactorRT( light, def );
#endif
if ( light.typeMap != 0 ) return omniShadowMap( light, def );
if ( !validTextureIndex(light.indexMap) )
#if VXGI
return voxelShadowFactor( light, def );
#else
return 1.0;
#endif
vec4 positionClip = light.projection * light.view * vec4(surface.position.world, 1.0);
positionClip.xyz /= positionClip.w;
if ( positionClip.x < -1 || positionClip.x >= 1 ) return def; //0.0;
if ( positionClip.y < -1 || positionClip.y >= 1 ) return def; //0.0;
if ( positionClip.z <= 0 || positionClip.z >= 1 ) return def; //0.0;
float factor = 1.0;
// spot light
if ( abs(light.type) == 2 || abs(light.type) == 3 ) {
const float dist = length( positionClip.xy );
if ( dist > 0.5 ) return def; //0.0;
// spot light with attenuation
if ( abs(light.type) == 3 ) {
factor = 1.0 - (pow(dist * 2,2.0));
}
}
const vec2 uv = positionClip.xy * 0.5 + 0.5;
const float bias = light.depthBias;
const float eyeDepth = positionClip.z;
const int samples = int(SHADOW_SAMPLES);
if ( samples < 1 ) return eyeDepth < texture(samplerTextures[nonuniformEXT(light.indexMap)], uv).r - bias ? 0.0 : factor;
for ( int i = 0; i < samples; ++i ) {
const int index = int( float(samples) * random(floor(surface.position.world.xyz * 1000.0), i)) % samples;
const float lightDepth = texture(samplerTextures[nonuniformEXT(light.indexMap)], uv + poissonDisk[index] / 700.0 ).r;
if ( eyeDepth < lightDepth - bias ) factor -= 1.0 / samples;
}
return factor;
}

View File

@ -0,0 +1,308 @@
struct EyeMatrices {
mat4 view;
mat4 projection;
mat4 model;
mat4 previous;
mat4 iView;
mat4 iProjection;
vec4 eyePos;
};
struct Viewport {
mat4 view;
mat4 projection;
};
struct Cursor {
vec2 position;
vec2 radius;
vec4 color;
};
struct Ray {
vec3 origin;
vec3 direction;
vec3 position;
float distance;
};
struct Space {
vec3 eye;
vec3 world;
};
struct Light {
mat4 view;
mat4 projection;
vec3 position;
float radius;
vec3 color;
float power;
int type;
int typeMap;
int indexMap;
float depthBias;
};
struct Material {
vec4 colorBase;
vec4 colorEmissive;
float factorMetallic;
float factorRoughness;
float factorOcclusion;
float factorAlphaCutoff;
int indexAlbedo;
int indexNormal;
int indexEmissive;
int indexOcclusion;
int indexMetallicRoughness;
int padding1;
int padding2;
int modeAlpha;
};
struct Texture {
int index;
int samp;
int remap;
float blend;
vec4 lerp;
};
struct DrawCommand {
uint indices; // triangle count
uint instances; // instance count
uint indexID; // starting triangle position
int vertexID; // starting vertex position
uint instanceID; // starting instance position
float padding1; //
float padding2; // material to use for this draw call
uint vertices; // number of vertices used
};
struct Bounds {
vec3 min;
float padding1;
vec3 max;
float padding2;
};
struct Instance {
mat4 model;
mat4 previous;
vec4 color;
uint materialID;
uint primitiveID;
uint meshID;
uint objectID;
int jointID;
int lightmapID;
uint imageID;
uint auxID;
Bounds bounds;
// InstanceAddresses addresses;
};
struct InstanceAddresses {
uint64_t vertex;
uint64_t index;
uint64_t indirect;
uint drawID;
uint padding0;
uint64_t position;
uint64_t uv;
uint64_t color;
uint64_t st;
uint64_t normal;
uint64_t tangent;
uint64_t joints;
uint64_t weights;
uint64_t id;
uint64_t padding1;
};
struct SurfaceMaterial {
vec4 albedo;
vec4 indirect;
float metallic;
float roughness;
float occlusion;
bool lightmapped;
};
struct Surface {
uint pass;
uint subID;
vec3 uv;
vec3 st;
Space position;
Space normal;
Space tangent;
mat3 tbn;
vec3 barycentric;
vec2 motion;
Ray ray;
SurfaceMaterial material;
Instance instance;
vec4 light;
vec4 fragment;
} surface;
// MSAA info
#if MULTISAMPLING
struct MSAA {
int currentID;
uvec2 IDs[MAX_MSAA_SAMPLES];
vec4 fragment;
vec4 fragments[MAX_MSAA_SAMPLES];
} msaa;
#endif
// UBO settings
struct SettingsLengths {
uint lights;
uint materials;
uint textures;
uint drawCommands;
};
struct SettingsMode {
vec4 parameters;
uint type;
uint scalar;
uint msaa;
uint frameNumber;
};
struct SettingsLighting {
vec3 ambient;
uint indexSkybox;
uint maxShadows;
uint shadowSamples;
uint useLightmaps;
};
struct SettingsFog {
vec3 color;
float stepScale;
vec3 offset;
float densityScale;
vec2 range;
float densityThreshold;
float densityMultiplier;
float absorbtion;
float padding1;
float padding2;
float padding3;
};
struct SettingsBloom {
float exposure;
float gamma;
float threshold;
uint padding;
};
struct SettingsVxgi {
mat4 matrix;
float cascadePower;
float granularity;
float voxelizeScale;
float occlusionFalloff;
float traceStartOffsetFactor;
uint shadows;
uint padding2;
uint padding3;
};
struct SettingsRayTrace {
vec2 defaultRayBounds;
float alphaTestOffset;
float padding1;
uint samples;
uint paths;
uint frameAccumulationMinimum;
uint padding2;
};
struct Settings {
SettingsLengths lengths;
SettingsMode mode;
SettingsLighting lighting;
SettingsFog fog;
SettingsBloom bloom;
SettingsVxgi vxgi;
SettingsRayTrace rt;
};
struct Voxel {
uvec2 id;
vec3 position;
vec3 normal;
vec2 uv;
vec4 color;
};
struct VoxelInfo {
vec3 min;
vec3 max;
float mipmapLevels;
float radianceSize;
float radianceSizeRecip;
} voxelInfo;
// Raytrace stuff
struct Vertex {
vec3 position;
vec2 uv;
uint color;
vec2 st;
vec3 normal;
vec3 tangent;
uvec2 joints;
vec4 weights;
uint id;
};
struct Triangle {
Vertex point;
vec3 geomNormal;
uint instanceID;
};
struct RayTracePayload {
bool hit;
uint instanceID;
uint primitiveID;
vec2 attributes;
// Triangle triangle;
};

View File

@ -0,0 +1,189 @@
// GI
uint cascadeIndex( vec3 v ) {
float x = max3( abs( v ) );
for ( uint cascade = 0; cascade < CASCADES; ++cascade )
if ( x / cascadePower(cascade) < 1 - voxelInfo.radianceSizeRecip ) return cascade;
return CASCADES - 1;
}
vec4 voxelTrace( inout Ray ray, float aperture, float maxDistance ) {
ray.origin += ray.direction * voxelInfo.radianceSizeRecip * 2 * SQRT2;
#if VXGI_NDC
ray.origin = vec3( ubo.settings.vxgi.matrix * vec4( ray.origin, 1.0 ) );
ray.direction = vec3( ubo.settings.vxgi.matrix * vec4( ray.direction, 0.0 ) );
uint cascade = cascadeIndex(ray.origin);
#else
uint cascade = cascadeIndex( vec3( ubo.settings.vxgi.matrix * vec4( ray.origin, 1.0 ) ) );
#endif
const float granularityRecip = ubo.settings.vxgi.granularity; //2.0; // 0.25f * (CASCADES - cascade);
const float granularity = 1.0f / granularityRecip;
const float occlusionFalloff = ubo.settings.vxgi.occlusionFalloff; //128.0f;
const vec3 voxelBounds = voxelInfo.max - voxelInfo.min;
const vec3 voxelBoundsRecip = 1.0f / voxelBounds;
const float coneCoefficient = 2.0 * tan(aperture * 0.5);
const uint maxSteps = uint(voxelInfo.radianceSize * cascadePower(CASCADES-1) * granularityRecip);
// box
const vec2 rayBoxInfoA = rayBoxDst( voxelInfo.min * cascadePower(cascade), voxelInfo.max * cascadePower(cascade), ray );
const vec2 rayBoxInfoB = rayBoxDst( voxelInfo.min * cascadePower(CASCADES-1), voxelInfo.max * cascadePower(CASCADES-1), ray );
const float tStart = rayBoxInfoA.x;
const float tEnd = maxDistance > 0 ? min(maxDistance, rayBoxInfoB.y) : rayBoxInfoB.y;
const float tDelta = voxelInfo.radianceSizeRecip * granularityRecip;
// marcher
ray.distance = tStart + tDelta * ubo.settings.vxgi.traceStartOffsetFactor;
ray.position = vec3(0);
vec4 radiance = vec4(0);
vec3 uvw = vec3(0);
float coneDiameter = coneCoefficient * ray.distance;
float level = aperture > 0 ? log2( coneDiameter ) : 0;
vec4 color = vec4(0);
float occlusion = 0.0;
uint stepCounter = 0;
while ( color.a < 1.0 && occlusion < 1.0 && ray.distance < tEnd && stepCounter++ < maxSteps ) {
ray.distance += tDelta * cascadePower(cascade) * max(1, coneDiameter);
ray.position = ray.origin + ray.direction * ray.distance;
#if VXGI_NDC
uvw = ray.position;
#else
uvw = vec3( ubo.settings.vxgi.matrix * vec4( ray.position, 1.0 ) );
#endif
cascade = cascadeIndex( uvw );
uvw = (uvw / cascadePower(cascade)) * 0.5 + 0.5;
if ( cascade >= CASCADES || uvw.x < 0.0 || uvw.y < 0.0 || uvw.z < 0.0 || uvw.x >= 1.0 || uvw.y >= 1.0 || uvw.z >= 1.0 ) break;
coneDiameter = coneCoefficient * ray.distance;
level = aperture > 0 ? log2( coneDiameter ) : 0;
if ( level >= voxelInfo.mipmapLevels ) break;
radiance = textureLod(voxelRadiance[nonuniformEXT(cascade)], uvw.xzy, level);
color += (1.0 - color.a) * radiance;
occlusion += ((1.0f - occlusion) * radiance.a) / (1.0f + occlusionFalloff * coneDiameter);
}
return maxDistance > 0 ? color : vec4(color.rgb, occlusion);
// return vec4(color.rgb, occlusion);
}
vec4 voxelConeTrace( inout Ray ray, float aperture ) {
return voxelTrace( ray, aperture, 0 );
}
vec4 voxelTrace( inout Ray ray, float maxDistance ) {
return voxelTrace( ray, 0, maxDistance );
}
uint voxelShadowsCount = 0;
float voxelShadowFactor( const Light light, float def ) {
if ( ubo.settings.vxgi.shadows < ++voxelShadowsCount ) return 1.0;
const float SHADOW_APERTURE = 0.2;
const float DEPTH_BIAS = 0.0;
Ray ray;
ray.direction = normalize( light.position - surface.position.world );
ray.origin = surface.position.world + ray.direction * 0.5;
float z = distance( surface.position.world, light.position ) - DEPTH_BIAS;
return 1.0 - voxelTrace( ray, SHADOW_APERTURE, z ).a;
}
void indirectLighting() {
voxelInfo.radianceSize = textureSize( voxelRadiance[0], 0 ).x;
voxelInfo.radianceSizeRecip = 1.0 / voxelInfo.radianceSize;
voxelInfo.mipmapLevels = log2(voxelInfo.radianceSize) + 1;
#if VXGI_NDC
voxelInfo.min = vec3( -1 );
voxelInfo.max = vec3( 1 );
#else
const mat4 inverseOrtho = inverse( ubo.settings.vxgi.matrix );
voxelInfo.min = vec3( inverseOrtho * vec4( -1, -1, -1, 1 ) );
voxelInfo.max = vec3( inverseOrtho * vec4( 1, 1, 1, 1 ) );
#endif
const vec3 P = surface.position.world;
const vec3 N = surface.normal.world;
#if 1
const vec3 right = normalize(orthogonal(N));
const vec3 up = normalize(cross(right, N));
const uint CONES_COUNT = 6;
const vec3 CONES[] = {
N,
normalize(N + 0.0f * right + 0.866025f * up),
normalize(N + 0.823639f * right + 0.267617f * up),
normalize(N + 0.509037f * right + -0.7006629f * up),
normalize(N + -0.50937f * right + -0.7006629f * up),
normalize(N + -0.823639f * right + 0.267617f * up),
};
#else
const vec3 ortho = normalize(orthogonal(N));
const vec3 ortho2 = normalize(cross(ortho, N));
const vec3 corner = 0.5f * (ortho + ortho2);
const vec3 corner2 = 0.5f * (ortho - ortho2);
const uint CONES_COUNT = 9;
const vec3 CONES[] = {
N,
normalize(mix(N, ortho, 0.5)),
normalize(mix(N, -ortho, 0.5)),
normalize(mix(N, ortho2, 0.5)),
normalize(mix(N, -ortho2, 0.5)),
normalize(mix(N, corner, 0.5)),
normalize(mix(N, -corner, 0.5)),
normalize(mix(N, corner2, 0.5)),
normalize(mix(N, -corner2, 0.5)),
};
#endif
const float DIFFUSE_CONE_APERTURE = 2.0 * 0.57735f;
const float DIFFUSE_INDIRECT_FACTOR = 0; // 1.0f / float(CONES_COUNT) * 0.125f;
const float SPECULAR_CONE_APERTURE = clamp(tan(PI * 0.5f * surface.material.roughness), 0.0174533f, PI); // tan( R * PI * 0.5f * 0.1f );
const float SPECULAR_INDIRECT_FACTOR = (1.0 - surface.material.metallic); // * 0.25; // 1.0f;
vec4 indirectDiffuse = vec4(0);
vec4 indirectSpecular = vec4(0);
// outFragColor.rgb = voxelConeTrace( surface.ray, 0 ).rgb; return;
if ( DIFFUSE_INDIRECT_FACTOR > 0.0f ) {
float weight = PI * 0.25f;
for ( uint i = 0; i < CONES_COUNT; ++i ) {
Ray ray;
ray.direction = CONES[i].xyz;
ray.origin = P; // + ray.direction;
indirectDiffuse += voxelConeTrace( ray, DIFFUSE_CONE_APERTURE ) * weight;
weight = PI * 0.15f;
}
// indirectDiffuse.rgb *= surface.material.albedo.rgb;
surface.material.occlusion += 1.0 - clamp(indirectDiffuse.a, 0.0, 1.0);
// outFragColor.rgb = indirectDiffuse.rgb; return;
// outFragColor.rgb = vec3(surface.material.occlusion); return;
}
if ( SPECULAR_INDIRECT_FACTOR > 0.0f ) {
const vec3 R = reflect( normalize(P - surface.ray.origin), N );
Ray ray;
ray.direction = R;
ray.origin = P; // + ray.direction;
indirectSpecular = voxelConeTrace( ray, SPECULAR_CONE_APERTURE );
// indirectSpecular.rgb *= surface.material.albedo.rgb;
// outFragColor.rgb = indirectSpecular.rgb; return;
}
/*
if ( true ) {
gammaCorrect(indirectDiffuse.rgb, 1.0 / ubo.settings.bloom.gamma);
}
*/
indirectDiffuse *= DIFFUSE_INDIRECT_FACTOR;
indirectSpecular *= SPECULAR_INDIRECT_FACTOR;
surface.material.indirect = indirectDiffuse + indirectSpecular;
// outFragColor.rgb = surface.material.indirect.rgb; return;
// deferred sampling doesn't have a blended albedo buffer
// in place we'll just cone trace behind the window
if ( surface.material.albedo.a < 1.0 ) {
Ray ray;
ray.direction = surface.ray.direction;
ray.origin = surface.position.world + ray.direction;
vec4 radiance = voxelConeTrace( ray, surface.material.albedo.a * 0.5 );
surface.fragment.rgb += (1.0 - surface.material.albedo.a) * radiance.rgb;
}
}

View File

@ -0,0 +1,67 @@
#version 450
#pragma shader_stage(compute)
#define COMPUTE 1
#define TEXTURES 0
#define CUBEMAPS 0
#define BLOOM 1
layout (local_size_x = 8, local_size_y = 8, local_size_z = 8) in;
layout( push_constant ) uniform PushBlock {
uint eye;
uint mode;
} PushConstant;
layout (binding = 0) uniform UBO {
float scale;
float strength;
float threshold;
float sigma;
float gamma;
float exposure;
uint samples;
uint padding;
} ubo;
layout (binding = 1, rgba16f) uniform volatile coherent image2D imageColor;
layout (binding = 2, rgba16f) uniform volatile coherent image2D imageBloom;
layout (binding = 3, rgba16f) uniform volatile coherent image2D imagePingPong;
#include "../../common/macros.h"
#include "../../common/structs.h"
#include "../../common/functions.h"
void main() {
const uint mode = PushConstant.mode;
const ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
const ivec2 size = imageSize( imageColor );
if ( texel.x >= size.x || texel.y >= size.y ) return;
if ( mode == 0 ) { // fill bloom
vec3 result = imageLoad( imageColor, texel ).rgb;
float brightness = dot(result, vec3(0.2126, 0.7152, 0.0722));
if ( brightness < ubo.threshold ) result = vec3(0, 0, 0);
imageStore( imageBloom, texel, vec4( result, 1.0 ) );
} else if ( mode == 1 ) { // bloom horizontal
vec3 result = imageLoad( imageBloom, texel ).rgb * gauss( 0, ubo.sigma ) * ubo.strength;
for( int i = 1; i < ubo.samples; ++i ) {
result += imageLoad( imageBloom, texel + ivec2(i * ubo.scale, 0.0)).rgb * gauss( i * ubo.scale / ubo.samples, ubo.sigma ) * ubo.strength;
result += imageLoad( imageBloom, texel - ivec2(i * ubo.scale, 0.0)).rgb * gauss( i * ubo.scale / ubo.samples, ubo.sigma ) * ubo.strength;
}
// write to PingPong
imageStore( imagePingPong, texel, vec4( result, 1.0 ) );
} else if ( mode == 2 ) { // bloom vertical
vec3 result = imageLoad( imagePingPong, texel ).rgb * gauss( 0, ubo.sigma ) * ubo.strength;
for( int i = 1; i < ubo.samples; ++i ) {
result += imageLoad( imagePingPong, texel + ivec2(0.0, i * ubo.scale)).rgb * gauss( i * ubo.scale / ubo.samples, ubo.sigma ) * ubo.strength;
result += imageLoad( imagePingPong, texel - ivec2(0.0, i * ubo.scale)).rgb * gauss( i * ubo.scale / ubo.samples, ubo.sigma ) * ubo.strength;
}
// write to Bloom
imageStore( imageBloom, texel, vec4( result, 1.0 ) );
} else if ( mode == 3 ) { // combine
vec3 result = imageLoad( imageColor, texel ).rgb + imageLoad( imageBloom, texel ).rgb;
imageStore( imageColor, texel, vec4( result, 1.0 ) );
}
}

View File

@ -0,0 +1,13 @@
#version 450
#pragma shader_stage(compute)
#define RT 0
#define VXGI 0
#define MULTISAMPLING 0
#include "./comp.h"
void main() {
populateSurface();
directLighting();
postProcess();
}

View File

@ -0,0 +1,278 @@
#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 = 8, local_size_y = 8, local_size_z = 1) in;
#define COMPUTE 1
#define DEFERRED 1
#define DEFERRED_SAMPLING 1
#define PBR 1
#define LAMBERT 0
#if RT || BARYCENTRIC
#define BUFFER_REFERENCE 0
#define UINT64_ENABLED 0
#endif
#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 Materials {
Material materials[];
};
layout (std140, binding = 15) readonly buffer Textures {
Texture textures[];
};
layout (std140, binding = 16) readonly buffer Lights {
Light lights[];
};
layout (binding = 17) uniform sampler2D samplerTextures[TEXTURES];
layout (binding = 18) uniform samplerCube samplerCubemaps[CUBEMAPS];
layout (binding = 19) uniform sampler3D samplerNoise;
#if VXGI
layout (binding = 20) uniform usampler3D voxelId[CASCADES];
layout (binding = 21) uniform sampler3D voxelNormal[CASCADES];
layout (binding = 22) uniform sampler3D voxelRadiance[CASCADES];
#endif
#if RT
layout (binding = 23) uniform accelerationStructureEXT tlas;
#endif
#if BUFFER_REFERENCE
layout(buffer_reference, scalar) buffer Vertices { Vertex v[]; };
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 VUv { vec2 v[]; };
layout(buffer_reference, scalar) buffer VColor { uint v[]; };
layout(buffer_reference, scalar) buffer VSt { vec2 v[]; };
layout(buffer_reference, scalar) buffer VNormal { vec3 v[]; };
layout(buffer_reference, scalar) buffer VTangent { vec3 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 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 )
void postProcess() {
#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;
IMAGE_STORE( imageColor, outFragColor );
IMAGE_STORE( imageBright, outFragBright );
IMAGE_STORE( imageMotion, vec4(outFragMotion, 0, 0) );
}
void populateSurface() {
uvec2 renderSize = imageSize(imageColor);
if ( gl_GlobalInvocationID.x >= renderSize.x || gl_GlobalInvocationID.y >= renderSize.y || gl_GlobalInvocationID.z > PushConstant.pass ) return;
surface.fragment = vec4(0);
surface.pass = PushConstant.pass;
{
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;*/ ubo.eyes[surface.pass].eyePos.xyz;
const float 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
surface.motion = vec2(0);
if ( ID.x == 0 || ID.y == 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;
}
surface.fragment.a = 0.0;
return;
}
{
const uint triangleID = ID.x - 1;
const uint instanceID = 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.fragment = vec4(0);
surface.light = vec4(0);
surface.instance = instances[instanceID];
populateSurfaceMaterial();
#endif
}
{
vec4 pNDC = ubo.eyes[surface.pass].previous * surface.instance.previous * vec4(surface.position.world, 1);
vec4 cNDC = ubo.eyes[surface.pass].model * surface.instance.model * vec4(surface.position.world, 1);
pNDC /= pNDC.w;
cNDC /= cNDC.w;
surface.motion = cNDC.xy - pNDC.xy;
}
}
void directLighting() {
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;
}
#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
indirectLighting();
#endif
directLighting();
}
msaa.fragment += surface.fragment;
msaa.fragments[msaa.currentID] = surface.fragment;
}
surface.fragment = msaa.fragment / ubo.settings.mode.msaa;
}
#endif

View File

@ -0,0 +1,13 @@
#version 450
#pragma shader_stage(compute)
#define RT 0
#define VXGI 0
#define MULTISAMPLING 1
#include "./comp.h"
void main() {
resolveSurfaceFragment();
postProcess();
}

View File

@ -0,0 +1,13 @@
#version 460
#pragma shader_stage(compute)
#define RT 1
#define VXGI 0
#define MULTISAMPLING 0
#include "./comp.h"
void main() {
populateSurface();
directLighting();
postProcess();
}

View File

@ -0,0 +1,13 @@
#version 460
#pragma shader_stage(compute)
#define RT 1
#define VXGI 0
#define MULTISAMPLING 1
#include "./comp.h"
void main() {
populateSurface();
directLighting();
postProcess();
}

View File

@ -0,0 +1,14 @@
#version 460
#pragma shader_stage(compute)
#define RT 1
#define VXGI 1
#define MULTISAMPLING 0
#include "./comp.h"
void main() {
populateSurface();
indirectLighting();
directLighting();
postProcess();
}

View File

@ -0,0 +1,13 @@
#version 460
#pragma shader_stage(compute)
#define RT 1
#define VXGI 1
#define MULTISAMPLING 1
#include "./comp.h"
void main() {
populateSurface();
directLighting();
postProcess();
}

View File

@ -0,0 +1,14 @@
#version 450
#pragma shader_stage(compute)
#define RT 0
#define VXGI 1
#define MULTISAMPLING 0
#include "./comp.h"
void main() {
populateSurface();
indirectLighting();
directLighting();
postProcess();
}

View File

@ -0,0 +1,12 @@
#version 450
#pragma shader_stage(compute)
#define RT 0
#define VXGI 1
#define MULTISAMPLING 1
#include "./comp.h"
void main() {
resolveSurfaceFragment();
postProcess();
}

View File

@ -0,0 +1,30 @@
#version 450
#pragma shader_stage(compute)
//#extension GL_EXT_nonuniform_qualifier : enable
layout (constant_id = 0) const uint MIPS = 6;
layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
#define COMPUTE 1
#include "../../common/macros.h"
#include "../../common/structs.h"
layout( push_constant ) uniform PushBlock {
uint _;
uint pass;
} PushConstant;
layout (binding = 3) uniform sampler2D inImage[MIPS];
layout (binding = 4, r32f) uniform volatile coherent image2D outImage[MIPS];
void main() {
vec2 imageSize = imageSize(outImage[PushConstant.pass]);
uvec2 pos = gl_GlobalInvocationID.xy;
if ( pos.x >= imageSize.x || pos.y >= imageSize.y ) return;
float depth = texture(inImage[PushConstant.pass], (vec2(pos) + vec2(0.5)) / imageSize).x;
imageStore(outImage[PushConstant.pass], ivec2(pos), vec4(depth));
}

View File

@ -0,0 +1,35 @@
#version 450
#pragma shader_stage(fragment)
#extension GL_EXT_samplerless_texture_functions : require
layout (location = 0) in vec2 inUv;
layout (location = 1) flat in uint inPass;
layout (location = 0) out vec4 outColor;
layout (binding = 0) uniform sampler2D samplerColor;
layout (binding = 1) uniform UBO {
float curTime;
float gamma;
float exposure;
uint padding;
} ubo;
#define TONE_MAP 1
#define GAMMA_CORRECT 1
#define TEXTURES 1
#include "../../common/macros.h"
#include "../../common/structs.h"
#include "../../common/functions.h"
void main() {
outColor = texture( samplerColor, inUv );
#if TONE_MAP
toneMap(outColor, ubo.exposure);
#endif
#if GAMMA_CORRECT
gammaCorrect(outColor, ubo.gamma);
#endif
}

View File

@ -0,0 +1,392 @@
#version 450
#pragma shader_stage(fragment)
#extension GL_EXT_samplerless_texture_functions : require
layout (location = 0) in vec2 inUv;
layout (location = 1) flat in uint inPass;
layout (location = 0) out vec4 outColor;
layout (binding = 0) uniform sampler2D samplerColor;
layout (binding = 1) uniform UBO {
float curTime;
float gamma;
float exposure;
uint padding;
} ubo;
#define TONE_MAP 1
#define GAMMA_CORRECT 1
#define TEXTURES 1
#include "../../common/macros.h"
#include "../../common/structs.h"
#include "../../common/functions.h"
#define M_PI 3.1415926535897932384626433832795
const float u_imgx = 0;
const float u_imgy = 0;
const float u_imgw = 1;
const float u_imgh = 1;
const float u_img_gain = 2;
const float u_img_bias = 0;
const float u_beam_bias = 0.185;
const float u_beam_gain = 0.25;
const float u_corner = 0.05;
const float u_zoom = 1.0;
const float u_shape = 2;
const float u_round = -0.02;
const float u_grain = 0.4;
const float u_vpitch = 936.1;
const float u_hpitch = 1024.6;
const float u_top = 1;
const float u_bot = 1;
void main() {
const vec2 screenResolution = textureSize( samplerColor, 0 );
const float u_lines = screenResolution.y * 0.75;
vec2 uv_orig = (inUv.xy * 2.0 - 1.0);
vec2 uv_mod = uv_orig * pow(1.0-abs(uv_orig),vec2(u_round)) * (u_zoom + u_corner * pow( abs(uv_orig.yx), vec2(u_shape)) );
vec2 uv = uv_mod / 2.0 + 0.5;
if ( abs(uv_mod).x > 1.0 || abs(uv_mod.y) > 1.0 ) {
outColor = vec4(0.0, 0.0, 0.0, 1.0);
return;
}
float spacing = 1.0/u_lines;
uv+=spacing*0.5;
float line_top = ( ceil(uv.y*u_lines)) / u_lines;
float line_bot = line_top - spacing;
vec2 scale = vec2(u_imgw, u_imgh);
vec2 offset = vec2(u_imgx, u_imgy);
vec2 uv_top = (vec2(uv.x, line_top)+offset) * scale - (scale-1.0)*0.5 ;
vec2 uv_bot = (vec2(uv.x, line_bot)+offset) * scale - (scale-1.0)*0.5 ;
uv_top -= spacing * 0.5;
uv_bot -= spacing * 0.5;
vec4 sampled_top = texture(samplerColor, uv_top);
vec4 sampled_bot = texture(samplerColor, uv_bot);
vec3 color_top = sampled_top.xyz * u_img_gain + u_img_bias;
vec3 color_bot = sampled_bot.xyz * u_img_gain + u_img_bias;
float dist_top = pow(abs(uv.y - line_top), 1.0);
float dist_bot = pow(abs(uv.y - line_bot), 1.0);
vec3 beam_top = 1.0 - (dist_top / (spacing * (color_top * u_beam_gain + u_beam_bias)));
vec3 beam_bot = 1.0 - (dist_bot / (spacing * (color_bot * u_beam_gain + u_beam_bias)));
beam_top = clamp(beam_top, 0.0, 1.0) ;
beam_bot = clamp(beam_bot, 0.0, 1.0) ;
vec3 color = (color_top*beam_top)*u_top + (color_bot*beam_bot)*u_bot;
vec2 dot;
dot.y = floor(uv.y * u_vpitch) ;
dot.x = uv.x;
if (mod(dot.y, 2.0) > 0.5)
dot.x += (4.5/3.0) / u_hpitch;
dot.x = (floor(dot.x*u_hpitch)) ;
int fil = int(mod(dot.x, 3.0));
vec3 out_color = color * (1.0-u_grain);
vec3 passthru = vec3(
float(fil == 0),
float(fil == 1),
float(fil == 2)
) * (u_grain);
out_color += color * passthru;
outColor = vec4(out_color, (sampled_top.a + sampled_bot.a) * 0.5 );
#if TONE_MAP
toneMap(outColor, ubo.exposure);
#endif
#if GAMMA_CORRECT
gammaCorrect(outColor, ubo.gamma);
#endif
}
#if 0
float iTime = 0;
float noise(vec2 p) {
float s = (fract(sin(dot(p * sin( iTime * 0.5 ), vec2(12.9898,78.233)*2.0)) * 43758.5453)); // texture(iChannel1,vec2(1.,2.*cos(iTime))*iTime*8. + p*1.).x;
s *= s;
return s;
}
float onOff(float a, float b, float c) {
return step(c, sin(iTime + a*cos(iTime*b)));
}
float ramp(float y, float start, float end) {
float inside = step(start,y) - step(end,y);
float fact = (y-start)/(end-start)*inside;
return (1.-fact) * inside;
}
float stripes(vec2 uv) {
float noi = noise(uv*vec2(0.5,1.) + vec2(1.,3.));
return ramp(mod(uv.y*4. + iTime/2.+sin(iTime + sin(iTime*0.63)),1.),0.5,0.6)*noi;
}
vec4 getVideo(vec2 uv) {
vec2 look = uv;
float window = 1./(1.+20.*(look.y-mod(iTime/4.,1.))*(look.y-mod(iTime/4.,1.)));
look.x = look.x + sin(look.y*10. + iTime)/50.*onOff(4.,4.,.3)*(1.+cos(iTime*80.))*window;
float vShift = 0.4*onOff(2.,3.,.9)*(sin(iTime)*sin(iTime*20.) +
(0.5 + 0.1*sin(iTime*200.)*cos(iTime)));
look.y = mod(look.y + vShift, 1.);
return texture(samplerColor,look);
}
vec2 screenDistort(vec2 uv) {
uv -= vec2(.5,.5);
uv = uv*1.2*(1./1.2+2.*uv.x*uv.x*uv.y*uv.y);
uv += vec2(.5,.5);
return uv;
}
void main() {
vec2 uv = inUv.xy; // fragCoord.xy / iResolution.xy;
iTime = ubo.curTime;
uv = screenDistort(uv);
vec4 video = getVideo(uv);
float vigAmt = 3.+.3*sin(iTime + 5.*cos(iTime*5.));
float vignette = (1.-vigAmt*(uv.y-.5)*(uv.y-.5))*(1.-vigAmt*(uv.x-.5)*(uv.x-.5));
video.rgb += stripes(uv);
video.rgb += noise(uv*2.)/4.;
video.rgb *= vignette;
video.rgb *= (12.+mod(uv.y*30.+iTime,1.))/13.;
outColor = video;
#if TONE_MAP
toneMap(outColor, ubo.exposure);
#endif
#if GAMMA_CORRECT
gammaCorrect(outColor, ubo.gamma);
#endif
}
#endif
#if 0
vec2 curveRemapUV(vec2 uv, vec2 curvature) {
uv = uv * 2.0 - 1.0;
vec2 offset = abs(uv.yx) / vec2(curvature.x, curvature.y);
uv = uv + uv * offset * offset;
uv = uv * 0.5 + 0.5;
return uv;
}
vec4 scanLineIntensity(float uv, float resolution, float opacity) {
float intensity = sin(uv * resolution * PI * 2.0);
intensity = ((0.5 * intensity) + 0.5) * 0.9 + 0.1;
return vec4(vec3(pow(intensity, opacity)), 1.0);
}
vec4 vignetteIntensity(vec2 uv, vec2 resolution, float opacity, float roundness) {
float intensity = uv.x * uv.y * (1.0 - uv.x) * (1.0 - uv.y);
return vec4(vec3(clamp(pow((resolution.x / roundness) * intensity, opacity), 0.0, 1.0)), 1.0);
}
void main(void) {
const vec2 screenResolution = textureSize( samplerColor, 0 );
const vec2 scanLineOpacity = vec2(0.5);
const float brightness = 2;
const float vignetteOpacity = 0.5;
const float vignetteRoundness = 0.5;
const vec2 curvature = vec2(8);
const vec2 remappedUV = curveRemapUV(vec2(inUv.x, inUv.y), curvature);
vec4 baseColor = texture(samplerColor, remappedUV);
baseColor *= vignetteIntensity(remappedUV, screenResolution, vignetteOpacity, vignetteRoundness);
baseColor *= scanLineIntensity(remappedUV.x, screenResolution.y, scanLineOpacity.x);
baseColor *= scanLineIntensity(remappedUV.y, screenResolution.x, scanLineOpacity.y);
baseColor *= vec4(vec3(brightness), 1.0);
if (remappedUV.x < 0.0 || remappedUV.y < 0.0 || remappedUV.x > 1.0 || remappedUV.y > 1.0){
outColor = vec4(0.0, 0.0, 0.0, 1.0);
} else {
outColor = baseColor;
}
#if TONE_MAP
toneMap(outColor, ubo.exposure);
#endif
#if GAMMA_CORRECT
gammaCorrect(outColor, ubo.gamma);
#endif
}
#endif
#if 0
vec2 fragCoord = vec2(0,0);
vec2 iResolution = vec2(640,480);
// Emulated input resolution.
#if 0
// Fix resolution to set amount.
#define res (vec2(320.0/1.0,160.0/1.0))
#else
// Optimize for resize.
#define res (iResolution.xy/6.0)
#endif
// Hardness of scanline.
// -8.0 = soft
// -16.0 = medium
float hardScan=-8.0;
// Hardness of pixels in scanline.
// -2.0 = soft
// -4.0 = hard
float hardPix=-3.0;
// Display warp.
// 0.0 = none
// 1.0/8.0 = extreme
vec2 warp=vec2(1.0/32.0,1.0/24.0);
// Amount of shadow mask.
float maskDark=0.5;
float maskLight=1.5;
//------------------------------------------------------------------------
// sRGB to Linear.
// Assuing using sRGB typed textures this should not be needed.
float ToLinear1(float c){return(c<=0.04045)?c/12.92:pow((c+0.055)/1.055,2.4);}
vec3 ToLinear(vec3 c){return vec3(ToLinear1(c.r),ToLinear1(c.g),ToLinear1(c.b));}
// Linear to sRGB.
// Assuing using sRGB typed textures this should not be needed.
float ToSrgb1(float c){return(c<0.0031308?c*12.92:1.055*pow(c,0.41666)-0.055);}
vec3 ToSrgb(vec3 c){return vec3(ToSrgb1(c.r),ToSrgb1(c.g),ToSrgb1(c.b));}
// Nearest emulated sample given floating point position and texel offset.
// Also zero's off screen.
vec3 Fetch(vec2 pos,vec2 off){
pos=floor(pos*res+off)/res;
if(max(abs(pos.x-0.5),abs(pos.y-0.5))>0.5)return vec3(0.0,0.0,0.0);
return ToLinear(texture(samplerColor,pos.xy,-16.0).rgb);}
// Distance in emulated pixels to nearest texel.
vec2 Dist(vec2 pos){pos=pos*res;return -((pos-floor(pos))-vec2(0.5));}
// 1D Gaussian.
float Gaus(float pos,float scale){return exp2(scale*pos*pos);}
// 3-tap Gaussian filter along horz line.
vec3 Horz3(vec2 pos,float off){
vec3 b=Fetch(pos,vec2(-1.0,off));
vec3 c=Fetch(pos,vec2( 0.0,off));
vec3 d=Fetch(pos,vec2( 1.0,off));
float dst=Dist(pos).x;
// Convert distance to weight.
float scale=hardPix;
float wb=Gaus(dst-1.0,scale);
float wc=Gaus(dst+0.0,scale);
float wd=Gaus(dst+1.0,scale);
// Return filtered sample.
return (b*wb+c*wc+d*wd)/(wb+wc+wd);}
// 5-tap Gaussian filter along horz line.
vec3 Horz5(vec2 pos,float off){
vec3 a=Fetch(pos,vec2(-2.0,off));
vec3 b=Fetch(pos,vec2(-1.0,off));
vec3 c=Fetch(pos,vec2( 0.0,off));
vec3 d=Fetch(pos,vec2( 1.0,off));
vec3 e=Fetch(pos,vec2( 2.0,off));
float dst=Dist(pos).x;
// Convert distance to weight.
float scale=hardPix;
float wa=Gaus(dst-2.0,scale);
float wb=Gaus(dst-1.0,scale);
float wc=Gaus(dst+0.0,scale);
float wd=Gaus(dst+1.0,scale);
float we=Gaus(dst+2.0,scale);
// Return filtered sample.
return (a*wa+b*wb+c*wc+d*wd+e*we)/(wa+wb+wc+wd+we);}
// Return scanline weight.
float Scan(vec2 pos,float off){
float dst=Dist(pos).y;
return Gaus(dst+off,hardScan);}
// Allow nearest three lines to effect pixel.
vec3 Tri(vec2 pos){
vec3 a=Horz3(pos,-1.0);
vec3 b=Horz5(pos, 0.0);
vec3 c=Horz3(pos, 1.0);
float wa=Scan(pos,-1.0);
float wb=Scan(pos, 0.0);
float wc=Scan(pos, 1.0);
return a*wa+b*wb+c*wc;}
// Distortion of scanlines, and end of screen alpha.
vec2 Warp(vec2 pos){
pos=pos*2.0-1.0;
pos*=vec2(1.0+(pos.y*pos.y)*warp.x,1.0+(pos.x*pos.x)*warp.y);
return pos*0.5+0.5;}
// Shadow mask.
vec3 Mask(vec2 pos){
pos.x+=pos.y*3.0;
vec3 mask=vec3(maskDark,maskDark,maskDark);
pos.x=fract(pos.x/6.0);
if(pos.x<0.333)mask.r=maskLight;
else if(pos.x<0.666)mask.g=maskLight;
else mask.b=maskLight;
return mask;}
void main() {
iResolution = textureSize( samplerColor, 0 );
fragCoord = inUv * iResolution;
vec2 pos = Warp(fragCoord.xy / iResolution.xy);
hardScan = -12.0;
maskDark = maskLight = 1.0;
outColor.rgb = Tri(pos) * Mask(fragCoord.xy);
outColor.rgb = ToSrgb(outColor.rgb);
outColor.a = 1.0;
#if TONE_MAP
toneMap(outColor, ubo.exposure);
#endif
#if GAMMA_CORRECT
gammaCorrect(outColor, ubo.gamma);
#endif
}
#endif
#if 0
void main() {
const vec2 uv = 0.025 * sin( ubo.curTime ) * inUv.xy;
const float mdf = 0.5;
const float noise = (fract(sin(dot(uv, vec2(12.9898,78.233)*2.0)) * 43758.5453));
const vec4 sampled = texture( samplerColor, inUv );
outColor = sampled - noise * mdf;
toneMap(outColor, ubo.exposure);
gammaCorrect(outColor, ubo.gamma);
}
#endif

View File

@ -0,0 +1,16 @@
#version 450
#pragma shader_stage(vertex)
layout (location = 0) out vec2 outUv;
layout (location = 1) out flat uint outPass;
layout( push_constant ) uniform PushBlock {
uint pass;
uint draw;
} PushConstant;
void main() {
outUv = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
outPass = PushConstant.pass;
gl_Position = vec4(outUv * 2.0f + -1.0f, 0.0f, 1.0f);
}

View File

@ -0,0 +1,148 @@
#version 450
#pragma shader_stage(compute)
#extension GL_EXT_samplerless_texture_functions : require
#extension GL_EXT_nonuniform_qualifier : enable
layout (local_size_x = 8, local_size_y = 8, local_size_z = 8) in;
#define COMPUTE 1
#define VXGI 1
#define MAX_CUBEMAPS CUBEMAPS
#define GAMMA_CORRECT 1
#define PBR 1
layout (constant_id = 0) const uint TEXTURES = 512;
layout (constant_id = 1) const uint CUBEMAPS = 128;
layout (constant_id = 2) const uint CASCADES = 16;
#include "../../common/macros.h"
#include "../../common/structs.h"
layout (binding = 0) uniform UBO {
EyeMatrices eyes[2];
Settings settings;
} ubo;
layout (std140, binding = 1) readonly buffer DrawCommands {
DrawCommand drawCommands[];
};
layout (std140, binding = 2) readonly buffer Instances {
Instance instances[];
};
layout (std140, binding = 3) readonly buffer InstanceAddresseses {
InstanceAddresses instanceAddresses[];
};
layout (std140, binding = 4) readonly buffer Materials {
Material materials[];
};
layout (std140, binding = 5) readonly buffer Textures {
Texture textures[];
};
layout (std140, binding = 6) readonly buffer Lights {
Light lights[];
};
layout (binding = 7) uniform sampler2D samplerTextures[TEXTURES];
layout (binding = 8) uniform samplerCube samplerCubemaps[CUBEMAPS];
layout (binding = 9) uniform sampler3D samplerNoise;
layout (binding = 10, rg16ui) uniform volatile coherent uimage3D voxelId[CASCADES];
layout (binding = 11, rg16f) uniform volatile coherent image3D voxelNormal[CASCADES];
#if VXGI_HDR
layout (binding = 12, rgba32f) uniform volatile coherent image3D voxelRadiance[CASCADES];
#else
layout (binding = 12, rgba16f) uniform volatile coherent image3D voxelRadiance[CASCADES];
#endif
#include "../../common/functions.h"
#include "../../common/light.h"
#undef VXGI //
#include "../../common/shadows.h"
void main() {
const vec3 tUvw = gl_GlobalInvocationID.xzy;
for ( uint CASCADE = 0; CASCADE < CASCADES; ++CASCADE ) {
surface.normal.world = decodeNormals( vec2(imageLoad(voxelNormal[CASCADE], ivec3(tUvw) ).xy) );
surface.normal.eye = vec3( ubo.settings.vxgi.matrix * vec4( surface.normal.world, 0.0f ) );
surface.position.eye = (vec3(gl_GlobalInvocationID.xyz) / vec3(imageSize(voxelRadiance[CASCADE])) * 2.0f - 1.0f) * cascadePower(CASCADE);
surface.position.world = vec3( inverse(ubo.settings.vxgi.matrix) * vec4( surface.position.eye, 1.0f ) );
const uvec2 ID = uvec2(imageLoad(voxelId[CASCADE], ivec3(tUvw) ).xy);
const uint drawID = ID.x - 1;
const uint instanceID = ID.y - 1;
if ( ID.x == 0 || ID.y == 0 ) {
imageStore(voxelRadiance[CASCADE], ivec3(tUvw), vec4(0));
continue;
}
const DrawCommand drawCommand = drawCommands[drawID];
surface.instance = instances[instanceID];
const Material material = materials[surface.instance.materialID];
surface.material.albedo = material.colorBase;
surface.fragment = material.colorEmissive;
surface.material.albedo = imageLoad(voxelRadiance[CASCADE], ivec3(tUvw) );
surface.material.metallic = material.factorMetallic;
surface.material.roughness = material.factorRoughness;
surface.material.occlusion = material.factorOcclusion;
const vec3 ambient = ubo.settings.lighting.ambient.rgb * surface.material.occlusion;
if ( validTextureIndex( surface.instance.lightmapID ) ) {
surface.fragment.rgb += surface.material.albedo.rgb;
} else {
surface.fragment.rgb += surface.material.albedo.rgb * ambient;
// corrections
surface.position.eye = vec3( ubo.eyes[surface.pass].view * vec4( surface.position.world, 1 ) );
surface.normal.eye = vec3( ubo.eyes[surface.pass].view * vec4(surface.normal.world, 0) );
pbr();
/*
surface.material.roughness *= 4.0;
const vec3 F0 = mix(vec3(0.04), surface.material.albedo.rgb, surface.material.metallic);
const vec3 Lo = normalize( surface.position.world );
const float cosLo = max(0.0, dot(surface.normal.world, Lo));
for ( uint i = 0; i < ubo.settings.lengths.lights; ++i ) {
const Light light = lights[i];
if ( light.power <= LIGHT_POWER_CUTOFF ) continue;
if ( light.type >= 0 && validTextureIndex( surface.instance.lightmapID ) ) continue;
const vec3 Lp = light.position;
const vec3 Liu = light.position - surface.position.world;
const vec3 Li = normalize(Liu);
const float Ls = shadowFactor( light, 0.0 );
const float La = 1.0 / (1 + (PI * pow(length(Liu), 2.0)));
if ( light.power * La * Ls <= LIGHT_POWER_CUTOFF ) continue;
const float cosLi = max(0.0, dot(surface.normal.world, Li));
const vec3 Lr = light.color.rgb * light.power * La * Ls;
#if LAMBERT
const vec3 diffuse = surface.material.albedo.rgb;
const vec3 specular = vec3(0);
#elif PBR
const vec3 Lh = normalize(Li + Lo);
const float cosLh = max(0.0, dot(surface.normal.world, Lh));
const vec3 F = fresnelSchlick( F0, max( 0.0, dot(Lh, Lo) ) );
const float D = ndfGGX( cosLh, surface.material.roughness );
const float G = gaSchlickGGX(cosLi, cosLo, surface.material.roughness);
const vec3 diffuse = mix( vec3(1.0) - F, vec3(0.0), surface.material.metallic ) * surface.material.albedo.rgb;
const vec3 specular = (F * D * G) / max(EPSILON, 4.0 * cosLi * cosLo);
#endif
// lightmapped, compute only specular
surface.light.rgb += (diffuse + specular) * Lr * cosLi;
surface.light.a += light.power * La * Ls;
}
*/
}
surface.fragment.rgb += surface.light.rgb;
#if TONE_MAP
toneMap(surface.fragment.rgb, ubo.settings.bloom.exposure);
#endif
#if GAMMA_CORRECT
gammaCorrect(surface.fragment.rgb, 1.0 / ubo.settings.bloom.gamma);
#endif
imageStore(voxelRadiance[CASCADE], ivec3(tUvw), vec4(surface.fragment.rgb, surface.material.albedo.a));
}
}

View File

@ -0,0 +1,67 @@
#version 450
#pragma shader_stage(compute)
#extension GL_EXT_samplerless_texture_functions : require
layout (local_size_x = 8, local_size_y = 8, local_size_z = 8) in;
layout (constant_id = 0) const uint CASCADES = 16;
layout (constant_id = 1) const uint MIPS = 16;
layout( push_constant ) uniform PushBlock {
uint cascade;
uint mip;
} PushConstant;
layout (binding = 1, rg16f) uniform volatile coherent image3D voxelRadiance[CASCADES * MIPS];
const float gaussianWeights[] = {
//Top slice
1 / 64.0f,
1 / 32.0f,
1 / 64.0f,
1 / 32.0f,
1 / 16.0f,
1 / 32.0f,
1 / 64.0f,
1 / 32.0f,
1 / 64.0f,
//Center slice
1 / 32.0f,
1 / 16.0f,
1 / 32.0f,
1 / 16.0f,
1 / 4.0f,
1 / 16.0f,
1 / 32.0f,
1 / 16.0f,
1 / 32.0f,
//Bottom slice
1 / 64.0f,
1 / 32.0f,
1 / 64.0f,
1 / 32.0f,
1 / 16.0f,
1 / 32.0f,
1 / 64.0f,
1 / 32.0f,
1 / 64.0f,
};
void main() {
const ivec3 inUVW = ivec3(gl_GlobalInvocationID.xyz) * 2;
const ivec3 outUVW = ivec3(gl_GlobalInvocationID.xyz);
const uint CASCADE_IN = PushConstant.cascade * CASCADES + PushConstant.mip;
const uint CASCADE_OUT = PushConstant.cascade * CASCADES + (PushConstant.mip + 1);
vec4 color = vec4(0);
for ( int z = -1; z <= 1; ++z ) {
for ( int y = -1; y <= 1; ++y ) {
for ( int x = -1; x <= 1; ++x ) {
color += imageLoad( voxelRadiance[CASCADE_IN], inUVW + ivec3(x,y,z) ) * gaussianWeights[x + 1 + (y + 1) * 3 + (z + 1) * 9];
}
}
}
imageStore(voxelRadiance[CASCADE_OUT], ivec3(outUVW), vec4(color));
}

View File

@ -0,0 +1,5 @@
#version 450
#pragma shader_stage(fragment)
#define RT 0
#include "./frag.h"

View File

@ -0,0 +1,204 @@
//#extension GL_EXT_nonuniform_qualifier : enable
#if RT
#extension GL_EXT_ray_tracing : enable
#extension GL_EXT_ray_query : enable
#endif
layout (constant_id = 0) const uint TEXTURES = 512;
layout (constant_id = 1) const uint CUBEMAPS = 128;
layout (constant_id = 2) const uint LAYERS = 32;
layout (binding = 5) uniform sampler2D samplerTextures[TEXTURES];
layout (binding = 6) uniform samplerCube samplerCubemaps[CUBEMAPS];
#define SHADOW_SAMPLES 16
#define FRAGMENT 1
#define BAKING 1
#define PBR 1
#define MAX_LIGHTS min(ubo.lights, lights.length())
#define MAX_SHADOWS MAX_LIGHTS
#define VIEW_MATRIX camera.viewport[0].view
#include "../../common/macros.h"
#include "../../common/structs.h"
layout (binding = 7) uniform Camera {
Viewport viewport[6];
} camera;
layout (binding = 8) uniform UBO {
uint lights;
uint currentID;
uint padding1;
uint padding2;
} ubo;
layout (std140, binding = 9) readonly buffer DrawCommands {
DrawCommand drawCommands[];
};
layout (std140, binding = 10) readonly buffer Instances {
Instance instances[];
};
layout (std140, binding = 11) readonly buffer InstanceAddresseses {
InstanceAddresses instanceAddresses[];
};
layout (std140, binding = 12) readonly buffer Materials {
Material materials[];
};
layout (std140, binding = 13) readonly buffer Textures {
Texture textures[];
};
layout (std140, binding = 14) readonly buffer Lights {
Light lights[];
};
layout (binding = 15, rgba8) uniform volatile coherent image3D outAlbedos;
#if RT
layout (binding = 16) uniform accelerationStructureEXT tlas;
#endif
#include "../../common/functions.h"
#if RT
float shadowFactor( const Light light, float def ) {
Ray ray;
ray.origin = surface.position.world;
ray.direction = light.position - ray.origin;
float tMin = 0.001;
float tMax = length(ray.direction) + tMin;
ray.direction = normalize(ray.direction);
uint rayFlags = gl_RayFlagsOpaqueEXT | gl_RayFlagsTerminateOnFirstHitEXT | gl_RayFlagsSkipClosestHitShaderEXT;
uint cullMask = 0xFF;
rayQueryEXT rayQuery;
rayQueryInitializeEXT(rayQuery, tlas, rayFlags, cullMask, ray.origin, tMin, ray.direction, tMax);
while(rayQueryProceedEXT(rayQuery)) {}
return rayQueryGetIntersectionTypeEXT(rayQuery, true) == gl_RayQueryCommittedIntersectionNoneEXT ? 1.0 : 0.0;
}
#else
#include "../../common/shadows.h"
#endif
#include "../../common/light.h"
layout (location = 0) flat in uvec4 inId;
layout (location = 1) flat in vec4 inPOS0;
layout (location = 2) in vec4 inPOS1;
layout (location = 3) in vec3 inPosition;
layout (location = 4) in vec2 inUv;
layout (location = 5) in vec4 inColor;
layout (location = 6) in vec2 inSt;
layout (location = 7) in vec3 inNormal;
layout (location = 8) in vec3 inTangent;
layout (location = 0) out vec4 outAlbedo;
void main() {
const uint triangleID = uint(inId.x); // gl_PrimitiveID
const uint drawID = uint(inId.y);
const uint instanceID = uint(inId.z);
if ( instanceID != ubo.currentID ) discard;
surface.uv.xy = wrap(inUv.xy);
surface.uv.z = mipLevel(dFdx(inUv), dFdy(inUv));
surface.position.world = inPosition;
surface.normal.world = inNormal;
const DrawCommand drawCommand = drawCommands[drawID];
const Instance instance = instances[instanceID];
const Material material = materials[instance.materialID];
const uint mapID = instance.auxID;
vec4 A = material.colorBase;
surface.material.metallic = material.factorMetallic;
surface.material.roughness = material.factorRoughness;
surface.material.occlusion = 1.0f - material.factorOcclusion;
#if 0
vec3 N = inNormal;
vec3 T = inTangent;
T = normalize(T - dot(T, N) * N);
vec3 B = cross(T, N);
mat3 TBN = mat3(T, B, N);
// mat3 TBN = mat3(N, B, T);
if ( T != vec3(0) && validTextureIndex( material.indexNormal ) ) {
surface.normal.world = TBN * normalize( sampleTexture( material.indexNormal ).xyz * 2.0 - 1.0 );
} else {
surface.normal.world = N;
}
#endif
surface.light = material.colorEmissive;
surface.material.albedo = vec4(1);
{
surface.normal.eye = surface.normal.eye;
surface.position.eye = surface.position.eye;
// pbr();
const vec3 F0 = mix(vec3(0.04), surface.material.albedo.rgb, surface.material.metallic);
for ( uint i = 0; i < min(ubo.lights, lights.length()); ++i ) {
const Light light = lights[i];
if ( light.type <= 0 ) continue;
const mat4 mat = light.view; // inverse(light.view);
const vec3 position = surface.position.world;
// const vec3 position = vec3( mat * vec4(surface.position.world, 1.0) );
const vec3 normal = surface.normal.world;
// const vec3 normal = vec3( mat * vec4(surface.normal.world, 0.0) );
if ( light.power <= LIGHT_POWER_CUTOFF ) continue;
const vec3 Lp = light.position;
const vec3 Liu = light.position - surface.position.world;
const float La = 1.0 / (1 + PI * pow(length(Liu), 2.0));
const float Ls = shadowFactor( light, 0.0 );
if ( light.power * La * Ls <= LIGHT_POWER_CUTOFF ) continue;
const vec3 Lo = normalize( -position );
const float cosLo = max(0.0, abs(dot(normal, Lo)));
const vec3 Li = normalize(Liu);
const vec3 Lr = light.color.rgb * light.power * La * Ls;
// const float cosLi = max(0.0, dot(normal, Li));
const float cosLi = abs(dot(normal, Li));
#if LAMBERT
const vec3 diffuse = surface.material.albedo.rgb;
const vec3 specular = vec3(0);
#elif PBR
const vec3 Lh = normalize(Li + Lo);
// const float cosLh = max(0.0, dot(normal, Lh));
const float cosLh = abs(dot(normal, Lh));
const vec3 F = fresnelSchlick( F0, max( 0.0, dot(Lh, Lo) ) );
const float D = 1; // ndfGGX( cosLh, surface.material.roughness );
const float G = gaSchlickGGX(cosLi, cosLo, surface.material.roughness);
const vec3 diffuse = mix( vec3(1.0) - F, vec3(0.0), surface.material.metallic ) * surface.material.albedo.rgb;
const vec3 specular = (F * D * G) / max(EPSILON, 4.0 * cosLi * cosLo);
#endif
surface.light.rgb += (diffuse + specular) * Lr * cosLi;
surface.light.a += light.power * La * Ls;
}
}
#define EXPOSURE 0
#define GAMMA 0
// surface.light.rgb = vec3(1.0) - exp(-surface.light.rgb * EXPOSURE);
// surface.light.rgb = pow(surface.light.rgb, vec3(1.0 / GAMMA));
outAlbedo = vec4(surface.light.rgb, 1);
{
const vec2 st = inSt.xy * imageSize(outAlbedos).xy;
const ivec3 uvw = ivec3(int(st.x), int(st.y), int(mapID));
imageStore(outAlbedos, uvw, vec4(surface.light.rgb, 1) );
}
}

View File

@ -0,0 +1,5 @@
#version 460
#pragma shader_stage(fragment)
#define RT 1
#include "./frag.h"

View File

@ -0,0 +1,8 @@
#version 450
#pragma shader_stage(vertex)
#define INSTANCED 1
#define SKINNED 0
#define BAKING 1
#include "../base/vert.h"

View File

@ -0,0 +1,126 @@
#version 450
#pragma shader_stage(fragment)
//#extension GL_EXT_nonuniform_qualifier : enable
#define FRAGMENT 1
#define CAN_DISCARD 1
#define MAX_TEXTURES textures.length()
layout (constant_id = 0) const uint TEXTURES = 1;
#include "../../common/macros.h"
#include "../../common/structs.h"
#if BARYCENTRIC && !BARYCENTRIC_CALCULATE
#define BARYCENTRIC_STABILIZE 1
// #define BARY_COORD gl_BaryCoordEXT
// #extension GL_EXT_fragment_shader_barycentric : enable
#define BARY_COORD gl_BaryCoordSmoothAMD
#extension GL_AMD_shader_explicit_vertex_parameter : enable
#endif
layout (binding = 5) uniform sampler2D samplerTextures[TEXTURES];
layout (std140, binding = 6) readonly buffer DrawCommands {
DrawCommand drawCommands[];
};
layout (std140, binding = 7) readonly buffer Instances {
Instance instances[];
};
layout (std140, binding = 8) readonly buffer InstanceAddresseses {
InstanceAddresses instanceAddresses[];
};
layout (std140, binding = 9) readonly buffer Materials {
Material materials[];
};
layout (std140, binding = 10) readonly buffer Textures {
Texture textures[];
};
layout (std140, binding = 11) readonly buffer Lights {
Light lights[];
};
#include "../../common/functions.h"
layout (location = 0) flat in uvec4 inId;
layout (location = 1) flat in vec4 inPOS0;
#if BARYCENTRIC_STABILIZE
layout (location = 2) __explicitInterpAMD in vec4 inPOS1;
#else
layout (location = 2) in vec4 inPOS1;
#endif
layout (location = 3) in vec3 inPosition;
layout (location = 4) in vec2 inUv;
layout (location = 5) in vec4 inColor;
layout (location = 6) in vec2 inSt;
layout (location = 7) in vec3 inNormal;
layout (location = 8) in vec3 inTangent;
layout (location = 0) out uvec2 outId;
#if BARYCENTRIC
layout (location = 1) out vec2 outBary;
#else
layout (location = 1) out vec4 outUv;
layout (location = 2) out vec4 outNormal;
#endif
void main() {
const uint triangleID = gl_PrimitiveID; // uint(inId.x);
const uint drawID = uint(inId.y);
const uint instanceID = uint(inId.z);
#if CAN_DISCARD
const DrawCommand drawCommand = drawCommands[drawID];
const Instance instance = instances[instanceID];
const Material material = materials[instance.materialID];
surface.uv.xy = wrap(inUv.xy);
surface.uv.z = mipLevel(dFdx(inUv), dFdy(inUv));
surface.st.xy = wrap(inSt.xy);
surface.st.z = mipLevel(dFdx(inSt), dFdy(inSt));
vec4 A = inColor * material.colorBase;
// sample albedo
if ( validTextureIndex( material.indexAlbedo ) ) {
A = sampleTexture( material.indexAlbedo );
}
// alpha mode OPAQUE
if ( material.modeAlpha == 0 ) {
A.a = 1;
// alpha mode BLEND
} else if ( material.modeAlpha == 1 ) {
// alpha mode MASK
} else if ( material.modeAlpha == 2 ) {
if ( A.a < abs(material.factorAlphaCutoff) ) discard;
A.a = 1;
}
if ( A.a < 0.0001 ) discard;
#if !BARYCENTRIC
outUv = vec4(surface.uv, surface.st);
outNormal = vec4( encodeNormals(inNormal), encodeNormals(inTangent) );
#endif
#endif
outId = uvec2(triangleID + 1, instanceID + 1);
#if BARYCENTRIC && !BARYCENTRIC_CALCULATE
vec3 bary = vec3(gl_BaryCoordSmoothAMD.xy, 1 - gl_BaryCoordSmoothAMD.x - gl_BaryCoordSmoothAMD.y);
bary = bary.yzx;
#if BARYCENTRIC_STABILIZE
vec4 v0 = interpolateAtVertexAMD(inPOS1, 0);
vec4 v1 = interpolateAtVertexAMD(inPOS1, 1);
vec4 v2 = interpolateAtVertexAMD(inPOS1, 2);
if (v0 == inPOS0) outBary = encodeBarycentrics(bary.yzx);
else if (v1 == inPOS0) outBary = encodeBarycentrics(bary.zxy);
else if (v2 == inPOS0) outBary = encodeBarycentrics(bary.xyz);
#else
outBary = encodeBarycentrics(bary.xyz);
#endif
#endif
}

View File

@ -0,0 +1,6 @@
#version 450
#pragma shader_stage(vertex)
#define INSTANCED 1
#define SKINNED 0
#include "./vert.h"

View File

@ -0,0 +1,6 @@
#version 450
#pragma shader_stage(vertex)
#define INSTANCED 1
#define SKINNED 1
#include "./vert.h"

View File

@ -0,0 +1,6 @@
#version 450
#pragma shader_stage(vertex)
#define INSTANCED 0
#define SKINNED 1
#include "./vert.h"

Some files were not shown because too many files have changed in this diff Show More