Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add blending option to use blend factor from the spine file #163

Merged
merged 4 commits into from
Apr 4, 2024
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
1 change: 1 addition & 0 deletions defold-spine/commonsrc/spine_ddf.proto
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ message SpineModelDesc
BLEND_MODE_ADD = 1 [(displayName) = "Add"];
BLEND_MODE_MULT = 3 [(displayName) = "Multiply"];
BLEND_MODE_SCREEN = 4 [(displayName) = "Screen"];
BLEND_MODE_INHERIT = 5 [(displayName) = "Inherit"];
}

required string spine_scene = 1 [(resource)=true];
Expand Down
75 changes: 52 additions & 23 deletions defold-spine/commonsrc/vertices.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,23 @@ uint32_t CalcVertexBufferSize(const spSkeleton* skeleton, uint32_t* out_max_tria
return count;
}

uint32_t CalcDrawDescCount(const spSkeleton* skeleton)
{
uint32_t count = 0;
for (int s = 0; s < skeleton->slotsCount; ++s)
{
spSlot* slot = skeleton->drawOrder[s];
spAttachment* attachment = slot->attachment;
if (!attachment)
{
continue;
}
count++;
}
return count;
}

uint32_t GenerateVertexData(dmArray<SpineVertex>& vertex_buffer, const spSkeleton* skeleton, const dmVMath::Matrix4& world)
uint32_t GenerateVertexData(dmArray<SpineVertex>& vertex_buffer, const spSkeleton* skeleton, const dmVMath::Matrix4& world, dmArray<SpineDrawDesc>* draw_descs_out)
{
dmArray<float> scratch; // scratch buffer

Expand All @@ -170,28 +185,7 @@ uint32_t GenerateVertexData(dmArray<SpineVertex>& vertex_buffer, const spSkeleto
continue;
}

// We let the user override the blend mode for the whole spine scene at the .spinemodel level
// // Fetch the blend mode from the slot and
// // translate it to the engine blend mode
// BlendMode engineBlendMode;
// switch (slot->data->blendMode) {
// case SP_BLEND_MODE_NORMAL:
// engineBlendMode = BLEND_NORMAL;
// break;
// case SP_BLEND_MODE_ADDITIVE:
// engineBlendMode = BLEND_ADDITIVE;
// break;
// case SP_BLEND_MODE_MULTIPLY:
// engineBlendMode = BLEND_MULTIPLY;
// break;
// case SP_BLEND_MODE_SCREEN:
// engineBlendMode = BLEND_SCREEN;
// break;
// default:
// // unknown Spine blend mode, fall back to
// // normal blend mode
// engineBlendMode = BLEND_NORMAL;
// }
uint32_t batch_vindex_start = vindex;

// Calculate the tinting color based on the skeleton's color
// and the slot's color. Each color channel is given in the
Expand Down Expand Up @@ -271,6 +265,15 @@ uint32_t GenerateVertexData(dmArray<SpineVertex>& vertex_buffer, const spSkeleto
addVertex(&vertex_buffer[vindex++], scratch[index], scratch[index + 1], uvs[index], uvs[index + 1], colorR, colorG, colorB, colorA, page_index);
}
}

if (draw_descs_out)
{
SpineDrawDesc desc;
desc.m_VertexStart = batch_vindex_start;
desc.m_BlendMode = (uint32_t) slot->data->blendMode;
desc.m_VertexCount = vindex - batch_vindex_start;
draw_descs_out->Push(desc);
}
Comment on lines +269 to +276
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only generate these if necessary

}
scratch.SetSize(0);

Expand All @@ -295,4 +298,30 @@ uint32_t GenerateVertexData(dmArray<SpineVertex>& vertex_buffer, const spSkeleto
return vcount;
}

void MergeDrawDescs(const dmArray<SpineDrawDesc>& src, dmArray<SpineDrawDesc>& dst)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could use a single array here, but it's a lot easier to read this function when we have a secondary buffer.

