Skip to content

Commit

Permalink
Added glsl includer
Browse files Browse the repository at this point in the history
  • Loading branch information
xCollateral committed Oct 25, 2023
1 parent e3dbe71 commit fd6becc
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 61 deletions.
109 changes: 96 additions & 13 deletions src/main/java/net/vulkanmod/vulkan/shader/SPIRVUtils.java
Original file line number Diff line number Diff line change
@@ -1,44 +1,56 @@
package net.vulkanmod.vulkan.shader;

import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import org.lwjgl.system.MemoryStack;
import org.lwjgl.system.MemoryUtil;
import org.lwjgl.system.NativeResource;
import org.lwjgl.util.shaderc.ShadercIncludeResolveI;
import org.lwjgl.util.shaderc.ShadercIncludeResult;
import org.lwjgl.util.shaderc.ShadercIncludeResultReleaseI;
import org.lwjgl.vulkan.VK12;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import static org.lwjgl.system.MemoryUtil.NULL;
import static org.lwjgl.system.MemoryUtil.memASCII;
import static org.lwjgl.util.shaderc.Shaderc.*;

public class SPIRVUtils {
private static final boolean DEBUG = true;
private static final boolean DEBUG = false;
private static final boolean OPTIMIZATIONS = false;

private static long compiler;
private static long options;

public static SPIRV compileShaderAbsoluteFile(String shaderFile, ShaderKind shaderKind) {
try {
String source = new String(Files.readAllBytes(Paths.get(new URI(shaderFile))));
return compileShader(shaderFile, source, shaderKind);
} catch (IOException | URISyntaxException e) {
e.printStackTrace();
}
return null;
}
//The dedicated Includer and Releaser Inner Classes used to Initialise #include Support for ShaderC
private static final ShaderIncluder SHADER_INCLUDER = new ShaderIncluder();
private static final ShaderReleaser SHADER_RELEASER = new ShaderReleaser();
private static final long pUserData = 0;

public static SPIRV compileShader(String filename, String source, ShaderKind shaderKind) {
private static ObjectArrayList<String> includePaths;

private static float time = 0.0f;

if(compiler == 0) compiler = shaderc_compiler_initialize();
static {
initCompiler();
}

private static void initCompiler() {
compiler = shaderc_compiler_initialize();

if(compiler == NULL) {
throw new RuntimeException("Failed to create shader compiler");
}

long options = shaderc_compile_options_initialize();
options = shaderc_compile_options_initialize();

if(options == NULL) {
throw new RuntimeException("Failed to create compiler options");
Expand All @@ -50,6 +62,33 @@ public static SPIRV compileShader(String filename, String source, ShaderKind sha
if(DEBUG)
shaderc_compile_options_set_generate_debug_info(options);

shaderc_compile_options_set_target_env(options, shaderc_env_version_vulkan_1_2, VK12.VK_API_VERSION_1_2);
shaderc_compile_options_set_include_callbacks(options, SHADER_INCLUDER, SHADER_RELEASER, pUserData);

includePaths = new ObjectArrayList<>();
addIncludePath("/assets/vulkanmod/shaders/include/");
}

public static void addIncludePath(String path) {
URL url = SPIRVUtils.class.getResource(path);

if(url != null)
includePaths.add(url.toExternalForm());
}

public static SPIRV compileShaderAbsoluteFile(String shaderFile, ShaderKind shaderKind) {
try {
String source = new String(Files.readAllBytes(Paths.get(new URI(shaderFile))));
return compileShader(shaderFile, source, shaderKind);
} catch (IOException | URISyntaxException e) {
e.printStackTrace();
}
return null;
}

public static SPIRV compileShader(String filename, String source, ShaderKind shaderKind) {
long startTime = System.nanoTime();

long result = shaderc_compile_into_spv(compiler, source, shaderKind.kind, filename, "main", options);

if(result == NULL) {
Expand All @@ -60,6 +99,8 @@ public static SPIRV compileShader(String filename, String source, ShaderKind sha
throw new RuntimeException("Failed to compile shader " + filename + " into SPIR-V:\n" + shaderc_result_get_error_message(result));
}

time += (System.nanoTime() - startTime) / 1000000.0f;

return new SPIRV(result, shaderc_result_get_bytes(result));
}

Expand Down Expand Up @@ -90,6 +131,48 @@ public enum ShaderKind {
}
}

private static class ShaderIncluder implements ShadercIncludeResolveI {

private static final int MAX_PATH_LENGTH = 4096; //Maximum Linux/Unix Path Length

@Override
public long invoke(long user_data, long requested_source, int type, long requesting_source, long include_depth) {
var requesting = memASCII(requesting_source);
var requested = memASCII(requested_source);

try(MemoryStack stack = MemoryStack.stackPush()) {
Path path;

for(String includePath : includePaths) {
path = Paths.get(new URI(String.format("%s%s", includePath, requested)));

if(Files.exists(path)) {
byte[] bytes = Files.readAllBytes(path);

return ShadercIncludeResult.malloc(stack)
.source_name(stack.ASCII(requested))
.content(stack.bytes(bytes))
.user_data(user_data).address();
}
}
} catch (IOException | URISyntaxException e) {
throw new RuntimeException(e);
}

throw new RuntimeException(String.format("%s: Unable to find %s in include paths", requesting, requested));
}
}

//TODO: Don't actually need the Releaser at all, (MemoryStack frees this for us)
//But ShaderC won't let us create the Includer without a corresponding Releaser, (so we need it anyway)
private static class ShaderReleaser implements ShadercIncludeResultReleaseI {

@Override
public void invoke(long user_data, long include_result) {
//TODO:Maybe dump Shader Compiled Binaries here to a .Misc Diretcory to allow easy caching.recompilation...
}
}

public static final class SPIRV implements NativeResource {

private final long handle;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
#version 450

vec4 linear_fog(vec4 inColor, float vertexDistance, float fogStart, float fogEnd, vec4 fogColor) {
if (vertexDistance <= fogStart) {
return inColor;
}

float fogValue = vertexDistance < fogEnd ? smoothstep(fogStart, fogEnd, vertexDistance) : 1.0;
return vec4(mix(inColor.rgb, fogColor.rgb, fogValue * fogColor.a), inColor.a);
}
#include "light.glsl"

layout(binding = 2) uniform sampler2D Sampler0;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
#version 460

//light.glsl
#define MINECRAFT_LIGHT_POWER 0.6
#define MINECRAFT_AMBIENT_LIGHT 0.4

vec4 minecraft_sample_lightmap(sampler2D lightMap, ivec2 uv) {
return texelFetch(lightMap, (uv & 255) >> 4, 0);
}
#include "light.glsl"

layout(binding = 0) uniform UniformBufferObject {
mat4 MVP;
Expand All @@ -24,9 +18,7 @@ layout(location = 1) out vec4 vertexColor;
layout(location = 2) out vec2 texCoord0;
//layout(location = 3) out vec4 normal;

#define COMPRESSED_VERTEX
#ifdef COMPRESSED_VERTEX

//Compressed Vertex
layout(location = 0) in ivec3 Position;
layout(location = 1) in vec4 Color;
layout(location = 2) in uvec2 UV0;
Expand All @@ -41,26 +33,23 @@ void main() {
gl_Position = MVP * vec4(pos + ChunkOffset, 1.0);

vertexDistance = length((ModelViewMat * vec4(pos + ChunkOffset, 1.0)).xyz);
vertexColor = Color * minecraft_sample_lightmap(Sampler2, UV2);
vertexColor = Color * sample_lightmap(Sampler2, UV2);
texCoord0 = UV0 * UV_INV;
// normal = MVP * vec4(Normal, 0.0);
}

#else

layout(location = 0) in vec3 Position;
layout(location = 1) in vec4 Color;
layout(location = 2) in vec2 UV0;
layout(location = 3) in ivec2 UV2;
layout(location = 4) in vec3 Normal;

void main() {
gl_Position = MVP * vec4(Position + ChunkOffset, 1.0);

vertexDistance = length((ModelViewMat * vec4(Position + ChunkOffset, 1.0)).xyz);
vertexColor = Color * minecraft_sample_lightmap(Sampler2, UV2);
texCoord0 = UV0;
// normal = MVP * vec4(Normal, 0.0);
}
//Default Vertex
//layout(location = 0) in vec3 Position;
//layout(location = 1) in vec4 Color;
//layout(location = 2) in vec2 UV0;
//layout(location = 3) in ivec2 UV2;
//layout(location = 4) in vec3 Normal;

#endif
//void main() {
// gl_Position = MVP * vec4(Position + ChunkOffset, 1.0);
//
// vertexDistance = length((ModelViewMat * vec4(Position + ChunkOffset, 1.0)).xyz);
// vertexColor = Color * minecraft_sample_lightmap(Sampler2, UV2);
// texCoord0 = UV0;
// // normal = MVP * vec4(Normal, 0.0);
//}
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
#version 450

vec4 linear_fog(vec4 inColor, float vertexDistance, float fogStart, float fogEnd, vec4 fogColor) {
if (vertexDistance <= fogStart) {
return inColor;
}

float fogValue = vertexDistance < fogEnd ? smoothstep(fogStart, fogEnd, vertexDistance) : 1.0;
return vec4(mix(inColor.rgb, fogColor.rgb, fogValue * fogColor.a), inColor.a);
}
#include "light.glsl"

layout(binding = 3) uniform sampler2D Sampler0;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@

#define MAX_OFFSET_COUNT 512

vec4 minecraft_sample_lightmap(sampler2D lightMap, ivec2 uv) {
return texelFetch(lightMap, (uv & 255) >> 4, 0);
}
#include "light.glsl"

layout(binding = 0) uniform UniformBufferObject {
mat4 MVP;
Expand Down Expand Up @@ -38,7 +36,7 @@ void main() {
gl_Position = MVP * vec4(pos + ChunkOffset[gl_DrawID], 1.0);

vertexDistance = length((ModelViewMat * vec4(pos + ChunkOffset[gl_DrawID], 1.0)).xyz);
vertexColor = Color * minecraft_sample_lightmap(Sampler2, UV2);
vertexColor = Color * sample_lightmap(Sampler2, UV2);
texCoord0 = UV0 * UV_INV;
// normal = MVP * vec4(Normal, 0.0);
}
Expand Down
29 changes: 29 additions & 0 deletions src/main/resources/assets/vulkanmod/shaders/include/light.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//light.glsl
#define MINECRAFT_LIGHT_POWER (0.6)
#define MINECRAFT_AMBIENT_LIGHT (0.4)

vec4 minecraft_mix_light(vec3 lightDir0, vec3 lightDir1, vec3 normal, vec4 color) {
lightDir0 = normalize(lightDir0);
lightDir1 = normalize(lightDir1);
float light0 = max(0.0, dot(lightDir0, normal));
float light1 = max(0.0, dot(lightDir1, normal));
float lightAccum = min(1.0, (light0 + light1) * MINECRAFT_LIGHT_POWER + MINECRAFT_AMBIENT_LIGHT);
return vec4(color.rgb * lightAccum, color.a);
}

//vec4 minecraft_sample_lightmap(sampler2D lightMap, ivec2 uv) {
// return texture(lightMap, clamp(uv / 256.0, vec2(0.5 / 16.0), vec2(15.5 / 16.0)));
//}

vec4 sample_lightmap(sampler2D lightMap, ivec2 uv) {
return texelFetch(lightMap, (uv & 255) >> 4, 0);
}

vec4 linear_fog(vec4 inColor, float vertexDistance, float fogStart, float fogEnd, vec4 fogColor) {
if (vertexDistance <= fogStart) {
return inColor;
}

float fogValue = vertexDistance < fogEnd ? smoothstep(fogStart, fogEnd, vertexDistance) : 1.0;
return vec4(mix(inColor.rgb, fogColor.rgb, fogValue * fogColor.a), inColor.a);
}

0 comments on commit fd6becc

Please sign in to comment.