Skip to content

Commit

Permalink
custom shader data
Browse files Browse the repository at this point in the history
  • Loading branch information
malytomas committed Jan 2, 2025
1 parent e9c6a73 commit 6a1dbb6
Show file tree
Hide file tree
Showing 17 changed files with 78 additions and 48 deletions.
15 changes: 12 additions & 3 deletions sources/asset-processor/shader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <cage-core/hashString.h>
#include <cage-core/timer.h>
#include <cage-engine/assetStructs.h>
#include <cage-engine/opengl.h>

namespace
Expand All @@ -16,7 +17,7 @@ namespace
std::set<String, StringComparatorFast> onces;
std::set<detail::StringBase<20>> keywords;

ConfigBool configShaderPrint("cage-asset-processor/shader/preview");
const ConfigBool configShaderPrint("cage-asset-processor/shader/preview", false);

bool validDefineChar(const char c)
{
Expand Down Expand Up @@ -478,15 +479,23 @@ void processShader()
}

{
ShaderProgramHeader header;
header.keywordsCount = keywords.size();
header.stagesCount = codes.size();
if (defines.count("customDataCount"))
{
const uint32 cdc = toUint32(defines["customDataCount"]);
CAGE_LOG(SeverityEnum::Info, "assetProcessor", Stringizer() + "custom data count: " + cdc);
header.customDataCount = cdc;
}
MemoryBuffer buff;
Serializer ser(buff);
ser << numeric_cast<uint32>(keywords.size());
ser << header;
for (const auto &it : keywords)
{
CAGE_LOG(SeverityEnum::Info, "assetProcessor", Stringizer() + "keyword: " + it);
ser << it;
}
ser << numeric_cast<uint32>(codes.size());
for (const auto &it : codes)
{
ser << (uint32)shaderType(it.first);
Expand Down
18 changes: 12 additions & 6 deletions sources/include/cage-engine/assetStructs.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,25 @@ namespace cage
{
enum class MeshRenderFlags : uint32;

/*
enum class ShaderProgramFlags : uint32
{
None = 0,
};

struct CAGE_ENGINE_API ShaderProgramHeader
{
ShaderProgramFlags flags = ShaderProgramFlags::None;
uint32 customDataCount = 0; // number of floats passed from the game to the shader, per instance
uint32 keywordsCount = 0;
uint32 stagesCount = 0;

// follows:
// number of keywords, uint32
// array of keywords, each StringBase<20>
// number of stages, uint32
// for each stage:
// stage name, uint32
// type, uint32
// length, uint32
// stage code, array of chars
// code, array of chars
};
*/

enum class TextureFlags : uint32
{
Expand Down
3 changes: 1 addition & 2 deletions sources/include/cage-engine/font.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,8 @@ namespace cage

class CAGE_ENGINE_API Font : private Immovable
{
#ifdef CAGE_DEBUG
protected:
detail::StringBase<64> debugName;
#endif // CAGE_DEBUG

public:
void setDebugName(const String &name);
Expand Down
3 changes: 1 addition & 2 deletions sources/include/cage-engine/model.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@ namespace cage

class CAGE_ENGINE_API Model : private Immovable
{
#ifdef CAGE_DEBUG
protected:
detail::StringBase<64> debugName;
#endif // CAGE_DEBUG

public:
void setDebugName(const String &name);
Expand Down
3 changes: 1 addition & 2 deletions sources/include/cage-engine/renderObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ namespace cage
{
class CAGE_ENGINE_API RenderObject : private Immovable
{
#ifdef CAGE_DEBUG
protected:
detail::StringBase<64> debugName;
#endif // CAGE_DEBUG

public:
void setDebugName(const String &name);
Expand Down
7 changes: 7 additions & 0 deletions sources/include/cage-engine/scene.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ namespace cage
uint32 sceneMask = 1;
};

union CAGE_ENGINE_API ShaderDataComponent
{
Mat4 matrix;
Vec4 data[4];
ShaderDataComponent() : data() {}
};

struct CAGE_ENGINE_API TextureAnimationComponent
{
uint64 startTime = 0;
Expand Down
1 change: 1 addition & 0 deletions sources/include/cage-engine/shaderConventions.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
#define CAGE_SHADER_UNIBLOCK_LIGHTS 4
#define CAGE_SHADER_UNIBLOCK_SHADOWEDLIGHTS 5
#define CAGE_SHADER_UNIBLOCK_OPTIONS 6
#define CAGE_SHADER_UNIBLOCK_CUSTOMDATA 7

// options indices

Expand Down
4 changes: 4 additions & 0 deletions sources/include/cage-engine/shaderProgram.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ namespace cage
#undef GCHL_GENERATE

void compute(const Vec3i &groupsCounts);

uint32 customDataCount = 0; // number of floats passed from the game to the shader, per instance
};

class CAGE_ENGINE_API MultiShaderProgram : private Immovable
Expand All @@ -53,6 +55,8 @@ namespace cage
void compile();

Holder<ShaderProgram> get(uint32 variant); // sum of hashes of keywords

uint32 customDataCount = 0; // number of floats passed from the game to the shader, per instance
};

CAGE_ENGINE_API Holder<ShaderProgram> newShaderProgram();
Expand Down
3 changes: 1 addition & 2 deletions sources/include/cage-engine/texture.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@ namespace cage

class CAGE_ENGINE_API Texture : private Immovable
{
#ifdef CAGE_DEBUG
protected:
detail::StringBase<64> debugName;
#endif // CAGE_DEBUG

public:
void setDebugName(const String &name);
Expand Down
22 changes: 10 additions & 12 deletions sources/libengine/assets/shaderProgram.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,28 +17,26 @@ namespace cage
shr->setDebugName(context->textId);

Deserializer des(context->originalData);
ShaderProgramHeader header;
des >> header;
shr->customDataCount = header.customDataCount;
{
std::vector<detail::StringBase<20>> keywords;
uint32 count;
des >> count;
for (uint32 i = 0; i < count; i++)
keywords.reserve(header.keywordsCount);
for (uint32 i = 0; i < header.keywordsCount; i++)
{
detail::StringBase<20> s;
des >> s;
keywords.push_back(s);
}
shr->setKeywords(keywords);
}
for (uint32 i = 0; i < header.stagesCount; i++)
{
uint32 count;
des >> count;
for (uint32 i = 0; i < count; i++)
{
uint32 type, len;
des >> type >> len;
PointerRange<const char> pos = des.read(len);
shr->setSource(type, pos);
}
uint32 type, len;
des >> type >> len;
PointerRange<const char> pos = des.read(len);
shr->setSource(type, pos);
}
CAGE_ASSERT(des.available() == 0);

Expand Down
2 changes: 0 additions & 2 deletions sources/libengine/graphics/font.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -492,9 +492,7 @@ namespace cage

void Font::setDebugName(const String &name)
{
#ifdef CAGE_DEBUG
debugName = name;
#endif // CAGE_DEBUG
}

void Font::importBuffer(PointerRange<const char> buffer)
Expand Down
2 changes: 0 additions & 2 deletions sources/libengine/graphics/model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,7 @@ namespace cage

void Model::setDebugName(const String &name)
{
#ifdef CAGE_DEBUG
debugName = name;
#endif // CAGE_DEBUG
ModelImpl *impl = (ModelImpl *)this;
CAGE_ASSERT(impl->id);
glObjectLabel(GL_VERTEX_ARRAY, impl->id, name.length(), name.c_str());
Expand Down
2 changes: 0 additions & 2 deletions sources/libengine/graphics/renderObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@ namespace cage

void RenderObject::setDebugName(const String &name)
{
#ifdef CAGE_DEBUG
debugName = name;
#endif // CAGE_DEBUG
}

void RenderObject::setLods(PointerRange<const Real> thresholds, PointerRange<const uint32> modelIndices, PointerRange<const uint32> modelNames)
Expand Down
37 changes: 26 additions & 11 deletions sources/libengine/graphics/renderPipeline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ namespace cage
{
UniMesh uni;
Holder<SkeletalAnimationPreparatorInstance> skeletalAnimation;
std::optional<Mat4> customShaderData;
};

struct ModelTranslucent : public ModelShared, public ModelInstance
Expand Down Expand Up @@ -393,7 +394,7 @@ namespace cage
}

template<RenderModeEnum RenderMode>
void renderModelsImpl(const CameraData &data, const ModelShared &sh, const PointerRange<const UniMesh> uniMeshes, const PointerRange<const Mat3x4> uniArmatures, bool translucent) const
void renderModelsImpl(const CameraData &data, const ModelShared &sh, const PointerRange<const ModelInstance> instances, const PointerRange<const Mat3x4> uniArmatures, bool translucent) const
{
const Holder<RenderQueue> &renderQueue = data.renderQueue;

Expand Down Expand Up @@ -485,12 +486,28 @@ namespace cage
renderQueue->universalUniformStruct(uniOptions, CAGE_SHADER_UNIBLOCK_OPTIONS);

const uint32 limit = sh.skeletal ? min(uint32(CAGE_SHADER_MAX_MESHES), CAGE_SHADER_MAX_BONES / sh.mesh->bones) : CAGE_SHADER_MAX_MESHES;
for (uint32 offset = 0; offset < uniMeshes.size(); offset += limit)
std::vector<float> customShaderData;
std::vector<UniMesh> meshes;
for (uint32 offset = 0; offset < instances.size(); offset += limit)
{
const uint32 count = min(limit, numeric_cast<uint32>(uniMeshes.size()) - offset);
renderQueue->universalUniformArray<const UniMesh>(subRange<const UniMesh>(uniMeshes, offset, count), CAGE_SHADER_UNIBLOCK_MESHES);
const uint32 count = min(limit, numeric_cast<uint32>(instances.size()) - offset);
meshes.resize(count);
for (uint32 i = 0; i < count; i++)
meshes[i] = instances[offset + i].uni;
renderQueue->universalUniformArray<const UniMesh>(meshes, CAGE_SHADER_UNIBLOCK_MESHES);
if (sh.skeletal)
renderQueue->universalUniformArray<const Mat3x4>(subRange<const Mat3x4>(uniArmatures, offset * sh.mesh->bones, count * sh.mesh->bones), CAGE_SHADER_UNIBLOCK_ARMATURES);
if (shader->customDataCount)
{
CAGE_ASSERT(shader->customDataCount <= 16);
customShaderData.resize(shader->customDataCount * count);
for (uint32 i = 0; i < count; i++)
{
if (instances[offset + i].customShaderData)
detail::memcpy(customShaderData.data() + i * shader->customDataCount, (float *)&*instances[offset + i].customShaderData, shader->customDataCount * sizeof(float));
}
renderQueue->universalUniformArray<const float>(customShaderData, CAGE_SHADER_UNIBLOCK_CUSTOMDATA);
}
renderQueue->draw(sh.mesh, count);
}

Expand Down Expand Up @@ -520,10 +537,6 @@ namespace cage
if (none(sh.mesh->flags & MeshRenderFlags::DepthWrite))
continue;
}
std::vector<UniMesh> uniMeshes;
uniMeshes.reserve(shit.second.size());
for (const ModelInstance &inst : shit.second)
uniMeshes.push_back(inst.uni);
std::vector<Mat3x4> uniArmatures;
if (sh.skeletal)
{
Expand All @@ -536,7 +549,7 @@ namespace cage
uniArmatures.push_back(it);
}
}
renderModelsImpl<RenderMode>(data, sh, uniMeshes, uniArmatures, false);
renderModelsImpl<RenderMode>(data, sh, shit.second, uniArmatures, false);
}
renderQueue->resetAllState();
renderQueue->viewport(Vec2i(), data.resolution);
Expand All @@ -547,14 +560,14 @@ namespace cage
const auto graphicsDebugScope = renderQueue->namedScope("translucent");
for (const auto &it : layer.translucent)
{
PointerRange<const UniMesh> uniMeshes = { &it.uni, &it.uni + 1 };
PointerRange<const Mat3x4> uniArmatures;
if (it.skeletal)
{
uniArmatures = it.skeletalAnimation->armature();
CAGE_ASSERT(uniArmatures.size() == it.mesh->bones);
}
renderModelsImpl<RenderMode>(data, it, uniMeshes, uniArmatures, true);
const ModelInstance &inst = (const ModelInstance &)it;
renderModelsImpl<RenderMode>(data, it, PointerRange<const ModelInstance>(&inst, &inst + 1), uniArmatures, true);
}
renderQueue->resetAllState();
renderQueue->viewport(Vec2i(), data.resolution);
Expand Down Expand Up @@ -798,6 +811,8 @@ namespace cage
prepare.model = modelTransform(e);
prepare.uni = initializeMeshUni(data, prepare.model);
prepare.frustum = Frustum(prepare.uni.mvpMat);
if (e->has<ShaderDataComponent>())
prepare.customShaderData = e->value<ShaderDataComponent>().matrix;
if (Holder<RenderObject> obj = assets->get<AssetSchemeIndexRenderObject, RenderObject>(rc.object))
{
prepareObject<PrepareMode>(data, prepare, std::move(obj));
Expand Down
1 change: 1 addition & 0 deletions sources/libengine/graphics/shaderProgram.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ namespace cage
const std::string defines_ = defines(checked);
Holder<ShaderProgram> prg = newShaderProgram();
prg->setDebugName(debugName);
prg->customDataCount = customDataCount;
for (const auto &it : sources)
{
const std::string src = enhance(it.second, defines_);
Expand Down
2 changes: 0 additions & 2 deletions sources/libengine/graphics/texture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,7 @@ namespace cage

void Texture::setDebugName(const String &name)
{
#ifdef CAGE_DEBUG
debugName = name;
#endif // CAGE_DEBUG
TextureImpl *impl = (TextureImpl *)this;
CAGE_ASSERT(impl->id);
glObjectLabel(GL_TEXTURE, impl->id, name.length(), name.c_str());
Expand Down
1 change: 1 addition & 0 deletions sources/libsimple/gameloop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,7 @@ namespace cage
entityMgr->defineComponent(TransformComponent());
transformHistoryComponent = entityMgr->defineComponent(TransformComponent());
entityMgr->defineComponent(RenderComponent());
entityMgr->defineComponent(ShaderDataComponent());
entityMgr->defineComponent(TextureAnimationComponent());
entityMgr->defineComponent(SkeletalAnimationComponent());
entityMgr->defineComponent(LightComponent());
Expand Down

0 comments on commit 6a1dbb6

Please sign in to comment.