Compare commits

..

No commits in common. "main" and "DeferredRendering" have entirely different histories.

536 changed files with 159165 additions and 30117 deletions

10
.gitignore vendored
View file

@ -27,9 +27,7 @@ build/
.idea/**/dynamic.xml .idea/**/dynamic.xml
.idea/**/uiDesigner.xml .idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml .idea/**/dbnavigator.xml
*.t4jlog
*.spv
*.spv.options
# Gradle # Gradle
.idea/**/gradle.xml .idea/**/gradle.xml
.idea/**/libraries .idea/**/libraries
@ -86,9 +84,3 @@ fabric.properties
/.idea/ /.idea/
/.gradle/buildOutputCleanup/ /.gradle/buildOutputCleanup/
/.gradle/ /.gradle/
/resources/models/bistrohd/
/resources/models/Cafe/
/resources/models/Forest/
/resources/models/tree/
/resources/models/woman/
/docs/

View file

@ -1,25 +1,8 @@
import org.gradle.internal.os.OperatingSystem import org.gradle.internal.os.OperatingSystem
buildscript {
repositories {
mavenCentral()
gradlePluginPortal()
}
}
plugins { plugins {
id 'application' id 'application'
id 'java' id 'java'
id 'com.gradleup.shadow' version '9.2.0'
} }
jar {
manifest {
attributes(
'Main-Class': 'net.halbear.Executable.Launcher'
)
}
}
project.ext.lwjglVersion = "3.4.1" project.ext.lwjglVersion = "3.4.1"
project.ext.jomlVersion = "1.10.8" project.ext.jomlVersion = "1.10.8"
project.ext.jomlprimitivesVersion = "1.10.0" project.ext.jomlprimitivesVersion = "1.10.0"
@ -28,20 +11,37 @@ project.ext.steamworks4jVersion = "1.9.0"
project.ext.steamworks4jserverVersion = "1.9.0" project.ext.steamworks4jserverVersion = "1.9.0"
project.ext.imguiVersion = "1.92.0" project.ext.imguiVersion = "1.92.0"
repositories { switch (OperatingSystem.current()) {
mavenCentral() case OperatingSystem.LINUX:
project.ext.lwjglNatives = "natives-linux"
def osArch = System.getProperty("os.arch")
if (osArch.startsWith("arm") || osArch.startsWith("aarch64")) {
project.ext.lwjglNatives += osArch.contains("64") || osArch.startsWith("armv8") ? "-arm64" : "-arm32"
} else if (osArch.startsWith("ppc")) {
project.ext.lwjglNatives += "-ppc64le"
} else if (osArch.startsWith("riscv")) {
project.ext.lwjglNatives += "-riscv64"
}
break
case OperatingSystem.MAC_OS:
project.ext.lwjglNatives = System.getProperty("os.arch").startsWith("aarch64") ? "natives-macos-arm64" : "natives-macos"
break
case OperatingSystem.WINDOWS:
def osArch = System.getProperty("os.arch")
project.ext.lwjglNatives = osArch.contains("64")
? "natives-windows${osArch.startsWith("aarch64") ? "-arm64" : ""}"
: "natives-windows-x86"
break
} }
application { repositories {
mainClass.set('net.halbear.Executable.Launcher') mavenCentral()
} }
dependencies { dependencies {
implementation platform("org.lwjgl:lwjgl-bom:$lwjglVersion") implementation platform("org.lwjgl:lwjgl-bom:$lwjglVersion")
implementation 'org.tinylog:tinylog-api:2.7.0' implementation 'org.tinylog:tinylog-api:2.7.0'
implementation 'org.tinylog:tinylog-impl:2.7.0' implementation 'org.tinylog:tinylog-impl:2.7.0'
// Core LWJGL modules
implementation "org.lwjgl:lwjgl" implementation "org.lwjgl:lwjgl"
implementation "org.lwjgl:lwjgl-assimp" implementation "org.lwjgl:lwjgl-assimp"
implementation "org.lwjgl:lwjgl-fmod" implementation "org.lwjgl:lwjgl-fmod"
@ -59,29 +59,22 @@ dependencies {
implementation "org.lwjgl:lwjgl-stb" implementation "org.lwjgl:lwjgl-stb"
implementation "org.lwjgl:lwjgl-vma" implementation "org.lwjgl:lwjgl-vma"
implementation "org.lwjgl:lwjgl-vulkan" implementation "org.lwjgl:lwjgl-vulkan"
implementation "org.lwjgl:lwjgl::$lwjglNatives"
implementation "org.lwjgl:lwjgl-assimp::$lwjglNatives"
implementation "org.lwjgl:lwjgl-freetype::$lwjglNatives"
implementation "org.lwjgl:lwjgl-glfw::$lwjglNatives"
implementation "org.lwjgl:lwjgl-jemalloc::$lwjglNatives"
implementation "org.lwjgl:lwjgl-llvm::$lwjglNatives"
implementation "org.lwjgl:lwjgl-lmdb::$lwjglNatives"
implementation "org.lwjgl:lwjgl-meshoptimizer::$lwjglNatives"
implementation "org.lwjgl:lwjgl-openal::$lwjglNatives"
implementation "org.lwjgl:lwjgl-rpmalloc::$lwjglNatives"
implementation "org.lwjgl:lwjgl-remotery:${lwjglVersion}" implementation "org.lwjgl:lwjgl-remotery:${lwjglVersion}"
runtimeOnly "org.lwjgl:lwjgl-remotery:${lwjglVersion}:${lwjglNatives}"
// Define targeted native platforms explicitly implementation "org.lwjgl:lwjgl-shaderc::$lwjglNatives"
def targetNatives = ["natives-windows", "natives-linux"] implementation "org.lwjgl:lwjgl-stb::$lwjglNatives"
implementation "org.lwjgl:lwjgl-vma::$lwjglNatives"
// Loop through and bundle natives for both Windows and Linux if (lwjglNatives == "natives-macos" || lwjglNatives == "natives-macos-arm64") implementation "org.lwjgl:lwjgl-vulkan::$lwjglNatives"
targetNatives.each { target ->
runtimeOnly "org.lwjgl:lwjgl::$target"
runtimeOnly "org.lwjgl:lwjgl-assimp::$target"
runtimeOnly "org.lwjgl:lwjgl-freetype::$target"
runtimeOnly "org.lwjgl:lwjgl-glfw::$target"
runtimeOnly "org.lwjgl:lwjgl-jemalloc::$target"
runtimeOnly "org.lwjgl:lwjgl-llvm::$target"
runtimeOnly "org.lwjgl:lwjgl-lmdb::$target"
runtimeOnly "org.lwjgl:lwjgl-meshoptimizer::$target"
runtimeOnly "org.lwjgl:lwjgl-openal::$target"
runtimeOnly "org.lwjgl:lwjgl-rpmalloc::$target"
runtimeOnly "org.lwjgl:lwjgl-remotery:${lwjglVersion}:$target"
runtimeOnly "org.lwjgl:lwjgl-shaderc::$target"
runtimeOnly "org.lwjgl:lwjgl-stb::$target"
runtimeOnly "org.lwjgl:lwjgl-vma::$target"
}
implementation "org.joml:joml:${jomlVersion}" implementation "org.joml:joml:${jomlVersion}"
implementation "org.joml:joml-primitives:${jomlprimitivesVersion}" implementation "org.joml:joml-primitives:${jomlprimitivesVersion}"
implementation "org.lwjglx:lwjgl3-awt:${lwjgl3awtVersion}" implementation "org.lwjglx:lwjgl3-awt:${lwjgl3awtVersion}"
@ -89,18 +82,13 @@ dependencies {
implementation "com.code-disaster.steamworks4j:steamworks4j-server:${steamworks4jserverVersion}" implementation "com.code-disaster.steamworks4j:steamworks4j-server:${steamworks4jserverVersion}"
implementation 'com.google.code.gson:gson:2.14.0' implementation 'com.google.code.gson:gson:2.14.0'
implementation "org.jcommander:jcommander:3.0" implementation "org.jcommander:jcommander:3.0"
['', '-opengl', '-glfw'].each { ['', '-opengl', '-glfw'].each {
implementation "org.lwjgl:lwjgl$it:$lwjglVersion" implementation "org.lwjgl:lwjgl$it:$lwjglVersion"
runtimeOnly "org.lwjgl:lwjgl$it::natives-windows" implementation "org.lwjgl:lwjgl$it::natives-windows"
runtimeOnly "org.lwjgl:lwjgl$it::natives-linux"
} }
// ImGui Setup
implementation "io.github.spair:imgui-java-binding:$imguiVersion" implementation "io.github.spair:imgui-java-binding:$imguiVersion"
implementation "io.github.spair:imgui-java-lwjgl3:$imguiVersion" implementation "io.github.spair:imgui-java-lwjgl3:$imguiVersion"
// ImGui Natives for both OS environments implementation "io.github.spair:imgui-java-natives-windows:$imguiVersion"
runtimeOnly "io.github.spair:imgui-java-natives-windows:$imguiVersion" }
runtimeOnly "io.github.spair:imgui-java-natives-linux:$imguiVersion"
}

View file

@ -1,10 +0,0 @@
def validationRun = System.currentTimeMillis()
gradle.projectsEvaluated {
allprojects {
tasks.withType(Test).configureEach {
binaryResultsDirectory.set(layout.buildDirectory.dir("renderer-validation/${validationRun}/binary"))
reports.junitXml.outputLocation.set(layout.buildDirectory.dir("renderer-validation/${validationRun}/xml"))
reports.html.outputLocation.set(layout.buildDirectory.dir("renderer-validation/${validationRun}/html"))
}
}
}

View file

@ -1,6 +1,7 @@
#Thu Jun 18 13:00:38 BST 2026
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.0-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

View file

@ -1,13 +0,0 @@
#version 330
in vec2 fragTextCoords;
in vec4 fragColour;
uniform sampler2D textureSampler;
out vec4 outColour;
void main()
{
outColour = fragColour * texture(textureSampler, fragTextCoords);
}

View file

@ -1,17 +0,0 @@
#version 330
layout (location=0) in vec2 inPos;
layout (location=1) in vec2 inTextCoords;
layout (location=2) in vec4 inColour;
out vec2 fragTextCoords;
out vec4 fragColour;
uniform vec2 scale;
void main()
{
fragTextCoords = inTextCoords;
fragColour = inColour;
gl_Position = vec4(inPos * scale + vec2(-1.0, 1.0), 0.0, 1.0);
}

View file

@ -1,172 +0,0 @@
#version 450
#extension GL_EXT_scalar_block_layout: require
// CREDITS: functions obtained from this link: https://github.com/SaschaWillems/Vulkan
// developed by Sascha Willems, https://twitter.com/JoeyDeVriez, licensed under MIT License (MIT)
// also Vulkan Book https://github.com/lwjglgamedev/vulkanbook/blob/master/bookcontents/chapter-15/chapter-15.md
const int MAX_LIGHTS = 32;
const float PI = 3.14159265359;
struct Light {
vec3 position;
uint directional;
float intensity;
vec3 color;
};
in vec2 inTextCoord;
out vec4 outFragColor;
uniform sampler2D outAlbedo;
uniform sampler2D outPosition;
uniform sampler2D outNormals;
uniform sampler2D outPBR;
struct Attenuation
{
float constant;
float linear;
float exponent;
};
struct Light {
vec3 position;
int lightType;
float intensity;
vec3 color;
vec3 conedir;
float cutoff;
Attenuation attenuation;
};
uniform Light lights[MAX_LIGHTS];
struct SceneInfo {
vec3 camPos;
float ambientLightIntensity;
vec3 ambientLightColor;
int LightCount;
};
uniform SceneInfo sceneInfo;
float distributionGGX(vec3 N, vec3 H, float roughness) {
float a = roughness * roughness;
float a2 = a * a;
float NdotH = max(dot(N, H), 0.0);
float NdotH2 = NdotH * NdotH;
float nom = a2;
float denom = (NdotH2 * (a2 - 1.0) + 1.0);
denom = PI * denom * denom;
return nom / denom;
}
float geometrySchlickGGX(float NdotV, float roughness) {
float r = (roughness + 1.0);
float k = (r * r) / 8.0;
float nom = NdotV;
float denom = NdotV * (1.0 - k) + k;
return nom / denom;
}
float geometrySmith(vec3 N, vec3 V, vec3 L, float roughness) {
float NdotV = max(dot(N, V), 0.0);
float NdotL = max(dot(N, L), 0.0);
float ggx2 = geometrySchlickGGX(NdotV, roughness);
float ggx1 = geometrySchlickGGX(NdotL, roughness);
return ggx1 * ggx2;
}
vec3 fresnelSchlick(float cosTheta, vec3 F0) {
return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0);
}
vec3 calculatePointLight(Light light, vec3 worldPos, vec3 V, vec3 N, vec3 F0, vec3 albedo, float metallic, float roughness) {
vec3 tmpSub = light.position - worldPos;
vec3 L = normalize(tmpSub);
vec3 H = normalize(V + L);
// Calculate distance and attenuation
float distance = length(tmpSub);
float attenuation = 1.0 / (distance * distance);
float intensity = 10.0f;
vec3 radiance = light.color * light.intensity * attenuation;
// Cook-Torrance BRDF
float NDF = distributionGGX(N, H, roughness);
float G = geometrySmith(N, V, L, roughness);
vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0);
vec3 numerator = NDF * G * F;
float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001;
vec3 specular = numerator / denominator;
vec3 kS = F;
vec3 kD = vec3(1.0) - kS;
kD *= 1.0 - metallic;
float NdotL = max(dot(N, L), 0.0);
return (kD * albedo / PI + specular) * radiance * NdotL;
}
vec3 calculateDirectionalLight(Light light, vec3 V, vec3 N, vec3 F0, vec3 albedo, float metallic, float roughness) {
vec3 L = normalize(-light.position);
vec3 H = normalize(V + L);
vec3 radiance = light.color * light.intensity;
// Cook-Torrance BRDF
float NDF = distributionGGX(N, H, roughness);
float G = geometrySmith(N, V, L, roughness);
vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0);
vec3 numerator = NDF * G * F;
float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001;
vec3 specular = numerator / denominator;
vec3 kS = F;
vec3 kD = vec3(1.0) - kS;
kD *= 1.0 - metallic;
float NdotL = max(dot(N, L), 0.0);
return (kD * albedo / PI + specular) * radiance * NdotL;
}
void main() {
vec3 albedo = texture(outAlbedo, inTextCoord).rgb;
vec3 normal = texture(outNormals, inTextCoord).rgb;
vec3 worldPos = texture(outPosition, inTextCoord).rgb;
vec3 pbr = texture(outPBR, inTextCoord).rgb;
float roughness = pbr.g;
float metallic = pbr.b;
vec3 N = normalize(normal);
vec3 V = normalize(sceneInfo.camPos - worldPos);
vec3 F0 = vec3(0.04);
F0 = mix(F0, albedo, metallic);
vec3 Lo = vec3(0.0);
for (uint i = 0; i < sceneInfo.LightCount; i++) {
Light light = lights[i];
if (light.lightType == 1) {
Lo += calculateDirectionalLight(light, V, N, F0, albedo, metallic, roughness);
} else {
Lo += calculatePointLight(light, worldPos, V, N, F0, albedo, metallic, roughness);
}
}
vec3 ambient = sceneInfo.ambientLightColor * albedo * sceneInfo.ambientLightIntensity;
vec3 color = ambient + Lo;
outFragColor = vec4(color, 1.0f);
if (length(normal) < 0.001) {
outFragColor = vec4(albedo,1.0f);
return;
}
// outFragColor = vec4(normal, 1.0f);
}

View file

@ -1,256 +0,0 @@
#version 330 core
const int MAX_LIGHTS = 32;
const float PI = 3.14159265359;
const float SPECULAR_POWER = 10;
in vec4 outPos;
in vec3 outNormal;
in vec3 outTangent;
in vec3 outBitangent;
in vec2 outTextCoords;
out vec4 fragColor;
struct Attenuation
{
float constant;
float linear;
float exponent;
};
struct Light {
vec3 position;
int lightType;
float intensity;
vec3 color;
vec3 conedir;
float cutoff;
Attenuation attenuation;
};
struct Material {
vec4 diffuse;
int hasTexture;
int hasNormalMap;
int hasRoughMap;
float roughnessFactor;
float metallicFactor;
};
uniform sampler2D textureSampler;
uniform sampler2D normalSampler;
uniform sampler2D roughnessSampler;
uniform Light lights[MAX_LIGHTS];
struct SceneInfo {
vec3 camPos;
float ambientLightIntensity;
vec3 ambientLightColor;
int LightCount;
};
uniform Material material;
uniform SceneInfo sceneInfo;
vec4 calcAmbient(Light ambientLight, vec4 ambient) {
return vec4(ambientLight.intensity * ambientLight.color, 1) * ambient;
}
vec4 calcLightColor(vec4 diffuse, vec4 specular, vec3 lightColor, float light_intensity, vec3 position, vec3 to_light_dir, vec3 normal, float Metallic) {
vec4 diffuseColor = vec4(0, 0, 0, 1);
vec4 specColor = vec4(0, 0, 0, 1);
float diffuseFactor = max(dot(normal, to_light_dir), 0.0);
diffuseColor = diffuse * vec4(lightColor, 1.0) * light_intensity * diffuseFactor;
vec3 camera_direction = normalize(-position);
vec3 from_light_dir = -to_light_dir;
vec3 reflected_light = normalize(reflect(from_light_dir, normal));
float specularFactor = max(dot(camera_direction, reflected_light), 0.0);
specularFactor = pow(specularFactor, SPECULAR_POWER);
specColor = specular * light_intensity * specularFactor * Metallic * vec4(lightColor, 1.0);
return (diffuseColor + specColor);
}
vec4 calcPointLight(vec4 diffuse, vec4 specular, Light light, vec3 position, vec3 normal, float Metallic) {
vec3 light_direction = light.position - position;
vec3 to_light_dir = normalize(light_direction);
vec4 light_color = calcLightColor(diffuse, specular, light.color, light.intensity, position, to_light_dir, normal,Metallic);
float distance = length(light_direction);
float attenuationInv = light.attenuation.constant + light.attenuation.linear * distance +
light.attenuation.exponent * distance * distance;
return light_color / attenuationInv;
}
vec4 calcSpotLight(vec4 diffuse, vec4 specular, Light light, vec3 position, vec3 normal,float Metallic) {
vec3 light_direction = light.position - position;
vec3 to_light_dir = normalize(light_direction);
vec3 from_light_dir = -to_light_dir;
float spot_alfa = dot(from_light_dir, normalize(light.conedir));
vec4 color = vec4(0, 0, 0, 0);
if (spot_alfa > light.cutoff)
{
color = calcPointLight(diffuse, specular, light, position, normal,Metallic);
color *= (1.0 - (1.0 - spot_alfa)/(1.0 - light.cutoff));
}
return color;
}
vec4 calcDirLight(vec4 diffuse, vec4 specular, Light light, vec3 position, vec3 normal,float Metallic) {
return calcLightColor(diffuse, specular, light.color, light.intensity, position, normalize(light.position), normal,Metallic);
}
vec3 calcNormal(Material material, vec3 normal, vec2 textCoords, mat3 TBN)
{
vec3 newNormal = normal;
if (material.hasNormalMap > 0)
{
newNormal = texture(normalSampler, textCoords).rgb;
newNormal = normalize(newNormal * 2.0 - 1.0);
newNormal = normalize(TBN * newNormal);
}
return newNormal;
}
float distributionGGX(vec3 N, vec3 H, float roughness) {
float a = roughness * roughness;
float a2 = a * a;
float NdotH = max(dot(N, H), 0.0);
float NdotH2 = NdotH * NdotH;
float nom = a2;
float denom = (NdotH2 * (a2 - 1.0) + 1.0);
denom = PI * denom * denom;
return nom / denom;
}
float geometrySchlickGGX(float NdotV, float roughness) {
float r = (roughness + 1.0);
float k = (r * r) / 8.0;
float nom = NdotV;
float denom = NdotV * (1.0 - k) + k;
return nom / denom;
}
float geometrySmith(vec3 N, vec3 V, vec3 L, float roughness) {
float NdotV = max(dot(N, V), 0.0);
float NdotL = max(dot(N, L), 0.0);
float ggx2 = geometrySchlickGGX(NdotV, roughness);
float ggx1 = geometrySchlickGGX(NdotL, roughness);
return ggx1 * ggx2;
}
vec3 fresnelSchlick(float cosTheta, vec3 F0) {
return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0);
}
vec3 calculatePointLight(Light light, vec3 worldPos, vec3 V, vec3 N, vec3 F0, vec3 albedo, float metallic, float roughness) {
vec3 tmpSub = light.position - worldPos;
vec3 L = normalize(tmpSub);
vec3 H = normalize(V + L);
// Calculate distance and attenuation
float distance = length(tmpSub);
float attenuation = 1.0 / (distance * distance);
float intensity = 10.0f;
vec3 radiance = light.color * light.intensity * attenuation;
// Cook-Torrance BRDF
float NDF = distributionGGX(N, H, roughness);
float G = geometrySmith(N, V, L, roughness);
vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0);
vec3 numerator = NDF * G * F;
float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001;
vec3 specular = numerator / denominator;
vec3 kS = F;
vec3 kD = vec3(1.0) - kS;
kD *= 1.0 - metallic;
float NdotL = max(dot(N, L), 0.0);
return (kD * albedo / PI + specular) * radiance * NdotL;
}
vec3 calculateDirectionalLight(Light light, vec3 V, vec3 N, vec3 F0, vec3 albedo, float metallic, float roughness) {
vec3 L = normalize(-light.position);
vec3 H = normalize(V + L);
vec3 radiance = light.color * light.intensity;
// Cook-Torrance BRDF
float NDF = distributionGGX(N, H, roughness);
float G = geometrySmith(N, V, L, roughness);
vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0);
vec3 numerator = NDF * G * F;
float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001;
vec3 specular = numerator / denominator;
vec3 kS = F;
vec3 kD = vec3(1.0) - kS;
kD *= 1.0 - metallic;
float NdotL = max(dot(N, L), 0.0);
return (kD * albedo / PI + specular) * radiance * NdotL;
}
void main()
{
vec4 text_color = texture(textureSampler, outTextCoords);
if(text_color.a < 0.5) discard;
vec4 diffuse = text_color;
mat3 TBN = mat3(outTangent, outBitangent, outNormal);
vec3 newNormal = calcNormal(material, outNormal, outTextCoords, TBN);
float ao = 0.5;
float roughnessFactor = 0.0;
float metallicFactor = 0.0;
if (material.hasRoughMap > 0) {
vec4 metRoughValue = texture(roughnessSampler, outTextCoords);
roughnessFactor = metRoughValue.g;
metallicFactor = metRoughValue.b;
} else {
roughnessFactor = material.roughnessFactor;
metallicFactor = material.metallicFactor;
}
vec4 specular = text_color + metallicFactor - roughnessFactor;
vec4 pbr = vec4(ao, roughnessFactor, metallicFactor, text_color.a);
float roughness = pbr.g;
float metallic = pbr.b;
vec3 N = normalize(newNormal);
vec3 V = normalize(sceneInfo.camPos - outPos.rgb);
vec3 F0 = vec3(0.04);
F0 = mix(F0, text_color.rgb, metallic);
vec3 Lo = vec3(0.0);
for (int i = 0; i < sceneInfo.LightCount; i++) {
Light light = lights[i];
vec3 Pos = vec3(outPos.rgb);
if (light.lightType == 1) {
//Lo += calculateDirectionalLight(light, V, N, F0, text_color.rgb, metallic, roughness);
Lo += calcDirLight(diffuse, specular, light, Pos, outNormal,metallic).rgb;
} else {
// Lo += calculatePointLight(light, outPos.rgb, V, N, F0, text_color.rgb, metallic, roughness);
Lo += calcPointLight(diffuse, specular, light, Pos, outNormal,metallic).rgb;
}
}
vec3 ambient = sceneInfo.ambientLightColor * text_color.rgb * sceneInfo.ambientLightIntensity;
vec3 color = ambient + Lo;
fragColor = vec4(color, 1.0f);
}

