Commit for 2021.03.01.7z

This commit is contained in:
mrq 2021-03-01 00:00:00 -06:00
parent 714db3db60
commit ed4fb47ad9
2672 changed files with 1049704 additions and 3287 deletions

278
Makefile Normal file
View File

@ -0,0 +1,278 @@
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-pointer-arith
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 += vulkan json:nlohmann png openal ogg freetype ncurses curl luajit bullet meshoptimizer # draco discord
FLAGS +=
DEPS += -lgdi32
else ifneq (,$(findstring dreamcast,$(ARCH)))
REQ_DEPS += opengl gldc json:nlohmann png meshoptimizer bullet freetype # lua ogg openal draco 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 -DUF_USE_OPENGL_FIXED_FUNCTION
ifneq (,$(findstring dreamcast,$(ARCH)))
ifneq (,$(findstring gldc,$(REQ_DEPS)))
DEPS += -lGLdc
FLAGS += -DUF_USE_OPENGL_GLDC
else
DEPS += -lGL #-lGLdc
endif
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 -lbz2
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
ifneq (,$(findstring dreamcast,$(ARCH)))
DEPS += -lvorbis -logg
else
DEPS += -lvorbis -lvorbisfile -logg
endif
endif
ifneq (,$(findstring freetype,$(REQ_DEPS)))
FLAGS += -DUF_USE_FREETYPE
DEPS += -lfreetype
ifneq (,$(findstring dreamcast,$(ARCH)))
DEPS += -lbrotlicommon-static -lbrotlidec-static
endif
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
ifneq (,$(findstring dreamcast,$(ARCH)))
DEPS += -llua
INCS += -I/opt/dreamcast/kos-ports/include/lua
endif
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 -lbulletlinearmath
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
ifneq (,$(findstring draco,$(REQ_DEPS)))
FLAGS += -DUF_USE_DRACO
DEPS += -ldraco
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) $(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++ # -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 $@
ifneq (,$(findstring dreamcast,$(ARCH)))
clean:
@-rm $(EX_DLL)
@-rm $(EXT_EX_DLL)
@-rm $(TARGET)
@-rm -f $(OBJS_DLL)
@-rm -f $(OBJS_EXT_DLL)
@-rm -f $(OBJS)
@-rm ./bin/dreamcast/build/*
@-rm ./bin/dreamcast/romdisk.*
@-rm ./bin/dreamcast/$(TARGET_NAME).*
else
clean:
@-rm $(EX_DLL)
@-rm $(EXT_EX_DLL)
@-rm $(TARGET)
@-rm -f $(OBJS_DLL)
@-rm -f $(OBJS_EXT_DLL)
@-rm -f $(OBJS)
endif
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

@ -0,0 +1,44 @@
#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

@ -0,0 +1,49 @@
#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

@ -0,0 +1,43 @@
#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

@ -0,0 +1,23 @@
#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

@ -0,0 +1,16 @@
#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

@ -0,0 +1,75 @@
#version 450
#extension GL_EXT_samplerless_texture_functions : require
#define MULTISAMPLING 1
#define UF_DEFERRED_SAMPLING 0
#define UF_CAN_DISCARD 1
#if !MULTISAMPLING
layout (binding = 1) uniform usampler2D textureId;
layout (binding = 2) uniform sampler2D textureNormals;
#if UF_DEFERRED_SAMPLING
layout (binding = 3) uniform sampler2D textureUvs;
#else
layout (binding = 3) uniform sampler2D textureAlbedo;
#endif
#else
layout (binding = 1) uniform usampler2DMS textureId;
layout (binding = 2) uniform sampler2DMS textureNormals;
#if UF_DEFERRED_SAMPLING
layout (binding = 3) uniform sampler2DMS textureUvs;
#else
layout (binding = 3) uniform sampler2DMS textureAlbedo;
#endif
#endif
struct Cursor {
vec2 position;
vec2 radius;
vec4 color;
};
vec4 resolve( sampler2DMS t, ivec2 uv ) {
vec4 resolved = vec4(0);
int samples = textureSamples(t);
for ( int i = 0; i < samples; ++i ) {
resolved += texelFetch(t, uv, i);
}
resolved /= float(samples);
return resolved;
}
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 !MULTISAMPLING
ivec2 screenSize = textureSize(textureId, 0);
#else
ivec2 screenSize = textureSize(textureId);
#endif
ivec2 uv = ivec2(inUv * screenSize);
if ( inCursor.radius.x <= 0 || inCursor.radius.y <= 0 ) {
#if !MULTISAMPLING
outAlbedo = texture(textureAlbedo, uv).rgba;
#else
outAlbedo = resolve( textureAlbedo, uv );
#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 !MULTISAMPLING
outAlbedo = texture(textureAlbedo, inUv);
#else
outAlbedo = resolve( textureAlbedo, uv );
#endif
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;
}

View File

@ -0,0 +1,41 @@
#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

@ -0,0 +1,741 @@
#version 450
#extension GL_EXT_samplerless_texture_functions : require
#define MULTISAMPLING 1
#define RAY_MARCH_FOG 1
#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;
};
#if !MULTISAMPLING
layout (input_attachment_index = 0, binding = 0) uniform usubpassInput samplerId;
layout (input_attachment_index = 1, binding = 1) uniform subpassInput samplerNormal;
#if UF_DEFERRED_SAMPLING
layout (input_attachment_index = 2, binding = 2) uniform subpassInput samplerUv;
#else
layout (input_attachment_index = 2, binding = 2) uniform subpassInput samplerAlbedo;
#endif
layout (input_attachment_index = 3, binding = 3) uniform subpassInput samplerDepth;
#else
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 = 3) uniform subpassInputMS samplerDepth;
#endif
layout (binding = 4) uniform sampler3D samplerNoise;
layout (binding = 5) uniform samplerCube samplerSkybox;
layout (binding = 6) uniform sampler2D samplerTextures[TEXTURES];
layout (binding = 7) uniform UBO {
Matrices matrices;
Mode mode;
Fog fog;
uint lights;
uint materials;
uint textures;
uint drawCalls;
vec3 ambient;
float kexp;
uint msaa;
uint poissonSamples;
uint padding1;
uint padding2;
} ubo;
layout (std140, binding = 8) readonly buffer Lights {
Light lights[];
};
layout (std140, binding = 9) readonly buffer Materials {
Material materials[];
};
layout (std140, binding = 10) readonly buffer Textures {
Texture textures[];
};
layout (std140, binding = 11) 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 = int(ubo.poissonSamples);
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 );
}
vec4 resolve( subpassInputMS t ) {
int samples = int(ubo.msaa);
vec4 resolved = vec4(0);
for ( int i = 0; i < samples; ++i ) {
resolved += subpassLoad(t, i);
}
resolved /= vec4(samples);
return resolved;
}
uvec4 resolve( usubpassInputMS t ) {
int samples = int(ubo.msaa);
uvec4 resolved = uvec4(0);
for ( int i = 0; i < samples; ++i ) {
resolved += subpassLoad(t, i);
}
resolved /= uvec4(samples);
return resolved;
}
void main() {
vec3 rayO = vec3(0);
vec3 rayD = vec3(0);
vec3 fragColor = vec3(0);
{
#if !MULTISAMPLING
float depth = subpassLoad(samplerDepth).r;
#else
float depth = resolve( samplerDepth ).r;
#endif
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 );
}
#if !MULTISAMPLING
normal.eye = decodeNormals( subpassLoad(samplerNormal).xy );
uvec2 ID = subpassLoad(samplerId).xy;
#else
normal.eye = decodeNormals( resolve(samplerNormal).xy );
uvec2 ID = resolve(samplerId).xy;
#endif
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
#if !MULTISAMPLING
vec2 uv = subpassLoad(samplerUv).xy;
#else
vec2 uv = resolve(samplerUv).xy;
#endif
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
#if !MULTISAMPLING
C = subpassLoad(samplerAlbedo);
#else
C = resolve(samplerAlbedo);
#endif
#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

@ -0,0 +1,559 @@
#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

@ -0,0 +1,24 @@
#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

@ -0,0 +1,17 @@
#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

@ -0,0 +1,138 @@
#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;
}
if ( C.a == 0 ) discard;
}
#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

@ -0,0 +1,62 @@
#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

@ -0,0 +1,74 @@
#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 ivec4 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

@ -0,0 +1,78 @@
#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 ivec4 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

@ -0,0 +1,64 @@
#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

@ -0,0 +1,66 @@
#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

@ -0,0 +1,62 @@
#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

@ -0,0 +1,47 @@
#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

@ -0,0 +1,41 @@
#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

@ -0,0 +1,19 @@
#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

@ -0,0 +1,52 @@
#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

@ -0,0 +1,10 @@
#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

@ -0,0 +1,35 @@
#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

@ -0,0 +1,23 @@
#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

@ -0,0 +1,295 @@
#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

@ -0,0 +1,20 @@
#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

@ -0,0 +1,51 @@
#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

@ -0,0 +1,11 @@
#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

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

266
client/client/ext.cpp Normal file
View File

@ -0,0 +1,266 @@
#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_OPENAL
if ( !ext::oal.terminate() ) {
std::cerr << "[ERROR] AL failed to terminate!" << std::endl;
std::exit(EXIT_SUCCESS);
return;
}
#endif
}

87
client/dreamcast.gldc.inl Normal file
View File

@ -0,0 +1,87 @@
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glkos.h>
/* A general OpenGL initialization function. Sets all of the initial parameters. */
void InitGL(int Width, int Height) // We call this right after our OpenGL window is created.
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // This Will Clear The Background Color To Black
glClearDepth(1.0); // Enables Clearing Of The Depth Buffer
glDepthFunc(GL_LESS); // The Type Of Depth Test To Do
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading
glEnableClientState(GL_VERTEX_ARRAY); // Enable vertex arrays
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); // Reset The Projection Matrix
gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f); // Calculate The Aspect Ratio Of The Window
glMatrixMode(GL_MODELVIEW);
}
/* The function called when our window is resized (which shouldn't happen, because we're fullscreen) */
void ReSizeGLScene(int Width, int Height)
{
if (Height == 0) // Prevent A Divide By Zero If The Window Is Too Small
Height = 1;
glViewport(0, 0, Width, Height); // Reset The Current Viewport And Perspective Transformation
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW);
}
/* The main drawing function. */
void DrawGLScene()
{
const GLfloat triangle [] = {
0.0f, 1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
-1.0f, -1.0f, 0.0f
};
const GLfloat square [] = {
-1.0f, 1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
-1.0f, -1.0f, 0.0f
};
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
glLoadIdentity(); // Reset The View
glTranslatef(-1.5f,0.0f,-6.0f); // Move Left 1.5 Units And Into The Screen 6.0
glVertexPointer(3, GL_FLOAT, 0, triangle);
glDrawArrays(GL_TRIANGLES, 0, 3);
glTranslatef(3.0f,0.0f,0.0f); // Move Right 3 Units
glVertexPointer(3, GL_FLOAT, 0, square);
glDrawArrays(GL_QUADS, 0, 4);
// swap buffers to display, since we're double buffered.
glKosSwapBuffers();
}
int main(int argc, char **argv)
{
glKosInit();
InitGL(640, 480);
ReSizeGLScene(640, 480);
while(1) {
UF_DEBUG_PRINT_MARKER();
DrawGLScene();
}
return 0;
}

