Added full support for runtime editing of material properties #215
|
@ -21,141 +21,6 @@
|
|||
Layer: 4294967295
|
||||
Strength: 0
|
||||
Scripts: ~
|
||||
- EID: 1
|
||||
Name: Floor
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: -1.440328, y: -4.41369677, z: -5}
|
||||
Rotate: {x: -0, y: 0, z: -0}
|
||||
Scale: {x: 49.4798889, y: 0.5, z: 17.5}
|
||||
Renderable Component:
|
||||
Mesh: 149697411
|
||||
Material: 126974645
|
||||
RigidBody Component:
|
||||
Type: Static
|
||||
Mass: 1
|
||||
Drag: 0.00999999978
|
||||
Angular Drag: 0.00999999978
|
||||
Use Gravity: true
|
||||
Interpolate: true
|
||||
Freeze Position X: false
|
||||
Freeze Position Y: false
|
||||
Freeze Position Z: false
|
||||
Freeze Rotation X: false
|
||||
Freeze Rotation Y: false
|
||||
Freeze Rotation Z: false
|
||||
Collider Component:
|
||||
Colliders:
|
||||
- Is Trigger: false
|
||||
Type: Box
|
||||
Half Extents: {x: 1, y: 1, z: 1}
|
||||
Friction: 0.400000006
|
||||
Bounciness: 0
|
||||
Density: 1
|
||||
Position Offset: {x: 0, y: 0, z: 0}
|
||||
Scripts: ~
|
||||
- EID: 10
|
||||
Name: Default
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: -4.40482807, y: 2.57871056, z: -5.21213436}
|
||||
Rotate: {x: -0.361265004, y: 1.11661232, z: -0.626627684}
|
||||
Scale: {x: 0.999982238, y: 0.999987125, z: 0.999981165}
|
||||
RigidBody Component:
|
||||
Type: Dynamic
|
||||
Mass: 1
|
||||
Drag: 0
|
||||
Angular Drag: 0
|
||||
Use Gravity: true
|
||||
Interpolate: true
|
||||
Freeze Position X: false
|
||||
Freeze Position Y: false
|
||||
Freeze Position Z: false
|
||||
Freeze Rotation X: false
|
||||
Freeze Rotation Y: false
|
||||
Freeze Rotation Z: false
|
||||
Collider Component:
|
||||
Colliders:
|
||||
- Is Trigger: false
|
||||
Type: Box
|
||||
Half Extents: {x: 1, y: 1, z: 1}
|
||||
Friction: 0.400000006
|
||||
Bounciness: 0
|
||||
Density: 1
|
||||
Position Offset: {x: 0, y: 0, z: 0}
|
||||
Scripts: ~
|
||||
- EID: 3
|
||||
Name: Empty
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: -0.0094268322, y: 0, z: 0}
|
||||
Rotate: {x: -0, y: 0, z: -0}
|
||||
Scale: {x: 1, y: 1, z: 1}
|
||||
Scripts: ~
|
||||
- EID: 4
|
||||
Name: Empty2
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: 0, y: 0, z: 0}
|
||||
Rotate: {x: 0, y: 0, z: 0}
|
||||
Scale: {x: 1, y: 1, z: 1}
|
||||
Scripts: ~
|
||||
- EID: 9
|
||||
Name: Bag
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: 0, y: 0, z: 0}
|
||||
Rotate: {x: 0, y: 0, z: 0}
|
||||
Scale: {x: 1, y: 1, z: 1}
|
||||
Renderable Component:
|
||||
Mesh: 144838771
|
||||
Material: 123745521
|
||||
Scripts: ~
|
||||
- EID: 6
|
||||
Name: AI
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: -8, y: -2, z: 2.5}
|
||||
Rotate: {x: 0, y: 0, z: 0}
|
||||
Scale: {x: 1, y: 1, z: 1}
|
||||
Renderable Component:
|
||||
Mesh: 149697411
|
||||
Material: 126974645
|
||||
RigidBody Component:
|
||||
Type: Dynamic
|
||||
Mass: 1
|
||||
Drag: 0
|
||||
Angular Drag: 0
|
||||
Use Gravity: true
|
||||
Interpolate: false
|
||||
Freeze Position X: false
|
||||
Freeze Position Y: false
|
||||
Freeze Position Z: false
|
||||
Freeze Rotation X: true
|
||||
Freeze Rotation Y: true
|
||||
Freeze Rotation Z: true
|
||||
Collider Component:
|
||||
Colliders:
|
||||
- Is Trigger: false
|
||||
Type: Box
|
||||
Half Extents: {x: 0.5, y: 0.5, z: 0.5}
|
||||
Friction: 0.400000006
|
||||
Bounciness: 0
|
||||
Density: 1
|
||||
Position Offset: {x: 0, y: 0.5, z: 0}
|
||||
Scripts: ~
|
||||
- EID: 7
|
||||
Name: BigBoi
|
||||
IsActive: true
|
||||
|
@ -181,46 +46,4 @@
|
|||
Color: {x: 1, y: 1, z: 1, w: 1}
|
||||
Layer: 4294967295
|
||||
Strength: 0.25
|
||||
Scripts: ~
|
||||
- EID: 5
|
||||
Name: item
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: 0, y: -2, z: -5}
|
||||
Rotate: {x: 0, y: 0, z: 0}
|
||||
Scale: {x: 2, y: 2, z: 2}
|
||||
Renderable Component:
|
||||
Mesh: 144838771
|
||||
Material: 123745521
|
||||
RigidBody Component:
|
||||
Type: Dynamic
|
||||
Mass: 1
|
||||
Drag: 0
|
||||
Angular Drag: 0
|
||||
Use Gravity: true
|
||||
Interpolate: false
|
||||
Freeze Position X: false
|
||||
Freeze Position Y: false
|
||||
Freeze Position Z: false
|
||||
Freeze Rotation X: true
|
||||
Freeze Rotation Y: true
|
||||
Freeze Rotation Z: true
|
||||
Collider Component:
|
||||
Colliders:
|
||||
- Is Trigger: false
|
||||
Type: Box
|
||||
Half Extents: {x: 1, y: 1, z: 1}
|
||||
Friction: 0.400000006
|
||||
Bounciness: 0
|
||||
Density: 1
|
||||
Position Offset: {x: 0, y: 0.5, z: 0}
|
||||
- Is Trigger: true
|
||||
Type: Box
|
||||
Half Extents: {x: 2, y: 2, z: 2}
|
||||
Friction: 0.400000006
|
||||
Bounciness: 0
|
||||
Density: 1
|
||||
Position Offset: {x: 0, y: 0.5, z: 0}
|
||||
Scripts: ~
|
|
@ -0,0 +1,50 @@
|
|||
#version 450
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
#extension GL_ARB_shading_language_420pack : enable
|
||||
#extension GL_EXT_nonuniform_qualifier : require
|
||||
|
||||
struct MatPropData
|
||||
{
|
||||
vec4 color;
|
||||
int textureIndex;
|
||||
float alpha;
|
||||
vec3 beta;
|
||||
};
|
||||
|
||||
layout(location = 0) in struct
|
||||
{
|
||||
vec4 vertPos; // location 0
|
||||
vec2 uv; // location = 1
|
||||
vec4 normal; // location = 2
|
||||
|
||||
} In;
|
||||
|
||||
// material stuff
|
||||
layout(location = 3) flat in struct
|
||||
{
|
||||
int materialIndex;
|
||||
uint eid;
|
||||
uint lightLayerIndex;
|
||||
} In2;
|
||||
|
||||
layout (set = 0, binding = 1) uniform sampler2D textures[]; // for textures (global)
|
||||
layout (std430, set = 3, binding = 0) buffer MaterialProperties // For materials
|
||||
{
|
||||
MatPropData data[];
|
||||
} MatProp;
|
||||
|
||||
layout(location = 0) out vec4 position;
|
||||
layout(location = 1) out uint outEntityID;
|
||||
layout(location = 2) out uint lightLayerIndices;
|
||||
layout(location = 3) out vec4 normals;
|
||||
layout(location = 4) out vec4 albedo;
|
||||
|
||||
void main()
|
||||
{
|
||||
position = In.vertPos;
|
||||
normals = In.normal;
|
||||
albedo = normals * texture(textures[nonuniformEXT(MatProp.data[In2.materialIndex].textureIndex)], In.uv) * MatProp.data[In2.materialIndex].color;
|
||||
|
||||
outEntityID = In2.eid;
|
||||
lightLayerIndices = In2.lightLayerIndex;
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,3 @@
|
|||
Name: Normals_FS
|
||||
ID: 48689301
|
||||
Type: 2
|
|
@ -78,7 +78,26 @@ namespace SHADE
|
|||
ImGui::BeginDisabled(!isDirty);
|
||||
if(ImGui::Button(std::format("{} Save", ICON_MD_SAVE).data()))
|
||||
{
|
||||
//save
|
||||
// Replace Material if it's been instantiated
|
||||
auto matHandle = SHResourceManager::Get<SHMaterial>(currentViewedMaterial);
|
||||
if (matHandle)
|
||||
{
|
||||
// - Get Shader Modules
|
||||
auto vertShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(currentMatSpec->vertexShader);
|
||||
auto fragShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(currentMatSpec->fragShader);
|
||||
auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
|
||||
if (vertShader && fragShader && gfxSystem)
|
||||
{
|
||||
// - Retrieve pipeline from pipeline library
|
||||
auto renderPass = gfxSystem->GetPrimaryRenderpass();
|
||||
auto subPass = renderPass->GetSubpass(currentMatSpec->subpassName);
|
||||
auto pipeline = renderPass->GetOrCreatePipeline({ vertShader, fragShader }, subPass);
|
||||
// - Set Pipeline
|
||||
matHandle->SetPipeline(pipeline);
|
||||
}
|
||||
}
|
||||
|
||||
// Save Properties
|
||||
if(auto matAsset = SHAssetManager::GetData<SHMaterialAsset>(currentViewedMaterial))
|
||||
{
|
||||
YAML::Emitter out;
|
||||
|
@ -136,12 +155,36 @@ namespace SHADE
|
|||
{
|
||||
/*if(!shaderModule)
|
||||
return;*/
|
||||
auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
|
||||
auto interface = gfxSystem->GetDefaultMaterialInstance()->GetBaseMaterial()->GetShaderBlockInterface();
|
||||
//auto interface = shaderModule->GetReflectedData().GetDescriptorBindingInfo().GetShaderBlockInterface(SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE, SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA);
|
||||
|
||||
int const varCount = static_cast<int>(interface->GetVariableCount());
|
||||
// Shader
|
||||
bool shaderChanged = false;
|
||||
const auto* SHADER_INFO = SHAssetManager::GetData<SHShaderAsset>(currentMatSpec->fragShader);
|
||||
const std::string SHADER_NAME = SHADER_INFO ? SHADER_INFO->name : "Unknown Shader";
|
||||
isDirty |= SHEditorWidgets::DragDropReadOnlyField<AssetID>
|
||||
(
|
||||
"Fragment Shader", SHADER_NAME.data(),
|
||||
[this]() { return currentMatSpec->fragShader; },
|
||||
[this](const AssetID& id) { currentMatSpec->fragShader = id; },
|
||||
SHDragDrop::DRAG_RESOURCE
|
||||
);
|
||||
|
||||
// Load the shader to access it's data
|
||||
auto fragShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(currentMatSpec->fragShader);
|
||||
if (!fragShader)
|
||||
return;
|
||||
|
||||
// Get interface for the shader combination
|
||||
auto interface = fragShader->GetReflectedData().GetDescriptorBindingInfo().GetShaderBlockInterface
|
||||
(
|
||||
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
||||
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA
|
||||
);
|
||||
if (!interface)
|
||||
return;
|
||||
|
||||
// Properties
|
||||
int const varCount = static_cast<int>(interface->GetVariableCount());
|
||||
for (int i = 0; i < varCount; ++i)
|
||||
{
|
||||
auto variable = interface->GetVariable(i);
|
||||
|
|
|
@ -38,11 +38,11 @@ namespace SHADE
|
|||
/// </summary>
|
||||
std::vector<vk::DescriptorPoolSize> Limits =
|
||||
{
|
||||
{ vk::DescriptorType::eCombinedImageSampler, 100 },
|
||||
{ vk::DescriptorType::eUniformBuffer, 100 },
|
||||
{ vk::DescriptorType::eUniformBufferDynamic, 100 },
|
||||
{ vk::DescriptorType::eStorageImage, 100},
|
||||
{ vk::DescriptorType::eStorageBufferDynamic, 100 }
|
||||
{ vk::DescriptorType::eCombinedImageSampler, 1000 },
|
||||
{ vk::DescriptorType::eUniformBuffer, 1000 },
|
||||
{ vk::DescriptorType::eUniformBufferDynamic, 1000 },
|
||||
{ vk::DescriptorType::eStorageImage, 1000 },
|
||||
{ vk::DescriptorType::eStorageBufferDynamic, 1000 }
|
||||
};
|
||||
/// <summary>
|
||||
/// Maximum number of descriptor sets allowed
|
||||
|
|
|
@ -43,6 +43,85 @@ namespace SHADE
|
|||
setAllDirtyFlags();
|
||||
}
|
||||
|
||||
SHBatch::SHBatch(SHBatch&& rhs)
|
||||
: device { rhs.device }
|
||||
, pipeline { rhs.pipeline }
|
||||
, referencedMatInstances { std::move(rhs.referencedMatInstances) }
|
||||
, matBufferDirty { std::move(rhs.matBufferDirty) }
|
||||
, subBatches { std::move(rhs.subBatches) }
|
||||
, drawData { std::move(drawData) }
|
||||
, transformData { std::move(rhs.transformData) }
|
||||
, instancedIntegerData { std::move(rhs.instancedIntegerData) }
|
||||
, matPropsData { std::move(rhs.matPropsData) }
|
||||
, matPropsDataSize { rhs.matPropsDataSize }
|
||||
, singleMatPropAlignedSize { rhs.singleMatPropAlignedSize }
|
||||
, singleMatPropSize { rhs.singleMatPropSize }
|
||||
, isCPUBuffersDirty { rhs.isCPUBuffersDirty }
|
||||
, drawDataBuffer { rhs.drawDataBuffer }
|
||||
, transformDataBuffer { rhs.transformDataBuffer }
|
||||
, instancedIntegerBuffer { rhs.instancedIntegerBuffer }
|
||||
, matPropsBuffer { rhs.matPropsBuffer }
|
||||
, matPropsDescSet { rhs.matPropsDescSet }
|
||||
{
|
||||
rhs.drawDataBuffer = {};
|
||||
rhs.transformDataBuffer = {};
|
||||
rhs.instancedIntegerBuffer = {};
|
||||
rhs.matPropsBuffer = {};
|
||||
rhs.matPropsDescSet = {};
|
||||
}
|
||||
|
||||
SHBatch& SHBatch::operator=(SHBatch&& rhs)
|
||||
{
|
||||
if (this == &rhs)
|
||||
return *this;
|
||||
|
||||
device = rhs.device ;
|
||||
pipeline = rhs.pipeline ;
|
||||
referencedMatInstances = std::move(rhs.referencedMatInstances);
|
||||
matBufferDirty = std::move(rhs.matBufferDirty) ;
|
||||
subBatches = std::move(rhs.subBatches) ;
|
||||
drawData = std::move(drawData) ;
|
||||
transformData = std::move(rhs.transformData) ;
|
||||
instancedIntegerData = std::move(rhs.instancedIntegerData) ;
|
||||
matPropsData = std::move(rhs.matPropsData) ;
|
||||
matPropsDataSize = rhs.matPropsDataSize ;
|
||||
singleMatPropAlignedSize = rhs.singleMatPropAlignedSize ;
|
||||
singleMatPropSize = rhs.singleMatPropSize ;
|
||||
isCPUBuffersDirty = rhs.isCPUBuffersDirty ;
|
||||
drawDataBuffer = rhs.drawDataBuffer ;
|
||||
transformDataBuffer = rhs.transformDataBuffer ;
|
||||
instancedIntegerBuffer = rhs.instancedIntegerBuffer ;
|
||||
matPropsBuffer = rhs.matPropsBuffer ;
|
||||
matPropsDescSet = rhs.matPropsDescSet ;
|
||||
|
||||
// Unset values
|
||||
rhs.drawDataBuffer = {};
|
||||
rhs.transformDataBuffer = {};
|
||||
rhs.instancedIntegerBuffer = {};
|
||||
rhs.matPropsBuffer = {};
|
||||
rhs.matPropsDescSet = {};
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
SHBatch::~SHBatch()
|
||||
{
|
||||
// Free GPU buffers
|
||||
for (int i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i)
|
||||
{
|
||||
if (drawDataBuffer[i])
|
||||
drawDataBuffer[i].Free();
|
||||
if (transformDataBuffer[i])
|
||||
transformDataBuffer[i].Free();
|
||||
if (instancedIntegerBuffer[i])
|
||||
instancedIntegerBuffer[i].Free();
|
||||
if (matPropsBuffer[i])
|
||||
matPropsBuffer[i].Free();
|
||||
if (matPropsDescSet[i])
|
||||
matPropsDescSet[i].Free();
|
||||
}
|
||||
}
|
||||
|
||||
void SHBatch::Add(const SHRenderable* renderable)
|
||||
{
|
||||
// Ignore if null
|
||||
|
|
|
@ -71,6 +71,11 @@ namespace SHADE
|
|||
/* Constructor/Destructors */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
SHBatch(Handle<SHVkPipeline> pipeline);
|
||||
SHBatch(const SHBatch&) = delete;
|
||||
SHBatch(SHBatch&& rhs);
|
||||
SHBatch& operator=(const SHBatch&) = delete;
|
||||
SHBatch& operator=(SHBatch&& rhs);
|
||||
~SHBatch();
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Usage Functions */
|
||||
|
|
|
@ -849,11 +849,16 @@ namespace SHADE
|
|||
|
||||
void SHGraphicsSystem::BatcherDispatcherRoutine::Execute(double) noexcept
|
||||
{
|
||||
auto& renderables = SHComponentManager::GetDense<SHRenderable>();
|
||||
auto& renderables = SHComponentManager::GetDense<SHRenderable>();
|
||||
for (auto& renderable : renderables)
|
||||
{
|
||||
// Check if the material instance is now unused
|
||||
renderable.CleanUpMaterials();
|
||||
|
||||
if (!renderable.HasChanged())
|
||||
continue;
|
||||
continue;
|
||||
|
||||
// TODO: Need to account for
|
||||
|
||||
// Remove from the SuperBatch it is previously in (prevMat if mat has changed)
|
||||
Handle<SHMaterialInstance> prevMaterial = renderable.HasMaterialChanged() ? renderable.GetPrevMaterial() : renderable.GetMaterial();
|
||||
|
@ -862,9 +867,8 @@ namespace SHADE
|
|||
Handle<SHSuperBatch> oldSuperBatch = prevMaterial->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch();
|
||||
oldSuperBatch->Remove(&renderable);
|
||||
}
|
||||
|
||||
// Add to new SuperBatch if there is a material
|
||||
// Add to new SuperBatch if there is a material and a mesh to render
|
||||
|
||||
// Add to new SuperBatch if there is a material and a mesh to render
|
||||
Handle<SHMaterialInstance> newMatInstance = renderable.GetMaterial();
|
||||
if (newMatInstance && renderable.GetMesh())
|
||||
{
|
||||
|
@ -875,6 +879,8 @@ namespace SHADE
|
|||
// Unset change flag
|
||||
renderable.ResetChangedFlag();
|
||||
}
|
||||
|
||||
// TODO: Also reset all material instances isDrity
|
||||
}
|
||||
#pragma endregion ROUTINES
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ namespace SHADE
|
|||
memset(dataStore.get(), 0, dataStoreSize);
|
||||
overrideData.clear();
|
||||
dataStore.reset();
|
||||
dataWasChanged = true;
|
||||
}
|
||||
|
||||
void SHMaterialInstance::ExportProperties(void* dest)
|
||||
|
@ -61,7 +62,7 @@ namespace SHADE
|
|||
}
|
||||
|
||||
// Data was exported so unflag
|
||||
dataWasChanged = false;
|
||||
//dataWasChanged = false;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
|
|
@ -70,6 +70,7 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------------*/
|
||||
Handle<SHMaterial> GetBaseMaterial() const noexcept { return baseMaterial; }
|
||||
bool HasChanged() const noexcept { return dataWasChanged; }
|
||||
bool IsBlank() const noexcept { return overrideData.empty(); } // No overrides
|
||||
|
||||
private:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
|
|
|
@ -96,6 +96,14 @@ namespace SHADE
|
|||
return material;
|
||||
}
|
||||
|
||||
void SHRenderable::CleanUpMaterials() noexcept
|
||||
{
|
||||
if (material && material->IsBlank())
|
||||
{
|
||||
SetMaterial(sharedMaterial);
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Mesh Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
@ -114,6 +122,20 @@ namespace SHADE
|
|||
return lightLayer;
|
||||
}
|
||||
|
||||
bool SHRenderable::HasChanged() const noexcept
|
||||
{
|
||||
if (matChanged || meshChanged)
|
||||
return true;
|
||||
|
||||
// If the underlying material has changed
|
||||
auto mat = GetMaterial();
|
||||
if (mat)
|
||||
{
|
||||
return mat->HasChanged();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Batcher Dispatcher Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
|
|
@ -53,6 +53,10 @@ namespace SHADE
|
|||
Handle<SHMaterialInstance> GetModifiableMaterial();
|
||||
Handle<SHMaterialInstance> GetPrevMaterial() const noexcept { return oldMaterial; }
|
||||
bool HasMaterialChanged() const noexcept { return matChanged; }
|
||||
/// <summary>
|
||||
/// Clears the modifiable material if it is unused.
|
||||
/// </summary>
|
||||
void CleanUpMaterials() noexcept;
|
||||
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Mesh Functions */
|
||||
|
@ -70,7 +74,7 @@ namespace SHADE
|
|||
/*-------------------------------------------------------------------------------*/
|
||||
/* Batcher Dispatcher Functions */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
bool HasChanged() const noexcept { return matChanged || meshChanged; } // Whether or not the mesh or material has changed
|
||||
bool HasChanged() const noexcept; // Whether or not the mesh or material has changed
|
||||
void ResetChangedFlag(); // TODO: Lock it so that only SHBatcherDispatcher can access this
|
||||
|
||||
private:
|
||||
|
|
Loading…
Reference in New Issue