View file

@ -1,77 +0,0 @@
#version 450
const int MAX_TEXTURES = 256;
out vec4 outPos;
out vec3 outNormal;
out vec3 outTangent;
out vec3 outBitangent;
out vec2 outTextCoords;
out vec4 outAlbedo ;
out vec4 outPosition;
out vec4 outNormals;
out vec4 outPBR;
struct Material {
vec4 diffuse;
int hasTexture;
int hasNormalMap;
int hasRoughMap;
float roughnessFactor;
float metallicFactor;
};
uniform sampler2D textureSampler;
uniform sampler2D normalSampler;
uniform sampler2D roughnessSampler;
uniform Material material;
vec3 calcNormal(Material material, vec3 normal, vec2 textCoords, mat3 TBN)
{
vec3 newNormal = normal;
if (material.hasNormalMap > 0)
{
newNormal = texture(normalSampler, textCoords).rgb;
newNormal = normalize(newNormal * 2.0 - 1.0);
newNormal = normalize(TBN * newNormal);
}
return newNormal;
}
layout(push_constant) uniform pc {
layout(offset = 64) uint materialIdx;
} push_constants;
void main()
{
outPosition = outPos;
if (material.hasTexture == 1) {
outAlbedo = texture(textureSampler, outTextCoords);
} else {
outAlbedo = material.diffuse;
}
if(outAlbedo.a < 0.5) discard;
mat3 TBN = mat3( outTangent, outBitangent, outNormal);
vec3 newNormal = calcNormal(material, outNormal, outTextCoords, TBN);
outNormals = vec4(newNormal, 1.0f);
float ao = 0.5f;
float roughnessFactor = 0.0f;
float metallicFactor = 0.0f;
if (material.hasRoughMap > 0) {
vec4 metRoughValue = texture(roughnessSampler, outTextCoords);
roughnessFactor = metRoughValue.g;
metallicFactor = metRoughValue.b;
} else {
roughnessFactor = material.roughnessFactor;
metallicFactor = material.metallicFactor;
}
outPBR = vec4(ao, roughnessFactor, metallicFactor, 1.0f);
}

View file

@ -1,37 +0,0 @@
#version 330 core
layout (location = 0) in vec3 inPos;
layout (location = 1) in vec3 inNormal;
layout (location = 2) in vec3 inTangent;
layout (location = 3) in vec3 inBitangent;
layout (location = 4) in vec2 inTextCoords;
out vec4 outPos;
out vec3 outNormal;
out vec3 outTangent;
out vec3 outBitangent;
out vec2 outTextCoords;
uniform mat4 projectionMatrix;
uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
void main()
{
// vec4 worldPos = modelMatrix * vec4(inPos,1);
// gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(inPos, 1.0);
// mat3 mNormal = transpose(inverse(mat3(modelMatrix)));
// outPos = worldPos;
// outNormal = mNormal * normalize(inNormal);
// outTextCoords = inTextCoords;
mat4 modelViewMatrix = viewMatrix * modelMatrix;
vec4 mvPosition = modelViewMatrix * vec4(inPos, 1.0);
gl_Position = projectionMatrix * mvPosition;
outPos = mvPosition;
outNormal = normalize(modelViewMatrix * vec4(inNormal, 0.0)).xyz;
outTangent = inNormal * normalize(inTangent);
outBitangent = inNormal * normalize(inBitangent);
outTextCoords = inTextCoords;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 MiB

View file

@ -1,2 +0,0 @@
Sky texture:
kaori669 on deviant art

View file

@ -1,28 +0,0 @@
#version 450
const int MAX_TEXTURES = 512;
const float GAMMA_CONST = 0.4545;
layout(location = 0) in vec2 inUV;
layout(location = 0) out vec4 outColor;
layout(push_constant) uniform pc {
layout(offset = 28) uint textureIndex;
} push_constants;
layout(set = 1, binding = 0) uniform sampler2D spriteTextures[MAX_TEXTURES];
vec4 gamma(vec4 color){
return color = vec4(pow(color.rgb,vec3(GAMMA_CONST)),color.a);
}
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);
outColor = gamma(tex);
if (outColor.a <= 0.09) {
discard;
}
}

View file

@ -1,19 +0,0 @@
#version 450
const int MAX_TEXTURES = 128;
layout(location = 0) in vec2 inUV;
layout(location = 0) out vec4 outColor;
layout(push_constant) uniform pc {
layout(offset = 28) uint textureIndex;
} push_constants;
layout(set = 1, binding = 0) uniform sampler2D spriteTextures[MAX_TEXTURES];
void main() {
vec4 tex = texture(spriteTextures[push_constants.textureIndex], inUV);
outColor = tex;
if(outColor.a >= 0.9 || outColor.a <= 0.001){discard;}
}

View file

@ -1,36 +0,0 @@
#version 450
layout(location = 0) in vec2 inPos;
layout(location = 1) in vec2 inUV;
layout(location = 0) out vec2 outUV;
layout(push_constant) uniform pc {
vec2 modelSize;
vec2 position;
vec2 screenSize;
float zAmount;
} push_constants;
layout(set = 0, binding = 0) uniform ViewUniform{
vec2 camPos;
vec2 camScale;
} viewUniform;
void main() {
vec2 ScaledPos = inPos * push_constants.modelSize;
vec2 worldPos = push_constants.position + ScaledPos;
worldPos += (viewUniform.camPos * push_constants.zAmount);
vec2 ndc = vec2(
(worldPos.x / push_constants.screenSize.x) * 2.0 - 1.0,
(worldPos.y / push_constants.screenSize.y) * 2.0 - 1.0
);
ndc.y = -ndc.y;
gl_Position = vec4(ndc * viewUniform.camScale, 0.0, 1.0);
outUV = vec2(inUV.x, 1 - inUV.y);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 217 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

View file

@ -1,236 +0,0 @@
#version 460
layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in;
const int CHUNK_SIZE = 16;
const int CHUNK_AREA = CHUNK_SIZE * CHUNK_SIZE;
const int VOXEL_COUNT = CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE;
const uint FLOATS_PER_VERTEX = 14u;
const uint INTEGERS_PER_VERTEX = 1u;
const uint VERTICES_PER_FACE = 4u;
const uint INDICES_PER_FACE = 6u;
const uint MAX_VISIBLE_FACES_PER_CHUNK = uint(CHUNK_SIZE * CHUNK_SIZE * 12);
const uint MAX_VERTICES = MAX_VISIBLE_FACES_PER_CHUNK * VERTICES_PER_FACE;
const uint MAX_INDICES = MAX_VISIBLE_FACES_PER_CHUNK * INDICES_PER_FACE;
layout(std430, binding = 0) readonly buffer VoxelData {
uint voxels[];
};
layout(std430, binding = 1) buffer VertexBuffer {
float vertices[];
};
layout(std430, binding = 2) buffer IndexBuffer {
uint indices[];
};
layout(std430, binding = 3) buffer DrawCommand {
uint indexCount;
uint instanceCount;
uint firstIndex;
int vertexOffset;
uint firstInstance;
} drawCmd;
layout(std430, binding = 4) buffer Counters {
uint vertexCount;
uint indexCount;
} counters;
layout(push_constant) uniform ChunkInfo {
ivec3 chunkPos;
int padding0;
};
uint flatten(ivec3 pos) {
return uint((pos.x * CHUNK_AREA) + (pos.y * CHUNK_SIZE) + pos.z);
}
uint getVoxel(ivec3 pos) {
if (pos.x < 0 || pos.x >= CHUNK_SIZE) return 0;
if (pos.y < 0 || pos.y >= CHUNK_SIZE) return 0;
if (pos.z < 0 || pos.z >= CHUNK_SIZE) return 0;
return voxels[flatten(pos)];
}
void writeVertex(uint vertexIndex,vec3 position,vec3 normal,
vec3 tangent,vec3 bitangent,vec2 uv) {
uint base = vertexIndex * FLOATS_PER_VERTEX;
vertices[base + 0u] = position.x;
vertices[base + 1u] = position.y;
vertices[base + 2u] = position.z;
vertices[base + 3u] = normal.x;
vertices[base + 4u] = normal.y;
vertices[base + 5u] = normal.z;
vertices[base + 6u] = tangent.x;
vertices[base + 7u] = tangent.y;
vertices[base + 8u] = tangent.z;
vertices[base + 9u] = bitangent.x;
vertices[base + 10u] = bitangent.y;
vertices[base + 11u] = bitangent.z;
vertices[base + 12u] = uv.x;
vertices[base + 13u] = uv.y;
}
void emitFace(ivec3 voxelPos, int faceIndex) {
uint baseVertex = atomicAdd(counters.vertexCount, VERTICES_PER_FACE);
uint baseIndex = atomicAdd(counters.indexCount, INDICES_PER_FACE);
if (baseVertex + VERTICES_PER_FACE > MAX_VERTICES ||
baseIndex + INDICES_PER_FACE > MAX_INDICES) {
return;
}
vec3 p = vec3(voxelPos);
vec3 normal;
vec3 tangent;
vec3 bitangent;
vec3 v0;
vec3 v1;
vec3 v2;
vec3 v3;
vec2 uv0;
vec2 uv1;
vec2 uv2;
vec2 uv3;
if (faceIndex == 0) {
// Top +Y
normal = vec3(0.0, 1.0, 0.0);
tangent = vec3(1.0, 0.0, 0.0);
bitangent = vec3(0.0, 0.0, 1.0);
v0 = p + vec3(0.0, 1.0, 0.0);
v1 = p + vec3(0.0, 1.0, 1.0);
v2 = p + vec3(1.0, 1.0, 1.0);
v3 = p + vec3(1.0, 1.0, 0.0);
uv0 = vec2(0.0, 0.5);
uv1 = vec2(0.0, 1.0);
uv2 = vec2(0.5, 1.0);
uv3 = vec2(0.5, 0.5);
} else if (faceIndex == 1) {
// Bottom -Y
normal = vec3(0.0, -1.0, 0.0);
tangent = vec3(1.0, 0.0, 0.0);
bitangent = vec3(0.0, 0.0, -1.0);
v0 = p + vec3(0.0, 0.0, 0.0);
v1 = p + vec3(1.0, 0.0, 0.0);
v2 = p + vec3(1.0, 0.0, 1.0);
v3 = p + vec3(0.0, 0.0, 1.0);
uv0 = vec2(0.5, 0.0);
uv1 = vec2(0.5, 0.5);
uv2 = vec2(1.0, 0.5);
uv3 = vec2(1.0, 0.0);
} else if (faceIndex == 2) {
// Right +X
normal = vec3(1.0, 0.0, 0.0);
tangent = vec3(0.0, 0.0, -1.0);
bitangent = vec3(0.0, 1.0, 0.0);
v0 = p + vec3(1.0, 0.0, 0.0);
v1 = p + vec3(1.0, 1.0, 0.0);
v2 = p + vec3(1.0, 1.0, 1.0);
v3 = p + vec3(1.0, 0.0, 1.0);
uv0 = vec2(0.0, 0.0);
uv3 = vec2(0.0, 0.5);
uv2 = vec2(0.5, 0.5);
uv1 = vec2(0.5, 0.0);
} else if (faceIndex == 3) {
// Left -X
normal = vec3(-1.0, 0.0, 0.0);
tangent = vec3(0.0, 0.0, 1.0);
bitangent = vec3(0.0, 1.0, 0.0);
v0 = p + vec3(0.0, 0.0, 0.0);
v1 = p + vec3(0.0, 0.0, 1.0);
v2 = p + vec3(0.0, 1.0, 1.0);
v3 = p + vec3(0.0, 1.0, 0.0);
uv0 = vec2(0.0, 0.0);
uv1 = vec2(0.0, 0.5);
uv2 = vec2(0.5, 0.5);
uv3 = vec2(0.5, 0.0);
} else if (faceIndex == 4) {
// Front +Z
normal = vec3(0.0, 0.0, 1.0);
tangent = vec3(1.0, 0.0, 0.0);
bitangent = vec3(0.0, 1.0, 0.0);
v0 = p + vec3(0.0, 0.0, 1.0);
v1 = p + vec3(1.0, 0.0, 1.0);
v2 = p + vec3(1.0, 1.0, 1.0);
v3 = p + vec3(0.0, 1.0, 1.0);
uv0 = vec2(0.0, 0.0);
uv1 = vec2(0.0, 0.5);
uv2 = vec2(0.5, 0.5);
uv3 = vec2(0.5, 0.0);
} else {
// Back -Z
normal = vec3(0.0, 0.0, -1.0);
tangent = vec3(-1.0, 0.0, 0.0);
bitangent = vec3(0.0, 1.0, 0.0);
v0 = p + vec3(0.0, 0.0, 0.0);
v1 = p + vec3(0.0, 1.0, 0.0);
v2 = p + vec3(1.0, 1.0, 0.0);
v3 = p + vec3(1.0, 0.0, 0.0);
uv0 = vec2(0.0, 0.0);
uv1 = vec2(0.0, 0.5);
uv2 = vec2(0.5, 0.5);
uv3 = vec2(0.5, 0.0);
}
writeVertex(baseVertex + 0u, v0, normal, tangent, bitangent, uv0);
writeVertex(baseVertex + 1u, v1, normal, tangent, bitangent, uv1);
writeVertex(baseVertex + 2u, v2, normal, tangent, bitangent, uv2);
writeVertex(baseVertex + 3u, v3, normal, tangent, bitangent, uv3);
indices[baseIndex + 0u] = baseVertex + 0u;
indices[baseIndex + 1u] = baseVertex + 1u;
indices[baseIndex + 2u] = baseVertex + 2u;
indices[baseIndex + 3u] = baseVertex + 0u;
indices[baseIndex + 4u] = baseVertex + 2u;
indices[baseIndex + 5u] = baseVertex + 3u;
atomicAdd(drawCmd.indexCount, INDICES_PER_FACE);
}
void main() {
ivec3 pos = ivec3(gl_GlobalInvocationID.xyz);
if (pos.x >= CHUNK_SIZE || pos.y >= CHUNK_SIZE || pos.z >= CHUNK_SIZE) {
return;
}
uint current = getVoxel(pos);
if (current == 0u) {
return;
}
if (getVoxel(pos + ivec3( 0, 1, 0)) == 0u) emitFace(pos, 0);
if (getVoxel(pos + ivec3( 0, -1, 0)) == 0u) emitFace(pos, 1);
if (getVoxel(pos + ivec3( 1, 0, 0)) == 0u) emitFace(pos, 2);
if (getVoxel(pos + ivec3(-1, 0, 0)) == 0u) emitFace(pos, 3);
if (getVoxel(pos + ivec3( 0, 0, 1)) == 0u) emitFace(pos, 4);
if (getVoxel(pos + ivec3( 0, 0, -1)) == 0u) emitFace(pos, 5);
}

View file

@ -1,201 +0,0 @@
#version 460
layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in;
const int CHUNK_SIZE = 16;
const int SCRATCH_SIZE = CHUNK_SIZE + 2;
const int SCRATCH_AREA = SCRATCH_SIZE * SCRATCH_SIZE;
const int SCRATCH_VOXEL_COUNT = SCRATCH_SIZE * SCRATCH_SIZE * SCRATCH_SIZE;
const uint MAX_VISIBLE_FACES_PER_CHUNK = uint(CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE * 6);
layout(std430, binding = 0) readonly buffer VoxelData {
uint voxels[];
};
layout(std430, binding = 1) buffer FaceBuffer {
uint faces[];
};
layout(std430, binding = 2) buffer Counters {
uint faceCount[];
} counters;
struct Voxel {
uint MaterialIndex;
uint BlockType;
uvec2[2] UpIndex;
uvec2[2] DownIndex;
uvec2[2] NorthIndex;
uvec2[2] SouthIndex;
uvec2[2] EastIndex;
uvec2[2] WestIndex;
};
layout(std430, set = 1, binding = 0) readonly buffer VoxelUniform {
Voxel materials[];
} voxelReg;
layout(push_constant) uniform ChunkInfo {
ivec3 chunkPos;
int slot;
uint faceOffset;
uint voxelTypeCount;
uint biomeCount;
uint structureCount;
uint worldSeed;
};
uint flatten(ivec3 pos) {
pos += ivec3(1);
return uint(slot * SCRATCH_VOXEL_COUNT + pos.x * SCRATCH_AREA + pos.y * SCRATCH_SIZE + pos.z);
}
bool isSeeThrough(Voxel voxel, uint type) {
if (type == 0u || voxel.BlockType == 3u || type > voxelTypeCount) return true;
return voxelReg.materials[type - 1u].BlockType >= 1u;
}
uint getVoxel(ivec3 pos) {
if (pos.x < -1 || pos.x > CHUNK_SIZE) return 0u;
if (pos.y < -1 || pos.y > CHUNK_SIZE) return 0u;
if (pos.z < -1 || pos.z > CHUNK_SIZE) return 0u;
return voxels[flatten(pos)];
}
uint hash21(uvec2 p) {
p = p * 1664525u + 1013904223u;
p.x += p.y * 1664525u;
p.y += p.x * 1664525u;
return p.x ^ (p.x >> 16);
}
uint pcg_hash(uint seed) {
uint state = seed * 747796405u + 289133645u;
uint word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u;
return (word >> 22u) ^ word;
}
uint randomRangeUint(uint seed, uint minVal, uint maxVal) {
uint range = maxVal - minVal + 1u;
return minVal + (pcg_hash(seed) % range);
}
uint random_1_to_3(vec2 uv, uint customSeed) {
uvec2 p = uvec2(floatBitsToUint(uv.x), floatBitsToUint(uv.y));
p.x ^= customSeed;
uint randInt = hash21(p);
return (randInt % 3u) + 1u;
}
uint packFace(uvec3 voxelPos, uint faceIndex, Voxel voxel) {
uint randomSeed = uint(voxelPos.x) * 73856093u ^ uint(voxelPos.z) * 19349663u;
uvec2 UpIndex = uvec2(randomRangeUint(randomSeed,voxel.UpIndex[0].x,voxel.UpIndex[1].x),randomRangeUint(randomSeed,voxel.UpIndex[0].y,voxel.UpIndex[1].y));
uvec2 DownIndex = uvec2(randomRangeUint(randomSeed,voxel.DownIndex[0].x,voxel.DownIndex[1].x),randomRangeUint(randomSeed,voxel.DownIndex[0].y,voxel.DownIndex[1].y));
uvec2 NorthIndex = uvec2(randomRangeUint(randomSeed,voxel.NorthIndex[0].x,voxel.NorthIndex[1].x),randomRangeUint(randomSeed,voxel.NorthIndex[0].y,voxel.NorthIndex[1].y));
uvec2 SouthIndex = uvec2(randomRangeUint(randomSeed,voxel.SouthIndex[0].x,voxel.SouthIndex[1].x),randomRangeUint(randomSeed,voxel.SouthIndex[0].y,voxel.SouthIndex[1].y));
uvec2 EastIndex = uvec2(randomRangeUint(randomSeed,voxel.EastIndex[0].x,voxel.EastIndex[1].x),randomRangeUint(randomSeed,voxel.EastIndex[0].y,voxel.EastIndex[1].y));
uvec2 WestIndex = uvec2(randomRangeUint(randomSeed,voxel.WestIndex[0].x,voxel.WestIndex[1].x),randomRangeUint(randomSeed,voxel.WestIndex[0].y,voxel.WestIndex[1].y));
uvec2 textureIndices[8] = uvec2[8](UpIndex, DownIndex, NorthIndex,
SouthIndex, EastIndex, WestIndex, NorthIndex,SouthIndex);
uvec2 tex = textureIndices[faceIndex];
uint textureIndexX = tex.x;
uint textureIndexY = tex.y;
uint materialId = voxel.MaterialIndex;
return (voxelPos.x & 0xFu) |
((voxelPos.y & 0xFu) << 4u) |
((voxelPos.z & 0xFu) << 8u) |
((faceIndex & 0x7u) << 12u) |
((materialId & 0x7FFu) << 15u) |
((textureIndexX & 0x7u) << 26u) |
((textureIndexY & 0x7u) << 29u);
}
uint packFace(uvec3 voxelPos, uint faceIndex, uint materialId) {
uint randomFaceValue = random_1_to_3(vec2(voxelPos.x, voxelPos.z),faceOffset);
uint textureIndexX = 0u;
uint textureIndexY = 0u;
if(materialId == 1u){
if(faceIndex == 0u){
textureIndexX = 0u;
textureIndexY = randomFaceValue;
} else if(faceIndex == 1u){
textureIndexX = 1u;
textureIndexY = 0u;
}
else{
textureIndexX = 0u;
textureIndexY = 0u;
}
} else if(materialId == 2u){
textureIndexX = 1u;
textureIndexY = 0u;
}else if(materialId == 3u){
textureIndexX = 1u;
textureIndexY = 0u;
}else if(materialId == 4u){
textureIndexX = 1u;
textureIndexY = randomFaceValue;
}else if(materialId == 5u){
textureIndexX = 2u;
textureIndexY = 3u;
}else if(materialId == 5u){
if (faceIndex == 0u || faceIndex == 1u){
textureIndexX = 2u;
textureIndexY = 1u;
} else{
textureIndexX = 2u;
textureIndexY = 2u;
}
}else if(materialId == 6u){
textureIndexX = 2u;
textureIndexY = 0u;
}
return (voxelPos.x & 0xFu) |
((voxelPos.y & 0xFu) << 4u) |
((voxelPos.z & 0xFu) << 8u) |
((faceIndex & 0x7u) << 12u) |
((materialId & 0x7FFu) << 15u) |
((textureIndexX & 0x7u) << 26u) |
((textureIndexY & 0x7u) << 29u);
}
void emitFace(ivec3 voxelPos, uint faceIndex, uint voxelType) {
if (voxelType == 0u || voxelType > voxelTypeCount) {
return;
}
uint localFace = atomicAdd(counters.faceCount[slot], 1u);
if (localFace >= MAX_VISIBLE_FACES_PER_CHUNK) {
return;
}
Voxel voxel = voxelReg.materials[voxelType - 1u];
faces[faceOffset + localFace] = packFace(uvec3(voxelPos), faceIndex, voxel);
}
void main() {
ivec3 pos = ivec3(gl_GlobalInvocationID.xyz);
if (pos.x >= CHUNK_SIZE || pos.y >= CHUNK_SIZE || pos.z >= CHUNK_SIZE) {
return;
}
uint current = getVoxel(pos);
if (current == 0u || current > voxelTypeCount) {
return;
}
Voxel voxel = voxelReg.materials[current - 1u];
if (voxel.BlockType == 1u) {
emitFace(pos, 6u, current);
emitFace(pos, 7u, current);
return;
}
if (isSeeThrough(voxel,getVoxel(pos + ivec3( 0, 1, 0)))) emitFace(pos, 0u, current);
if (isSeeThrough(voxel,getVoxel(pos + ivec3( 0, -1, 0)))) emitFace(pos, 1u, current);
if (isSeeThrough(voxel,getVoxel(pos + ivec3( 1, 0, 0)))) emitFace(pos, 2u, current);
if (isSeeThrough(voxel,getVoxel(pos + ivec3(-1, 0, 0)))) emitFace(pos, 3u, current);
if (isSeeThrough(voxel,getVoxel(pos + ivec3( 0, 0, 1)))) emitFace(pos, 4u, current);
if (isSeeThrough(voxel,getVoxel(pos + ivec3( 0, 0, -1)))) emitFace(pos, 5u, current);
}

View file

@ -1,27 +0,0 @@
#version 460
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
layout(std430, binding = 0) buffer DrawCommand {
uint indexCount;
uint instanceCount;
uint firstIndex;
int vertexOffset;
uint firstInstance;
} drawCmd;
layout(std430, binding = 1) buffer Counters {
uint vertexCount;
uint indexCount;
} counters;
void main() {
drawCmd.indexCount = 0u;
drawCmd.instanceCount = 1u;
drawCmd.firstIndex = 0u;
drawCmd.vertexOffset = 0;
drawCmd.firstInstance = 0u;
counters.vertexCount = 0u;
counters.indexCount = 0u;
}

View file

@ -1,21 +0,0 @@
#version 460
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
layout(std430, binding = 0) buffer Counters {
uint faceCount[];
} counters;
layout(push_constant) uniform ChunkInfo {
ivec3 chunkPos;
int slot;
uint faceOffset;
uint voxelTypeCount;
uint biomeCount;
uint structureCount;
uint worldSeed;
};
void main() {
counters.faceCount[slot] = 0u;
}

View file

@ -1,201 +0,0 @@
#version 460
layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in;
const int CHUNK_SIZE = 16;
const int CHUNK_AREA = CHUNK_SIZE * CHUNK_SIZE;
// A 1D storage buffer representing a flat 3D array of voxel IDs
layout(std430, binding = 0) buffer VoxelData {
uint voxels[];
};
layout(push_constant) uniform ChunkOffset {
ivec3 chunkPos;
int padding0;
};
// Description : Array and textureless GLSL 2D/3D/4D simplex
// noise functions.
// Author : Ian McEwan, Ashima Arts.
// Maintainer : stegu
// Lastmod : 20110822 (ijm)
// License : Copyright (C) 2011 Ashima Arts. All rights reserved.
// Distributed under the MIT License. See LICENSE file.
// https://github.com
vec4 permute(vec4 x) { return mod(((x * 34.0) + 1.0) * x, 289.0); }
vec4 taylorInvSqrt(vec4 r) { return 1.79284291400159 - 0.85373472095314 * r; }
float simplex_noise(vec3 v) {
const vec2 C = vec2(1.0/6.0, 1.0/3.0);
const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);
// First corner
vec3 i = floor(v + dot(v, C.yyy));
vec3 x0 = v - i + dot(i, C.xxx);
// Other corners
vec3 g = step(x0.yzx, x0.xyz);
vec3 l = 1.0 - g;
vec3 i1 = min(g.xyz, l.zxy);
vec3 i2 = max(g.xyz, l.zxy);
// x0 = x0 - 0.0 + 0.0 * C.xxx;
// x1 = x0 - i1 + 1.0 * C.xxx;
// x2 = x0 - i2 + 2.0 * C.xxx;
// x3 = x0 - 1.0 + 3.0 * C.xxx;
vec3 x1 = x0 - i1 + C.xxx;
vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y
vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y
// Permutations
i = mod(i, 289.0);
vec4 p = permute(permute(permute(
i.z + vec4(0.0, i1.z, i2.z, 1.0))
+ i.y + vec4(0.0, i1.y, i2.y, 1.0))
+ i.x + vec4(0.0, i1.x, i2.x, 1.0));
// Gradients: 7x7 points over a square, mapped onto an octahedron.
// The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)
float n_ = 0.142857142857; // 1.0/7.0
vec3 ns = n_ * D.wyz - D.xzx;
vec4 j = p - 49.0 * floor(p * ns.z); // mod(p,7*7)
vec4 x_ = floor(j * ns.z);
vec4 y_ = floor(j - 7.0 * x_); // mod(j,N)
vec4 x = x_ * ns.x + ns.yyyy;
vec4 y = y_ * ns.x + ns.yyyy;
vec4 h = 1.0 - abs(x) - abs(y);
vec4 b0 = vec4(x.xy, y.xy);
vec4 b1 = vec4(x.zw, y.zw);
//vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;
//vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;
vec4 s0 = floor(b0) * 2.0 + 1.0;
vec4 s1 = floor(b1) * 2.0 + 1.0;
vec4 sh = -step(h, vec4(0.0));
vec4 a0 = b0.xzyw + s0.xzyw * sh.xxyy;
vec4 a1 = b1.xzyw + s1.xzyw * sh.zzww;
vec3 p0 = vec3(a0.xy, h.x);
vec3 p1 = vec3(a0.zw, h.y);
vec3 p2 = vec3(a1.xy, h.z);
vec3 p3 = vec3(a1.zw, h.w);
// Normalise gradients
vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));
p0 *= norm.x;
p1 *= norm.y;
p2 *= norm.z;
p3 *= norm.w;
// Mix final noise value
vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);
m = m * m;
// Returns a value scaled exactly between -1.0 and 1.0
return 42.0 * dot(m * m, vec4(dot(p0,x0), dot(p1,x1), dot(p2,x2), dot(p3,x3)));
}
float noise2D(vec2 p) {
return simplex_noise(vec3(p.x, p.y, 0.0));
}
float fbm(vec2 p, int octaves, float lacunarity, float gain) {
float value = 0.0;
float amplitude = 0.5;
float frequency = 1.0;
float amplitudeSum = 0.0;
for (int i = 0; i < octaves; i++) {
value += noise2D(p * frequency) * amplitude;
amplitudeSum += amplitude;
frequency *= lacunarity;
amplitude *= gain;
}
return value / amplitudeSum;
}
float ridgedFbm(vec2 p, int octaves, float lacunarity, float gain) {
float value = 0.0;
float amplitude = 0.5;
float frequency = 1.0;
float amplitudeSum = 0.0;
for (int i = 0; i < octaves; i++) {
float n = noise2D(p * frequency);
n = 1.0 - abs(n);
n = n * n;
value += n * amplitude;
amplitudeSum += amplitude;
frequency *= lacunarity;
amplitude *= gain;
}
return value / amplitudeSum;
}
vec2 domainWarp(vec2 p) {
float wx = fbm(p + vec2(17.31, 91.73), 3, 2.0, 0.5);
float wz = fbm(p + vec2(43.17, 12.89), 3, 2.0, 0.5);
return p + vec2(wx, wz) * 35.0;
}
float terrainHeight(vec2 worldXZ) {
vec2 p = worldXZ;
vec2 warped = domainWarp(p * 0.006);
float continent = fbm(warped * 0.45, 5, 2.0, 0.5);
continent = continent * 0.5 + 0.5;
float hills = fbm(p * 0.025, 5, 2.0, 0.48);
float detail = fbm(p * 0.09, 3, 2.1, 0.45);
float mountainMask = smoothstep(0.52, 0.82, continent);
float mountains = ridgedFbm(warped * 1.15, 5, 2.0, 0.52);
float height = 18.0;
height += continent * 28.0;
height += hills * 14.0;
height += detail * 3.0;
height += mountainMask * mountains * 55.0;
return height;
}
void main() {
ivec3 localPos = ivec3(gl_GlobalInvocationID.xyz);
if (localPos.x >= CHUNK_SIZE || localPos.y >= CHUNK_SIZE || localPos.z >= CHUNK_SIZE) {
return;
}
ivec3 worldPos = chunkPos * CHUNK_SIZE + localPos;
float height = terrainHeight(vec2(worldPos.x,worldPos.z) * 0.02) * 0.0015 + 10 ;
uint voxelType = 0u;
if (float(worldPos.y) <= height) {
float depthBelowSurface = height - float(worldPos.y);
if (depthBelowSurface < 1.5) {
voxelType = 1u; // Grass/topsoil
} else if (depthBelowSurface < 5.0) {
voxelType = 2u; // Dirt
} else {
voxelType = 3u; // Stone
}
}
uint index = uint((localPos.x * CHUNK_AREA) + (localPos.y * CHUNK_SIZE) + localPos.z);
voxels[index] = voxelType;
}