{
dst.SetCapacity(src.Size());
dst.SetSize(src.Size());

SpineDrawDesc* current_draw_desc = dst.Begin();
*current_draw_desc = src[0];

// If we are using "inherit" blending mode, we need to produce render objects based
// on the blend mode. If two consecutive draws have the same blend mode, we can merge them.
for (int i = 1; i < src.Size(); ++i)
{
if (current_draw_desc->m_BlendMode == src[i].m_BlendMode)
{
current_draw_desc->m_VertexCount += src[i].m_VertexCount;
}
else
{
current_draw_desc++;
*current_draw_desc = src[i];
}
}
uint32_t trimmed_size = current_draw_desc - dst.Begin() + 1;
dst.SetSize(trimmed_size);
}

} // dmSpine
52 changes: 31 additions & 21 deletions defold-spine/editor/src/spineext.clj
Original file line number Diff line number Diff line change
Expand Up @@ -346,9 +346,22 @@
(defn- set-constants! [^GL2 gl shader ro]
(doall (map (fn [constant] (set-constant! gl shader constant)) (.m_Constants ro))))

(defn- blend-factor-value-to-blend-mode [blend-factor-value]
(case blend-factor-value
0 :blend-mode-alpha
1 :blend-mode-add
2 :blend-mode-mult
3 :blend-mode-screen
:blend-mode-alpha))

Jhonnyg marked this conversation as resolved.
Show resolved Hide resolved
(defn- do-render-object! [^GL2 gl render-args shader renderable ro]
(let [start (.m_VertexStart ro) ; the name is from the engine, but in this case refers to the index
count (.m_VertexCount ro)
renderable-user-data (:user-data renderable)
renderable-blend-mode (:blend-mode renderable-user-data)
blend-mode (if (= renderable-blend-mode :blend-mode-inherit)
(blend-factor-value-to-blend-mode (.m_BlendFactor ro))
renderable-blend-mode)
face-winding (if (not= (.m_FaceWindingCCW ro) 0) GL/GL_CCW GL/GL_CW)
_ (set-constants! gl shader ro)
ro-transform (double-array (.m (.m_WorldTransform ro)))
Expand All @@ -363,7 +376,7 @@
(:view render-args)
(:projection render-args)
(:texture render-args)))]

(gl/set-blend-mode gl blend-mode)
Jhonnyg marked this conversation as resolved.
Show resolved Hide resolved
(shader/set-uniform shader gl "world_view_proj" (:world-view-proj render-args))
(when (not= (.m_SetFaceWinding ro) 0)
(gl/gl-front-face gl face-winding))
Expand All @@ -373,8 +386,7 @@
(gl/gl-draw-arrays gl triangle-mode start count))
(when use-index-buffer
(gl/gl-draw-elements gl triangle-mode start count))
; reset blend state
(.glBlendFunc gl GL/GL_SRC_ALPHA GL/GL_ONE_MINUS_SRC_ALPHA)))
(gl/set-blend-mode gl :blend-mode-alpha)))

(set! *warn-on-reflection* true)

Expand All @@ -391,15 +403,13 @@
(defn- render-group-transparent [^GL2 gl render-args override-shader group]
(let [renderable (:renderable group)
user-data (:user-data renderable)
blend-mode (:blend-mode user-data)
gpu-texture (or (get user-data :gpu-texture) texture/white-pixel)
shader (if (not= override-shader nil) override-shader (:shader user-data))
vb (:vertex-buffer group)
render-objects (:render-objects group)
vertex-binding (vtx/use-with ::spine-trans vb shader)]
(gl/with-gl-bindings gl render-args [gpu-texture shader vertex-binding]
(setup-gl gl)
(gl/set-blend-mode gl blend-mode)
(doall (map (fn [ro] (do-render-object! gl render-args shader renderable ro)) render-objects))
(restore-gl gl))))

Expand Down Expand Up @@ -428,20 +438,19 @@

