Commit for 2021.02.22.7z

This commit is contained in:
mrq 2021-02-22 00:00:00 -06:00
parent 802a448393
commit 714db3db60
2461 changed files with 3287 additions and 1023376 deletions

246
Makefile
View File

@ -1,246 +0,0 @@
ARCH = win64
PREFIX = gcc
TARGET_NAME = program
TARGET_EXTENSION = exe
TARGET_LIB_EXTENSION = dll
include makefiles/$(ARCH).$(PREFIX).make
.PHONY: $(ARCH)-$(PREFIX)
BIN_DIR += ./bin
ENGINE_SRC_DIR += ./engine/src
ENGINE_INC_DIR += ./engine/inc
ENGINE_LIB_DIR += ./engine/lib
EXT_SRC_DIR += ./ext
CLIENT_SRC_DIR += ./client
UF_LIBS +=
EXT_LIBS +=
FLAGS += -Wno-unknown-pragmas -std=c++17 -g
LIB_NAME += uf
EXT_LIB_NAME += ext
#VULKAN_SDK_PATH += /c/VulkanSDK/1.2.154.0/
VULKAN_SDK_PATH += /c/VulkanSDK/1.2.162.0/
GLSL_VALIDATOR += $(VULKAN_SDK_PATH)/Bin32/glslangValidator
# Base Engine's DLL
INC_DIR += $(ENGINE_INC_DIR)/$(ARCH)/$(PREFIX)
DEPS +=
ifneq (,$(findstring win64,$(ARCH)))
REQ_DEPS += opengl json:nlohmann png openal ogg freetype ncurses curl openvr luajit ultralight-ux bullet meshoptimizer # discord
FLAGS +=
DEPS += -lgdi32
else ifneq (,$(findstring dreamcast,$(ARCH)))
REQ_DEPS += opengl json:nlohmann #freetype ogg openal meshoptimizer # luajit ultralight-ux ncurses curl openvr discord
FLAGS += $(KOS_CPPFLAGS) -frtti -DUF_NO_EXCEPTIONS
INCS += $(KOS_INC_PATHS) -I/opt/dreamcast/sh-elf/sh-elf/include
LIBS += $(KOS_LIB_PATHS) -L/opt/dreamcast/sh-elf/sh-elf/lib
endif
ifneq (,$(findstring vulkan,$(REQ_DEPS)))
FLAGS += -DVK_USE_PLATFORM_WIN32_KHR -DUF_USE_VULKAN
DEPS += -lvulkan -lspirv-cross
endif
ifneq (,$(findstring opengl,$(REQ_DEPS)))
FLAGS += -DUF_USE_OPENGL -DUF_USE_GLEW
ifneq (,$(findstring dreamcast,$(ARCH)))
DEPS += -lGLdc
else
DEPS += -lglew32 -lopengl32 -lglu32
endif
endif
ifneq (,$(findstring json,$(REQ_DEPS)))
FLAGS += -DUF_USE_JSON
DEPS +=
ifneq (,$(findstring nlohmann,$(REQ_DEPS)))
FLAGS += -DUF_JSON_USE_NLOHMANN
endif
endif
ifneq (,$(findstring png,$(REQ_DEPS)))
FLAGS += -DUF_USE_PNG
DEPS += -lpng -lz
endif
ifneq (,$(findstring openal,$(REQ_DEPS)))
FLAGS += -DUF_USE_OPENAL
ifneq (,$(findstring dreamcast,$(ARCH)))
DEPS += -lAL
else
FLAGS += -DUF_USE_ALUT
DEPS += -lopenal -lalut
endif
endif
ifneq (,$(findstring ogg,$(REQ_DEPS)))
FLAGS += -DUF_USE_VORBIS
DEPS += -lvorbis -lvorbisfile -logg
endif
ifneq (,$(findstring freetype,$(REQ_DEPS)))
FLAGS += -DUF_USE_FREETYPE
DEPS += -lfreetype
endif
ifneq (,$(findstring ncurses,$(REQ_DEPS)))
FLAGS += -DUF_USE_NCURSES
DEPS += -lncursesw
endif
ifneq (,$(findstring curl,$(REQ_DEPS)))
FLAGS += -DUF_USE_CURL
DEPS += -lcurl
endif
ifneq (,$(findstring discord,$(REQ_DEPS)))
FLAGS += -DUF_USE_DISCORD
DEPS += -ldiscord_game_sdk
endif
ifneq (,$(findstring openvr,$(REQ_DEPS)))
FLAGS += -DUF_USE_OPENVR -DUSE_OPENVR_MINGW
DEPS += -lopenvr_api
endif
ifneq (,$(findstring lua,$(REQ_DEPS)))
FLAGS += -DUF_USE_LUA
ifneq (,$(findstring luajit,$(REQ_DEPS)))
FLAGS += -DUF_USE_LUAJIT
DEPS += -lluajit-5.1
INCS += -I/mingw64/include/luajit-2.1
else
DEPS += -llua-5.1
endif
endif
ifneq (,$(findstring ultralight-ux,$(REQ_DEPS)))
FLAGS += -DUF_USE_ULTRALIGHT_UX
DEPS += -lUltralight -lUltralightCore -lWebCore -lAppCore
endif
ifneq (,$(findstring bullet,$(REQ_DEPS)))
FLAGS += -DUF_USE_BULLET
ifneq (,$(findstring dreamcast,$(ARCH)))
DEPS += -lbulletdynamics -lbulletcollision -lbulletmath
else
DEPS += -lBulletDynamics -lBulletCollision -lLinearMath
INCS += -I$(ENGINE_INC_DIR)/bullet/
endif
endif
ifneq (,$(findstring simd,$(REQ_DEPS)))
FLAGS += -DUF_USE_SIMD #-march=native
endif
ifneq (,$(findstring meshoptimizer,$(REQ_DEPS)))
FLAGS += -DUF_USE_MESHOPTIMIZER
DEPS += -lmeshoptimizer
endif
#DEPS += -lvulkan -lncursesw
LINKS += $(UF_LIBS) $(EXT_LIBS) $(DEPS)
#-Wl,-subsystem,windows
LIB_DIR += $(ENGINE_LIB_DIR)/$(ARCH)
INCS += -I$(ENGINE_INC_DIR) -I$(INC_DIR) -I$(VULKAN_SDK_PATH)/include -I/mingw64/include
LIBS += -L$(ENGINE_LIB_DIR) -L$(LIB_DIR) -L$(LIB_DIR)/$(PREFIX) -L$(VULKAN_SDK_PATH)/Lib
SRCS_DLL += $(wildcard $(ENGINE_SRC_DIR)/*.cpp) $(wildcard $(ENGINE_SRC_DIR)/*/*.cpp) $(wildcard $(ENGINE_SRC_DIR)/*/*/*.cpp) $(wildcard $(ENGINE_SRC_DIR)/*/*/*/*.cpp) $(wildcard $(ENGINE_SRC_DIR)/*/*/*/*/*.cpp)
OBJS_DLL += $(patsubst %.cpp,%.$(ARCH).$(PREFIX).o,$(SRCS_DLL))
BASE_DLL += lib$(LIB_NAME)
IM_DLL += $(ENGINE_LIB_DIR)/$(ARCH)/$(PREFIX)/$(BASE_DLL).$(TARGET_LIB_EXTENSION).a
EX_DLL += $(BIN_DIR)/exe/lib/$(ARCH)/$(PREFIX)/$(BASE_DLL).$(TARGET_LIB_EXTENSION)
# External Engine's DLL
EXT_INC_DIR += $(INC_DIR)
EXT_LB_FLAGS += $(LIB_DIR)
EXT_DEPS += -l$(LIB_NAME) $(DEPS)
EXT_LINKS += $(UF_LIBS) $(EXT_LIBS) $(EXT_DEPS)
#-Wl,-subsystem,windows
EXT_LIB_DIR += $(ENGINE_LIB_DIR)/$(ARCH)
EXT_INCS += -I$(ENGINE_INC_DIR) -I$(EXT_INC_DIR) -I$(VULKAN_SDK_PATH)/include -I/mingw64/include
EXT_LIBS += -L$(ENGINE_LIB_DIR) -L$(EXT_LIB_DIR) -L$(EXT_LIB_DIR)/$(PREFIX) -L$(VULKAN_SDK_PATH)/Lib -L/mingw64/lib
SRCS_EXT_DLL += $(wildcard $(EXT_SRC_DIR)/*.cpp) $(wildcard $(EXT_SRC_DIR)/*/*.cpp) $(wildcard $(EXT_SRC_DIR)/*/*/*.cpp) $(wildcard $(EXT_SRC_DIR)/*/*/*/*.cpp) $(wildcard $(EXT_SRC_DIR)/*/*/*/*/*.cpp)
OBJS_EXT_DLL += $(patsubst %.cpp,%.$(ARCH).$(PREFIX).o,$(SRCS_EXT_DLL))
BASE_EXT_DLL += lib$(EXT_LIB_NAME)
EXT_IM_DLL += $(ENGINE_LIB_DIR)/$(ARCH)/$(PREFIX)/$(BASE_EXT_DLL).$(TARGET_LIB_EXTENSION).a
EXT_EX_DLL += $(BIN_DIR)/exe/lib/$(ARCH)/$(PREFIX)/$(BASE_EXT_DLL).$(TARGET_LIB_EXTENSION)
# Client EXE
SRCS += $(wildcard $(CLIENT_SRC_DIR)/*.cpp) $(wildcard $(CLIENT_SRC_DIR)/*/*.cpp)
OBJS += $(patsubst %.cpp,%.$(ARCH).$(PREFIX).o,$(SRCS))
TARGET += $(BIN_DIR)/exe/$(TARGET_NAME).$(PREFIX).$(TARGET_EXTENSION)
# Shaders
SRCS_SHADERS += $(wildcard bin/data/shaders/*.glsl)
TARGET_SHADERS += $(patsubst %.glsl,%.spv,$(SRCS_SHADERS))
ifneq (,$(findstring dreamcast,$(ARCH)))
$(ARCH): $(EX_DLL) $(EXT_EX_DLL) $(TARGET) ./bin/dreamcast/$(TARGET_NAME).cdi
#$(ARCH): $(TARGET) ./bin/dreamcast/$(TARGET_NAME).cdi
OBJS = $(patsubst %.cpp,%.$(ARCH).$(PREFIX).o,$(SRCS_DLL)) $(patsubst %.cpp,%.$(ARCH).$(PREFIX).o,$(SRCS_EXT_DLL)) $(patsubst %.cpp,%.$(ARCH).$(PREFIX).o,$(SRCS))
DEPS += -lkallisti -lc -lm -lgcc -lstdc++ -lGLdc -lAL # -l$(LIB_NAME) -l$(EXT_LIB_NAME)
%.$(ARCH).$(PREFIX).o: %.cpp
$(CC) $(FLAGS) $(INCS) -c $< -o $@
$(EX_DLL): FLAGS += -DUF_EXPORTS -DJSON_DLL_BUILD
$(EX_DLL): $(OBJS_DLL)
$(KOS_AR) cru $@ $^
$(KOS_RANLIB) $@
cp $@ $(ENGINE_LIB_DIR)/$(ARCH)/$(PREFIX)/$(BASE_DLL).a
$(EXT_EX_DLL): FLAGS += -DEXT_EXPORTS -DJSON_DLL_BUILD
$(EXT_EX_DLL): $(OBJS_EXT_DLL)
$(KOS_AR) cru $@ $^
$(KOS_RANLIB) $@
cp $@ $(ENGINE_LIB_DIR)/$(ARCH)/$(PREFIX)/$(BASE_EXT_DLL).a
./bin/dreamcast/romdisk.img:
$(KOS_GENROMFS) -f ./bin/dreamcast/romdisk.img -d ./bin/dreamcast/romdisk/ -v
./bin/dreamcast/romdisk.o: ./bin/dreamcast/romdisk.img
$(KOS_BASE)/utils/bin2o/bin2o ./bin/dreamcast/romdisk.img romdisk ./bin/dreamcast/romdisk.o
$(TARGET): $(OBJS) ./bin/dreamcast/romdisk.o
$(CC) -O2 -fomit-frame-pointer -ml -m4-single-only -ffunction-sections -fdata-sections $(KOS_INC_PATHS) $(INCS) -D_arch_dreamcast -D_arch_sub_pristine -Wall -g -fno-builtin -ml -m4-single-only -Wl,-Ttext=0x8c010000 -Wl,--gc-sections -T/opt/dreamcast/kos/utils/ldscripts/shlelf.xc -nodefaultlibs $(KOS_LIB_PATHS) $(LIBS) -o $(TARGET) $(OBJS) ./bin/dreamcast/romdisk.o -Wl,--start-group $(DEPS) -Wl,--end-group
./bin/dreamcast/$(TARGET_NAME).cdi: $(TARGET)
cd ./bin/dreamcast/; ./elf2cdi.sh $(TARGET_NAME)
else
$(ARCH): $(EX_DLL) $(EXT_EX_DLL) $(TARGET) $(TARGET_SHADERS)
%.$(ARCH).$(PREFIX).o: %.cpp
$(CC) $(FLAGS) $(INCS) -c $< -o $@
$(EX_DLL): FLAGS += -DUF_EXPORTS -DJSON_DLL_BUILD
$(EX_DLL): $(OBJS_DLL)
$(CC) -shared -o $(EX_DLL) -g -Wl,--out-implib=$(IM_DLL) $(OBJS_DLL) $(LIBS) $(INCS) $(LINKS)
cp $(ENGINE_LIB_DIR)/$(ARCH)/$(PREFIX)/$(BASE_DLL).$(TARGET_LIB_EXTENSION).a $(ENGINE_LIB_DIR)/$(ARCH)/$(PREFIX)/$(BASE_DLL).a
$(EXT_EX_DLL): FLAGS += -DEXT_EXPORTS -DJSON_DLL_BUILD
$(EXT_EX_DLL): $(OBJS_EXT_DLL)
$(CC) -shared -o $(EXT_EX_DLL) -g -Wl,--out-implib=$(EXT_IM_DLL) $(OBJS_EXT_DLL) $(EXT_LIBS) $(EXT_INCS) $(EXT_LINKS)
cp $(ENGINE_LIB_DIR)/$(ARCH)/$(PREFIX)/$(BASE_EXT_DLL).$(TARGET_LIB_EXTENSION).a $(ENGINE_LIB_DIR)/$(ARCH)/$(PREFIX)/$(BASE_EXT_DLL).a
$(TARGET): $(OBJS)
$(CC) $(FLAGS) $(OBJS) $(LIBS) $(INCS) $(LINKS) -l$(LIB_NAME) -l$(EXT_LIB_NAME) -o $(TARGET)
endif
%.spv: %.glsl
$(GLSL_VALIDATOR) -V $< -o $@
clean:
@-rm $(EX_DLL)
@-rm $(EXT_EX_DLL)
@-rm $(TARGET)
@-rm -f $(OBJS_DLL)
@-rm -f $(OBJS_EXT_DLL)
@-rm -f $(OBJS)
clean-uf:
@-rm $(EX_DLL)
@-rm -f $(OBJS_DLL)
clean-exf:
@-rm $(EXT_EX_DLL)
@-rm -f $(OBJS_EXT_DLL)
clean-exe:
-rm $(EX_DLL)
-rm $(EXT_EX_DLL)
-rm $(TARGET)
-rm $(TARGET_SHADERS)

View File

@ -1,44 +0,0 @@
#version 450
layout (constant_id = 0) const uint PASSES = 6;
layout (location = 0) in vec3 inPos;
layout (location = 1) in vec2 inUv;
layout (location = 2) in vec3 inNormal;
layout (location = 3) in vec4 inColor;
layout( push_constant ) uniform PushBlock {
uint pass;
uint draw;
} PushConstant;
struct Matrices {
mat4 model;
mat4 view[PASSES];
mat4 projection[PASSES];
};
layout (binding = 0) uniform UBO {
Matrices matrices;
vec4 color;
} ubo;
layout (location = 0) out vec2 outUv;
layout (location = 1) out vec4 outColor;
layout (location = 2) out vec3 outNormal;
layout (location = 3) out vec3 outPosition;
out gl_PerVertex {
vec4 gl_Position;
};
void main() {
outUv = inUv;
outColor = inColor.rgba;
outPosition = vec3(ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inPos.xyz, 1.0));
outNormal = vec3(ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inNormal.xyz, 0.0));
outNormal = normalize(outNormal);
gl_Position = ubo.matrices.projection[PushConstant.pass] * ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inPos.xyz, 1.0);
}

View File

@ -1,49 +0,0 @@
#version 450
#define UF_DEFERRED_SAMPLING 0
#define UF_CAN_DISCARD 1
layout (binding = 1) uniform sampler2D samplerTexture;
layout (location = 0) in vec2 inUv;
layout (location = 1) in vec4 inColor;
layout (location = 2) in vec3 inNormal;
layout (location = 3) in vec3 inPosition;
layout (location = 0) out uvec2 outId;
layout (location = 1) out vec2 outNormals;
#if UF_DEFERRED_SAMPLING
layout (location = 2) out vec2 outUvs;
#else
layout (location = 2) out vec4 outAlbedo;
#endif
vec2 encodeNormals( vec3 n ) {
float p = sqrt(n.z*8+8);
return n.xy/p + 0.5;
}
float mipLevel( in vec2 uv ) {
vec2 dx_vtc = dFdx(uv);
vec2 dy_vtc = dFdy(uv);
return 0.5 * log2(max(dot(dx_vtc, dx_vtc), dot(dy_vtc, dy_vtc)));
}
void main() {
float mip = mipLevel(inUv.xy);
vec2 uv = inUv.xy;
vec4 C = vec4(1, 1, 1, 1);
vec3 P = inPosition;
vec3 N = inNormal;
#if UF_DEFERRED_SAMPLING
outUvs = wrap(inUv.xy);
vec4 outAlbedo = vec4(0,0,0,0);
#endif
#if !UF_DEFERRED_SAMPLING || UF_CAN_DISCARD
C = textureLod( samplerTexture, uv, mip );
#endif
#if !UF_DEFERRED_SAMPLING
outAlbedo = C * inColor;
#endif
outNormals = encodeNormals( N );
//outId = ivec2(0, 0);
}

View File

@ -1,43 +0,0 @@
#version 450
layout (constant_id = 0) const uint PASSES = 6;
layout (location = 0) in vec3 inPos;
layout (location = 1) in vec2 inUv;
layout (location = 2) in vec3 inNormal;
layout( push_constant ) uniform PushBlock {
uint pass;
uint draw;
} PushConstant;
struct Matrices {
mat4 model;
mat4 view[PASSES];
mat4 projection[PASSES];
};
layout (binding = 0) uniform UBO {
Matrices matrices;
vec4 color;
} ubo;
layout (location = 0) out vec2 outUv;
layout (location = 1) out vec4 outColor;
layout (location = 2) out vec3 outNormal;
layout (location = 3) out vec3 outPosition;
out gl_PerVertex {
vec4 gl_Position;
};
void main() {
outUv = inUv;
outColor = ubo.color;
outPosition = vec3(ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inPos.xyz, 1.0));
outNormal = vec3(ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inNormal.xyz, 0.0));
outNormal = normalize(outNormal);
gl_Position = ubo.matrices.projection[PushConstant.pass] * ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inPos.xyz, 1.0);
}

View File

@ -1,23 +0,0 @@
#version 450
#extension GL_EXT_samplerless_texture_functions : require
layout (binding = 1) uniform sampler samp;
layout (binding = 2) uniform texture2D albedoLeftTexture;
layout (binding = 3) uniform texture2D albedoRightTexture;
layout (location = 0) in vec2 inUv;
layout (location = 0) out vec4 outAlbedoSpecular;
layout( push_constant ) uniform PushBlock {
uint pass;
} PushConstant;
void main() {
if ( PushConstant.pass == 0 ) {
outAlbedoSpecular.rgb = texture(sampler2D(albedoLeftTexture, samp), inUv).rgb;
} else {
outAlbedoSpecular.rgb = texture(sampler2D(albedoRightTexture, samp), inUv).rgb;
}
outAlbedoSpecular.a = 1;
}

View File

@ -1,16 +0,0 @@
#version 450
layout (location = 0) in vec2 inPos;
layout (location = 1) in vec2 inUv;
layout (location = 0) out vec2 outUv;
out gl_PerVertex {
vec4 gl_Position;
};
void main() {
outUv = inUv;
gl_Position = vec4(inPos.xy, 0.0, 1.0);
}

View File

@ -1,75 +0,0 @@
#version 450
#extension GL_EXT_samplerless_texture_functions : require
#define UF_DEFERRED_SAMPLING 0
#define UF_CAN_DISCARD 1
layout (binding = 1) uniform sampler samp;
layout (binding = 2) uniform utexture2D textureId;
layout (binding = 3) uniform texture2D textureNormals;
#if UF_DEFERRED_SAMPLING
layout (binding = 4) uniform texture2D textureUvs;
#else
layout (binding = 4) uniform texture2D textureAlbedo;
#endif
struct Cursor {
vec2 position;
vec2 radius;
vec4 color;
};
layout (location = 0) in vec2 inUv;
layout (location = 1) in float inAlpha;
layout (location = 2) in Cursor inCursor;
layout (location = 0) out vec4 outAlbedo;
void main() {
if ( inCursor.radius.x <= 0 && inCursor.radius.y <= 0 ) {
vec2 uv = gl_FragCoord.xy / textureSize(textureId, 0);
outAlbedo = texture(sampler2D(textureAlbedo, samp), uv).rgba;
return;
}
float dist = pow(inUv.x - inCursor.position.x, 2) / pow(inCursor.radius.x, 2) + pow(inUv.y - inCursor.position.y, 2) / pow(inCursor.radius.y, 2);
outAlbedo = texture(sampler2D(textureAlbedo, samp), inUv);
if ( dist <= 1 ) {
float attenuation = dist;
outAlbedo.rgb = mix( inCursor.color.rgb * inCursor.color.a, outAlbedo.rgb, attenuation );
}
if ( inAlpha < 1.0 ) outAlbedo.a = inAlpha;
}
/*
layout (location = 0) out uvec2 outId;
layout (location = 1) out vec2 outNormals;
#if UF_DEFERRED_SAMPLING
layout (location = 2) out vec2 outUvs;
#else
layout (location = 2) out vec4 outAlbedo;
#endif
void main() {
if ( inCursor.radius.x <= 0 && inCursor.radius.y <= 0 ) {
vec2 uv = gl_FragCoord.xy / textureSize(textureId, 0);
outId = texture(usampler2D(textureId, samp), uv).xy;
outNormals = texture(sampler2D(textureNormals, samp), uv).xy;
#if UF_DEFERRED_SAMPLING
outUvs = texture(sampler2D(textureUvs, samp), uv).xy;
#else
outAlbedo = texture(sampler2D(textureAlbedo, samp), uv).rgba;
#endif
return;
}
float dist = pow(inUv.x - inCursor.position.x, 2) / pow(inCursor.radius.x, 2) + pow(inUv.y - inCursor.position.y, 2) / pow(inCursor.radius.y, 2);
#if !UF_DEFERRED_SAMPLING
outAlbedo = texture(sampler2D(textureAlbedo, samp), inUv);
if ( dist <= 1 ) {
float attenuation = dist;
outAlbedo.rgb = mix( inCursor.color.rgb * inCursor.color.a, outAlbedo.rgb, attenuation );
}
if ( inAlpha < 1.0 ) outAlbedo.a = inAlpha;
#endif
}
*/

View File

@ -1,41 +0,0 @@
#version 450
layout (location = 0) in vec2 inPos;
layout (location = 1) in vec2 inUv;
struct Cursor {
vec2 position;
vec2 radius;
vec4 color;
};
layout (location = 0) out vec2 outUv;
layout (location = 1) out float outAlpha;
layout (location = 2) out flat Cursor outCursor;
layout( push_constant ) uniform PushBlock {
uint pass;
uint draw;
} PushConstant;
out gl_PerVertex {
vec4 gl_Position;
};
struct Matrices {
mat4 model[2];
};
layout (binding = 0) uniform UBO {
Matrices matrices;
Cursor cursor;
// float alpha;
// float padding;
} ubo;
void main() {
outUv = inUv;
outCursor = ubo.cursor;
outAlpha = 1;
gl_Position = ubo.matrices.model[PushConstant.pass] * vec4(inPos.xy, 0.0, 1.0);
}

View File

@ -1,693 +0,0 @@
#version 450
#extension GL_EXT_samplerless_texture_functions : require
#define SAMPLES 16
#define POISSON_DISK 16
#define RAY_MARCH_FOG 0
#define UF_DEFERRED_SAMPLING 0
layout (constant_id = 0) const uint TEXTURES = 256;
struct Matrices {
mat4 view[2];
mat4 projection[2];
mat4 iView[2];
mat4 iProjection[2];
mat4 iProjectionView[2];
};
struct Space {
vec3 eye;
vec3 world;
} position, normal, view;
struct Fog {
vec3 color;
float stepScale;
vec3 offset;
float densityScale;
float densityThreshold;
float densityMultiplier;
float absorbtion;
float padding1;
vec2 range;
float padding2;
float padding3;
};
struct Mode {
uint type;
uint scalar;
vec2 padding;
vec4 parameters;
};
struct Light {
vec3 position;
float radius;
vec3 color;
float power;
int type;
int mapIndex;
float depthBias;
float padding;
mat4 view;
mat4 projection;
};
struct Material {
vec4 colorBase;
vec4 colorEmissive;
float factorMetallic;
float factorRoughness;
float factorOcclusion;
float factorAlphaCutoff;
int indexAlbedo;
int indexNormal;
int indexEmissive;
int indexOcclusion;
int indexMetallicRoughness;
int modeAlpha;
int padding1;
int padding2;
};
struct Texture {
int index;
int samp;
int remap;
float blend;
vec4 lerp;
};
struct DrawCall {
int materialIndex;
uint materials;
int textureIndex;
uint textures;
};
layout (input_attachment_index = 0, binding = 0) uniform usubpassInputMS samplerId;
layout (input_attachment_index = 1, binding = 1) uniform subpassInputMS samplerNormal;
#if UF_DEFERRED_SAMPLING
layout (input_attachment_index = 2, binding = 2) uniform subpassInputMS samplerUv;
#else
layout (input_attachment_index = 2, binding = 2) uniform subpassInputMS samplerAlbedo;
#endif
layout (input_attachment_index = 3, binding = 4) uniform subpassInputMS samplerDepth;
layout (binding = 5) uniform sampler3D samplerNoise;
layout (binding = 6) uniform samplerCube samplerSkybox;
layout (binding = 7) uniform sampler2D samplerTextures[TEXTURES];
layout (binding = 8) uniform UBO {
Matrices matrices;
Mode mode;
Fog fog;
uint lights;
uint materials;
uint textures;
uint drawCalls;
vec3 ambient;
float kexp;
} ubo;
layout (std140, binding = 9) readonly buffer Lights {
Light lights[];
};
layout (std140, binding = 10) readonly buffer Materials {
Material materials[];
};
layout (std140, binding = 11) readonly buffer Textures {
Texture textures[];
};
layout (std140, binding = 12) readonly buffer DrawCalls {
DrawCall drawCalls[];
};
layout (location = 0) in vec2 inUv;
layout (location = 1) in flat uint inPushConstantPass;
layout (location = 0) out vec4 outFragColor;
vec2 poissonDisk[16] = vec2[](
vec2( -0.94201624, -0.39906216 ),
vec2( 0.94558609, -0.76890725 ),
vec2( -0.094184101, -0.92938870 ),
vec2( 0.34495938, 0.29387760 ),
vec2( -0.91588581, 0.45771432 ),
vec2( -0.81544232, -0.87912464 ),
vec2( -0.38277543, 0.27676845 ),
vec2( 0.97484398, 0.75648379 ),
vec2( 0.44323325, -0.97511554 ),
vec2( 0.53742981, -0.47373420 ),
vec2( -0.26496911, -0.41893023 ),
vec2( 0.79197514, 0.19090188 ),
vec2( -0.24188840, 0.99706507 ),
vec2( -0.81409955, 0.91437590 ),
vec2( 0.19984126, 0.78641367 ),
vec2( 0.14383161, -0.14100790 )
);
void phong( Light light, vec4 albedoSpecular, inout vec3 i ) {
vec3 Ls = vec3(1.0, 1.0, 1.0); // light specular
vec3 Ld = light.color; // light color
vec3 La = vec3(1.0, 1.0, 1.0);
vec3 Ks = vec3(albedoSpecular.a); // material specular
vec3 Kd = albedoSpecular.rgb; // material diffuse
vec3 Ka = vec3(1.0, 1.0, 1.0);
float Kexp = ubo.kexp;
vec3 V = position.eye;
vec3 N = normal.eye;
vec3 L = light.position.xyz - V;
float dist = length(L);
// if ( light.radius > 0.001 && light.radius < dist ) return;
vec3 D = normalize(L);
float d_dot = max(dot( D, N ), 0.0);
vec3 R = reflect( -D, N );
vec3 S = normalize(-V);
float s_factor = pow( max(dot( R, S ), 0.0), Kexp );
if ( Kexp < 0.0001 ) s_factor = 0;
float radiance = light.power / (dist * dist);
vec3 Ia = La * Ka;
vec3 Id = Ld * Kd * d_dot * radiance;
vec3 Is = Ls * Ks * s_factor * radiance;
i += Id + Is;
}
const float PI = 3.14159265359;
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 num = a2;
float denom = (NdotH2 * (a2 - 1.0) + 1.0);
denom = PI * denom * denom;
return num / denom;
}
float GeometrySchlickGGX(float NdotV, float roughness) {
float r = (roughness + 1.0);
float k = (r*r) / 8.0;
float num = NdotV;
float denom = NdotV * (1.0 - k) + k;
return num / 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(1.0 - cosTheta, 5.0);
}
float random(vec3 seed, int i){
vec4 seed4 = vec4(seed,i);
float dot_product = dot(seed4, vec4(12.9898,78.233,45.164,94.673));
return fract(sin(dot_product) * 43758.5453);
}
float shadowFactor( Light light, uint shadowMap ) {
vec4 positionClip = light.projection * light.view * vec4(position.world, 1.0);
positionClip.xyz /= positionClip.w;
if ( positionClip.x < -1 || positionClip.x >= 1 ) return 0.0;
if ( positionClip.y < -1 || positionClip.y >= 1 ) return 0.0;
if ( positionClip.z <= 0 || positionClip.z >= 1 ) return 0.0;
float factor = 1.0;
// spot light
if ( light.type == 2 || light.type == 3 ) {
float dist = length( positionClip.xy );
if ( dist > 0.5 ) return 0.0;
// spot light with attenuation
if ( light.type == 3 ) {
factor = 1.0 - (pow(dist * 2,2.0));
}
}
vec2 uv = positionClip.xy * 0.5 + 0.5;
float bias = light.depthBias;
/*
if ( true ) {
float cosTheta = clamp(dot(normal.eye, normalize(light.position.xyz - position.eye)), 0, 1);
bias = clamp(bias * tan(acos(cosTheta)), 0, 0.01);
} else if ( true ) {
bias = max(bias * 10 * (1.0 - dot(normal.eye, normalize(light.position.xyz - position.eye))), bias);
}
*/
float eyeDepth = positionClip.z;
int samples = POISSON_DISK;
if ( samples <= 1 ) {
return eyeDepth < texture(samplerTextures[shadowMap], uv).r - bias ? 0.0 : factor;
}
for ( int i = 0; i < samples; ++i ) {
// int index = i;
// int index = int( float(samples) * random(gl_FragCoord.xyy, i) ) % samples;
int index = int( float(samples) * random(floor(position.world.xyz * 1000.0), i)) % samples;
float lightDepth = texture(samplerTextures[shadowMap], uv + poissonDisk[index] / 700.0 ).r;
if ( eyeDepth < lightDepth - bias ) factor -= 1.0 / samples;
}
return factor;
}
vec3 hslToRgb(vec3 HSL) {
vec3 RGB; {
float H = HSL.x;
float R = abs(H * 6 - 3) - 1;
float G = 2 - abs(H * 6 - 2);
float B = 2 - abs(H * 6 - 4);
RGB = clamp(vec3(R,G,B), 0, 1);
}
float C = (1 - abs(2 * HSL.z - 1)) * HSL.y;
return (RGB - 0.5) * C + HSL.z;
}
vec3 rgbToHsl(vec3 RGB) {
float Epsilon = 1e-10;
vec3 HCV; {
vec4 P = (RGB.g < RGB.b) ? vec4(RGB.bg, -1.0, 2.0/3.0) : vec4(RGB.gb, 0.0, -1.0/3.0);
vec4 Q = (RGB.r < P.x) ? vec4(P.xyw, RGB.r) : vec4(RGB.r, P.yzx);
float C = Q.x - min(Q.w, Q.y);
float H = abs((Q.w - Q.y) / (6 * C + Epsilon) + Q.z);
HCV = vec3(H, C, Q.x);
}
float L = HCV.z - HCV.y * 0.5;
float S = HCV.y / (1 - abs(L * 2 - 1) + Epsilon);
return vec3(HCV.x, S, L);
}
float hueDistance(float h1, float h2) {
float diff = abs((h1 - h2));
return min(abs((1.0 - diff)), diff);
}
const float lightnessSteps = 4.0;
float lightnessStep(float l) {
return floor((0.5 + l * lightnessSteps)) / lightnessSteps;
}
const int indexMatrix16x16[256] = int[](0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255,
128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127,
32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223,
160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95,
8,200, 56,248, 4,196, 52,244, 11,203, 59,251, 7,199, 55,247,
136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119,
40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215,
168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87,
2,194, 50,242, 14,206, 62,254, 1,193, 49,241, 13,205, 61,253,
130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125,
34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221,
162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93,
10,202, 58,250, 6,198, 54,246, 9,201, 57,249, 5,197, 53,245,
138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117,
42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213,
170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85);
float indexValue16x16( float scale ) {
int x = int(mod(gl_FragCoord.x * scale, 16));
int y = int(mod(gl_FragCoord.y * scale, 16));
return indexMatrix16x16[(x + y * 16)] / 256.0;
}
const int indexMatrix8x8[64] = int[](0, 32, 8, 40, 2, 34, 10, 42,
48, 16, 56, 24, 50, 18, 58, 26,
12, 44, 4, 36, 14, 46, 6, 38,
60, 28, 52, 20, 62, 30, 54, 22,
3, 35, 11, 43, 1, 33, 9, 41,
51, 19, 59, 27, 49, 17, 57, 25,
15, 47, 7, 39, 13, 45, 5, 37,
63, 31, 55, 23, 61, 29, 53, 21);
float indexValue8x8( float scale ) {
int x = int(mod(gl_FragCoord.x * scale, 8));
int y = int(mod(gl_FragCoord.y * scale, 8));
return indexMatrix8x8[(x + y * 8)] / 64.0;
}
const int indexMatrix4x4[16] = int[](0, 8, 2, 10,
12, 4, 14, 6,
3, 11, 1, 9,
15, 7, 13, 5);
float indexValue4x4( float scale ) {
int x = int(mod(gl_FragCoord.x * scale, 4));
int y = int(mod(gl_FragCoord.y * scale, 4));
return indexMatrix4x4[(x + y * 4)] / 16.0;
}
vec3[2] closestColors(float hue) {
vec3 ret[2];
vec3 closest = vec3(-2, 0, 0);
vec3 secondClosest = vec3(-2, 0, 0);
vec3 temp;
/*
for (int i = 0; i < palette.length(); ++i) {
temp = rgbToHsl(palette[i].rgb);
float tempDistance = hueDistance(temp.x, hue);
if (tempDistance < hueDistance(closest.x, hue)) {
secondClosest = closest;
closest = temp;
} else {
if (tempDistance < hueDistance(secondClosest.x, hue)) {
secondClosest = temp;
}
}
}
*/
ret[0] = closest;
ret[1] = secondClosest;
return ret;
}
float dither(float color) {
float closestColor = (color < 0.5) ? 0 : 1;
float secondClosestColor = 1 - closestColor;
float d = 1; // -0.5 - fract(ubo.mode.parameters.w / 8.0);
if ( ubo.mode.scalar == 16 ) {
d = indexValue16x16(1);
} else if ( ubo.mode.scalar == 8 ) {
d = indexValue8x8(1);
} else if ( ubo.mode.scalar == 4 ) {
d = indexValue4x4(1);
}
float distance = abs(closestColor - color);
return (distance < d) ? closestColor : secondClosestColor;
}
void dither(inout vec3 color) {
vec3 hsl = rgbToHsl(color);
hsl.x = dither(hsl.x);
color = hslToRgb(hsl);
}
void dither1(inout vec3 color) {
vec3 hsl = rgbToHsl(color);
float d = 0;
vec3 cs[2] = { hsl, hsl }; // closestColors(hsl.x);
float scale = 1;
if ( ubo.mode.scalar == 16 ) {
d = indexValue16x16(scale);
} else if ( ubo.mode.scalar == 8 ) {
d = indexValue8x8(scale);
} else if ( ubo.mode.scalar == 4 ) {
d = indexValue4x4(scale);
}
float hueDiff = hueDistance(hsl.x, cs[0].x) / hueDistance(cs[1].x, cs[0].x);
float l1 = lightnessStep(max((hsl.z - 0.125), 0.0));
float l2 = lightnessStep(min((hsl.z + 0.124), 1.0));
float lightnessDiff = (hsl.z - l1) / (l2 - l1);
vec3 resultColor = (hueDiff < d) ? cs[0] : cs[1];
resultColor.z = (lightnessDiff < d) ? l1 : l2;
color = hslToRgb(resultColor);
}
vec3 dither2() {
vec3 vDither = dot( vec2( 171.0, 231.0 ), inUv.xy + ubo.mode.parameters.w ).xxx;
vDither.rgb = fract( vDither.rgb / vec3( 103.0, 71.0, 97.0 ) ) - vec3( 0.5, 0.5, 0.5 );
return ( vDither.rgb / 255.0 ) * 0.375;
}
float rand2(vec2 co){
return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 143758.5453);
}
float rand3(vec3 co){
return fract(sin(dot(co.xyz ,vec3(12.9898,78.233, 37.719))) * 143758.5453);
}
void whitenoise(inout vec3 color) {
float flicker = ubo.mode.parameters.x;
float pieces = ubo.mode.parameters.y;
float blend = ubo.mode.parameters.z;
float time = ubo.mode.parameters.w;
if ( blend < 0.0001 ) return;
float freq = sin(pow(mod(time, flicker) + flicker, 1.9));
// float whiteNoise = rand3( floor(position.world / pieces) + floor(time * 2) );
float whiteNoise = rand2( floor(gl_FragCoord.xy / pieces) + mod(time, freq) );
color = mix( color, vec3(whiteNoise), blend );
}
void pbr( Light light, vec3 albedo, float metallic, float roughness, vec3 lightPositionWorld, inout vec3 i ) {
vec3 F0 = vec3(0.04);
F0 = mix(F0, albedo, metallic);
vec3 N = normalize(normal.eye);
vec3 L = light.position.xyz - position.eye;
float dist = length(L);
L = normalize(L);
vec3 V = normalize(-position.eye);
vec3 H = normalize(V + L);
float NdotL = max(dot(N, L), 0.0);
float NdotV = max(dot(N, V), 0.0);
float attenuation = light.power / (dist * dist);
vec3 radiance = light.color.rgb * attenuation;
// cook-torrance brdf
float NDF = DistributionGGX(N, H, roughness);
float G = GeometrySmith(N, V, L, roughness);
vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0);
vec3 kD = vec3(1.0) - F;
kD *= 1.0 - metallic;
vec3 numerator = NDF * G * F;
float denominator = 4.0 * NdotV * NdotL;
vec3 specular = numerator / max(denominator, 0.001);
// add to outgoing radiance Lo
i += (kD * albedo / PI + specular) * radiance * NdotL;
}
vec2 rayBoxDst( vec3 boundsMin, vec3 boundsMax, vec3 rayO, vec3 rayD ) {
vec3 t0 = (boundsMin - rayO) / rayD;
vec3 t1 = (boundsMax - rayO) / rayD;
vec3 tmin = min(t0, t1);
vec3 tmax = max(t0, t1);
float dstA = max( max(tmin.x, tmin.y), tmin.z );
float dstB = min( tmax.x, min(tmax.y, tmax.z) );
float dstToBox = max(0, dstA);
float dstInsideBox = max(0, dstB - dstToBox);
return vec2(dstToBox, dstInsideBox);
}
float sampleDensity( vec3 position ) {
vec3 uvw = position * ubo.fog.densityScale * 0.001 + ubo.fog.offset * 0.01;
return max(0, texture(samplerNoise, uvw).r - ubo.fog.densityThreshold) * ubo.fog.densityMultiplier;
}
void fog( vec3 rayO, vec3 rayD, inout vec3 i, float scale ) {
if ( ubo.fog.stepScale <= 0 ) return;
if ( ubo.fog.range.x == 0 || ubo.fog.range.y == 0 ) return;
#if RAY_MARCH_FOG
float range = ubo.fog.range.y;
vec3 boundsMin = vec3(-range,-range,-range) + rayO;
vec3 boundsMax = vec3(range,range,range) + rayO;
int numSteps = int(length(boundsMax - boundsMin) * ubo.fog.stepScale );
vec2 rayBoxInfo = rayBoxDst( boundsMin, boundsMax, rayO, rayD );
float dstToBox = rayBoxInfo.x;
float dstInsideBox = rayBoxInfo.y;
float depth = position.eye.z;
float lightEnergy = 0;
// march
if ( 0 <= dstInsideBox && dstToBox <= depth ) {
float dstTravelled = 0;
float stepSize = dstInsideBox / numSteps;
float dstLimit = min( depth - dstToBox, dstInsideBox );
float totalDensity = 0;
float transmittance = 1;
while ( dstTravelled < dstLimit ) {
vec3 rayPos = rayO + rayD * (dstToBox + dstTravelled);
float density = sampleDensity(rayPos);
if ( density > 0 ) {
transmittance *= exp(-density * stepSize * ubo.fog.absorbtion);
if ( transmittance < 0.01 ) break;
}
dstTravelled += stepSize;
}
i.rgb = mix(ubo.fog.color.rgb, i.rgb, transmittance);
}
#endif
vec3 color = ubo.fog.color.rgb;
float inner = ubo.fog.range.x;
float outer = ubo.fog.range.y * scale;
float distance = length(-position.eye);
float factor = (distance - inner) / (outer - inner);
factor = clamp( factor, 0.0, 1.0 );
i.rgb = mix(i.rgb, color, factor);
}
vec3 decodeNormals( vec2 enc ) {
vec2 fenc = enc*4-2;
float f = dot(fenc,fenc);
float g = sqrt(1-f/4);
vec3 n;
n.xy = fenc*g;
n.z = 1-f/2;
return normalize(n);
}
float wrap( float i ) {
return fract(i);
}
vec2 wrap( vec2 uv ) {
return vec2( wrap( uv.x ), wrap( uv.y ) );
}
float mipLevel( in vec2 uv ) {
vec2 dx_vtc = dFdx(uv);
vec2 dy_vtc = dFdy(uv);
return 0.5 * log2(max(dot(dx_vtc, dx_vtc), dot(dy_vtc, dy_vtc)));
}
bool validTextureIndex( int textureIndex ) {
return 0 <= textureIndex && textureIndex < ubo.textures;
}
vec4 sampleTexture( uint drawId, int textureIndex, in vec2 uv, vec4 base ) {
if ( !validTextureIndex( textureIndex ) ) return base;
Texture t = textures[textureIndex+1];
float mip = mipLevel( uv );
return texture( samplerTextures[drawId], mix( t.lerp.xy, t.lerp.zw, wrap( uv ) ), mip );
}
void main() {
vec3 rayO = vec3(0);
vec3 rayD = vec3(0);
vec3 fragColor = vec3(0);
{
float depth = subpassLoad(samplerDepth, SAMPLES).r;
vec4 positionClip = vec4(inUv * 2.0 - 1.0, depth, 1.0);
vec4 positionEye = ubo.matrices.iProjection[inPushConstantPass] * positionClip;
positionEye /= positionEye.w;
position.eye = positionEye.xyz;
vec4 positionWorld = ubo.matrices.iView[inPushConstantPass] * positionEye;
position.world = positionWorld.xyz;
}
{
vec4 near4 = ubo.matrices.iProjectionView[inPushConstantPass] * (vec4(2.0 * inUv - 1.0, -1.0, 1.0));
vec4 far4 = ubo.matrices.iProjectionView[inPushConstantPass] * (vec4(2.0 * inUv - 1.0, 1.0, 1.0));
vec3 near3 = near4.xyz / near4.w;
vec3 far3 = far4.xyz / far4.w;
rayO = near3;
}
{
mat4 iProjectionView = inverse( ubo.matrices.projection[inPushConstantPass] * mat4(mat3(ubo.matrices.view[inPushConstantPass])) );
vec4 near4 = iProjectionView * (vec4(2.0 * inUv - 1.0, -1.0, 1.0));
vec4 far4 = iProjectionView * (vec4(2.0 * inUv - 1.0, 1.0, 1.0));
vec3 near3 = near4.xyz / near4.w;
vec3 far3 = far4.xyz / far4.w;
rayD = normalize( far3 - near3 );
}
normal.eye = decodeNormals( subpassLoad(samplerNormal, SAMPLES).xy );
uvec2 ID = subpassLoad(samplerId, SAMPLES).xy;
uint drawId = ID.x;
uint materialId = ID.y;
if ( drawId == 0 || materialId == 0 ) {
fragColor.rgb = texture( samplerSkybox, rayD ).rgb;
fog(rayO, rayD, fragColor, 0.0);
outFragColor = vec4(fragColor,1);
return;
}
--drawId;
--materialId;
DrawCall drawCall = drawCalls[drawId];
materialId += drawCall.materialIndex;
Material material = materials[materialId];
vec4 C = material.colorBase;
#if UF_DEFERRED_SAMPLING
vec2 uv = subpassLoad(samplerUv, SAMPLES).xy;
C = sampleTexture( drawId, drawCall.textureIndex + material.indexAlbedo, uv, C );
// OPAQUE
if ( material.modeAlpha == 0 ) {
C.a = 1;
// BLEND
} else if ( material.modeAlpha == 1 ) {
// MASK
} else if ( material.modeAlpha == 2 ) {
}
#else
C = subpassLoad(samplerAlbedo, SAMPLES);
#endif
float M = material.factorMetallic;
float R = material.factorRoughness * 4.0;
float AO = material.factorOcclusion;
bool usePbr = true;
bool gammaCorrect = false;
float litFactor = 1.0;
fragColor = C.rgb * ubo.ambient.rgb * AO;
for ( uint i = 0; i < ubo.lights; ++i ) {
Light light = lights[i];
if ( light.power <= 0.001 ) continue;
vec3 lightPositionWorld = light.position.xyz;
light.position.xyz = vec3(ubo.matrices.view[inPushConstantPass] * vec4(light.position.xyz, 1));
if ( 0 <= light.mapIndex && light.mapIndex < TEXTURES ) {
float factor = shadowFactor( light, light.mapIndex );
// if ( factor <= 0.0001 ) continue;
light.power *= factor;
litFactor += light.power;
}
if ( light.power <= 0.0001 ) continue;
if ( usePbr ) {
pbr( light, C.rgb, M, R, lightPositionWorld, fragColor );
} else
phong( light, C, fragColor );
}
if ( gammaCorrect ) {
fragColor = fragColor / (fragColor + vec3(1.0));
fragColor = pow(fragColor, vec3(1.0/2.2));
}
fog(rayO, rayD, fragColor, litFactor);
/*
if ( (ubo.mode.type & (0x1 << 0)) == (0x1 << 0) ) {
//dither1(fragColor);
fragColor += dither2();
}
*/
if ( (ubo.mode.type & (0x1 << 1)) == (0x1 << 1) ) {
whitenoise(fragColor);
}
outFragColor = vec4(fragColor,1);
}