View file

@ -1,596 +0,0 @@
#version 460
layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in;
const int CHUNK_SIZE = 16;
const int SCRATCH_SIZE = CHUNK_SIZE + 2;
const int SCRATCH_AREA = SCRATCH_SIZE * SCRATCH_SIZE;
const int SCRATCH_VOXEL_COUNT = SCRATCH_SIZE * SCRATCH_SIZE * SCRATCH_SIZE;
const int STRUCTURE_CELL_SIZE = 16;
const int REPLACE_AIR_ONLY = 1;
const int REPLACE_FOLIAGE = 2;
const int REQUIRE_FLAT_GROUND = 4;
const int HAS_FOUNDATION = 8;
layout(push_constant) uniform ChunkInfo {
ivec3 chunkPos;
int slot;
uint faceOffset;
uint voxelTypeCount;
uint biomeCount;
uint structureCount;
uint worldSeed;
};
struct Biome {
uint surfaceBlock;
uint dirtBlock;
uint stoneBlock;
uint grassFoliage;
uint[4] flowers;
uint[4] tallBlocks;
uint[4] otherFoliage;
};
struct Structure {
uint sizeX;
uint sizeY;
uint sizeZ;
uint blockOffset;
uint spawnSpacing;
uint spawnChance;
uint allowedBiome;
uint groundBlock;
uint flags;
};
struct StructureVoxelResult {
uint block;
uint flags;
};
layout(std430, binding = 0) buffer VoxelData {
uint voxels[];
};
layout(std430, set = 1, binding = 0) readonly buffer BiomeUniform {
Biome biomes[];
} BiomeReg;
layout(std430, set = 2, binding = 0) readonly buffer StructureRegistry {
Structure structures[];
} structureReg;
layout(std430, set = 2, binding = 1) readonly buffer StructureBlocks {
uint blocks[];
} structureBlocks;
uint hash21(uvec2 p) {
p = p * 1664525u + 1013904223u;
p.x += p.y * 1664525u;
p.y += p.x * 1664525u;
return p.x ^ (p.x >> 16);
}
float random3to1(vec3 st) {
return fract(sin(dot(st, vec3(127.1, 311.7, 74.7))) * 43758.5453123);
}
float interpolate(float a, float b, float c, float d, float x) {
float p = (d - c) - (a - b);
return x * (x * (x * p + ((a - b) - p)) + (c - a)) + b;
}
float sampleX(vec3 at) {
float floored = floor(at.x);
return interpolate(
random3to1(vec3(floored - 1.0, at.yz)),
random3to1(vec3(floored, at.yz)),
random3to1(vec3(floored + 1.0, at.yz)),
random3to1(vec3(floored + 2.0, at.yz)),
at.x - floored) * 0.5 + 0.25;
}
float sampleY(vec3 at) {
float floored = floor(at.y);
return interpolate(
sampleX(vec3(at.x, floored - 1.0, at.z)),
sampleX(vec3(at.x, floored, at.z)),
sampleX(vec3(at.x, floored + 1.0, at.z)),
sampleX(vec3(at.x, floored + 2.0, at.z)),
at.y - floored);
}
float cubicNoise(vec3 at) {
float floored = floor(at.z);
return interpolate(
sampleY(vec3(at.xy, floored - 1.0)),
sampleY(vec3(at.xy, floored)),
sampleY(vec3(at.xy, floored + 1.0)),
sampleY(vec3(at.xy, floored + 2.0)),
at.z - floored);
}
float rand(vec2 co) {
return fract(sin(dot(co.xy, vec2(12.9898, 78.233))) * 43758.5453123);
}
float valueNoise(vec2 st) {
vec2 i = floor(st);
vec2 f = fract(st);
float a = rand(i);
float b = rand(i + vec2(1.0, 0.0));
float c = rand(i + vec2(0.0, 1.0));
float d = rand(i + vec2(1.0, 1.0));
vec2 u = f * f * (3.0 - 2.0 * f);
return mix(a, b, u.x) +
(c - a) * u.y * (1.0 - u.x) +
(d - b) * u.x * u.y;
}
uint pcg_hash(uint seed) {
uint state = seed * 747796405u + 289133645u;
uint word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u;
return (word >> 22u) ^ word;
}
uint randomRangeUint(uint seed, uint minVal, uint maxVal) {
uint range = maxVal - minVal + 1u;
return minVal + (pcg_hash(seed) % range);
}
uint GetBiome(vec3 worldPos, uint MaxBiomes) {
if (MaxBiomes == 0u) return 0u;
vec3 X = vec3(worldPos);
X = mat3(
0.788675134594813, -0.211324865405187, -0.577350269189626,
-0.211324865405187, 0.788675134594813, -0.577350269189626,
0.577350269189626, 0.577350269189626, 0.577350269189626) * X;
float n = clamp(cubicNoise(X), 0.0, 0.9999);
uint Biome = uint(floor(n * float(MaxBiomes)));
return min(Biome, MaxBiomes - 1u);
}
bool isCave(vec3 worldPos) {
vec3 X = vec3(worldPos);
X = mat3(
0.788675134594813, -0.211324865405187, -0.577350269189626,
-0.211324865405187, 0.788675134594813, -0.577350269189626,
0.577350269189626, 0.577350269189626, 0.577350269189626) * X;
float n = cubicNoise(X);
return n > 0.5;
}
bool shouldSpawn(uint seed, Structure s) {
return pcg_hash(seed) % 1000u < s.spawnChance;
}
bool hasFlag(uint flags, uint flag) {
return (flags & flag) != 0u;
}
int floorDiv(int value, int divisor) {
int q = value / divisor;
int r = value - q * divisor;
if (r != 0 && ((r < 0) != (divisor < 0))) {
q -= 1;
}
return q;
}
ivec2 getStructureCell(ivec2 worldXZ, int spacing) {
return ivec2(
floorDiv(worldXZ.x, spacing),
floorDiv(worldXZ.y, spacing)
);
}
float getPrimarySurfaceHeight(int worldX, int worldY, int worldZ) {
float YZone = floor(float(worldY) / 150.0) * 150.0;
return valueNoise(vec2(float(worldX) + YZone * 2.0, float(worldZ) + YZone * 2.0) * 0.005) * 100.0 +
valueNoise(vec2(float(worldX) + YZone * 2.0, float(worldZ) + YZone * 2.0) * 0.01) * 10.0 +
valueNoise(vec2(float(worldX) + YZone * 2.0, float(worldZ) + YZone * 2.0) * 0.1) * 5.0 +
valueNoise(vec2(float(worldX) + YZone * 2.0, float(worldZ) + YZone * 2.0)) * 0.5 +
YZone;
}
float getSecondarySurfaceHeight(int worldX, int worldY, int worldZ) {
float YZone2 = floor(float(worldY) / 75.0) * 75.0;
return valueNoise(vec2(float(worldX) + YZone2 * 2.0, float(worldZ) + YZone2 * 2.0) * 0.005) * 50.0 +
valueNoise(vec2(float(worldX) + YZone2 * 2.0, float(worldZ) + YZone2 * 2.0) * 0.01) * 10.0 +
valueNoise(vec2(float(worldX) + YZone2 * 2.0, float(worldZ) + YZone2 * 2.0) * 0.1) * 5.0 +
valueNoise(vec2(float(worldX) + YZone2 * 2.0, float(worldZ) + YZone2 * 2.0)) * 0.5 +
YZone2;
}
float getSurfaceHeight(int worldX, int worldZ, int referenceY) {
float primary = getPrimarySurfaceHeight(worldX, referenceY, worldZ);
float secondary = getSecondarySurfaceHeight(worldX, referenceY, worldZ);
float primaryDist = abs(primary - float(referenceY));
float secondaryDist = abs(secondary - float(referenceY));
return primaryDist <= secondaryDist ? primary : secondary;
}
bool cellSpawnsStructure(uint seed, Structure s) {
if (s.spawnChance == 0u) {
return false;
}
return pcg_hash(seed) % 1000u < s.spawnChance;
}
uint chooseStructure(uint seed, uint biome) {
if (structureCount == 0u) {
return 0u;
}
uint start = pcg_hash(seed ^ 0xA53A9D31u) % structureCount;
for (uint i = 0u; i < structureCount; i++) {
uint id = (start + i) % structureCount;
Structure s = structureReg.structures[id];
if (s.allowedBiome == 0u || s.allowedBiome == biome + 1u) {
return id;
}
}
return start;
}
ivec2 getStructureAnchorXZ(ivec2 cell, uint seed, uint spacing) {
int structureSpacing = int(max(spacing, 1u));
uint jitterX = randomRangeUint(seed ^ 0xB5297A4Du, 0u, uint(structureSpacing - 1));
uint jitterZ = randomRangeUint(seed ^ 0x68E31DA4u, 0u, uint(structureSpacing - 1));
return cell * structureSpacing + ivec2(int(jitterX), int(jitterZ));
}
uint getStructureBlock(uint structureId, ivec3 localPos) {
Structure s = structureReg.structures[structureId];
if (localPos.x < 0 || localPos.x >= int(s.sizeX)) return 0u;
if (localPos.y < 0 || localPos.y >= int(s.sizeY)) return 0u;
if (localPos.z < 0 || localPos.z >= int(s.sizeZ)) return 0u;
uint index =
uint(localPos.x) * s.sizeY * s.sizeZ +
uint(localPos.y) * s.sizeZ +
uint(localPos.z);
return structureBlocks.blocks[s.blockOffset + index];
}
bool isGroundFlatEnough(ivec2 anchorXZ, uint structureId, int referenceY) {
Structure s = structureReg.structures[structureId];
float h0 = getSurfaceHeight(anchorXZ.x, anchorXZ.y, referenceY);
float h1 = getSurfaceHeight(anchorXZ.x + int(s.sizeX) - 1, anchorXZ.y, referenceY);
float h2 = getSurfaceHeight(anchorXZ.x, anchorXZ.y + int(s.sizeZ) - 1, referenceY);
float h3 = getSurfaceHeight(anchorXZ.x + int(s.sizeX) - 1, anchorXZ.y + int(s.sizeZ) - 1, referenceY);
float minH = min(min(h0, h1), min(h2, h3));
float maxH = max(max(h0, h1), max(h2, h3));
return maxH - minH <= 2.0;
}
ivec3 getStructureCell3D(ivec3 worldPos, int spacing) {
return ivec3(
floorDiv(worldPos.x, spacing),
floorDiv(worldPos.y, 75),
floorDiv(worldPos.z, spacing)
);
}
uint hash31(ivec3 p) {
uvec3 v = uvec3(p) * uvec3(1664525u, 22695477u, 1103515245u) + uvec3(1013904223u);
v.x += v.y * v.z;
v.y += v.z * v.x;
v.z += v.x * v.y;
return v.x ^ v.y ^ v.z;
}
uint getBaseTerrainVoxelAt(ivec3 worldPos, uint biome) {
Biome currentBiome = BiomeReg.biomes[biome];
float YZone = floor(float(worldPos.y) / 150.0) * 150.0;
float SurfaceHeight =
valueNoise(vec2(float(worldPos.x) + YZone * 2.0, float(worldPos.z) + YZone * 2.0) * 0.005) * 100.0 +
valueNoise(vec2(float(worldPos.x) + YZone * 2.0, float(worldPos.z) + YZone * 2.0) * 0.01) * 10.0 +
valueNoise(vec2(float(worldPos.x) + YZone * 2.0, float(worldPos.z) + YZone * 2.0) * 0.1) * 5.0 +
valueNoise(vec2(float(worldPos.x) + YZone * 2.0, float(worldPos.z) + YZone * 2.0)) * 0.5 +
YZone;
float IslandUnderneathHeight =
valueNoise(vec2(float(worldPos.x) + YZone * 2.0, float(worldPos.z) + YZone * 2.0) * 0.005) * 100.0 +
valueNoise(vec2(float(worldPos.x) + YZone * 2.0, float(worldPos.z) + YZone * 2.0) * 0.1) * 20.0 +
valueNoise(vec2(float(worldPos.x) + YZone * 2.0, float(worldPos.z) + YZone * 2.0) * 0.1) * 5.0 +
valueNoise(vec2(float(worldPos.x) + YZone * 2.0, float(worldPos.z) + YZone * 2.0)) * 0.5 -
15.0 +
YZone;
float grassNoise = valueNoise(vec2(float(worldPos.z) * 0.5 - YZone * 2.0, float(worldPos.x) * 0.5 - YZone * 2.0));
uint randomBlockVal = randomRangeUint(uint(worldPos.x) * 73856093u ^ uint(worldPos.z) * 19349663u, 0u, 3u);
uint voxelType = 0u;
if (float(worldPos.y) <= SurfaceHeight && float(worldPos.y) >= IslandUnderneathHeight) {
float depthBelowSurface = SurfaceHeight - float(worldPos.y);
if (depthBelowSurface < 0.5) {
if (grassNoise < 0.65) voxelType = currentBiome.grassFoliage;
else if (grassNoise < 0.75) voxelType = currentBiome.flowers[randomBlockVal];
else if (grassNoise < 0.85) voxelType = currentBiome.otherFoliage[randomBlockVal];
else voxelType = 0u;
} else if (depthBelowSurface < 2.5) {
voxelType = currentBiome.surfaceBlock;
} else if (depthBelowSurface < 6.0) {
voxelType = currentBiome.dirtBlock;
} else {
voxelType = currentBiome.stoneBlock;
}
} else {
float YZone2 = floor(float(worldPos.y) / 75.0) * 75.0;
float IslandUnderneathHeight2 =
valueNoise(vec2(float(worldPos.x) - YZone2 * 2.0, float(worldPos.z) - YZone2 * 2.0) * 0.005) * 60.0 +
valueNoise(vec2(float(worldPos.x) + YZone2 * 2.0, float(worldPos.z) + YZone2 * 2.0) * 0.1) * 20.0 +
valueNoise(vec2(float(worldPos.x) + YZone2 * 2.0, float(worldPos.z) + YZone2 * 2.0) * 0.1) * 10.0 +
valueNoise(vec2(float(worldPos.x) + YZone2 * 2.0, float(worldPos.z) + YZone2 * 2.0)) * 0.5 -
5.0 +
YZone2;
float height2 =
valueNoise(vec2(float(worldPos.x) + YZone2 * 2.0, float(worldPos.z) + YZone2 * 2.0) * 0.005) * 50.0 +
valueNoise(vec2(float(worldPos.x) + YZone2 * 2.0, float(worldPos.z) + YZone2 * 2.0) * 0.01) * 10.0 +
valueNoise(vec2(float(worldPos.x) + YZone2 * 2.0, float(worldPos.z) + YZone2 * 2.0) * 0.1) * 5.0 +
valueNoise(vec2(float(worldPos.x) + YZone2 * 2.0, float(worldPos.z) + YZone2 * 2.0)) * 0.5 +
YZone2;
if (float(worldPos.y) <= height2 && float(worldPos.y) >= IslandUnderneathHeight2) {
float depthBelowSurface = height2 - float(worldPos.y);
if (depthBelowSurface < 0.5) {
if (grassNoise < 0.65) voxelType = currentBiome.grassFoliage;
else if (grassNoise < 0.75) voxelType = currentBiome.flowers[randomBlockVal];
else if (grassNoise < 0.85) voxelType = currentBiome.otherFoliage[randomBlockVal];
else voxelType = 0u;
} else if (depthBelowSurface < 1.5) {
voxelType = currentBiome.surfaceBlock;
} else if (depthBelowSurface < 6.0) {
voxelType = currentBiome.dirtBlock;
} else {
voxelType = currentBiome.stoneBlock;
}
}
}
if (voxelType != 0u && isCave(vec3(worldPos) * 0.05)) {
voxelType = 0u;
}
return voxelType;
}
bool isValidStructureAnchor(ivec3 origin, uint structureId, uint biome) {
Structure s = structureReg.structures[structureId];
ivec3 groundPos = origin + ivec3(0, -1, 0);
ivec3 basePos = origin;
uint groundVoxel = getBaseTerrainVoxelAt(groundPos, biome);
uint baseVoxel = getBaseTerrainVoxelAt(basePos, biome);
if (groundVoxel == 0u) {
return false;
}
if (s.groundBlock != 0u && groundVoxel != s.groundBlock) {
return false;
}
if (baseVoxel != 0u) {
return false;
}
if (isCave(vec3(groundPos) * 0.05)) {
return false;
}
return true;
}
int getStructureReferenceY(int worldY) {
return floorDiv(worldY, 75) * 75;
}
bool isStructureFootprintSupported(ivec3 origin, uint structureId, uint biome) {
Structure s = structureReg.structures[structureId];
int supportedCorners = 0;
ivec3 p0 = origin + ivec3(0, -1, 0);
ivec3 p1 = origin + ivec3(int(s.sizeX) - 1, -1, 0);
ivec3 p2 = origin + ivec3(0, -1, int(s.sizeZ) - 1);
ivec3 p3 = origin + ivec3(int(s.sizeX) - 1, -1, int(s.sizeZ) - 1);
if (getBaseTerrainVoxelAt(p0, biome) != 0u) supportedCorners++;
if (getBaseTerrainVoxelAt(p1, biome) != 0u) supportedCorners++;
if (getBaseTerrainVoxelAt(p2, biome) != 0u) supportedCorners++;
if (getBaseTerrainVoxelAt(p3, biome) != 0u) supportedCorners++;
return supportedCorners == 4;
}
StructureVoxelResult getStructureVoxelAt(ivec3 worldPos, uint biome) {
StructureVoxelResult result;
result.block = 0u;
result.flags = 0u;
if (structureCount == 0u) {
return result;
}
for (uint structureId = 0u; structureId < structureCount; structureId++) {
Structure s = structureReg.structures[structureId];
if (s.allowedBiome != 0u && s.allowedBiome != biome + 1u) {
continue;
}
int spacing = int(max(s.spawnSpacing, 1u));
ivec3 baseCell = getStructureCell3D(worldPos, spacing);
for (int ox = -1; ox <= 1; ox++) {
for (int oy = -1; oy <= 1; oy++) {
for (int oz = -1; oz <= 1; oz++) {
ivec3 cell = baseCell + ivec3(ox, oy, oz);
uint seed = hash31(cell + ivec3(0, int(structureId) * 97, 0)) ^ worldSeed;
if (!cellSpawnsStructure(seed, s)) {
continue;
}
ivec2 anchorXZ = getStructureAnchorXZ(cell.xz, seed, s.spawnSpacing);
// Match getStructureBlock's uncentered footprint before sampling terrain.
ivec2 localXZ = worldPos.xz - anchorXZ;
if (localXZ.x < 0 || localXZ.x >= int(s.sizeX) ||
localXZ.y < 0 || localXZ.y >= int(s.sizeZ)) {
continue;
}
int referenceY = cell.y * 75;
float anchorHeight = getSurfaceHeight(int(anchorXZ.x - s.sizeX/2), int(anchorXZ.y - s.sizeZ/2), referenceY);
int anchorY = int(floor(anchorHeight)) + 1;
ivec3 origin = ivec3(anchorXZ.x, anchorY, anchorXZ.y);
if (!isValidStructureAnchor(origin, structureId, biome)) {
continue;
}
ivec3 local = worldPos - origin;
uint block = getStructureBlock(structureId, local);
if (block != 0u) {
result.block = block;
result.flags = s.flags;
return result;
}
}
}
}
}
return result;
}
void main() {
if (any(greaterThanEqual(gl_GlobalInvocationID.xyz, uvec3(SCRATCH_SIZE)))) {
return;
}
ivec3 localPos = ivec3(gl_GlobalInvocationID.xyz) - ivec3(1);
ivec3 worldPos = chunkPos * CHUNK_SIZE + localPos;
uint biome = GetBiome(vec3(worldPos.z, worldPos.y, worldPos.x) * 0.005, biomeCount);
Biome currentBiome = BiomeReg.biomes[biome];
float YZone = floor(worldPos.y/150.0)*150.0;
float SurfaceHeight = valueNoise(vec2(worldPos.x + YZone * 2, worldPos.z + YZone * 2) * 0.005) * 100 +
valueNoise(vec2(worldPos.x + YZone * 2, worldPos.z + YZone * 2) * 0.01) * 10 +
valueNoise(vec2(worldPos.x + YZone * 2, worldPos.z + YZone * 2) * 0.1) * 5 +
valueNoise(vec2(worldPos.x + YZone * 2, worldPos.z + YZone * 2)) * 0.5 + YZone;
uint RandomBlockVal = randomRangeUint(uint(worldPos.x) * 73856093u ^ uint(worldPos.z) * 19349663u,0u ,3u);
float IslandUnderneathHeight = valueNoise(vec2(worldPos.x + YZone * 2, worldPos.z + YZone * 2) * 0.005) * 100 +
valueNoise(vec2(worldPos.x + YZone * 2, worldPos.z + YZone * 2) * 0.1) * 20 +
valueNoise(vec2(worldPos.x + YZone * 2, worldPos.z + YZone * 2) * 0.1) * 5 +
valueNoise(vec2(worldPos.x + YZone * 2, worldPos.z + YZone * 2)) * 0.5 - 15 + YZone;
float grassNoise = valueNoise(vec2(worldPos.z * 0.5 - YZone * 2, worldPos.x * 0.5 - YZone * 2));
uint voxelType = 0u;
if (float(worldPos.y) <= SurfaceHeight && float(worldPos.y) >= IslandUnderneathHeight) {
float depthBelowSurface = SurfaceHeight - float(worldPos.y);
if (depthBelowSurface < 0.5) {
if(grassNoise < 0.65) voxelType = currentBiome.grassFoliage; // Grass foliage
else if (grassNoise < 0.75) voxelType = currentBiome.flowers[RandomBlockVal];
else if (grassNoise < 0.85) voxelType = currentBiome.otherFoliage[RandomBlockVal];
else voxelType = 0u;
}else if (depthBelowSurface < 2.5) {
voxelType = currentBiome.surfaceBlock; // Grass
} else if (depthBelowSurface < 6.0) {
voxelType = currentBiome.dirtBlock; // Dirt(also stone rn)
} else {
voxelType = currentBiome.stoneBlock; // Stone
}
}
else{
float YZone2 = floor(worldPos.y/75.0)*75.0;
float IslandUnderneathHeight2 = valueNoise(vec2(worldPos.x - YZone2 * 2, worldPos.z -YZone2 * 2) * 0.005) * 60 +
valueNoise(vec2(worldPos.x + YZone2 * 2, worldPos.z + YZone2 * 2) * 0.1) * 20 +
valueNoise(vec2(worldPos.x + YZone2 * 2, worldPos.z + YZone2 * 2) * 0.1) * 10+
valueNoise(vec2(worldPos.x + YZone2 * 2, worldPos.z + YZone2 * 2)) * 0.5 - 5 + YZone2;
float height2 = valueNoise(vec2(worldPos.x + YZone2 * 2, worldPos.z + YZone2 * 2) * 0.005) * 50 +
valueNoise(vec2(worldPos.x + YZone2 * 2, worldPos.z + YZone2 * 2) * 0.01) * 10 +
valueNoise(vec2(worldPos.x + YZone2 * 2, worldPos.z + YZone2 * 2) * 0.1) * 5+
valueNoise(vec2(worldPos.x + YZone2 * 2, worldPos.z + YZone2 * 2)) * 0.5 + YZone2;
if (float(worldPos.y) <= height2 && float(worldPos.y) >= IslandUnderneathHeight2) {
float depthBelowSurface = height2 - float(worldPos.y);
if (depthBelowSurface < 0.5) {
if (grassNoise < 0.65) voxelType = currentBiome.grassFoliage; // Grass foliage
else if (grassNoise < 0.75) voxelType = currentBiome.flowers[RandomBlockVal];
else if (grassNoise < 0.85) voxelType = currentBiome.otherFoliage[RandomBlockVal];
else voxelType = 0u;
} else if (depthBelowSurface < 1.5) {
voxelType = currentBiome.surfaceBlock; // Grass
} else if (depthBelowSurface < 6.0) {
voxelType = currentBiome.dirtBlock; // Dirt(also stone rn)
} else {
voxelType = currentBiome.stoneBlock; // Stone
}
}
}
if (voxelType != 0u) {
if (isCave(vec3(worldPos*0.05))) {
voxelType = 0u;
}
}
StructureVoxelResult structureVoxel = getStructureVoxelAt(worldPos, biome);
if (structureVoxel.block != 0u) {
if (hasFlag(structureVoxel.flags, uint(REPLACE_AIR_ONLY))) {
if (voxelType == 0u) {
voxelType = structureVoxel.block;
}
} else {
voxelType = structureVoxel.block;
}
}
uint index = uint(slot * SCRATCH_VOXEL_COUNT + (localPos.x + 1) * SCRATCH_AREA +
(localPos.y + 1) * SCRATCH_SIZE + localPos.z + 1);
voxels[index] = voxelType;
}