82
client/dreamcast.inl Normal file
View File

@ -0,0 +1,82 @@
/*
KallistiOS 2.0.0
nehe02.c
(c)2014 Josh Pearson
(c)2001 Benoit Miller
(c)2000 Jeff Molofee
*/
#include <kos.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
/*
The simplest OpenGL example ever!
Essentially the same thing as NeHe's lesson02 code.
To learn more, go to http://nehe.gamedev.net/.
*/
void draw_gl(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(-1.5f, 0.0f, -6.0f);
glBegin(GL_TRIANGLES);
glVertex3f(0.0f, 1.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 0.0f);
glVertex3f(1.0f, -1.0f, 0.0f);
glEnd();
glTranslatef(3.0f, 0.0f, 0.0f);
glBegin(GL_QUADS);
glVertex3f(-1.0f, 1.0f, 0.0f);
glVertex3f(1.0f, 1.0f, 0.0f);
glVertex3f(1.0f, -1.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 0.0f);
glEnd();
}
int main(int argc, char **argv) {
maple_device_t *cont;
cont_state_t *state;
/* Get basic stuff initialized */
printf("nehe02 beginning\n");
/* Notice we do not init the PVR here, that is handled by OpenGL */
glKosInit();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, 640.0f / 480.0f, 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
while(1) {
cont = maple_enum_type(0, MAPLE_FUNC_CONTROLLER);
/* Check key status */
state = (cont_state_t *)maple_dev_status(cont);
if(!state) {
printf("Error reading controller\n");
break;
}
if(state->buttons & CONT_START)
break;
/* Draw the "scene" */
draw_gl();
/* Finish the frame - Notice there is no glKosBegin/FinshFrame */
glutSwapBuffers();
}
return 0;
}