View File

@ -1,559 +0,0 @@
#version 450
#extension GL_EXT_samplerless_texture_functions : require
layout (constant_id = 0) const uint LIGHTS = 256;
layout (input_attachment_index = 0, binding = 1) uniform subpassInput samplerAlbedoMetallic;
layout (input_attachment_index = 0, binding = 2) uniform subpassInput samplerNormalRoughness;
layout (input_attachment_index = 0, binding = 3) uniform subpassInput samplerDepth;
layout (binding = 5) uniform sampler3D samplerNoise;
layout (binding = 6) uniform sampler2D samplerShadows[LIGHTS];
layout (location = 0) in vec2 inUv;
layout (location = 1) in flat uint inPushConstantPass;
layout (location = 0) out vec4 outFragColor;
/*
const vec2 poissonDisk[4] = vec2[](
vec2( -0.94201624, -0.39906216 ),
vec2( 0.94558609, -0.76890725 ),
vec2( -0.094184101, -0.92938870 ),
vec2( 0.34495938, 0.29387760 )
);
*/
vec2 poissonDisk[16] = vec2[](
vec2( -0.94201624, -0.39906216 ),
vec2( 0.94558609, -0.76890725 ),
vec2( -0.094184101, -0.92938870 ),
vec2( 0.34495938, 0.29387760 ),
vec2( -0.91588581, 0.45771432 ),
vec2( -0.81544232, -0.87912464 ),
vec2( -0.38277543, 0.27676845 ),
vec2( 0.97484398, 0.75648379 ),
vec2( 0.44323325, -0.97511554 ),
vec2( 0.53742981, -0.47373420 ),
vec2( -0.26496911, -0.41893023 ),
vec2( 0.79197514, 0.19090188 ),
vec2( -0.24188840, 0.99706507 ),
vec2( -0.81409955, 0.91437590 ),
vec2( 0.19984126, 0.78641367 ),
vec2( 0.14383161, -0.14100790 )
);
struct Light {
vec3 position;
float radius;
vec3 color;
float power;
int type;
float depthBias;
float padding1;
float padding2;
mat4 view;
mat4 projection;
};
struct Matrices {
mat4 view[2];
mat4 projection[2];
};
struct Space {
vec3 eye;
vec3 world;
} position, normal, view;
struct Fog {
vec3 color;
float stepScale;
vec3 offset;
float densityScale;
float densityThreshold;
float densityMultiplier;
float absorbtion;
float padding1;
vec2 range;
float padding2;
float padding3;
};
struct Mode {
uint type;
uint scalar;
vec2 padding;
vec4 parameters;
};
layout (binding = 0) uniform UBO {
Matrices matrices;
vec3 ambient;
float kexp;
Mode mode;
Fog fog;
Light lights[LIGHTS];
} ubo;
void phong( Light light, vec4 albedoSpecular, inout vec3 i ) {
vec3 Ls = vec3(1.0, 1.0, 1.0); // light specular
vec3 Ld = light.color; // light color
vec3 La = vec3(1.0, 1.0, 1.0);
vec3 Ks = vec3(albedoSpecular.a); // material specular
vec3 Kd = albedoSpecular.rgb; // material diffuse
vec3 Ka = vec3(1.0, 1.0, 1.0);
float Kexp = ubo.kexp;
vec3 V = position.eye;
vec3 N = normal.eye;
vec3 L = light.position.xyz - V;
float dist = length(L);
// if ( light.radius > 0.001 && light.radius < dist ) return;
vec3 D = normalize(L);
float d_dot = max(dot( D, N ), 0.0);
vec3 R = reflect( -D, N );
vec3 S = normalize(-V);
float s_factor = pow( max(dot( R, S ), 0.0), Kexp );
if ( Kexp < 0.0001 ) s_factor = 0;
float radiance = light.power / (dist * dist);
vec3 Ia = La * Ka;
vec3 Id = Ld * Kd * d_dot * radiance;
vec3 Is = Ls * Ks * s_factor * radiance;
i += Id + Is;
}
const float PI = 3.14159265359;
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 num = a2;
float denom = (NdotH2 * (a2 - 1.0) + 1.0);
denom = PI * denom * denom;
return num / denom;
}
float GeometrySchlickGGX(float NdotV, float roughness) {
float r = (roughness + 1.0);
float k = (r*r) / 8.0;
float num = NdotV;
float denom = NdotV * (1.0 - k) + k;
return num / 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(1.0 - cosTheta, 5.0);
}
float random(vec3 seed, int i){
vec4 seed4 = vec4(seed,i);
float dot_product = dot(seed4, vec4(12.9898,78.233,45.164,94.673));
return fract(sin(dot_product) * 43758.5453);
}
float shadowFactor( Light light, uint shadowMap ) {
vec4 positionClip = light.projection * light.view * vec4(position.world, 1.0);
positionClip.xyz /= positionClip.w;
if ( positionClip.x < -1 || positionClip.x >= 1 ) return 0.0;
if ( positionClip.y < -1 || positionClip.y >= 1 ) return 0.0;
if ( positionClip.z <= 0 || positionClip.z >= 1 ) return 0.0;
float factor = 1.0;
// spot light
if ( light.type == -2 || light.type == -3 ) {
float dist = length( positionClip.xy );
if ( dist > 0.5 ) return 0.0;
// spot light with attenuation
if ( light.type == -3 ) {
factor = 1.0 - (pow(dist * 2,2.0));
}
}
vec2 uv = positionClip.xy * 0.5 + 0.5;
float bias = light.depthBias;
if ( !true ) {
float cosTheta = clamp(dot(normal.eye, normalize(light.position.xyz - position.eye)), 0, 1);
bias = clamp(bias * tan(acos(cosTheta)), 0, 0.01);
} else if ( true ) {
bias = max(bias * 10 * (1.0 - dot(normal.eye, normalize(light.position.xyz - position.eye))), bias);
}
float eyeDepth = positionClip.z;
int samples = poissonDisk.length();
if ( samples <= 1 ) {
return eyeDepth < texture(samplerShadows[shadowMap], uv).r - bias ? 0.0 : factor;
}
for ( int i = 0; i < samples; ++i ) {
// int index = i;
// int index = int( float(samples) * random(gl_FragCoord.xyy, i) ) % samples;
int index = int( float(samples) * random(floor(position.world.xyz * 1000.0), i)) % samples;
float lightDepth = texture(samplerShadows[shadowMap], uv + poissonDisk[index] / 700.0 ).r;
if ( eyeDepth < lightDepth - bias ) factor -= 1.0 / samples;
}
return factor;
}
vec3 hslToRgb(vec3 HSL) {
vec3 RGB; {
float H = HSL.x;
float R = abs(H * 6 - 3) - 1;
float G = 2 - abs(H * 6 - 2);
float B = 2 - abs(H * 6 - 4);
RGB = clamp(vec3(R,G,B), 0, 1);
}
float C = (1 - abs(2 * HSL.z - 1)) * HSL.y;
return (RGB - 0.5) * C + HSL.z;
}
vec3 rgbToHsl(vec3 RGB) {
float Epsilon = 1e-10;
vec3 HCV; {
vec4 P = (RGB.g < RGB.b) ? vec4(RGB.bg, -1.0, 2.0/3.0) : vec4(RGB.gb, 0.0, -1.0/3.0);
vec4 Q = (RGB.r < P.x) ? vec4(P.xyw, RGB.r) : vec4(RGB.r, P.yzx);
float C = Q.x - min(Q.w, Q.y);
float H = abs((Q.w - Q.y) / (6 * C + Epsilon) + Q.z);
HCV = vec3(H, C, Q.x);
}
float L = HCV.z - HCV.y * 0.5;
float S = HCV.y / (1 - abs(L * 2 - 1) + Epsilon);
return vec3(HCV.x, S, L);
}
float hueDistance(float h1, float h2) {
float diff = abs((h1 - h2));
return min(abs((1.0 - diff)), diff);
}
const float lightnessSteps = 4.0;
float lightnessStep(float l) {
return floor((0.5 + l * lightnessSteps)) / lightnessSteps;
}
const int indexMatrix16x16[256] = int[](0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255,
128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127,
32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223,
160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95,
8,200, 56,248, 4,196, 52,244, 11,203, 59,251, 7,199, 55,247,
136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119,
40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215,
168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87,
2,194, 50,242, 14,206, 62,254, 1,193, 49,241, 13,205, 61,253,
130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125,
34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221,
162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93,
10,202, 58,250, 6,198, 54,246, 9,201, 57,249, 5,197, 53,245,
138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117,
42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213,
170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85);
float indexValue16x16( float scale ) {
int x = int(mod(gl_FragCoord.x * scale, 16));
int y = int(mod(gl_FragCoord.y * scale, 16));
return indexMatrix16x16[(x + y * 16)] / 256.0;
}
const int indexMatrix8x8[64] = int[](0, 32, 8, 40, 2, 34, 10, 42,
48, 16, 56, 24, 50, 18, 58, 26,
12, 44, 4, 36, 14, 46, 6, 38,
60, 28, 52, 20, 62, 30, 54, 22,
3, 35, 11, 43, 1, 33, 9, 41,
51, 19, 59, 27, 49, 17, 57, 25,
15, 47, 7, 39, 13, 45, 5, 37,
63, 31, 55, 23, 61, 29, 53, 21);
float indexValue8x8( float scale ) {
int x = int(mod(gl_FragCoord.x * scale, 8));
int y = int(mod(gl_FragCoord.y * scale, 8));
return indexMatrix8x8[(x + y * 8)] / 64.0;
}
const int indexMatrix4x4[16] = int[](0, 8, 2, 10,
12, 4, 14, 6,
3, 11, 1, 9,
15, 7, 13, 5);
float indexValue4x4( float scale ) {
int x = int(mod(gl_FragCoord.x * scale, 4));
int y = int(mod(gl_FragCoord.y * scale, 4));
return indexMatrix4x4[(x + y * 4)] / 16.0;
}
vec3[2] closestColors(float hue) {
vec3 ret[2];
vec3 closest = vec3(-2, 0, 0);
vec3 secondClosest = vec3(-2, 0, 0);
vec3 temp;
/*
for (int i = 0; i < palette.length(); ++i) {
temp = rgbToHsl(palette[i].rgb);
float tempDistance = hueDistance(temp.x, hue);
if (tempDistance < hueDistance(closest.x, hue)) {
secondClosest = closest;
closest = temp;
} else {
if (tempDistance < hueDistance(secondClosest.x, hue)) {
secondClosest = temp;
}
}
}
*/
ret[0] = closest;
ret[1] = secondClosest;
return ret;
}
float dither(float color) {
float closestColor = (color < 0.5) ? 0 : 1;
float secondClosestColor = 1 - closestColor;
float d = 1; // -0.5 - fract(ubo.mode.parameters.w / 8.0);
if ( ubo.mode.scalar == 16 ) {
d = indexValue16x16(1);
} else if ( ubo.mode.scalar == 8 ) {
d = indexValue8x8(1);
} else if ( ubo.mode.scalar == 4 ) {
d = indexValue4x4(1);
}
float distance = abs(closestColor - color);
return (distance < d) ? closestColor : secondClosestColor;
}
void dither(inout vec3 color) {
vec3 hsl = rgbToHsl(color);
hsl.x = dither(hsl.x);
color = hslToRgb(hsl);
}
void dither1(inout vec3 color) {
vec3 hsl = rgbToHsl(color);
float d = 0;
vec3 cs[2] = { hsl, hsl }; // closestColors(hsl.x);
float scale = 1;
if ( ubo.mode.scalar == 16 ) {
d = indexValue16x16(scale);
} else if ( ubo.mode.scalar == 8 ) {
d = indexValue8x8(scale);
} else if ( ubo.mode.scalar == 4 ) {
d = indexValue4x4(scale);
}
float hueDiff = hueDistance(hsl.x, cs[0].x) / hueDistance(cs[1].x, cs[0].x);
float l1 = lightnessStep(max((hsl.z - 0.125), 0.0));
float l2 = lightnessStep(min((hsl.z + 0.124), 1.0));
float lightnessDiff = (hsl.z - l1) / (l2 - l1);
vec3 resultColor = (hueDiff < d) ? cs[0] : cs[1];
resultColor.z = (lightnessDiff < d) ? l1 : l2;
color = hslToRgb(resultColor);
}
vec3 dither2() {
vec3 vDither = dot( vec2( 171.0, 231.0 ), inUv.xy + ubo.mode.parameters.w ).xxx;
vDither.rgb = fract( vDither.rgb / vec3( 103.0, 71.0, 97.0 ) ) - vec3( 0.5, 0.5, 0.5 );
return ( vDither.rgb / 255.0 ) * 0.375;
}
float rand2(vec2 co){
return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 143758.5453);
}
float rand3(vec3 co){
return fract(sin(dot(co.xyz ,vec3(12.9898,78.233, 37.719))) * 143758.5453);
}
void whitenoise(inout vec3 color) {
float flicker = ubo.mode.parameters.x;
float pieces = ubo.mode.parameters.y;
float blend = ubo.mode.parameters.z;
float time = ubo.mode.parameters.w;
if ( blend < 0.0001 ) return;
float freq = sin(pow(mod(time, flicker) + flicker, 1.9));
// float whiteNoise = rand3( floor(position.world / pieces) + floor(time * 2) );
float whiteNoise = rand2( floor(gl_FragCoord.xy / pieces) + mod(time, freq) );
color = mix( color, vec3(whiteNoise), blend );
}
void pbr( Light light, vec3 albedo, float metallic, float roughness, vec3 lightPositionWorld, inout vec3 i ) {
vec3 F0 = vec3(0.04);
F0 = mix(F0, albedo, metallic);
vec3 N = normalize(normal.eye);
vec3 L = light.position.xyz - position.eye;
float dist = length(L);
// if ( light.radius > 0.001 && light.radius < dist ) return;
vec3 D = normalize(L);
vec3 V = normalize(-position.eye);
vec3 H = normalize(V + D);
float NdotD = max(dot(N, D), 0.0);
float NdotV = max(dot(N, V), 0.0);
vec3 radiance = light.color.rgb * light.power / (dist * dist);
/*
if ( light.radius > 0.0001 ) {
radiance *= clamp( light.radius / (pow(dist, 2.0) + 1.0), 0.0, 1.0 );
} else if ( false ) {
radiance /= dist * dist;
}
*/
// cook-torrance brdf
float NDF = DistributionGGX(N, H, roughness);
float G = GeometrySmith(N, V, D, roughness);
vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0);
vec3 kS = F;
vec3 kD = vec3(1.0) - kS;
kD *= 1.0 - metallic;
vec3 numerator = NDF * G * F;
float denominator = 4.0 * NdotV * NdotD;
vec3 specular = numerator / max(denominator, 0.001);
// add to outgoing radiance Lo
i += (kD * albedo / PI + specular) * radiance * NdotD;
}
vec2 rayBoxDst( vec3 boundsMin, vec3 boundsMax, vec3 rayOrigin, vec3 rayDir ) {
vec3 t0 = (boundsMin - rayOrigin) / rayDir;
vec3 t1 = (boundsMax - rayOrigin) / rayDir;
vec3 tmin = min(t0, t1);
vec3 tmax = max(t0, t1);
float dstA = max( max(tmin.x, tmin.y), tmin.z );
float dstB = min( tmax.x, min(tmax.y, tmax.z) );
float dstToBox = max(0, dstA);
float dstInsideBox = max(0, dstB - dstToBox);
return vec2(dstToBox, dstInsideBox);
}
float sampleDensity( vec3 position ) {
vec3 uvw = position * ubo.fog.densityScale * 0.001 + ubo.fog.offset * 0.01;
return max(0, texture(samplerNoise, uvw).r - ubo.fog.densityThreshold) * ubo.fog.densityMultiplier;
}
void fog( inout vec3 i, float scale ) {
if ( ubo.fog.stepScale <= 0 ) return;
if ( ubo.fog.range.x == 0 || ubo.fog.range.y == 0 ) return;
mat4 iProjView = inverse( ubo.matrices.projection[inPushConstantPass] * ubo.matrices.view[inPushConstantPass] );
vec4 near4 = iProjView * (vec4(2.0 * inUv - 1.0, -1.0, 1.0));
vec4 far4 = iProjView * (vec4(2.0 * inUv - 1.0, 1.0, 1.0));
vec3 near3 = near4.xyz / near4.w;
vec3 far3 = far4.xyz / far4.w;
vec3 rayOrigin = near3;
vec3 rayDir = normalize( far3 - near3 );
float range = ubo.fog.range.y;
vec3 boundsMin = vec3(-range,-range,-range) + rayOrigin;
vec3 boundsMax = vec3(range,range,range) + rayOrigin;
int numSteps = int(length(boundsMax - boundsMin) * ubo.fog.stepScale );
vec2 rayBoxInfo = rayBoxDst( boundsMin, boundsMax, rayOrigin, rayDir );
float dstToBox = rayBoxInfo.x;
float dstInsideBox = rayBoxInfo.y;
float depth = position.eye.z;
float lightEnergy = 0;
// march
if ( 0 <= dstInsideBox && dstToBox <= depth ) {
float dstTravelled = 0;
float stepSize = dstInsideBox / numSteps;
float dstLimit = min( depth - dstToBox, dstInsideBox );
float totalDensity = 0;
float transmittance = 1;
while ( dstTravelled < dstLimit ) {
vec3 rayPos = rayOrigin + rayDir * (dstToBox + dstTravelled);
float density = sampleDensity(rayPos);
if ( density > 0 ) {
transmittance *= exp(-density * stepSize * ubo.fog.absorbtion);
if ( transmittance < 0.01 ) break;
}
dstTravelled += stepSize;
}
i.rgb = mix(ubo.fog.color.rgb, i.rgb, transmittance);
}
vec3 color = ubo.fog.color.rgb;
float inner = ubo.fog.range.x;
float outer = ubo.fog.range.y * scale;
float distance = length(-position.eye);
float factor = (distance - inner) / (outer - inner);
factor = clamp( factor, 0.0, 1.0 );
i.rgb = mix(i.rgb, color, factor);
}
void main() {
vec4 albedoMetallic = subpassLoad(samplerAlbedoMetallic);
vec4 normalRoughness = subpassLoad(samplerNormalRoughness);
// vec4 positionAO = subpassLoad(samplerPositionAO);
normal.eye = normalRoughness.rgb;
{
mat4 iProj = inverse( ubo.matrices.projection[inPushConstantPass] );
mat4 iView = inverse( ubo.matrices.view[inPushConstantPass] );
float depth = subpassLoad(samplerDepth).r;
vec4 positionClip = vec4(inUv * 2.0 - 1.0, depth, 1.0);
vec4 positionEye = iProj * positionClip;
positionEye /= positionEye.w;
position.eye = positionEye.xyz;
vec4 positionWorld = iView * positionEye;
position.world = positionWorld.xyz;
}
bool usePbr = true;
bool gammaCorrect = false;
float litFactor = 1.0;
float ao = 1; // positionAO.a;
vec3 fragColor = albedoMetallic.rgb * ubo.ambient.rgb * ao;
for ( uint i = 0; i < LIGHTS; ++i ) {
Light light = ubo.lights[i];
if ( light.power <= 0.001 ) continue;
vec3 lightPositionWorld = light.position.xyz;
light.position.xyz = vec3(ubo.matrices.view[inPushConstantPass] * vec4(light.position.xyz, 1));
if ( light.type < 0 ) {
float factor = shadowFactor( light, i );
if ( factor <= 0.0001 ) continue;
light.power *= factor;
litFactor += light.power;
}
if ( usePbr ) {
pbr( light, albedoMetallic.rgb, albedoMetallic.a, normalRoughness.a, lightPositionWorld, fragColor );
} else
phong( light, albedoMetallic, fragColor );
}
if ( gammaCorrect ) {
fragColor = fragColor / (fragColor + vec3(1.0));
fragColor = pow(fragColor, vec3(1.0/2.2));
}
fog(fragColor, litFactor);
/*
if ( (ubo.mode.type & (0x1 << 0)) == (0x1 << 0) ) {
//dither1(fragColor);
fragColor += dither2();
}
if ( (ubo.mode.type & (0x1 << 1)) == (0x1 << 1) ) {
whitenoise(fragColor);
}
*/
outFragColor = vec4(fragColor,1);
}

