Commit for 2021.02.04.7z
This commit is contained in:
parent
dd3d4b8de3
commit
77f24467e9
44
bin/data/shaders/base.colored.vert.glsl
Normal file
44
bin/data/shaders/base.colored.vert.glsl
Normal file
@ -0,0 +1,44 @@
|
||||
#version 450
|
||||
|
||||
layout (constant_id = 0) const uint PASSES = 6;
|
||||
layout (location = 0) in vec3 inPos;
|
||||
layout (location = 1) in vec2 inUv;
|
||||
layout (location = 2) in vec3 inNormal;
|
||||
layout (location = 3) in vec4 inColor;
|
||||
|
||||
layout( push_constant ) uniform PushBlock {
|
||||
uint pass;
|
||||
uint draw;
|
||||
} PushConstant;
|
||||
|
||||
struct Matrices {
|
||||
mat4 model;
|
||||
mat4 view[PASSES];
|
||||
mat4 projection[PASSES];
|
||||
};
|
||||
|
||||
layout (binding = 0) uniform UBO {
|
||||
Matrices matrices;
|
||||
vec4 color;
|
||||
} ubo;
|
||||
|
||||
layout (location = 0) out vec2 outUv;
|
||||
layout (location = 1) out vec4 outColor;
|
||||
layout (location = 2) out vec3 outNormal;
|
||||
layout (location = 3) out vec3 outPosition;
|
||||
|
||||
out gl_PerVertex {
|
||||
vec4 gl_Position;
|
||||
};
|
||||
|
||||
|
||||
void main() {
|
||||
outUv = inUv;
|
||||
outColor = inColor.rgba;
|
||||
|
||||
outPosition = vec3(ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inPos.xyz, 1.0));
|
||||
outNormal = vec3(ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inNormal.xyz, 0.0));
|
||||
outNormal = normalize(outNormal);
|
||||
|
||||
gl_Position = ubo.matrices.projection[PushConstant.pass] * ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inPos.xyz, 1.0);
|
||||
}
|
||||
22
bin/data/shaders/base.frag.glsl
Normal file
22
bin/data/shaders/base.frag.glsl
Normal file
@ -0,0 +1,22 @@
|
||||
#version 450
|
||||
|
||||
layout (binding = 1) uniform sampler2D samplerColor;
|
||||
|
||||
layout (location = 0) in vec2 inUv;
|
||||
layout (location = 1) in vec4 inColor;
|
||||
layout (location = 2) in vec3 inNormal;
|
||||
layout (location = 3) in vec3 inPosition;
|
||||
|
||||
layout (location = 0) out vec4 outAlbedoSpecular;
|
||||
layout (location = 1) out vec4 outNormal;
|
||||
layout (location = 2) out vec4 outPosition;
|
||||
|
||||
void main() {
|
||||
outAlbedoSpecular = texture(samplerColor, inUv);
|
||||
if ( outAlbedoSpecular.a < 0.001 ) discard;
|
||||
outAlbedoSpecular.rgb *= inColor.rgb;
|
||||
outAlbedoSpecular.a = 1;
|
||||
|
||||
outNormal = vec4(inNormal,1);
|
||||
outPosition = vec4(inPosition,1);
|
||||
}
|
||||
@ -7,6 +7,7 @@ layout (location = 2) in vec3 inNormal;
|
||||
|
||||
layout( push_constant ) uniform PushBlock {
|
||||
uint pass;
|
||||
uint draw;
|
||||
} PushConstant;
|
||||
|
||||
struct Matrices {
|
||||
|
||||
@ -15,6 +15,7 @@ layout (location = 2) out flat Cursor outCursor;
|
||||
|
||||
layout( push_constant ) uniform PushBlock {
|
||||
uint pass;
|
||||
uint draw;
|
||||
} PushConstant;
|
||||
|
||||
out gl_PerVertex {
|
||||
|
||||
@ -1,14 +1,70 @@
|
||||
#version 450
|
||||
#extension GL_EXT_samplerless_texture_functions : require
|
||||
|
||||
layout (constant_id = 0) const uint LIGHTS = 256;
|
||||
#define UF_DEFERRED_SAMPLING 0
|
||||
|
||||
layout (input_attachment_index = 0, binding = 1) uniform subpassInput samplerAlbedoMetallic;
|
||||
layout (input_attachment_index = 0, binding = 2) uniform subpassInput samplerNormalRoughness;
|
||||
layout (input_attachment_index = 0, binding = 3) uniform subpassInput samplerDepth;
|
||||
layout (constant_id = 0) const uint LIGHTS = 256;
|
||||
layout (constant_id = 1) const uint TEXTURES = 256;
|
||||
|
||||
struct Material {
|
||||
vec4 colorBase;
|
||||
vec4 colorEmissive;
|
||||
|
||||
float factorMetallic;
|
||||
float factorRoughness;
|
||||
float factorOcclusion;
|
||||
float factorAlphaCutoff;
|
||||
|
||||
int indexAlbedo;
|
||||
int indexNormal;
|
||||
int indexEmissive;
|
||||
int indexOcclusion;
|
||||
|
||||
int indexMetallicRoughness;
|
||||
|
||||
int padding1;
|
||||
int padding2;
|
||||
int padding3;
|
||||
};
|
||||
struct Texture {
|
||||
int index;
|
||||
int samp;
|
||||
int remap;
|
||||
float blend;
|
||||
|
||||
vec4 lerp;
|
||||
};
|
||||
struct DrawCall {
|
||||
int materialIndex;
|
||||
uint materials;
|
||||
int textureIndex;
|
||||
uint textures;
|
||||
};
|
||||
|
||||
layout (input_attachment_index = 0, binding = 1) uniform usubpassInput samplerId;
|
||||
layout (input_attachment_index = 1, binding = 2) uniform subpassInput samplerNormal;
|
||||
|
||||
#if UF_DEFERRED_SAMPLING
|
||||
layout (input_attachment_index = 2, binding = 3) uniform subpassInput samplerUv;
|
||||
#else
|
||||
layout (input_attachment_index = 2, binding = 3) uniform subpassInput samplerAlbedo;
|
||||
#endif
|
||||
|
||||
layout (input_attachment_index = 3, binding = 4) uniform subpassInput samplerDepth;
|
||||
|
||||
layout (binding = 5) uniform sampler3D samplerNoise;
|
||||
layout (binding = 6) uniform sampler2D samplerShadows[LIGHTS];
|
||||
layout (binding = 6) uniform sampler2D samplerTextures[TEXTURES];
|
||||
layout (binding = 7) uniform sampler2D samplerShadows[LIGHTS];
|
||||
layout (std140, binding = 8) readonly buffer Materials {
|
||||
Material materials[];
|
||||
};
|
||||
layout (std140, binding = 9) readonly buffer Textures {
|
||||
Texture textures[];
|
||||
};
|
||||
layout (std140, binding = 10) readonly buffer DrawCalls {
|
||||
DrawCall drawCalls[];
|
||||
};
|
||||
|
||||
|
||||
layout (location = 0) in vec2 inUv;
|
||||
layout (location = 1) in flat uint inPushConstantPass;
|
||||
@ -177,7 +233,9 @@ float random(vec3 seed, int i){
|
||||
}
|
||||
|
||||
float shadowFactor( Light light, uint shadowMap ) {
|
||||
vec4 positionClip = light.projection * light.view * vec4(position.world, 1.0);
|
||||
vec3 point = position.world;
|
||||
|
||||
vec4 positionClip = light.projection * light.view * vec4(point, 1.0);
|
||||
positionClip.xyz /= positionClip.w;
|
||||
|
||||
if ( positionClip.x < -1 || positionClip.x >= 1 ) return 0.0;
|
||||
@ -199,12 +257,14 @@ float shadowFactor( Light light, uint shadowMap ) {
|
||||
|
||||
vec2 uv = positionClip.xy * 0.5 + 0.5;
|
||||
float bias = light.depthBias;
|
||||
if ( !true ) {
|
||||
/*
|
||||
if ( true ) {
|
||||
float cosTheta = clamp(dot(normal.eye, normalize(light.position.xyz - position.eye)), 0, 1);
|
||||
bias = clamp(bias * tan(acos(cosTheta)), 0, 0.01);
|
||||
} else if ( true ) {
|
||||
bias = max(bias * 10 * (1.0 - dot(normal.eye, normalize(light.position.xyz - position.eye))), bias);
|
||||
}
|
||||
bias = max(bias * 10 * (1.0 - dot(normal.eye, normalize(light.position.xyz - position.eye))), bias);
|
||||
}
|
||||
*/
|
||||
|
||||
float eyeDepth = positionClip.z;
|
||||
int samples = poissonDisk.length();
|
||||
@ -391,39 +451,30 @@ void pbr( Light light, vec3 albedo, float metallic, float roughness, vec3 lightP
|
||||
vec3 N = normalize(normal.eye);
|
||||
vec3 L = light.position.xyz - position.eye;
|
||||
float dist = length(L);
|
||||
// if ( light.radius > 0.001 && light.radius < dist ) return;
|
||||
|
||||
vec3 D = normalize(L);
|
||||
L = normalize(L);
|
||||
vec3 V = normalize(-position.eye);
|
||||
vec3 H = normalize(V + D);
|
||||
vec3 H = normalize(V + L);
|
||||
|
||||
float NdotD = max(dot(N, D), 0.0);
|
||||
float NdotL = max(dot(N, L), 0.0);
|
||||
float NdotV = max(dot(N, V), 0.0);
|
||||
|
||||
vec3 radiance = light.color.rgb * light.power / (dist * dist);
|
||||
/*
|
||||
if ( light.radius > 0.0001 ) {
|
||||
radiance *= clamp( light.radius / (pow(dist, 2.0) + 1.0), 0.0, 1.0 );
|
||||
} else if ( false ) {
|
||||
radiance /= dist * dist;
|
||||
}
|
||||
*/
|
||||
float attenuation = light.power / (dist * dist);
|
||||
vec3 radiance = light.color.rgb * attenuation;
|
||||
|
||||
// cook-torrance brdf
|
||||
float NDF = DistributionGGX(N, H, roughness);
|
||||
float G = GeometrySmith(N, V, D, roughness);
|
||||
float G = GeometrySmith(N, V, L, roughness);
|
||||
vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0);
|
||||
|
||||
vec3 kS = F;
|
||||
vec3 kD = vec3(1.0) - kS;
|
||||
kD *= 1.0 - metallic;
|
||||
vec3 kD = vec3(1.0) - F;
|
||||
kD *= 1.0 - metallic;
|
||||
|
||||
vec3 numerator = NDF * G * F;
|
||||
float denominator = 4.0 * NdotV * NdotD;
|
||||
float denominator = 4.0 * NdotV * NdotL;
|
||||
vec3 specular = numerator / max(denominator, 0.001);
|
||||
|
||||
// add to outgoing radiance Lo
|
||||
i += (kD * albedo / PI + specular) * radiance * NdotD;
|
||||
i += (kD * albedo / PI + specular) * radiance * NdotL;
|
||||
}
|
||||
|
||||
vec2 rayBoxDst( vec3 boundsMin, vec3 boundsMax, vec3 rayOrigin, vec3 rayDir ) {
|
||||
@ -496,12 +547,34 @@ void fog( inout vec3 i, float scale ) {
|
||||
i.rgb = mix(i.rgb, color, factor);
|
||||
}
|
||||
|
||||
vec3 decodeNormals( vec2 enc ) {
|
||||
vec2 fenc = enc*4-2;
|
||||
float f = dot(fenc,fenc);
|
||||
float g = sqrt(1-f/4);
|
||||
vec3 n;
|
||||
n.xy = fenc*g;
|
||||
n.z = 1-f/2;
|
||||
return normalize(n);
|
||||
}
|
||||
/*
|
||||
vec4 sampleTexture( uint drawId, int textureIndex, vec2 uv, vec4 base ) {
|
||||
if ( TEXTURES <= textureIndex || textureIndex < 0 ) return base;
|
||||
Texture t = textures[textureIndex+1];
|
||||
return texture( samplerTextures[drawId], mix( t.lerp.xy, t.lerp.zw, uv ) );
|
||||
}
|
||||
*/
|
||||
|
||||
bool validTextureIndex( int textureIndex ) {
|
||||
return 0 <= textureIndex && textureIndex < TEXTURES;
|
||||
}
|
||||
vec4 sampleTexture( uint drawId, int textureIndex, vec2 uv, vec4 base ) {
|
||||
if ( !validTextureIndex( textureIndex ) ) return base;
|
||||
Texture t = textures[textureIndex+1];
|
||||
// if ( 0 <= t.remap && t.remap <= TEXTURES && t.remap != textureIndex ) t = textures[t.remap+1];
|
||||
return texture( samplerTextures[drawId], mix( t.lerp.xy, t.lerp.zw, uv ) );
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec4 albedoMetallic = subpassLoad(samplerAlbedoMetallic);
|
||||
vec4 normalRoughness = subpassLoad(samplerNormalRoughness);
|
||||
// vec4 positionAO = subpassLoad(samplerPositionAO);
|
||||
|
||||
normal.eye = normalRoughness.rgb;
|
||||
{
|
||||
mat4 iProj = inverse( ubo.matrices.projection[inPushConstantPass] );
|
||||
mat4 iView = inverse( ubo.matrices.view[inPushConstantPass] );
|
||||
@ -515,12 +588,34 @@ void main() {
|
||||
vec4 positionWorld = iView * positionEye;
|
||||
position.world = positionWorld.xyz;
|
||||
}
|
||||
|
||||
normal.eye = decodeNormals( subpassLoad(samplerNormal).xy );
|
||||
|
||||
uvec2 ID = subpassLoad(samplerId).xy;
|
||||
uint drawId = ID.x;
|
||||
|
||||
DrawCall drawCall = drawCalls[drawId];
|
||||
uint materialId = ID.y + 1;
|
||||
materialId += drawCall.materialIndex;
|
||||
|
||||
Material material = materials[materialId];
|
||||
vec4 C = material.colorBase;
|
||||
|
||||
#if UF_DEFERRED_SAMPLING
|
||||
vec2 uv = subpassLoad(samplerUv).xy;
|
||||
C = sampleTexture( drawId, drawCall.textureIndex + material.indexAlbedo, uv, C );
|
||||
#else
|
||||
C = subpassLoad(samplerAlbedo);
|
||||
#endif
|
||||
|
||||
float M = material.factorMetallic;
|
||||
float R = 0.5; //material.factorRoughness;
|
||||
float AO = material.factorOcclusion;
|
||||
|
||||
bool usePbr = true;
|
||||
bool gammaCorrect = false;
|
||||
float litFactor = 1.0;
|
||||
float ao = 1; // positionAO.a;
|
||||
vec3 fragColor = albedoMetallic.rgb * ubo.ambient.rgb * ao;
|
||||
vec3 fragColor = C.rgb * ubo.ambient.rgb * AO;
|
||||
for ( uint i = 0; i < LIGHTS; ++i ) {
|
||||
Light light = ubo.lights[i];
|
||||
|
||||
@ -533,12 +628,12 @@ void main() {
|
||||
light.power *= factor;
|
||||
litFactor += light.power;
|
||||
}
|
||||
if ( light.power <= 0.0001 ) continue;
|
||||
if ( usePbr ) {
|
||||
pbr( light, albedoMetallic.rgb, albedoMetallic.a, normalRoughness.a, lightPositionWorld, fragColor );
|
||||
pbr( light, C.rgb, M, R, lightPositionWorld, fragColor );
|
||||
} else
|
||||
phong( light, albedoMetallic, fragColor );
|
||||
phong( light, C, fragColor );
|
||||
}
|
||||
|
||||
if ( gammaCorrect ) {
|
||||
fragColor = fragColor / (fragColor + vec3(1.0));
|
||||
fragColor = pow(fragColor, vec3(1.0/2.2));
|
||||
@ -551,9 +646,9 @@ void main() {
|
||||
//dither1(fragColor);
|
||||
fragColor += dither2();
|
||||
}
|
||||
*/
|
||||
if ( (ubo.mode.type & (0x1 << 1)) == (0x1 << 1) ) {
|
||||
whitenoise(fragColor);
|
||||
}
|
||||
*/
|
||||
outFragColor = vec4(fragColor,1);
|
||||
}
|
||||
@ -5,7 +5,7 @@ layout (constant_id = 0) const uint LIGHTS = 256;
|
||||
|
||||
layout (input_attachment_index = 0, binding = 1) uniform subpassInput samplerAlbedoMetallic;
|
||||
layout (input_attachment_index = 0, binding = 2) uniform subpassInput samplerNormalRoughness;
|
||||
layout (input_attachment_index = 0, binding = 3) uniform subpassInput samplerPositionAO;
|
||||
layout (input_attachment_index = 0, binding = 3) uniform subpassInput samplerDepth;
|
||||
|
||||
layout (binding = 5) uniform sampler3D samplerNoise;
|
||||
layout (binding = 6) uniform sampler2D samplerShadows[LIGHTS];
|
||||
@ -177,10 +177,7 @@ float random(vec3 seed, int i){
|
||||
}
|
||||
|
||||
float shadowFactor( Light light, uint shadowMap ) {
|
||||
vec3 point = position.world;
|
||||
// point += normalize(normal.world) * light.depthBias;
|
||||
|
||||
vec4 positionClip = light.projection * light.view * vec4(point, 1.0);
|
||||
vec4 positionClip = light.projection * light.view * vec4(position.world, 1.0);
|
||||
positionClip.xyz /= positionClip.w;
|
||||
|
||||
if ( positionClip.x < -1 || positionClip.x >= 1 ) return 0.0;
|
||||
@ -202,14 +199,12 @@ float shadowFactor( Light light, uint shadowMap ) {
|
||||
|
||||
vec2 uv = positionClip.xy * 0.5 + 0.5;
|
||||
float bias = light.depthBias;
|
||||
/*
|
||||
if ( true ) {
|
||||
if ( !true ) {
|
||||
float cosTheta = clamp(dot(normal.eye, normalize(light.position.xyz - position.eye)), 0, 1);
|
||||
bias = clamp(bias * tan(acos(cosTheta)), 0, 0.01);
|
||||
} else if ( true ) {
|
||||
bias = max(bias * 10 * (1.0 - dot(normal.eye, normalize(light.position.xyz - position.eye))), bias);
|
||||
}
|
||||
*/
|
||||
bias = max(bias * 10 * (1.0 - dot(normal.eye, normalize(light.position.xyz - position.eye))), bias);
|
||||
}
|
||||
|
||||
float eyeDepth = positionClip.z;
|
||||
int samples = poissonDisk.length();
|
||||
@ -504,12 +499,20 @@ void fog( inout vec3 i, float scale ) {
|
||||
void main() {
|
||||
vec4 albedoMetallic = subpassLoad(samplerAlbedoMetallic);
|
||||
vec4 normalRoughness = subpassLoad(samplerNormalRoughness);
|
||||
vec4 positionAO = subpassLoad(samplerPositionAO);
|
||||
// vec4 positionAO = subpassLoad(samplerPositionAO);
|
||||
|
||||
normal.eye = normalRoughness.rgb;
|
||||
position.eye = positionAO.rgb; {
|
||||
{
|
||||
mat4 iProj = inverse( ubo.matrices.projection[inPushConstantPass] );
|
||||
mat4 iView = inverse( ubo.matrices.view[inPushConstantPass] );
|
||||
vec4 positionWorld = iView * vec4(position.eye, 1);
|
||||
float depth = subpassLoad(samplerDepth).r;
|
||||
|
||||
vec4 positionClip = vec4(inUv * 2.0 - 1.0, depth, 1.0);
|
||||
vec4 positionEye = iProj * positionClip;
|
||||
positionEye /= positionEye.w;
|
||||
position.eye = positionEye.xyz;
|
||||
|
||||
vec4 positionWorld = iView * positionEye;
|
||||
position.world = positionWorld.xyz;
|
||||
}
|
||||
|
||||
@ -530,7 +533,6 @@ void main() {
|
||||
light.power *= factor;
|
||||
litFactor += light.power;
|
||||
}
|
||||
if ( light.power <= 0.0001 ) continue;
|
||||
if ( usePbr ) {
|
||||
pbr( light, albedoMetallic.rgb, albedoMetallic.a, normalRoughness.a, lightPositionWorld, fragColor );
|
||||
} else
|
||||
@ -8,6 +8,7 @@ layout (location = 1) out flat uint outPushConstantPass;
|
||||
|
||||
layout( push_constant ) uniform PushBlock {
|
||||
uint pass;
|
||||
uint draw;
|
||||
} PushConstant;
|
||||
|
||||
out gl_PerVertex {
|
||||
|
||||
@ -1,35 +1,138 @@
|
||||
#version 450
|
||||
|
||||
#define UF_DEFERRED_SAMPLING 0
|
||||
|
||||
layout (constant_id = 0) const uint TEXTURES = 1;
|
||||
layout (binding = 0) uniform sampler2D samplerTextures[TEXTURES];
|
||||
|
||||
struct Material {
|
||||
vec4 colorBase;
|
||||
vec4 colorEmissive;
|
||||
|
||||
float factorMetallic;
|
||||
float factorRoughness;
|
||||
float factorOcclusion;
|
||||
float factorMappedBlend;
|
||||
float factorAlphaCutoff;
|
||||
float factorPadding;
|
||||
|
||||
int indexAlbedo;
|
||||
int indexNormal;
|
||||
int indexEmissive;
|
||||
int indexOcclusion;
|
||||
|
||||
int indexMetallicRoughness;
|
||||
int indexMappedTarget;
|
||||
|
||||
int padding1;
|
||||
int padding2;
|
||||
int padding3;
|
||||
};
|
||||
struct Texture {
|
||||
int index;
|
||||
int samp;
|
||||
int remap;
|
||||
float blend;
|
||||
|
||||
vec4 lerp;
|
||||
};
|
||||
layout (std140, binding = 1) readonly buffer Materials {
|
||||
Material materials[];
|
||||
};
|
||||
layout (std140, binding = 2) readonly buffer Textures {
|
||||
Texture textures[];
|
||||
};
|
||||
|
||||
layout (location = 0) in vec2 inUv;
|
||||
layout (location = 1) in vec4 inColor;
|
||||
layout (location = 2) in vec3 inNormal;
|
||||
layout (location = 3) in mat3 inTBN;
|
||||
layout (location = 6) in vec3 inPosition;
|
||||
layout (location = 7) flat in ivec2 inId;
|
||||
layout (location = 7) flat in ivec4 inId;
|
||||
|
||||
layout (location = 0) out uvec2 outId;
|
||||
layout (location = 1) out vec2 outNormals;
|
||||
|
||||
#if UF_DEFERRED_SAMPLING
|
||||
layout (location = 2) out vec2 outUvs;
|
||||
#else
|
||||
layout (location = 2) out vec4 outAlbedo;
|
||||
#endif
|
||||
|
||||
vec2 encodeNormals( vec3 n ) {
|
||||
float p = sqrt(n.z*8+8);
|
||||
return n.xy/p + 0.5;
|
||||
}
|
||||
|
||||
bool validTextureIndex( int textureIndex ) {
|
||||
return 0 <= textureIndex && textureIndex < TEXTURES;
|
||||
}
|
||||
vec4 sampleTexture( int textureIndex, vec2 uv, vec4 base ) {
|
||||
if ( !validTextureIndex( textureIndex ) ) return base;
|
||||
Texture t = textures[textureIndex+1];
|
||||
// if ( 0 <= t.remap && t.remap <= TEXTURES && t.remap != textureIndex ) t = textures[t.remap+1];
|
||||
return texture( samplerTextures[0], mix( t.lerp.xy, t.lerp.zw, uv ) );
|
||||
}
|
||||
|
||||
void main() {
|
||||
#if UF_DEFERRED_SAMPLING
|
||||
vec3 N = inNormal;
|
||||
outUvs = fract(inUv);
|
||||
#else
|
||||
int materialId = int(inId.y);
|
||||
Material material = materials[materialId];
|
||||
|
||||
vec2 uv = fract(inUv.xy);
|
||||
|
||||
vec4 C = vec4(0, 0, 0, 0);
|
||||
vec3 N = inNormal;
|
||||
vec3 P = inPosition;
|
||||
float M = material.factorMetallic;
|
||||
float R = material.factorRoughness;
|
||||
float AO = material.factorOcclusion;
|
||||
|
||||
// sample albedo
|
||||
// C = sampleTexture( material.indexAlbedo, uv, material.colorBase );
|
||||
if ( !validTextureIndex( material.indexAlbedo ) ) {
|
||||
discard;
|
||||
}
|
||||
{
|
||||
Texture t = textures[material.indexAlbedo + 1];
|
||||
C = texture( samplerTextures[0], mix( t.lerp.xy, t.lerp.zw, uv ) );
|
||||
}
|
||||
|
||||
// sample normal
|
||||
if ( validTextureIndex( material.indexNormal ) ) {
|
||||
Texture t = textures[material.indexNormal + 1];
|
||||
N = inTBN * normalize( texture( samplerTextures[0], mix( t.lerp.xy, t.lerp.zw, uv ) ).xyz * 2.0 - vec3(1.0));
|
||||
}
|
||||
|
||||
#if 0
|
||||
// sample metallic/roughness
|
||||
if ( validTextureIndex( material.indexMetallicRoughness ) ) {
|
||||
Texture t = textures[material.indexMetallicRoughness + 1];
|
||||
vec4 sampled = texture( samplerTextures[0], mix( t.lerp.xy, t.lerp.zw, uv ) );
|
||||
M = sampled.b;
|
||||
R = sampled.g;
|
||||
}
|
||||
// sample ao
|
||||
AO = material.factorOcclusion;
|
||||
if ( validTextureIndex( material.indexOcclusion ) ) {
|
||||
Texture t = textures[material.indexMetallicRoughness + 1];
|
||||
AO = texture( samplerTextures[0], mix( t.lerp.xy, t.lerp.zw, uv ) ).r;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( C.a < abs(material.factorAlphaCutoff) ) {
|
||||
// outTransparency = C;
|
||||
discard;
|
||||
} else {
|
||||
C.rgb *= inColor.rgb * C.a;
|
||||
outAlbedo = vec4(C.rgb,1);
|
||||
}
|
||||
#endif
|
||||
outNormals = encodeNormals( N );
|
||||
outId = ivec2(inId.w, inId.y);
|
||||
}
|
||||
|
||||
/*
|
||||
layout (location = 0) out vec4 outAlbedoMetallic;
|
||||
layout (location = 1) out vec4 outNormalRoughness;
|
||||
layout (location = 2) out vec4 outPositionAO;
|
||||
@ -99,4 +202,5 @@ void main() {
|
||||
outAlbedoMetallic = vec4(C.rgb,M);
|
||||
outNormalRoughness = vec4(N,R);
|
||||
outPositionAO = vec4(P,AO);
|
||||
}
|
||||
}
|
||||
*/
|
||||
@ -9,14 +9,15 @@ layout (location = 4) in ivec2 inId;
|
||||
|
||||
layout( push_constant ) uniform PushBlock {
|
||||
uint pass;
|
||||
uint draw;
|
||||
} PushConstant;
|
||||
|
||||
layout (binding = 2) uniform UBO {
|
||||
layout (binding = 3) uniform UBO {
|
||||
mat4 view[PASSES];
|
||||
mat4 projection[PASSES];
|
||||
} ubo;
|
||||
|
||||
layout (std140, binding = 3) readonly buffer Models {
|
||||
layout (std140, binding = 4) readonly buffer Models {
|
||||
mat4 models[];
|
||||
};
|
||||
|
||||
@ -25,10 +26,10 @@ layout (location = 1) out vec4 outColor;
|
||||
layout (location = 2) out vec3 outNormal;
|
||||
layout (location = 3) out mat3 outTBN;
|
||||
layout (location = 6) out vec3 outPosition;
|
||||
layout (location = 7) out ivec2 outId;
|
||||
layout (location = 7) out ivec4 outId;
|
||||
|
||||
out gl_PerVertex {
|
||||
vec4 gl_Position;
|
||||
vec4 gl_Position;
|
||||
};
|
||||
|
||||
vec4 snap(vec4 vertex, vec2 resolution) {
|
||||
@ -42,7 +43,7 @@ vec4 snap(vec4 vertex, vec2 resolution) {
|
||||
void main() {
|
||||
outUv = inUv;
|
||||
outColor = vec4(1.0);
|
||||
outId = inId;
|
||||
outId = ivec4(inId, PushConstant.pass, PushConstant.draw);
|
||||
|
||||
mat4 model = models.length() <= 0 ? mat4(1.0) : models[int(inId.x)];
|
||||
outPosition = vec3(ubo.view[PushConstant.pass] * model * vec4(inPos.xyz, 1.0));
|
||||
@ -57,5 +58,5 @@ void main() {
|
||||
}
|
||||
|
||||
gl_Position = ubo.projection[PushConstant.pass] * ubo.view[PushConstant.pass] * model * vec4(inPos.xyz, 1.0);
|
||||
// gl_Position = snap( gl_Position, vec2(320.0, 240.0) );
|
||||
// gl_Position = snap( gl_Position, vec2(256.0, 224.0) );
|
||||
}
|
||||
@ -11,18 +11,19 @@ layout (location = 6) in vec4 inWeights;
|
||||
|
||||
layout( push_constant ) uniform PushBlock {
|
||||
uint pass;
|
||||
uint draw;
|
||||
} PushConstant;
|
||||
|
||||
layout (binding = 2) uniform UBO {
|
||||
layout (binding = 3) uniform UBO {
|
||||
mat4 view[PASSES];
|
||||
mat4 projection[PASSES];
|
||||
} ubo;
|
||||
|
||||
layout (std140, binding = 3) readonly buffer Models {
|
||||
layout (std140, binding = 4) readonly buffer Models {
|
||||
mat4 models[];
|
||||
};
|
||||
|
||||
layout (std140, binding = 4) readonly buffer Joints {
|
||||
layout (std140, binding = 5) readonly buffer Joints {
|
||||
mat4 joints[];
|
||||
};
|
||||
|
||||
@ -31,7 +32,7 @@ layout (location = 1) out vec4 outColor;
|
||||
layout (location = 2) out vec3 outNormal;
|
||||
layout (location = 3) out mat3 outTBN;
|
||||
layout (location = 6) out vec3 outPosition;
|
||||
layout (location = 7) out ivec2 outId;
|
||||
layout (location = 7) out ivec4 outId;
|
||||
|
||||
out gl_PerVertex {
|
||||
vec4 gl_Position;
|
||||
@ -48,7 +49,7 @@ vec4 snap(vec4 vertex, vec2 resolution) {
|
||||
void main() {
|
||||
outUv = inUv;
|
||||
outColor = vec4(1.0);
|
||||
outId = inId;
|
||||
outId = ivec4(inId, PushConstant.pass, PushConstant.draw);
|
||||
|
||||
mat4 model = models.length() <= 0 ? mat4(1.0) : models[int(inId.x)];
|
||||
mat4 skinnedMatrix = joints.length() <= 0 ? mat4(1.0) :
|
||||
|
||||
@ -11,6 +11,7 @@ layout (location = 6) in vec4 inWeights;
|
||||
|
||||
layout( push_constant ) uniform PushBlock {
|
||||
uint pass;
|
||||
uint draw;
|
||||
} PushConstant;
|
||||
|
||||
struct Matrices {
|
||||
@ -18,12 +19,12 @@ struct Matrices {
|
||||
mat4 view[PASSES];
|
||||
mat4 projection[PASSES];
|
||||
};
|
||||
layout (binding = 2) uniform UBO {
|
||||
layout (binding = 3) uniform UBO {
|
||||
Matrices matrices;
|
||||
vec4 color;
|
||||
} ubo;
|
||||
|
||||
layout (std140, binding = 3) readonly buffer Joints {
|
||||
layout (std140, binding = 4) readonly buffer Joints {
|
||||
mat4 joints[];
|
||||
};
|
||||
|
||||
@ -33,7 +34,7 @@ layout (location = 1) out vec4 outColor;
|
||||
layout (location = 2) out vec3 outNormal;
|
||||
layout (location = 3) out mat3 outTBN;
|
||||
layout (location = 6) out vec3 outPosition;
|
||||
layout (location = 7) out ivec2 outId;
|
||||
layout (location = 7) out ivec4 outId;
|
||||
|
||||
out gl_PerVertex {
|
||||
vec4 gl_Position;
|
||||
@ -50,7 +51,7 @@ vec4 snap(vec4 vertex, vec2 resolution) {
|
||||
void main() {
|
||||
outUv = inUv;
|
||||
outColor = ubo.color;
|
||||
outId = inId;
|
||||
outId = ivec4(inId, PushConstant.pass, PushConstant.draw);
|
||||
|
||||
mat4 skinnedMatrix = joints.length() <= 0 ? mat4(1.0) :
|
||||
inWeights.x * joints[int(inJoints.x)] +
|
||||
|
||||
@ -9,6 +9,7 @@ layout (location = 4) in ivec2 inId;
|
||||
|
||||
layout( push_constant ) uniform PushBlock {
|
||||
uint pass;
|
||||
uint draw;
|
||||
} PushConstant;
|
||||
|
||||
struct Matrices {
|
||||
@ -17,7 +18,7 @@ struct Matrices {
|
||||
mat4 projection[PASSES];
|
||||
};
|
||||
|
||||
layout (binding = 2) uniform UBO {
|
||||
layout (binding = 3) uniform UBO {
|
||||
Matrices matrices;
|
||||
vec4 color;
|
||||
} ubo;
|
||||
@ -27,7 +28,7 @@ layout (location = 1) out vec4 outColor;
|
||||
layout (location = 2) out vec3 outNormal;
|
||||
layout (location = 3) out mat3 outTBN;
|
||||
layout (location = 6) out vec3 outPosition;
|
||||
layout (location = 7) out ivec2 outId;
|
||||
layout (location = 7) out ivec4 outId;
|
||||
|
||||
out gl_PerVertex {
|
||||
vec4 gl_Position;
|
||||
@ -44,7 +45,7 @@ vec4 snap(vec4 vertex, vec2 resolution) {
|
||||
void main() {
|
||||
outUv = inUv;
|
||||
outColor = ubo.color;
|
||||
outId = inId;
|
||||
outId = ivec4(inId, PushConstant.pass, PushConstant.draw);
|
||||
|
||||
outPosition = vec3(ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inPos.xyz, 1.0));
|
||||
outNormal = vec3(ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inNormal.xyz, 0.0));
|
||||
|
||||
@ -6,6 +6,7 @@ layout (location = 1) in vec2 inUv;
|
||||
|
||||
layout( push_constant ) uniform PushBlock {
|
||||
uint pass;
|
||||
uint draw;
|
||||
} PushConstant;
|
||||
|
||||
struct Matrices {
|
||||
|
||||
@ -6,6 +6,7 @@ layout (location = 1) in vec2 inUv;
|
||||
|
||||
layout( push_constant ) uniform PushBlock {
|
||||
uint pass;
|
||||
uint draw;
|
||||
} PushConstant;
|
||||
|
||||
struct Matrices {
|
||||
|
||||
@ -8,6 +8,7 @@ layout (location = 3) in uint inColor;
|
||||
|
||||
layout( push_constant ) uniform PushBlock {
|
||||
uint pass;
|
||||
uint draw;
|
||||
} PushConstant;
|
||||
|
||||
struct Matrices {
|
||||
|
||||
@ -5,6 +5,7 @@ layout (location = 0) in vec3 inPos;
|
||||
|
||||
layout( push_constant ) uniform PushBlock {
|
||||
uint pass;
|
||||
uint draw;
|
||||
} PushConstant;
|
||||
|
||||
struct Matrices {
|
||||
|
||||
@ -8,6 +8,7 @@ layout (location = 3) in uint inColor;
|
||||
|
||||
layout( push_constant ) uniform PushBlock {
|
||||
uint pass;
|
||||
uint draw;
|
||||
} PushConstant;
|
||||
|
||||
struct Matrices {
|
||||
|
||||
@ -13,10 +13,23 @@
|
||||
#include <queue>
|
||||
|
||||
namespace pod {
|
||||
struct UF_API DrawCall {
|
||||
alignas(4) int32_t materialIndex = -1;
|
||||
alignas(4) uint32_t materials = 0;
|
||||
alignas(4) int32_t textureIndex = -1;
|
||||
alignas(4) uint32_t textures = 0;
|
||||
};
|
||||
struct UF_API Texture {
|
||||
std::string name = "";
|
||||
int32_t index = -1;
|
||||
int32_t sampler = -1;
|
||||
struct Storage {
|
||||
alignas(4) int32_t index = -1;
|
||||
alignas(4) int32_t sampler = -1;
|
||||
alignas(4) int32_t remap = -1;
|
||||
alignas(4) float blend = 0;
|
||||
|
||||
alignas(16) pod::Vector4f lerp = {0, 0, 1, 1};
|
||||
} storage;
|
||||
uf::renderer::Texture2D texture;
|
||||
};
|
||||
struct UF_API Light {
|
||||
std::string name = "";
|
||||
@ -35,24 +48,23 @@ namespace pod {
|
||||
std::string name = "";
|
||||
//
|
||||
struct Storage {
|
||||
alignas(16) pod::Vector4f colorBase = { 1, 0, 1, 1 };
|
||||
|
||||
alignas(16) pod::Vector4f colorBase = { 0, 0, 0, 0 };
|
||||
alignas(16) pod::Vector4f colorEmissive = { 0, 0, 0, 0 };
|
||||
|
||||
alignas(4) float factorMetallic = 0.0f;
|
||||
alignas(4) float factorRoughness = 0.0f;
|
||||
alignas(4) float factorOcclusion = 0.0f;
|
||||
alignas(4) float factorMappedBlend = 0.0f;
|
||||
|
||||
alignas(4) float factorAlphaCutoff = 1.0f;
|
||||
alignas(4) float factorPadding = 0.0f;
|
||||
|
||||
alignas(4) int indexAlbedo = -1;
|
||||
alignas(4) int indexNormal = -1;
|
||||
|
||||
alignas(4) int indexEmissive = -1;
|
||||
alignas(4) int indexOcclusion = -1;
|
||||
|
||||
alignas(4) int indexMetallicRoughness = -1;
|
||||
alignas(4) int indexMappedTarget = -1;
|
||||
alignas(4) int padding1 = -1;
|
||||
alignas(4) int padding2 = -1;
|
||||
alignas(4) int padding3 = -1;
|
||||
} storage;
|
||||
};
|
||||
struct UF_API Node {
|
||||
@ -69,6 +81,7 @@ namespace pod {
|
||||
uf::Object* entity = NULL;
|
||||
size_t jointBufferIndex = -1;
|
||||
size_t materialBufferIndex = -1;
|
||||
size_t textureBufferIndex = -1;
|
||||
|
||||
int32_t skin = -1;
|
||||
Mesh mesh;
|
||||
|
||||
@ -78,7 +78,7 @@ namespace ext {
|
||||
void initialize( Graphic& graphic, GraphicDescriptor& descriptor );
|
||||
void update( Graphic& graphic );
|
||||
void update( Graphic& graphic, GraphicDescriptor& descriptor );
|
||||
void record( Graphic& graphic, VkCommandBuffer, size_t = 0 );
|
||||
void record( Graphic& graphic, VkCommandBuffer, size_t = 0, size_t = 0 );
|
||||
void destroy();
|
||||
};
|
||||
struct UF_API Material {
|
||||
@ -123,8 +123,8 @@ namespace ext {
|
||||
Pipeline& getPipeline( GraphicDescriptor& descriptor );
|
||||
void updatePipelines();
|
||||
|
||||
void record( VkCommandBuffer commandBuffer, size_t pass = 0 );
|
||||
void record( VkCommandBuffer commandBuffer, GraphicDescriptor& descriptor, size_t pass = 0 );
|
||||
void record( VkCommandBuffer commandBuffer, size_t pass = 0, size_t draw = 0 );
|
||||
void record( VkCommandBuffer commandBuffer, GraphicDescriptor& descriptor, size_t pass = 0, size_t draw = 0 );
|
||||
|
||||
bool hasStorage( const std::string& name );
|
||||
Buffer* getStorageBuffer( const std::string& name );
|
||||
|
||||
@ -35,8 +35,10 @@ namespace ext {
|
||||
Device* device = VK_NULL_HANDLE;
|
||||
VkRenderPass renderPass = VK_NULL_HANDLE;
|
||||
std::vector<VkFramebuffer> framebuffers;
|
||||
uint32_t width = 0, height = 0;
|
||||
uint32_t width = 0;
|
||||
uint32_t height = 0;
|
||||
uint8_t multiviews = 1;
|
||||
uint8_t samples = 1;
|
||||
// RAII
|
||||
void initialize( Device& device );
|
||||
void destroy();
|
||||
|
||||
@ -52,6 +52,7 @@ namespace ext {
|
||||
extern UF_API bool waitOnRenderEnd;
|
||||
extern UF_API bool individualPipelines;
|
||||
extern UF_API bool multithreadedCommandRecording;
|
||||
extern UF_API std::string deferredMode;
|
||||
extern UF_API bool deferredReconstructPosition;
|
||||
extern UF_API bool deferredAliasOutputToSwapchain;
|
||||
extern UF_API bool multiview;
|
||||
|
||||
@ -165,6 +165,7 @@ std::string uf::Asset::load( const std::string& uri, const std::string& hash ) {
|
||||
UF_ASSET_REGISTER(pod::Graph)
|
||||
auto& metadata = this->getComponent<uf::Serializer>();
|
||||
|
||||
metadata[uri]["flags"]["ATLAS"] = true;
|
||||
ext::gltf::load_mode_t LOAD_FLAGS = 0;
|
||||
#define LOAD_FLAG(name)\
|
||||
if ( metadata[uri]["flags"][#name].as<bool>() )\
|
||||
|
||||
@ -274,7 +274,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*/, false );
|
||||
}
|
||||
|
||||
/*
|
||||
if ( graph.materials.empty() && graphic.hasStorage("Materials") ) {
|
||||
auto& shader = graphic.material.getShader("fragment");
|
||||
std::vector<pod::Material::Storage> materials( graph.materials.size() );
|
||||
@ -307,8 +307,9 @@ void uf::GltfBehavior::tick( uf::Object& self ) {
|
||||
});
|
||||
}
|
||||
auto& storageBuffer = *graphic.getStorageBuffer("Materials");
|
||||
graphic.updateBuffer( (void*) materials.data(), materials.size() * sizeof(pod::Material::Storage), graph.root.materialBufferIndex /*storageBuffer*/, false );
|
||||
graphic.updateBuffer( (void*) materials.data(), materials.size() * sizeof(pod::Material::Storage), graph.root.materialBufferIndex /*storageBuffer/, false );
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
class BulletDebugDrawer : public btIDebugDraw {
|
||||
protected:
|
||||
int m;
|
||||
uf::BaseMesh<pod::Vertex_3F2F3F32B> mesh;
|
||||
uf::BaseMesh<pod::Vertex_3F2F3F4F> mesh;
|
||||
public:
|
||||
virtual void drawLine( const btVector3& from, const btVector3& to, const btVector3& color ) {
|
||||
drawLine( from, to, color, color );
|
||||
@ -51,7 +51,8 @@ public:
|
||||
}
|
||||
int getDebugMode(void) const { return m; }
|
||||
|
||||
const uf::BaseMesh<pod::Vertex_3F2F3F32B>& getMesh() const { return mesh; }
|
||||
uf::BaseMesh<pod::Vertex_3F2F3F4F>& getMesh() { return mesh; }
|
||||
const uf::BaseMesh<pod::Vertex_3F2F3F4F>& getMesh() const { return mesh; }
|
||||
};
|
||||
|
||||
bool ext::bullet::debugDrawEnabled = false;
|
||||
@ -476,9 +477,11 @@ void UF_API ext::bullet::activateCollision( pod::Bullet& collider, bool enabled
|
||||
}
|
||||
|
||||
void UF_API ext::bullet::debugDraw( uf::Object& object ) {
|
||||
auto& mesh = ext::bullet::debugDrawer.getMesh();
|
||||
if ( mesh.vertices.empty() ) return;
|
||||
bool create = !object.hasComponent<uf::Graphic>();
|
||||
auto& graphic = object.getComponent<uf::Graphic>();
|
||||
auto mesh = ext::bullet::debugDrawer.getMesh();
|
||||
graphic.process = false;
|
||||
if ( create ) {
|
||||
graphic.process = true;
|
||||
|
||||
@ -488,16 +491,16 @@ void UF_API ext::bullet::debugDraw( uf::Object& object ) {
|
||||
|
||||
graphic.material.attachShader("./data/shaders/base.colored.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
|
||||
graphic.material.attachShader("./data/shaders/base.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
|
||||
|
||||
graphic.initialize();
|
||||
graphic.initializeGeometry( mesh );
|
||||
graphic.initializeGeometry( mesh, 0 );
|
||||
graphic.descriptor.topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
|
||||
graphic.descriptor.fill = VK_POLYGON_MODE_LINE;
|
||||
graphic.descriptor.lineWidth = 8.0f;
|
||||
} else {
|
||||
graphic.process = true;
|
||||
|
||||
graphic.initializeGeometry( mesh );
|
||||
graphic.initializeGeometry( mesh, 0 );
|
||||
graphic.getPipeline().update( graphic );
|
||||
}
|
||||
}
|
||||
@ -181,11 +181,13 @@ namespace {
|
||||
vertex.id.x = nodeIndex;
|
||||
vertex.id.y = primitive.material;
|
||||
|
||||
/*
|
||||
if ( !(graph.mode & ext::gltf::LoadMode::SEPARATE) && (graph.mode & ext::gltf::LoadMode::ATLAS) ) {
|
||||
auto& material = graph.materials[primitive.material];
|
||||
auto& texture = graph.textures[material.storage.indexAlbedo];
|
||||
vertex.uv = graph.atlas->mapUv( vertex.uv, texture.index );
|
||||
}
|
||||
*/
|
||||
// required due to reverse-Z projection matrix flipping the X axis as well
|
||||
// default is to proceed with this
|
||||
if ( !(graph.mode & ext::gltf::LoadMode::INVERT) ){
|
||||
@ -256,6 +258,7 @@ pod::Graph ext::gltf::load( const std::string& filename, ext::gltf::load_mode_t
|
||||
graph.mode = mode;
|
||||
graph.metadata = metadata;
|
||||
|
||||
|
||||
if ( !warn.empty() ) uf::iostream << "glTF warning: " << warn << "\n";
|
||||
if ( !err.empty() ) uf::iostream << "glTF error: " << err << "\n";
|
||||
if ( !ret ) { uf::iostream << "glTF error: failed to parse file: " << filename << "\n";
|
||||
@ -295,12 +298,28 @@ pod::Graph ext::gltf::load( const std::string& filename, ext::gltf::load_mode_t
|
||||
for ( auto& t : model.textures ) {
|
||||
auto& texture = graph.textures.emplace_back();
|
||||
texture.name = t.name;
|
||||
texture.index = t.source;
|
||||
texture.sampler = t.sampler;
|
||||
|
||||
texture.storage.index = t.source;
|
||||
texture.storage.sampler = t.sampler;
|
||||
if ( graph.atlas ) {
|
||||
auto& atlas = *graph.atlas;
|
||||
auto atlasMin = atlas.mapUv( {0, 0}, t.source );
|
||||
auto atlasMax = atlas.mapUv( {1, 1}, t.source );
|
||||
|
||||
texture.storage.lerp = {
|
||||
atlasMin.x,
|
||||
atlasMin.y,
|
||||
|
||||
atlasMax.x,
|
||||
atlasMax.y,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
// load materials
|
||||
{
|
||||
// null material
|
||||
// graph.materials.emplace_back();
|
||||
for ( auto& m : model.materials ) {
|
||||
auto& material = graph.materials.emplace_back();
|
||||
material.name = m.name;
|
||||
@ -321,25 +340,33 @@ pod::Graph ext::gltf::load( const std::string& filename, ext::gltf::load_mode_t
|
||||
m.emissiveFactor[2],
|
||||
0
|
||||
};
|
||||
|
||||
material.storage.factorMetallic = m.pbrMetallicRoughness.metallicFactor;
|
||||
material.storage.factorRoughness = m.pbrMetallicRoughness.roughnessFactor;
|
||||
material.storage.factorOcclusion = m.occlusionTexture.strength;
|
||||
|
||||
|
||||
/*
|
||||
if ( 0 <= material.storage.indexAlbedo && material.storage.indexAlbedo < graph.textures.size() ) {
|
||||
material.storage.indexAlbedo = graph.textures[material.storage.indexAlbedo].index;
|
||||
auto& texture = graph.textures[material.storage.indexAlbedo];
|
||||
material.storage.indexAlbedo = texture.storage.index;
|
||||
}
|
||||
if ( 0 <= material.storage.indexNormal && material.storage.indexNormal < graph.textures.size() ) {
|
||||
material.storage.indexNormal = graph.textures[material.storage.indexNormal].index;
|
||||
auto& texture = graph.textures[material.storage.indexNormal];
|
||||
material.storage.indexNormal = texture.storage.index;
|
||||
}
|
||||
if ( 0 <= material.storage.indexEmissive && material.storage.indexEmissive < graph.textures.size() ) {
|
||||
material.storage.indexEmissive = graph.textures[material.storage.indexEmissive].index;
|
||||
auto& texture = graph.textures[material.storage.indexEmissive];
|
||||
material.storage.indexEmissive = texture.storage.index;
|
||||
}
|
||||
if ( 0 <= material.storage.indexOcclusion && material.storage.indexOcclusion < graph.textures.size() ) {
|
||||
material.storage.indexOcclusion = graph.textures[material.storage.indexOcclusion].index;
|
||||
auto& texture = graph.textures[material.storage.indexOcclusion];
|
||||
material.storage.indexOcclusion = texture.storage.index;
|
||||
}
|
||||
if ( 0 <= material.storage.indexMetallicRoughness && material.storage.indexMetallicRoughness < graph.textures.size() ) {
|
||||
material.storage.indexMetallicRoughness = graph.textures[material.storage.indexMetallicRoughness].index;
|
||||
auto& texture = graph.textures[material.storage.indexMetallicRoughness];
|
||||
material.storage.indexMetallicRoughness = texture.storage.index;
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
// load node information/meshes
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
#include <uf/ext/bullet/bullet.h>
|
||||
#include <uf/utils/math/physics.h>
|
||||
|
||||
#define UF_VK_TESTING 1
|
||||
|
||||
namespace {
|
||||
void initializeGraphics( pod::Graph& graph, uf::Object& entity ) {
|
||||
auto& graphic = entity.getComponent<uf::Graphic>();
|
||||
@ -9,25 +11,35 @@ namespace {
|
||||
graphic.material.device = &uf::renderer::device;
|
||||
graphic.descriptor.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
|
||||
graphic.descriptor.cullMode = !(graph.mode & ext::gltf::LoadMode::INVERT) ? VK_CULL_MODE_BACK_BIT : VK_CULL_MODE_FRONT_BIT; // VK_CULL_MODE_NONE
|
||||
if ( graph.mode & ext::gltf::LoadMode::ATLAS ) {
|
||||
auto& atlas = *graph.atlas;
|
||||
auto& texture = graphic.material.textures.emplace_back();
|
||||
texture.loadFromImage( atlas.getAtlas() );
|
||||
} else {
|
||||
for ( auto& image : graph.images ) {
|
||||
auto& texture = graphic.material.textures.emplace_back();
|
||||
if ( graph.metadata["filter"].is<std::string>() ) {
|
||||
std::string filter = graph.metadata["filter"].as<std::string>();
|
||||
if ( filter == "NEAREST" ) {
|
||||
texture.sampler.descriptor.filter.min = VK_FILTER_NEAREST;
|
||||
texture.sampler.descriptor.filter.mag = VK_FILTER_NEAREST;
|
||||
} else if ( filter == "LINEAR" ) {
|
||||
texture.sampler.descriptor.filter.min = VK_FILTER_LINEAR;
|
||||
texture.sampler.descriptor.filter.mag = VK_FILTER_LINEAR;
|
||||
}
|
||||
}
|
||||
texture.loadFromImage( image );
|
||||
{
|
||||
#if UF_VK_TESTING
|
||||
for ( auto& texture : graph.textures ) {
|
||||
graphic.material.textures.emplace_back().aliasTexture(texture.texture);
|
||||
}
|
||||
#else
|
||||
if ( graph.mode & ext::gltf::LoadMode::ATLAS ) {
|
||||
auto& atlas = *graph.atlas;
|
||||
auto& texture = graphic.material.textures.emplace_back();
|
||||
texture.loadFromImage( atlas.getAtlas() );
|
||||
} else {
|
||||
graphic.material.textures.emplace_back().aliasTexture(uf::renderer::Texture2D::empty);
|
||||
for ( auto& image : graph.images ) {
|
||||
auto& texture = graphic.material.textures.emplace_back();
|
||||
|
||||
if ( graph.metadata["filter"].is<std::string>() ) {
|
||||
std::string filter = graph.metadata["filter"].as<std::string>();
|
||||
if ( filter == "NEAREST" ) {
|
||||
texture.sampler.descriptor.filter.min = VK_FILTER_NEAREST;
|
||||
texture.sampler.descriptor.filter.mag = VK_FILTER_NEAREST;
|
||||
} else if ( filter == "LINEAR" ) {
|
||||
texture.sampler.descriptor.filter.min = VK_FILTER_LINEAR;
|
||||
texture.sampler.descriptor.filter.mag = VK_FILTER_LINEAR;
|
||||
}
|
||||
}
|
||||
texture.loadFromImage( image );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
for ( auto& sampler : graph.samplers ) {
|
||||
graphic.material.samplers.emplace_back( sampler );
|
||||
}
|
||||
@ -104,6 +116,51 @@ void uf::graph::process( uf::Object& entity ) {
|
||||
for ( auto index : graph.root.children ) process( graph, index, entity );
|
||||
}
|
||||
void uf::graph::process( pod::Graph& graph ) {
|
||||
if ( graph.atlas ) {
|
||||
auto& texture = *graph.textures.emplace(graph.textures.begin());
|
||||
texture.name = "atlas";
|
||||
texture.storage.index = 0;
|
||||
texture.storage.sampler = 0;
|
||||
texture.storage.remap = 0;
|
||||
texture.storage.blend = 0;
|
||||
auto& image = *graph.images.emplace(graph.images.begin(), graph.atlas->getAtlas());
|
||||
}
|
||||
#if UF_VK_TESTING
|
||||
if ( graph.atlas ) {
|
||||
auto& image = graph.images[0];
|
||||
auto& texture = graph.textures[0].texture;
|
||||
|
||||
if ( graph.metadata["filter"].is<std::string>() ) {
|
||||
std::string filter = graph.metadata["filter"].as<std::string>();
|
||||
if ( filter == "NEAREST" ) {
|
||||
texture.sampler.descriptor.filter.min = VK_FILTER_NEAREST;
|
||||
texture.sampler.descriptor.filter.mag = VK_FILTER_NEAREST;
|
||||
} else if ( filter == "LINEAR" ) {
|
||||
texture.sampler.descriptor.filter.min = VK_FILTER_LINEAR;
|
||||
texture.sampler.descriptor.filter.mag = VK_FILTER_LINEAR;
|
||||
}
|
||||
}
|
||||
texture.loadFromImage( image );
|
||||
} else {
|
||||
for ( size_t i = 0; i < graph.textures.size() && i < graph.images.size(); ++i ) {
|
||||
auto& image = graph.images[i];
|
||||
auto& texture = graph.textures[i].texture;
|
||||
|
||||
if ( graph.metadata["filter"].is<std::string>() ) {
|
||||
std::string filter = graph.metadata["filter"].as<std::string>();
|
||||
if ( filter == "NEAREST" ) {
|
||||
texture.sampler.descriptor.filter.min = VK_FILTER_NEAREST;
|
||||
texture.sampler.descriptor.filter.mag = VK_FILTER_NEAREST;
|
||||
} else if ( filter == "LINEAR" ) {
|
||||
texture.sampler.descriptor.filter.min = VK_FILTER_LINEAR;
|
||||
texture.sampler.descriptor.filter.mag = VK_FILTER_LINEAR;
|
||||
}
|
||||
}
|
||||
texture.loadFromImage( image );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( !graph.root.entity ) graph.root.entity = new uf::Object;
|
||||
for ( auto index : graph.root.children ) process( graph, index, *graph.root.entity );
|
||||
|
||||
@ -122,8 +179,7 @@ void uf::graph::process( pod::Graph& graph ) {
|
||||
(void*) instances.data(),
|
||||
instances.size() * sizeof(pod::Matrix4f),
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
true
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
|
||||
);
|
||||
// Joints storage buffer
|
||||
if ( graph.mode & ext::gltf::LoadMode::SKINNED ) {
|
||||
@ -134,8 +190,7 @@ void uf::graph::process( pod::Graph& graph ) {
|
||||
(void*) skin.inverseBindMatrices.data(),
|
||||
skin.inverseBindMatrices.size() * sizeof(pod::Matrix4f),
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
true
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
|
||||
);
|
||||
break;
|
||||
}
|
||||
@ -144,7 +199,6 @@ void uf::graph::process( pod::Graph& graph ) {
|
||||
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;
|
||||
materials[i].indexMappedTarget = i;
|
||||
if ( graph.metadata["alpha cutoff"].is<float>() )
|
||||
materials[i].factorAlphaCutoff = graph.metadata["alpha cutoff"].as<float>();
|
||||
}
|
||||
@ -152,8 +206,19 @@ void uf::graph::process( pod::Graph& graph ) {
|
||||
(void*) materials.data(),
|
||||
materials.size() * sizeof(pod::Material::Storage),
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
true
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
|
||||
);
|
||||
// Texture storage buffer
|
||||
std::vector<pod::Texture::Storage> textures( graph.textures.size() );
|
||||
for ( size_t i = 0; i < graph.textures.size(); ++i ) {
|
||||
textures[i] = graph.textures[i].storage;
|
||||
textures[i].remap = i;
|
||||
}
|
||||
graph.root.textureBufferIndex = graphic.initializeBuffer(
|
||||
(void*) textures.data(),
|
||||
textures.size() * sizeof(pod::Texture::Storage),
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
|
||||
);
|
||||
}
|
||||
|
||||
@ -367,7 +432,6 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
|
||||
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;
|
||||
materials[i].indexMappedTarget = i;
|
||||
}
|
||||
if ( !ext::json::isNull( graph.metadata["tags"][node.name] ) ) {
|
||||
auto& info = graph.metadata["tags"][node.name];
|
||||
@ -382,6 +446,18 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
true
|
||||
);
|
||||
// Texture storage buffer
|
||||
std::vector<pod::Texture::Storage> textures( graph.textures.size() );
|
||||
for ( size_t i = 0; i < graph.textures.size(); ++i ) {
|
||||
textures[i] = graph.textures[i].storage;
|
||||
textures[i].remap = i;
|
||||
}
|
||||
graph.root.textureBufferIndex = graphic.initializeBuffer(
|
||||
(void*) textures.data(),
|
||||
textures.size() * sizeof(pod::Texture::Storage),
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -212,8 +212,8 @@ void ext::vulkan::Buffers::updateBuffer( void* data, VkDeviceSize length, size_t
|
||||
void ext::vulkan::Buffers::updateBuffer( void* data, VkDeviceSize length, Buffer& buffer, bool stage ) {
|
||||
// assert(buffer.allocationInfo.size == length);
|
||||
|
||||
if ( buffer.allocationInfo.size != length ) {
|
||||
if ( true ) {
|
||||
if ( length > buffer.allocationInfo.size ) {
|
||||
if ( !true ) {
|
||||
VK_VALIDATION_MESSAGE("Mismatch buffer update: Requesting " << buffer.allocationInfo.size << ", got " << length << "; Userdata might've been corrupted, please try validating with shader.validate() before updating buffer");
|
||||
} else {
|
||||
length = buffer.allocationInfo.size;
|
||||
|
||||
@ -450,16 +450,16 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const std::st
|
||||
size_t size = comp.get_declared_struct_size(base_type);
|
||||
if ( size <= 0 ) break;
|
||||
if ( size > device.properties.limits.maxUniformBufferRange ) {
|
||||
VK_VALIDATION_MESSAGE("Invalid uniform buffer length of " << size << " for shader " << filename);
|
||||
//VK_VALIDATION_MESSAGE("Invalid uniform buffer length of " << size << " for shader " << filename);
|
||||
size = device.properties.limits.maxUniformBufferRange;
|
||||
}
|
||||
size_t misalignment = size % device.properties.limits.minStorageBufferOffsetAlignment;
|
||||
if ( misalignment != 0 ) {
|
||||
VK_VALIDATION_MESSAGE("Invalid uniform buffer alignment of " << misalignment << " for shader " << filename << ", correcting...");
|
||||
//VK_VALIDATION_MESSAGE("Invalid uniform buffer alignment of " << misalignment << " for shader " << filename << ", correcting...");
|
||||
size += misalignment;
|
||||
}
|
||||
{
|
||||
VK_VALIDATION_MESSAGE("Uniform size of " << size << " for shader " << filename);
|
||||
//VK_VALIDATION_MESSAGE("Uniform size of " << size << " for shader " << filename);
|
||||
auto& uniform = uniforms.emplace_back();
|
||||
uniform.create( size );
|
||||
}
|
||||
@ -496,7 +496,7 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const std::st
|
||||
//for ( const auto& resource : res.key ) {
|
||||
#define LOOP_RESOURCES( key, type ) for ( size_t i = 0; i < res.key.size(); ++i ) {\
|
||||
const auto& resource = res.key[i];\
|
||||
VK_VALIDATION_MESSAGE("["<<filename<<"] Found resource: "#type " with binding: " << comp.get_decoration(resource.id, spv::DecorationBinding));\
|
||||
if ( false ) VK_VALIDATION_MESSAGE("["<<filename<<"] Found resource: "#type " with binding: " << comp.get_decoration(resource.id, spv::DecorationBinding));\
|
||||
parseResource( resource, type, i );\
|
||||
}
|
||||
LOOP_RESOURCES( sampled_images, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER );
|
||||
@ -519,16 +519,16 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const std::st
|
||||
if ( size <= 0 ) continue;
|
||||
// not a multiple of 4, for some reason
|
||||
if ( size % 4 != 0 ) {
|
||||
VK_VALIDATION_MESSAGE("Invalid push constant length of " << size << " for shader " << filename << ", must be multiple of 4, correcting...");
|
||||
//VK_VALIDATION_MESSAGE("Invalid push constant length of " << size << " for shader " << filename << ", must be multiple of 4, correcting...");
|
||||
size /= 4;
|
||||
++size;
|
||||
size *= 4;
|
||||
}
|
||||
if ( size > device.properties.limits.maxPushConstantsSize ) {
|
||||
VK_VALIDATION_MESSAGE("Invalid push constant length of " << size << " for shader " << filename);
|
||||
//VK_VALIDATION_MESSAGE("Invalid push constant length of " << size << " for shader " << filename);
|
||||
size = device.properties.limits.maxPushConstantsSize;
|
||||
}
|
||||
VK_VALIDATION_MESSAGE("Push constant size of " << size << " for shader " << filename);
|
||||
//VK_VALIDATION_MESSAGE("Push constant size of " << size << " for shader " << filename);
|
||||
{
|
||||
auto& pushConstant = pushConstants.emplace_back();
|
||||
pushConstant.create( size );
|
||||
@ -557,7 +557,7 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const std::st
|
||||
}
|
||||
if ( specializationSize > 0 ) {
|
||||
specializationConstants.create( specializationSize );
|
||||
VK_VALIDATION_MESSAGE("Specialization constants size of " << specializationSize << " for shader " << filename);
|
||||
//VK_VALIDATION_MESSAGE("Specialization constants size of " << specializationSize << " for shader " << filename);
|
||||
|
||||
uint8_t* s = (uint8_t*) (void*) specializationConstants;
|
||||
size_t offset = 0;
|
||||
@ -599,13 +599,13 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const std::st
|
||||
memcpy( &buffer[0], &v, sizeof(v) );
|
||||
} break;
|
||||
default: {
|
||||
VK_VALIDATION_MESSAGE("Unregistered specialization constant type at offset " << offset << " for shader " << filename );
|
||||
//VK_VALIDATION_MESSAGE("Unregistered specialization constant type at offset " << offset << " for shader " << filename );
|
||||
} break;
|
||||
}
|
||||
member["name"] = name;
|
||||
member["size"] = size;
|
||||
member["default"] = member["value"];
|
||||
VK_VALIDATION_MESSAGE("Specialization constant: " << member["type"].as<std::string>() << " " << name << " = " << member["value"].dump() << "; at offset " << offset << " for shader " << filename );
|
||||
//VK_VALIDATION_MESSAGE("Specialization constant: " << member["type"].as<std::string>() << " " << name << " = " << member["value"].dump() << "; at offset " << offset << " for shader " << filename );
|
||||
metadata["specializationConstants"].emplace_back(member);
|
||||
|
||||
memcpy( &s[offset], &buffer, size );
|
||||
@ -675,7 +675,7 @@ bool ext::vulkan::Shader::validate() {
|
||||
if ( it == uniforms.end() ) break;
|
||||
auto& uniform = *(it++);
|
||||
if ( uniform.data().len != buffer.allocationInfo.size ) {
|
||||
VK_VALIDATION_MESSAGE("Uniform size mismatch: Expected " << buffer.allocationInfo.size << ", got " << uniform.data().len << "; fixing...");
|
||||
//VK_VALIDATION_MESSAGE("Uniform size mismatch: Expected " << buffer.allocationInfo.size << ", got " << uniform.data().len << "; fixing...");
|
||||
uniform.destroy();
|
||||
uniform.create(buffer.allocationInfo.size);
|
||||
valid = false;
|
||||
@ -795,7 +795,7 @@ void ext::vulkan::Pipeline::initialize( Graphic& graphic, GraphicDescriptor& des
|
||||
for ( auto& pushConstant : shader.pushConstants ) {
|
||||
size_t len = pushConstant.data().len;
|
||||
if ( len <= 0 || len > device.properties.limits.maxPushConstantsSize ) {
|
||||
VK_VALIDATION_MESSAGE("Invalid push constant length of " << len << " for shader " << shader.filename);
|
||||
//VK_VALIDATION_MESSAGE("Invalid push constant length of " << len << " for shader " << shader.filename);
|
||||
// goto PIPELINE_INITIALIZATION_INVALID;
|
||||
len = device.properties.limits.maxPushConstantsSize;
|
||||
}
|
||||
@ -931,7 +931,8 @@ void ext::vulkan::Pipeline::initialize( Graphic& graphic, GraphicDescriptor& des
|
||||
1, 1, 0
|
||||
);
|
||||
VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
switch ( ext::vulkan::settings::msaa ) {
|
||||
// switch ( ext::vulkan::settings::msaa ) {
|
||||
switch ( renderTarget.samples ) {
|
||||
case 64: samples = VK_SAMPLE_COUNT_64_BIT; break;
|
||||
case 32: samples = VK_SAMPLE_COUNT_32_BIT; break;
|
||||
case 16: samples = VK_SAMPLE_COUNT_16_BIT; break;
|
||||
@ -992,7 +993,7 @@ void ext::vulkan::Pipeline::initialize( Graphic& graphic, GraphicDescriptor& des
|
||||
int32_t& v = ((int32_t*) s)[i];
|
||||
// failsafe, because for some reason things break
|
||||
if ( payload["validate"].as<bool>() && v == 0 ) {
|
||||
VK_VALIDATION_MESSAGE("Specialization constant of 0 for `" << payload.dump() << "` for shader `" << shader.filename << "`");
|
||||
//VK_VALIDATION_MESSAGE("Specialization constant of 0 for `" << payload.dump() << "` for shader `" << shader.filename << "`");
|
||||
v = payload["value"].is<int32_t>() ? payload["value"].as<int32_t>() : payload["default"].as<int32_t>();
|
||||
}
|
||||
payload["value"] = v;
|
||||
@ -1000,7 +1001,7 @@ void ext::vulkan::Pipeline::initialize( Graphic& graphic, GraphicDescriptor& des
|
||||
uint32_t& v = ((uint32_t*) s)[i];
|
||||
// failsafe, because for some reason things break
|
||||
if ( payload["validate"].as<bool>() && v == 0 ) {
|
||||
VK_VALIDATION_MESSAGE("Specialization constant of 0 for `" << payload.dump() << "` for shader `" << shader.filename << "`");
|
||||
//VK_VALIDATION_MESSAGE("Specialization constant of 0 for `" << payload.dump() << "` for shader `" << shader.filename << "`");
|
||||
v = payload["value"].is<uint32_t>() ? payload["value"].as<uint32_t>() : payload["default"].as<uint32_t>();
|
||||
}
|
||||
payload["value"] = v;
|
||||
@ -1008,13 +1009,13 @@ void ext::vulkan::Pipeline::initialize( Graphic& graphic, GraphicDescriptor& des
|
||||
float& v = ((float*) s)[i];
|
||||
// failsafe, because for some reason things break
|
||||
if ( payload["validate"].as<bool>() && v == 0 ) {
|
||||
VK_VALIDATION_MESSAGE("Specialization constant of 0 for `" << payload.dump() << "` for shader `" << shader.filename << "`");
|
||||
//VK_VALIDATION_MESSAGE("Specialization constant of 0 for `" << payload.dump() << "` for shader `" << shader.filename << "`");
|
||||
v = payload["value"].is<float>() ? payload["value"].as<float>() : payload["default"].as<float>();
|
||||
}
|
||||
payload["value"] = v;
|
||||
}
|
||||
}
|
||||
VK_VALIDATION_MESSAGE("Specialization constants for shader `" << shader.filename << "`: " << shader.metadata["specializationConstants"].dump(1, '\t'));
|
||||
//VK_VALIDATION_MESSAGE("Specialization constants for shader `" << shader.filename << "`: " << shader.metadata["specializationConstants"].dump(1, '\t'));
|
||||
|
||||
|
||||
{
|
||||
@ -1046,20 +1047,20 @@ void ext::vulkan::Pipeline::initialize( Graphic& graphic, GraphicDescriptor& des
|
||||
pipelineCreateInfo.subpass = descriptor.subpass;
|
||||
|
||||
VK_CHECK_RESULT(vkCreateGraphicsPipelines( device, device.pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipeline));
|
||||
VK_VALIDATION_MESSAGE("Created graphics pipeline");
|
||||
//VK_VALIDATION_MESSAGE("Created graphics pipeline");
|
||||
}
|
||||
|
||||
graphic.process = true;
|
||||
return;
|
||||
PIPELINE_INITIALIZATION_INVALID:
|
||||
graphic.process = false;
|
||||
VK_VALIDATION_MESSAGE("Pipeline initialization invalid, updating next tick...");
|
||||
//VK_VALIDATION_MESSAGE("Pipeline initialization invalid, updating next tick...");
|
||||
uf::thread::add( uf::thread::get("Main"), [&]() -> int {
|
||||
this->initialize( graphic, descriptor );
|
||||
return 0;}, true );
|
||||
return;
|
||||
}
|
||||
void ext::vulkan::Pipeline::record( Graphic& graphic, VkCommandBuffer commandBuffer, size_t pass ) {
|
||||
void ext::vulkan::Pipeline::record( Graphic& graphic, VkCommandBuffer commandBuffer, size_t pass, size_t draw ) {
|
||||
auto bindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||
for ( auto& shader : graphic.material.shaders ) {
|
||||
if ( shader.descriptor.stage == VK_SHADER_STAGE_COMPUTE_BIT ) {
|
||||
@ -1072,7 +1073,8 @@ void ext::vulkan::Pipeline::record( Graphic& graphic, VkCommandBuffer commandBuf
|
||||
if ( shader.descriptor.stage == VK_SHADER_STAGE_VERTEX_BIT ) {
|
||||
struct PushConstant {
|
||||
uint32_t pass;
|
||||
} pushConstant = { pass };
|
||||
uint32_t draw;
|
||||
} pushConstant = { pass, draw };
|
||||
vkCmdPushConstants( commandBuffer, pipelineLayout, shader.descriptor.stage, 0, sizeof(pushConstant), &pushConstant );
|
||||
}
|
||||
} else {
|
||||
@ -1253,18 +1255,18 @@ void ext::vulkan::Pipeline::update( Graphic& graphic, GraphicDescriptor& descrip
|
||||
for ( size_t i = 0; i < descriptor.descriptorCount; ++i ) {
|
||||
if ( descriptor.pBufferInfo ) {
|
||||
if ( descriptor.pBufferInfo[i].offset % device->properties.limits.minUniformBufferOffsetAlignment != 0 ) {
|
||||
VK_VALIDATION_MESSAGE("Invalid descriptor for buffer: " << descriptor.pBufferInfo[i].buffer << " (Offset: " << descriptor.pBufferInfo[i].offset << ", Range: " << descriptor.pBufferInfo[i].range << "), invalidating...");
|
||||
//VK_VALIDATION_MESSAGE("Invalid descriptor for buffer: " << descriptor.pBufferInfo[i].buffer << " (Offset: " << descriptor.pBufferInfo[i].offset << ", Range: " << descriptor.pBufferInfo[i].range << "), invalidating...");
|
||||
goto PIPELINE_UPDATE_INVALID;
|
||||
}
|
||||
}
|
||||
if ( descriptor.pImageInfo ) {
|
||||
if ( descriptor.pImageInfo[i].imageLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ) {
|
||||
VK_VALIDATION_MESSAGE("Image layout is VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, fixing to VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL");
|
||||
//VK_VALIDATION_MESSAGE("Image layout is VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, fixing to VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL");
|
||||
auto pointer = const_cast<VkDescriptorImageInfo*>(&descriptor.pImageInfo[i]);
|
||||
pointer->imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
|
||||
}
|
||||
if ( descriptor.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER && !descriptor.pImageInfo[i].sampler ) {
|
||||
VK_VALIDATION_MESSAGE("Image descriptor type is VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, yet lacks a sampler, adding default sampler...");
|
||||
//VK_VALIDATION_MESSAGE("Image descriptor type is VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, yet lacks a sampler, adding default sampler...");
|
||||
auto pointer = const_cast<VkDescriptorImageInfo*>(&descriptor.pImageInfo[i]);
|
||||
pointer->sampler = emptyTexture.sampler.sampler;
|
||||
}
|
||||
@ -1285,7 +1287,7 @@ void ext::vulkan::Pipeline::update( Graphic& graphic, GraphicDescriptor& descrip
|
||||
|
||||
PIPELINE_UPDATE_INVALID:
|
||||
graphic.process = false;
|
||||
VK_VALIDATION_MESSAGE("Pipeline update invalid, updating next tick...");
|
||||
//VK_VALIDATION_MESSAGE("Pipeline update invalid, updating next tick...");
|
||||
uf::thread::add( uf::thread::get("Main"), [&]() -> int {
|
||||
this->update( graphic, descriptor );
|
||||
return 0;}, true );
|
||||
@ -1427,19 +1429,19 @@ void ext::vulkan::Graphic::updatePipelines() {
|
||||
pair.second.update( *this );
|
||||
}
|
||||
}
|
||||
void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer, size_t pass ) {
|
||||
return this->record( commandBuffer, descriptor, pass );
|
||||
void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer, size_t pass, size_t draw ) {
|
||||
return this->record( commandBuffer, descriptor, pass, draw );
|
||||
}
|
||||
void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer, GraphicDescriptor& descriptor, size_t pass ) {
|
||||
void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer, GraphicDescriptor& descriptor, size_t pass, size_t draw ) {
|
||||
if ( !process ) return;
|
||||
if ( !this->hasPipeline( descriptor ) ) {
|
||||
VK_VALIDATION_MESSAGE(this << ": has no valid pipeline");
|
||||
//VK_VALIDATION_MESSAGE(this << ": has no valid pipeline");
|
||||
return;
|
||||
}
|
||||
|
||||
auto& pipeline = this->getPipeline( descriptor );
|
||||
if ( pipeline.descriptorSet == VK_NULL_HANDLE ) {
|
||||
VK_VALIDATION_MESSAGE(this << ": has no valid pipeline descriptor set");
|
||||
//VK_VALIDATION_MESSAGE(this << ": has no valid pipeline descriptor set");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1451,7 +1453,7 @@ void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer, GraphicDescrip
|
||||
}
|
||||
assert( vertexBuffer && indexBuffer );
|
||||
|
||||
pipeline.record(*this, commandBuffer, pass);
|
||||
pipeline.record(*this, commandBuffer, pass, draw);
|
||||
// Bind triangle vertex buffer (contains position and colors)
|
||||
VkDeviceSize offsets[1] = { 0 };
|
||||
vkCmdBindVertexBuffers(commandBuffer, 0, 1, &vertexBuffer->buffer, offsets);
|
||||
|
||||
@ -18,7 +18,8 @@ const std::string ext::vulkan::RenderMode::getType() const {
|
||||
return "";
|
||||
}
|
||||
const std::string ext::vulkan::RenderMode::getName() const {
|
||||
return this->metadata["name"].as<std::string>();
|
||||
auto& metadata = *const_cast<uf::Serializer*>(&this->metadata);
|
||||
return metadata["name"].as<std::string>();
|
||||
}
|
||||
ext::vulkan::RenderTarget& ext::vulkan::RenderMode::getRenderTarget( size_t i ) {
|
||||
return renderTarget;
|
||||
|
||||
@ -208,7 +208,7 @@ void ext::vulkan::BaseRenderMode::initialize( Device& device ) {
|
||||
std::array<VkAttachmentDescription, 2> attachments = {};
|
||||
|
||||
// Color attachment
|
||||
attachments[0].format = ext::vulkan::settings::formats::color; // Use the color format selected by the swapchain
|
||||
attachments[0].format = ext::vulkan::settings::formats::color; // Use the color format selected by the swapchain
|
||||
attachments[0].samples = VK_SAMPLE_COUNT_1_BIT; // We don't use multi sampling in this example
|
||||
attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; // Clear this attachment at the start of the render pass
|
||||
attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; // Keep it's contents after the render pass is finished (for displaying it)
|
||||
@ -218,7 +218,7 @@ void ext::vulkan::BaseRenderMode::initialize( Device& device ) {
|
||||
attachments[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; // Layout to which the attachment is transitioned when the render pass is finished
|
||||
// As we want to present the color buffer to the swapchain, we transition to PRESENT_KHR
|
||||
// Depth attachment
|
||||
attachments[1].format = ext::vulkan::settings::formats::depth; // A proper depth format is selected in the example base
|
||||
attachments[1].format = ext::vulkan::settings::formats::depth; // A proper depth format is selected in the example base
|
||||
attachments[1].samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; // Clear depth at start of first subpass
|
||||
attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; // We don't need depth after render pass has finished (DONT_CARE may result in better performance)
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
#include <uf/utils/math/transform.h>
|
||||
|
||||
#include <uf/ext/vulkan/graphic.h>
|
||||
#include <uf/ext/gltf/graph.h>
|
||||
|
||||
const std::string ext::vulkan::DeferredRenderMode::getType() const {
|
||||
return "Deferred";
|
||||
@ -37,20 +38,21 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
|
||||
ext::vulkan::RenderMode::initialize( device );
|
||||
{
|
||||
renderTarget.device = &device;
|
||||
// attach targets
|
||||
renderTarget.samples = ext::vulkan::settings::msaa;
|
||||
struct {
|
||||
size_t albedo, normals, position, depth, output, ping, pong;
|
||||
size_t id, normals, uvs, albedo, depth, output;
|
||||
} attachments;
|
||||
|
||||
attachments.albedo = renderTarget.attach( ext::vulkan::settings::formats::color, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // albedo
|
||||
attachments.normals = renderTarget.attach( ext::vulkan::settings::formats::normal, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // normals
|
||||
if ( !settings::experimental::deferredReconstructPosition )
|
||||
attachments.position = renderTarget.attach( ext::vulkan::settings::formats::position, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // position
|
||||
attachments.depth = renderTarget.attach( ext::vulkan::settings::formats::depth, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false ); // depth
|
||||
|
||||
// attachments.ping = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ); // albedo
|
||||
// attachments.pong = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ); // albedo
|
||||
|
||||
if ( ext::vulkan::settings::experimental::deferredMode == "deferredSampling" ) {
|
||||
attachments.id = renderTarget.attach( VK_FORMAT_R16G16_UINT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // ID
|
||||
attachments.normals = renderTarget.attach( VK_FORMAT_R16G16_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // normals
|
||||
attachments.uvs = renderTarget.attach( VK_FORMAT_R16G16_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // uvs
|
||||
attachments.depth = renderTarget.attach( ext::vulkan::settings::formats::depth, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false ); // depth
|
||||
} else {
|
||||
attachments.id = renderTarget.attach( VK_FORMAT_R16G16_UINT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // ID
|
||||
attachments.normals = renderTarget.attach( VK_FORMAT_R16G16_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // normals
|
||||
attachments.albedo = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // ID
|
||||
attachments.depth = renderTarget.attach( ext::vulkan::settings::formats::depth, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false ); // depth
|
||||
}
|
||||
// Attach swapchain's image as output
|
||||
if ( settings::experimental::deferredAliasOutputToSwapchain ) {
|
||||
attachments.output = renderTarget.attachments.size();
|
||||
@ -80,8 +82,145 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
|
||||
} else {
|
||||
attachments.output = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true ); // albedo
|
||||
}
|
||||
|
||||
if ( ext::vulkan::settings::experimental::deferredMode == "deferredSampling" ) {
|
||||
// First pass: fill the G-Buffer
|
||||
{
|
||||
renderTarget.addPass(
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
{ attachments.id, attachments.normals, attachments.uvs },
|
||||
{},
|
||||
attachments.depth
|
||||
);
|
||||
}
|
||||
// Second pass: write to output
|
||||
{
|
||||
renderTarget.addPass(
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
|
||||
{ attachments.output },
|
||||
{ attachments.id, attachments.normals, attachments.uvs, attachments.depth },
|
||||
attachments.depth
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// First pass: fill the G-Buffer
|
||||
{
|
||||
renderTarget.addPass(
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
{ attachments.id, attachments.normals, attachments.albedo },
|
||||
{},
|
||||
attachments.depth
|
||||
);
|
||||
}
|
||||
// Second pass: write to output
|
||||
{
|
||||
renderTarget.addPass(
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
|
||||
{ attachments.output },
|
||||
{ attachments.id, attachments.normals, attachments.albedo, attachments.depth },
|
||||
attachments.depth
|
||||
);
|
||||
}
|
||||
}
|
||||
/*
|
||||
#if UF_VK_TESTING
|
||||
struct {
|
||||
size_t normals, uvs, id, depth, output;
|
||||
} attachments;
|
||||
attachments.normals = renderTarget.attach( VK_FORMAT_R16G16_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // normals
|
||||
attachments.uvs = renderTarget.attach( VK_FORMAT_R16G16_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // uvs
|
||||
attachments.id = renderTarget.attach( VK_FORMAT_R16G16_UINT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // ID
|
||||
attachments.depth = renderTarget.attach( ext::vulkan::settings::formats::depth, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false ); // depth
|
||||
#else
|
||||
// attach targets
|
||||
struct {
|
||||
size_t normals, albedo, depth, output;
|
||||
} attachments;
|
||||
//VK_FORMAT_R16G16B16A16_SFLOAT
|
||||
attachments.normals = renderTarget.attach( VK_FORMAT_R16G16_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // normals
|
||||
attachments.albedo = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // ID
|
||||
attachments.depth = renderTarget.attach( ext::vulkan::settings::formats::depth, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false ); // depth
|
||||
#endif
|
||||
// Attach swapchain's image as output
|
||||
if ( settings::experimental::deferredAliasOutputToSwapchain ) {
|
||||
attachments.output = renderTarget.attachments.size();
|
||||
RenderTarget::Attachment swapchainAttachment;
|
||||
swapchainAttachment.format = ext::vulkan::settings::formats::color; //device.formats.color;
|
||||
swapchainAttachment.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
swapchainAttachment.layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||
swapchainAttachment.aliased = true;
|
||||
{
|
||||
VkBool32 blendEnabled = VK_TRUE;
|
||||
VkColorComponentFlags writeMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
|
||||
VkPipelineColorBlendAttachmentState blendAttachmentState = ext::vulkan::initializers::pipelineColorBlendAttachmentState(
|
||||
writeMask,
|
||||
blendEnabled
|
||||
);
|
||||
if ( blendEnabled == VK_TRUE ) {
|
||||
blendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
|
||||
blendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||
blendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD;
|
||||
blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
|
||||
blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
|
||||
blendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD;
|
||||
}
|
||||
swapchainAttachment.blendState = blendAttachmentState;
|
||||
}
|
||||
renderTarget.attachments.push_back(swapchainAttachment);
|
||||
} else {
|
||||
attachments.output = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true ); // albedo
|
||||
}
|
||||
#if UF_VK_TESTING
|
||||
// First pass: fill the G-Buffer
|
||||
{
|
||||
renderTarget.addPass(
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
{ attachments.normals, attachments.uvs, attachments.id },
|
||||
{},
|
||||
attachments.depth
|
||||
);
|
||||
}
|
||||
// Second pass: write to output
|
||||
{
|
||||
renderTarget.addPass(
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
|
||||
{ attachments.output },
|
||||
{ attachments.normals, attachments.uvs, attachments.id, attachments.depth },
|
||||
attachments.depth
|
||||
);
|
||||
}
|
||||
#else
|
||||
// First pass: fill the G-Buffer
|
||||
{
|
||||
renderTarget.addPass(
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
{ attachments.normals, attachments.albedo },
|
||||
{},
|
||||
attachments.depth
|
||||
);
|
||||
}
|
||||
// Second pass: write to output
|
||||
{
|
||||
renderTarget.addPass(
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
|
||||
{ attachments.output },
|
||||
{ attachments.normals, attachments.albedo, attachments.depth },
|
||||
attachments.depth
|
||||
);
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
/*
|
||||
struct {
|
||||
size_t albedo, normals, position, depth, output, ping, pong;
|
||||
} attachments;
|
||||
attachments.albedo = renderTarget.attach( ext::vulkan::settings::formats::color, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // albedo
|
||||
attachments.normals = renderTarget.attach( ext::vulkan::settings::formats::normal, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // normals
|
||||
if ( !settings::experimental::deferredReconstructPosition )
|
||||
attachments.position = renderTarget.attach( ext::vulkan::settings::formats::position, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // position
|
||||
attachments.depth = renderTarget.attach( ext::vulkan::settings::formats::depth, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false ); // depth
|
||||
|
||||
// attachments.ping = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ); // albedo
|
||||
// attachments.pong = renderTarget.attach( VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ); // albedo
|
||||
if ( settings::experimental::deferredReconstructPosition ) {
|
||||
renderTarget.addPass(
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
@ -113,6 +252,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
|
||||
attachments.depth
|
||||
);
|
||||
}
|
||||
*/
|
||||
}
|
||||
renderTarget.initialize( device );
|
||||
|
||||
@ -133,56 +273,54 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
|
||||
|
||||
blitter.initialize( this->getName() );
|
||||
blitter.initializeGeometry( mesh );
|
||||
if ( settings::experimental::deferredReconstructPosition ) {
|
||||
blitter.material.initializeShaders({
|
||||
{"./data/shaders/display.subpass.vert.spv", VK_SHADER_STAGE_VERTEX_BIT},
|
||||
{"./data/shaders/display.subpass.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT}
|
||||
});
|
||||
} else {
|
||||
blitter.material.initializeShaders({
|
||||
{"./data/shaders/display.subpass.vert.spv", VK_SHADER_STAGE_VERTEX_BIT},
|
||||
{"./data/shaders/display.subpass.stereo.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT}
|
||||
});
|
||||
}
|
||||
|
||||
blitter.material.initializeShaders({
|
||||
{"./data/shaders/display.subpass.vert.spv", VK_SHADER_STAGE_VERTEX_BIT},
|
||||
{"./data/shaders/display.subpass.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT}
|
||||
});
|
||||
{
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto& metadata = scene.getComponent<uf::Serializer>();
|
||||
|
||||
auto& shader = blitter.material.shaders.back();
|
||||
struct SpecializationConstant {
|
||||
uint32_t maxLights = 16;
|
||||
uint32_t maxLights = 256;
|
||||
uint32_t maxTextures = 256;
|
||||
};
|
||||
auto& specializationConstants = shader.specializationConstants.get<SpecializationConstant>();
|
||||
|
||||
auto& metadata = scene.getComponent<uf::Serializer>();
|
||||
specializationConstants.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.maxLights;
|
||||
}
|
||||
|
||||
/*
|
||||
struct Light {
|
||||
alignas(16) pod::Vector4f position;
|
||||
alignas(16) pod::Vector4f color;
|
||||
std::vector<pod::Material::Storage> materials(specializationConstants.maxTextures);
|
||||
std::vector<pod::Texture::Storage> textures(specializationConstants.maxTextures);
|
||||
std::vector<pod::DrawCall> drawCalls(specializationConstants.maxTextures);
|
||||
|
||||
alignas(4) int32_t type = 0;
|
||||
alignas(4) float depthBias = 0;
|
||||
alignas(4) float padding1 = 0;
|
||||
alignas(4) float padding2 = 0;
|
||||
|
||||
alignas(16) pod::Matrix4f view;
|
||||
alignas(16) pod::Matrix4f projection;
|
||||
};
|
||||
std::vector<Light> lights;
|
||||
lights.resize(specializationConstants.maxLights);
|
||||
|
||||
blitter.initializeBuffer(
|
||||
(void*) lights.data(),
|
||||
lights.size() * sizeof(Light),
|
||||
for ( auto& material : materials ) material.colorBase = {0,0,0,0};
|
||||
this->metadata["materialBufferIndex"] = blitter.initializeBuffer(
|
||||
(void*) materials.data(),
|
||||
materials.size() * sizeof(pod::Material::Storage),
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
true
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
|
||||
);
|
||||
|
||||
this->metadata["textureBufferIndex"] = blitter.initializeBuffer(
|
||||
(void*) textures.data(),
|
||||
textures.size() * sizeof(pod::Texture::Storage),
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
|
||||
);
|
||||
|
||||
this->metadata["drawCallBufferIndex"] = blitter.initializeBuffer(
|
||||
(void*) drawCalls.data(),
|
||||
drawCalls.size() * sizeof(pod::DrawCall),
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
|
||||
);
|
||||
*/
|
||||
}
|
||||
blitter.initializePipeline();
|
||||
}
|
||||
@ -286,11 +424,12 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const std::vector<ex
|
||||
vkCmdSetViewport(commands[i], 0, 1, &viewport);
|
||||
vkCmdSetScissor(commands[i], 0, 1, &scissor);
|
||||
// render to geometry buffers
|
||||
size_t currentDraw = 0;
|
||||
for ( auto graphic : graphics ) {
|
||||
// only draw graphics that are assigned to this type of render mode
|
||||
if ( graphic->descriptor.renderMode != this->getName() ) continue;
|
||||
ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(graphic->descriptor);
|
||||
graphic->record( commands[i], descriptor, currentPass );
|
||||
graphic->record( commands[i], descriptor, currentPass, currentDraw++ );
|
||||
}
|
||||
// blit any RT's that request this subpass
|
||||
{
|
||||
|
||||
@ -6,7 +6,8 @@
|
||||
#include <uf/ext/vulkan/graphic.h>
|
||||
|
||||
const std::string ext::vulkan::RenderTargetRenderMode::getTarget() const {
|
||||
return this->metadata["target"].as<std::string>();
|
||||
auto& metadata = *const_cast<uf::Serializer*>(&this->metadata);
|
||||
return metadata["target"].as<std::string>();
|
||||
}
|
||||
void ext::vulkan::RenderTargetRenderMode::setTarget( const std::string& target ) {
|
||||
this->metadata["target"] = target;
|
||||
@ -56,6 +57,7 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
|
||||
attachments.depth
|
||||
);
|
||||
} else {
|
||||
#if 1
|
||||
struct {
|
||||
size_t albedo, normals, position, depth;
|
||||
} attachments;
|
||||
@ -82,6 +84,35 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
|
||||
attachments.depth
|
||||
);
|
||||
}
|
||||
#else
|
||||
struct {
|
||||
size_t normals, uvs, id, depth;
|
||||
} attachments;
|
||||
//VK_FORMAT_R16G16B16A16_SFLOAT
|
||||
attachments.normals = renderTarget.attach( VK_FORMAT_R16G16_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // normals
|
||||
attachments.uvs = renderTarget.attach( VK_FORMAT_R16G16_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // uvs
|
||||
attachments.id = renderTarget.attach( VK_FORMAT_R16G16_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // ID
|
||||
attachments.depth = renderTarget.attach( ext::vulkan::settings::formats::depth, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false ); // depth
|
||||
|
||||
// First pass: fill the G-Buffer
|
||||
{
|
||||
renderTarget.addPass(
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
{ attachments.normals, attachments.uvs, attachments.id },
|
||||
{},
|
||||
attachments.depth
|
||||
);
|
||||
}
|
||||
// Second pass: write to output
|
||||
{
|
||||
renderTarget.addPass(
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
|
||||
{ attachments.output },
|
||||
{ attachments.normals, attachments.uvs, attachments.id, attachments.depth },
|
||||
attachments.depth
|
||||
);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -277,10 +308,11 @@ void ext::vulkan::RenderTargetRenderMode::createCommandBuffers( const std::vecto
|
||||
vkCmdSetViewport(commands[i], 0, 1, &viewport);
|
||||
vkCmdSetScissor(commands[i], 0, 1, &scissor);
|
||||
for ( size_t currentPass = 0; currentPass < subpasses; ++currentPass ) {
|
||||
size_t currentDraw = 0;
|
||||
for ( auto graphic : graphics ) {
|
||||
if ( graphic->descriptor.renderMode != this->getTarget() ) continue;
|
||||
ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(graphic->descriptor, currentPass);
|
||||
graphic->record( commands[i], descriptor, currentPass );
|
||||
graphic->record( commands[i], descriptor, currentPass, currentDraw++ );
|
||||
}
|
||||
if ( currentPass + 1 < subpasses ) vkCmdNextSubpass(commands[i], VK_SUBPASS_CONTENTS_INLINE);
|
||||
}
|
||||
|
||||
@ -250,7 +250,7 @@ void ext::vulkan::StereoscopicDeferredRenderMode::createCommandBuffers( const st
|
||||
{ &renderTargets.left, &renderBlitters.left },
|
||||
{ &renderTargets.right, &renderBlitters.right },
|
||||
};
|
||||
for ( ext::openvr::renderPass = 0; ext::openvr::renderPass < eyes.size(); ++ext::openvr::renderPass ) {
|
||||
for ( size_t eyePass = 0; eyePass < eyes.size(); ++eyePass ) {
|
||||
auto& renderTarget = *eyes[ext::openvr::renderPass].renderTarget;
|
||||
auto& blitter = *eyes[ext::openvr::renderPass].blitter;
|
||||
// Fill GBuffer
|
||||
@ -315,7 +315,7 @@ void ext::vulkan::StereoscopicDeferredRenderMode::createCommandBuffers( const st
|
||||
// only draw graphics that are assigned to this type of render mode
|
||||
if ( graphic->descriptor.renderMode != this->getName() ) continue;
|
||||
ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(graphic->descriptor);
|
||||
graphic->record( commands[i], descriptor, currentPass );
|
||||
graphic->record( commands[i], descriptor, eyePass );
|
||||
}
|
||||
// render gui layer
|
||||
{
|
||||
|
||||
@ -3,10 +3,6 @@
|
||||
#include <uf/ext/vulkan/initializers.h>
|
||||
#include <uf/utils/window/window.h>
|
||||
|
||||
namespace {
|
||||
bool USEVR = false;
|
||||
}
|
||||
|
||||
void ext::vulkan::RenderTarget::addPass( VkPipelineStageFlags stage, VkAccessFlags access, const std::vector<size_t>& colors, const std::vector<size_t>& inputs, size_t depth ) {
|
||||
Subpass pass;
|
||||
pass.stage = stage;
|
||||
@ -24,6 +20,19 @@ size_t ext::vulkan::RenderTarget::attach( VkFormat format, VkImageUsageFlags usa
|
||||
if ( !attachment ) {
|
||||
attachments.resize(attachments.size()+1);
|
||||
attachment = &attachments.back();
|
||||
// no MSAA for depth
|
||||
if ( false && usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ) {
|
||||
} else {
|
||||
switch ( samples ) {
|
||||
case 64: attachment->samples = VK_SAMPLE_COUNT_64_BIT; break;
|
||||
case 32: attachment->samples = VK_SAMPLE_COUNT_32_BIT; break;
|
||||
case 16: attachment->samples = VK_SAMPLE_COUNT_16_BIT; break;
|
||||
case 8: attachment->samples = VK_SAMPLE_COUNT_8_BIT; break;
|
||||
case 4: attachment->samples = VK_SAMPLE_COUNT_4_BIT; break;
|
||||
case 2: attachment->samples = VK_SAMPLE_COUNT_2_BIT; break;
|
||||
default: attachment->samples = VK_SAMPLE_COUNT_1_BIT; break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ( attachment->view ) {
|
||||
vkDestroyImageView(*device, attachment->view, nullptr);
|
||||
@ -47,22 +56,9 @@ size_t ext::vulkan::RenderTarget::attach( VkFormat format, VkImageUsageFlags usa
|
||||
} else {
|
||||
aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
}
|
||||
|
||||
VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
switch ( ext::vulkan::settings::msaa ) {
|
||||
case 64: samples = VK_SAMPLE_COUNT_64_BIT; break;
|
||||
case 32: samples = VK_SAMPLE_COUNT_32_BIT; break;
|
||||
case 16: samples = VK_SAMPLE_COUNT_16_BIT; break;
|
||||
case 8: samples = VK_SAMPLE_COUNT_8_BIT; break;
|
||||
case 4: samples = VK_SAMPLE_COUNT_4_BIT; break;
|
||||
case 2: samples = VK_SAMPLE_COUNT_2_BIT; break;
|
||||
default: samples = VK_SAMPLE_COUNT_1_BIT; break;
|
||||
}
|
||||
|
||||
attachment->layout = layout;
|
||||
attachment->format = format;
|
||||
attachment->usage = usage;
|
||||
attachment->samples = samples;
|
||||
|
||||
VkImageCreateInfo imageCreateInfo = {};
|
||||
imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||
@ -71,7 +67,7 @@ size_t ext::vulkan::RenderTarget::attach( VkFormat format, VkImageUsageFlags usa
|
||||
imageCreateInfo.extent = { width, height, 1 };
|
||||
imageCreateInfo.mipLevels = 1;
|
||||
imageCreateInfo.arrayLayers = this->multiviews;
|
||||
imageCreateInfo.samples = samples;
|
||||
imageCreateInfo.samples = attachment->samples;
|
||||
imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
imageCreateInfo.usage = usage;
|
||||
imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
|
||||
@ -29,6 +29,7 @@ bool ext::vulkan::settings::experimental::rebuildOnTickBegin = false;
|
||||
bool ext::vulkan::settings::experimental::waitOnRenderEnd = false;
|
||||
bool ext::vulkan::settings::experimental::individualPipelines = false;
|
||||
bool ext::vulkan::settings::experimental::multithreadedCommandRecording = false;
|
||||
std::string ext::vulkan::settings::experimental::deferredMode = "";
|
||||
bool ext::vulkan::settings::experimental::deferredReconstructPosition = false;
|
||||
bool ext::vulkan::settings::experimental::deferredAliasOutputToSwapchain = true;
|
||||
bool ext::vulkan::settings::experimental::multiview = true;
|
||||
|
||||
@ -117,12 +117,10 @@ pod::Vector2f uf::Atlas::mapUv( const pod::Vector2f& uv, size_t index ) {
|
||||
|
||||
pod::Vector2ui coord = { uv.x * dim.x + it.coord.x, uv.y * dim.y + it.coord.y };
|
||||
nuv = { (float) coord.x / (float) size.x, (float) coord.y / (float) size.y };
|
||||
nuv.y = 1.0f - nuv.y;
|
||||
// nuv.y = 1.0f - nuv.y;
|
||||
return nuv;
|
||||
}
|
||||
{
|
||||
// std::cout << "Could not find requested index of " << index << std::endl;
|
||||
}
|
||||
return uv;
|
||||
}
|
||||
pod::Vector3f uf::Atlas::mapUv( const pod::Vector3f& uv ) {
|
||||
|
||||
@ -325,9 +325,11 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
|
||||
} lights;
|
||||
};
|
||||
struct SpecializationConstant {
|
||||
uint32_t maxLights = 32;
|
||||
uint32_t maxLights = 256;
|
||||
uint32_t maxTextures = 256;
|
||||
} specializationConstants;
|
||||
specializationConstants.maxLights = metadata["system"]["config"]["engine"]["scenes"]["lights"]["max"].as<size_t>();
|
||||
specializationConstants.maxTextures = metadata["system"]["config"]["engine"]["scenes"]["textures"]["max"].as<size_t>();
|
||||
|
||||
struct LightInfo {
|
||||
uf::Entity* entity = NULL;
|
||||
@ -336,11 +338,16 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
|
||||
bool shadows = false;
|
||||
};
|
||||
std::vector<LightInfo> entities;
|
||||
std::vector<pod::Graph*> graphs;
|
||||
// std::vector<uf::Entity*> graphs;
|
||||
|
||||
this->process([&]( uf::Entity* entity ) { if ( !entity ) return;
|
||||
auto& metadata = entity->getComponent<uf::Serializer>();
|
||||
if ( entity == &controller ) return;
|
||||
if ( entity == this ) return;
|
||||
if ( entity->hasComponent<pod::Graph>() ) graphs.emplace_back(&entity->getComponent<pod::Graph>());
|
||||
// if ( entity->hasComponent<pod::Graph>() && entity->hasComponent<uf::Graphic>() ) graphs.emplace_back(entity);
|
||||
//
|
||||
if ( entity->getName() != "Light" && !ext::json::isObject( metadata["light"] ) ) return;
|
||||
//
|
||||
if ( entity->hasComponent<uf::renderer::RenderTargetRenderMode>() ) {
|
||||
@ -443,7 +450,66 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
|
||||
graphic.material.textures.clear();
|
||||
// add noise texture
|
||||
graphic.material.textures.emplace_back().aliasTexture(this->getComponent<uf::renderer::Texture2D>());
|
||||
// add materials
|
||||
{
|
||||
size_t attachedTextures = 0;
|
||||
std::vector<pod::Material::Storage> materials;
|
||||
materials.reserve(specializationConstants.maxTextures);
|
||||
|
||||
std::vector<pod::Texture::Storage> textures;
|
||||
textures.reserve(specializationConstants.maxTextures);
|
||||
|
||||
std::vector<pod::DrawCall> drawCalls;
|
||||
drawCalls.reserve(specializationConstants.maxTextures);
|
||||
|
||||
materials.emplace_back().colorBase = {0,0,0,0};
|
||||
|
||||
for ( auto* entity : graphs ) {
|
||||
auto& graph = *entity;
|
||||
|
||||
size_t startMaterial = materials.size() - 1;
|
||||
size_t startTexture = textures.size();
|
||||
|
||||
{
|
||||
auto& drawCall = drawCalls.emplace_back();
|
||||
drawCall.materialIndex = startMaterial;
|
||||
drawCall.textureIndex = startTexture;
|
||||
|
||||
drawCall.materials = graph.materials.size() - 1;
|
||||
drawCall.textures = graph.textures.size();
|
||||
}
|
||||
for ( auto& material : graph.materials ) {
|
||||
auto& m = materials.emplace_back( material.storage );
|
||||
// m.indexAlbedo += startMaterial;
|
||||
// m.indexNormal += startMaterial;
|
||||
// m.indexEmissive += startMaterial;
|
||||
// m.indexOcclusion += startMaterial;
|
||||
// m.indexMetallicRoughness += startMaterial;
|
||||
}
|
||||
for ( auto& texture : graph.textures ) {
|
||||
auto& t = textures.emplace_back( texture.storage );
|
||||
// t.index += startTexture;
|
||||
// t.remap += startTexture;
|
||||
}
|
||||
for ( auto& texture : graph.textures ) {
|
||||
if ( !texture.texture.device ) continue;
|
||||
++attachedTextures;
|
||||
graphic.material.textures.emplace_back().aliasTexture(texture.texture);
|
||||
if ( graph.atlas ) break;
|
||||
}
|
||||
}
|
||||
while ( attachedTextures++ < specializationConstants.maxTextures ) {
|
||||
graphic.material.textures.emplace_back().aliasTexture(uf::renderer::Texture2D::empty);
|
||||
}
|
||||
|
||||
size_t materialBufferIndex = renderMode.metadata["materialBufferIndex"].as<size_t>();
|
||||
size_t textureBufferIndex = renderMode.metadata["textureBufferIndex"].as<size_t>();
|
||||
size_t drawCallBufferIndex = renderMode.metadata["drawCallBufferIndex"].as<size_t>();
|
||||
graphic.updateBuffer( (void*) materials.data(), materials.size() * sizeof(pod::Material::Storage), materialBufferIndex, false );
|
||||
graphic.updateBuffer( (void*) textures.data(), textures.size() * sizeof(pod::Texture::Storage), textureBufferIndex, false );
|
||||
graphic.updateBuffer( (void*) drawCalls.data(), drawCalls.size() * sizeof(pod::DrawCall), drawCallBufferIndex, false );
|
||||
}
|
||||
// add lighting
|
||||
int updateThreshold = metadata["system"]["config"]["engine"]["scenes"]["lights"]["update threshold"].as<size_t>();
|
||||
std::vector<UniformDescriptor::Light> lightPool;
|
||||
lightPool.reserve( entities.size() );
|
||||
@ -494,13 +560,18 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
|
||||
}
|
||||
} else {
|
||||
lightPool.emplace_back(light);
|
||||
auto& texture = graphic.material.textures.emplace_back();
|
||||
texture.aliasTexture(uf::renderer::Texture2D::empty);
|
||||
graphic.material.textures.emplace_back().aliasTexture(uf::renderer::Texture2D::empty);
|
||||
}
|
||||
}
|
||||
|
||||
for ( size_t i = 0; i < specializationConstants.maxLights && i < lightPool.size(); ++i )
|
||||
lights[i] = lightPool[i];
|
||||
{
|
||||
size_t lightsAdded = 0;
|
||||
for ( size_t i = 0; i < specializationConstants.maxLights && i < lightPool.size(); ++i, ++lightsAdded ) lights[i] = lightPool[i];
|
||||
// std::cout << "Shadowmaps added: " << lightsAdded << "\t";
|
||||
while ( lightsAdded++ < specializationConstants.maxLights ) {
|
||||
graphic.material.textures.emplace_back().aliasTexture(uf::renderer::Texture2D::empty);
|
||||
}
|
||||
// std::cout << "Total shadowmaps: " << lightsAdded << std::endl;
|
||||
}
|
||||
|
||||
{
|
||||
size_t i = 0;
|
||||
|
||||
@ -326,6 +326,7 @@ void EXT_API ext::initialize() {
|
||||
uf::renderer::settings::experimental::waitOnRenderEnd = ::config["engine"]["ext"]["vulkan"]["experimental"]["wait on render end"].as<bool>();
|
||||
uf::renderer::settings::experimental::individualPipelines = ::config["engine"]["ext"]["vulkan"]["experimental"]["individual pipelines"].as<bool>();
|
||||
uf::renderer::settings::experimental::multithreadedCommandRecording = ::config["engine"]["ext"]["vulkan"]["experimental"]["multithreaded command recording"].as<bool>();
|
||||
uf::renderer::settings::experimental::deferredMode = ::config["engine"]["ext"]["vulkan"]["experimental"]["deferred mode"].as<std::string>();
|
||||
uf::renderer::settings::experimental::deferredReconstructPosition = ::config["engine"]["ext"]["vulkan"]["experimental"]["deferred reconstruct position"].as<bool>();
|
||||
uf::renderer::settings::experimental::deferredAliasOutputToSwapchain = ::config["engine"]["ext"]["vulkan"]["experimental"]["deferred alias output to swapchain"].as<bool>();
|
||||
uf::renderer::settings::experimental::hdr = ::config["engine"]["ext"]["vulkan"]["experimental"]["hdr"].as<bool>();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user