Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions doc/pr-changelogs/3374.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
### Features
* glTF models now load the `COLOR_0` vertex attribute. Model shaders can read it as `layout (location = 15) in vec4 color`, and Lua as the `color` attribute of `VBO:ModelsVBO()`. Models without it (including all S3O, 3DO and assimp models) read opaque white. `Engine.FeatureSupport.modelVertexColor` is `true` on engines that have it.

### Caveats
* one element of `VBO:ModelsVBO()` is now 80 bytes instead of 76; Lua code that hardcoded the old stride needs updating.
2 changes: 2 additions & 0 deletions rts/Lua/LuaConstEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
* @field reliableLuaMapShaders boolean Whether forward-only Lua map shaders activate without a deferred draw and Spring.SetMapShader program swaps refresh cached uniform locations
* @field nanoParticleUpdateCallin boolean Whether LuaUI receives batched `NanoParticleUpdate` lifecycle events
* @field nanoParticlesGL4 boolean Whether the engine has the standalone shader-based nano particle effect (the `NanoParticles*` springsettings)
* @field modelVertexColor boolean Whether glTF `COLOR_0` is loaded into the models VBO (`color`, attribute 15; opaque white when absent)
*/

/***
Expand Down Expand Up @@ -89,6 +90,7 @@ bool LuaConstEngine::PushEntries(lua_State* L)
LuaPushNamedBool(L, "reliableLuaMapShaders", true);
LuaPushNamedBool(L, "nanoParticleUpdateCallin", true);
LuaPushNamedBool(L, "nanoParticlesGL4", true);
LuaPushNamedBool(L, "modelVertexColor", true);
lua_rawset(L, -3);

lua_pushliteral(L, "textColorCodes");
Expand Down
14 changes: 13 additions & 1 deletion rts/Lua/LuaVBOImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -814,6 +814,7 @@ void LuaVBOImpl::UpdateModelsVBOElementCount()
// support an arbitrary number of channels, would be easy but overkill (for now)
float2 texCoords[NUM_MODEL_UVCHANNS];
uvec3 in uvec3 bonesInfo;
u8vec4 color;
*/
size_t LuaVBOImpl::ModelsVBOImpl()
{
Expand Down Expand Up @@ -884,7 +885,18 @@ size_t LuaVBOImpl::ModelsVBOImpl()
3 * sizeof(uint32_t) //strideSizeInBytes
};

this->attributesCount = 6;
// uint8_t color[4]
this->bufferAttribDefs[15] = {
GL_UNSIGNED_BYTE, //type
4, //size
GL_TRUE, //normalized
"color", //name
offsetof(SVertexData, color), //pointer
sizeof(uint8_t), //typeSizeInBytes
4 * sizeof(uint8_t) //strideSizeInBytes
};

this->attributesCount = 7;
this->elemSizeInBytes = sizeof(SVertexData);
this->bufferSizeInBytes = vbo->GetSize();
this->elementsCount = S3DModelVAO::GetInstance().GetVertElemCount();
Expand Down
7 changes: 7 additions & 0 deletions rts/Rendering/Models/3DModelVAO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ void S3DModelVAO::EnableAttribs(bool inst) const
glVertexAttribPointer (3, 3, GL_FLOAT , false, sizeof(SVertexData), (const void*)offsetof(SVertexData, tTangent ));
glVertexAttribPointer (4, 4, GL_FLOAT , false, sizeof(SVertexData), (const void*)offsetof(SVertexData, texCoords[0]));
glVertexAttribIPointer(5, 3, GL_UNSIGNED_INT, sizeof(SVertexData), (const void*)offsetof(SVertexData, boneIDsLow ));

// last guaranteed slot, Lua VAOs on this buffer put their instance attribs from 6 up
glEnableVertexAttribArray(15);
glVertexAttribDivisor(15, 0);
glVertexAttribPointer (15, 4, GL_UNSIGNED_BYTE, true , sizeof(SVertexData), (const void*)offsetof(SVertexData, color ));
}
else {
for (int i = 6; i <= 6; ++i) {
Expand All @@ -50,6 +55,8 @@ void S3DModelVAO::DisableAttribs() const
glDisableVertexAttribArray(i);
glVertexAttribDivisor(i, 0);
}

glDisableVertexAttribArray(15);
}