View file

@ -1,29 +0,0 @@
#version 450
layout(location = 0) in vec3 fragPosition;
layout(location = 1) in vec4 fragWeights;
layout(location = 2) in vec2 fragUV;
layout(binding = 1) uniform sampler2DArray terrainTexArray;
layout(location = 0) out vec4 outColor;
void main() {
vec4 colorGrass = texture(terrainTexArray, vec3(fragUV, 0.0)); // Index 0
vec4 colorRock = texture(terrainTexArray, vec3(fragUV, 1.0)); // Index 1
vec4 colorSand = texture(terrainTexArray, vec3(fragUV, 2.0)); // Index 2
vec4 colorMud = texture(terrainTexArray, vec3(fragUV, 3.0)); // Index 3
vec4 dynamicTerrainColor =
(colorGrass * fragWeights.r) +
(colorRock * fragWeights.g) +
(colorSand * fragWeights.b) +
(colorMud * fragWeights.a);
float totalWeight = fragWeights.r + fragWeights.g + fragWeights.b + fragWeights.a;
if (totalWeight > 0.0) {
dynamicTerrainColor /= totalWeight;
}
outColor = dynamicTerrainColor;
}

View file

@ -1,21 +0,0 @@
#version 450
layout(binding = 0) uniform UniformBufferObject {
mat4 model;
mat4 view;
mat4 proj;
} ubo;
layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec4 inMaterialWeights;
layout(location = 0) out vec3 fragPosition;
layout(location = 1) out vec4 fragWeights;
layout(location = 2) out vec2 fragUV;
void main() {
gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 1.0);
fragPosition = inPosition;
fragWeights = inMaterialWeights;
fragUV = inPosition.xz * 0.1;
}

View file

@ -1,29 +0,0 @@
#version 450
layout(location = 0) in vec2 inTextCoord;
layout(location = 0) out vec4 outBloomColour;
layout(set = 0, binding = 0) uniform sampler2D inputTexture;
layout(push_constant) uniform PassConfig {
int horizontal;
float GAMMA_CONST;
float Exposure;
float blur_radius;
vec2 bloomSize;
} config;
vec3 extractBloom(vec2 uv) {
vec3 color = max(texture(inputTexture, uv).rgb, vec3(0.0));
float brightness = dot(color, vec3(0.2126, 0.7152, 0.0722));
float contribution = max(brightness - 1.0, 0.0);
return color * (contribution / (contribution + 0.5));
}
void main() {
vec2 offset = 0.25 / config.bloomSize;
vec3 bloom = extractBloom(inTextCoord + vec2(-offset.x, -offset.y))
+ extractBloom(inTextCoord + vec2( offset.x, -offset.y))
+ extractBloom(inTextCoord + vec2(-offset.x, offset.y))
+ extractBloom(inTextCoord + vec2( offset.x, offset.y));
outBloomColour = vec4(bloom * 0.25, 1.0);
}

View file

@ -1,30 +0,0 @@
#version 450
layout(location = 0) out vec4 FragColor;
layout(location = 0) in vec2 TexCoords;
layout(set = 0, binding = 0) uniform sampler2D bloomImage;
layout(push_constant) uniform PassConfig {
int horizontal;
float GAMMA_CONST;
float Exposure;
float blur_radius;
vec2 bloomSize;
} config;
const float weight[5] = float[](0.227027, 0.1945946, 0.1216216, 0.054054, 0.016216);
vec3 safeBloomSample(vec2 uv) {
return max(texture(bloomImage, uv).rgb, vec3(0.0));
}
void main() {
vec2 tex_offset = config.blur_radius / vec2(textureSize(bloomImage, 0));
vec2 direction = config.horizontal != 0 ? vec2(tex_offset.x, 0.0) : vec2(0.0, tex_offset.y);
vec3 result = safeBloomSample(TexCoords) * weight[0];
for (int i = 1; i < 5; i++) {
result += safeBloomSample(TexCoords + direction * i) * weight[i];
result += safeBloomSample(TexCoords - direction * i) * weight[i];
}
FragColor = vec4(result, 1.0);
}

View file

@ -1,11 +0,0 @@
#version 450
layout(location = 0) in vec3 outTexCoords;
layout(location = 0) out vec4 outColor;
layout(set = 2, binding = 0) uniform samplerCube skyboxSampler;
void main() {
outColor = vec4(texture(skyboxSampler, outTexCoords).rgb, 1.0);
}

View file

@ -1,172 +0,0 @@
#version 450
#extension GL_EXT_scalar_block_layout: require
// CREDITS: functions obtained from this link: https://github.com/SaschaWillems/Vulkan
// developed by Sascha Willems, https://twitter.com/JoeyDeVriez, licensed under MIT License (MIT)
// also Vulkan Book https://github.com/lwjglgamedev/vulkanbook/blob/master/bookcontents/chapter-15/chapter-15.md
const int MAX_LIGHTS = 1000;
const float PI = 3.14159265359;
struct Light {
vec3 position;
uint directional;
float intensity;
vec3 color;
};
layout(location = 0) in vec2 inTextCoord;
layout(location = 0) out vec4 outFragColor;
layout(set = 0, binding = 0) uniform sampler2D posSampler;
layout(set = 0, binding = 1) uniform sampler2D albedoSampler;
layout(set = 0, binding = 2) uniform sampler2D normalsSampler;
layout(set = 0, binding = 3) uniform sampler2D pbrSampler;
layout(set = 0, binding = 4) uniform sampler2D emissiveSampler;
layout(set = 0, binding = 5) uniform sampler2D TranslucencySampler;
layout(set = 0, binding = 6) uniform sampler2D OpacitySampler;
layout(set = 0, binding = 7) uniform sampler2D ViewPos;
layout(set = 0, binding = 8) uniform sampler2D ssaoBlur;
layout(scalar, set = 1, binding = 0) readonly buffer Lights {
Light lights[];
} lights;
layout(scalar, set = 2, binding = 0) uniform SceneInfo {
vec3 camPos;
float ambientLightIntensity;
vec3 ambientLightColor;
uint numLights;
mat4 viewMatrix;
} sceneInfo;
float distributionGGX(vec3 N, vec3 H, float roughness) {
float a = roughness * roughness;
float a2 = a * a;
float NdotH = max(dot(N, H), 0.0);
float NdotH2 = NdotH * NdotH;
float nom = a2;
float denom = (NdotH2 * (a2 - 1.0) + 1.0);
denom = PI * denom * denom;
return nom / denom;
}
float geometrySchlickGGX(float NdotV, float roughness) {
float r = (roughness + 1.0);
float k = (r * r) / 8.0;
float nom = NdotV;
float denom = NdotV * (1.0 - k) + k;
return nom / denom;
}
float geometrySmith(vec3 N, vec3 V, vec3 L, float roughness) {
float NdotV = max(dot(N, V), 0.0);
float NdotL = max(dot(N, L), 0.0);
float ggx2 = geometrySchlickGGX(NdotV, roughness);
float ggx1 = geometrySchlickGGX(NdotL, roughness);
return ggx1 * ggx2;
}
vec3 fresnelSchlick(float cosTheta, vec3 F0) {
return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0);
}
vec3 calculatePointLight(Light light, vec3 worldPos, vec3 V, vec3 N, vec3 F0, vec3 albedo, float metallic, float roughness) {
vec3 tmpSub = light.position - worldPos;
vec3 L = normalize(tmpSub);
vec3 H = normalize(V + L);
// Calculate distance and attenuation
float distance = length(tmpSub);
float attenuation = 1.0 / (distance * distance);
float intensity = 10.0f;
vec3 radiance = light.color * light.intensity * attenuation;
// Cook-Torrance BRDF
float NDF = distributionGGX(N, H, roughness);
float G = geometrySmith(N, V, L, roughness);
vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0);
vec3 numerator = NDF * G * F;
float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001;
vec3 specular = numerator / denominator;
vec3 kS = F;
vec3 kD = vec3(1.0) - kS;
kD *= 1.0 - metallic;
float NdotL = max(dot(N, L), 0.0);
return (kD * albedo / PI + specular) * radiance * NdotL;
}
vec3 calculateDirectionalLight(Light light, vec3 V, vec3 N, vec3 F0, vec3 albedo, float metallic, float roughness) {
vec3 L = normalize(-light.position);
vec3 H = normalize(V + L);
vec3 radiance = light.color * light.intensity;
// Cook-Torrance BRDF
float NDF = distributionGGX(N, H, roughness);
float G = geometrySmith(N, V, L, roughness);
vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0);
vec3 numerator = NDF * G * F;
float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001;
vec3 specular = numerator / denominator;
vec3 kS = F;
vec3 kD = vec3(1.0) - kS;
kD *= 1.0 - metallic;
float NdotL = max(dot(N, L), 0.0);
return (kD * albedo / PI + specular) * radiance * NdotL;
}
void main() {
vec3 albedo = texture(albedoSampler, inTextCoord).rgb;
vec4 normalW = texture(normalsSampler, inTextCoord);
vec3 normal = normalW.rgb;
vec3 viewPos = texture(ViewPos, inTextCoord).rgb;
vec3 worldPos = texture(posSampler, inTextCoord).rgb;
vec4 pbr = texture(pbrSampler, inTextCoord);
vec3 emissive = texture(emissiveSampler, inTextCoord).rgb;
vec3 translucency = texture(TranslucencySampler, inTextCoord).rgb;
float emissiveness = emissive.r;
float ssao = texture(ssaoBlur, inTextCoord).r;
float roughness = pbr.g;
float metallic = pbr.b;
vec3 N = normalize(normal);
vec3 V = normalize(sceneInfo.camPos - worldPos);
vec3 F0 = vec3(0.04);
F0 = mix(F0, albedo, metallic);
vec3 Lo = vec3(0.0);
for (uint i = 0; i < sceneInfo.numLights; i++) {
Light light = lights.lights[i];
if (light.directional == 1) {
Lo += calculateDirectionalLight(light, V, N, F0, albedo, metallic, roughness);
} else {
Lo += calculatePointLight(light, worldPos, V, N, F0, albedo, metallic, roughness);
}
}
vec3 ambient = sceneInfo.ambientLightColor * albedo * sceneInfo.ambientLightIntensity * vec3(ssao,ssao,ssao);;
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);
if (length(normal) < 0.001) {
outFragColor = vec4(albedo,1.0f);
return;
}
// outFragColor = vec4(normal, 1.0f);
}

