various UI and rt changes
This commit is contained in:
+12
-8
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.7...3.23)
|
|||||||
if(${CMAKE_VERSION} VERSION_LESS 3.12)
|
if(${CMAKE_VERSION} VERSION_LESS 3.12)
|
||||||
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
|
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
|
||||||
endif()
|
endif()
|
||||||
set(CMAKE_CXX_STANDARD 20)
|
set(CMAKE_CXX_STANDARD 23)
|
||||||
# Handle superbuild first
|
# Handle superbuild first
|
||||||
option (USE_SUPERBUILD "Whether or not a superbuild should be invoked" ON)
|
option (USE_SUPERBUILD "Whether or not a superbuild should be invoked" ON)
|
||||||
|
|
||||||
@@ -46,6 +46,7 @@ find_package(assimp CONFIG REQUIRED)
|
|||||||
find_package(Stb REQUIRED)
|
find_package(Stb REQUIRED)
|
||||||
find_package(EnTT CONFIG REQUIRED)
|
find_package(EnTT CONFIG REQUIRED)
|
||||||
find_package(FreeType CONFIG REQUIRED)
|
find_package(FreeType CONFIG REQUIRED)
|
||||||
|
find_package(harfbuzz CONFIG REQUIRED)
|
||||||
find_package(glfw3 CONFIG REQUIRED)
|
find_package(glfw3 CONFIG REQUIRED)
|
||||||
find_package(glm CONFIG REQUIRED)
|
find_package(glm CONFIG REQUIRED)
|
||||||
find_package(Ktx CONFIG REQUIRED)
|
find_package(Ktx CONFIG REQUIRED)
|
||||||
@@ -66,11 +67,14 @@ add_library(Engine SHARED "")
|
|||||||
|
|
||||||
target_compile_definitions(Engine PRIVATE GLFW_WINDOWS)
|
target_compile_definitions(Engine PRIVATE GLFW_WINDOWS)
|
||||||
target_include_directories(Engine PRIVATE src/Engine)
|
target_include_directories(Engine PRIVATE src/Engine)
|
||||||
|
target_include_directories(Engine PRIVATE ${VCPKG_INSTALLED_DIR}/x64-windows/include/)
|
||||||
target_link_libraries(Engine PUBLIC Vulkan::Vulkan)
|
target_link_libraries(Engine PUBLIC Vulkan::Vulkan)
|
||||||
target_link_libraries(Engine PUBLIC EnTT::EnTT)
|
target_link_libraries(Engine PUBLIC EnTT::EnTT)
|
||||||
target_link_libraries(Engine PUBLIC glfw)
|
target_link_libraries(Engine PUBLIC glfw)
|
||||||
target_link_libraries(Engine PUBLIC glm::glm)
|
target_link_libraries(Engine PUBLIC glm::glm)
|
||||||
target_link_libraries(Engine PUBLIC freetype)
|
target_link_libraries(Engine PUBLIC freetype)
|
||||||
|
target_link_libraries(Engine PUBLIC harfbuzz::harfbuzz)
|
||||||
|
target_link_libraries(Engine PUBLIC harfbuzz::harfbuzz-subset)
|
||||||
target_link_libraries(Engine PUBLIC assimp::assimp)
|
target_link_libraries(Engine PUBLIC assimp::assimp)
|
||||||
target_link_libraries(Engine PUBLIC KTX::ktx)
|
target_link_libraries(Engine PUBLIC KTX::ktx)
|
||||||
target_link_libraries(Engine PUBLIC nlohmann_json::nlohmann_json)
|
target_link_libraries(Engine PUBLIC nlohmann_json::nlohmann_json)
|
||||||
@@ -78,8 +82,8 @@ target_link_libraries(Engine PUBLIC crcpp)
|
|||||||
target_link_libraries(Engine PUBLIC fmt::fmt)
|
target_link_libraries(Engine PUBLIC fmt::fmt)
|
||||||
target_link_libraries(Engine PUBLIC unofficial::lunasvg::lunasvg)
|
target_link_libraries(Engine PUBLIC unofficial::lunasvg::lunasvg)
|
||||||
target_link_libraries(Engine PUBLIC GPUOpen::VulkanMemoryAllocator)
|
target_link_libraries(Engine PUBLIC GPUOpen::VulkanMemoryAllocator)
|
||||||
|
target_link_libraries(Engine PUBLIC ${VCPKG_INSTALLED_DIR}/x64-windows/lib/slang.lib)
|
||||||
|
|
||||||
target_link_libraries(Engine PUBLIC slang)
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
target_link_libraries(Engine PUBLIC metal)
|
target_link_libraries(Engine PUBLIC metal)
|
||||||
SET(CMAKE_OSX_DEPLOYMENT_TARGET 14.3)
|
SET(CMAKE_OSX_DEPLOYMENT_TARGET 14.3)
|
||||||
@@ -105,8 +109,8 @@ target_include_directories(Benchmark PRIVATE src/Benchmark)
|
|||||||
|
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||||
target_compile_options(Engine PUBLIC /std:c++20 /Zi /MP14 /W4 /wd4505)
|
target_compile_options(Engine PUBLIC /Zi /MP14 /W4 /wd4505)
|
||||||
target_compile_options(Editor PUBLIC /std:c++20 /Zi /MP14 /W4)
|
target_compile_options(Editor PUBLIC /Zi /MP14 /W4)
|
||||||
target_sources(Engine INTERFACE
|
target_sources(Engine INTERFACE
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/Seele.natvis>
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/Seele.natvis>
|
||||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_PREFIX}/Seele/Seele.natvis>
|
$<INSTALL_INTERFACE:${CMAKE_INSTALL_PREFIX}/Seele/Seele.natvis>
|
||||||
@@ -115,8 +119,8 @@ if(MSVC)
|
|||||||
Seele.natvis
|
Seele.natvis
|
||||||
DESTINATION Seele/)
|
DESTINATION Seele/)
|
||||||
else()
|
else()
|
||||||
target_compile_options(Engine PUBLIC -g -Wall -Wextra -Wno-error -pedantic -std=c++20 -Wno-missing-field-initializers -Wno-unused-function)
|
target_compile_options(Engine PUBLIC -g -Wall -Wextra -Wno-error -pedantic -Wno-missing-field-initializers -Wno-unused-function)
|
||||||
target_compile_options(Editor PUBLIC -g -Wall -Wextra -Wno-error -pedantic -std=c++20)
|
target_compile_options(Editor PUBLIC -g -Wall -Wextra -Wno-error -pedantic)
|
||||||
endif()
|
endif()
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
#Metal lib throws that internally for some reason
|
#Metal lib throws that internally for some reason
|
||||||
@@ -132,8 +136,8 @@ add_subdirectory(src/)
|
|||||||
if(WIN32)
|
if(WIN32)
|
||||||
add_custom_target(dll_copy ALL
|
add_custom_target(dll_copy ALL
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_RUNTIME_DLLS:Engine> $<TARGET_FILE_DIR:Editor>
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_RUNTIME_DLLS:Engine> $<TARGET_FILE_DIR:Editor>
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${SLANG_ROOT}bin/slang.dll $<TARGET_FILE_DIR:Editor>
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${VCPKG_INSTALLED_DIR}/x64-windows/bin/slang.dll $<TARGET_FILE_DIR:Editor>
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${SLANG_ROOT}bin/slang-glslang.dll $<TARGET_FILE_DIR:Editor>
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${VCPKG_INSTALLED_DIR}/x64-windows/bin/slang-glslang.dll $<TARGET_FILE_DIR:Editor>
|
||||||
COMMAND_EXPAND_LISTS
|
COMMAND_EXPAND_LISTS
|
||||||
DEPENDS Editor)
|
DEPENDS Editor)
|
||||||
elseif(APPLE)
|
elseif(APPLE)
|
||||||
|
|||||||
@@ -1,36 +1,5 @@
|
|||||||
include (ExternalProject)
|
include (ExternalProject)
|
||||||
|
|
||||||
|
|
||||||
#--------------SLang------------------------------
|
|
||||||
add_library(slang SHARED IMPORTED)
|
|
||||||
if(WIN32)
|
|
||||||
add_library(slang-glslang SHARED IMPORTED)
|
|
||||||
set(SLANG_ROOT ${PROJECT_SOURCE_DIR}/../slang/build/Release/)
|
|
||||||
set_target_properties(slang-glslang PROPERTIES IMPORTED_LOCATION ${SLANG_ROOT}bin/slang-glslang.dll)
|
|
||||||
set_target_properties(slang-glslang PROPERTIES IMPORTED_IMPLIB ${SLANG_ROOT}lib/slang.lib)
|
|
||||||
set_target_properties(slang PROPERTIES IMPORTED_LOCATION ${SLANG_ROOT}bin/slang.dll)
|
|
||||||
set_target_properties(slang PROPERTIES IMPORTED_IMPLIB ${SLANG_ROOT}lib/slang.lib)
|
|
||||||
target_link_libraries(slang INTERFACE slang-glslang)
|
|
||||||
install(FILES
|
|
||||||
${SLANG_ROOT}bin/slang-glslang.dll
|
|
||||||
${SLANG_ROOT}bin/slang.dll
|
|
||||||
DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
|
|
||||||
install(FILES
|
|
||||||
${SLANG_ROOT}lib/slang.lib
|
|
||||||
DESTINATION ${CMAKE_INSTALL_PREFIX}/lib)
|
|
||||||
elseif(APPLE)
|
|
||||||
set(BINARY_ROOT ${PROJECT_SOURCE_DIR}/../slang/build/Debug)
|
|
||||||
set_target_properties(slang PROPERTIES IMPORTED_LOCATION ${BINARY_ROOT}/lib/libslang.dylib)
|
|
||||||
install(FILES
|
|
||||||
${BINARY_ROOT}/lib/libslang.dylib
|
|
||||||
DESTINATION ${CMAKE_INSTALL_PREFIX}/lib)
|
|
||||||
endif()
|
|
||||||
target_include_directories(slang INTERFACE
|
|
||||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/../slang/include>
|
|
||||||
$<INSTALL_INTERFACE:include>
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
#--------------CRC++------------------------------
|
#--------------CRC++------------------------------
|
||||||
add_library(crcpp INTERFACE)
|
add_library(crcpp INTERFACE)
|
||||||
|
|
||||||
|
|||||||
Vendored
+1
-1
Submodule external/vcpkg updated: 509f71e53f...ab42fb3032
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -59,5 +59,5 @@ float4 fragmentMain(
|
|||||||
if(style.textureIndex == -1) {
|
if(style.textureIndex == -1) {
|
||||||
return float4(style.color, style.opacity);
|
return float4(style.color, style.opacity);
|
||||||
}
|
}
|
||||||
return float4(pParams.textures[style.textureIndex].Sample(pParams.sampler, texCoords.xy).xyz, style.opacity);
|
return pParams.textures[style.textureIndex].Sample(pParams.sampler, texCoords.xy);
|
||||||
}
|
}
|
||||||
@@ -16,6 +16,7 @@ struct Phong : IBRDF
|
|||||||
float3 normal;
|
float3 normal;
|
||||||
float3 ambient;
|
float3 ambient;
|
||||||
float shininess;
|
float shininess;
|
||||||
|
float3 emissive;
|
||||||
|
|
||||||
__init()
|
__init()
|
||||||
{
|
{
|
||||||
@@ -25,6 +26,7 @@ struct Phong : IBRDF
|
|||||||
normal = float3(0, 0, 1);
|
normal = float3(0, 0, 1);
|
||||||
ambient = float3(0, 0, 0);
|
ambient = float3(0, 0, 0);
|
||||||
shininess = 0;
|
shininess = 0;
|
||||||
|
emissive = float3(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
float3 evaluate(float3x3 tangentToWorld, float3 viewDir_WS, float3 lightDir_WS, float3 lightColor)
|
float3 evaluate(float3x3 tangentToWorld, float3 viewDir_WS, float3 lightDir_WS, float3 lightColor)
|
||||||
@@ -59,6 +61,7 @@ struct BlinnPhong : IBRDF
|
|||||||
float3 normal;
|
float3 normal;
|
||||||
float shininess;
|
float shininess;
|
||||||
float3 ambient;
|
float3 ambient;
|
||||||
|
float3 emissive;
|
||||||
|
|
||||||
__init()
|
__init()
|
||||||
{
|
{
|
||||||
@@ -66,8 +69,9 @@ struct BlinnPhong : IBRDF
|
|||||||
alpha = 1;
|
alpha = 1;
|
||||||
specularColor = float3(0, 0, 0);
|
specularColor = float3(0, 0, 0);
|
||||||
normal = float3(0, 0, 1);
|
normal = float3(0, 0, 1);
|
||||||
shininess = 0;
|
shininess = 4;
|
||||||
ambient = float3(0, 0, 0);
|
ambient = float3(0, 0, 0);
|
||||||
|
emissive = float3(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
float3 evaluate(float3x3 tangentToWorld, float3 viewDir_WS, float3 lightDir_WS, float3 lightColor)
|
float3 evaluate(float3x3 tangentToWorld, float3 viewDir_WS, float3 lightDir_WS, float3 lightColor)
|
||||||
@@ -77,7 +81,7 @@ struct BlinnPhong : IBRDF
|
|||||||
float3 h = normalize(lightDir_WS + viewDir_WS);
|
float3 h = normalize(lightDir_WS + viewDir_WS);
|
||||||
float specular = pow(saturate(dot(normal_WS, h)), shininess);
|
float specular = pow(saturate(dot(normal_WS, h)), shininess);
|
||||||
|
|
||||||
return (baseColor * diffuse * lightColor);// + (specularColor * specular);
|
return (baseColor * diffuse * lightColor) + (specularColor * specular);
|
||||||
}
|
}
|
||||||
|
|
||||||
float3 evaluateAmbient()
|
float3 evaluateAmbient()
|
||||||
@@ -99,12 +103,14 @@ struct CelShading : IBRDF
|
|||||||
float3 baseColor;
|
float3 baseColor;
|
||||||
float alpha;
|
float alpha;
|
||||||
float3 normal;
|
float3 normal;
|
||||||
|
float3 emissive;
|
||||||
|
|
||||||
__init()
|
__init()
|
||||||
{
|
{
|
||||||
baseColor = float3(0, 0, 0);
|
baseColor = float3(0, 0, 0);
|
||||||
alpha = 1;
|
alpha = 1;
|
||||||
normal = float3(0, 0, 1);
|
normal = float3(0, 0, 1);
|
||||||
|
emissive = float3(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
float3 evaluate(float3x3 tangentToWorld, float3 viewDir_WS, float3 lightDir_WS, float3 lightColor)
|
float3 evaluate(float3x3 tangentToWorld, float3 viewDir_WS, float3 lightDir_WS, float3 lightColor)
|
||||||
@@ -146,6 +152,7 @@ struct CookTorrance : IBRDF
|
|||||||
float roughness;
|
float roughness;
|
||||||
float metallic;
|
float metallic;
|
||||||
float ambientOcclusion;
|
float ambientOcclusion;
|
||||||
|
float3 emissive;
|
||||||
|
|
||||||
__init()
|
__init()
|
||||||
{
|
{
|
||||||
@@ -155,6 +162,7 @@ struct CookTorrance : IBRDF
|
|||||||
roughness = 0;
|
roughness = 0;
|
||||||
metallic = 0;
|
metallic = 0;
|
||||||
ambientOcclusion = 1;
|
ambientOcclusion = 1;
|
||||||
|
emissive = float3(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
float TrowbridgeReitzGGX(float3 normal, float3 halfway)
|
float TrowbridgeReitzGGX(float3 normal, float3 halfway)
|
||||||
|
|||||||
@@ -106,15 +106,15 @@ struct FragmentParameter
|
|||||||
FragmentParameter result;
|
FragmentParameter result;
|
||||||
result.position_CS = f0.position_CS * barycentricCoords.x + f1.position_CS * barycentricCoords.y + f2.position_CS * barycentricCoords.z;
|
result.position_CS = f0.position_CS * barycentricCoords.x + f1.position_CS * barycentricCoords.y + f2.position_CS * barycentricCoords.z;
|
||||||
#ifndef POS_ONLY
|
#ifndef POS_ONLY
|
||||||
result.normal_WS = f0.normal_WS * barycentricCoords.x + f1.normal_WS * barycentricCoords.y + f2.normal_WS * barycentricCoords.z;
|
result.normal_WS = f0.normal_WS * barycentricCoords.x + f1.normal_WS * barycentricCoords.y + f2.normal_WS * barycentricCoords.z;
|
||||||
result.tangent_WS = f0.tangent_WS * barycentricCoords.x + f1.tangent_WS * barycentricCoords.y + f2.tangent_WS * barycentricCoords.z;
|
result.tangent_WS = f0.tangent_WS * barycentricCoords.x + f1.tangent_WS * barycentricCoords.y + f2.tangent_WS * barycentricCoords.z;
|
||||||
result.biTangent_WS = f0.biTangent_WS * barycentricCoords.x + f1.biTangent_WS * barycentricCoords.y + f2.biTangent_WS * barycentricCoords.z;
|
result.biTangent_WS = f0.biTangent_WS * barycentricCoords.x + f1.biTangent_WS * barycentricCoords.y + f2.biTangent_WS * barycentricCoords.z;
|
||||||
result.position_WS = f0.position_WS * barycentricCoords.x + f1.position_WS * barycentricCoords.y + f2.position_WS * barycentricCoords.z;
|
result.position_WS = f0.position_WS * barycentricCoords.x + f1.position_WS * barycentricCoords.y + f2.position_WS * barycentricCoords.z;
|
||||||
result.vertexColor = f0.vertexColor * barycentricCoords.x + f1.vertexColor * barycentricCoords.y + f2.vertexColor * barycentricCoords.z;
|
result.vertexColor = f0.vertexColor * barycentricCoords.x + f1.vertexColor * barycentricCoords.y + f2.vertexColor * barycentricCoords.z;
|
||||||
result.texCoords0 = f0.texCoords0 * barycentricCoords.x + f1.texCoords0 * barycentricCoords.y + f2.texCoords0 * barycentricCoords.z;
|
result.texCoords0 = f0.texCoords0 * barycentricCoords.x + f1.texCoords0 * barycentricCoords.y + f2.texCoords0 * barycentricCoords.z;
|
||||||
result.texCoords1 = f0.texCoords1 * barycentricCoords.x + f1.texCoords1 * barycentricCoords.y + f2.texCoords1 * barycentricCoords.z;
|
result.texCoords1 = f0.texCoords1 * barycentricCoords.x + f1.texCoords1 * barycentricCoords.y + f2.texCoords1 * barycentricCoords.z;
|
||||||
result.texCoords2 = f0.texCoords2 * barycentricCoords.x + f1.texCoords2 * barycentricCoords.y + f2.texCoords2 * barycentricCoords.z;
|
result.texCoords2 = f0.texCoords2 * barycentricCoords.x + f1.texCoords2 * barycentricCoords.y + f2.texCoords2 * barycentricCoords.z;
|
||||||
result.texCoords3 = f0.texCoords3 * barycentricCoords.x + f1.texCoords3 * barycentricCoords.y + f2.texCoords3 * barycentricCoords.z;
|
result.texCoords3 = f0.texCoords3 * barycentricCoords.x + f1.texCoords3 * barycentricCoords.y + f2.texCoords3 * barycentricCoords.z;
|
||||||
#endif
|
#endif
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,69 @@ import MATERIAL_FILE_NAME;
|
|||||||
|
|
||||||
// simplification: all BLAS only have 1 geometry
|
// simplification: all BLAS only have 1 geometry
|
||||||
|
|
||||||
|
/*vec3 nextEventEstimation(vec3 accmat, vec3 w, vec3 x, vec3 nl, float kt, bool useAtt, vec3 rnd) {
|
||||||
|
uint triId = 0;
|
||||||
|
uint sphereId = 0;
|
||||||
|
ShadingParams paramsls;
|
||||||
|
Material matls;
|
||||||
|
vec3 result = vec3(0);
|
||||||
|
// Direct Illumination: Next Event Estimation over any present lights
|
||||||
|
for (int i = spheres.length(); i-->0;) {
|
||||||
|
Sphere ls = spheres[i];
|
||||||
|
if (all(equal(ls.e, vec3(0)))) continue; // skip non-emissive spheres
|
||||||
|
vec3 xc = ls.geo.xyz - x;
|
||||||
|
vec3 sw = normalize(xc), su = normalize(cross((abs(sw.x)>.1 ? vec3(0,1,0) : vec3(1,0,0)), sw)), sv = cross(sw,su);
|
||||||
|
float cos_a_max = sqrt(float(1 - ls.geo.w*ls.geo.w / dot(xc,xc)));
|
||||||
|
float cos_a = 1 - rnd.x + rnd.x*cos_a_max, sin_a = sqrt(1 - cos_a*cos_a);
|
||||||
|
float phi = 2 * pi * rnd.y;
|
||||||
|
vec3 l = normalize(su*cos(phi)*sin_a + sv*sin(phi)*sin_a + sw*cos_a); // sampled direction towards light
|
||||||
|
if (intersect(Ray(x,l), matls, paramsls, sphereId, triId) && sphereId == i) { // test if shadow ray hits this light source
|
||||||
|
float omega = 2 * pi * (1-cos_a_max);
|
||||||
|
if(useAtt) {
|
||||||
|
float tau = exp(-kt * length(x - paramsls.x));
|
||||||
|
result += max(dot(l,nl),0) * ls.e * omega * tau;
|
||||||
|
} else {
|
||||||
|
result += accmat / pi * max(dot(l,nl),0) * ls.e * omega; // brdf term obj.c.xyz already in accmat, 1/pi for brdf
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(int i = meshLights.length(); i-->0;) {
|
||||||
|
MeshDescriptor mesh = meshes[meshLights[i]];
|
||||||
|
for(int j = 0; j < mesh.numIndices; j+=3) {
|
||||||
|
vec3 A = vec3(vertices[mesh.vertexOffset + indices[mesh.indexOffset + j + 0]]);
|
||||||
|
vec3 B = vec3(vertices[mesh.vertexOffset + indices[mesh.indexOffset + j + 1]]);
|
||||||
|
vec3 C = vec3(vertices[mesh.vertexOffset + indices[mesh.indexOffset + j + 2]]);
|
||||||
|
float b1 = 1 - sqrt(rnd.x);
|
||||||
|
float b2 = (1 - rnd.y) * sqrt(rnd.x);
|
||||||
|
float b3 = rnd.y * sqrt(rnd.x);
|
||||||
|
vec3 P = A * b1 + B * b2 + C * b3;
|
||||||
|
vec3 omega = P - x;
|
||||||
|
vec3 l = normalize(omega);
|
||||||
|
float v = 0.f;
|
||||||
|
if(intersect(Ray(x,l), matls, paramsls, sphereId, triId) && triId == j) {
|
||||||
|
v = 1.0f;
|
||||||
|
}
|
||||||
|
vec3 e1 = C - A;
|
||||||
|
vec3 e2 = B - A;
|
||||||
|
float area = length(cross(e1, e2)) / 2;
|
||||||
|
float rayLen = length(omega);
|
||||||
|
float cosTheta = dot(nl, l);
|
||||||
|
float cosThetaDash = dot(paramsls.n, -l);
|
||||||
|
float factor = area * (cosThetaDash / (rayLen * rayLen));
|
||||||
|
if(useAtt) {
|
||||||
|
float tau = phase(w, l) * exp(-kt * length(x - paramsls.x));
|
||||||
|
result += tau * matls.e * max(cosTheta, 0) * factor;
|
||||||
|
} else {
|
||||||
|
result += accmat * (matls.e * max(cosTheta, 0) * factor) / pi;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
const float eps = 1e-5;
|
||||||
[shader("closesthit")]
|
[shader("closesthit")]
|
||||||
void closestHit(inout RayPayload hitValue, in BuiltInTriangleIntersectionAttributes attr)
|
void closestHit(inout RayPayload hitValue, in BuiltInTriangleIntersectionAttributes attr)
|
||||||
{
|
{
|
||||||
@@ -46,12 +109,11 @@ void closestHit(inout RayPayload hitValue, in BuiltInTriangleIntersectionAttribu
|
|||||||
let brdf = Material.prepare(materialParams);
|
let brdf = Material.prepare(materialParams);
|
||||||
|
|
||||||
float3 normal_WS = normalize(mul(params.getTangentToWorld(), brdf.normal));
|
float3 normal_WS = normalize(mul(params.getTangentToWorld(), brdf.normal));
|
||||||
float3 normalLight_WS = dot(normal_WS,WorldRayOrigin())<0 ? normal_WS : -normal_WS;
|
float3 normalLight_WS = dot(normal_WS,WorldRayDirection())<0 ? normal_WS : -normal_WS;
|
||||||
float3 intersection_WS = params.position_WS + normal_WS * 0.001f;
|
float3 intersection_WS = params.position_WS;
|
||||||
|
|
||||||
hitValue.depth++;
|
hitValue.depth++;
|
||||||
float3 localAccRad = float3(0);
|
float3 rnd = rand01(hitValue.rndSeed);
|
||||||
float3 rnd = rand01(uint3(vertexIndex0, vertexIndex1, vertexIndex2));
|
|
||||||
//float kt = ka + ks;
|
//float kt = ka + ks;
|
||||||
//float s = -log(rnd.z) / kt;
|
//float s = -log(rnd.z) / kt;
|
||||||
//float3 xs = r.o + s * r.d;
|
//float3 xs = r.o + s * r.d;
|
||||||
@@ -73,13 +135,13 @@ void closestHit(inout RayPayload hitValue, in BuiltInTriangleIntersectionAttribu
|
|||||||
// continue;
|
// continue;
|
||||||
//}
|
//}
|
||||||
|
|
||||||
//float p = max(max(brdf.baseColor.x, brdf.baseColor.color.y), brdf.baseColor.color.z);
|
//float p = max(max(brdf.baseColor.x, brdf.baseColor.y), brdf.baseColor.z);
|
||||||
//if(hitValue.depth > 5) {
|
//if(hitValue.depth > 5) {
|
||||||
// if (rnd.z >= p) return;
|
// if (rnd.z >= p) return;
|
||||||
// else hitValue.accmat /= p;
|
// else hitValue.accmat /= p;
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
hitValue.light += brdf.emissive * hitValue.emissive + brdf.evaluateAmbient();
|
||||||
//-- Ideal DIFFUSE reflection
|
//-- Ideal DIFFUSE reflection
|
||||||
//if(bool(useNEE)) {
|
//if(bool(useNEE)) {
|
||||||
// accrad += nextEventEstimation(accmat, r.d, params.x, params.nl, kt, false, rnd);
|
// accrad += nextEventEstimation(accmat, r.d, params.x, params.nl, kt, false, rnd);
|
||||||
@@ -89,22 +151,25 @@ void closestHit(inout RayPayload hitValue, in BuiltInTriangleIntersectionAttribu
|
|||||||
float3 l = -pLightEnv.directionalLights[i].direction.xyz;
|
float3 l = -pLightEnv.directionalLights[i].direction.xyz;
|
||||||
RayDesc rayDesc;
|
RayDesc rayDesc;
|
||||||
rayDesc.TMax = 10000.0f;
|
rayDesc.TMax = 10000.0f;
|
||||||
rayDesc.TMin = 0.001f;
|
rayDesc.TMin = eps;
|
||||||
rayDesc.Origin = x;
|
rayDesc.Origin = x;
|
||||||
rayDesc.Direction = l;
|
rayDesc.Direction = l;
|
||||||
RayPayload payload;
|
RayPayload payload;
|
||||||
payload.depth = hitValue.depth;
|
payload.depth = hitValue.depth;
|
||||||
payload.emissive = 1;
|
payload.emissive = 1;
|
||||||
payload.anyHit = true;
|
payload.anyHit = true;
|
||||||
|
payload.hit = false;
|
||||||
|
payload.rndSeed = hitValue.rndSeed;
|
||||||
TraceRay(pRayTracingParams.scene, 0, 0xff, 0, 0, 0, rayDesc, payload);
|
TraceRay(pRayTracingParams.scene, 0, 0xff, 0, 0, 0, rayDesc, payload);
|
||||||
|
|
||||||
// we have missed all geometry, so directional light is affecting us
|
// we have missed all geometry, so directional light is affecting us
|
||||||
if(!payload.hit) {
|
//if(!payload.hit) {
|
||||||
localAccRad += pLightEnv.directionalLights[i].illuminate(lightingParams, brdf);
|
//hitValue.light += pLightEnv.directionalLights[i].illuminate(lightingParams, brdf);
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
for(uint i = 0; i < pLightEnv.numPointLights; ++i) {
|
for(uint i = 0; i < pLightEnv.numPointLights; ++i) {
|
||||||
RayPayload payload;
|
RayPayload payload;
|
||||||
|
payload.rndSeed = hitValue.rndSeed;
|
||||||
float3 x = intersection_WS;
|
float3 x = intersection_WS;
|
||||||
float3 l = pLightEnv.pointLights[i].position_WS.xyz - intersection_WS;
|
float3 l = pLightEnv.pointLights[i].position_WS.xyz - intersection_WS;
|
||||||
if(length(l) > pLightEnv.pointLights[i].colorRange.w) {
|
if(length(l) > pLightEnv.pointLights[i].colorRange.w) {
|
||||||
@@ -112,40 +177,37 @@ void closestHit(inout RayPayload hitValue, in BuiltInTriangleIntersectionAttribu
|
|||||||
}
|
}
|
||||||
RayDesc rayDesc;
|
RayDesc rayDesc;
|
||||||
rayDesc.TMax = 1.0f;
|
rayDesc.TMax = 1.0f;
|
||||||
rayDesc.TMin = 0.001f;
|
rayDesc.TMin = eps;
|
||||||
rayDesc.Origin = x;
|
rayDesc.Origin = x;
|
||||||
rayDesc.Direction = l;
|
rayDesc.Direction = l;
|
||||||
TraceRay(pRayTracingParams.scene, 0, 0xff, 0, 0, 0, rayDesc, payload);
|
TraceRay(pRayTracingParams.scene, 0, 0xff, 0, 0, 0, rayDesc, payload);
|
||||||
|
|
||||||
// hitting only after the light
|
// hitting only after the light
|
||||||
if(!payload.hit) {
|
if(!payload.hit) {
|
||||||
localAccRad += pLightEnv.pointLights[i].illuminate(lightingParams, brdf);
|
hitValue.light += pLightEnv.pointLights[i].illuminate(lightingParams, brdf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Indirect Illumination: cosine-weighted importance sampling
|
// Indirect Illumination: cosine-weighted importance sampling
|
||||||
if(hitValue.depth < 12) {
|
if(hitValue.depth < 12) {
|
||||||
float r1 = 2 * PI * rnd.x, r2 = rnd.y, r2s = sqrt(r2);
|
float r1 = 2 * PI * rnd.x, r2 = rnd.y, r2s = sqrt(r2);
|
||||||
float3 w = normalLight_WS;
|
float3 w = normalLight_WS;
|
||||||
float3 u = normalize((cross(abs(w.x)>0.1 ? float3(0,1,0) : float3(1,0,0), w)));
|
float3 u = normalize(cross(abs(w.x)>0.1 ? float3(0,1,0) : float3(1,0,0), w));
|
||||||
float3 v = cross(w,u);
|
float3 v = cross(w,u);
|
||||||
RayDesc rayDesc;
|
RayDesc rayDesc;
|
||||||
rayDesc.TMax = 10000.0f;
|
rayDesc.TMax = 10000.0f;
|
||||||
rayDesc.TMin = 0.001f;
|
rayDesc.TMin = eps;
|
||||||
rayDesc.Origin = intersection_WS;
|
rayDesc.Origin = intersection_WS;
|
||||||
rayDesc.Direction = normalize(u*cos(r1)*r2s + v * sin(r1)*r2s + w * sqrt(1 - r2));
|
rayDesc.Direction = normalize(u*cos(r1)*r2s + v * sin(r1)*r2s + w * sqrt(1 - r2));
|
||||||
RayPayload payload;
|
RayPayload payload;
|
||||||
payload.light = float3(0);
|
payload.light = float3(0);
|
||||||
payload.emissive = 0; // in the next bounce, consider reflective part only!
|
payload.emissive = 1;
|
||||||
payload.depth = hitValue.depth+1;
|
payload.hit = false;
|
||||||
|
//payload.emissive = 0; // in the next bounce, consider reflective part only!
|
||||||
|
payload.depth = hitValue.depth;
|
||||||
payload.anyHit = false;
|
payload.anyHit = false;
|
||||||
|
payload.rndSeed = hitValue.rndSeed + 1;
|
||||||
TraceRay(pRayTracingParams.scene, 0, 0xff, 0, 0, 0, rayDesc, payload);
|
TraceRay(pRayTracingParams.scene, 0, 0xff, 0, 0, 0, rayDesc, payload);
|
||||||
if(payload.hit) {
|
float bias = dot(normalLight_WS, rayDesc.Direction);
|
||||||
DirectionalLight dir;
|
hitValue.light += brdf.evaluate(params.getTangentToWorld(), -WorldRayDirection(), rayDesc.Direction, payload.light / bias);
|
||||||
dir.color = float4(payload.light, 0);
|
|
||||||
dir.direction = float4(-rayDesc.Direction, 0);
|
|
||||||
localAccRad += dir.illuminate(lightingParams, brdf);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hitValue.light += localAccRad;
|
|
||||||
}
|
}
|
||||||
@@ -108,10 +108,13 @@ void raygen()
|
|||||||
payload.light=float3(0);
|
payload.light=float3(0);
|
||||||
payload.emissive = 1;
|
payload.emissive = 1;
|
||||||
payload.depth = 1;
|
payload.depth = 1;
|
||||||
|
payload.rndSeed = rndSeed + 1;
|
||||||
payload.anyHit = false;
|
payload.anyHit = false;
|
||||||
TraceRay(pRayTracingParams.scene, 0, 0xff, 0, 0, 0, rayDesc, payload);
|
TraceRay(pRayTracingParams.scene, 0, 0xff, 0, 0, 0, rayDesc, payload);
|
||||||
|
|
||||||
if(pSamps.pass == 0) pRayTracingParams.radianceAccumulator[pix] = float4(0);
|
if(pSamps.pass == 0) pRayTracingParams.radianceAccumulator[pix] = float4(0);
|
||||||
pRayTracingParams.radianceAccumulator[pix] += float4(payload.light / pSamps.samplesPerPixel, 0);
|
float3 accumulatedRadiance = payload.light / pSamps.samplesPerPixel;
|
||||||
pRayTracingParams.image[pix] = float4(clamp(pRayTracingParams.radianceAccumulator[pix].xyz, 0, 1), 1);
|
pRayTracingParams.radianceAccumulator[pix] += float4(accumulatedRadiance, 0);
|
||||||
|
float3 compensatedRadiance = pRayTracingParams.radianceAccumulator[pix].xyz * pSamps.samplesPerPixel / (pSamps.pass + 1);
|
||||||
|
pRayTracingParams.image[pix] = float4(clamp(compensatedRadiance, 0, 1), 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ struct RayPayload
|
|||||||
uint depth;
|
uint depth;
|
||||||
bool hit;
|
bool hit;
|
||||||
bool anyHit;
|
bool anyHit;
|
||||||
|
uint3 rndSeed;
|
||||||
};
|
};
|
||||||
|
|
||||||
float3 rand01(uint3 x){ // pseudo-random number generator
|
float3 rand01(uint3 x){ // pseudo-random number generator
|
||||||
|
|||||||
@@ -32,9 +32,9 @@ void FontLoader::importAsset(FontImportArgs args) {
|
|||||||
// so we create a single pixel empty texture
|
// so we create a single pixel empty texture
|
||||||
void FontLoader::import(FontImportArgs args, PFontAsset asset) {
|
void FontLoader::import(FontImportArgs args, PFontAsset asset) {
|
||||||
std::ifstream stream(args.filePath.c_str(), std::ios::binary | std::ios::ate);
|
std::ifstream stream(args.filePath.c_str(), std::ios::binary | std::ios::ate);
|
||||||
Array<uint8> ttfFile(stream.tellg());
|
Array<char> ttfFile(stream.tellg());
|
||||||
stream.seekg(0);
|
stream.seekg(0);
|
||||||
stream.read((char*)ttfFile.data(), ttfFile.size());
|
stream.read(ttfFile.data(), ttfFile.size());
|
||||||
asset->ttfFile = std::move(ttfFile);
|
asset->ttfFile = std::move(ttfFile);
|
||||||
asset->graphics = graphics;
|
asset->graphics = graphics;
|
||||||
asset->loadFace();
|
asset->loadFace();
|
||||||
|
|||||||
@@ -92,6 +92,8 @@ constexpr const char* KEY_AMBIENT_COLOR = "k_a";
|
|||||||
constexpr const char* KEY_SHININESS = "k_shiny";
|
constexpr const char* KEY_SHININESS = "k_shiny";
|
||||||
constexpr const char* KEY_ROUGHNESS = "k_r";
|
constexpr const char* KEY_ROUGHNESS = "k_r";
|
||||||
constexpr const char* KEY_METALLIC = "k_m";
|
constexpr const char* KEY_METALLIC = "k_m";
|
||||||
|
constexpr const char* KEY_EMISSIVE_COLOR = "k_e";
|
||||||
|
constexpr const char* KEY_EMISSIVE_INTENSITY = "k_ei";
|
||||||
|
|
||||||
constexpr const char* KEY_DIFFUSE_TEXTURE = "tex_d";
|
constexpr const char* KEY_DIFFUSE_TEXTURE = "tex_d";
|
||||||
constexpr const char* KEY_SPECULAR_TEXTURE = "tex_s";
|
constexpr const char* KEY_SPECULAR_TEXTURE = "tex_s";
|
||||||
@@ -101,6 +103,7 @@ constexpr const char* KEY_SHININESS_TEXTURE = "tex_shiny";
|
|||||||
constexpr const char* KEY_ROUGHNESS_TEXTURE = "tex_r";
|
constexpr const char* KEY_ROUGHNESS_TEXTURE = "tex_r";
|
||||||
constexpr const char* KEY_METALLIC_TEXTURE = "tex_m";
|
constexpr const char* KEY_METALLIC_TEXTURE = "tex_m";
|
||||||
constexpr const char* KEY_AMBIENT_OCCLUSION_TEXTURE = "tex_ao";
|
constexpr const char* KEY_AMBIENT_OCCLUSION_TEXTURE = "tex_ao";
|
||||||
|
constexpr const char* KEY_EMISSIVE_TEXTURE = "tex_emissive";
|
||||||
|
|
||||||
void MeshLoader::loadMaterials(const aiScene* scene, const Array<PTextureAsset>& textures, const std::string& baseName,
|
void MeshLoader::loadMaterials(const aiScene* scene, const Array<PTextureAsset>& textures, const std::string& baseName,
|
||||||
const std::filesystem::path& meshDirectory, const std::string& importPath,
|
const std::filesystem::path& meshDirectory, const std::string& importPath,
|
||||||
@@ -353,9 +356,19 @@ void MeshLoader::loadMaterials(const aiScene* scene, const Array<PTextureAsset>&
|
|||||||
addTextureParameter(KEY_AMBIENT_OCCLUSION_TEXTURE, aiTextureType_AMBIENT_OCCLUSION, i, outputAO, {0, -1, -1, -1});
|
addTextureParameter(KEY_AMBIENT_OCCLUSION_TEXTURE, aiTextureType_AMBIENT_OCCLUSION, i, outputAO, {0, -1, -1, -1});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Emissive
|
||||||
|
//addScalarParameter(KEY_EMISSIVE_INTENSITY, AI_MATKEY_EMISSIVE_INTENSITY);
|
||||||
|
addVectorParameter(KEY_EMISSIVE_COLOR, AI_MATKEY_COLOR_EMISSIVE);
|
||||||
|
std::string outputEmissive = KEY_EMISSIVE_COLOR;
|
||||||
|
uint32 numEmissive = material->GetTextureCount(aiTextureType_EMISSION_COLOR);
|
||||||
|
for (uint32 i = 0; i < numEmissive; ++i) {
|
||||||
|
addTextureParameter(KEY_EMISSIVE_TEXTURE, aiTextureType_EMISSION_COLOR, i, outputEmissive);
|
||||||
|
}
|
||||||
|
|
||||||
MaterialNode brdf;
|
MaterialNode brdf;
|
||||||
brdf.variables["baseColor"] = outputDiffuse;
|
brdf.variables["baseColor"] = outputDiffuse;
|
||||||
brdf.variables["alpha"] = outputAlpha;
|
brdf.variables["alpha"] = outputAlpha;
|
||||||
|
brdf.variables["emissive"] = outputEmissive;
|
||||||
if (!outputNormal.empty()) {
|
if (!outputNormal.empty()) {
|
||||||
expressions.add(new MulExpression());
|
expressions.add(new MulExpression());
|
||||||
expressions.back()->key = "NormalMul";
|
expressions.back()->key = "NormalMul";
|
||||||
@@ -381,6 +394,13 @@ void MeshLoader::loadMaterials(const aiScene* scene, const Array<PTextureAsset>&
|
|||||||
case aiShadingMode_Toon:
|
case aiShadingMode_Toon:
|
||||||
brdf.profile = "CelShading";
|
brdf.profile = "CelShading";
|
||||||
break;
|
break;
|
||||||
|
case aiShadingMode_Blinn:
|
||||||
|
brdf.profile = "BlinnPhong";
|
||||||
|
brdf.variables["specularColor"] = outputSpecular;
|
||||||
|
brdf.variables["ambient"] = outputAmbient;
|
||||||
|
brdf.variables["shininess"] = outputShininess;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
case aiShadingMode_CookTorrance:
|
case aiShadingMode_CookTorrance:
|
||||||
brdf.profile = "CookTorrance";
|
brdf.profile = "CookTorrance";
|
||||||
brdf.variables["roughness"] = outputRoughness;
|
brdf.variables["roughness"] = outputRoughness;
|
||||||
@@ -389,13 +409,6 @@ void MeshLoader::loadMaterials(const aiScene* scene, const Array<PTextureAsset>&
|
|||||||
brdf.variables["ambientOcclusion"] = outputAmbient;
|
brdf.variables["ambientOcclusion"] = outputAmbient;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
case aiShadingMode_Blinn:
|
|
||||||
brdf.profile = "BlinnPhong";
|
|
||||||
brdf.variables["specularColor"] = outputSpecular;
|
|
||||||
brdf.variables["ambient"] = outputAmbient;
|
|
||||||
brdf.variables["shininess"] = outputShininess;
|
|
||||||
break;
|
|
||||||
};
|
};
|
||||||
uint32 twoSided = false;
|
uint32 twoSided = false;
|
||||||
float opacity = 1.0f;
|
float opacity = 1.0f;
|
||||||
|
|||||||
@@ -111,12 +111,12 @@ void TextureLoader::import(TextureImportArgs args, PTextureAsset textureAsset) {
|
|||||||
ktxBasisParams basisParams = {
|
ktxBasisParams basisParams = {
|
||||||
.structSize = sizeof(ktxBasisParams),
|
.structSize = sizeof(ktxBasisParams),
|
||||||
.uastc = true,
|
.uastc = true,
|
||||||
.threadCount = 14,
|
.threadCount = 1,
|
||||||
.uastcFlags = KTX_PACK_UASTC_LEVEL_FASTEST,
|
.uastcFlags = KTX_PACK_UASTC_LEVEL_FASTEST,
|
||||||
.uastcRDO = true,
|
.uastcRDO = true,
|
||||||
};
|
};
|
||||||
//KTX_ASSERT(ktxTexture2_CompressBasisEx(kTexture, &basisParams));
|
// KTX_ASSERT(ktxTexture2_CompressBasisEx(kTexture, &basisParams));
|
||||||
//KTX_ASSERT(ktxTexture2_DeflateZstd(kTexture, 20));
|
// KTX_ASSERT(ktxTexture2_DeflateZstd(kTexture, 20));
|
||||||
|
|
||||||
char writer[100];
|
char writer[100];
|
||||||
snprintf(writer, sizeof(writer), "%s version %s", "SeeleEngine", "0.0.1");
|
snprintf(writer, sizeof(writer), "%s version %s", "SeeleEngine", "0.0.1");
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ InspectorView::InspectorView(Gfx::PGraphics graphics, PWindow window, const View
|
|||||||
new UI::Div<M_8>(UI::Attributes{}, {
|
new UI::Div<M_8>(UI::Attributes{}, {
|
||||||
new UI::Div<BG_Red, Inline>({},
|
new UI::Div<BG_Red, Inline>({},
|
||||||
{
|
{
|
||||||
new UI::Text<Font_Arial, Text_9XL>("OtherTestT"),
|
new UI::Text<Font_Arial, Text_9XL>("Other Test T"),
|
||||||
}),
|
}),
|
||||||
new UI::Text<Font_Arial>("Test"),
|
new UI::Text<Font_Arial>("Test fasdf agll;sdfgkj ahsf"),
|
||||||
}))) {
|
}))) {
|
||||||
renderGraph.addPass(new UIPass(graphics, uiSystem));
|
renderGraph.addPass(new UIPass(graphics, uiSystem));
|
||||||
renderGraph.setViewport(viewport);
|
renderGraph.setViewport(viewport);
|
||||||
|
|||||||
+35
-37
@@ -54,6 +54,8 @@ Array<Halfedge> generateEdges() {
|
|||||||
return edges;
|
return edges;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Array<uint32> generateArray() { return Array<uint32>(); }
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
std::string gameName = "MeshShadingDemo";
|
std::string gameName = "MeshShadingDemo";
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
@@ -113,26 +115,22 @@ int main() {
|
|||||||
// AssetImporter::importTexture(TextureImportArgs{
|
// AssetImporter::importTexture(TextureImportArgs{
|
||||||
// .filePath = sourcePath / "import/textures/wgen.png",
|
// .filePath = sourcePath / "import/textures/wgen.png",
|
||||||
//});
|
//});
|
||||||
// AssetImporter::importMesh(MeshImportArgs{
|
//AssetImporter::importMesh(MeshImportArgs{
|
||||||
// .filePath = sourcePath / "import/models/after-the-rain-vr-sound/source/Whitechapel.glb",
|
// .filePath = sourcePath / "import/models/after-the-rain-vr-sound/source/Whitechapel.glb",
|
||||||
// .importPath = "Whitechapel",
|
// .importPath = "Whitechapel",
|
||||||
//});
|
//});
|
||||||
// AssetImporter::importMesh(MeshImportArgs{
|
AssetImporter::importMesh(MeshImportArgs{
|
||||||
// .filePath = sourcePath / "import/models/plane.obj",
|
.filePath = sourcePath / "import/models/box.glb",
|
||||||
// .importPath = "",
|
.importPath = "",
|
||||||
// });
|
});
|
||||||
// AssetImporter::importMesh(MeshImportArgs{
|
AssetImporter::importMesh(MeshImportArgs{
|
||||||
// .filePath = sourcePath / "import/models/city-suburbs/source/city-suburbs.obj",
|
.filePath = sourcePath / "import/models/rttest.glb",
|
||||||
// .importPath = "suburbs",
|
.importPath = "",
|
||||||
// });
|
});
|
||||||
// AssetImporter::importMesh(MeshImportArgs{
|
AssetImporter::importMesh(MeshImportArgs{
|
||||||
// .filePath = sourcePath / "import/models/minecraft-medieval-city.fbx",
|
.filePath = sourcePath / "import/models/town_hall.glb",
|
||||||
// .importPath = "minecraft",
|
.importPath = "",
|
||||||
// });
|
});
|
||||||
// AssetImporter::importMesh(MeshImportArgs{
|
|
||||||
// .filePath = sourcePath / "import/models/Volvo/Volvo.fbx",
|
|
||||||
// .importPath = "Volvo",
|
|
||||||
// });
|
|
||||||
getThreadPool().waitIdle();
|
getThreadPool().waitIdle();
|
||||||
vd->commitMeshes();
|
vd->commitMeshes();
|
||||||
WindowCreateInfo mainWindowInfo = {
|
WindowCreateInfo mainWindowInfo = {
|
||||||
@@ -142,26 +140,26 @@ int main() {
|
|||||||
.preferredFormat = Gfx::SE_FORMAT_B8G8R8A8_SRGB,
|
.preferredFormat = Gfx::SE_FORMAT_B8G8R8A8_SRGB,
|
||||||
};
|
};
|
||||||
auto window = windowManager->addWindow(graphics, mainWindowInfo);
|
auto window = windowManager->addWindow(graphics, mainWindowInfo);
|
||||||
// ViewportCreateInfo sceneViewInfo = {
|
ViewportCreateInfo sceneViewInfo = {
|
||||||
// .dimensions =
|
.dimensions =
|
||||||
// {
|
{
|
||||||
// .size = {1920, 1080},
|
.size = {1920, 1080},
|
||||||
// .offset = {0, 0},
|
.offset = {0, 0},
|
||||||
// },
|
},
|
||||||
// .numSamples = Gfx::SE_SAMPLE_COUNT_4_BIT,
|
.numSamples = Gfx::SE_SAMPLE_COUNT_4_BIT,
|
||||||
// };
|
};
|
||||||
// OGameView sceneView = new Editor::PlayView(graphics, window, sceneViewInfo, binaryPath.generic_string());
|
OGameView sceneView = new Editor::PlayView(graphics, window, sceneViewInfo, binaryPath.generic_string());
|
||||||
// sceneView->setFocused();
|
sceneView->setFocused();
|
||||||
OInspectorView inspectorView = new Editor::InspectorView(graphics, window,
|
//OInspectorView inspectorView = new Editor::InspectorView(graphics, window,
|
||||||
ViewportCreateInfo{
|
// ViewportCreateInfo{
|
||||||
.dimensions =
|
// .dimensions =
|
||||||
{
|
// {
|
||||||
.size = {1920, 1080},
|
// .size = {1920, 1080},
|
||||||
.offset = {0, 0},
|
// .offset = {0, 0},
|
||||||
},
|
// },
|
||||||
.fieldOfView = 0,
|
// .fieldOfView = 0,
|
||||||
.numSamples = Gfx::SE_SAMPLE_COUNT_1_BIT,
|
// .numSamples = Gfx::SE_SAMPLE_COUNT_1_BIT,
|
||||||
});
|
// });
|
||||||
|
|
||||||
while (windowManager->isActive() && getGlobals().running) {
|
while (windowManager->isActive() && getGlobals().running) {
|
||||||
windowManager->render();
|
windowManager->render();
|
||||||
|
|||||||
@@ -12,8 +12,11 @@ FontAsset::FontAsset(std::string_view folderPath, std::string_view name) : Asset
|
|||||||
}
|
}
|
||||||
|
|
||||||
FontAsset::~FontAsset() {
|
FontAsset::~FontAsset() {
|
||||||
FT_Done_Face(face);
|
FT_Done_Face(ft_face);
|
||||||
FT_Done_FreeType(ft);
|
FT_Done_FreeType(ft);
|
||||||
|
hb_font_destroy(hb_font);
|
||||||
|
hb_face_destroy(hb_face);
|
||||||
|
hb_blob_destroy(blob);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FontAsset::save(ArchiveBuffer& buffer) const { Serialization::save(buffer, ttfFile); }
|
void FontAsset::save(ArchiveBuffer& buffer) const { Serialization::save(buffer, ttfFile); }
|
||||||
@@ -25,23 +28,57 @@ void FontAsset::load(ArchiveBuffer& buffer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FontAsset::loadFace() {
|
void FontAsset::loadFace() {
|
||||||
FT_Error error = FT_New_Memory_Face(ft, ttfFile.data(), ttfFile.size(), 0, &face);
|
FT_Error error = FT_New_Memory_Face(ft, (unsigned char*)ttfFile.data(), ttfFile.size(), 0, &ft_face);
|
||||||
assert(!error);
|
assert(!error);
|
||||||
|
blob = hb_blob_create(ttfFile.data(), ttfFile.size(), HB_MEMORY_MODE_DUPLICATE, nullptr, nullptr);
|
||||||
|
hb_face = hb_face_create(blob, 0);
|
||||||
|
hb_font = hb_font_create(hb_face);
|
||||||
|
}
|
||||||
|
UVector2 FontAsset::shapeText(std::string_view view, uint32 fontSize, Array<RenderGlyph>& render) {
|
||||||
|
loadGlyphs(fontSize);
|
||||||
|
hb_buffer_t* buf = hb_buffer_create();
|
||||||
|
hb_buffer_add_utf8(buf, view.data(), view.size(), 0, -1);
|
||||||
|
hb_buffer_set_language(buf, hb_language_from_string("en", -1));
|
||||||
|
hb_buffer_set_script(buf, HB_SCRIPT_LATIN);
|
||||||
|
hb_buffer_set_direction(buf, HB_DIRECTION_LTR);
|
||||||
|
hb_shape(hb_font, buf, nullptr, 0);
|
||||||
|
uint32 num_glyphs;
|
||||||
|
hb_glyph_info_t* glyphs = hb_buffer_get_glyph_infos(buf, &num_glyphs);
|
||||||
|
hb_glyph_position_t* positions = hb_buffer_get_glyph_positions(buf, &num_glyphs);
|
||||||
|
Vector2 min = Vector2(std::numeric_limits<float>::max());
|
||||||
|
Vector2 max = Vector2(std::numeric_limits<float>::lowest());
|
||||||
|
int32 xppem, yppem;
|
||||||
|
hb_font_get_scale(hb_font, &xppem, &yppem);
|
||||||
|
Vector2 cursor = Vector2(0);
|
||||||
|
for (uint32 i = 0; i < num_glyphs; ++i) {
|
||||||
|
hb_codepoint_t glyphid = glyphs[i].codepoint;
|
||||||
|
float xOffset = positions[i].x_offset * fontSize / xppem;
|
||||||
|
float yOffset = positions[i].y_offset * fontSize / yppem;
|
||||||
|
float xAdvance = positions[i].x_advance * fontSize / xppem;
|
||||||
|
float yAdvance = positions[i].y_advance * fontSize / yppem;
|
||||||
|
Vector2 position = cursor + Vector2(xOffset, yOffset);
|
||||||
|
Vector2 dimensions = fontSizes[fontSize].glyphs[glyphid].size;
|
||||||
|
render.add(RenderGlyph{
|
||||||
|
.texture = fontSizes[fontSize].glyphs[glyphid].texture,
|
||||||
|
.position = position,
|
||||||
|
.dimensions = dimensions,
|
||||||
|
});
|
||||||
|
cursor += Vector2(xAdvance, yAdvance);
|
||||||
|
min = Vector2(std::min(min.x, position.x), std::min(min.y, position.y));
|
||||||
|
max = Vector2(std::max(max.x, position.x + dimensions.x), std::max(min.y, position.y + dimensions.y));
|
||||||
|
}
|
||||||
|
hb_buffer_destroy(buf);
|
||||||
|
return UVector2(max - min);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FontAsset::loadFontSize(uint32 fontSize) {
|
void FontAsset::loadGlyphs(uint32 fontSize) {
|
||||||
FT_Set_Pixel_Sizes(face, 0, fontSize);
|
FT_Set_Pixel_Sizes(ft_face, 0, fontSize);
|
||||||
fontSizes[fontSize].ascent = face->ascender;
|
for (uint32 i = 0; i < ft_face->num_glyphs; ++i) {
|
||||||
fontSizes[fontSize].descent = face->descender;
|
assert(FT_Load_Glyph(ft_face, i, FT_LOAD_RENDER | FT_LOAD_COLOR) == 0);
|
||||||
fontSizes[fontSize].linegap = 0;
|
FontAsset::Glyph& glyph = fontSizes[fontSize].glyphs[i];
|
||||||
for (uint32 c = 0; c < 256; ++c) {
|
glyph.size = IVector2(ft_face->glyph->bitmap.width, ft_face->glyph->bitmap.rows);
|
||||||
if (FT_Load_Char(face, c, FT_LOAD_RENDER | FT_LOAD_COLOR)) {
|
glyph.bearing = IVector2(ft_face->glyph->bitmap_left, ft_face->glyph->bitmap_top);
|
||||||
continue;
|
glyph.advance = ft_face->glyph->advance.x;
|
||||||
}
|
|
||||||
FontAsset::Glyph& glyph = fontSizes[fontSize].glyphs[c];
|
|
||||||
glyph.size = IVector2(face->glyph->bitmap.width, face->glyph->bitmap.rows);
|
|
||||||
glyph.bearing = IVector2(face->glyph->bitmap_left, face->glyph->bitmap_top);
|
|
||||||
glyph.advance = face->glyph->advance.x;
|
|
||||||
glyph.textureData.resize(glyph.size.x * glyph.size.y);
|
glyph.textureData.resize(glyph.size.x * glyph.size.y);
|
||||||
if (glyph.textureData.size() == 0) {
|
if (glyph.textureData.size() == 0) {
|
||||||
glyph.size.x = 1;
|
glyph.size.x = 1;
|
||||||
@@ -49,7 +86,7 @@ void FontAsset::loadFontSize(uint32 fontSize) {
|
|||||||
glyph.textureData.add(0);
|
glyph.textureData.add(0);
|
||||||
// load a single transparent pixel, so that we dont have to handle empty textures later
|
// load a single transparent pixel, so that we dont have to handle empty textures later
|
||||||
} else {
|
} else {
|
||||||
std::memcpy(glyph.textureData.data(), face->glyph->bitmap.buffer, glyph.textureData.size());
|
std::memcpy(glyph.textureData.data(), ft_face->glyph->bitmap.buffer, glyph.textureData.size());
|
||||||
}
|
}
|
||||||
glyph.texture = graphics->createTexture2D(TextureCreateInfo{
|
glyph.texture = graphics->createTexture2D(TextureCreateInfo{
|
||||||
.sourceData =
|
.sourceData =
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "Graphics/Texture.h"
|
#include "Graphics/Texture.h"
|
||||||
#include "Math/Math.h"
|
#include "Math/Math.h"
|
||||||
#include <freetype/freetype.h>
|
#include <freetype/freetype.h>
|
||||||
|
#include <harfbuzz/hb.h>
|
||||||
|
|
||||||
namespace Seele {
|
namespace Seele {
|
||||||
class FontAsset : public Asset {
|
class FontAsset : public Asset {
|
||||||
@@ -25,25 +26,26 @@ class FontAsset : public Asset {
|
|||||||
void load(ArchiveBuffer& buffer);
|
void load(ArchiveBuffer& buffer);
|
||||||
};
|
};
|
||||||
struct FontData {
|
struct FontData {
|
||||||
int32 ascent;
|
|
||||||
int32 descent;
|
|
||||||
int32 linegap;
|
|
||||||
Map<uint32, Glyph> glyphs;
|
Map<uint32, Glyph> glyphs;
|
||||||
};
|
};
|
||||||
const Glyph& getGlyphData(char c, uint32 fontSize) {
|
|
||||||
if (!fontSizes.contains(fontSize))
|
|
||||||
loadFontSize(fontSize);
|
|
||||||
return fontSizes[fontSize].glyphs[c];
|
|
||||||
}
|
|
||||||
const FontData& getFontData(uint32 fontSize) { return fontSizes[fontSize]; }
|
|
||||||
void loadFace();
|
void loadFace();
|
||||||
|
|
||||||
|
struct RenderGlyph {
|
||||||
|
Gfx::PTexture2D texture;
|
||||||
|
UVector2 position;
|
||||||
|
UVector2 dimensions;
|
||||||
|
};
|
||||||
|
UVector2 shapeText(std::string_view view, uint32 fontSize, Array<RenderGlyph>& render);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void loadFontSize(uint32 fontSize);
|
void loadGlyphs(uint32 fontSize);
|
||||||
Gfx::PGraphics graphics;
|
Gfx::PGraphics graphics;
|
||||||
|
hb_blob_t* blob;
|
||||||
|
hb_face_t* hb_face;
|
||||||
|
hb_font_t* hb_font;
|
||||||
FT_Library ft;
|
FT_Library ft;
|
||||||
FT_Face face;
|
FT_Face ft_face;
|
||||||
Array<uint8> ttfFile;
|
Array<char> ttfFile;
|
||||||
Map<uint32, FontData> fontSizes;
|
Map<uint32, FontData> fontSizes;
|
||||||
friend class FontLoader;
|
friend class FontLoader;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ void Camera::moveY(float amount) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Camera::buildViewMatrix() {
|
void Camera::buildViewMatrix() {
|
||||||
Vector eyePos = getTransform().getPosition() + Vector(0, 0, -5);
|
Vector eyePos = getTransform().getPosition();
|
||||||
Vector lookAt = eyePos + getTransform().getForward();
|
Vector lookAt = eyePos + getTransform().getForward();
|
||||||
viewMatrix = glm::lookAt(eyePos, lookAt, Vector(0, 1, 0));
|
viewMatrix = glm::lookAt(eyePos, lookAt, Vector(0, 1, 0));
|
||||||
cameraPos = eyePos;
|
cameraPos = eyePos;
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <concepts>
|
#include <concepts>
|
||||||
|
#include <ranges>
|
||||||
|
|
||||||
namespace Seele {
|
namespace Seele {
|
||||||
|
|
||||||
|
template <typename Range, typename T>
|
||||||
|
concept container_compatible_range = (std::ranges::input_range<Range>) && std::convertible_to<std::ranges::range_reference_t<Range>, T>;
|
||||||
|
|
||||||
template <class F, class... Args>
|
template <class F, class... Args>
|
||||||
concept invocable = std::invocable<F, Args...>;
|
concept invocable = std::invocable<F, Args...>;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "EngineTypes.h"
|
#include "EngineTypes.h"
|
||||||
|
#include "Concepts.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
@@ -117,7 +118,20 @@ template <typename T, typename Allocator = std::pmr::polymorphic_allocator<T>> s
|
|||||||
assert(_data != nullptr);
|
assert(_data != nullptr);
|
||||||
std::uninitialized_copy(init.begin(), init.end(), begin());
|
std::uninitialized_copy(init.begin(), init.end(), begin());
|
||||||
}
|
}
|
||||||
|
template <container_compatible_range<T> Range>
|
||||||
|
constexpr Array(std::from_range_t, Range&& rg, const allocator_type& alloc = allocator_type())
|
||||||
|
: arraySize(0), allocated(0), allocator(alloc) {
|
||||||
|
if constexpr (std::ranges::sized_range<Range> || std::ranges::forward_range<Range>) {
|
||||||
|
arraySize = std::ranges::size(rg);
|
||||||
|
allocated = arraySize;
|
||||||
|
_data = allocateArray(allocated);
|
||||||
|
std::ranges::uninitialized_copy(rg.begin(), rg.end(), begin(), end());
|
||||||
|
} else {
|
||||||
|
for (auto it = std::ranges::begin(rg); it != std::ranges::end(rg); it++) {
|
||||||
|
add(*it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
constexpr Array(const Array& other)
|
constexpr Array(const Array& other)
|
||||||
: arraySize(other.arraySize), allocated(other.allocated),
|
: arraySize(other.arraySize), allocated(other.allocated),
|
||||||
allocator(std::allocator_traits<allocator_type>::select_on_container_copy_construction(other.allocator)) {
|
allocator(std::allocator_traits<allocator_type>::select_on_container_copy_construction(other.allocator)) {
|
||||||
|
|||||||
@@ -58,40 +58,21 @@ void UIPass::beginFrame(const Component::Camera& cam) {
|
|||||||
for (auto& render : renderElements) {
|
for (auto& render : renderElements) {
|
||||||
float x = render.position.x;
|
float x = render.position.x;
|
||||||
float y = render.position.y;
|
float y = render.position.y;
|
||||||
if (render.text.empty()) {
|
//todo: convert using actual tree depth
|
||||||
//todo: convert using actual tree depth
|
uint32 textureIndex = -1ul;
|
||||||
elements.add(RenderElementStyle{
|
if (render.backgroundTexture != nullptr) {
|
||||||
.x = x,
|
textureIndex = usedTextures.size();
|
||||||
.y = y,
|
usedTextures.add(render.backgroundTexture);
|
||||||
.w = render.dimensions.x,
|
|
||||||
.h = render.dimensions.y,
|
|
||||||
.color = render.backgroundColor,
|
|
||||||
.z = render.level / 100.f,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
y = y + render.baseline;
|
|
||||||
for (uint32 c : render.text) {
|
|
||||||
const FontAsset::Glyph& glyph = render.font->getGlyphData(c, render.fontSize);
|
|
||||||
Vector2 bearing = Vector2(glyph.bearing);
|
|
||||||
Vector2 size = Vector2(glyph.size);
|
|
||||||
float xpos = x + glyph.bearing.x;
|
|
||||||
float ypos = y - bearing.y;
|
|
||||||
|
|
||||||
float w = size.x;
|
|
||||||
float h = size.y;
|
|
||||||
|
|
||||||
glyphs.add(GlyphInstanceData{
|
|
||||||
.x = xpos,
|
|
||||||
.y = ypos,
|
|
||||||
.z = render.level / 100.0f,
|
|
||||||
.width = w,
|
|
||||||
.height = h,
|
|
||||||
.glyphIndex = (uint32)usedTextures.size(),
|
|
||||||
});
|
|
||||||
usedTextures.add(glyph.texture);
|
|
||||||
x += glyph.advance / 64.0f;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
elements.add(RenderElementStyle{
|
||||||
|
.x = x,
|
||||||
|
.y = y,
|
||||||
|
.w = render.dimensions.x,
|
||||||
|
.h = render.dimensions.y,
|
||||||
|
.color = render.backgroundColor,
|
||||||
|
.z = render.level / 100.f,
|
||||||
|
.textureIndex = textureIndex,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
glyphInstanceBuffer->rotateBuffer(sizeof(GlyphInstanceData) * glyphs.size());
|
glyphInstanceBuffer->rotateBuffer(sizeof(GlyphInstanceData) * glyphs.size());
|
||||||
glyphInstanceBuffer->updateContents(0, sizeof(GlyphInstanceData) * glyphs.size(), glyphs.data());
|
glyphInstanceBuffer->updateContents(0, sizeof(GlyphInstanceData) * glyphs.size(), glyphs.data());
|
||||||
@@ -115,6 +96,9 @@ void UIPass::beginFrame(const Component::Camera& cam) {
|
|||||||
uiDescriptorSet = uiDescriptorLayout->allocateDescriptorSet();
|
uiDescriptorSet = uiDescriptorLayout->allocateDescriptorSet();
|
||||||
uiDescriptorSet->updateBuffer(0, 0, elementBuffer);
|
uiDescriptorSet->updateBuffer(0, 0, elementBuffer);
|
||||||
uiDescriptorSet->updateSampler(1, 0, glyphSampler);
|
uiDescriptorSet->updateSampler(1, 0, glyphSampler);
|
||||||
|
for (uint32 i = 0; i < usedTextures.size(); ++i) {
|
||||||
|
uiDescriptorSet->updateTexture(2, i, usedTextures[i]);
|
||||||
|
}
|
||||||
uiDescriptorSet->writeChanges();
|
uiDescriptorSet->writeChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -122,7 +122,6 @@ TopLevelAS::TopLevelAS(PGraphics graphics, const Gfx::TopLevelASCreateInfo& crea
|
|||||||
.flags = 0,
|
.flags = 0,
|
||||||
.size = buildSizesInfo.accelerationStructureSize,
|
.size = buildSizesInfo.accelerationStructureSize,
|
||||||
.usage = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
|
.usage = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
|
||||||
|
|
||||||
},
|
},
|
||||||
VmaAllocationCreateInfo{
|
VmaAllocationCreateInfo{
|
||||||
.usage = VMA_MEMORY_USAGE_AUTO,
|
.usage = VMA_MEMORY_USAGE_AUTO,
|
||||||
@@ -156,7 +155,7 @@ TopLevelAS::TopLevelAS(PGraphics graphics, const Gfx::TopLevelASCreateInfo& crea
|
|||||||
VkAccelerationStructureBuildGeometryInfoKHR buildGeometry = {
|
VkAccelerationStructureBuildGeometryInfoKHR buildGeometry = {
|
||||||
.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR,
|
.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR,
|
.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR,
|
||||||
.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR,
|
.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR,
|
||||||
.dstAccelerationStructure = handle,
|
.dstAccelerationStructure = handle,
|
||||||
.geometryCount = 1,
|
.geometryCount = 1,
|
||||||
|
|||||||
+7
-11
@@ -7,14 +7,10 @@
|
|||||||
namespace Seele {
|
namespace Seele {
|
||||||
namespace UI {
|
namespace UI {
|
||||||
struct UIRender {
|
struct UIRender {
|
||||||
std::string text;
|
Gfx::PTexture2D backgroundTexture;
|
||||||
PFontAsset font;
|
|
||||||
uint32 fontSize;
|
|
||||||
Vector textColor;
|
|
||||||
Vector backgroundColor;
|
Vector backgroundColor;
|
||||||
Vector2 position;
|
Vector2 position;
|
||||||
Vector2 dimensions;
|
Vector2 dimensions;
|
||||||
uint32 baseline;
|
|
||||||
uint32 z;
|
uint32 z;
|
||||||
uint32 level;
|
uint32 level;
|
||||||
};
|
};
|
||||||
@@ -45,15 +41,15 @@ class Element {
|
|||||||
} else if (style.widthType == DimensionType::Percent) {
|
} else if (style.widthType == DimensionType::Percent) {
|
||||||
dimensions.x = parentSize.x * style.width / 100.0f;
|
dimensions.x = parentSize.x * style.width / 100.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& child : children) {
|
|
||||||
child->layout(maxDimensions - Vector2(style.marginLeft + style.marginRight, style.marginTop + style.marginBottom));
|
|
||||||
}
|
|
||||||
if (style.heightType == DimensionType::Pixel) {
|
if (style.heightType == DimensionType::Pixel) {
|
||||||
dimensions.y = style.height;
|
dimensions.y = style.height;
|
||||||
} else if (style.heightType == DimensionType::Percent) {
|
} else if (style.heightType == DimensionType::Percent) {
|
||||||
dimensions.y = parentSize.y * style.height / 100.0f;
|
dimensions.y = parentSize.y * style.height / 100.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto& child : children) {
|
||||||
|
child->layout(maxDimensions - Vector2(style.marginLeft + style.marginRight, style.marginTop + style.marginBottom));
|
||||||
|
}
|
||||||
switch (style.innerDisplay) {
|
switch (style.innerDisplay) {
|
||||||
case InnerDisplayType::Flow:
|
case InnerDisplayType::Flow:
|
||||||
flowLayout();
|
flowLayout();
|
||||||
@@ -73,7 +69,7 @@ class Element {
|
|||||||
// create a new line in case the element doesnt fit on the current one anymore,
|
// create a new line in case the element doesnt fit on the current one anymore,
|
||||||
// but keep in current line in case we are still at the start, as a new line wouldnt help here
|
// but keep in current line in case we are still at the start, as a new line wouldnt help here
|
||||||
if (cursor.x + child->dimensions.x > maxDimensions.x - child->style.left && cursor.x != 0) {
|
if (cursor.x + child->dimensions.x > maxDimensions.x - child->style.left && cursor.x != 0) {
|
||||||
cursor.x = 0;
|
cursor.x = style.paddingLeft;
|
||||||
cursor.y += lineHeight;
|
cursor.y += lineHeight;
|
||||||
lineHeight = 0;
|
lineHeight = 0;
|
||||||
}
|
}
|
||||||
@@ -94,7 +90,7 @@ class Element {
|
|||||||
if (child->style.position == PositionType::Static || child->style.position == PositionType::Relative) {
|
if (child->style.position == PositionType::Static || child->style.position == PositionType::Relative) {
|
||||||
// create a new line in case we are not already at one
|
// create a new line in case we are not already at one
|
||||||
if (cursor.x != 0) {
|
if (cursor.x != 0) {
|
||||||
cursor.x = 0;
|
cursor.x = style.paddingLeft;
|
||||||
cursor.y += lineHeight;
|
cursor.y += lineHeight;
|
||||||
}
|
}
|
||||||
child->position.x = cursor.x + child->style.marginLeft;
|
child->position.x = cursor.x + child->style.marginLeft;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "UI/Element.h"
|
#include "UI/Element.h"
|
||||||
#include "UI/Style/Class.h"
|
#include "UI/Style/Class.h"
|
||||||
|
#include <ranges>
|
||||||
|
|
||||||
namespace Seele {
|
namespace Seele {
|
||||||
namespace UI {
|
namespace UI {
|
||||||
@@ -13,31 +14,24 @@ template <StyleClass... classes> class Text : public Element {
|
|||||||
(classes::apply(style), ...);
|
(classes::apply(style), ...);
|
||||||
}
|
}
|
||||||
virtual void layout(UVector2 parentSize) override {
|
virtual void layout(UVector2 parentSize) override {
|
||||||
size_t cursor = 0;
|
UVector2 cursor = UVector2(0);
|
||||||
for (uint32 i = 0; i < text.size() - 1; ++i) {
|
dimensions = style.fontFamily->shapeText(text, style.fontSize, glyphRenders);
|
||||||
dimensions.x += style.fontFamily->getGlyphData(text[i], style.fontSize).advance / 64.0f;
|
|
||||||
}
|
|
||||||
dimensions.x += style.fontFamily->getGlyphData(text[text.size() - 1], style.fontSize).size.x;
|
|
||||||
dimensions.y = style.fontSize;
|
|
||||||
}
|
}
|
||||||
virtual Array<UIRender> render(Vector2 anchor, uint32 level) override {
|
virtual Array<UIRender> render(Vector2 anchor, uint32 level) override {
|
||||||
return {
|
return Array<UIRender>(std::from_range, glyphRenders | std::views::transform([=](const FontAsset::RenderGlyph& glyph) {
|
||||||
UIRender{
|
return UIRender{
|
||||||
.text = text,
|
.backgroundTexture = glyph.texture,
|
||||||
.font = style.fontFamily,
|
.position = Vector2(glyph.position) + anchor,
|
||||||
.fontSize = style.fontSize,
|
.dimensions = Vector2(glyph.dimensions),
|
||||||
.position = position + anchor,
|
.level = level,
|
||||||
.dimensions = dimensions,
|
};
|
||||||
.baseline = style.fontSize * 3 / 4, // TODO: improve
|
}));
|
||||||
.z = style.z,
|
|
||||||
.level = level,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
// height = fontsize * 1.12
|
// height = fontsize * 1.12
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string text;
|
std::string text;
|
||||||
|
Array<FontAsset::RenderGlyph> glyphRenders;
|
||||||
};
|
};
|
||||||
} // namespace UI
|
} // namespace UI
|
||||||
} // namespace Seele
|
} // namespace Seele
|
||||||
+3
-1
@@ -12,6 +12,8 @@
|
|||||||
"fmt",
|
"fmt",
|
||||||
"gtest",
|
"gtest",
|
||||||
"vulkan-memory-allocator",
|
"vulkan-memory-allocator",
|
||||||
"lunasvg"
|
"lunasvg",
|
||||||
|
"harfbuzz",
|
||||||
|
"shader-slang"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user