Commit for 2022.07.31 22-17-30.7z
This commit is contained in:
parent
212347ee9c
commit
cfdb877ed3
@ -5,13 +5,13 @@
|
||||
"matrix": { "reverseInfinite": true },
|
||||
"meshes": { "interleaved": false },
|
||||
"lights": { "enabled": true,
|
||||
"useLightmaps": false,
|
||||
"max": 48,
|
||||
"useLightmaps": true,
|
||||
"max": 16,
|
||||
"shadows": {
|
||||
"enabled": true,
|
||||
"update": 4,
|
||||
"max": 24,
|
||||
"samples": 16
|
||||
"update": 2,
|
||||
"max": 4,
|
||||
"samples": 1
|
||||
},
|
||||
"bloom": {
|
||||
"scale": 1.0,
|
||||
@ -30,6 +30,7 @@
|
||||
},
|
||||
"vxgi": {
|
||||
"limiter": 0.5,
|
||||
// "limiter": 0.125,
|
||||
"size": 128,
|
||||
"dispatch": 8,
|
||||
"cascades": 3,
|
||||
@ -37,15 +38,16 @@
|
||||
"granularity": 12,
|
||||
"voxelizeScale": 1,
|
||||
"occlusionFalloff": 2,
|
||||
"traceStartOffsetFactor": 2.5,
|
||||
"traceStartOffsetFactor": 1,
|
||||
"shadows": 0,
|
||||
"extents": {
|
||||
"min": [ -8, -4, -8 ],
|
||||
"max": [ 8, 4, 8 ]
|
||||
"min": [ -16, -4, -16 ],
|
||||
"max": [ 16, 4, 16 ]
|
||||
}
|
||||
},
|
||||
"rt": {
|
||||
// "size": [ 1280, 720 ],
|
||||
"full": false,
|
||||
"filter": "nearest",
|
||||
"defaultRayBounds": [ 0.5, 256.0 ],
|
||||
"alphaTestOffset": 0.01,
|
||||
@ -90,10 +92,7 @@
|
||||
},
|
||||
"framebuffer": {
|
||||
"msaa": 1,
|
||||
// "size": 0.25
|
||||
// "size": 0.50
|
||||
// "size": 0.75
|
||||
"size": 1
|
||||
"size": 1 // 0.5
|
||||
// "size": [ 640, 480, "NEAREST" ]
|
||||
// "size": [ 1280, 720 ]
|
||||
// "size": [ 960, 540 ]
|
||||
@ -101,7 +100,7 @@
|
||||
},
|
||||
"gpu": 1,
|
||||
"experimental": {
|
||||
"batch queue submissions": true,
|
||||
"batch queue submissions": false,
|
||||
"rebuild on tick begin": false,
|
||||
"dedicated thread": false
|
||||
},
|
||||
@ -110,12 +109,12 @@
|
||||
"deferred": true,
|
||||
"vsync": false,
|
||||
"hdr": false,
|
||||
"vxgi": false,
|
||||
"vxgi": true,
|
||||
"culling": true,
|
||||
"bloom": true,
|
||||
"rt": false,
|
||||
"rt": true,
|
||||
"postProcess": false,
|
||||
"fsr": false
|
||||
"fsr": true
|
||||
},
|
||||
"formats": {
|
||||
"depth": "D32_SFLOAT",
|
||||
@ -137,6 +136,8 @@
|
||||
"fragmentStoresAndAtomics",
|
||||
"geometryShader",
|
||||
"multiViewport",
|
||||
"shaderInt16",
|
||||
"shaderFloat16",
|
||||
"shaderInt64",
|
||||
"shaderFloat64",
|
||||
"shaderSubgroupClock",
|
||||
@ -174,6 +175,7 @@
|
||||
"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"
|
||||
]
|
||||
}
|
||||
@ -217,7 +219,10 @@
|
||||
"enabled": false
|
||||
},
|
||||
"fsr": {
|
||||
"enabled": true
|
||||
"enabled": true,
|
||||
"sharpness": 1,
|
||||
"jitter scale": 0.0125,
|
||||
"preset": "ultra" // native (1x), quality (1.5x), balanced (1.7x), performance (2.0x), ultra (3.0x)
|
||||
},
|
||||
"reactphysics": {
|
||||
"timescale": 0.01666666666,
|
||||
@ -321,8 +326,8 @@
|
||||
"mode" : "windowed", // fullscreen, borderless, windowed
|
||||
"icon" : "./data/textures/icon.png",
|
||||
// "size" : [ 1920, 1080 ],
|
||||
// "size" : [ 1280, 720 ],
|
||||
"size" : [ 960, 540 ],
|
||||
"size" : [ 1280, 720 ],
|
||||
// "size" : [ 960, 540 ],
|
||||
// "size" : [ 640, 480 ],
|
||||
// "size" : [ 256, 224 ],
|
||||
"title" : "Grimgram",
|
||||
|
||||
@ -31,7 +31,7 @@
|
||||
"radius": [0.1, 0],
|
||||
"resolution": 512,
|
||||
"shadows": true,
|
||||
"static": false
|
||||
"dynamic": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -38,7 +38,7 @@
|
||||
},
|
||||
"baking": {
|
||||
"enabled": true,
|
||||
"resolution": 2048,
|
||||
"resolution": 4096,
|
||||
"shadows": 1024,
|
||||
"layers": 1,
|
||||
"trigger": { "mode": "rendered", "quit": true },
|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
"radius": [0.001, 0],
|
||||
"resolution": 512,
|
||||
"shadows": false,
|
||||
"static": false
|
||||
"dynamic": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -79,7 +79,7 @@ ent:bind( "tick", function(self)
|
||||
local center = flattenedTransform.position
|
||||
local direction = flattenedTransform.forward * 4
|
||||
|
||||
local offset = 0.05
|
||||
local offset = 0.25
|
||||
local _, depth = physicsState:rayCast( center, direction )
|
||||
if depth >= 0.5 then
|
||||
depth = 0.5
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
{
|
||||
"import": "/model.json",
|
||||
"assets": [
|
||||
// { "filename": "./models/sm64_bbb.glb" }
|
||||
{ "filename": "./models/sm64_bbb/graph.json" }
|
||||
{ "filename": "./models/sm64_bbb.glb" }
|
||||
// { "filename": "./models/sm64_bbb/graph.json" }
|
||||
],
|
||||
"metadata": {
|
||||
"graph": {
|
||||
@ -20,8 +20,8 @@
|
||||
"tags": {
|
||||
"/^worldspawn/": {
|
||||
"physics": { "type": "mesh", "static": true },
|
||||
"grid": { "size": [3,1,3], "epsilon": 1.0, "cleanup": true, "print": true },
|
||||
// "optimize mesh": { "simplify": 0 },
|
||||
// "grid": { "size": [3,1,3], "epsilon": 1.0, "cleanup": true, "print": true },
|
||||
"optimize mesh": { "simplify": 0 },
|
||||
"unwrap mesh": true
|
||||
},
|
||||
"info_player_spawn": { "action": "attach", "filename": "./player.json" },
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
"metadata": {
|
||||
"graph": {
|
||||
// "renderer": { "separate": true },
|
||||
"baking": { "enabled": false },
|
||||
"baking": { "enabled": true },
|
||||
"tags": {
|
||||
// exact matches
|
||||
"worldspawn": {
|
||||
|
||||
@ -13,8 +13,8 @@
|
||||
// "ambient": [ 0.8, 0.8, 0.8 ],
|
||||
// "ambient": [ 0.1, 0.1, 0.2 ],
|
||||
|
||||
"exposure": 0.125,
|
||||
"gamma": 2.2,
|
||||
"exposure": 1, // 0.125,
|
||||
"gamma": 2.2, // 2.2,
|
||||
|
||||
"bloom": {
|
||||
"threshold": 1.2,
|
||||
|
||||
@ -6,6 +6,9 @@
|
||||
],
|
||||
"metadata": {
|
||||
"graph": {
|
||||
"lights": {
|
||||
"lightmap": false
|
||||
},
|
||||
"assets": [
|
||||
"./audio/soundscape/sh2_ambience.ogg"
|
||||
],
|
||||
|
||||
@ -3,6 +3,23 @@ float random(vec3 seed, int i){ return fract(sin(dot(vec4(seed,i), vec4(12.9898,
|
||||
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)));
|
||||
}
|
||||
//
|
||||
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;
|
||||
@ -27,7 +44,6 @@ float rnd(inout uint prev) { return (float(lcg(prev)) / float(0x01000000)); }
|
||||
uint prngSeed;
|
||||
float rnd() { return rnd(prngSeed); }
|
||||
//
|
||||
float shadowFactor( const Light light, float def );
|
||||
float ndfGGX(float cosLh, float roughness) {
|
||||
const float alpha = roughness * roughness;
|
||||
const float alphaSq = alpha * alpha;
|
||||
@ -119,7 +135,7 @@ bool validCubemapIndex( int textureIndex ) {
|
||||
return 0 <= textureIndex && textureIndex < MAX_CUBEMAPS;
|
||||
}
|
||||
#endif
|
||||
#if !BLOOM && (DEFERRED || FRAGMENT || COMPUTE)
|
||||
#if !BLOOM && (DEFERRED || FRAGMENT || COMPUTE || RT)
|
||||
bool validTextureIndex( uint id ) {
|
||||
return 0 <= id && id < MAX_TEXTURES;
|
||||
}
|
||||
@ -160,7 +176,7 @@ float cascadePower( uint x ) {
|
||||
// return max( 1, x * ubo.settings.vxgi.cascadePower );
|
||||
}
|
||||
#endif
|
||||
#if !COMPUTE
|
||||
#if FRAGMENT
|
||||
void whitenoise(inout vec3 color, const vec4 parameters) {
|
||||
const float flicker = parameters.x;
|
||||
const float pieces = parameters.y;
|
||||
@ -171,13 +187,6 @@ void whitenoise(inout vec3 color, const vec4 parameters) {
|
||||
const float whiteNoise = rand2( floor(gl_FragCoord.xy / pieces) + mod(time, freq) );
|
||||
color = mix( color, vec3(whiteNoise), blend );
|
||||
}
|
||||
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)));
|
||||
}
|
||||
vec4 resolve( subpassInputMS t, const uint samples ) {
|
||||
vec4 resolved = vec4(0);
|
||||
for ( int i = 0; i < samples; ++i ) resolved += subpassLoad(t, i);
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
float shadowFactor( const Light light, float def );
|
||||
|
||||
#if PBR
|
||||
#include "../common/pbr.h"
|
||||
#endif
|
||||
|
||||
@ -1,20 +1,24 @@
|
||||
// PBR
|
||||
void pbr() {
|
||||
if ( surface.material.lightmapped ) return;
|
||||
// if ( surface.material.lightmapped ) return;
|
||||
|
||||
const float Rs = 4.0; // specular lighting looks gross without this
|
||||
const vec3 F0 = mix(vec3(0.04), surface.material.albedo.rgb, surface.material.metallic);
|
||||
const vec3 Lo = normalize( -surface.position.eye );
|
||||
const float cosLo = max(0.0, dot(surface.normal.eye, Lo));
|
||||
|
||||
|
||||
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 vec3 Li = normalize(Liu);
|
||||
const bool reverseZ = light.projection[2][2] < 0.00001;
|
||||
const float Ls = shadowFactor( light, 0.0 );
|
||||
const float La = 1.0 / (PI * pow(length(Liu), 2.0));
|
||||
const float Ls = ( shadows++ < ubo.settings.lighting.maxShadows ) ? shadowFactor( light, 0.0 ) : 1;
|
||||
// const float La = 1.0 / (PI * pow(length(Liu), 2.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.eye, Li));
|
||||
|
||||
@ -102,7 +102,33 @@ float omniShadowMap( const Light light, float def ) {
|
||||
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) - 0.0001;
|
||||
|
||||
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) )
|
||||
|
||||
@ -200,9 +200,9 @@ struct SettingsMode {
|
||||
};
|
||||
struct SettingsLighting {
|
||||
vec3 ambient;
|
||||
float padding1;
|
||||
|
||||
uint indexSkybox;
|
||||
|
||||
uint maxShadows;
|
||||
uint shadowSamples;
|
||||
uint useLightmaps;
|
||||
};
|
||||
|
||||
@ -165,7 +165,16 @@ void indirectLighting() {
|
||||
// outFragColor.rgb = indirectSpecular.rgb; return;
|
||||
}
|
||||
|
||||
surface.material.indirect = indirectDiffuse * DIFFUSE_INDIRECT_FACTOR + indirectSpecular * SPECULAR_INDIRECT_FACTOR;
|
||||
/*
|
||||
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
|
||||
|
||||
@ -2,7 +2,8 @@
|
||||
#extension GL_EXT_nonuniform_qualifier : enable
|
||||
|
||||
#if RT
|
||||
#extension GL_EXT_ray_query : require
|
||||
#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;
|
||||
@ -129,18 +130,8 @@ void postProcess() {
|
||||
float brightness = dot(surface.fragment.rgb, vec3(0.2126, 0.7152, 0.0722));
|
||||
vec4 outFragBright = brightness > ubo.settings.bloom.threshold ? vec4(surface.fragment.rgb, 1.0) : vec4(0, 0, 0, 1);
|
||||
vec2 outFragMotion = surface.motion;
|
||||
|
||||
#if FOG
|
||||
fog( surface.ray, surface.fragment.rgb, surface.fragment.a );
|
||||
#endif
|
||||
#if TONE_MAP
|
||||
surface.fragment.rgb = vec3(1.0) - exp(-surface.fragment.rgb * ubo.settings.bloom.exposure);
|
||||
#endif
|
||||
#if GAMMA_CORRECT
|
||||
surface.fragment.rgb = pow(surface.fragment.rgb, vec3(1.0 / ubo.settings.bloom.gamma));
|
||||
#endif
|
||||
#if WHITENOISE
|
||||
if ( enabled(ubo.settings.mode.type, 1) ) whitenoise(surface.fragment.rgb, ubo.settings.mode.parameters);
|
||||
#endif
|
||||
vec4 outFragColor = vec4(surface.fragment.rgb, 1.0);
|
||||
|
||||
@ -151,7 +142,7 @@ void postProcess() {
|
||||
|
||||
void populateSurface() {
|
||||
uvec2 renderSize = imageSize(imageColor);
|
||||
if ( gl_GlobalInvocationID.x >= renderSize.x|| gl_GlobalInvocationID.y >= renderSize.y ) return;
|
||||
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;
|
||||
@ -231,6 +222,12 @@ void populateSurface() {
|
||||
}
|
||||
|
||||
void directLighting() {
|
||||
#if RT && COMPUTE && !VXGI
|
||||
{
|
||||
|
||||
}
|
||||
#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
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#version 450
|
||||
#version 460
|
||||
#pragma shader_stage(compute)
|
||||
|
||||
#define RT 1
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#version 450
|
||||
#version 460
|
||||
#pragma shader_stage(compute)
|
||||
|
||||
#define RT 1
|
||||
|
||||
14
bin/data/shaders/display/deferred/comp/rt.vxgi.comp.glsl
Normal file
14
bin/data/shaders/display/deferred/comp/rt.vxgi.comp.glsl
Normal 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();
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
#version 450
|
||||
#version 460
|
||||
#pragma shader_stage(compute)
|
||||
|
||||
#define RT 1
|
||||
|
||||
@ -5,10 +5,31 @@
|
||||
layout (location = 0) in vec2 inUv;
|
||||
layout (location = 1) flat in uint inPass;
|
||||
|
||||
layout (location = 0) out vec4 outAlbedo;
|
||||
layout (location = 0) out vec4 outColor;
|
||||
|
||||
layout (binding = 0) uniform sampler2D samplerAlbedo;
|
||||
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() {
|
||||
outAlbedo = texture( samplerAlbedo, inUv );
|
||||
outColor = texture( samplerColor, inUv );
|
||||
#if TONE_MAP
|
||||
toneMap(outColor, ubo.exposure);
|
||||
#endif
|
||||
#if GAMMA_CORRECT
|
||||
gammaCorrect(outColor, ubo.gamma);
|
||||
#endif
|
||||
}
|
||||
@ -5,15 +5,26 @@
|
||||
layout (location = 0) in vec2 inUv;
|
||||
layout (location = 1) flat in uint inPass;
|
||||
|
||||
layout (location = 0) out vec4 fragColor;
|
||||
layout (location = 0) out vec4 outColor;
|
||||
|
||||
layout (binding = 0) uniform sampler2D samplerAlbedo;
|
||||
layout (binding = 0) uniform sampler2D samplerColor;
|
||||
|
||||
layout (binding = 1) uniform UBO {
|
||||
float curTime;
|
||||
float gamma;
|
||||
float exposure;
|
||||
uint padding;
|
||||
} ubo;
|
||||
|
||||
#define PI 3.14159265358
|
||||
|
||||
#define TONE_MAP 1
|
||||
#define GAMMA_CORRECT 1
|
||||
#define TEXTURES 1
|
||||
|
||||
#include "../../common/macros.h"
|
||||
#include "../../common/structs.h"
|
||||
#include "../../common/functions.h"
|
||||
|
||||
#if 0
|
||||
float iTime = 0;
|
||||
float noise(vec2 p) {
|
||||
@ -45,7 +56,7 @@ vec4 getVideo(vec2 uv) {
|
||||
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(samplerAlbedo,look);
|
||||
return texture(samplerColor,look);
|
||||
}
|
||||
|
||||
vec2 screenDistort(vec2 uv) {
|
||||
@ -69,52 +80,65 @@ void main() {
|
||||
video.rgb *= vignette;
|
||||
video.rgb *= (12.+mod(uv.y*30.+iTime,1.))/13.;
|
||||
|
||||
fragColor = video;
|
||||
outColor = video;
|
||||
#if TONE_MAP
|
||||
toneMap(outColor, ubo.exposure);
|
||||
#endif
|
||||
#if GAMMA_CORRECT
|
||||
gammaCorrect(outColor, ubo.gamma);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#if 1
|
||||
vec2 curveRemapUV(vec2 uv, vec2 curvature) {
|
||||
uv = uv * 2.0 - 1.0;
|
||||
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;
|
||||
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);
|
||||
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);
|
||||
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( samplerAlbedo, 0 );
|
||||
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(samplerAlbedo, remappedUV);
|
||||
const vec2 remappedUV = curveRemapUV(vec2(inUv.x, inUv.y), curvature);
|
||||
vec4 baseColor = texture(samplerColor, remappedUV);
|
||||
|
||||
baseColor *= vignetteIntensity(remappedUV, screenResolution, vignetteOpacity, vignetteRoundness);
|
||||
baseColor *= vignetteIntensity(remappedUV, screenResolution, vignetteOpacity, vignetteRoundness);
|
||||
|
||||
baseColor *= scanLineIntensity(remappedUV.x, screenResolution.y, scanLineOpacity.x);
|
||||
baseColor *= scanLineIntensity(remappedUV.y, screenResolution.x, scanLineOpacity.y);
|
||||
baseColor *= scanLineIntensity(remappedUV.x, screenResolution.y, scanLineOpacity.x);
|
||||
baseColor *= scanLineIntensity(remappedUV.y, screenResolution.x, scanLineOpacity.y);
|
||||
|
||||
baseColor *= vec4(vec3(brightness), 1.0);
|
||||
baseColor *= vec4(vec3(brightness), 1.0);
|
||||
|
||||
if (remappedUV.x < 0.0 || remappedUV.y < 0.0 || remappedUV.x > 1.0 || remappedUV.y > 1.0){
|
||||
fragColor = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
} else {
|
||||
fragColor = baseColor;
|
||||
}
|
||||
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
|
||||
@ -123,15 +147,15 @@ 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))
|
||||
// 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)
|
||||
// Optimize for resize.
|
||||
#define res (iResolution.xy/6.0)
|
||||
#endif
|
||||
|
||||
// Hardness of scanline.
|
||||
// -8.0 = soft
|
||||
// -8.0 = soft
|
||||
// -16.0 = medium
|
||||
float hardScan=-8.0;
|
||||
|
||||
@ -164,92 +188,98 @@ 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(samplerAlbedo,pos.xy,-16.0).rgb);}
|
||||
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);}
|
||||
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);}
|
||||
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);}
|
||||
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;}
|
||||
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;}
|
||||
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;}
|
||||
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( samplerAlbedo, 0 );
|
||||
iResolution = textureSize( samplerColor, 0 );
|
||||
fragCoord = inUv * iResolution;
|
||||
|
||||
vec2 pos = Warp(fragCoord.xy / iResolution.xy);
|
||||
|
||||
hardScan = -12.0;
|
||||
maskDark = maskLight = 1.0;
|
||||
hardScan = -12.0;
|
||||
maskDark = maskLight = 1.0;
|
||||
|
||||
fragColor.rgb = Tri(pos) * Mask(fragCoord.xy);
|
||||
fragColor.rgb = ToSrgb(fragColor.rgb);
|
||||
fragColor.a = 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
|
||||
@ -257,8 +287,11 @@ 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( samplerAlbedo, inUv );
|
||||
|
||||
fragColor = sampled - noise * mdf;
|
||||
const vec4 sampled = texture( samplerColor, inUv );
|
||||
|
||||
outColor = sampled - noise * mdf;
|
||||
|
||||
toneMap(outColor, ubo.exposure);
|
||||
gammaCorrect(outColor, ubo.gamma);
|
||||
}
|
||||
#endif
|
||||
@ -10,6 +10,7 @@ layout (local_size_x = 8, local_size_y = 8, local_size_z = 8) in;
|
||||
|
||||
#define VXGI 1
|
||||
#define MAX_CUBEMAPS CUBEMAPS
|
||||
#define GAMMA_CORRECT 1
|
||||
|
||||
layout (constant_id = 0) const uint TEXTURES = 512;
|
||||
layout (constant_id = 1) const uint CUBEMAPS = 128;
|
||||
@ -104,7 +105,7 @@ void main() {
|
||||
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 / (PI * pow(length(Liu), 2.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));
|
||||
@ -130,6 +131,13 @@ void main() {
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
@ -17,26 +17,37 @@ layout (binding = 6) uniform samplerCube samplerCubemaps[CUBEMAPS];
|
||||
#include "../../common/macros.h"
|
||||
#include "../../common/structs.h"
|
||||
|
||||
layout (std140, binding = 7) readonly buffer DrawCommands {
|
||||
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 = 8) readonly buffer Instances {
|
||||
layout (std140, binding = 10) readonly buffer Instances {
|
||||
Instance instances[];
|
||||
};
|
||||
layout (std140, binding = 9) readonly buffer InstanceAddresseses {
|
||||
layout (std140, binding = 11) readonly buffer InstanceAddresseses {
|
||||
InstanceAddresses instanceAddresses[];
|
||||
};
|
||||
layout (std140, binding = 10) readonly buffer Materials {
|
||||
layout (std140, binding = 12) readonly buffer Materials {
|
||||
Material materials[];
|
||||
};
|
||||
layout (std140, binding = 11) readonly buffer Textures {
|
||||
layout (std140, binding = 13) readonly buffer Textures {
|
||||
Texture textures[];
|
||||
};
|
||||
layout (std140, binding = 12) readonly buffer Lights {
|
||||
layout (std140, binding = 14) readonly buffer Lights {
|
||||
Light lights[];
|
||||
};
|
||||
|
||||
layout (binding = 13, rgba8) uniform volatile coherent image3D outAlbedos;
|
||||
layout (binding = 15, rgba8) uniform volatile coherent image3D outAlbedos;
|
||||
|
||||
#include "../../common/functions.h"
|
||||
#include "../../common/shadows.h"
|
||||
@ -60,19 +71,26 @@ void main() {
|
||||
const uint drawID = uint(inId.y);
|
||||
const uint instanceID = uint(inId.z);
|
||||
|
||||
const DrawCommand drawCommand = drawCommands[drawID];
|
||||
const Instance instance = instances[instanceID];
|
||||
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);
|
||||
@ -84,14 +102,19 @@ void main() {
|
||||
} else {
|
||||
surface.normal.world = N;
|
||||
}
|
||||
#endif
|
||||
|
||||
surface.light = material.colorEmissive;
|
||||
surface.material.albedo = vec4(1);
|
||||
#if 1
|
||||
#if 1
|
||||
{
|
||||
const vec3 F0 = mix(vec3(0.04), surface.material.albedo.rgb, surface.material.metallic);
|
||||
for ( uint i = 0; i < lights.length(); ++i ) {
|
||||
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) );
|
||||
@ -106,7 +129,7 @@ void main() {
|
||||
if ( light.power * La * Ls <= LIGHT_POWER_CUTOFF ) continue;
|
||||
|
||||
const vec3 Lo = normalize( -position );
|
||||
const float cosLo = max(0.0, dot(normal, Lo));
|
||||
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;
|
||||
@ -168,8 +191,8 @@ void main() {
|
||||
surface.light.rgb += (diffuse + specular) * Lr * cosLi;
|
||||
surface.light.a += light.power * La * Ls;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#define EXPOSURE 0
|
||||
#define GAMMA 0
|
||||
@ -181,7 +204,7 @@ void main() {
|
||||
|
||||
{
|
||||
const vec2 st = inSt.xy * imageSize(outAlbedos).xy;
|
||||
const ivec3 uvw = ivec3(int(st.x), int(st.y), int(drawCommand.auxID));
|
||||
const ivec3 uvw = ivec3(int(st.x), int(st.y), int(mapID));
|
||||
imageStore(outAlbedos, uvw, vec4(surface.light.rgb, 1) );
|
||||
}
|
||||
}
|
||||
@ -4,6 +4,5 @@
|
||||
#define INSTANCED 1
|
||||
#define SKINNED 0
|
||||
#define BAKING 1
|
||||
#define LAYERED 1
|
||||
|
||||
#include "../base/vert.h"
|
||||
|
||||
@ -1,8 +1,5 @@
|
||||
layout (constant_id = 0) const uint PASSES = 6;
|
||||
#extension GL_ARB_shader_draw_parameters : enable
|
||||
#if LAYERED
|
||||
#extension GL_ARB_shader_viewport_layer_array : enable
|
||||
#endif
|
||||
|
||||
#include "../../common/macros.h"
|
||||
#include "../../common/structs.h"
|
||||
|
||||
@ -11,7 +11,6 @@ layout (constant_id = 3) const uint CASCADES = 1;
|
||||
|
||||
// shader type settings
|
||||
#define RT 1
|
||||
#define COMPUTE 1
|
||||
#define DEFERRED_SAMPLING 1
|
||||
#define BUFFER_REFERENCE 1
|
||||
#define UINT64_ENABLED 1
|
||||
@ -379,20 +378,11 @@ void main() {
|
||||
#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);
|
||||
// imageStore(outImage, ivec2(gl_LaunchIDEXT.xy), outFragBright);
|
||||
#endif
|
||||
#if FOG
|
||||
fog( surface.ray, surface.fragment.rgb, surface.fragment.a );
|
||||
#endif
|
||||
#if TONE_MAP
|
||||
surface.fragment.rgb = vec3(1.0) - exp(-surface.fragment.rgb * ubo.settings.bloom.exposure);
|
||||
#endif
|
||||
#if GAMMA_CORRECT
|
||||
surface.fragment.rgb = pow(surface.fragment.rgb, vec3(1.0 / ubo.settings.bloom.gamma));
|
||||
#endif
|
||||
#if WHITENOISE
|
||||
if ( enabled(ubo.settings.mode.type, 1) ) whitenoise(surface.fragment.rgb, ubo.settings.mode.parameters);
|
||||
#endif
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@ -109,10 +109,8 @@ void client::initialize() {
|
||||
#endif
|
||||
|
||||
if ( !ext::json::isArray( configRenderJson["framebuffer"]["size"] ) ) {
|
||||
float scale = configRenderJson["framebuffer"]["size"].as(1.0f);
|
||||
uf::renderer::settings::width = payload.window.size.x * scale;
|
||||
uf::renderer::settings::height = payload.window.size.y * scale;
|
||||
|
||||
uf::renderer::settings::width = payload.window.size.x;
|
||||
uf::renderer::settings::height = payload.window.size.y;
|
||||
}
|
||||
uf::renderer::states::resized = true;
|
||||
} );
|
||||
@ -126,9 +124,6 @@ void client::initialize() {
|
||||
#if UF_ENV_DREAMCAST
|
||||
client::window.pollEvents();
|
||||
#endif
|
||||
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void client::tick() {
|
||||
|
||||
@ -7,9 +7,13 @@
|
||||
#if UF_USE_FFX_FSR
|
||||
namespace ext {
|
||||
namespace fsr {
|
||||
extern pod::Vector2f UF_API jitter;
|
||||
extern float UF_API sharpness;
|
||||
extern bool UF_API initialized;
|
||||
|
||||
extern uf::stl::string UF_API preset;
|
||||
|
||||
extern float UF_API sharpness;
|
||||
extern pod::Vector2f UF_API jitter;
|
||||
extern float UF_API jitterScale;
|
||||
|
||||
void UF_API initialize();
|
||||
void UF_API tick();
|
||||
|
||||
@ -19,6 +19,9 @@ namespace ext {
|
||||
namespace Format {
|
||||
typedef decltype(VK_FORMAT_R32G32_SFLOAT) type_t;
|
||||
#include "enums/format.inl"
|
||||
|
||||
static const type_t HDR = R32G32B32A32_SFLOAT;
|
||||
static const type_t SDR = R16G16B16A16_SFLOAT;
|
||||
}
|
||||
namespace Face {
|
||||
typedef decltype(VK_FRONT_FACE_CLOCKWISE) type_t;
|
||||
|
||||
@ -18,6 +18,7 @@ namespace ext {
|
||||
|
||||
uint32_t width = 0;
|
||||
uint32_t height = 0;
|
||||
float scale = 0;
|
||||
|
||||
struct {
|
||||
uf::Serializer json;
|
||||
|
||||
@ -47,6 +47,7 @@ namespace ext {
|
||||
uint32_t width = 0;
|
||||
uint32_t height = 0;
|
||||
uint8_t views = 1;
|
||||
float scale = 0;
|
||||
// RAII
|
||||
void initialize( Device& device );
|
||||
void destroy();
|
||||
|
||||
@ -354,7 +354,7 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity, uf::M
|
||||
uf::stl::string geometryShaderFilename = uf::io::resolveURI("/graph/baking/geom.spv");
|
||||
uf::stl::string fragmentShaderFilename = uf::io::resolveURI("/graph/baking/frag.spv");
|
||||
graphic.material.attachShader(vertexShaderFilename, uf::renderer::enums::Shader::VERTEX, "baking");
|
||||
graphic.material.attachShader(geometryShaderFilename, uf::renderer::enums::Shader::GEOMETRY, "baking");
|
||||
// graphic.material.attachShader(geometryShaderFilename, uf::renderer::enums::Shader::GEOMETRY, "baking");
|
||||
graphic.material.attachShader(fragmentShaderFilename, uf::renderer::enums::Shader::FRAGMENT, "baking");
|
||||
graphic.material.metadata.autoInitializeUniformBuffers = true;
|
||||
}
|
||||
@ -539,6 +539,9 @@ void uf::graph::process( pod::Graph& graph ) {
|
||||
}
|
||||
}
|
||||
|
||||
if ( graph.metadata["lights"]["lightmap"].is<bool>() && !graph.metadata["lights"]["lightmap"].as<bool>() ) {
|
||||
graph.metadata["baking"]["enabled"] = false;
|
||||
}
|
||||
if ( !sceneMetadataJson["light"]["useLightmaps"].as<bool>(true) ) {
|
||||
graph.metadata["lights"]["lightmap"] = false;
|
||||
graph.metadata["baking"]["enabled"] = false;
|
||||
@ -564,31 +567,38 @@ void uf::graph::process( pod::Graph& graph ) {
|
||||
|
||||
graph.metadata["baking"]["layers"] = lightmapCount;
|
||||
|
||||
if ( graph.metadata["lights"]["lightmap"].as<bool>() ) for ( auto& pair : filenames ) {
|
||||
auto i = pair.first;
|
||||
auto f = uf::io::sanitize( pair.second, uf::io::directory( graph.name ) );
|
||||
|
||||
if ( !uf::io::exists( f ) ) {
|
||||
UF_MSG_ERROR( "lightmap does not exist: {} {}", i, f )
|
||||
continue;
|
||||
if ( graph.metadata["lights"]["lightmap"].as<bool>() ) {
|
||||
for ( auto& pair : filenames ) {
|
||||
auto i = pair.first;
|
||||
auto f = uf::io::sanitize( pair.second, uf::io::directory( graph.name ) );
|
||||
if ( !uf::io::exists( f ) ) {
|
||||
graph.metadata["lights"]["lightmap"] = false;
|
||||
UF_MSG_ERROR( "lightmap does not exist: {} {}, disabling lightmaps", i, f )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if ( graph.metadata["lights"]["lightmap"].as<bool>() ) {
|
||||
for ( auto& pair : filenames ) {
|
||||
auto i = pair.first;
|
||||
auto f = uf::io::sanitize( pair.second, uf::io::directory( graph.name ) );
|
||||
|
||||
auto textureID = graph.textures.size();
|
||||
auto imageID = graph.images.size();
|
||||
auto textureID = graph.textures.size();
|
||||
auto imageID = graph.images.size();
|
||||
|
||||
auto& texture = /*graph.storage*/uf::graph::storage.textures[graph.textures.emplace_back(f)];
|
||||
auto& image = /*graph.storage*/uf::graph::storage.images[graph.images.emplace_back(f)];
|
||||
image.open( f, false );
|
||||
auto& texture = /*graph.storage*/uf::graph::storage.textures[graph.textures.emplace_back(f)];
|
||||
auto& image = /*graph.storage*/uf::graph::storage.images[graph.images.emplace_back(f)];
|
||||
image.open( f, false );
|
||||
|
||||
texture.index = imageID;
|
||||
texture.index = imageID;
|
||||
|
||||
lightmapIDs[i] = textureID;
|
||||
lightmapIDs[i] = textureID;
|
||||
|
||||
graph.metadata["lights"]["lightmaps"][i] = f;
|
||||
graph.metadata["baking"]["enabled"] = false;
|
||||
graph.metadata["lights"]["lightmaps"][i] = f;
|
||||
graph.metadata["baking"]["enabled"] = false;
|
||||
|
||||
isSrgb[f] = false;
|
||||
isSrgb[f] = false;
|
||||
}
|
||||
}
|
||||
|
||||
for ( auto& name : graph.instances ) {
|
||||
@ -960,7 +970,11 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
|
||||
// ignore pesky light_Orientation nodes
|
||||
if ( uf::string::split( node.name, "_" ).back() == "Orientation" ) ignore = true;
|
||||
// for dreamcast, ignore lights if we're baked
|
||||
if ( graph.metadata["lights"]["lightmapped"].as<bool>() && graph.metadata["lights"]["disable if lightmapped"].as<bool>(true) ) if ( graph.lights.count(node.name) > 0 ) ignore = true;
|
||||
/*
|
||||
if ( graph.metadata["lights"]["lightmap"].as<bool>() && graph.metadata["lights"]["disable if lightmapped"].as<bool>(true) ) {
|
||||
if ( graph.lights.count(node.name) > 0 ) ignore = true;
|
||||
}
|
||||
*/
|
||||
|
||||
// on systems where frametime is very, very important, we can set all static nodes to not tick
|
||||
|
||||
@ -969,6 +983,19 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
|
||||
if ( graph.metadata["baking"]["enabled"].as<bool>(false) && !tag["bake"].as<bool>(true) ) ignore = true;
|
||||
if ( tag["ignore"].as<bool>() ) ignore = true;
|
||||
}
|
||||
bool isLight = graph.lights.count(node.name) > 0;
|
||||
/*
|
||||
if ( graph.metadata["lights"]["lightmap"].as<bool>() )
|
||||
if ( ext::json::isObject( tag ) ) {
|
||||
if ( !tag["light"]["dynamic"].as<bool>() && !tag["light"]["shadows"].as<bool>() ) {
|
||||
ignore = true;
|
||||
UF_MSG_DEBUG("IGNORING {}", node.name);
|
||||
}
|
||||
} else {
|
||||
ignore = true;
|
||||
}
|
||||
}
|
||||
*/
|
||||
if ( ignore ) return;
|
||||
|
||||
// create child
|
||||
@ -1017,7 +1044,7 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
|
||||
|
||||
// create as light
|
||||
{
|
||||
if ( graph.lights.count(node.name) > 0 ) {
|
||||
if ( isLight ) {
|
||||
auto& l = graph.lights[node.name];
|
||||
|
||||
#if UF_USE_OPENGL
|
||||
@ -1034,8 +1061,9 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
|
||||
metadataLight["color"][1] = l.color.y;
|
||||
metadataLight["color"][2] = l.color.z;
|
||||
metadataLight["shadows"] = graph.metadata["lights"]["shadows"].as<bool>();
|
||||
metadataLight["dynamic"] = false;
|
||||
|
||||
if ( uf::string::matched( node.name, "/\\bspot\\b/" ) ) {
|
||||
if ( uf::string::matched( node.name, R"(/\bspot\b/)" ) ) {
|
||||
metadataLight["type"] = "spot";
|
||||
}
|
||||
|
||||
@ -1050,28 +1078,20 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
|
||||
if ( key == "transform" ) return;
|
||||
metadataLight[key] = value;
|
||||
});
|
||||
#if !UF_USE_OPENGL
|
||||
/*
|
||||
bool should = false;
|
||||
if ( !graph.metadata["lights"]["lightmapped"].as<bool>() ) {
|
||||
if ( !graph.metadata["lights"]["lightmap"].as<bool>() ) {
|
||||
should = true;
|
||||
} else if ( metadataLight["shadows"].as<bool>() || metadataLight["dynamic"].as<bool>() ) {
|
||||
should = true;
|
||||
}
|
||||
if ( should ) {
|
||||
auto& metadataJson = entity.getComponent<uf::Serializer>();
|
||||
entity.load("/light.json");
|
||||
// copy
|
||||
ext::json::forEach( metadataLight, [&]( const uf::stl::string& key, ext::json::Value& value ) {
|
||||
metadataJson["light"][key] = value;
|
||||
});
|
||||
/*
|
||||
if ( metadataJson["light"]["type"].as<uf::stl::string>() == "point" ) {
|
||||
auto& transform = entity.getComponent<pod::Transform<>>();
|
||||
transform.orientation = uf::quaternion::identity();
|
||||
}
|
||||
*/
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
auto& metadataJson = entity.getComponent<uf::Serializer>();
|
||||
entity.load("/light.json");
|
||||
// copy
|
||||
ext::json::forEach( metadataLight, [&]( const uf::stl::string& key, ext::json::Value& value ) {
|
||||
metadataJson["light"][key] = value;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -143,8 +143,8 @@ uf::Scene& uf::scene::loadScene( const uf::stl::string& name, const uf::stl::str
|
||||
const uf::stl::string filename = _filename != "" ? _filename : (uf::stl::string("/") + uf::string::lowercase(name) + "/scene.json");
|
||||
#endif
|
||||
scene->load(filename);
|
||||
if ( uf::renderer::settings::pipelines::vxgi ) uf::instantiator::bind( "VoxelizerSceneBehavior", *scene );
|
||||
if ( uf::renderer::settings::pipelines::rt ) uf::instantiator::bind( "RayTraceSceneBehavior", *scene );
|
||||
if ( uf::renderer::settings::pipelines::vxgi ) uf::instantiator::bind( "VoxelizerSceneBehavior", *scene );
|
||||
scene->initialize();
|
||||
return *scene;
|
||||
}
|
||||
@ -152,8 +152,8 @@ uf::Scene& uf::scene::loadScene( const uf::stl::string& name, const uf::Serializ
|
||||
uf::Scene* scene = uf::instantiator::objects->has( name ) ? (uf::Scene*) &uf::instantiator::instantiate( name ) : new uf::Scene;
|
||||
uf::scene::scenes.emplace_back( scene );
|
||||
if ( data != "" ) scene->load(data);
|
||||
if ( uf::renderer::settings::pipelines::vxgi ) uf::instantiator::bind( "VoxelizerSceneBehavior", *scene );
|
||||
if ( uf::renderer::settings::pipelines::rt ) uf::instantiator::bind( "RayTraceSceneBehavior", *scene );
|
||||
if ( uf::renderer::settings::pipelines::vxgi ) uf::instantiator::bind( "VoxelizerSceneBehavior", *scene );
|
||||
scene->initialize();
|
||||
return *scene;
|
||||
}
|
||||
|
||||
@ -17,6 +17,8 @@ namespace {
|
||||
FfxFsr2Context context;
|
||||
FfxFsr2ContextDescription contextDescription;
|
||||
|
||||
uf::renderer::Texture fsrTarget;
|
||||
|
||||
uf::stl::string FFX_ERROR_TO_STRING( FfxErrorCode code ) {
|
||||
switch ( code ) {
|
||||
case FFX_OK: return "OK"; break;
|
||||
@ -66,55 +68,14 @@ namespace {
|
||||
#if 1
|
||||
FfxFsr2DispatchDescription dispatchParameters = {};
|
||||
dispatchParameters.commandList = ffxGetCommandListVK(commandBuffer);
|
||||
|
||||
if ( uf::renderer::settings::pipelines::rt ) {
|
||||
if ( !uf::renderer::hasRenderMode("Compute:RT", true) ) return;
|
||||
|
||||
auto& renderMode = uf::renderer::getRenderMode("Compute:RT", true);
|
||||
pod::Vector2ui renderSize = {
|
||||
renderMode.width > 0 ? renderMode.width : uf::renderer::settings::width,
|
||||
renderMode.height > 0 ? renderMode.height : uf::renderer::settings::height,
|
||||
};
|
||||
dispatchParameters.renderSize.width = renderSize.x;
|
||||
dispatchParameters.renderSize.height = renderSize.y;
|
||||
|
||||
auto& attachmentColor = renderMode.hasAttachment("output") ? renderMode.getAttachment("output") : renderMode.getAttachment("color");
|
||||
auto& attachmentDepth = renderMode.getAttachment("depth");
|
||||
auto& attachmentMotion = renderMode.getAttachment("motion");
|
||||
|
||||
dispatchParameters.color = ffxGetTextureResourceVK(&::context,
|
||||
attachmentColor.image,
|
||||
attachmentColor.view,
|
||||
renderSize.x,
|
||||
renderSize.y,
|
||||
attachmentColor.descriptor.format,
|
||||
L"FSR2_InputColor"
|
||||
);
|
||||
dispatchParameters.depth = ffxGetTextureResourceVK(&::context,
|
||||
attachmentDepth.image,
|
||||
attachmentDepth.view,
|
||||
renderSize.x,
|
||||
renderSize.y,
|
||||
attachmentDepth.descriptor.format,
|
||||
L"FSR2_InputDepth"
|
||||
);
|
||||
dispatchParameters.motionVectors = ffxGetTextureResourceVK(&::context,
|
||||
attachmentMotion.image,
|
||||
attachmentMotion.view,
|
||||
renderSize.x,
|
||||
renderSize.y,
|
||||
attachmentMotion.descriptor.format,
|
||||
L"FSR2_InputMotionVectors"
|
||||
);
|
||||
dispatchParameters.motionVectorScale.x = renderSize.x;
|
||||
dispatchParameters.motionVectorScale.y = renderSize.y;
|
||||
} else {
|
||||
|
||||
{
|
||||
if ( !uf::renderer::hasRenderMode("", true) ) return;
|
||||
|
||||
auto& renderMode = uf::renderer::getRenderMode("", true);
|
||||
pod::Vector2ui renderSize = {
|
||||
renderMode.width > 0 ? renderMode.width : uf::renderer::settings::width,
|
||||
renderMode.height > 0 ? renderMode.height : uf::renderer::settings::height,
|
||||
renderMode.width > 0 ? renderMode.width : (uf::renderer::settings::width * renderMode.scale),
|
||||
renderMode.height > 0 ? renderMode.height : (uf::renderer::settings::height * renderMode.scale),
|
||||
};
|
||||
dispatchParameters.renderSize.width = renderSize.x;
|
||||
dispatchParameters.renderSize.height = renderSize.y;
|
||||
@ -151,15 +112,16 @@ namespace {
|
||||
dispatchParameters.motionVectorScale.y = renderSize.y;
|
||||
}
|
||||
{
|
||||
/*
|
||||
if ( !uf::renderer::hasRenderMode("Swapchain", true) ) return;
|
||||
|
||||
auto& swapchainRenderMode = uf::renderer::getRenderMode("Swapchain", true);
|
||||
auto& attachmentOutput = swapchainRenderMode.getAttachment("color["+std::to_string(swapchainIndex)+"]");
|
||||
// auto& attachmentOutput = swapchainRenderMode.getAttachment("color["+std::to_string(swapchainIndex)+"]");
|
||||
pod::Vector2ui displaySize = {
|
||||
swapchainRenderMode.width, // uf::renderer::settings::width
|
||||
swapchainRenderMode.height, // uf::renderer::settings::height
|
||||
};
|
||||
|
||||
auto& attachmentOutput = swapchainRenderMode.getAttachment("fsr");
|
||||
dispatchParameters.output = ffxGetTextureResourceVK(&::context,
|
||||
attachmentOutput.image,
|
||||
attachmentOutput.view,
|
||||
@ -168,6 +130,15 @@ namespace {
|
||||
attachmentOutput.descriptor.format,
|
||||
L"FSR2_OutputUpscaledColor", FFX_RESOURCE_STATE_UNORDERED_ACCESS
|
||||
);
|
||||
*/
|
||||
dispatchParameters.output = ffxGetTextureResourceVK(&::context,
|
||||
fsrTarget.image,
|
||||
fsrTarget.view,
|
||||
fsrTarget.width,
|
||||
fsrTarget.height,
|
||||
fsrTarget.format,
|
||||
L"FSR2_OutputUpscaledColor", FFX_RESOURCE_STATE_UNORDERED_ACCESS
|
||||
);
|
||||
}
|
||||
|
||||
dispatchParameters.exposure = ffxGetTextureResourceVK(&::context,
|
||||
@ -202,7 +173,7 @@ namespace {
|
||||
dispatchParameters.jitterOffset.x = ext::fsr::jitter.x; // m_JitterX;
|
||||
dispatchParameters.jitterOffset.y = ext::fsr::jitter.y; // m_JitterY;
|
||||
|
||||
dispatchParameters.reset = false; // uf::renderer::states::frameAccumulateReset; // pState->bReset;
|
||||
dispatchParameters.reset = uf::renderer::states::frameAccumulateReset; // pState->bReset;
|
||||
dispatchParameters.enableSharpening = ext::fsr::sharpness > 0.0f; // pState->bUseRcas;
|
||||
dispatchParameters.sharpness = ext::fsr::sharpness; //1.0f; // pState->sharpening;
|
||||
dispatchParameters.frameTimeDelta = uf::time::delta;
|
||||
@ -216,8 +187,10 @@ namespace {
|
||||
}
|
||||
}
|
||||
|
||||
uf::stl::string ext::fsr::preset = "native";
|
||||
pod::Vector2f ext::fsr::jitter = {};
|
||||
float ext::fsr::sharpness = 1.0f;
|
||||
float ext::fsr::jitterScale = 2.0f;
|
||||
bool ext::fsr::initialized = false;
|
||||
|
||||
void UF_API ext::fsr::initialize() {
|
||||
@ -230,7 +203,7 @@ void UF_API ext::fsr::initialize() {
|
||||
::contextDescription.maxRenderSize.height = 2160; // uf::renderer::settings::height;
|
||||
::contextDescription.displaySize.width = uf::renderer::settings::width;
|
||||
::contextDescription.displaySize.height = uf::renderer::settings::height;
|
||||
::contextDescription.flags = FFX_FSR2_ENABLE_AUTO_EXPOSURE | FFX_FSR2_ENABLE_DYNAMIC_RESOLUTION; // | FFX_FSR2_ENABLE_TEXTURE1D_USAGE;
|
||||
::contextDescription.flags = FFX_FSR2_ENABLE_AUTO_EXPOSURE | FFX_FSR2_ENABLE_MOTION_VECTORS_JITTER_CANCELLATION ; // | FFX_FSR2_ENABLE_DYNAMIC_RESOLUTION; // | FFX_FSR2_ENABLE_TEXTURE1D_USAGE;
|
||||
if ( uf::renderer::settings::pipelines::hdr ) ::contextDescription.flags |= FFX_FSR2_ENABLE_HIGH_DYNAMIC_RANGE;
|
||||
if ( uf::matrix::reverseInfiniteProjection ) ::contextDescription.flags |= FFX_FSR2_ENABLE_DEPTH_INVERTED | FFX_FSR2_ENABLE_DEPTH_INFINITE;
|
||||
|
||||
@ -242,30 +215,56 @@ void UF_API ext::fsr::initialize() {
|
||||
#if 0
|
||||
swapchainRenderMode.bindCallback( swapchainRenderMode.CALLBACK_BEGIN, draw);
|
||||
#endif
|
||||
|
||||
{
|
||||
fsrTarget.destroy();
|
||||
fsrTarget.fromBuffers(
|
||||
NULL, 0,
|
||||
uf::renderer::settings::pipelines::hdr ? uf::renderer::enums::Format::HDR : uf::renderer::enums::Format::SDR,
|
||||
uf::renderer::settings::width, uf::renderer::settings::height, 1, 1,
|
||||
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL
|
||||
);
|
||||
|
||||
auto& renderMode = uf::renderer::getRenderMode("", true);
|
||||
auto& blitter = *renderMode.getBlitter();
|
||||
auto& shader = blitter.material.getShader("fragment");
|
||||
shader.textures.clear();
|
||||
shader.textures.emplace_back().aliasTexture( fsrTarget );
|
||||
}
|
||||
}
|
||||
void UF_API ext::fsr::tick() {
|
||||
if ( !ext::fsr::initialized ) return;
|
||||
pod::Vector2ui renderSize = {};
|
||||
pod::Vector2ui displaySize = {};
|
||||
|
||||
if ( uf::renderer::settings::pipelines::rt ) {
|
||||
if ( !uf::renderer::hasRenderMode("Compute:RT", true) ) return;
|
||||
if ( uf::renderer::states::resized ) {
|
||||
::contextDescription.displaySize.width = uf::renderer::settings::width;
|
||||
::contextDescription.displaySize.height = uf::renderer::settings::height;
|
||||
FFX_ERROR_CHECK(ffxFsr2ContextDestroy( &::context ));
|
||||
FFX_ERROR_CHECK(ffxFsr2ContextCreate( &::context, &::contextDescription ));
|
||||
|
||||
auto& renderMode = uf::renderer::getRenderMode("Compute:RT", true);
|
||||
auto& blitter = *renderMode.getBlitter(); if ( !blitter.material.hasShader("fragment") ) return;
|
||||
auto& shader = blitter.material.getShader("fragment"); if ( shader.textures.empty() ) return;
|
||||
fsrTarget.destroy();
|
||||
fsrTarget.fromBuffers(
|
||||
NULL, 0,
|
||||
uf::renderer::settings::pipelines::hdr ? uf::renderer::enums::Format::HDR : uf::renderer::enums::Format::SDR,
|
||||
::contextDescription.displaySize.width, ::contextDescription.displaySize.height, 1, 1,
|
||||
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL
|
||||
);
|
||||
|
||||
auto& attachmentColor = shader.textures.front();
|
||||
renderSize = {
|
||||
attachmentColor.width > 0 ? attachmentColor.width : uf::renderer::settings::width,
|
||||
attachmentColor.height > 0 ? attachmentColor.height : uf::renderer::settings::height,
|
||||
};
|
||||
} else {
|
||||
auto& renderMode = uf::renderer::getRenderMode("", true);
|
||||
auto& blitter = *renderMode.getBlitter();
|
||||
auto& shader = blitter.material.getShader("fragment");
|
||||
shader.textures.clear();
|
||||
shader.textures.emplace_back().aliasTexture( fsrTarget );
|
||||
}
|
||||
|
||||
{
|
||||
if ( !uf::renderer::hasRenderMode("", true) ) return;
|
||||
|
||||
auto& renderMode = uf::renderer::getRenderMode("", true);
|
||||
renderSize = {
|
||||
renderMode.width > 0 ? renderMode.width : uf::renderer::settings::width,
|
||||
renderMode.height > 0 ? renderMode.height : uf::renderer::settings::height,
|
||||
renderMode.width > 0 ? renderMode.width : (uf::renderer::settings::width * renderMode.scale),
|
||||
renderMode.height > 0 ? renderMode.height : (uf::renderer::settings::height * renderMode.scale),
|
||||
};
|
||||
}
|
||||
|
||||
@ -281,13 +280,17 @@ void UF_API ext::fsr::tick() {
|
||||
|
||||
const int32_t jitterPhaseCount = ffxFsr2GetJitterPhaseCount(renderSize.x, displaySize.x);
|
||||
static uint32_t index = 0;
|
||||
if ( ++index > jitterPhaseCount ) index = 0;
|
||||
if ( index++ > jitterPhaseCount ) index = 0;
|
||||
|
||||
ffxFsr2GetJitterOffset(&ext::fsr::jitter.x, &ext::fsr::jitter.x, index, jitterPhaseCount);
|
||||
ffxFsr2GetJitterOffset(&ext::fsr::jitter.x, &ext::fsr::jitter.y, index, jitterPhaseCount);
|
||||
|
||||
pod::Vector2f jitter = {};
|
||||
jitter.x = 2.0f * jitter.x / (float) renderSize.x;
|
||||
jitter.y = 2.0f * jitter.y / (float) renderSize.y;
|
||||
|
||||
jitter.x = ext::fsr::jitterScale * ext::fsr::jitter.x / (float) renderSize.x;
|
||||
jitter.y = ext::fsr::jitterScale * ext::fsr::jitter.y / (float) renderSize.y;
|
||||
|
||||
ext::fsr::jitter = jitter;
|
||||
// UF_MSG_DEBUG("{}, {} x {} ({} {})", ext::fsr::jitterScale, jitter.x, jitter.y, index, jitterPhaseCount);
|
||||
::jitterMatrix = uf::matrix::translate( uf::matrix::identity(), pod::Vector3f{ jitter.x, jitter.y, 0 } );
|
||||
}
|
||||
void UF_API ext::fsr::render() {
|
||||
@ -295,7 +298,6 @@ void UF_API ext::fsr::render() {
|
||||
auto commandBuffer = uf::renderer::device.fetchCommandBuffer(uf::renderer::QueueEnum::GRAPHICS, true);
|
||||
draw(commandBuffer, uf::renderer::states::currentBuffer);
|
||||
uf::renderer::device.flushCommandBuffer(commandBuffer);
|
||||
|
||||
}
|
||||
void UF_API ext::fsr::terminate() {
|
||||
if ( !ext::fsr::initialized ) return;
|
||||
|
||||
@ -1058,6 +1058,7 @@ void ext::vulkan::Device::initialize() {
|
||||
VkPhysicalDeviceAccelerationStructureFeaturesKHR accelerationStructureFeatures{};
|
||||
VkPhysicalDeviceShaderClockFeaturesKHR shaderClockFeatures{};
|
||||
VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR fragmentShaderBarycentricFeatures{};
|
||||
VkPhysicalDeviceSubgroupSizeControlFeatures subgroupSizeControlFeatures{};
|
||||
|
||||
VkPhysicalDeviceVulkan12Features enabledPhysicalDeviceVulkan12Features{};
|
||||
VkPhysicalDeviceFeatures2 enabledDeviceFeatures2{}; {
|
||||
@ -1121,6 +1122,10 @@ void ext::vulkan::Device::initialize() {
|
||||
fragmentShaderBarycentricFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_KHR;
|
||||
fragmentShaderBarycentricFeatures.fragmentShaderBarycentric = VK_TRUE;
|
||||
}
|
||||
{
|
||||
subgroupSizeControlFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES;
|
||||
subgroupSizeControlFeatures.subgroupSizeControl = true;
|
||||
}
|
||||
|
||||
deviceCreateInfo.pNext = &physicalDeviceFeatures2;
|
||||
physicalDeviceFeatures2.pNext = &physicalDeviceVulkan12Features;
|
||||
@ -1133,6 +1138,7 @@ void ext::vulkan::Device::initialize() {
|
||||
rayQueryFeatures.pNext = &accelerationStructureFeatures;
|
||||
accelerationStructureFeatures.pNext = &shaderClockFeatures;
|
||||
shaderClockFeatures.pNext = &fragmentShaderBarycentricFeatures;
|
||||
fragmentShaderBarycentricFeatures.pNext = &subgroupSizeControlFeatures;
|
||||
|
||||
if ( settings::experimental::enableMultiGPU ) {
|
||||
UF_MSG_DEBUG("Multiple devices supported, using {} devices...", groupDeviceCreateInfo.physicalDeviceCount);
|
||||
|
||||
@ -459,9 +459,9 @@ void ext::vulkan::Pipeline::record( const Graphic& graphic, const GraphicDescrip
|
||||
if ( shader->descriptor.stage != VK_SHADER_STAGE_COMPUTE_BIT ) continue;
|
||||
auto& localSize = shader->metadata.definitions.localSize;
|
||||
vkCmdDispatch(commandBuffer,
|
||||
localSize.x ? ((width / localSize.x) + 1) : 1,
|
||||
localSize.y ? ((height / localSize.y) + 1) : 1,
|
||||
localSize.z ? ((depth / localSize.z) + 1) : 1
|
||||
1 < localSize.x ? ((width / localSize.x) + 1) : 1,
|
||||
1 < localSize.y ? ((height / localSize.y) + 1) : 1,
|
||||
1 < localSize.z ? ((depth / localSize.z) + 1) : 1
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -566,7 +566,6 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip
|
||||
}
|
||||
|
||||
if ( attachment ) {
|
||||
|
||||
// subscript on name will grab the view # from attachment->views
|
||||
if ( 0 <= view ) {
|
||||
texture.aliasAttachment( *attachment, (size_t) view );
|
||||
@ -578,6 +577,10 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip
|
||||
if ( descriptor.layout != VK_IMAGE_LAYOUT_UNDEFINED ) {
|
||||
texture.imageLayout = descriptor.layout;
|
||||
texture.descriptor.imageLayout = descriptor.layout;
|
||||
} else {
|
||||
texture.imageLayout = ext::vulkan::Texture::remapRenderpassLayout( texture.imageLayout );
|
||||
texture.descriptor.imageLayout = ext::vulkan::Texture::remapRenderpassLayout( texture.imageLayout );
|
||||
|
||||
}
|
||||
|
||||
INSERT_IMAGE(texture);
|
||||
@ -1038,14 +1041,6 @@ void ext::vulkan::Graphic::initializeMesh( uf::Mesh& mesh, bool buffer ) {
|
||||
// ensure our descriptors are proper
|
||||
mesh.updateDescriptor();
|
||||
|
||||
#if 0
|
||||
// it makes my life 10000x easier if we interleave a mesh while also requesting RT pipelines
|
||||
if ( !mesh.isInterleaved() && uf::renderer::settings::pipelines::rt ) {
|
||||
auto interleaved = mesh.interleave();
|
||||
return initializeMesh(interleaved);
|
||||
}
|
||||
#endif
|
||||
|
||||
// copy descriptors
|
||||
descriptor.inputs.vertex = mesh.vertex;
|
||||
descriptor.inputs.index = mesh.index;
|
||||
@ -1584,6 +1579,7 @@ void ext::vulkan::Graphic::generateTopAccelerationStructure( const uf::stl::vect
|
||||
} else UF_EXCEPTION("Buffers not found: {}", "tlasInstance");
|
||||
rebuild = rebuild || this->updateBuffer( (const void*) instancesVK.data(), instancesVK.size() * sizeof(VkAccelerationStructureInstanceKHR), instanceIndex, false );
|
||||
}
|
||||
|
||||
size_t instanceBufferAddress = this->buffers[instanceIndex].getAddress();
|
||||
|
||||
// have a front-and-back TLAS (buffer)
|
||||
@ -1784,7 +1780,6 @@ void ext::vulkan::Graphic::generateTopAccelerationStructure( const uf::stl::vect
|
||||
// uf::renderer::states::rebuild = true;
|
||||
}
|
||||
|
||||
|
||||
// build SBT
|
||||
if ( !this->material.hasShader("ray:gen", uf::renderer::settings::pipelines::names::rt) ) {
|
||||
{
|
||||
@ -1802,7 +1797,7 @@ void ext::vulkan::Graphic::generateTopAccelerationStructure( const uf::stl::vect
|
||||
auto& shader = this->material.getShader("ray:gen", uf::renderer::settings::pipelines::names::rt);
|
||||
shader.buffers.emplace_back( this->buffers[tlasBufferIndex].alias() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bool ext::vulkan::Graphic::hasPipeline( const GraphicDescriptor& descriptor ) const {
|
||||
return pipelines.count( descriptor ) > 0;
|
||||
|
||||
@ -343,9 +343,12 @@ void ext::vulkan::RenderMode::initialize( Device& device ) {
|
||||
|
||||
// this->width = 0; //ext::vulkan::width;
|
||||
// this->height = 0; //ext::vulkan::height;
|
||||
if ( this->scale == 0 ) this->scale = 1;
|
||||
|
||||
{
|
||||
if ( this->width > 0 ) renderTarget.width = this->width;
|
||||
if ( this->height > 0 ) renderTarget.height = this->height;
|
||||
if ( this->scale > 0 ) renderTarget.scale = this->scale;
|
||||
}
|
||||
|
||||
// Set sync objects
|
||||
|
||||
@ -40,10 +40,12 @@ void ext::vulkan::BaseRenderMode::createCommandBuffers( const uf::stl::vector<ex
|
||||
imageMemoryBarrier.subresourceRange.layerCount = 1;
|
||||
imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
|
||||
uf::stl::vector<RenderMode*> layers = ext::vulkan::getRenderModes(uf::stl::vector<uf::stl::string>{"RenderTarget", "Compute:RT", "Deferred"}, false);
|
||||
if ( !settings::pipelines::rt ) {
|
||||
uf::stl::vector<RenderMode*> layers = ext::vulkan::getRenderModes(uf::stl::vector<uf::stl::string>{"Deferred", "Compute:RT", "RenderTarget"}, false);
|
||||
#if 0
|
||||
if ( settings::pipelines::rt ) {
|
||||
std::reverse( layers.begin(), layers.end() );
|
||||
}
|
||||
#endif
|
||||
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto& sceneMetadataJson = scene.getComponent<uf::Serializer>();
|
||||
@ -214,6 +216,7 @@ void ext::vulkan::BaseRenderMode::tick() {
|
||||
}
|
||||
}
|
||||
void ext::vulkan::BaseRenderMode::render() {
|
||||
// if ( ext::vulkan::states::frameSkip ) return;
|
||||
// if ( ext::vulkan::renderModes.size() > 1 ) return;
|
||||
// if ( ext::vulkan::renderModes.back() != this ) return;
|
||||
|
||||
@ -273,13 +276,13 @@ void ext::vulkan::BaseRenderMode::initialize( Device& device ) {
|
||||
// create image views for swapchain images
|
||||
|
||||
renderTarget.attachments.clear();
|
||||
renderTarget.attachments.resize( ext::vulkan::swapchain.buffers + 1 );
|
||||
renderTarget.attachments.resize( ext::vulkan::swapchain.buffers );
|
||||
|
||||
// uint32_t width = windowSize.x; //this->width > 0 ? this->width : windowSize.x;
|
||||
// uint32_t height = windowSize.y; //this->height > 0 ? this->height : windowSize.y;
|
||||
|
||||
size_t attachmentIndex = 0;
|
||||
for ( size_t i = 0; i < images.size(); ++i ) {
|
||||
for ( size_t i = 0; i < ext::vulkan::swapchain.buffers; ++i ) {
|
||||
VkImageViewCreateInfo colorAttachmentView = {};
|
||||
colorAttachmentView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
colorAttachmentView.pNext = NULL;
|
||||
@ -310,10 +313,11 @@ void ext::vulkan::BaseRenderMode::initialize( Device& device ) {
|
||||
|
||||
metadata.attachments["color["+std::to_string((int) i)+"]"] = attachmentIndex++;
|
||||
}
|
||||
// Create depth
|
||||
auto& depthAttachment = renderTarget.attachments.back();
|
||||
metadata.attachments["depth"] = attachmentIndex++;
|
||||
{
|
||||
// Create depth
|
||||
auto& attachment = renderTarget.attachments.emplace_back();
|
||||
metadata.attachments["depth"] = attachmentIndex++;
|
||||
|
||||
// Create an optimal image used as the depth stencil attachment
|
||||
VkImageCreateInfo imageCreateInfo = {};
|
||||
imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||
@ -330,25 +334,9 @@ void ext::vulkan::BaseRenderMode::initialize( Device& device ) {
|
||||
|
||||
VmaAllocationCreateInfo allocInfo = {};
|
||||
allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
|
||||
VK_CHECK_RESULT(vmaCreateImage(allocator, &imageCreateInfo, &allocInfo, &depthAttachment.image, &depthAttachment.allocation, &depthAttachment.allocationInfo));
|
||||
depthAttachment.mem = depthAttachment.allocationInfo.deviceMemory;
|
||||
VK_CHECK_RESULT(vmaCreateImage(allocator, &imageCreateInfo, &allocInfo, &attachment.image, &attachment.allocation, &attachment.allocationInfo));
|
||||
attachment.mem = attachment.allocationInfo.deviceMemory;
|
||||
|
||||
/*
|
||||
VK_CHECK_RESULT(vkCreateImage(device, &imageCreateInfo, nullptr, &depthAttachment.image));
|
||||
|
||||
// Allocate memory for the image (device local) and bind it to our image
|
||||
VkMemoryAllocateInfo memAlloc = {};
|
||||
memAlloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||
VkMemoryRequirements memReqs;
|
||||
vkGetImageMemoryRequirements(device, depthAttachment.image, &memReqs);
|
||||
memAlloc.allocationSize = memReqs.size;
|
||||
memAlloc.memoryTypeIndex = getMemoryTypeIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &depthAttachment.mem));
|
||||
VK_CHECK_RESULT(vkBindImageMemory(device, depthAttachment.image, depthAttachment.mem, 0));
|
||||
*/
|
||||
// Create a view for the depth stencil image
|
||||
// Images aren't directly accessed in Vulkan, but rather through views described by a subresource range
|
||||
// This allows for multiple views of one image with differing ranges (e.g. for different layers)
|
||||
VkImageViewCreateInfo depthStencilView = {};
|
||||
depthStencilView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
depthStencilView.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
@ -359,11 +347,49 @@ void ext::vulkan::BaseRenderMode::initialize( Device& device ) {
|
||||
depthStencilView.subresourceRange.levelCount = 1;
|
||||
depthStencilView.subresourceRange.baseArrayLayer = 0;
|
||||
depthStencilView.subresourceRange.layerCount = 1;
|
||||
depthStencilView.image = depthAttachment.image;
|
||||
depthStencilView.image = attachment.image;
|
||||
|
||||
VK_CHECK_RESULT(vkCreateImageView(device, &depthStencilView, nullptr, &depthAttachment.view));
|
||||
|
||||
VK_CHECK_RESULT(vkCreateImageView(device, &depthStencilView, nullptr, &attachment.view));
|
||||
}
|
||||
// Create FSR dump
|
||||
/*
|
||||
if ( settings::pipelines::fsr ) {
|
||||
auto& attachment = renderTarget.attachments.emplace_back();
|
||||
|
||||
VkImageCreateInfo imageCreateInfo = {};
|
||||
imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||
imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
|
||||
imageCreateInfo.format = ext::vulkan::settings::pipelines::hdr ? enums::Format::HDR : enums::Format::SDR;
|
||||
|
||||
imageCreateInfo.extent = { width, height, 1 };
|
||||
imageCreateInfo.mipLevels = 1;
|
||||
imageCreateInfo.arrayLayers = 1;
|
||||
imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
imageCreateInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
|
||||
VmaAllocationCreateInfo allocInfo = {};
|
||||
allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
|
||||
VK_CHECK_RESULT(vmaCreateImage(allocator, &imageCreateInfo, &allocInfo, &attachment.image, &attachment.allocation, &attachment.allocationInfo));
|
||||
attachment.mem = attachment.allocationInfo.deviceMemory;
|
||||
|
||||
VkImageViewCreateInfo imageViewCreateInfo = {};
|
||||
imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
imageViewCreateInfo.format = ext::vulkan::settings::pipelines::hdr ? enums::Format::HDR : enums::Format::SDR;
|
||||
imageViewCreateInfo.subresourceRange = {};
|
||||
imageViewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
imageViewCreateInfo.subresourceRange.baseMipLevel = 0;
|
||||
imageViewCreateInfo.subresourceRange.levelCount = 1;
|
||||
imageViewCreateInfo.subresourceRange.baseArrayLayer = 0;
|
||||
imageViewCreateInfo.subresourceRange.layerCount = 1;
|
||||
imageViewCreateInfo.image = attachment.image;
|
||||
|
||||
VK_CHECK_RESULT(vkCreateImageView(device, &imageViewCreateInfo, nullptr, &attachment.view));
|
||||
metadata.attachments["fsr"] = attachmentIndex++;
|
||||
}
|
||||
*/
|
||||
// Create renderpass
|
||||
if ( !renderTarget.renderPass ) {// Create render pass
|
||||
// This example will use a single render pass with one subpass
|
||||
@ -459,8 +485,8 @@ void ext::vulkan::BaseRenderMode::initialize( Device& device ) {
|
||||
for (size_t i = 0; i < renderTarget.framebuffers.size(); i++)
|
||||
{
|
||||
std::array<VkImageView, 2> attachments;
|
||||
attachments[0] = renderTarget.attachments[i].view; // Color attachment is the view of the swapchain image
|
||||
attachments[1] = depthAttachment.view; // Depth/Stencil attachment is the same for all frame buffers
|
||||
attachments[0] = renderTarget.attachments[i].view; // Color attachment is the view of the swapchain image
|
||||
attachments[1] = renderTarget.attachments[metadata.attachments["depth"]].view; // Depth/Stencil attachment is the same for all frame buffers
|
||||
|
||||
VkFramebufferCreateInfo frameBufferCreateInfo = {};
|
||||
frameBufferCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
||||
|
||||
@ -41,14 +41,16 @@ uf::stl::vector<ext::vulkan::Graphic*> ext::vulkan::DeferredRenderMode::getBlitt
|
||||
}
|
||||
|
||||
void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
|
||||
auto HDR_FORMAT = VK_FORMAT_R32G32B32A32_SFLOAT;
|
||||
auto SDR_FORMAT = VK_FORMAT_R16G16B16A16_SFLOAT;
|
||||
|
||||
ext::vulkan::RenderMode::initialize( device );
|
||||
|
||||
uint32_t width = this->width > 0 ? this->width : (ext::vulkan::settings::width * this->scale);
|
||||
uint32_t height = this->height > 0 ? this->height : (ext::vulkan::settings::height * this->scale);
|
||||
|
||||
renderTarget.device = &device;
|
||||
renderTarget.views = metadata.eyes;
|
||||
size_t msaa = ext::vulkan::settings::msaa;
|
||||
|
||||
|
||||
struct {
|
||||
size_t id, bary, depth, uv, normal;
|
||||
size_t color, bright, motion, scratch, output;
|
||||
@ -100,21 +102,21 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
|
||||
});
|
||||
// output buffers
|
||||
attachments.color = renderTarget.attach(RenderTarget::Attachment::Descriptor{
|
||||
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? HDR_FORMAT : SDR_FORMAT,
|
||||
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? enums::Format::HDR : enums::Format::SDR,
|
||||
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
/*.blend =*/ blend,
|
||||
/*.samples =*/ 1,
|
||||
});
|
||||
attachments.bright = renderTarget.attach(RenderTarget::Attachment::Descriptor{
|
||||
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? HDR_FORMAT : SDR_FORMAT,
|
||||
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? enums::Format::HDR : enums::Format::SDR,
|
||||
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
/*.blend =*/ blend,
|
||||
/*.samples =*/ 1,
|
||||
});
|
||||
attachments.scratch = renderTarget.attach(RenderTarget::Attachment::Descriptor{
|
||||
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? HDR_FORMAT : SDR_FORMAT,
|
||||
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? enums::Format::HDR : enums::Format::SDR,
|
||||
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
/*.blend =*/ blend,
|
||||
@ -213,7 +215,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
|
||||
uf::stl::string fragmentShaderFilename = uf::io::root+"/shaders/display/renderTarget/frag.spv";
|
||||
{
|
||||
std::pair<bool, uf::stl::string> settings[] = {
|
||||
{ !settings::pipelines::rt && settings::pipelines::postProcess, "postProcess.frag" },
|
||||
{ settings::pipelines::postProcess /*&& !settings::pipelines::rt*/, "postProcess.frag" },
|
||||
// { msaa > 1, "msaa.frag" },
|
||||
};
|
||||
FOR_ARRAY( settings ) if ( settings[i].first ) fragmentShaderFilename = uf::string::replace( fragmentShaderFilename, "frag", settings[i].second );
|
||||
@ -226,15 +228,25 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
|
||||
|
||||
if ( blitter.material.hasShader("fragment") ) {
|
||||
auto& shader = blitter.material.getShader("fragment");
|
||||
shader.aliasAttachment("output", this);
|
||||
if ( !settings::pipelines::fsr ) {
|
||||
shader.aliasAttachment("output", this);
|
||||
}
|
||||
/*
|
||||
if ( settings::pipelines::fsr ) {
|
||||
auto& renderMode = ext::vulkan::getRenderMode("Swapchain", true);
|
||||
shader.aliasAttachment("fsr", &renderMode, VK_IMAGE_LAYOUT_GENERAL);
|
||||
} else {
|
||||
shader.aliasAttachment("output", this);
|
||||
}
|
||||
*/
|
||||
}
|
||||
if ( settings::pipelines::deferred ) {
|
||||
if ( DEFERRED_MODE == "compute" ) {
|
||||
uf::stl::string computeShaderFilename = "comp.spv"; {
|
||||
std::pair<bool, uf::stl::string> settings[] = {
|
||||
{ uf::renderer::settings::pipelines::vxgi, "vxgi.comp" },
|
||||
{ msaa > 1, "msaa.comp" },
|
||||
{ uf::renderer::settings::pipelines::rt, "rt.comp" },
|
||||
{ uf::renderer::settings::pipelines::vxgi, "vxgi.comp" },
|
||||
};
|
||||
FOR_ARRAY( settings ) if ( settings[i].first ) computeShaderFilename = uf::string::replace( computeShaderFilename, "comp", settings[i].second );
|
||||
}
|
||||
@ -383,18 +395,6 @@ void ext::vulkan::DeferredRenderMode::tick() {
|
||||
bool resized = (this->width == 0 && this->height == 0 && ext::vulkan::states::resized) || this->resized;
|
||||
bool rebuild = resized || ext::vulkan::states::rebuild || this->rebuild;
|
||||
|
||||
// update post processing
|
||||
if ( blitter.material.hasShader("fragment") && !settings::pipelines::rt && settings::pipelines::postProcess ) {
|
||||
auto& shader = blitter.material.getShader("fragment");
|
||||
|
||||
struct {
|
||||
float curTime = 0;
|
||||
} uniforms;
|
||||
|
||||
uniforms.curTime = uf::time::current;
|
||||
|
||||
shader.updateBuffer( (const void*) &uniforms, sizeof(uniforms), shader.getUniformBuffer("UBO") );
|
||||
}
|
||||
|
||||
if ( resized ) {
|
||||
this->resized = false;
|
||||
@ -403,6 +403,11 @@ void ext::vulkan::DeferredRenderMode::tick() {
|
||||
}
|
||||
// update blitter descriptor set
|
||||
if ( rebuild && blitter.initialized ) {
|
||||
uint32_t width = this->width > 0 ? this->width : (ext::vulkan::settings::width * this->scale);
|
||||
uint32_t height = this->height > 0 ? this->height : (ext::vulkan::settings::height * this->scale);
|
||||
|
||||
// UF_MSG_DEBUG("{} x {} ({:3f}%)", width, height, this->scale*100.0f);
|
||||
|
||||
if ( blitter.hasPipeline( blitter.descriptor ) ){
|
||||
blitter.getPipeline( blitter.descriptor ).update( blitter, blitter.descriptor );
|
||||
}
|
||||
@ -457,6 +462,8 @@ VkSubmitInfo ext::vulkan::DeferredRenderMode::queue() {
|
||||
return submitInfo;
|
||||
}
|
||||
void ext::vulkan::DeferredRenderMode::render() {
|
||||
// if ( ext::vulkan::states::frameSkip ) return;
|
||||
|
||||
if ( commandBufferCallbacks.count(EXECUTE_BEGIN) > 0 ) commandBufferCallbacks[EXECUTE_BEGIN]( VkCommandBuffer{}, 0 );
|
||||
|
||||
//lockMutex( this->mostRecentCommandPoolId );
|
||||
@ -494,8 +501,8 @@ ext::vulkan::GraphicDescriptor ext::vulkan::DeferredRenderMode::bindGraphicDescr
|
||||
return descriptor;
|
||||
}
|
||||
void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vector<ext::vulkan::Graphic*>& graphics ) {
|
||||
float width = this->width > 0 ? this->width : ext::vulkan::settings::width;
|
||||
float height = this->height > 0 ? this->height : ext::vulkan::settings::height;
|
||||
uint32_t width = this->width > 0 ? this->width : (ext::vulkan::settings::width * this->scale);
|
||||
uint32_t height = this->height > 0 ? this->height : (ext::vulkan::settings::height * this->scale);
|
||||
|
||||
VkCommandBufferBeginInfo cmdBufInfo = {};
|
||||
cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||
@ -534,12 +541,11 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool shouldRecord = true; // ( settings::pipelines::rt && !sceneMetadataJson["system"]["config"]["engine"]["scenes"]["rt"]["full"].as<bool>() ) || !settings::pipelines::rt;
|
||||
for (size_t i = 0; i < commands.size(); ++i) {
|
||||
VK_CHECK_RESULT(vkBeginCommandBuffer(commands[i], &cmdBufInfo));
|
||||
// Fill GBuffer
|
||||
if ( !settings::pipelines::rt ) {
|
||||
|
||||
{
|
||||
VkRenderPassBeginInfo renderPassBeginInfo = {};
|
||||
renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||
renderPassBeginInfo.pNext = nullptr;
|
||||
@ -604,7 +610,7 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto
|
||||
}
|
||||
}
|
||||
// skip deferred pass if RT is enabled, we still process geometry for a depth buffer
|
||||
if ( !settings::pipelines::rt ) for ( size_t eye = 0; eye < metadata.eyes; ++eye ) {
|
||||
if ( DEFERRED_MODE == "fragment" ) for ( size_t eye = 0; eye < metadata.eyes; ++eye ) {
|
||||
size_t currentPass = 0;
|
||||
size_t currentDraw = 0;
|
||||
{
|
||||
@ -621,7 +627,7 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto
|
||||
}
|
||||
vkCmdEndRenderPass(commands[i]);
|
||||
|
||||
if ( !settings::pipelines::rt && settings::pipelines::deferred && DEFERRED_MODE == "compute" && blitter.material.hasShader(DEFERRED_MODE, "deferred") ) {
|
||||
if ( settings::pipelines::deferred && DEFERRED_MODE == "compute" && blitter.material.hasShader(DEFERRED_MODE, "deferred") ) {
|
||||
auto& shader = blitter.material.getShader(DEFERRED_MODE, "deferred");
|
||||
ext::vulkan::GraphicDescriptor descriptor = blitter.descriptor;
|
||||
descriptor.renderMode = "";
|
||||
|
||||
@ -56,6 +56,9 @@ ext::vulkan::GraphicDescriptor ext::vulkan::RenderTargetRenderMode::bindGraphicD
|
||||
}
|
||||
|
||||
void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
|
||||
uint32_t width = this->width > 0 ? this->width : (ext::vulkan::settings::width * this->scale);
|
||||
uint32_t height = this->height > 0 ? this->height : (ext::vulkan::settings::height * this->scale);
|
||||
|
||||
ext::vulkan::RenderMode::initialize( device );
|
||||
|
||||
this->setTarget( this->getName() );
|
||||
@ -101,9 +104,6 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
|
||||
size_t depth, color, bright, motion, scratch, output;
|
||||
} attachments = {};
|
||||
|
||||
auto HDR_FORMAT = uf::renderer::enums::Format::R32G32B32A32_SFLOAT;
|
||||
auto SDR_FORMAT = uf::renderer::enums::Format::R16G16B16A16_SFLOAT; // uf::renderer::enums::Format::R8G8B8A8_UNORM
|
||||
|
||||
bool blend = true;
|
||||
attachments.depth = renderTarget.attach(RenderTarget::Attachment::Descriptor{
|
||||
/*.format = */ext::vulkan::settings::formats::depth,
|
||||
@ -113,21 +113,21 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
|
||||
/*.samples = */1,
|
||||
});
|
||||
attachments.color = renderTarget.attach(RenderTarget::Attachment::Descriptor{
|
||||
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? HDR_FORMAT : SDR_FORMAT,
|
||||
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? enums::Format::HDR : enums::Format::SDR,
|
||||
/*.layout = */ VK_IMAGE_LAYOUT_GENERAL,
|
||||
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
/*.blend =*/ blend,
|
||||
/*.samples =*/ 1,
|
||||
});
|
||||
attachments.bright = renderTarget.attach(RenderTarget::Attachment::Descriptor{
|
||||
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? HDR_FORMAT : SDR_FORMAT,
|
||||
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? enums::Format::HDR : enums::Format::SDR,
|
||||
/*.layout = */ VK_IMAGE_LAYOUT_GENERAL,
|
||||
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
/*.blend =*/ blend,
|
||||
/*.samples =*/ 1,
|
||||
});
|
||||
attachments.scratch = renderTarget.attach(RenderTarget::Attachment::Descriptor{
|
||||
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? HDR_FORMAT : SDR_FORMAT,
|
||||
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? enums::Format::HDR : enums::Format::SDR,
|
||||
/*.layout = */ VK_IMAGE_LAYOUT_GENERAL,
|
||||
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
/*.blend =*/ blend,
|
||||
@ -160,6 +160,71 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
|
||||
|
||||
metadata.attachments["output"] = attachments.color;
|
||||
#endif
|
||||
} else if ( metadata.type == "full" ) {
|
||||
#if 0
|
||||
struct {
|
||||
size_t id, position, normal, depth, color;
|
||||
} attachments = {};
|
||||
|
||||
// input g-buffers
|
||||
attachments.id = renderTarget.attach(RenderTarget::Attachment::Descriptor{
|
||||
/*.format = */VK_FORMAT_R32G32_UINT,
|
||||
/*.layout = */VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
/*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
|
||||
/*.blend = */false,
|
||||
/*.samples = */msaa,
|
||||
});
|
||||
attachments.position = renderTarget.attach(RenderTarget::Attachment::Descriptor{
|
||||
/*.format = */VK_FORMAT_R16G16B16A16_SFLOAT,
|
||||
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
/*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
|
||||
/*.blend = */false,
|
||||
/*.samples = */msaa,
|
||||
});
|
||||
attachments.normal = renderTarget.attach(RenderTarget::Attachment::Descriptor{
|
||||
/*.format = */VK_FORMAT_R16G16B16A16_SFLOAT,
|
||||
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
/*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
|
||||
/*.blend = */false,
|
||||
/*.samples = */msaa,
|
||||
});
|
||||
attachments.depth = renderTarget.attach(RenderTarget::Attachment::Descriptor{
|
||||
/*.format = */ext::vulkan::settings::formats::depth,
|
||||
/*.layout = */VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
|
||||
/*.usage = */VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
|
||||
/*.blend = */false,
|
||||
/*.samples = */msaa,
|
||||
});
|
||||
// output buffers
|
||||
attachments.color = renderTarget.attach(RenderTarget::Attachment::Descriptor{
|
||||
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? enums::Format::HDR : enums::Format::SDR,
|
||||
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
/*.blend =*/ blend,
|
||||
/*.samples =*/ 1,
|
||||
});
|
||||
|
||||
metadata.attachments["id"] = attachments.id;
|
||||
metadata.attachments["position"] = attachments.position;
|
||||
metadata.attachments["normal"] = attachments.normal;
|
||||
|
||||
metadata.attachments["depth"] = attachments.depth;
|
||||
metadata.attachments["color"] = attachments.color;
|
||||
metadata.attachments["output"] = attachments.color;
|
||||
|
||||
// First pass: fill the G-Buffer
|
||||
for ( size_t eye = 0; eye < metadata.eyes; ++eye ) {
|
||||
renderTarget.addPass(
|
||||
/*.*/ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
/*.colors =*/ { attachments.id, attachments.uv, attachments.normal },
|
||||
/*.inputs =*/ {},
|
||||
/*.resolve =*/{},
|
||||
/*.depth = */ attachments.depth,
|
||||
/*.layer = */eye,
|
||||
/*.autoBuildPipeline =*/ true
|
||||
);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
for ( size_t currentPass = 0; currentPass < metadata.subpasses; ++currentPass ) {
|
||||
struct {
|
||||
@ -331,8 +396,8 @@ void ext::vulkan::RenderTargetRenderMode::tick() {
|
||||
bool resized = this->width == 0 && this->height == 0 && (ext::vulkan::states::resized || this->resized);
|
||||
bool rebuild = resized || ext::vulkan::states::rebuild || this->rebuild;
|
||||
|
||||
uint32_t width = this->width > 0 ? this->width : ext::vulkan::settings::width;
|
||||
uint32_t height = this->height > 0 ? this->height : ext::vulkan::settings::height;
|
||||
uint32_t width = this->width > 0 ? this->width : (ext::vulkan::settings::width * this->scale);
|
||||
uint32_t height = this->height > 0 ? this->height : (ext::vulkan::settings::height * this->scale);
|
||||
|
||||
if ( resized ) {
|
||||
this->resized = false;
|
||||
@ -397,8 +462,8 @@ void ext::vulkan::RenderTargetRenderMode::pipelineBarrier( VkCommandBuffer comma
|
||||
}
|
||||
void ext::vulkan::RenderTargetRenderMode::createCommandBuffers( const uf::stl::vector<ext::vulkan::Graphic*>& graphics ) {
|
||||
// destroy if exists
|
||||
float width = this->width > 0 ? this->width : ext::vulkan::settings::width;
|
||||
float height = this->height > 0 ? this->height : ext::vulkan::settings::height;
|
||||
uint32_t width = this->width > 0 ? this->width : (ext::vulkan::settings::width * this->scale);
|
||||
uint32_t height = this->height > 0 ? this->height : (ext::vulkan::settings::height * this->scale);
|
||||
|
||||
VkCommandBufferBeginInfo cmdBufInfo = {};
|
||||
cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||
|
||||
@ -25,8 +25,8 @@ size_t ext::vulkan::RenderTarget::attach( const Attachment::Descriptor& descript
|
||||
if ( this->views == 0 ) this->views = 1;
|
||||
|
||||
size_t index = attachments.size();
|
||||
uint32_t width = this->width > 0 ? this->width : ext::vulkan::settings::width;
|
||||
uint32_t height = this->height > 0 ? this->height : ext::vulkan::settings::height;
|
||||
uint32_t width = this->width > 0 ? this->width : (ext::vulkan::settings::width * this->scale);
|
||||
uint32_t height = this->height > 0 ? this->height : (ext::vulkan::settings::height * this->scale);
|
||||
|
||||
if ( attachment ) {
|
||||
for ( auto& view : attachment->views ) vkDestroyImageView(*device, view, nullptr);
|
||||
@ -149,8 +149,8 @@ size_t ext::vulkan::RenderTarget::attach( const Attachment::Descriptor& descript
|
||||
void ext::vulkan::RenderTarget::initialize( Device& device ) {
|
||||
// Bind
|
||||
this->device = &device;
|
||||
uint32_t width = this->width > 0 ? this->width : ext::vulkan::settings::width;
|
||||
uint32_t height = this->height > 0 ? this->height : ext::vulkan::settings::height;
|
||||
uint32_t width = this->width > 0 ? this->width : (ext::vulkan::settings::width * this->scale);
|
||||
uint32_t height = this->height > 0 ? this->height : (ext::vulkan::settings::height * this->scale);
|
||||
|
||||
// resize attachments if necessary
|
||||
if ( initialized ) {
|
||||
|
||||
@ -31,7 +31,7 @@ size_t ext::vulkan::settings::viewCount = 2;
|
||||
size_t ext::vulkan::settings::gpuID = -1;
|
||||
size_t ext::vulkan::settings::scratchBufferAlignment = 256;
|
||||
size_t ext::vulkan::settings::scratchBufferInitialSize = 1024 * 1024;
|
||||
size_t ext::vulkan::settings::defaultTimeout = 100000000000;
|
||||
size_t ext::vulkan::settings::defaultTimeout = UINT64_MAX; // 100000000000;
|
||||
|
||||
uf::stl::vector<uf::stl::string> ext::vulkan::settings::validationFilters;
|
||||
uf::stl::vector<uf::stl::string> ext::vulkan::settings::requestedDeviceFeatures;
|
||||
@ -229,11 +229,22 @@ uf::stl::vector<ext::vulkan::RenderMode*> ext::vulkan::getRenderModes( const uf:
|
||||
}
|
||||
uf::stl::vector<ext::vulkan::RenderMode*> ext::vulkan::getRenderModes( const uf::stl::vector<uf::stl::string>& names, bool isName ) {
|
||||
uf::stl::vector<RenderMode*> targets;
|
||||
#if 1
|
||||
// this way keeps the render mode ordered as requested
|
||||
for ( auto& name : names ) {
|
||||
for ( auto& renderMode: renderModes ) {
|
||||
if ( (isName && renderMode->getName() == name) || (!isName && renderMode->getType() == name) ) {
|
||||
targets.emplace_back( renderMode );
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
for ( auto& renderMode: renderModes ) {
|
||||
if ( ( isName && std::find(names.begin(), names.end(), renderMode->getName()) != names.end() ) || std::find(names.begin(), names.end(), renderMode->getType()) != names.end() ) {
|
||||
targets.push_back(renderMode);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return targets;
|
||||
}
|
||||
void ext::vulkan::removeRenderMode( ext::vulkan::RenderMode* mode, bool free ) {
|
||||
@ -447,7 +458,7 @@ void ext::vulkan::tick() {
|
||||
}
|
||||
void ext::vulkan::render() {
|
||||
if ( ext::vulkan::states::frameSkip ) {
|
||||
ext::vulkan::states::frameSkip = false;
|
||||
// ext::vulkan::states::frameSkip = false;
|
||||
return;
|
||||
}
|
||||
ext::vulkan::mutex.lock();
|
||||
@ -543,7 +554,7 @@ void ext::vulkan::render() {
|
||||
}
|
||||
#if UF_USE_FFX_FSR
|
||||
if ( settings::pipelines::fsr ) {
|
||||
ext::fsr::tick();
|
||||
ext::fsr::render();
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -556,6 +567,14 @@ void ext::vulkan::render() {
|
||||
for ( auto& renderMode : renderModes ) {
|
||||
if ( !renderMode || !renderMode->execute || !renderMode->metadata.limiter.execute ) continue;
|
||||
|
||||
if ( renderMode->getName() == "Swapchain" ) {
|
||||
#if UF_USE_FFX_FSR
|
||||
if ( settings::pipelines::fsr ) {
|
||||
ext::fsr::render();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// renderMode->lockMutex( renderMode->mostRecentCommandPoolId );
|
||||
// auto guard = renderMode->guardMutex( renderMode->mostRecentCommandPoolId );
|
||||
ext::vulkan::setCurrentRenderMode(renderMode);
|
||||
|
||||
@ -17,8 +17,14 @@
|
||||
|
||||
#define UF_BAKER_SAVE_MULTITHREAD 0
|
||||
|
||||
namespace {
|
||||
bool accumulated = false;
|
||||
size_t frames = 0;
|
||||
size_t totalIDs = 0;
|
||||
}
|
||||
|
||||
UF_BEHAVIOR_REGISTER_CPP(ext::BakingBehavior)
|
||||
UF_BEHAVIOR_TRAITS_CPP(ext::BakingBehavior, ticks = true, renders = false, multithread = true)
|
||||
UF_BEHAVIOR_TRAITS_CPP(ext::BakingBehavior, ticks = true, renders = false, multithread = false)
|
||||
#define this (&self)
|
||||
void ext::BakingBehavior::initialize( uf::Object& self ) {
|
||||
#if UF_USE_VULKAN
|
||||
@ -37,6 +43,12 @@ void ext::BakingBehavior::initialize( uf::Object& self ) {
|
||||
sceneMetadata.shadow.update = metadata.max.shadows;
|
||||
UF_MSG_DEBUG("Temporarily altering shadow limits...");
|
||||
|
||||
{
|
||||
metadata.uniforms.lights = metadata.max.shadows;
|
||||
metadata.uniforms.currentID = 0;
|
||||
metadata.buffers.uniforms.initialize( (const void*) &metadata.uniforms, sizeof(metadata.uniforms), uf::renderer::enums::Buffer::UNIFORM );
|
||||
}
|
||||
|
||||
this->addHook( "entity:PostInitialization.%UID%", [&](){
|
||||
metadata.output = this->resolveURI( metadataJson["baking"]["output"].as<uf::stl::string>(), metadataJson["baking"]["root"].as<uf::stl::string>() );
|
||||
metadata.renderModeName = "B:" + std::to_string((int) this->getUid());
|
||||
@ -76,17 +88,23 @@ void ext::BakingBehavior::initialize( uf::Object& self ) {
|
||||
for ( auto& texture : uf::graph::storage.shadow2Ds ) textures2D.emplace_back().aliasTexture(texture);
|
||||
for ( auto& texture : uf::graph::storage.shadowCubes ) texturesCube.emplace_back().aliasTexture(texture);
|
||||
|
||||
::totalIDs = uf::graph::storage.instances.keys.size();
|
||||
|
||||
metadata.buffers.baked.fromBuffers( NULL, 0, uf::renderer::enums::Format::R8G8B8A8_UNORM, metadata.size.x, metadata.size.y, metadata.max.layers, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
|
||||
|
||||
scene.process([&]( uf::Entity* entity ) {
|
||||
if ( !entity->hasComponent<uf::Graphic>() ) return;
|
||||
auto& graphic = entity->getComponent<uf::Graphic>();
|
||||
if ( !graphic.material.hasShader("fragment", "baking") ) return;
|
||||
|
||||
auto& shader = graphic.material.getShader("fragment", "baking");
|
||||
|
||||
for ( auto& t : textures2D ) shader.textures.emplace_back().aliasTexture( t );
|
||||
for ( auto& t : texturesCube ) shader.textures.emplace_back().aliasTexture( t );
|
||||
|
||||
shader.textures.emplace_back().aliasTexture( metadata.buffers.baked );
|
||||
|
||||
shader.buffers.insert( shader.buffers.begin(), metadata.buffers.uniforms.alias() );
|
||||
});
|
||||
// uf::thread::queue([&]{
|
||||
uf::renderer::addRenderMode( &renderMode, metadata.renderModeName );
|
||||
@ -98,13 +116,30 @@ void ext::BakingBehavior::initialize( uf::Object& self ) {
|
||||
#endif
|
||||
}
|
||||
void ext::BakingBehavior::tick( uf::Object& self ) {
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto& sceneMetadata = scene.getComponent<ext::ExtSceneBehavior::Metadata>();
|
||||
|
||||
#if UF_USE_VULKAN
|
||||
if ( !this->hasComponent<uf::renderer::RenderTargetRenderMode>() ) return;
|
||||
auto& metadata = this->getComponent<ext::BakingBehavior::Metadata>();
|
||||
auto& renderMode = this->getComponent<uf::renderer::RenderTargetRenderMode>();
|
||||
if ( renderMode.executed && !metadata.initialized.renderMode ) goto PREPARE;
|
||||
else if ( renderMode.executed && !metadata.initialized.map ) {
|
||||
TIMER(1.0, (metadata.trigger.mode == "rendered" || (metadata.trigger.mode == "key" && uf::Window::isKeyPressed(metadata.trigger.value))) ) {
|
||||
sceneMetadata.shadow.update = metadata.previous.update;
|
||||
{
|
||||
if ( metadata.uniforms.currentID == ::totalIDs ) {
|
||||
if ( !accumulated ) {
|
||||
accumulated = true;
|
||||
renderMode.execute = false;
|
||||
UF_MSG_DEBUG("Finished accumulating lightmaps");
|
||||
}
|
||||
} else {
|
||||
UF_MSG_DEBUG("Baking instance ID {} / {}", metadata.uniforms.currentID, ::totalIDs);
|
||||
metadata.buffers.uniforms.update( (const void*) &metadata.uniforms, sizeof(metadata.uniforms) );
|
||||
++metadata.uniforms.currentID;
|
||||
}
|
||||
}
|
||||
TIMER(1.0, accumulated && (metadata.trigger.mode == "rendered" || (metadata.trigger.mode == "key" && uf::Window::isKeyPressed(metadata.trigger.value))) ) {
|
||||
goto SAVE;
|
||||
}
|
||||
}
|
||||
@ -142,11 +177,9 @@ SAVE: {
|
||||
uf::thread::execute( tasks );
|
||||
|
||||
UF_MSG_DEBUG("Baked.");
|
||||
// ext::vulkan::states::frameSkip = false;
|
||||
metadata.initialized.map = true;
|
||||
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto& sceneMetadata = scene.getComponent<ext::ExtSceneBehavior::Metadata>();
|
||||
|
||||
sceneMetadata.light.max = metadata.previous.lights;
|
||||
sceneMetadata.shadow.max = metadata.previous.shadows;
|
||||
sceneMetadata.shadow.update = metadata.previous.update;
|
||||
|
||||
@ -25,7 +25,14 @@ namespace ext {
|
||||
size_t light = 0;
|
||||
|
||||
uf::renderer::Texture3D baked;
|
||||
uf::renderer::Buffer uniforms;
|
||||
} buffers;
|
||||
struct UBO {
|
||||
alignas(4) uint32_t lights = 0;
|
||||
alignas(4) uint32_t currentID = 0;
|
||||
alignas(4) uint32_t totalIDs = 0;
|
||||
alignas(4) uint32_t padding2 = 0;
|
||||
} uniforms;
|
||||
struct {
|
||||
size_t textures2D = 1024;
|
||||
size_t texturesCube = 512;
|
||||
|
||||
@ -251,11 +251,14 @@ void ext::LightBehavior::Metadata::serialize( uf::Object& self, uf::Serializer&
|
||||
serializer["system"]["renderer"]["mode"] = /*this->*/renderer.mode;
|
||||
serializer["light"]["external update"] = /*this->*/renderer.external;
|
||||
// serializer["system"]["renderer"]["timer"] = /*this->*/renderer.limiter;
|
||||
switch ( /*this->*/type ) {
|
||||
switch ( abs(/*this->*/type) ) {
|
||||
case 0: serializer["light"]["type"] = "point"; break;
|
||||
case 1: serializer["light"]["type"] = "point"; break;
|
||||
case 2: serializer["light"]["type"] = "spot"; break;
|
||||
}
|
||||
if ( type < 0 ) {
|
||||
serializer["light"]["dynamic"] = true;
|
||||
}
|
||||
}
|
||||
void ext::LightBehavior::Metadata::deserialize( uf::Object& self, uf::Serializer& serializer ){
|
||||
/*this->*/color = uf::vector::decode( serializer["light"]["color"], /*this->*/color );
|
||||
@ -268,16 +271,13 @@ void ext::LightBehavior::Metadata::deserialize( uf::Object& self, uf::Serializer
|
||||
/*this->*/renderer.external = serializer["light"]["external update"].as(/*this->*/renderer.external);
|
||||
// /*this->*/renderer.limiter = serializer["system"]["renderer"]["timer"].as<float>(/*this->*/renderer.limiter);
|
||||
|
||||
if ( serializer["light"]["type"].is<size_t>() ) {
|
||||
if ( serializer["light"]["type"].is<int32_t>() ) {
|
||||
/*this->*/type = serializer["light"]["type"].as(/*this->*/type);
|
||||
if ( serializer["light"]["dynamic"].as<bool>() ) /*this->*/type = -/*this->*/type;
|
||||
|
||||
} else if ( serializer["light"]["type"].is<uf::stl::string>() ) {
|
||||
|
||||
uf::stl::string lightType = serializer["light"]["type"].as<uf::stl::string>();
|
||||
if ( lightType == "point" ) /*this->*/type = 1;
|
||||
else if ( lightType == "spot" ) /*this->*/type = 2;
|
||||
if ( serializer["light"]["dynamic"].as<bool>() ) /*this->*/type = -/*this->*/type;
|
||||
}
|
||||
if ( serializer["light"]["dynamic"].as<bool>() ) /*this->*/type = -/*this->*/type;
|
||||
}
|
||||
#undef this
|
||||
@ -28,54 +28,60 @@ UF_BEHAVIOR_TRAITS_CPP(ext::RayTraceSceneBehavior, ticks = true, renders = false
|
||||
void ext::RayTraceSceneBehavior::initialize( uf::Object& self ) {
|
||||
auto& metadata = this->getComponent<ext::RayTraceSceneBehavior::Metadata>();
|
||||
auto& metadataJson = this->getComponent<uf::Serializer>();
|
||||
|
||||
if ( !uf::renderer::hasRenderMode("Compute:RT", true) ) {
|
||||
auto* renderMode = new uf::renderer::RenderTargetRenderMode;
|
||||
renderMode->setTarget("Compute:RT");
|
||||
|
||||
|
||||
{
|
||||
uf::stl::string vertexShaderFilename = "/shaders/display/renderTarget/vert.spv";
|
||||
uf::stl::string fragmentShaderFilename = "/shaders/display/renderTarget/frag.spv";
|
||||
|
||||
std::pair<bool, uf::stl::string> settings[] = {
|
||||
{ uf::renderer::settings::pipelines::postProcess, "postProcess.frag" },
|
||||
// { msaa > 1, "msaa.frag" },
|
||||
};
|
||||
FOR_ARRAY( settings ) if ( settings[i].first ) fragmentShaderFilename = uf::string::replace( fragmentShaderFilename, "frag", settings[i].second );
|
||||
|
||||
renderMode->metadata.json["shaders"]["vertex"] = vertexShaderFilename;
|
||||
renderMode->metadata.json["shaders"]["fragment"] = fragmentShaderFilename;
|
||||
}
|
||||
|
||||
renderMode->blitter.descriptor.renderMode = "Swapchain";
|
||||
renderMode->blitter.descriptor.subpass = 0;
|
||||
|
||||
renderMode->metadata.type = uf::renderer::settings::pipelines::names::rt;
|
||||
renderMode->metadata.pipelines.emplace_back(uf::renderer::settings::pipelines::names::rt);
|
||||
renderMode->execute = false;
|
||||
renderMode->metadata.limiter.execute = false;
|
||||
// renderMode->blitter.process = false;
|
||||
uf::renderer::addRenderMode( renderMode, "Compute:RT" );
|
||||
}
|
||||
#if !UF_USE_EXTERNAL_IMAGE
|
||||
#else
|
||||
{
|
||||
uf::stl::vector<uint8_t> pixels = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
::emptyTexture.sampler.descriptor.filter.min = VK_FILTER_NEAREST;
|
||||
::emptyTexture.sampler.descriptor.filter.mag = VK_FILTER_NEAREST;
|
||||
::emptyTexture.fromBuffers( (void*) &pixels[0], pixels.size(), ext::vulkan::enums::Format::R8G8B8A8_UNORM, 2, 2, ext::vulkan::device, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
|
||||
|
||||
auto& renderMode = uf::renderer::getRenderMode("Compute:RT", true);
|
||||
auto& blitter = *renderMode.getBlitter();
|
||||
blitter.material.textures.emplace_back().aliasTexture( ::emptyTexture );
|
||||
}
|
||||
#endif
|
||||
|
||||
UF_BEHAVIOR_METADATA_BIND_SERIALIZER_HOOKS(metadata, metadataJson);
|
||||
|
||||
if ( metadata.renderer.full ) {
|
||||
if ( !uf::renderer::hasRenderMode("Compute:RT", true) ) {
|
||||
auto* renderMode = new uf::renderer::RenderTargetRenderMode;
|
||||
renderMode->setTarget("Compute:RT");
|
||||
|
||||
{
|
||||
uf::stl::string vertexShaderFilename = "/shaders/display/renderTarget/vert.spv";
|
||||
uf::stl::string fragmentShaderFilename = "/shaders/display/renderTarget/frag.spv";
|
||||
|
||||
std::pair<bool, uf::stl::string> settings[] = {
|
||||
{ uf::renderer::settings::pipelines::postProcess, "postProcess.frag" },
|
||||
// { msaa > 1, "msaa.frag" },
|
||||
};
|
||||
FOR_ARRAY( settings ) if ( settings[i].first ) fragmentShaderFilename = uf::string::replace( fragmentShaderFilename, "frag", settings[i].second );
|
||||
|
||||
renderMode->metadata.json["shaders"]["vertex"] = vertexShaderFilename;
|
||||
renderMode->metadata.json["shaders"]["fragment"] = fragmentShaderFilename;
|
||||
}
|
||||
|
||||
renderMode->blitter.descriptor.renderMode = "Swapchain";
|
||||
renderMode->blitter.descriptor.subpass = 0;
|
||||
|
||||
renderMode->metadata.type = uf::renderer::settings::pipelines::names::rt;
|
||||
renderMode->metadata.pipelines.emplace_back(uf::renderer::settings::pipelines::names::rt);
|
||||
renderMode->execute = false;
|
||||
renderMode->metadata.limiter.execute = false;
|
||||
// renderMode->blitter.process = false;
|
||||
uf::renderer::addRenderMode( renderMode, "Compute:RT" );
|
||||
}
|
||||
#if UF_USE_EXTERNAL_IMAGE
|
||||
{
|
||||
uf::stl::vector<uint8_t> pixels = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
::emptyTexture.sampler.descriptor.filter.min = VK_FILTER_NEAREST;
|
||||
::emptyTexture.sampler.descriptor.filter.mag = VK_FILTER_NEAREST;
|
||||
::emptyTexture.fromBuffers(
|
||||
(void*) &pixels[0],
|
||||
pixels.size(),
|
||||
uf::renderer::enums::Format::R8G8B8A8_UNORM,
|
||||
2, 2,
|
||||
uf::renderer::device,
|
||||
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL
|
||||
);
|
||||
|
||||
auto& renderMode = uf::renderer::getRenderMode("Compute:RT", true);
|
||||
auto& blitter = *renderMode.getBlitter();
|
||||
blitter.material.textures.emplace_back().aliasTexture( ::emptyTexture );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
void ext::RayTraceSceneBehavior::tick( uf::Object& self ) {
|
||||
auto& metadata = this->getComponent<ext::RayTraceSceneBehavior::Metadata>();
|
||||
@ -97,9 +103,12 @@ void ext::RayTraceSceneBehavior::tick( uf::Object& self ) {
|
||||
if ( graphics.empty() ) return;
|
||||
|
||||
bool update = false;
|
||||
auto& graphic = this->getComponent<uf::renderer::Graphic>();
|
||||
auto& renderMode = uf::renderer::getRenderMode("", true);
|
||||
auto& graphic = metadata.renderer.full ? this->getComponent<uf::renderer::Graphic>() : *renderMode.getBlitter();
|
||||
if ( !metadata.renderer.bound ) {
|
||||
graphic.initialize("Compute:RT");
|
||||
if ( metadata.renderer.full ) {
|
||||
graphic.initialize("Compute:RT");
|
||||
}
|
||||
update = true;
|
||||
} else {
|
||||
if ( previousInstances.size() != instances.size() ) update = true;
|
||||
@ -116,6 +125,7 @@ void ext::RayTraceSceneBehavior::tick( uf::Object& self ) {
|
||||
|
||||
auto& sceneMetadata = this->getComponent<ext::ExtSceneBehavior::Metadata>();
|
||||
sceneMetadata.shader.frameAccumulateReset = true;
|
||||
uf::renderer::states::frameAccumulateReset = true;
|
||||
|
||||
previousInstances = instances;
|
||||
previousGraphics = graphics;
|
||||
@ -123,166 +133,156 @@ void ext::RayTraceSceneBehavior::tick( uf::Object& self ) {
|
||||
|
||||
if ( !metadata.renderer.bound ) {
|
||||
if ( graphic.material.hasShader("ray:gen", uf::renderer::settings::pipelines::names::rt) ) {
|
||||
#if !UF_USE_EXTERNAL_IMAGE
|
||||
auto& shader = graphic.material.getShader("ray:gen", uf::renderer::settings::pipelines::names::rt);
|
||||
auto& renderMode = uf::renderer::getRenderMode("Compute:RT", true);
|
||||
shader.aliasAttachment("color", &renderMode, VK_IMAGE_LAYOUT_GENERAL);
|
||||
shader.aliasAttachment("bright", &renderMode, VK_IMAGE_LAYOUT_GENERAL);
|
||||
shader.aliasAttachment("motion", &renderMode, VK_IMAGE_LAYOUT_GENERAL);
|
||||
metadata.renderer.bound = true;
|
||||
if ( metadata.renderer.full ) {
|
||||
graphic.process = false;
|
||||
auto& shader = graphic.material.getShader("ray:gen", uf::renderer::settings::pipelines::names::rt);
|
||||
#if !UF_USE_EXTERNAL_IMAGE
|
||||
auto& renderMode = uf::renderer::getRenderMode("Compute:RT", true);
|
||||
shader.aliasAttachment("color", &renderMode, VK_IMAGE_LAYOUT_GENERAL);
|
||||
shader.aliasAttachment("bright", &renderMode, VK_IMAGE_LAYOUT_GENERAL);
|
||||
shader.aliasAttachment("motion", &renderMode, VK_IMAGE_LAYOUT_GENERAL);
|
||||
|
||||
graphic.descriptor.bind.width = renderMode.width > 0 ? renderMode.width : ext::vulkan::settings::width;
|
||||
graphic.descriptor.bind.height = renderMode.height > 0 ? renderMode.height : ext::vulkan::settings::height;
|
||||
graphic.descriptor.bind.point = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;
|
||||
graphic.descriptor.pipeline = uf::renderer::settings::pipelines::names::rt;
|
||||
#else
|
||||
auto& shader = graphic.material.getShader("ray:gen", uf::renderer::settings::pipelines::names::rt);
|
||||
//
|
||||
pod::Vector2ui size = metadata.renderer.size;
|
||||
UF_MSG_DEBUG("Size: {}", uf::vector::toString( size ));
|
||||
if ( size.x == 0 ) size.x = uf::renderer::settings::width; // * metadata.renderer.scale;
|
||||
if ( size.y == 0 ) size.y = uf::renderer::settings::height; // * metadata.renderer.scale;
|
||||
UF_MSG_DEBUG("Size: {}", uf::vector::toString( size ));
|
||||
graphic.descriptor.bind.width = renderMode.width > 0 ? renderMode.width : uf::renderer::settings::width;
|
||||
graphic.descriptor.bind.height = renderMode.height > 0 ? renderMode.height : uf::renderer::settings::height;
|
||||
graphic.descriptor.bind.point = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;
|
||||
graphic.descriptor.pipeline = uf::renderer::settings::pipelines::names::rt;
|
||||
#else
|
||||
//
|
||||
pod::Vector2ui size = metadata.renderer.size;
|
||||
if ( size.x == 0 ) size.x = uf::renderer::settings::width;
|
||||
if ( size.y == 0 ) size.y = uf::renderer::settings::height;
|
||||
|
||||
auto HDR_FORMAT = uf::renderer::enums::Format::R32G32B32A32_SFLOAT;
|
||||
auto SDR_FORMAT = uf::renderer::enums::Format::R16G16B16A16_SFLOAT; // uf::renderer::enums::Format::R8G8B8A8_UNORM
|
||||
auto& image = shader.textures.emplace_back();
|
||||
image.fromBuffers(
|
||||
NULL, 0,
|
||||
uf::renderer::settings::pipelines::hdr ? uf::renderer::enums::Format::HDR : uf::renderer::enums::Format::SDR,
|
||||
size.x, size.y, 1, 1,
|
||||
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL
|
||||
);
|
||||
|
||||
auto& image = shader.textures.emplace_back();
|
||||
image.fromBuffers(
|
||||
NULL, 0,
|
||||
uf::renderer::settings::pipelines::hdr ? HDR_FORMAT : SDR_FORMAT,
|
||||
size.x, size.y, 1, 1,
|
||||
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL
|
||||
);
|
||||
graphic.descriptor.pipeline = uf::renderer::settings::pipelines::names::rt;
|
||||
graphic.descriptor.bind.width = image.width;
|
||||
graphic.descriptor.bind.height = image.height;
|
||||
graphic.descriptor.bind.point = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;
|
||||
#endif
|
||||
|
||||
graphic.descriptor.pipeline = uf::renderer::settings::pipelines::names::rt;
|
||||
graphic.descriptor.bind.width = image.width;
|
||||
graphic.descriptor.bind.height = image.height;
|
||||
graphic.descriptor.bind.point = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;
|
||||
#endif
|
||||
//
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto& sceneMetadataJson = scene.getComponent<uf::Serializer>();
|
||||
size_t maxLights = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["lights"]["max"].as<size_t>(512);
|
||||
size_t maxTextures2D = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["2D"].as<size_t>(512);
|
||||
size_t maxTexturesCube = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["cube"].as<size_t>(128);
|
||||
size_t maxTextures3D = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["3D"].as<size_t>(1);
|
||||
size_t maxCascades = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["vxgi"]["cascades"].as<size_t>(16);
|
||||
|
||||
//
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto& sceneMetadataJson = scene.getComponent<uf::Serializer>();
|
||||
size_t maxLights = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["lights"]["max"].as<size_t>(512);
|
||||
size_t maxTextures2D = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["2D"].as<size_t>(512);
|
||||
size_t maxTexturesCube = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["cube"].as<size_t>(128);
|
||||
size_t maxTextures3D = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["3D"].as<size_t>(1);
|
||||
size_t maxCascades = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["vxgi"]["cascades"].as<size_t>(16);
|
||||
shader.buffers.emplace_back( uf::graph::storage.buffers.instance.alias() );
|
||||
shader.buffers.emplace_back( uf::graph::storage.buffers.instanceAddresses.alias() );
|
||||
shader.buffers.emplace_back( uf::graph::storage.buffers.material.alias() );
|
||||
shader.buffers.emplace_back( uf::graph::storage.buffers.texture.alias() );
|
||||
shader.buffers.emplace_back( uf::graph::storage.buffers.light.alias() );
|
||||
|
||||
shader.buffers.emplace_back( uf::graph::storage.buffers.instance.alias() );
|
||||
shader.buffers.emplace_back( uf::graph::storage.buffers.instanceAddresses.alias() );
|
||||
shader.buffers.emplace_back( uf::graph::storage.buffers.material.alias() );
|
||||
shader.buffers.emplace_back( uf::graph::storage.buffers.texture.alias() );
|
||||
shader.buffers.emplace_back( uf::graph::storage.buffers.light.alias() );
|
||||
uint32_t* specializationConstants = (uint32_t*) (void*) shader.specializationConstants;
|
||||
for ( auto pair : shader.metadata.definitions.specializationConstants ) {
|
||||
auto& sc = pair.second;
|
||||
if ( sc.name == "TEXTURES" ) sc.value.ui = (specializationConstants[sc.index] = maxTextures2D);
|
||||
else if ( sc.name == "CUBEMAPS" ) sc.value.ui = (specializationConstants[sc.index] = maxTexturesCube);
|
||||
else if ( sc.name == "CASCADES" ) sc.value.ui = (specializationConstants[sc.index] = maxCascades);
|
||||
}
|
||||
for ( auto pair : shader.metadata.definitions.textures ) {
|
||||
auto& tx = pair.second;
|
||||
for ( auto& layout : shader.descriptorSetLayoutBindings ) {
|
||||
if ( layout.binding != tx.binding ) continue;
|
||||
if ( tx.name == "samplerTextures" ) layout.descriptorCount = maxTextures2D;
|
||||
else if ( tx.name == "samplerCubemaps" ) layout.descriptorCount = maxTexturesCube;
|
||||
else if ( tx.name == "voxelId" ) layout.descriptorCount = maxCascades;
|
||||
else if ( tx.name == "voxelUv" ) layout.descriptorCount = maxCascades;
|
||||
else if ( tx.name == "voxelNormal" ) layout.descriptorCount = maxCascades;
|
||||
else if ( tx.name == "voxelRadiance" ) layout.descriptorCount = maxCascades;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t* specializationConstants = (uint32_t*) (void*) shader.specializationConstants;
|
||||
for ( auto pair : shader.metadata.definitions.specializationConstants ) {
|
||||
auto& sc = pair.second;
|
||||
if ( sc.name == "TEXTURES" ) sc.value.ui = (specializationConstants[sc.index] = maxTextures2D);
|
||||
else if ( sc.name == "CUBEMAPS" ) sc.value.ui = (specializationConstants[sc.index] = maxTexturesCube);
|
||||
else if ( sc.name == "CASCADES" ) sc.value.ui = (specializationConstants[sc.index] = maxCascades);
|
||||
}
|
||||
for ( auto pair : shader.metadata.definitions.textures ) {
|
||||
auto& tx = pair.second;
|
||||
for ( auto& layout : shader.descriptorSetLayoutBindings ) {
|
||||
if ( layout.binding != tx.binding ) continue;
|
||||
if ( tx.name == "samplerTextures" ) layout.descriptorCount = maxTextures2D;
|
||||
else if ( tx.name == "samplerCubemaps" ) layout.descriptorCount = maxTexturesCube;
|
||||
else if ( tx.name == "voxelId" ) layout.descriptorCount = maxCascades;
|
||||
else if ( tx.name == "voxelUv" ) layout.descriptorCount = maxCascades;
|
||||
else if ( tx.name == "voxelNormal" ) layout.descriptorCount = maxCascades;
|
||||
else if ( tx.name == "voxelRadiance" ) layout.descriptorCount = maxCascades;
|
||||
}
|
||||
}
|
||||
if ( metadata.renderer.full ) {
|
||||
/* Update lights */ {
|
||||
ext::ExtSceneBehavior::bindBuffers( *this, graphic, "ray:gen", uf::renderer::settings::pipelines::names::rt );
|
||||
}
|
||||
if ( !metadata.renderer.bound ) return;
|
||||
#if !UF_USE_EXTERNAL_IMAGE
|
||||
if ( uf::renderer::states::resized ) {
|
||||
auto& renderMode = uf::renderer::getRenderMode("Compute:RT", true);
|
||||
graphic.descriptor.bind.width = renderMode.width > 0 ? renderMode.width : uf::renderer::settings::width;
|
||||
graphic.descriptor.bind.height = renderMode.height > 0 ? renderMode.height : uf::renderer::settings::height;
|
||||
graphic.descriptor.bind.point = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;
|
||||
graphic.descriptor.pipeline = uf::renderer::settings::pipelines::names::rt;
|
||||
graphic.getPipeline().update( graphic );
|
||||
}
|
||||
#else
|
||||
{
|
||||
auto& shader = graphic.material.getShader("ray:gen", uf::renderer::settings::pipelines::names::rt);
|
||||
auto& image = shader.textures.front();
|
||||
|
||||
auto& renderMode = uf::renderer::getRenderMode("Compute:RT", true);
|
||||
auto& blitter = *renderMode.getBlitter();
|
||||
|
||||
if ( blitter.material.hasShader("fragment") ) {
|
||||
auto& shader = blitter.material.getShader("fragment");
|
||||
if ( shader.textures.empty() || ( !shader.textures.empty() && shader.textures.front().image == ::emptyTexture.image ) ) {
|
||||
shader.textures.clear();
|
||||
auto& tex = shader.textures.emplace_back();
|
||||
tex.aliasTexture( image );
|
||||
|
||||
tex.sampler.descriptor.filter.min = metadata.renderer.filter;
|
||||
tex.sampler.descriptor.filter.mag = metadata.renderer.filter;
|
||||
|
||||
renderMode.execute = true;
|
||||
renderMode.metadata.limiter.execute = true;
|
||||
blitter.process = true;
|
||||
graphic.process = true;
|
||||
}
|
||||
}
|
||||
|
||||
metadata.renderer.bound = true;
|
||||
if ( uf::renderer::states::resized ) {
|
||||
pod::Vector2ui size = metadata.renderer.size;
|
||||
if ( size.x == 0 ) size.x = uf::renderer::settings::width;
|
||||
if ( size.y == 0 ) size.y = uf::renderer::settings::height;
|
||||
image.destroy();
|
||||
image.fromBuffers(
|
||||
NULL, 0,
|
||||
uf::renderer::settings::pipelines::hdr ? uf::renderer::enums::Format::HDR : uf::renderer::enums::Format::SDR,
|
||||
size.x, size.y, 1, 1,
|
||||
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL
|
||||
);
|
||||
|
||||
graphic.descriptor.bind.width = image.width;
|
||||
graphic.descriptor.bind.height = image.height;
|
||||
graphic.descriptor.bind.point = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;
|
||||
|
||||
graphic.getPipeline().update( graphic );
|
||||
|
||||
if ( blitter.material.hasShader("fragment") ) {
|
||||
auto& shader = blitter.material.getShader("fragment");
|
||||
shader.textures.front().aliasTexture( image );
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
if ( graphic.material.hasShader("ray:hit:closest", uf::renderer::settings::pipelines::names::rt) ) {
|
||||
auto& shader = graphic.material.getShader("ray:hit:closest", uf::renderer::settings::pipelines::names::rt);
|
||||
shader.buffers.emplace_back( uf::graph::storage.buffers.instanceAddresses.alias() );
|
||||
#endif
|
||||
#if 0
|
||||
TIMER(1.0, uf::Window::isKeyPressed("R") ) {
|
||||
UF_MSG_DEBUG("Screenshotting RT scene...");
|
||||
image.screenshot().save("./data/rt.png");
|
||||
}
|
||||
if ( graphic.material.hasShader("ray:hit:any", uf::renderer::settings::pipelines::names::rt) ) {
|
||||
auto& shader = graphic.material.getShader("ray:hit:any", uf::renderer::settings::pipelines::names::rt);
|
||||
shader.buffers.emplace_back( uf::graph::storage.buffers.instanceAddresses.alias() );
|
||||
}
|
||||
*/
|
||||
|
||||
graphic.process = false;
|
||||
#endif
|
||||
}
|
||||
/* Update lights */ {
|
||||
ext::ExtSceneBehavior::bindBuffers( *this, graphic, "ray:gen", uf::renderer::settings::pipelines::names::rt );
|
||||
}
|
||||
if ( !metadata.renderer.bound ) return;
|
||||
#if !UF_USE_EXTERNAL_IMAGE
|
||||
if ( uf::renderer::states::resized ) {
|
||||
auto& renderMode = uf::renderer::getRenderMode("Compute:RT", true);
|
||||
graphic.descriptor.bind.width = renderMode.width > 0 ? renderMode.width : ext::vulkan::settings::width;
|
||||
graphic.descriptor.bind.height = renderMode.height > 0 ? renderMode.height : ext::vulkan::settings::height;
|
||||
graphic.descriptor.bind.point = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;
|
||||
graphic.descriptor.pipeline = uf::renderer::settings::pipelines::names::rt;
|
||||
graphic.getPipeline().update( graphic );
|
||||
}
|
||||
#else
|
||||
auto& shader = graphic.material.getShader("ray:gen", uf::renderer::settings::pipelines::names::rt);
|
||||
auto& image = shader.textures.front();
|
||||
|
||||
auto& renderMode = uf::renderer::getRenderMode("Compute:RT", true);
|
||||
auto& blitter = *renderMode.getBlitter();
|
||||
|
||||
if ( blitter.material.hasShader("fragment") ) {
|
||||
auto& shader = blitter.material.getShader("fragment");
|
||||
if ( shader.textures.empty() || ( !shader.textures.empty() && shader.textures.front().image == ::emptyTexture.image ) ) {
|
||||
shader.textures.clear();
|
||||
auto& tex = shader.textures.emplace_back();
|
||||
tex.aliasTexture( image );
|
||||
|
||||
tex.sampler.descriptor.filter.min = metadata.renderer.filter;
|
||||
tex.sampler.descriptor.filter.mag = metadata.renderer.filter;
|
||||
|
||||
renderMode.execute = true;
|
||||
renderMode.metadata.limiter.execute = true;
|
||||
blitter.process = true;
|
||||
graphic.process = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( uf::renderer::states::resized ) {
|
||||
pod::Vector2ui size = metadata.renderer.size;
|
||||
if ( size.x == 0 ) size.x = uf::renderer::settings::width * metadata.renderer.scale;
|
||||
if ( size.y == 0 ) size.y = uf::renderer::settings::height * metadata.renderer.scale;
|
||||
image.destroy();
|
||||
image.fromBuffers(
|
||||
NULL, 0,
|
||||
uf::renderer::enums::Format::R8G8B8A8_UNORM,
|
||||
size.x, size.y, 1, 1,
|
||||
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL
|
||||
);
|
||||
|
||||
graphic.descriptor.bind.width = image.width;
|
||||
graphic.descriptor.bind.height = image.height;
|
||||
graphic.descriptor.bind.point = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;
|
||||
|
||||
graphic.getPipeline().update( graphic );
|
||||
|
||||
if ( blitter.material.hasShader("fragment") ) {
|
||||
auto& shader = blitter.material.getShader("fragment");
|
||||
shader.textures.front().aliasTexture( image );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
TIMER(1.0, uf::Window::isKeyPressed("R") ) {
|
||||
UF_MSG_DEBUG("Screenshotting RT scene...");
|
||||
image.screenshot().save("./data/rt.png");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
void ext::RayTraceSceneBehavior::render( uf::Object& self ){}
|
||||
void ext::RayTraceSceneBehavior::destroy( uf::Object& self ){
|
||||
auto& metadata = this->getComponent<ext::RayTraceSceneBehavior::Metadata>();
|
||||
auto& graphic = this->getComponent<uf::renderer::Graphic>();
|
||||
|
||||
if ( !metadata.renderer.full ) return;
|
||||
auto& graphic = this->getComponent<uf::renderer::Graphic>();
|
||||
graphic.destroy();
|
||||
}
|
||||
void ext::RayTraceSceneBehavior::Metadata::serialize( uf::Object& self, uf::Serializer& serializer ) {
|
||||
@ -312,6 +312,8 @@ void ext::RayTraceSceneBehavior::Metadata::deserialize( uf::Object& self, uf::Se
|
||||
} else if ( ext::config["engine"]["ext"]["vulkan"]["framebuffer"]["size"].is<float>() ) {
|
||||
/*this->*/renderer.scale = ext::config["engine"]["ext"]["vulkan"]["framebuffer"]["size"].as(/*this->*/renderer.scale);
|
||||
}
|
||||
|
||||
/*this->*/renderer.full = serializer["rt"]["full"].as(/*this->*/renderer.full);
|
||||
|
||||
/*this->*/settings.defaultRayBounds = uf::vector::decode(serializer["rt"]["defaultRayBounds"], settings.defaultRayBounds); // serializer["rt"]["defaultRayBounds"].as(/*this->*/settings.defaultRayBounds);
|
||||
/*this->*/settings.alphaTestOffset = serializer["rt"]["alphaTestOffset"].as(/*this->*/settings.alphaTestOffset);
|
||||
|
||||
@ -19,6 +19,8 @@ namespace ext {
|
||||
float scale = 1;
|
||||
pod::Vector2ui size{};
|
||||
uf::renderer::enums::Filter::type_t filter = uf::renderer::enums::Filter::NEAREST;
|
||||
|
||||
bool full = true;
|
||||
} renderer;
|
||||
|
||||
struct {
|
||||
|
||||
@ -225,8 +225,8 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
|
||||
metadata.shader.frameAccumulateReset = false;
|
||||
}
|
||||
|
||||
uf::renderer::states::frameAccumulate = metadata.shader.frameAccumulate;
|
||||
uf::renderer::states::frameAccumulateReset = metadata.shader.frameAccumulateReset;
|
||||
// uf::renderer::states::frameAccumulate = metadata.shader.frameAccumulate;
|
||||
// uf::renderer::states::frameAccumulateReset = metadata.shader.frameAccumulateReset;
|
||||
|
||||
/* Print World Tree */ {
|
||||
TIMER(1, uf::inputs::kbm::states::U ) {
|
||||
@ -603,6 +603,28 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
|
||||
ext::ExtSceneBehavior::bindBuffers( *this, "", "fragment", "deferred" );
|
||||
}
|
||||
}
|
||||
|
||||
/* Update post processing */ {
|
||||
auto& renderMode = uf::renderer::getRenderMode("", true);
|
||||
auto& blitter = *renderMode.getBlitter();
|
||||
if ( blitter.material.hasShader("fragment") ) {
|
||||
auto& shader = blitter.material.getShader("fragment");
|
||||
|
||||
struct {
|
||||
float curTime = 0;
|
||||
float gamma = 1.0;
|
||||
float exposure = 1.0;
|
||||
uint32_t padding = 0;
|
||||
} uniforms = {
|
||||
.curTime = uf::time::current,
|
||||
.gamma = metadata.light.gamma,
|
||||
.exposure = metadata.light.exposure
|
||||
};
|
||||
|
||||
|
||||
shader.updateBuffer( (const void*) &uniforms, sizeof(uniforms), shader.getUniformBuffer("UBO") );
|
||||
}
|
||||
}
|
||||
}
|
||||
void ext::ExtSceneBehavior::render( uf::Object& self ) {}
|
||||
void ext::ExtSceneBehavior::destroy( uf::Object& self ) {
|
||||
@ -698,6 +720,7 @@ void ext::ExtSceneBehavior::Metadata::deserialize( uf::Object& self, uf::Seriali
|
||||
/*this->*/light.max = serializer["light"]["max"].as(/*this->*/light.max);
|
||||
/*this->*/light.ambient = uf::vector::decode( serializer["light"]["ambient"], /*this->*/light.ambient);
|
||||
|
||||
if ( uf::renderer::settings::pipelines::fsr ) serializer["light"]["exposure"] = 1;
|
||||
/*this->*/light.exposure = serializer["light"]["exposure"].as(/*this->*/light.exposure);
|
||||
/*this->*/light.gamma = serializer["light"]["gamma"].as(/*this->*/light.gamma);
|
||||
/*this->*/light.useLightmaps = serializer["light"]["useLightmaps"].as(/*this->*/light.useLightmaps);
|
||||
@ -841,9 +864,9 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, uf::renderer::Graphic
|
||||
|
||||
struct Lighting {
|
||||
pod::Vector3f ambient;
|
||||
alignas(4) float padding1;
|
||||
|
||||
alignas(4) uint32_t indexSkybox;
|
||||
|
||||
alignas(4) uint32_t maxShadows;
|
||||
alignas(4) uint32_t shadowSamples;
|
||||
alignas(4) uint32_t useLightmaps;
|
||||
} lighting;
|
||||
@ -941,20 +964,20 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, uf::renderer::Graphic
|
||||
UniformDescriptor uniforms; {
|
||||
for ( auto i = 0; i < 2; ++i ) {
|
||||
#if UF_USE_FFX_FSR
|
||||
auto jitter = ext::fsr::getJitterMatrix();
|
||||
auto projection = ext::fsr::getJitterMatrix() * camera.getProjection(i);
|
||||
#else
|
||||
auto jitter = uf::matrix::identity();
|
||||
auto projection = camera.getProjection(i);
|
||||
#endif
|
||||
uniforms.matrices[i] = UniformDescriptor::Matrices{
|
||||
.view = camera.getView(i),
|
||||
.projection = jitter * camera.getProjection(i),
|
||||
.projection = projection,
|
||||
|
||||
.model = jitter * camera.getProjection(i) * camera.getView(i),
|
||||
.model = projection * camera.getView(i),
|
||||
.previous = camera.getPrevious(i),
|
||||
|
||||
.iView = uf::matrix::inverse( camera.getView(i) ),
|
||||
.iProjection = uf::matrix::inverse( jitter * camera.getProjection(i) ),
|
||||
// .iProjectionView = uf::matrix::inverse( jitter * camera.getProjection(i) * camera.getView(i) ),
|
||||
.iProjection = uf::matrix::inverse( projection ),
|
||||
// .iProjectionView = uf::matrix::inverse( projection * camera.getView(i) ),
|
||||
|
||||
.eyePos = camera.getEye( i ),
|
||||
};
|
||||
@ -976,8 +999,9 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, uf::renderer::Graphic
|
||||
};
|
||||
uniforms.settings.lighting = UniformDescriptor::Settings::Lighting{
|
||||
.ambient = metadata.light.ambient,
|
||||
|
||||
.indexSkybox = indexSkybox,
|
||||
|
||||
.maxShadows = metadata.shadow.max,
|
||||
.shadowSamples = std::min( 0, metadata.shadow.samples ),
|
||||
.useLightmaps = metadata.light.useLightmaps,
|
||||
};
|
||||
@ -1017,7 +1041,6 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, uf::renderer::Graphic
|
||||
.paths = metadataRt.settings.paths, // 1,
|
||||
.frameAccumulationMinimum = metadataRt.settings.frameAccumulationMinimum, // 0,
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
uf::stl::vector<VkImage> previousTextures;
|
||||
@ -1046,6 +1069,7 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, uf::renderer::Graphic
|
||||
bool shouldUpdate2 = !uf::matrix::equals( uniforms.matrices[0].view, previousUniforms.matrices[0].view, 0.0001f );
|
||||
if ( shouldUpdate || shouldUpdate2 ) {
|
||||
metadata.shader.frameAccumulateReset = true;
|
||||
uf::renderer::states::frameAccumulateReset = true;
|
||||
previousUniforms = uniforms;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -33,61 +33,20 @@ void ext::VoxelizerSceneBehavior::initialize( uf::Object& self ) {
|
||||
|
||||
UF_BEHAVIOR_METADATA_BIND_SERIALIZER_HOOKS(metadata, metadataJson);
|
||||
|
||||
// initialize voxel map
|
||||
#if 0
|
||||
{
|
||||
const uint32_t DEFAULT_VOXEL_SIZE = ext::config["engine"]["scenes"]["vxgi"]["size"].as<uint32_t>(256);
|
||||
const float DEFAULT_VOXELIZE_LIMITER = ext::config["engine"]["scenes"]["vxgi"]["limiter"].as<float>(0);
|
||||
const uint32_t DEFAULT_DISPATCH_SIZE = ext::config["engine"]["scenes"]["vxgi"]["dispatch"].as<uint32_t>(8);
|
||||
const uint32_t DEFAULT_CASCADES = ext::config["engine"]["scenes"]["vxgi"]["cascades"].as<uint32_t>(8);
|
||||
const float DEFAULT_CASCADE_POWER = ext::config["engine"]["scenes"]["vxgi"]["cascadePower"].as<float>(1.5);
|
||||
const float DEFAULT_GRANULARITY = ext::config["engine"]["scenes"]["vxgi"]["granularity"].as<float>(2.0);
|
||||
const float DEFAULT_SHADOWS = ext::config["engine"]["scenes"]["vxgi"]["shadows"].as<size_t>(8);
|
||||
const float DEFAULT_PIXEL_SCALE = ext::config["engine"]["scenes"]["vxgi"]["voxelizeScale"].as<float>(1);
|
||||
const float DEFAULT_OCCLUSION_FALLOFF = ext::config["engine"]["scenes"]["vxgi"]["occlusionFalloff"].as<float>(128.0f);
|
||||
|
||||
if ( metadata.voxelSize.x == 0 ) metadata.voxelSize.x = DEFAULT_VOXEL_SIZE;
|
||||
if ( metadata.voxelSize.y == 0 ) metadata.voxelSize.y = DEFAULT_VOXEL_SIZE;
|
||||
if ( metadata.voxelSize.z == 0 ) metadata.voxelSize.z = DEFAULT_VOXEL_SIZE;
|
||||
|
||||
if ( metadata.limiter.frequency == 0 ) metadata.limiter.frequency = DEFAULT_VOXELIZE_LIMITER;
|
||||
|
||||
if ( metadata.dispatchSize.x == 0 ) metadata.dispatchSize.x = DEFAULT_DISPATCH_SIZE;
|
||||
if ( metadata.dispatchSize.y == 0 ) metadata.dispatchSize.y = DEFAULT_DISPATCH_SIZE;
|
||||
if ( metadata.dispatchSize.z == 0 ) metadata.dispatchSize.z = DEFAULT_DISPATCH_SIZE;
|
||||
|
||||
if ( metadata.cascades == 0 ) metadata.cascades = DEFAULT_CASCADES;
|
||||
if ( metadata.cascadePower == 0 ) metadata.cascadePower = DEFAULT_CASCADE_POWER;
|
||||
if ( metadata.granularity == 0 ) metadata.granularity = DEFAULT_GRANULARITY;
|
||||
if ( metadata.voxelizeScale == 0 ) metadata.voxelizeScale = DEFAULT_PIXEL_SCALE;
|
||||
if ( metadata.occlusionFalloff == 0 ) metadata.occlusionFalloff = DEFAULT_OCCLUSION_FALLOFF;
|
||||
if ( metadata.shadows == 0 ) metadata.shadows = DEFAULT_SHADOWS;
|
||||
|
||||
metadata.extents.min = uf::vector::decode( ext::config["engine"]["scenes"]["vxgi"]["extents"]["min"], pod::Vector3f{-32, -32, -32} );
|
||||
metadata.extents.max = uf::vector::decode( ext::config["engine"]["scenes"]["vxgi"]["extents"]["max"], pod::Vector3f{ 32, 32, 32} );
|
||||
|
||||
// uf::stl::vector<uint8_t> empty(metadata.voxelSize.x * metadata.voxelSize.y * metadata.voxelSize.z * sizeof(uint8_t) * 4);
|
||||
}
|
||||
#endif
|
||||
|
||||
for ( size_t i = 0; i < metadata.cascades; ++i ) {
|
||||
const bool HDR = false;
|
||||
auto& id = sceneTextures.voxels.id.emplace_back();
|
||||
// auto& uv = sceneTextures.voxels.uv.emplace_back();
|
||||
auto& normal = sceneTextures.voxels.normal.emplace_back();
|
||||
auto& radiance = sceneTextures.voxels.radiance.emplace_back();
|
||||
// auto& depth = sceneTextures.voxels.depth.emplace_back();
|
||||
|
||||
id.sampler.descriptor.filter.min = uf::renderer::enums::Filter::NEAREST;
|
||||
id.sampler.descriptor.filter.mag = uf::renderer::enums::Filter::NEAREST;
|
||||
|
||||
auto HDR_FORMAT = uf::renderer::enums::Format::R32G32B32A32_SFLOAT;
|
||||
auto SDR_FORMAT = uf::renderer::enums::Format::R16G16B16A16_SFLOAT; // uf::renderer::enums::Format::R8G8B8A8_UNORM
|
||||
|
||||
id.fromBuffers( NULL, 0, uf::renderer::enums::Format::R16G16_UINT, metadata.voxelSize.x, metadata.voxelSize.y, metadata.voxelSize.z, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
|
||||
|
||||
// auto& uv = sceneTextures.voxels.uv.emplace_back();
|
||||
// uv.fromBuffers( NULL, 0, uf::renderer::enums::Format::R16G16_SFLOAT, metadata.voxelSize.x, metadata.voxelSize.y, metadata.voxelSize.z, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
|
||||
auto& normal = sceneTextures.voxels.normal.emplace_back();
|
||||
normal.fromBuffers( NULL, 0, uf::renderer::enums::Format::R16G16_SFLOAT, metadata.voxelSize.x, metadata.voxelSize.y, metadata.voxelSize.z, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
|
||||
radiance.fromBuffers( NULL, 0, uf::renderer::settings::pipelines::hdr ? HDR_FORMAT : SDR_FORMAT, metadata.voxelSize.x, metadata.voxelSize.y, metadata.voxelSize.z, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
|
||||
auto& radiance = sceneTextures.voxels.radiance.emplace_back();
|
||||
radiance.fromBuffers( NULL, 0, uf::renderer::settings::pipelines::hdr ? uf::renderer::enums::Format::HDR : uf::renderer::enums::Format::SDR, metadata.voxelSize.x, metadata.voxelSize.y, metadata.voxelSize.z, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
|
||||
// auto& depth = sceneTextures.voxels.depth.emplace_back();
|
||||
// depth.fromBuffers( (void*) empty.data(), empty.size(), uf::renderer::enums::Format::R16_SFLOAT, metadata.voxelSize.x, metadata.voxelSize.y, metadata.voxelSize.z, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
|
||||
}
|
||||
// initialize render mode
|
||||
@ -108,7 +67,7 @@ void ext::VoxelizerSceneBehavior::initialize( uf::Object& self ) {
|
||||
renderMode.metadata.samples = 1;
|
||||
renderMode.metadata.subpasses = metadata.cascades;
|
||||
|
||||
renderMode.blitter.device = &ext::vulkan::device;
|
||||
renderMode.blitter.device = &uf::renderer::device;
|
||||
renderMode.width = metadata.fragmentSize.x;
|
||||
renderMode.height = metadata.fragmentSize.y;
|
||||
|
||||
@ -118,9 +77,6 @@ void ext::VoxelizerSceneBehavior::initialize( uf::Object& self ) {
|
||||
if ( renderMode.metadata.samples > 1 ) {
|
||||
computeShaderFilename = uf::string::replace( computeShaderFilename, "comp", "msaa.comp" );
|
||||
}
|
||||
// if ( uf::renderer::settings::invariant::deferredSampling ) {
|
||||
// computeShaderFilename = uf::string::replace( computeShaderFilename, "comp", "deferredSampling.comp" );
|
||||
// }
|
||||
renderMode.metadata.json["shaders"]["compute"] = computeShaderFilename;
|
||||
renderMode.blitter.descriptor.renderMode = metadata.renderModeName;
|
||||
renderMode.blitter.descriptor.subpass = -1;
|
||||
@ -128,13 +84,6 @@ void ext::VoxelizerSceneBehavior::initialize( uf::Object& self ) {
|
||||
renderMode.blitter.descriptor.bind.height = metadata.voxelSize.y;
|
||||
renderMode.blitter.descriptor.bind.depth = metadata.voxelSize.z;
|
||||
renderMode.blitter.descriptor.bind.point = VK_PIPELINE_BIND_POINT_COMPUTE;
|
||||
/*
|
||||
renderMode.blitter.descriptor.bind.dispatch = {
|
||||
(metadata.voxelSize.x / metadata.dispatchSize.x),
|
||||
(metadata.voxelSize.y / metadata.dispatchSize.y),
|
||||
(metadata.voxelSize.z / metadata.dispatchSize.z),
|
||||
};
|
||||
*/
|
||||
renderMode.blitter.process = true;
|
||||
|
||||
size_t maxTextures2D = ext::config["engine"]["scenes"]["textures"]["max"]["2D"].as<size_t>(512);
|
||||
@ -305,6 +254,7 @@ void ext::VoxelizerSceneBehavior::tick( uf::Object& self ) {
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
ext::ExtSceneBehavior::bindBuffers( scene, metadata.renderModeName, "compute", "" );
|
||||
|
||||
auto& deferredRenderMode = uf::renderer::getRenderMode("", true);
|
||||
|
||||
@ -54,6 +54,7 @@ void ext::GuiManagerBehavior::initialize( uf::Object& self ) {
|
||||
if ( !uf::renderer::hasRenderMode( "Gui", true ) ) {
|
||||
auto& renderMode = this->getComponent<uf::renderer::RenderTargetRenderMode>();
|
||||
uf::stl::string name = "Gui";
|
||||
renderMode.blitter.descriptor.renderMode = "Swapchain";
|
||||
renderMode.blitter.descriptor.subpass = 0;
|
||||
renderMode.metadata.type = "single";
|
||||
uf::renderer::addRenderMode( &renderMode, name );
|
||||
@ -68,6 +69,19 @@ void ext::GuiManagerBehavior::initialize( uf::Object& self ) {
|
||||
this->addHook( "window:Resized", [&](pod::payloads::windowResized& payload){
|
||||
ext::gui::size.current = payload.window.size;
|
||||
ext::gui::size.reference = payload.window.size;
|
||||
|
||||
/*
|
||||
uf::renderer::RenderTargetRenderMode* renderModePointer = NULL;
|
||||
if ( this->hasComponent<uf::renderer::RenderTargetRenderMode>() ) {
|
||||
renderModePointer = this->getComponentPointer<uf::renderer::RenderTargetRenderMode>();
|
||||
} else {
|
||||
renderModePointer = (uf::renderer::RenderTargetRenderMode*) &uf::renderer::getRenderMode( "Gui", true );
|
||||
}
|
||||
auto& renderMode = *renderModePointer;
|
||||
renderMode.width = payload.window.size.x;
|
||||
renderMode.height = payload.window.size.y;
|
||||
renderMode.rebuild = true;
|
||||
*/
|
||||
} );
|
||||
this->addHook( "window:Mouse.Moved", [&](pod::payloads::windowMouseMoved& payload){
|
||||
bool clicked = false;
|
||||
@ -98,8 +112,36 @@ void ext::GuiManagerBehavior::tick( uf::Object& self ) {
|
||||
auto& blitter = renderMode.blitter;
|
||||
|
||||
if ( !blitter.initialized ) return;
|
||||
if ( !blitter.material.hasShader("fragment") ) return;
|
||||
|
||||
/* Update post processing */ {
|
||||
uf::renderer::RenderTargetRenderMode* renderModePointer = NULL;
|
||||
if ( this->hasComponent<uf::renderer::RenderTargetRenderMode>() ) {
|
||||
renderModePointer = this->getComponentPointer<uf::renderer::RenderTargetRenderMode>();
|
||||
} else {
|
||||
renderModePointer = (uf::renderer::RenderTargetRenderMode*) &uf::renderer::getRenderMode( "Gui", true );
|
||||
}
|
||||
auto& renderMode = *renderModePointer;
|
||||
auto& blitter = *renderMode.getBlitter();
|
||||
if ( blitter.material.hasShader("fragment") ) {
|
||||
auto& shader = blitter.material.getShader("fragment");
|
||||
|
||||
struct {
|
||||
float curTime = 0;
|
||||
float gamma = 1.0;
|
||||
float exposure = 1.0;
|
||||
uint32_t padding = 0;
|
||||
} uniforms = {
|
||||
.curTime = uf::time::current,
|
||||
.gamma = 1,
|
||||
.exposure = 1
|
||||
};
|
||||
|
||||
shader.updateBuffer( (const void*) &uniforms, sizeof(uniforms), shader.getUniformBuffer("UBO") );
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
if ( !blitter.material.hasShader("fragment") ) return;
|
||||
return;
|
||||
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
@ -112,56 +154,59 @@ void ext::GuiManagerBehavior::tick( uf::Object& self ) {
|
||||
#else
|
||||
// if ( metadata.overlay.cursor.type == "" ) metadata.deserialize( self, metadataJson );
|
||||
#endif
|
||||
struct UniformDescriptor {
|
||||
struct {
|
||||
/*alignas(16)*/ pod::Matrix4f models[2];
|
||||
} matrices;
|
||||
struct {
|
||||
/*alignas(8)*/ pod::Vector2f position = { 0.5f, 0.5f };
|
||||
/*alignas(8)*/ pod::Vector2f radius = { 0.1f, 0.1f };
|
||||
/*alignas(16)*/ pod::Vector4f color = { 1, 1, 1, 1 };
|
||||
} cursor;
|
||||
// /*alignas(8)*/ pod::Vector2f alpha;
|
||||
};
|
||||
|
||||
auto& shader = blitter.material.getShader("vertex");
|
||||
#if UF_UNIFORMS_REUSE
|
||||
auto& uniform = shader.getUniform("UBO");
|
||||
auto& uniforms = uniform.get<UniformDescriptor>();
|
||||
#else
|
||||
UniformDescriptor uniforms;
|
||||
#endif
|
||||
for ( size_t i = 0; i < 2; ++i ) {
|
||||
#if UF_USE_OPENVR
|
||||
if ( ext::openvr::enabled && metadata.overlay.enabled ) {
|
||||
if ( metadata.overlay.floating ) {
|
||||
pod::Matrix4f model = uf::transform::model( metadata.overlay.transform );
|
||||
uniforms.matrices.models[i] = camera.getProjection(i) * ext::openvr::hmdEyePositionMatrix( i == 0 ? vr::Eye_Left : vr::Eye_Right ) * model;
|
||||
} else {
|
||||
auto translation = uf::matrix::translate( uf::matrix::identity(), camera.getTransform().position + controller.getComponent<pod::Transform<>>().position );
|
||||
auto rotation = uf::quaternion::matrix( controller.getComponent<pod::Transform<>>().orientation );
|
||||
|
||||
pod::Matrix4f model = translation * rotation * uf::transform::model( metadata.overlay.transform );
|
||||
uniforms.matrices.models[i] = camera.getProjection(i) * camera.getView(i) * model;
|
||||
}
|
||||
} else {
|
||||
{
|
||||
struct UniformDescriptor {
|
||||
struct {
|
||||
/*alignas(16)*/ pod::Matrix4f models[2];
|
||||
} matrices;
|
||||
struct {
|
||||
/*alignas(8)*/ pod::Vector2f position = { 0.5f, 0.5f };
|
||||
/*alignas(8)*/ pod::Vector2f radius = { 0.1f, 0.1f };
|
||||
/*alignas(16)*/ pod::Vector4f color = { 1, 1, 1, 1 };
|
||||
} cursor;
|
||||
// /*alignas(8)*/ pod::Vector2f alpha;
|
||||
};
|
||||
|
||||
auto& shader = blitter.material.getShader("vertex");
|
||||
#if UF_UNIFORMS_REUSE
|
||||
auto& uniform = shader.getUniform("UBO");
|
||||
auto& uniforms = uniform.get<UniformDescriptor>();
|
||||
#else
|
||||
{
|
||||
UniformDescriptor uniforms;
|
||||
#endif
|
||||
pod::Matrix4t<> model = uf::matrix::translate( uf::matrix::identity(), { 0, 0, 1 } );
|
||||
uniforms.matrices.models[i] = model;
|
||||
}
|
||||
for ( size_t i = 0; i < 2; ++i ) {
|
||||
#if UF_USE_OPENVR
|
||||
if ( ext::openvr::enabled && metadata.overlay.enabled ) {
|
||||
if ( metadata.overlay.floating ) {
|
||||
pod::Matrix4f model = uf::transform::model( metadata.overlay.transform );
|
||||
uniforms.matrices.models[i] = camera.getProjection(i) * ext::openvr::hmdEyePositionMatrix( i == 0 ? vr::Eye_Left : vr::Eye_Right ) * model;
|
||||
} else {
|
||||
auto translation = uf::matrix::translate( uf::matrix::identity(), camera.getTransform().position + controller.getComponent<pod::Transform<>>().position );
|
||||
auto rotation = uf::quaternion::matrix( controller.getComponent<pod::Transform<>>().orientation );
|
||||
|
||||
if ( metadata.overlay.cursor.enabled ) {
|
||||
uniforms.cursor.position = metadata.overlay.cursor.position * 0.5f + 0.5f;
|
||||
uniforms.cursor.radius = uf::matrix::multiply<float>( uf::matrix::inverse( uf::matrix::scale( uf::matrix::identity() , metadata.overlay.transform.scale) ), pod::Vector3f{ metadata.overlay.cursor.radius, metadata.overlay.cursor.radius, 0 } );
|
||||
pod::Matrix4f model = translation * rotation * uf::transform::model( metadata.overlay.transform );
|
||||
uniforms.matrices.models[i] = camera.getProjection(i) * camera.getView(i) * model;
|
||||
}
|
||||
} else {
|
||||
#else
|
||||
{
|
||||
#endif
|
||||
pod::Matrix4t<> model = uf::matrix::translate( uf::matrix::identity(), { 0, 0, 1 } );
|
||||
uniforms.matrices.models[i] = model;
|
||||
}
|
||||
|
||||
if ( metadata.overlay.cursor.enabled ) {
|
||||
uniforms.cursor.position = metadata.overlay.cursor.position * 0.5f + 0.5f;
|
||||
uniforms.cursor.radius = uf::matrix::multiply<float>( uf::matrix::inverse( uf::matrix::scale( uf::matrix::identity() , metadata.overlay.transform.scale) ), pod::Vector3f{ metadata.overlay.cursor.radius, metadata.overlay.cursor.radius, 0 } );
|
||||
}
|
||||
uniforms.cursor.color = metadata.overlay.cursor.color;
|
||||
}
|
||||
uniforms.cursor.color = metadata.overlay.cursor.color;
|
||||
#if UF_UNIFORMS_REUSE
|
||||
shader.updateUniform( "UBO", uniform );
|
||||
#else
|
||||
shader.updateBuffer( (const void*) &uniforms, sizeof(uniforms), shader.getUniformBuffer("UBO") );
|
||||
#endif
|
||||
}
|
||||
#if UF_UNIFORMS_REUSE
|
||||
shader.updateUniform( "UBO", uniform );
|
||||
#else
|
||||
shader.updateBuffer( (const void*) &uniforms, sizeof(uniforms), shader.getUniformBuffer("UBO") );
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
40
ext/main.cpp
40
ext/main.cpp
@ -366,9 +366,9 @@ void EXT_API ext::initialize() {
|
||||
uf::renderer::settings::defaultCommandBufferWait = configRenderJson["invariant"]["default command buffer wait"].as( uf::renderer::settings::defaultCommandBufferWait );
|
||||
|
||||
if ( configRenderJson["framebuffer"]["size"].is<float>() ) {
|
||||
float scale = configRenderJson["framebuffer"]["size"].as(1.0f);
|
||||
uf::renderer::settings::width *= scale;
|
||||
uf::renderer::settings::height *= scale;
|
||||
// float scale = configRenderJson["framebuffer"]["size"].as(1.0f);
|
||||
// uf::renderer::settings::width *= scale;
|
||||
// uf::renderer::settings::height *= scale;
|
||||
} else if ( ext::json::isArray( configRenderJson["framebuffer"]["size"] ) ) {
|
||||
uf::renderer::settings::width = configRenderJson["framebuffer"]["size"][0].as(uf::renderer::settings::width);
|
||||
uf::renderer::settings::height = configRenderJson["framebuffer"]["size"][1].as(uf::renderer::settings::height);
|
||||
@ -431,10 +431,17 @@ void EXT_API ext::initialize() {
|
||||
uf::renderer::settings::pipelines::rt = configRenderPipelinesJson["rt"].as( uf::renderer::settings::pipelines::rt );
|
||||
uf::renderer::settings::pipelines::postProcess = configRenderPipelinesJson["postProcess"].as( uf::renderer::settings::pipelines::postProcess );
|
||||
uf::renderer::settings::pipelines::fsr = configRenderPipelinesJson["fsr"].as( uf::renderer::settings::pipelines::fsr );
|
||||
|
||||
|
||||
#if UF_USE_FFX_FSR
|
||||
// ext::fsr::enabled = uf::renderer::settings::pipelines::fsr;
|
||||
ext::fsr::preset = ::json["engine"]["ext"]["fsr"]["preset"].as(ext::fsr::preset);
|
||||
ext::fsr::jitterScale = ::json["engine"]["ext"]["fsr"]["jitter scale"].as(ext::fsr::jitterScale);
|
||||
ext::fsr::sharpness = ::json["engine"]["ext"]["fsr"]["sharpness"].as(ext::fsr::sharpness);
|
||||
#endif
|
||||
|
||||
if ( uf::renderer::settings::pipelines::rt ) {
|
||||
uf::renderer::settings::pipelines::vxgi = false;
|
||||
uf::renderer::settings::pipelines::culling = false;
|
||||
// uf::renderer::settings::pipelines::vxgi = false;
|
||||
// uf::renderer::settings::pipelines::culling = false;
|
||||
::json["engine"]["scenes"]["lights"]["shadows"]["enabled"] = false;
|
||||
}
|
||||
#define JSON_TO_FORMAT( key ) if ( configRenderJson["formats"][#key].is<uf::stl::string>() ) {\
|
||||
@ -491,6 +498,7 @@ void EXT_API ext::initialize() {
|
||||
|
||||
/* Initialize Vulkan */ {
|
||||
// setup render mode
|
||||
/*
|
||||
if ( ::json["engine"]["render modes"]["gui"].as<bool>(true) ) {
|
||||
auto* renderMode = new uf::renderer::RenderTargetRenderMode;
|
||||
renderMode->blitter.descriptor.renderMode = "Swapchain";
|
||||
@ -498,11 +506,29 @@ void EXT_API ext::initialize() {
|
||||
renderMode->metadata.type = "single";
|
||||
uf::renderer::addRenderMode( renderMode, "Gui" );
|
||||
}
|
||||
*/
|
||||
if ( ::json["engine"]["render modes"]["deferred"].as<bool>(true) ) {
|
||||
auto* renderMode = new uf::renderer::DeferredRenderMode;
|
||||
|
||||
renderMode->blitter.descriptor.renderMode = "Swapchain";
|
||||
renderMode->blitter.descriptor.subpass = 0;
|
||||
#if UF_USE_FFX_FSR
|
||||
if ( uf::renderer::settings::pipelines::fsr ) {
|
||||
auto mode = uf::string::lowercase( ext::fsr::preset );
|
||||
if ( mode == "native" ) renderMode->scale = 1;
|
||||
else if ( mode == "quality" ) renderMode->scale = 1.0f / (1.5f);
|
||||
else if ( mode == "balanced" ) renderMode->scale = 1.0f / (1.7f);
|
||||
else if ( mode == "performance" ) renderMode->scale = 1.0f / (2.0f);
|
||||
else if ( mode == "ultra" ) renderMode->scale = 1.0f / (3.0f);
|
||||
else {
|
||||
renderMode->scale = 1;
|
||||
UF_MSG_WARNING("Invalid FFX FSR preset enum string specified: {}", mode);
|
||||
}
|
||||
UF_MSG_DEBUG("Using FFX FSR Preset: {} ({:.3f}% render scale)", mode, (1.0f / renderMode->scale));
|
||||
} else
|
||||
#endif
|
||||
renderMode->scale = ::json["engine"]["ext"]["vulkan"]["framebuffer"]["size"].as(1.0f);
|
||||
UF_MSG_DEBUG("Geometry render scale: {:.3f}", renderMode->scale);
|
||||
|
||||
if ( ::json["engine"]["render modes"]["stereo deferred"].as<bool>() ) {
|
||||
renderMode->metadata.eyes = 2;
|
||||
@ -692,7 +718,7 @@ void EXT_API ext::tick() {
|
||||
spec::controller::tick();
|
||||
}
|
||||
#if UF_USE_FFX_FSR
|
||||
/* OpenVR */ if ( ext::fsr::initialized ) {
|
||||
/* FFX FSR */ if ( ext::fsr::initialized ) {
|
||||
ext::fsr::tick();
|
||||
}
|
||||
#endif
|
||||
|
||||
Loading…
Reference in New Issue
Block a user