View file

@ -1,291 +0,0 @@
#version 450
#extension GL_EXT_scalar_block_layout: require
// CREDITS: Most of the functions here have been obtained from this link: https://github.com/SaschaWillems/Vulkan
// developed by Sascha Willems, https://twitter.com/JoeyDeVriez, and licensed under the terms of the MIT License (MIT)
layout (constant_id = 0) const int SHADOW_MAP_CASCADE_COUNT = 6;
layout (constant_id = 1) const int DEBUG_SHADOWS = 0;
const float PI = 3.14159265359;
struct Light {
vec3 position;
uint directional;
float intensity;
vec3 color;
};
struct CascadeShadow {
mat4 projViewMatrix;
vec4 splitDistance;
};
layout(location = 0) in vec2 inTextCoord;
layout(location = 0) out vec4 outFragColor;
layout(set = 0, binding = 0) uniform sampler2D posSampler;
layout(set = 0, binding = 1) uniform sampler2D albedoSampler;
layout(set = 0, binding = 2) uniform sampler2D normalsSampler;
layout(set = 0, binding = 3) uniform sampler2D pbrSampler;
layout(set = 0, binding = 4) uniform sampler2D emissiveSampler;
layout(set = 0, binding = 5) uniform sampler2D TranslucencySampler;
layout(set = 0, binding = 6) uniform sampler2D OpacitySampler;
layout(set = 0, binding = 7) uniform sampler2D viewPos;
layout(set = 0, binding = 8) uniform sampler2D ssaoBlur;
layout(set = 0, binding = 9) uniform sampler2DArray shadowSampler;
layout(scalar, set = 1, binding = 0) readonly buffer Lights {
Light lights[];
} lights;
layout(set = 2, binding = 0) readonly buffer Shadows {
CascadeShadow cascadeshadows[];
} shadows;
layout(scalar, set = 3, binding = 0) uniform SceneInfo {
vec3 camPos;
float ambientLightIntensity;
vec3 ambientLightColor;
uint numLights;
mat4 viewMatrix;
} sceneInfo;
float chebyshevUpperBound(vec2 moments, float t) {
// Surface is fully lit if the current fragment is before the light occluder
if (t <= moments.x)
return 1.0;
// Compute variance
float variance = moments.y - (moments.x * moments.x);
variance = max(variance, 0.00002); // Small epsilon to avoid divide by zero
// Compute probabilistic upper bound
float d = t - moments.x;
float p_max = variance / (variance + d * d);
// Reduce light bleeding
p_max = smoothstep(0.5, 1.0, p_max);
return p_max;
}
float calcVisibility(vec4 worldPosition, uint cascadeIndex, vec2 texelSize) {
vec4 shadowMapPosition = shadows.cascadeshadows[cascadeIndex].projViewMatrix * worldPosition;
if (!(shadowMapPosition.w > 0.0) || any(isnan(shadowMapPosition)) || any(isinf(shadowMapPosition))) {
return 1.0;
}
shadowMapPosition.xyz /= shadowMapPosition.w;
vec2 uv = vec2(
shadowMapPosition.x * 0.5 + 0.5,
shadowMapPosition.y * -0.5 + 0.5
);
float depth = shadowMapPosition.z;
if (uv.x < 0.0 || uv.x > 1.0 ||
uv.y < 0.0 || uv.y > 1.0 ||
depth < 0.0 || depth > 1.0) {
return 1.0;
}
float shadow = 0.0;
// vec2 moments = texture(shadowSampler, vec3((uv), cascadeIndex)).rg;
// float visibility = chebyshevUpperBound(moments, depth);
// shadow += visibility;
for(int x = -1; x <= 1; ++x)
{
for(int y = -1; y <= 1; ++y)
{
vec2 sampleUV = uv + vec2(x, y) * texelSize;
if (any(lessThan(sampleUV, vec2(0.0))) || any(greaterThan(sampleUV, vec2(1.0)))) {
shadow += 1.0;
continue;
}
sampleUV = clamp(sampleUV, texelSize * 0.5, vec2(1.0) - texelSize * 0.5);
vec2 moments = texture(shadowSampler, vec3(sampleUV, cascadeIndex)).rg;
float visibility = chebyshevUpperBound(moments, depth);
shadow += visibility;
}
}
shadow /= 9.0;
return shadow;
}
float distributionGGX(vec3 N, vec3 H, float roughness) {
float a = roughness * roughness;
float a2 = a * a;
float NdotH = max(dot(N, H), 0.0);
float NdotH2 = NdotH * NdotH;
float nom = a2;
float denom = (NdotH2 * (a2 - 1.0) + 1.0);
denom = PI * denom * denom;
return nom / denom;
}
float geometrySchlickGGX(float NdotV, float roughness) {
float r = (roughness + 1.0);
float k = (r * r) / 8.0;
float nom = NdotV;
float denom = NdotV * (1.0 - k) + k;
return nom / denom;
}
float geometrySmith(vec3 N, vec3 V, vec3 L, float roughness) {
float NdotV = max(dot(N, V), 0.0);
float NdotL = max(dot(N, L), 0.0);
float ggx2 = geometrySchlickGGX(NdotV, roughness);
float ggx1 = geometrySchlickGGX(NdotL, roughness);
return ggx1 * ggx2;
}
vec3 fresnelSchlick(float cosTheta, vec3 F0) {
return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0);
}
vec3 calculatePointLight(Light light, vec3 worldPos, vec3 V, vec3 N, vec3 F0, vec3 albedo, float metallic, float roughness) {
vec3 tmpSub = light.position - worldPos;
vec3 L = normalize(tmpSub);
vec3 H = normalize(V + L);
// Calculate distance and attenuation
float distance = length(tmpSub);
float attenuation = 1.0 / (distance * distance);
float intensity = 10.0f;
vec3 radiance = light.color * light.intensity * attenuation;
// Cook-Torrance BRDF
float NDF = distributionGGX(N, H, roughness);
float G = geometrySmith(N, V, L, roughness);
vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0);
vec3 numerator = NDF * G * F;
float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001;
vec3 specular = numerator / denominator;
vec3 kS = F;
vec3 kD = vec3(1.0) - kS;
kD *= 1.0 - metallic;
float NdotL = max(dot(N, L), 0.0);
return (kD * albedo / PI + specular) * radiance * NdotL;
}
vec3 calculateDirectionalLight(Light light, vec3 V, vec3 N, vec3 F0, vec3 albedo, float metallic, float roughness, float translucency) {
vec3 L = normalize(-light.position);
vec3 H = normalize(V + L);
vec3 radiance = light.color * light.intensity;
// Cook-Torrance BRDF
float NDF = distributionGGX(N, H, roughness);
float G = geometrySmith(N, V, L, roughness);
vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0);
vec3 numerator = NDF * G * F;
float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001;
vec3 specular = numerator / denominator;
vec3 kS = F;
vec3 kD = vec3(1.0) - kS;
kD *= 1.0 - metallic;
float NdotL = max(dot(N, L), 0.0);
vec3 shadowValue = (kD * albedo / PI + specular) * radiance * NdotL;
vec3 lightValue = (kD * albedo / PI + specular) * radiance;
return (shadowValue * (1 - translucency)) + (lightValue * translucency);
}
void main() {
vec3 albedo = texture(albedoSampler, inTextCoord).rgb;
vec4 normalW = texture(normalsSampler, inTextCoord);
vec3 normal = normalW.rgb;
vec4 worldPosW = texture(posSampler, inTextCoord);
vec3 worldPos = worldPosW.xyz;
vec4 pbrW = texture(pbrSampler, inTextCoord);
vec3 pbr = pbrW.rgb;
vec3 emissive = texture(emissiveSampler, inTextCoord).rgb;
vec3 Opacity = texture(OpacitySampler, inTextCoord).rgb;
vec3 translucency = texture(TranslucencySampler, inTextCoord).rgb;
float Reflectivity = pbrW.a;
float Refractivity = normalW.a;
float emissiveness = emissive.r;
float translucencyf = translucency.r;
float ssao = texture(ssaoBlur, inTextCoord).r;
// outFragColor = vec4(emissive,1);
// return;
float opacityf = Opacity.x + Opacity.y + Opacity.z;
opacityf = opacityf/3.0;
float roughness = pbr.g;
float metallic = pbr.b;
vec3 N = normalize(normal);
vec3 V = normalize(sceneInfo.camPos - worldPos);
vec3 F0 = vec3(0.04);
F0 = mix(F0, albedo, metallic);
uint cascadeIndex = SHADOW_MAP_CASCADE_COUNT;
vec4 viewPos = sceneInfo.viewMatrix * vec4(worldPos, 1.0);
float lastSplit = shadows.cascadeshadows[SHADOW_MAP_CASCADE_COUNT - 1].splitDistance.x;
float shadow = 1.0;
if (lastSplit < 0.0 && viewPos.z < 0.0 && viewPos.z >= lastSplit) {
cascadeIndex = 0;
for (uint i = 0; i < SHADOW_MAP_CASCADE_COUNT - 1; ++i) {
if (viewPos.z < shadows.cascadeshadows[i].splitDistance.x) {
cascadeIndex = i + 1;
}
}
vec2 texelSizeShadow = 1.0 / textureSize(shadowSampler, 0).rg;
shadow = calcVisibility(vec4(worldPos, 1), cascadeIndex, texelSizeShadow);
}
vec3 Lo = vec3(0.0);
for (uint i = 0; i < sceneInfo.numLights; i++) {
Light light = lights.lights[i];
if (light.directional == 1) {
Lo += calculateDirectionalLight(light, V, N, F0, albedo, metallic, roughness,translucencyf) * shadow;
} else {
Lo += calculatePointLight(light, worldPos, V, N, F0, albedo, metallic, roughness);
}
}
vec3 ambient = sceneInfo.ambientLightColor * albedo * sceneInfo.ambientLightIntensity * vec3(ssao,ssao,ssao);
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);
if (DEBUG_SHADOWS == 1 && cascadeIndex < SHADOW_MAP_CASCADE_COUNT) {
switch (cascadeIndex) {
case 0:
outFragColor.rgb *= vec3(1.0f, 0.25f, 0.25f);
break;
case 1:
outFragColor.rgb *= vec3(0.25f, 1.0f, 0.25f);
break;
case 2:
outFragColor.rgb *= vec3(0.25f, 0.25f, 1.0f);
break;
default:
outFragColor.rgb *= vec3(1.0f, 1.0f, 0.25f);
break;
}
}
if (length(normal) < 0.001) {
outFragColor = vec4(albedo,1.0f);
return;
}
}

View file

@ -1,34 +0,0 @@
#version 450
layout(location = 0) in vec2 inTextCoord;
layout(location = 0) out vec4 outBloomColour;
layout(set = 0, binding = 0) uniform sampler2DMS inputTexture;
layout(push_constant) uniform PassConfig {
int horizontal;
float GAMMA_CONST;
float Exposure;
float blur_radius;
vec2 bloomSize;
} config;
vec3 extractBloom(vec2 uv) {
ivec2 size = textureSize(inputTexture);
ivec2 pixel = clamp(ivec2(uv * vec2(size)), ivec2(0), size - 1);
int samples = textureSamples(inputTexture);
vec3 color = vec3(0.0);
for (int i = 0; i < samples; i++) color += texelFetch(inputTexture, pixel, i).rgb;
color = max(color / float(samples), vec3(0.0));
float brightness = dot(color, vec3(0.2126, 0.7152, 0.0722));
float contribution = max(brightness - 1.0, 0.0);
return color * (contribution / (contribution + 0.5));
}
void main() {
vec2 offset = 0.25 / config.bloomSize;
vec3 bloom = extractBloom(inTextCoord + vec2(-offset.x, -offset.y))
+ extractBloom(inTextCoord + vec2( offset.x, -offset.y))
+ extractBloom(inTextCoord + vec2(-offset.x, offset.y))
+ extractBloom(inTextCoord + vec2( offset.x, offset.y));
outBloomColour = vec4(bloom * 0.25, 1.0);
}

View file

@ -1,42 +1,53 @@
#version 450 #version 450
layout(constant_id = 0) const int USE_AA = 0;
const float GAMMA_CONST = 0.4545;
const float SPAN_MAX = 8.0;
const float REDUCE_MIN = 1.0/128.0;
const float REDUCE_MUL = 1.0/32.0;
layout(location = 0) in vec2 inTextCoord; layout(location = 0) in vec2 inTextCoord;
layout(location = 0) out vec4 outFragColor; layout(location = 0) out vec4 outFragColor;
layout(set = 0, binding = 0) uniform sampler2DMS inputTexture; layout(set = 0, binding = 0) uniform sampler2DMS inputTexture;
layout(set = 0, binding = 1) uniform sampler2D bloomImage;
layout(push_constant) uniform PassConfig { layout(set = 1, binding = 0) uniform ScreenSize{
int horizontal; vec2 size;
float GAMMA_CONST; } screenSize;
float Exposure;
float blur_radius;
vec2 bloomSize;
} config;
vec4 msaa(int sampleCount, sampler2DMS textureIn, vec2 TextCoord) { vec4 gamma(vec4 color){
ivec2 size = textureSize(textureIn); return color = vec4(pow(color.rgb,vec3(GAMMA_CONST)),color.a);
ivec2 pixelCoords = clamp(ivec2(TextCoord * vec2(size)), ivec2(0), size - 1); }
vec4 msaa(int sampleCount, sampler2DMS textureIn,vec2 TextCoord){
ivec2 pixelCoords = ivec2(TextCoord * textureSize(textureIn));
vec4 colorSum = vec4(0.0); vec4 colorSum = vec4(0.0);
for (int i = 0; i < sampleCount; i++) colorSum += texelFetch(textureIn, pixelCoords, i);
for(int i = 0; i < sampleCount; ++i) {
vec4 sampleColor = texelFetch(textureIn, pixelCoords, i);
colorSum += sampleColor;
}
return colorSum / float(sampleCount); return colorSum / float(sampleCount);
} }
vec3 bloomAt(ivec2 pixel, ivec2 size) { void main(){
return texelFetch(bloomImage, clamp(pixel, ivec2(0), size - 1), 0).rgb; ivec2 pixelCoords = ivec2(inTextCoord * textureSize(inputTexture));
}
vec3 upsampleBloom(vec2 uv) { if(USE_AA == 0){
ivec2 size = textureSize(bloomImage, 0); outFragColor = texelFetch(inputTexture,pixelCoords,0);
vec2 pixel = uv * vec2(size) - 0.5; }
ivec2 base = ivec2(floor(pixel)); if(USE_AA == 1){
vec2 blend = fract(pixel); outFragColor = texelFetch(inputTexture,pixelCoords,0);
return mix(mix(bloomAt(base, size), bloomAt(base + ivec2(1, 0), size), blend.x), }
mix(bloomAt(base + ivec2(0, 1), size), bloomAt(base + ivec2(1, 1), size), blend.x), blend.y); if(USE_AA == 2){
} outFragColor = msaa(2,inputTexture,inTextCoord);
}
void main() { if(USE_AA == 3){
vec4 sceneColor = msaa(textureSamples(inputTexture), inputTexture, inTextCoord); outFragColor = msaa(4,inputTexture,inTextCoord);
vec3 hdrColour = max(sceneColor.rgb + upsampleBloom(inTextCoord), vec3(0.0)); }
vec3 result = vec3(1.0) - exp(-hdrColour * config.Exposure); if(USE_AA == 4){
outFragColor = vec4(pow(result, vec3(1.0 / config.GAMMA_CONST)), sceneColor.a); outFragColor = msaa(8,inputTexture,inTextCoord);
} }
outFragColor = gamma(outFragColor);
}

View file

@ -1,88 +0,0 @@
#version 450
#extension GL_EXT_nonuniform_qualifier : require
const int MAX_TEXTURES = 128;
layout(location = 0) in vec4 inPos;
layout(location = 1) in vec3 inNormal;
layout(location = 2) in vec3 inTangent;
layout(location = 3) in vec3 inBitangent;
layout(location = 4) in vec2 inTextCoords;
layout(location = 5) in mat4 viewMatrix;
layout(location = 9) in flat uint textureIndex;
layout(location = 0) out vec4 outAlbedo;
layout(location = 1) out vec4 outViewPos;
struct Material {
vec4 diffuseColor; //16
uint hasTexture; //20
uint textureIdx; //24
uint hasNormalMap; //28
uint normalMapIdx; //32
uint hasRoughMap; //36
uint roughMapIdx; //40
float roughnessFactor; //44
float metallicFactor; //48
vec4 emissiveColour; //64
uint hasEmissiveMap; //68
uint emissiveMapIdx; //72
uint hasTranslucencyMap; //76
uint translucencyMapIdx; //80
float translucencyFactor; //84
uint hasOpacityMap; //88
uint OpacityMapIdx; //92
float OpacityFactor; //96
float reflectiveness; //100
float refractiveness; //104
float Padding1; //108
float Padding2; //112
};
layout(set = 2, binding = 0) readonly buffer MaterialUniform{
Material materials[];
} matUniform;
layout(set = 3, binding = 0) uniform sampler2D textSampler[MAX_TEXTURES];
layout(push_constant) uniform pc{
layout(offset = 64) uint materialIdx;
} push_constants;
void main()
{
vec4 viewPos = vec4(viewMatrix * inPos);
outViewPos = viewPos;
Material material = matUniform.materials[textureIndex];
uint albedoTextureIndex = material.textureIdx;
if (albedoTextureIndex >= MAX_TEXTURES){
outAlbedo = vec4(0.0,0.0,1.0,1.0);
return;
}
if(material.hasTexture == 1){
vec4 texColor = texture(textSampler[nonuniformEXT(albedoTextureIndex)], inTextCoords);
outAlbedo = texColor;
} else{
outAlbedo = material.diffuseColor;
}
vec4 Opacity = vec4(outAlbedo.a, outAlbedo.a, outAlbedo.a, 1.0);
if (material.OpacityFactor > 0.0 && material.OpacityFactor < 1.0) {
Opacity = vec4(material.OpacityFactor, material.OpacityFactor, material.OpacityFactor, 1.0);
}
if (material.hasOpacityMap > 0 && material.OpacityMapIdx < MAX_TEXTURES) {
Opacity = texture(textSampler[nonuniformEXT(material.OpacityMapIdx)], inTextCoords);
}
float opacityf = Opacity.x + Opacity.y + Opacity.z;
opacityf = opacityf / 3;
if(opacityf < 0.4){ discard; }
outAlbedo = vec4(outAlbedo.rgb, opacityf);
}

View file

@ -1,149 +0,0 @@
#version 450
#extension GL_EXT_nonuniform_qualifier : require
const int MAX_TEXTURES = 128;
layout(location = 0) in vec4 inPos;
layout(location = 1) in vec3 inNormal;
layout(location = 2) in vec3 inTangent;
layout(location = 3) in vec3 inBitangent;
layout(location = 4) in vec2 inTextCoords;
layout(location = 5) in mat4 viewMatrix;
layout(location = 9) in flat uint MaterialID;
layout(location = 1) out vec4 outAlbedo ;
layout(location = 0) out vec4 outPos;
layout(location = 2) out vec4 outNormal;
layout(location = 3) out vec4 outPBR;
layout(location = 4) out vec4 outEmissive;
layout(location = 5) out vec4 outTranslucency;
layout(location = 6) out vec4 outOpacity;
layout(location = 7) out vec4 outViewPos;
struct Material {
vec4 diffuseColor; //16
uint hasTexture; //20
uint textureIdx; //24
uint hasNormalMap; //28
uint normalMapIdx; //32
uint hasRoughMap; //36
uint roughMapIdx; //40
float roughnessFactor; //44
float metallicFactor; //48
vec4 emissiveColour; //64
uint hasEmissiveMap; //68
uint emissiveMapIdx; //72
uint hasTranslucencyMap; //76
uint translucencyMapIdx; //80
float translucencyFactor; //84
uint hasOpacityMap; //88
uint OpacityMapIdx; //92
float OpacityFactor; //96
float reflectiveness; //100
float refractiveness; //104
float Padding1; //108
float Padding2; //112
};
layout(set = 2, binding = 0) readonly buffer MaterialUniform {
Material materials[];
} matUniform;
layout(set = 3, binding = 0) uniform sampler2D textSampler[MAX_TEXTURES];
vec3 calcNormal(Material material, vec3 normal, vec2 textCoords, mat3 TBN)
{
vec3 newNormal = normal;
if (material.hasNormalMap > 0 && material.normalMapIdx < MAX_TEXTURES)
{
newNormal = texture(textSampler[nonuniformEXT(material.normalMapIdx)], textCoords).rgb;
newNormal = normalize(newNormal * 2.0 - 1.0);
newNormal = normalize(TBN * newNormal);
}
return newNormal;
}
layout(push_constant) uniform pc {
layout(offset = 64) uint materialIdx;
} push_constants;
void main()
{
outPos = inPos;
vec4 viewPos = vec4(viewMatrix * vec4(inPos.xyz, 1.0));
outViewPos = viewPos;
Material material = matUniform.materials[MaterialID];
uint albedoTextureIndex = material.textureIdx;
if (albedoTextureIndex >= 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) {
outAlbedo = texture(textSampler[nonuniformEXT(albedoTextureIndex)], inTextCoords);
} else {
outAlbedo = material.diffuseColor;
}
vec4 Opacity = vec4(outAlbedo.a, outAlbedo.a, outAlbedo.a, 1.0);
if (material.OpacityFactor > 0.0 && material.OpacityFactor < 1.0) {
Opacity = vec4(material.OpacityFactor, material.OpacityFactor, material.OpacityFactor, 1.0);
}
if (material.hasOpacityMap > 0 && material.OpacityMapIdx < MAX_TEXTURES) {
outOpacity = texture(textSampler[nonuniformEXT(material.OpacityMapIdx)], inTextCoords);
} else {
outOpacity = Opacity;
}
Opacity = outOpacity;
float opacityf = Opacity.x + Opacity.y + Opacity.z;
opacityf = opacityf / 3;
outAlbedo = vec4(outAlbedo.rgb, opacityf);
if(outAlbedo.a < 0.5) discard;
mat3 TBN = mat3(inTangent, inBitangent, inNormal);
vec3 newNormal = calcNormal(material, inNormal, inTextCoords, TBN);
float ao = 0.5f;
float roughnessFactor = 0.0f;
float metallicFactor = 0.0f;
if (material.hasRoughMap > 0 && material.roughMapIdx < MAX_TEXTURES) {
vec4 metRoughValue = texture(textSampler[nonuniformEXT(material.roughMapIdx)], inTextCoords);
roughnessFactor = metRoughValue.g;
metallicFactor = metRoughValue.b;
} else {
roughnessFactor = material.roughnessFactor;
metallicFactor = material.metallicFactor;
}
vec4 emissive = material.emissiveColour;
if (material.hasEmissiveMap > 0 && material.emissiveMapIdx < MAX_TEXTURES) {
emissive = texture(textSampler[nonuniformEXT(material.emissiveMapIdx)], inTextCoords);
}
outEmissive = emissive;
vec4 Translucency = vec4(material.translucencyFactor, material.translucencyFactor, material.translucencyFactor, 1);
if(material.hasTranslucencyMap > 0 && material.translucencyMapIdx < MAX_TEXTURES){
Translucency = texture(textSampler[nonuniformEXT(material.translucencyMapIdx)], inTextCoords);
}
outTranslucency = Translucency;
float Refractiveness = material.refractiveness;
float Reflectiveness = material.reflectiveness;
outNormal = vec4(newNormal, Refractiveness);
outPBR = vec4(ao, roughnessFactor, metallicFactor, Reflectiveness);
}