View File

@ -1,24 +0,0 @@
#version 450
layout (location = 0) in vec2 inPos;
layout (location = 1) in vec2 inUv;
layout (location = 0) out vec2 outUv;
layout (location = 1) out flat uint outPushConstantPass;
layout( push_constant ) uniform PushBlock {
uint pass;
uint draw;
} PushConstant;
out gl_PerVertex {
vec4 gl_Position;
};
void main() {
outUv = inUv;
outPushConstantPass = PushConstant.pass;
gl_Position = vec4(inPos.xy, 0.0, 1.0);
}

View File

@ -1,17 +0,0 @@
#version 450
layout (location = 0) in vec2 inPos;
layout (location = 1) in vec2 inUv;
layout (location = 0) out vec2 outUv;
out gl_PerVertex {
vec4 gl_Position;
};
void main() {
outUv = inUv;
gl_Position = vec4(inPos.xy, 0.0, 1.0);
}

View File

@ -1,139 +0,0 @@
#version 450
#define UF_DEFERRED_SAMPLING 0
#define UF_CAN_DISCARD 1
layout (constant_id = 0) const uint TEXTURES = 1;
layout (binding = 0) uniform sampler2D samplerTextures[TEXTURES];
struct Material {
vec4 colorBase;
vec4 colorEmissive;
float factorMetallic;
float factorRoughness;
float factorOcclusion;
float factorAlphaCutoff;
int indexAlbedo;
int indexNormal;
int indexEmissive;
int indexOcclusion;
int indexMetallicRoughness;
int modeAlpha;
int padding1;
int padding2;
};
struct Texture {
int index;
int samp;
int remap;
float blend;
vec4 lerp;
};
layout (std140, binding = 1) readonly buffer Materials {
Material materials[];
};
layout (std140, binding = 2) readonly buffer Textures {
Texture textures[];
};
layout (location = 0) in vec2 inUv;
layout (location = 1) in vec4 inColor;
layout (location = 2) in vec3 inNormal;
layout (location = 3) in mat3 inTBN;
layout (location = 6) in vec3 inPosition;
layout (location = 7) flat in ivec4 inId;
layout (location = 0) out uvec2 outId;
layout (location = 1) out vec2 outNormals;
#if UF_DEFERRED_SAMPLING
layout (location = 2) out vec2 outUvs;
#else
layout (location = 2) out vec4 outAlbedo;
#endif
vec2 encodeNormals( vec3 n ) {
float p = sqrt(n.z*8+8);
return n.xy/p + 0.5;
}
float wrap( float i ) {
return fract(i);
}
vec2 wrap( vec2 uv ) {
return vec2( wrap( uv.x ), wrap( uv.y ) );
}
float mipLevel( in vec2 uv ) {
vec2 dx_vtc = dFdx(uv);
vec2 dy_vtc = dFdy(uv);
return 0.5 * log2(max(dot(dx_vtc, dx_vtc), dot(dy_vtc, dy_vtc)));
}
bool validTextureIndex( int textureIndex ) {
return 0 <= textureIndex && textureIndex < TEXTURES;
}
void main() {
float mip = mipLevel(inUv.xy);
vec2 uv = wrap(inUv.xy);
vec4 C = vec4(0, 0, 0, 0);
vec3 P = inPosition;
vec3 N = inNormal;
#if UF_DEFERRED_SAMPLING
outUvs = wrap(inUv.xy);
vec4 outAlbedo = vec4(0,0,0,0);
#endif
#if !UF_DEFERRED_SAMPLING || UF_CAN_DISCARD
int materialId = int(inId.y);
Material material = materials[materialId];
float M = material.factorMetallic;
float R = material.factorRoughness;
float AO = material.factorOcclusion;
// sample albedo
if ( !validTextureIndex( material.indexAlbedo ) ) discard; {
Texture t = textures[material.indexAlbedo + 1];
C = textureLod( samplerTextures[0], mix( t.lerp.xy, t.lerp.zw, uv ), mip );
// alpha mode OPAQUE
if ( material.modeAlpha == 0 ) {
C.a = 1;
// alpha mode BLEND
} else if ( material.modeAlpha == 1 ) {
// alpha mode MASK
} else if ( material.modeAlpha == 2 ) {
if ( C.a < abs(material.factorAlphaCutoff) ) discard;
C.a = 1;
}
}
#endif
#if !UF_DEFERRED_SAMPLING
// sample normal
if ( validTextureIndex( material.indexNormal ) ) {
Texture t = textures[material.indexNormal + 1];
N = inTBN * normalize( textureLod( samplerTextures[0], mix( t.lerp.xy, t.lerp.zw, uv ), mip ).xyz * 2.0 - vec3(1.0));
}
#if 0
// sample metallic/roughness
if ( validTextureIndex( material.indexMetallicRoughness ) ) {
Texture t = textures[material.indexMetallicRoughness + 1];
vec4 sampled = texture( samplerTextures[0], mix( t.lerp.xy, t.lerp.zw, uv ), mip );
M = sampled.b;
R = sampled.g;
}
// sample ao
AO = material.factorOcclusion;
if ( validTextureIndex( material.indexOcclusion ) ) {
Texture t = textures[material.indexMetallicRoughness + 1];
AO = texture( samplerTextures[0], mix( t.lerp.xy, t.lerp.zw, uv ) ).r;
}
#endif
outAlbedo = C * inColor;
#endif
outNormals = encodeNormals( N );
outId = ivec2(inId.w+1, inId.y+1);
}