(g/defnk produce-main-scene [_node-id aabb material-shader gpu-texture default-tex-params aabb spine-scene-pb spine-data-handle]
(when (and gpu-texture)
(let [blend-mode :blend-mode-alpha]
(assoc {:node-id _node-id :aabb aabb}
:renderable {:render-fn render-spine-scenes
:tags #{:spine}
:batch-key [gpu-texture material-shader]
:select-batch-key _node-id
:user-data {:aabb aabb
:spine-scene-pb spine-scene-pb
:spine-data-handle spine-data-handle
:shader material-shader
:gpu-texture gpu-texture
:tex-params default-tex-params
:blend-mode blend-mode}
:passes [pass/transparent pass/selection]}))))
(assoc {:node-id _node-id :aabb aabb}
:renderable {:render-fn render-spine-scenes
:tags #{:spine}
:batch-key [gpu-texture material-shader]
:select-batch-key _node-id
:user-data {:aabb aabb
:spine-scene-pb spine-scene-pb
:spine-data-handle spine-data-handle
:shader material-shader
:gpu-texture gpu-texture
:tex-params default-tex-params
:blend-mode :blend-mode-alpha}
:passes [pass/transparent pass/selection]})))

(defn- make-spine-outline-scene [_node-id aabb]
{:aabb aabb
Expand Down Expand Up @@ -776,7 +785,7 @@

;;//////////////////////////////////////////////////////////////////////////////////////////////

(g/defnk produce-model-pb [spine-scene-resource default-animation skin material-resource blend-mode create-go-bones playback-rate offset]
(g/defnk produce-model-pb [spine-scene-resource blend-mode default-animation skin material-resource create-go-bones playback-rate offset]
(cond-> {:spine-scene (resource/resource->proj-path spine-scene-resource)
:default-animation default-animation
:skin skin
Expand Down Expand Up @@ -953,13 +962,14 @@

(output updatable g/Any :cached produce-spine-data-handle-updatable)

(output scene g/Any :cached (g/fnk [_node-id spine-main-scene aabb material-shader tex-params spine-data-handle default-animation skin updatable]
(output scene g/Any :cached (g/fnk [_node-id spine-main-scene aabb blend-mode material-shader tex-params spine-data-handle default-animation skin updatable]
(if (and (some? material-shader) (some? (:renderable spine-main-scene)))
(let [aabb aabb
spine-scene-node-id (:node-id spine-main-scene)]
(-> spine-main-scene
(assoc-in [:renderable :user-data :shader] material-shader)
(update-in [:renderable :user-data :gpu-texture] texture/set-params tex-params)
(assoc-in [:renderable :user-data :blend-mode] blend-mode)
(assoc-in [:renderable :user-data :skin] skin)
(assoc-in [:renderable :user-data :animation] default-animation)
(assoc-in [:renderable :user-data :spine-data-handle] spine-data-handle)
Expand Down
12 changes: 10 additions & 2 deletions defold-spine/include/common/vertices.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

struct spSkeleton;


namespace dmSpine
{

Expand All @@ -27,8 +26,17 @@ struct SpineModelBounds
float maxY;
};

struct SpineDrawDesc
{
uint32_t m_VertexStart;
uint32_t m_VertexCount;
uint32_t m_BlendMode; // spBlendMode
};

uint32_t CalcVertexBufferSize(const spSkeleton* skeleton, uint32_t* out_max_triangle_count);
uint32_t GenerateVertexData(dmArray<SpineVertex>& vertex_buffer, const spSkeleton* skeleton, const dmVMath::Matrix4& world);
uint32_t CalcDrawDescCount(const spSkeleton* skeleton);
uint32_t GenerateVertexData(dmArray<SpineVertex>& vertex_buffer, const spSkeleton* skeleton, const dmVMath::Matrix4& world, dmArray<SpineDrawDesc>* draw_descs);
void GetSkeletonBounds(const spSkeleton* skeleton, SpineModelBounds& bounds);
void MergeDrawDescs(const dmArray<SpineDrawDesc>& src, dmArray<SpineDrawDesc>& dst);

} // dmSpine
Binary file modified defold-spine/plugins/lib/arm64-osx/libSpineExt.dylib
Binary file not shown.
Binary file modified defold-spine/plugins/lib/x86_64-linux/libSpineExt.so
Binary file not shown.
Binary file modified defold-spine/plugins/lib/x86_64-osx/libSpineExt.dylib
Binary file not shown.
Binary file modified defold-spine/plugins/lib/x86_64-win32/libSpineExt.dll
Binary file not shown.
Binary file modified defold-spine/plugins/share/pluginSpineExt.jar
Binary file not shown.
4 changes: 2 additions & 2 deletions defold-spine/pluginsrc/com/defold/bob/pipeline/Spine.java
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ static public class RenderObject extends Structure {
public int m_NumConstants;
public int m_VertexStart;
public int m_VertexCount;
public int pad1;
public int m_BlendFactor;
public byte m_SetBlendFactors;
public byte m_SetStencilTest;
public byte m_SetFaceWinding;
Expand All @@ -268,7 +268,7 @@ static public class RenderObject extends Structure {
protected List getFieldOrder() {
return Arrays.asList(new String[] {
"m_StencilTestParams", "m_WorldTransform", "m_Constants",
"m_NumConstants", "m_VertexStart", "m_VertexCount", "pad1",
"m_NumConstants", "m_VertexStart", "m_VertexCount", "m_BlendFactor",
"m_SetBlendFactors", "m_SetStencilTest", "m_SetFaceWinding", "m_FaceWindingCCW", "m_UseIndexBuffer", "m_IsTriangleStrip", "pad2"});
}

Expand Down
37 changes: 24 additions & 13 deletions defold-spine/pluginsrc/plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -676,24 +676,35 @@ static void UpdateRenderData(SpineFile* file)
file->m_RenderObjects.SetSize(0);
file->m_VertexBuffer.SetSize(0);

uint32_t ro_count = 1;
uint32_t ro_count = dmSpine::CalcDrawDescCount(file->m_SkeletonInstance);
AdjustArraySize(file->m_RenderObjects, ro_count);

dmArray<dmSpine::SpineDrawDesc> draw_descs;
draw_descs.SetCapacity(ro_count);

dmVMath::Matrix4 transform = dmVMath::Matrix4::identity();
dmSpine::GenerateVertexData(file->m_VertexBuffer, file->m_SkeletonInstance, transform);
dmSpine::GenerateVertexData(file->m_VertexBuffer, file->m_SkeletonInstance, transform, &draw_descs);

dmArray<dmSpine::SpineDrawDesc> merged_draw_descs;
MergeDrawDescs(draw_descs, merged_draw_descs);

dmSpinePlugin::RenderObject& ro = file->m_RenderObjects[0];
ro.Init();
ro.m_VertexStart = 0; // byte offset
ro.m_VertexCount = file->m_VertexBuffer.Size();
ro.m_SetStencilTest = 0;
ro.m_UseIndexBuffer = 0;
ro.m_IsTriangleStrip = 0; // 0 == GL_TRIANGLES, 1 == GL_TRIANGLE_STRIP
file->m_RenderObjects.SetSize(merged_draw_descs.Size());

ro.m_SetFaceWinding = 0;
ro.m_FaceWindingCCW = dmGraphics::FACE_WINDING_CCW;
for (int i = 0; i < merged_draw_descs.Size(); ++i)
{
dmSpinePlugin::RenderObject& ro = file->m_RenderObjects[i];
ro.Init();
ro.m_VertexStart = merged_draw_descs[i].m_VertexStart; // byte offset
ro.m_VertexCount = merged_draw_descs[i].m_VertexCount;
ro.m_SetStencilTest = 0;
ro.m_UseIndexBuffer = 0;
ro.m_IsTriangleStrip = 0; // 0 == GL_TRIANGLES, 1 == GL_TRIANGLE_STRIP
ro.m_BlendFactor = merged_draw_descs[i].m_BlendMode;
ro.m_SetFaceWinding = 0;
ro.m_FaceWindingCCW = dmGraphics::FACE_WINDING_CCW;

//ro.AddConstant(UNIFORM_TINT, dmVMath::Vector4(1.0f, 1.0f, 1.0f, 1.0f));
//ro.AddConstant(UNIFORM_TINT, dmVMath::Vector4(1.0f, 1.0f, 1.0f, 1.0f));

ro.m_WorldTransform = transform;
ro.m_WorldTransform = transform;
}
}
2 changes: 1 addition & 1 deletion defold-spine/pluginsrc/renderobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ namespace dmSpinePlugin
uint32_t m_NumConstants;
uint32_t m_VertexStart;
uint32_t m_VertexCount;
uint32_t : 32;
uint32_t m_BlendFactor;

bool m_SetBlendFactors;
bool m_SetStencilTest;
Expand Down
Loading
Loading