78
client/main.cpp Normal file
View File

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

18
client/main.h Normal file
View File

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

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 170 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

View File

@ -1,166 +0,0 @@
{
"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
}
}

View File

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

View File

@ -1,23 +0,0 @@
{
"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

@ -1,36 +0,0 @@
{
"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

@ -1,154 +0,0 @@
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

@ -1,38 +0,0 @@
{
"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

@ -1,25 +0,0 @@
{
"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

@ -1,25 +0,0 @@
{
"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

@ -1,26 +0,0 @@
{
"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

@ -1,30 +0,0 @@
{
"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

@ -1,35 +0,0 @@
{
"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

@ -1,142 +0,0 @@
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

@ -1,35 +0,0 @@
{
"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.

Before

Width:  |  Height:  |  Size: 425 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 225 B

View File

@ -1,23 +0,0 @@
{
"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

@ -1,25 +0,0 @@
{
"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

@ -1,30 +0,0 @@
{
"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

@ -1,25 +0,0 @@
{
"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

@ -1,25 +0,0 @@
{
"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

@ -1,23 +0,0 @@
{
"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

@ -1,29 +0,0 @@
{
"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

@ -1,43 +0,0 @@
{
"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

@ -1,194 +0,0 @@
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

@ -1,38 +0,0 @@
{
"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

@ -1,24 +0,0 @@
{
"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.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 225 B

View File

@ -1,21 +0,0 @@
{
"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

@ -1,21 +0,0 @@
{
"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

@ -1,25 +0,0 @@
{
"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

@ -1,22 +0,0 @@
{
"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

@ -1,42 +0,0 @@
{
"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
}
}
}

View File

@ -1,76 +0,0 @@
{
"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
}
}
}
}
}
}

View File

@ -1,29 +0,0 @@
{
"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": "."
}
}
}

View File

@ -1,44 +0,0 @@
{
"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
}
}
}

View File

@ -1,108 +0,0 @@
{
"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

@ -1,49 +0,0 @@
{
"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
}
}
}
}

View File

@ -1,31 +0,0 @@
{
"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": {
}
}
]
}
}

View File

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

View File

@ -1,32 +0,0 @@
{
"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

@ -1,24 +0,0 @@
{
"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

@ -1,78 +0,0 @@
{
"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

@ -1,19 +0,0 @@
{
"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

@ -1,50 +0,0 @@
{
"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

@ -1,18 +0,0 @@
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