View File

@ -1,62 +0,0 @@
#version 450
layout (constant_id = 0) const uint PASSES = 6;
layout (location = 0) in vec3 inPos;
layout (location = 1) in vec2 inUv;
layout (location = 2) in vec3 inNormal;
layout (location = 3) in vec4 inTangent;
layout (location = 4) in ivec2 inId;
layout( push_constant ) uniform PushBlock {
uint pass;
uint draw;
} PushConstant;
layout (binding = 3) uniform UBO {
mat4 view[PASSES];
mat4 projection[PASSES];
} ubo;
layout (std140, binding = 4) readonly buffer Models {
mat4 models[];
};
layout (location = 0) out vec2 outUv;
layout (location = 1) out vec4 outColor;
layout (location = 2) out vec3 outNormal;
layout (location = 3) out mat3 outTBN;
layout (location = 6) out vec3 outPosition;
layout (location = 7) out ivec4 outId;
out gl_PerVertex {
vec4 gl_Position;
};
vec4 snap(vec4 vertex, vec2 resolution) {
vec4 snappedPos = vertex;
snappedPos.xyz = vertex.xyz / vertex.w;
snappedPos.xy = floor(resolution * snappedPos.xy) / resolution;
snappedPos.xyz *= vertex.w;
return snappedPos;
}
void main() {
outUv = inUv;
outColor = vec4(1.0);
outId = ivec4(inId, PushConstant.pass, PushConstant.draw);
mat4 model = models.length() <= 0 ? mat4(1.0) : models[int(inId.x)];
outPosition = vec3(ubo.view[PushConstant.pass] * model * vec4(inPos.xyz, 1.0));
outNormal = vec3(ubo.view[PushConstant.pass] * model * vec4(inNormal.xyz, 0.0));
outNormal = normalize(outNormal);
{
vec3 T = vec3(ubo.view[PushConstant.pass] * model * vec4(inTangent.xyz, 0.0));
vec3 N = outNormal;
vec3 B = cross(N, T) * inTangent.w;
outTBN = mat3( T, B, N );
}
gl_Position = ubo.projection[PushConstant.pass] * ubo.view[PushConstant.pass] * model * vec4(inPos.xyz, 1.0);
// gl_Position = snap( gl_Position, vec2(256.0, 224.0) );
}

View File

@ -1,74 +0,0 @@
#version 450
layout (constant_id = 0) const uint PASSES = 6;
layout (location = 0) in vec3 inPos;
layout (location = 1) in vec2 inUv;
layout (location = 2) in vec3 inNormal;
layout (location = 3) in vec4 inTangent;
layout (location = 4) in ivec2 inId;
layout (location = 5) in vec4 inJoints;
layout (location = 6) in vec4 inWeights;
layout( push_constant ) uniform PushBlock {
uint pass;
uint draw;
} PushConstant;
layout (binding = 3) uniform UBO {
mat4 view[PASSES];
mat4 projection[PASSES];
} ubo;
layout (std140, binding = 4) readonly buffer Models {
mat4 models[];
};
layout (std140, binding = 5) readonly buffer Joints {
mat4 joints[];
};
layout (location = 0) out vec2 outUv;
layout (location = 1) out vec4 outColor;
layout (location = 2) out vec3 outNormal;
layout (location = 3) out mat3 outTBN;
layout (location = 6) out vec3 outPosition;
layout (location = 7) out ivec4 outId;
out gl_PerVertex {
vec4 gl_Position;
};
vec4 snap(vec4 vertex, vec2 resolution) {
vec4 snappedPos = vertex;
snappedPos.xyz = vertex.xyz / vertex.w;
snappedPos.xy = floor(resolution * snappedPos.xy) / resolution;
snappedPos.xyz *= vertex.w;
return snappedPos;
}
void main() {
outUv = inUv;
outColor = vec4(1.0);
outId = ivec4(inId, PushConstant.pass, PushConstant.draw);
mat4 model = models.length() <= 0 ? mat4(1.0) : models[int(inId.x)];
mat4 skinnedMatrix = joints.length() <= 0 ? mat4(1.0) :
inWeights.x * joints[int(inJoints.x)] +
inWeights.y * joints[int(inJoints.y)] +
inWeights.z * joints[int(inJoints.z)] +
inWeights.w * joints[int(inJoints.w)];
outPosition = vec3(ubo.view[PushConstant.pass] * model * skinnedMatrix * vec4(inPos.xyz, 1.0));
outNormal = vec3(ubo.view[PushConstant.pass] * model * vec4(inNormal.xyz, 0.0));
outNormal = normalize(outNormal);
{
vec3 T = vec3(ubo.view[PushConstant.pass] * model * vec4(inTangent.xyz, 0.0));
vec3 N = outNormal;
vec3 B = cross(N, T) * inTangent.w;
outTBN = mat3( T, B, N );
}
gl_Position = ubo.projection[PushConstant.pass] * ubo.view[PushConstant.pass] * model * skinnedMatrix * vec4(inPos.xyz, 1.0);
}

View File

@ -1,78 +0,0 @@
#version 450
layout (constant_id = 0) const uint PASSES = 6;
layout (location = 0) in vec3 inPos;
layout (location = 1) in vec2 inUv;
layout (location = 2) in vec3 inNormal;
layout (location = 3) in vec4 inTangent;
layout (location = 4) in ivec2 inId;
layout (location = 5) in vec4 inJoints;
layout (location = 6) in vec4 inWeights;
layout( push_constant ) uniform PushBlock {
uint pass;
uint draw;
} PushConstant;
struct Matrices {
mat4 model;
mat4 view[PASSES];
mat4 projection[PASSES];
};
layout (binding = 3) uniform UBO {
Matrices matrices;
vec4 color;
} ubo;
layout (std140, binding = 4) readonly buffer Joints {
mat4 joints[];
};
layout (location = 0) out vec2 outUv;
layout (location = 1) out vec4 outColor;
layout (location = 2) out vec3 outNormal;
layout (location = 3) out mat3 outTBN;
layout (location = 6) out vec3 outPosition;
layout (location = 7) out ivec4 outId;
out gl_PerVertex {
vec4 gl_Position;
};
vec4 snap(vec4 vertex, vec2 resolution) {
vec4 snappedPos = vertex;
snappedPos.xyz = vertex.xyz / vertex.w;
snappedPos.xy = floor(resolution * snappedPos.xy) / resolution;
snappedPos.xyz *= vertex.w;
return snappedPos;
}
void main() {
outUv = inUv;
outColor = ubo.color;
outId = ivec4(inId, PushConstant.pass, PushConstant.draw);
mat4 skinnedMatrix = joints.length() <= 0 ? mat4(1.0) :
inWeights.x * joints[int(inJoints.x)] +
inWeights.y * joints[int(inJoints.y)] +
inWeights.z * joints[int(inJoints.z)] +
inWeights.w * joints[int(inJoints.w)];
outPosition = vec3(ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * skinnedMatrix * vec4(inPos.xyz, 1.0));
outNormal = vec3(ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inNormal.xyz, 0.0));
outNormal = normalize(outNormal);
{
vec3 T = vec3(ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inTangent.xyz, 0.0));
vec3 N = outNormal;
vec3 B = cross(N, T) * inTangent.w;
outTBN = mat3( T, B, N );
}
gl_Position = ubo.matrices.projection[PushConstant.pass] * ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * skinnedMatrix * vec4(inPos.xyz, 1.0);
// gl_Position = snap( gl_Position, vec2(320.0, 240.0) );
// gl_Position = snap( gl_Position, vec2(480.0, 270.0) );
// gl_Position = snap( gl_Position, vec2(640.0, 480.0) );
}

View File

@ -1,64 +0,0 @@
#version 450
layout (constant_id = 0) const uint PASSES = 6;
layout (location = 0) in vec3 inPos;
layout (location = 1) in vec2 inUv;
layout (location = 2) in vec3 inNormal;
layout (location = 3) in vec4 inTangent;
layout (location = 4) in ivec2 inId;
layout( push_constant ) uniform PushBlock {
uint pass;
uint draw;
} PushConstant;
struct Matrices {
mat4 model;
mat4 view[PASSES];
mat4 projection[PASSES];
};
layout (binding = 3) uniform UBO {
Matrices matrices;
vec4 color;
} ubo;
layout (location = 0) out vec2 outUv;
layout (location = 1) out vec4 outColor;
layout (location = 2) out vec3 outNormal;
layout (location = 3) out mat3 outTBN;
layout (location = 6) out vec3 outPosition;
layout (location = 7) out ivec4 outId;
out gl_PerVertex {
vec4 gl_Position;
};
vec4 snap(vec4 vertex, vec2 resolution) {
vec4 snappedPos = vertex;
snappedPos.xyz = vertex.xyz / vertex.w;
snappedPos.xy = floor(resolution * snappedPos.xy) / resolution;
snappedPos.xyz *= vertex.w;
return snappedPos;
}
void main() {
outUv = inUv;
outColor = ubo.color;
outId = ivec4(inId, PushConstant.pass, PushConstant.draw);
outPosition = vec3(ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inPos.xyz, 1.0));
outNormal = vec3(ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inNormal.xyz, 0.0));
outNormal = normalize(outNormal);
{
vec3 T = vec3(ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inTangent.xyz, 0.0));
vec3 N = outNormal;
vec3 B = cross(N, T) * inTangent.w;
outTBN = mat3( T, B, N );
}
gl_Position = ubo.matrices.projection[PushConstant.pass] * ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inPos.xyz, 1.0);
// gl_Position = snap( gl_Position, vec2(320.0, 240.0) );
}

View File