View file

@ -1,96 +0,0 @@
#version 450
layout(location = 0) in uint inPackedVertex;
layout(location = 0) out vec4 outPos;
layout(location = 1) out vec3 outNormal;
layout(location = 2) out vec3 outTangent;
layout(location = 3) out vec3 outBitangent;
layout(location = 4) out vec2 outTextCoords;
layout(location = 5) out mat4 viewMatrix;
const vec3 NORMALS[6] = vec3[6](
vec3( 0.0, 1.0, 0.0),
vec3( 0.0, -1.0, 0.0),
vec3( 1.0, 0.0, 0.0),
vec3(-1.0, 0.0, 0.0),
vec3( 0.0, 0.0, 1.0),
vec3( 0.0, 0.0, -1.0)
);
const vec3 TANGENTS[6] = vec3[6](
vec3( 1.0, 0.0, 0.0),
vec3( 1.0, 0.0, 0.0),
vec3( 0.0, 0.0, -1.0),
vec3( 0.0, 0.0, 1.0),
vec3( 1.0, 0.0, 0.0),
vec3(-1.0, 0.0, 0.0)
);
const vec3 BITANGENTS[6] = vec3[6](
vec3( 0.0, 0.0, 1.0),
vec3( 0.0, 0.0, -1.0),
vec3( 0.0, 1.0, 0.0),
vec3( 0.0, 1.0, 0.0),
vec3( 0.0, 1.0, 0.0),
vec3( 0.0, 1.0, 0.0)
);
const vec2 CORNER_UVS[16] = vec2[16](
vec2(0.5, 0.0),
vec2(0.5, 0.5),
vec2(1.0, 0.5),
vec2(1.0, 0.0),
vec2(0.0, 0.5),
vec2(0.0, 1.0),
vec2(0.5, 1.0),
vec2(0.5, 0.5),
vec2(0.5, 0.0),
vec2(0.5, 0.5),
vec2(1.0, 0.5),
vec2(1.0, 0.0),
vec2(0.5, 0.0),
vec2(0.5, 0.5),
vec2(1.0, 0.5),
vec2(1.0, 0.0)
);
layout(set = 0, binding = 0) uniform ProjUniform { mat4 matrix; } projUniform;
layout(set = 1, binding = 0) uniform ViewUniform { mat4 matrix; } viewUniform;
layout(push_constant) uniform pc {
vec4 ModelOffset;
vec4 Padding0;
vec4 Padding1;
vec4 Padding2;
} push_constants;
void main() {
viewMatrix = viewUniform.matrix;
uint posX = inPackedVertex & 0x1Fu;
uint posY = (inPackedVertex >> 5u) & 0x1Fu;
uint posZ = (inPackedVertex >> 10u) & 0x1Fu;
uint faceIdx = (inPackedVertex >> 15u) & 0x7u;
uint cornerIdx = (inPackedVertex >> 18u) & 0x3u;
uint matId = (inPackedVertex >> 20u) & 0xFFu;
vec3 inPos = vec3(posX, posY, posZ) + push_constants.ModelOffset.xyz * 16.0;
vec3 inNormal = NORMALS[faceIdx];
vec3 inTangent = TANGENTS[faceIdx];
vec3 inBitangent = BITANGENTS[faceIdx];
vec2 inTextCoords = CORNER_UVS[cornerIdx + 4 * matId];
vec4 worldPos = vec4(inPos, 1.0);
gl_Position = projUniform.matrix * viewUniform.matrix * worldPos;
outPos = worldPos;
outNormal = inNormal;
outTangent = inTangent;
outBitangent = inBitangent;
outTextCoords = inTextCoords;
}

View file

@ -1,134 +0,0 @@
#version 450
layout(location = 0) out vec4 outPos;
layout(location = 1) out vec3 outNormal;
layout(location = 2) out vec3 outTangent;
layout(location = 3) out vec3 outBitangent;
layout(location = 4) out vec2 outTextCoords;
layout(location = 5) out mat4 viewMatrix;
layout(location = 9) out flat uint outMaterialID;
layout(set = 0, binding = 0) uniform ProjUniform { mat4 matrix; } projUniform;
layout(set = 1, binding = 0) uniform ViewUniform { mat4 matrix; } viewUniform;
layout(set = 4, binding = 0) readonly buffer FaceBuffer {
uint faces[];
};
layout(push_constant) uniform pc {
vec4 ModelOffset;
vec4 Padding0;
vec4 Padding1;
vec4 Padding2;
} push_constants;
const uint TRI_TO_CORNER[6] = uint[6](0u, 1u, 2u, 0u, 2u, 3u);
const vec3 NORMALS[8] = vec3[8](
vec3( 0.0, 1.0, 0.0), // Face 0 (+Y)
vec3( 0.0, -1.0, 0.0), // Face 1 (-Y)
vec3( 1.0, 0.0, 0.0), // Face 2 (+X)
vec3(-1.0, 0.0, 0.0), // Face 3 (-X)
vec3( 0.0, 0.0, 1.0), // Face 4 (+Z)
vec3( 0.0, 0.0, -1.0), // Face 5 (-Z)
vec3(-0.7071, 0.0, 0.7071), // Face 6
vec3( 0.7071, 0.0, 0.7071) // Face 7
);
const vec3 TANGENTS[8] = vec3[8](
vec3( 1.0, 0.0, 0.0), // Face 0
vec3( 1.0, 0.0, 0.0), // Face 1
vec3( 0.0, 0.0, -1.0), // Face 2
vec3( 0.0, 0.0, 1.0), // Face 3
vec3( 1.0, 0.0, 0.0), // Face 4
vec3(-1.0, 0.0, 0.0), // Face 5
vec3( 0.7071, 0.0, 0.7071), // Face 6
vec3( 0.7071, 0.0,-0.7071) // Face 7
);
const vec3 BITANGENTS[8] = vec3[8](
vec3( 0.0, 0.0, 1.0), // Face 0
vec3( 0.0, 0.0, -1.0), // Face 1
vec3( 0.0, 1.0, 0.0), // Face 2
vec3( 0.0, 1.0, 0.0), // Face 3
vec3( 0.0, 1.0, 0.0), // Face 4
vec3( 0.0, 1.0, 0.0), // Face 5
vec3( 0.0, 1.0, 0.0), // Face 6
vec3( 0.0, 1.0, 0.0) // Face 7
);
const vec2 CORNER_UVS[5][4] = vec2[5][4](
vec2[4](vec2(0.5, 0.0), vec2(0.5, 0.5), vec2(1.0, 0.5), vec2(1.0, 0.0)),
vec2[4](vec2(0.0, 0.5), vec2(0.0, 1.0), vec2(0.5, 1.0), vec2(0.5, 0.5)),
vec2[4](vec2(0.5, 0.0), vec2(0.5, 0.5), vec2(1.0, 0.5), vec2(1.0, 0.0)),
vec2[4](vec2(0.5, 0.0), vec2(0.5, 0.5), vec2(1.0, 0.5), vec2(1.0, 0.0)),
vec2[4](vec2(1.0, 1.0), vec2(1.0, 0.5), vec2(0.5, 0.5), vec2(0.5, 1.0))
);
const vec2 CORNER_UVS_GRASS_BLOCK[8][4] = vec2[8][4](
vec2[4](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0)),
vec2[4](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0)),
vec2[4](vec2(1.0, 1.0), vec2(1.0, 0.0),vec2(0.0, 0.0), vec2(0.0, 1.0)),
vec2[4]( vec2(0.0, 1.0),vec2(1.0, 1.0), vec2(1.0, 0.0),vec2(0.0, 0.0)),
vec2[4]( vec2(0.0, 1.0),vec2(1.0, 1.0), vec2(1.0, 0.0),vec2(0.0, 0.0)),
vec2[4](vec2(1.0, 1.0), vec2(1.0, 0.0),vec2(0.0, 0.0), vec2(0.0, 1.0)),
vec2[4](vec2(1.0, 1.0), vec2(1.0, 0.0), vec2(0.0, 0.0), vec2(0.0, 1.0)),
vec2[4](vec2(1.0, 1.0), vec2(1.0, 0.0), vec2(0.0, 0.0), vec2(0.0, 1.0))
);
const vec3 FACE_CORNERS[8][4] = vec3[8][4](
vec3[4](vec3(0.0, 1.0, 0.0), vec3(0.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 0.0)), // Face 0 (+Y)
vec3[4](vec3(0.0, 0.0, 0.0), vec3(1.0, 0.0, 0.0), vec3(1.0, 0.0, 1.0), vec3(0.0, 0.0, 1.0)), // Face 1 (-Y)
vec3[4](vec3(1.0, 0.0, 0.0), vec3(1.0, 1.0, 0.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 0.0, 1.0)), // Face 2 (+X)
vec3[4](vec3(0.0, 0.0, 0.0), vec3(0.0, 0.0, 1.0), vec3(0.0, 1.0, 1.0), vec3(0.0, 1.0, 0.0)), // Face 3 (-X)
vec3[4](vec3(0.0, 0.0, 1.0), vec3(1.0, 0.0, 1.0), vec3(1.0, 1.0, 1.0), vec3(0.0, 1.0, 1.0)), // Face 4 (+Z)
vec3[4](vec3(0.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(1.0, 1.0, 0.0), vec3(1.0, 0.0, 0.0)), // Face 5 (-Z)
vec3[4](vec3(0.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 0.0, 1.0)), // Face 6 (cross model pane 1)
vec3[4](vec3(0.0, 0.0, 1.0), vec3(0.0, 1.0, 1.0), vec3(1.0, 1.0, 0.0), vec3(1.0, 0.0, 0.0)) // Face 7 (cross model pane 2)
);
void main() {
viewMatrix = viewUniform.matrix;
uint faceRecordIndex = uint(gl_VertexIndex) / 6u;
uint triangleVertex = (uint(gl_VertexIndex))% 6u;
uint cornerIndex = TRI_TO_CORNER[triangleVertex];
uint packedFace = faces[faceRecordIndex];
uint voxelX = packedFace & 0xFu;
uint voxelY = (packedFace >> 4u) & 0xFu;
uint voxelZ = (packedFace >> 8u) & 0xFu;
uint faceId = (packedFace >> 12u) & 0x7u;
uint matId = (packedFace >> 15u) & 0x7FFu;
uint texIdxX = (packedFace >> 26u) & 0x7u;
uint texIdxY = (packedFace >> 29u) & 0x7u;
vec2 texID = vec2((texIdxX)/4.0,(texIdxY)/4.0);
vec2 scalar = vec2(1.0/4.0,1.0/4.0);
faceId = min(faceId, 7u);
vec3 localPos = vec3(voxelX, voxelY, voxelZ) + FACE_CORNERS[faceId][cornerIndex];
vec3 Offset = vec3(0,0,0);
if (gl_InstanceIndex != 0) {
uint encoded = uint(gl_InstanceIndex);
Offset = vec3(int(encoded & 1023u) - 512, int((encoded >> 10u) & 1023u) - 512,
int((encoded >> 20u) & 1023u) - 512) * 16.0;
}
vec3 worldPos = localPos + Offset + push_constants.ModelOffset.xyz * 16.0;
vec4 worldPosVec4 = vec4(worldPos, 1.0);
gl_Position = projUniform.matrix * viewUniform.matrix * worldPosVec4;
outPos = worldPosVec4;
outNormal = NORMALS[faceId];
outTangent = TANGENTS[faceId];
outBitangent = BITANGENTS[faceId];
vec2 atlasSize = vec2(64, 64);
vec2 texel = 0.5 / atlasSize;
vec2 tileMin = vec2(texIdxX, texIdxY) * scalar + texel;
vec2 tileMax = vec2(texIdxX + 1u, texIdxY + 1u) * scalar - texel;
outTextCoords = mix(tileMin, tileMax, CORNER_UVS_GRASS_BLOCK[faceId][cornerIndex]);
outMaterialID = matId;
}

View file

@ -2,6 +2,7 @@
layout(constant_id = 0) const int USE_AA = 0; layout(constant_id = 0) const int USE_AA = 0;
const float GAMMA_CONST = 0.4545;
const float SPAN_MAX = 8.0; const float SPAN_MAX = 8.0;
const float REDUCE_MIN = 1.0/128.0; const float REDUCE_MIN = 1.0/128.0;
const float REDUCE_MUL = 1.0/32.0; const float REDUCE_MUL = 1.0/32.0;
@ -10,19 +11,18 @@ layout(location = 0) in vec2 inTextCoord;
layout(location = 0) out vec4 outFragColor; layout(location = 0) out vec4 outFragColor;
layout(set = 0, binding = 0) uniform sampler2D inputTexture; layout(set = 0, binding = 0) uniform sampler2D inputTexture;
layout(set = 0, binding = 1) uniform sampler2D bloomImage;
layout(push_constant) uniform PassConfig { layout(set = 1, binding = 0) uniform ScreenSize{
int horizontal; vec2 size;
float GAMMA_CONST; } screenSize;
float Exposure;
float blur_radius; vec4 gamma(vec4 color){
vec2 bloomSize; return color = vec4(pow(color.rgb,vec3(GAMMA_CONST)),color.a);
} config; }
// Sourced from: https://mini.gmshaders.com/p/gm-shaders-mini-fxaa // Sourced from: https://mini.gmshaders.com/p/gm-shaders-mini-fxaa
vec4 fxaa(sampler2D tex, vec2 uv) { vec4 fxaa(sampler2D tex, vec2 uv) {
vec2 u_texel = 1.0 / vec2(textureSize(inputTexture, 0)); vec2 u_texel = 1.0 / screenSize.size;
//Sample center and 4 corners //Sample center and 4 corners
vec3 rgbCC = texture(tex, uv).rgb; vec3 rgbCC = texture(tex, uv).rgb;
@ -70,22 +70,21 @@ vec4 fxaa(sampler2D tex, vec2 uv) {
return ((lumaB < lumaMin) || (lumaB > lumaMax)) ? A : B; return ((lumaB < lumaMin) || (lumaB > lumaMax)) ? A : B;
} }
vec3 bloomAt(ivec2 pixel, ivec2 size) {
return texelFetch(bloomImage, clamp(pixel, ivec2(0), size - 1), 0).rgb;
}
vec3 upsampleBloom(vec2 uv) {
ivec2 size = textureSize(bloomImage, 0);
vec2 pixel = uv * vec2(size) - 0.5;
ivec2 base = ivec2(floor(pixel));
vec2 blend = fract(pixel);
return mix(mix(bloomAt(base, size), bloomAt(base + ivec2(1, 0), size), blend.x),
mix(bloomAt(base + ivec2(0, 1), size), bloomAt(base + ivec2(1, 1), size), blend.x), blend.y);
}
void main(){ void main(){
vec4 sceneColor = USE_AA == 1 ? fxaa(inputTexture, inTextCoord) : texture(inputTexture, inTextCoord);
vec3 hdrColour = max(sceneColor.rgb + upsampleBloom(inTextCoord), vec3(0.0)); if(USE_AA == 1){
vec3 result = vec3(1.0) - exp(-hdrColour * config.Exposure); outFragColor = fxaa(inputTexture, inTextCoord);
outFragColor = vec4(pow(result, vec3(1.0 / config.GAMMA_CONST)), sceneColor.a); outFragColor = gamma(outFragColor);
return;
}
if(USE_AA == 2){
}
if(USE_AA == 3){
}
if(USE_AA == 4){
}
outFragColor = gamma(texture(inputTexture,inTextCoord));
} }

View file

@ -0,0 +1,9 @@
#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);
}

View file

@ -1,40 +1,15 @@
#version 450 #version 450
const int MAX_TEXTURES = 128; const int MAX_TEXTURES = 500;
layout(location = 0) in vec4 inPos; layout(location = 0) in vec2 inTextCoords;
layout(location = 1) in vec3 inNormal; layout(location = 0) out vec4 outFragColor;
layout(location = 2) in vec3 inTangent;
layout(location = 3) in vec3 inBitangent;
layout(location = 4) in vec2 inTextCoords;
layout(location = 5) in mat4 viewMatrix;
layout(location = 0) out vec4 outAlbedo; struct Material{
layout(location = 1) out vec4 outViewPos; vec4 diffuseColor;
uint hasTexture;
struct Material { uint textureIdx;
vec4 diffuseColor; //16 uint padding[2];
uint hasTexture; //20
uint textureIdx; //24
uint hasNormalMap; //28
uint normalMapIdx; //32
uint hasRoughMap; //36
uint roughMapIdx; //40
float roughnessFactor; //44
float metallicFactor; //48
vec4 emissiveColour; //64
uint hasEmissiveMap; //68
uint emissiveMapIdx; //72
uint hasTranslucencyMap; //76
uint translucencyMapIdx; //80
float translucencyFactor; //84
uint hasOpacityMap; //88
uint OpacityMapIdx; //92
float OpacityFactor; //96
float reflectiveness; //100
float refractiveness; //104
float Padding1; //108
float Padding2; //112
}; };
layout(set = 2, binding = 0) readonly buffer MaterialUniform{ layout(set = 2, binding = 0) readonly buffer MaterialUniform{
@ -43,42 +18,18 @@ layout(set = 2, binding = 0) readonly buffer MaterialUniform{
layout(set = 3, binding = 0) uniform sampler2D textSampler[MAX_TEXTURES]; layout(set = 3, binding = 0) uniform sampler2D textSampler[MAX_TEXTURES];
layout(push_constant) uniform pc{ layout(push_constant) uniform pc{
layout(offset = 64) uint materialIdx; layout(offset = 64) uint materialIdx;
} push_constants; } push_constants;
void main() void main()
{ {
vec4 viewPos = vec4(viewMatrix * inPos);
outViewPos = viewPos;
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; if(texColor.a < 0.1){discard;}
outFragColor = texColor;
} else{ } else{
outAlbedo = material.diffuseColor; outFragColor = material.diffuseColor;
} }
vec4 Opacity = vec4(outAlbedo.a, outAlbedo.a, outAlbedo.a, 1.0);
if (material.OpacityFactor > 0.0 && material.OpacityFactor < 1.0) {
Opacity = vec4(material.OpacityFactor, material.OpacityFactor, material.OpacityFactor, 1.0);
}
if (material.hasOpacityMap > 0 && material.OpacityMapIdx < MAX_TEXTURES) {
Opacity = texture(textSampler[material.OpacityMapIdx], inTextCoords);
}
float opacityf = Opacity.x + Opacity.y + Opacity.z;
opacityf = opacityf/3;
if(opacityf < 0.4){discard;}
outAlbedo = vec4(outAlbedo.rgb, opacityf);
} }

View file

@ -1,143 +0,0 @@
#version 450
const int MAX_TEXTURES = 128;
layout(location = 0) in vec4 inPos;
layout(location = 1) in vec3 inNormal;
layout(location = 2) in vec3 inTangent;
layout(location = 3) in vec3 inBitangent;
layout(location = 4) in vec2 inTextCoords;
layout(location = 5) in mat4 viewMatrix;
layout(location = 1) out vec4 outAlbedo ;
layout(location = 0) out vec4 outPos;
layout(location = 2) out vec4 outNormal;
layout(location = 3) out vec4 outPBR;
layout(location = 4) out vec4 outEmissive;
layout(location = 5) out vec4 outTranslucency;
layout(location = 6) out vec4 outOpacity;
layout(location = 7) out vec4 outViewPos;
struct Material {
vec4 diffuseColor; //16
uint hasTexture; //20
uint textureIdx; //24
uint hasNormalMap; //28
uint normalMapIdx; //32
uint hasRoughMap; //36
uint roughMapIdx; //40
float roughnessFactor; //44
float metallicFactor; //48
vec4 emissiveColour; //64
uint hasEmissiveMap; //68
uint emissiveMapIdx; //72
uint hasTranslucencyMap; //76
uint translucencyMapIdx; //80
float translucencyFactor; //84
uint hasOpacityMap; //88
uint OpacityMapIdx; //92
float OpacityFactor; //96
float reflectiveness; //100
float refractiveness; //104
float Padding1; //108
float Padding2; //112
};
layout(set = 2, binding = 0) readonly buffer MaterialUniform {
Material materials[];
} matUniform;
layout(set = 3, binding = 0) uniform sampler2D textSampler[MAX_TEXTURES];
vec3 calcNormal(Material material, vec3 normal, vec2 textCoords, mat3 TBN)
{
vec3 newNormal = normal;
if (material.hasNormalMap > 0)
{
newNormal = texture(textSampler[material.normalMapIdx], textCoords).rgb;
newNormal = normalize(newNormal * 2.0 - 1.0);
newNormal = normalize(TBN * newNormal);
}
return newNormal;
}
layout(push_constant) uniform pc {
layout(offset = 64) uint materialIdx;
} push_constants;
void main()
{
outPos = inPos;
vec4 viewPos = vec4(viewMatrix * vec4(inPos.xyz, 1.0));
outViewPos = viewPos;
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) {
outAlbedo = texture(textSampler[material.textureIdx], inTextCoords);
} else {
outAlbedo = material.diffuseColor;
}
vec4 Opacity = vec4(outAlbedo.a, outAlbedo.a, outAlbedo.a, 1.0);
if (material.OpacityFactor > 0.0 && material.OpacityFactor < 1.0) {
Opacity = vec4(material.OpacityFactor, material.OpacityFactor, material.OpacityFactor, 1.0);
}
if (material.hasOpacityMap > 0 && material.OpacityMapIdx < MAX_TEXTURES) {
Opacity = texture(textSampler[material.OpacityMapIdx], inTextCoords);
}
outOpacity = Opacity;
float opacityf = Opacity.x + Opacity.y + Opacity.z;
opacityf = opacityf/3;
outAlbedo = vec4(outAlbedo.rgb, opacityf);
if(outAlbedo.a < 0.5) discard;
mat3 TBN = mat3(inTangent, inBitangent, inNormal);
vec3 newNormal = calcNormal(material, inNormal, inTextCoords, TBN);
float ao = 0.5f;
float roughnessFactor = 0.0f;
float metallicFactor = 0.0f;
if (material.hasRoughMap > 0) {
vec4 metRoughValue = texture(textSampler[material.roughMapIdx], inTextCoords);
roughnessFactor = metRoughValue.g;
metallicFactor = metRoughValue.b;
} else {
roughnessFactor = material.roughnessFactor;
metallicFactor = material.metallicFactor;
}
vec4 emissive = material.emissiveColour;
if (material.hasEmissiveMap > 0 && material.emissiveMapIdx < MAX_TEXTURES) {
emissive = texture(textSampler[material.emissiveMapIdx], inTextCoords);
}
outEmissive = emissive;
vec4 Translucency = vec4(material.translucencyFactor,material.translucencyFactor,material.translucencyFactor,1);
if(material.hasTranslucencyMap > 0 && material.translucencyMapIdx < MAX_TEXTURES){
Translucency = texture(textSampler[material.translucencyMapIdx], inTextCoords);
}
outTranslucency = Translucency;
float Refractiveness = material.refractiveness;
float Reflectiveness = material.reflectiveness;
outNormal = vec4(newNormal, Refractiveness);
outPBR = vec4(ao, roughnessFactor, metallicFactor, Reflectiveness);
}

View file

@ -1,41 +1,15 @@
#version 450 #version 450
const int MAX_TEXTURES = 128; const int MAX_TEXTURES = 500;
layout(location = 0) in vec2 inTextCoords;
layout(location = 0) out vec4 outFragColor;
layout(location = 0) in vec4 inPos; struct Material{
layout(location = 1) in vec3 inNormal; vec4 diffuseColor;
layout(location = 2) in vec3 inTangent; uint hasTexture;
layout(location = 3) in vec3 inBitangent; uint textureIdx;
layout(location = 4) in vec2 inTextCoords; uint padding[2];
layout(location = 5) in mat4 viewMatrix;
layout(location = 0) out vec4 outAlbedo;
layout(location = 1) out vec4 outViewPos;
struct Material {
vec4 diffuseColor; //16
uint hasTexture; //20
uint textureIdx; //24
uint hasNormalMap; //28
uint normalMapIdx; //32
uint hasRoughMap; //36
uint roughMapIdx; //40
float roughnessFactor; //44
float metallicFactor; //48
vec4 emissiveColour; //64
uint hasEmissiveMap; //68
uint emissiveMapIdx; //72
uint hasTranslucencyMap; //76
uint translucencyMapIdx; //80
float translucencyFactor; //84
uint hasOpacityMap; //88
uint OpacityMapIdx; //92
float OpacityFactor; //96
float reflectiveness; //100
float refractiveness; //104
float Padding1; //108
float Padding2; //112
}; };
layout(set = 2, binding = 0) readonly buffer MaterialUniform{ layout(set = 2, binding = 0) readonly buffer MaterialUniform{
@ -50,34 +24,12 @@ layout(push_constant) uniform pc{
void main() void main()
{ {
vec4 viewPos = vec4(viewMatrix * inPos);
outViewPos = viewPos;
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; if(texColor.a < 0.9){discard;}
outFragColor = texColor;
} else{ } else{
outAlbedo = material.diffuseColor; outFragColor = material.diffuseColor;
} }
vec4 Opacity = vec4(outAlbedo.a, outAlbedo.a, outAlbedo.a, 1.0);
if (material.OpacityFactor > 0.0 && material.OpacityFactor < 1.0) {
Opacity = vec4(material.OpacityFactor, material.OpacityFactor, material.OpacityFactor, 1.0);
}
if (material.hasOpacityMap > 0 && material.OpacityMapIdx < MAX_TEXTURES) {
Opacity = texture(textSampler[material.OpacityMapIdx], inTextCoords);
}
float opacityf = Opacity.x + Opacity.y + Opacity.z;
opacityf = opacityf/3;
if(opacityf < 0.9){discard;}
outAlbedo = vec4(outAlbedo.rgb, opacityf);
} }

View file

@ -1,148 +0,0 @@
#version 450
const int MAX_TEXTURES = 128;
layout(location = 0) in vec4 inPos;
layout(location = 1) in vec3 inNormal;
layout(location = 2) in vec3 inTangent;
layout(location = 3) in vec3 inBitangent;
layout(location = 4) in vec2 inTextCoords;
layout(location = 5) in mat4 viewMatrix;
layout(location = 1) out vec4 outAlbedo ;
layout(location = 0) out vec4 outPos;
layout(location = 2) out vec4 outNormal;
layout(location = 3) out vec4 outPBR;
layout(location = 4) out vec4 outEmissive;
layout(location = 5) out vec4 outTranslucency;
layout(location = 6) out vec4 outOpacity;
layout(location = 7) out vec4 outViewPos;
const float bayerMatrix[16] = float[](
0.0 / 16.0, 8.0 / 16.0, 2.0 / 16.0, 10.0 / 16.0,
12.0 / 16.0, 4.0 / 16.0, 14.0 / 16.0, 6.0 / 16.0,
3.0 / 16.0, 11.0 / 16.0, 1.0 / 16.0, 9.0 / 16.0,
15.0 / 16.0, 7.0 / 16.0, 13.0 / 16.0, 5.0 / 16.0
);
struct Material {
vec4 diffuseColor; //16
uint hasTexture; //20
uint textureIdx; //24
uint hasNormalMap; //28
uint normalMapIdx; //32
uint hasRoughMap; //36
uint roughMapIdx; //40
float roughnessFactor; //44
float metallicFactor; //48
vec4 emissiveColour; //64
uint hasEmissiveMap; //68
uint emissiveMapIdx; //72
uint hasTranslucencyMap; //76
uint translucencyMapIdx; //80
float translucencyFactor; //84
uint hasOpacityMap; //88
uint OpacityMapIdx; //92
float OpacityFactor; //96
float reflectiveness; //100
float refractiveness; //104
float Padding1; //108
float Padding2; //112
};
layout(set = 2, binding = 0) readonly buffer MaterialUniform {
Material materials[];
} matUniform;
layout(set = 3, binding = 0) uniform sampler2D textSampler[MAX_TEXTURES];
vec3 calcNormal(Material material, vec3 normal, vec2 textCoords, mat3 TBN)
{
vec3 newNormal = normal;
if (material.hasNormalMap > 0)
{
newNormal = texture(textSampler[material.normalMapIdx], textCoords).rgb;
newNormal = normalize(newNormal * 2.0 - 1.0);
newNormal = normalize(TBN * newNormal);
}
return newNormal;
}
layout(push_constant) uniform pc {
layout(offset = 64) uint materialIdx;
} push_constants;
void main()
{
outPos = inPos;
vec4 viewPos = vec4(viewMatrix * vec4(inPos.xyz, 1.0));
outViewPos = viewPos;
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) {
outAlbedo = texture(textSampler[material.textureIdx], inTextCoords);
} else {
outAlbedo = material.diffuseColor;
}
vec4 Opacity = vec4(outAlbedo.a, outAlbedo.a, outAlbedo.a, 1.0);
if (material.OpacityFactor > 0.0 && material.OpacityFactor < 1.0) {
Opacity = vec4(material.OpacityFactor, material.OpacityFactor, material.OpacityFactor, 1.0);
}
if (material.hasOpacityMap > 0 && material.OpacityMapIdx < MAX_TEXTURES) {
Opacity = texture(textSampler[material.OpacityMapIdx], inTextCoords);
}
outOpacity = Opacity;
float opacityf = Opacity.x + Opacity.y + Opacity.z;
opacityf = opacityf/3;
outAlbedo = vec4(outAlbedo.rgb, opacityf);
if(outAlbedo.a < 0.9) discard;
mat3 TBN = mat3(inTangent, inBitangent, inNormal);
vec3 newNormal = calcNormal(material, inNormal, inTextCoords, TBN);
float ao = 0.5f;
float roughnessFactor = 0.0f;
float metallicFactor = 0.0f;
if (material.hasRoughMap > 0) {
vec4 metRoughValue = texture(textSampler[material.roughMapIdx], inTextCoords);
roughnessFactor = metRoughValue.g;
metallicFactor = metRoughValue.b;
} else {
roughnessFactor = material.roughnessFactor;
metallicFactor = material.metallicFactor;
}
vec4 emissive = material.emissiveColour;
if (material.hasEmissiveMap > 0 && material.emissiveMapIdx < MAX_TEXTURES) {
emissive = texture(textSampler[material.emissiveMapIdx], inTextCoords);
}
outEmissive = emissive;
vec4 Translucency = vec4(material.translucencyFactor,material.translucencyFactor,material.translucencyFactor,1);
if(material.hasTranslucencyMap > 0 && material.translucencyMapIdx < MAX_TEXTURES){
Translucency = texture(textSampler[material.translucencyMapIdx], inTextCoords);
}
outTranslucency = Translucency;
float Refractiveness = material.refractiveness;
float Reflectiveness = material.reflectiveness;
outNormal = vec4(newNormal, Refractiveness);
outPBR = vec4(ao, roughnessFactor, metallicFactor, Reflectiveness);
}

View file

@ -1,41 +1,17 @@
#version 450 #version 450
const int MAX_TEXTURES = 128; const int MAX_TEXTURES = 500;
layout(location = 0) in vec4 inPos; layout(location = 0) in vec2 inTextCoords;
layout(location = 1) in vec3 inNormal; layout(location = 0) out vec4 outFragColor;
layout(location = 2) in vec3 inTangent;
layout(location = 3) in vec3 inBitangent;
layout(location = 4) in vec2 inTextCoords;
layout(location = 5) in mat4 viewMatrix;
layout(location = 0) out vec4 outAlbedo; struct Material{
layout(location = 1) out vec4 outViewPos; vec4 diffuseColor;
uint hasTexture;
struct Material { uint textureIdx;
vec4 diffuseColor; //16 uint padding[2];
uint hasTexture; //20
uint textureIdx; //24
uint hasNormalMap; //28
uint normalMapIdx; //32
uint hasRoughMap; //36
uint roughMapIdx; //40
float roughnessFactor; //44
float metallicFactor; //48
vec4 emissiveColour; //64
uint hasEmissiveMap; //68
uint emissiveMapIdx; //72
uint hasTranslucencyMap; //76
uint translucencyMapIdx; //80
float translucencyFactor; //84
uint hasOpacityMap; //88
uint OpacityMapIdx; //92
float OpacityFactor; //96
float reflectiveness; //100
float refractiveness; //104
float Padding1; //108
float Padding2; //112
}; };
layout(set = 2, binding = 0) readonly buffer MaterialUniform{ layout(set = 2, binding = 0) readonly buffer MaterialUniform{
Material materials[]; Material materials[];
} matUniform; } matUniform;
@ -48,36 +24,12 @@ layout(push_constant) uniform pc{
void main() void main()
{ {
vec4 viewPos = vec4(viewMatrix * inPos);
outViewPos = viewPos;
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; if(texColor.a < 0.05 || texColor.a >= 0.9){discard;}
outFragColor = texColor;
} else{ } else{
outAlbedo = material.diffuseColor; outFragColor = material.diffuseColor;
} }
vec4 Opacity = vec4(outAlbedo.a, outAlbedo.a, outAlbedo.a, 1.0);
if (material.OpacityFactor > 0.0 && material.OpacityFactor < 1.0) {
Opacity = vec4(material.OpacityFactor, material.OpacityFactor, material.OpacityFactor, 1.0);
}
if (material.hasOpacityMap > 0 && material.OpacityMapIdx < MAX_TEXTURES) {
Opacity = texture(textSampler[material.OpacityMapIdx], inTextCoords);
}
float opacityf = Opacity.x + Opacity.y + Opacity.z;
opacityf = opacityf/3;
if(opacityf >= 0.9){discard;}
outAlbedo = vec4(outAlbedo.rgb, opacityf);
} }

