Compare commits
62 commits
DeferredRe
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9424b29d0a | ||
|
|
d1abde919d | ||
|
|
a0b00b0f1c | ||
| 7fda2614d7 | |||
| 95a27cfd50 | |||
|
|
0074bf1d1f | ||
| 4565188f15 | |||
|
|
8c301d0ac1 | ||
|
|
ce7051d8ca | ||
|
|
bf9af81f38 | ||
|
|
fa7bf893e7 | ||
|
|
04befce27d | ||
|
|
577836a03f | ||
|
|
5b231d6920 | ||
|
|
0d41f3e15b | ||
|
|
f7127e0878 | ||
|
|
5518dae1d7 | ||
|
|
5ea45890c8 | ||
|
|
c9ef43a2a0 | ||
|
|
3e886e5ba8 | ||
|
|
5a05b9d65e | ||
|
|
6d7ea4ebc5 | ||
|
|
bf11da6799 | ||
|
|
0d8f23cb1f | ||
| 4af61ca2c8 | |||
| 1284a9835a | |||
|
|
9723a3567c | ||
|
|
59c5486299 | ||
| f3aee6cb84 | |||
| 92fb49191b | |||
| ffb7b842af | |||
| 0f8fa9c9f9 | |||
|
|
aff4c2a57a | ||
|
|
3fbf3485b1 | ||
|
|
745d38fb09 | ||
|
|
f3c83bea80 | ||
| 2e929abf46 | |||
| 1c5f6d41ad | |||
|
|
c270a049b5 | ||
|
|
613e31658f | ||
|
|
db4de8f791 | ||
|
|
d49ff709e2 | ||
| 7bad787477 | |||
| 94858a7cad | |||
| f2174e4364 | |||
|
|
9c08fb6248 | ||
|
|
42fc70100d | ||
|
|
8a92f99474 | ||
|
|
8ab8c06f9c | ||
|
|
605c96362b | ||
|
|
d05c5d0171 | ||
|
|
eb09963e3a | ||
|
|
2b0344630e | ||
|
|
e746462295 | ||
|
|
b817940716 | ||
|
|
c02b9ed2ca | ||
| 6b51c9b680 | |||
| f135d99d74 | |||
|
|
eb01ec4877 | ||
| 8d219d2a35 | |||
|
|
441bd95ddd | ||
|
|
2d37c574d6 |
10
.gitignore
vendored
|
|
@ -27,7 +27,9 @@ build/
|
|||
.idea/**/dynamic.xml
|
||||
.idea/**/uiDesigner.xml
|
||||
.idea/**/dbnavigator.xml
|
||||
|
||||
*.t4jlog
|
||||
*.spv
|
||||
*.spv.options
|
||||
# Gradle
|
||||
.idea/**/gradle.xml
|
||||
.idea/**/libraries
|
||||
|
|
@ -84,3 +86,9 @@ fabric.properties
|
|||
/.idea/
|
||||
/.gradle/buildOutputCleanup/
|
||||
/.gradle/
|
||||
/resources/models/bistrohd/
|
||||
/resources/models/Cafe/
|
||||
/resources/models/Forest/
|
||||
/resources/models/tree/
|
||||
/resources/models/woman/
|
||||
/docs/
|
||||
|
|
|
|||
92
build.gradle
|
|
@ -1,8 +1,25 @@
|
|||
import org.gradle.internal.os.OperatingSystem
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
plugins {
|
||||
id 'application'
|
||||
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.jomlVersion = "1.10.8"
|
||||
project.ext.jomlprimitivesVersion = "1.10.0"
|
||||
|
|
@ -11,37 +28,20 @@ project.ext.steamworks4jVersion = "1.9.0"
|
|||
project.ext.steamworks4jserverVersion = "1.9.0"
|
||||
project.ext.imguiVersion = "1.92.0"
|
||||
|
||||
switch (OperatingSystem.current()) {
|
||||
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
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
application {
|
||||
mainClass.set('net.halbear.Executable.Launcher')
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation platform("org.lwjgl:lwjgl-bom:$lwjglVersion")
|
||||
implementation 'org.tinylog:tinylog-api:2.7.0'
|
||||
implementation 'org.tinylog:tinylog-impl:2.7.0'
|
||||
|
||||
// Core LWJGL modules
|
||||
implementation "org.lwjgl:lwjgl"
|
||||
implementation "org.lwjgl:lwjgl-assimp"
|
||||
implementation "org.lwjgl:lwjgl-fmod"
|
||||
|
|
@ -59,22 +59,29 @@ dependencies {
|
|||
implementation "org.lwjgl:lwjgl-stb"
|
||||
implementation "org.lwjgl:lwjgl-vma"
|
||||
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}"
|
||||
runtimeOnly "org.lwjgl:lwjgl-remotery:${lwjglVersion}:${lwjglNatives}"
|
||||
implementation "org.lwjgl:lwjgl-shaderc::$lwjglNatives"
|
||||
implementation "org.lwjgl:lwjgl-stb::$lwjglNatives"
|
||||
implementation "org.lwjgl:lwjgl-vma::$lwjglNatives"
|
||||
if (lwjglNatives == "natives-macos" || lwjglNatives == "natives-macos-arm64") implementation "org.lwjgl:lwjgl-vulkan::$lwjglNatives"
|
||||
|
||||
// Define targeted native platforms explicitly
|
||||
def targetNatives = ["natives-windows", "natives-linux"]
|
||||
|
||||
// Loop through and bundle natives for both Windows and Linux
|
||||
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-primitives:${jomlprimitivesVersion}"
|
||||
implementation "org.lwjglx:lwjgl3-awt:${lwjgl3awtVersion}"
|
||||
|
|
@ -82,13 +89,18 @@ dependencies {
|
|||
implementation "com.code-disaster.steamworks4j:steamworks4j-server:${steamworks4jserverVersion}"
|
||||
implementation 'com.google.code.gson:gson:2.14.0'
|
||||
implementation "org.jcommander:jcommander:3.0"
|
||||
|
||||
['', '-opengl', '-glfw'].each {
|
||||
implementation "org.lwjgl:lwjgl$it:$lwjglVersion"
|
||||
implementation "org.lwjgl:lwjgl$it::natives-windows"
|
||||
runtimeOnly "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-lwjgl3:$imguiVersion"
|
||||
|
||||
implementation "io.github.spair:imgui-java-natives-windows:$imguiVersion"
|
||||
// ImGui Natives for both OS environments
|
||||
runtimeOnly "io.github.spair:imgui-java-natives-windows:$imguiVersion"
|
||||
runtimeOnly "io.github.spair:imgui-java-natives-linux:$imguiVersion"
|
||||
}
|
||||
10
gradle/renderer-validation.init.gradle
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
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"))
|
||||
}
|
||||
}
|
||||
}
|
||||
5
gradle/wrapper/gradle-wrapper.properties
vendored
|
|
@ -1,7 +1,6 @@
|
|||
#Thu Jun 18 13:00:38 BST 2026
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.0-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
|
|
|||
13
resources/EngineResources/GLShaders/gui_fragment.glsl
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#version 330
|
||||
|
||||
in vec2 fragTextCoords;
|
||||
in vec4 fragColour;
|
||||
|
||||
uniform sampler2D textureSampler;
|
||||
|
||||
out vec4 outColour;
|
||||
|
||||
void main()
|
||||
{
|
||||
outColour = fragColour * texture(textureSampler, fragTextCoords);
|
||||
}
|
||||
17
resources/EngineResources/GLShaders/gui_vertex.glsl
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#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);
|
||||
}
|
||||
172
resources/EngineResources/GLShaders/lighting_frag.glsl
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
#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);
|
||||
}
|
||||
256
resources/EngineResources/GLShaders/scene_frag.glsl
Normal file
|
|
@ -0,0 +1,256 @@
|
|||
#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);
|
||||
}
|
||||
77
resources/EngineResources/GLShaders/scene_frag_deferred.glsl
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
#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);
|
||||
|
||||
}
|
||||
37
resources/EngineResources/GLShaders/scene_vert.glsl
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
#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;
|
||||
}
|
||||
BIN
resources/EngineResources/SkyBoxTextures/SkyTop.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 3.5 MiB |
|
After Width: | Height: | Size: 2.8 MiB |
|
After Width: | Height: | Size: 3.4 MiB |
|
After Width: | Height: | Size: 3.6 MiB |
|
After Width: | Height: | Size: 3.4 MiB |
|
After Width: | Height: | Size: 5.1 MiB |
BIN
resources/EngineResources/SkyBoxTextures/skySide.png
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
|
|
@ -0,0 +1,2 @@
|
|||
Sky texture:
|
||||
kaori669 on deviant art
|
||||
28
resources/EngineResources/SpriteShaders/sprite_fragment.glsl
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
#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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
#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;}
|
||||
}
|
||||
36
resources/EngineResources/SpriteShaders/sprite_vertex.glsl
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
#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);
|
||||
}
|
||||
BIN
resources/EngineResources/Texture/NoTexture.png
Normal file
|
After Width: | Height: | Size: 217 KiB |
BIN
resources/EngineResources/Texture/Terrain4JTitleImage.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
resources/EngineResources/Texture/blueleaf_set.png
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
resources/EngineResources/Texture/blueleaf_set_2.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
resources/EngineResources/Texture/blueleaf_set_2_translucent.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
resources/EngineResources/Texture/blueleaf_set_translucent.png
Normal file
|
After Width: | Height: | Size: 2 KiB |
BIN
resources/EngineResources/Texture/test_cube.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
resources/EngineResources/Texture/test_cube_translucency.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
|
|
@ -0,0 +1,236 @@
|
|||
#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);
|
||||
}
|
||||
|
|
@ -0,0 +1,201 @@
|
|||
#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);
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
#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;
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
#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;
|
||||
}
|
||||
|
|
@ -0,0 +1,201 @@
|
|||
#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;
|
||||
}
|
||||
|
|
@ -0,0 +1,596 @@
|
|||
#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;
|
||||
}
|
||||
BIN
resources/EngineResources/audio/music/BAR_FIGHT_boogieparty.ogg
Normal file
BIN
resources/EngineResources/audio/music/CHILL_REGGAE_Firmament.ogg
Normal file
BIN
resources/EngineResources/audio/music/GuitarSpam (1).mp3
Normal file
BIN
resources/EngineResources/audio/music/GuitarSpam (1).ogg
Normal file
|
Before Width: | Height: | Size: 12 MiB After Width: | Height: | Size: 12 MiB |
BIN
resources/EngineResources/audio/music/WildWestIntroTheme.ogg
Normal file
BIN
resources/EngineResources/audio/music/theshiteventhefar.mp3
Normal file
BIN
resources/EngineResources/audio/music/theshiteventhefar.ogg
Normal file
BIN
resources/EngineResources/audio/sounds/BulletHit1.ogg
Normal file
BIN
resources/EngineResources/audio/sounds/BulletHit2.ogg
Normal file
BIN
resources/EngineResources/audio/sounds/CricketAmbience.ogg
Normal file
BIN
resources/EngineResources/audio/sounds/EagleCry.ogg
Normal file
BIN
resources/EngineResources/audio/sounds/GunCock.ogg
Normal file
BIN
resources/EngineResources/audio/sounds/GunReload.ogg
Normal file
BIN
resources/EngineResources/audio/sounds/MusketFire.ogg
Normal file
BIN
resources/EngineResources/audio/sounds/WildWestAmbientMusic.ogg
Normal file
29
resources/EngineResources/shaders/TerrainFragment.glsl
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#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;
|
||||
}
|
||||
21
resources/EngineResources/shaders/Terrain_vertex.glsl
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#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;
|
||||
}
|
||||
29
resources/EngineResources/shaders/bloom_extract_frag.glsl
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#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);
|
||||
}
|
||||
30
resources/EngineResources/shaders/bloom_pass_frag.glsl
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#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);
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
#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);
|
||||
}
|
||||
172
resources/EngineResources/shaders/lighting_frag.glsl
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
#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);
|
||||
}
|
||||
|
|
@ -0,0 +1,291 @@
|
|||
#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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
#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);
|
||||
}
|
||||
|
|
@ -1,53 +1,42 @@
|
|||
#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) out vec4 outFragColor;
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2DMS inputTexture;
|
||||
layout(set = 0, binding = 1) uniform sampler2D bloomImage;
|
||||
|
||||
layout(set = 1, binding = 0) uniform ScreenSize{
|
||||
vec2 size;
|
||||
} screenSize;
|
||||
|
||||
vec4 gamma(vec4 color){
|
||||
return color = vec4(pow(color.rgb,vec3(GAMMA_CONST)),color.a);
|
||||
}
|
||||
layout(push_constant) uniform PassConfig {
|
||||
int horizontal;
|
||||
float GAMMA_CONST;
|
||||
float Exposure;
|
||||
float blur_radius;
|
||||
vec2 bloomSize;
|
||||
} config;
|
||||
|
||||
vec4 msaa(int sampleCount, sampler2DMS textureIn, vec2 TextCoord) {
|
||||
ivec2 pixelCoords = ivec2(TextCoord * textureSize(textureIn));
|
||||
ivec2 size = textureSize(textureIn);
|
||||
ivec2 pixelCoords = clamp(ivec2(TextCoord * vec2(size)), ivec2(0), size - 1);
|
||||
vec4 colorSum = vec4(0.0);
|
||||
|
||||
for(int i = 0; i < sampleCount; ++i) {
|
||||
vec4 sampleColor = texelFetch(textureIn, pixelCoords, i);
|
||||
colorSum += sampleColor;
|
||||
}
|
||||
for (int i = 0; i < sampleCount; i++) colorSum += texelFetch(textureIn, pixelCoords, i);
|
||||
return colorSum / float(sampleCount);
|
||||
}
|
||||
|
||||
void main(){
|
||||
ivec2 pixelCoords = ivec2(inTextCoord * textureSize(inputTexture));
|
||||
vec3 bloomAt(ivec2 pixel, ivec2 size) {
|
||||
return texelFetch(bloomImage, clamp(pixel, ivec2(0), size - 1), 0).rgb;
|
||||
}
|
||||
|
||||
if(USE_AA == 0){
|
||||
outFragColor = texelFetch(inputTexture,pixelCoords,0);
|
||||
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);
|
||||
}
|
||||
if(USE_AA == 1){
|
||||
outFragColor = texelFetch(inputTexture,pixelCoords,0);
|
||||
}
|
||||
if(USE_AA == 2){
|
||||
outFragColor = msaa(2,inputTexture,inTextCoord);
|
||||
}
|
||||
if(USE_AA == 3){
|
||||
outFragColor = msaa(4,inputTexture,inTextCoord);
|
||||
}
|
||||
if(USE_AA == 4){
|
||||
outFragColor = msaa(8,inputTexture,inTextCoord);
|
||||
}
|
||||
outFragColor = gamma(outFragColor);
|
||||
|
||||
void main() {
|
||||
vec4 sceneColor = msaa(textureSamples(inputTexture), inputTexture, inTextCoord);
|
||||
vec3 hdrColour = max(sceneColor.rgb + upsampleBloom(inTextCoord), vec3(0.0));
|
||||
vec3 result = vec3(1.0) - exp(-hdrColour * config.Exposure);
|
||||
outFragColor = vec4(pow(result, vec3(1.0 / config.GAMMA_CONST)), sceneColor.a);
|
||||
}
|
||||
88
resources/EngineResources/shaders/packed_scene_fragment.glsl
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
#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);
|
||||
}
|
||||
|
|
@ -0,0 +1,149 @@
|
|||
#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);
|
||||
}
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
#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;
|
||||
}
|
||||
134
resources/EngineResources/shaders/packed_scene_vertex.glsl
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
#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;
|
||||
}
|
||||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
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;
|
||||
|
|
@ -11,18 +10,19 @@ layout(location = 0) in vec2 inTextCoord;
|
|||
layout(location = 0) out vec4 outFragColor;
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D inputTexture;
|
||||
layout(set = 0, binding = 1) uniform sampler2D bloomImage;
|
||||
|
||||
layout(set = 1, binding = 0) uniform ScreenSize{
|
||||
vec2 size;
|
||||
} screenSize;
|
||||
|
||||
vec4 gamma(vec4 color){
|
||||
return color = vec4(pow(color.rgb,vec3(GAMMA_CONST)),color.a);
|
||||
}
|
||||
layout(push_constant) uniform PassConfig {
|
||||
int horizontal;
|
||||
float GAMMA_CONST;
|
||||
float Exposure;
|
||||
float blur_radius;
|
||||
vec2 bloomSize;
|
||||
} config;
|
||||
|
||||
// Sourced from: https://mini.gmshaders.com/p/gm-shaders-mini-fxaa
|
||||
vec4 fxaa(sampler2D tex, vec2 uv) {
|
||||
vec2 u_texel = 1.0 / screenSize.size;
|
||||
vec2 u_texel = 1.0 / vec2(textureSize(inputTexture, 0));
|
||||
|
||||
//Sample center and 4 corners
|
||||
vec3 rgbCC = texture(tex, uv).rgb;
|
||||
|
|
@ -70,21 +70,22 @@ vec4 fxaa(sampler2D tex, vec2 uv) {
|
|||
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(){
|
||||
|
||||
if(USE_AA == 1){
|
||||
outFragColor = fxaa(inputTexture, inTextCoord);
|
||||
outFragColor = gamma(outFragColor);
|
||||
return;
|
||||
}
|
||||
if(USE_AA == 2){
|
||||
|
||||
}
|
||||
if(USE_AA == 3){
|
||||
|
||||
}
|
||||
if(USE_AA == 4){
|
||||
|
||||
}
|
||||
outFragColor = gamma(texture(inputTexture,inTextCoord));
|
||||
vec4 sceneColor = USE_AA == 1 ? fxaa(inputTexture, inTextCoord) : texture(inputTexture, inTextCoord);
|
||||
vec3 hdrColour = max(sceneColor.rgb + upsampleBloom(inTextCoord), vec3(0.0));
|
||||
vec3 result = vec3(1.0) - exp(-hdrColour * config.Exposure);
|
||||
outFragColor = vec4(pow(result, vec3(1.0 / config.GAMMA_CONST)), sceneColor.a);
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
#version 450
|
||||
|
||||
layout(location = 0 ) out vec2 outTextCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
outTextCoord = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
|
||||
gl_Position = vec4(outTextCoord.x * 2.0f - 1.0f, outTextCoord.y * -2.0f + 1.0f,0.0f,1.0f);
|
||||
}
|
||||
|
|
@ -1,15 +1,40 @@
|
|||
#version 450
|
||||
|
||||
const int MAX_TEXTURES = 500;
|
||||
const int MAX_TEXTURES = 128;
|
||||
|
||||
layout(location = 0) in vec2 inTextCoords;
|
||||
layout(location = 0) out vec4 outFragColor;
|
||||
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 = 0) out vec4 outAlbedo;
|
||||
layout(location = 1) out vec4 outViewPos;
|
||||
|
||||
struct Material {
|
||||
vec4 diffuseColor;
|
||||
uint hasTexture;
|
||||
uint textureIdx;
|
||||
uint padding[2];
|
||||
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{
|
||||
|
|
@ -18,18 +43,42 @@ layout(set = 2, binding = 0) readonly buffer MaterialUniform{
|
|||
|
||||
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[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){
|
||||
vec4 texColor = texture(textSampler[material.textureIdx],inTextCoords);
|
||||
if(texColor.a < 0.1){discard;}
|
||||
outFragColor = texColor;
|
||||
outAlbedo = texColor;
|
||||
} else{
|
||||
outFragColor = material.diffuseColor;
|
||||
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);
|
||||
}
|
||||
|
||||
float opacityf = Opacity.x + Opacity.y + Opacity.z;
|
||||
opacityf = opacityf/3;
|
||||
if(opacityf < 0.4){discard;}
|
||||
|
||||
outAlbedo = vec4(outAlbedo.rgb, opacityf);
|
||||
}
|
||||
143
resources/EngineResources/shaders/scene_fragment_deferred.glsl
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
#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);
|
||||
}
|
||||
|
|
@ -1,15 +1,41 @@
|
|||
#version 450
|
||||
|
||||
const int MAX_TEXTURES = 500;
|
||||
const int MAX_TEXTURES = 128;
|
||||
|
||||
layout(location = 0) in vec2 inTextCoords;
|
||||
layout(location = 0) out vec4 outFragColor;
|
||||
|
||||
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 = 0) out vec4 outAlbedo;
|
||||
layout(location = 1) out vec4 outViewPos;
|
||||
|
||||
struct Material {
|
||||
vec4 diffuseColor;
|
||||
uint hasTexture;
|
||||
uint textureIdx;
|
||||
uint padding[2];
|
||||
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{
|
||||
|
|
@ -24,12 +50,34 @@ layout(push_constant) uniform pc{
|
|||
|
||||
void main()
|
||||
{
|
||||
vec4 viewPos = vec4(viewMatrix * inPos);
|
||||
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);
|
||||
return;
|
||||
}
|
||||
if(material.hasTexture == 1){
|
||||
vec4 texColor = texture(textSampler[material.textureIdx],inTextCoords);
|
||||
if(texColor.a < 0.9){discard;}
|
||||
outFragColor = texColor;
|
||||
outAlbedo = texColor;
|
||||
} else{
|
||||
outFragColor = material.diffuseColor;
|
||||
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);
|
||||
}
|
||||
|
||||
float opacityf = Opacity.x + Opacity.y + Opacity.z;
|
||||
opacityf = opacityf/3;
|
||||
if(opacityf < 0.9){discard;}
|
||||
|
||||
outAlbedo = vec4(outAlbedo.rgb, opacityf);
|
||||
}
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
#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);
|
||||
}
|
||||
|
|
@ -1,17 +1,41 @@
|
|||
#version 450
|
||||
|
||||
const int MAX_TEXTURES = 500;
|
||||
const int MAX_TEXTURES = 128;
|
||||
|
||||
layout(location = 0) in vec2 inTextCoords;
|
||||
layout(location = 0) out vec4 outFragColor;
|
||||
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 = 0) out vec4 outAlbedo;
|
||||
layout(location = 1) out vec4 outViewPos;
|
||||
|
||||
struct Material {
|
||||
vec4 diffuseColor;
|
||||
uint hasTexture;
|
||||
uint textureIdx;
|
||||
uint padding[2];
|
||||
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;
|
||||
|
|
@ -24,12 +48,36 @@ layout(push_constant) uniform pc{
|
|||
|
||||
void main()
|
||||
{
|
||||
|
||||
vec4 viewPos = vec4(viewMatrix * inPos);
|
||||
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);
|
||||
return;
|
||||
}
|
||||
if(material.hasTexture == 1){
|
||||
vec4 texColor = texture(textSampler[material.textureIdx],inTextCoords);
|
||||
if(texColor.a < 0.05 || texColor.a >= 0.9){discard;}
|
||||
outFragColor = texColor;
|
||||
outAlbedo = texColor;
|
||||
} else{
|
||||
outFragColor = material.diffuseColor;
|
||||
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);
|
||||
}
|
||||
|
||||
float opacityf = Opacity.x + Opacity.y + Opacity.z;
|
||||
opacityf = opacityf/3;
|
||||
if(opacityf >= 0.9){discard;}
|
||||
|
||||
outAlbedo = vec4(outAlbedo.rgb, opacityf);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,150 @@
|
|||
#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);
|
||||
}
|
||||
|
|
@ -1,10 +1,17 @@
|
|||
#version 450
|
||||
|
||||
layout(location = 0) in vec3 inPos;
|
||||
layout(location = 1) in vec2 inTextCoords;
|
||||
|
||||
layout(location = 0) out vec2 outTextCoords;
|
||||
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 = 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{
|
||||
mat4 matrix;
|
||||
|
|
@ -20,6 +27,13 @@ layout(push_constant) uniform pc{
|
|||
|
||||
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);
|
||||
mat3 mNormal = transpose(inverse(mat3(push_constants.modelMatrix)));
|
||||
outPos = worldPos;
|
||||
outNormal = mNormal * normalize(inNormal);
|
||||
outTangent = mNormal * normalize(inTangent);
|
||||
outBitangent = mNormal * normalize(inBitangent);
|
||||
outTextCoords = inTextCoords;
|
||||
}
|
||||
104
resources/EngineResources/shaders/screen_space_fog.glsl
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
#version 450
|
||||
|
||||
layout(location = 0) in vec2 inTextCoord;
|
||||
layout(location = 0) out float outAO;
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D posSampler;
|
||||
layout(set = 0, binding = 1) uniform sampler2D normalSampler;
|
||||
layout(set = 0, binding = 2) uniform sampler2D noiseSampler;
|
||||
|
||||
layout(set = 1, binding = 0) readonly buffer SSAOKernel {
|
||||
vec4 samples[];
|
||||
} kernel;
|
||||
|
||||
layout(set = 2, binding = 0) uniform SSAOInfo {
|
||||
mat4 projection; //64
|
||||
mat4 view; //128
|
||||
vec2 screenSize; // 136
|
||||
float radius; //140
|
||||
float bias; //144
|
||||
int kernelSize; //160
|
||||
} ssao;
|
||||
|
||||
void main() {
|
||||
vec2 uv = inTextCoord;
|
||||
|
||||
vec3 worldPos = texture(posSampler, uv).xyz;
|
||||
vec3 worldNormal = normalize(texture(normalSampler, uv).xyz);
|
||||
|
||||
|
||||
if (length(worldNormal) < 0.001) {
|
||||
outAO = 1.0;
|
||||
return;
|
||||
}
|
||||
|
||||
vec3 fragPos = vec3(ssao.view * vec4(worldPos, 1.0));
|
||||
vec3 normal = normalize(mat3(ssao.view) * worldNormal);
|
||||
|
||||
vec2 noiseScale = ssao.screenSize / 4.0;
|
||||
vec3 randomVec = normalize(texture(noiseSampler, inTextCoord * noiseScale).xyz);
|
||||
|
||||
|
||||
vec3 tangent = normalize(randomVec - normal * dot(randomVec, normal));
|
||||
vec3 bitangent = cross(normal, tangent);
|
||||
mat3 TBN = mat3(tangent, bitangent, normal);
|
||||
|
||||
float occlusion = 0.0;
|
||||
float validSamples = 0.0;;
|
||||
|
||||
for (int i = 0; i < ssao.kernelSize; i++) {
|
||||
vec3 samplePos = TBN * kernel.samples[i].xyz;
|
||||
samplePos = fragPos + samplePos * ssao.radius;
|
||||
|
||||
vec4 offset = vec4(samplePos, 1.0);
|
||||
offset = ssao.projection * offset;
|
||||
offset.xyz /= offset.w;
|
||||
offset.xyz = offset.xyz * 0.5 + 0.5;
|
||||
|
||||
vec2 sampleUV = offset.xy;
|
||||
sampleUV.y = 1.0 - sampleUV.y;
|
||||
|
||||
if (sampleUV.x < 0.0 || sampleUV.x > 1.0 ||
|
||||
sampleUV.y < 0.0 || sampleUV.y > 1.0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
vec3 sampleWorldPos = texture(posSampler, sampleUV).xyz;
|
||||
vec3 sampleWorldNormal = texture(normalSampler, sampleUV).xyz;
|
||||
|
||||
if (length(sampleWorldNormal) < 0.001) {
|
||||
continue;
|
||||
}
|
||||
|
||||
vec3 sampleViewPos = vec3(ssao.view * vec4(sampleWorldPos, 1.0));
|
||||
|
||||
float depthDelta = abs(fragPos.z - sampleViewPos.z);
|
||||
|
||||
occlusion += abs(fragPos.z)/200.0f;
|
||||
validSamples += 1.0;
|
||||
continue;
|
||||
|
||||
if (depthDelta > ssao.radius) {
|
||||
continue;
|
||||
}
|
||||
|
||||
float rangeCheck = 1.0 - depthDelta / ssao.radius;
|
||||
rangeCheck = rangeCheck * rangeCheck * (3.0 - 2.0 * rangeCheck);
|
||||
|
||||
|
||||
|
||||
if (sampleViewPos.z >= samplePos.z + ssao.bias) {
|
||||
occlusion += rangeCheck;
|
||||
}
|
||||
|
||||
validSamples += 1.0;
|
||||
}
|
||||
|
||||
if (validSamples <= 0.0) {
|
||||
outAO = 1.0;
|
||||
return;
|
||||
}
|
||||
|
||||
occlusion = 1.0 - occlusion / validSamples;
|
||||
outAO = clamp(occlusion, 0.0, 1.0);
|
||||
}
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
#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);
|
||||
}
|
||||
81
resources/EngineResources/shaders/shadow_frag.glsl
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
#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);
|
||||
}
|
||||
29
resources/EngineResources/shaders/shadow_geometry.glsl
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#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();
|
||||
}
|
||||
23
resources/EngineResources/shaders/shadow_vertex.glsl
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
#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);
|
||||
}
|
||||
115
resources/EngineResources/shaders/shadow_vertex_packed.glsl
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
#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);
|
||||
}
|
||||
11
resources/EngineResources/shaders/skybox_fragment.glsl
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#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);
|
||||
}
|
||||
18
resources/EngineResources/shaders/skybox_vertex.glsl
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
#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);
|
||||
}
|
||||
45
resources/EngineResources/shaders/ssao_blur_frag.glsl
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
#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;
|
||||
}
|
||||
78
resources/EngineResources/shaders/ssao_frag.glsl
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
#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);
|
||||
}
|
||||
34
resources/EngineResources/shaders/ssr_composite_frag.glsl
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
#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);
|
||||
}
|
||||
1
resources/ProgramResources/ServerCache/UUIDs.json
Normal file
|
|
@ -0,0 +1 @@
|
|||
[]
|
||||
|
Before Width: | Height: | Size: 5.7 KiB |
|
|
@ -1,15 +0,0 @@
|
|||
{
|
||||
"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"
|
||||
}
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
# Made in Blockbench 5.1.4
|
||||
newmtl m_43544ac2-29ce-cec1-9562-1ae6e86abc5a
|
||||
map_Kd Alice040.png
|
||||
newmtl none
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
[
|
||||
{
|
||||
"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
|
||||
}
|
||||
}
|
||||
]
|
||||