@ -1,66 +0,0 @@
#version 450
#define UF_DEFERRED_SAMPLING 0
#define UF_CAN_DISCARD 1
layout (binding = 1) uniform sampler2D samplerTexture;
struct Gui {
vec4 offset;
vec4 color;
int mode;
float depth;
vec2 padding;
};
layout (location = 0) in vec2 inUv;
layout (location = 1) in flat Gui inGui;
layout (location = 0) out uvec2 outId;
layout (location = 1) out vec2 outNormals;
#if UF_DEFERRED_SAMPLING
layout (location = 2) out vec2 outUvs;
#else
layout (location = 2) out vec4 outAlbedo;
#endif
vec2 encodeNormals( vec3 n ) {
float p = sqrt(n.z*8+8);
return n.xy/p + 0.5;
}
float mipLevel( in vec2 uv ) {
vec2 dx_vtc = dFdx(uv);
vec2 dy_vtc = dFdy(uv);
return 0.5 * log2(max(dot(dx_vtc, dx_vtc), dot(dy_vtc, dy_vtc)));
}
void main() {
if ( inUv.x < inGui.offset.x ) discard;
if ( inUv.y < inGui.offset.y ) discard;
if ( inUv.x > inGui.offset.z ) discard;
if ( inUv.y > inGui.offset.w ) discard;
float mip = mipLevel(inUv.xy);
vec2 uv = inUv.xy;
vec4 C = vec4(1, 1, 1, 1);
//vec3 N = inNormal;
#if UF_DEFERRED_SAMPLING
outUvs = wrap(inUv.xy);
vec4 outAlbedo = vec4(0,0,0,0);
#endif
#if !UF_DEFERRED_SAMPLING || UF_CAN_DISCARD
C = textureLod( samplerTexture, uv, mip );
#endif
#if !UF_DEFERRED_SAMPLING
if ( inGui.mode == 1 ) {
C = inGui.color;
} else {
C *= inGui.color;
}
outAlbedo = C;
#endif
/*
outNormals = encodeNormals( N );
outId = ivec2(0, 0);
*/
}

View File

@ -1,62 +0,0 @@
#version 450
#define UF_DEFERRED_SAMPLING 0
#define UF_CAN_DISCARD 1
layout (binding = 1) uniform sampler2D samplerTexture;
struct Gui {
vec4 offset;
vec4 color;
int mode;
float depth;
int sdf;
int shadowbox;
vec4 stroke;
float weight;
int spread;
float scale;
float padding;
};
layout (location = 0) in vec2 inUv;
layout (location = 1) in flat Gui inGui;
layout (location = 0) out uvec2 outId;
layout (location = 1) out vec2 outNormals;
#if UF_DEFERRED_SAMPLING
layout (location = 2) out vec2 outUvs;
#else
layout (location = 2) out vec4 outAlbedo;
#endif
void main() {
if ( inUv.x < inGui.offset.x ) discard;
if ( inUv.y < inGui.offset.y ) discard;
if ( inUv.x > inGui.offset.z ) discard;
if ( inUv.y > inGui.offset.w ) discard;
#if UF_DEFERRED_SAMPLING
vec4 outAlbedo = vec4(0,0,0,0);
#endif
if ( inGui.shadowbox == 1 ) {
outAlbedo = inGui.color;
return;
}
float dist = texture(samplerTexture, inUv).r;
if ( inGui.sdf == 1 ) {
float smoothing = ( inGui.spread > 0 && inGui.scale > 0 ) ? 0.25 / (inGui.spread * inGui.scale) : 0.25 / (4 * 1.5);
float outlining = smoothstep(0.5 - smoothing, 0.5 + smoothing, dist);
float alpha = smoothstep(inGui.weight - smoothing, inGui.weight + smoothing, dist);
vec4 c = inGui.color;
outAlbedo = mix(inGui.stroke, c, outlining);
outAlbedo.a = inGui.color.a * alpha;
if ( alpha < 0.001 ) discard;
if ( alpha > 1 ) discard;
} else {
outAlbedo = vec4(inGui.color) * dist;
if ( dist < 0.001 ) discard;
if ( dist > 1 ) discard;
}
}

View File

@ -1,47 +0,0 @@
#version 450
layout (constant_id = 0) const uint PASSES = 6;
layout (location = 0) in vec2 inPos;
layout (location = 1) in vec2 inUv;
layout( push_constant ) uniform PushBlock {
uint pass;
uint draw;
} PushConstant;
struct Matrices {
mat4 model[PASSES];
};
struct Gui {
vec4 offset;
vec4 color;
int mode;
float depth;
int sdf;
int shadowbox;
vec4 stroke;
float weight;
int spread;
float scale;
float padding;
};
layout (binding = 0) uniform UBO {
Matrices matrices;
Gui gui;
} ubo;
layout (location = 0) out vec2 outUv;
layout (location = 1) out flat Gui outGui;
out gl_PerVertex {
vec4 gl_Position;
};
void main() {
outUv = inUv;
outGui = ubo.gui;
gl_Position = ubo.matrices.model[PushConstant.pass] * vec4(inPos.xy, ubo.gui.depth, 1.0);
}

View File

@ -1,41 +0,0 @@
#version 450
layout (constant_id = 0) const uint PASSES = 6;
layout (location = 0) in vec2 inPos;
layout (location = 1) in vec2 inUv;
layout( push_constant ) uniform PushBlock {
uint pass;
uint draw;
} PushConstant;
struct Matrices {
mat4 model[PASSES];
};
struct Gui {
vec4 offset;
vec4 color;
int mode;
float depth;
vec2 padding;
};
layout (binding = 0) uniform UBO {
Matrices matrices;
Gui gui;
} ubo;
layout (location = 0) out vec2 outUv;
layout (location = 1) out flat Gui outGui;
out gl_PerVertex {
vec4 gl_Position;
};
void main() {
outUv = inUv;
outGui = ubo.gui;
gl_Position = ubo.matrices.model[PushConstant.pass] * vec4(inPos.xy, ubo.gui.depth, 1.0);
}

View File

@ -1,19 +0,0 @@
#version 450
layout (binding = 1) uniform sampler2D samplerColor;
layout (location = 0) in vec2 inUv;
layout (location = 1) in vec3 inNormal;
layout (location = 2) in vec4 inColor;
layout (location = 0) out vec4 outAlbedoSpecular;
layout (location = 1) out vec4 outNormal;
void main() {
outAlbedoSpecular = texture(samplerColor, inUv);
outAlbedoSpecular = vec4(1,1,1,1);
outAlbedoSpecular.rgb *= inColor.rgb;
outAlbedoSpecular.a = 1;
// outPosition = vec4(inPosition, 1.0);
outNormal = vec4(normalize(inNormal), 1.0);
}

View File

@ -1,52 +0,0 @@
#version 450
layout (constant_id = 0) const uint PASSES = 6;
layout (location = 0) in vec3 inPos;
layout (location = 1) in vec2 inUv;
layout (location = 2) in vec3 inNormal;
layout (location = 3) in uint inColor;
layout( push_constant ) uniform PushBlock {
uint pass;
uint draw;
} PushConstant;
struct Matrices {
mat4 model;
mat4 view[PASSES];
mat4 projection[PASSES];
};
layout (binding = 0) uniform UBO {
Matrices matrices;
vec4 color;
} ubo;
layout (location = 0) out vec2 outUv;
layout (location = 1) out vec3 outNormal;
layout (location = 2) out vec4 outColor;
out gl_PerVertex {
vec4 gl_Position;
};
void main() {
outUv = inUv;
// outColor = ubo.color;
// outPosition = vec3(ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inPos.xyz, 1.0));
outNormal = vec3(ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inNormal.xyz, 0.0));
// outPosition = vec3(ubo.matrices.model * vec4(inPos.xyz, 1.0));
// outNormal = vec3(ubo.matrices.model * vec4(inNormal.xyz, 0.0));
outColor.a = (inColor >> 24u) & 0xFF;
outColor.b = (inColor >> 16u) & 0xFF;
outColor.g = (inColor >> 8u) & 0xFF;
outColor.r = (inColor ) & 0xFF;
outColor.rgb /= 256.0;
outColor.a = 0.5;
gl_Position = ubo.matrices.projection[PushConstant.pass] * ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inPos.xyz, 1.0);
}

View File

@ -1,10 +0,0 @@
#version 450
layout (location = 0) in vec3 inColor;
layout (location = 0) out vec4 outAlbedoSpecular;
void main() {
outAlbedoSpecular.rgb *= inColor.rgb;
outAlbedoSpecular.a = 1;
}

View File

@ -1,35 +0,0 @@
#version 450
layout (constant_id = 0) const uint PASSES = 6;
layout (location = 0) in vec3 inPos;
layout( push_constant ) uniform PushBlock {
uint pass;
uint draw;
} PushConstant;
struct Matrices {
mat4 model;
mat4 view[PASSES];
mat4 projection[PASSES];
};
layout (binding = 0) uniform UBO {
Matrices matrices;
vec4 color;
} ubo;
layout (location = 0) out vec4 outColor;
out gl_PerVertex {
vec4 gl_Position;
};
void main() {
outColor = ubo.color;
// outPosition = vec3(ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inPos.xyz, 1.0));
gl_Position = ubo.matrices.projection[PushConstant.pass] * ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inPos.xyz, 1.0);
}

View File

@ -1,23 +0,0 @@
#version 450
layout (binding = 1) uniform sampler3D samplerColor;
layout (location = 0) in vec2 inUv;
layout (location = 1) in vec4 inColor;
layout (location = 2) in vec3 inNormal;
layout (location = 3) in vec3 inPosition;
layout (location = 0) out vec4 outAlbedoSpecular;
layout (location = 1) out vec4 outNormal;
layout (location = 2) out vec4 outPosition;
layout (binding = 2) uniform UBO {
float slice;
} ubo;
void main() {
outAlbedoSpecular.rgb = vec3(texture(samplerColor, vec3(inUv,ubo.slice)).r);
outAlbedoSpecular.a = 1;
outNormal = vec4(inNormal,1);
outPosition = vec4(inPosition,1);
}

View File

@ -1,295 +0,0 @@
#version 450
layout (local_size_x = 32, local_size_y = 32) in;
layout (constant_id = 0) const uint LIGHTS = 16;
layout (constant_id = 1) const uint EYES = 2;
layout (binding = 0, rgba8) uniform writeonly image2D resultImage[EYES];
#define EPSILON 0.0001
#define MAXLEN 1000.0
layout( push_constant ) uniform PushBlock {
uint marchingSteps;
uint rayBounces;
float shadowFactor;
float reflectionStrength;
float reflectionFalloff;
} PushConstant;
struct Ray {
vec3 origin;
vec3 direction;
};
struct Result {
vec3 color;
float t;
int id;
};
struct Light {
vec3 position;
float radius;
vec3 color;
float power;
vec2 type;
vec2 padding;
mat4 view;
mat4 projection;
};
struct State {
vec3 viewPosition;
Ray ray;
Result result;
} state;
struct Fog {
vec2 range;
vec2 padding;
vec4 color;
};
layout (binding = 1) uniform UBO {
mat4 matrices[2];
vec4 ambient;
Fog fog;
Light lights[LIGHTS];
} ubo;
struct Shape {
vec4 values;
vec4 albedoSpecular;
int type;
};
layout (std140, binding = 2) buffer Shapes {
Shape shapes[];
};
void reflectRay(inout vec3 rayD, in vec3 normal) {
rayD = rayD + 2.0 * -dot(normal, rayD) * normal;
}
// Lighting =========================================================
float lightDiffuse(vec3 normal, vec3 lightDir) {
return clamp(dot(normal, lightDir), 0.1, 1.0);
}
float lightSpecular(vec3 normal, vec3 lightDir, float specularFactor) {
vec3 viewVec = normalize(state.viewPosition);
vec3 halfVec = normalize(lightDir + viewVec);
return pow(clamp(dot(normal, halfVec), 0.0, 1.0), specularFactor);
}
// Sphere ===========================================================
float sphereIntersect(in vec3 rayO, in vec3 rayD, in Shape shape ) {
vec3 oc = rayO - shape.values.xyz;
float b = 2.0 * dot(oc, rayD);
float c = dot(oc, oc) - shape.values.w * shape.values.w;
float h = b*b - 4.0*c;
if (h < 0.0) return -1.0;
float t = (-b - sqrt(h)) / 2.0;
return t;
}
vec3 sphereNormal(in vec3 position, in Shape shape) {
return (position - shape.values.xyz) / shape.values.w;
}
float sphereSDF( vec3 position, in Shape shape ) {
return length(position - shape.values.xyz) - shape.values.w;
}
// Plane ===========================================================
float planeIntersect(in vec3 rayO, in vec3 rayD, in Shape shape) {
float d = dot(rayD, shape.values.xyz);
if (d == 0.0) return 0.0;
float t = -(shape.values.w + dot(rayO, shape.values.xyz)) / d;
return t < 0.0 ? 0.0 : t;
}
vec3 planeNormal(in vec3 position, in Shape shape) {
return shape.values.xyz;
}
float planeSDF( vec3 position, in Shape shape ) {
return dot( position, shape.values.xyz ) + shape.values.w;
}
// Generic =========================================================
float shapeIntersect(in vec3 rayO, in vec3 rayD, in Shape shape) {
if ( shape.type == 1 ) return sphereIntersect( rayO, rayD, shape );
if ( shape.type == 2 ) return planeIntersect( rayO, rayD, shape );
return 0.0;
}
vec3 shapeNormal( vec3 position, in Shape shape ) {
if ( shape.type == 1 ) return sphereNormal(position, shape);
if ( shape.type == 2 ) return planeNormal(position, shape);
return vec3(0.0);
}
float shapeSDF( vec3 position, in Shape shape ) {
if ( shape.type == 1 ) return sphereSDF(position, shape);
if ( shape.type == 2 ) return planeSDF(position, shape);
return MAXLEN;
}
// Intersect =======================================================
int intersect(in vec3 rayO, in vec3 rayD, inout float resT) {
int id = -1;
for (int i = 0; i < shapes.length(); i++) {
Shape shape = shapes[i];
float tShape = shapeIntersect(rayO, rayD, shape);
if ((tShape > EPSILON) && (tShape < resT)) {
id = i;
resT = tShape;
}
}
return id;
}
float calcShadow(in vec3 rayO, in vec3 rayD, in int objectID, inout float resT) {
for (int i = 0; i < shapes.length(); i++) {
if ( i == objectID ) continue;
Shape shape = shapes[i];
float tShape = shapeIntersect(rayO, rayD, shape);
if ((tShape > EPSILON) && (tShape < resT)) {
resT = tShape;
return PushConstant.shadowFactor;
}
}
return 1.0;
}
// Marching ========================================
int intersectMarch( in vec3 rayO, in vec3 rayD, inout float resT ) {
resT = 0;
for (int i = 0; i < PushConstant.marchingSteps; ++i) {
vec3 position = resT * rayD + rayO;
float tNearest = MAXLEN;
int objectID = -1;
for ( int j = 0; j < shapes.length(); ++j ) {
Shape shape = shapes[j];
float tShape = shapeSDF(position, shape);
// if ((tShape > EPSILON) && (tShape < tNearest)) {
if ( tShape < tNearest ) {
objectID = j;
tNearest = tShape;
}
}
if (tNearest < EPSILON) {
return objectID;
}
if (resT > MAXLEN) break;
resT += tNearest;
}
resT = MAXLEN;
return -1;
}
float calcShadowMarch( in vec3 rayO, in vec3 rayD, in int objectID, inout float resT ) {
float distance = resT;
resT = 0;
for (int i = 0; i < PushConstant.marchingSteps; ++i) {
vec3 position = resT * rayD + rayO;
float tNearest = distance;
int objectID = -1;
for ( int j = 0; j < shapes.length(); ++j ) {
if ( j == objectID ) continue;
Shape shape = shapes[j];
float tShape = shapeSDF(position, shape);
// if ((tShape > EPSILON) && (tShape < tNearest)) {
if ( tShape < tNearest ) {
objectID = j;
tNearest = tShape;
}
}
if (tNearest < EPSILON) {
return PushConstant.shadowFactor;
}
if (resT > distance) break;
resT += tNearest;
}
resT = distance;
return 1.0;
}
void fog(inout vec3 i, in float t ) {
/*
vec3 fogColor = ubo.ambient.rgb;
i = mix(i, fogColor.rgb, clamp(sqrt(t*t)/20.0, 0.0, 1.0));
*/
if ( ubo.fog.range.x == 0 || ubo.fog.range.y == 0 ) return;
vec3 color = ubo.fog.color.rgb;
float inner = ubo.fog.range.x, outer = ubo.fog.range.y;
float factor = (t - inner) / (outer - inner);
factor = clamp( factor, 0.0, 1.0 );
i = mix(i.rgb, color, factor);
}
Result renderScene(inout vec3 rayO, inout vec3 rayD ) {
Result result;
result.color = vec3(0.0);
result.t = MAXLEN;
result.id = PushConstant.marchingSteps > 0 ? intersectMarch(rayO, rayD, result.t) : intersect(rayO, rayD, result.t);
if (result.id == -1) return result;
Shape shape = shapes[result.id];
vec3 position = rayO + result.t * rayD;
vec3 normal = shapeNormal( position, shape );
for ( uint i = 0; i < LIGHTS; ++i ) {
Light light = ubo.lights[i];
if ( light.radius <= EPSILON ) continue;
if ( light.power <= EPSILON ) continue;
vec3 L = light.position - position;
float dist = length(L);
vec3 D = normalize(L);
float attenuation = light.radius / (pow(dist, 2.0) + 1.0);;
attenuation = 1;
// if ( dist > light.radius ) continue;
vec4 albedoSpecular = shape.albedoSpecular;
float d_dot = lightDiffuse(normal, D);
float s_factor = lightSpecular(normal, D, albedoSpecular.a);
vec3 color = (light.color * albedoSpecular.rgb) * d_dot + s_factor;
// Shadows
float tShadow = dist;
float shadowed = 1;
if ( PushConstant.shadowFactor < 1.0 )
shadowed = PushConstant.marchingSteps > 0 ? calcShadowMarch(position, D, result.id, tShadow) : calcShadow(position, D, result.id, tShadow);
result.color += color * light.power * attenuation * shadowed;
}
// Fog
// fog(t, result.color);
// Reflect ray for next render pass
reflectRay(rayD, normal);
rayO = position;
return result;
}
void main() {
for ( int pass = 0; pass < EYES; ++pass ) {
{
vec2 uv = vec2(gl_GlobalInvocationID.xy) / imageSize(resultImage[pass]);
vec4 near4 = ubo.matrices[pass] * (vec4(2.0 * uv - 1.0, -1.0, 1.0));
vec4 far4 = ubo.matrices[pass] * (vec4(2.0 * uv - 1.0, 1.0, 1.0));
vec3 near3 = near4.xyz / near4.w;
vec3 far3 = far4.xyz / far4.w;
state.viewPosition = near3;
state.ray.origin = near3;
state.ray.direction = normalize( far3 - near3 );
}
// Basic color path
state.result = renderScene(state.ray.origin, state.ray.direction);
vec3 finalColor = state.result.color;
// Reflection
float reflectionStrength = PushConstant.reflectionStrength;
for (int i = 0; i < PushConstant.rayBounces; i++) {
Result result = renderScene(state.ray.origin, state.ray.direction);
vec3 reflectionColor = result.color;
finalColor = (1.0 - reflectionStrength) * finalColor + reflectionStrength * mix(reflectionColor, finalColor, 1.0 - reflectionStrength);
reflectionStrength *= PushConstant.reflectionFalloff;
}
imageStore(resultImage[pass], ivec2(gl_GlobalInvocationID.xy), vec4(finalColor, 1.0));
}
}

View File

@ -1,20 +0,0 @@
#version 450
layout (binding = 1) uniform sampler2D samplerColor;
layout (location = 0) in vec2 inUv;
layout (location = 1) in vec4 inColor;
layout (location = 2) in vec3 inNormal;
layout (location = 3) in vec3 inPosition;
layout (location = 0) out vec4 outAlbedoSpecular;
layout (location = 1) out vec4 outNormal;
layout (location = 2) out vec4 outPosition;
void main() {
outAlbedoSpecular = texture(samplerColor, inUv);
// outAlbedoSpecular.rgb *= inColor.rgb;
outAlbedoSpecular.a = 1;
outNormal = vec4(inNormal,1);
outPosition = vec4(inPosition,1);
}

View File

@ -1,51 +0,0 @@
#version 450
layout (constant_id = 0) const uint PASSES = 6;
layout (location = 0) in vec3 inPos;
layout (location = 1) in vec2 inUv;
layout (location = 2) in vec3 inNormal;
layout (location = 3) in uint inColor;
layout( push_constant ) uniform PushBlock {
uint pass;
uint draw;
} PushConstant;
struct Matrices {
mat4 model;
mat4 view[PASSES];
mat4 projection[PASSES];
};
layout (binding = 0) uniform UBO {
Matrices matrices;
vec4 color;
} ubo;
layout (location = 0) out vec2 outUv;
layout (location = 1) out vec4 outColor;
layout (location = 2) out vec3 outNormal;
layout (location = 3) out vec3 outPosition;
out gl_PerVertex {
vec4 gl_Position;
};
void main() {
outUv = inUv;
// outColor = ubo.color;
outPosition = vec3(ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inPos.xyz, 1.0));
outNormal = vec3(ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inNormal.xyz, 0.0));
outNormal = normalize(outNormal);
outColor.a = (inColor >> 24u) & 0xFF;
outColor.b = (inColor >> 16u) & 0xFF;
outColor.g = (inColor >> 8u) & 0xFF;
outColor.r = (inColor ) & 0xFF;
outColor.rgb /= 256.0;
outColor.a = 0.5;
gl_Position = ubo.matrices.projection[PushConstant.pass] * ubo.matrices.view[PushConstant.pass] * ubo.matrices.model * vec4(inPos.xyz, 1.0);
}