View file

@ -1,150 +0,0 @@
#version 450
const int MAX_TEXTURES = 128;
layout(location = 0) in vec4 inPos;
layout(location = 1) in vec3 inNormal;
layout(location = 2) in vec3 inTangent;
layout(location = 3) in vec3 inBitangent;
layout(location = 4) in vec2 inTextCoords;
layout(location = 5) in mat4 viewMatrix;
layout(location = 1) out vec4 outAlbedo ;
layout(location = 0) out vec4 outPos;
layout(location = 2) out vec4 outNormal;
layout(location = 3) out vec4 outPBR;
layout(location = 4) out vec4 outEmissive;
layout(location = 5) out vec4 outTranslucency;
layout(location = 6) out vec4 outOpacity;
layout(location = 7) out vec4 outViewPos;
const float bayerMatrix[16] = float[](
0.0 / 16.0, 8.0 / 16.0, 2.0 / 16.0, 10.0 / 16.0,
12.0 / 16.0, 4.0 / 16.0, 14.0 / 16.0, 6.0 / 16.0,
3.0 / 16.0, 11.0 / 16.0, 1.0 / 16.0, 9.0 / 16.0,
15.0 / 16.0, 7.0 / 16.0, 13.0 / 16.0, 5.0 / 16.0
);
struct Material {
vec4 diffuseColor; //16
uint hasTexture; //20
uint textureIdx; //24
uint hasNormalMap; //28
uint normalMapIdx; //32
uint hasRoughMap; //36
uint roughMapIdx; //40
float roughnessFactor; //44
float metallicFactor; //48
vec4 emissiveColour; //64
uint hasEmissiveMap; //68
uint emissiveMapIdx; //72
uint hasTranslucencyMap; //76
uint translucencyMapIdx; //80
float translucencyFactor; //84
uint hasOpacityMap; //88
uint OpacityMapIdx; //92
float OpacityFactor; //96
float reflectiveness; //100
float refractiveness; //104
float Padding1; //108
float Padding2; //112
};
layout(set = 2, binding = 0) readonly buffer MaterialUniform {
Material materials[];
} matUniform;
layout(set = 3, binding = 0) uniform sampler2D textSampler[MAX_TEXTURES];
vec3 calcNormal(Material material, vec3 normal, vec2 textCoords, mat3 TBN)
{
vec3 newNormal = normal;
if (material.hasNormalMap > 0)
{
newNormal = texture(textSampler[material.normalMapIdx], textCoords).rgb;
newNormal = normalize(newNormal * 2.0 - 1.0);
newNormal = normalize(TBN * newNormal);
}
return newNormal;
}
layout(push_constant) uniform pc {
layout(offset = 64) uint materialIdx;
} push_constants;
void main()
{
outPos = inPos;
vec4 viewPos = vec4(viewMatrix * vec4(inPos.xyz, 1.0));
outViewPos = viewPos;
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) {
outAlbedo = texture(textSampler[material.textureIdx], inTextCoords);
} else {
outAlbedo = material.diffuseColor;
}
vec4 Opacity = vec4(outAlbedo.a, outAlbedo.a, outAlbedo.a, 1.0);
if (material.OpacityFactor > 0.0 && material.OpacityFactor < 1.0) {
Opacity = vec4(material.OpacityFactor, material.OpacityFactor, material.OpacityFactor, 1.0);
}
if (material.hasOpacityMap > 0 && material.OpacityMapIdx < MAX_TEXTURES) {
Opacity = texture(textSampler[material.OpacityMapIdx], inTextCoords);
}
outOpacity = Opacity;
float opacityf = Opacity.x + Opacity.y + Opacity.z;
opacityf = opacityf/3;
outAlbedo = vec4(outAlbedo.rgb, opacityf);
if(outAlbedo.a >= 0.9 || outAlbedo.a <= 0.1) discard;
mat3 TBN = mat3(inTangent, inBitangent, inNormal);
vec3 newNormal = calcNormal(material, inNormal, inTextCoords, TBN);
float ao = 0.5f;
float roughnessFactor = 0.0f;
float metallicFactor = 0.0f;
if (material.hasRoughMap > 0) {
vec4 metRoughValue = texture(textSampler[material.roughMapIdx], inTextCoords);
roughnessFactor = metRoughValue.g;
metallicFactor = metRoughValue.b;
} else {
roughnessFactor = material.roughnessFactor;
metallicFactor = material.metallicFactor;
}
vec4 emissive = material.emissiveColour;
if (material.hasEmissiveMap > 0 && material.emissiveMapIdx < MAX_TEXTURES) {
emissive = texture(textSampler[material.emissiveMapIdx], inTextCoords);
}
outEmissive = emissive;
vec4 Translucency = vec4(material.translucencyFactor,material.translucencyFactor,material.translucencyFactor,1);
if(material.hasTranslucencyMap > 0 && material.translucencyMapIdx < MAX_TEXTURES){
Translucency = texture(textSampler[material.translucencyMapIdx], inTextCoords);
}
outTranslucency = Translucency;
float Refractiveness = material.refractiveness;
float Reflectiveness = material.reflectiveness;
outNormal = vec4(newNormal, Refractiveness);
outPBR = vec4(ao, roughnessFactor, metallicFactor, Reflectiveness);
}

View file

@ -1,17 +1,10 @@
#version 450 #version 450
layout(location = 0) in vec3 inPos; layout(location = 0) in vec3 inPos;
layout(location = 1) in vec3 inNormal; layout(location = 1) in vec2 inTextCoords;
layout(location = 2) in vec3 inTangent;
layout(location = 3) in vec3 inBitangent; layout(location = 0) out vec2 outTextCoords;
layout(location = 4) in vec2 inTextCoords;
layout(location = 0) out vec4 outPos;
layout(location = 1) out vec3 outNormal;
layout(location = 2) out vec3 outTangent;
layout(location = 3) out vec3 outBitangent;
layout(location = 4) out vec2 outTextCoords;
layout(location = 5) out mat4 viewMatrix;
layout(set = 0, binding = 0) uniform ProjUniform{ layout(set = 0, binding = 0) uniform ProjUniform{
mat4 matrix; mat4 matrix;
@ -27,13 +20,6 @@ layout(push_constant) uniform pc{
void main() void main()
{ {
viewMatrix = viewUniform.matrix;
vec4 worldPos = push_constants.modelMatrix * vec4(inPos,1);
gl_Position = projUniform.matrix * viewUniform.matrix * push_constants.modelMatrix * vec4(inPos,1); gl_Position = projUniform.matrix * viewUniform.matrix * push_constants.modelMatrix * vec4(inPos,1);
mat3 mNormal = transpose(inverse(mat3(push_constants.modelMatrix)));
outPos = worldPos;
outNormal = mNormal * normalize(inNormal);
outTangent = mNormal * normalize(inTangent);
outBitangent = mNormal * normalize(inBitangent);
outTextCoords = inTextCoords; outTextCoords = inTextCoords;
} }

View file

@ -1,104 +0,0 @@
#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);
}

View file

@ -1,122 +0,0 @@
#version 450
layout(location = 0) in vec2 fragTexCoord;
layout(location = 0) out vec4 outColor;
layout(set = 0, binding = 0) uniform sampler2D albedoSampler;
layout(set = 0, binding = 1) uniform sampler2D worldPosSampler;
layout(set = 0, binding = 2) uniform sampler2D normalSampler;
layout(set = 0, binding = 3) uniform sampler2D pbrSampler;
layout(set = 1, binding = 0) uniform CameraProperties {
mat4 projection;
mat4 view;
float ssrStepSize;
float ssrMaxDistance;
int maxSteps;
int padding;
vec4 cameraWorldPos;
} ubo;
const float THICKNESS = 0.35;
const float MIN_REFLECTION = 0.01;
float edgeFade(vec2 uv) {
vec2 fade = smoothstep(vec2(0.0), vec2(0.08), uv) *
smoothstep(vec2(0.0), vec2(0.08), vec2(1.0) - uv);
return fade.x * fade.y;
}
void main() {
outColor = vec4(0.0);
vec4 posSample = texture(worldPosSampler, fragTexCoord);
vec4 normalSample = texture(normalSampler, fragTexCoord);
vec4 pbrSample = texture(pbrSampler, fragTexCoord);
if (posSample.a == 0.0 || length(posSample.xyz) == 0.0 || length(normalSample.xyz) < 0.001) {
return;
}
vec3 worldPos = posSample.xyz;
vec3 worldNormal = normalize(normalSample.xyz);
float roughness = clamp(pbrSample.g, 0.0, 1.0);
float metallic = clamp(pbrSample.b, 0.0, 1.0);
float reflectiveness = clamp(pbrSample.a, 0.0, 1.0);
float refractiveness = clamp(normalSample.a, 0.0, 2.0);
vec3 viewDirToCamera = normalize(ubo.cameraWorldPos.xyz - worldPos);
float NoV = clamp(dot(worldNormal, viewDirToCamera), 0.0, 1.0);
float fresnel = pow(1.0 - NoV, 5.0);
float materialReflection = reflectiveness + (refractiveness - 1.05);
materialReflection *= mix(0.75, 1.0, metallic);
materialReflection *= 1.0 - smoothstep(0.05, 0.7, roughness);
materialReflection *= mix(0.45, 1.0, fresnel);
if (materialReflection <= MIN_REFLECTION) {
return;
}
vec3 viewDir = normalize(worldPos - ubo.cameraWorldPos.xyz);
vec3 reflectDir = normalize(reflect(viewDir, worldNormal));
if (dot(reflectDir, worldNormal) <= 0.0) {
return;
}
int steps = clamp(ubo.maxSteps, 1, 128);
float stepSize = max(ubo.ssrStepSize, 0.01);
float maxDistance = max(ubo.ssrMaxDistance, stepSize);
vec3 rayPos = worldPos;
vec2 hitUV = vec2(0.0);
bool hitFound = false;
for (int i = 0; i < steps; i++) {
rayPos += reflectDir * stepSize;
if (distance(rayPos, worldPos) > maxDistance) {
break;
}
vec4 clip = ubo.projection * ubo.view * vec4(rayPos, 1.0);
if (clip.w <= 0.0) {
break;
}
vec2 uv = clip.xy / clip.w;
uv = uv * 0.5 + 0.5;
uv.y = 1.0 - uv.y;
if (uv.x <= 0.0 || uv.x >= 1.0 || uv.y <= 0.0 || uv.y >= 1.0) {
break;
}
vec4 surfaceWorld = texture(worldPosSampler, uv);
if (surfaceWorld.a == 0.0 || length(surfaceWorld.xyz) == 0.0) {
continue;
}
float rayViewZ = abs((ubo.view * vec4(rayPos, 1.0)).z);
float surfaceViewZ = abs((ubo.view * vec4(surfaceWorld.xyz, 1.0)).z);
float depthDelta = rayViewZ - surfaceViewZ;
if (depthDelta >= 0.0 && depthDelta < THICKNESS) {
hitUV = uv;
hitFound = true;
break;
}
}
if (!hitFound) {
return;
}
vec3 reflectedColor = texture(albedoSampler, hitUV).rgb;
float fade = edgeFade(hitUV);
float weight = clamp(materialReflection * fade, 0.0, 0.85);
outColor = vec4(reflectedColor * weight, weight);
}

View file

@ -1,81 +0,0 @@
#version 450
// Keep in sync manually with Java code
const int MAX_TEXTURES = 128;
layout (location = 0) in vec2 inTextCoords;
layout (location = 1) in flat uint inMaterialIdx;
layout(location = 0) out vec2 outFragColor;
struct Material {
vec4 diffuseColor; //16
uint hasTexture; //20
uint textureIdx; //24
uint hasNormalMap; //28
uint normalMapIdx; //32
uint hasRoughMap; //36
uint roughMapIdx; //40
float roughnessFactor; //44
float metallicFactor; //48
vec4 emissiveColour; //64
uint hasEmissiveMap; //68
uint emissiveMapIdx; //72
uint hasTranslucencyMap; //76
uint translucencyMapIdx; //80
float translucencyFactor; //84
uint hasOpacityMap; //88
uint OpacityMapIdx; //92
float OpacityFactor; //96
float reflectiveness; //100
float refractiveness; //104
float Padding1; //108
float Padding2; //112
};
layout(set = 1, binding = 0) uniform sampler2D textSampler[MAX_TEXTURES];
layout(set = 2, binding = 0) readonly buffer MaterialUniform {
Material materials[];
} matUniform;
void main()
{
Material material = matUniform.materials[inMaterialIdx];
float Refractiveness = material.refractiveness;
float Reflectiveness = material.reflectiveness;
float Translucency = material.translucencyFactor;
float Opacity = material.OpacityFactor;
if(material.hasTranslucencyMap > 0){
vec4 translucencyMap = texture(textSampler[material.translucencyMapIdx], inTextCoords);
Translucency = (translucencyMap.x + translucencyMap.y + translucencyMap.z)/3.0;
}
if(material.hasOpacityMap > 0){
vec4 opacityMap = texture(textSampler[material.OpacityMapIdx], inTextCoords);
Opacity = (opacityMap.x + opacityMap.y + opacityMap.z)/3.0;
}
int textureIndex = int(material.textureIdx);
if (textureIndex >= MAX_TEXTURES){
outFragColor = vec2(0.0,0.0);
return;
}
vec4 albedo;
if (material.hasTexture == 1) {
albedo = texture(textSampler[material.textureIdx], inTextCoords);
} else {
albedo = material.diffuseColor;
}
if (albedo.a < 0.5 || Translucency > 0.95 || Opacity < 0.5) {
discard;
}
float depth = gl_FragCoord.z;
float moment1 = depth;
float moment2 = depth * depth;
float dx = dFdx(depth);
float dy = dFdy(depth);
moment2 += 0.25 * (dx * dx + dy * dy);
outFragColor = vec2(moment1, moment2) * (1 - Translucency);
}

View file

@ -1,29 +0,0 @@
#version 450
#define SHADOW_MAP_CASCADE_COUNT 6
layout (triangles, invocations = SHADOW_MAP_CASCADE_COUNT) in;
layout (triangle_strip, max_vertices = 3) out;
layout (location = 0) in vec2 inTextCoords[];
layout (location = 1) in flat uint inMaterialIdx[];
layout (location = 0) out vec2 outTextCoords;
layout (location = 1) out flat uint outMaterialIdx;
layout(set = 0, binding = 0) uniform ProjUniforms {
mat4 projViewMatrices[SHADOW_MAP_CASCADE_COUNT];
} projUniforms;
void main()
{
for (int i = 0; i < 3; i++)
{
outTextCoords = inTextCoords[i];
outMaterialIdx = inMaterialIdx[i];
gl_Layer = gl_InvocationID;
gl_Position = projUniforms.projViewMatrices[gl_InvocationID] * gl_in[i].gl_Position;
EmitVertex();
}
EndPrimitive();
}

View file

@ -1,23 +0,0 @@
#version 450
layout(location = 0) in vec3 entityPos;
layout(location = 1) in vec3 entityNormal;
layout(location = 2) in vec3 entityTangent;
layout(location = 3) in vec3 entityBitangent;
layout(location = 4) in vec2 entityTextCoords;
layout(push_constant) uniform matrices {
mat4 modelMatrix;
uint materialIdx;
} push_constants;
layout (location = 0) out vec2 outTextCoord;
layout (location = 1) out flat uint outMaterialIdx;
void main()
{
outTextCoord = entityTextCoords;
outMaterialIdx = push_constants.materialIdx;
gl_Position = push_constants.modelMatrix * vec4(entityPos, 1.0f);
}

View file

@ -1,115 +0,0 @@
#version 450
layout(set = 3, binding = 0) readonly buffer FaceBuffer {
uint faces[];
};
layout(push_constant) uniform matrices {
vec4 ModelOffset;
vec4 Padding0;
vec4 Padding1;
vec4 Padding2;
uint materialIdx;
} push_constants;
layout(location = 0) out vec2 outTextCoord;
layout(location = 1) out flat uint outMaterialIdx;
const uint TRI_TO_CORNER[6] = uint[6](0u, 1u, 2u, 0u, 2u, 3u);
const vec3 NORMALS[8] = vec3[8](
vec3( 0.0, 1.0, 0.0), // Face 0 (+Y)
vec3( 0.0, -1.0, 0.0), // Face 1 (-Y)
vec3( 1.0, 0.0, 0.0), // Face 2 (+X)
vec3(-1.0, 0.0, 0.0), // Face 3 (-X)
vec3( 0.0, 0.0, 1.0), // Face 4 (+Z)
vec3( 0.0, 0.0, -1.0), // Face 5 (-Z)
vec3(-0.7071, 0.0, 0.7071), // Face 6
vec3( 0.7071, 0.0, 0.7071) // Face 7
);
const vec3 TANGENTS[8] = vec3[8](
vec3( 1.0, 0.0, 0.0), // Face 0
vec3( 1.0, 0.0, 0.0), // Face 1
vec3( 0.0, 0.0, -1.0), // Face 2
vec3( 0.0, 0.0, 1.0), // Face 3
vec3( 1.0, 0.0, 0.0), // Face 4
vec3(-1.0, 0.0, 0.0), // Face 5
vec3( 0.7071, 0.0, 0.7071), // Face 6
vec3( 0.7071, 0.0,-0.7071) // Face 7
);
const vec3 BITANGENTS[8] = vec3[8](
vec3( 0.0, 0.0, 1.0), // Face 0
vec3( 0.0, 0.0, -1.0), // Face 1
vec3( 0.0, 1.0, 0.0), // Face 2
vec3( 0.0, 1.0, 0.0), // Face 3
vec3( 0.0, 1.0, 0.0), // Face 4
vec3( 0.0, 1.0, 0.0), // Face 5
vec3( 0.0, 1.0, 0.0), // Face 6
vec3( 0.0, 1.0, 0.0) // Face 7
);
const vec2 CORNER_UVS[5][4] = vec2[5][4](
vec2[4](vec2(0.5, 0.0), vec2(0.5, 0.5), vec2(1.0, 0.5), vec2(1.0, 0.0)),
vec2[4](vec2(0.0, 0.5), vec2(0.0, 1.0), vec2(0.5, 1.0), vec2(0.5, 0.5)),
vec2[4](vec2(0.5, 0.0), vec2(0.5, 0.5), vec2(1.0, 0.5), vec2(1.0, 0.0)),
vec2[4](vec2(0.5, 0.0), vec2(0.5, 0.5), vec2(1.0, 0.5), vec2(1.0, 0.0)),
vec2[4](vec2(1.0, 1.0), vec2(1.0, 0.5), vec2(0.5, 0.5), vec2(0.5, 1.0))
);
const vec2 CORNER_UVS_GRASS_BLOCK[8][4] = vec2[8][4](
vec2[4](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0)),
vec2[4](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0)),
vec2[4](vec2(1.0, 1.0), vec2(1.0, 0.0),vec2(0.0, 0.0), vec2(0.0, 1.0)),
vec2[4]( vec2(0.0, 1.0),vec2(1.0, 1.0), vec2(1.0, 0.0),vec2(0.0, 0.0)),
vec2[4]( vec2(0.0, 1.0),vec2(1.0, 1.0), vec2(1.0, 0.0),vec2(0.0, 0.0)),
vec2[4](vec2(1.0, 1.0), vec2(1.0, 0.0),vec2(0.0, 0.0), vec2(0.0, 1.0)),
vec2[4](vec2(1.0, 1.0), vec2(1.0, 0.0), vec2(0.0, 0.0), vec2(0.0, 1.0)),
vec2[4](vec2(1.0, 1.0), vec2(1.0, 0.0), vec2(0.0, 0.0), vec2(0.0, 1.0))
);
const vec3 FACE_CORNERS[8][4] = vec3[8][4](
vec3[4](vec3(0.0, 1.0, 0.0), vec3(0.0, 1.0, 1.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 1.0, 0.0)), // Face 0 (+Y)
vec3[4](vec3(0.0, 0.0, 0.0), vec3(1.0, 0.0, 0.0), vec3(1.0, 0.0, 1.0), vec3(0.0, 0.0, 1.0)), // Face 1 (-Y)
vec3[4](vec3(1.0, 0.0, 0.0), vec3(1.0, 1.0, 0.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 0.0, 1.0)), // Face 2 (+X)
vec3[4](vec3(0.0, 0.0, 0.0), vec3(0.0, 0.0, 1.0), vec3(0.0, 1.0, 1.0), vec3(0.0, 1.0, 0.0)), // Face 3 (-X)
vec3[4](vec3(0.0, 0.0, 1.0), vec3(1.0, 0.0, 1.0), vec3(1.0, 1.0, 1.0), vec3(0.0, 1.0, 1.0)), // Face 4 (+Z)
vec3[4](vec3(0.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(1.0, 1.0, 0.0), vec3(1.0, 0.0, 0.0)), // Face 5 (-Z)
vec3[4](vec3(0.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(1.0, 1.0, 1.0), vec3(1.0, 0.0, 1.0)), // Face 6 (cross model pane 1)
vec3[4](vec3(0.0, 0.0, 1.0), vec3(0.0, 1.0, 1.0), vec3(1.0, 1.0, 0.0), vec3(1.0, 0.0, 0.0)) // Face 7 (cross model pane 2)
);
void main() {
uint faceRecordIndex = uint(gl_VertexIndex) / 6u;
uint triangleVertex = (uint(gl_VertexIndex))% 6u;
uint cornerIndex = TRI_TO_CORNER[triangleVertex];
uint packedFace = faces[faceRecordIndex];
uint voxelX = packedFace & 0xFu;
uint voxelY = (packedFace >> 4u) & 0xFu;
uint voxelZ = (packedFace >> 8u) & 0xFu;
uint faceId = (packedFace >> 12u) & 0x7u;
uint matId = (packedFace >> 15u) & 0x7FFu;
uint texIdxX = (packedFace >> 26u) & 0x7u;
uint texIdxY = (packedFace >> 29u) & 0x7u;
vec2 texID = vec2((texIdxX)/4.0,(texIdxY)/4.0);
vec2 scalar = vec2(1.0/4.0,1.0/4.0);
faceId = min(faceId, 7u);
vec3 localPos = vec3(voxelX, voxelY, voxelZ) + FACE_CORNERS[faceId][cornerIndex];
vec3 worldPos = localPos + push_constants.ModelOffset.xyz * 16.0;
if (gl_InstanceIndex != 0) {
uint encoded = uint(gl_InstanceIndex);
worldPos += vec3(int(encoded & 1023u) - 512, int((encoded >> 10u) & 1023u) - 512,
int((encoded >> 20u) & 1023u) - 512) * 16.0;
}
outTextCoord = CORNER_UVS_GRASS_BLOCK[faceId][cornerIndex] * scalar + texID;
outMaterialIdx = matId;
gl_Position = vec4(worldPos, 1.0);
}

View file

@ -1,11 +0,0 @@
#version 450
layout(location = 0) in vec3 outTexCoords;
layout(location = 1) out vec4 outColor;
layout(set = 2, binding = 0) uniform samplerCube skyboxSampler;
void main() {
outColor = texture(skyboxSampler, outTexCoords); //* vec4(0.0,0.05,0.1,1);
}

View file

@ -1,18 +0,0 @@
#version 450
layout(location = 0) in vec3 inPosition;
layout(location = 0) out vec3 outTexCoords;
layout(set = 0, binding = 0) uniform ProjectionBuffer {
mat4 proj;
} uboProj;
layout(set = 1, binding = 0) uniform ViewBuffer {
mat4 view;
} uboView;
void main() {
outTexCoords = inPosition;
mat4 skyView = mat4(mat3(uboView.view));
vec4 pos = uboProj.proj * skyView * vec4(inPosition, 1.0);
gl_Position = vec4(pos.xy, 0.0, pos.w);
}

View file

@ -1,45 +0,0 @@
#version 450
layout(location = 0) in vec2 inTextCoord;
layout(location = 0) out float outAO;
layout(set = 0, binding = 0) uniform sampler2D ssaoSampler;
layout(set = 0, binding = 1) uniform sampler2D viewPosSampler;
void main() {
vec2 texelSize = 1.0 / vec2(textureSize(ssaoSampler, 0));
float centerAO = texture(ssaoSampler, inTextCoord).r;
float centerDepth = texture(viewPosSampler, inTextCoord).z;
float totalAO = centerAO;
float totalWeight = 1.0;
float weights[4] = float[](0.1216216, 0.1945946, 0.1945946, 0.1216216);
int offsets[4] = int[](-2, -1, 1, 2);
const float Sharpness = 20.0;
for (int i = 0; i < 4; i++) {
vec2 offsetH = vec2(float(offsets[i]), 0.0) * texelSize;
vec2 uvH = inTextCoord + offsetH;
float neighborAOH = texture(ssaoSampler, uvH).r;
float neighborDepthH = texture(viewPosSampler, uvH).z;
float weightH = weights[i] * max(0.0, 1.0 - Sharpness * abs(centerDepth - neighborDepthH));
totalAO += neighborAOH * weightH;
totalWeight += weightH;
vec2 offsetV = vec2(0.0, float(offsets[i])) * texelSize;
vec2 uvV = inTextCoord + offsetV;
float neighborAOV = texture(ssaoSampler, uvV).r;
float neighborDepthV = texture(viewPosSampler, uvV).z;
float weightV = weights[i] * max(0.0, 1.0 - Sharpness * abs(centerDepth - neighborDepthV));
totalAO += neighborAOV * weightV;
totalWeight += weightV;
}
outAO = totalAO / totalWeight;
}

View file

@ -1,78 +0,0 @@
#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) uniform SSAOKernel {
vec4 samples[64];
} 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; //148
} ssao;
void main() {
int KERNEL_SIZE = clamp(ssao.kernelSize, 1, 64);
vec3 fragPos = texture(posSampler, inTextCoord).xyz;
vec3 worldNorm = texture(normalSampler, inTextCoord).xyz;
if (dot(worldNorm, worldNorm) < 0.001 || fragPos.z >= 0.0) {
outAO = 1.0;
return;
}
vec3 normal = normalize(mat3(ssao.view) * worldNorm);
vec3 randomVec = texelFetch(noiseSampler, ivec2(gl_FragCoord.xy) % 4, 0).xyz;
vec3 tangent = randomVec - normal * dot(randomVec, normal);
if (dot(tangent, tangent) < 0.0001) {
tangent = cross(normal, abs(normal.z) < 0.9 ? vec3(0, 0, 1) : vec3(0, 1, 0));
}
tangent = normalize(tangent);
vec3 bitangent = cross(normal, tangent);
mat3 TBN = mat3(tangent, bitangent, normal);
float fragDepth = -fragPos.z;
float occlusion = 0.0;
float Passes = 0.0f;
for (int i = 0; i < KERNEL_SIZE; i++) {
// Cover the complete radius distribution, even with a smaller sample budget.
int sampleIndex = i * 64 / KERNEL_SIZE;
vec3 samplePos = fragPos + (TBN * kernel.samples[sampleIndex].xyz) * ssao.radius;
vec4 offset = ssao.projection * vec4(samplePos, 1.0);
if (offset.w <= 0.0) continue;
offset.xyz /= offset.w;
offset.xyz = offset.xyz * 0.5 + 0.5;
vec2 sampleUV = vec2(offset.x, 1.0 - offset.y);
if (any(lessThan(sampleUV, vec2(0))) || any(greaterThan(sampleUV, vec2(1)))) continue;
vec3 sampleViewPos = texture(posSampler, sampleUV).xyz;
if (sampleViewPos.z >= 0.0) continue;
float sampleDepth = -sampleViewPos.z;
float depthDelta = abs(fragDepth - sampleDepth);
if (depthDelta > ssao.radius * 2.0) {
continue;
}
float rangeCheck = smoothstep(0.0, 1.0, ssao.radius / max(depthDelta, 0.0001));
float isOccluded = step(samplePos.z + ssao.bias, sampleViewPos.z);
occlusion += isOccluded * rangeCheck;
Passes += 1.0;
}
float Subtraction = 0.0;
if(Passes > 0){
Subtraction = (occlusion / Passes);
}
occlusion = 1.0 - Subtraction;
outAO = clamp(pow(occlusion, 3), 0.0, 1.0);
}

View file

@ -1,34 +0,0 @@
#version 450
layout(location = 0) in vec2 fragTexCoord;
layout(location = 0) out vec4 outColor;
layout(set = 0, binding = 0) uniform sampler2D sceneSampler;
layout(set = 0, binding = 1) uniform sampler2D reflectionSampler;
layout(set = 0, binding = 2) uniform sampler2D pbrSampler;
layout(set = 0, binding = 3) uniform sampler2D normalSampler;
vec4 reflectionAt(ivec2 pixel, ivec2 size) {
return texelFetch(reflectionSampler, clamp(pixel, ivec2(0), size - 1), 0);
}
void main() {
vec4 sceneColor = texture(sceneSampler, fragTexCoord);
vec4 pbr = texture(pbrSampler, fragTexCoord);
vec4 normal = texture(normalSampler, fragTexCoord);
float materialReflection = (pbr.a + normal.a - 1.05) * (1.0 - smoothstep(0.05, 0.7, pbr.g));
if (dot(normal.xyz, normal.xyz) < 0.001 || materialReflection <= 0.01) {
outColor = sceneColor;
return;
}
// The shared sampler is nearest-filtered. Upsample only premultiplied reflections.
ivec2 size = textureSize(reflectionSampler, 0);
vec2 pixel = fragTexCoord * vec2(size) - 0.5;
ivec2 base = ivec2(floor(pixel));
vec2 blend = fract(pixel);
vec4 reflection = mix(
mix(reflectionAt(base, size), reflectionAt(base + ivec2(1, 0), size), blend.x),
mix(reflectionAt(base + ivec2(0, 1), size), reflectionAt(base + ivec2(1, 1), size), blend.x), blend.y);
outColor = vec4(sceneColor.rgb * (1.0 - reflection.a) + reflection.rgb, sceneColor.a);
}

View file

@ -4,5 +4,5 @@ layout(location = 0) out vec2 outTextCoord;
void main() { void main() {
outTextCoord = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2); 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); gl_Position = vec4(outTextCoord.x * 2.0f - 1.0f, outTextCoord.y * -2.0f + 1.0f,0.0f,1.0f);
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

View file

@ -0,0 +1,15 @@
{
"ID": "Welsh040Alice",
"Meshes": [
{
"ID": "cube_0",
"MaterialID": "Welsh040Alice-mat-1",
"OffsetVertex": 0,
"VertexSize": 42720,
"OffsetIndex": 0,
"IndexSize": 14976
}
],
"VertexPath": "resources/models/Alice/Welsh040Alice.vtx",
"IndexPath": "resources/models/Alice/Welsh040Alice.idx"
}

View file

@ -0,0 +1,4 @@
# Made in Blockbench 5.1.4
newmtl m_43544ac2-29ce-cec1-9562-1ae6e86abc5a
map_Kd Alice040.png
newmtl none

File diff suppressed because it is too large Load diff

Binary file not shown.

View file

@ -0,0 +1,32 @@
[
{
"ID": "Welsh040Alice-mat-0",
"TexturePath": "",
"DiffuseColour": {
"X": 0.6,
"Y": 0.6,
"Z": 0.6,
"W": 1.0
}
},
{
"ID": "Welsh040Alice-mat-1",
"TexturePath": "resources\\models\\Alice\\Alice040.png",
"DiffuseColour": {
"X": 0.6,
"Y": 0.6,
"Z": 0.6,
"W": 1.0
}
},
{
"ID": "Welsh040Alice-mat-2",
"TexturePath": "",
"DiffuseColour": {
"X": 0.6,
"Y": 0.6,
"Z": 0.6,
"W": 1.0
}
}
]

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

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