Implementing ECS SystemBase and updating slang
This commit is contained in:
@@ -34,3 +34,6 @@
|
||||
[submodule "external/entt"]
|
||||
path = external/entt
|
||||
url = git@github.com:skypjack/entt.git
|
||||
[submodule "external/thread-pool"]
|
||||
path = external/thread-pool
|
||||
url = https://github.com/DeveloperPaul123/thread-pool.git
|
||||
|
||||
+13
-10
@@ -9,6 +9,7 @@ set(CMAKE_CXX_STANDARD 20)
|
||||
option (USE_SUPERBUILD "Whether or not a superbuild should be invoked" ON)
|
||||
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
set(CMAKE_COMPILE_WARNING_AS_ERROR OFF)
|
||||
|
||||
set(ENGINE_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/src/Engine)
|
||||
set(EXTERNAL_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/external)
|
||||
@@ -25,6 +26,7 @@ set(FREETYPE_ROOT ${EXTERNAL_ROOT}/freetype)
|
||||
set(SPIRV_ROOT ${EXTERNAL_ROOT}/SPIRV-Cross)
|
||||
set(ENTT_ROOT ${EXTERNAL_ROOT}/entt)
|
||||
set(NSAM_ROOT ${EXTERNAL_ROOT}/aftermath)
|
||||
set(THREADPOOL_ROOT ${EXTERNAL_ROOT}/thread-pool)
|
||||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/)
|
||||
set(Boost_NO_WARN_NEW_VERSIONS 1)
|
||||
@@ -53,7 +55,8 @@ if(CMAKE_DEBUG_POSTFIX)
|
||||
add_compile_definitions(ENABLE_VALIDATION)
|
||||
add_compile_definitions(SEELE_DEBUG)
|
||||
endif()
|
||||
add_library(Engine "")
|
||||
|
||||
add_library(Engine SHARED "")
|
||||
add_executable(Editor "")
|
||||
target_compile_definitions(Engine PUBLIC GLFW_WINDOWS)
|
||||
target_include_directories(Engine PUBLIC src/Engine)
|
||||
@@ -70,9 +73,10 @@ target_link_libraries(Engine PUBLIC nsam)
|
||||
target_link_libraries(Engine PUBLIC ktx)
|
||||
target_link_libraries(Engine PUBLIC stb)
|
||||
target_link_libraries(Engine PUBLIC nlohmann_json::nlohmann_json)
|
||||
target_link_libraries(Engine PUBLIC dp::thread-pool)
|
||||
if(UNIX)
|
||||
target_link_libraries(Engine Threads::Threads)
|
||||
target_link_libraries(Engine dl)
|
||||
target_link_libraries(Engine Threads::Threads)
|
||||
target_link_libraries(Engine dl)
|
||||
endif()
|
||||
target_precompile_headers(Engine
|
||||
PUBLIC
|
||||
@@ -89,20 +93,19 @@ target_precompile_headers(Engine
|
||||
<mutex>
|
||||
<string>
|
||||
<thread>
|
||||
<boost/serialization/serialization.hpp>
|
||||
<boost/crc.hpp>)
|
||||
|
||||
target_link_libraries(Editor PRIVATE Engine)
|
||||
|
||||
add_subdirectory(src/)
|
||||
<boost/serialization/serialization.hpp>)
|
||||
|
||||
if(MSVC)
|
||||
set(_CRT_SECURE_NO_WARNINGS)
|
||||
target_compile_options(Engine PUBLIC -Zi -MP -DEBUG)
|
||||
target_compile_options(Engine PUBLIC /Zi /MP /W4 /DEBUG "/WX-")
|
||||
else()
|
||||
target_compile_options(Engine PUBLIC -g -Wall -Wextra -Wno-delete-incomplete -pedantic -fcoroutines)
|
||||
endif()
|
||||
|
||||
target_link_libraries(Editor PUBLIC Engine)
|
||||
|
||||
add_subdirectory(src/)
|
||||
|
||||
add_executable(Seele_unit_tests "")
|
||||
add_subdirectory(test/)
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ add_subdirectory(${JSON_ROOT})
|
||||
|
||||
#--------------GLM------------------------------
|
||||
add_subdirectory(${GLM_ROOT})
|
||||
target_compile_options(glm_shared INTERFACE /W0)
|
||||
|
||||
#--------------GLFW------------------------------
|
||||
set(ENKITS_BUILD_EXAMPLES OFF CACHE BOOL "Build basic example applications" )
|
||||
@@ -61,6 +62,10 @@ target_link_libraries(nsam INTERFACE ${NSAM_ROOT}/lib/${CMAKE_PLATFORM}/*.lib)
|
||||
set_target_properties(nsam PROPERTIES NSAM_BINARY ${NSAM_ROOT}/lib/${CMAKE_PLATFORM}/GFSDK_Aftermath_Lib.${CMAKE_PLATFORM}.dll)
|
||||
set_target_properties(nsam PROPERTIES LLVM_BINARY ${NSAM_ROOT}/lib/${CMAKE_PLATFORM}/llvm_7_0_1.dll)
|
||||
|
||||
#--------------thread-pool------------------------------
|
||||
add_subdirectory(${THREADPOOL_ROOT})
|
||||
|
||||
target_compile_options(ThreadPool INTERFACE "/WX-")
|
||||
|
||||
#--------------SLang------------------------------
|
||||
string(TOLOWER release_${CMAKE_PLATFORM} SLANG_CONFIG)
|
||||
|
||||
Vendored
+1
-1
Submodule external/slang updated: ec530b3005...cedd93690c
+1
Submodule external/thread-pool added at dad69c1661
@@ -1,8 +1,7 @@
|
||||
import Common;
|
||||
import Material;
|
||||
import VERTEX_INPUT_IMPORT;
|
||||
import MATERIAL_IMPORT;
|
||||
import PrimitiveSceneData;
|
||||
import StaticMeshVertexInput;
|
||||
|
||||
|
||||
struct VertexStageOutput
|
||||
|
||||
@@ -2,9 +2,8 @@ import Common;
|
||||
import LightEnv;
|
||||
import BRDF;
|
||||
import Material;
|
||||
import StaticMeshVertexInput;
|
||||
|
||||
import VERTEX_INPUT_IMPORT;
|
||||
import MATERIAL_IMPORT;
|
||||
import PrimitiveSceneData;
|
||||
import MaterialParameter;
|
||||
|
||||
@@ -13,7 +12,6 @@ StructuredBuffer<uint> lightIndexList;
|
||||
layout(set = INDEX_LIGHT_ENV, binding = 5)
|
||||
RWTexture2D<uint2> lightGrid;
|
||||
|
||||
|
||||
struct VertexStageOutput
|
||||
{
|
||||
ShaderAttributeInterpolation shaderAttributeInterpolation : Interpolation;
|
||||
@@ -50,7 +48,7 @@ float4 fragmentMain(
|
||||
) : SV_Target
|
||||
{
|
||||
MaterialFragmentParameter materialParams = input.getMaterialParameter(position);
|
||||
TMaterial.BRDF brdf = gMaterial.prepare(materialParams);
|
||||
let brdf = gMaterial.prepare(materialParams);
|
||||
|
||||
float3 viewDir = normalize(materialParams.viewDir);
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ void tAppendLight(uint lightIndex)
|
||||
[shader("compute")]
|
||||
void cullLights(ComputeShaderInput in)
|
||||
{
|
||||
int2 texCoord = in.dispatchThreadID.xy;
|
||||
int2 texCoord = int2(in.dispatchThreadID.xy);
|
||||
float fDepth = depthTextureVS.Load(int3(texCoord, 0)).r;
|
||||
|
||||
uint uDepth = asuint(fDepth);
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
interface IMaterial
|
||||
{
|
||||
float4 sample(float2 texCoord);
|
||||
}
|
||||
|
||||
type_param TMaterial : IMaterial;
|
||||
ParameterBlock<TMaterial> gMaterial;
|
||||
@@ -0,0 +1,10 @@
|
||||
import Mat;
|
||||
|
||||
|
||||
struct SimpleMaterial : IMaterial
|
||||
{
|
||||
float4 sample(float2 texCoord)
|
||||
{
|
||||
return float4(1, 0, 1, 1);
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,5 @@ interface IMaterial
|
||||
float getSheen(MaterialFragmentParameter input);
|
||||
};
|
||||
|
||||
type_param TMaterial : IMaterial;
|
||||
layout(set = INDEX_MATERIAL, binding = 0, std430)
|
||||
ParameterBlock<TMaterial> gMaterial;
|
||||
ParameterBlock<IMaterial> gMaterial;
|
||||
|
||||
@@ -63,7 +63,7 @@ struct ShaderAttributeInterpolation
|
||||
#if NUM_MATERIAL_TEXCOORDS
|
||||
for(int i = 0; i < NUM_MATERIAL_TEXCOORDS; ++i)
|
||||
{
|
||||
if(i % 2)
|
||||
if(i % 2 == 1)
|
||||
{
|
||||
result.texCoords[i] = packedTexCoords[i / 2].zw;
|
||||
}
|
||||
@@ -191,7 +191,7 @@ struct VertexShaderInput
|
||||
result.viewPosition = vertexParams.viewPosition;
|
||||
for(int i = 0; i < NUM_MATERIAL_TEXCOORDS; ++i)
|
||||
{
|
||||
if(i % 2)
|
||||
if(i % 2 == 1)
|
||||
{
|
||||
result.packedTexCoords[i / 2].zw = vertexParams.texCoords[i];
|
||||
}
|
||||
|
||||
+4
-481
@@ -1,485 +1,8 @@
|
||||
// shaders.slang
|
||||
import Mat;
|
||||
import Simple;
|
||||
|
||||
//
|
||||
// This example builds on the simplistic shaders presented in the
|
||||
// "Hello, World" example by adding support for (intentionally
|
||||
// simplistic) surface materil and light shading.
|
||||
//
|
||||
// The code here is not meant to exemplify state-of-the-art material
|
||||
// and lighting techniques, but rather to show how a shader
|
||||
// library can be developed in a modular fashion without reliance
|
||||
// on the C preprocessor manual parameter-binding decorations.
|
||||
//
|
||||
|
||||
// We are going to define a simple model for surface material shading.
|
||||
//
|
||||
// The first building block in our model will be the representation of
|
||||
// the geometry attributes of a surface as fed into the material.
|
||||
//
|
||||
struct SurfaceGeometry
|
||||
{
|
||||
float3 position;
|
||||
float3 normal;
|
||||
|
||||
// TODO: tangent vectors would be the natural next thing to add here,
|
||||
// and would be required for anisotropic materials. However, the
|
||||
// simplistic model loading code we are currently using doesn't
|
||||
// produce tangents...
|
||||
//
|
||||
// float3 tangentU;
|
||||
// float3 tangentV;
|
||||
|
||||
// We store a single UV parameterization in these geometry attributes.
|
||||
// A more complex renderer might need support for multiple UV sets,
|
||||
// and indeed it might choose to use interfaces and generics to capture
|
||||
// the different requirements that different materials impose on
|
||||
// the available surface attributes. We won't go to that kind of
|
||||
// trouble for such a simple example.
|
||||
//
|
||||
float2 uv;
|
||||
};
|
||||
//
|
||||
// Next, we want to define the fundamental concept of a refletance
|
||||
// function, so that we can use it as a building block for other
|
||||
// parts of the system. This is a case where we are trying to
|
||||
// show how a proper physically-based renderer (PBR) might
|
||||
// decompose the problem using Slang, even though our simple
|
||||
// example is *not* physically based.
|
||||
//
|
||||
interface IBRDF
|
||||
{
|
||||
// Technically, a BRDF is only a function of the incident
|
||||
// (`wi`) and exitant (`wo`) directions, but for simplicity
|
||||
// we are passing in the surface normal (`N`) as well.
|
||||
//
|
||||
float3 evaluate(float3 wo, float3 wi, float3 N);
|
||||
};
|
||||
//
|
||||
// We can now define various implemntations of the `IBRDF` interface
|
||||
// that represent different reflectance functions we want to support.
|
||||
// For now we keep things simple by defining about the simplest
|
||||
// reflectance function we can think of: the Blinn-Phong reflectance
|
||||
// model:
|
||||
//
|
||||
struct BlinnPhong : IBRDF
|
||||
{
|
||||
// Blinn-Phong needs diffuse and specular reflectances, plus
|
||||
// a specular exponent value (which relates to "roughness"
|
||||
// in more modern physically-based models).
|
||||
//
|
||||
float3 kd;
|
||||
float3 ks;
|
||||
float specularity;
|
||||
|
||||
// Here we implement the one requirement of the `IBRDF` interface
|
||||
// for our concrete implementation, using a textbook definition
|
||||
// of Blinng-Phong shading.
|
||||
//
|
||||
// Note: our "BRDF" definition here folds the N-dot-L term into
|
||||
// the evlauation of the reflectance function in case there are
|
||||
// useful algebraic simplifications this enables.
|
||||
//
|
||||
float3 evaluate(float3 V, float3 L, float3 N)
|
||||
{
|
||||
float nDotL = saturate(dot(N, L));
|
||||
float3 H = normalize(L + V);
|
||||
float nDotH = saturate(dot(N, H));
|
||||
|
||||
return kd*nDotL + ks*pow(nDotH, specularity);
|
||||
}
|
||||
};
|
||||
//
|
||||
// It is important to note that a reflectance function is *not*
|
||||
// a "material." In most cases, a material will have spatially-varying
|
||||
// properties so that it cannot be summarized as a single `IBRDF`
|
||||
// instance.
|
||||
//
|
||||
// Thus a "material" is a value that can produce a BRDF for any point
|
||||
// on a surface (e.g., by sampling texture maps, etc.).
|
||||
//
|
||||
interface IMaterial
|
||||
{
|
||||
// Different concrete material implementations might yield BRDF
|
||||
// values with different types. E.g., one material might yield
|
||||
// reflectance functions using `BlinnPhong` while another uses
|
||||
// a much more complicated/accurate representation.
|
||||
//
|
||||
// We encapsulate the choice of BRDF parameters/evaluation in
|
||||
// our material interface with an "associated type." In the
|
||||
// simplest terms, think of this as an interface requirement
|
||||
// that is a type, instead of a method.
|
||||
//
|
||||
// (If you are C++-minded, you might think of this as akin to
|
||||
// how every container provided an `iterator` type, but different
|
||||
// containers may have different types of iterators)
|
||||
//
|
||||
associatedtype BRDF : IBRDF;
|
||||
|
||||
// For our simple example program, it is enough for a material to
|
||||
// be able to return a BRDF given a point on the surface.
|
||||
//
|
||||
// A more complex implementation of material shading might also
|
||||
// have the material return updated surface geometry to reflect
|
||||
// the result of normal mapping, occlusion mapping, etc. or
|
||||
// return an opacity/coverage value for partially transparent
|
||||
// surfaces.
|
||||
//
|
||||
BRDF prepare(SurfaceGeometry geometry);
|
||||
};
|
||||
|
||||
// We will now define a trivial first implementation of the material
|
||||
// interface, which uses our Blinn-Phong BRDF with uniform values
|
||||
// for its parameters.
|
||||
//
|
||||
// Note that this implemetnation is being provided *after* the
|
||||
// shader parameter `gMaterial` is declared, so that there is no
|
||||
// assumption in the shader code that `gMaterial` will be plugged
|
||||
// in using an instance of `SimpleMaterial`
|
||||
//
|
||||
//
|
||||
struct SimpleMaterial : IMaterial
|
||||
{
|
||||
// We declare the properties we need as fields of the material type.
|
||||
// When `SimpleMaterial` is used for `TMaterial` above, then
|
||||
// `gMaterial` will be a `ParameterBlock<SimpleMaterial>`, and these
|
||||
// parameters will be allocated to a constant buffer that is part of
|
||||
// that parameter block.
|
||||
//
|
||||
// TODO: A future version of this example will include texture parameters
|
||||
// here to show that they are declared just like simple uniforms.
|
||||
//
|
||||
float3 diffuseColor;
|
||||
float3 specularColor;
|
||||
float specularity;
|
||||
|
||||
// To satisfy the requirements of the `IMaterial` interface, our
|
||||
// material type needs to provide a suitable `BRDF` type. We
|
||||
// do this by using a simple `typedef`, although a nested
|
||||
// `struct` type can also satisfy an associated type requirement.
|
||||
//
|
||||
// A future version of the Slang compiler may allow the "right"
|
||||
// associated type definition to be inferred from the signature
|
||||
// of the `prepare()` method below.
|
||||
//
|
||||
typedef BlinnPhong BRDF;
|
||||
|
||||
BlinnPhong prepare(SurfaceGeometry geometry)
|
||||
{
|
||||
BlinnPhong brdf;
|
||||
brdf.kd = diffuseColor;
|
||||
brdf.ks = specularColor;
|
||||
brdf.specularity = specularity;
|
||||
return brdf;
|
||||
}
|
||||
};
|
||||
//
|
||||
// Note that no other code in this file statically
|
||||
// references the `SimpleMaterial` type, and instead
|
||||
// it is up to the application to "plug in" this type,
|
||||
// or another `IMaterial` implementation for the
|
||||
// `TMaterial` parameter.
|
||||
//
|
||||
|
||||
// A light, or an entire lighting *environment* is an object
|
||||
// that can illuminate a surface using some BRDF implemented
|
||||
// with our abstractions above.
|
||||
//
|
||||
interface ILightEnv
|
||||
{
|
||||
// The `illuminate` method is intended to integrate incoming
|
||||
// illumination from this light (environment) incident at the
|
||||
// surface point given by `g` (which has the reflectance function
|
||||
// `brdf`) and reflected into the outgoing direction `wo`.
|
||||
//
|
||||
float3 illuminate<B:IBRDF>(SurfaceGeometry g, B brdf, float3 wo);
|
||||
//
|
||||
// Note that the `illuminate()` method is allowed as an interface
|
||||
// requirement in Slang even though it is a generic. Constract that
|
||||
// with C++ where a `template` method cannot be `virtual`.
|
||||
};
|
||||
|
||||
// Given the `ILightEnv` interface, we can write up almost textbook
|
||||
// definition of directional and point lights.
|
||||
|
||||
struct DirectionalLight : ILightEnv
|
||||
{
|
||||
float3 direction;
|
||||
float3 intensity;
|
||||
|
||||
float3 illuminate<B:IBRDF>(SurfaceGeometry g, B brdf, float3 wo)
|
||||
{
|
||||
return intensity * brdf.evaluate(wo, direction, g.normal);
|
||||
}
|
||||
};
|
||||
struct PointLight : ILightEnv
|
||||
{
|
||||
float3 position;
|
||||
float3 intensity;
|
||||
|
||||
float3 illuminate<B:IBRDF>(SurfaceGeometry g, B brdf, float3 wo)
|
||||
{
|
||||
float3 delta = position - g.position;
|
||||
float d = length(delta);
|
||||
float3 direction = normalize(delta);
|
||||
float3 illuminance = intensity / (d*d);
|
||||
return illuminance * brdf.evaluate(wo, direction, g.normal);
|
||||
}
|
||||
};
|
||||
|
||||
// In most cases, a shader entry point will only be specialized for a single
|
||||
// material, but interesting rendering almost always needs multiple lights.
|
||||
// For that reason we will next define types to represent *composite* lighting
|
||||
// environment with multiple lights.
|
||||
//
|
||||
// A naive approach might be to have a single undifferntiated list of lights
|
||||
// where any type of light may appear at any index, but this would lose all
|
||||
// of the benefits of static specialization: we would have to perform dynamic
|
||||
// branching to determine what kind of light is stored at each index.
|
||||
//
|
||||
// Instead, we will start with a type for *homogeneous* arrays of lights:
|
||||
//
|
||||
struct LightArray<L : ILightEnv, let N : int> : ILightEnv
|
||||
{
|
||||
// The `LightArray` type has two generic parameters:
|
||||
//
|
||||
// - `L` is a type parameter, representing the type of lights that will be in our array
|
||||
// - `N` is a generic *value* parameter, representing the maximum number of lights allowed
|
||||
//
|
||||
// Slang's support for generic value parameters is currently experimental,
|
||||
// and the syntax might change.
|
||||
|
||||
int count;
|
||||
L lights[N];
|
||||
|
||||
float3 illuminate<B:IBRDF>(SurfaceGeometry g, B brdf, float3 wo)
|
||||
{
|
||||
// Our light array integrates illumination by naively summing
|
||||
// contributions from all the lights in the array (up to `count`).
|
||||
//
|
||||
// A more advanced renderer might try apply sampling techniques
|
||||
// to pick a subset of lights to sample.
|
||||
//
|
||||
float3 sum = 0;
|
||||
for( int ii = 0; ii < count; ++ii )
|
||||
{
|
||||
sum += lights[ii].illuminate(g, brdf, wo);
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
};
|
||||
|
||||
// `LightArray` can handle multiple lights as long as they have the
|
||||
// same type, but we need a way to have a scene with multiple lights
|
||||
// of different types *without* losing static specialization.
|
||||
//
|
||||
// The `LightPair<T,U>` type supports this in about the simplest way
|
||||
// possible, by aggregating a light (environment) of type `T` and
|
||||
// one of type `U`. Those light environments might themselves be
|
||||
// `LightArray`s or `LightPair`s, so that arbitrarily complex
|
||||
// environments can be created from just these two composite types.
|
||||
//
|
||||
// This is probably a good place to insert a reminder the Slang's
|
||||
// generics are *not* C++ templates, so that the error messages
|
||||
// produced when working with these types are in general reasonable,
|
||||
// and this is *not* any form of "template metaprogramming."
|
||||
//
|
||||
// That said, we expect that future versions of Slang will make
|
||||
// defining composite types light this a bit less cumbersome.
|
||||
//
|
||||
struct LightPair<T : ILightEnv, U : ILightEnv> : ILightEnv
|
||||
{
|
||||
T first;
|
||||
U second;
|
||||
|
||||
float3 illuminate<B:IBRDF>(SurfaceGeometry g, B brdf, float3 wo)
|
||||
{
|
||||
return first.illuminate(g, brdf, wo)
|
||||
+ second.illuminate(g, brdf, wo);
|
||||
}
|
||||
};
|
||||
|
||||
// As a final (degenerate) case, we will define a light
|
||||
// environment with *no* lights, which contributes no illumination.
|
||||
//
|
||||
struct EmptyLightEnv : ILightEnv
|
||||
{
|
||||
float3 illuminate<B:IBRDF>(SurfaceGeometry g, B brdf, float3 wo)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
// The code above constitutes the "shader library" for our
|
||||
// application, while the code below this point is the
|
||||
// implementation of a simple forward rendering pass
|
||||
// using that library.
|
||||
//
|
||||
// While the shader library has used many of Slang's advanced
|
||||
// mechanisms, the vertex and fragment shaders will be
|
||||
// much more modest, and hopefully easier to follow.
|
||||
|
||||
|
||||
// We will start with a `struct` for per-view parameters that
|
||||
// will be allocated into a `ParameterBlock`.
|
||||
//
|
||||
// As written, this isn't very different from using an HLSL
|
||||
// `cbuffer` declaration, but importantly this code will
|
||||
// continue to work if we add one or more resources (e.g.,
|
||||
// an enironment map texture) to the `PerView` type.
|
||||
//
|
||||
struct PerView
|
||||
{
|
||||
float4x4 viewProjection;
|
||||
float3 eyePosition;
|
||||
};
|
||||
ParameterBlock<PerView> gViewParams;
|
||||
|
||||
// Declaring a block for per-model parameter data is
|
||||
// similarly simple.
|
||||
//
|
||||
struct PerModel
|
||||
{
|
||||
float4x4 modelTransform;
|
||||
float4x4 inverseTransposeModelTransform;
|
||||
};
|
||||
ParameterBlock<PerModel> gModelParams;
|
||||
|
||||
// We want our shader to work with any kind of lighting environment
|
||||
// - that is, and type that implements `ILightEnv`. Furthermore,
|
||||
// we want the parameters of that lighting environment to be passed
|
||||
// as parameter block - `ParameterBlock<L>` for some type `L`.
|
||||
//
|
||||
// We handle this by defining a global generic type parameter for
|
||||
// our shader, and constrainting it to implement `ILightEnv`...
|
||||
//
|
||||
type_param TLightEnv : ILightEnv;
|
||||
//
|
||||
// ... and then defining a parameter block that uses that type
|
||||
// parameter as the "element type" of the block:
|
||||
//
|
||||
ParameterBlock<TLightEnv> gLightEnv;
|
||||
|
||||
// Our handling of the material parameter for our shader
|
||||
// is quite similar to the case for the lighting environment:
|
||||
//
|
||||
type_param TMaterial : IMaterial;
|
||||
ParameterBlock<TMaterial> gMaterial;
|
||||
|
||||
// Our vertex shader entry point is only marginally more
|
||||
// complicated than the Hello World example. We will
|
||||
// start by declaring the various "connector" `struct`s.
|
||||
//
|
||||
struct AssembledVertex
|
||||
{
|
||||
float3 position : POSITION;
|
||||
float3 normal : NORMAL;
|
||||
float2 uv : UV;
|
||||
};
|
||||
struct CoarseVertex
|
||||
{
|
||||
float3 worldPosition;
|
||||
float3 worldNormal;
|
||||
float2 uv;
|
||||
};
|
||||
struct VertexStageOutput
|
||||
{
|
||||
CoarseVertex coarseVertex : CoarseVertex;
|
||||
float4 sv_position : SV_Position;
|
||||
};
|
||||
|
||||
// Perhaps most interesting new feature of the entry
|
||||
// point decalrations is that we use a `[shader(...)]`
|
||||
// attribute (as introduced in HLSL Shader Model 6.x)
|
||||
// in order to tag our entry points.
|
||||
//
|
||||
// This attribute informs the Slang compiler which
|
||||
// functions are intended to be compiled as shader
|
||||
// entry points (and what stage they target), so that
|
||||
// the programmer no longer needs to specify the
|
||||
// entry point name/stage through the API (or on
|
||||
// the command line when using `slangc`).
|
||||
//
|
||||
// While HLSL added this feature only in newer versions,
|
||||
// the Slang compiler supports this attribute across
|
||||
// *all* targets, so that it is okay to use whether you
|
||||
// want DXBC, DXIL, or SPIR-V output.
|
||||
//
|
||||
[shader("vertex")]
|
||||
VertexStageOutput vertexMain(
|
||||
AssembledVertex assembledVertex)
|
||||
{
|
||||
VertexStageOutput output;
|
||||
|
||||
float3 position = assembledVertex.position;
|
||||
float3 normal = assembledVertex.normal;
|
||||
float2 uv = assembledVertex.uv;
|
||||
|
||||
float3 worldPosition = mul(gModelParams.modelTransform, float4(position, 1.0)).xyz;
|
||||
float3 worldNormal = mul(gModelParams.inverseTransposeModelTransform, float4(normal, 0.0)).xyz;
|
||||
|
||||
output.coarseVertex.worldPosition = worldPosition;
|
||||
output.coarseVertex.worldNormal = worldNormal;
|
||||
output.coarseVertex.uv = uv;
|
||||
|
||||
output.sv_position = mul(gViewParams.viewProjection, float4(worldPosition, 1.0));
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
// Our fragment shader is almost trivial, with the most interesting
|
||||
// thing being how it uses the `TMaterial` type parameter (through the
|
||||
// value stored in the `gMaterial` parameter block) to dispatch to
|
||||
// the correct implementation of the `getDiffuseColor()` method
|
||||
// in the `IMaterial` interface.
|
||||
//
|
||||
// The `gMaterial` parameter block declaration thus serves not only
|
||||
// to group certain shader parameters for efficient CPU-to-GPU
|
||||
// communication, but also to select the code that will execute
|
||||
// in specialized versions of the `fragmentMain` entry point.
|
||||
//
|
||||
[shader("fragment")]
|
||||
float4 fragmentMain(
|
||||
CoarseVertex coarseVertex : CoarseVertex) : SV_Target
|
||||
float4 fragmentMain(float2 texCoord)
|
||||
{
|
||||
// We start by using our interpolated vertex attributes
|
||||
// to construct the local surface geometry that we will
|
||||
// use for material evaluation.
|
||||
//
|
||||
SurfaceGeometry g;
|
||||
g.position = coarseVertex.worldPosition;
|
||||
g.normal = normalize(coarseVertex.worldNormal);
|
||||
g.uv = coarseVertex.uv;
|
||||
|
||||
float3 V = normalize(gViewParams.eyePosition - g.position);
|
||||
|
||||
// Next we prepare the material, which involves running
|
||||
// any "pattern generation" logic of the material (e.g.,
|
||||
// sampling and blending texture layers), to produce
|
||||
// a BRDF suitable for evaluating under illumination
|
||||
// from different light sources.
|
||||
//
|
||||
// Note that the return type here is `TMaterial.BRDF`,
|
||||
// which is the `BRDF` type *associated* with the (unknown)
|
||||
// `TMaterial` type. When `TMaterial` gets substituted for
|
||||
// a concrete type later (e.g., `SimpleMaterial`) this
|
||||
// will resolve to a concrete type too (e.g., `SimpleMaterial.BRDF`
|
||||
// which is an alias for `BlinnPhong`).
|
||||
//
|
||||
TMaterial.BRDF brdf = gMaterial.prepare(g);
|
||||
|
||||
// Now that we've done the first step of material evaluation
|
||||
// and sampled texture maps, etc., it is time to start
|
||||
// integrating incident light at our surface point.
|
||||
//
|
||||
// Because we've wrapped up the lighting environment as
|
||||
// a single (composite) object, this is as simple as calling
|
||||
// its `illuminate()` method. Our particular fragment shader
|
||||
// is thus abstracted from how the renderer chooses to structure
|
||||
// this integration step, somewhat similar to how an
|
||||
// `illuminance` loop in RenderMan Shading Language works.
|
||||
//
|
||||
|
||||
float3 color = gLightEnv.illuminate(g, brdf, V);
|
||||
|
||||
return float4(color, 1);
|
||||
return gMaterial.sample(texCoord);
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
#include "Window/WindowManager.h"
|
||||
#include "Scene/Components/PrimitiveComponent.h"
|
||||
#include "Window/SceneView.h"
|
||||
#include "Window/InspectorView.h"
|
||||
#include "Asset/AssetRegistry.h"
|
||||
|
||||
@@ -31,10 +31,10 @@ public:
|
||||
std::scoped_lock lck(lock);
|
||||
return status;
|
||||
}
|
||||
inline void setStatus(Status status)
|
||||
inline void setStatus(Status _status)
|
||||
{
|
||||
std::scoped_lock lck(lock);
|
||||
this->status = status;
|
||||
status = _status;
|
||||
}
|
||||
protected:
|
||||
std::mutex lock;
|
||||
|
||||
@@ -91,10 +91,10 @@ AssetRegistry::AssetRegistry()
|
||||
{
|
||||
}
|
||||
|
||||
void AssetRegistry::init(const std::filesystem::path &rootFolder, Gfx::PGraphics graphics)
|
||||
void AssetRegistry::init(const std::filesystem::path &_rootFolder, Gfx::PGraphics graphics)
|
||||
{
|
||||
AssetRegistry ® = get();
|
||||
reg.rootFolder = rootFolder;
|
||||
reg.rootFolder = _rootFolder;
|
||||
reg.fontLoader = new FontLoader(graphics);
|
||||
reg.meshLoader = new MeshLoader(graphics);
|
||||
reg.textureLoader = new TextureLoader(graphics);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include "MinimalEngine.h"
|
||||
#include "Asset.h"
|
||||
#include "Material/MaterialAsset.h"
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
|
||||
@@ -52,8 +52,8 @@ void FontAsset::load()
|
||||
continue;
|
||||
}
|
||||
Glyph& glyph = 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.size = Math::IVector2(face->glyph->bitmap.width, face->glyph->bitmap.rows);
|
||||
glyph.bearing = Math::IVector2(face->glyph->bitmap_left, face->glyph->bitmap_top);
|
||||
glyph.advance = face->glyph->advance.x;
|
||||
TextureCreateInfo imageData;
|
||||
imageData.format = Gfx::SE_FORMAT_R8_UINT;
|
||||
|
||||
@@ -17,8 +17,8 @@ public:
|
||||
struct Glyph
|
||||
{
|
||||
Gfx::PTexture2D texture;
|
||||
IVector2 size;
|
||||
IVector2 bearing;
|
||||
Math::IVector2 size;
|
||||
Math::IVector2 bearing;
|
||||
uint32 advance;
|
||||
};
|
||||
const std::map<uint32, Glyph> getGlyphData() const { return glyphs; }
|
||||
|
||||
@@ -36,7 +36,7 @@ void MeshLoader::importAsset(const std::filesystem::path &path)
|
||||
import(path, asset);
|
||||
}
|
||||
|
||||
void MeshLoader::loadMaterials(const aiScene* scene, Array<PMaterialAsset>& globalMaterials, Gfx::PGraphics graphics)
|
||||
void MeshLoader::loadMaterials(const aiScene* scene, Array<PMaterialAsset>& globalMaterials)
|
||||
{
|
||||
using json = nlohmann::json;
|
||||
for(uint32 i = 0; i < scene->mNumMaterials; ++i)
|
||||
@@ -111,44 +111,44 @@ void findMeshRoots(aiNode *node, List<aiNode *> &meshNodes)
|
||||
}
|
||||
VertexStreamComponent createVertexStream(uint32 size, aiVector3D* sourceData, Gfx::PGraphics graphics)
|
||||
{
|
||||
Array<Vector> buffer(size);
|
||||
Array<Math::Vector> buffer(size);
|
||||
for(uint32 i = 0; i < size; ++i)
|
||||
{
|
||||
buffer[i] = Vector(sourceData[i].x, sourceData[i].y, sourceData[i].z);
|
||||
buffer[i] = Math::Vector(sourceData[i].x, sourceData[i].y, sourceData[i].z);
|
||||
}
|
||||
VertexBufferCreateInfo vbInfo;
|
||||
vbInfo.numVertices = size;
|
||||
vbInfo.vertexSize = sizeof(Vector);
|
||||
vbInfo.vertexSize = sizeof(Math::Vector);
|
||||
vbInfo.resourceData.data = (uint8 *)buffer.data();
|
||||
vbInfo.resourceData.owner = Gfx::QueueType::DEDICATED_TRANSFER;
|
||||
vbInfo.resourceData.size = sizeof(Vector) * (uint32)buffer.size();
|
||||
vbInfo.resourceData.size = sizeof(Math::Vector) * buffer.size();
|
||||
Gfx::PVertexBuffer vertexBuffer = graphics->createVertexBuffer(vbInfo);
|
||||
vertexBuffer->transferOwnership(Gfx::QueueType::GRAPHICS);
|
||||
return VertexStreamComponent(vertexBuffer, 0, vbInfo.vertexSize, Gfx::SE_FORMAT_R32G32B32_SFLOAT);
|
||||
}
|
||||
VertexStreamComponent createVertexStream(uint32 size, aiVector2D* sourceData, Gfx::PGraphics graphics)
|
||||
{
|
||||
Array<Vector2> buffer(size);
|
||||
Array<Math::Vector2> buffer(size);
|
||||
for(uint32 i = 0; i < size; ++i)
|
||||
{
|
||||
buffer[i] = Vector2(sourceData[i].x, sourceData[i].y);
|
||||
buffer[i] = Math::Vector2(sourceData[i].x, sourceData[i].y);
|
||||
}
|
||||
VertexBufferCreateInfo vbInfo;
|
||||
vbInfo.numVertices = size;
|
||||
vbInfo.vertexSize = sizeof(Vector2);
|
||||
vbInfo.vertexSize = sizeof(Math::Vector2);
|
||||
vbInfo.resourceData.data = (uint8 *)buffer.data();
|
||||
vbInfo.resourceData.owner = Gfx::QueueType::DEDICATED_TRANSFER;
|
||||
vbInfo.resourceData.size = sizeof(Vector2) * (uint32)buffer.size();
|
||||
vbInfo.resourceData.size = sizeof(Math::Vector2) * buffer.size();
|
||||
Gfx::PVertexBuffer vertexBuffer = graphics->createVertexBuffer(vbInfo);
|
||||
vertexBuffer->transferOwnership(Gfx::QueueType::GRAPHICS);
|
||||
return VertexStreamComponent(vertexBuffer, 0, vbInfo.vertexSize, Gfx::SE_FORMAT_R32G32_SFLOAT);
|
||||
}
|
||||
void MeshLoader::loadGlobalMeshes(const aiScene* scene, Array<PMesh>& globalMeshes, const Array<PMaterialAsset>& materials, Gfx::PGraphics graphics)
|
||||
void MeshLoader::loadGlobalMeshes(const aiScene* scene, Array<PMesh>& globalMeshes, const Array<PMaterialAsset>& materials)
|
||||
{
|
||||
for (uint32 meshIndex = 0; meshIndex < scene->mNumMeshes; ++meshIndex)
|
||||
{
|
||||
aiMesh *mesh = scene->mMeshes[meshIndex];
|
||||
|
||||
PMaterialAsset material = materials[mesh->mMaterialIndex];
|
||||
PStaticMeshVertexInput vertexShaderInput = new StaticMeshVertexInput(std::string(mesh->mName.C_Str()));
|
||||
StaticMeshDataType data;
|
||||
data.positionStream = createVertexStream(mesh->mNumVertices, mesh->mVertices, graphics);
|
||||
@@ -188,7 +188,7 @@ void MeshLoader::loadGlobalMeshes(const aiScene* scene, Array<PMesh>& globalMesh
|
||||
idxInfo.indexType = Gfx::SE_INDEX_TYPE_UINT32;
|
||||
idxInfo.resourceData.data = (uint8 *)indices.data();
|
||||
idxInfo.resourceData.owner = Gfx::QueueType::DEDICATED_TRANSFER;
|
||||
idxInfo.resourceData.size = sizeof(uint32) * (uint32)indices.size();
|
||||
idxInfo.resourceData.size = sizeof(uint32) * indices.size();
|
||||
Gfx::PIndexBuffer indexBuffer = graphics->createIndexBuffer(idxInfo);
|
||||
indexBuffer->transferOwnership(Gfx::QueueType::GRAPHICS);
|
||||
|
||||
@@ -249,10 +249,10 @@ void MeshLoader::import(std::filesystem::path path, PMeshAsset meshAsset)
|
||||
|
||||
Array<PMaterialAsset> globalMaterials(scene->mNumMaterials);
|
||||
loadTextures(scene, path.parent_path());
|
||||
loadMaterials(scene, globalMaterials, graphics);
|
||||
loadMaterials(scene, globalMaterials);
|
||||
|
||||
Array<PMesh> globalMeshes(scene->mNumMeshes);
|
||||
loadGlobalMeshes(scene, globalMeshes, globalMaterials, graphics);
|
||||
loadGlobalMeshes(scene, globalMeshes, globalMaterials);
|
||||
|
||||
|
||||
List<aiNode *> meshNodes;
|
||||
|
||||
@@ -18,9 +18,9 @@ public:
|
||||
~MeshLoader();
|
||||
void importAsset(const std::filesystem::path& filePath);
|
||||
private:
|
||||
void loadMaterials(const aiScene* scene, Array<PMaterialAsset>& globalMaterials, Gfx::PGraphics graphics);
|
||||
void loadMaterials(const aiScene* scene, Array<PMaterialAsset>& globalMaterials);
|
||||
void loadTextures(const aiScene* scene, const std::filesystem::path& meshPath);
|
||||
void loadGlobalMeshes(const aiScene* scene, Array<PMesh>& globalMeshes, const Array<PMaterialAsset>& materials, Gfx::PGraphics graphics);
|
||||
void loadGlobalMeshes(const aiScene* scene, Array<PMesh>& globalMeshes, const Array<PMaterialAsset>& materials);
|
||||
void convertAssimpARGB(unsigned char* dst, aiTexel* src, uint32 numPixels);
|
||||
|
||||
void import(std::filesystem::path path, PMeshAsset meshAsset);
|
||||
|
||||
@@ -50,10 +50,10 @@ void TextureAsset::load()
|
||||
createInfo.mipLevels = kTexture->numLevels;
|
||||
createInfo.usage = Gfx::SE_IMAGE_USAGE_SAMPLED_BIT;
|
||||
createInfo.resourceData.data = ktxTexture_GetData(ktxTexture(kTexture));
|
||||
createInfo.resourceData.size = (uint32)ktxTexture_GetDataSize(ktxTexture(kTexture));
|
||||
createInfo.resourceData.size = ktxTexture_GetDataSize(ktxTexture(kTexture));
|
||||
createInfo.resourceData.owner = Gfx::QueueType::DEDICATED_TRANSFER;
|
||||
Gfx::PTexture2D texture = WindowManager::getGraphics()->createTexture2D(createInfo);
|
||||
texture->transferOwnership(Gfx::QueueType::GRAPHICS);
|
||||
setTexture(texture);
|
||||
Gfx::PTexture2D tex = WindowManager::getGraphics()->createTexture2D(createInfo);
|
||||
tex->transferOwnership(Gfx::QueueType::GRAPHICS);
|
||||
setTexture(tex);
|
||||
setStatus(Asset::Status::Ready);
|
||||
}
|
||||
@@ -12,10 +12,10 @@ public:
|
||||
virtual ~TextureAsset();
|
||||
virtual void save() override;
|
||||
virtual void load() override;
|
||||
void setTexture(Gfx::PTexture texture)
|
||||
void setTexture(Gfx::PTexture _texture)
|
||||
{
|
||||
std::scoped_lock lck(lock);
|
||||
this->texture = texture;
|
||||
texture = _texture;
|
||||
}
|
||||
Gfx::PTexture getTexture()
|
||||
{
|
||||
|
||||
@@ -679,6 +679,16 @@ public:
|
||||
beginIt = iterator(_data);
|
||||
endIt = iterator(_data + N);
|
||||
}
|
||||
StaticArray(std::initializer_list<T> init)
|
||||
{
|
||||
assert(init.size() == N);
|
||||
auto beg = init.begin();
|
||||
for (int i = 0; i < N; ++i)
|
||||
{
|
||||
_data[i] = *beg;
|
||||
beg++;
|
||||
}
|
||||
}
|
||||
~StaticArray()
|
||||
{
|
||||
}
|
||||
|
||||
+18
-18
@@ -40,8 +40,8 @@ private:
|
||||
size_t rightChild;
|
||||
Pair<K, V> pair;
|
||||
Node()
|
||||
: leftChild(-1)
|
||||
, rightChild(-1)
|
||||
: leftChild(SIZE_MAX)
|
||||
, rightChild(SIZE_MAX)
|
||||
, pair()
|
||||
{
|
||||
}
|
||||
@@ -50,8 +50,8 @@ private:
|
||||
Node& operator=(const Node& other) = default;
|
||||
Node& operator=(Node&& other) = default;
|
||||
Node(K key)
|
||||
: leftChild(-1)
|
||||
, rightChild(-1)
|
||||
: leftChild(SIZE_MAX)
|
||||
, rightChild(SIZE_MAX)
|
||||
, pair(std::move(key))
|
||||
{
|
||||
}
|
||||
@@ -71,7 +71,7 @@ public:
|
||||
using reference = PairType&;
|
||||
using pointer = PairType*;
|
||||
|
||||
IteratorBase(size_t x = -1)
|
||||
IteratorBase(size_t x = SIZE_MAX)
|
||||
: node(x)
|
||||
{
|
||||
}
|
||||
@@ -199,9 +199,9 @@ public:
|
||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
|
||||
constexpr Map() noexcept
|
||||
: root(-1)
|
||||
, beginIt(-1)
|
||||
, endIt(-1)
|
||||
: root(SIZE_MAX)
|
||||
, beginIt(SIZE_MAX)
|
||||
, endIt(SIZE_MAX)
|
||||
, iteratorsDirty(true)
|
||||
, _size(0)
|
||||
, comp(Compare())
|
||||
@@ -209,9 +209,9 @@ public:
|
||||
}
|
||||
constexpr explicit Map(const Compare& comp, const Allocator& alloc = Allocator()) noexcept(noexcept(Allocator()))
|
||||
: nodeContainer(alloc)
|
||||
, root(-1)
|
||||
, beginIt(-1)
|
||||
, endIt(-1)
|
||||
, root(SIZE_MAX)
|
||||
, beginIt(SIZE_MAX)
|
||||
, endIt(SIZE_MAX)
|
||||
, iteratorsDirty(true)
|
||||
, _size(0)
|
||||
, comp(comp)
|
||||
@@ -219,9 +219,9 @@ public:
|
||||
}
|
||||
constexpr explicit Map(const Allocator& alloc) noexcept(noexcept(Compare))
|
||||
: nodeContainer(alloc)
|
||||
, root(-1)
|
||||
, beginIt(-1)
|
||||
, endIt(-1)
|
||||
, root(SIZE_MAX)
|
||||
, beginIt(SIZE_MAX)
|
||||
, endIt(SIZE_MAX)
|
||||
, iteratorsDirty(true)
|
||||
, _size(0)
|
||||
, comp(Compare())
|
||||
@@ -335,7 +335,7 @@ public:
|
||||
constexpr void clear()
|
||||
{
|
||||
nodeContainer.clear();
|
||||
root = -1;
|
||||
root = SIZE_MAX;
|
||||
_size = 0;
|
||||
markIteratorsDirty();
|
||||
}
|
||||
@@ -510,13 +510,13 @@ private:
|
||||
{
|
||||
newNode->rightChild = r;
|
||||
newNode->leftChild = node->leftChild;
|
||||
node->leftChild = -1;
|
||||
node->leftChild = SIZE_MAX;
|
||||
}
|
||||
else
|
||||
{
|
||||
newNode->leftChild = r;
|
||||
newNode->rightChild = node->rightChild;
|
||||
node->rightChild = -1;
|
||||
node->rightChild = SIZE_MAX;
|
||||
}
|
||||
return nodeContainer.size() - 1;
|
||||
}
|
||||
@@ -525,7 +525,7 @@ private:
|
||||
{
|
||||
size_t temp;
|
||||
if (!isValid(r))
|
||||
return -1;
|
||||
return SIZE_MAX;
|
||||
|
||||
r = splay(r, key);
|
||||
Node* node = getNode(r);
|
||||
|
||||
@@ -18,10 +18,10 @@ PVertexBuffer Graphics::getNullVertexBuffer()
|
||||
{
|
||||
VertexBufferCreateInfo createInfo;
|
||||
createInfo.numVertices = 1;
|
||||
createInfo.vertexSize = sizeof(Vector4);
|
||||
Vector4 data = Vector4(1, 1, 1, 1);
|
||||
createInfo.vertexSize = sizeof(Math::Vector4);
|
||||
Math::Vector4 data = Math::Vector4(1, 1, 1, 1);
|
||||
createInfo.resourceData.data = reinterpret_cast<uint8*>(&data);
|
||||
createInfo.resourceData.size = sizeof(Vector4);
|
||||
createInfo.resourceData.size = sizeof(Math::Vector4);
|
||||
nullVertexBuffer = createVertexBuffer(createInfo);
|
||||
}
|
||||
return nullVertexBuffer;
|
||||
|
||||
@@ -50,7 +50,8 @@ struct ViewportCreateInfo
|
||||
// doesnt own the data, only proxy it
|
||||
struct BulkResourceData
|
||||
{
|
||||
uint32 size = 0;
|
||||
uint64 size = 0;
|
||||
uint64 offset = 0;
|
||||
uint8 *data = nullptr;
|
||||
Gfx::QueueType owner = Gfx::QueueType::GRAPHICS;
|
||||
};
|
||||
@@ -111,8 +112,9 @@ struct StructuredBufferCreateInfo
|
||||
};
|
||||
struct ShaderCreateInfo
|
||||
{
|
||||
std::string mainModule;
|
||||
//It's possible to input multiple source files for materials or vertexFactories
|
||||
Array<std::string> shaderCode;
|
||||
Array<std::string> additionalModules;
|
||||
std::string name; // Debug info
|
||||
std::string entryPoint;
|
||||
Array<const char*> typeParameter;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "Graphics.h"
|
||||
#include "RenderPass/DepthPrepass.h"
|
||||
#include "RenderPass/BasePass.h"
|
||||
#include "Material/MaterialAsset.h"
|
||||
|
||||
using namespace Seele;
|
||||
using namespace Seele::Gfx;
|
||||
@@ -11,9 +12,9 @@ std::string getShaderNameFromRenderPassType(Gfx::RenderPassType type)
|
||||
switch (type)
|
||||
{
|
||||
case Gfx::RenderPassType::DepthPrepass:
|
||||
return "DepthPrepass.slang";
|
||||
return "DepthPrepass";
|
||||
case Gfx::RenderPassType::BasePass:
|
||||
return "ForwardPlus.slang";
|
||||
return "ForwardPlus";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
@@ -64,8 +65,6 @@ ShaderCollection& ShaderMap::createShaders(
|
||||
ShaderCreateInfo createInfo;
|
||||
createInfo.entryPoint = "vertexMain";
|
||||
createInfo.typeParameter = {material->getName().c_str()};
|
||||
createInfo.defines["VERTEX_INPUT_IMPORT"] = vertexInput->getShaderFilename();
|
||||
createInfo.defines["MATERIAL_IMPORT"] = material->getName().c_str();
|
||||
createInfo.defines["NUM_MATERIAL_TEXCOORDS"] = "1";
|
||||
createInfo.defines["USE_INSTANCING"] = "0";
|
||||
modifyRenderPassMacros(renderPass, createInfo.defines);
|
||||
@@ -73,7 +72,9 @@ ShaderCollection& ShaderMap::createShaders(
|
||||
|
||||
std::ifstream codeStream("./shaders/" + getShaderNameFromRenderPassType(renderPass));
|
||||
|
||||
createInfo.shaderCode.add(std::string(std::istreambuf_iterator<char>{codeStream}, {}));
|
||||
createInfo.mainModule = getShaderNameFromRenderPassType(renderPass);
|
||||
createInfo.additionalModules.add(vertexInput->getShaderFilename());
|
||||
createInfo.additionalModules.add(material->getName());
|
||||
|
||||
collection.vertexShader = graphics->createVertexShader(createInfo);
|
||||
|
||||
@@ -227,7 +228,7 @@ VertexBuffer::VertexBuffer(QueueFamilyMapping mapping, uint32 numVertices, uint3
|
||||
VertexBuffer::~VertexBuffer()
|
||||
{
|
||||
}
|
||||
IndexBuffer::IndexBuffer(QueueFamilyMapping mapping, uint32 size, Gfx::SeIndexType indexType, QueueType startQueueType)
|
||||
IndexBuffer::IndexBuffer(QueueFamilyMapping mapping, uint64 size, Gfx::SeIndexType indexType, QueueType startQueueType)
|
||||
: Buffer(mapping, startQueueType)
|
||||
, indexType(indexType)
|
||||
{
|
||||
@@ -264,6 +265,129 @@ const Array<VertexElement> VertexStream::getVertexDescriptions() const
|
||||
{
|
||||
return vertexDescription;
|
||||
}
|
||||
|
||||
VertexDataManager::VertexDataManager(PGraphics graphics)
|
||||
: currentSize(8 * 1024 * 1024)
|
||||
, inUse(0)
|
||||
, graphics(graphics)
|
||||
{
|
||||
VertexBufferCreateInfo defaultInfo = {
|
||||
.resourceData = {
|
||||
.size = currentSize,
|
||||
.data = nullptr,
|
||||
}
|
||||
};
|
||||
buffer = graphics->createVertexBuffer(defaultInfo);
|
||||
}
|
||||
|
||||
VertexDataManager::~VertexDataManager()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
VertexDataAllocation VertexDataManager::createVertexBuffer(const VertexBufferCreateInfo& vbInfo)
|
||||
{
|
||||
VertexDataAllocation data = allocateData(vbInfo.resourceData.size);
|
||||
|
||||
buffer->updateRegion(BulkResourceData{
|
||||
.size = data.size,
|
||||
.offset = data.offset,
|
||||
.data = vbInfo.resourceData.data
|
||||
});
|
||||
|
||||
activeAllocations[data.offset] = data;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void VertexDataManager::freeAllocation(VertexDataAllocation alloc)
|
||||
{
|
||||
uint64 lowerBound = alloc.offset;
|
||||
uint64 upperBound = alloc.offset + alloc.size;
|
||||
bool joinedLower = false;
|
||||
uint64 lowerOffset = 0;
|
||||
|
||||
//Join lower bound
|
||||
for (auto& [offset, freeAlloc] : freeRanges)
|
||||
{
|
||||
if (freeAlloc.offset <= lowerBound
|
||||
&& freeAlloc.offset + freeAlloc.size >= upperBound)
|
||||
{
|
||||
// allocation is already in a free region
|
||||
return;
|
||||
}
|
||||
if (freeAlloc.offset + freeAlloc.size == lowerBound)
|
||||
{
|
||||
//extend freeAlloc by the allocatedSize
|
||||
freeAlloc.size += alloc.size;
|
||||
joinedLower = true;
|
||||
lowerOffset = freeAlloc.offset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//Join upper bound
|
||||
auto foundAlloc = freeRanges.find(upperBound);
|
||||
if (foundAlloc != freeRanges.end())
|
||||
{
|
||||
// There is a free allocation ending where the new free one ends
|
||||
if (joinedLower)
|
||||
{
|
||||
// extend allocHandle by another foundAlloc->allocatedSize bytes
|
||||
freeRanges[lowerOffset].size += foundAlloc->value.size;
|
||||
freeRanges.erase(upperBound);
|
||||
}
|
||||
else
|
||||
{
|
||||
// set foundAlloc back by size amount
|
||||
freeRanges[upperBound].offset -= alloc.size;
|
||||
freeRanges[upperBound].size += alloc.size;
|
||||
// place back at correct offset
|
||||
freeRanges[freeRanges[upperBound].offset] = freeRanges[upperBound];
|
||||
// remove from offset map since key changes
|
||||
freeRanges.erase(upperBound);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No matching upper bound found
|
||||
if(!joinedLower)
|
||||
{
|
||||
// Lower bound also not joined, create new range
|
||||
freeRanges[alloc.offset] = alloc;
|
||||
}
|
||||
}
|
||||
activeAllocations.erase(alloc.offset);
|
||||
inUse -= alloc.size;
|
||||
}
|
||||
|
||||
|
||||
VertexDataAllocation VertexDataManager::allocateData(uint64 size)
|
||||
{
|
||||
for (auto& [offset, freeAllocation] : freeRanges)
|
||||
{
|
||||
assert(offset == freeAllocation.offset);
|
||||
if (freeAllocation.size == size)
|
||||
{
|
||||
activeAllocations[offset] = freeAllocation;
|
||||
freeRanges.erase(offset);
|
||||
inUse += size;
|
||||
return freeAllocation;
|
||||
}
|
||||
else if (size < freeAllocation.size)
|
||||
{
|
||||
freeAllocation.size -= size;
|
||||
freeAllocation.offset += size;
|
||||
VertexDataAllocation subAlloc = VertexDataAllocation(size, offset);
|
||||
activeAllocations[offset] = subAlloc;
|
||||
freeRanges[freeAllocation.offset] = freeAllocation;
|
||||
freeRanges.erase(offset);
|
||||
inUse += size;
|
||||
return subAlloc;
|
||||
}
|
||||
}
|
||||
throw std::logic_error("TODO: expand buffer");
|
||||
}
|
||||
|
||||
VertexDeclaration::VertexDeclaration()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
#include "Containers/Array.h"
|
||||
#include "Containers/List.h"
|
||||
#include "GraphicsInitializer.h"
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4701)
|
||||
#include <boost/crc.hpp>
|
||||
#pragma warning(pop)
|
||||
#include <functional>
|
||||
|
||||
|
||||
@@ -372,6 +375,8 @@ public:
|
||||
return vertexSize;
|
||||
}
|
||||
|
||||
virtual void updateRegion(BulkResourceData update) = 0;
|
||||
|
||||
protected:
|
||||
// Inherited via QueueOwnedResource
|
||||
virtual void executeOwnershipBarrier(QueueType newOwner) = 0;
|
||||
@@ -385,9 +390,9 @@ DEFINE_REF(VertexBuffer)
|
||||
class IndexBuffer : public Buffer
|
||||
{
|
||||
public:
|
||||
IndexBuffer(QueueFamilyMapping mapping, uint32 size, Gfx::SeIndexType index, QueueType startQueueType);
|
||||
IndexBuffer(QueueFamilyMapping mapping, uint64 size, Gfx::SeIndexType index, QueueType startQueueType);
|
||||
virtual ~IndexBuffer();
|
||||
constexpr uint32 getNumIndices() const
|
||||
constexpr uint64 getNumIndices() const
|
||||
{
|
||||
return numIndices;
|
||||
}
|
||||
@@ -402,7 +407,7 @@ protected:
|
||||
virtual void executePipelineBarrier(SeAccessFlags srcAccess, SePipelineStageFlags srcStage,
|
||||
SeAccessFlags dstAccess, SePipelineStageFlags dstStage) = 0;
|
||||
Gfx::SeIndexType indexType;
|
||||
uint32 numIndices;
|
||||
uint64 numIndices;
|
||||
};
|
||||
DEFINE_REF(IndexBuffer)
|
||||
|
||||
@@ -442,7 +447,6 @@ protected:
|
||||
uint32 stride;
|
||||
};
|
||||
DEFINE_REF(StructuredBuffer)
|
||||
|
||||
class VertexStream
|
||||
{
|
||||
public:
|
||||
@@ -459,6 +463,34 @@ public:
|
||||
uint8 instanced;
|
||||
};
|
||||
DEFINE_REF(VertexStream)
|
||||
|
||||
struct VertexDataAllocation
|
||||
{
|
||||
uint64 size;
|
||||
uint64 offset;
|
||||
};
|
||||
|
||||
class VertexDataManager
|
||||
{
|
||||
public:
|
||||
VertexDataManager(PGraphics graphics);
|
||||
virtual ~VertexDataManager();
|
||||
|
||||
VertexDataAllocation createVertexBuffer(const VertexBufferCreateInfo& vbInfo);
|
||||
void freeAllocation(VertexDataAllocation alloc);
|
||||
|
||||
PVertexBuffer getVertexBuffer() const { return buffer; }
|
||||
private:
|
||||
VertexDataAllocation allocateData(uint64 size);
|
||||
Map<uint64, VertexDataAllocation> freeRanges;
|
||||
Map<uint64, VertexDataAllocation> activeAllocations;
|
||||
uint64 currentSize;
|
||||
uint64 inUse;
|
||||
PVertexBuffer buffer;
|
||||
PGraphics graphics;
|
||||
};
|
||||
DEFINE_REF(VertexDataManager)
|
||||
|
||||
class VertexDeclaration
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -34,7 +34,7 @@ public:
|
||||
};
|
||||
struct MeshBatch
|
||||
{
|
||||
std::vector<MeshBatchElement> elements;
|
||||
Array<MeshBatchElement> elements;
|
||||
|
||||
uint8 useReverseCulling : 1;
|
||||
uint8 isBackfaceCullingDisabled : 1;
|
||||
@@ -73,10 +73,8 @@ struct MeshBatch
|
||||
MeshBatch& operator=(const MeshBatch& other) = default;
|
||||
MeshBatch& operator=(MeshBatch&& other) = default;
|
||||
};
|
||||
DECLARE_REF(PrimitiveComponent)
|
||||
struct StaticMeshBatch : public MeshBatch
|
||||
{
|
||||
uint32 index;
|
||||
PPrimitiveComponent primitiveComponent;
|
||||
};
|
||||
} // namespace Seele
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
#include "BasePass.h"
|
||||
#include "Graphics/Graphics.h"
|
||||
#include "Window/Window.h"
|
||||
#include "Scene/Components/CameraComponent.h"
|
||||
#include "Scene/Component/Camera.h"
|
||||
#include "Scene/Actor/CameraActor.h"
|
||||
#include "Math/Vector.h"
|
||||
#include "RenderGraph.h"
|
||||
#include "Material/MaterialAsset.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
@@ -73,7 +74,7 @@ BasePass::BasePass(Gfx::PGraphics graphics, Gfx::PViewport viewport, PCameraActo
|
||||
: RenderPass(graphics, viewport)
|
||||
, processor(new BasePassMeshProcessor(viewport, graphics, false))
|
||||
, descriptorSets(4)
|
||||
, source(source->getCameraComponent())
|
||||
, source(source)
|
||||
{
|
||||
UniformBufferCreateInfo uniformInitializer;
|
||||
basePassLayout = graphics->createPipelineLayout();
|
||||
@@ -120,11 +121,11 @@ void BasePass::beginFrame()
|
||||
primitiveLayout->reset();
|
||||
BulkResourceData uniformUpdate;
|
||||
|
||||
viewParams.viewMatrix = source->getViewMatrix();
|
||||
viewParams.projectionMatrix = source->getProjectionMatrix();
|
||||
viewParams.cameraPosition = Vector4(source->getCameraPosition(), 0);
|
||||
viewParams.viewMatrix = source->getCameraComponent().getViewMatrix();
|
||||
viewParams.projectionMatrix = source->getCameraComponent().getProjectionMatrix();
|
||||
viewParams.cameraPosition = Math::Vector4(source->getCameraComponent().getCameraPosition(), 0);
|
||||
viewParams.inverseProjectionMatrix = glm::inverse(viewParams.projectionMatrix);
|
||||
viewParams.screenDimensions = Vector2(static_cast<float>(viewport->getSizeX()), static_cast<float>(viewport->getSizeY()));
|
||||
viewParams.screenDimensions = Math::Vector2(static_cast<float>(viewport->getSizeX()), static_cast<float>(viewport->getSizeY()));
|
||||
uniformUpdate.size = sizeof(ViewParameter);
|
||||
uniformUpdate.data = (uint8*)&viewParams;
|
||||
viewParamBuffer->updateContents(uniformUpdate);
|
||||
|
||||
@@ -27,10 +27,9 @@ private:
|
||||
};
|
||||
DEFINE_REF(BasePassMeshProcessor)
|
||||
DECLARE_REF(CameraActor)
|
||||
DECLARE_REF(CameraComponent)
|
||||
struct BasePassData
|
||||
{
|
||||
std::vector<StaticMeshBatch> staticDrawList;
|
||||
Array<StaticMeshBatch> staticDrawList;
|
||||
};
|
||||
class BasePass : public RenderPass<BasePassData>
|
||||
{
|
||||
@@ -49,7 +48,7 @@ private:
|
||||
UPBasePassMeshProcessor processor;
|
||||
|
||||
Array<Gfx::PDescriptorSet> descriptorSets;
|
||||
PCameraComponent source;
|
||||
PCameraActor source;
|
||||
Gfx::PPipelineLayout basePassLayout;
|
||||
// Set 0: Light environment
|
||||
static constexpr uint32 INDEX_LIGHT_ENV = 0;
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
#include "DepthPrepass.h"
|
||||
#include "Graphics/Graphics.h"
|
||||
#include "Window/Window.h"
|
||||
#include "Scene/Components/CameraComponent.h"
|
||||
#include "Scene/Component/Camera.h"
|
||||
#include "Scene/Actor/CameraActor.h"
|
||||
#include "Math/Vector.h"
|
||||
#include "RenderGraph.h"
|
||||
#include "Material/MaterialAsset.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
@@ -72,7 +73,7 @@ DepthPrepass::DepthPrepass(Gfx::PGraphics graphics, Gfx::PViewport viewport, PCa
|
||||
: RenderPass(graphics, viewport)
|
||||
, processor(new DepthPrepassMeshProcessor(viewport, graphics))
|
||||
, descriptorSets(3)
|
||||
, source(source->getCameraComponent())
|
||||
, source(source)
|
||||
{
|
||||
UniformBufferCreateInfo uniformInitializer;
|
||||
|
||||
@@ -103,11 +104,11 @@ void DepthPrepass::beginFrame()
|
||||
primitiveLayout->reset();
|
||||
BulkResourceData uniformUpdate;
|
||||
|
||||
viewParams.viewMatrix = source->getViewMatrix();
|
||||
viewParams.projectionMatrix = source->getProjectionMatrix();
|
||||
viewParams.cameraPosition = Vector4(source->getCameraPosition(), 0);
|
||||
viewParams.viewMatrix = source->getCameraComponent().getViewMatrix();
|
||||
viewParams.projectionMatrix = source->getCameraComponent().getProjectionMatrix();
|
||||
viewParams.cameraPosition = Math::Vector4(source->getCameraComponent().getCameraPosition(), 0);
|
||||
viewParams.inverseProjectionMatrix = glm::inverse(viewParams.projectionMatrix);
|
||||
viewParams.screenDimensions = Vector2(static_cast<float>(viewport->getSizeX()), static_cast<float>(viewport->getSizeY()));
|
||||
viewParams.screenDimensions = Math::Vector2(static_cast<float>(viewport->getSizeX()), static_cast<float>(viewport->getSizeY()));
|
||||
uniformUpdate.size = sizeof(ViewParameter);
|
||||
uniformUpdate.data = (uint8*)&viewParams;
|
||||
viewParamBuffer->updateContents(uniformUpdate);
|
||||
|
||||
@@ -24,10 +24,9 @@ private:
|
||||
};
|
||||
DEFINE_REF(DepthPrepassMeshProcessor)
|
||||
DECLARE_REF(CameraActor)
|
||||
DECLARE_REF(CameraComponent)
|
||||
struct DepthPrepassData
|
||||
{
|
||||
std::vector<StaticMeshBatch> staticDrawList;
|
||||
Array<StaticMeshBatch> staticDrawList;
|
||||
};
|
||||
class DepthPrepass : public RenderPass<DepthPrepassData>
|
||||
{
|
||||
@@ -46,7 +45,7 @@ private:
|
||||
UPDepthPrepassMeshProcessor processor;
|
||||
|
||||
Array<Gfx::PDescriptorSet> descriptorSets;
|
||||
PCameraComponent source;
|
||||
PCameraActor source;
|
||||
Gfx::PPipelineLayout depthPrepassLayout;
|
||||
// Set 0: viewParameter
|
||||
static constexpr uint32 INDEX_VIEW_PARAMS = 0;
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
#include "Graphics/Graphics.h"
|
||||
#include "Scene/Scene.h"
|
||||
#include "Scene/Actor/CameraActor.h"
|
||||
#include "Scene/Components/CameraComponent.h"
|
||||
#include "Scene/Component/Camera.h"
|
||||
#include "RenderGraph.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
LightCullingPass::LightCullingPass(Gfx::PGraphics graphics, Gfx::PViewport viewport, PCameraActor camera)
|
||||
: RenderPass(graphics, viewport)
|
||||
, source(camera->getCameraComponent())
|
||||
, source(camera)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -24,11 +24,11 @@ void LightCullingPass::beginFrame()
|
||||
uint32_t viewportHeight = viewport->getSizeY();
|
||||
|
||||
BulkResourceData uniformUpdate;
|
||||
viewParams.viewMatrix = source->getViewMatrix();
|
||||
viewParams.projectionMatrix = source->getProjectionMatrix();
|
||||
viewParams.cameraPosition = Vector4(source->getCameraPosition(), 0);
|
||||
viewParams.viewMatrix = source->getCameraComponent().getViewMatrix();
|
||||
viewParams.projectionMatrix = source->getCameraComponent().getProjectionMatrix();
|
||||
viewParams.cameraPosition = Math::Vector4(source->getCameraComponent().getCameraPosition(), 0);
|
||||
viewParams.inverseProjectionMatrix = glm::inverse(viewParams.projectionMatrix);
|
||||
viewParams.screenDimensions = Vector2(static_cast<float>(viewportWidth), static_cast<float>(viewportHeight));
|
||||
viewParams.screenDimensions = Math::Vector2(static_cast<float>(viewportWidth), static_cast<float>(viewportHeight));
|
||||
uniformUpdate.size = sizeof(ViewParameter);
|
||||
uniformUpdate.data = (uint8*)&viewParams;
|
||||
viewParamsBuffer->updateContents(uniformUpdate);
|
||||
@@ -162,13 +162,7 @@ void LightCullingPass::publishOutputs()
|
||||
ShaderCreateInfo createInfo;
|
||||
createInfo.name = "Culling";
|
||||
|
||||
std::ifstream codeStream("./shaders/LightCulling.slang", std::ios::ate);
|
||||
auto fileSize = codeStream.tellg();
|
||||
codeStream.seekg(0);
|
||||
Array<char> buffer(static_cast<uint32>(fileSize));
|
||||
codeStream.read(buffer.data(), fileSize);
|
||||
|
||||
createInfo.shaderCode.add(std::string(buffer.data()));
|
||||
createInfo.mainModule = "LightCulling";
|
||||
createInfo.entryPoint = "cullLights";
|
||||
createInfo.defines["INDEX_VIEW_PARAMS"] = "0";
|
||||
createInfo.defines["INDEX_LIGHT_ENV"] = "1";
|
||||
@@ -269,10 +263,10 @@ void LightCullingPass::setupFrustums()
|
||||
glm::uvec3 numThreadGroups = glm::ceil(glm::vec3(numThreads.x / (float)BLOCK_SIZE, numThreads.y / (float)BLOCK_SIZE, 1));
|
||||
|
||||
viewParams = {
|
||||
.viewMatrix = source->getViewMatrix(),
|
||||
.projectionMatrix = source->getProjectionMatrix(),
|
||||
.inverseProjectionMatrix = glm::inverse(source->getProjectionMatrix()),
|
||||
.cameraPosition = Vector4(source->getCameraPosition(), 0),
|
||||
.viewMatrix = source->getCameraComponent().getViewMatrix(),
|
||||
.projectionMatrix = source->getCameraComponent().getProjectionMatrix(),
|
||||
.inverseProjectionMatrix = glm::inverse(source->getCameraComponent().getProjectionMatrix()),
|
||||
.cameraPosition = Math::Vector4(source->getTransform().getPosition(), 0),
|
||||
.screenDimensions = glm::vec2(viewportWidth, viewportHeight),
|
||||
};
|
||||
dispatchParams.numThreads = numThreads;
|
||||
@@ -288,13 +282,7 @@ void LightCullingPass::setupFrustums()
|
||||
ShaderCreateInfo createInfo;
|
||||
createInfo.name = "Frustum";
|
||||
|
||||
std::ifstream codeStream("./shaders/ComputeFrustums.slang", std::ios::ate);
|
||||
auto fileSize = codeStream.tellg();
|
||||
codeStream.seekg(0);
|
||||
Array<char> buffer(static_cast<uint32>(fileSize));
|
||||
codeStream.read(buffer.data(), fileSize);
|
||||
|
||||
createInfo.shaderCode.add(std::string(buffer.data()));
|
||||
createInfo.mainModule = "ComputeFrustums";
|
||||
createInfo.entryPoint = "computeFrustums";
|
||||
createInfo.defines["INDEX_VIEW_PARAMS"] = "0";
|
||||
frustumShader = graphics->createComputeShader(createInfo);
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
namespace Seele
|
||||
{
|
||||
DECLARE_REF(CameraActor)
|
||||
DECLARE_REF(CameraComponent)
|
||||
DECLARE_REF(Scene)
|
||||
DECLARE_REF(Viewport)
|
||||
struct LightCullingPassData
|
||||
@@ -37,7 +36,7 @@ private:
|
||||
} dispatchParams;
|
||||
struct Plane
|
||||
{
|
||||
Vector n;
|
||||
Math::Vector n;
|
||||
float d;
|
||||
};
|
||||
struct Frustum
|
||||
@@ -72,7 +71,7 @@ private:
|
||||
Gfx::PComputeShader cullingShader;
|
||||
Gfx::PPipelineLayout cullingLayout;
|
||||
Gfx::PComputePipeline cullingPipeline;
|
||||
PCameraComponent source;
|
||||
PCameraActor source;
|
||||
};
|
||||
DEFINE_REF(LightCullingPass)
|
||||
} // namespace Seele
|
||||
|
||||
@@ -26,15 +26,16 @@ public:
|
||||
virtual void endFrame() = 0;
|
||||
virtual void publishOutputs() = 0;
|
||||
virtual void createRenderPass() = 0;
|
||||
void setResources(PRenderGraphResources resources) { this->resources = resources; }
|
||||
void setResources(PRenderGraphResources _resources) { resources = _resources; }
|
||||
protected:
|
||||
struct ViewParameter
|
||||
{
|
||||
Matrix4 viewMatrix;
|
||||
Matrix4 projectionMatrix;
|
||||
Matrix4 inverseProjectionMatrix;
|
||||
Vector4 cameraPosition;
|
||||
Vector2 screenDimensions;
|
||||
Math::Matrix4 viewMatrix;
|
||||
Math::Matrix4 projectionMatrix;
|
||||
Math::Matrix4 inverseProjectionMatrix;
|
||||
Math::Vector4 cameraPosition;
|
||||
Math::Vector2 screenDimensions;
|
||||
Math::Vector2 pad0;
|
||||
} viewParams;
|
||||
PRenderGraphResources resources;
|
||||
RenderPassDataType passData;
|
||||
|
||||
@@ -20,16 +20,16 @@ void TextPass::beginFrame()
|
||||
{
|
||||
for(TextRender& render : passData.texts)
|
||||
{
|
||||
FontData& fontData = getFontData(render.font);
|
||||
TextResources& resources = textResources[render.font].add();
|
||||
FontData& fd = getFontData(render.font);
|
||||
TextResources& res = textResources[render.font].add();
|
||||
Array<GlyphInstanceData> instanceData;
|
||||
float x = render.position.x;
|
||||
float y = render.position.y;
|
||||
for(uint32 c : render.text)
|
||||
{
|
||||
const GlyphData& glyph = fontData.glyphDataSet[fontData.characterToGlyphIndex[c]];
|
||||
Vector2 bearing = glyph.bearing;
|
||||
Vector2 size = glyph.size;
|
||||
const GlyphData& glyph = fd.glyphDataSet[fd.characterToGlyphIndex[c]];
|
||||
Math::Vector2 bearing = glyph.bearing;
|
||||
Math::Vector2 size = glyph.size;
|
||||
float xpos = x + bearing.x * render.scale;
|
||||
float ypos = y - (size.y - bearing.y) * render.scale;
|
||||
|
||||
@@ -37,9 +37,9 @@ void TextPass::beginFrame()
|
||||
float h = size.y * render.scale;
|
||||
|
||||
instanceData.add(GlyphInstanceData{
|
||||
.position = Vector2(xpos, ypos),
|
||||
.widthHeight = Vector2(w, h),
|
||||
.glyphIndex = fontData.characterToGlyphIndex[c],
|
||||
.position = Math::Vector2(xpos, ypos),
|
||||
.widthHeight = Math::Vector2(w, h),
|
||||
.glyphIndex = fd.characterToGlyphIndex[c],
|
||||
});
|
||||
x += (glyph.advance >> 6) * render.scale;
|
||||
}
|
||||
@@ -51,11 +51,11 @@ void TextPass::beginFrame()
|
||||
.vertexSize = sizeof(GlyphInstanceData),
|
||||
.numVertices = static_cast<uint32>(instanceData.size()),
|
||||
};
|
||||
resources.vertexBuffer = graphics->createVertexBuffer(vbInfo);
|
||||
res.vertexBuffer = graphics->createVertexBuffer(vbInfo);
|
||||
|
||||
resources.textureArraySet = fontData.textureArraySet;
|
||||
res.textureArraySet = fd.textureArraySet;
|
||||
|
||||
resources.textData = {
|
||||
res.textData = {
|
||||
.textColor = render.textColor,
|
||||
.scale = render.scale,
|
||||
};
|
||||
@@ -67,12 +67,12 @@ void TextPass::render()
|
||||
{
|
||||
graphics->beginRenderPass(renderPass);
|
||||
Array<Gfx::PRenderCommand> commands;
|
||||
for(const auto& [fontAsset, resources] : textResources)
|
||||
for(const auto& [fontAsset, res] : textResources)
|
||||
{
|
||||
Gfx::PRenderCommand command = graphics->createRenderCommand("TextPassCommand");
|
||||
command->setViewport(viewport);
|
||||
command->bindPipeline(pipeline);
|
||||
for(const auto& resource : resources)
|
||||
for(const auto& resource : res)
|
||||
{
|
||||
command->bindDescriptor({generalSet, resource.textureArraySet});
|
||||
command->bindVertexBuffer({VertexInputStream(0, 0, resource.vertexBuffer)});
|
||||
@@ -100,14 +100,8 @@ void TextPass::publishOutputs()
|
||||
void TextPass::createRenderPass()
|
||||
{
|
||||
depthAttachment = resources->requestRenderTarget("UIPASS_DEPTH");
|
||||
std::ifstream codeStream("./shaders/TextPass.slang", std::ios::ate);
|
||||
auto fileSize = codeStream.tellg();
|
||||
codeStream.seekg(0);
|
||||
Array<char> buffer(static_cast<uint32>(fileSize));
|
||||
codeStream.read(buffer.data(), fileSize);
|
||||
|
||||
ShaderCreateInfo createInfo;
|
||||
createInfo.shaderCode.add(std::string(buffer.data()));
|
||||
createInfo.mainModule = "TextPass";
|
||||
createInfo.defines["INDEX_VIEW_PARAMS"] = "0";
|
||||
createInfo.name = "TextVertex";
|
||||
createInfo.entryPoint = "vertexMain";
|
||||
@@ -152,10 +146,10 @@ void TextPass::createRenderPass()
|
||||
textureArrayLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 256, Gfx::SE_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT);
|
||||
textureArrayLayout->create();
|
||||
|
||||
Matrix4 projectionMatrix = glm::ortho(0.f, (float)viewport->getSizeX(), 0.f, (float)viewport->getSizeY());
|
||||
Math::Matrix4 projectionMatrix = glm::ortho(0.f, (float)viewport->getSizeX(), 0.f, (float)viewport->getSizeY());
|
||||
projectionBuffer = graphics->createUniformBuffer({
|
||||
.resourceData = {
|
||||
.size = sizeof(Matrix4),
|
||||
.size = sizeof(Math::Matrix4),
|
||||
.data = (uint8*)&projectionMatrix,
|
||||
},
|
||||
.bDynamic = false,
|
||||
|
||||
@@ -13,8 +13,8 @@ struct TextRender
|
||||
{
|
||||
std::string text;
|
||||
PFontAsset font;
|
||||
Vector4 textColor;
|
||||
Vector2 position;
|
||||
Math::Vector4 textColor;
|
||||
Math::Vector2 position;
|
||||
float scale;
|
||||
};
|
||||
struct TextPassData
|
||||
@@ -35,19 +35,19 @@ public:
|
||||
private:
|
||||
struct GlyphData
|
||||
{
|
||||
Vector2 bearing;
|
||||
Vector2 size;
|
||||
Math::Vector2 bearing;
|
||||
Math::Vector2 size;
|
||||
uint32 advance;
|
||||
};
|
||||
struct GlyphInstanceData
|
||||
{
|
||||
Vector2 position;
|
||||
Vector2 widthHeight;
|
||||
Math::Vector2 position;
|
||||
Math::Vector2 widthHeight;
|
||||
uint32 glyphIndex;
|
||||
};
|
||||
struct TextData
|
||||
{
|
||||
Vector4 textColor;
|
||||
Math::Vector4 textColor;
|
||||
float scale;
|
||||
};
|
||||
struct FontData
|
||||
|
||||
@@ -26,7 +26,7 @@ void UIPass::beginFrame()
|
||||
.numVertices = (uint32)passData.renderElements.size(),
|
||||
};
|
||||
elementBuffer = graphics->createVertexBuffer(info);
|
||||
uint32 numTextures = passData.usedTextures.size();
|
||||
uint32 numTextures = static_cast<uint32>(passData.usedTextures.size());
|
||||
numTexturesBuffer->updateContents({
|
||||
.size = sizeof(uint32),
|
||||
.data = (uint8*)&numTextures,
|
||||
@@ -45,7 +45,7 @@ void UIPass::render()
|
||||
command->bindPipeline(pipeline);
|
||||
command->bindVertexBuffer({VertexInputStream(0, 0, elementBuffer)});
|
||||
command->bindDescriptor(descriptorSet);
|
||||
command->draw(4, passData.renderElements.size(), 0, 0);
|
||||
command->draw(4, static_cast<uint32>(passData.renderElements.size()), 0, 0);
|
||||
graphics->executeCommands(Array<Gfx::PRenderCommand>({command}));
|
||||
graphics->endRenderPass();
|
||||
//co_return;
|
||||
@@ -76,14 +76,8 @@ void UIPass::publishOutputs()
|
||||
|
||||
void UIPass::createRenderPass()
|
||||
{
|
||||
std::ifstream codeStream("./shaders/UIPass.slang", std::ios::ate);
|
||||
auto fileSize = codeStream.tellg();
|
||||
codeStream.seekg(0);
|
||||
Array<char> buffer(static_cast<uint32>(fileSize));
|
||||
codeStream.read(buffer.data(), fileSize);
|
||||
|
||||
ShaderCreateInfo createInfo;
|
||||
createInfo.shaderCode.add(std::string(buffer.data()));
|
||||
createInfo.mainModule = "UIPass";
|
||||
createInfo.name = "UIVertex";
|
||||
createInfo.entryPoint = "vertexMain";
|
||||
vertexShader = graphics->createVertexShader(createInfo);
|
||||
@@ -141,10 +135,10 @@ void UIPass::createRenderPass()
|
||||
descriptorLayout->addDescriptorBinding(3, Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 256, Gfx::SE_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT | Gfx::SE_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT);
|
||||
descriptorLayout->create();
|
||||
|
||||
Matrix4 projectionMatrix = glm::ortho(0, 1, 1, 0);
|
||||
Math::Matrix4 projectionMatrix = glm::ortho(0, 1, 1, 0);
|
||||
UniformBufferCreateInfo info = {
|
||||
.resourceData = {
|
||||
.size = sizeof(Matrix4),
|
||||
.size = sizeof(Math::Matrix4),
|
||||
.data = (uint8*)&projectionMatrix,
|
||||
},
|
||||
.bDynamic = false,
|
||||
|
||||
@@ -54,16 +54,16 @@ void StaticMeshVertexInput::init(Gfx::PGraphics graphics)
|
||||
{
|
||||
elements.add(accessStreamComponent(
|
||||
data.textureCoordinates[coordinateIndex],
|
||||
baseTexCoordAttribute + coordinateIndex
|
||||
static_cast<uint8>(baseTexCoordAttribute + coordinateIndex)
|
||||
));
|
||||
}
|
||||
}
|
||||
initDeclaration(graphics, elements);
|
||||
}
|
||||
|
||||
void StaticMeshVertexInput::setData(StaticMeshDataType&& data)
|
||||
void StaticMeshVertexInput::setData(StaticMeshDataType&& _data)
|
||||
{
|
||||
this->data = std::move(data);
|
||||
data = std::move(_data);
|
||||
}
|
||||
|
||||
IMPLEMENT_VERTEX_INPUT_TYPE(StaticMeshVertexInput, "StaticMeshVertexInput")
|
||||
@@ -43,7 +43,7 @@ const char* VertexInputType::getName()
|
||||
return name;
|
||||
}
|
||||
|
||||
const char* VertexInputType::getShaderFilename()
|
||||
std::string VertexInputType::getShaderFilename()
|
||||
{
|
||||
return shaderFilename;
|
||||
}
|
||||
@@ -90,20 +90,22 @@ Gfx::VertexElement VertexShaderInput::accessStreamComponent(const VertexStreamCo
|
||||
{
|
||||
VertexStream vertexStream;
|
||||
vertexStream.vertexBuffer = component.vertexBuffer;
|
||||
vertexStream.stride = component.stride;
|
||||
vertexStream.offset = component.offset;
|
||||
assert(component.stride < UINT8_MAX && component.offset < UINT8_MAX && component.offset < UINT8_MAX);
|
||||
vertexStream.stride = static_cast<uint8>(component.stride);
|
||||
vertexStream.offset = static_cast<uint8>(component.offset);
|
||||
|
||||
return Gfx::VertexElement((uint8)streams.indexOf(streams.addUnique(vertexStream)), component.offset, component.type, attributeIndex, vertexStream.stride);
|
||||
return Gfx::VertexElement((uint8)streams.indexOf(streams.addUnique(vertexStream)), static_cast<uint8>(component.offset), component.type, attributeIndex, vertexStream.stride);
|
||||
}
|
||||
|
||||
Gfx::VertexElement VertexShaderInput::accessPositionStreamComponent(const VertexStreamComponent& component, uint8 attributeIndex)
|
||||
{
|
||||
VertexStream vertexStream;
|
||||
vertexStream.vertexBuffer = component.vertexBuffer;
|
||||
vertexStream.stride = component.stride;
|
||||
vertexStream.offset = component.offset;
|
||||
assert(component.stride < UINT8_MAX && component.offset < UINT8_MAX && component.offset < UINT8_MAX);
|
||||
vertexStream.stride = static_cast<uint8>(component.stride);
|
||||
vertexStream.offset = static_cast<uint8>(component.offset);
|
||||
|
||||
return Gfx::VertexElement((uint8)positionStreams.indexOf(positionStreams.addUnique(vertexStream)), component.offset, component.type, attributeIndex, vertexStream.stride);
|
||||
return Gfx::VertexElement((uint8)positionStreams.indexOf(positionStreams.addUnique(vertexStream)), static_cast<uint8>(component.offset), component.type, attributeIndex, vertexStream.stride);
|
||||
}
|
||||
|
||||
void VertexShaderInput::initDeclaration(Gfx::PGraphics graphics, Array<Gfx::VertexElement>& elements)
|
||||
|
||||
@@ -91,7 +91,7 @@ public:
|
||||
virtual ~VertexInputType();
|
||||
|
||||
const char* getName();
|
||||
const char* getShaderFilename();
|
||||
std::string getShaderFilename();
|
||||
private:
|
||||
const char* name;
|
||||
const char* shaderFilename;
|
||||
|
||||
@@ -95,7 +95,7 @@ PSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDevice
|
||||
VkDeviceSize allocatedOffset = it.first;
|
||||
PSubAllocation freeAllocation = it.second;
|
||||
assert(allocatedOffset == freeAllocation->allocatedOffset);
|
||||
VkDeviceSize alignedOffset = align(allocatedOffset, alignment);
|
||||
VkDeviceSize alignedOffset = Math::align(allocatedOffset, alignment);
|
||||
VkDeviceSize alignmentAdjustment = alignedOffset - allocatedOffset;
|
||||
VkDeviceSize size = alignmentAdjustment + requestedSize;
|
||||
if (freeAllocation->size == size)
|
||||
@@ -171,6 +171,8 @@ void Allocation::markFree(SubAllocation *allocation)
|
||||
allocHandle = foundAlloc->second;
|
||||
allocHandle->allocatedOffset -= allocation->allocatedSize;
|
||||
allocHandle->alignedOffset -= allocation->allocatedSize;
|
||||
allocHandle->size += allocation->allocatedSize;
|
||||
allocHandle->allocatedSize += allocation->allocatedSize;
|
||||
// place back at correct offset
|
||||
freeRanges[allocHandle->allocatedOffset] = allocHandle;
|
||||
// remove from offset map since key changes
|
||||
@@ -310,7 +312,7 @@ void StagingManager::clearPending()
|
||||
{
|
||||
}
|
||||
|
||||
PStagingBuffer StagingManager::allocateStagingBuffer(uint32 size, VkBufferUsageFlags usage, bool bCPURead)
|
||||
PStagingBuffer StagingManager::allocateStagingBuffer(uint64 size, VkBufferUsageFlags usage, bool bCPURead)
|
||||
{
|
||||
std::scoped_lock l(lock);
|
||||
for (auto it = freeBuffers.begin(); it != freeBuffers.end(); ++it)
|
||||
|
||||
@@ -191,7 +191,7 @@ public:
|
||||
{
|
||||
return allocation->getOffset();
|
||||
}
|
||||
uint32 getSize() const
|
||||
uint64 getSize() const
|
||||
{
|
||||
return size;
|
||||
}
|
||||
@@ -203,7 +203,7 @@ public:
|
||||
private:
|
||||
PSubAllocation allocation;
|
||||
VkBuffer buffer;
|
||||
uint32 size;
|
||||
uint64 size;
|
||||
VkBufferUsageFlags usage;
|
||||
uint8 bReadable;
|
||||
friend class StagingManager;
|
||||
@@ -215,7 +215,7 @@ class StagingManager
|
||||
public:
|
||||
StagingManager(PGraphics graphics, PAllocator allocator);
|
||||
~StagingManager();
|
||||
PStagingBuffer allocateStagingBuffer(uint32 size, VkBufferUsageFlags usageFlags = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, bool bCPURead = false);
|
||||
PStagingBuffer allocateStagingBuffer(uint64 size, VkBufferUsageFlags usageFlags = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, bool bCPURead = false);
|
||||
void releaseStagingBuffer(PStagingBuffer buffer);
|
||||
void clearPending();
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@ using namespace Seele::Vulkan;
|
||||
|
||||
struct PendingBuffer
|
||||
{
|
||||
uint64 offset;
|
||||
uint64 size;
|
||||
PStagingBuffer stagingBuffer;
|
||||
Gfx::QueueType prevQueue;
|
||||
bool bWriteOnly;
|
||||
@@ -16,7 +18,7 @@ struct PendingBuffer
|
||||
|
||||
static std::map<ShaderBuffer *, PendingBuffer> pendingBuffers;
|
||||
|
||||
ShaderBuffer::ShaderBuffer(PGraphics graphics, uint32 size, VkBufferUsageFlags usage, Gfx::QueueType& queueType, bool bDynamic)
|
||||
ShaderBuffer::ShaderBuffer(PGraphics graphics, uint64 size, VkBufferUsageFlags usage, Gfx::QueueType& queueType, bool bDynamic)
|
||||
: graphics(graphics)
|
||||
, currentBuffer(0)
|
||||
, size(size)
|
||||
@@ -63,7 +65,7 @@ ShaderBuffer::~ShaderBuffer()
|
||||
{
|
||||
PCmdBuffer cmdBuffer = graphics->getQueueCommands(owner)->getCommands();
|
||||
VkDevice device = graphics->getDevice();
|
||||
auto deletionLambda = [cmdBuffer, device](VkBuffer buffer) -> void
|
||||
auto deletionLambda = [cmdBuffer, device](VkBuffer) -> void
|
||||
{
|
||||
//co_await cmdBuffer->asyncWait();
|
||||
//vkDestroyBuffer(device, buffer, nullptr);
|
||||
@@ -169,6 +171,11 @@ void ShaderBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineSta
|
||||
}
|
||||
|
||||
void *ShaderBuffer::lock(bool bWriteOnly)
|
||||
{
|
||||
return lockRegion(0, size, bWriteOnly);
|
||||
}
|
||||
|
||||
void *ShaderBuffer::lockRegion(uint64 regionOffset, uint64 regionSize, bool bWriteOnly)
|
||||
{
|
||||
void *data = nullptr;
|
||||
|
||||
@@ -189,10 +196,12 @@ void *ShaderBuffer::lock(bool bWriteOnly)
|
||||
PendingBuffer pending;
|
||||
pending.bWriteOnly = bWriteOnly;
|
||||
pending.prevQueue = owner;
|
||||
pending.offset = regionOffset;
|
||||
pending.size = regionSize;
|
||||
if (bWriteOnly)
|
||||
{
|
||||
//requestOwnershipTransfer(Gfx::QueueType::DEDICATED_TRANSFER);
|
||||
PStagingBuffer stagingBuffer = graphics->getStagingManager()->allocateStagingBuffer(size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
|
||||
PStagingBuffer stagingBuffer = graphics->getStagingManager()->allocateStagingBuffer(regionSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
|
||||
data = stagingBuffer->getMappedPointer();
|
||||
pending.stagingBuffer = stagingBuffer;
|
||||
}
|
||||
@@ -255,7 +264,8 @@ void ShaderBuffer::unlock()
|
||||
|
||||
VkBufferCopy region;
|
||||
std::memset(®ion, 0, sizeof(VkBufferCopy));
|
||||
region.size = size;
|
||||
region.size = pending.size;
|
||||
region.dstOffset = pending.offset;
|
||||
vkCmdCopyBuffer(cmdHandle, stagingBuffer->getHandle(), buffers[currentBuffer].buffer, 1, ®ion);
|
||||
graphics->getQueueCommands(owner)->submitCommands();
|
||||
}
|
||||
@@ -448,6 +458,14 @@ VertexBuffer::~VertexBuffer()
|
||||
{
|
||||
}
|
||||
|
||||
void VertexBuffer::updateRegion(BulkResourceData update)
|
||||
{
|
||||
void* data = lockRegion(update.offset, update.size);
|
||||
std::memcpy(data, update.data, update.size);
|
||||
unlock();
|
||||
}
|
||||
|
||||
|
||||
void VertexBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner)
|
||||
{
|
||||
Gfx::QueueOwnedResource::transferOwnership(newOwner);
|
||||
|
||||
@@ -302,7 +302,7 @@ void RenderCommand::pushConstants(Gfx::PPipelineLayout layout, Gfx::SeShaderStag
|
||||
void RenderCommand::draw(const MeshBatchElement& data)
|
||||
{
|
||||
assert(threadId == std::this_thread::get_id());
|
||||
vkCmdDrawIndexed(handle, data.indexBuffer->getNumIndices(), data.numInstances, data.minVertexIndex, data.baseVertexIndex, 0);
|
||||
vkCmdDrawIndexed(handle, static_cast<uint32>(data.indexBuffer->getNumIndices()), data.numInstances, data.minVertexIndex, data.baseVertexIndex, 0);
|
||||
}
|
||||
|
||||
void RenderCommand::draw(uint32 vertexCount, uint32 instanceCount, int32 firstVertex, uint32 firstInstance)
|
||||
|
||||
@@ -67,6 +67,7 @@ public:
|
||||
virtual Gfx::PPipelineLayout createPipelineLayout(Gfx::PPipelineLayout baseLayout = nullptr) override;
|
||||
|
||||
virtual void copyTexture(Gfx::PTexture srcTexture, Gfx::PTexture dstTexture) override;
|
||||
|
||||
protected:
|
||||
Array<const char *> getRequiredExtensions();
|
||||
void initInstance(GraphicsInitializer initInfo);
|
||||
|
||||
@@ -1390,7 +1390,7 @@ Gfx::SeCompareOp Seele::Vulkan::cast(const VkCompareOp &op)
|
||||
VkClearValue Seele::Vulkan::cast(const Gfx::SeClearValue& clear)
|
||||
{
|
||||
VkClearValue result;
|
||||
if(sizeof(clear) == sizeof(Gfx::SeClearColorValue))
|
||||
if constexpr (sizeof(clear) == sizeof(Gfx::SeClearColorValue))
|
||||
{
|
||||
result.color.float32[0] = clear.color.float32[0];
|
||||
result.color.float32[1] = clear.color.float32[1];
|
||||
@@ -1408,7 +1408,7 @@ VkClearValue Seele::Vulkan::cast(const Gfx::SeClearValue& clear)
|
||||
Gfx::SeClearValue Seele::Vulkan::cast(const VkClearValue& clear)
|
||||
{
|
||||
Gfx::SeClearValue result;
|
||||
if(sizeof(clear) == sizeof(VkClearColorValue))
|
||||
if constexpr (sizeof(clear) == sizeof(VkClearColorValue))
|
||||
{
|
||||
result.color.float32[0] = clear.color.float32[0];
|
||||
result.color.float32[1] = clear.color.float32[1];
|
||||
|
||||
@@ -72,13 +72,13 @@ DEFINE_REF(VertexDeclaration)
|
||||
class ShaderBuffer
|
||||
{
|
||||
public:
|
||||
ShaderBuffer(PGraphics graphics, uint32 size, VkBufferUsageFlags usage, Gfx::QueueType& queueType, bool bDynamic = false);
|
||||
ShaderBuffer(PGraphics graphics, uint64 size, VkBufferUsageFlags usage, Gfx::QueueType& queueType, bool bDynamic = false);
|
||||
virtual ~ShaderBuffer();
|
||||
VkBuffer getHandle() const
|
||||
{
|
||||
return buffers[currentBuffer].buffer;
|
||||
}
|
||||
uint32 getSize() const
|
||||
uint64 getSize() const
|
||||
{
|
||||
return size;
|
||||
}
|
||||
@@ -88,6 +88,7 @@ public:
|
||||
currentBuffer = (currentBuffer + 1) % numBuffers;
|
||||
}
|
||||
virtual void *lock(bool bWriteOnly = true);
|
||||
virtual void *lockRegion(uint64 regionOffset, uint64 regionSize, bool bWriteOnly = true);
|
||||
virtual void unlock();
|
||||
|
||||
protected:
|
||||
@@ -98,7 +99,7 @@ protected:
|
||||
};
|
||||
PGraphics graphics;
|
||||
uint32 currentBuffer;
|
||||
uint32 size;
|
||||
uint64 size;
|
||||
Gfx::QueueType& owner;
|
||||
BufferAllocation buffers[Gfx::numFramesBuffered];
|
||||
uint32 numBuffers;
|
||||
@@ -168,6 +169,8 @@ public:
|
||||
VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo &resourceData);
|
||||
virtual ~VertexBuffer();
|
||||
|
||||
virtual void updateRegion(BulkResourceData update) override;
|
||||
|
||||
protected:
|
||||
// Inherited via Vulkan::Buffer
|
||||
virtual VkAccessFlags getSourceAccessMask();
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
#include "VulkanGraphics.h"
|
||||
#include "VulkanDescriptorSets.h"
|
||||
#include "slang.h"
|
||||
#include "slang-com-ptr.h"
|
||||
#include "stdlib.h"
|
||||
|
||||
using namespace slang;
|
||||
using namespace Seele;
|
||||
using namespace Seele::Vulkan;
|
||||
|
||||
@@ -33,85 +33,130 @@ uint32 Seele::Vulkan::Shader::getShaderHash() const
|
||||
return hash;
|
||||
}
|
||||
|
||||
static SlangStage getStageFromShaderType(ShaderType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case ShaderType::VERTEX:
|
||||
return SLANG_STAGE_VERTEX;
|
||||
case ShaderType::CONTROL:
|
||||
return SLANG_STAGE_HULL;
|
||||
case ShaderType::EVALUATION:
|
||||
return SLANG_STAGE_DOMAIN;
|
||||
case ShaderType::GEOMETRY:
|
||||
return SLANG_STAGE_GEOMETRY;
|
||||
case ShaderType::FRAGMENT:
|
||||
return SLANG_STAGE_PIXEL;
|
||||
default:
|
||||
return SLANG_STAGE_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
void Shader::create(const ShaderCreateInfo& createInfo)
|
||||
{
|
||||
entryPointName = createInfo.entryPoint;
|
||||
static SlangSession* session = spCreateSession(nullptr);
|
||||
|
||||
SlangCompileRequest* request = spCreateCompileRequest(session);
|
||||
int targetIndex = spAddCodeGenTarget(request, SLANG_SPIRV);
|
||||
spSetTargetProfile(request, targetIndex, spFindProfile(session, "glsl_vk"));
|
||||
spSetDumpIntermediates(request, true);
|
||||
int translationUnitIndex = spAddTranslationUnit(request, SLANG_SOURCE_LANGUAGE_SLANG, "");
|
||||
|
||||
for(auto code : createInfo.shaderCode)
|
||||
thread_local Slang::ComPtr<slang::IGlobalSession> globalSession;
|
||||
if(!globalSession)
|
||||
{
|
||||
spAddTranslationUnitSourceString(
|
||||
request,
|
||||
translationUnitIndex,
|
||||
entryPointName.c_str(),
|
||||
code.data()
|
||||
);
|
||||
slang::createGlobalSession(globalSession.writeRef());
|
||||
}
|
||||
slang::SessionDesc sessionDesc;
|
||||
sessionDesc.flags = 0;
|
||||
sessionDesc.defaultMatrixLayoutMode = SLANG_MATRIX_LAYOUT_COLUMN_MAJOR;
|
||||
Array<slang::PreprocessorMacroDesc> macros;
|
||||
for(auto define : createInfo.defines)
|
||||
{
|
||||
spAddPreprocessorDefine(request, define.key, define.value);
|
||||
macros.add(slang::PreprocessorMacroDesc{
|
||||
.name = define.key,
|
||||
.value = define.value
|
||||
});
|
||||
}
|
||||
spAddSearchPath(request, "shaders/lib/");
|
||||
spAddSearchPath(request, "shaders/generated/");
|
||||
sessionDesc.preprocessorMacroCount = macros.size();
|
||||
sessionDesc.preprocessorMacros = macros.data();
|
||||
slang::TargetDesc vulkan;
|
||||
vulkan.profile = globalSession->findProfile("glsl_vk");
|
||||
vulkan.format = SLANG_SPIRV;
|
||||
sessionDesc.targetCount = 1;
|
||||
sessionDesc.targets = &vulkan;
|
||||
StaticArray<const char*, 3> searchPaths = {"shaders/", "shaders/lib/", "shaders/generated/"};
|
||||
sessionDesc.searchPaths = searchPaths.data();
|
||||
sessionDesc.searchPathCount = searchPaths.size();
|
||||
|
||||
spSetGlobalGenericArgs(request, (int)createInfo.typeParameter.size(), createInfo.typeParameter.data());
|
||||
Slang::ComPtr<slang::ISession> session;
|
||||
globalSession->createSession(sessionDesc, session.writeRef());
|
||||
|
||||
int entryPointIndex = spAddEntryPoint(request, translationUnitIndex, entryPointName.c_str(), getStageFromShaderType(type));
|
||||
if(spCompile(request))
|
||||
Slang::ComPtr<slang::IBlob> diagnostics;
|
||||
Array<slang::IComponentType*> modules;
|
||||
Slang::ComPtr<slang::IEntryPoint> entrypoint;
|
||||
|
||||
for (auto moduleName : createInfo.additionalModules)
|
||||
{
|
||||
char const* diagnostics = spGetDiagnosticOutput(request);
|
||||
std::cout << "Compile error for shader " << createInfo.name << std::endl;
|
||||
std::cout << diagnostics << std::endl;
|
||||
std::cout << "Defines: " << std::endl;
|
||||
for(auto define : createInfo.defines)
|
||||
modules.add(session->loadModule(moduleName.c_str(), diagnostics.writeRef()));
|
||||
if(diagnostics)
|
||||
{
|
||||
std::cout << define.key << ": " << define.value << std::endl;
|
||||
std::cout << (const char*)diagnostics->getBufferPointer() << std::endl;
|
||||
}
|
||||
std::cout << "For shader code: " << std::endl;
|
||||
for(auto code : createInfo.shaderCode)
|
||||
{
|
||||
std::cout << code << std::endl;
|
||||
}
|
||||
return;
|
||||
}
|
||||
size_t dataSize = 0;
|
||||
const uint32* data = reinterpret_cast<const uint32*>(spGetEntryPointCode(request, entryPointIndex, &dataSize));
|
||||
slang::IModule* mainModule = session->loadModule(createInfo.mainModule.c_str(), diagnostics.writeRef());
|
||||
modules.add(mainModule);
|
||||
|
||||
if(diagnostics)
|
||||
{
|
||||
std::cout << (const char*)diagnostics->getBufferPointer() << std::endl;
|
||||
}
|
||||
|
||||
mainModule->findEntryPointByName(createInfo.entryPoint.c_str(), entrypoint.writeRef());
|
||||
modules.add(entrypoint);
|
||||
|
||||
slang::IComponentType* moduleComposition;
|
||||
session->createCompositeComponentType(modules.data(), modules.size(), &moduleComposition, diagnostics.writeRef());
|
||||
|
||||
if(diagnostics)
|
||||
{
|
||||
std::cout << (const char*)diagnostics->getBufferPointer() << std::endl;
|
||||
}
|
||||
|
||||
/*for(auto typeParam : createInfo.typeParameter)
|
||||
{
|
||||
Slang::ComPtr<slang::ITypeConformance> typeConformance;
|
||||
session->createTypeConformanceComponentType(moduleComposition->getLayout()->findTypeByName(typeParam), moduleComposition->getLayout()->findTypeByName("IMaterial"), typeConformance.writeRef(), -1, diagnostics.writeRef());
|
||||
modules.add(typeConformance);
|
||||
if(diagnostics)
|
||||
{
|
||||
std::cout << (const char*)diagnostics->getBufferPointer() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
Slang::ComPtr<slang::IComponentType> conformingModule;
|
||||
session->createCompositeComponentType(modules.data(), modules.size(), conformingModule.writeRef(), diagnostics.writeRef());
|
||||
*/
|
||||
Slang::ComPtr<slang::IComponentType> linkedProgram;
|
||||
moduleComposition->link(linkedProgram.writeRef(), diagnostics.writeRef());
|
||||
if(diagnostics)
|
||||
{
|
||||
std::cout << (const char*)diagnostics->getBufferPointer() << std::endl;
|
||||
}
|
||||
|
||||
slang::ProgramLayout* reflection = linkedProgram->getLayout(0, diagnostics.writeRef());
|
||||
if(diagnostics)
|
||||
{
|
||||
std::cout << (const char*)diagnostics->getBufferPointer() << std::endl;
|
||||
}
|
||||
|
||||
Array<slang::SpecializationArg> specialization;
|
||||
for(auto typeArg : createInfo.typeParameter)
|
||||
{
|
||||
specialization.add(slang::SpecializationArg::fromType(reflection->findTypeByName(typeArg)));
|
||||
}
|
||||
Slang::ComPtr<slang::IComponentType> specializedComponent;
|
||||
linkedProgram->specialize(specialization.data(), specialization.size(), specializedComponent.writeRef(), diagnostics.writeRef());
|
||||
if(diagnostics)
|
||||
{
|
||||
std::cout << (const char*)diagnostics->getBufferPointer() << std::endl;
|
||||
}
|
||||
Slang::ComPtr<slang::IBlob> kernelBlob;
|
||||
specializedComponent->getEntryPointCode(
|
||||
0,
|
||||
0,
|
||||
kernelBlob.writeRef(),
|
||||
diagnostics.writeRef()
|
||||
);
|
||||
if(diagnostics)
|
||||
{
|
||||
std::cout << (const char*)diagnostics->getBufferPointer() << std::endl;
|
||||
}
|
||||
|
||||
VkShaderModuleCreateInfo moduleInfo;
|
||||
moduleInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||
moduleInfo.pNext = nullptr;
|
||||
moduleInfo.flags = 0;
|
||||
moduleInfo.codeSize = dataSize;
|
||||
moduleInfo.pCode = data;
|
||||
moduleInfo.codeSize = kernelBlob->getBufferSize();
|
||||
moduleInfo.pCode = (uint32_t*)kernelBlob->getBufferPointer();
|
||||
VK_CHECK(vkCreateShaderModule(graphics->getDevice(), &moduleInfo, nullptr, &module));
|
||||
|
||||
boost::crc_32_type result;
|
||||
result.process_bytes(entryPointName.data(), entryPointName.size());
|
||||
result.process_bytes(data, dataSize);
|
||||
result.process_bytes(kernelBlob->getBufferPointer(), kernelBlob->getBufferSize());
|
||||
hash = result.checksum();
|
||||
}
|
||||
@@ -53,7 +53,6 @@ void MaterialAsset::load()
|
||||
std::ofstream codeStream("./shaders/generated/"+materialName+".slang");
|
||||
std::string profile = j["profile"].get<std::string>();
|
||||
|
||||
codeStream << "import VERTEX_INPUT_IMPORT;" << std::endl;
|
||||
codeStream << "import Material;" << std::endl;
|
||||
codeStream << "import BRDF;" << std::endl;
|
||||
codeStream << "import MaterialParameter;" << std::endl << std::endl;
|
||||
@@ -94,7 +93,7 @@ void MaterialAsset::load()
|
||||
uniformBufferOffset += 12;
|
||||
if(defaultValue != param.value().end())
|
||||
{
|
||||
p->data = parseVector(defaultValue.value().get<std::string>().c_str());
|
||||
p->data = Math::parseVector(defaultValue.value().get<std::string>().c_str());
|
||||
}
|
||||
parameters.add(p);
|
||||
}
|
||||
@@ -184,6 +183,6 @@ const Gfx::ShaderCollection* MaterialAsset::getShaders(Gfx::RenderPassType rende
|
||||
|
||||
Gfx::ShaderCollection& MaterialAsset::createShaders(Gfx::PGraphics graphics, Gfx::RenderPassType renderPass, VertexInputType* vertexInput)
|
||||
{
|
||||
std::scoped_lock lock(shaderMapLock);
|
||||
std::scoped_lock l(shaderMapLock);
|
||||
return shaderMap.createShaders(graphics, renderPass, this, vertexInput, false);
|
||||
}
|
||||
|
||||
@@ -40,6 +40,8 @@ private:
|
||||
uint8* uniformData;
|
||||
int32 uniformBinding;
|
||||
std::string materialName;
|
||||
// With draw-indirect, we batch vertex data into big vertex buffers
|
||||
// Gfx::PVertexDataManager vertexData;
|
||||
};
|
||||
DEFINE_REF(MaterialAsset)
|
||||
} // namespace Seele
|
||||
|
||||
@@ -40,7 +40,7 @@ VectorParameter::~VectorParameter()
|
||||
|
||||
void VectorParameter::updateDescriptorSet(Gfx::PDescriptorSet, uint8* dst)
|
||||
{
|
||||
std::memcpy(dst + byteOffset, &data, sizeof(Vector));
|
||||
std::memcpy(dst + byteOffset, &data, sizeof(Math::Vector));
|
||||
}
|
||||
|
||||
TextureParameter::TextureParameter(std::string name, uint32 byteOffset, uint32 binding)
|
||||
|
||||
@@ -36,7 +36,7 @@ struct FloatParameter : public ShaderParameter
|
||||
DEFINE_REF(FloatParameter)
|
||||
struct VectorParameter : public ShaderParameter
|
||||
{
|
||||
Vector data;
|
||||
Math::Vector data;
|
||||
VectorParameter(std::string name, uint32 byteOffset, uint32 binding);
|
||||
virtual ~VectorParameter();
|
||||
virtual void updateDescriptorSet(Gfx::PDescriptorSet descriptorSet, uint8* dst) override;
|
||||
|
||||
@@ -2,7 +2,7 @@ target_sources(Engine
|
||||
PUBLIC
|
||||
Math.h
|
||||
Matrix.h
|
||||
Vector.h
|
||||
Vector.cpp
|
||||
Transform.h
|
||||
Transform.cpp)
|
||||
Transform.cpp
|
||||
Vector.h
|
||||
Vector.cpp)
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
namespace Math
|
||||
{
|
||||
struct Rect
|
||||
{
|
||||
Rect()
|
||||
@@ -58,4 +60,5 @@ inline constexpr T align(const T ptr, int64_t alignment)
|
||||
{
|
||||
return (T)(((uint64_t)ptr + alignment - 1) & ~(alignment - 1));
|
||||
}
|
||||
} // namespace Math
|
||||
} // namespace Seele
|
||||
@@ -5,7 +5,10 @@
|
||||
#include <glm/mat4x4.hpp>
|
||||
namespace Seele
|
||||
{
|
||||
namespace Math
|
||||
{
|
||||
typedef glm::mat2 Matrix2;
|
||||
typedef glm::mat3 Matrix3;
|
||||
typedef glm::mat4 Matrix4;
|
||||
} // namespace Math
|
||||
} // namespace Seele
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
|
||||
using namespace Seele;
|
||||
using namespace Seele::Math;
|
||||
|
||||
Transform::Transform()
|
||||
: position(Vector4(0, 0, 0, 0)), rotation(Quaternion(1, 0, 0, 0)), scale(Vector4(1, 1, 1, 0))
|
||||
@@ -44,7 +45,7 @@ Vector Transform::inverseTransformPosition(const Vector &v) const
|
||||
{
|
||||
return (unrotateVector(rotation, v - Vector(position))) * getSafeScaleReciprocal(scale);
|
||||
}
|
||||
Matrix4 Transform::toMatrix()
|
||||
Matrix4 Transform::toMatrix() const
|
||||
{
|
||||
Matrix4 mat;
|
||||
|
||||
@@ -197,20 +198,26 @@ void Transform::add(Transform *outTransform, const Transform *a, const Transform
|
||||
|
||||
Transform &Transform::operator=(const Transform &other)
|
||||
{
|
||||
position = other.position;
|
||||
rotation = other.rotation;
|
||||
scale = other.scale;
|
||||
if(&other != this)
|
||||
{
|
||||
position = other.position;
|
||||
rotation = other.rotation;
|
||||
scale = other.scale;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Transform &Transform::operator=(Transform &&other)
|
||||
{
|
||||
position = other.position;
|
||||
rotation = other.rotation;
|
||||
scale = other.scale;
|
||||
other.position = Vector4(0, 0, 0, 0);
|
||||
other.rotation = Quaternion(1, 0, 0, 0);
|
||||
other.scale = Vector4(0, 0, 0, 0);
|
||||
if(&other != this)
|
||||
{
|
||||
position = other.position;
|
||||
rotation = other.rotation;
|
||||
scale = other.scale;
|
||||
other.position = Vector4(0, 0, 0, 0);
|
||||
other.rotation = Quaternion(1, 0, 0, 0);
|
||||
other.scale = Vector4(0, 0, 0, 0);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
#pragma once
|
||||
#include "Vector.h"
|
||||
#include "Matrix.h"
|
||||
#include "Math/Vector.h"
|
||||
#include "Math/Matrix.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
namespace Math
|
||||
{
|
||||
class Transform
|
||||
{
|
||||
public:
|
||||
@@ -16,7 +18,7 @@ public:
|
||||
Transform(Quaternion rotation, Vector scale);
|
||||
~Transform();
|
||||
Vector inverseTransformPosition(const Vector &v) const;
|
||||
Matrix4 toMatrix();
|
||||
Matrix4 toMatrix() const;
|
||||
static Vector getSafeScaleReciprocal(const Vector4 &inScale, float tolerance = 0.000000001f);
|
||||
Vector transformPosition(const Vector &v) const;
|
||||
|
||||
@@ -41,4 +43,5 @@ private:
|
||||
Quaternion rotation;
|
||||
Vector4 scale;
|
||||
};
|
||||
} // namespace Math
|
||||
} // namespace Seele
|
||||
@@ -1,25 +1,25 @@
|
||||
#include "Vector.h"
|
||||
#include <regex>
|
||||
|
||||
using namespace Seele;
|
||||
using namespace Seele::Math;
|
||||
|
||||
std::ostream& Seele::operator<<(std::ostream& stream, const Vector2& vector)
|
||||
std::ostream& operator<<(std::ostream& stream, const Vector2& vector)
|
||||
{
|
||||
stream << "(" << vector.x << ", " << vector.y << ")";
|
||||
return stream;
|
||||
}
|
||||
std::ostream& Seele::operator<<(std::ostream& stream, const Vector& vector)
|
||||
std::ostream& operator<<(std::ostream& stream, const Vector& vector)
|
||||
{
|
||||
stream << "(" << vector.x << ", " << vector.y << ", " << vector.z << ")";
|
||||
return stream;
|
||||
}
|
||||
std::ostream& Seele::operator<<(std::ostream& stream, const Vector4& vector)
|
||||
std::ostream& operator<<(std::ostream& stream, const Vector4& vector)
|
||||
{
|
||||
stream << "(" << vector.x << ", " << vector.y << ", " << vector.z << ", " << vector.w << ")";
|
||||
return stream;
|
||||
}
|
||||
|
||||
Vector Seele::parseVector(const char* str)
|
||||
Vector Seele::Math::parseVector(const char* str)
|
||||
{
|
||||
//regex pattern consisting of 'float3(xComp, yComp, zComp)', more also matches for invalid floats, but that will throw later
|
||||
std::regex pattern("float3\\(\\s*([0-9.]+f?)\\s*,\\s*([0-9.]+f?)\\s*,\\s*([0-9.]+f?)\\s*\\)");
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
#pragma once
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4201)
|
||||
#include <glm/vec2.hpp>
|
||||
#include <glm/vec3.hpp>
|
||||
#include <glm/vec4.hpp>
|
||||
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
#pragma warning(pop)
|
||||
namespace Seele
|
||||
{
|
||||
namespace Math
|
||||
{
|
||||
typedef glm::vec2 Vector2;
|
||||
typedef glm::vec3 Vector;
|
||||
typedef glm::vec4 Vector4;
|
||||
@@ -95,4 +100,5 @@ static inline Vector toRotator(const Quaternion &other)
|
||||
}
|
||||
return rotatorFromQuat;
|
||||
}
|
||||
} // namespace Math
|
||||
} // namespace Seele
|
||||
@@ -1,61 +1,19 @@
|
||||
#include "Actor.h"
|
||||
#include "Scene/Components/Component.h"
|
||||
#include "Scene/Scene.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
Actor::Actor()
|
||||
Actor::Actor(PScene scene)
|
||||
: Entity(scene)
|
||||
{
|
||||
|
||||
scene->attachComponent<Component::Transform>(identifier);
|
||||
}
|
||||
|
||||
Actor::~Actor()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Actor::launchStart()
|
||||
{
|
||||
rootComponent->launchStart();
|
||||
for(auto child : children)
|
||||
{
|
||||
child->launchStart();
|
||||
}
|
||||
start();
|
||||
}
|
||||
void Actor::launchTick(float deltaTime) const
|
||||
{
|
||||
rootComponent->launchTick(deltaTime);
|
||||
for(auto child : children)
|
||||
{
|
||||
child->launchTick(deltaTime);
|
||||
}
|
||||
tick(deltaTime);
|
||||
}
|
||||
|
||||
void Actor::launchUpdate()
|
||||
{
|
||||
rootComponent->launchUpdate();
|
||||
for(auto child : children)
|
||||
{
|
||||
child->launchUpdate();
|
||||
}
|
||||
update();
|
||||
}
|
||||
void Actor::notifySceneAttach(PScene scene)
|
||||
{
|
||||
owningScene = scene;
|
||||
rootComponent->notifySceneAttach(scene);
|
||||
for(auto child : children)
|
||||
{
|
||||
child->notifySceneAttach(scene);
|
||||
}
|
||||
}
|
||||
|
||||
PScene Actor::getScene()
|
||||
{
|
||||
return owningScene;
|
||||
}
|
||||
|
||||
void Actor::setParent(PActor newParent)
|
||||
{
|
||||
if(parent != nullptr)
|
||||
@@ -68,86 +26,19 @@ void Actor::addChild(PActor child)
|
||||
{
|
||||
children.add(child);
|
||||
child->setParent(this);
|
||||
child->notifySceneAttach(owningScene);
|
||||
}
|
||||
void Actor::removeChild(PActor child)
|
||||
{
|
||||
children.remove(children.find(child), false);
|
||||
child->setParent(nullptr);
|
||||
child->notifySceneAttach(nullptr);
|
||||
}
|
||||
//void Actor::setAbsoluteLocation(Vector location)
|
||||
//{
|
||||
// rootComponent->setWorldLocation(location);
|
||||
//}
|
||||
//
|
||||
//void Actor::setAbsoluteRotation(Quaternion rotation)
|
||||
//{
|
||||
// rootComponent->setAbsoluteRotation(rotation);
|
||||
//}
|
||||
//void Actor::setAbsoluteRotation(Vector rotation)
|
||||
//{
|
||||
// rootComponent->setAbsoluteRotation(rotation);
|
||||
//}
|
||||
//void Actor::setWorldScale(Vector scale)
|
||||
//{
|
||||
// rootComponent->setWorldScale(scale);
|
||||
//}
|
||||
void Actor::setRelativeLocation(Vector location)
|
||||
const Component::Transform& Actor::getTransform() const
|
||||
{
|
||||
rootComponent->setRelativeLocation(location);
|
||||
}
|
||||
void Actor::setRelativeRotation(Quaternion rotation)
|
||||
{
|
||||
rootComponent->setRelativeRotation(rotation);
|
||||
}
|
||||
void Actor::setRelativeRotation(Vector rotation)
|
||||
{
|
||||
rootComponent->setRelativeRotation(rotation);
|
||||
}
|
||||
void Actor::setRelativeScale(Vector scale)
|
||||
{
|
||||
rootComponent->setRelativeScale(scale);
|
||||
}
|
||||
//void Actor::addAbsoluteTranslation(Vector translation)
|
||||
//{
|
||||
// rootComponent->addAbsoluteTranslation(translation);
|
||||
//}
|
||||
//void Actor::addAbsoluteRotation(Quaternion rotation)
|
||||
//{
|
||||
// rootComponent->addAbsoluteRotation(rotation);
|
||||
//}
|
||||
//void Actor::addAbsoluteRotation(Vector rotation)
|
||||
//{
|
||||
// rootComponent->addAbsoluteRotation(rotation);
|
||||
//}
|
||||
void Actor::addRelativeLocation(Vector translation)
|
||||
{
|
||||
rootComponent->addRelativeLocation(translation);
|
||||
}
|
||||
void Actor::addRelativeRotation(Quaternion rotation)
|
||||
{
|
||||
rootComponent->addRelativeRotation(rotation);
|
||||
}
|
||||
void Actor::addRelativeRotation(Vector rotation)
|
||||
{
|
||||
rootComponent->addRelativeRotation(rotation);
|
||||
}
|
||||
PComponent Actor::getRootComponent()
|
||||
{
|
||||
return rootComponent;
|
||||
}
|
||||
void Actor::setRootComponent(PComponent newRoot)
|
||||
{
|
||||
if(rootComponent != nullptr)
|
||||
{
|
||||
rootComponent->owner = nullptr;
|
||||
}
|
||||
rootComponent = newRoot;
|
||||
rootComponent->owner = this;
|
||||
return scene->accessComponent<Component::Transform>(identifier);
|
||||
}
|
||||
|
||||
Transform Actor::getTransform() const
|
||||
{
|
||||
return rootComponent->getTransform();
|
||||
}
|
||||
//Component::Transform& Actor::getTransform()
|
||||
//{
|
||||
// return scene->accessComponent<Component::Transform>(identifier);
|
||||
//}
|
||||
|
||||
|
||||
@@ -1,60 +1,31 @@
|
||||
#pragma once
|
||||
#include "MinimalEngine.h"
|
||||
#include "Math/Transform.h"
|
||||
#include "Entity.h"
|
||||
#include "Scene/Component/Transform.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
DECLARE_REF(Actor)
|
||||
DECLARE_REF(Component)
|
||||
DECLARE_REF(Scene)
|
||||
class Actor
|
||||
// Actors are entities that are part of the scene hierarchy
|
||||
// In order for that hierarchy to make sense it requires at least a transform component
|
||||
class Actor : public Entity
|
||||
{
|
||||
public:
|
||||
Actor();
|
||||
Actor(PScene scene);
|
||||
virtual ~Actor();
|
||||
virtual void launchStart();
|
||||
virtual void start() {}
|
||||
void launchTick(float deltaTime) const;
|
||||
virtual void tick(float) const { }//co_return; }
|
||||
void launchUpdate();
|
||||
virtual void update() { }//co_return; }
|
||||
void notifySceneAttach(PScene scene);
|
||||
PScene getScene();
|
||||
|
||||
PActor getParent();
|
||||
void addChild(PActor child);
|
||||
void removeChild(PActor child);
|
||||
Array<PActor> getChildren();
|
||||
//void setAbsoluteLocation(Vector location);
|
||||
//void setAbsoluteRotation(Quaternion rotation);
|
||||
//void setAbsoluteRotation(Vector rotation);
|
||||
//void setWorldScale(Vector scale);
|
||||
|
||||
void setRelativeLocation(Vector location);
|
||||
void setRelativeRotation(Quaternion rotation);
|
||||
void setRelativeRotation(Vector rotation);
|
||||
void setRelativeScale(Vector scale);
|
||||
|
||||
//void addAbsoluteTranslation(Vector translation);
|
||||
//void addAbsoluteRotation(Quaternion rotation);
|
||||
//void addAbsoluteRotation(Vector rotation);
|
||||
|
||||
void addRelativeLocation(Vector translation);
|
||||
void addRelativeRotation(Quaternion rotation);
|
||||
void addRelativeRotation(Vector rotation);
|
||||
|
||||
PComponent getRootComponent();
|
||||
void setRootComponent(PComponent newRoot);
|
||||
|
||||
// Returns a read-only copy of the actors transform
|
||||
Transform getTransform() const;
|
||||
const Component::Transform& getTransform() const;
|
||||
|
||||
protected:
|
||||
//Component::Transform& getTransform();
|
||||
void setParent(PActor parent);
|
||||
PScene owningScene;
|
||||
PActor parent;
|
||||
Array<PActor> children;
|
||||
PComponent rootComponent;
|
||||
};
|
||||
DEFINE_REF(Actor)
|
||||
} // namespace Seele
|
||||
@@ -3,4 +3,6 @@ target_sources(Engine
|
||||
Actor.cpp
|
||||
Actor.h
|
||||
CameraActor.cpp
|
||||
CameraActor.h)
|
||||
CameraActor.h
|
||||
Entity.cpp
|
||||
Entity.h)
|
||||
@@ -1,21 +1,25 @@
|
||||
#include "CameraActor.h"
|
||||
#include "Scene/Components/Component.h"
|
||||
#include "Scene/Components/CameraComponent.h"
|
||||
#include "Scene/Scene.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
CameraActor::CameraActor()
|
||||
CameraActor::CameraActor(PScene scene)
|
||||
: Actor(scene)
|
||||
{
|
||||
sceneComponent = new Component();
|
||||
setRootComponent(sceneComponent);
|
||||
|
||||
cameraComponent = new CameraComponent();
|
||||
cameraComponent->fieldOfView = 70.0f;
|
||||
cameraComponent->setParent(sceneComponent);
|
||||
cameraComponent->setOwner(this);
|
||||
sceneComponent->addChildComponent(cameraComponent);
|
||||
scene->attachComponent<Component::Camera>(identifier);
|
||||
scene->accessComponent<Component::Transform>(identifier).setRelativeLocation(Math::Vector(10, 5, 14));
|
||||
}
|
||||
|
||||
CameraActor::~CameraActor()
|
||||
{
|
||||
}
|
||||
|
||||
Component::Camera& CameraActor::getCameraComponent()
|
||||
{
|
||||
return scene->accessComponent<Component::Camera>(identifier);
|
||||
}
|
||||
|
||||
const Component::Camera& CameraActor::getCameraComponent() const
|
||||
{
|
||||
return scene->accessComponent<Component::Camera>(identifier);
|
||||
}
|
||||
@@ -1,21 +1,17 @@
|
||||
#pragma once
|
||||
#include "Actor.h"
|
||||
#include "Scene/Component/Camera.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
DECLARE_REF(CameraComponent)
|
||||
class CameraActor : public Actor
|
||||
{
|
||||
public:
|
||||
CameraActor();
|
||||
CameraActor(PScene scene);
|
||||
virtual ~CameraActor();
|
||||
PCameraComponent getCameraComponent() const
|
||||
{
|
||||
return cameraComponent;
|
||||
}
|
||||
Component::Camera& getCameraComponent();
|
||||
const Component::Camera& getCameraComponent() const;
|
||||
private:
|
||||
PCameraComponent cameraComponent;
|
||||
PComponent sceneComponent; // This will be the root, camera will be the child
|
||||
};
|
||||
DEFINE_REF(CameraActor)
|
||||
} // namespace Seele
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
#include "Entity.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
Entity::Entity(PScene scene)
|
||||
: identifier(scene->createEntity())
|
||||
, scene(scene)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Entity::~Entity()
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
#include <entt/entt.hpp>
|
||||
#include "MinimalEngine.h"
|
||||
#include "Scene/Scene.h"
|
||||
namespace Seele
|
||||
{
|
||||
// An entity describes a part of a scene
|
||||
// It is just a wrapper the ID of a registry
|
||||
class Entity
|
||||
{
|
||||
public:
|
||||
Entity(PScene scene);
|
||||
virtual ~Entity();
|
||||
|
||||
template<typename Component, typename... Args>
|
||||
void attachComponent(Args... args)
|
||||
{
|
||||
scene->attachComponent<Component>(identifier, args...);
|
||||
}
|
||||
protected:
|
||||
PScene scene;
|
||||
entt::entity identifier;
|
||||
};
|
||||
DEFINE_REF(Entity)
|
||||
} // namespace Seele
|
||||
@@ -5,4 +5,5 @@ target_sources(Engine
|
||||
Scene.h)
|
||||
|
||||
add_subdirectory(Actor/)
|
||||
add_subdirectory(Components/)
|
||||
add_subdirectory(Component/)
|
||||
add_subdirectory(System/)
|
||||
@@ -0,0 +1,8 @@
|
||||
target_sources(Engine
|
||||
PUBLIC
|
||||
Component.h
|
||||
Camera.h
|
||||
Camera.cpp
|
||||
StaticMesh.h
|
||||
Transform.h
|
||||
Transform.cpp)
|
||||
+19
-18
@@ -1,13 +1,15 @@
|
||||
#include "CameraComponent.h"
|
||||
#include "Camera.h"
|
||||
#include "Scene/Actor/Actor.h"
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
using namespace Seele;
|
||||
using namespace Seele::Component;
|
||||
using namespace Seele::Math;
|
||||
|
||||
CameraComponent::CameraComponent()
|
||||
Camera::Camera()
|
||||
: aspectRatio(0)
|
||||
, fieldOfView(0)
|
||||
, fieldOfView(glm::radians(70.f))
|
||||
, bNeedsViewBuild(true)
|
||||
, bNeedsProjectionBuild(true)
|
||||
, viewMatrix(Matrix4())
|
||||
@@ -15,14 +17,13 @@ CameraComponent::CameraComponent()
|
||||
{
|
||||
yaw = 0;
|
||||
pitch = 0;
|
||||
setRelativeLocation(Vector(0, 10, -50));
|
||||
}
|
||||
|
||||
CameraComponent::~CameraComponent()
|
||||
Camera::~Camera()
|
||||
{
|
||||
}
|
||||
|
||||
void CameraComponent::mouseMove(float deltaYaw, float deltaPitch)
|
||||
void Camera::mouseMove(float deltaYaw, float deltaPitch)
|
||||
{
|
||||
yaw -= deltaYaw / 500.f;
|
||||
pitch += deltaPitch / 500.f;
|
||||
@@ -31,29 +32,29 @@ void CameraComponent::mouseMove(float deltaYaw, float deltaPitch)
|
||||
Vector xyz = glm::cross(cameraDirection, Vector(0, 0, 1));
|
||||
Quaternion result = Quaternion(glm::dot(cameraDirection, Vector(0, 0, 1)) + 1, xyz.x, xyz.y, xyz.z);
|
||||
//std::cout << "Result " << Vector(0, 0, 1) * glm::normalize(result) << " cameraDirection: " << cameraDirection << std::endl;
|
||||
setRelativeRotation(result);
|
||||
getTransform().setRelativeRotation(result);
|
||||
bNeedsViewBuild = true;
|
||||
}
|
||||
|
||||
void CameraComponent::mouseScroll(float x)
|
||||
void Camera::mouseScroll(float x)
|
||||
{
|
||||
addRelativeLocation(getTransform().getForward()*x);
|
||||
getTransform().addRelativeLocation(getTransform().getForward()*x);
|
||||
bNeedsViewBuild = true;
|
||||
}
|
||||
|
||||
void CameraComponent::moveX(float amount)
|
||||
void Camera::moveX(float amount)
|
||||
{
|
||||
addRelativeLocation(getTransform().getForward()*amount);
|
||||
getTransform().addRelativeLocation(getTransform().getForward()*amount);
|
||||
bNeedsViewBuild = true;
|
||||
}
|
||||
|
||||
void CameraComponent::moveY(float amount)
|
||||
void Camera::moveY(float amount)
|
||||
{
|
||||
addRelativeLocation(getTransform().getRight()*amount);
|
||||
getTransform().addRelativeLocation(getTransform().getRight()*amount);
|
||||
bNeedsViewBuild = true;
|
||||
}
|
||||
|
||||
void CameraComponent::setViewport(Gfx::PViewport newViewport)
|
||||
void Camera::setViewport(Gfx::PViewport newViewport)
|
||||
{
|
||||
viewport = newViewport;
|
||||
aspectRatio = viewport->getSizeX() / (float)viewport->getSizeY();
|
||||
@@ -61,17 +62,17 @@ void CameraComponent::setViewport(Gfx::PViewport newViewport)
|
||||
bNeedsProjectionBuild = true;
|
||||
}
|
||||
|
||||
void CameraComponent::buildViewMatrix()
|
||||
void Camera::buildViewMatrix()
|
||||
{
|
||||
Vector eyePos = getAbsoluteTransform().getPosition();
|
||||
Vector lookAt = eyePos + glm::normalize(Vector(cos(yaw) * cos(pitch), sin(pitch), sin(yaw) * cos(pitch)));
|
||||
Vector eyePos = getTransform().getPosition();//getAbsoluteTransform().getPosition();
|
||||
Vector lookAt = Vector(0, 0, 0);//eyePos + glm::normalize(Vector(cos(yaw) * cos(pitch), sin(pitch), sin(yaw) * cos(pitch)));
|
||||
//std::cout << "Eye: " << eyePos << " lookAt: " << lookAt << std::endl;
|
||||
viewMatrix = glm::lookAt(eyePos, lookAt, Vector(0, 1, 0));
|
||||
|
||||
bNeedsViewBuild = false;
|
||||
}
|
||||
|
||||
void CameraComponent::buildProjectionMatrix()
|
||||
void Camera::buildProjectionMatrix()
|
||||
{
|
||||
projectionMatrix = glm::perspective(fieldOfView, aspectRatio, 1.0f, 1000.f);
|
||||
static Matrix4 correctionMatrix =
|
||||
+18
-20
@@ -2,32 +2,30 @@
|
||||
#include "Component.h"
|
||||
#include "Math/Matrix.h"
|
||||
#include "Graphics/GraphicsResources.h"
|
||||
#include "Transform.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
class CameraComponent : public Component
|
||||
namespace Component
|
||||
{
|
||||
public:
|
||||
CameraComponent();
|
||||
virtual ~CameraComponent();
|
||||
struct Camera
|
||||
{
|
||||
REQUIRE_COMPONENT(Transform)
|
||||
|
||||
Matrix4 getViewMatrix()
|
||||
Camera();
|
||||
~Camera();
|
||||
|
||||
Math::Matrix4 getViewMatrix()
|
||||
{
|
||||
if (bNeedsViewBuild)
|
||||
{
|
||||
buildViewMatrix();
|
||||
}
|
||||
assert (!bNeedsViewBuild);
|
||||
return viewMatrix;
|
||||
}
|
||||
Matrix4 getProjectionMatrix()
|
||||
Math::Matrix4 getProjectionMatrix()
|
||||
{
|
||||
if (bNeedsProjectionBuild)
|
||||
{
|
||||
buildProjectionMatrix();
|
||||
}
|
||||
assert (!bNeedsProjectionBuild);
|
||||
return projectionMatrix;
|
||||
}
|
||||
Vector getCameraPosition()
|
||||
Math::Vector getCameraPosition()
|
||||
{
|
||||
return getTransform().getPosition();
|
||||
}
|
||||
@@ -38,19 +36,19 @@ public:
|
||||
void moveY(float amount);
|
||||
float aspectRatio;
|
||||
float fieldOfView;
|
||||
void buildViewMatrix();
|
||||
void buildProjectionMatrix();
|
||||
private:
|
||||
bool bNeedsViewBuild;
|
||||
bool bNeedsProjectionBuild;
|
||||
void buildViewMatrix();
|
||||
void buildProjectionMatrix();
|
||||
|
||||
Gfx::PViewport viewport;
|
||||
|
||||
//Transforms relative to actor
|
||||
Matrix4 viewMatrix;
|
||||
Matrix4 projectionMatrix;
|
||||
Math::Matrix4 viewMatrix;
|
||||
Math::Matrix4 projectionMatrix;
|
||||
float yaw;
|
||||
float pitch;
|
||||
};
|
||||
DEFINE_REF(CameraComponent)
|
||||
} // namespace Component
|
||||
} // namespace Seele
|
||||
@@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
#include <concepts>
|
||||
#include <tuple>
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
template<typename... Types>
|
||||
struct Dependencies;
|
||||
template<>
|
||||
struct Dependencies<>
|
||||
{};
|
||||
template<typename This, typename... Rest>
|
||||
struct Dependencies<This, Rest...> : public Dependencies<Rest...>
|
||||
{
|
||||
template<typename... Right>
|
||||
Dependencies<This, Rest..., Right...> operator|(const Dependencies<Right...>& other)
|
||||
{
|
||||
return Dependencies<This, Rest..., Right...>();
|
||||
}
|
||||
};
|
||||
|
||||
namespace Component
|
||||
{
|
||||
#pragma warning(disable: 4505)
|
||||
template<typename Comp>
|
||||
static int accessComponent(Comp& comp);
|
||||
}
|
||||
|
||||
template<typename T, typename... Deps>
|
||||
concept is_component = std::same_as<decltype(T::dependencies), Dependencies<Deps...>>;
|
||||
|
||||
#define REQUIRE_COMPONENT(x) \
|
||||
private: \
|
||||
x& get##x() { return *tl_##x; } \
|
||||
const x& get##x() const { return *tl_##x; }; \
|
||||
public: \
|
||||
static Dependencies<x> dependencies;
|
||||
|
||||
#define DECLARE_COMPONENT(x) \
|
||||
thread_local extern x* tl_##x; \
|
||||
template<> \
|
||||
int accessComponent<x>(x& val) { tl_##x = &val; return 0; }
|
||||
|
||||
#define DEFINE_COMPONENT(x) \
|
||||
thread_local x* Seele::Component::tl_##x;
|
||||
|
||||
} // namespace Seele
|
||||
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
#include "Graphics/GraphicsResources.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
namespace Component
|
||||
{
|
||||
struct StaticMesh
|
||||
{
|
||||
PVertexShaderInput vertexBuffer;
|
||||
Gfx::PIndexBuffer indexBuffer;
|
||||
PMaterialAsset material;
|
||||
};
|
||||
} // namespace Component
|
||||
} // namespace Seele
|
||||
@@ -0,0 +1,34 @@
|
||||
#include "Transform.h"
|
||||
|
||||
using namespace Seele::Component;
|
||||
|
||||
DEFINE_COMPONENT(Transform)
|
||||
|
||||
void Transform::setRelativeLocation(Math::Vector location)
|
||||
{
|
||||
transform = Math::Transform(location, transform.getRotation(), transform.getScale());
|
||||
}
|
||||
void Transform::setRelativeRotation(Math::Vector rotation)
|
||||
{
|
||||
transform = Math::Transform(transform.getPosition(), Math::Quaternion(rotation), transform.getScale());
|
||||
}
|
||||
void Transform::setRelativeRotation(Math::Quaternion rotation)
|
||||
{
|
||||
transform = Math::Transform(transform.getPosition(), rotation, transform.getScale());
|
||||
}
|
||||
void Transform::setRelativeScale(Math::Vector scale)
|
||||
{
|
||||
transform = Math::Transform(transform.getPosition(), transform.getRotation(), scale);
|
||||
}
|
||||
void Transform::addRelativeLocation(Math::Vector translation)
|
||||
{
|
||||
transform = Math::Transform(transform.getPosition() + translation, transform.getRotation(), transform.getScale());
|
||||
}
|
||||
void Transform::addRelativeRotation(Math::Vector rotation)
|
||||
{
|
||||
transform = Math::Transform(transform.getPosition(), transform.getRotation() * Math::Quaternion(rotation), transform.getScale());
|
||||
}
|
||||
void Transform::addRelativeRotation(Math::Quaternion rotation)
|
||||
{
|
||||
transform = Math::Transform(transform.getPosition(), transform.getRotation() * rotation, transform.getScale());
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
#include "Math/Transform.h"
|
||||
#include "Component.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
namespace Component
|
||||
{
|
||||
struct Transform
|
||||
{
|
||||
Transform() {}
|
||||
Transform(const Transform& other) : transform(other.transform) {}
|
||||
Transform(Transform&& other) : transform(other.transform) {}
|
||||
Transform& operator=(const Transform& other) {
|
||||
if (&other != this)
|
||||
{
|
||||
transform = other.transform;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
Transform& operator=(Transform&& other) {
|
||||
if(&other != this)
|
||||
{
|
||||
transform = std::move(other.transform);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
Math::Vector getPosition() const { return transform.getPosition(); }
|
||||
Math::Quaternion getRotation() const { return transform.getRotation(); }
|
||||
Math::Vector getScale() const { return transform.getScale(); }
|
||||
|
||||
Math::Vector getForward() const { return transform.getForward(); }
|
||||
Math::Vector getUp() const { return transform.getUp(); }
|
||||
Math::Vector getRight() const { return transform.getRight(); }
|
||||
|
||||
Math::Matrix4 toMatrix() const { return transform.toMatrix(); }
|
||||
|
||||
void setRelativeLocation(Math::Vector location);
|
||||
void setRelativeRotation(Math::Quaternion rotation);
|
||||
void setRelativeRotation(Math::Vector rotation);
|
||||
void setRelativeScale(Math::Vector scale);
|
||||
|
||||
void addRelativeLocation(Math::Vector translation);
|
||||
void addRelativeRotation(Math::Quaternion rotation);
|
||||
void addRelativeRotation(Math::Vector rotation);
|
||||
private:
|
||||
Math::Transform transform;
|
||||
};
|
||||
DECLARE_COMPONENT(Transform)
|
||||
|
||||
} // namespace Component
|
||||
} // namespace Seele
|
||||
@@ -1,12 +0,0 @@
|
||||
target_sources(Engine
|
||||
PUBLIC
|
||||
CameraComponent.h
|
||||
CameraComponent.cpp
|
||||
Component.h
|
||||
Component.cpp
|
||||
MyComponent.h
|
||||
MyComponent.cpp
|
||||
MyOtherComponent.h
|
||||
MyOtherComponent.cpp
|
||||
PrimitiveComponent.cpp
|
||||
PrimitiveComponent.h)
|
||||
@@ -1,201 +0,0 @@
|
||||
#include "Component.h"
|
||||
#include "Scene/Actor/Actor.h"
|
||||
#include "Scene/Scene.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
Component::Component()
|
||||
{
|
||||
}
|
||||
Component::~Component()
|
||||
{
|
||||
}
|
||||
|
||||
void Component::launchStart()
|
||||
{
|
||||
for(auto child : children)
|
||||
{
|
||||
child->launchStart();
|
||||
}
|
||||
start();
|
||||
}
|
||||
|
||||
void Component::launchTick(float deltaTime) const
|
||||
{
|
||||
for(auto child : children)
|
||||
{
|
||||
child->launchTick(deltaTime);
|
||||
}
|
||||
tick(deltaTime);
|
||||
}
|
||||
|
||||
void Component::launchUpdate()
|
||||
{
|
||||
for(auto child : children)
|
||||
{
|
||||
child->launchUpdate();
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
PComponent Component::getParent()
|
||||
{
|
||||
return parent;
|
||||
}
|
||||
PActor Component::getOwner()
|
||||
{
|
||||
if (owner != nullptr)
|
||||
{
|
||||
return owner;
|
||||
}
|
||||
if (parent != nullptr)
|
||||
{
|
||||
return parent->getOwner();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
const Array<PComponent>& Component::getChildComponents()
|
||||
{
|
||||
return children;
|
||||
}
|
||||
|
||||
void Component::setParent(PComponent newParent)
|
||||
{
|
||||
parent = newParent;
|
||||
}
|
||||
|
||||
void Component::setOwner(PActor newOwner)
|
||||
{
|
||||
owner = newOwner;
|
||||
}
|
||||
|
||||
void Component::addChildComponent(PComponent component)
|
||||
{
|
||||
children.add(component);
|
||||
}
|
||||
|
||||
void Component::notifySceneAttach(PScene scene)
|
||||
{
|
||||
owningScene = scene;
|
||||
for (auto child : children)
|
||||
{
|
||||
child->notifySceneAttach(scene);
|
||||
}
|
||||
}
|
||||
|
||||
//void Component::setAbsoluteLocation(Vector location)
|
||||
//{
|
||||
// Vector newRelLocation = location;
|
||||
// if (parent != nullptr)
|
||||
// {
|
||||
// Transform parentToWorld = getParent()->getTransform();
|
||||
// newRelLocation = parentToWorld.inverseTransformPosition(location);
|
||||
// }
|
||||
// setRelativeLocation(newRelLocation);
|
||||
//}
|
||||
//void Component::setAbsoluteRotation(Vector rotation)
|
||||
//{
|
||||
// Vector newRelRotator = rotation;
|
||||
// if (parent == nullptr)
|
||||
// {
|
||||
// setRelativeRotation(rotation);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// setAbsoluteRotation(toQuaternion(newRelRotator));
|
||||
// }
|
||||
//}
|
||||
//void Component::setAbsoluteRotation(Quaternion rotation)
|
||||
//{
|
||||
// Quaternion newRelRotation = getRelativeWorldRotation(rotation);
|
||||
// setRelativeRotation(newRelRotation);
|
||||
//}
|
||||
//void Component::setWorldScale(Vector scale)
|
||||
//{
|
||||
// Vector newRelScale = scale;
|
||||
// if (parent != nullptr)
|
||||
// {
|
||||
// Transform parentToWorld = parent->getTransform();
|
||||
// newRelScale = scale * parentToWorld.getSafeScaleReciprocal(Vector4(parentToWorld.getScale(), 0));
|
||||
// }
|
||||
// setRelativeScale(newRelScale);
|
||||
//}
|
||||
|
||||
void Component::setRelativeLocation(Vector location)
|
||||
{
|
||||
transform = Transform(location, transform.getRotation(), transform.getScale());
|
||||
propagateTransformUpdate();
|
||||
}
|
||||
void Component::setRelativeRotation(Vector rotation)
|
||||
{
|
||||
transform = Transform(transform.getPosition(), Quaternion(rotation), transform.getScale());
|
||||
propagateTransformUpdate();
|
||||
}
|
||||
void Component::setRelativeRotation(Quaternion rotation)
|
||||
{
|
||||
transform = Transform(transform.getPosition(), rotation, transform.getScale());
|
||||
propagateTransformUpdate();
|
||||
}
|
||||
void Component::setRelativeScale(Vector scale)
|
||||
{
|
||||
transform = Transform(transform.getPosition(), transform.getRotation(), scale);
|
||||
propagateTransformUpdate();
|
||||
}
|
||||
|
||||
//void Component::addAbsoluteTranslation(Vector translation)
|
||||
//{
|
||||
// const Vector newWorldLocation = translation + getTransform().getPosition();
|
||||
// setAbsoluteLocation(newWorldLocation);
|
||||
//}
|
||||
//void Component::addAbsoluteRotation(Vector rotation)
|
||||
//{
|
||||
// const Quaternion newWorldRotation = toQuaternion(rotation) * getTransform().getRotation();
|
||||
// setAbsoluteRotation(newWorldRotation);
|
||||
//}
|
||||
//void Component::addAbsoluteRotation(Quaternion rotation)
|
||||
//{
|
||||
// const Quaternion newWorldRotation = rotation * getTransform().getRotation();
|
||||
// setAbsoluteRotation(newWorldRotation);
|
||||
//}
|
||||
|
||||
void Component::addRelativeLocation(Vector translation)
|
||||
{
|
||||
transform = Transform(transform.getPosition() + translation, transform.getRotation(), transform.getScale());
|
||||
propagateTransformUpdate();
|
||||
}
|
||||
void Component::addRelativeRotation(Vector rotation)
|
||||
{
|
||||
transform = Transform(transform.getPosition(), transform.getRotation() * Quaternion(rotation), transform.getScale());
|
||||
propagateTransformUpdate();
|
||||
}
|
||||
void Component::addRelativeRotation(Quaternion rotation)
|
||||
{
|
||||
transform = Transform(transform.getPosition(), transform.getRotation() * rotation, transform.getScale());
|
||||
propagateTransformUpdate();
|
||||
}
|
||||
|
||||
Transform Component::getTransform() const
|
||||
{
|
||||
return transform;
|
||||
}
|
||||
|
||||
Transform Component::getAbsoluteTransform() const
|
||||
{
|
||||
return absoluteTransform;
|
||||
}
|
||||
|
||||
void Component::propagateTransformUpdate()
|
||||
{
|
||||
if(parent != nullptr)
|
||||
{
|
||||
absoluteTransform = transform + parent->getAbsoluteTransform();
|
||||
}
|
||||
else
|
||||
{
|
||||
absoluteTransform = transform;
|
||||
}
|
||||
for(auto child : children)
|
||||
{
|
||||
child->propagateTransformUpdate();
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
#pragma once
|
||||
#include "MinimalEngine.h"
|
||||
#include "Math/Transform.h"
|
||||
#include "Scene/Util.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
DECLARE_REF(Actor)
|
||||
DECLARE_REF(Scene)
|
||||
DECLARE_REF(Component)
|
||||
class Component
|
||||
{
|
||||
public:
|
||||
Component();
|
||||
virtual ~Component();
|
||||
void launchStart();
|
||||
virtual void start() {};
|
||||
void launchTick(float deltaTime) const;
|
||||
virtual void tick(float) const { }//co_return; }
|
||||
void launchUpdate();
|
||||
virtual void update() { }//co_return; }
|
||||
PComponent getParent();
|
||||
PActor getOwner();
|
||||
const Array<PComponent>& getChildComponents();
|
||||
void setParent(PComponent parent);
|
||||
void setOwner(PActor owner);
|
||||
void addChildComponent(PComponent component);
|
||||
virtual void notifySceneAttach(PScene scene);
|
||||
|
||||
void setRelativeLocation(Vector location);
|
||||
void setRelativeRotation(Vector rotation);
|
||||
void setRelativeRotation(Quaternion rotation);
|
||||
void setRelativeScale(Vector scale);
|
||||
|
||||
void addRelativeLocation(Vector translation);
|
||||
void addRelativeRotation(Vector rotation);
|
||||
void addRelativeRotation(Quaternion rotation);
|
||||
|
||||
Transform getTransform() const;
|
||||
Transform getAbsoluteTransform() const;
|
||||
|
||||
template<typename ComponentType>
|
||||
RefPtr<ComponentType> getComponent()
|
||||
{
|
||||
return tryFindComponent<ComponentType>();
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename ComponentType>
|
||||
RefPtr<ComponentType> tryFindComponent()
|
||||
{
|
||||
for(auto child : children)
|
||||
{
|
||||
RefPtr<ComponentType> result = child.cast<ComponentType>();
|
||||
if(result != nullptr)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
result = parent->tryFindComponent<ComponentType>();
|
||||
if(result != nullptr)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
void propagateTransformUpdate();
|
||||
Transform transform;
|
||||
Transform absoluteTransform;
|
||||
PScene owningScene;
|
||||
PActor owner;
|
||||
PComponent parent;
|
||||
Array<PComponent> children;
|
||||
friend class Actor;
|
||||
};
|
||||
DEFINE_REF(Component)
|
||||
} // namespace Seele
|
||||
@@ -1,30 +0,0 @@
|
||||
#include "MyComponent.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
MyComponent::MyComponent()
|
||||
{
|
||||
}
|
||||
|
||||
void MyComponent::start()
|
||||
{
|
||||
otherComp = getComponent<MyOtherComponent>();
|
||||
otherComp.update();
|
||||
}
|
||||
|
||||
void MyComponent::tick(float) const
|
||||
{
|
||||
//std::cout << "MyComponent::tick" << std::endl;
|
||||
++writable;
|
||||
//std::cout << "MyComponent::tick finished" << std::endl;
|
||||
otherComp->data = *writable;
|
||||
//co_return;
|
||||
}
|
||||
|
||||
void MyComponent::update()
|
||||
{
|
||||
//std::cout << "MyComponent::update" << std::endl;
|
||||
writable.update();
|
||||
//std::cout << "MyComponent::update finished" << std::endl;
|
||||
//co_return;
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
#pragma once
|
||||
#include "Component.h"
|
||||
#include "MyOtherComponent.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
class MyComponent : public Component
|
||||
{
|
||||
public:
|
||||
MyComponent();
|
||||
virtual void start();
|
||||
virtual void tick(float deltatime) const;
|
||||
virtual void update();
|
||||
private:
|
||||
Writable<PMyOtherComponent> otherComp;
|
||||
Writable<uint32> writable = 0;
|
||||
uint32 notWritable = 10;
|
||||
};
|
||||
DECLARE_REF(MyComponent);
|
||||
} // namespace Seele
|
||||
@@ -1,15 +0,0 @@
|
||||
#include "MyOtherComponent.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
void MyOtherComponent::tick(float) const
|
||||
{
|
||||
//std::cout << *data << std::endl;
|
||||
//co_return;
|
||||
}
|
||||
|
||||
void MyOtherComponent::update()
|
||||
{
|
||||
data.update();
|
||||
//co_return;
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
#pragma once
|
||||
#include "Component.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
class MyOtherComponent : public Component
|
||||
{
|
||||
public:
|
||||
virtual void tick(float deltaTime) const;
|
||||
virtual void update();
|
||||
Writable<uint32> data = Writable<uint32>(0);
|
||||
private:
|
||||
};
|
||||
DEFINE_REF(MyOtherComponent);
|
||||
} // namespace Seele
|
||||
@@ -1,54 +0,0 @@
|
||||
#include "PrimitiveComponent.h"
|
||||
#include "Scene/Scene.h"
|
||||
#include "Material/MaterialAsset.h"
|
||||
#include "Asset/MeshAsset.h"
|
||||
#include "Graphics/VertexShaderInput.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
PrimitiveComponent::PrimitiveComponent()
|
||||
{
|
||||
}
|
||||
|
||||
PrimitiveComponent::PrimitiveComponent(PMeshAsset asset)
|
||||
{
|
||||
auto assetMeshes = asset->getMeshes();
|
||||
staticMeshes.resize(assetMeshes.size());
|
||||
for (uint32 i = 0; i < assetMeshes.size(); i++)
|
||||
{
|
||||
auto& batch = staticMeshes[i];
|
||||
batch.material = asset->referencedMaterials[i];
|
||||
batch.isBackfaceCullingDisabled = false;
|
||||
batch.isCastingShadow = true;
|
||||
batch.primitiveComponent = this;
|
||||
batch.topology = Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||
batch.useReverseCulling = false;
|
||||
batch.useWireframe = false;
|
||||
batch.vertexInput = assetMeshes[i]->vertexInput;
|
||||
MeshBatchElement batchElement;
|
||||
batchElement.baseVertexIndex = 0;
|
||||
batchElement.firstIndex = 0;
|
||||
batchElement.indexBuffer = assetMeshes[i]->indexBuffer;
|
||||
batchElement.indirectArgsBuffer = nullptr;
|
||||
batchElement.instanceRuns = nullptr;
|
||||
batchElement.isInstanced = false;
|
||||
batchElement.numInstances = 1;
|
||||
batchElement.numPrimitives = assetMeshes[i]->indexBuffer->getNumIndices() / 3; //TODO: hardcoded
|
||||
batch.elements.push_back(batchElement);
|
||||
}
|
||||
}
|
||||
|
||||
PrimitiveComponent::~PrimitiveComponent()
|
||||
{
|
||||
}
|
||||
|
||||
void PrimitiveComponent::notifySceneAttach(PScene scene)
|
||||
{
|
||||
scene->addPrimitiveComponent(this);
|
||||
}
|
||||
|
||||
Matrix4 PrimitiveComponent::getRenderMatrix()
|
||||
{
|
||||
return getAbsoluteTransform().toMatrix();
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
#pragma once
|
||||
#include "Component.h"
|
||||
#include "Graphics/GraphicsResources.h"
|
||||
#include "Graphics/Mesh.h"
|
||||
#include "Material/MaterialAsset.h"
|
||||
#include "Graphics/MeshBatch.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
DECLARE_REF(MeshAsset)
|
||||
class PrimitiveComponent : public Component
|
||||
{
|
||||
public:
|
||||
PrimitiveComponent();
|
||||
PrimitiveComponent(PMeshAsset asset);
|
||||
~PrimitiveComponent();
|
||||
virtual void notifySceneAttach(PScene scene) override;
|
||||
Matrix4 getRenderMatrix();
|
||||
std::vector<StaticMeshBatch>& getStaticMeshes()
|
||||
{
|
||||
return staticMeshes;
|
||||
}
|
||||
private:
|
||||
std::vector<PMaterialAsset> materials;
|
||||
Gfx::PUniformBuffer uniformBuffer;
|
||||
std::vector<StaticMeshBatch> staticMeshes;
|
||||
friend class Scene;
|
||||
};
|
||||
DEFINE_REF(PrimitiveComponent)
|
||||
struct PrimitiveUniformBuffer
|
||||
{
|
||||
Matrix4 localToWorld;
|
||||
Matrix4 worldToLocal;
|
||||
Vector4 actorWorldPosition;
|
||||
};
|
||||
} // namespace Seele
|
||||
+64
-50
@@ -1,7 +1,8 @@
|
||||
#include "Scene.h"
|
||||
#include "Components/PrimitiveComponent.h"
|
||||
#include "Material/MaterialAsset.h"
|
||||
#include "Graphics/Graphics.h"
|
||||
#include "Component/StaticMesh.h"
|
||||
#include "Component/Transform.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
@@ -13,19 +14,6 @@ inline float frand()
|
||||
Scene::Scene(Gfx::PGraphics graphics)
|
||||
: graphics(graphics)
|
||||
{
|
||||
lightEnv.directionalLights[0].color = Vector4(1, 1, 1, 1);
|
||||
lightEnv.directionalLights[0].direction = Vector4(1, 1, 0, 1);
|
||||
lightEnv.directionalLights[0].intensity = Vector4(1, 1, 1, 1);
|
||||
lightEnv.numDirectionalLights = 1;
|
||||
srand((unsigned int)time(NULL));
|
||||
for(uint32 i = 0; i < 16; ++i)
|
||||
{
|
||||
lightEnv.pointLights[i].colorRange = Vector4(frand(), frand(), frand(), frand() * 300);
|
||||
lightEnv.pointLights[i].positionWS = Vector4(frand() * 100-50, frand(), frand() * 100-50, 1);
|
||||
}
|
||||
lightEnv.numPointLights = 16;
|
||||
lightEnv.pointLights[0].colorRange = Vector4(1, 0, 1, 1000);
|
||||
lightEnv.pointLights[0].positionWS = Vector4(0, 10, 0, 1);
|
||||
}
|
||||
|
||||
Scene::~Scene()
|
||||
@@ -34,23 +22,20 @@ Scene::~Scene()
|
||||
|
||||
void Scene::start()
|
||||
{
|
||||
for(auto actor : rootActors)
|
||||
{
|
||||
actor->launchStart();
|
||||
}
|
||||
//for(auto actor : rootActors)
|
||||
//{
|
||||
// actor->launchStart();
|
||||
//}
|
||||
}
|
||||
|
||||
static int64 lastUpdate;
|
||||
static uint64 numUpdates;
|
||||
|
||||
void Scene::beginUpdate(double deltaTime)
|
||||
void Scene::beginUpdate(double)
|
||||
{
|
||||
//std::cout << "Scene::beginUpdate" << std::endl;
|
||||
auto startTime = std::chrono::high_resolution_clock::now();
|
||||
for(auto actor : rootActors)
|
||||
{
|
||||
actor->launchTick(static_cast<float>(deltaTime));
|
||||
}
|
||||
// TODO
|
||||
auto endTime = std::chrono::high_resolution_clock::now();
|
||||
int64 delta = std::chrono::duration_cast<std::chrono::microseconds>(endTime - startTime).count();
|
||||
lastUpdate += delta;
|
||||
@@ -66,38 +51,67 @@ void Scene::beginUpdate(double deltaTime)
|
||||
void Scene::commitUpdate()
|
||||
{
|
||||
//std::cout << "Scene::commitUpdate" << std::endl;
|
||||
for(auto actor : rootActors)
|
||||
{
|
||||
actor->launchUpdate();
|
||||
}
|
||||
//for(auto actor : rootActors)
|
||||
//{
|
||||
// actor->launchUpdate();
|
||||
//}
|
||||
//std::cout << "Scene::commitUpdate finished waiting" << std::endl;
|
||||
}
|
||||
|
||||
void Scene::addActor(PActor actor)
|
||||
Array<StaticMeshBatch> Scene::getStaticMeshes()
|
||||
{
|
||||
rootActors.push_back(actor);
|
||||
actor->notifySceneAttach(this);
|
||||
Array<StaticMeshBatch> result;
|
||||
auto view = registry.view<Component::StaticMesh, Component::Transform>();
|
||||
struct PrimitiveSceneData
|
||||
{
|
||||
Math::Matrix4 localToWorld;
|
||||
Math::Matrix4 worldToLocal;
|
||||
Math::Vector4 actorLocation;
|
||||
};
|
||||
for(auto&& [entity, mesh, transform] : view.each())
|
||||
{
|
||||
PrimitiveSceneData sceneData = {
|
||||
.localToWorld = transform.toMatrix(),
|
||||
.worldToLocal = glm::inverse(transform.toMatrix()),
|
||||
.actorLocation = Math::Vector4(transform.getPosition(), 1.0f)
|
||||
};
|
||||
UniformBufferCreateInfo info = {
|
||||
.resourceData = {
|
||||
.size = sizeof(PrimitiveSceneData),
|
||||
.data = (uint8_t*)&sceneData,
|
||||
}
|
||||
};
|
||||
Gfx::PUniformBuffer transformBuf = graphics->createUniformBuffer(info);
|
||||
auto& batch = result.add();
|
||||
batch.material = mesh.material;
|
||||
batch.isBackfaceCullingDisabled = false;
|
||||
batch.isCastingShadow = true;
|
||||
batch.topology = Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||
batch.useReverseCulling = false;
|
||||
batch.useWireframe = false;
|
||||
batch.vertexInput = mesh.vertexBuffer;
|
||||
MeshBatchElement batchElement;
|
||||
batchElement.baseVertexIndex = 0;
|
||||
batchElement.firstIndex = 0;
|
||||
batchElement.indexBuffer = mesh.indexBuffer;
|
||||
batchElement.indirectArgsBuffer = nullptr;
|
||||
batchElement.instanceRuns = nullptr;
|
||||
batchElement.isInstanced = false;
|
||||
batchElement.numInstances = 1;
|
||||
batchElement.uniformBuffer = transformBuf;
|
||||
batchElement.numPrimitives = static_cast<uint32>(mesh.indexBuffer->getNumIndices() / 3); //TODO: hardcoded
|
||||
batch.elements.add(batchElement);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void Scene::addPrimitiveComponent(PPrimitiveComponent comp)
|
||||
LightEnv Scene::getLightBuffer() const
|
||||
{
|
||||
primitives.push_back(comp);
|
||||
for(auto& batch : comp->getStaticMeshes())
|
||||
{
|
||||
PrimitiveUniformBuffer data;
|
||||
data.actorWorldPosition = Vector4(comp->getTransform().getPosition(), 1);
|
||||
data.localToWorld = comp->getRenderMatrix();
|
||||
data.worldToLocal = glm::inverse(data.localToWorld);
|
||||
UniformBufferCreateInfo createInfo;
|
||||
createInfo.resourceData.data = reinterpret_cast<uint8*>(&data);
|
||||
createInfo.resourceData.owner = Gfx::QueueType::GRAPHICS;
|
||||
createInfo.resourceData.size = sizeof(data);
|
||||
createInfo.bDynamic = true;
|
||||
Gfx::PUniformBuffer uniformBuffer = graphics->createUniformBuffer(createInfo);
|
||||
for(auto& element : batch.elements)
|
||||
{
|
||||
element.uniformBuffer = uniformBuffer;
|
||||
}
|
||||
staticMeshes.push_back(batch);
|
||||
}
|
||||
LightEnv result;
|
||||
result.directionalLights[0].color = Math::Vector4(0.4, 0.3, 0.5, 1.0);
|
||||
result.directionalLights[0].direction = Math::Vector4(0.5, 0.5, 0, 0);
|
||||
result.directionalLights[0].intensity = Math::Vector4(1.0, 0.9, 0.7, 0.5);\
|
||||
result.numDirectionalLights = 1;
|
||||
result.numPointLights = 0;
|
||||
return result;
|
||||
}
|
||||
+30
-16
@@ -1,26 +1,26 @@
|
||||
#pragma once
|
||||
#include <entt/entt.hpp>
|
||||
#include "MinimalEngine.h"
|
||||
#include "Actor/Actor.h"
|
||||
#include "Graphics/GraphicsResources.h"
|
||||
#include "Components/PrimitiveComponent.h"
|
||||
#include "Graphics/MeshBatch.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
DECLARE_REF(Material)
|
||||
DECLARE_REF(Entity)
|
||||
|
||||
struct DirectionalLight
|
||||
{
|
||||
Vector4 color;
|
||||
Vector4 direction;
|
||||
Vector4 intensity;
|
||||
Math::Vector4 color;
|
||||
Math::Vector4 direction;
|
||||
Math::Vector4 intensity;
|
||||
};
|
||||
|
||||
struct PointLight
|
||||
{
|
||||
Vector4 positionWS;
|
||||
Math::Vector4 positionWS;
|
||||
//Vector4 positionVS;
|
||||
Vector4 colorRange;
|
||||
Math::Vector4 colorRange;
|
||||
};
|
||||
|
||||
#define MAX_DIRECTIONAL_LIGHTS 4
|
||||
@@ -41,17 +41,31 @@ public:
|
||||
void start();
|
||||
void beginUpdate(double deltaTime);
|
||||
void commitUpdate();
|
||||
void addActor(PActor actor);
|
||||
void addPrimitiveComponent(PPrimitiveComponent comp);
|
||||
entt::entity createEntity()
|
||||
{
|
||||
return registry.create();
|
||||
}
|
||||
template<typename Component, typename... Args>
|
||||
Component& attachComponent(entt::entity entity, Args... args)
|
||||
{
|
||||
return registry.emplace<Component>(entity, args...);
|
||||
}
|
||||
template<typename Component>
|
||||
Component& accessComponent(entt::entity entity)
|
||||
{
|
||||
return registry.get<Component>(entity);
|
||||
}
|
||||
template<typename Component>
|
||||
const Component& accessComponent(entt::entity entity) const
|
||||
{
|
||||
return registry.get<Component>(entity);
|
||||
}
|
||||
Array<StaticMeshBatch> getStaticMeshes();
|
||||
LightEnv getLightBuffer() const;
|
||||
|
||||
const std::vector<PPrimitiveComponent>& getPrimitives() const { return primitives; }
|
||||
const std::vector<StaticMeshBatch>& getStaticMeshes() const { return staticMeshes; }
|
||||
LightEnv& getLightBuffer() { return lightEnv; }
|
||||
entt::registry registry;
|
||||
private:
|
||||
std::vector<StaticMeshBatch> staticMeshes;
|
||||
std::vector<PActor> rootActors;
|
||||
std::vector<PPrimitiveComponent> primitives;
|
||||
LightEnv lightEnv;
|
||||
Gfx::PGraphics graphics;
|
||||
};
|
||||
DEFINE_REF(Scene)
|
||||
} // namespace Seele
|
||||
@@ -1,75 +0,0 @@
|
||||
#include "SceneUpdater.h"
|
||||
#include "Components/Component.h"
|
||||
#include "Actor/Actor.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
SceneUpdater::SceneUpdater()
|
||||
: pendingUpdatesSem(0)
|
||||
{
|
||||
running.store(true);
|
||||
workers.resize(std::thread::hardware_concurrency());
|
||||
for (size_t i = 0; i < workers.size(); i++)
|
||||
{
|
||||
workers[i] = std::thread(&SceneUpdater::work, this);
|
||||
}
|
||||
}
|
||||
|
||||
SceneUpdater::~SceneUpdater()
|
||||
{
|
||||
running.store(false);
|
||||
for (size_t i = 0; i < workers.size(); i++)
|
||||
{
|
||||
workers[i].join();
|
||||
}
|
||||
}
|
||||
|
||||
void SceneUpdater::registerComponentUpdate(PComponent component)
|
||||
{
|
||||
std::scoped_lock lck(pendingUpdatesLock);
|
||||
updatesRan.add([component](float delta) mutable { component->tick(delta); });
|
||||
}
|
||||
|
||||
void SceneUpdater::registerActorUpdate(PActor actor)
|
||||
{
|
||||
std::scoped_lock lck(pendingUpdatesLock);
|
||||
updatesRan.add([actor](float delta) mutable { actor->tick(delta); });
|
||||
}
|
||||
|
||||
void SceneUpdater::runUpdates(float delta)
|
||||
{
|
||||
|
||||
std::scoped_lock pendingLock(pendingUpdatesLock);
|
||||
frameDelta = delta;
|
||||
pendingUpdates = std::move(updatesRan);
|
||||
updatesRan = List<std::function<void(float)>>();
|
||||
|
||||
std::scoped_lock lck(frameFinishedLock);
|
||||
pendingLock.unlock();
|
||||
pendingUpdatesSem.release(pendingUpdates.size());
|
||||
frameFinishedCV.wait(lck);
|
||||
}
|
||||
|
||||
void SceneUpdater::work()
|
||||
{
|
||||
while(running.load())
|
||||
{
|
||||
pendingUpdatesSem.acquire();
|
||||
std::function<void(float)> function;
|
||||
{
|
||||
std::scoped_lock lck(pendingUpdatesLock);
|
||||
function = std::move(pendingUpdates.front());
|
||||
pendingUpdates.popFront();
|
||||
if(pendingUpdates.empty())
|
||||
{
|
||||
std::scoped_lock lck(frameFinishedLock);
|
||||
frameFinishedCV.notify_all();
|
||||
}
|
||||
}
|
||||
function(frameDelta);
|
||||
{
|
||||
std::scoped_lock lck(pendingUpdatesLock);
|
||||
updatesRan.add(std::move(function));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
#pragma once
|
||||
#include "MinimalEngine.h"
|
||||
#include "Containers/List.h"
|
||||
#include <semaphore>
|
||||
//DEPRECATED
|
||||
namespace Seele
|
||||
{
|
||||
DECLARE_REF(Component);
|
||||
DECLARE_REF(Actor);
|
||||
class SceneUpdater
|
||||
{
|
||||
public:
|
||||
SceneUpdater();
|
||||
~SceneUpdater();
|
||||
void registerComponentUpdate(PComponent component);
|
||||
void registerActorUpdate(PActor actor);
|
||||
void runUpdates(float delta);
|
||||
private:
|
||||
Array<std::thread> workers;
|
||||
std::mutex pendingUpdatesLock;
|
||||
std::counting_semaphore<> pendingUpdatesSem;
|
||||
List<std::function<void(float)>> pendingUpdates;
|
||||
List<std::function<void(float)>> updatesRan;
|
||||
void work();
|
||||
float frameDelta;
|
||||
std::atomic_bool running;
|
||||
std::mutex frameFinishedLock;
|
||||
std::condition_variable frameFinishedCV;
|
||||
};
|
||||
DEFINE_REF(SceneUpdater)
|
||||
} // namespace Seele
|
||||
@@ -0,0 +1,7 @@
|
||||
target_sources(Engine
|
||||
PUBLIC
|
||||
Executor.h
|
||||
Executor.cpp
|
||||
CameraSystem.h
|
||||
CameraSystem.cpp
|
||||
SystemBase.h)
|
||||
@@ -0,0 +1,11 @@
|
||||
#include "CameraSystem.h"
|
||||
#include "Scene/Component/Camera.h"
|
||||
|
||||
using namespace Seele;
|
||||
using namespace Seele::System;
|
||||
|
||||
void CameraSystem::update(Component::Camera& camera)
|
||||
{
|
||||
camera.buildViewMatrix();
|
||||
camera.buildProjectionMatrix();
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
#include "SystemBase.h"
|
||||
#include "Scene/Component/Camera.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
namespace System
|
||||
{
|
||||
class CameraSystem : public SystemBase<Component::Camera>
|
||||
{
|
||||
public:
|
||||
CameraSystem(entt::registry& registry) : SystemBase(registry) {}
|
||||
virtual ~CameraSystem() {}
|
||||
virtual void update(Component::Camera& component);
|
||||
private:
|
||||
};
|
||||
} // namespace System
|
||||
} // namespace Seele
|
||||
@@ -0,0 +1,4 @@
|
||||
#include "Executor.h"
|
||||
|
||||
using namespace Seele;
|
||||
using namespace Seele::System;
|
||||
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include "MinimalEngine.h"
|
||||
#include "SystemBase.h"
|
||||
#include <thread_pool/thread_pool.h>
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
namespace System
|
||||
{
|
||||
class Executor
|
||||
{
|
||||
public:
|
||||
Executor();
|
||||
~Executor();
|
||||
private:
|
||||
dp::thread_pool<> pool;
|
||||
};
|
||||
} // namespace System
|
||||
} // namespace Seele
|
||||
@@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
#include <entt/entt.hpp>
|
||||
#include <thread_pool/thread_pool.h>
|
||||
#include "Scene/Component/Component.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
namespace System
|
||||
{
|
||||
|
||||
template<typename... Components>
|
||||
class SystemBase
|
||||
{
|
||||
public:
|
||||
SystemBase(entt::registry& registry) : registry(registry) {}
|
||||
virtual ~SystemBase() {}
|
||||
template<typename Comp>
|
||||
auto getDependencies()
|
||||
{
|
||||
return Comp::dependencies;
|
||||
}
|
||||
template<typename... Dep>
|
||||
auto mergeDependencies(Dep... deps)
|
||||
{
|
||||
return (deps | ...);
|
||||
}
|
||||
template<typename... Deps>
|
||||
void setupView(Dependencies<Deps...>, dp::thread_pool<>&)
|
||||
{
|
||||
registry.view<Components..., Deps...>().each([&](Components&... comp, Deps&... deps){
|
||||
//pool.enqueue_detach([&](){
|
||||
int ret = (accessComponent(deps) + ...);
|
||||
assert(ret == 0);
|
||||
update((comp,...));
|
||||
//});
|
||||
});
|
||||
}
|
||||
void run(dp::thread_pool<>& pool)
|
||||
{
|
||||
setupView(mergeDependencies((getDependencies<Components>(),...)), pool);
|
||||
}
|
||||
virtual void update(Components&... components) = 0;
|
||||
private:
|
||||
entt::registry& registry;
|
||||
};
|
||||
} // namespace System
|
||||
} // namespace Seele
|
||||
@@ -59,12 +59,12 @@ bool Element::isEnabled() const
|
||||
return enabled;
|
||||
}
|
||||
|
||||
Rect& Element::getBoundingBox()
|
||||
Math::Rect& Element::getBoundingBox()
|
||||
{
|
||||
return boundingBox;
|
||||
}
|
||||
|
||||
const Rect Element::getBoundingBox() const
|
||||
const Math::Rect Element::getBoundingBox() const
|
||||
{
|
||||
return boundingBox;
|
||||
}
|
||||
@@ -23,13 +23,13 @@ public:
|
||||
bool isEnabled() const;
|
||||
// maybe not the healthiest inteface
|
||||
// non-const version
|
||||
Rect& getBoundingBox();
|
||||
Math::Rect& getBoundingBox();
|
||||
// The bounding box describes the relative size of any Element
|
||||
// relative to the total view, meaning a bounding box of (0,0), (1,1)
|
||||
// would take up the entire view
|
||||
const Rect getBoundingBox() const;
|
||||
const Math::Rect getBoundingBox() const;
|
||||
protected:
|
||||
Rect boundingBox;
|
||||
Math::Rect boundingBox;
|
||||
bool dirty;
|
||||
|
||||
bool enabled;
|
||||
|
||||
@@ -18,14 +18,14 @@ HorizontalLayout::~HorizontalLayout()
|
||||
void HorizontalLayout::apply()
|
||||
{
|
||||
Array<PElement> children = element->getChildren();
|
||||
const Rect parent = element->getBoundingBox();
|
||||
const Math::Rect parent = element->getBoundingBox();
|
||||
float xOffset = parent.offset.x;
|
||||
float yOffset = parent.offset.y;
|
||||
float xSize = parent.size.x / children.size();
|
||||
float ySize = parent.size.y;
|
||||
for(uint32 index = 0; index < children.size(); ++index)
|
||||
{
|
||||
Rect& child = children[index]->getBoundingBox();
|
||||
Math::Rect& child = children[index]->getBoundingBox();
|
||||
child.offset.x = xOffset + (index * xSize);
|
||||
child.offset.y = yOffset;
|
||||
child.size.x = xSize;
|
||||
|
||||
@@ -9,9 +9,9 @@ namespace UI
|
||||
{
|
||||
struct RenderElementStyle
|
||||
{
|
||||
Vector position = Vector(0, 0, 0);
|
||||
uint32 backgroundImageIndex = -1;
|
||||
Vector backgroundColor = Vector(1, 1, 1);
|
||||
Math::Vector position = Math::Vector(0, 0, 0);
|
||||
uint32 backgroundImageIndex = UINT32_MAX;
|
||||
Math::Vector backgroundColor = Math::Vector(1, 1, 1);
|
||||
float opacity = 1.0f;
|
||||
//Vector4 borderBottomColor = Vector4(1, 1, 1, 1);
|
||||
//Vector4 borderLeftColor = Vector4(1, 1, 1, 1);
|
||||
@@ -21,7 +21,7 @@ struct RenderElementStyle
|
||||
//float borderBottomRightRadius = 0;
|
||||
//float borderTopLeftRadius = 0;
|
||||
//float borderTopRightRadius = 0;
|
||||
Vector2 dimensions = Vector2(1, 1);
|
||||
Math::Vector2 dimensions = Math::Vector2(1, 1);
|
||||
};
|
||||
class RenderElement
|
||||
{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user