View File

@ -1,11 +0,0 @@
#version 450
layout (binding = 0) uniform sampler2D samplerColor;
layout (location = 0) in vec2 inUV;
layout (location = 0) out vec4 outFragColor;
void main() {
vec4 sampledColor = texture(samplerColor, inUV);
if ( sampledColor.r <= 0.000001 && sampledColor.g <= 0.000001 && sampledColor.b <= 0.000001 ) discard;
outFragColor = sampledColor;
}

View File

@ -1,14 +0,0 @@
#version 450
layout (location = 0) out vec2 outUV;
out gl_PerVertex
{
vec4 gl_Position;
};
void main()
{
outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
gl_Position = vec4(outUV * 2.0f + -1.0f, 0.0f, 1.0f);
}

View File

@ -1,266 +0,0 @@
#include "../main.h"
#include <uf/utils/window/window.h>
#include <uf/utils/io/iostream.h>
#include <uf/utils/image/image.h>
#include <uf/utils/audio/audio.h>
#include <uf/spec/terminal/terminal.h>
#include <uf/utils/hook/hook.h>
#include <uf/utils/thread/thread.h>
#include <uf/utils/renderer/renderer.h>
bool client::ready = false;
bool client::terminated = false;
uf::Window client::window;
uf::Serializer client::config;
void client::initialize() {
uf::IoStream::ncurses = true;
uf::renderer::device.window = &client::window;
ext::load();
#if 1
client::config = ext::config;
#else
/* Initialize config */ {
struct {
uf::Serializer ext;
uf::Serializer fallback;
} config;
/* Get configuration */ {
config.ext = ext::config.serialize();
}
/* Merge */ {
client::config = config.ext;
client::config.merge( config.fallback, true );
}
}
#endif
/* Initialize window */ {
// Window size
pod::Vector2i size; {
size.x = client::config["window"]["size"]["x"].as<size_t>();
size.y = client::config["window"]["size"]["y"].as<size_t>();
// request system size
if ( size.x <= 0 && size.y <= 0 ) {
auto resolution = client::window.getResolution();
client::config["window"]["size"]["x"] = (size.x = resolution.x);
client::config["window"]["size"]["y"] = (size.y = resolution.y);
}
}
// Window title
uf::String title; {
title = client::config["window"]["title"].as<std::string>();
}
// Terminal window;
spec::terminal.setVisible( client::config["window"]["terminal"]["visible"].as<bool>() );
// Ncurses
uf::IoStream::ncurses = client::config["window"]["terminal"]["ncurses"].as<bool>();
// Window's context settings
uf::renderer::settings::width = size.x;
uf::renderer::settings::height = size.y;
client::window.create( size, title );
#if !UF_ENV_DREAMCAST
// Set refresh rate
ext::config["window"]["refresh rate"] = client::window.getRefreshRate();
// Miscellaneous
client::window.setVisible(client::config["window"]["visible"].as<bool>());
client::window.setCursorVisible(client::config["window"]["cursor"]["visible"].as<bool>());
client::window.setKeyRepeatEnabled(client::config["window"]["keyboard"]["repeat"].as<bool>());
// client::window.centerWindow();
// client::window.setPosition({0, 0});
// client::window.setMouseGrabbed(true);
/* Set Icon */ if ( client::config["window"]["icon"].is<std::string>() ) {
uf::Image icon;
icon.open(client::config["window"]["icon"].as<std::string>());
client::window.setIcon({(int) icon.getDimensions().x, (int) icon.getDimensions().y}, ((uint8_t*)icon.getPixelsPtr()));
}
client::window.setTitle(title); {
uf::Serializer json;
std::string hook = "window:Title.Changed";
json["type"] = hook;
json["invoker"] = "os";
json["window"]["title"] = std::string(title);
uf::hooks.call( hook, json );
}
#endif
/*
uf::hooks.shouldPreferReadable();
if ( client::config["engine"]["hook"]["mode"] == "Readable" ) {
}
*/
}
#if UF_USE_OPENAL
/* Initialize OpenAL */ {
if ( !ext::oal.initialize() ) {
std::cerr << "[ERROR] AL failed to initialize!" << std::endl;
std::exit(EXIT_SUCCESS);
return;
}
}
#endif
/* Initialize hooks */ {
// if ( client::config["engine"]["hook"]["mode"] == "Both" || client::config["engine"]["hook"]["mode"] == "Readable" ) {
uf::hooks.addHook( "window:Mouse.CursorVisibility", [&](const ext::json::Value& json){
client::window.setCursorVisible(json["state"].as<bool>());
client::window.setMouseGrabbed(!json["state"].as<bool>());
client::config["mouse"]["visible"] = json["state"].as<bool>();
client::config["window"]["mouse"]["center"] = !json["state"].as<bool>();
});
uf::hooks.addHook( "window:Mouse.Lock", [&](const ext::json::Value& json){
if ( client::window.hasFocus() ) {
client::window.setMousePosition(client::window.getSize()/2);
}
});
uf::hooks.addHook( "window:Closed", [&](const ext::json::Value& json){
client::ready = false;
// std::exit(EXIT_SUCCESS);
} );
uf::hooks.addHook( "window:Title.Changed", [&](const ext::json::Value& json){
if ( json["invoker"] != "os" ) {
if ( !ext::json::isObject( json["window"] ) ) return;
uf::String title = json["window"]["title"].as<std::string>();
client::window.setTitle(title);
}
} );
uf::hooks.addHook( "window:Resized", [&](const ext::json::Value& json){
pod::Vector2i size; {
size.x = json["window"]["size"]["x"].as<size_t>();
size.y = json["window"]["size"]["y"].as<size_t>();
}
if ( json["invoker"] != "os" ) {
client::window.setSize(size);
}
// Update viewport
if ( !ext::json::isArray( client::config["engine"]["ext"]["vulkan"]["framebuffer"]["size"] ) ) {
float scale = client::config["engine"]["ext"]["vulkan"]["framebuffer"]["size"].is<double>() ? client::config["engine"]["ext"]["vulkan"]["framebuffer"]["size"].as<float>() : 1;
uf::renderer::settings::width = size.x * scale;
uf::renderer::settings::height = size.y * scale;
}
uf::renderer::states::resized = true;
} );
/*
}
else if ( client::config["engine"]["hook"]["mode"] == "Both" || client::config["engine"]["hook"]["mode"] == "Optimal" ) {
uf::hooks.addHook( "window:Closed", [&](const uf::OptimalHook::argument_t& userdata)->uf::OptimalHook::return_t{
client::ready = false;
std::exit(EXIT_SUCCESS);
return NULL;
} );
uf::hooks.addHook( "window:Title.Changed", [&](const uf::OptimalHook::argument_t& userdata)->uf::OptimalHook::return_t{
// Hook information
struct Hook {
std::string type;
std::string invoker;
struct {
std::string title;
} window;
};
const Hook& hook = uf::userdata::get<Hook>(userdata);
if ( hook.invoker != "os" ) {
uf::String title = hook.window.title;
client::window.setTitle(title);
}
return NULL;
} );
uf::hooks.addHook( "window:Resized", [&](const uf::OptimalHook::argument_t& userdata)->uf::OptimalHook::return_t{
// Hook information
struct Hook {
std::string type;
std::string invoker;
struct {
pod::Vector2i size;
} window;
};
const Hook& hook = uf::userdata::get<Hook>(userdata);
if ( hook.invoker != "os" ) {
client::window.setSize(hook.window.size);
}
// Update viewport
return NULL;
} );
}
*/
}
#if !UF_ENV_DREAMCAST
if ( client::config["window"]["mode"].as<std::string>() == "fullscreen" ) client::window.switchToFullscreen();
if ( client::config["window"]["mode"].as<std::string>() == "borderless" ) client::window.switchToFullscreen( true );
#endif
client::ready = true;
}
void client::tick() {
// uf::hooks.call("system:Tick");
client::window.pollEvents();
// call mouse move
// query lock
if ( client::window.hasFocus() && client::config["window"]["mouse"]["center"].as<bool>() ) {
auto previous = client::window.getMousePosition();
client::window.setMousePosition(client::window.getSize()/2);
auto current = client::window.getMousePosition();
auto size = client::window.getSize();
uf::Serializer payload;
payload["invoker"] = "client";
payload["mouse"]["delta"]["x"] = previous.x - current.x;
payload["mouse"]["delta"]["y"] = previous.y - current.y;
payload["mouse"]["position"]["x"] = current.x;
payload["mouse"]["position"]["y"] = current.y;
payload["mouse"]["size"]["x"] = size.x;
payload["mouse"]["size"]["y"] = size.y;
payload["mouse"]["state"] = "???";
payload["type"] = "window:Mouse.Moved";
uf::hooks.call("window:Mouse.Moved", payload);
}
/*
{
"invoker" : "os",
"mouse" :
{
"delta" :
{
"x" : -17,
"y" : -12
},
"position" :
{
"x" : 371,
"y" : 276
},
"size" :
{
"x" : 800,
"y" : 600
},
"state" : "???"
},
"type" : "window:Mouse.Moved"
}
*/
}
void client::render() {
client::window.display();
}
void client::terminate() {
/* Close Threads */ {
uf::thread::terminate();
}
client::window.terminate();
#if UF_USE_BULLET
if ( !ext::oal.terminate() ) {
std::cerr << "[ERROR] AL failed to terminate!" << std::endl;
std::exit(EXIT_SUCCESS);
return;
}
#endif
}

View File

@ -1,20 +0,0 @@
#if 0
#include <uf/ext/ext.h>
#include <uf/ext/opengl/opengl.h>
#include <uf/ext/opengl/commands.h>
int main(int argc, char **argv) {
ext::opengl::settings::width = 640;
ext::opengl::settings::height = 480;
ext::opengl::initialize();
while ( true ) {
ext::opengl::tick();
ext::opengl::render();
}
ext::opengl::destroy();
return 0;
}
#endif

View File

@ -1,79 +0,0 @@
#include "main.h"
#include <uf/utils/io/iostream.h>
#include <uf/utils/time/time.h>
#include <uf/utils/mempool/mempool.h>
#if UF_NO_EXCEPTIONS
#define HANDLE_EXCEPTIONS 0
#else
#define HANDLE_EXCEPTIONS 1
#endif
int main(int argc, char** argv){
for ( size_t i = 0; i < argc; ++i ) {
char* c_str = argv[i];
std::string string(argv[i]);
ext::arguments.emplace_back(string);
}
std::atexit([]{
uf::iostream << "Termination via std::atexit()!" << "\n";
client::terminated = !(client::ready = ext::ready = false);
});
client::initialize();
ext::initialize();
// For Multithreaded initialization
while ( !client::ready || !ext::ready ) {
static uf::Timer<long long> timer(false);
static double next = 1;
if ( !timer.running() ) timer.start();
if ( timer.elapsed().asDouble() >= next ) {
uf::iostream << "Waiting for " << ( client::ready ? "client" : "extension / engine" ) << " to initialize... Retrying in " << next << " seconds." << "\n";
next *= 2;
}
}
while ( client::ready && ext::ready ) {
#if HANDLE_EXCEPTIONS
try {
#endif
static bool first = false; if ( !first ) { first = true;
uf::Serializer json;
std::string hook = "window:Resized";
json["type"] = hook;
json["invoker"] = "ext";
json["window"]["size"]["x"] = client::config["window"]["size"]["x"];
json["window"]["size"]["y"] = client::config["window"]["size"]["y"];
uf::hooks.call(hook, json);
}
client::tick();
ext::tick();
client::render();
ext::render();
#if HANDLE_EXCEPTIONS
} catch ( std::runtime_error& e ) {
uf::iostream << "RUNTIME ERROR: " << e.what() << "\n";
break;
} catch ( std::exception& e ) {
uf::iostream << "EXCEPTION ERROR: " << e.what() << "\n";
throw e;
} catch ( bool handled ) {
if (!handled) uf::iostream << "UNHANDLED ERROR: " << "???" << "\n";
} catch ( ... ) {
uf::iostream << "UNKNOWN ERROR: " << "???" << "\n";
}
#endif
}
if ( !client::terminated ) {
uf::iostream << "Natural termination!" << "\n";
}
ext::terminate();
client::terminate();
return 0;
}

View File

@ -1,18 +0,0 @@
#pragma once
#include <uf/ext/ext.h>
#include <uf/utils/window/window.h>
#include <uf/utils/serialize/serializer.h>
#include <uf/utils/thread/thread.h>
namespace client {
extern bool ready;
extern bool terminated;
extern uf::Window window;
extern uf::Serializer config;
void initialize();
void tick();
void render();
void terminate();
}

BIN
data/audio/footstep/1.ogg Normal file

Binary file not shown.

BIN
data/audio/footstep/2.ogg Normal file

Binary file not shown.

BIN
data/audio/ui/ding.ogg Normal file

Binary file not shown.

BIN
data/audio/ui/hover.ogg Normal file

Binary file not shown.

Binary file not shown.

BIN
data/audio/ui/main menu.ogg Normal file

Binary file not shown.

Binary file not shown.

BIN
data/audio/ui/menu exit.ogg Normal file

Binary file not shown.

BIN
data/audio/ui/menu flip.ogg Normal file

Binary file not shown.

BIN
data/audio/ui/menu open.ogg Normal file

Binary file not shown.

BIN
data/audio/ui/register.ogg Normal file

Binary file not shown.

BIN
data/audio/ui/select.ogg Normal file

Binary file not shown.

BIN
data/audio/ui/turn.ogg Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

166
data/config.json Normal file
View File

@ -0,0 +1,166 @@
{
"engine": {
"scenes": {
"start": "McDonalds",
"lights": {
"max": 256,
"update threshold": 6,
"shadow threshold": 20
},
"textures": {
"max": 256
}
},
"ext": {
"vulkan": {
"validation": {
"enabled": false,
"filters": [
"MessageID = 0x4dae5635", // UNASSIGNED-CoreValidation-DrawState-InvalidImageLayout (false positive for cubemaps)
"MessageID = 0x71500fba", // VUID-vkDestroyDevice-device-00378 (don't care about a clean cleanup)
"MessageID = 0x609a13b", // UNASSIGNED-CoreValidation-Shader-OutputNotConsumed (from depth-only calls)
"MessageID = 0x23e43bb7" // UNASSIGNED-CoreValidation-Shader-InputNotProduced (from depth-only calls)
// "MessageID = 0xe91b58a0" // VUID-vkCmdDrawIndexed-None-02686 (?)
]
},
"framebuffer": {
"size": 0.8,
// "size": [ 640, 480, "NEAREST" ],
// "size": [ 256, 224, "NEAREST" ],
// "msaa": 16
"msaa": 4
},
"experimental": {
"rebuild on tick begin": false,
"wait on render end": false,
"individual pipelines": true,
"multithreaded command recording": true,
"deferred mode": "",
// "deferred mode": "deferredSampling",
"deferred reconstruct position": true,
"deferred alias output to swapchain": true,
"hdr": false
},
"formats": {
"depth": "D32_SFLOAT",
"color": "R8G8B8A8_UNORM", // "R32G32B32A32_SFLOAT",
"normal": "R16G16B16A16_SFLOAT",
"position": "R16G16B16A16_SFLOAT"
},
"features": [
"independentBlend",
"deviceCoherentMemory",
"robustBufferAccess",
"samplerAnisotropy",
"sampleRateShading",
"nullDescriptor"
],
"extensions": {
"instance": [
"VK_KHR_get_physical_device_properties2",
"VK_KHR_get_surface_capabilities2"
],
"device": [
]
}
},
"lua": {
"main": "/main.lua",
"modules": {
"json": "/json.lua"
}
},
"vr" : {
"enable" : false,
"manifest": "./data/openvr_manifest.json",
"swap eyes": false,
"dominant eye": 0,
"scale": 1
},
"ultralight": {
"enabled": true,
"scale": 1.5
},
"bullet": {
"iterations": 1,
"substeps": 12,
"timescale": 1,
"multithreaded": false,
"debug draw": {
"enabled": false,
"rate": 1.0
}
},
"discord": {
"enabled": false
}
},
"audio": {
"mute": false
},
"memory pool": {
"globalOverride": false,
"subPools": true,
"size": "512 MiB",
"pools": {
"entity": "128 MiB",
"userdata": "128 MiB",
"component": "128 MiB"
}
},
"hook" : {
"mode" : "Readable"
},
"render modes": {
"gui": true,
"deferred": true,
"stereo deferred": false,
"multiview stereo deferred": false
},
"limiters": {
"deltaTime": 10,
"framerate": "auto"
},
"threads": {
"workers" : "auto",
"frame limiter": "auto"
},
"debug": {
"framerate": {
"print": false,
"every": 1
},
"garbage collection": {
"enabled": true,
"mode": 1,
"rate": 16,
"announce": true
},
"entity": {
"delete children on destroy": false,
"delete components on destroy": false
}
}
},
"window" : {
"terminal" : {
"ncurses" : false,
"visible" : true
},
"keyboard" : {
"repeat" : false
},
"cursor" : {
"visible" : true,
"center" : false
},
"mode" : "windowed", // fullscreen, borderless, windowed
"icon" : "./data/textures/icon.png",
"size" : {
"x" : 960,
"y" : 540
},
"title" : "Grimgram",
"visible" : true
}
}

8
data/entities/gui.json Normal file
View File

@ -0,0 +1,8 @@
{
"name": "Gui Manager",
"type": "Object",
"behaviors": [
"GuiManagerBehavior"
],
"ignore": false
}

View File

@ -0,0 +1,23 @@
{
"name": "HUD",
"type": "Gui",
"ignore": false,
"assets": [
"./scripts/hud.lua"
],
"system": {
"clickable": false,
"hoverable": false
},
"transform": {
"position": [ 0, 0, 0 ],
"rotation": {
"axis": [ 0, 0, 1 ],
"angle": 0
},
"scale": [ 16, 16, 16 ]
},
"metadata": {
}
}

View File

@ -0,0 +1,36 @@
{
"name": "HUD Overlay",
"type": "Gui",
"ignore": false,
"assets": [
{ "filename": "./textures/mp.png", "hash": "68e7c459f9aecd6815ff7df1e2eefa82db60a23713b0134f0bfc15d82f55453d" }
// { "filename": "./textures/ss2.png" }
],
"system": {
"clickable": false,
"hoverable": false
},
"transform": {
"position": [ 0, 0, 0 ],
"rotation": {
"axis": [ 0, 0, 1 ],
"angle": 0
},
// "scale": [ 1.7776, -1, -1 ]
"scale": [ 1, 1, 1 ]
},
"metadata": {
"uv": [ 0, 0, 1, 1 ],
// "color": [ 0.8, 0.8, 1, 1 ],
// "color": [ 0.416, 0.573, 0.667, 1 ],
"color": [ 1, 1, 1, 1 ],
"location": "",
"scaling": "relative",
// "depth": 0.1,
// "alpha": 0.5,
"alpha": 0.75,
"mode": 1,
"gui layer": true,
"only model": true
}
}

View File

