Commit for 2021.05.03.7z

This commit is contained in:
mrq 2021-05-03 00:00:00 -05:00
parent 891301fc24
commit e34f03c3d0
24 changed files with 1042 additions and 881 deletions

View File

@ -2,25 +2,25 @@
#extension GL_EXT_samplerless_texture_functions : require
#define MULTISAMPLING 1
#define UF_DEFERRED_SAMPLING 0
#define UF_CAN_DISCARD 1
#define DEFERRED_SAMPLING 0
#define CAN_DISCARD 1
#if !MULTISAMPLING
layout (binding = 1) uniform usampler2D textureId;
layout (binding = 2) uniform sampler2D textureNormals;
#if UF_DEFERRED_SAMPLING
#if DEFERRED_SAMPLING
layout (binding = 3) uniform sampler2D textureUvs;
#else
layout (binding = 3) uniform sampler2D textureAlbedo;
#endif
layout (binding = 3) uniform sampler2D textureAlbedo;
#endif
#else
layout (binding = 1) uniform usampler2DMS textureId;
layout (binding = 2) uniform sampler2DMS textureNormals;
#if UF_DEFERRED_SAMPLING
#if DEFERRED_SAMPLING
layout (binding = 3) uniform sampler2DMS textureUvs;
#else
layout (binding = 3) uniform sampler2DMS textureAlbedo;
#endif
layout (binding = 3) uniform sampler2DMS textureAlbedo;
#endif
#endif
struct Cursor {
@ -44,6 +44,7 @@ layout (location = 1) in float inAlpha;
layout (location = 2) in Cursor inCursor;
layout (location = 0) out vec4 outAlbedo;
void main() {
#if !MULTISAMPLING
ivec2 screenSize = textureSize(textureId, 0);
@ -53,7 +54,7 @@ void main() {
ivec2 uv = ivec2(inUv * screenSize);
if ( inCursor.radius.x <= 0 || inCursor.radius.y <= 0 ) {
#if !MULTISAMPLING
outAlbedo = texture(textureAlbedo, uv).rgba;
outAlbedo = texture( textureAlbedo, uv ).rgba;
#else
outAlbedo = resolve( textureAlbedo, uv );
#endif
@ -62,7 +63,7 @@ void main() {
float dist = pow(inUv.x - inCursor.position.x, 2) / pow(inCursor.radius.x, 2) + pow(inUv.y - inCursor.position.y, 2) / pow(inCursor.radius.y, 2);
#if !MULTISAMPLING
outAlbedo = texture(textureAlbedo, inUv);
outAlbedo = texture( textureAlbedo, inUv );
#else
outAlbedo = resolve( textureAlbedo, uv );
#endif

View File

@ -2,14 +2,25 @@
#extension GL_EXT_samplerless_texture_functions : require
#define MULTISAMPLING 1
#define DEFERRED_SAMPLING 0
#define RAY_MARCH_FOG 1
#define DEFERRED_SAMPLING 1
#define VXGI_NDC 1
#define VXGI_SHADOWS 0
#define VXGI_CASCADES 1
#define FOG 1
#define FOG_RAY_MARCH 1
#define WHITENOISE 1
#define GAMMA_CORRECT 1
#define TONE_MAP 1
#define LAMBERT 0
#define PBR 1
const float PI = 3.14159265359;
const float EPSILON = 0.00001;
const float SQRT2 = 1.41421356237;
const float LIGHT_POWER_CUTOFF = 0.005;
@ -40,13 +51,20 @@ struct Matrices {
mat4 iView[2];
mat4 iProjection[2];
mat4 iProjectionView[2];
mat4 ortho;
vec4 eyePos[2];
mat4 vxgi;
};
struct Ray {
vec3 origin;
vec3 direction;
float distance;
};
struct Space {
vec3 eye;
vec3 world;
} position, normal, view;
};
struct Fog {
vec3 color;
@ -107,6 +125,7 @@ struct Material {
int indexLightmap;
int modeAlpha;
};
struct Texture {
int index;
int samp;
@ -115,6 +134,7 @@ struct Texture {
vec4 lerp;
};
struct DrawCall {
int materialIndex;
uint materials;
@ -122,6 +142,29 @@ struct DrawCall {
uint textures;
};
struct SurfaceMaterial {
uint id;
vec4 albedo;
vec4 indirect;
float metallic;
float roughness;
float occlusion;
};
struct Surface {
vec2 uv;
Space position;
Space normal;
Ray ray;
SurfaceMaterial material;
vec4 fragment;
} surface;
#if !MULTISAMPLING
layout (input_attachment_index = 0, binding = 0) uniform usubpassInput samplerId;
layout (input_attachment_index = 1, binding = 1) uniform subpassInput samplerNormal;
@ -144,7 +187,7 @@ struct DrawCall {
layout (binding = 4) uniform UBO {
Matrices matrices;
Mode mode;
Fog fog;
@ -154,12 +197,12 @@ layout (binding = 4) uniform UBO {
uint drawCalls;
vec3 ambient;
float kexp;
uint msaa;
uint poissonSamples;
float gamma;
float exposure;
uint msaa;
uint shadowSamples;
uint padding1;
} ubo;
layout (std140, binding = 5) readonly buffer Lights {
@ -179,7 +222,6 @@ layout (binding = 9) uniform sampler3D samplerNoise;
layout (binding = 10) uniform samplerCube samplerSkybox;
layout (binding = 11) uniform sampler2D samplerTextures[TEXTURES];
layout (location = 0) in vec2 inUv;
layout (location = 1) in flat uint inPushConstantPass;
@ -239,9 +281,9 @@ vec3 gamma( vec3 i ) {
return pow(i.rgb, vec3(1.0 / 2.2));
}
vec2 rayBoxDst( vec3 boundsMin, vec3 boundsMax, vec3 rayO, vec3 rayD ) {
const vec3 t0 = (boundsMin - rayO) / rayD;
const vec3 t1 = (boundsMax - rayO) / rayD;
vec2 rayBoxDst( vec3 boundsMin, vec3 boundsMax, in Ray ray ) {
const vec3 t0 = (boundsMin - ray.origin) / ray.direction;
const vec3 t1 = (boundsMax - ray.origin) / ray.direction;
const vec3 tmin = min(t0, t1);
const vec3 tmax = max(t0, t1);
const float tStart = max(0, max( max(tmin.x, tmin.y), tmin.z ));
@ -254,20 +296,20 @@ float sampleDensity( vec3 position ) {
return max(0, texture(samplerNoise, uvw).r - ubo.fog.densityThreshold) * ubo.fog.densityMultiplier;
}
void fog( vec3 rayO, vec3 rayD, inout vec3 i, float scale ) {
void fog( in Ray ray, inout vec3 i, float scale ) {
if ( ubo.fog.stepScale <= 0 ) return;
if ( ubo.fog.range.x == 0 || ubo.fog.range.y == 0 ) return;
#if RAY_MARCH_FOG
#if FOG_RAY_MARCH
const float range = ubo.fog.range.y;
const vec3 boundsMin = vec3(-range,-range,-range) + rayO;
const vec3 boundsMax = vec3(range,range,range) + rayO;
const vec3 boundsMin = vec3(-range,-range,-range) + ray.origin;
const vec3 boundsMax = vec3(range,range,range) + ray.origin;
const int numSteps = int(length(boundsMax - boundsMin) * ubo.fog.stepScale );
const vec2 rayBoxInfo = rayBoxDst( boundsMin, boundsMax, rayO, rayD );
const vec2 rayBoxInfo = rayBoxDst( boundsMin, boundsMax, ray );
const float dstToBox = rayBoxInfo.x;
const float dstInsideBox = rayBoxInfo.y;
const float depth = position.eye.z;
const float depth = surface.position.eye.z;
float lightEnergy = 0;
// march
@ -278,7 +320,7 @@ void fog( vec3 rayO, vec3 rayD, inout vec3 i, float scale ) {
float totalDensity = 0;
float transmittance = 1;
while ( dstTravelled < dstLimit ) {
vec3 rayPos = rayO + rayD * (dstToBox + dstTravelled);
vec3 rayPos = ray.origin + ray.direction * (dstToBox + dstTravelled);
float density = sampleDensity(rayPos);
if ( density > 0 ) {
transmittance *= exp(-density * stepSize * ubo.fog.absorbtion);
@ -293,7 +335,7 @@ void fog( vec3 rayO, vec3 rayD, inout vec3 i, float scale ) {
const vec3 color = ubo.fog.color.rgb;
const float inner = ubo.fog.range.x;
const float outer = ubo.fog.range.y * scale;
const float distance = length(-position.eye);
const float distance = length(-surface.position.eye);
const float factor = clamp( (distance - inner) / (outer - inner), 0.0, 1.0 );
i.rgb = mix(i.rgb, color, factor);
@ -304,12 +346,6 @@ vec3 decodeNormals( vec2 enc ) {
const vec2 scth = vec2( sin(ang.x * PI), cos(ang.x * PI) );
const vec2 scphi = vec2(sqrt(1.0 - ang.y*ang.y), ang.y);
return normalize( vec3(scth.y*scphi.x, scth.x*scphi.x, scphi.y) );
/*
vec2 fenc = enc*4-2;
float f = dot(fenc,fenc);
float g = sqrt(1-f/4);
return normalize( vec3(fenc * g, 1 - f / 2) );
*/
}
float wrap( float i ) {
return fract(i);
@ -347,7 +383,7 @@ uvec4 resolve( usubpassInputMS t ) {
float shadowFactor( const Light light, float def ) {
if ( !validTextureIndex(light.mapIndex) ) return 1.0;
vec4 positionClip = light.projection * light.view * vec4(position.world, 1.0);
vec4 positionClip = light.projection * light.view * vec4(surface.position.world, 1.0);
positionClip.xyz /= positionClip.w;
if ( positionClip.x < -1 || positionClip.x >= 1 ) return def; //0.0;
@ -370,21 +406,34 @@ float shadowFactor( const Light light, float def ) {
const vec2 uv = positionClip.xy * 0.5 + 0.5;
const float bias = light.depthBias;
const float eyeDepth = positionClip.z;
const int samples = int(ubo.poissonSamples);
if ( samples <= 1 ) return eyeDepth < texture(samplerTextures[light.mapIndex], uv).r - bias ? 0.0 : factor;
const int samples = int(ubo.shadowSamples);
if ( samples < 1 ) return eyeDepth < texture(samplerTextures[light.mapIndex], uv).r - bias ? 0.0 : factor;
for ( int i = 0; i < samples; ++i ) {
const int index = int( float(samples) * random(floor(position.world.xyz * 1000.0), i)) % samples;
const int index = int( float(samples) * random(floor(surface.position.world.xyz * 1000.0), i)) % samples;
const float lightDepth = texture(samplerTextures[light.mapIndex], uv + poissonDisk[index] / 700.0 ).r;
if ( eyeDepth < lightDepth - bias ) factor -= 1.0 / samples;
}
return factor;
}
void main() {
vec3 rayO = vec3(0);
vec3 rayD = vec3(0);
vec3 fragColor = vec3(0);
vec4 postProcess() {
#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.exposure);
#endif
#if GAMMA_CORRECT
surface.fragment.rgb = pow(surface.fragment.rgb, vec3(1.0 / ubo.gamma));
#endif
#if WHITENOISE
if ( (ubo.mode.type & (0x1 << 1)) == (0x1 << 1) ) whitenoise(surface.fragment.rgb);
#endif
return vec4(surface.fragment.rgb,1);
}
void main() {
{
#if !MULTISAMPLING
const float depth = subpassLoad(samplerDepth).r;
@ -394,65 +443,79 @@ void main() {
vec4 positionEye = ubo.matrices.iProjection[inPushConstantPass] * vec4(inUv * 2.0 - 1.0, depth, 1.0);
positionEye /= positionEye.w;
position.eye = positionEye.xyz;
position.world = vec3( ubo.matrices.iView[inPushConstantPass] * positionEye );
surface.position.eye = positionEye.xyz;
surface.position.world = vec3( ubo.matrices.iView[inPushConstantPass] * positionEye );
}
#if 0
{
const vec4 near4 = ubo.matrices.iProjectionView[inPushConstantPass] * (vec4(2.0 * inUv - 1.0, -1.0, 1.0));
const vec4 far4 = ubo.matrices.iProjectionView[inPushConstantPass] * (vec4(2.0 * inUv - 1.0, 1.0, 1.0));
const vec3 near3 = near4.xyz / near4.w;
const vec3 far3 = far4.xyz / far4.w;
rayO = near3;
rayD = normalize( far3 - near3 );
surface.ray.origin = near3;
surface.ray.direction = normalize( far3 - near3 );
}
// separate our ray direction due to floating point precision problems
if ( false ) {
{
const mat4 iProjectionView = inverse( ubo.matrices.projection[inPushConstantPass] * mat4(mat3(ubo.matrices.view[inPushConstantPass])) );
const vec4 near4 = iProjectionView * (vec4(2.0 * inUv - 1.0, -1.0, 1.0));
const vec4 far4 = iProjectionView * (vec4(2.0 * inUv - 1.0, 1.0, 1.0));
const vec3 near3 = near4.xyz / near4.w;
const vec3 far3 = far4.xyz / far4.w;
rayD = normalize( far3 - near3 );
surface.ray.direction = normalize( far3 - near3 );
}
#else
{
const mat4 iProjectionView = inverse( ubo.matrices.projection[inPushConstantPass] * mat4(mat3(ubo.matrices.view[inPushConstantPass])) );
const vec4 near4 = iProjectionView * (vec4(2.0 * inUv - 1.0, -1.0, 1.0));
const vec4 far4 = iProjectionView * (vec4(2.0 * inUv - 1.0, 1.0, 1.0));
const vec3 near3 = near4.xyz / near4.w;
const vec3 far3 = far4.xyz / far4.w;
surface.ray.direction = normalize( far3 - near3 );
surface.ray.origin = ubo.matrices.eyePos[inPushConstantPass].xyz;
}
#endif
#if !MULTISAMPLING
normal.world = decodeNormals( subpassLoad(samplerNormal).xy );
surface.normal.world = decodeNormals( subpassLoad(samplerNormal).xy );
const uvec2 ID = subpassLoad(samplerId).xy;
#else
normal.world = decodeNormals( resolve(samplerNormal).xy );
surface.normal.world = decodeNormals( resolve(samplerNormal).xy );
const uvec2 ID = resolve(samplerId).xy;
#endif
normal.eye = vec3( ubo.matrices.view[inPushConstantPass] * vec4(normal.world, 0.0) );
surface.normal.eye = vec3( ubo.matrices.view[inPushConstantPass] * vec4(surface.normal.world, 0.0) );
if ( ID.x == 0 || ID.y == 0 ) {
fragColor.rgb = texture( samplerSkybox, rayD ).rgb;
fog(rayO, rayD, fragColor, 0.0);
outFragColor = vec4(fragColor,1);
surface.fragment.rgb = texture( samplerSkybox, surface.ray.direction ).rgb;
surface.fragment.a = 0.0;
outFragColor = postProcess();
return;
}
const uint drawId = ID.x - 1;
const DrawCall drawCall = drawCalls[drawId];
const uint materialId = ID.y + drawCall.materialIndex - 1;
const Material material = materials[materialId];
vec4 A = material.colorBase;
surface.material.id = ID.y + drawCall.materialIndex - 1;
const Material material = materials[surface.material.id];
surface.material.albedo = material.colorBase;
surface.fragment = material.colorEmissive;
#if DEFERRED_SAMPLING
#if !MULTISAMPLING
const vec2 uv = subpassLoad(samplerUv).xy;
surface.uv = subpassLoad(samplerUv).xy;
#else
const vec2 uv = resolve(samplerUv).xy;
surface.uv = resolve(samplerUv).xy;
#endif
const float mip = mipLevel(inUv.xy);
const bool useAtlas = validTextureIndex( drawCall.textureIndex + material.indexAtlas );
Texture textureAtlas;
if ( useAtlas ) textureAtlas = textures[drawCall.textureIndex + material.indexAtlas];
if ( validTextureIndex( drawCall.textureIndex + material.indexAtlas ) ) {
Texture t = textures[drawCall.textureIndex + material.indexAlbedo];
A = texture( samplerTextures[(useAtlas)?textureAtlas.index:t.index], ( useAtlas ) ? mix( t.lerp.xy, t.lerp.zw, uv ) : uv, mip );
if ( validTextureIndex( drawCall.textureIndex + material.indexAlbedo ) ) {
const Texture t = textures[drawCall.textureIndex + material.indexAlbedo];
surface.material.albedo = textureLod( samplerTextures[(useAtlas)?textureAtlas.index:t.index], ( useAtlas ) ? mix( t.lerp.xy, t.lerp.zw, surface.uv ) : surface.uv, mip );
}
// OPAQUE
if ( material.modeAlpha == 0 ) {
A.a = 1;
surface.material.albedo.a = 1;
// BLEND
} else if ( material.modeAlpha == 1 ) {
@ -460,83 +523,72 @@ void main() {
} else if ( material.modeAlpha == 2 ) {
}
// Emissive textures
if ( validTextureIndex( drawCall.textureIndex + material.indexEmissive ) ) {
const Texture t = textures[drawCall.textureIndex + material.indexEmissive];
surface.fragment += textureLod( samplerTextures[(useAtlas)?textureAtlas.index:t.index], ( useAtlas ) ? mix( t.lerp.xy, t.lerp.zw, surface.uv ) : surface.uv, mip );
}
#else
#if !MULTISAMPLING
A = subpassLoad(samplerAlbedo);
surface.material.albedo = subpassLoad(samplerAlbedo);
#else
A = resolve(samplerAlbedo);
surface.material.albedo = resolve(samplerAlbedo);
#endif
#endif
const float M = material.factorMetallic;
const float R = material.factorRoughness;
const float AO = 1.0f - material.factorOcclusion;
surface.material.metallic = material.factorMetallic;
surface.material.roughness = material.factorRoughness;
surface.material.occlusion = material.factorOcclusion;
float litFactor = 1.0;
if ( 0 <= material.indexLightmap ) {
fragColor = A.rgb + ubo.ambient.rgb * (1 - AO);
surface.fragment.rgb += surface.material.albedo.rgb + ubo.ambient.rgb * surface.material.occlusion;
} else {
fragColor = A.rgb * ubo.ambient.rgb * (1 - AO);
surface.fragment.rgb += surface.material.albedo.rgb * ubo.ambient.rgb * surface.material.occlusion;
}
{
const vec3 N = normal.eye;
const vec3 F0 = mix(vec3(0.04), A.rgb, M);
const vec3 Lo = normalize( -position.eye );
const float cosLo = max(0.0, dot(N, Lo));
// corrections
surface.material.roughness *= 4.0;
{
const vec3 F0 = mix(vec3(0.04), surface.material.albedo.rgb, surface.material.metallic);
const vec3 Lo = normalize( -surface.position.eye );
const float cosLo = max(0.0, dot(surface.normal.eye, Lo));
for ( uint i = 0; i < ubo.lights; ++i ) {
const Light light = lights[i];
if ( light.power <= LIGHT_POWER_CUTOFF ) continue;
const vec3 Lp = light.position;
const vec3 Liu = vec3(ubo.matrices.view[inPushConstantPass] * vec4(light.position, 1)) - position.eye;
const vec3 Liu = vec3(ubo.matrices.view[inPushConstantPass] * vec4(light.position, 1)) - surface.position.eye;
const vec3 Li = normalize(Liu);
#if VXGI_SHADOWS
const float Ls = i < ubo.shadowSamples ? shadowFactor( light, 0.0 ) : 1.0;
#else
const float Ls = shadowFactor( light, 0.0 );
#endif
const float La = 1.0 / (PI * pow(length(Liu), 2.0));
if ( light.power * La * Ls <= LIGHT_POWER_CUTOFF ) continue;
const float cosLi = max(0.0, dot(N, Li));
const float cosLi = max(0.0, dot(surface.normal.eye, Li));
const vec3 Lr = light.color.rgb * light.power * La * Ls;
#if LAMBERT
const vec3 diffuse = A.rgb;
const vec3 diffuse = surface.material.albedo.rgb;
const vec3 specular = vec3(0);
#elif PBR
const vec3 Lh = normalize(Li + Lo);
const float cosLh = max(0.0, dot(N, Lh));
const float cosLh = max(0.0, dot(surface.normal.eye, Lh));
const vec3 F = fresnelSchlick( F0, max( 0.0, dot(Lh, Lo) ) );
const float D = ndfGGX( cosLh, R );
const float G = gaSchlickGGX(cosLi, cosLo, R);
const vec3 diffuse = mix( vec3(1.0) - F, vec3(0.0), M ) * A.rgb;
const float D = ndfGGX( cosLh, surface.material.roughness );
const float G = gaSchlickGGX(cosLi, cosLo, surface.material.roughness);
const vec3 diffuse = mix( vec3(1.0) - F, vec3(0.0), surface.material.metallic ) * surface.material.albedo.rgb;
const vec3 specular = (F * D * G) / max(EPSILON, 4.0 * cosLi * cosLo);
#endif
// lightmapped, compute only specular
if ( light.type >= 0 && 0 <= material.indexLightmap ) fragColor.rgb += (specular) * Lr * cosLi;
if ( light.type >= 0 && 0 <= material.indexLightmap ) surface.fragment.rgb += (specular) * Lr * cosLi;
// point light, compute only diffuse
// else if ( abs(light.type) == 1 ) fragColor.rgb += (diffuse) * Lr * cosLi;
else fragColor.rgb += (diffuse + specular) * Lr * cosLi;
litFactor += light.power * La * Ls;
// else if ( abs(light.type) == 1 ) surface.fragment.rgb += (diffuse) * Lr * cosLi;
else surface.fragment.rgb += (diffuse + specular) * Lr * cosLi;
surface.fragment.a += light.power * La * Ls;
}
}
fog(rayO, rayD, fragColor, litFactor);
#if TONE_MAP
// fragColor = fragColor / (fragColor + 1.0f);
fragColor = vec3(1.0) - exp(-fragColor * ubo.exposure);
#endif
#if GAMMA_CORRECT
fragColor = pow(fragColor, vec3(1.0 / ubo.gama));
#endif
/*
if ( (ubo.mode.type & (0x1 << 0)) == (0x1 << 0) ) {
//dither1(fragColor);
fragColor += dither2();
}
*/
if ( (ubo.mode.type & (0x1 << 1)) == (0x1 << 1) ) {
whitenoise(fragColor);
}
outFragColor = vec4(fragColor,1);
outFragColor = postProcess();
}

View File

@ -2,13 +2,15 @@
#extension GL_EXT_samplerless_texture_functions : require
#define MULTISAMPLING 1
#define FOG 1
#define RAY_MARCH_FOG 1
#define WHITENOISE 1
#define DEFERRED_SAMPLING 0
#define SHADOW_CONE_TRACED 0
#define VOXEL_TRACE_IN_NDC 1
#define DEFERRED_SAMPLING 1
#define VXGI_NDC 0
#define VXGI_SHADOWS 1
#define FOG 1
#define FOG_RAY_MARCH 1
#define WHITENOISE 1
#define GAMMA_CORRECT 1
#define TONE_MAP 1
@ -41,6 +43,7 @@ const vec2 poissonDisk[16] = vec2[](
);
layout (constant_id = 0) const uint TEXTURES = 256;
layout (constant_id = 1) const uint CASCADES = 1;
struct Matrices {
mat4 view[2];
@ -48,13 +51,22 @@ struct Matrices {
mat4 iView[2];
mat4 iProjection[2];
mat4 iProjectionView[2];
mat4 voxel;
vec4 eyePos[2];
mat4 vxgi;
};
struct Ray {
vec3 origin;
vec3 direction;
vec3 position;
float distance;
};
struct Space {
vec3 eye;
vec3 world;
} position, normal, view;
};
struct Fog {
vec3 color;
@ -115,6 +127,7 @@ struct Material {
int indexLightmap;
int modeAlpha;
};
struct Texture {
int index;
int samp;
@ -123,12 +136,37 @@ struct Texture {
vec4 lerp;
};
struct DrawCall {
int materialIndex;
uint materials;
int textureIndex;
uint textures;
};
struct SurfaceMaterial {
uint id;
vec4 albedo;
vec4 indirect;
float metallic;
float roughness;
float occlusion;
};
struct Surface {
vec2 uv;
Space position;
Space normal;
Ray ray;
SurfaceMaterial material;
vec4 fragment;
} surface;
struct Voxel {
uvec2 id;
vec3 position;
@ -169,12 +207,12 @@ layout (binding = 4) uniform UBO {
uint drawCalls;
vec3 ambient;
float kexp;
uint msaa;
uint poissonSamples;
float gamma;
float exposure;
uint msaa;
uint shadowSamples;
uint padding1;
} ubo;
layout (std140, binding = 5) readonly buffer Lights {
@ -190,10 +228,10 @@ layout (std140, binding = 8) readonly buffer DrawCalls {
DrawCall drawCalls[];
};
layout (binding = 9) uniform usampler3D voxelId;
layout (binding = 10) uniform sampler3D voxelNormal;
layout (binding = 11) uniform sampler3D voxelUv;
layout (binding = 12) uniform sampler3D voxelAlbedo;
layout (binding = 9) uniform usampler3D voxelId[CASCADES];
layout (binding = 10) uniform sampler3D voxelUv[CASCADES];
layout (binding = 11) uniform sampler3D voxelNormal[CASCADES];
layout (binding = 12) uniform sampler3D voxelRadiance[CASCADES];
layout (binding = 13) uniform sampler3D samplerNoise;
layout (binding = 14) uniform samplerCube samplerSkybox;
@ -258,9 +296,9 @@ vec3 gamma( vec3 i ) {
return pow(i.rgb, vec3(1.0 / 2.2));
}
vec2 rayBoxDst( vec3 boundsMin, vec3 boundsMax, vec3 rayO, vec3 rayD ) {
const vec3 t0 = (boundsMin - rayO) / rayD;
const vec3 t1 = (boundsMax - rayO) / rayD;
vec2 rayBoxDst( vec3 boundsMin, vec3 boundsMax, in Ray ray ) {
const vec3 t0 = (boundsMin - ray.origin) / ray.direction;
const vec3 t1 = (boundsMax - ray.origin) / ray.direction;
const vec3 tmin = min(t0, t1);
const vec3 tmax = max(t0, t1);
const float tStart = max(0, max( max(tmin.x, tmin.y), tmin.z ));
@ -273,20 +311,20 @@ float sampleDensity( vec3 position ) {
return max(0, texture(samplerNoise, uvw).r - ubo.fog.densityThreshold) * ubo.fog.densityMultiplier;
}
void fog( vec3 rayO, vec3 rayD, inout vec3 i, float scale ) {
void fog( in Ray ray, inout vec3 i, float scale ) {
if ( ubo.fog.stepScale <= 0 ) return;
if ( ubo.fog.range.x == 0 || ubo.fog.range.y == 0 ) return;
#if RAY_MARCH_FOG
#if FOG_RAY_MARCH
const float range = ubo.fog.range.y;
const vec3 boundsMin = vec3(-range,-range,-range) + rayO;
const vec3 boundsMax = vec3(range,range,range) + rayO;
const vec3 boundsMin = vec3(-range,-range,-range) + ray.origin;
const vec3 boundsMax = vec3(range,range,range) + ray.origin;
const int numSteps = int(length(boundsMax - boundsMin) * ubo.fog.stepScale );
const vec2 rayBoxInfo = rayBoxDst( boundsMin, boundsMax, rayO, rayD );
const vec2 rayBoxInfo = rayBoxDst( boundsMin, boundsMax, ray );
const float dstToBox = rayBoxInfo.x;
const float dstInsideBox = rayBoxInfo.y;
const float depth = position.eye.z;
const float depth = surface.position.eye.z;
float lightEnergy = 0;
// march
@ -297,7 +335,7 @@ void fog( vec3 rayO, vec3 rayD, inout vec3 i, float scale ) {
float totalDensity = 0;
float transmittance = 1;
while ( dstTravelled < dstLimit ) {
vec3 rayPos = rayO + rayD * (dstToBox + dstTravelled);
vec3 rayPos = ray.origin + ray.direction * (dstToBox + dstTravelled);
float density = sampleDensity(rayPos);
if ( density > 0 ) {
transmittance *= exp(-density * stepSize * ubo.fog.absorbtion);
@ -312,7 +350,7 @@ void fog( vec3 rayO, vec3 rayD, inout vec3 i, float scale ) {
const vec3 color = ubo.fog.color.rgb;
const float inner = ubo.fog.range.x;
const float outer = ubo.fog.range.y * scale;
const float distance = length(-position.eye);
const float distance = length(-surface.position.eye);
const float factor = clamp( (distance - inner) / (outer - inner), 0.0, 1.0 );
i.rgb = mix(i.rgb, color, factor);
@ -323,12 +361,6 @@ vec3 decodeNormals( vec2 enc ) {
const vec2 scth = vec2( sin(ang.x * PI), cos(ang.x * PI) );
const vec2 scphi = vec2(sqrt(1.0 - ang.y*ang.y), ang.y);
return normalize( vec3(scth.y*scphi.x, scth.x*scphi.x, scphi.y) );
/*
vec2 fenc = enc*4-2;
float f = dot(fenc,fenc);
float g = sqrt(1-f/4);
return normalize( vec3(fenc * g, 1 - f / 2) );
*/
}
float wrap( float i ) {
return fract(i);
@ -363,10 +395,11 @@ uvec4 resolve( usubpassInputMS t ) {
return resolved;
}
#if !VXGI_SHADOWS
float shadowFactor( const Light light, float def ) {
if ( !validTextureIndex(light.mapIndex) ) return 1.0;
vec4 positionClip = light.projection * light.view * vec4(position.world, 1.0);
vec4 positionClip = light.projection * light.view * vec4(surface.position.world, 1.0);
positionClip.xyz /= positionClip.w;
if ( positionClip.x < -1 || positionClip.x >= 1 ) return def; //0.0;
@ -389,25 +422,43 @@ float shadowFactor( const Light light, float def ) {
const vec2 uv = positionClip.xy * 0.5 + 0.5;
const float bias = light.depthBias;
const float eyeDepth = positionClip.z;
const int samples = int(ubo.poissonSamples);
if ( samples <= 1 ) return eyeDepth < texture(samplerTextures[light.mapIndex], uv).r - bias ? 0.0 : factor;
const int samples = int(ubo.shadowSamples);
if ( samples < 1 ) return eyeDepth < texture(samplerTextures[light.mapIndex], uv).r - bias ? 0.0 : factor;
for ( int i = 0; i < samples; ++i ) {
const int index = int( float(samples) * random(floor(position.world.xyz * 1000.0), i)) % samples;
const int index = int( float(samples) * random(floor(surface.position.world.xyz * 1000.0), i)) % samples;
const float lightDepth = texture(samplerTextures[light.mapIndex], uv + poissonDisk[index] / 700.0 ).r;
if ( eyeDepth < lightDepth - bias ) factor -= 1.0 / samples;
}
return factor;
}
#endif
vec4 postProcess() {
#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.exposure);
#endif
#if GAMMA_CORRECT
surface.fragment.rgb = pow(surface.fragment.rgb, vec3(1.0 / ubo.gamma));
#endif
#if WHITENOISE
if ( (ubo.mode.type & (0x1 << 1)) == (0x1 << 1) ) whitenoise(surface.fragment.rgb);
#endif
return vec4(surface.fragment.rgb,1);
}
Voxel getVoxel( vec3 P ) {
const vec3 uvw = vec3( ubo.matrices.voxel * vec4( P, 1.0f ) ) * 0.5f + 0.5f;
const vec3 uvw = vec3( ubo.matrices.vxgi * vec4( P, 1.0f ) ) * 0.5f + 0.5f;
Voxel voxel;
voxel.id = uvec2(texture(voxelId, uvw).xy);
voxel.id = uvec2(texture(voxelId[0], uvw).xy);
voxel.position = P;
voxel.normal = decodeNormals( texture(voxelNormal, uvw).xy );
voxel.uv = texture(voxelUv, uvw).xy;
voxel.color = texture(voxelAlbedo, uvw).rgba;
voxel.normal = decodeNormals( texture(voxelNormal[0], uvw).xy );
voxel.uv = texture(voxelUv[0], uvw).xy;
voxel.color = texture(voxelRadiance[0], uvw).rgba;
return voxel;
}
@ -417,76 +468,88 @@ struct VoxelInfo {
vec3 max;
float mipmapLevels;
float albedoSize;
float radianceSize;
float voxelSize;
float albedoSizeRecip;
float radianceSizeRecip;
float voxelSizeRecip;
};
VoxelInfo voxelInfo;
} voxelInfo;
vec4 voxelConeTrace( vec3 rayO, vec3 rayD, float aperture, float maxDistance ) {
#if VOXEL_TRACE_IN_NDC
rayO = vec3( ubo.matrices.voxel * vec4( rayO, 1.0 ) );
rayD = vec3( ubo.matrices.voxel * vec4( rayD, 0.0 ) );
const float granularity = 1.0f / 8.0f;
const uint maxSteps = uint(voxelInfo.albedoSize * 2);
vec4 voxelTrace( inout Ray ray, float aperture, float maxDistance ) {
#if VXGI_NDC
ray.origin = vec3( ubo.matrices.vxgi * vec4( ray.origin, 1.0 ) );
ray.direction = vec3( ubo.matrices.vxgi * vec4( ray.direction, 0.0 ) );
const float granularity = 1.0f / 16.0f;
const uint maxSteps = uint(voxelInfo.radianceSize * 2);
#else
const float granularity = 8.0f;
const uint maxSteps = uint(voxelInfo.albedoSize * granularity);
const float granularity = 10.0f;
const uint maxSteps = uint(voxelInfo.radianceSize * granularity);
#endif
const float granularityRecip = 1.0f / granularity;
// box
const vec2 rayBoxInfo = rayBoxDst( voxelInfo.min, voxelInfo.max, rayO, rayD );
const vec2 rayBoxInfo = rayBoxDst( voxelInfo.min, voxelInfo.max, ray );
const float tStart = rayBoxInfo.x;
const float tEnd = maxDistance > 0 ? min(maxDistance, rayBoxInfo.y) : rayBoxInfo.y;
// steps
const float tDelta = voxelInfo.voxelSize * granularityRecip;
// marcher
float t = tStart + 2.0 * SQRT2;
vec3 rayPos = vec3(0);
ray.distance = tStart + tDelta * granularity;
ray.position = vec3(0);
vec4 radiance = vec4(0);
vec3 uvw = vec3(0);
// cone mipmap shit
const float coneCoefficient = 2.0 * tan(aperture * 0.5);
float coneDiameter = coneCoefficient * t;
float coneDiameter = coneCoefficient * ray.distance;
float level = aperture > 0 ? log2( coneDiameter ) : 0;
// results
vec4 color = vec4(0);
float occlusion = 0.0;
uint stepCounter = 0;
float tD;
const float falloff = 256.0f;
const float falloff = 32.0f; // maxDistance > 0.0 ? 0.0f : 256.0f;
const vec3 voxelBoundsRecip = 1.0f / (voxelInfo.max - voxelInfo.min);
// while ( t < tEnd && color.a < 1.0 && occlusion < 1.0 && stepCounter++ < maxSteps ) {
while ( t < tEnd && color.a < 1.0 && occlusion < 1.0 ) {
t += tDelta * (aperture > 0 ? coneDiameter : 1);
rayPos = rayO + rayD * t;
#if VOXEL_TRACE_IN_NDC
uvw = rayPos * 0.5 + 0.5;
// while ( ray.distance < tEnd && color.a < 1.0 && occlusion < 1.0 && stepCounter++ < maxSteps ) {
while ( ray.distance < tEnd && color.a < 1.0 && occlusion < 1.0 ) {
ray.distance += tDelta * (aperture > 0 ? coneDiameter : 1);
ray.position = ray.origin + ray.direction * ray.distance;
#if VXGI_NDC
uvw = ray.position * 0.5 + 0.5;
#else
uvw = (rayPos - voxelInfo.min) * voxelBoundsRecip;
uvw = (ray.position - voxelInfo.min) * voxelBoundsRecip;
#endif
if ( abs(uvw.x) > 1.0 || abs(uvw.y) > 1.0 || abs(uvw.z) > 1.0 ) break;
coneDiameter = coneCoefficient * t;
coneDiameter = coneCoefficient * ray.distance;
level = log2( coneDiameter );
if ( level >= voxelInfo.mipmapLevels ) break;
radiance = texture(voxelAlbedo, uvw, level);
radiance = textureLod(voxelRadiance[0], uvw.xzy, level);
color += (1.0 - color.a) * radiance;
occlusion += ((1.0f - occlusion) * radiance.a) / (1.0f + falloff * coneDiameter);
}
return vec4(color.rgb, occlusion);
return maxDistance > 0 ? color : vec4(color.rgb, occlusion);
// return vec4(color.rgb, occlusion);
}
vec4 voxelConeTrace( vec3 rayO, vec3 rayD, float aperture ) {
return voxelConeTrace( rayO, rayD, aperture, 0 );
vec4 voxelConeTrace( inout Ray ray, float aperture ) {
return voxelTrace( ray, aperture, 0 );
}
vec4 voxelTrace( inout Ray ray, float maxDistance ) {
return voxelTrace( ray, 0, maxDistance );
}
#if VXGI_SHADOWS
float shadowFactor( const Light light, float def ) {
const float SHADOW_APERTURE = 0.2;
const float DEPTH_BIAS = 0.0;
Ray ray;
ray.origin = surface.position.world;
ray.direction = normalize( light.position - surface.position.world );
ray.origin -= ray.direction * 0.5;
float z = distance( surface.position.world, light.position ) - DEPTH_BIAS;
return 1.0 - voxelTrace( ray, SHADOW_APERTURE, z ).a;
}
#endif
void main() {
vec3 rayO = vec3(0);
vec3 rayD = vec3(0);
vec3 fragColor = vec3(0);
{
#if !MULTISAMPLING
const float depth = subpassLoad(samplerDepth).r;
@ -496,65 +559,79 @@ void main() {
vec4 positionEye = ubo.matrices.iProjection[inPushConstantPass] * vec4(inUv * 2.0 - 1.0, depth, 1.0);
positionEye /= positionEye.w;
position.eye = positionEye.xyz;
position.world = vec3( ubo.matrices.iView[inPushConstantPass] * positionEye );
surface.position.eye = positionEye.xyz;
surface.position.world = vec3( ubo.matrices.iView[inPushConstantPass] * positionEye );
}
#if 0
{
const vec4 near4 = ubo.matrices.iProjectionView[inPushConstantPass] * (vec4(2.0 * inUv - 1.0, -1.0, 1.0));
const vec4 far4 = ubo.matrices.iProjectionView[inPushConstantPass] * (vec4(2.0 * inUv - 1.0, 1.0, 1.0));
const vec3 near3 = near4.xyz / near4.w;
const vec3 far3 = far4.xyz / far4.w;
rayO = near3;
rayD = normalize( far3 - near3 );
surface.ray.origin = near3;
surface.ray.direction = normalize( far3 - near3 );
}
// separate our ray direction due to floating point precision problems
if ( true ) {
{
const mat4 iProjectionView = inverse( ubo.matrices.projection[inPushConstantPass] * mat4(mat3(ubo.matrices.view[inPushConstantPass])) );
const vec4 near4 = iProjectionView * (vec4(2.0 * inUv - 1.0, -1.0, 1.0));
const vec4 far4 = iProjectionView * (vec4(2.0 * inUv - 1.0, 1.0, 1.0));
const vec3 near3 = near4.xyz / near4.w;
const vec3 far3 = far4.xyz / far4.w;
rayD = normalize( far3 - near3 );
surface.ray.direction = normalize( far3 - near3 );
}
#else
{
const mat4 iProjectionView = inverse( ubo.matrices.projection[inPushConstantPass] * mat4(mat3(ubo.matrices.view[inPushConstantPass])) );
const vec4 near4 = iProjectionView * (vec4(2.0 * inUv - 1.0, -1.0, 1.0));
const vec4 far4 = iProjectionView * (vec4(2.0 * inUv - 1.0, 1.0, 1.0));
const vec3 near3 = near4.xyz / near4.w;
const vec3 far3 = far4.xyz / far4.w;
surface.ray.direction = normalize( far3 - near3 );
surface.ray.origin = ubo.matrices.eyePos[inPushConstantPass].xyz;
}
#endif
#if !MULTISAMPLING
normal.world = decodeNormals( subpassLoad(samplerNormal).xy );
surface.normal.world = decodeNormals( subpassLoad(samplerNormal).xy );
const uvec2 ID = subpassLoad(samplerId).xy;
#else
normal.world = decodeNormals( resolve(samplerNormal).xy );
surface.normal.world = decodeNormals( resolve(samplerNormal).xy );
const uvec2 ID = resolve(samplerId).xy;
#endif
normal.eye = vec3( ubo.matrices.view[inPushConstantPass] * vec4(normal.world, 0.0) );
surface.normal.eye = vec3( ubo.matrices.view[inPushConstantPass] * vec4(surface.normal.world, 0.0) );
if ( ID.x == 0 || ID.y == 0 ) {
fragColor.rgb = texture( samplerSkybox, rayD ).rgb;
fog(rayO, rayD, fragColor, 0.5);
outFragColor = vec4(fragColor,1);
surface.fragment.rgb = texture( samplerSkybox, surface.ray.direction ).rgb;
surface.fragment.a = 0.0;
outFragColor = postProcess();
return;
}
const uint drawId = ID.x - 1;
const DrawCall drawCall = drawCalls[drawId];
const uint materialId = ID.y + drawCall.materialIndex - 1;
const Material material = materials[materialId];
vec4 A = material.colorBase;
surface.material.id = ID.y + drawCall.materialIndex - 1;
const Material material = materials[surface.material.id];
surface.material.albedo = material.colorBase;
surface.fragment = material.colorEmissive;
#if DEFERRED_SAMPLING
#if !MULTISAMPLING
const vec2 uv = subpassLoad(samplerUv).xy;
surface.uv = subpassLoad(samplerUv).xy;
#else
const vec2 uv = resolve(samplerUv).xy;
surface.uv = resolve(samplerUv).xy;
#endif
const float mip = mipLevel(inUv.xy);
const bool useAtlas = validTextureIndex( drawCall.textureIndex + material.indexAtlas );
Texture textureAtlas;
if ( useAtlas ) textureAtlas = textures[drawCall.textureIndex + material.indexAtlas];
if ( validTextureIndex( drawCall.textureIndex + material.indexAtlas ) ) {
Texture t = textures[drawCall.textureIndex + material.indexAlbedo];
A = texture( samplerTextures[(useAtlas)?textureAtlas.index:t.index], ( useAtlas ) ? mix( t.lerp.xy, t.lerp.zw, uv ) : uv, mip );
if ( validTextureIndex( drawCall.textureIndex + material.indexAlbedo ) ) {
const Texture t = textures[drawCall.textureIndex + material.indexAlbedo];
surface.material.albedo = textureLod( samplerTextures[(useAtlas)?textureAtlas.index:t.index], ( useAtlas ) ? mix( t.lerp.xy, t.lerp.zw, surface.uv ) : surface.uv, mip );
}
// OPAQUE
if ( material.modeAlpha == 0 ) {
A.a = 1;
surface.material.albedo.a = 1;
// BLEND
} else if ( material.modeAlpha == 1 ) {
@ -562,142 +639,177 @@ void main() {
} else if ( material.modeAlpha == 2 ) {
}
// Emissive textures
if ( validTextureIndex( drawCall.textureIndex + material.indexEmissive ) ) {
const Texture t = textures[drawCall.textureIndex + material.indexEmissive];
surface.fragment += textureLod( samplerTextures[(useAtlas)?textureAtlas.index:t.index], ( useAtlas ) ? mix( t.lerp.xy, t.lerp.zw, surface.uv ) : surface.uv, mip );
}
#else
#if !MULTISAMPLING
A = subpassLoad(samplerAlbedo);
surface.material.albedo = subpassLoad(samplerAlbedo);
#else
A = resolve(samplerAlbedo);
surface.material.albedo = resolve(samplerAlbedo);
#endif
#endif
const float M = material.factorMetallic;
const float R = material.factorRoughness;
float AO = material.factorOcclusion;
vec4 indirectLighting = vec4(0);
surface.material.metallic = material.factorMetallic;
surface.material.roughness = material.factorRoughness;
surface.material.occlusion = material.factorOcclusion;
// GI
{
const vec3 P = surface.position.world;
const vec3 N = surface.normal.world;
#if 1
const vec3 right = normalize(orthogonal(N));
const vec3 up = normalize(cross(right, N));
const uint CONES_COUNT = 6;
const vec3 CONES[] = {
N,
normalize(N + 0.0f * right + 0.866025f * up),
normalize(N + 0.823639f * right + 0.267617f * up),
normalize(N + 0.509037f * right + -0.7006629f * up),
normalize(N + -0.50937f * right + -0.7006629f * up),
normalize(N + -0.823639f * right + 0.267617f * up),
};
#else
const vec3 ortho = normalize(orthogonal(N));
const vec3 ortho2 = normalize(cross(ortho, N));
const vec3 corner = 0.5f * (ortho + ortho2);
const vec3 corner2 = 0.5f * (ortho - ortho2);
const uint CONES_COUNT = 9;
const vec3 CONES[] = {
N,
normalize(mix(N, ortho, 0.5)),
normalize(mix(N, -ortho, 0.5)),
normalize(mix(N, ortho2, 0.5)),
normalize(mix(N, -ortho2, 0.5)),
normalize(mix(N, corner, 0.5)),
normalize(mix(N, -corner, 0.5)),
normalize(mix(N, corner2, 0.5)),
normalize(mix(N, -corner2, 0.5)),
};
#endif
const float DIFFUSE_CONE_APERTURE = 0.57735f;
const float DIFFUSE_INDIRECT_FACTOR = 1.0f / float(CONES_COUNT);
const float SPECULAR_CONE_APERTURE = clamp(tan(PI * 0.5f * surface.material.roughness), 0.0174533f, PI); // tan( R * PI * 0.5f * 0.1f );
const float SPECULAR_INDIRECT_FACTOR = (1.0 - surface.material.metallic) * 0.5; // 1.0f;
vec4 indirectDiffuse = vec4(0);
vec4 indirectSpecular = vec4(0);
const vec3 P = position.world;
const vec3 N = normal.world;
const float DIFFUSE_CONE_APERTURE = 0.57735f;
const float DIFFUSE_INDIRECT_FACTOR = 1.0f / 6.0f; // 1.0f;
const float SPECULAR_CONE_APERTURE = clamp(tan(PI * 0.5f * R), 0.0174533f, PI); // tan( R * PI * 0.5f * 0.1f );
const float SPECULAR_INDIRECT_FACTOR = (1.0 - M) * 0.5; // 1.0f;
const vec4 CONES[] = {
vec4(0.0f, 1.0f, 0.0f, PI / 4.0f),
vec4(0.0f, 0.5f, 0.866025f, 3.0f * PI / 20.0f),
vec4(0.823639f, 0.5f, 0.267617f, 3.0f * PI / 20.0f),
vec4(0.509037f, 0.5f, -0.7006629f, 3.0f * PI / 20.0f),
vec4(-0.50937f, 0.5f, -0.7006629f, 3.0f * PI / 20.0f),
vec4(-0.823639f, 0.5f, 0.267617f, 3.0f * PI / 20.0f)
};
{
voxelInfo.albedoSize = textureSize( voxelAlbedo, 0 ).x;
voxelInfo.albedoSizeRecip = 1.0 / voxelInfo.albedoSize;
voxelInfo.mipmapLevels = log2(voxelInfo.albedoSize) + 1; //textureQueryLod( voxelAlbedo, vec3(0) ).x;
#if VOXEL_TRACE_IN_NDC
voxelInfo.radianceSize = textureSize( voxelRadiance[0], 0 ).x;
voxelInfo.radianceSizeRecip = 1.0 / voxelInfo.radianceSize;
voxelInfo.mipmapLevels = log2(voxelInfo.radianceSize) + 1;
#if VXGI_NDC
voxelInfo.min = vec3( -1 );
voxelInfo.max = vec3( 1 );
voxelInfo.voxelSize = voxelInfo.albedoSizeRecip;
voxelInfo.voxelSize = voxelInfo.radianceSizeRecip;
#else
const mat4 inverseOrtho = inverse( ubo.matrices.voxel );
const mat4 inverseOrtho = inverse( ubo.matrices.vxgi );
voxelInfo.min = vec3( inverseOrtho * vec4( -1, -1, -1, 1 ) );
voxelInfo.max = vec3( inverseOrtho * vec4( 1, 1, 1, 1 ) );
voxelInfo.voxelSize = 1;
#endif
voxelInfo.voxelSizeRecip = 1.0 / voxelInfo.voxelSize;
}
// outFragColor.rgb = voxelConeTrace( rayO, rayD, 0 ).rgb; return;
// outFragColor.rgb = voxelConeTrace( surface.ray, 0 ).rgb; return;
Ray ray;
if ( DIFFUSE_INDIRECT_FACTOR > 0.0f ) {
vec3 guide = vec3(0.0f, 1.0f, 0.0f);
if (abs(dot(N,guide)) == 1.0f) guide = vec3(0.0f, 0.0f, 1.0f);
const vec3 right = normalize(guide - dot(N, guide) * N);
const vec3 up = cross(right, N);
for ( uint i = 0; i < 6; ++i ) {
const vec3 coneDirection = normalize(N + CONES[i].x * right + CONES[i].z * up);
indirectDiffuse += voxelConeTrace(P, coneDirection * ( dot(coneDirection, N) < 0 ? -1 : 1 ), DIFFUSE_CONE_APERTURE ) * CONES[i].w;
for ( uint i = 0; i < CONES_COUNT; ++i ) {
float weight = i == 0 ? PI * 0.25f : PI * 0.15f;
ray.origin = P;
ray.direction = CONES[i].xyz;
indirectDiffuse += voxelConeTrace( ray, DIFFUSE_CONE_APERTURE ) * weight;
}
// indirectDiffuse.rgb *= A.rgb;
// outFragColor.rgb = indirectDiffuse.rgb; return;
AO = indirectDiffuse.a;
surface.material.occlusion = 1.0 - clamp(indirectDiffuse.a, 0.0, 1.0);
// outFragColor.rgb = indirectDiffuse.rgb; return;
// outFragColor.rgb = vec3(surface.material.occlusion); return;
}
if ( SPECULAR_INDIRECT_FACTOR > 0.0f ) {
// const vec3 R = reflect( normalize(P - rayO), N );
const vec3 R = reflect( normalize(P - rayO), N );
indirectSpecular = voxelConeTrace( P, R, SPECULAR_CONE_APERTURE );
// outFragColor.rgb = indirectSpecular.rgb; return;
ray.origin = P;
ray.direction = reflect( normalize(P - surface.ray.origin), N );
indirectSpecular = voxelConeTrace( ray, SPECULAR_CONE_APERTURE );
// outFragColor.rgb = indirectSpecular.rgb; return;
/*
if ( indirectSpecular.a < 1.0 ) {
vec4 radiance = texture( samplerSkybox, ray.direction ) * 0.25;
indirectSpecular += (1.0 - indirectSpecular.a) * radiance;
}
*/
}
indirectLighting = indirectDiffuse * DIFFUSE_INDIRECT_FACTOR + indirectSpecular * SPECULAR_INDIRECT_FACTOR;
// outFragColor.rgb = indirectLighting.rgb; return;
surface.material.indirect = indirectDiffuse * DIFFUSE_INDIRECT_FACTOR + indirectSpecular * SPECULAR_INDIRECT_FACTOR;
// outFragColor.rgb = surface.material.indirect.rgb; return;
}
float litFactor = 1.0;
if ( 0 <= material.indexLightmap ) {
fragColor = A.rgb + ubo.ambient.rgb * (1 - AO) + indirectLighting.rgb;
surface.fragment.rgb += surface.material.albedo.rgb + ubo.ambient.rgb * surface.material.occlusion + surface.material.indirect.rgb;
} else {
fragColor = A.rgb * ubo.ambient.rgb * (1 - AO) + indirectLighting.rgb;
surface.fragment.rgb += surface.material.albedo.rgb * ubo.ambient.rgb * surface.material.occlusion + surface.material.indirect.rgb;
}
#if DEFERRED_SAMPLING
// deferred sampling doesn't have a blended albedo buffer
// in place we'll just cone trace behind the window
if ( surface.material.albedo.a < 1.0 ) {
Ray ray;
ray.origin = surface.position.world;
ray.direction = surface.ray.direction;
vec4 radiance = voxelConeTrace( ray, surface.material.albedo.a );
surface.fragment.rgb += (1.0 - surface.material.albedo.a) * radiance.rgb;
}
#endif
// corrections
surface.material.roughness *= 4.0;
{
const float R = material.factorRoughness * 2.0f;
const vec3 N = normal.eye;
const vec3 F0 = mix(vec3(0.04), A.rgb, M);
const vec3 Lo = normalize( -position.eye );
const float cosLo = max(0.0, dot(N, Lo));
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));
for ( uint i = 0; i < ubo.lights; ++i ) {
const Light light = lights[i];
if ( light.power <= LIGHT_POWER_CUTOFF ) continue;
const vec3 Lp = light.position;
const vec3 Liu = vec3(ubo.matrices.view[inPushConstantPass] * vec4(light.position, 1)) - position.eye;
const vec3 Liu = vec3(ubo.matrices.view[inPushConstantPass] * vec4(light.position, 1)) - surface.position.eye;
const vec3 Li = normalize(Liu);
#if VXGI_SHADOWS
const float Ls = i < ubo.shadowSamples ? shadowFactor( light, 0.0 ) : 1.0;
#else
const float Ls = shadowFactor( light, 0.0 );
#endif
const float La = 1.0 / (PI * pow(length(Liu), 2.0));
if ( light.power * La * Ls <= LIGHT_POWER_CUTOFF ) continue;
const float cosLi = max(0.0, dot(N, Li));
const float cosLi = max(0.0, dot(surface.normal.eye, Li));
const vec3 Lr = light.color.rgb * light.power * La * Ls;
#if LAMBERT
const vec3 diffuse = A.rgb;
const vec3 diffuse = surface.material.albedo.rgb;
const vec3 specular = vec3(0);
#elif PBR
const vec3 Lh = normalize(Li + Lo);
const float cosLh = max(0.0, dot(N, Lh));
const float cosLh = max(0.0, dot(surface.normal.eye, Lh));
const vec3 F = fresnelSchlick( F0, max( 0.0, dot(Lh, Lo) ) );
const float D = ndfGGX( cosLh, R );
const float G = gaSchlickGGX(cosLi, cosLo, R);
const vec3 diffuse = mix( vec3(1.0) - F, vec3(0.0), M ) * A.rgb;
const float D = ndfGGX( cosLh, surface.material.roughness );
const float G = gaSchlickGGX(cosLi, cosLo, surface.material.roughness);
const vec3 diffuse = mix( vec3(1.0) - F, vec3(0.0), surface.material.metallic ) * surface.material.albedo.rgb;
const vec3 specular = (F * D * G) / max(EPSILON, 4.0 * cosLi * cosLo);
#endif
// lightmapped, compute only specular
if ( light.type >= 0 && 0 <= material.indexLightmap ) fragColor.rgb += (specular) * Lr * cosLi;
if ( light.type >= 0 && 0 <= material.indexLightmap ) surface.fragment.rgb += (specular) * Lr * cosLi;
// point light, compute only diffuse
// else if ( abs(light.type) == 1 ) fragColor.rgb += (diffuse) * Lr * cosLi;
else fragColor.rgb += (diffuse + specular) * Lr * cosLi;
litFactor += light.power * La * Ls;
// else if ( abs(light.type) == 1 ) surface.fragment.rgb += (diffuse) * Lr * cosLi;
else surface.fragment.rgb += (diffuse + specular) * Lr * cosLi;
surface.fragment.a += light.power * La * Ls;
}
}
#if FOG
fog(rayO, rayD, fragColor, 1.0 ); //litFactor);
#endif
#if TONE_MAP
fragColor = vec3(1.0) - exp(-fragColor * ubo.exposure);
#endif
#if GAMMA_CORRECT
fragColor = pow(fragColor, vec3(1.0 / ubo.gamma));
#endif
#if WHITENOISE
if ( (ubo.mode.type & (0x1 << 1)) == (0x1 << 1) ) whitenoise(fragColor);
#endif
outFragColor = vec4(fragColor,1);
outFragColor = postProcess();
}

View File

@ -4,8 +4,7 @@
layout (local_size_x = 8, local_size_y = 8, local_size_z = 8) in;
#define MULTISAMPLING 1
#define RAY_MARCH_FOG 1
#define DEFERRED_SAMPLING 0
#define DEFERRED_SAMPLING 1
#define LAMBERT 1
#define PBR 0
@ -15,26 +14,8 @@ const float EPSILON = 0.00001;
const float LIGHT_POWER_CUTOFF = 0.005;
const vec2 poissonDisk[16] = vec2[](
vec2( -0.94201624, -0.39906216 ),
vec2( 0.94558609, -0.76890725 ),
vec2( -0.094184101, -0.92938870 ),
vec2( 0.34495938, 0.29387760 ),
vec2( -0.91588581, 0.45771432 ),
vec2( -0.81544232, -0.87912464 ),
vec2( -0.38277543, 0.27676845 ),
vec2( 0.97484398, 0.75648379 ),
vec2( 0.44323325, -0.97511554 ),
vec2( 0.53742981, -0.47373420 ),
vec2( -0.26496911, -0.41893023 ),
vec2( 0.79197514, 0.19090188 ),
vec2( -0.24188840, 0.99706507 ),
vec2( -0.81409955, 0.91437590 ),
vec2( 0.19984126, 0.78641367 ),
vec2( 0.14383161, -0.14100790 )
);
layout (constant_id = 0) const uint TEXTURES = 256;
layout (constant_id = 1) const uint CASCADES = 1;
struct Matrices {
mat4 view[2];
@ -42,13 +23,22 @@ struct Matrices {
mat4 iView[2];
mat4 iProjection[2];
mat4 iProjectionView[2];
mat4 voxel;
vec4 eyePos[2];
mat4 vxgi;
};
struct Space {
vec3 eye;
vec3 world;
} position, normal, view;
};
struct Ray {
vec3 origin;
vec3 direction;
vec3 position;
float distance;
};
struct Fog {
vec3 color;
@ -109,6 +99,7 @@ struct Material {
int indexLightmap;
int modeAlpha;
};
struct Texture {
int index;
int samp;
@ -117,6 +108,7 @@ struct Texture {
vec4 lerp;
};
struct DrawCall {
int materialIndex;
uint materials;
@ -124,6 +116,29 @@ struct DrawCall {
uint textures;
};
struct SurfaceMaterial {
uint id;
vec4 albedo;
vec4 indirect;
float metallic;
float roughness;
float occlusion;
};
struct Surface {
vec2 uv;
Space position;
Space normal;
Ray ray;
SurfaceMaterial material;
vec4 fragment;
} surface;
layout (binding = 4) uniform UBO {
Matrices matrices;
@ -136,12 +151,12 @@ layout (binding = 4) uniform UBO {
uint drawCalls;
vec3 ambient;
float kexp;
uint msaa;
uint poissonSamples;
float gamma;
float exposure;
uint msaa;
uint shadowSamples;
uint padding1;
} ubo;
layout (std140, binding = 5) readonly buffer Lights {
@ -157,10 +172,10 @@ layout (std140, binding = 8) readonly buffer DrawCalls {
DrawCall drawCalls[];
};
layout (binding = 9, rg16ui) uniform volatile coherent uimage3D voxelID;
layout (binding = 10, rg16f) uniform volatile coherent image3D voxelNormal;
layout (binding = 11, rg16f) uniform volatile coherent image3D voxelUv;
layout (binding = 12, rgba8) uniform volatile coherent image3D voxelAlbedo;
layout (binding = 9, rg16ui) uniform volatile coherent uimage3D voxelId[CASCADES];
layout (binding = 10, rg16f) uniform volatile coherent image3D voxelUv[CASCADES];
layout (binding = 11, rg16f) uniform volatile coherent image3D voxelNormal[CASCADES];
layout (binding = 12, rgba8) uniform volatile coherent image3D voxelRadiance[CASCADES];
layout (binding = 13) uniform sampler3D samplerNoise;
layout (binding = 14) uniform samplerCube samplerSkybox;
@ -230,7 +245,7 @@ bool validTextureIndex( int textureIndex ) {
float shadowFactor( const Light light, float def ) {
if ( !validTextureIndex(light.mapIndex) ) return 1.0;
vec4 positionClip = light.projection * light.view * vec4(position.world, 1.0);
vec4 positionClip = light.projection * light.view * vec4(surface.position.world, 1.0);
positionClip.xyz /= positionClip.w;
if ( positionClip.x < -1 || positionClip.x >= 1 ) return def; //0.0;
@ -253,11 +268,11 @@ float shadowFactor( const Light light, float def ) {
const vec2 uv = positionClip.xy * 0.5 + 0.5;
const float bias = light.depthBias;
const float eyeDepth = positionClip.z;
const int samples = int(ubo.poissonSamples);
const int samples = int(ubo.shadowSamples);
return eyeDepth < texture(samplerTextures[light.mapIndex], uv).r - bias ? 0.0 : factor;
#if 0
for ( int i = 0; i < samples; ++i ) {
const int index = int( float(samples) * random(floor(position.world.xyz * 1000.0), i)) % samples;
const int index = int( float(samples) * random(floor(surface.position.world.xyz * 1000.0), i)) % samples;
const float lightDepth = texture(samplerTextures[light.mapIndex], uv + poissonDisk[index] / 700.0 ).r;
if ( eyeDepth < lightDepth - bias ) factor -= 1.0 / samples;
}
@ -266,121 +281,105 @@ float shadowFactor( const Light light, float def ) {
}
void main() {
vec3 fragColor = vec3(0);
const vec3 tUvw = gl_GlobalInvocationID.xzy;
for ( uint CASCADE = 0; CASCADE < CASCADES; ++CASCADE ) {
surface.normal.world = decodeNormals( vec2(imageLoad(voxelNormal[CASCADE], ivec3(tUvw) ).xy) );
surface.normal.eye = vec3( ubo.matrices.vxgi * vec4( surface.normal.world, 0.0f ) );
const vec3 tUvw = gl_GlobalInvocationID.xyz;
{
const vec2 N = vec2(imageLoad(voxelNormal, ivec3(tUvw) ).xy);
normal.world = decodeNormals( N );
normal.eye = vec3( ubo.matrices.voxel * vec4( normal.world, 0.0f ) );
position.eye = vec3(gl_GlobalInvocationID.xyz) / vec3(imageSize(voxelAlbedo)) * 2.0f - 1.0f;
position.world = vec3( inverse(ubo.matrices.voxel) * vec4( position.eye, 1.0f ) );
}
const uvec2 ID = uvec2(imageLoad(voxelID, ivec3(tUvw) ).xy);
if ( ID.x == 0 || ID.y == 0 ) {
imageStore(voxelAlbedo, ivec3(tUvw), vec4(0));
return;
}
#if 0
{
const uvec3 dim = imageSize(voxelAlbedo);
float sdf = max(dim.x, max(dim.y, dim.z)) * 2.82842712;
uvec2 ID;
ivec3 coord;
for ( uint z = 0; z < dim.z; ++z ) {
for ( uint y = 0; y < dim.y; ++y ) {
for ( uint x = 0; x < dim.x; ++x ) {
coord = ivec3(x,y,z);
ID = imageLoad( voxelID, coord ).xy;
if ( ID.x == 0 || ID.y == 0 ) continue;
sdf = min(distance(tUvw, coord), sdf);
surface.position.eye = vec3(gl_GlobalInvocationID.xyz) / (vec3(imageSize(voxelRadiance[CASCADE])) / (CASCADE + 1)) * 2.0f - 1.0f;
surface.position.world = vec3( inverse(ubo.matrices.vxgi) * vec4( surface.position.eye, 1.0f ) );
const uvec2 ID = uvec2(imageLoad(voxelId[CASCADE], ivec3(tUvw) ).xy);
if ( ID.x == 0 || ID.y == 0 ) {
imageStore(voxelRadiance[CASCADE], ivec3(tUvw), vec4(0));
continue;
}
const uint drawId = ID.x - 1;
const DrawCall drawCall = drawCalls[drawId];
surface.material.id = ID.y + drawCall.materialIndex - 1;
const Material material = materials[surface.material.id];
surface.material.albedo = material.colorBase;
surface.fragment = material.colorEmissive;
#if DEFERRED_SAMPLING
surface.uv = imageLoad(voxelUv[CASCADE], ivec3(tUvw) ).xy;
const bool useAtlas = validTextureIndex( drawCall.textureIndex + material.indexAtlas );
Texture textureAtlas;
if ( useAtlas ) textureAtlas = textures[drawCall.textureIndex + material.indexAtlas];
if ( validTextureIndex( drawCall.textureIndex + material.indexAlbedo ) ) {
const Texture t = textures[drawCall.textureIndex + material.indexAlbedo];
surface.material.albedo = texture( samplerTextures[(useAtlas)?textureAtlas.index:t.index], ( useAtlas ) ? mix( t.lerp.xy, t.lerp.zw, surface.uv ) : surface.uv );
}
// OPAQUE
if ( material.modeAlpha == 0 ) {
surface.material.albedo.a = 1;
// BLEND
} else if ( material.modeAlpha == 1 ) {
// MASK
} else if ( material.modeAlpha == 2 ) {
}
}
#endif
const uint drawId = ID.x - 1;
const DrawCall drawCall = drawCalls[drawId];
const uint materialId = ID.y + drawCall.materialIndex - 1;
const Material material = materials[materialId];
vec4 A = material.colorBase;
#if DEFERRED_SAMPLING
const vec2 uv = imageLoad(voxelUv, ivec3(tUvw) ).xy;
const bool useAtlas = validTextureIndex( drawCall.textureIndex + material.indexAtlas );
Texture textureAtlas;
if ( useAtlas ) textureAtlas = textures[drawCall.textureIndex + material.indexAtlas];
if ( validTextureIndex( drawCall.textureIndex + material.indexAtlas ) ) {
Texture t = textures[drawCall.textureIndex + material.indexAlbedo];
A = texture( samplerTextures[(useAtlas)?textureAtlas.index:t.index], ( useAtlas ) ? mix( t.lerp.xy, t.lerp.zw, uv ) : uv );
}
// OPAQUE
if ( material.modeAlpha == 0 ) {
A.a = 1;
// BLEND
} else if ( material.modeAlpha == 1 ) {
// MASK
} else if ( material.modeAlpha == 2 ) {
}
#else
A = imageLoad(voxelAlbedo, ivec3(tUvw) );
#endif
const float M = material.factorMetallic;
const float R = material.factorRoughness;
const float AO = material.factorOcclusion;
float litFactor = 1.0;
if ( 0 <= material.indexLightmap ) {
fragColor = A.rgb + ubo.ambient.rgb * (1 - AO);
} else {
fragColor = A.rgb * ubo.ambient.rgb * (1 - AO);
}
{
const float R = material.factorRoughness * 2.0f;
const vec3 N = normal.world;
const vec3 F0 = mix(vec3(0.04), A.rgb, M);
const vec3 Lo = normalize( position.world );
const float cosLo = max(0.0, dot(N, Lo));
for ( uint i = 0; i < ubo.lights; ++i ) {
const Light light = lights[i];
if ( light.power <= LIGHT_POWER_CUTOFF ) continue;
if ( light.type >= 0 && 0 <= material.indexLightmap ) continue;
const vec3 Lp = light.position;
const vec3 Liu = light.position - 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));
if ( light.power * La * Ls <= LIGHT_POWER_CUTOFF ) continue;
const float cosLi = max(0.0, dot(N, Li));
const vec3 Lr = light.color.rgb * light.power * La * Ls;
#if LAMBERT
const vec3 diffuse = A.rgb;
const vec3 specular = vec3(0);
#elif PBR
const vec3 Lh = normalize(Li + Lo);
const float cosLh = max(0.0, dot(N, Lh));
const vec3 F = fresnelSchlick( F0, max( 0.0, dot(Lh, Lo) ) );
const float D = ndfGGX( cosLh, R );
const float G = gaSchlickGGX(cosLi, cosLo, R);
const vec3 diffuse = mix( vec3(1.0) - F, vec3(0.0), M ) * A.rgb;
const vec3 specular = (F * D * G) / max(EPSILON, 4.0 * cosLi * cosLo);
#endif
// lightmapped, compute only specular
if ( light.type >= 0 && 0 <= material.indexLightmap ) fragColor.rgb += (specular) * Lr * cosLi;
// point light, compute only diffuse
// else if ( abs(light.type) == 1 ) fragColor.rgb += (diffuse) * Lr * cosLi;
else fragColor.rgb += (diffuse + specular) * Lr * cosLi;
litFactor += light.power * La * Ls;
// Emissive textures
if ( validTextureIndex( drawCall.textureIndex + material.indexEmissive ) ) {
const Texture t = textures[drawCall.textureIndex + material.indexEmissive];
surface.fragment += texture( samplerTextures[(useAtlas)?textureAtlas.index:t.index], ( useAtlas ) ? mix( t.lerp.xy, t.lerp.zw, surface.uv ) : surface.uv );
}
}
#else
surface.material.albedo = imageLoad(voxelRadiance[CASCADE], ivec3(tUvw) );
#endif
surface.material.metallic = material.factorMetallic;
surface.material.roughness = material.factorRoughness;
surface.material.occlusion = material.factorOcclusion;
imageStore(voxelAlbedo, ivec3(tUvw), vec4(fragColor.rgb, 1));
float litFactor = 1.0;
if ( 0 <= material.indexLightmap ) {
surface.fragment.rgb += surface.material.albedo.rgb + ubo.ambient.rgb * surface.material.occlusion;
} else {
surface.fragment.rgb += surface.material.albedo.rgb * ubo.ambient.rgb * surface.material.occlusion;
}
// corrections
surface.material.roughness *= 4.0;
{
const vec3 F0 = mix(vec3(0.04), surface.material.albedo.rgb, surface.material.metallic);
const vec3 Lo = normalize( surface.position.world );
const float cosLo = max(0.0, dot(surface.normal.world, Lo));
for ( uint i = 0; i < ubo.lights; ++i ) {
const Light light = lights[i];
if ( light.power <= LIGHT_POWER_CUTOFF ) continue;
if ( light.type >= 0 && 0 <= material.indexLightmap ) continue;
const vec3 Lp = light.position;
const vec3 Liu = light.position - surface.position.world;
const vec3 Li = normalize(Liu);
const float Ls = shadowFactor( light, 0.0 );
const float La = 1.0 / (PI * pow(length(Liu), 2.0));
if ( light.power * La * Ls <= LIGHT_POWER_CUTOFF ) continue;
const float cosLi = max(0.0, dot(surface.normal.world, Li));
const vec3 Lr = light.color.rgb * light.power * La * Ls;
#if LAMBERT
const vec3 diffuse = surface.material.albedo.rgb;
const vec3 specular = vec3(0);
#elif PBR
const vec3 Lh = normalize(Li + Lo);
const float cosLh = max(0.0, dot(surface.normal.world, Lh));
const vec3 F = fresnelSchlick( F0, max( 0.0, dot(Lh, Lo) ) );
const float D = ndfGGX( cosLh, surface.material.roughness );
const float G = gaSchlickGGX(cosLi, cosLo, surface.material.roughness);
const vec3 diffuse = mix( vec3(1.0) - F, vec3(0.0), surface.material.metallic ) * surface.material.albedo.rgb;
const vec3 specular = (F * D * G) / max(EPSILON, 4.0 * cosLi * cosLo);
#endif
// lightmapped, compute only specular
if ( light.type >= 0 && 0 <= material.indexLightmap ) surface.fragment.rgb += (specular) * Lr * cosLi;
// point light, compute only diffuse
// else if ( abs(light.type) == 1 ) surface.fragment.rgb += (diffuse) * Lr * cosLi;
else surface.fragment.rgb += (diffuse + specular) * Lr * cosLi;
surface.fragment.a += light.power * La * Ls;
}
}
imageStore(voxelRadiance[CASCADE], ivec3(tUvw), vec4(surface.fragment.rgb, 1));
}
}

View File

@ -50,6 +50,7 @@ struct Material {
int indexLightmap;
int modeAlpha;
};
struct Texture {
int index;
int samp;
@ -58,6 +59,7 @@ struct Texture {
vec4 lerp;
};
struct Light {
vec3 position;
float radius;
@ -73,6 +75,43 @@ struct Light {
mat4 view;
mat4 projection;
};
struct Ray {
vec3 origin;
vec3 direction;
vec3 position;
float distance;
};
struct Space {
vec3 eye;
vec3 world;
};
struct SurfaceMaterial {
uint id;
vec4 albedo;
vec4 indirect;
float metallic;
float roughness;
float occlusion;
};
struct Surface {
vec2 uv;
Space position;
Space normal;
Ray ray;
SurfaceMaterial material;
vec4 fragment;
} surface;
layout (std140, binding = 3) readonly buffer Materials {
Material materials[];
};
@ -160,10 +199,10 @@ bool validTextureIndex( int textureIndex ) {
return 0 <= textureIndex; // && textureIndex < ubo.textures;
}
float shadowFactor( const Light light, const vec3 P, float def ) {
float shadowFactor( const Light light, float def ) {
if ( !validTextureIndex(light.mapIndex) ) return 1.0;
vec4 positionClip = light.projection * light.view * vec4(P, 1.0);
vec4 positionClip = light.projection * light.view * vec4(surface.position.world, 1.0);
positionClip.xyz /= positionClip.w;
if ( positionClip.x < -1 || positionClip.x >= 1 ) return def; //0.0;
@ -189,7 +228,7 @@ float shadowFactor( const Light light, const vec3 P, float def ) {
const int samples = 16; //int(ubo.poissonSamples);
if ( samples <= 1 ) return eyeDepth < texture(samplerTextures[light.mapIndex], uv).r - bias ? 0.0 : factor;
for ( int i = 0; i < samples; ++i ) {
const int index = int( float(samples) * random(floor(P * 1000.0), i)) % samples;
const int index = int( float(samples) * random(floor(surface.position.world * 1000.0), i)) % samples;
const float lightDepth = texture(samplerTextures[light.mapIndex], uv + poissonDisk[index] / 700.0 ).r;
if ( eyeDepth < lightDepth - bias ) factor -= 1.0 / samples;
}
@ -198,16 +237,18 @@ float shadowFactor( const Light light, const vec3 P, float def ) {
void main() {
vec4 A = vec4(1, 1, 1, 1);
vec3 N = normalize( inNormal );
surface.normal.world = normalize( inNormal );
const float mip = mipLevel(inUv.xy);
const vec2 uv = wrap(inUv.xy);
const vec3 P = inPosition;
const int materialId = int(inId.y);
const Material material = materials[materialId];
surface.uv = wrap(inUv.xy);
surface.position.world = inPosition;
surface.material.id = int(inId.y);
const Material material = materials[surface.material.id];
const float M = material.factorMetallic;
const float R = material.factorRoughness;
const float AO = 1.0f - material.factorOcclusion;
surface.material.metallic = material.factorMetallic;
surface.material.roughness = material.factorRoughness;
surface.material.occlusion = 1.0f - material.factorOcclusion;
surface.fragment = material.colorEmissive;
#if 0
// sample albedo
const bool useAtlas = validTextureIndex( material.indexAtlas );
@ -215,66 +256,70 @@ void main() {
if ( useAtlas ) textureAtlas = textures[material.indexAtlas];
if ( !validTextureIndex( material.indexAlbedo ) ) discard;
{
Texture t = textures[material.indexAlbedo];
A = textureLod( samplerTextures[(useAtlas) ? textureAtlas.index : t.index], (useAtlas) ? mix( t.lerp.xy, t.lerp.zw, uv ) : uv, mip );
const Texture t = textures[material.indexAlbedo];
surface.material.albedo = textureLod( samplerTextures[(useAtlas) ? textureAtlas.index : t.index], (useAtlas) ? mix( t.lerp.xy, t.lerp.zw, uv ) : uv, mip );
// alpha mode OPAQUE
if ( material.modeAlpha == 0 ) {
A.a = 1;
surface.material.albedo.a = 1;
// alpha mode BLEND
} else if ( material.modeAlpha == 1 ) {
// alpha mode MASK
} else if ( material.modeAlpha == 2 ) {
if ( A.a < abs(material.factorAlphaCutoff) ) discard;
A.a = 1;
if ( surface.material.albedo.a < abs(material.factorAlphaCutoff) ) discard;
surface.material.albedo.a = 1;
}
if ( A.a == 0 ) discard;
if ( surface.material.albedo.a == 0 ) discard;
}
// sample normal
if ( validTextureIndex( material.indexNormal ) ) {
Texture t = textures[material.indexNormal];
N = inTBN * normalize( textureLod( samplerTextures[(useAtlas)?textureAtlas.index:t.index], ( useAtlas ) ? mix( t.lerp.xy, t.lerp.zw, uv ) : uv, mip ).xyz * 2.0 - vec3(1.0));
const Texture t = textures[material.indexNormal];
surfacem.normal.world = inTBN * normalize( textureLod( samplerTextures[(useAtlas)?textureAtlas.index:t.index], ( useAtlas ) ? mix( t.lerp.xy, t.lerp.zw, uv ) : uv, mip ).xyz * 2.0 - vec3(1.0));
}
// sample emissive
if ( validTextureIndex( material.indexEmissive ) ) {
const Texture t = textures[material.indexEmissive];
surface.fragment = textureLod( samplerTextures[(useAtlas) ? textureAtlas.index : t.index], (useAtlas) ? mix( t.lerp.xy, t.lerp.zw, uv ) : uv, mip );
}
#else
A = vec4(1);
surface.material.albedo = vec4(1);
#endif
float litFactor = 1.0;
vec3 fragColor = vec3(0);
{
const vec3 F0 = mix(vec3(0.04), A.rgb, M);
const vec3 Lo = normalize( -P );
const float cosLo = max(0.0, dot(N, Lo));
const vec3 F0 = mix(vec3(0.04), surface.material.albedo.rgb, surface.material.metallic);
const vec3 Lo = normalize( -surface.position.world );
const float cosLo = max(0.0, dot(surface.normal.world, Lo));
for ( uint i = 0; i < lights.length(); ++i ) {
const Light light = lights[i];
if ( light.power <= LIGHT_POWER_CUTOFF ) continue;
const vec3 Lp = light.position;
const vec3 Liu = light.position - P;
const vec3 Liu = light.position - surface.position.world;
const float La = 1.0 / (PI * pow(length(Liu), 2.0));
const float Ls = shadowFactor( light, P, 0.0 );
const float Ls = shadowFactor( light, 0.0 );
if ( light.power * La * Ls <= LIGHT_POWER_CUTOFF ) continue;
const vec3 Li = normalize(Liu);
const vec3 Lr = light.color.rgb * light.power * La * Ls;
const float cosLi = abs(dot(N, Li));// max(0.0, dot(N, Li));
const float cosLi = abs(dot(surface.normal.world, Li));// max(0.0, dot(N, Li));
#if LAMBERT
const vec3 diffuse = A.rgb;
const vec3 diffuse = surface.material.albedo.rgb;
const vec3 specular = vec3(0);
#elif PBR
const vec3 Lh = normalize(Li + Lo);
const float cosLh = max(0.0, dot(N, Lh));
const vec3 F = fresnelSchlick( F0, max( 0.0, dot(Lh, Lo) ) );
const float D = ndfGGX( cosLh, R );
const float G = gaSchlickGGX(cosLi, cosLo, R);
const vec3 diffuse = mix( vec3(1.0) - F, vec3(0.0), M ) * A.rgb;
const float D = ndfGGX( cosLh, surface.material.roughness );
const float G = gaSchlickGGX(cosLi, cosLo, surface.material.roughness);
const vec3 diffuse = mix( vec3(1.0) - F, vec3(0.0), surface.material.metallic ) * surface.material.albedo.rgb;
const vec3 specular = (F * D * G) / max(EPSILON, 4.0 * cosLi * cosLo);
#endif
fragColor.rgb += (diffuse + specular) * Lr * cosLi;
litFactor += light.power * La * Ls;
surface.fragment.rgb += (diffuse + specular) * Lr * cosLi;
surface.fragment.a += light.power * La * Ls;
}
}
outAlbedo = vec4(fragColor, 1);
outAlbedo = vec4(surface.fragment.rgb, 1);
}

View File

@ -1,6 +1,6 @@
#version 450
#define DEFERRED_SAMPLING 0
#define DEFERRED_SAMPLING 1
#define CAN_DISCARD 1
#define USE_LIGHTMAP 1
@ -137,7 +137,7 @@ void main() {
// sample metallic/roughness
if ( validTextureIndex( material.indexMetallicRoughness ) ) {
Texture t = textures[material.indexMetallicRoughness];
const vec4 sampled = texture( samplerTextures[(useAtlas)?textureAtlas.index:t.index], ( useAtlas ) ? mix( t.lerp.xy, t.lerp.zw, uv ) : uv, mip );
const vec4 sampled = textureLod( samplerTextures[(useAtlas)?textureAtlas.index:t.index], ( useAtlas ) ? mix( t.lerp.xy, t.lerp.zw, uv ) : uv, mip );
M = sampled.b;
R = sampled.g;
}
@ -145,7 +145,7 @@ void main() {
AO = material.factorOcclusion;
if ( validTextureIndex( material.indexOcclusion ) ) {
Texture t = textures[material.indexOcclusion];
AO = texture( samplerTextures[(useAtlas)?textureAtlas.index:t.index], ( useAtlas ) ? mix( t.lerp.xy, t.lerp.zw, uv ) : uv ).r;
AO = textureLod( samplerTextures[(useAtlas)?textureAtlas.index:t.index], ( useAtlas ) ? mix( t.lerp.xy, t.lerp.zw, uv ) : uv ).r;
}
#endif
outAlbedo = A * inColor;

View File

@ -1,11 +1,12 @@
#version 450
#define DEFERRED_SAMPLING 0
#define DEFERRED_SAMPLING 1
#define USE_LIGHTMAP 1
#define PI 3.1415926536f
layout (constant_id = 0) const uint TEXTURES = 1;
layout (constant_id = 1) const uint CASCADES = 1;
struct Material {
vec4 colorBase;
@ -51,10 +52,11 @@ layout (location = 7) in vec3 inPosition;
layout (location = 8) flat in ivec4 inId;
layout (binding = 7) uniform sampler2D samplerTextures[TEXTURES];
layout (binding = 8, rg16ui) uniform volatile coherent uimage3D voxelID;
layout (binding = 9, rg16f) uniform volatile coherent image3D voxelNormal;
layout (binding = 10, rg16f) uniform volatile coherent image3D voxelUv;
layout (binding = 11, rgba8) uniform volatile coherent image3D voxelAlbedo;
layout (binding = 8, rg16ui) uniform volatile coherent uimage3D voxelId[CASCADES];
layout (binding = 9, rg16f) uniform volatile coherent image3D voxelUv[CASCADES];
layout (binding = 10, rg16f) uniform volatile coherent image3D voxelNormal[CASCADES];
layout (binding = 11, rgba8) uniform volatile coherent image3D voxelRadiance[CASCADES];
layout (location = 0) out uvec2 outId;
layout (location = 1) out vec2 outNormals;
@ -84,8 +86,9 @@ bool validTextureIndex( int textureIndex ) {
}
void main() {
const vec3 P = inPosition;
if ( !(abs(P.x) < 1.0 && abs(P.y) < 1 && abs(P.z) < 1) ) discard;
const vec3 P = inPosition.xzy;
const uint CASCADE = uint(max( abs(floor(P.x)), max( abs(floor(P.y)), abs(floor(P.z)) ) ));
if ( CASCADES <= CASCADE ) discard;
vec4 A = vec4(0, 0, 0, 0);
const vec3 N = inNormal;
@ -136,8 +139,8 @@ void main() {
const vec2 outNormals = encodeNormals( normalize( N ) );
const vec2 outUvs = wrap(inUv.xy);
imageStore(voxelID, ivec3(P * imageSize(voxelID)), uvec4(outId, 0, 0));
imageStore(voxelNormal, ivec3(P * imageSize(voxelNormal)), vec4(outNormals, 0, 0));
imageStore(voxelUv, ivec3(P * imageSize(voxelUv)), vec4(outUvs, 0, 0));
imageStore(voxelAlbedo, ivec3(P * imageSize(voxelAlbedo)), outAlbedo);
imageStore(voxelId[CASCADE], ivec3(P * (1 + CASCADE) * imageSize(voxelId[CASCADE])), uvec4(outId, 0, 0));
imageStore(voxelNormal[CASCADE], ivec3(P * (1 + CASCADE) * imageSize(voxelNormal[CASCADE])), vec4(outNormals, 0, 0));
imageStore(voxelUv[CASCADE], ivec3(P * (1 + CASCADE) * imageSize(voxelUv[CASCADE])), vec4(outUvs, 0, 0));
imageStore(voxelRadiance[CASCADE], ivec3(P * (1 + CASCADE) * imageSize(voxelRadiance[CASCADE])), outAlbedo);
}

View File

@ -24,39 +24,42 @@ layout (binding = 6) uniform UBO {
} ubo;
void main(){
vec3 norm = abs(inNormal[0] + inNormal[1] + inNormal[2]);
uint axis = norm.y > norm.x ? 1 : 0;
axis = norm.z > norm[axis] ? 2 : axis;
const float RENDER_RESOLUTION = 256.0;
const float PIXEL_SCALE = 2.0;
const float HALF_PIXEL = 1.0 / (RENDER_RESOLUTION * PIXEL_SCALE);
const vec3 C = ( inPosition[0] + inPosition[1] + inPosition[2] ) / 3.0;
mat4 invOrtho = inverse( ubo.voxel );
vec3 extentMin = vec3( invOrtho * vec4(-1, -1, -1, 1 ) );
vec3 extentMid = vec3( invOrtho * vec4( 0, 0, 0, 1 ) );
vec3 extentMax = vec3( invOrtho * vec4( 1, 1, 1, 1 ) );
vec3 extentSize = extentMax - extentMin;
for( uint i = 0; i < 3; ++i ){
#if USE_CROSS
const vec3 N = abs(cross(inPosition[2] - inPosition[0], inPosition[1] - inPosition[0]));
#else
const vec3 N = abs(inNormal[0] + inNormal[1] + inNormal[2]);
uint A = N.y > N.x ? 1 : 0;
A = N.z > N[A] ? 2 : A;
#endif
for(uint i = 0; i < 3; ++i){
outUv = inUv[i];
outSt = inSt[i];
outColor = inColor[i];
outNormal = inNormal[i];
outTBN = inTBN[i];
outPosition = inPosition[i];
outPosition = vec3( ubo.voxel * vec4( inPosition[i], 1 ) ) + normalize( inPosition[i] - C ) * HALF_PIXEL;
outId = inId[i];
outPosition = vec3( ubo.voxel * vec4( outPosition, 1 ) );
gl_Position = vec4( outPosition.xyz, 1 );
if ( axis == 0 ) gl_Position.xyz = gl_Position.zyx;
else if ( axis == 1 ) gl_Position.xyz = gl_Position.xzy;
// outPosition = (inPosition[i] - extentMin) / extentSize;
// outPosition = fract(outPosition * 0.5 + 0.5);
const vec3 P = fract(outPosition);
// const vec3 P = fract(outPosition + normalize( inPosition[i] - C ) * HALF_PIXEL);
#if USE_CROSS
if ( N.z > N.x && N.z > N.y ) gl_Position = vec4(P.x, P.y, 0, 1);
else if ( N.x > N.y && N.x > N.z ) gl_Position = vec4(P.y, P.z, 0, 1);
else gl_Position = vec4(P.x, P.z, 0, 1);
#else
if ( A == 0 ) gl_Position = vec4(P.zy, 1, 1 );
else if ( A == 1 ) gl_Position = vec4(P.xz, 1, 1 );
else if ( A == 2 ) gl_Position = vec4(P.xy, 1, 1 );
#endif
outPosition = outPosition * 0.5 + 0.5;
// gl_Position.xy = fract( gl_Position.xy * 0.5 + 0.5 ) * 2.0 - 1.0;
// gl_Position.xy = fract( gl_Position.xy * 0.5 + 0.5 ) * 2.0 - 1.0;
gl_Position.z = 1;
EmitVertex();
}
EndPrimitive();

View File

@ -1,7 +1,7 @@
#version 450
#define UF_DEFERRED_SAMPLING 0
#define UF_CAN_DISCARD 1
#define DEFERRED_SAMPLING 0
#define CAN_DISCARD 1
layout (binding = 1) uniform sampler2D samplerTexture;
@ -18,12 +18,18 @@ layout (location = 1) in flat Gui inGui;
layout (location = 0) out uvec2 outId;
layout (location = 1) out vec2 outNormals;
#if UF_DEFERRED_SAMPLING
#if DEFERRED_SAMPLING
layout (location = 2) out vec2 outUvs;
#else
layout (location = 2) out vec4 outAlbedo;
#endif
float wrap( float i ) {
return fract(i);
}
vec2 wrap( vec2 uv ) {
return vec2( wrap( uv.x ), wrap( uv.y ) );
}
vec2 encodeNormals( vec3 n ) {
float p = sqrt(n.z*8+8);
return n.xy/p + 0.5;
@ -44,14 +50,14 @@ void main() {
vec2 uv = inUv.xy;
vec4 C = vec4(1, 1, 1, 1);
//vec3 N = inNormal;
#if UF_DEFERRED_SAMPLING
#if DEFERRED_SAMPLING
outUvs = wrap(inUv.xy);
vec4 outAlbedo = vec4(0,0,0,0);
#endif
#if !UF_DEFERRED_SAMPLING || UF_CAN_DISCARD
#if !DEFERRED_SAMPLING || CAN_DISCARD
C = textureLod( samplerTexture, uv, mip );
#endif
#if !UF_DEFERRED_SAMPLING
#if !DEFERRED_SAMPLING
if ( inGui.mode == 1 ) {
C = inGui.color;
} else {

View File

@ -1,7 +1,7 @@
#version 450
#define UF_DEFERRED_SAMPLING 0
#define UF_CAN_DISCARD 1
#define DEFERRED_SAMPLING 0
#define CAN_DISCARD 1
layout (binding = 1) uniform sampler2D samplerTexture;
@ -24,7 +24,7 @@ layout (location = 1) in flat Gui inGui;
layout (location = 0) out uvec2 outId;
layout (location = 1) out vec2 outNormals;
#if UF_DEFERRED_SAMPLING
#if DEFERRED_SAMPLING
layout (location = 2) out vec2 outUvs;
#else
layout (location = 2) out vec4 outAlbedo;
@ -36,7 +36,7 @@ void main() {
if ( inUv.x > inGui.offset.z ) discard;
if ( inUv.y > inGui.offset.w ) discard;
#if UF_DEFERRED_SAMPLING
#if DEFERRED_SAMPLING
vec4 outAlbedo = vec4(0,0,0,0);
#endif

View File

@ -10,10 +10,10 @@ namespace pod {
uf::renderer::Texture3D noise;
uf::renderer::TextureCube skybox;
struct {
uf::renderer::Texture3D id;
uf::renderer::Texture3D normal;
uf::renderer::Texture3D albedo;
uf::renderer::Texture3D uv;
std::vector<uf::renderer::Texture3D> id;
std::vector<uf::renderer::Texture3D> uv;
std::vector<uf::renderer::Texture3D> normal;
std::vector<uf::renderer::Texture3D> radiance;
pod::Matrix4f matrix;
} voxels;
};

View File

@ -39,11 +39,7 @@ namespace uf {
static bool USE_REVERSE_INFINITE_PROJECTION;
Camera();
/*
Camera( const pod::Math::num_t& fov, const pod::Vector2& size, const pod::Vector2& bounds, const pod::Vector3& offset = {0, 0, 0}, const pod::Vector2& tops = {0, 0} );
Camera( Camera&& move );
Camera( const Camera& copy );
*/
bool modified() const;
void setStereoscopic( bool );
pod::Transform<>& getTransform();
@ -55,8 +51,7 @@ namespace uf {
pod::Matrix4& getProjection( size_t = 0 );
const pod::Matrix4& getProjection( size_t = 0 ) const;
// pod::Matrix4& getModel();
// const pod::Matrix4& getModel() const;
pod::Vector3f getEye( size_t = 0 ) const;
pod::Math::num_t& getFov();
pod::Math::num_t getFov() const;

View File

@ -0,0 +1 @@
#pragma once

View File

@ -38,6 +38,7 @@ void uf::GltfBehavior::initialize( uf::Object& self ) {
assetLoader.remove<pod::Graph>(filename);
bool shouldUpdate = false;
auto& sceneMetadataJson = scene.getComponent<uf::Serializer>();
if ( !ext::json::isNull(graph.metadata["ambient"]) ) {
sceneMetadataJson["light"]["ambient"] = graph.metadata["ambient"];
@ -48,6 +49,7 @@ void uf::GltfBehavior::initialize( uf::Object& self ) {
shouldUpdate = true;
}
if ( shouldUpdate ) scene.callHook("object:UpdateMetadata.%UID%");
// deferred shader loading
auto& transform = this->getComponent<pod::Transform<>>();
graph.root.entity->getComponent<pod::Transform<>>().reference = &transform;
@ -75,23 +77,25 @@ void uf::GltfBehavior::destroy( uf::Object& self ) {
uf::graph::destroy( graph );
}
}
#define UNIFORMS_UPDATE_IN_TICK 1
void uf::GltfBehavior::tick( uf::Object& self ) {
/* Animation change test */
/* Update animations */ if ( this->hasComponent<pod::Graph>() ) {
auto& graph = this->getComponent<pod::Graph>();
if ( graph.metadata["flags"]["SKINNED"].as<bool>() ) uf::graph::update( graph );
}
/* Update uniforms */
if ( !this->hasComponent<uf::Graphic>() ) return;
auto& scene = uf::scene::getCurrentScene();
auto& metadata = this->getComponent<uf::Serializer>();
auto& graphic = this->getComponent<uf::Graphic>();
auto& controller = scene.getController();
auto& controllerTransform = controller.getComponent<pod::Transform<>>();
auto& camera = controller.getComponent<uf::Camera>();
auto& transform = this->getComponent<pod::Transform<>>();
if ( !graphic.initialized ) return;
auto* objectWithGraph = this;
while ( objectWithGraph != &scene ) {
if ( objectWithGraph->hasComponent<pod::Graph>() ) break;
@ -100,6 +104,7 @@ void uf::GltfBehavior::tick( uf::Object& self ) {
if ( !objectWithGraph->hasComponent<pod::Graph>() ) return;
auto& graph = objectWithGraph->getComponent<pod::Graph>();
#if UNIFORMS_UPDATE_IN_TICK
#if UF_USE_OPENGL
if ( graphic.material.hasShader("vertex") ) {
auto& shader = graphic.material.getShader("vertex");
@ -119,7 +124,7 @@ void uf::GltfBehavior::tick( uf::Object& self ) {
}
}
#elif UF_USE_VULKAN
if ( graphic.material.hasShader("fragment") && !(graph.metadata["flags"]["SEPARATE"].as<bool>()) ) {
if ( graphic.material.hasShader("vertex") && !(graph.metadata["flags"]["SEPARATE"].as<bool>()) ) {
auto& shader = graphic.material.getShader("vertex");
std::vector<pod::Matrix4f> instances( graph.nodes.size() );
for ( size_t i = 0; i < graph.nodes.size(); ++i ) {
@ -129,31 +134,7 @@ void uf::GltfBehavior::tick( uf::Object& self ) {
auto& storageBuffer = *graphic.getStorageBuffer("Models");
graphic.updateBuffer( (void*) instances.data(), instances.size() * sizeof(pod::Matrix4f), graph.instanceBufferIndex /*storageBuffer*/ );
}
if ( graphic.material.hasShader("geometry", "vxgi") ) {
auto& shader = graphic.material.getShader("geometry", "vxgi");
/*
pod::Vector3f min = uf::vector::decode( graph.metadata["extents"]["min"], pod::Vector3f{} );
pod::Vector3f max = uf::vector::decode( graph.metadata["extents"]["max"], pod::Vector3f{} );
min.x += floor(controllerTransform.position.x);
min.y -= floor(controllerTransform.position.y);
min.z -= floor(controllerTransform.position.z);
max.x += floor(controllerTransform.position.x);
max.y -= floor(controllerTransform.position.y);
max.z -= floor(controllerTransform.position.z);
// uniforms.matrix = uf::matrix::translate( uf::matrix::identity(), -controllerTransform.position )
uniforms.matrix = uf::matrix::ortho<float>( min.x, max.x, min.y, max.y, min.z, max.z );
*/
auto& sceneTextures = scene.getComponent<pod::SceneTextures>();
struct UniformDescriptor {
alignas(16) pod::Matrix4f matrix;
};
auto& uniform = shader.getUniform("UBO");
auto& uniforms = uniform.get<UniformDescriptor>();
uniforms.matrix = sceneTextures.voxels.matrix;
shader.updateUniform( "UBO", uniform );
}
#endif
#endif
}
@ -202,24 +183,15 @@ void uf::GltfBehavior::render( uf::Object& self ) {
if ( graphic.material.hasShader("vertex") ) {
auto& shader = graphic.material.getShader("vertex");
auto& uniform = shader.getUniform("UBO");
#if UF_UNIFORMS_UPDATE_WITH_JSON
if ( !(graph.metadata["flags"]["SEPARATE"].as<bool>()) ) {
#if UF_UNIFORMS_UPDATE_WITH_JSON
ext::json::Value uniforms;
for ( std::size_t i = 0; i < uf::renderer::settings::maxViews; ++i ) {
uniforms["view"][i] = uf::matrix::encode( camera.getView( i ) );
uniforms["projection"][i] = uf::matrix::encode( camera.getProjection( i ) );
}
shader.updateUniform("UBO", uniforms );
#else
auto& uniforms = uniform.get<UniformDescriptor<>>();
for ( std::size_t i = 0; i < uf::renderer::settings::maxViews; ++i ) {
uniforms.view[i] = camera.getView( i );
uniforms.projection[i] = camera.getProjection( i );
}
shader.updateUniform( "UBO", uniform );
#endif
} else {
#if UF_UNIFORMS_UPDATE_WITH_JSON
// auto uniforms = shader.getUniformJson("UBO");
ext::json::Value uniforms;
uniforms["matrices"]["model"] = uf::matrix::encode( uf::transform::model( transform ) );
@ -239,24 +211,61 @@ void uf::GltfBehavior::render( uf::Object& self ) {
uniforms["color"][3] = 1.0f;
}
shader.updateUniform("UBO", uniforms );
#else
}
#else
if ( !(graph.metadata["flags"]["SEPARATE"].as<bool>()) ) {
auto& uniforms = uniform.get<UniformDescriptor<>>();
for ( std::size_t i = 0; i < uf::renderer::settings::maxViews; ++i ) {
uniforms.view[i] = camera.getView( i );
uniforms.projection[i] = camera.getProjection( i );
}
shader.updateUniform( "UBO", uniform );
} else {
auto& uniforms = uniform.get<uf::MeshDescriptor<>>();
uniforms.matrices.model = uf::transform::model( transform );
for ( std::size_t i = 0; i < uf::renderer::settings::maxViews; ++i ) {
uniforms.matrices.view[i] = camera.getView( i );
uniforms.matrices.projection[i] = camera.getProjection( i );
}
if ( ext::json::isArray(metadata["color"]) ) {
uniforms.color[0] = metadata["color"][0].as<float>();
uniforms.color[1] = metadata["color"][1].as<float>();
uniforms.color[2] = metadata["color"][2].as<float>();
uniforms.color[3] = metadata["color"][3].as<float>();
} else {
uniforms.color = { 1, 1, 1, 1 };
}
uniforms.color = uf::vector::decode( metadata["color"], pod::Vector4f{1,1,1,1} );
shader.updateUniform( "UBO", uniform );
#endif
}
#endif
}
#endif
#if !UNIFORMS_UPDATE_IN_TICK
if ( uf::renderer::currentRenderMode == uf::renderer::renderModes.front() ) {
#if UF_USE_OPENGL
if ( graphic.material.hasShader("vertex") ) {
auto& shader = graphic.material.getShader("vertex");
auto& mesh = this->getComponent<ext::gltf::mesh_t>();
if ( !(graph.metadata["flags"]["SEPARATE"].as<bool>()) ) {
std::vector<pod::Matrix4f> instances( graph.nodes.size() );
for ( size_t i = 0; i < graph.nodes.size(); ++i ) {
auto& node = graph.nodes[i];
instances[i] = node.entity ? uf::transform::model( node.entity->getComponent<pod::Transform<>>() ) : uf::transform::model( node.transform );
}
graphic.updateBuffer( (void*) instances.data(), instances.size() * sizeof(pod::Matrix4f), graph.instanceBufferIndex );
shader.execute( graphic, &mesh.vertices[0] );
} else if ( graph.metadata["flags"]["SKINNED"].as<bool>() ) {
shader.execute( graphic, &mesh.vertices[0] );
}
}
#elif UF_USE_VULKAN
if ( graphic.material.hasShader("vertex") && !(graph.metadata["flags"]["SEPARATE"].as<bool>()) ) {
auto& shader = graphic.material.getShader("vertex");
std::vector<pod::Matrix4f> instances( graph.nodes.size() );
for ( size_t i = 0; i < graph.nodes.size(); ++i ) {
auto& node = graph.nodes[i];
instances[i] = node.entity ? uf::transform::model( node.entity->getComponent<pod::Transform<>>() ) : uf::transform::model( node.transform );
}
auto& storageBuffer = *graphic.getStorageBuffer("Models");
graphic.updateBuffer( (void*) instances.data(), instances.size() * sizeof(pod::Matrix4f), graph.instanceBufferIndex /*storageBuffer*/ );
}
#endif
}
#endif
}

View File

@ -16,8 +16,10 @@ namespace {
auto& graphic = entity.getComponent<uf::Graphic>();
std::string root = uf::io::directory( graph.name );
size_t texture2Ds = 0;
size_t texture3Ds = 0;
for ( auto& texture : graphic.material.textures ) {
if ( texture.width > 1 && texture.height > 1 && texture.depth == 1 && texture.layers == 1 ) ++texture2Ds;
else if ( texture.width > 1 && texture.height > 1 && texture.depth > 1 && texture.layers == 1 ) ++texture3Ds;
}
// standard pipeline
@ -62,9 +64,14 @@ namespace {
ext::json::forEach( shader.metadata["specializationConstants"], [&]( ext::json::Value& sc ){
if ( sc["name"].as<std::string>() == "TEXTURES" ) sc["value"] = specializationConstants.textures;
});
for ( auto& binding : shader.descriptorSetLayoutBindings ) {
if ( binding.descriptorCount > 1 ) binding.descriptorCount = specializationConstants.textures;
}
ext::json::forEach( shader.metadata["definitions"]["textures"], [&]( ext::json::Value& t ){
if ( t["name"].as<std::string>() != "samplerTextures" ) return;
size_t binding = t["binding"].as<size_t>();
for ( auto& layout : shader.descriptorSetLayoutBindings ) {
if ( layout.binding == binding ) layout.descriptorCount = specializationConstants.textures;
}
});
}
#endif
}
@ -73,15 +80,7 @@ namespace {
std::string vertexShaderFilename = graph.metadata["shaders"]["vertex"].as<std::string>("/gltf/base.vert.spv");
std::string geometryShaderFilename = graph.metadata["shaders"]["geometry"].as<std::string>("/gltf/voxelize.geom.spv");
std::string fragmentShaderFilename = graph.metadata["shaders"]["fragment"].as<std::string>("/gltf/voxelize.frag.spv");
/*
{
if ( !graph.metadata["flags"]["SEPARATE"].as<bool>() ) {
vertexShaderFilename = graph.metadata["flags"]["SKINNED"].as<bool>() ? "/gltf/skinned.instanced.vert.spv" : "/gltf/instanced.vert.spv";
} else if ( graph.metadata["flags"]["SKINNED"].as<bool>() ) vertexShaderFilename = "/gltf/skinned.vert.spv";
vertexShaderFilename = entity.grabURI( vertexShaderFilename, root );
graphic.material.attachShader(vertexShaderFilename, uf::renderer::enums::Shader::VERTEX, "vxgi");
}
*/
if ( geometryShaderFilename != "" && uf::renderer::device.enabledFeatures.geometryShader ) {
geometryShaderFilename = entity.grabURI( geometryShaderFilename, root );
graphic.material.attachShader(geometryShaderFilename, uf::renderer::enums::Shader::GEOMETRY, "vxgi");
@ -91,48 +90,32 @@ namespace {
graphic.material.attachShader(fragmentShaderFilename, uf::renderer::enums::Shader::FRAGMENT, "vxgi");
}
#if UF_USE_VULKAN
/*
{
auto& shader = graphic.material.getShader("vertex", "vxgi");
struct SpecializationConstant {
uint32_t passes = 6;
};
auto& specializationConstants = shader.specializationConstants.get<SpecializationConstant>();
specializationConstants.passes = uf::renderer::settings::maxViews;
ext::json::forEach( shader.metadata["specializationConstants"], [&]( ext::json::Value& sc ){
if ( sc["name"].as<std::string>() == "PASSES" ) sc["value"] = specializationConstants.passes;
});
}
*/
/*
if ( geometryShaderFilename != "" && uf::renderer::device.enabledFeatures.geometryShader ) {
auto& shader = graphic.material.getShader("geometry", "vxgi");
pod::Vector3f min = uf::vector::decode( graph.metadata["extents"]["min"], pod::Vector3f{} );
pod::Vector3f max = uf::vector::decode( graph.metadata["extents"]["max"], pod::Vector3f{} );
struct UniformDescriptor {
alignas(16) pod::Matrix4f matrix;
};
auto& uniform = shader.getUniform("UBO");
auto& uniforms = uniform.get<UniformDescriptor>();
uniforms.matrix = uf::matrix::ortho<float>( min.x, max.x, min.y, max.y, max.z, min.z );
shader.updateUniform( "UBO", uniform );
}
*/
{
auto& shader = graphic.material.getShader("fragment", "vxgi");
struct SpecializationConstant {
uint32_t textures = 1;
uint32_t textures = 256;
uint32_t cascades = 2;
};
auto& specializationConstants = shader.specializationConstants.get<SpecializationConstant>();
specializationConstants.textures = texture2Ds;
specializationConstants.cascades = texture3Ds / 4;
ext::json::forEach( shader.metadata["specializationConstants"], [&]( ext::json::Value& sc ){
if ( sc["name"].as<std::string>() == "TEXTURES" ) sc["value"] = specializationConstants.textures;
std::string name = sc["name"].as<std::string>();
if ( name == "TEXTURES" ) sc["value"] = specializationConstants.textures;
else if ( name == "CASCADES" ) sc["value"] = specializationConstants.cascades;
});
ext::json::forEach( shader.metadata["definitions"]["textures"], [&]( ext::json::Value& t ){
size_t binding = t["binding"].as<size_t>();
std::string name = t["name"].as<std::string>();
for ( auto& layout : shader.descriptorSetLayoutBindings ) {
if ( layout.binding != binding ) continue;
if ( name == "samplerTextures" ) layout.descriptorCount = specializationConstants.textures;
else if ( name == "voxelId" ) layout.descriptorCount = specializationConstants.cascades;
else if ( name == "voxelUv" ) layout.descriptorCount = specializationConstants.cascades;
else if ( name == "voxelNormal" ) layout.descriptorCount = specializationConstants.cascades;
else if ( name == "voxelRadiance" ) layout.descriptorCount = specializationConstants.cascades;
}
});
for ( auto& binding : shader.descriptorSetLayoutBindings ) {
if ( binding.descriptorCount > 1 ) binding.descriptorCount = specializationConstants.textures;
}
}
#endif
}
@ -167,10 +150,10 @@ namespace {
if ( uf::renderer::settings::experimental::deferredMode == "vxgi" ) {
auto& scene = uf::scene::getCurrentScene();
auto& sceneTextures = scene.getComponent<pod::SceneTextures>();
graphic.material.textures.emplace_back().aliasTexture(sceneTextures.voxels.id);
graphic.material.textures.emplace_back().aliasTexture(sceneTextures.voxels.normal);
graphic.material.textures.emplace_back().aliasTexture(sceneTextures.voxels.uv);
graphic.material.textures.emplace_back().aliasTexture(sceneTextures.voxels.albedo);
for ( auto& t : sceneTextures.voxels.id ) graphic.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.uv ) graphic.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.normal ) graphic.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.radiance ) graphic.material.textures.emplace_back().aliasTexture(t);
}
}
if ( graph.metadata["flags"]["LOAD"].as<bool>() ) {
@ -340,12 +323,14 @@ void uf::graph::process( pod::Graph& graph ) {
break;
}
}
// Failsafe
if ( graph.materials.empty() ) graph.materials.emplace_back();
if ( graph.textures.empty() ) graph.textures.emplace_back();
// Materials storage buffer
std::vector<pod::Material::Storage> materials( graph.materials.size() );
for ( size_t i = 0; i < graph.materials.size(); ++i ) {
materials[i] = graph.materials[i].storage;
if ( graph.metadata["alpha cutoff"].is<float>() )
materials[i].factorAlphaCutoff = graph.metadata["alpha cutoff"].as<float>();
}
graph.root.materialBufferIndex = graphic.initializeBuffer(
(void*) materials.data(),
@ -1434,7 +1419,7 @@ void uf::graph::save( const pod::Graph& graph, const std::string& filename ) {
if ( saveSeparately ) {
for ( size_t i = 0; i < graph.images.size(); ++i ) {
std::string f = "image."+std::to_string(i)+(compression?".jpg":".png");
graph.images[i].save(directory + "/" + f, true);
graph.images[i].save(directory + "/" + f);
serializer["images"].emplace_back(f);
}
} else {
@ -1523,7 +1508,7 @@ void uf::graph::save( const pod::Graph& graph, const std::string& filename ) {
if ( saveSeparately ) {
for ( size_t i = 0; i < graph.images.size(); ++i ) {
std::string f = "image."+std::to_string(i)+(compression?".jpg":".png");
graph.images[i].save(directory + "/" + f, true);
graph.images[i].save(directory + "/" + f);
serializer["images"].emplace_back(f);
}
} else {

View File

@ -62,7 +62,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
/*.blend = */false,
/*.samples = */msaa,
});
if ( ext::vulkan::settings::experimental::deferredMode == "deferredSampling" ) {
if ( ext::vulkan::settings::experimental::deferredMode != "" ) {
attachments.uvs = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */VK_FORMAT_R16G16_UNORM,
/*.layout = */VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
@ -131,7 +131,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
/*.samples = */1,
});
if ( ext::vulkan::settings::experimental::deferredMode == "deferredSampling" ) {
if ( ext::vulkan::settings::experimental::deferredMode != "" ) {
// First pass: fill the G-Buffer
{
renderTarget.addPass(
@ -213,23 +213,56 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
auto& scene = uf::scene::getCurrentScene();
auto& shader = blitter.material.shaders.back();
struct SpecializationConstant {
uint32_t maxTextures = 512;
};
auto& specializationConstants = shader.specializationConstants.get<SpecializationConstant>();
size_t maxLights = metadata["system"]["config"]["engine"]["scenes"]["lights"]["max"].as<size_t>(256);
size_t maxTextures = metadata["system"]["config"]["engine"]["scenes"]["textures"]["max"].as<size_t>(256);
auto& metadata = scene.getComponent<uf::Serializer>();
size_t maxLights = metadata["system"]["config"]["engine"]["scenes"]["lights"]["max"].as<size_t>();
specializationConstants.maxTextures = metadata["system"]["config"]["engine"]["scenes"]["textures"]["max"].as<size_t>();
for ( auto& binding : shader.descriptorSetLayoutBindings ) {
if ( binding.descriptorCount > 1 )
binding.descriptorCount = specializationConstants.maxTextures;
UF_DEBUG_MSG( maxLights << "\t" << maxTextures );
if ( ext::vulkan::settings::experimental::deferredMode == "vxgi" ) {
struct SpecializationConstant {
uint32_t maxTextures = 256;
uint32_t maxCascades = 2;
};
auto& specializationConstants = shader.specializationConstants.get<SpecializationConstant>();
auto& metadata = scene.getComponent<uf::Serializer>();
specializationConstants.maxTextures = maxTextures;
specializationConstants.maxCascades = metadata["system"]["config"]["engine"]["scenes"]["vxgi"]["cascades"].as<size_t>(2);
ext::json::forEach( shader.metadata["definitions"]["textures"], [&]( ext::json::Value& t ){
size_t binding = t["binding"].as<size_t>();
std::string name = t["name"].as<std::string>();
for ( auto& layout : shader.descriptorSetLayoutBindings ) {
if ( layout.binding != binding ) continue;
if ( name == "samplerTextures" ) layout.descriptorCount = specializationConstants.maxTextures;
else if ( name == "voxelId" ) layout.descriptorCount = specializationConstants.maxCascades;
else if ( name == "voxelUv" ) layout.descriptorCount = specializationConstants.maxCascades;
else if ( name == "voxelNormal" ) layout.descriptorCount = specializationConstants.maxCascades;
else if ( name == "voxelRadiance" ) layout.descriptorCount = specializationConstants.maxCascades;
}
});
} else {
struct SpecializationConstant {
uint32_t maxTextures = 256;
};
auto& specializationConstants = shader.specializationConstants.get<SpecializationConstant>();
auto& metadata = scene.getComponent<uf::Serializer>();
specializationConstants.maxTextures = maxTextures;
ext::json::forEach( shader.metadata["definitions"]["textures"], [&]( ext::json::Value& t ){
if ( t["name"].as<std::string>() != "samplerTextures" ) return;
size_t binding = t["binding"].as<size_t>();
for ( auto& layout : shader.descriptorSetLayoutBindings ) {
if ( layout.binding == binding ) layout.descriptorCount = specializationConstants.maxTextures;
}
});
}
std::vector<pod::Light::Storage> lights(maxLights);
std::vector<pod::Material::Storage> materials(specializationConstants.maxTextures);
std::vector<pod::Texture::Storage> textures(specializationConstants.maxTextures);
std::vector<pod::DrawCall::Storage> drawCalls(specializationConstants.maxTextures);
std::vector<pod::Material::Storage> materials(maxTextures);
std::vector<pod::Texture::Storage> textures(maxTextures);
std::vector<pod::DrawCall::Storage> drawCalls(maxTextures);
for ( auto& material : materials ) material.colorBase = {0,0,0,0};

View File

@ -40,9 +40,10 @@ ext::vulkan::GraphicDescriptor ext::vulkan::RenderTargetRenderMode::bindGraphicD
if ( pass == 0 && type == "vxgi" ) {
descriptor.cullMode = VK_CULL_MODE_NONE;
descriptor.depth.test = false;
descriptor.depth.write = false;
descriptor.pipeline = "vxgi";
} else if ( type == "depth" ) {
descriptor.cullMode = VK_CULL_MODE_NONE;
// descriptor.cullMode = VK_CULL_MODE_NONE;
}
// invalidate
if ( target != "" && descriptor.renderMode != this->getName() && descriptor.renderMode != target ) {
@ -185,7 +186,7 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
/*.blend = */false,
/*.samples = */msaa,
});
if ( ext::vulkan::settings::experimental::deferredMode == "deferredSampling" ) {
if ( false && ext::vulkan::settings::experimental::deferredMode != "" ) {
attachments.uvs = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */VK_FORMAT_R16G16_UNORM,
/*.layout = */VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
@ -216,7 +217,7 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
/*.blend =*/ true,
/*.samples =*/ 1,
});
if ( ext::vulkan::settings::experimental::deferredMode == "deferredSampling" ) {
if ( false && ext::vulkan::settings::experimental::deferredMode != "" ) {
// First pass: fill the G-Buffer
{
renderTarget.addPass(
@ -347,16 +348,28 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
auto& shader = blitter.material.getShader("compute");
struct SpecializationConstant {
uint32_t maxTextures = 512;
uint32_t maxCascades = 1;
};
auto& specializationConstants = shader.specializationConstants.get<SpecializationConstant>();
auto& metadata = scene.getComponent<uf::Serializer>();
size_t maxLights = metadata["system"]["config"]["engine"]["scenes"]["lights"]["max"].as<size_t>();
specializationConstants.maxTextures = metadata["system"]["config"]["engine"]["scenes"]["textures"]["max"].as<size_t>();
for ( auto& binding : shader.descriptorSetLayoutBindings ) {
if ( binding.descriptorCount > 1 )
binding.descriptorCount = specializationConstants.maxTextures;
}
size_t maxLights = metadata["system"]["config"]["engine"]["scenes"]["lights"]["max"].as<size_t>(256);
specializationConstants.maxTextures = metadata["system"]["config"]["engine"]["scenes"]["textures"]["max"].as<size_t>(256);
specializationConstants.maxCascades = metadata["system"]["config"]["engine"]["scenes"]["vxgi"]["cascades"].as<size_t>(2);
ext::json::forEach( shader.metadata["definitions"]["textures"], [&]( ext::json::Value& t ){
size_t binding = t["binding"].as<size_t>();
std::string name = t["name"].as<std::string>();
for ( auto& layout : shader.descriptorSetLayoutBindings ) {
if ( layout.binding != binding ) continue;
if ( name == "samplerTextures" ) layout.descriptorCount = specializationConstants.maxTextures;
else if ( name == "voxelId" ) layout.descriptorCount = specializationConstants.maxCascades;
else if ( name == "voxelUv" ) layout.descriptorCount = specializationConstants.maxCascades;
else if ( name == "voxelNormal" ) layout.descriptorCount = specializationConstants.maxCascades;
else if ( name == "voxelRadiance" ) layout.descriptorCount = specializationConstants.maxCascades;
}
});
std::vector<pod::Light::Storage> lights(maxLights);
std::vector<pod::Material::Storage> materials(specializationConstants.maxTextures);

View File

@ -530,12 +530,14 @@ void ext::vulkan::Texture::aliasTexture( const Texture& texture ) {
view = texture.view;
imageLayout = texture.imageLayout;
deviceMemory = texture.deviceMemory;
sampler = texture.sampler;
width = texture.width;
height = texture.height;
depth = texture.depth;
layers = texture.layers;
sampler = texture.sampler;
sampler.device = NULL;
this->updateDescriptors();
}
void ext::vulkan::Texture::aliasAttachment( const RenderTarget::Attachment& attachment, bool createSampler ) {

View File

@ -16,9 +16,6 @@ uf::Camera::Camera() : m_modified(false) {
this->m_settings.offset = {0, 0, 0};
this->m_settings.mode = 1;
// this->setModel(uf::matrix::identity());
// this->setView(uf::matrix::identity());
// this->setProjection(uf::matrix::identity());
this->m_matrices.views.resize(6, uf::matrix::identity());
this->m_matrices.projections.resize(6, uf::matrix::identity());
@ -39,89 +36,30 @@ const pod::Transform<>& uf::Camera::getTransform() const {
pod::Matrix4& uf::Camera::getView( size_t eye ) {
if ( eye >= this->m_matrices.views.size() ) eye = 0;
return this->m_matrices.views[eye];
// if ( eye >= this->m_matrices.views.size() ) return uf::matrix::identity();
// if ( eye >= this->m_matrices.views.size() ) this->m_matrices.views.resize( uf::matrix::identity() );
/*
switch ( eye ) {
case 0:
return this->m_matrices.left.view;
break;
case 1:
return this->m_matrices.right.view;
break;
default:
return this->m_matrices.left.view;
break;
}
*/
}
pod::Matrix4& uf::Camera::getProjection( size_t eye ) {
if ( eye >= this->m_matrices.projections.size() ) eye = 0;
return this->m_matrices.projections[eye];
// if ( eye >= this->m_matrices.projections.size() ) return uf::matrix::identity();
// if ( eye >= this->m_matrices.projections.size() ) this->m_matrices.projections.resize( eye, uf::matrix::identity() );
/*
switch ( eye ) {
case 0:
return this->m_matrices.left.projection;
break;
case 1:
return this->m_matrices.right.projection;
break;
default:
return this->m_matrices.left.projection;
break;
}
*/
}
/*
pod::Matrix4& uf::Camera::getModel() {
return this->m_matrices.model;
}
*/
const pod::Matrix4& uf::Camera::getView( size_t eye ) const {
if ( eye >= this->m_matrices.views.size() ) eye = 0;
return this->m_matrices.views[eye];
// if ( eye >= this->m_matrices.views.size() ) return uf::matrix::identity();
// if ( eye >= this->m_matrices.views.size() ) this->m_matrices.views.resize( eye, uf::matrix::identity() );
/*
switch ( eye ) {
case 0:
return this->m_matrices.left.view;
break;
case 1:
return this->m_matrices.right.view;
break;
default:
return this->m_matrices.left.view;
break;
}
*/
}
const pod::Matrix4& uf::Camera::getProjection( size_t eye ) const {
if ( eye >= this->m_matrices.projections.size() ) eye = 0;
return this->m_matrices.projections[eye];
// if ( eye >= this->m_matrices.projections.size() ) return uf::matrix::identity();
// if ( eye >= this->m_matrices.projections.size() ) this->m_matrices.projections.resize( eye, uf::matrix::identity() );
/*
switch ( eye ) {
case 0:
return this->m_matrices.left.projection;
break;
case 1:
return this->m_matrices.right.projection;
break;
default:
return this->m_matrices.left.projection;
break;
}
pod::Vector3f uf::Camera::getEye( size_t eye ) const {
pod::Vector3f position = uf::transform::flatten( this->m_transform ).position;
#if UF_USE_OPENVR
if ( this->m_settings.stereoscopic && ext::openvr::context ) {
position += ext::openvr::hmdPosition( eye == 0 ? vr::Eye_Left : vr::Eye_Right );
}
*/
#endif
return position;
}
/*
const pod::Matrix4& uf::Camera::getModel() const {
return this->m_matrices.model;
}
*/
pod::Math::num_t& uf::Camera::getFov() {
return this->m_settings.perspective.fov;
}
@ -162,20 +100,6 @@ void uf::Camera::setView( const pod::Matrix4& mat, size_t i ) {
}
if ( i >= this->m_matrices.views.size() ) this->m_matrices.views.resize( i, uf::matrix::identity() );
this->m_matrices.views[i] = mat;
/*
switch ( i ) {
case 0:
this->m_matrices.left.view = mat;
break;
case 1:
this->m_matrices.right.view = mat;
break;
default:
this->setView( mat, 0 );
this->setView( mat, 1 );
break;
}
*/
}
void uf::Camera::setProjection( const pod::Matrix4& mat, size_t i ) {
if ( i >= uf::renderer::settings::maxViews ) {
@ -185,26 +109,7 @@ void uf::Camera::setProjection( const pod::Matrix4& mat, size_t i ) {
}
if ( i >= this->m_matrices.projections.size() ) this->m_matrices.projections.resize( i, uf::matrix::identity() );
this->m_matrices.projections[i] = mat;
/*
switch ( i ) {
case 0:
this->m_matrices.left.projection = mat;
break;
case 1:
this->m_matrices.right.projection = mat;
break;
default:
this->setProjection( mat, 0 );
this->setProjection( mat, 1 );
break;
}
*/
}
/*
void uf::Camera::setModel( const pod::Matrix4& mat ) {
this->m_matrices.model = mat;
}
*/
void uf::Camera::setFov( pod::Math::num_t fov ) {
this->m_settings.mode = 1;
this->m_settings.perspective.fov = fov;

View File

@ -0,0 +1,2 @@
#include <uf/utils/octree/octree.h>

View File

@ -71,8 +71,9 @@ void ext::PlayerModelBehavior::render( uf::Object& self ){
auto& transform = this->getComponent<pod::Transform<>>();
// auto& renderMode = *uf::renderer::currentRenderMode;
// if ( renderMode.getType() == "Deferred" ) {
if ( player.getUid() == controller.getUid() && uf::renderer::currentRenderMode->getName() != "RenderTarget" ) {
// UF_DEBUG_MSG( uf::renderer::currentRenderMode->getName() << ": " << uf::renderer::currentRenderMode->getType() );
if ( uf::renderer::currentRenderMode->getName() == "Gui" ) {
// if ( player.getUid() == controller.getUid() && uf::renderer::currentRenderMode->getName() != "RenderTarget" ) {
transform.scale = { 0, 0, 0 };
} else {
transform.scale = metadata.scale;

View File

@ -210,10 +210,12 @@ void ext::ExtSceneBehavior::initialize( uf::Object& self ) {
auto& metadata = this->getComponent<ext::ExtSceneBehavior::Metadata>();
metadata.serialize = [&]() {
metadataJson["light"]["should"] = metadata.light.enabled;
metadataJson["light"]["ambient"] = uf::vector::encode( metadata.light.ambient );
metadataJson["light"]["specular"] = uf::vector::encode( metadata.light.specular );
metadataJson["light"]["exposure"] = metadata.light.exposure;
metadataJson["light"]["gamma"] = metadata.light.gamma;
metadataJson["light"]["fog"]["color"] = uf::vector::encode( metadata.fog.color );
metadataJson["light"]["fog"]["step scale"] = metadata.fog.stepScale;
metadataJson["light"]["fog"]["absorbtion"] = metadata.fog.absorbtion;
@ -227,14 +229,17 @@ void ext::ExtSceneBehavior::initialize( uf::Object& self ) {
metadata.deserialize = [&](){
metadata.max.textures = ext::config["engine"]["scenes"]["textures"]["max"].as<size_t>();
metadata.max.lights = ext::config["engine"]["scenes"]["lights"]["max"].as<size_t>();
metadata.light.enabled = ext::config["engine"]["scenes"]["lights"]["enabled"].as<bool>() && metadataJson["light"]["should"].as<bool>();
metadata.light.shadowSamples = ext::config["engine"]["scenes"]["lights"]["shadow samples"].as<size_t>();
metadata.light.shadowThreshold = ext::config["engine"]["scenes"]["lights"]["shadow threshold"].as<size_t>();
metadata.light.updateThreshold = ext::config["engine"]["scenes"]["lights"]["update threshold"].as<size_t>();
metadata.light.ambient = uf::vector::decode( metadataJson["light"]["ambient"], pod::Vector4f{ 1, 1, 1, 1 } );
metadata.light.specular = uf::vector::decode( metadataJson["light"]["specular"], pod::Vector4f{ 1, 1, 1, 1 } );
metadata.light.exposure = metadataJson["light"]["exposure"].as<float>(1.0f);
metadata.light.gamma = metadataJson["light"]["gamma"].as<float>(2.2f);
metadata.fog.color = uf::vector::decode( metadataJson["light"]["fog"]["color"], pod::Vector3f{ 1, 1, 1 } );
metadata.fog.stepScale = metadataJson["light"]["fog"]["step scale"].as<float>();
metadata.fog.absorbtion = metadataJson["light"]["fog"]["absorbtion"].as<float>();
@ -244,6 +249,7 @@ void ext::ExtSceneBehavior::initialize( uf::Object& self ) {
metadata.fog.density.threshold = metadataJson["light"]["fog"]["density"]["threshold"].as<float>();
metadata.fog.density.multiplier = metadataJson["light"]["fog"]["density"]["multiplier"].as<float>();
metadata.fog.density.scale = metadataJson["light"]["fog"]["density"]["scale"].as<float>();
#if UF_USE_OPENGL_FIXED_FUNCTION
uf::renderer::states::rebuild = true;
#endif
@ -364,6 +370,7 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
#else
if ( !metadata.max.textures ) metadata.max.textures = ext::config["engine"]["scenes"]["textures"]["max"].as<size_t>();
if ( !metadata.max.lights ) metadata.max.lights = ext::config["engine"]["scenes"]["lights"]["max"].as<size_t>();
if ( !metadata.light.enabled ) metadata.light.enabled = ext::config["engine"]["scenes"]["lights"]["enabled"].as<bool>() && metadataJson["light"]["should"].as<bool>();
if ( !metadata.light.shadowSamples ) metadata.light.shadowSamples = ext::config["engine"]["scenes"]["lights"]["shadow samples"].as<size_t>();
if ( !metadata.light.shadowThreshold ) metadata.light.shadowThreshold = ext::config["engine"]["scenes"]["lights"]["shadow threshold"].as<size_t>();
@ -371,7 +378,7 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
if ( !metadata.light.exposure ) metadata.light.exposure = metadataJson["light"]["exposure"].as<float>(1.0f);
if ( !metadata.light.gamma ) metadata.light.gamma = metadataJson["light"]["gamma"].as<float>(2.2f);
#endif
/* Update lights */ if ( metadata.light.enabled ) {
/* Update lights */ if ( uf::renderer::settings::experimental::deferredMode != "vxgi" ) {
ext::ExtSceneBehavior::bindBuffers( *this );
}
@ -456,7 +463,8 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const std::string& re
alignas(16) pod::Matrix4f iView[2];
alignas(16) pod::Matrix4f iProjection[2];
alignas(16) pod::Matrix4f iProjectionView[2];
alignas(16) pod::Matrix4f ortho;
alignas(16) pod::Vector4f eyePos[2];
alignas(16) pod::Matrix4f vxgi;
} matrices;
struct Mode {
alignas(8) pod::Vector2ui type;
@ -482,12 +490,14 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const std::string& re
alignas(4) uint32_t textures = 0;
alignas(4) uint32_t drawCalls = 0;
} lengths;
alignas(16) pod::Vector4f ambient;
alignas(4) uint32_t msaa;
alignas(4) uint32_t poissonSamples;
// alignas(16) pod::Vector4f ambient;
pod::Vector3f ambient;
alignas(4) float gamma;
alignas(4) float exposure;
alignas(4) uint32_t msaa;
alignas(4) uint32_t shadowSamples;
alignas(4) uint32_t padding1;
};
struct SpecializationConstant {
uint32_t maxTextures = 512;
@ -536,7 +546,7 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const std::string& re
int shadowSamples = metadata.light.shadowSamples;
int shadowThreshold = metadata.light.shadowThreshold;
if ( shadowSamples <= 0 ) shadowSamples = 16;
if ( shadowSamples < 0 ) shadowSamples = 0;
if ( shadowThreshold <= 0 ) shadowThreshold = std::numeric_limits<int>::max();
{
std::vector<LightInfo> scratch;
@ -565,14 +575,16 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const std::string& re
uniforms->matrices.iView[i] = uf::matrix::inverse( uniforms->matrices.view[i] );
uniforms->matrices.iProjection[i] = uf::matrix::inverse( uniforms->matrices.projection[i] );
uniforms->matrices.iProjectionView[i] = uf::matrix::inverse( uniforms->matrices.projection[i] * uniforms->matrices.view[i] );
uniforms->matrices.eyePos[i] = camera.getEye( i );
}
uniforms->ambient = metadata.light.ambient;
uniforms->msaa = ext::vulkan::settings::msaa;
uniforms->poissonSamples = shadowSamples;
uniforms->shadowSamples = shadowSamples;
uniforms->exposure = metadata.light.exposure;
uniforms->gamma = metadata.light.gamma;
uniforms->fog.color = metadata.fog.color;
uniforms->fog.color.w = metadata.fog.stepScale;
@ -598,10 +610,10 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const std::string& re
graphic.material.textures.clear();
if ( uf::renderer::settings::experimental::deferredMode == "vxgi" ) {
graphic.material.textures.emplace_back().aliasTexture(sceneTextures.voxels.id); //this->getComponent<uf::renderer::Texture3D>());
graphic.material.textures.emplace_back().aliasTexture(sceneTextures.voxels.normal); //this->getComponent<uf::renderer::Texture3D>());
graphic.material.textures.emplace_back().aliasTexture(sceneTextures.voxels.uv); //this->getComponent<uf::renderer::Texture3D>());
graphic.material.textures.emplace_back().aliasTexture(sceneTextures.voxels.albedo); //this->getComponent<uf::renderer::Texture3D>());
for ( auto& t : sceneTextures.voxels.id ) graphic.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.uv ) graphic.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.normal ) graphic.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.radiance ) graphic.material.textures.emplace_back().aliasTexture(t);
}
graphic.material.textures.emplace_back().aliasTexture(sceneTextures.noise); //this->getComponent<uf::renderer::Texture3D>());
@ -645,33 +657,8 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const std::string& re
graphic.material.textures.emplace_back().aliasTexture(texture.texture);
++textureSlot;
}
#if 1
}
uniforms->matrices.ortho = sceneTextures.voxels.matrix;
#else
// calculate extents
pod::Vector3f graphMin = uf::vector::decode( graph.metadata["extents"]["min"], pod::Vector3f{} );
pod::Vector3f graphMax = uf::vector::decode( graph.metadata["extents"]["max"], pod::Vector3f{} );
min.x = std::min( min.x, graphMin.x );
min.y = std::min( min.y, graphMin.y );
min.z = std::min( min.z, graphMin.z );
max.x = std::max( max.x, graphMax.x );
max.y = std::max( max.y, graphMax.y );
max.z = std::max( max.z, graphMax.z );
}
min.x += floor(controllerTransform.position.x );
min.y -= floor(controllerTransform.position.y );
min.z -= floor(controllerTransform.position.z );
max.x += floor(controllerTransform.position.x );
max.y -= floor(controllerTransform.position.y );
max.z -= floor(controllerTransform.position.z );
uniforms->matrices.ortho = /*uf::matrix::translate( uf::matrix::identity(), controllerTransform.position ) **/ uf::matrix::ortho( min.x, max.x, min.y, max.y, min.z, max.z );
#endif
uniforms->matrices.vxgi = sceneTextures.voxels.matrix;
uniforms->lengths.materials = std::min( materials.size(), maxTextures );
uniforms->lengths.textures = std::min( textures.size(), maxTextures );
uniforms->lengths.drawCalls = std::min( drawCalls.size(), maxTextures );
@ -740,6 +727,7 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const std::string& re
graphic.updatePipelines();
}
shader.updateUniform( "UBO", uniform );
}
}

View File

@ -28,7 +28,8 @@ void ext::VoxelizerBehavior::initialize( uf::Object& self ) {
{
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_LIMITER = ext::config["engine"]["scenes"]["vxgi"]["dispatch"].as<uint32_t>(8);
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);
if ( metadata.voxelSize.x == 0 ) metadata.voxelSize.x = DEFAULT_VOXEL_SIZE;
if ( metadata.voxelSize.y == 0 ) metadata.voxelSize.y = DEFAULT_VOXEL_SIZE;
@ -36,33 +37,42 @@ void ext::VoxelizerBehavior::initialize( uf::Object& self ) {
if ( metadata.renderer.limiter == 0 ) metadata.renderer.limiter = DEFAULT_VOXELIZE_LIMITER;
if ( metadata.dispatchSize.x == 0 ) metadata.dispatchSize.x = DEFAULT_DISPATCH_LIMITER;
if ( metadata.dispatchSize.y == 0 ) metadata.dispatchSize.y = DEFAULT_DISPATCH_LIMITER;
if ( metadata.dispatchSize.z == 0 ) metadata.dispatchSize.z = DEFAULT_DISPATCH_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;
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} );
std::vector<uint8_t> empty(metadata.voxelSize.x * metadata.voxelSize.y * metadata.voxelSize.z * sizeof(uint8_t) * 4);
sceneTextures.voxels.id.sampler.descriptor.filter.min = VK_FILTER_NEAREST;
sceneTextures.voxels.id.sampler.descriptor.filter.mag = VK_FILTER_NEAREST;
for ( size_t i = 0; i < metadata.cascades; ++i ) {
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();
sceneTextures.voxels.id.fromBuffers( (void*) empty.data(), empty.size(), 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 );
sceneTextures.voxels.normal.fromBuffers( (void*) empty.data(), empty.size(), 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 );
sceneTextures.voxels.uv.fromBuffers( (void*) empty.data(), empty.size(), 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 );
sceneTextures.voxels.albedo.fromBuffers( (void*) empty.data(), empty.size(), uf::renderer::enums::Format::R8G8B8A8_UNORM, metadata.voxelSize.x, metadata.voxelSize.y, metadata.voxelSize.z, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
id.sampler.descriptor.filter.min = VK_FILTER_NEAREST;
id.sampler.descriptor.filter.mag = VK_FILTER_NEAREST;
id.fromBuffers( (void*) empty.data(), empty.size(), 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 );
uv.fromBuffers( (void*) empty.data(), empty.size(), 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 );
normal.fromBuffers( (void*) empty.data(), empty.size(), 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( (void*) empty.data(), empty.size(), uf::renderer::enums::Format::R8G8B8A8_UNORM, 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
{
// if ( metadata.fragmentSize.x == 0 ) metadata.fragmentSize.x = metadata.voxelSize.x * 2;
// if ( metadata.fragmentSize.y == 0 ) metadata.fragmentSize.y = metadata.voxelSize.y * 2;
if ( metadata.fragmentSize.x == 0 ) metadata.fragmentSize.x = metadata.voxelSize.x;
if ( metadata.fragmentSize.y == 0 ) metadata.fragmentSize.y = metadata.voxelSize.y;
auto& renderMode = this->getComponent<uf::renderer::RenderTargetRenderMode>();
metadata.renderModeName = "VXGI:" + std::to_string((int) this->getUid());
uf::renderer::addRenderMode( &renderMode, metadata.renderModeName );
renderMode.metadata["type"] = "vxgi";
renderMode.metadata["samples"] = 1;
renderMode.metadata["samples"] = 2;
renderMode.blitter.device = &ext::vulkan::device;
renderMode.width = metadata.fragmentSize.x;
@ -77,12 +87,13 @@ void ext::VoxelizerBehavior::initialize( uf::Object& self ) {
renderMode.blitter.process = false;
#endif
renderMode.blitter.material.textures.emplace_back().aliasTexture(sceneTextures.voxels.id); //this->getComponent<uf::renderer::Texture3D>());
renderMode.blitter.material.textures.emplace_back().aliasTexture(sceneTextures.voxels.normal); //this->getComponent<uf::renderer::Texture3D>());
renderMode.blitter.material.textures.emplace_back().aliasTexture(sceneTextures.voxels.uv); //this->getComponent<uf::renderer::Texture3D>());
renderMode.blitter.material.textures.emplace_back().aliasTexture(sceneTextures.voxels.albedo); //this->getComponent<uf::renderer::Texture3D>());
renderMode.blitter.material.textures.emplace_back().aliasTexture(sceneTextures.noise); //this->getComponent<uf::renderer::Texture3D>());
renderMode.blitter.material.textures.emplace_back().aliasTexture(sceneTextures.skybox); //this->getComponent<uf::renderer::TextureCube>());
for ( auto& t : sceneTextures.voxels.id ) renderMode.blitter.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.uv ) renderMode.blitter.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.normal ) renderMode.blitter.material.textures.emplace_back().aliasTexture(t);
for ( auto& t : sceneTextures.voxels.radiance ) renderMode.blitter.material.textures.emplace_back().aliasTexture(t);
renderMode.blitter.material.textures.emplace_back().aliasTexture(sceneTextures.noise);
renderMode.blitter.material.textures.emplace_back().aliasTexture(sceneTextures.skybox);
renderMode.bindCallback( renderMode.CALLBACK_BEGIN, [&]( VkCommandBuffer commandBuffer ){
// clear textures
@ -94,10 +105,10 @@ void ext::VoxelizerBehavior::initialize( uf::Object& self ) {
subresourceRange.layerCount = 1;
VkClearColorValue clearColor = { 0.0, 0.0, 0.0, 0.0 };
vkCmdClearColorImage( commandBuffer, sceneTextures.voxels.id.image, sceneTextures.voxels.id.imageLayout, &clearColor, 1, &subresourceRange );
vkCmdClearColorImage( commandBuffer, sceneTextures.voxels.normal.image, sceneTextures.voxels.normal.imageLayout, &clearColor, 1, &subresourceRange );
vkCmdClearColorImage( commandBuffer, sceneTextures.voxels.uv.image, sceneTextures.voxels.uv.imageLayout, &clearColor, 1, &subresourceRange );
vkCmdClearColorImage( commandBuffer, sceneTextures.voxels.albedo.image, sceneTextures.voxels.albedo.imageLayout, &clearColor, 1, &subresourceRange );
for ( auto& t : sceneTextures.voxels.id ) vkCmdClearColorImage( commandBuffer, t.image, t.imageLayout, &clearColor, 1, &subresourceRange );
for ( auto& t : sceneTextures.voxels.normal ) vkCmdClearColorImage( commandBuffer, t.image, t.imageLayout, &clearColor, 1, &subresourceRange );
for ( auto& t : sceneTextures.voxels.uv ) vkCmdClearColorImage( commandBuffer, t.image, t.imageLayout, &clearColor, 1, &subresourceRange );
for ( auto& t : sceneTextures.voxels.radiance ) vkCmdClearColorImage( commandBuffer, t.image, t.imageLayout, &clearColor, 1, &subresourceRange );
});
renderMode.bindCallback( renderMode.CALLBACK_END, [&]( VkCommandBuffer commandBuffer ){
// parse voxel lighting
@ -113,24 +124,25 @@ void ext::VoxelizerBehavior::initialize( uf::Object& self ) {
subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
subresourceRange.baseMipLevel = 0;
subresourceRange.baseArrayLayer = 0;
subresourceRange.levelCount = sceneTextures.voxels.albedo.mips;
subresourceRange.layerCount = 1;
sceneTextures.voxels.albedo.setImageLayout(
commandBuffer,
sceneTextures.voxels.albedo.image,
sceneTextures.voxels.albedo.imageLayout,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
subresourceRange
);
sceneTextures.voxels.albedo.generateMipmaps( commandBuffer, 0 );
sceneTextures.voxels.albedo.setImageLayout(
commandBuffer,
sceneTextures.voxels.albedo.image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
sceneTextures.voxels.albedo.imageLayout,
subresourceRange
);
for ( auto& t : sceneTextures.voxels.radiance ) {
subresourceRange.levelCount = t.mips;
t.setImageLayout(
commandBuffer,
t.image,
t.imageLayout,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
subresourceRange
);
t.generateMipmaps( commandBuffer, 0 );
t.setImageLayout(
commandBuffer,
t.image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
t.imageLayout,
subresourceRange
);
}
});
}
#endif
@ -145,9 +157,10 @@ void ext::VoxelizerBehavior::tick( uf::Object& self ) {
auto& scene = uf::scene::getCurrentScene();
auto& sceneTextures = scene.getComponent<pod::SceneTextures>();
auto& controller = scene.getController();
auto& controllerTransform = controller.getComponent<pod::Transform<>>();
auto controllerTransform = uf::transform::flatten( controller.getComponent<uf::Camera>().getTransform() );
renderMode.setTarget("");
if ( renderMode.executed ) {
if ( renderMode.executed ) {
if ( !metadata.initialized ) metadata.initialized = true;
if ( metadata.renderer.limiter > 0 ) {
@ -159,50 +172,42 @@ void ext::VoxelizerBehavior::tick( uf::Object& self ) {
renderMode.execute = false;
}
}
#if 0
if ( renderMode.execute ) {
pod::Vector3f min = metadata.extents.min;
pod::Vector3f max = metadata.extents.max;
pod::Vector3f controllerPosition = controllerTransform.position;
controllerPosition.x = floor(controllerPosition.x);
controllerPosition.y = floor(controllerPosition.y);
controllerPosition.z = -floor(controllerPosition.z);
min.x += floor(controllerTransform.position.x);
min.y -= floor(controllerTransform.position.y);
min.z -= floor(controllerTransform.position.z);
max.x += floor(controllerTransform.position.x);
max.y -= floor(controllerTransform.position.y);
max.z -= floor(controllerTransform.position.z);
pod::Vector3f min = metadata.extents.min + controllerPosition;
pod::Vector3f max = metadata.extents.max + controllerPosition;
sceneTextures.voxels.matrix = uf::matrix::ortho<float>( min.x, max.x, min.y, max.y, min.z, max.z );
auto graph = uf::scene::generateGraph();
for ( auto entity : graph ) {
if ( !entity->hasComponent<uf::Graphic>() ) continue;
auto& graphic = entity->getComponent<uf::Graphic>();
if ( graphic.material.hasShader("geometry", "vxgi") ) {
auto& shader = graphic.material.getShader("geometry", "vxgi");
auto& sceneTextures = scene.getComponent<pod::SceneTextures>();
struct UniformDescriptor {
alignas(16) pod::Matrix4f matrix;
};
auto& uniform = shader.getUniform("UBO");
auto& uniforms = uniform.get<UniformDescriptor>();
uniforms.matrix = sceneTextures.voxels.matrix;
shader.updateUniform( "UBO", uniform );
}
}
}
#endif
}
#if COMP_SHADER_USED
ext::ExtSceneBehavior::bindBuffers( scene, metadata.renderModeName, true );
ext::ExtSceneBehavior::bindBuffers( scene );
#endif
#endif
}
void ext::VoxelizerBehavior::render( uf::Object& self ){
auto& metadata = this->getComponent<ext::VoxelizerBehavior::Metadata>();
auto& renderMode = this->getComponent<uf::renderer::RenderTargetRenderMode>();
auto& scene = uf::scene::getCurrentScene();
auto& sceneTextures = scene.getComponent<pod::SceneTextures>();
auto& controller = scene.getController();
auto& controllerTransform = controller.getComponent<pod::Transform<>>();
if ( uf::renderer::currentRenderMode->getName() != "RenderTarget" && renderMode.execute ) {
pod::Vector3f min = metadata.extents.min;
pod::Vector3f max = metadata.extents.max;
min.x += floor(controllerTransform.position.x);
min.y -= floor(controllerTransform.position.y);
min.z -= floor(controllerTransform.position.z);
max.x += floor(controllerTransform.position.x);
max.y -= floor(controllerTransform.position.y);
max.z -= floor(controllerTransform.position.z);
sceneTextures.voxels.matrix = uf::matrix::ortho<float>( min.x, max.x, min.y, max.y, min.z, max.z );
}
}
void ext::VoxelizerBehavior::render( uf::Object& self ){}
void ext::VoxelizerBehavior::destroy( uf::Object& self ){
#if UF_USE_VULKAN
if ( this->hasComponent<uf::renderer::RenderTargetRenderMode>() ) {

View File

@ -20,6 +20,7 @@ namespace ext {
pod::Vector3ui voxelSize = { 0, 0, 0 };
pod::Vector3ui dispatchSize = { 0, 0, 0 };
std::string renderModeName = "VXGI";
size_t cascades = 0;
struct {
pod::Vector3f min = {};
pod::Vector3f max = {};