S3DModelVAO::S3DModelVAO()
Expand Down
12 changes: 12 additions & 0 deletions rts/Rendering/Models/GLTFParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,18 @@ namespace Impl {
});
seenTangents = true;
} break;
case hashString("COLOR_0"): {
const auto ToByte = [](float v) { return static_cast<uint8_t>(std::clamp(v, 0.0f, 1.0f) * 255.0f + 0.5f); };
if (accessor.type == fastgltf::AccessorType::Vec3) {
fastgltf::iterateAccessorWithIndex<fastgltf::math::fvec3>(asset, accessor, [&](const auto& val, std::size_t idx) {
verts[prevVertSize + idx].color = { ToByte(val.x()), ToByte(val.y()), ToByte(val.z()), 255 };
});
} else if (accessor.type == fastgltf::AccessorType::Vec4) {
fastgltf::iterateAccessorWithIndex<fastgltf::math::fvec4>(asset, accessor, [&](const auto& val, std::size_t idx) {
verts[prevVertSize + idx].color = { ToByte(val.x()), ToByte(val.y()), ToByte(val.z()), ToByte(val.w()) };
});
}
} break;
case hashString("JOINTS_0"): {
assert(skinPtr);
fastgltf::iterateAccessorWithIndex<fastgltf::math::uvec4>(asset, accessor, [&](const auto& val, std::size_t idx) {
Expand Down
2 changes: 1 addition & 1 deletion rts/Rendering/Models/VertexData.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "VertexData.hpp"

static_assert(sizeof(SVertexData) == (3 + 3 + 3 + 3 + 4 + 2 + 1) * 4);
static_assert(sizeof(SVertexData) == (3 + 3 + 3 + 3 + 4 + 2 + 1 + 1) * 4);

void SVertexData::TransformBy(const Transform& transform)
{
Expand Down
5 changes: 5 additions & 0 deletions rts/Rendering/Models/VertexData.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ struct SVertexData {
boneIDsLow = DEFAULT_BONEIDS_LOW;
boneWeights = DEFAULT_BONEWEIGHTS;
boneIDsHigh = DEFAULT_BONEIDS_HIGH;
color = DEFAULT_COLOR;
}
SVertexData(
const float3& p,
Expand All @@ -42,12 +43,14 @@ struct SVertexData {
boneIDsLow = DEFAULT_BONEIDS_LOW;
boneWeights = DEFAULT_BONEWEIGHTS;
boneIDsHigh = DEFAULT_BONEIDS_HIGH;
color = DEFAULT_COLOR;
}

static constexpr size_t NUM_MODEL_UVCHANNS = 2;
static constexpr std::array<uint8_t, 4> DEFAULT_BONEIDS_HIGH = { 255, 255, 255, 255 };
static constexpr std::array<uint8_t, 4> DEFAULT_BONEIDS_LOW = { 255, 255, 255, 255 };
static constexpr std::array<uint8_t, 4> DEFAULT_BONEWEIGHTS = { 255, 0 , 0, 0 };
static constexpr std::array<uint8_t, 4> DEFAULT_COLOR = { 255, 255, 255, 255 };
static constexpr uint16_t INVALID_BONEID = 0xFFFF;
static constexpr size_t MAX_BONES_PER_VERTEX = 4;

Expand All @@ -61,6 +64,8 @@ struct SVertexData {
std::array<uint8_t, MAX_BONES_PER_VERTEX> boneWeights;
std::array<uint8_t, MAX_BONES_PER_VERTEX> boneIDsHigh;

std::array<uint8_t, 4> color;

template <Concepts::HasSizeAndData C>
void SetBones(const C& bi) {
static_assert(std::is_same_v<typename C::value_type, std::pair<uint16_t, float>>);
Expand Down
Loading