@ -0,0 +1,154 @@
local scene = entities.currentScene()
local controller = entities.controller()
local metadata = ent:getComponent("Metadata")
local masterdata = scene:getComponent("Metadata")
local visorLayers = 5
local children = {}
for i=1, visorLayers do
children[i] = ent:loadChild("./overlay.json",true)
end
local soundEmitter = ent:loadChild("./sound.json",true)
local timer = Timer.new()
if not timer:running() then timer:start() end
Static = {
values = {},
get = function( obj )
if obj == nil then
obj = scene
end
if Static.values[""..obj:uid()] == nil then
Static.values[""..obj:uid()] = {}
end
return Static.values[""..obj:uid()]
end
}
local lerper = {
to = Quaternion(0,0,0,1),
from = Quaternion(0,0,0,1),
a = 0
}
local rotate = function( delta )
delta.x = delta.x * 0.1
delta.y = delta.y * 0.1
local transform = ent:getComponent("Transform")
local rotation = {
x = Quaternion.axisAngle( Vector3f(0, 1, 0), delta.x ),
y = Quaternion.axisAngle( Vector3f(1, 0, 0), delta.y )
}
lerper.a = 0
lerper.from = Quaternion.multiply( transform.orientation, rotation.x:multiply(rotation.y) )
transform.orientation = lerper.from
for k, obj in pairs(children) do
obj:getComponent("Transform").orientation = transform.orientation
end
end
local windowSize = masterdata["system"]["config"]["window"]["size"];
local entTransform = ent:getComponent("Transform")
entTransform.scale.x = entTransform.scale.x * windowSize.x / windowSize.y;
for k, obj in pairs(children) do
local transform = obj:getComponent("Transform")
transform.scale = entTransform.scale;
transform.position.z = -0.5 + ((k-1) * 0.005)
end
ent:addHook( "window:Resized", function( payload )
if entTransform.scale.y == entTransform.scale.z then
entTransform.scale.x = entTransform.scale.y * payload["window"]["size"]["x"] / payload["window"]["size"]["y"];
end
for k, obj in pairs(children) do
local transform = obj:getComponent("Transform")
transform.scale = entTransform.scale;
end
end )
ent:addHook( "controller:Camera.Rotated", function( payload )
rotate( {
x = -payload.angle.yaw,
y = -payload.angle.pitch
})
--[[
local transform = ent:getComponent("Transform")
lerper.a = 0
local counterOrientation = Quaternion( payload.delta[1], payload.delta[2], payload.delta[3], payload.delta[4] ):inverse()
lerper.from = Quaternion.multiply( transform.orientation, counterOrientation )
transform.orientation = lerper.from
for k, obj in pairs(children) do
obj:getComponent("Transform").orientation = transform.orientation
end
]]
end )
--[[
ent:addHook( "window:Mouse.Moved", function( payload )
if payload.invoker ~= "client" then return end
local delta = payload.mouse.delta
local size = payload.mouse.size
if delta == nil or size == nil then return end
if delta.x == 0 or delta.y == 0 then return end
delta.x = -delta.x / size.x
delta.y = -delta.y / size.y
rotate( delta )
end )
]]
ent:bind( "tick", function(self)
for k, obj in pairs(children) do
local metadata = obj:getComponent("Metadata")
local glow = math.sin(time.current()) * 0.5 + 0.5 -- constrained to [0,1]
glow = glow * 0.2 + 0.65 -- constrained to [0.65, 0.85]
metadata["alpha"] = glow
obj:setComponent("Metadata", metadata)
end
local controllerTransform = controller:getComponent("Transform")
local controllerCamera = controller:getComponent("Camera")
local controllerCameraTransform = controllerCamera:getTransform()
local transform = ent:getComponent("Transform")
local speed = 2.5
if lerper.a == 1 then return end
lerper.a = lerper.a + time.delta() * speed
if lerper.a > 1 then lerper.a = 1 end
transform.orientation = lerper.from:slerp( lerper.to, lerper.a )
local orientation = transform.orientation
for k, obj in pairs(children) do
local transform = obj:getComponent("Transform")
transform.orientation = orientation
transform.model = controllerCamera:getProjection() * Matrix4f.translate( transform.position ) * transform.orientation:matrix() * Matrix4f.scale( transform.scale ) --Matrix4f.scale( Vector3f( 1.7776 * 2, 2, 2 ) )
end
end )
--[[
controller:callHook( "object:UpdateMetadata.%UID%", {
path = "overlay.position",
value = {
[1] = position.x,
[2] = position.y,
[3] = position.z
}
} )
controller:callHook( "object:UpdateMetadata.%UID%", {
path = "overlay.orientation",
value = {
[1] = orientation.x,
[2] = orientation.y,
[3] = orientation.z,
[4] = orientation.w
}
} )
]]

View File

@ -0,0 +1,38 @@
{
"type": "Object",
"name": "Sound Emitter",
"ignore": false,
"assets": [
],
"behaviors": [
"SoundEmitterBehavior"
],
"transform": {
"position": [ 0, 0, 0 ],
"rotation": {
"axis": [ 0, 1, 0 ],
"angle": 0
},
"scale": [ 1, 1, 1 ]
},
"system": {
"hot reload": {
"enabled": true
},
"defaults": {
"render": true,
"asset load": true
},
"load": {
"ignore": true
}
},
"metadata": {
"audio": {
"spatial": false,
"loop": false,
"volume": "sfx",
"rolloffFactor": 2
}
}
}

View File

@ -0,0 +1,25 @@
{
"name": "Menu: Circle Inner",
"type": "Gui",
"ignore": false,
"transform": {
"position": [ 0.86, 0.86, 0 ],
"rotation": {
"axis": [ 1, 0, 0 ],
"angle": 0
},
"scale": [ 1, 1, 1 ]
},
"clickable": false,
"hoverable": false,
"metadata": {
"uv": [ 0, 0, 1, 1 ],
"color": [ 1, 1, 1, 0.8 ],
"location": "",
"scaling": [ 0.64, 1 ],
"mode": "flat"
},
"assets": [
"https://cdn..xyz//unity/Android/sprite/sprite_magiccircle_in2.png"
]
}

View File

@ -0,0 +1,25 @@
{
"name": "Menu: Circle Outer",
"type": "Gui",
"ignore": false,
"transform": {
"position": [ 0.86, 0.86, 0 ],
"rotation": {
"axis": [ 1, 0, 0 ],
"angle": 0
},
"scale": [ 1, 1, 1 ]
},
"clickable": false,
"hoverable": true,
"metadata": {
"uv": [ 0, 0, 1, 1 ],
"color": [ 1, 1, 1, 0.8 ],
"location": "",
"scaling": [ 0.64, 1 ],
"mode": "flat"
},
"assets": [
"https://cdn..xyz//unity/Android/sprite/sprite_magiccircle_out2.png"
]
}

View File

@ -0,0 +1,26 @@
{
"name": "Menu: Main Text",
"type": "Gui",
"ignore": false,
"transform": {
"position": [ -0.922623, -0.854923, 0 ],
"rotation": {
"axis": [ 0, 0, 1 ],
"angle": 0
},
"scale": [ 1, 1, 1 ]
},
"metadata": {
"uv": [ 0, 0, 1, 1 ],
"location": "",
"scaling": "relative",
"debug": {
"moveable": false
},
"text settings": {
"scale": 2,
"font": "Coolvetica.ttf",
"string": "Grimgram"
}
}
}

View File

@ -0,0 +1,30 @@
{
"name": "Gui: Menu",
"type": "Gui",
"ignore": false,
"assets": [
"./textures/menu.png",
"./scripts/menu.lua"
],
"system": {
"clickable": true,
"hoverable": true
},
"transform": {
"position": [ 0, 0, 0 ],
"rotation": {
"axis": [ 0, 0, 1 ],
"angle": 0
},
"scale": [ 1, 1, 1 ]
},
"metadata": {
"experimental": true,
"uv": [ 0, 0, 1, 1 ],
"color": [ 1, 1, 1, 1 ],
"location": "",
"scaling": "relative",
"depth": 0.2,
"mode": "flat"
}
}

View File

@ -0,0 +1,35 @@
{
"name": "Menu: Close Option",
"type": "Gui",
"ignore": false,
"transform": {
"position": [ -0.75622, 0.638136, 0 ],
"rotation": {
"axis": [ 0, 0, 1 ],
"angle": 0
},
"scale": [ 1, 1, 1 ]
},
"clickable": true,
"hoverable": true,
"metadata": {
"uv": [ 0, 0, 1, 1 ],
"location": "",
"scaling": "relative",
"debug": {
"moveable": false
},
"events": {
"click": {
"name": "system:Quit",
"payload": {
"scene": "StartMenu"
}
}
},
"text settings": {
"legacy": false,
"string": "Quit"
}
}
}

View File

@ -0,0 +1,142 @@
Static = {
values = {},
get = function( obj )
if Static.values[""..obj:uid()] == nil then
Static.values[""..obj:uid()] = {}
end
return Static.values[""..obj:uid()]
end
}
local scene = entities.currentScene()
local controller = entities.controller()
local camera = controller:getComponent("Camera")
local metadata = ent:getComponent("Metadata")
local masterdata = scene:getComponent("Metadata")
local children = {
mainText = ent:loadChild("./main-text.json",true),
circleOut = ent:loadChild("./circle-out.json",true),
circleIn = ent:loadChild("./circle-in.json",true),
start = ent:loadChild("./start.json",true),
quit = ent:loadChild("./quit.json",true),
}
local timer = Timer.new()
if not timer:running() then timer:start() end
local playSound = function( key )
local url = "/ui/" .. key .. ".ogg"
local assetLoader = scene:getComponent("Asset")
assetLoader:cache(string.resolveURI(url), ent:formatHookName("asset:Load.%UID%"))
end
local destination = function( obj, x, y, z )
local static = Static.get(obj)
local transform = obj:getComponent("Transform")
static.from = Vector3f(x or transform.position.x, y or transform.position.y, z or transform.position.z)
end
pcall( function()
local metadata = controller:getComponent("Metadata")
local json = json.readFromFile("./data/entities/player.json");
controller:callHook("object:UpdateMetadata.%UID%", {
overlay = json["metadata"]["overlay"]
})
camera:update(true);
end )
destination(children.mainText, nil, -2, 0)
destination(children.circleOut, nil, -2, 0)
destination(children.circleIn, nil, 2, 0)
destination(children.start, -1.5, nil, 0)
destination(children.quit, -1.5, nil, 0)
ent:addHook("asset:Load.%UID%", function( json )
local filename = json["filename"]
if filename == "" or string.extension( filename ) ~= "ogg" then return false end
local sfx = ent:getComponent("Audio")
if not sfx:playing() then sfx:stop() end
sfx:load( filename )
sfx:setVolume( masterdata["volumes"]["sfx"] )
sfx:play()
return true
end )
ent:bind( "tick", function(self)
local static = Static.get(self)
if not static.alpha then
static.alpha = 0
end
metadata["initialized"] = true;
if static.alpha >= 1.0 then
static.alpha = 1.0
else
static.alpha = static.alpha + time.delta() * 1.5
end
-- make background glow
local glow = 1 + math.sin(1.25 * time.current()) * 0.125
metadata["color"][1] = glow
metadata["color"][2] = glow
metadata["color"][3] = glow
metadata["alpha"] = static.alpha;
self:setComponent("Metadata", metadata)
camera:update(true);
-- iterate children in batch
for k, v in pairs(children) do
if v:uid() <= 0 then goto continue end
-- set alpha
local metadata = v:getComponent("Metadata")
metadata["alpha"] = static.alpha
v:setComponent("Metadata", metadata)
local transform = v:getComponent("Transform")
local static = Static.get(v)
-- translation
if not static.from then goto continue end
if not static.to then static.to = Vector3f(transform.position) end
if not static.delta then static.delta = 0 end
if static.delta >= 1 then
static.delta = 1
else
static.delta = static.delta + time.delta() * 1.5
transform.position = Vector3f.lerp( static.from, static.to, static.delta )
end
::continue::
end
-- circle in
child = children.circleIn
if child:uid() > 0 then
local static = Static.get( child )
local transform = child:getComponent("Transform")
local metadata = child:getComponent("Metadata")
-- rotation
local speed = metadata["hovered"] and 0.25 or 0.0125
static.time = (static.time or 0) + time.delta() * -speed
transform.orientation = Quaternion.axisAngle( Vector3f(0, 0, 1), static.time )
end
-- circle out
child = children.circleOut
if child:uid() > 0 then
local static = Static.get( child )
local transform = child:getComponent("Transform")
local metadata = child:getComponent("Metadata")
-- rotation
local speed = metadata["hovered"] and 0.25 or 0.0125
static.time = (static.time or 0) + time.delta() * speed
transform.orientation = Quaternion.axisAngle( Vector3f(0, 0, 1), static.time )
end
end )

View File

