SSAO, performance sucks and it flickers so tweaking is needed, also more material support
This commit is contained in:
parent
5b231d6920
commit
577836a03f
39 changed files with 889 additions and 74 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -84,3 +84,6 @@ fabric.properties
|
||||||
/.idea/
|
/.idea/
|
||||||
/.gradle/buildOutputCleanup/
|
/.gradle/buildOutputCleanup/
|
||||||
/.gradle/
|
/.gradle/
|
||||||
|
/resources/models/bistrohd/
|
||||||
|
/resources/models/Cafe/
|
||||||
|
/resources/models/Forest/
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
const int MAX_TEXTURES = 128;
|
const int MAX_TEXTURES = 512;
|
||||||
const float GAMMA_CONST = 0.4545;
|
const float GAMMA_CONST = 0.4545;
|
||||||
layout(location = 0) in vec2 inUV;
|
layout(location = 0) in vec2 inUV;
|
||||||
|
|
||||||
|
|
@ -16,9 +16,12 @@ vec4 gamma(vec4 color){
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
if (push_constants.textureIndex >= MAX_TEXTURES){
|
||||||
|
outColor = vec4(0.0,0.0,1.0,1.0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
vec4 tex = texture(spriteTextures[push_constants.textureIndex], inUV);
|
vec4 tex = texture(spriteTextures[push_constants.textureIndex], inUV);
|
||||||
outColor = gamma(tex);
|
outColor = gamma(tex);
|
||||||
|
|
||||||
if (outColor.a <= 0.09) {
|
if (outColor.a <= 0.09) {
|
||||||
discard;
|
discard;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ layout(set = 0, binding = 3) uniform sampler2D pbrSampler;
|
||||||
layout(set = 0, binding = 4) uniform sampler2D emissiveSampler;
|
layout(set = 0, binding = 4) uniform sampler2D emissiveSampler;
|
||||||
layout(set = 0, binding = 5) uniform sampler2D TranslucencySampler;
|
layout(set = 0, binding = 5) uniform sampler2D TranslucencySampler;
|
||||||
layout(set = 0, binding = 6) uniform sampler2D OpacitySampler;
|
layout(set = 0, binding = 6) uniform sampler2D OpacitySampler;
|
||||||
|
layout(set = 0, binding = 7) uniform sampler2D ssaoBlur;
|
||||||
|
|
||||||
layout(scalar, set = 1, binding = 0) readonly buffer Lights {
|
layout(scalar, set = 1, binding = 0) readonly buffer Lights {
|
||||||
Light lights[];
|
Light lights[];
|
||||||
|
|
@ -134,6 +135,10 @@ void main() {
|
||||||
vec3 translucency = texture(TranslucencySampler, inTextCoord).rgb;
|
vec3 translucency = texture(TranslucencySampler, inTextCoord).rgb;
|
||||||
float emissiveness = emissive.r;
|
float emissiveness = emissive.r;
|
||||||
|
|
||||||
|
// outFragColor = vec4(vec3(texture(ssaoBlur, inTextCoord).r), 1);
|
||||||
|
// return;
|
||||||
|
|
||||||
|
float ssao = texture(ssaoBlur, inTextCoord).r;
|
||||||
|
|
||||||
float roughness = pbr.g;
|
float roughness = pbr.g;
|
||||||
float metallic = pbr.b;
|
float metallic = pbr.b;
|
||||||
|
|
@ -153,8 +158,10 @@ void main() {
|
||||||
Lo += calculatePointLight(light, worldPos, V, N, F0, albedo, metallic, roughness);
|
Lo += calculatePointLight(light, worldPos, V, N, F0, albedo, metallic, roughness);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vec3 ambient = sceneInfo.ambientLightColor * albedo * sceneInfo.ambientLightIntensity;
|
vec3 ambient = sceneInfo.ambientLightColor * albedo * sceneInfo.ambientLightIntensity * vec3(ssao,ssao,ssao);;
|
||||||
outFragColor = vec4(Lo + ambient + vec3(emissiveness), 1.0f);
|
if(emissive.x > 0 || emissive.y > 0 || emissive.z > 0) ambient = emissive;
|
||||||
|
outFragColor = vec4(Lo + ambient, 1.0f);
|
||||||
|
outFragColor = vec4(outFragColor.xyz/2 + (outFragColor.xyz/2) * vec3(ssao,ssao,ssao),1);
|
||||||
|
|
||||||
// outFragColor = vec4(color, 1.0f);
|
// outFragColor = vec4(color, 1.0f);
|
||||||
if (length(normal) < 0.001) {
|
if (length(normal) < 0.001) {
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
|
|
@ -30,7 +30,8 @@ layout(set = 0, binding = 3) uniform sampler2D pbrSampler;
|
||||||
layout(set = 0, binding = 4) uniform sampler2D emissiveSampler;
|
layout(set = 0, binding = 4) uniform sampler2D emissiveSampler;
|
||||||
layout(set = 0, binding = 5) uniform sampler2D TranslucencySampler;
|
layout(set = 0, binding = 5) uniform sampler2D TranslucencySampler;
|
||||||
layout(set = 0, binding = 6) uniform sampler2D OpacitySampler;
|
layout(set = 0, binding = 6) uniform sampler2D OpacitySampler;
|
||||||
layout(set = 0, binding = 7) uniform sampler2DArray shadowSampler;
|
layout(set = 0, binding = 7) uniform sampler2D ssaoBlur;
|
||||||
|
layout(set = 0, binding = 8) uniform sampler2DArray shadowSampler;
|
||||||
|
|
||||||
|
|
||||||
layout(scalar, set = 1, binding = 0) readonly buffer Lights {
|
layout(scalar, set = 1, binding = 0) readonly buffer Lights {
|
||||||
|
|
@ -203,6 +204,7 @@ void main() {
|
||||||
float emissiveness = emissive.r;
|
float emissiveness = emissive.r;
|
||||||
float translucencyf = translucency.r;
|
float translucencyf = translucency.r;
|
||||||
|
|
||||||
|
float ssao = texture(ssaoBlur, inTextCoord).r;
|
||||||
// outFragColor = vec4(emissive,1);
|
// outFragColor = vec4(emissive,1);
|
||||||
// return;
|
// return;
|
||||||
|
|
||||||
|
|
@ -240,9 +242,10 @@ void main() {
|
||||||
Lo += calculatePointLight(light, worldPos, V, N, F0, albedo, metallic, roughness);
|
Lo += calculatePointLight(light, worldPos, V, N, F0, albedo, metallic, roughness);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vec3 ambient = sceneInfo.ambientLightColor * albedo * sceneInfo.ambientLightIntensity;
|
vec3 ambient = sceneInfo.ambientLightColor * albedo * sceneInfo.ambientLightIntensity * vec3(ssao,ssao,ssao);;
|
||||||
if(emissive.x > 0 || emissive.y > 0 || emissive.z > 0) ambient = emissive;
|
if(emissive.x > 0 || emissive.y > 0 || emissive.z > 0) ambient = emissive;
|
||||||
outFragColor = vec4(Lo + ambient, 1.0f);
|
outFragColor = vec4(Lo + ambient, 1.0f);
|
||||||
|
outFragColor = vec4(outFragColor.xyz/2 + (outFragColor.xyz/2) * vec3(ssao,ssao,ssao),1);
|
||||||
|
|
||||||
if (DEBUG_SHADOWS == 1) {
|
if (DEBUG_SHADOWS == 1) {
|
||||||
switch (cascadeIndex) {
|
switch (cascadeIndex) {
|
||||||
|
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
#version 450
|
|
||||||
|
|
||||||
layout(location = 0 ) out vec2 outTextCoord;
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
outTextCoord = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
|
|
||||||
gl_Position = vec4(outTextCoord.x * 2.0f - 1.0f, outTextCoord.y * -2.0f + 1.0f,0.0f,1.0f);
|
|
||||||
}
|
|
||||||
Binary file not shown.
|
|
@ -1,6 +1,6 @@
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
const int MAX_TEXTURES = 256;
|
const int MAX_TEXTURES = 512;
|
||||||
|
|
||||||
layout(location = 0) in vec4 inPos;
|
layout(location = 0) in vec4 inPos;
|
||||||
layout(location = 1) in vec3 inNormal;
|
layout(location = 1) in vec3 inNormal;
|
||||||
|
|
@ -44,7 +44,12 @@ layout(push_constant) uniform pc{
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
Material material = matUniform.materials[inMaterialIdx];
|
||||||
|
int textureIndex = int(material.textureIdx);
|
||||||
|
if (textureIndex >= MAX_TEXTURES){
|
||||||
|
outAlbedo = vec4(0.0,0.0,1.0,1.0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
Material material = matUniform.materials[push_constants.materialIdx];
|
Material material = matUniform.materials[push_constants.materialIdx];
|
||||||
if(material.hasTexture == 1){
|
if(material.hasTexture == 1){
|
||||||
vec4 texColor = texture(textSampler[material.textureIdx],inTextCoords);
|
vec4 texColor = texture(textSampler[material.textureIdx],inTextCoords);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
const int MAX_TEXTURES = 256;
|
const int MAX_TEXTURES = 512;
|
||||||
|
|
||||||
|
|
||||||
layout(location = 0) in vec4 inPos;
|
layout(location = 0) in vec4 inPos;
|
||||||
layout(location = 1) in vec3 inNormal;
|
layout(location = 1) in vec3 inNormal;
|
||||||
|
|
@ -62,6 +63,16 @@ void main()
|
||||||
outPos = inPos;
|
outPos = inPos;
|
||||||
|
|
||||||
Material material = matUniform.materials[push_constants.materialIdx];
|
Material material = matUniform.materials[push_constants.materialIdx];
|
||||||
|
int textureIndex = int(material.textureIdx);
|
||||||
|
if (textureIndex >= MAX_TEXTURES){
|
||||||
|
outAlbedo = vec4(0.0,0.0,1.0,1.0);
|
||||||
|
outOpacity = vec4(0.0,0.0,1.0,1.0);
|
||||||
|
outNormal = vec4(0.0,0.0,1.0,1.0);
|
||||||
|
outEmissive = vec4(0.0,0.0,1.0,1.0);
|
||||||
|
outTranslucency = vec4(0.0,0.0,1.0,1.0);
|
||||||
|
outPBR = vec4(0.0,0.0,1.0,1.0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (material.hasTexture == 1) {
|
if (material.hasTexture == 1) {
|
||||||
outAlbedo = texture(textSampler[material.textureIdx], inTextCoords);
|
outAlbedo = texture(textSampler[material.textureIdx], inTextCoords);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -1,6 +1,7 @@
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
const int MAX_TEXTURES = 256;
|
const int MAX_TEXTURES = 512;
|
||||||
|
|
||||||
|
|
||||||
layout(location = 0) in vec4 inPos;
|
layout(location = 0) in vec4 inPos;
|
||||||
layout(location = 1) in vec3 inNormal;
|
layout(location = 1) in vec3 inNormal;
|
||||||
|
|
@ -44,6 +45,11 @@ layout(push_constant) uniform pc{
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
Material material = matUniform.materials[push_constants.materialIdx];
|
Material material = matUniform.materials[push_constants.materialIdx];
|
||||||
|
int textureIndex = int(material.textureIdx);
|
||||||
|
if (textureIndex >= MAX_TEXTURES){
|
||||||
|
outAlbedo = vec4(0.0,0.0,1.0,1.0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if(material.hasTexture == 1){
|
if(material.hasTexture == 1){
|
||||||
vec4 texColor = texture(textSampler[material.textureIdx],inTextCoords);
|
vec4 texColor = texture(textSampler[material.textureIdx],inTextCoords);
|
||||||
outAlbedo = texColor;
|
outAlbedo = texColor;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
const int MAX_TEXTURES = 256;
|
const int MAX_TEXTURES = 512;
|
||||||
|
|
||||||
layout(location = 0) in vec4 inPos;
|
layout(location = 0) in vec4 inPos;
|
||||||
layout(location = 1) in vec3 inNormal;
|
layout(location = 1) in vec3 inNormal;
|
||||||
|
|
@ -69,6 +69,16 @@ void main()
|
||||||
outPos = inPos;
|
outPos = inPos;
|
||||||
|
|
||||||
Material material = matUniform.materials[push_constants.materialIdx];
|
Material material = matUniform.materials[push_constants.materialIdx];
|
||||||
|
int textureIndex = int(material.textureIdx);
|
||||||
|
if (textureIndex >= MAX_TEXTURES){
|
||||||
|
outAlbedo = vec4(0.0,0.0,1.0,1.0);
|
||||||
|
outOpacity = vec4(0.0,0.0,1.0,1.0);
|
||||||
|
outNormal = vec4(0.0,0.0,1.0,1.0);
|
||||||
|
outEmissive = vec4(0.0,0.0,1.0,1.0);
|
||||||
|
outTranslucency = vec4(0.0,0.0,1.0,1.0);
|
||||||
|
outPBR = vec4(0.0,0.0,1.0,1.0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (material.hasTexture == 1) {
|
if (material.hasTexture == 1) {
|
||||||
outAlbedo = texture(textSampler[material.textureIdx], inTextCoords);
|
outAlbedo = texture(textSampler[material.textureIdx], inTextCoords);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -1,6 +1,6 @@
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
const int MAX_TEXTURES = 256;
|
const int MAX_TEXTURES = 512;
|
||||||
|
|
||||||
layout(location = 0) in vec4 inPos;
|
layout(location = 0) in vec4 inPos;
|
||||||
layout(location = 1) in vec3 inNormal;
|
layout(location = 1) in vec3 inNormal;
|
||||||
|
|
@ -43,6 +43,11 @@ layout(push_constant) uniform pc{
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
Material material = matUniform.materials[push_constants.materialIdx];
|
Material material = matUniform.materials[push_constants.materialIdx];
|
||||||
|
int textureIndex = int(material.textureIdx);
|
||||||
|
if (textureIndex >= MAX_TEXTURES){
|
||||||
|
outAlbedo = vec4(0.0,0.0,1.0,1.0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if(material.hasTexture == 1){
|
if(material.hasTexture == 1){
|
||||||
vec4 texColor = texture(textSampler[material.textureIdx],inTextCoords);
|
vec4 texColor = texture(textSampler[material.textureIdx],inTextCoords);
|
||||||
outAlbedo = texColor;
|
outAlbedo = texColor;
|
||||||
|
|
@ -60,4 +65,5 @@ void main()
|
||||||
if(opacityf >= 0.9){discard;}
|
if(opacityf >= 0.9){discard;}
|
||||||
|
|
||||||
outAlbedo = vec4(outAlbedo.rgb, opacityf);
|
outAlbedo = vec4(outAlbedo.rgb, opacityf);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
const int MAX_TEXTURES = 256;
|
const int MAX_TEXTURES = 512;
|
||||||
|
|
||||||
layout(location = 0) in vec4 inPos;
|
layout(location = 0) in vec4 inPos;
|
||||||
layout(location = 1) in vec3 inNormal;
|
layout(location = 1) in vec3 inNormal;
|
||||||
|
|
@ -69,8 +69,17 @@ layout(push_constant) uniform pc {
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
outPos = inPos;
|
outPos = inPos;
|
||||||
|
|
||||||
Material material = matUniform.materials[push_constants.materialIdx];
|
Material material = matUniform.materials[push_constants.materialIdx];
|
||||||
|
int textureIndex = int(material.textureIdx);
|
||||||
|
if (textureIndex >= MAX_TEXTURES){
|
||||||
|
outAlbedo = vec4(0.0,0.0,1.0,1.0);
|
||||||
|
outOpacity = vec4(0.0,0.0,1.0,1.0);
|
||||||
|
outNormal = vec4(0.0,0.0,1.0,1.0);
|
||||||
|
outEmissive = vec4(0.0,0.0,1.0,1.0);
|
||||||
|
outTranslucency = vec4(0.0,0.0,1.0,1.0);
|
||||||
|
outPBR = vec4(0.0,0.0,1.0,1.0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (material.hasTexture == 1) {
|
if (material.hasTexture == 1) {
|
||||||
outAlbedo = texture(textSampler[material.textureIdx], inTextCoords);
|
outAlbedo = texture(textSampler[material.textureIdx], inTextCoords);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
Binary file not shown.
104
resources/EngineResources/shaders/screen_space_fog.glsl
Normal file
104
resources/EngineResources/shaders/screen_space_fog.glsl
Normal file
|
|
@ -0,0 +1,104 @@
|
||||||
|
#version 450
|
||||||
|
|
||||||
|
layout(location = 0) in vec2 inTextCoord;
|
||||||
|
layout(location = 0) out float outAO;
|
||||||
|
|
||||||
|
layout(set = 0, binding = 0) uniform sampler2D posSampler;
|
||||||
|
layout(set = 0, binding = 1) uniform sampler2D normalSampler;
|
||||||
|
layout(set = 0, binding = 2) uniform sampler2D noiseSampler;
|
||||||
|
|
||||||
|
layout(set = 1, binding = 0) readonly buffer SSAOKernel {
|
||||||
|
vec4 samples[];
|
||||||
|
} kernel;
|
||||||
|
|
||||||
|
layout(set = 2, binding = 0) uniform SSAOInfo {
|
||||||
|
mat4 projection; //64
|
||||||
|
mat4 view; //128
|
||||||
|
vec2 screenSize; // 136
|
||||||
|
float radius; //140
|
||||||
|
float bias; //144
|
||||||
|
int kernelSize; //160
|
||||||
|
} ssao;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec2 uv = inTextCoord;
|
||||||
|
|
||||||
|
vec3 worldPos = texture(posSampler, uv).xyz;
|
||||||
|
vec3 worldNormal = normalize(texture(normalSampler, uv).xyz);
|
||||||
|
|
||||||
|
|
||||||
|
if (length(worldNormal) < 0.001) {
|
||||||
|
outAO = 1.0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 fragPos = vec3(ssao.view * vec4(worldPos, 1.0));
|
||||||
|
vec3 normal = normalize(mat3(ssao.view) * worldNormal);
|
||||||
|
|
||||||
|
vec2 noiseScale = ssao.screenSize / 4.0;
|
||||||
|
vec3 randomVec = normalize(texture(noiseSampler, inTextCoord * noiseScale).xyz);
|
||||||
|
|
||||||
|
|
||||||
|
vec3 tangent = normalize(randomVec - normal * dot(randomVec, normal));
|
||||||
|
vec3 bitangent = cross(normal, tangent);
|
||||||
|
mat3 TBN = mat3(tangent, bitangent, normal);
|
||||||
|
|
||||||
|
float occlusion = 0.0;
|
||||||
|
float validSamples = 0.0;;
|
||||||
|
|
||||||
|
for (int i = 0; i < ssao.kernelSize; i++) {
|
||||||
|
vec3 samplePos = TBN * kernel.samples[i].xyz;
|
||||||
|
samplePos = fragPos + samplePos * ssao.radius;
|
||||||
|
|
||||||
|
vec4 offset = vec4(samplePos, 1.0);
|
||||||
|
offset = ssao.projection * offset;
|
||||||
|
offset.xyz /= offset.w;
|
||||||
|
offset.xyz = offset.xyz * 0.5 + 0.5;
|
||||||
|
|
||||||
|
vec2 sampleUV = offset.xy;
|
||||||
|
sampleUV.y = 1.0 - sampleUV.y;
|
||||||
|
|
||||||
|
if (sampleUV.x < 0.0 || sampleUV.x > 1.0 ||
|
||||||
|
sampleUV.y < 0.0 || sampleUV.y > 1.0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 sampleWorldPos = texture(posSampler, sampleUV).xyz;
|
||||||
|
vec3 sampleWorldNormal = texture(normalSampler, sampleUV).xyz;
|
||||||
|
|
||||||
|
if (length(sampleWorldNormal) < 0.001) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 sampleViewPos = vec3(ssao.view * vec4(sampleWorldPos, 1.0));
|
||||||
|
|
||||||
|
float depthDelta = abs(fragPos.z - sampleViewPos.z);
|
||||||
|
|
||||||
|
occlusion += abs(fragPos.z)/200.0f;
|
||||||
|
validSamples += 1.0;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (depthDelta > ssao.radius) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
float rangeCheck = 1.0 - depthDelta / ssao.radius;
|
||||||
|
rangeCheck = rangeCheck * rangeCheck * (3.0 - 2.0 * rangeCheck);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (sampleViewPos.z >= samplePos.z + ssao.bias) {
|
||||||
|
occlusion += rangeCheck;
|
||||||
|
}
|
||||||
|
|
||||||
|
validSamples += 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (validSamples <= 0.0) {
|
||||||
|
outAO = 1.0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
occlusion = 1.0 - occlusion / validSamples;
|
||||||
|
outAO = clamp(occlusion, 0.0, 1.0);
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
// Keep in sync manually with Java code
|
// Keep in sync manually with Java code
|
||||||
const int MAX_TEXTURES = 256;
|
const int MAX_TEXTURES = 512;
|
||||||
|
|
||||||
layout (location = 0) in vec2 inTextCoords;
|
layout (location = 0) in vec2 inTextCoords;
|
||||||
layout (location = 1) in flat uint inMaterialIdx;
|
layout (location = 1) in flat uint inMaterialIdx;
|
||||||
|
|
@ -36,6 +36,11 @@ layout(set = 2, binding = 0) readonly buffer MaterialUniform {
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
Material material = matUniform.materials[inMaterialIdx];
|
Material material = matUniform.materials[inMaterialIdx];
|
||||||
|
int textureIndex = int(material.textureIdx);
|
||||||
|
if (textureIndex >= MAX_TEXTURES){
|
||||||
|
outFragColor = vec2(0.0,0.0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
vec4 albedo;
|
vec4 albedo;
|
||||||
if (material.hasTexture == 1) {
|
if (material.hasTexture == 1) {
|
||||||
albedo = texture(textSampler[material.textureIdx], inTextCoords);
|
albedo = texture(textSampler[material.textureIdx], inTextCoords);
|
||||||
|
|
|
||||||
21
resources/EngineResources/shaders/ssao_blur_frag.glsl
Normal file
21
resources/EngineResources/shaders/ssao_blur_frag.glsl
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
#version 450
|
||||||
|
|
||||||
|
layout(location = 0) in vec2 inTextCoord;
|
||||||
|
layout(location = 0) out float outAO;
|
||||||
|
|
||||||
|
layout(set = 0, binding = 0) uniform sampler2D ssaoSampler;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
|
||||||
|
vec2 texelSize = 1.0 / vec2(textureSize(ssaoSampler, 0));
|
||||||
|
float result = 0.0;
|
||||||
|
|
||||||
|
for (int x = -2; x <= 2; x++) {
|
||||||
|
for (int y = -2; y <= 2; y++) {
|
||||||
|
vec2 offset = vec2(float(x), float(y)) * texelSize;
|
||||||
|
result += texture(ssaoSampler, vec2(inTextCoord.x,inTextCoord.y) + offset).r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
outAO = result / 25.0;
|
||||||
|
}
|
||||||
95
resources/EngineResources/shaders/ssao_frag.glsl
Normal file
95
resources/EngineResources/shaders/ssao_frag.glsl
Normal file
|
|
@ -0,0 +1,95 @@
|
||||||
|
#version 450
|
||||||
|
|
||||||
|
layout(location = 0) in vec2 inTextCoord;
|
||||||
|
layout(location = 0) out float outAO;
|
||||||
|
|
||||||
|
layout(set = 0, binding = 0) uniform sampler2D posSampler;
|
||||||
|
layout(set = 0, binding = 1) uniform sampler2D normalSampler;
|
||||||
|
layout(set = 0, binding = 2) uniform sampler2D noiseSampler;
|
||||||
|
|
||||||
|
layout(set = 1, binding = 0) readonly buffer SSAOKernel {
|
||||||
|
vec4 samples[];
|
||||||
|
} kernel;
|
||||||
|
|
||||||
|
layout(set = 2, binding = 0) uniform SSAOInfo {
|
||||||
|
mat4 projection; //64
|
||||||
|
mat4 view; //128
|
||||||
|
vec2 screenSize; // 136
|
||||||
|
float radius; //140
|
||||||
|
float bias; //144
|
||||||
|
int kernelSize; //160
|
||||||
|
} ssao;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec2 uv = inTextCoord;
|
||||||
|
|
||||||
|
vec3 worldPos = texture(posSampler, uv).xyz;
|
||||||
|
vec3 worldNormal = normalize(texture(normalSampler, uv).xyz);
|
||||||
|
|
||||||
|
vec2 noiseScale = ssao.screenSize / 4.0;
|
||||||
|
|
||||||
|
if (length(worldNormal) < 0.001) {
|
||||||
|
outAO = 1.0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 fragPos = vec3(ssao.view * vec4(worldPos, 1.0));
|
||||||
|
vec3 normal = normalize(mat3(ssao.view) * worldNormal);
|
||||||
|
|
||||||
|
vec3 randomVec = normalize(texture(noiseSampler, inTextCoord * noiseScale).xyz);
|
||||||
|
|
||||||
|
vec3 tangent = normalize(randomVec - normal * dot(randomVec, normal));
|
||||||
|
vec3 bitangent = cross(normal, tangent);
|
||||||
|
mat3 TBN = mat3(tangent, bitangent, normal);
|
||||||
|
|
||||||
|
float occlusion = 0.0;
|
||||||
|
float validSamples = 0.0;;
|
||||||
|
|
||||||
|
for (int i = 0; i < ssao.kernelSize; i++) {
|
||||||
|
vec3 samplePos = TBN * kernel.samples[i].xyz;
|
||||||
|
samplePos = fragPos + samplePos * ssao.radius;
|
||||||
|
|
||||||
|
vec4 offset = vec4(samplePos, 1.0);
|
||||||
|
offset = ssao.projection * offset;
|
||||||
|
offset.xyz /= offset.w;
|
||||||
|
offset.xyz = offset.xyz * 0.5 + 0.5;
|
||||||
|
|
||||||
|
vec2 sampleUV = offset.xy;
|
||||||
|
sampleUV.y = 1 - sampleUV.y;
|
||||||
|
|
||||||
|
if (sampleUV.x < 0.0 || sampleUV.x > 1.0 ||
|
||||||
|
sampleUV.y < 0.0 || sampleUV.y > 1.0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 sampleWorldPos = texture(posSampler, sampleUV).xyz;
|
||||||
|
vec3 sampleWorldNormal = texture(normalSampler, sampleUV).xyz;
|
||||||
|
|
||||||
|
if (length(sampleWorldNormal) < 0.001) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 sampleViewPos = vec3(ssao.view * vec4(sampleWorldPos, 1.0));
|
||||||
|
|
||||||
|
float depthDelta = abs(fragPos.z - sampleViewPos.z);
|
||||||
|
if (depthDelta > ssao.radius) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
float rangeCheck = 1.0 - depthDelta / ssao.radius;
|
||||||
|
rangeCheck = rangeCheck * rangeCheck * (3.0 - 2.0 * rangeCheck);
|
||||||
|
|
||||||
|
if (sampleViewPos.z >= samplePos.z + ssao.bias) {
|
||||||
|
occlusion += rangeCheck;
|
||||||
|
}
|
||||||
|
validSamples += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (validSamples <= 0.0) {
|
||||||
|
outAO = 1.0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
occlusion = 1.0 - occlusion / validSamples;
|
||||||
|
outAO = occlusion * pow(occlusion, 3.0);
|
||||||
|
}
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
#version 450
|
|
||||||
|
|
||||||
layout(location = 0) out vec2 outTextCoord;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
outTextCoord = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
|
|
||||||
gl_Position = vec4(outTextCoord.x * 2.0f - 1.0f, outTextCoord.y * -2.0f + 1.0f,0.0f,1.0f);
|
|
||||||
}
|
|
||||||
Binary file not shown.
|
|
@ -12,6 +12,7 @@ import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.DeferredRe
|
||||||
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.Images.Attachment;
|
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.Images.Attachment;
|
||||||
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.Images.TextureCache;
|
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.Images.TextureCache;
|
||||||
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.PostProcessing.PostProcess;
|
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.PostProcessing.PostProcess;
|
||||||
|
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.ScreenSpace.AmbientOcclusionRenderer;
|
||||||
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Shadows.ShadowRenderer;
|
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Shadows.ShadowRenderer;
|
||||||
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.VkModel.*;
|
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.VkModel.*;
|
||||||
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.SpriteRendering.SpriteRenderer;
|
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.SpriteRendering.SpriteRenderer;
|
||||||
|
|
@ -51,6 +52,7 @@ public class VulkanRenderer implements Renderer {
|
||||||
private final Queue.PresentQueue PresentQueue;
|
private final Queue.PresentQueue PresentQueue;
|
||||||
private final Semaphore[] RenderCompleteSemaphores;
|
private final Semaphore[] RenderCompleteSemaphores;
|
||||||
private final SceneRenderer sceneRender;
|
private final SceneRenderer sceneRender;
|
||||||
|
private final AmbientOcclusionRenderer ssaoRenderer;
|
||||||
private final SpriteRenderer spriteRenderer;
|
private final SpriteRenderer spriteRenderer;
|
||||||
private final LightRenderer lightRenderer;
|
private final LightRenderer lightRenderer;
|
||||||
private final PostProcess PostProcessor;
|
private final PostProcess PostProcessor;
|
||||||
|
|
@ -110,13 +112,16 @@ public class VulkanRenderer implements Renderer {
|
||||||
if(Deferred) {
|
if(Deferred) {
|
||||||
sceneRender = new DeferredSceneRender(RendererContext, engineInstance);
|
sceneRender = new DeferredSceneRender(RendererContext, engineInstance);
|
||||||
shadowRender = new ShadowRenderer(RendererContext);
|
shadowRender = new ShadowRenderer(RendererContext);
|
||||||
|
ssaoRenderer = new AmbientOcclusionRenderer(RendererContext,sceneRender.GetMRTAttachments().GetColourAttachments(), GraphicsQueue);
|
||||||
List<Attachment> attachments = new ArrayList<>(sceneRender.GetMRTAttachments().GetColourAttachments());
|
List<Attachment> attachments = new ArrayList<>(sceneRender.GetMRTAttachments().GetColourAttachments());
|
||||||
|
attachments.add(ssaoRenderer.getSSAOBlurAttachment());
|
||||||
attachments.add(shadowRender.getShadowAttachment());
|
attachments.add(shadowRender.getShadowAttachment());
|
||||||
lightRenderer = new LightRenderer(RendererContext, attachments);
|
lightRenderer = new LightRenderer(RendererContext, attachments);
|
||||||
PostProcessor = new PostProcess(RendererContext, lightRenderer.getAttachment());
|
PostProcessor = new PostProcess(RendererContext, lightRenderer.getAttachment());
|
||||||
|
|
||||||
} else{
|
} else{
|
||||||
sceneRender = new ForwardSceneRender(RendererContext);
|
sceneRender = new ForwardSceneRender(RendererContext);
|
||||||
|
ssaoRenderer = null;
|
||||||
PostProcessor = new PostProcess(RendererContext, sceneRender.GetAttachmentColour());
|
PostProcessor = new PostProcess(RendererContext, sceneRender.GetAttachmentColour());
|
||||||
lightRenderer = null;
|
lightRenderer = null;
|
||||||
shadowRender = null;
|
shadowRender = null;
|
||||||
|
|
@ -189,6 +194,7 @@ public class VulkanRenderer implements Renderer {
|
||||||
RendererContext.GetDevice().waitIdle();
|
RendererContext.GetDevice().waitIdle();
|
||||||
Logger.debug("Waiting Vulkan Context");
|
Logger.debug("Waiting Vulkan Context");
|
||||||
sceneRender.cleanup(RendererContext);
|
sceneRender.cleanup(RendererContext);
|
||||||
|
if(ssaoRenderer != null)ssaoRenderer.cleanup(RendererContext);
|
||||||
if(shadowRender != null)shadowRender.cleanup(RendererContext);
|
if(shadowRender != null)shadowRender.cleanup(RendererContext);
|
||||||
if(lightRenderer != null)lightRenderer.cleanup(RendererContext);
|
if(lightRenderer != null)lightRenderer.cleanup(RendererContext);
|
||||||
PostProcessor.CleanUp(RendererContext);
|
PostProcessor.CleanUp(RendererContext);
|
||||||
|
|
@ -231,16 +237,15 @@ public class VulkanRenderer implements Renderer {
|
||||||
|
|
||||||
sceneRender.Render(engineInstance,RendererContext,CommandBuffer, modelsCache,materialsCache,CurrentFrame);
|
sceneRender.Render(engineInstance,RendererContext,CommandBuffer, modelsCache,materialsCache,CurrentFrame);
|
||||||
boolean RenderShadows = ShadowRenderer.AllowShadowRendering() && EngineConfig.getInstance().RenderShadows();
|
boolean RenderShadows = ShadowRenderer.AllowShadowRendering() && EngineConfig.getInstance().RenderShadows();
|
||||||
//lightRenderer.render(engineInstance, RendererContext, CommandBuffer, sceneRender.GetMRTAttachments(), shadowRender.getShadowAttachment(), CurrentFrame, shadowRender.getCascadeShadows(CurrentFrame));
|
if(RenderShadows) {shadowRender.render(engineInstance, RendererContext, CommandBuffer, modelsCache, materialsCache, CurrentFrame); }
|
||||||
|
ssaoRenderer.Render(RendererContext,engineInstance, CommandBuffer, sceneRender.GetMRTAttachments(), CurrentFrame);
|
||||||
if(RenderShadows) {
|
if(RenderShadows) {
|
||||||
shadowRender.render(engineInstance, RendererContext, CommandBuffer, modelsCache, materialsCache, CurrentFrame);
|
lightRenderer.render(engineInstance, RendererContext, CommandBuffer, sceneRender.GetMRTAttachments(),
|
||||||
lightRenderer.render(engineInstance, RendererContext, CommandBuffer, sceneRender.GetMRTAttachments(), shadowRender.getShadowAttachment(), CurrentFrame, shadowRender.getCascadeShadows(CurrentFrame));
|
shadowRender.getShadowAttachment(), ssaoRenderer.getSSAOBlurAttachment(), CurrentFrame, shadowRender.getCascadeShadows(CurrentFrame));
|
||||||
} else lightRenderer.render(engineInstance, RendererContext, CommandBuffer, sceneRender.GetMRTAttachments(),CurrentFrame);
|
} else lightRenderer.render(engineInstance, RendererContext, CommandBuffer, sceneRender.GetMRTAttachments(),ssaoRenderer.getSSAOBlurAttachment(),CurrentFrame);
|
||||||
PostProcessor.Render(RendererContext,CommandBuffer,lightRenderer.getAttachment());
|
PostProcessor.Render(RendererContext,CommandBuffer,lightRenderer.getAttachment());
|
||||||
spriteRenderer.Render(engineInstance,RendererContext,CommandBuffer,PostProcessor.GetAttachment(),modelsCache,CurrentFrame);
|
spriteRenderer.Render(engineInstance,RendererContext,CommandBuffer,PostProcessor.GetAttachment(),modelsCache,CurrentFrame);
|
||||||
GuiRender.Render(RendererContext,CommandBuffer,CurrentFrame,PostProcessor.GetAttachment());
|
GuiRender.Render(RendererContext,CommandBuffer,CurrentFrame,PostProcessor.GetAttachment());
|
||||||
|
|
||||||
|
|
||||||
swapChainRender.Render(RendererContext,CommandBuffer,PostProcessor.GetAttachment(),ImageIndex);
|
swapChainRender.Render(RendererContext,CommandBuffer,PostProcessor.GetAttachment(),ImageIndex);
|
||||||
|
|
||||||
RecordingStop(CommandBuffer);
|
RecordingStop(CommandBuffer);
|
||||||
|
|
@ -302,6 +307,7 @@ public class VulkanRenderer implements Renderer {
|
||||||
shadowRender.RebuildPipelineAndRenderingAttachments(RendererContext);
|
shadowRender.RebuildPipelineAndRenderingAttachments(RendererContext);
|
||||||
|
|
||||||
List<Attachment> attachments = new ArrayList<>(sceneRender.GetMRTAttachments().GetColourAttachments());
|
List<Attachment> attachments = new ArrayList<>(sceneRender.GetMRTAttachments().GetColourAttachments());
|
||||||
|
attachments.add(ssaoRenderer.getSSAOBlurAttachment());
|
||||||
attachments.add(shadowRender.getShadowAttachment());
|
attachments.add(shadowRender.getShadowAttachment());
|
||||||
lightRenderer.updateAttachmentDescriptors(RendererContext, attachments);
|
lightRenderer.updateAttachmentDescriptors(RendererContext, attachments);
|
||||||
|
|
||||||
|
|
@ -332,6 +338,11 @@ public class VulkanRenderer implements Renderer {
|
||||||
sceneRender.Resize(engineInstance,RendererContext);
|
sceneRender.Resize(engineInstance,RendererContext);
|
||||||
if(Deferred) {
|
if(Deferred) {
|
||||||
List<Attachment> attachments = new ArrayList<>(sceneRender.GetMRTAttachments().GetColourAttachments());
|
List<Attachment> attachments = new ArrayList<>(sceneRender.GetMRTAttachments().GetColourAttachments());
|
||||||
|
List<Attachment> ssaoAttachments = new ArrayList<>();
|
||||||
|
ssaoAttachments.add(attachments.get(0));
|
||||||
|
ssaoAttachments.add(attachments.get(2));
|
||||||
|
ssaoRenderer.resize(RendererContext, ssaoAttachments);
|
||||||
|
attachments.add(ssaoRenderer.getSSAOBlurAttachment());
|
||||||
attachments.add(shadowRender.getShadowAttachment());
|
attachments.add(shadowRender.getShadowAttachment());
|
||||||
lightRenderer.resize(RendererContext, attachments);
|
lightRenderer.resize(RendererContext, attachments);
|
||||||
PostProcessor.Resize(RendererContext, lightRenderer.getAttachment());
|
PostProcessor.Resize(RendererContext, lightRenderer.getAttachment());
|
||||||
|
|
|
||||||
|
|
@ -122,6 +122,7 @@ public class ModelCompiler {
|
||||||
String NormalTexture = ProcessTexture(aiScene,aiMaterial,BaseDirectory,aiTextureType_NORMALS);
|
String NormalTexture = ProcessTexture(aiScene,aiMaterial,BaseDirectory,aiTextureType_NORMALS);
|
||||||
String EmissiveTexture = ProcessTexture(aiScene,aiMaterial,BaseDirectory,aiTextureType_EMISSIVE);
|
String EmissiveTexture = ProcessTexture(aiScene,aiMaterial,BaseDirectory,aiTextureType_EMISSIVE);
|
||||||
String TranslucencyTexture = ProcessTexture(aiScene,aiMaterial,BaseDirectory,aiTextureType_TRANSMISSION);
|
String TranslucencyTexture = ProcessTexture(aiScene,aiMaterial,BaseDirectory,aiTextureType_TRANSMISSION);
|
||||||
|
String SpecularTexture = ProcessTexture(aiScene,aiMaterial,BaseDirectory,aiTextureType_SPECULAR);
|
||||||
String MetallicRoughTexture = ProcessTexture(aiScene, aiMaterial, BaseDirectory, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE);
|
String MetallicRoughTexture = ProcessTexture(aiScene, aiMaterial, BaseDirectory, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE);
|
||||||
String OpacityTexture = ProcessTexture(aiScene,aiMaterial,BaseDirectory,aiTextureType_OPACITY);
|
String OpacityTexture = ProcessTexture(aiScene,aiMaterial,BaseDirectory,aiTextureType_OPACITY);
|
||||||
|
|
||||||
|
|
@ -132,6 +133,18 @@ public class ModelCompiler {
|
||||||
MetallicArray = new float[]{0.0f};
|
MetallicArray = new float[]{0.0f};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float[] SpecularArray = new float[]{0.0f};
|
||||||
|
Result = aiGetMaterialFloatArray(aiMaterial,AI_MATKEY_SPECULAR_FACTOR,aiTextureType_NONE,0,SpecularArray,MaxPointer);
|
||||||
|
if(Result != aiReturn_SUCCESS){
|
||||||
|
SpecularArray = new float[]{0.0f};
|
||||||
|
}
|
||||||
|
|
||||||
|
if(MetallicArray[0] == 0.0f && SpecularArray[0] != 0.0f)
|
||||||
|
MetallicArray[0] = SpecularArray[0];
|
||||||
|
if(MetallicRoughTexture.isEmpty()){
|
||||||
|
MetallicRoughTexture = SpecularTexture;
|
||||||
|
}
|
||||||
|
|
||||||
float[] RoughnessArray = new float[]{0.0f};
|
float[] RoughnessArray = new float[]{0.0f};
|
||||||
Result = aiGetMaterialFloatArray(aiMaterial,AI_MATKEY_ROUGHNESS_FACTOR,aiTextureType_NONE,0,RoughnessArray,MaxPointer);
|
Result = aiGetMaterialFloatArray(aiMaterial,AI_MATKEY_ROUGHNESS_FACTOR,aiTextureType_NONE,0,RoughnessArray,MaxPointer);
|
||||||
if(Result != aiReturn_SUCCESS){
|
if(Result != aiReturn_SUCCESS){
|
||||||
|
|
@ -151,13 +164,32 @@ public class ModelCompiler {
|
||||||
}
|
}
|
||||||
|
|
||||||
float[] OpacityArray = new float[]{0.0f};
|
float[] OpacityArray = new float[]{0.0f};
|
||||||
|
|
||||||
Result = aiGetMaterialFloatArray(aiMaterial,AI_MATKEY_OPACITY,aiTextureType_NONE,0,OpacityArray,MaxPointer);
|
Result = aiGetMaterialFloatArray(aiMaterial,AI_MATKEY_OPACITY,aiTextureType_NONE,0,OpacityArray,MaxPointer);
|
||||||
if(Result != aiReturn_SUCCESS){
|
if(Result != aiReturn_SUCCESS){
|
||||||
OpacityArray = new float[]{0.0f};
|
OpacityArray = new float[]{0.0f};
|
||||||
}
|
}
|
||||||
|
|
||||||
return new MaterialData(ModelName + "-mat-" + Position,DiffuseTexture,NormalTexture, MetallicRoughTexture,diffuse,RoughnessArray[0],MetallicArray[0], EmissiveTexture,emissiveColour, TranslucencyTexture, TranslucencyArray[0], OpacityTexture, OpacityArray[0]);
|
float[] RefractionArray = new float[]{0.0f};
|
||||||
|
Result = aiGetMaterialFloatArray(aiMaterial,AI_MATKEY_REFRACTI,aiTextureType_NONE,0,RefractionArray,MaxPointer);
|
||||||
|
if(Result != aiReturn_SUCCESS){
|
||||||
|
RefractionArray = new float[]{0.0f};
|
||||||
|
}
|
||||||
|
|
||||||
|
float[] ReflectionArray = new float[]{0.0f};
|
||||||
|
Result = aiGetMaterialFloatArray(aiMaterial,AI_MATKEY_REFLECTIVITY,aiTextureType_NONE,0,ReflectionArray,MaxPointer);
|
||||||
|
if(Result != aiReturn_SUCCESS){
|
||||||
|
ReflectionArray = new float[]{0.0f};
|
||||||
|
}
|
||||||
|
|
||||||
|
AIColor4D colour_transparency = AIColor4D.create();
|
||||||
|
Vector4f ColorTransparency = new Vector4f();
|
||||||
|
|
||||||
|
Result = aiGetMaterialColor(aiMaterial,AI_MATKEY_COLOR_TRANSPARENT,aiTextureType_NONE,0,colour_transparency);
|
||||||
|
if(Result != aiReturn_SUCCESS){
|
||||||
|
ColorTransparency.set(colour_transparency.r(),colour_transparency.g(),colour_transparency.b(),colour_transparency.a());
|
||||||
|
}
|
||||||
|
|
||||||
|
return new MaterialData(ModelName + "-mat-" + Position,DiffuseTexture,NormalTexture, MetallicRoughTexture,diffuse,RoughnessArray[0],MetallicArray[0], EmissiveTexture,emissiveColour, TranslucencyTexture, TranslucencyArray[0], OpacityTexture, OpacityArray[0],ColorTransparency,RefractionArray[0], ReflectionArray[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MeshData ProcessMesh(AIMesh aiMesh, List<MaterialData> MaterialList, int MeshPosition, ModelBinaryData BinaryData) throws IOException {
|
public static MeshData ProcessMesh(AIMesh aiMesh, List<MaterialData> MaterialList, int MeshPosition, ModelBinaryData BinaryData) throws IOException {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
package net.halbear.Terrain4J.EngineCore.RenderingAPI.Universal.SSAO;
|
||||||
|
|
||||||
|
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Util.VulkanUtils;
|
||||||
|
import org.joml.Vector4f;
|
||||||
|
import org.lwjgl.BufferUtils;
|
||||||
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.FloatBuffer;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class SSAO_Utils {
|
||||||
|
|
||||||
|
public static FloatBuffer GenerateSampleKernel(int size, long MappedMemory) {
|
||||||
|
FloatBuffer kernel = MemoryUtil.memFloatBuffer(MappedMemory,size * 4); // vec4 alignment
|
||||||
|
Random rnd = new Random();
|
||||||
|
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
|
||||||
|
Vector4f sample = new Vector4f(rnd.nextFloat() * 2.0f - 1.0f,rnd.nextFloat() * 2.0f - 1.0f,rnd.nextFloat(),0);
|
||||||
|
sample = sample.normalize();
|
||||||
|
|
||||||
|
float scale = (float) i / (float) size;
|
||||||
|
scale = Lerp(0.1f, 1.0f, scale * scale);
|
||||||
|
sample.mul(scale);
|
||||||
|
kernel.put(sample.x);
|
||||||
|
kernel.put(sample.y);
|
||||||
|
kernel.put(sample.z);
|
||||||
|
kernel.put(0.0f);
|
||||||
|
}
|
||||||
|
return kernel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ByteBuffer GenerateNoiseTexture() {
|
||||||
|
ByteBuffer buffer = BufferUtils.createByteBuffer(16 * 4 * Float.BYTES);
|
||||||
|
Random rnd = new Random();
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
float x = rnd.nextFloat() * 2.0f - 1.0f;
|
||||||
|
float y = rnd.nextFloat() * 2.0f - 1.0f;
|
||||||
|
buffer.putFloat(x);
|
||||||
|
buffer.putFloat(y);
|
||||||
|
buffer.putFloat(0.0f);
|
||||||
|
buffer.putFloat(0.0f);
|
||||||
|
}
|
||||||
|
buffer.flip();
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static float Lerp(float a, float b, float f) {
|
||||||
|
return a + f * (b - a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -50,7 +50,7 @@ public class LightRenderer {
|
||||||
private static final String FRAGMENT_SHADER_FILE_SPV = FRAGMENT_SHADER_FILE_GLSL + ".spv";
|
private static final String FRAGMENT_SHADER_FILE_SPV = FRAGMENT_SHADER_FILE_GLSL + ".spv";
|
||||||
private static final String NO_SHADOWS_FRAGMENT_SHADER_FILE_GLSL = "resources/EngineResources/shaders/lighting_frag.glsl";
|
private static final String NO_SHADOWS_FRAGMENT_SHADER_FILE_GLSL = "resources/EngineResources/shaders/lighting_frag.glsl";
|
||||||
private static final String NO_SHADOWS_FRAGMENT_SHADER_FILE_SPV = NO_SHADOWS_FRAGMENT_SHADER_FILE_GLSL + ".spv";
|
private static final String NO_SHADOWS_FRAGMENT_SHADER_FILE_SPV = NO_SHADOWS_FRAGMENT_SHADER_FILE_GLSL + ".spv";
|
||||||
private static final String VERTEX_SHADER_FILE_GLSL = "resources/EngineResources/shaders/lighting_vertex.glsl";
|
private static final String VERTEX_SHADER_FILE_GLSL = "resources/EngineResources/shaders/basic_screen_vertex.glsl";
|
||||||
private static final String VERTEX_SHADER_FILE_SPV = VERTEX_SHADER_FILE_GLSL + ".spv";
|
private static final String VERTEX_SHADER_FILE_SPV = VERTEX_SHADER_FILE_GLSL + ".spv";
|
||||||
|
|
||||||
private final DescriptorSetLayout AttachmentDescriptorSetLayout;
|
private final DescriptorSetLayout AttachmentDescriptorSetLayout;
|
||||||
|
|
@ -69,6 +69,8 @@ public class LightRenderer {
|
||||||
private final DescriptorSetLayout StorageDescriptorSetLayout;
|
private final DescriptorSetLayout StorageDescriptorSetLayout;
|
||||||
private final VulkanBuffer[] shadowMatrices;
|
private final VulkanBuffer[] shadowMatrices;
|
||||||
|
|
||||||
|
private int MinimumAttachments = 9; // shadow + ssaoBlur
|
||||||
|
|
||||||
public LightRenderer(VulkanContext VkCtx, List<Attachment> attachments){
|
public LightRenderer(VulkanContext VkCtx, List<Attachment> attachments){
|
||||||
ClearValueColour = VkClearValue.calloc().color(
|
ClearValueColour = VkClearValue.calloc().color(
|
||||||
c -> c.float32(0, 0.0f).float32(1, 0.0f).float32(2, 0.0f).float32(3, 0.0f));
|
c -> c.float32(0, 0.0f).float32(1, 0.0f).float32(2, 0.0f).float32(3, 0.0f));
|
||||||
|
|
@ -84,8 +86,9 @@ public class LightRenderer {
|
||||||
VK_BORDER_COLOR_INT_OPAQUE_BLACK, 1, true);
|
VK_BORDER_COLOR_INT_OPAQUE_BLACK, 1, true);
|
||||||
textureSampler = new TextureSampler(VkCtx, textureSamplerInfo);
|
textureSampler = new TextureSampler(VkCtx, textureSamplerInfo);
|
||||||
int numAttachments = attachments.size();
|
int numAttachments = attachments.size();
|
||||||
DescriptorSetLayout.LayoutInformation[] descSetLayouts = new DescriptorSetLayout.LayoutInformation[numAttachments + 1];
|
if(numAttachments < MinimumAttachments) numAttachments = MinimumAttachments;
|
||||||
for (int i = 0; i < numAttachments + 1; i++) {
|
DescriptorSetLayout.LayoutInformation[] descSetLayouts = new DescriptorSetLayout.LayoutInformation[numAttachments];
|
||||||
|
for (int i = 0; i < numAttachments; i++) {
|
||||||
descSetLayouts[i] = new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, i, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
descSetLayouts[i] = new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, i, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||||
}
|
}
|
||||||
AttachmentDescriptorSetLayout = new DescriptorSetLayout(VkCtx, descSetLayouts);
|
AttachmentDescriptorSetLayout = new DescriptorSetLayout(VkCtx, descSetLayouts);
|
||||||
|
|
@ -209,7 +212,7 @@ public class LightRenderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void render(EngineInstance engineInstance, VulkanContext VkCtx, CommandBuffer cmdBuffer, MultiRenderTargetAttachments mrtAttachments,Attachment shadowAttachment, int CurrentFrame, CascadeShadows cascadeShadows) {
|
public void render(EngineInstance engineInstance, VulkanContext VkCtx, CommandBuffer cmdBuffer, MultiRenderTargetAttachments mrtAttachments,Attachment shadowAttachment, Attachment ssaoBlurAttachment, int CurrentFrame, CascadeShadows cascadeShadows) {
|
||||||
try (var stack = MemoryStack.stackPush()) {
|
try (var stack = MemoryStack.stackPush()) {
|
||||||
VkCommandBuffer cmdHandle = cmdBuffer.GetVulkanCommandBuffer();
|
VkCommandBuffer cmdHandle = cmdBuffer.GetVulkanCommandBuffer();
|
||||||
|
|
||||||
|
|
@ -219,16 +222,6 @@ public class LightRenderer {
|
||||||
VK_ACCESS_2_NONE, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT,
|
VK_ACCESS_2_NONE, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT,
|
||||||
VK_IMAGE_ASPECT_COLOR_BIT);
|
VK_IMAGE_ASPECT_COLOR_BIT);
|
||||||
|
|
||||||
List<Attachment> attachments = mrtAttachments.GetColourAttachments();
|
|
||||||
int numAttachments = attachments.size();
|
|
||||||
for (int i = 0; i < numAttachments; i++) {
|
|
||||||
Attachment attachment = attachments.get(i);
|
|
||||||
VulkanUtils.ImageBarrier(stack, cmdHandle, attachment.GetVkImage().getVulkanImage(),
|
|
||||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
|
||||||
VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT,
|
|
||||||
VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_2_SHADER_READ_BIT,
|
|
||||||
VK_IMAGE_ASPECT_COLOR_BIT);
|
|
||||||
}
|
|
||||||
VulkanUtils.ImageBarrier(stack, cmdHandle, mrtAttachments.GetDepthAttachment().GetVkImage().getVulkanImage(),
|
VulkanUtils.ImageBarrier(stack, cmdHandle, mrtAttachments.GetDepthAttachment().GetVkImage().getVulkanImage(),
|
||||||
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||||
VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT,
|
VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT,
|
||||||
|
|
@ -285,7 +278,7 @@ public class LightRenderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void render(EngineInstance engineInstance, VulkanContext VkCtx, CommandBuffer cmdBuffer, MultiRenderTargetAttachments mrtAttachments, int CurrentFrame) {
|
public void render(EngineInstance engineInstance, VulkanContext VkCtx, CommandBuffer cmdBuffer, MultiRenderTargetAttachments mrtAttachments, Attachment SSAOattachment, int CurrentFrame) {
|
||||||
try (var stack = MemoryStack.stackPush()) {
|
try (var stack = MemoryStack.stackPush()) {
|
||||||
VkCommandBuffer cmdHandle = cmdBuffer.GetVulkanCommandBuffer();
|
VkCommandBuffer cmdHandle = cmdBuffer.GetVulkanCommandBuffer();
|
||||||
|
|
||||||
|
|
@ -295,16 +288,6 @@ public class LightRenderer {
|
||||||
VK_ACCESS_2_NONE, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT,
|
VK_ACCESS_2_NONE, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT,
|
||||||
VK_IMAGE_ASPECT_COLOR_BIT);
|
VK_IMAGE_ASPECT_COLOR_BIT);
|
||||||
|
|
||||||
List<Attachment> attachments = mrtAttachments.GetColourAttachments();
|
|
||||||
int numAttachments = attachments.size();
|
|
||||||
for (int i = 0; i < numAttachments; i++) {
|
|
||||||
Attachment attachment = attachments.get(i);
|
|
||||||
VulkanUtils.ImageBarrier(stack, cmdHandle, attachment.GetVkImage().getVulkanImage(),
|
|
||||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
|
||||||
VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT,
|
|
||||||
VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_2_SHADER_READ_BIT,
|
|
||||||
VK_IMAGE_ASPECT_COLOR_BIT);
|
|
||||||
}
|
|
||||||
VulkanUtils.ImageBarrier(stack, cmdHandle, mrtAttachments.GetDepthAttachment().GetVkImage().getVulkanImage(),
|
VulkanUtils.ImageBarrier(stack, cmdHandle, mrtAttachments.GetDepthAttachment().GetVkImage().getVulkanImage(),
|
||||||
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||||
VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT,
|
VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT,
|
||||||
|
|
@ -422,7 +405,7 @@ public class LightRenderer {
|
||||||
|
|
||||||
DescriptorSet noShadowDescSet = VkCtx.GetDescriptorAllocator().GetDescriptorSet(DESC_ID_NOSHADOW_ATT);
|
DescriptorSet noShadowDescSet = VkCtx.GetDescriptorAllocator().GetDescriptorSet(DESC_ID_NOSHADOW_ATT);
|
||||||
var noShadowImageViews = new ArrayList<ImageView>();
|
var noShadowImageViews = new ArrayList<ImageView>();
|
||||||
for (int i = 0; i < attachments.size() - 1; i++) {
|
for (int i = 0; i < attachments.size(); i++) {
|
||||||
noShadowImageViews.add(attachments.get(i).GetVkImageView());
|
noShadowImageViews.add(attachments.get(i).GetVkImageView());
|
||||||
}
|
}
|
||||||
noShadowDescSet.SetImages(VkCtx.GetDevice(), noShadowImageViews, textureSampler, 0);
|
noShadowDescSet.SetImages(VkCtx.GetDevice(), noShadowImageViews, textureSampler, 0);
|
||||||
|
|
@ -444,7 +427,7 @@ public class LightRenderer {
|
||||||
|
|
||||||
DescriptorSet noShadowDescSet = VkCtx.GetDescriptorAllocator().GetDescriptorSet(DESC_ID_NOSHADOW_ATT);
|
DescriptorSet noShadowDescSet = VkCtx.GetDescriptorAllocator().GetDescriptorSet(DESC_ID_NOSHADOW_ATT);
|
||||||
var noShadowImageViews = new ArrayList<ImageView>();
|
var noShadowImageViews = new ArrayList<ImageView>();
|
||||||
for (int i = 0; i < attachments.size() - 1; i++) {
|
for (int i = 0; i < attachments.size(); i++) {
|
||||||
noShadowImageViews.add(attachments.get(i).GetVkImageView());
|
noShadowImageViews.add(attachments.get(i).GetVkImageView());
|
||||||
}
|
}
|
||||||
noShadowDescSet.SetImages(VkCtx.GetDevice(), noShadowImageViews, textureSampler, 0);
|
noShadowDescSet.SetImages(VkCtx.GetDevice(), noShadowImageViews, textureSampler, 0);
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,9 @@ public class MultiRenderTargetAttachments {
|
||||||
public static final int EMISSIVE_FORMAT = VK_FORMAT_R16G16B16A16_SFLOAT;
|
public static final int EMISSIVE_FORMAT = VK_FORMAT_R16G16B16A16_SFLOAT;
|
||||||
public static final int TRANSLUCECNY_FORMAT = VK_FORMAT_R16G16B16A16_SFLOAT;
|
public static final int TRANSLUCECNY_FORMAT = VK_FORMAT_R16G16B16A16_SFLOAT;
|
||||||
public static final int OPACITY_FORMAT = VK_FORMAT_R16G16B16A16_SFLOAT;
|
public static final int OPACITY_FORMAT = VK_FORMAT_R16G16B16A16_SFLOAT;
|
||||||
public static final int POSITION_FORMAT = VK_FORMAT_R16G16B16A16_SFLOAT;
|
public static final int POSITION_FORMAT = VK_FORMAT_R32G32B32A32_SFLOAT;
|
||||||
|
public static final int SSAO_RAW_ATTACHMENT = VK_FORMAT_R8_UNORM;
|
||||||
|
public static final int SSAO_BLUR_ATTACHMENT = VK_FORMAT_R8_UNORM;
|
||||||
private final List<Attachment> ColourAttachments;
|
private final List<Attachment> ColourAttachments;
|
||||||
private final Attachment DepthAttachment;
|
private final Attachment DepthAttachment;
|
||||||
private final int Height;
|
private final int Height;
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,20 @@ package net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.
|
||||||
import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig;
|
import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig;
|
||||||
import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext;
|
import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext;
|
||||||
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DisplayToScreen.ImageView;
|
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DisplayToScreen.ImageView;
|
||||||
|
import org.w3c.dom.Text;
|
||||||
|
|
||||||
import static org.lwjgl.vulkan.VK13.*;
|
import static org.lwjgl.vulkan.VK13.*;
|
||||||
public class Attachment {
|
public class Attachment {
|
||||||
private final Image VkImage;
|
private final Image VkImage;
|
||||||
private final ImageView VkImageView;
|
private final ImageView VkImageView;
|
||||||
private boolean DepthAttachment;
|
private boolean DepthAttachment;
|
||||||
|
|
||||||
|
public Attachment(VulkanContext VkCtx, Texture ExistingImage){
|
||||||
|
VkImageView = ExistingImage.GetImageView();
|
||||||
|
VkImage = ExistingImage.GetImage();
|
||||||
|
DepthAttachment = VkImageView.IsDepthImage();
|
||||||
|
}
|
||||||
|
|
||||||
public Attachment(VulkanContext VkCtx, int Width, int Height, int Format, int Usage, boolean MultiSamples){
|
public Attachment(VulkanContext VkCtx, int Width, int Height, int Format, int Usage, boolean MultiSamples){
|
||||||
var ImageData = new Image.ImageData().Width(Width).Height(Height).Format(Format).SampleCount(EngineConfig.getInstance().GetRenderSampleCount());
|
var ImageData = new Image.ImageData().Width(Width).Height(Height).Format(Format).SampleCount(EngineConfig.getInstance().GetRenderSampleCount());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ public class Texture implements ITexture {
|
||||||
.AspectMask(VK_IMAGE_ASPECT_COLOR_BIT).MipLevels(MipMapLevels);
|
.AspectMask(VK_IMAGE_ASPECT_COLOR_BIT).MipLevels(MipMapLevels);
|
||||||
imageView = new ImageView(VkCtx.GetDevice(), image.getVulkanImage(), ImageViewData, false);
|
imageView = new ImageView(VkCtx.GetDevice(), image.getVulkanImage(), ImageViewData, false);
|
||||||
}
|
}
|
||||||
|
public Image GetImage(){return image;}
|
||||||
public boolean HasTransparency(){return Transparent;}
|
public boolean HasTransparency(){return Transparent;}
|
||||||
public void SetTransparency(ByteBuffer data){
|
public void SetTransparency(ByteBuffer data){
|
||||||
int PixelCount = data.capacity()/4;
|
int PixelCount = data.capacity()/4;
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ import java.util.UUID;
|
||||||
import static org.lwjgl.vulkan.VK10.VK_FORMAT_R8G8B8A8_SRGB;
|
import static org.lwjgl.vulkan.VK10.VK_FORMAT_R8G8B8A8_SRGB;
|
||||||
|
|
||||||
public class TextureCache implements ITextureCache {
|
public class TextureCache implements ITextureCache {
|
||||||
public static final int MAX_TEXTURES = 256;
|
public static final int MAX_TEXTURES = 512;
|
||||||
private final IndexedLinkedHashMap<String, ITexture> TextureMap;
|
private final IndexedLinkedHashMap<String, ITexture> TextureMap;
|
||||||
private final IndexedLinkedHashMap<String, ITexture> CubemapTextures;
|
private final IndexedLinkedHashMap<String, ITexture> CubemapTextures;
|
||||||
private final List<String> ActualTextures;
|
private final List<String> ActualTextures;
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ public class PostProcess {
|
||||||
private static final String MULTI_PASS_FRAGMENT_SHADER_FILE_SPV = MULTI_PASS_FRAGMENT_SHADER_FILE_GLSL + ".spv";
|
private static final String MULTI_PASS_FRAGMENT_SHADER_FILE_SPV = MULTI_PASS_FRAGMENT_SHADER_FILE_GLSL + ".spv";
|
||||||
private static final String SINGLE_PASS_FRAGMENT_SHADER_FILE_GLSL = "resources/EngineResources/shaders/post_process_frag.glsl";
|
private static final String SINGLE_PASS_FRAGMENT_SHADER_FILE_GLSL = "resources/EngineResources/shaders/post_process_frag.glsl";
|
||||||
private static final String SINGLE_PASS_FRAGMENT_SHADER_FILE_SPV = SINGLE_PASS_FRAGMENT_SHADER_FILE_GLSL + ".spv";
|
private static final String SINGLE_PASS_FRAGMENT_SHADER_FILE_SPV = SINGLE_PASS_FRAGMENT_SHADER_FILE_GLSL + ".spv";
|
||||||
private static final String VERTEX_SHADER_FILE_GLSL = "resources/EngineResources/shaders/post_process_vtx.glsl";
|
private static final String VERTEX_SHADER_FILE_GLSL = "resources/EngineResources/shaders/basic_screen_vertex.glsl";
|
||||||
private static final String VERTEX_SHADER_FILE_SPV = VERTEX_SHADER_FILE_GLSL + ".spv";
|
private static final String VERTEX_SHADER_FILE_SPV = VERTEX_SHADER_FILE_GLSL + ".spv";
|
||||||
|
|
||||||
private final DescriptorSetLayout AttachmentDescriptorSetLayout;
|
private final DescriptorSetLayout AttachmentDescriptorSetLayout;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,442 @@
|
||||||
|
package net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.ScreenSpace;
|
||||||
|
|
||||||
|
import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig;
|
||||||
|
import net.halbear.Terrain4J.EngineCore.Logic.EngineInstance;
|
||||||
|
import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext;
|
||||||
|
import net.halbear.Terrain4J.EngineCore.Main.Scene.IScene;
|
||||||
|
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Universal.SSAO.SSAO_Utils;
|
||||||
|
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.DeferredRendering.MultiRenderTargetAttachments;
|
||||||
|
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.EmptyVertexBufferStruct;
|
||||||
|
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.DefaultPipeline;
|
||||||
|
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.Images.Attachment;
|
||||||
|
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.Images.Image;
|
||||||
|
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.Images.ImageSrc;
|
||||||
|
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.Images.Texture;
|
||||||
|
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.Pipeline;
|
||||||
|
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.PipelineBuildInfo;
|
||||||
|
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Shader.*;
|
||||||
|
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DeviceLayers.CommandBuffer;
|
||||||
|
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DeviceLayers.CommandPool;
|
||||||
|
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DeviceLayers.Queues.Queue;
|
||||||
|
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DisplayToScreen.ImageView;
|
||||||
|
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.SwapChain.SwapChain;
|
||||||
|
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Util.VulkanBuffer;
|
||||||
|
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Util.VulkanUtils;
|
||||||
|
import org.lwjgl.system.MemoryStack;
|
||||||
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
import org.lwjgl.util.shaderc.Shaderc;
|
||||||
|
import org.lwjgl.vulkan.*;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.FloatBuffer;
|
||||||
|
import java.nio.LongBuffer;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.DeferredRendering.MultiRenderTargetAttachments.SSAO_BLUR_ATTACHMENT;
|
||||||
|
import static net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.DeferredRendering.MultiRenderTargetAttachments.SSAO_RAW_ATTACHMENT;
|
||||||
|
import static org.lwjgl.vulkan.VK10.*;
|
||||||
|
import static org.lwjgl.vulkan.VK10.VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||||
|
import static org.lwjgl.vulkan.VK13.*;
|
||||||
|
|
||||||
|
public class AmbientOcclusionRenderer {
|
||||||
|
|
||||||
|
private static final long SSAO_INFO_BUFFER_SIZE =
|
||||||
|
VulkanUtils.MATRIX4X4_SIZE + // projection
|
||||||
|
VulkanUtils.MATRIX4X4_SIZE + // view
|
||||||
|
VulkanUtils.VEC4_SIZE + // screenSize.xy, radius, bias
|
||||||
|
VulkanUtils.VEC4_SIZE; // kernelSize + padding
|
||||||
|
private static final int SSAO_KERNEL_SIZE = 32;
|
||||||
|
private static final float SSAO_RADIUS = 5.0f;
|
||||||
|
private static final float SSAO_BIAS = 0.15f;
|
||||||
|
private static final long SSAO_KERNEL_BUFFER_SIZE = SSAO_KERNEL_SIZE * 4L * VulkanUtils.FLOAT_SIZE;
|
||||||
|
|
||||||
|
private static final String DESC_ID_SSAO_ATTACHMENTS = "SSAO_DESC_ID_ATTACHMENTS";
|
||||||
|
private static final String DESC_ID_SSAO_KERNEL = "SSAO_DESC_ID_KERNEL";
|
||||||
|
private static final String DESC_ID_SSAO_INFO = "SSAO_DESC_ID_INFO";
|
||||||
|
private static final String DESC_ID_SSAO_BLUR_INPUT = "SSAO_DESC_ID_BLUR_INPUT";
|
||||||
|
|
||||||
|
private static final String BLUR_FRAGMENT_SHADER_FILE_GLSL = "resources/EngineResources/shaders/ssao_blur_frag.glsl";
|
||||||
|
private static final String BLUR_FRAGMENT_SHADER_FILE_SPV = BLUR_FRAGMENT_SHADER_FILE_GLSL + ".spv";
|
||||||
|
private static final String FRAGMENT_SHADER_FILE_GLSL = "resources/EngineResources/shaders/ssao_frag.glsl";
|
||||||
|
private static final String FRAGMENT_SHADER_FILE_SPV = FRAGMENT_SHADER_FILE_GLSL + ".spv";
|
||||||
|
private static final String VERTEX_SHADER_FILE_GLSL = "resources/EngineResources/shaders/basic_screen_vertex.glsl";
|
||||||
|
private static final String VERTEX_SHADER_FILE_SPV = VERTEX_SHADER_FILE_GLSL + ".spv";
|
||||||
|
private Attachment ssaoAttachment;
|
||||||
|
private VkRenderingAttachmentInfo.Buffer ssaoAttachmentInfo;
|
||||||
|
private Attachment ssaoBlurAttachment;
|
||||||
|
private VkRenderingAttachmentInfo.Buffer ssaoBlurAttachmentInfo;
|
||||||
|
private final Attachment[] SSAO_ATTACHMENTS = new Attachment[2];
|
||||||
|
|
||||||
|
private final Pipeline ssaoPipeline;
|
||||||
|
private final Pipeline blurPipeline;
|
||||||
|
private final TextureSampler textureSampler;
|
||||||
|
|
||||||
|
private DescriptorSetLayout ssaoAttachmentDescriptorLayout;
|
||||||
|
private DescriptorSetLayout ssaoKernelDescriptorLayout;
|
||||||
|
private DescriptorSetLayout ssaoInfoDescriptorLayout;
|
||||||
|
private DescriptorSetLayout blurDescriptorLayout;
|
||||||
|
|
||||||
|
private final VkClearValue clearColour;
|
||||||
|
private VulkanBuffer sampleKernelBuffer;
|
||||||
|
private VkRenderingInfo ssaoRenderInfo;
|
||||||
|
private VkRenderingInfo ssaoBlurRenderInfo;
|
||||||
|
|
||||||
|
private VulkanBuffer[] ssaoInfoBuffers;
|
||||||
|
|
||||||
|
private Texture NoiseTexture;
|
||||||
|
private Attachment NoiseImageAttachment;
|
||||||
|
|
||||||
|
public AmbientOcclusionRenderer(VulkanContext VkCtx, List<Attachment> MRTAttachments, Queue queue) {
|
||||||
|
List<Attachment> attachments = new ArrayList<>();
|
||||||
|
attachments.add(MRTAttachments.get(0)); // position
|
||||||
|
attachments.add(MRTAttachments.get(2)); // normal
|
||||||
|
CreateAttachments(VkCtx);
|
||||||
|
clearColour = VkClearValue.calloc().color(
|
||||||
|
c -> c.float32(0, 0.0f).float32(1, 0.0f).float32(2, 0.0f).float32(3, 0.0f));
|
||||||
|
ssaoAttachmentInfo = CreateColourAttachmentInfo(ssaoAttachment, clearColour);
|
||||||
|
ssaoBlurAttachmentInfo = CreateColourAttachmentInfo(ssaoBlurAttachment, clearColour);
|
||||||
|
var textureSamplerInfo = new TextureSamplerInfo(VK_SAMPLER_ADDRESS_MODE_REPEAT,
|
||||||
|
VK_BORDER_COLOR_INT_OPAQUE_BLACK, 1, true);
|
||||||
|
textureSampler = new TextureSampler(VkCtx, textureSamplerInfo);
|
||||||
|
|
||||||
|
ByteBuffer NoiseTexturedata = SSAO_Utils.GenerateNoiseTexture();
|
||||||
|
ImageSrc imageSrc = new ImageSrc(NoiseTexturedata, 4, 4,4);
|
||||||
|
NoiseTexture = new Texture(VkCtx,"SSAO_NOISE_SAMPLE", imageSrc,VK_FORMAT_R32G32B32A32_SFLOAT);
|
||||||
|
|
||||||
|
var commandPool = new CommandPool(VkCtx, queue.GetQueueFamilyIndex(), false);
|
||||||
|
var commandBuffer = new CommandBuffer(VkCtx, commandPool, true, true);
|
||||||
|
commandBuffer.BeginRecording();
|
||||||
|
NoiseTexture.RecordTextureTransition(commandBuffer);
|
||||||
|
commandBuffer.EndRecording();
|
||||||
|
commandBuffer.SubmitAndWait(VkCtx, queue);
|
||||||
|
commandBuffer.cleanup(VkCtx,commandPool);
|
||||||
|
commandPool.cleanup(VkCtx);
|
||||||
|
|
||||||
|
NoiseImageAttachment = new Attachment(VkCtx, NoiseTexture);
|
||||||
|
|
||||||
|
attachments.add(NoiseImageAttachment);
|
||||||
|
|
||||||
|
ssaoKernelDescriptorLayout = new DescriptorSetLayout(VkCtx, new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||||
|
0, 1, VK_SHADER_STAGE_FRAGMENT_BIT));
|
||||||
|
sampleKernelBuffer = VulkanUtils.CreateHostVisibleBuffer(VkCtx, SSAO_KERNEL_BUFFER_SIZE, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
|
||||||
|
DESC_ID_SSAO_KERNEL, ssaoKernelDescriptorLayout);
|
||||||
|
long MappedMemory = sampleKernelBuffer.MapMemory(VkCtx);
|
||||||
|
FloatBuffer KernelBuffer = SSAO_Utils.GenerateSampleKernel(SSAO_KERNEL_SIZE, MappedMemory);
|
||||||
|
sampleKernelBuffer.UnMapMemory(VkCtx);
|
||||||
|
|
||||||
|
int numAttachments = attachments.size();
|
||||||
|
DescriptorSetLayout.LayoutInformation[] descSetLayouts = new DescriptorSetLayout.LayoutInformation[numAttachments];
|
||||||
|
for (int i = 0; i < numAttachments; i++) {
|
||||||
|
descSetLayouts[i] = new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, i, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||||
|
}
|
||||||
|
ssaoAttachmentDescriptorLayout = new DescriptorSetLayout(VkCtx, descSetLayouts);
|
||||||
|
CreateSSAOAttachmentDescriptorSet(VkCtx, attachments);
|
||||||
|
|
||||||
|
ssaoInfoDescriptorLayout = new DescriptorSetLayout(VkCtx,new DescriptorSetLayout.LayoutInformation( VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||||
|
0,1,VK_SHADER_STAGE_FRAGMENT_BIT ));
|
||||||
|
|
||||||
|
blurDescriptorLayout = new DescriptorSetLayout(VkCtx,new DescriptorSetLayout.LayoutInformation( VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||||
|
0,1,VK_SHADER_STAGE_FRAGMENT_BIT ));
|
||||||
|
|
||||||
|
CreateBlurDescriptorSet(VkCtx);
|
||||||
|
|
||||||
|
ssaoInfoBuffers = VulkanUtils.CreateHostVisibleBuffers(VkCtx,SSAO_INFO_BUFFER_SIZE, VulkanUtils.MAX_IN_FLIGHT,
|
||||||
|
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, DESC_ID_SSAO_INFO,ssaoInfoDescriptorLayout);
|
||||||
|
|
||||||
|
ssaoRenderInfo = CreateRenderInfo(ssaoAttachment, ssaoAttachmentInfo);
|
||||||
|
ssaoBlurRenderInfo = CreateRenderInfo(ssaoBlurAttachment, ssaoBlurAttachmentInfo);
|
||||||
|
|
||||||
|
ShaderModule[] shaderModules = CreateRawShaderModules(VkCtx);
|
||||||
|
ssaoPipeline = CreatePipeline(VkCtx, shaderModules,
|
||||||
|
new DescriptorSetLayout[]{
|
||||||
|
ssaoAttachmentDescriptorLayout,
|
||||||
|
ssaoKernelDescriptorLayout,
|
||||||
|
ssaoInfoDescriptorLayout
|
||||||
|
},false);
|
||||||
|
Arrays.stream(shaderModules).toList().forEach(shaderModule -> shaderModule.CleanUp(VkCtx));
|
||||||
|
|
||||||
|
shaderModules = CreateBlurShaderModules(VkCtx);
|
||||||
|
blurPipeline = CreatePipeline( VkCtx, shaderModules,
|
||||||
|
new DescriptorSetLayout[]{ blurDescriptorLayout },
|
||||||
|
true );
|
||||||
|
Arrays.stream(shaderModules).toList().forEach(shaderModule -> shaderModule.CleanUp(VkCtx));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static Pipeline CreatePipeline(VulkanContext VkCtx, ShaderModule[] shaderModules, DescriptorSetLayout[] descSetLayouts, boolean blur) {
|
||||||
|
var vtxBuffStruct = new EmptyVertexBufferStruct();
|
||||||
|
var buildInfo = new PipelineBuildInfo(shaderModules, vtxBuffStruct.GetVertexInput(),new int[]{blur ? SSAO_BLUR_ATTACHMENT : SSAO_RAW_ATTACHMENT})
|
||||||
|
.SetDescriptorSetLayouts(descSetLayouts)
|
||||||
|
.BlendingIsUsed(false)
|
||||||
|
.SetDepthWrite(false)
|
||||||
|
.SetDepthTest(false);
|
||||||
|
var pipeline = new DefaultPipeline(VkCtx, buildInfo);
|
||||||
|
vtxBuffStruct.CleanUp();
|
||||||
|
return pipeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ShaderModule[] CreateRawShaderModules(VulkanContext VkCtx) {
|
||||||
|
if (EngineConfig.getInstance().RecompileShaders()) {
|
||||||
|
ShaderCompiler.CompileGLSLShaderOnChange(VERTEX_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_vertex_shader);
|
||||||
|
ShaderCompiler.CompileGLSLShaderOnChange( FRAGMENT_SHADER_FILE_GLSL , Shaderc.shaderc_glsl_fragment_shader);
|
||||||
|
}
|
||||||
|
return new ShaderModule[]{
|
||||||
|
new ShaderModule(VkCtx, VK_SHADER_STAGE_VERTEX_BIT, VERTEX_SHADER_FILE_SPV, null),
|
||||||
|
new ShaderModule(VkCtx, VK_SHADER_STAGE_FRAGMENT_BIT, FRAGMENT_SHADER_FILE_SPV, null),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ShaderModule[] CreateBlurShaderModules(VulkanContext VkCtx) {
|
||||||
|
if (EngineConfig.getInstance().RecompileShaders()) {
|
||||||
|
ShaderCompiler.CompileGLSLShaderOnChange(VERTEX_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_vertex_shader);
|
||||||
|
ShaderCompiler.CompileGLSLShaderOnChange( BLUR_FRAGMENT_SHADER_FILE_GLSL , Shaderc.shaderc_glsl_fragment_shader);
|
||||||
|
}
|
||||||
|
return new ShaderModule[]{
|
||||||
|
new ShaderModule(VkCtx, VK_SHADER_STAGE_VERTEX_BIT, VERTEX_SHADER_FILE_SPV, null),
|
||||||
|
new ShaderModule(VkCtx, VK_SHADER_STAGE_FRAGMENT_BIT, BLUR_FRAGMENT_SHADER_FILE_SPV, null),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static VkRenderingAttachmentInfo.Buffer CreateColourAttachmentInfo(Attachment attachment, VkClearValue clearValue) {
|
||||||
|
return VkRenderingAttachmentInfo.calloc(1)
|
||||||
|
.sType$Default()
|
||||||
|
.imageView(attachment.GetVkImageView().GetVulkanImageView())
|
||||||
|
.imageLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
|
||||||
|
.loadOp(VK_ATTACHMENT_LOAD_OP_CLEAR)
|
||||||
|
.storeOp(VK_ATTACHMENT_STORE_OP_STORE)
|
||||||
|
.clearValue(clearValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static VkRenderingInfo CreateRenderInfo(Attachment attachment, VkRenderingAttachmentInfo.Buffer attachmentInfo) {
|
||||||
|
return VkRenderingInfo.calloc()
|
||||||
|
.sType$Default()
|
||||||
|
.renderArea(area -> area
|
||||||
|
.offset(offset -> offset.x(0).y(0))
|
||||||
|
.extent(extent -> extent
|
||||||
|
.width(attachment.GetVkImage().GetWidth())
|
||||||
|
.height(attachment.GetVkImage().GetHeight())))
|
||||||
|
.layerCount(1)
|
||||||
|
.pColorAttachments(attachmentInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateSSAOAttachmentDescriptorSet(VulkanContext vkCtx, List<Attachment> Attachments ) {
|
||||||
|
DescriptorSet descSet = vkCtx.GetDescriptorAllocator().AddDescriptorSet(
|
||||||
|
vkCtx.GetDevice(), DESC_ID_SSAO_ATTACHMENTS,ssaoAttachmentDescriptorLayout );
|
||||||
|
|
||||||
|
List<ImageView> imageViews = new ArrayList<>();
|
||||||
|
Attachments.forEach(a -> imageViews.add(a.GetVkImageView()));
|
||||||
|
|
||||||
|
descSet.SetImages(vkCtx.GetDevice(), imageViews, textureSampler, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void CreateBlurDescriptorSet(VulkanContext vkCtx) {
|
||||||
|
DescriptorSet descSet = vkCtx.GetDescriptorAllocator().AddDescriptorSet(
|
||||||
|
vkCtx.GetDevice(),DESC_ID_SSAO_BLUR_INPUT, blurDescriptorLayout);
|
||||||
|
|
||||||
|
descSet.SetImage(vkCtx.GetDevice(), ssaoAttachment.GetVkImageView(),
|
||||||
|
textureSampler,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateAttachments(VulkanContext VkCtx){
|
||||||
|
SwapChain swapChain = VkCtx.GetSwapChain();
|
||||||
|
VkExtent2D swapChainExtent = swapChain.GetSwapChainExtent();
|
||||||
|
//SSAO Raw
|
||||||
|
ssaoAttachment = new Attachment(VkCtx, swapChainExtent.width(), swapChainExtent.height(), SSAO_RAW_ATTACHMENT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, 1);
|
||||||
|
SSAO_ATTACHMENTS[0] = ssaoAttachment;
|
||||||
|
//SSAO Blur
|
||||||
|
ssaoBlurAttachment = new Attachment(VkCtx, swapChainExtent.width(), swapChainExtent.height(), SSAO_BLUR_ATTACHMENT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, 1);
|
||||||
|
SSAO_ATTACHMENTS[1] = ssaoBlurAttachment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Render(VulkanContext VkCtx,EngineInstance engineInstance, CommandBuffer cmdBuffer, MultiRenderTargetAttachments MRT,int CurrentFrame) {
|
||||||
|
try (var stack = MemoryStack.stackPush()) {
|
||||||
|
|
||||||
|
|
||||||
|
VkCommandBuffer cmdHandle = cmdBuffer.GetVulkanCommandBuffer();
|
||||||
|
|
||||||
|
UpdateSSAOInfo(VkCtx, engineInstance, CurrentFrame);
|
||||||
|
|
||||||
|
VulkanUtils.ImageBarrier(stack, cmdHandle, ssaoAttachment.GetVkImage().getVulkanImage(),
|
||||||
|
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||||
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||||
|
VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT,
|
||||||
|
VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||||
|
VK_ACCESS_2_SHADER_READ_BIT,
|
||||||
|
VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT,
|
||||||
|
VK_IMAGE_ASPECT_COLOR_BIT);
|
||||||
|
|
||||||
|
TransitionMRTtoReadOnly(stack, cmdHandle, MRT);
|
||||||
|
|
||||||
|
|
||||||
|
vkCmdBeginRendering(cmdHandle, ssaoRenderInfo);
|
||||||
|
|
||||||
|
vkCmdBindPipeline(cmdHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, ssaoPipeline.GetVulkanPipeline());
|
||||||
|
|
||||||
|
SetViewportAndScissor(stack, cmdHandle, ssaoAttachment);
|
||||||
|
|
||||||
|
DescriptorAllocator descAllocator = VkCtx.GetDescriptorAllocator();
|
||||||
|
LongBuffer descriptorSets = stack.mallocLong(3)
|
||||||
|
.put(0, descAllocator.GetDescriptorSet(DESC_ID_SSAO_ATTACHMENTS).GetVkDescriptorSet())
|
||||||
|
.put(1, descAllocator.GetDescriptorSet(DESC_ID_SSAO_KERNEL).GetVkDescriptorSet())
|
||||||
|
.put(2, descAllocator.GetDescriptorSet(DESC_ID_SSAO_INFO, CurrentFrame).GetVkDescriptorSet());
|
||||||
|
|
||||||
|
vkCmdBindDescriptorSets(cmdHandle, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
|
ssaoPipeline.GetVulkanPipelineLayout(), 0, descriptorSets, null);
|
||||||
|
|
||||||
|
vkCmdDraw(cmdHandle, 3, 1, 0, 0);
|
||||||
|
|
||||||
|
vkCmdEndRendering(cmdHandle);
|
||||||
|
|
||||||
|
//blur pass
|
||||||
|
VulkanUtils.ImageBarrier(stack, cmdHandle, ssaoAttachment.GetVkImage().getVulkanImage(),
|
||||||
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||||
|
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||||
|
VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||||
|
VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT,
|
||||||
|
VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT,
|
||||||
|
VK_ACCESS_2_SHADER_READ_BIT,
|
||||||
|
VK_IMAGE_ASPECT_COLOR_BIT);
|
||||||
|
|
||||||
|
VulkanUtils.ImageBarrier(stack, cmdHandle, ssaoBlurAttachment.GetVkImage().getVulkanImage(),
|
||||||
|
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||||
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||||
|
VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT,
|
||||||
|
VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||||
|
VK_ACCESS_2_SHADER_READ_BIT,
|
||||||
|
VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT,
|
||||||
|
VK_IMAGE_ASPECT_COLOR_BIT);
|
||||||
|
|
||||||
|
vkCmdBeginRendering(cmdHandle, ssaoBlurRenderInfo);
|
||||||
|
|
||||||
|
vkCmdBindPipeline(cmdHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, blurPipeline.GetVulkanPipeline());
|
||||||
|
|
||||||
|
SetViewportAndScissor(stack, cmdHandle, ssaoBlurAttachment);
|
||||||
|
|
||||||
|
LongBuffer blurDescriptorSets = stack.mallocLong(1)
|
||||||
|
.put(0, descAllocator.GetDescriptorSet(DESC_ID_SSAO_BLUR_INPUT).GetVkDescriptorSet());
|
||||||
|
|
||||||
|
vkCmdBindDescriptorSets(cmdHandle,VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
|
blurPipeline.GetVulkanPipelineLayout(),0, blurDescriptorSets,null );
|
||||||
|
|
||||||
|
vkCmdDraw(cmdHandle, 3, 1, 0, 0);
|
||||||
|
|
||||||
|
vkCmdEndRendering(cmdHandle);
|
||||||
|
|
||||||
|
VulkanUtils.ImageBarrier( stack, cmdHandle, ssaoBlurAttachment.GetVkImage().getVulkanImage(),
|
||||||
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||||
|
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||||
|
VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||||
|
VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT,
|
||||||
|
VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT,
|
||||||
|
VK_ACCESS_2_SHADER_READ_BIT,
|
||||||
|
VK_IMAGE_ASPECT_COLOR_BIT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void TransitionMRTtoReadOnly(MemoryStack stack,VkCommandBuffer cmdHandle, MultiRenderTargetAttachments MRT) {
|
||||||
|
List<Attachment> attachments = MRT.GetColourAttachments();
|
||||||
|
|
||||||
|
for (Attachment attachment : attachments) {
|
||||||
|
VulkanUtils.ImageBarrier( stack,cmdHandle, attachment.GetVkImage().getVulkanImage(),
|
||||||
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||||
|
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||||
|
VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||||
|
VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT,
|
||||||
|
VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT,
|
||||||
|
VK_ACCESS_2_SHADER_READ_BIT,
|
||||||
|
VK_IMAGE_ASPECT_COLOR_BIT
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetViewportAndScissor(MemoryStack stack, VkCommandBuffer cmdHandle, Attachment attachment){
|
||||||
|
Image ColourImage = attachment.GetVkImage();
|
||||||
|
int width = ColourImage.GetWidth();
|
||||||
|
int height = ColourImage.GetHeight();
|
||||||
|
var viewport = VkViewport.calloc(1, stack)
|
||||||
|
.x(0)
|
||||||
|
.y(height)
|
||||||
|
.height(-height)
|
||||||
|
.width(width)
|
||||||
|
.minDepth(0.0f)
|
||||||
|
.maxDepth(1.0f);
|
||||||
|
vkCmdSetViewport(cmdHandle, 0, viewport);
|
||||||
|
|
||||||
|
var scissor = VkRect2D.calloc(1, stack)
|
||||||
|
.extent(it -> it.width(width).height(height))
|
||||||
|
.offset(it -> it.x(0).y(0));
|
||||||
|
vkCmdSetScissor(cmdHandle, 0, scissor);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateSSAOInfo(VulkanContext vkCtx, EngineInstance engineInstance, int currentFrame) {
|
||||||
|
VulkanBuffer buffer = ssaoInfoBuffers[currentFrame];
|
||||||
|
long mappedMemory = buffer.MapMemory(vkCtx);
|
||||||
|
ByteBuffer data = MemoryUtil.memByteBuffer(mappedMemory, (int) buffer.GetRequestedSize());
|
||||||
|
|
||||||
|
int offset = 0;
|
||||||
|
|
||||||
|
engineInstance.scene().GetProjection().GetProjectionMatrix().get(offset, data);
|
||||||
|
offset += VulkanUtils.MATRIX4X4_SIZE;
|
||||||
|
|
||||||
|
engineInstance.scene().GetCamera().GetViewMatrix().get(offset, data);
|
||||||
|
offset += VulkanUtils.MATRIX4X4_SIZE;
|
||||||
|
|
||||||
|
data.putFloat(offset, ssaoAttachment.GetVkImage().GetWidth());
|
||||||
|
data.putFloat(offset + VulkanUtils.FLOAT_SIZE, ssaoAttachment.GetVkImage().GetHeight());
|
||||||
|
data.putFloat(offset + VulkanUtils.FLOAT_SIZE * 2, SSAO_RADIUS);
|
||||||
|
data.putFloat(offset + VulkanUtils.FLOAT_SIZE * 3, SSAO_BIAS);
|
||||||
|
offset += VulkanUtils.VEC4_SIZE;
|
||||||
|
|
||||||
|
data.putInt(offset, SSAO_KERNEL_SIZE);
|
||||||
|
|
||||||
|
buffer.UnMapMemory(vkCtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Attachment getSSAOBlurAttachment() {
|
||||||
|
return ssaoBlurAttachment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resize(VulkanContext VkCtx, List<Attachment> attachments) {
|
||||||
|
ssaoRenderInfo.free();
|
||||||
|
ssaoBlurRenderInfo.free();
|
||||||
|
ssaoAttachmentInfo.free();
|
||||||
|
ssaoAttachment.CleanUp(VkCtx);
|
||||||
|
ssaoBlurAttachmentInfo.free();
|
||||||
|
ssaoBlurAttachment.CleanUp(VkCtx);
|
||||||
|
|
||||||
|
CreateAttachments(VkCtx);
|
||||||
|
|
||||||
|
ssaoAttachmentInfo = CreateColourAttachmentInfo(ssaoAttachment, clearColour);
|
||||||
|
ssaoBlurAttachmentInfo = CreateColourAttachmentInfo(ssaoBlurAttachment, clearColour);
|
||||||
|
ssaoRenderInfo = CreateRenderInfo(ssaoAttachment, ssaoAttachmentInfo);
|
||||||
|
ssaoBlurRenderInfo = CreateRenderInfo(ssaoBlurAttachment, ssaoBlurAttachmentInfo);
|
||||||
|
|
||||||
|
attachments.add(NoiseImageAttachment);
|
||||||
|
|
||||||
|
CreateSSAOAttachmentDescriptorSet(VkCtx,attachments);
|
||||||
|
CreateBlurDescriptorSet(VkCtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cleanup(VulkanContext VkCtx) {
|
||||||
|
ssaoRenderInfo.free();
|
||||||
|
ssaoBlurRenderInfo.free();
|
||||||
|
ssaoAttachmentInfo.free();
|
||||||
|
ssaoAttachment.CleanUp(VkCtx);
|
||||||
|
ssaoBlurAttachmentInfo.free();
|
||||||
|
ssaoBlurAttachment.CleanUp(VkCtx);
|
||||||
|
ssaoPipeline.CleanUp(VkCtx);
|
||||||
|
blurPipeline.CleanUp(VkCtx);
|
||||||
|
clearColour.free();
|
||||||
|
Arrays.stream(ssaoInfoBuffers).toList().forEach(b -> b.cleanup(VkCtx));
|
||||||
|
sampleKernelBuffer.cleanup(VkCtx);
|
||||||
|
ssaoAttachmentDescriptorLayout.CleanUp(VkCtx);
|
||||||
|
blurDescriptorLayout.CleanUp(VkCtx);
|
||||||
|
ssaoInfoDescriptorLayout.CleanUp(VkCtx);
|
||||||
|
ssaoKernelDescriptorLayout.CleanUp(VkCtx);
|
||||||
|
NoiseTexture.CleanUp(VkCtx);
|
||||||
|
textureSampler.CleanUp(VkCtx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Shader;
|
package net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Shader;
|
||||||
|
|
||||||
|
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.Images.TextureCache;
|
||||||
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DeviceLayers.Device;
|
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DeviceLayers.Device;
|
||||||
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DisplayToScreen.ImageView;
|
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DisplayToScreen.ImageView;
|
||||||
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Util.VulkanBuffer;
|
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Util.VulkanBuffer;
|
||||||
|
|
@ -100,9 +101,19 @@ public class DescriptorSet {
|
||||||
public void SetImageArray(Device device, List<ImageView> imageViews, TextureSampler textureSampler, int BaseBinding){
|
public void SetImageArray(Device device, List<ImageView> imageViews, TextureSampler textureSampler, int BaseBinding){
|
||||||
try(var MemStack = MemoryStack.stackPush()){
|
try(var MemStack = MemoryStack.stackPush()){
|
||||||
int ImageCount = imageViews.size();
|
int ImageCount = imageViews.size();
|
||||||
|
if (textureSampler == null || textureSampler.GetVkSampler() == 0) {
|
||||||
|
throw new NullPointerException("The provided TextureSampler is uninitialized or null!");
|
||||||
|
}
|
||||||
VkDescriptorImageInfo.Buffer imageInfos = VkDescriptorImageInfo.calloc(ImageCount,MemStack);
|
VkDescriptorImageInfo.Buffer imageInfos = VkDescriptorImageInfo.calloc(ImageCount,MemStack);
|
||||||
for(int i = 0; i < ImageCount; i++){
|
for(int i = 0; i < ImageCount; i++){
|
||||||
|
|
||||||
ImageView imageView = imageViews.get(i);
|
ImageView imageView = imageViews.get(i);
|
||||||
|
if (imageView == null || imageView.GetVulkanImageView() == 0) {
|
||||||
|
Logger.error("Texture or ImageView at index " + i + " is NULL! Check your material cache loading.");
|
||||||
|
imageView = imageViews.getFirst();
|
||||||
|
if(imageView == null || imageView.GetVulkanImageView() == 0) throw new NullPointerException("The provided TextureSampler is uninitialized or null!");
|
||||||
|
}
|
||||||
|
|
||||||
VkDescriptorImageInfo imageInfo = imageInfos.get(i);
|
VkDescriptorImageInfo imageInfo = imageInfos.get(i);
|
||||||
imageInfo.imageView(imageView.GetVulkanImageView()).sampler(textureSampler.GetVkSampler());
|
imageInfo.imageView(imageView.GetVulkanImageView()).sampler(textureSampler.GetVkSampler());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,5 +2,5 @@ package net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.VkModel;
|
||||||
|
|
||||||
import org.joml.Vector4f;
|
import org.joml.Vector4f;
|
||||||
|
|
||||||
public record MaterialData(String ID, String TexturePath,String NormalTexturePath,String MetalRoughnessMap, Vector4f DiffuseColour,float Roughness, float Metallic, String EmissiveTexture,Vector4f EmissiveColour, String TranslucencyTexture, float Translucency, String OpacityTexture, float Opacity) {
|
public record MaterialData(String ID, String TexturePath,String NormalTexturePath,String MetalRoughnessMap, Vector4f DiffuseColour,float Roughness, float Metallic, String EmissiveTexture,Vector4f EmissiveColour, String TranslucencyTexture, float Translucency, String OpacityTexture, float Opacity, Vector4f ColorTransparency, float Refractiveness, float Reflectiveness) {
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -205,9 +205,11 @@ public class SpriteRenderer {
|
||||||
public void LoadMaterials(VulkanContext VkCtx, MaterialsCache materialsCache, TextureCache textureCache){
|
public void LoadMaterials(VulkanContext VkCtx, MaterialsCache materialsCache, TextureCache textureCache){
|
||||||
DescriptorAllocator descriptorAllocator = VkCtx.GetDescriptorAllocator();
|
DescriptorAllocator descriptorAllocator = VkCtx.GetDescriptorAllocator();
|
||||||
Device device = VkCtx.GetDevice();
|
Device device = VkCtx.GetDevice();
|
||||||
List<ImageView> imageViews = new ArrayList<>(textureCache.GetAll2DTextures().stream().map(ITexture::GetImageView).toList());
|
|
||||||
|
|
||||||
ImageView fallback = textureCache.GetTexture("resources/EngineResources/Texture/NoTexture.png").GetImageView();
|
ImageView fallback = textureCache.GetTexture("resources/EngineResources/Texture/NoTexture.png").GetImageView();
|
||||||
|
List<ImageView> imageViews = new ArrayList<>();
|
||||||
|
imageViews.add(fallback);
|
||||||
|
imageViews.addAll(textureCache.GetAll2DTextures().stream().map(ITexture::GetImageView).toList());
|
||||||
while (imageViews.size() < TextureCache.MAX_TEXTURES) {
|
while (imageViews.size() < TextureCache.MAX_TEXTURES) {
|
||||||
imageViews.add(fallback);
|
imageViews.add(fallback);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ public class SwapChainRender {
|
||||||
private static final String DESCRIPTOR_ID_ATTACHMENT = "FWD_DESC_ID_ATT";
|
private static final String DESCRIPTOR_ID_ATTACHMENT = "FWD_DESC_ID_ATT";
|
||||||
private static final String FRAGMENT_SHADER_FILE_GLSL = "resources/EngineResources/shaders/swap_frag.glsl";
|
private static final String FRAGMENT_SHADER_FILE_GLSL = "resources/EngineResources/shaders/swap_frag.glsl";
|
||||||
private static final String FRAGMENT_SHADER_FILE_SPV = FRAGMENT_SHADER_FILE_GLSL + ".spv";
|
private static final String FRAGMENT_SHADER_FILE_SPV = FRAGMENT_SHADER_FILE_GLSL + ".spv";
|
||||||
private static final String VERTEX_SHADER_FILE_GLSL = "resources/EngineResources/shaders/swap_vtx.glsl";
|
private static final String VERTEX_SHADER_FILE_GLSL = "resources/EngineResources/shaders/basic_screen_vertex.glsl";
|
||||||
private static final String VERTEX_SHADER_FILE_SPV = VERTEX_SHADER_FILE_GLSL + ".spv";
|
private static final String VERTEX_SHADER_FILE_SPV = VERTEX_SHADER_FILE_GLSL + ".spv";
|
||||||
private final DescriptorSetLayout AttachmentDescriptorSetLayout;
|
private final DescriptorSetLayout AttachmentDescriptorSetLayout;
|
||||||
private final VkClearValue ClearValueColour;
|
private final VkClearValue ClearValueColour;
|
||||||
|
|
|
||||||
|
|
@ -160,7 +160,7 @@ public class VulkanUtils {
|
||||||
descriptorAllocator.AddDescriptorSets(device, ID, BufferCount, layout);
|
descriptorAllocator.AddDescriptorSets(device, ID, BufferCount, layout);
|
||||||
DescriptorSetLayout.LayoutInformation LayoutInfo = layout.GetLayoutInfo();
|
DescriptorSetLayout.LayoutInformation LayoutInfo = layout.GetLayoutInfo();
|
||||||
for(int i = 0; i < BufferCount; i++){
|
for(int i = 0; i < BufferCount; i++){
|
||||||
Result[i] = new VulkanBuffer(VkCtx, BufferSize, Usage,VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE,VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
|
Result[i] = new VulkanBuffer(VkCtx, BufferSize, Usage,VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE,VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
||||||
DescriptorSet descriptorSet = descriptorAllocator.GetDescriptorSet(ID, i);
|
DescriptorSet descriptorSet = descriptorAllocator.GetDescriptorSet(ID, i);
|
||||||
descriptorSet.SetBuffer(device, Result[i], Result[i].GetRequestedSize(), layout.GetLayoutInfo().Binding(),layout.GetLayoutInfo().DescriptorType());
|
descriptorSet.SetBuffer(device, Result[i], Result[i].GetRequestedSize(), layout.GetLayoutInfo().Binding(),layout.GetLayoutInfo().DescriptorType());
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue