Merge pull request #15 from harfang3dadmin/main

3.2.3 Release.
This commit is contained in:
HARFANG 3D (admin) 2022-07-25 09:32:04 +02:00 committed by GitHub
commit b2ff839cbd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 2905 additions and 73 deletions

View File

@ -101,6 +101,10 @@ if(MSVC)
#add_compile_options(/Od /Zi /Zo) #add_compile_options(/Od /Zi /Zo)
add_link_options(/DEBUG) add_link_options(/DEBUG)
#add_link_options(/LTCG) #add_link_options(/LTCG)
# Don't forget to remove this as soon as CMake is fixed.
# Tells MSVC to update __cplusplus value, otherwise it will be stuck to 199711L and libraries like bx (if updated) won't compile anymore even if we set CMAKE_CXX_STANDARD to C++14.
add_compile_options(/Zc:__cplusplus)
elseif(ANDROID) elseif(ANDROID)
add_compile_definitions(ANDROID) add_compile_definitions(ANDROID)
elseif(CMAKE_SYSTEM_NAME STREQUAL "Emscripten") elseif(CMAKE_SYSTEM_NAME STREQUAL "Emscripten")

View File

@ -1300,6 +1300,8 @@ def bind_scene(gen):
gen.bind_member(scene, 'hg::Scene::Environment environment') gen.bind_member(scene, 'hg::Scene::Environment environment')
gen.bind_method(scene, 'SetProbe', 'void', ['hg::TextureRef irradiance', 'hg::TextureRef radiance', 'hg::TextureRef brdf'])
# #
gen.bind_method(scene, 'GetCurrentCamera', 'hg::Node', []) gen.bind_method(scene, 'GetCurrentCamera', 'hg::Node', [])
gen.bind_method(scene, 'SetCurrentCamera', 'void', ['const hg::Node &camera']) gen.bind_method(scene, 'SetCurrentCamera', 'void', ['const hg::Node &camera'])
@ -1698,13 +1700,13 @@ static void __LuaVM_DestroyScripts(hg::SceneLuaVM *vm, const std::vector<hg::Scr
static hg::LuaObject __LuaVM_GetScriptEnv(hg::SceneLuaVM *vm, const hg::Script &script) { return vm->GetScriptEnv(script.ref); } static hg::LuaObject __LuaVM_GetScriptEnv(hg::SceneLuaVM *vm, const hg::Script &script) { return vm->GetScriptEnv(script.ref); }
static hg::LuaObject __LuaVM_GetScriptValue(hg::SceneLuaVM *vm, const hg::Script &script, const std::string &name) { return vm->GetScriptValue(script.ref, name); } static hg::LuaObject __LuaVM_GetScriptValue(hg::SceneLuaVM *vm, const hg::Script &script, const std::string &name) { return vm->GetScriptValue(script.ref, name); }
static bool __LuaVM_SetScriptValue(hg::SceneLuaVM *vm, const hg::Script &script, const std::string &name, const hg::LuaObject &value) { return vm->SetScriptValue(script.ref, name, value); } static bool __LuaVM_SetScriptValue(hg::SceneLuaVM *vm, const hg::Script &script, const std::string &name, const hg::LuaObject &value, bool notify = true) { return vm->SetScriptValue(script.ref, name, value, notify); }
''') ''')
gen.bind_method(vm, 'GetScriptEnv', 'hg::LuaObject', ['const hg::Script &script'], {'route': route_lambda('__LuaVM_GetScriptEnv')}) gen.bind_method(vm, 'GetScriptEnv', 'hg::LuaObject', ['const hg::Script &script'], {'route': route_lambda('__LuaVM_GetScriptEnv')})
gen.bind_method(vm, 'GetScriptValue', 'hg::LuaObject', ['const hg::Script &script', 'const std::string &name'], {'route': route_lambda('__LuaVM_GetScriptValue')}) gen.bind_method(vm, 'GetScriptValue', 'hg::LuaObject', ['const hg::Script &script', 'const std::string &name'], {'route': route_lambda('__LuaVM_GetScriptValue')})
gen.bind_method(vm, 'SetScriptValue', 'bool', ['const hg::Script &script', 'const std::string &name', 'const hg::LuaObject &value'], {'route': route_lambda('__LuaVM_SetScriptValue')}) gen.bind_method(vm, 'SetScriptValue', 'bool', ['const hg::Script &script', 'const std::string &name', 'const hg::LuaObject &value', '?bool notify'], {'route': route_lambda('__LuaVM_SetScriptValue')})
gen.bind_method_overloads(vm, 'Call', expand_std_vector_proto(gen, [ gen.bind_method_overloads(vm, 'Call', expand_std_vector_proto(gen, [
('bool', ['const hg::Script &script', 'const std::string &function', 'const std::vector<hg::LuaObject> &args', 'std::vector<hg::LuaObject> *ret_vals'], {'arg_out': ['ret_vals']}) ('bool', ['const hg::Script &script', 'const std::string &function', 'const std::vector<hg::LuaObject> &args', 'std::vector<hg::LuaObject> *ret_vals'], {'arg_out': ['ret_vals']})
@ -2658,8 +2660,8 @@ def bind_forward_pipeline(gen):
gen.end_class(fog) gen.end_class(fog)
# submit model to forward pipeline stage # submit model to forward pipeline stage
gen.bind_function('hg::SubmitModelToForwardPipeline', 'void', ['bgfx::ViewId &view_id', 'const hg::Model &mdl', 'const hg::ForwardPipeline &pipeline', 'const hg::PipelineProgram &prg', 'uint32_t prg_variant', #gen.bind_function('hg::SubmitModelToForwardPipeline', 'void', ['bgfx::ViewId &view_id', 'const hg::Model &mdl', 'const hg::ForwardPipeline &pipeline', 'const hg::PipelineProgram &prg', 'uint32_t prg_variant',
'uint8_t pipeline_stage', 'const hg::Color &ambient', 'const hg::ForwardPipelineLights &lights', 'const hg::ForwardPipelineFog &fog', 'const hg::Mat4 &mtx'], {'arg_in_out': ['view_id']}) #'uint8_t pipeline_stage', 'const hg::Color &ambient', 'const hg::ForwardPipelineLights &lights', 'const hg::ForwardPipelineFog &fog', 'const hg::Mat4 &mtx'], {'arg_in_out': ['view_id']})
def bind_file(gen): def bind_file(gen):
gen.add_include('foundation/file.h') gen.add_include('foundation/file.h')
@ -3609,11 +3611,10 @@ def bind_imgui(gen):
gen.bind_named_enum('ImGuiCond', ['ImGuiCond_Always', 'ImGuiCond_Once', 'ImGuiCond_FirstUseEver', 'ImGuiCond_Appearing'], 'int', namespace='') gen.bind_named_enum('ImGuiCond', ['ImGuiCond_Always', 'ImGuiCond_Once', 'ImGuiCond_FirstUseEver', 'ImGuiCond_Appearing'], 'int', namespace='')
gen.bind_named_enum('ImGuiMouseButton', [ gen.bind_named_enum('ImGuiMouseButton', [
'ImGuiPopupFlags_None', 'ImGuiMouseButton_Left',
'ImGuiPopupFlags_MouseButtonLeft', 'ImGuiPopupFlags_MouseButtonRight', 'ImGuiPopupFlags_MouseButtonMiddle', 'ImGuiMouseButton_Right',
'ImGuiPopupFlags_NoOpenOverExistingPopup', 'ImGuiPopupFlags_NoOpenOverItems', 'ImGuiMouseButton_Middle',
'ImGuiPopupFlags_AnyPopupId', 'ImGuiPopupFlags_AnyPopupLevel', 'ImGuiPopupFlags_AnyPopup'
], 'int', namespace='') ], 'int', namespace='')
gen.bind_named_enum('ImGuiHoveredFlags', [ gen.bind_named_enum('ImGuiHoveredFlags', [

View File

@ -7,4 +7,5 @@
* François Gutherz * François Gutherz
* Emmanuel Julien * Emmanuel Julien
* Eric Kernin * Eric Kernin
* Elie Michel
* Thomas "Scorpheus" Simonnet * Thomas "Scorpheus" Simonnet

View File

@ -1 +1 @@
A function taking a time value as parameter with no return value, see [man.UnitSystem]. A function taking a time value as parameter with no return value, see [man.CoordinateAndUnitSystem].

View File

@ -61,18 +61,18 @@ This file is a JSON file listing the supported features and additional uniforms.
The following features are supported and have the following effect on the compilation process. The following features are supported and have the following effect on the compilation process.
Feature | States | Preprocessor Directive | Uniform | Stage channel Feature | States | Preprocessor Directive | Uniform | Recommended channel
------- | ----------- | ---------------------- | ------- |-------------- ------- | ----------- | ---------------------- | ------- |--------------
OptionalBaseColorOpacityMap | 2 | USE_BASE_COLOR_OPACITY_MAP=[1 or 0] | uBaseOpacityMap | 0 OptionalBaseColorOpacityMap | 2 | USE_BASE_COLOR_OPACITY_MAP=[1 or 0] | uBaseOpacityMap | 0
OptionalDiffuseMap | 2 | USE_DIFFUSE_MAP=[1 or 0] | uDiffuseMap | 0
OptionalOcclusionRoughnessMetalnessMap | 2 | USE_OCCLUSION_ROUGHNESS_METALNESS_MAP=[1 or 0] | uOcclusionRoughnessMetalnessMap| 1 OptionalOcclusionRoughnessMetalnessMap | 2 | USE_OCCLUSION_ROUGHNESS_METALNESS_MAP=[1 or 0] | uOcclusionRoughnessMetalnessMap| 1
OptionalDiffuseMap | 2 | USE_DIFFUSE_MAP=[1 or 0] | uDiffuseMap | 3
OptionalSpecularMap | 2 | USE_SPECULAR_MAP=[1 or 0] | uSpecularMap | 1 OptionalSpecularMap | 2 | USE_SPECULAR_MAP=[1 or 0] | uSpecularMap | 1
OptionalNormalMap | 2 | USE_NORMAL_MAP=[1 or 0] | uNormalMap | 2
OptionalLightMap | 2 | USE_LIGHT_MAP=[1 or 0] | uLightMap | 3 OptionalLightMap | 2 | USE_LIGHT_MAP=[1 or 0] | uLightMap | 3
OptionalSelfMap | 2 | USE_SELF_MAP=[1 or 0] | uSelfMap | 4 OptionalSelfMap | 2 | USE_SELF_MAP=[1 or 0] | uSelfMap | 4
OptionalOpacityMap | 2 | USE_OPACITY_MAP=[1 or 0] | uOpacityMap | 5 OptionalOpacityMap | 2 | USE_OPACITY_MAP=[1 or 0] | uOpacityMap | 5
OptionalAmbientMap | 2 | USE_AMBIENT_MAP=[1 or 0] | uAmbientMap | 6 OptionalAmbientMap | 2 | USE_AMBIENT_MAP=[1 or 0] | uAmbientMap | 6
OptionalReflectionMap | 2 | USE_REFLECTION_MAP=[1 or 0] | uReflectionMap | 7 OptionalReflectionMap | 2 | USE_REFLECTION_MAP=[1 or 0] | uReflectionMap | 7
OptionalNormalMap | 2 | USE_NORMAL_MAP=[1 or 0] | uNormalMap | 2
NormalMapInWorldSpace | 2 | NORMAL_MAP_IN_WORLD_SPACE=[1 or 0] | - | - NormalMapInWorldSpace | 2 | NORMAL_MAP_IN_WORLD_SPACE=[1 or 0] | - | -
DiffuseUV1 | 2 | DIFFUSE_UV_CHANNEL=[1 or 0] | - | - DiffuseUV1 | 2 | DIFFUSE_UV_CHANNEL=[1 or 0] | - | -
SpecularUV1 | 2 | SPECULAR_UV_CHANNEL=[1 or 0] | - | - SpecularUV1 | 2 | SPECULAR_UV_CHANNEL=[1 or 0] | - | -

View File

@ -8,7 +8,7 @@ Once you have a functioning installation of Harfang for your language of choice:
Follow the following steps: Follow the following steps:
1. Download the tutorials from Github [here](https://github.com/harfang3d/tutorials-hg2.git) and unzip them to your computer _(eg. in `d:/tutorials-hg2`)_. 1. Download the tutorials from Github [here](https://github.com/harfang3d/tutorials-hg2.git) and unzip them to your computer _(eg. in `d:/tutorials-hg2`)_.
1. Download _assetc_ for your platform from [here](https://www.harfang3d.com/releases) to compile the tutorial resources. 1. Download _assetc_ for your platform from [here](https://dev.harfang3d.com/releases) to compile the tutorial resources.
1. Drag and drop the tutorial resources folder on the assetc executable **-OR-** execute assetc passing it the path to the tutorial resources folder _(eg. `assetc d:/tutorials-hg2/resources`)_. 1. Drag and drop the tutorial resources folder on the assetc executable **-OR-** execute assetc passing it the path to the tutorial resources folder _(eg. `assetc d:/tutorials-hg2/resources`)_.
![assetc drag & drop](/images/docs/${HG_VERSION}/assetc.gif) ![assetc drag & drop](/images/docs/${HG_VERSION}/assetc.gif)

View File

@ -0,0 +1,30 @@
#[[
Try to find libuuid
Provides the following target and variables:
* uuid : library target
* UUID_FOUND : set if libuuid was found
* UUID_INCLUDE_DIR : libuuid include diretory
* UUID_LIBRARY : libuuid library file
#]]
find_path(UUID_INCLUDE_DIR
NAMES uuid/uuid.h
HINTS ${UUID_ROOT_DIR}
)
find_library(UUID_LIBRARY
NAMES uuid
HINTS ${UUID_ROOT_DIR}
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(uuid REQUIRED_VARS UUID_LIBRARY UUID_INCLUDE_DIR)
mark_as_advanced(UUID_FOUND UUID_LIBRARY UUID_INCLUDE_DIR)
if(UUID_FOUND AND NOT TARGET uuid)
add_library(uuid UNKNOWN IMPORTED)
set_target_properties(uuid PROPERTIES
IMPORTED_LOCATION "${UUID_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES "${UUID_INCLUDE_DIR}"
)
endif()

View File

@ -133,6 +133,17 @@ static bool Package_file_is_EOF(Asset_ &asset) { return asset.pkg_file.cursor >=
// //
static generational_vector_list<Asset_> assets; static generational_vector_list<Asset_> assets;
std::string FindAssetPath(const char *name) {
std::lock_guard<std::mutex> lock(assets_mutex);
for (auto &p : assets_folders) {
const auto asset_path = hg::PathJoin({p, name});
if (IsFile(asset_path.c_str()))
return asset_path;
}
return "";
}
Asset OpenAsset(const char *name, bool silent) { Asset OpenAsset(const char *name, bool silent) {
std::lock_guard<std::mutex> lock(assets_mutex); std::lock_guard<std::mutex> lock(assets_mutex);

View File

@ -25,6 +25,7 @@ struct Asset {
gen_ref ref; gen_ref ref;
}; };
std::string FindAssetPath(const char *name);
Asset OpenAsset(const char *name, bool silent = false); Asset OpenAsset(const char *name, bool silent = false);
void Close(Asset asset); void Close(Asset asset);

View File

@ -386,6 +386,10 @@ static void ALChannelSetState(ALint src, const StereoSourceState &state, bool st
__AL_CALL(alSourcei(src, AL_LOOPING, !stream && state.repeat == SR_Loop ? AL_TRUE : AL_FALSE)); // [EJ20190512] looping is handled manually with streaming __AL_CALL(alSourcei(src, AL_LOOPING, !stream && state.repeat == SR_Loop ? AL_TRUE : AL_FALSE)); // [EJ20190512] looping is handled manually with streaming
__AL_CALL(alSource3f(src, AL_POSITION, state.panning, 0.f, sqrtf(1.f - state.panning * state.panning))); __AL_CALL(alSource3f(src, AL_POSITION, state.panning, 0.f, sqrtf(1.f - state.panning * state.panning)));
const ALfloat o[6] = {0, 0, -1, 0, 1, 0};
__AL_CALL(alSourcefv(src, AL_ORIENTATION, o));
const ALfloat v[3] = {0, 0, 0};
__AL_CALL(alSourcefv(src, AL_VELOCITY, v));
} }
static void ALChannelSetState(ALint src, const SpatializedSourceState &state, bool stream) { static void ALChannelSetState(ALint src, const SpatializedSourceState &state, bool stream) {

View File

@ -64,7 +64,6 @@ enum ForwardPipelineUniformTexture {
UT_BrdfMap, UT_BrdfMap,
UT_NoiseMap, UT_NoiseMap,
UT_AmbientOcclusion,
UT_LinearShadowMap, UT_LinearShadowMap,
UT_SpotShadowMap, UT_SpotShadowMap,
@ -176,7 +175,7 @@ void UpdateForwardPipelineProbe(
} }
void UpdateForwardPipelineNoise(ForwardPipeline &pipeline, Texture noise) { pipeline.uniform_textures[UT_NoiseMap].texture = noise; } void UpdateForwardPipelineNoise(ForwardPipeline &pipeline, Texture noise) { pipeline.uniform_textures[UT_NoiseMap].texture = noise; }
void UpdateForwardPipelineAO(ForwardPipeline &pipeline, Texture ao) { pipeline.uniform_textures[UT_AmbientOcclusion].texture = ao; } void UpdateForwardPipelineAO(ForwardPipeline &pipeline, Texture ao) { /*pipeline.uniform_textures[UT_AmbientOcclusion].texture = ao;*/ }
// //
static float backbuffer_ratio[bgfx::BackbufferRatio::Count] = {1.f, 2.f, 4.f, 8.f, 16.f, 0.5f}; static float backbuffer_ratio[bgfx::BackbufferRatio::Count] = {1.f, 2.f, 4.f, 8.f, 16.f, 0.5f};
@ -204,19 +203,6 @@ void UpdateForwardPipelineAAA(ForwardPipeline &pipeline, Texture ssgi, Texture s
} }
// //
void SubmitModelToForwardPipeline(bgfx::ViewId view_id, const Model &mdl, const ForwardPipeline &pipeline, const PipelineProgram &prg, uint32_t prg_variant,
uint8_t pipeline_stage, const Color &ambient, const ForwardPipelineLights &lights, const ForwardPipelineFog &fog, const Mat4 &mtx) {
const auto _mtx = to_bgfx(mtx);
/*
const auto pipeline_set_draw_env = [&](int mat_idx) {
UpdateForwardPipelineUniforms(pipeline.uniforms, ambient, lights, fog);
set_draw_env(mat_idx);
};
RenderModel(view_id, mdl, prg.variants[prg_variant][pipeline_stage], pipeline_set_draw_env, mtx);
*/
}
static Mat4 ComputeCropMatrix() { static Mat4 ComputeCropMatrix() {
const bgfx::Caps *caps = bgfx::getCaps(); const bgfx::Caps *caps = bgfx::getCaps();
const float sy = caps->originBottomLeft ? 0.5f : -0.5f; const float sy = caps->originBottomLeft ? 0.5f : -0.5f;
@ -494,13 +480,12 @@ ForwardPipeline CreateForwardPipeline(int shadow_map_resolution, bool spot_16bit
__ASSERT__(pipeline.uniform_values.size() == UV_Count); __ASSERT__(pipeline.uniform_values.size() == UV_Count);
pipeline.uniform_textures = { pipeline.uniform_textures = {
MakeUniformSetTexture("uIrradianceMap", {}, 7), MakeUniformSetTexture("uIrradianceMap", {}, 8),
MakeUniformSetTexture("uRadianceMap", {}, 8), MakeUniformSetTexture("uRadianceMap", {}, 9),
MakeUniformSetTexture("uSSIrradianceMap", {}, 9), MakeUniformSetTexture("uSSIrradianceMap", {}, 10),
MakeUniformSetTexture("uSSRadianceMap", {}, 10), MakeUniformSetTexture("uSSRadianceMap", {}, 11),
MakeUniformSetTexture("uBrdfMap", {}, 11), MakeUniformSetTexture("uBrdfMap", {}, 12),
MakeUniformSetTexture("uNoiseMap", {}, 12), MakeUniformSetTexture("uNoiseMap", {}, 13),
MakeUniformSetTexture("uAmbientOcclusion", {}, 13),
MakeUniformSetTexture("uLinearShadowMap", {BGFX_TEXTURE_RT | BGFX_SAMPLER_COMPARE_LEQUAL, pipeline.textures["linear_shadow_map"]}, 14), MakeUniformSetTexture("uLinearShadowMap", {BGFX_TEXTURE_RT | BGFX_SAMPLER_COMPARE_LEQUAL, pipeline.textures["linear_shadow_map"]}, 14),
MakeUniformSetTexture("uSpotShadowMap", {BGFX_TEXTURE_RT | BGFX_SAMPLER_COMPARE_LEQUAL, pipeline.textures["spot_shadow_map"]}, 15), MakeUniformSetTexture("uSpotShadowMap", {BGFX_TEXTURE_RT | BGFX_SAMPLER_COMPARE_LEQUAL, pipeline.textures["spot_shadow_map"]}, 15),
}; };

View File

@ -96,9 +96,6 @@ const PipelineInfo &GetForwardPipelineInfo();
// //
enum ForwardPipelineStage { FPS_AttributeBuffers, FPS_Basic, FPS_Advanced, FPS_DepthOnly }; enum ForwardPipelineStage { FPS_AttributeBuffers, FPS_Basic, FPS_Advanced, FPS_DepthOnly };
void SubmitModelToForwardPipeline(bgfx::ViewId view_id, const Model &mdl, const ForwardPipeline &pipeline, const PipelineProgram &prg, uint32_t prg_variant,
uint8_t pipeline_config_idx, const Color &ambient, const ForwardPipelineLights &lights, const ForwardPipelineFog &fog, const Mat4 &mtx);
// //
enum ForwardPipelineShadowPass { FPSP_Slot0LinearSplit0, FPSP_Slot0LinearSplit1, FPSP_Slot0LinearSplit2, FPSP_Slot0LinearSplit3, FPSP_Slot1Spot, FPSP_Count }; enum ForwardPipelineShadowPass { FPSP_Slot0LinearSplit0, FPSP_Slot0LinearSplit1, FPSP_Slot0LinearSplit2, FPSP_Slot0LinearSplit3, FPSP_Slot1Spot, FPSP_Count };

View File

@ -35,8 +35,7 @@ static HiZ _CreateHiZ(
hiz.pyramid_infos.format = bgfx::TextureFormat::RG32F; hiz.pyramid_infos.format = bgfx::TextureFormat::RG32F;
bgfx::TextureHandle handle = rb_factory.create_texture2d( bgfx::TextureHandle handle = rb_factory.create_texture2d(
ratio, hiz.pyramid_infos.numMips > 0, ratio, hiz.pyramid_infos.numMips > 0, hiz.pyramid_infos.numLayers, hiz.pyramid_infos.format, BGFX_TEXTURE_COMPUTE_WRITE | flags);
hiz.pyramid_infos.numLayers, hiz.pyramid_infos.format, BGFX_TEXTURE_COMPUTE_WRITE | flags);
hiz.pyramid = MakeTexture(handle, BGFX_TEXTURE_COMPUTE_WRITE | flags); hiz.pyramid = MakeTexture(handle, BGFX_TEXTURE_COMPUTE_WRITE | flags);
hiz.prg_copy = LoadComputeProgram(ir, ip, format("%1/shader/hiz_copy_cs.sc").arg(path)); hiz.prg_copy = LoadComputeProgram(ir, ip, format("%1/shader/hiz_copy_cs.sc").arg(path));
@ -66,11 +65,9 @@ void DestroyHiZ(HiZ &hiz) {
bgfx_Destroy(hiz.u_projection); bgfx_Destroy(hiz.u_projection);
} }
void ComputeHiZ( void ComputeHiZ(bgfx::ViewId &view_id, const hg::iVec2 &fb_size, const iRect &rect, const Mat44 &proj, float z_thickness, const Texture &depth, HiZ &hiz) {
bgfx::ViewId &view_id, const hg::iVec2 &fb_size, const iRect &rect, const Mat44 &proj, float z_thickness, const Texture &depth, HiZ &hiz) {
__ASSERT__(IsValid(hiz)); __ASSERT__(IsValid(hiz));
int div = 1; int div = 1;
switch (hiz.ratio) { switch (hiz.ratio) {
case bgfx::BackbufferRatio::Half: case bgfx::BackbufferRatio::Half:
@ -88,7 +85,8 @@ void ComputeHiZ(
default: default:
div = 1; div = 1;
break; break;
}; }
auto width = fb_size.x; auto width = fb_size.x;
auto height = fb_size.y; auto height = fb_size.y;
bgfx::calcTextureSize(hiz.pyramid_infos, width / div, height / div, hiz.pyramid_infos.depth, hiz.pyramid_infos.cubeMap, hiz.pyramid_infos.numMips, bgfx::calcTextureSize(hiz.pyramid_infos, width / div, height / div, hiz.pyramid_infos.depth, hiz.pyramid_infos.cubeMap, hiz.pyramid_infos.numMips,

View File

@ -15,6 +15,7 @@
#include "stb_image.h" #include "stb_image.h"
#include "stb_image_write.h" #include "stb_image_write.h"
#include "stb_image_resize.h"
namespace hg { namespace hg {
@ -143,7 +144,13 @@ void Picture::Clear() {
// TODO EJ implement these // TODO EJ implement these
Picture Crop(const Picture &picture, uint16_t width, uint16_t height) { return picture; } Picture Crop(const Picture &picture, uint16_t width, uint16_t height) { return picture; }
Picture Resize(const Picture &picture, uint16_t width, uint16_t height) { return picture; } Picture Resize(const Picture &picture, uint16_t width, uint16_t height) {
Picture pic(width, height, picture.GetFormat());
stbir_resize_uint8(picture.GetData(), picture.GetWidth(), picture.GetHeight(), picture.GetWidth() * size_of(picture.GetFormat()),
pic.GetData(), pic.GetWidth(), pic.GetHeight(), pic.GetWidth() * size_of(pic.GetFormat()), size_of(pic.GetFormat()));
return pic;
}
// //
Color GetPixelRGBA(const Picture &pic, uint16_t x, uint16_t y) { Color GetPixelRGBA(const Picture &pic, uint16_t x, uint16_t y) {

View File

@ -400,7 +400,8 @@ void SetMaterialSkinning(Material &m, bool enable);
bool GetMaterialAlphaCut(const Material &m); bool GetMaterialAlphaCut(const Material &m);
void SetMaterialAlphaCut(Material &m, bool enable); void SetMaterialAlphaCut(Material &m, bool enable);
/// Compute a render state to control subsequent render calls culling mode, blending mode, Z mask, etc... The same render state can be used by different render calls. /// Compute a render state to control subsequent render calls culling mode, blending mode, Z mask, etc... The same render state can be used by different render
/// calls.
/// @see DrawLines, DrawTriangles and DrawModel. /// @see DrawLines, DrawTriangles and DrawModel.
RenderState ComputeRenderState(BlendMode blend, bool write_z, bool write_r = true, bool write_g = true, bool write_b = true, bool write_a = true); RenderState ComputeRenderState(BlendMode blend, bool write_z, bool write_r = true, bool write_g = true, bool write_b = true, bool write_a = true);
RenderState ComputeRenderState(BlendMode blend, DepthTest test = DT_Less, FaceCulling culling = FC_Clockwise, bool write_z = true, bool write_r = true, RenderState ComputeRenderState(BlendMode blend, DepthTest test = DT_Less, FaceCulling culling = FC_Clockwise, bool write_z = true, bool write_r = true,
@ -526,7 +527,8 @@ TextureRef LoadTextureFromAssets(const char *path, uint64_t flags, PipelineResou
/// Capture a texture content to a Picture. Return the frame counter at which the capture will be complete. /// Capture a texture content to a Picture. Return the frame counter at which the capture will be complete.
/// A Picture object can be accessed by the CPU. /// A Picture object can be accessed by the CPU.
/// This function is asynchronous and its result will not be available until the returned frame counter is equal or greater to the frame counter returned by Frame. /// This function is asynchronous and its result will not be available until the returned frame counter is equal or greater to the frame counter returned by
/// Frame.
uint32_t CaptureTexture(const PipelineResources &resources, const TextureRef &t, Picture &pic); uint32_t CaptureTexture(const PipelineResources &resources, const TextureRef &t, Picture &pic);
MaterialRef LoadMaterialRef(const Reader &ir, const Handle &h, const char *path, const Reader &deps_ir, const ReadProvider &deps_ip, MaterialRef LoadMaterialRef(const Reader &ir, const Handle &h, const char *path, const Reader &deps_ir, const ReadProvider &deps_ip,

View File

@ -30,6 +30,14 @@ Scene::~Scene() {
scene_ref->scene = nullptr; scene_ref->scene = nullptr;
} }
//
void Scene::SetProbe(TextureRef irradiance, TextureRef radiance, TextureRef brdf) {
environment.probe = {};
environment.probe.irradiance_map = irradiance;
environment.probe.radiance_map = radiance;
environment.brdf_map = brdf;
}
// //
static void _ResizeComponents(std::vector<ComponentRef> &cs) { static void _ResizeComponents(std::vector<ComponentRef> &cs) {
ptrdiff_t i; ptrdiff_t i;
@ -2631,6 +2639,24 @@ void SetAnimableNodePropertyColor(Scene &scene, NodeRef ref, const std::string &
} }
} }
//
std::vector<hg::Material *> Scene::GetMaterialsWithName(const std::string &name) {
std::vector<hg::Material *> mats;
mats.reserve(objects.size() / 8); // guesstimate
for (auto ref = objects.first_ref(); objects.is_valid(ref); ref = objects.next_ref(ref)) {
auto &obj = objects[ref.idx];
const auto mat_count = obj.material_infos.size();
for (size_t i = 0; i < mat_count; ++i)
if (obj.material_infos[i].name == name)
mats.push_back(&obj.materials[i]);
}
return mats;
}
// //
std::string GetAnimableNodePropertyString(const Scene &scene, NodeRef ref, const std::string &name) { std::string GetAnimableNodePropertyString(const Scene &scene, NodeRef ref, const std::string &name) {
if (const auto node = scene.GetNode(ref)) { if (const auto node = scene.GetNode(ref)) {

View File

@ -355,6 +355,8 @@ public:
Object GetNodeObject(NodeRef ref) const { return {scene_ref, GetNodeObjectRef(ref)}; } Object GetNodeObject(NodeRef ref) const { return {scene_ref, GetNodeObjectRef(ref)}; }
void SetNodeObject(NodeRef ref, const Object &v) { SetNodeObject(ref, v.ref); } void SetNodeObject(NodeRef ref, const Object &v) { SetNodeObject(ref, v.ref); }
std::vector<hg::Material *> GetMaterialsWithName(const std::string &name);
// light component // light component
Light CreateLight(); Light CreateLight();
void DestroyLight(ComponentRef ref); void DestroyLight(ComponentRef ref);
@ -584,6 +586,8 @@ public:
Environment environment{}; Environment environment{};
void SetProbe(TextureRef irradiance, TextureRef radiance, TextureRef brdf);
// scene state // scene state
Node GetCurrentCamera() const { return {scene_ref, current_camera}; } Node GetCurrentCamera() const { return {scene_ref, current_camera}; }
void SetCurrentCamera(NodeRef ref) { current_camera = ref; } void SetCurrentCamera(NodeRef ref) { current_camera = ref; }

View File

@ -257,7 +257,7 @@ void SceneBullet3Physics::NodeCreatePhysics(const Node &node, const Reader &ir,
} else if (type == CT_Capsule) { } else if (type == CT_Capsule) {
shapes.push_back(new btCapsuleShape(size.x, size.y)); shapes.push_back(new btCapsuleShape(size.x, size.y));
} else if (type == CT_Cylinder) { } else if (type == CT_Cylinder) {
shapes.push_back(new btCylinderShape(btVector3(size.x, size.y, size.z))); shapes.push_back(new btCylinderShape(btVector3(size.x, size.y * 0.5f, size.z)));
} else if (type == CT_Mesh) { } else if (type == CT_Mesh) {
if (auto tree = LoadCollisionTree(ir, ip, col.GetCollisionResource().c_str())) if (auto tree = LoadCollisionTree(ir, ip, col.GetCollisionResource().c_str()))
shapes.push_back(tree); shapes.push_back(tree);

View File

@ -178,13 +178,17 @@ LuaObject SceneLuaVM::GetScriptValue(ComponentRef ref, const std::string &name)
return i == std::end(lua_scripts) ? LuaObject{} : Get(i->second, name); return i == std::end(lua_scripts) ? LuaObject{} : Get(i->second, name);
} }
bool SceneLuaVM::SetScriptValue(ComponentRef ref, const std::string &name, const LuaObject &v) { bool SceneLuaVM::SetScriptValue(ComponentRef ref, const std::string &name, const LuaObject &v, bool notify) {
auto i = lua_scripts.find(ref); auto i = lua_scripts.find(ref);
if (i == std::end(lua_scripts)) if (i == std::end(lua_scripts))
return false; return false;
SetForeign(i->second, name, v); SetForeign(i->second, name, v);
if (notify)
Call(ref, "OnSetScriptValue", {MakeLuaObj(L, name)});
return true; return true;
} }
@ -312,8 +316,10 @@ std::vector<ComponentRef> SceneLuaVM::GarbageCollect(const Scene &scene) const {
void SceneLuaVM::DestroyScripts(const std::vector<ComponentRef> &scripts) { void SceneLuaVM::DestroyScripts(const std::vector<ComponentRef> &scripts) {
for (auto ref : scripts) { for (auto ref : scripts) {
auto i = lua_scripts.find(ref); auto i = lua_scripts.find(ref);
if (i != std::end(lua_scripts)) if (i != std::end(lua_scripts)) {
Call(ref, "OnDestroy", {});
lua_scripts.erase(i); lua_scripts.erase(i);
}
} }
} }

View File

@ -65,7 +65,7 @@ public:
/// Return the value of a script variable. /// Return the value of a script variable.
LuaObject GetScriptValue(ComponentRef script, const std::string &name) const; LuaObject GetScriptValue(ComponentRef script, const std::string &name) const;
/// Set the value of a script variable. /// Set the value of a script variable.
bool SetScriptValue(ComponentRef script, const std::string &name, const LuaObject &value); bool SetScriptValue(ComponentRef script, const std::string &name, const LuaObject &value, bool notify = true);
/// Return the VM lua state. /// Return the VM lua state.
lua_State *GetL() const { return L; } lua_State *GetL() const { return L; }

View File

@ -118,16 +118,6 @@ static void CallScriptDetachFromNode(SceneLuaVM &vm, Node &node, const Script &s
// //
static size_t SceneScriptsDestroyGarbageCall(SceneLuaVM &vm, Scene &scene) { static size_t SceneScriptsDestroyGarbageCall(SceneLuaVM &vm, Scene &scene) {
const auto garbage = vm.GarbageCollect(scene); const auto garbage = vm.GarbageCollect(scene);
for (auto s : garbage) {
auto env = vm.GetScriptEnv(s);
if (auto on_destroy = Get(env, "OnDestroy")) {
on_destroy.Push();
hg_lua_OnDestroy(env.L(), -1);
}
}
vm.DestroyScripts(garbage); vm.DestroyScripts(garbage);
return garbage.size(); return garbage.size();
} }

File diff suppressed because it is too large Load Diff

View File

@ -164,6 +164,7 @@ set_property(TARGET foundation PROPERTY PUBLIC_HEADER "${HDRS}")
set_target_properties(foundation PROPERTIES FOLDER "harfang") set_target_properties(foundation PROPERTIES FOLDER "harfang")
if(NOT WIN32) if(NOT WIN32)
find_package(uuid REQUIRED)
target_link_libraries(foundation PUBLIC uuid) target_link_libraries(foundation PUBLIC uuid)
else() else()
target_link_libraries(foundation PUBLIC Iphlpapi) target_link_libraries(foundation PUBLIC Iphlpapi)

View File

@ -156,7 +156,7 @@ bool LineIntersectCone(const Vec3 &a, const Vec3 &v, const Vec3 &c, const Vec3 &
if (((t0 < h0) || (t0 > h1)) && ((t1 < h0) || (t1 > h1))) { if (((t0 < h0) || (t0 > h1)) && ((t1 < h0) || (t1 > h1))) {
return false; return false;
} }
} else if (dvac > h) { } else if (ddac > h) {
return false; return false;
} }

View File

@ -15,6 +15,9 @@ static bool log_is_detailed = false;
void set_log_level(int level) { log_level = level; } void set_log_level(int level) { log_level = level; }
void set_log_detailed(bool is_detailed) { log_is_detailed = is_detailed; } void set_log_detailed(bool is_detailed) { log_is_detailed = is_detailed; }
int get_log_level() { return log_level; }
bool get_log_detailed() { return log_is_detailed; }
// //
static void default_log_hook(const char *msg, int mask, const char *details, void *user) { static void default_log_hook(const char *msg, int mask, const char *details, void *user) {

View File

@ -17,5 +17,7 @@ void set_log_hook(void (*on_log)(const char *msg, int mask, const char *details,
void set_log_level(int log_level); void set_log_level(int log_level);
/// Enable detailed log output. /// Enable detailed log output.
void set_log_detailed(bool is_detailed); void set_log_detailed(bool is_detailed);
int get_log_level();
bool get_log_detailed();
} // namespace hg } // namespace hg

View File

@ -9,6 +9,7 @@
#include <cctype> #include <cctype>
#include <locale> #include <locale>
#include <sstream> #include <sstream>
#include <memory>
#include <codecvt> #include <codecvt>

View File

@ -221,6 +221,14 @@ bool SaveFileDialog(const std::string &title, const std::vector<hg::FileFilter>
} }
pFileSave->Release(); pFileSave->Release();
} }
// ensure extension is present
const auto ext = hg::GetFileExtension(output);
if (ext.empty() && !filters.empty())
if (filters[0].pattern.size() > 2)
output += &filters[0].pattern[1];
return SUCCEEDED(hr); return SUCCEEDED(hr);
} }

View File

@ -129,6 +129,7 @@ TEST(BGFX, RenderModelNoPipeline) {
} }
// //
/*
TEST(BGFX, SubmitModelToForwardPipeline) { TEST(BGFX, SubmitModelToForwardPipeline) {
InputInit(); InputInit();
@ -192,6 +193,7 @@ TEST(BGFX, SubmitModelToForwardPipeline) {
RenderShutdown(); RenderShutdown();
DestroyWindow(window); DestroyWindow(window);
} }
*/
// //
TEST(BGFX, AddModelToSceneAndSubmitToForwardPipeline) { TEST(BGFX, AddModelToSceneAndSubmitToForwardPipeline) {

View File

@ -1 +1 @@
3.2.2 3.2.3

View File

@ -13,7 +13,7 @@ See https://www.harfang3d.com/license for licensing terms.
| **Quickstart** | **Quickstart**
1. Download the tutorials https://github.com/harfang3d/tutorials-hg2 and unzip them to your computer (eg. *d:/tutorials-hg2*). 1. Download the tutorials https://github.com/harfang3d/tutorials-hg2 and unzip them to your computer (eg. *d:/tutorials-hg2*).
2. To compile the tutorial resources, download **assetc** for your platform: https://www.harfang3d.com/releases/ 2. To compile the tutorial resources, download **assetc** for your platform: https://dev.harfang3d.com/releases/
3. Drag and drop the tutorial resources folder on the **`assetc** executable -OR- execute **assetc** passing it the path to the tutorial resources folder (eg. *assetc d:/tutorials-hg2/resources*). 3. Drag and drop the tutorial resources folder on the **`assetc** executable -OR- execute **assetc** passing it the path to the tutorial resources folder (eg. *assetc d:/tutorials-hg2/resources*).
.. image:: https://raw.githubusercontent.com/harfang3d/image-storage/main/tutorials/assetc.gif .. image:: https://raw.githubusercontent.com/harfang3d/image-storage/main/tutorials/assetc.gif

View File

@ -56,6 +56,12 @@ Physics API
Audio API Audio API
* Play/stream WAV/OGG formats * Play/stream WAV/OGG formats
* 3D audio spatialization * 3D audio spatialization
Languages supported
* C++
* Python _(3.2+)_
* Lua _(5.3)_
* Go _(1+, experimental)_
<a name="subsection_1b"></a> <a name="subsection_1b"></a>
## Screenshots ## Screenshots
@ -84,6 +90,7 @@ https://dev.harfang3d.com/releases
* CPython 3.2+ * CPython 3.2+
* Go 1+ _(for Harfang Go module)_ * Go 1+ _(for Harfang Go module)_
* Doxygen _(for Harfang C++ SDK documentation)_ * Doxygen _(for Harfang C++ SDK documentation)_
* Autodesk FBX SDK _(for FBX Converter)_
### Windows ### Windows
* Visual Studio 2019 _(C++ compiler and IDE)_ * Visual Studio 2019 _(C++ compiler and IDE)_

View File

@ -1,3 +1,49 @@
# [3.2.3] - 2022-08-13
This minor release brings several fixes to the rendering, physics, engine, foundation and tools.
### Framework integration and source code maintenance
- Added a CMake option to force MSVC to use updated __cplusplus macro.
- Build fixes for GCC 12.
### Toolchain
- Added a way to select the input channel from an input texture within a `construct` when processing textures in **Assetc**.
- Changed `BC6H_UF16` into `BC6H_SF16` to produce a valid DDS from a HDR file.
- **Assetc** now parses the shaders to check their dependencies for any modification and triggers a rebuild if needed.
- Properly quote **Luac** and **Recastc** invocations to support space in arguments.
### Binding
- Fixed `ImGuiMouseButton` enums (`ImGuiMouseButton_Left`, `ImGuiMouseButton_Right`, `ImGuiMouseButton_Middle`).
- Added a `SetProbe` function to set the radiance and irradiance map to a scene.
- :warning: Deprecated `SubmitModelToForwardPipeline`.
### Engine
- Added `GetMaterialsWithName`.
- Added `GetFullPathAsset`
- Added `get_log_level`, `get_log_detailed` functions.
- Fixed the ray/cone intersection.
- Ensure an extension is specified before returning output path from `SaveFileDialog`.
- Fixed the reserved texture units used by the **AAA** pipeline (see https://dev.harfang3d.com/docs/3.2.3/man.pipelineshader/). As a consequence, the `core\` folder will need to be updated if your project is using the **Forward** or **AAA** rendering pipelines.
- Fixed a nasty issue in forward pipeline texture table.
- :warning: Deprecated `UpdateForwardPipelineAO` and `UT_AmbientOcclusion`.
### Physics
- Fixed #14, Bullet uses half extend for cylinders.
### Audio
- Fixed #13, properly reset OpenAL source velocity when starting a stereo sound.
### Documentation
- Fixed a dead link in the API documentation.
- URLs updates (Quickstart, Wheel description, Readme file).
# [3.2.2] - 2022-06-03 # [3.2.2] - 2022-06-03
This minor release brings several fixes, a better implementation of the AAA rendering pipeline including probe reprojection and a more stable screen space raytracer.<br> This minor release brings several fixes, a better implementation of the AAA rendering pipeline including probe reprojection and a more stable screen space raytracer.<br>

View File

@ -714,7 +714,7 @@ static std::string Get_texconv_Format(const std::string &f) {
if (f == "BC5") if (f == "BC5")
return "BC5_UNORM"; return "BC5_UNORM";
if (f == "BC6H") if (f == "BC6H")
return "BC6H_UF16"; return "BC6H_SF16";
if (f == "BC7") if (f == "BC7")
return "BC7_UNORM"; return "BC7_UNORM";
return ""; return "";
@ -743,6 +743,10 @@ static bool PreprocessTexture(const json &i_preprocess_texture, std::map<std::st
dependencies.insert(path); // swizzle from input texture dependencies.insert(path); // swizzle from input texture
else else
dependencies.insert(channel_v); // swizzle from foreign texture dependencies.insert(channel_v); // swizzle from foreign texture
} else if (v.is_object()) { // channel or texture path
const auto dep_path = v["path"].get<std::string>();
const auto channel_v = v["channel"].get<std::string>();
dependencies.insert(dep_path);
} }
} }
} else { } else {
@ -785,8 +789,8 @@ static bool PreprocessTexture(const json &i_preprocess_texture, std::map<std::st
// conform dependencies // conform dependencies
for (auto i : picture_dependencies) for (auto i : picture_dependencies)
if (i.second.GetWidth() != out_width && i.second.GetHeight() != out_height) { if (i.second.GetWidth() != out_width && i.second.GetHeight() != out_height) {
error(format("Cannot construct '%1' due to dependency '%2' with incompatible resolution").arg(path).arg(i.first)); // resize
return false; picture_dependencies[i.first] = hg::Resize(i.second, out_width, out_height);
} }
// //
@ -872,6 +876,35 @@ static bool PreprocessTexture(const json &i_preprocess_texture, std::map<std::st
in_stride = size_of(in_pic.GetFormat()); in_stride = size_of(in_pic.GetFormat());
} }
for (uint16_t y = 0; y < out_height; ++y)
for (uint16_t x = 0; x < out_width; ++x) {
*out = *in;
in += in_stride;
out += out_stride;
}
} else if (v.is_object()) { // channel and texture path
const auto dep_path = v["path"].get<std::string>();
auto &in_pic = picture_dependencies[dep_path];
const char *channel_names[] = {"R", "G", "B", "A"};
const auto input_channel_v = v["channel"].get<std::string>();
size_t input_channel = 5;
for (size_t c = 0; c < 4; ++c)
if (input_channel_v == channel_names[c]) {
input_channel = c;
break;
}
if (GetChannelCount(in_pic.GetFormat()) <= input_channel) {
error(format("Cannot construct '%1' due to '%2' missing %3 channel").arg(path).arg(dep_path).arg(input_channel));
return false;
}
uint8_t *in = in_pic.GetData() + input_channel;
size_t in_stride = size_of(in_pic.GetFormat());
for (uint16_t y = 0; y < out_height; ++y) for (uint16_t y = 0; y < out_height; ++y)
for (uint16_t x = 0; x < out_width; ++x) { for (uint16_t x = 0; x < out_width; ++x) {
*out = *in; *out = *in;
@ -1096,6 +1129,28 @@ void Geometry(std::map<std::string, Hash> &hashes, const std::string &path) {
} }
} }
//
void GatherShaderDependencies(const std::string &path, std::set<std::string> &deps, const std::string &base) {
const auto rel_path = base + path;
if (deps.find(rel_path) != std::end(deps))
return; // processed already, don't need no cyclic references
deps.insert(rel_path);
const auto src = hg::FileToString(FullInputPath(rel_path).c_str());
static std::regex include_regex("#include\\s*(?:\"|<)(.+)(?:\"|>)");
const auto base_path = hg::GetFilePath(rel_path); // #include directives are relative to the current source
for (std::sregex_iterator i = std::sregex_iterator(src.begin(), src.end(), include_regex); i != std::sregex_iterator(); ++i)
GatherShaderDependencies((*i)[1], deps, base_path); // recurse down the dependency tree
}
void GatherShaderDependencies(const std::set<std::string> &paths, std::set<std::string> &deps) {
for (const auto &path : paths)
GatherShaderDependencies(path, deps, "");
}
// //
static void BuildComputeShader(std::map<std::string, Hash> &hashes, const std::string &cs_path, const std::string &defines) { static void BuildComputeShader(std::map<std::string, Hash> &hashes, const std::string &cs_path, const std::string &defines) {
ProfilerPerfSection perf("Command/ComputeShader"); ProfilerPerfSection perf("Command/ComputeShader");
@ -1128,7 +1183,10 @@ static void BuildComputeShader(std::map<std::string, Hash> &hashes, const std::s
if (toolchain.shaderc.empty()) { if (toolchain.shaderc.empty()) {
warn(" Skipping, no compiler found for compute resource"); warn(" Skipping, no compiler found for compute resource");
} else { } else {
if (NeedsCompilation(hashes, {cs_path}, {cs_path}, cs_build_ctx)) { std::set<std::string> inputs;
GatherShaderDependencies({cs_path}, inputs);
if (NeedsCompilation(hashes, inputs, {cs_path}, cs_build_ctx)) {
if (!cs_profile.empty()) // GLES profile must be empty... if (!cs_profile.empty()) // GLES profile must be empty...
cs_profile = "-p " + cs_profile; cs_profile = "-p " + cs_profile;
@ -1194,7 +1252,10 @@ static void BuildShader(std::map<std::string, Hash> &hashes, const std::string &
if (toolchain.shaderc.empty()) { if (toolchain.shaderc.empty()) {
warn(" Skipping, no compiler found for shader resource"); warn(" Skipping, no compiler found for shader resource");
} else { } else {
if (NeedsCompilation(hashes, {vs_path, varying_path}, {vs_name}, vs_build_ctx)) { std::set<std::string> inputs;
GatherShaderDependencies({vs_path, varying_path}, inputs);
if (NeedsCompilation(hashes, inputs, {vs_name}, vs_build_ctx)) {
if (!vs_profile.empty()) // GLES profile must be empty... if (!vs_profile.empty()) // GLES profile must be empty...
vs_profile = "-p " + vs_profile; vs_profile = "-p " + vs_profile;
@ -1232,7 +1293,10 @@ static void BuildShader(std::map<std::string, Hash> &hashes, const std::string &
if (toolchain.shaderc.empty()) { if (toolchain.shaderc.empty()) {
warn(" Skipping, no compiler found for shader resource"); warn(" Skipping, no compiler found for shader resource");
} else { } else {
if (NeedsCompilation(hashes, {fs_path, varying_path}, {fs_name}, fs_build_ctx)) { std::set<std::string> inputs;
GatherShaderDependencies({fs_path, varying_path}, inputs);
if (NeedsCompilation(hashes, inputs, {fs_name}, fs_build_ctx)) {
if (!fs_profile.empty()) if (!fs_profile.empty())
fs_profile = "-p " + fs_profile; fs_profile = "-p " + fs_profile;
@ -1387,7 +1451,7 @@ static void LuaScript(std::map<std::string, Hash> &hashes, const std::string &pa
MkOutputTree(path); MkOutputTree(path);
CleanOutputs({path}); CleanOutputs({path});
const auto cmd = format("%1 -o %3 -s %2").arg(toolchain.luac).arg(src).arg(dst); const auto cmd = format("%1 -o \"%3\" -s \"%2\"").arg(toolchain.luac).arg(src).arg(dst);
PushAsyncProcessTask(path, cmd, cwd); PushAsyncProcessTask(path, cmd, cwd);
} else { } else {
debug(" [O] Lua script up to date"); debug(" [O] Lua script up to date");
@ -1418,7 +1482,7 @@ static void PathFinding(std::map<std::string, Hash> &hashes, const std::string &
MkOutputTree(path); MkOutputTree(path);
CleanOutputs({path}); CleanOutputs({path});
const auto cmd = format("%1 %2 %3 -root %4").arg(toolchain.recastc).arg(src).arg(dst).arg(input_dir); const auto cmd = format("%1 \"%2\" \"%3\" -root \"%4\"").arg(toolchain.recastc).arg(src).arg(dst).arg(input_dir);
PushAsyncProcessTask(path, cmd, GetCurrentWorkingDirectory()); PushAsyncProcessTask(path, cmd, GetCurrentWorkingDirectory());
} else { } else {
debug(" [O] Pathfinding resource up to date"); debug(" [O] Pathfinding resource up to date");