@ -0,0 +1,35 @@
{
"name": "Menu: Start Option",
"type": "Gui",
"ignore": false,
"transform": {
"position": [ -0.75622, 0.446468, 0 ],
"rotation": {
"axis": [ 0, 0, 1 ],
"angle": 0
},
"scale": [ 1, 1, 1 ]
},
"clickable": true,
"hoverable": true,
"metadata": {
"uv": [ 0, 0, 1, 1 ],
"location": "",
"scaling": "relative",
"debug": {
"moveable": false
},
"events": {
"click": {
"name": "game:Scene.Load",
"payload": {
"scene": "SS2"
}
}
},
"text settings": {
"string": "Start",
"string1": "スタート"
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 425 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 B

View File

@ -0,0 +1,23 @@
{
"name": "Menu: Circle Inner",
"type": "Gui",
"ignore": false,
"transform": {
"position": [ -0.86, 0.86, 0 ],
"rotation": {
"axis": [ 1, 0, 0 ],
"angle": 0
},
"scale": [ 1, 1, 1 ]
},
"metadata": {
"uv": [ 0, 0, 1, 1 ],
"color": [ 1, 1, 1, 0.8 ],
"location": "",
"scaling": [ 0.64, 1 ],
"mode": "flat"
},
"assets": [
"https://cdn..xyz//unity/Android/sprite/sprite_magiccircle_in.png"
]
}

View File

@ -0,0 +1,25 @@
{
"name": "Menu: Circle Outer",
"type": "Gui",
"ignore": false,
"transform": {
"position": [ -0.86, 0.86, 0 ],
"rotation": {
"axis": [ 1, 0, 0 ],
"angle": 0
},
"scale": [ 1, 1, 1 ]
},
"clickable": false,
"hoverable": true,
"metadata": {
"uv": [ 0, 0, 1, 1 ],
"color": [ 1, 1, 1, 0.8 ],
"location": "",
"scaling": [ 0.64, 1 ],
"mode": "flat"
},
"assets": [
"https://cdn..xyz//unity/Android/sprite/sprite_magiccircle_out.png"
]
}

View File

@ -0,0 +1,30 @@
{
"name": "Menu: Close Option",
"type": "Gui",
"ignore": false,
"transform": {
"position": [ -0.65544, -0.339642, 0 ],
"rotation": {
"axis": [ 0, 0, 1 ],
"angle": 0
},
"scale": [ 0.156407, 0.0788377, 1 ]
},
"clickable": true,
"hoverable": true,
"metadata": {
"uv": [ 0, 0, 1, 1 ],
"location": "",
"scaling": "relative",
"events": {
"click": {
"name": "menu:Close.%P-UID%",
"payload": {}
}
},
"text settings": {
"string": "Close",
"string1": "クローズ"
}
}
}

View File

@ -0,0 +1,25 @@
{
"name": "Menu: Command Text",
"type": "Gui",
"ignore": false,
"transform": {
"position": [ -0.830591, -0.699509, 0 ],
"rotation": {
"axis": [ 1, 0, 0 ],
"angle": 0
},
"scale": [ 0.258737, 0.115371, 1 ]
},
"metadata": {
"uv": [ 0, 0, 1, 1 ],
"location": "",
"scaling": "relative",
"text settings": {
"stroke": [ 1, 0.749, 0.368, 1 ],
"color": [ 1, 0.749, 0.368, 1 ],
"string": "Menu",
"string1": "コマンド"
}
}
}

View File

@ -0,0 +1,25 @@
{
"name": "Gui: Icon",
"type": "Gui",
"ignore": false,
"transform": {
"position": [ 0, 0, 0 ],
"rotation": {
"axis": [ 0, 0, 1 ],
"angle": 0
},
"scale": [ 1, 1, 1 ]
},
"metadata": {
"gui": {
"position": [ -0.875, -0.775, 0 ],
"uv": [ 0, 0, 1, 1 ],
"color": [ 1, 1, 1, 1 ],
"location": "",
"scaling": "fixed"
}
},
"assets": [
"https://cdn..xyz//unity/Android/icon/icon_agyou01_skin1.png"
]
}

View File

@ -0,0 +1,23 @@
{
"name": "Menu: Main Scroller",
"type": "Gui",
"ignore": true,
"transform": {
"position": [ 0.98, -2, 0 ],
"rotation": {
"axis": [ 0, 0, 1 ],
"angle": 1.5707963
},
"scale": [ 0.16, 1, 1 ]
},
"hoverable": true,
"metadata": {
"uv": [ 0, 0, 1, 1 ],
"color": [ 0.113, 0.756, 0.988, 0.4 ],
"location": "",
"scaling": "relative"
},
"assets": [
"./textures/main.png"
]
}

View File

@ -0,0 +1,29 @@
{
"name": "Gui: Menu",
"type": "Gui",
"behaviors": [
"GuiBehavior"
],
"ignore": false,
"transform": {
"position": [ 0, 0, 0 ],
"rotation": {
"axis": [ 0, 0, 1 ],
"angle": 0
},
"scale": [ 1, 1, 1 ]
},
"metadata": {
"uv": [ 0, 0, 1, 1 ],
"color": [ 0.1, 0.05, 0.1, 0.5 ],
"location": "",
"scaling": "relative",
// "depth": 0.2,
"alpha": 1,
"mode": 1
},
"assets": [
// "./textures/menu.png",
"./scripts/menu.lua"
]
}

View File

@ -0,0 +1,43 @@
{
"name": "Menu: Close Option",
"type": "Gui",
"ignore": false,
"transform": {
"position": [ -0.65544, -0.157698, 0 ],
"rotation": {
"axis": [ 0, 0, 1 ],
"angle": 0
},
"scale": [ 0.156407, 0.0788377, 1 ]
},
"clickable": true,
"hoverable": true,
"metadata": {
"uv": [ 0, 0, 1, 1 ],
"location": "",
"scaling": "relative",
"debug": {
"moveable": true
},
"events": {
"click": [
{
"name": "menu:Close.%P-UID%",
"payload": {
"callback": {
"name": "game:Scene.Load",
"payload": {
"scene": "StartMenu"
},
"scope": "scene"
}
}
}
]
},
"text settings": {
"string": "Quit",
"string1": "終了する"
}
}
}

View File

@ -0,0 +1,194 @@
local scene = entities.currentScene()
local metadata = ent:getComponent("Metadata")
local masterdata = scene:getComponent("Metadata")
local children = {
mainText = ent:loadChild("./main-text.json",true),
circleOut = ent:loadChild("./circle-out.json",true),
circleIn = ent:loadChild("./circle-in.json",true),
coverBar = ent:loadChild("./yellow-box.json",true),
commandText = ent:loadChild("./command-text.json",true),
tenkouseiOption = ent:loadChild("./tenkousei.json",true),
closeOption = ent:loadChild("./close.json",true),
quit = ent:loadChild("./quit.json",true),
}
local soundEmitter = ent:loadChild("./sound.json",true)
local timer = Timer.new()
if not timer:running() then timer:start() end
Static = {
values = {},
get = function( obj )
if obj == nil then
obj = scene
end
if Static.values[""..obj:uid()] == nil then
Static.values[""..obj:uid()] = {}
end
return Static.values[""..obj:uid()]
end
}
local destination = function( obj, x, y, z )
local static = Static.get(obj)
local transform = obj:getComponent("Transform")
static.from = Vector3f(x or transform.position.x, y or transform.position.y, z or transform.position.z)
end
-- circleOut
destination(children.circleOut, nil, -2, 0)
destination(children.circleIn, nil, 2, 0)
destination(children.coverBar, -1.5, nil, 0)
destination(children.commandText, -1.5, nil, 0)
destination(children.tenkouseiOption, -1.5, nil, 0)
destination(children.closeOption, -1.5, nil, 0)
destination(children.quit, -1.5, nil, 0)
local playSound = function( key )
local url = "/ui/" .. key .. ".ogg"
local assetLoader = scene:getComponent("Asset")
assetLoader:cache(string.resolveURI(url), soundEmitter:formatHookName("asset:Load.%UID%"), "")
end
ent:addHook("menu:Close.%UID%", function( json )
playSound("menu close")
metadata["system"]["hooks"]["onClose"] = json["callback"];
metadata["system"]["closing"] = true;
ent:setComponent("Metadata", metadata)
end )
--[[
ent:addHook("asset:Load.%UID%", function( json )
local filename = json["filename"]
if filename == "" or string.extension( filename ) ~= "ogg" then return false end
local sfx = ent:getComponent("Audio")
if not sfx:playing() then sfx:stop() end
sfx:load( filename )
sfx:setVolume( masterdata["volumes"]["sfx"] )
sfx:play()
return true
end )
]]
playSound("menu open")
ent:bind( "tick", function(self)
local static = Static.get(self)
if not static.alpha then
static.alpha = 0
end
-- handle closing
if metadata["system"]["closing"] then
if static.alpha <= 0 then
static.alpha = 0
metadata["system"]["closing"] = false
metadata["system"]["closed"] = true
else
static.alpha = static.alpha - time.delta()
end
elseif metadata["system"]["closed"] then
timer:stop()
local callback = metadata["system"]["hooks"]["onClose"]
if callback then
local payload = callback["payload"]
local target = self
if callback["scope"] == "parent" then
target = ent:getParent()
elseif callback["scope"] == "scene" then
target = scene
end
if type(callback["delay"]) == "number" and target:uid() ~= self:uid() then
target:queueHook( callback["name"], payload, callback["delay"] );
else
target:callHook( callback["name"], payload );
end
end
entities.destroy(self)
-- scene:queueHook("system:Destroy", { uid = self:uid() }, 0)
return
else
if not metadata["initialized"] then
static.alpha = 0
end
metadata["initialized"] = true;
if static.alpha >= 1.0 then
static.alpha = 1.0
else
static.alpha = static.alpha + time.delta() * 1.5
end
end
metadata["alpha"] = static.alpha;
self:setComponent("Metadata", metadata)
-- set alphas
for k, v in pairs(children) do
if v:uid() <= 0 then goto continue end
-- set alpha
local metadata = v:getComponent("Metadata")
metadata["alpha"] = static.alpha
v:setComponent("Metadata", metadata)
local transform = v:getComponent("Transform")
local static = Static.get(v)
-- translation
if not static.from then goto continue end
if not static.to then static.to = Vector3f(transform.position) end
if not static.delta then static.delta = 0 end
if static.delta >= 1 then
static.delta = 1
else
static.delta = static.delta + time.delta() * 1.5
transform.position = Vector3f.lerp( static.from, static.to, static.delta )
end
::continue::
end
-- main text
local child = children.mainText
if child:uid() > 0 then
local transform = child:getComponent("Transform")
local metadata = child:getComponent("Metadata")
local speed = metadata["hovered"] and 0.75 or 0.5
transform.position.y = transform.position.y + time.delta() * speed
if transform.position.y > 2 then
transform.position.y = -2
end
end
-- circle in
child = children.circleIn
if child:uid() > 0 then
local static = Static.get( child )
local transform = child:getComponent("Transform")
local metadata = child:getComponent("Metadata")
-- rotation
local speed = metadata["hovered"] and 0.25 or 0.0125
static.time = (static.time or 0) + time.delta() * -speed
transform.orientation = Quaternion.axisAngle( Vector3f(0, 0, 1), static.time )
end
-- circle out
child = children.circleOut
if child:uid() > 0 then
local static = Static.get( child )
local transform = child:getComponent("Transform")
local metadata = child:getComponent("Metadata")
-- rotation
local speed = metadata["hovered"] and 0.25 or 0.0125
static.time = (static.time or 0) + time.delta() * speed
transform.orientation = Quaternion.axisAngle( Vector3f(0, 0, 1), static.time )
end
if window.keyPressed("Escape") and timer:elapsed() >= 1 then
timer:reset()
self:callHook("menu:Close.%UID%", {})
end
end )

View File

@ -0,0 +1,38 @@
{
"type": "Object",
"name": "Sound Emitter",
"ignore": false,
"assets": [
],
"behaviors": [
"SoundEmitterBehavior"
],
"transform": {
"position": [ 0, 0, 0 ],
"rotation": {
"axis": [ 0, 1, 0 ],
"angle": 0
},
"scale": [ 1, 1, 1 ]
},
"system": {
"hot reload": {
"enabled": true
},
"defaults": {
"render": true,
"asset load": true
},
"load": {
"ignore": true
}
},
"metadata": {
"audio": {
"spatial": false,
"loop": false,
"volume": "sfx",
"rolloffFactor": 2
}
}
}

View File

@ -0,0 +1,24 @@
{
"name": "Menu: Tenkousei Option",
"type": "Gui",
"ignore": true,
"transform": {
"position": [ -0.65544, -0.52853, 0 ],
"rotation": {
"axis": [ 0, 0, 1 ],
"angle": 0
},
"scale": [ 0.156407, 0.0788377, 1 ]
},
"clickable": true,
"hoverable": true,
"metadata": {
"uv": [ 0, 0, 1, 1 ],
"location": "",
"scaling": "relative",
"text settings": {
"string": "",
"string1": "「転光生」"
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 B

View File

@ -0,0 +1,21 @@
{
"name": "Menu: Transient Portrait",
"type": "Gui",
"ignore": true,
"transform": {
"position": [ 0.76, 0.2, 0 ],
"rotation": {
"axis": [ 1, 0, 0 ],
"angle": 0
},
"scale": [ 0.43, 1, 1 ]
},
"clickable": true,
"metadata": {
"uv": [ 0, 0, 1, 1 ],
"color": [ 1, 1, 1, 0 ],
"location": "",
"scaling": "relative",
"depth": 0.1
}
}

View File

@ -0,0 +1,21 @@
{
"name": "Menu: Transient Shadow",
"type": "Gui",
"ignore": true,
"transform": {
"position": [ 0.46, 0, 0 ],
"rotation": {
"axis": [ 1, 0, 0 ],
"angle": 0
},
"scale": [ 0.43, 1, 1 ]
},
"metadata": {
"uv": [ 0, 0, 1, 1 ],
"color": [ 1, 1, 1, 0 ],
"location": "",
"scaling": "relative",
"shader": 1,
"depth": 0.1
}
}

View File

@ -0,0 +1,25 @@
{
"name": "Menu: Left Rectangle",
"type": "Gui",
"ignore": false,
"transform": {
"position": [ -0.933374, 0, 0 ],
"rotation": {
"axis": [ 1, 0, 0 ],
"angle": 0
},
"scale": [ 0.067, 1, 1 ]
},
"metadata": {
"uv": [ 0, 0, 1, 1 ],
// "color": [ 1, 0.749, 0.368, 1 ],
"color": [ 1, 0.749, 0.368, 1 ],
"location": "",
"scaling": "relative",
"shader": 1,
"mode": "flat"
},
"assets": [
"./textures/square.png"
]
}

View File

@ -0,0 +1,22 @@
{
"name": "Gui: Text",
"type": "Object",
"behaviors": [
"GuiBehavior"
],
"ignore": false,
"transform": {
"position": [ 0, 0, 0 ],
"rotation": {
"axis": [ 0, 0, 1 ],
"angle": 0
},
"scale": [ 1, 1, 1 ]
},
"metadata": {
"uv": [ 0, 0, 1, 1 ],
"color": [ 1, 1, 1, 1 ],
"location": "",
"scaling": "relative"
}
}

View File

@ -0,0 +1,42 @@
{
"name": "Gui: Text",
"type": "Gui",
"ignore": true,
"transform": {
"position": [ 0, 0, 0 ],
"rotation": {
"axis": [ 0, 0, 1 ],
"angle": 0
},
"scale": [ 1, 1, 1 ]
},
"metadata": {
"text settings": {
"legacy": false,
"padding": [ 4, 4 ],
"spread": 4,
"weight": 0.48395,
"size": 72,
"scale": 1.25,
// "size": 112,
// "scale": 1,
"sdf": true,
"font": "TAZUGANEGOTHICSTDN-BOLD.otf",
"kerning": 24,
// "font": "Coolvetica.ttf",
"stroke": [ 0, 0, 0, 0 ],
"color": [ 1, 1, 1, 1 ],
"direction": "down",
"align": "left",
"origin": [ 0, 0 ],
"string": "",
"world": false,
// "depth": 0,
"wrap": true
}
}
}

76
data/entities/hands.json Normal file
View File

@ -0,0 +1,76 @@
{
"name": "Hands",
"type": "Object",
"ignore": true,
"transform": {
"position": [ 0, 0, 0 ],
"rotation": {
"axis": [ 0, 1, 0 ],
"angle": 0.0
},
"scale": [ 1, 1, 1 ]
},
"assets": [
],
"behaviors": [
"PlayerHandBehavior"
],
"metadata": {
"hands": {
"left": {
"controller": {
"model": "{indexcontroller}valve_controller_knu_1_0_left",
"color": [ 1, 1, 1, 1 ]
},
"light": {
"should": false,
"type": 3,
"color": [1, 1, 1],
"power": 50,
"fov": 80,
"shadows": true,
"bias": 0.000005,
"resolution": 512,
"static": false
},
"pointer": {
"color": [ 1, 0, 1, 1 ],
"length": 0, //128,
"width": 8,
"offset": [ 0, 0, 0 ],
"orientation": {
"axis": [ 1, 0, 0 ],
"angle": 0
}
}
},
"right": {
"controller": {
"model": "{indexcontroller}valve_controller_knu_1_0_right",
"color": [ 1, 1, 1, 1 ]
},
"light": {
"should": false,
"type": 3,
"color": [1, 1, 1],
"power": 50,
"fov": 80,
"shadows": true,
"bias": 0.000005,
"resolution": 512,
"static": false
},
"pointer": {
"color": [ 1, 0, 1, 1 ],
"length": 0, //128,
"width": 8,
"offset": [ 0, 0, 0 ],
"orientation": {
"axis": [ 1, 0, 0 ],
"angle": 0
}
}
}
}
}
}

29
data/entities/hud.json Normal file
View File

@ -0,0 +1,29 @@
{
"name": "HUD Text",
"type": "Gui",
"ignore": false,
"transform": {
"position": [ -0.830591, -0.899509, 0 ],
"rotation": {
"axis": [ 1, 0, 0 ],
"angle": 0
},
"scale": [ 0.258737, 0.115371, 1 ]
},
"system": {
"hot reload": {
"enabled": true
}
},
"metadata": {
"uv": [ 0, 0, 1, 1 ],
"location": "",
"scaling": "relative",
"text settings": {
"stroke": [ 1, 0.749, 0.368, 1 ],
"color": [ 1, 0.749, 0.368, 1 ],
"depth": 0.5,
"string": "."
}
}
}

44
data/entities/light.json Normal file
View File

@ -0,0 +1,44 @@
{
"type": "Object",
"name": "Light",
"behaviors": [ "LightBehavior" ],
"ignore": false,
"transform": {
"reference": true
},
"system": {
"renderer": {
// "limiter": 128
// "mode": "round robin"
// "mode": "once"
"mode": "in-range"
},
"behavior-0": {
"tick": {
"head loop children": true,
"forward iteration": false,
"multithreading": false
},
"render": {
"multithreading": false
}
}
},
"metadata": {
"light": {
"type": "point",
"color": [1, 1, 1],
"power": 100,
"fov": 90,
"bias": {
"constant": 1.25,
"slope": 1.75,
"shader": 0.00005
},
"radius": [0.05, 0],
"resolution": 512,
"shadows": true,
"static": false
}
}
}

108
data/entities/player.json Normal file
View File

@ -0,0 +1,108 @@
{
"name": "Player",
"type": "Object",
"behaviors": [
"PlayerBehavior",
"CraetureBehavior"
],
"ignore": false,
"transform": {
"position": [ 0, 0, 0 ],
"rotation": {
"axis": [ 0, 1, 0 ],
"angle": 0.0
},
"scale": [ 1, 1, 1 ]
},
"assets": [
{ "filename": "./playerModel.json", "delay": 1.0, "single threaded": true },
"./hands.json"
],
"system": {
"behavior-0": {
"tick": {
"head loop children": false,
"multithreading": false
}
},
"physics": {
"collision": 1.0,
"impulse": true,
"gravity": [ 0, -9.81, 0 ],
"walk": 1,
"move": 4,
"run": 8,
"rotate": 1.25,
"crouch": 1,
"jump": [ 0, 4, 0 ],
"type": "Capsule",
"radius": 1,
"height": 2,
"mass": 100,
"shared": false
}
},
"metadata": {
"overlay": {
// "position": [ 0, 0, -3 ],
// "scale": [ -1.77778, -1, 1 ],
"position": [ 0, 0, -3 ],
"scale": [ 1.77778, -1, 1 ],
"orientation": [ 0, 0, 0, 1 ],
"floating": false,
"enabled": true,
"alpha": 1.0,
"cursor": {
"type": "mouse",
"radius": 0.05,
"color": [ 0.2, 0.2, 1.0, 1.0 ],
"enabled": false
}
},
"light": {
"should": false,
"color": [1, 1, 1],
"position": [ 0, 2.5, 0 ],
"power": 0.1,
"radius": [0.001, 32]
},
"region": {
"track": true,
"persist": true
},
"audio": {
"footstep": {
"volume": 0.5,
"list": [
"./data/audio/footstep/1.ogg",
"./data/audio/footstep/2.ogg"
]
}
},
"camera": {
"offset": [ 0, 0, 0 ],
"position" : [ 0, 2, 0 ],
"scale": [ 1, 1, 1 ],
"invert": [ false, false, false ],
"limit": {
// "minima": [ null, -1.57079633, null ],
// "maxima": [ null, 1.57079633, null ],
"minima": [ null, -1.0, null ],
"maxima": [ null, 1.0, null ],
"current": [ null, 0, null ]
},
"settings": {
"fov" : 90,
"clip" : { "near" : 0.01, "far" : 512.0 },
"size" : {
"auto" : true,
"x" : 7680,
"y" : 4320
}
}
}
}
}

View File

@ -0,0 +1,49 @@
{
"type": "Object",
"name": "Player: Model",
"ignore": false,
"assets": [
"/player/bear.glb"
// "/player/s.glb"
],
"behaviors": [
"PlayerModelBehavior"
],
"transform": {
"position": [ 0, -2.0, 0 ],
"rotation": {
"axis": [ 0, 1, 0 ],
"angle": 0
},
"scale": [ 0.16, 0.16, 0.16 ]
},
"system": {
"hot reload": {
"enabled": true
},
"defaults": {
// "render": true,
"asset load": true
}
},
"metadata": {
"track via reference": true,
"track player": true,
"hide player model": true,
"model": {
"animation": "wank",
"print animations": true,
// "mesh optimization": 1,
"flags": {
"RENDER": true,
"COLLISION": false,
"SEPARATE": true,
"NORMALS": false,
"LOAD": false,
"ATLAS": false,
"SKINNED": true,
"INVERT": true
}
}
}
}

31
data/entities/portal.json Normal file
View File

@ -0,0 +1,31 @@
{
"type": "Portals",
"ignore": false,
"metadata": {
"portals": [
{
"transform": {
"position": [ 0, 0, -10 ],
"orientation": [ 0, 0, 0, 1 ],
"scale": [ 6, 4, 1 ]
},
"metadata": {
}
},
{
"transform": {
"position": [ 0, 0, 10 ],
"rotation": {
"axis": [ 0, 1, 0 ],
"angle": 3.14159
},
"scale": [ 6, 4, 1 ]
},
"metadata": {
}
}
]
}
}

11
data/entities/scene.json Normal file
View File

@ -0,0 +1,11 @@
{
"name": "Scene",
"assets": [
"/gui.json"
],
"behaviors": [
"SceneBehavior",
"SceneCollisionBehavior",
"ExtSceneBehavior"
]
}

View File

@ -0,0 +1,32 @@
{
"name": "Gui: Loading",
"type": "Object",
"behaviors": [
// "GuiBehavior"
],
"assets": [
{ "filename": "./mcdonalds.json", "delay": 0 }
],
"ignore": false,
"transform": {
"position": [ -0.830591, -0.699509, 0 ],
"rotation": {
"axis": [ 1, 0, 0 ],
"angle": 0
},
"scale": [ 0.258737, 0.115371, 1 ]
},
"metadata": {
"uv": [ 0, 0, 1, 1 ],
"color": [ 1, 1, 1, 0.1 ],
"location": "",
"scaling": "relative",
"text settings": {
"stroke": [ 1, 0.749, 0.368, 1 ],
"color": [ 1, 0.749, 0.368, 1 ],
"string": "Loading...",
"string1": "コマンド"
}
}
}

View File

@ -0,0 +1,24 @@
{
"name": "Marker",
"type": "Gui",
"ignore": false,
"transform": {
"position": [ 0, 0, 0 ],
"rotation": {
"axis": [ 1, 0, 0 ],
"angle": 0
},
"scale": [ 1, 1, 1 ]
},
"metadata": {
"uv": [ 0, 0, 1, 1 ],
"color": [ 1, 1, 1, 0.8 ],
"location": "",
"scaling": [ 1, 1 ],
"world": true,
"gui layer": false
},
"assets": [
"https://cdn..xyz//unity/Android/sprite/sprite_magiccircle_in2.png"
]
}

View File

@ -0,0 +1,78 @@
{
"type": "Object",
"name": "Map",
"ignore": false,
"assets": [
{ "filename": "./models/mcdonalds.glb", "delay": 0, "single threaded": false },
{ "filename": "./static.json", "delay": 1 }
],
"behaviors": [
"LoadingBehavior"
],
"transform": {
"position": [ 0, 0, 0 ],
"rotation": {
"axis": [ 0, 1, 0 ],
"angle": 0
},
"scale": [ 1, 1, 1 ]
},
"system": {
"defaults": {
"asset load": true
}
},
"metadata": {
"textures": {
"map": {
// "22": [ 86, "sin(time)" ],
// "4": [ 88, "sin(time)" ],
// "36": [ 87, 1.0 ]
}
},
"model": {
// "mesh optimization": 0,
"cull mode": "auto",
"flags": {
"RENDER": true,
"COLLISION": false,
"SEPARATE": false,
"NORMALS": false,
"LOAD": false,
"ATLAS": true,
"SKINNED": false,
"INVERT": false,
"TRANSFORM": false
},
"lights": {
// "renderMode": { "target": "worldspawn_1" },
"shadows": true
},
"tags": {
"worldspawn_1": { "collision": "static mesh" },
"worldspawn_2": { "collision": "static mesh" },
"info_player_spawn": { "action": "attach", "filename": "./player.json", "preserve orientation": true },
/*
"light_5752": {
"transform": { "offset": true, "position": [ 0, -2.1768, 0 ] },
"light": {
// "flicker": { "rate": 0.5, "power": 0, "timeout": 4 },
"fade": { "rate": 4, "color": [0, 0, 0], "timeout": 16 },
"shadows": false
}
},
*/
"func_door_rotating_5243": { "action": "load", "payload": { "assets": ["./scripts/door.lua"], "metadata": { "angle":-1.570795 } } },
"func_door_rotating_5444": { "action": "load", "payload": { "assets": ["./scripts/door.lua"], "metadata": { "angle": 1.570795 } } },
"func_door_rotating_5495": { "action": "load", "payload": { "assets": ["./scripts/door.lua"], "metadata": { "angle": 1.570795 } } },
"func_door_rotating_5220": { "action": "load", "payload": { "assets": ["./scripts/door.lua"], "metadata": { "angle":-1.570795 } } },
"func_door_rotating_5556": { "action": "load", "payload": { "assets": ["./scripts/door.lua"], "metadata": { "angle": 1.570795 } } },
"func_door_rotating_5689": { "action": "load", "payload": { "assets": ["./scripts/door.lua"], "metadata": { "angle":-1.570795 } } },
"func_door_rotating_5712": { "action": "load", "payload": { "assets": ["./scripts/door.lua"], "metadata": { "angle": 1.570795 } } },
"func_door_rotating_5576": { "action": "load", "payload": { "assets": ["./scripts/door.lua"], "metadata": { "angle":-1.570795 } } },
"func_door_rotating_5584": { "action": "load", "payload": { "assets": ["./scripts/door.lua"], "metadata": { "angle":-1.570795 } } },
"func_door_rotating_5568": { "action": "load", "payload": { "assets": ["./scripts/door.lua"], "metadata": { "angle":-1.570795 } } }
}
}
}
}

View File

@ -0,0 +1,19 @@
{
"import": "/player.json",
"assets": [
// { "filename": "/gui/hud/hud.json", "delay": 0 }
],
"metadata": {
"overlay": {
"floating": true
},
"collider": true,
"light": {
"should": false,
"color": [1, 1, 1],
"position": [ 0, 2.5, 0 ],
"power": 1,
"radius": [0.001, 32]
}
}
}

View File

@ -0,0 +1,50 @@
{
"import": "/scene.json",
"assets": [
"./audio/soundscape/ambience.ogg",
"./loading.json"
],
"system": {
"hot reload": {
"enabled": true
},
"renderer": {
"shader": {
"mode": 1,
"scalar": 16,
"parameters": [ 0, 0, 0, 0 ]
},
"clear values": [
[ 1, 1, 1, 0 ]
]
}
},
"metadata": {
"menus": {
"pause": "/gui/pause/menu.json"
},
"volumes": {
"sfx": 0.25,
"bgm": 0.75,
"voice": 1.0
},
"light": {
"ambient": [ 0.025, 0.025, 0.025 ],
"kexp": 0,
"fog": {
"color": [ 0.25, 0.25, 0.25 ],
"range": [ 32, 64 ],
"step scale": 4,
"absorbtion": 0.07,
"density": {
"threshold": 0.35,
"multiplier": 5.0,
"scale": 25.0,
"offset": [0, -1, 1],
"timescale": 8
}
},
"should": true
}
}
}

View File

@ -0,0 +1,18 @@
local scene = entities.currentScene()
local controller = entities.controller()
local timer = Timer.new()
if not timer:running() then
timer:start();
end
local target = Vector3f(0,0,0)
local transform = ent:getComponent("Transform")
local metadata = ent:getComponent("Metadata")
local speed = metadata["speed"] or 1.0 / 3.0
local starting = Quaternion(transform.orientation)
local ending = transform.orientation:multiply(Quaternion.axisAngle( Vector3f(0,1,0), metadata["angle"] ))
-- on tick
ent:bind( "tick", function(self)
transform.orientation = starting:slerp( ending, math.cos(time.current() * speed) * 0.5 + 0.5 )
end )

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