From 3ed9290c6f1ca539b03ff8706f6cd6d9158823aa Mon Sep 17 00:00:00 2001 From: badlogic Date: Tue, 14 Mar 2017 13:14:23 +0100 Subject: [PATCH] [cocos2d-objc] More two color tinting work. --- spine-c/spine-c/include/spine/extension.h | 2 + spine-c/spine-c/src/spine/extension.c | 3 + .../project.pbxproj | 12 ++-- .../spine/{TwoColorBatcher.c => GLUtils.c} | 71 ++++++++++++++++--- .../spine/{TwoColorBatcher.h => GLUtils.h} | 42 +++++++++-- .../src/spine/SkeletonRenderer.h | 4 +- .../src/spine/SkeletonRenderer.m | 51 ++++++++++--- 7 files changed, 149 insertions(+), 36 deletions(-) rename spine-cocos2d-objc/src/spine/{TwoColorBatcher.c => GLUtils.c} (72%) rename spine-cocos2d-objc/src/spine/{TwoColorBatcher.h => GLUtils.h} (68%) diff --git a/spine-c/spine-c/include/spine/extension.h b/spine-c/spine-c/include/spine/extension.h index 3586c479d..80247df92 100644 --- a/spine-c/spine-c/include/spine/extension.h +++ b/spine-c/spine-c/include/spine/extension.h @@ -64,6 +64,7 @@ /* All allocation uses these. */ #define MALLOC(TYPE,COUNT) ((TYPE*)_malloc(sizeof(TYPE) * (COUNT), __FILE__, __LINE__)) #define CALLOC(TYPE,COUNT) ((TYPE*)_calloc(COUNT, sizeof(TYPE), __FILE__, __LINE__)) +#define REALLOC(PTR,TYPE,COUNT) ((TYPE*)_realloc(PTR, sizeof(TYPE) * (COUNT))) #define NEW(TYPE) CALLOC(TYPE,1) /* Gets the direct super class. Type safe. */ @@ -162,6 +163,7 @@ char* _spUtil_readFile (const char* path, int* length); void* _malloc (size_t size, const char* file, int line); void* _calloc (size_t num, size_t size, const char* file, int line); +void* _realloc(void* ptr, size_t size); void _free (void* ptr); void _setMalloc (void* (*_malloc) (size_t size)); diff --git a/spine-c/spine-c/src/spine/extension.c b/spine-c/spine-c/src/spine/extension.c index cc43ad3dc..b0633664d 100644 --- a/spine-c/spine-c/src/spine/extension.c +++ b/spine-c/spine-c/src/spine/extension.c @@ -46,6 +46,9 @@ void* _calloc (size_t num, size_t size, const char* file, int line) { if (ptr) memset(ptr, 0, num * size); return ptr; } +void* _realloc(void* ptr, size_t size) { + return realloc(ptr, size); +} void _free (void* ptr) { freeFunc(ptr); } diff --git a/spine-cocos2d-objc/spine-cocos2d-objc.xcodeproj/project.pbxproj b/spine-cocos2d-objc/spine-cocos2d-objc.xcodeproj/project.pbxproj index 7974ea1f7..66c7a676e 100644 --- a/spine-cocos2d-objc/spine-cocos2d-objc.xcodeproj/project.pbxproj +++ b/spine-cocos2d-objc/spine-cocos2d-objc.xcodeproj/project.pbxproj @@ -33,7 +33,7 @@ 652107961895250000B1FF07 /* CoreText.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 652107951895250000B1FF07 /* CoreText.framework */; }; 765A2EF61D7D7A08003FB779 /* goblins.atlas in Resources */ = {isa = PBXBuildFile; fileRef = 765A2EF41D7D7A08003FB779 /* goblins.atlas */; }; 765A2EF71D7D7A08003FB779 /* goblins.png in Resources */ = {isa = PBXBuildFile; fileRef = 765A2EF51D7D7A08003FB779 /* goblins.png */; }; - 76BF7E071E66ED9C00485998 /* TwoColorBatcher.c in Sources */ = {isa = PBXBuildFile; fileRef = 76BF7E051E66ED9C00485998 /* TwoColorBatcher.c */; }; + 76BF7E071E66ED9C00485998 /* GLUtils.c in Sources */ = {isa = PBXBuildFile; fileRef = 76BF7E051E66ED9C00485998 /* GLUtils.c */; }; 76F28D161DEC810300CDE54D /* Animation.c in Sources */ = {isa = PBXBuildFile; fileRef = 76F28CF41DEC810200CDE54D /* Animation.c */; }; 76F28D171DEC810300CDE54D /* AnimationState.c in Sources */ = {isa = PBXBuildFile; fileRef = 76F28CF51DEC810300CDE54D /* AnimationState.c */; }; 76F28D181DEC810300CDE54D /* AnimationStateData.c in Sources */ = {isa = PBXBuildFile; fileRef = 76F28CF61DEC810300CDE54D /* AnimationStateData.c */; }; @@ -160,8 +160,8 @@ 652107951895250000B1FF07 /* CoreText.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreText.framework; path = System/Library/Frameworks/CoreText.framework; sourceTree = SDKROOT; }; 765A2EF41D7D7A08003FB779 /* goblins.atlas */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = goblins.atlas; path = Resources/goblins.atlas; sourceTree = ""; }; 765A2EF51D7D7A08003FB779 /* goblins.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = goblins.png; path = Resources/goblins.png; sourceTree = ""; }; - 76BF7E051E66ED9C00485998 /* TwoColorBatcher.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = TwoColorBatcher.c; path = src/spine/TwoColorBatcher.c; sourceTree = ""; }; - 76BF7E061E66ED9C00485998 /* TwoColorBatcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TwoColorBatcher.h; path = src/spine/TwoColorBatcher.h; sourceTree = ""; }; + 76BF7E051E66ED9C00485998 /* GLUtils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = GLUtils.c; path = src/spine/GLUtils.c; sourceTree = ""; }; + 76BF7E061E66ED9C00485998 /* GLUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GLUtils.h; path = src/spine/GLUtils.h; sourceTree = ""; }; 76F28CF41DEC810200CDE54D /* Animation.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Animation.c; path = "../spine-c/spine-c/src/spine/Animation.c"; sourceTree = ""; }; 76F28CF51DEC810300CDE54D /* AnimationState.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = AnimationState.c; path = "../spine-c/spine-c/src/spine/AnimationState.c"; sourceTree = ""; }; 76F28CF61DEC810300CDE54D /* AnimationStateData.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = AnimationStateData.c; path = "../spine-c/spine-c/src/spine/AnimationStateData.c"; sourceTree = ""; }; @@ -329,8 +329,8 @@ 43F7FF861927F94800CA4038 /* SkeletonRenderer.m */, 43C3282E170B0C19004A9460 /* spine-cocos2d-objc.h */, 43C3282D170B0C19004A9460 /* spine-cocos2d-objc.m */, - 76BF7E051E66ED9C00485998 /* TwoColorBatcher.c */, - 76BF7E061E66ED9C00485998 /* TwoColorBatcher.h */, + 76BF7E051E66ED9C00485998 /* GLUtils.c */, + 76BF7E061E66ED9C00485998 /* GLUtils.h */, ); name = "spine-cocos2d-objc"; sourceTree = ""; @@ -562,7 +562,7 @@ 76F28D171DEC810300CDE54D /* AnimationState.c in Sources */, 76F28D221DEC810300CDE54D /* extension.c in Sources */, 76F28D231DEC810300CDE54D /* IkConstraint.c in Sources */, - 76BF7E071E66ED9C00485998 /* TwoColorBatcher.c in Sources */, + 76BF7E071E66ED9C00485998 /* GLUtils.c in Sources */, 43C3282F170B0C19004A9460 /* spine-cocos2d-objc.m in Sources */, 76F28D1F1DEC810300CDE54D /* BoundingBoxAttachment.c in Sources */, 76F28D281DEC810300CDE54D /* PathConstraint.c in Sources */, diff --git a/spine-cocos2d-objc/src/spine/TwoColorBatcher.c b/spine-cocos2d-objc/src/spine/GLUtils.c similarity index 72% rename from spine-cocos2d-objc/src/spine/TwoColorBatcher.c rename to spine-cocos2d-objc/src/spine/GLUtils.c index 31574d6f0..b6ad4abd2 100644 --- a/spine-cocos2d-objc/src/spine/TwoColorBatcher.c +++ b/spine-cocos2d-objc/src/spine/GLUtils.c @@ -28,7 +28,7 @@ * POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -#include "TwoColorBatcher.h" +#include "GLUtils.h" #include @@ -52,6 +52,8 @@ attribute vec4 a_position; attribute vec4 a_color; attribute vec4 a_color2; attribute vec2 a_texCoords; + +uniform mat4 transform; \n#ifdef GL_ES\n varying lowp vec4 v_light; @@ -68,7 +70,7 @@ void main() { v_light = a_color; v_dark = a_color2; v_texCoord = a_texCoords; - gl_Position = CC_PMatrix * a_position; + gl_Position = transform * a_position; } ); @@ -76,19 +78,62 @@ const char* TWO_COLOR_TINT_FRAGMENT_SHADER = STRINGIFY( \n#ifdef GL_ES\n precision lowp float; \n#endif\n + +uniform sampler2D texture; varying vec4 v_light; varying vec4 v_dark; varying vec2 v_texCoord; void main() { - vec4 texColor = texture2D(CC_Texture0, v_texCoord); + vec4 texColor = texture2D(texture, v_texCoord); float alpha = texColor.a * v_light.a; gl_FragColor.a = alpha; gl_FragColor.rgb = (1.0 - texColor.rgb) * v_dark.rgb * alpha + texColor.rgb * v_light.rgb; } ); +spMesh* spMesh_create(uint32_t numVertices, uint32_t numIndices) { + spMesh* mesh = MALLOC(spMesh, 1); + mesh->vertices = MALLOC(spVertex, numVertices); + mesh->indices = MALLOC(unsigned short, numIndices); + mesh->numVertices = numVertices; + mesh->numIndices = numIndices; + mesh->numAllocatedVertices = 0; + mesh->numAllocatedIndices = 0; + return mesh; +} + +void spMesh_allocatePart(spMesh* mesh, spMeshPart* part, uint32_t numVertices, uint32_t numIndices, uint32_t textureHandle, uint32_t srcBlend, uint32_t dstBlend) { + if (mesh->numVertices < mesh->numAllocatedVertices + numVertices) { + mesh->numVertices = mesh->numAllocatedVertices + numVertices; + mesh->vertices = REALLOC(mesh->vertices, spVertex, mesh->numVertices); + } + if (mesh->numIndices < mesh->numAllocatedIndices + numIndices) { + mesh->numIndices = mesh->numAllocatedIndices + numIndices; + mesh->indices = REALLOC(mesh->indices, unsigned short, mesh->numIndices); + } + + part->mesh = mesh; + part->startVertex = mesh->numAllocatedVertices; + part->numIndices = numIndices; + part->startIndex = mesh->numAllocatedIndices; + part->numVertices = numVertices; + mesh->numAllocatedVertices += numVertices; + mesh->numAllocatedIndices += numIndices; +} + +void spMesh_clearParts(spMesh* mesh) { + mesh->numAllocatedIndices = 0; + mesh->numAllocatedVertices = 0; +} + +void spMesh_dispose(spMesh* mesh) { + FREE(mesh->vertices); + FREE(mesh->indices); + FREE(mesh); +} + GLuint compileShader(GLenum shaderType, const char* shaderSource) { GLuint shader = glCreateShader(shaderType); glShaderSource(shader, 1, &shaderSource, 0); @@ -134,7 +179,14 @@ spShader* spShader_create(const char* vertexShaderSource, const char* fragmentSh return shader; } -spTwoColorBatcher* _spTwoColorBatcher_create() { +void spShader_dispose(spShader* shader) { + glDeleteProgram(shader->program); + glDeleteShader(shader->vertexShader); + glDeleteShader(shader->fragmentShader); + FREE(shader); +} + +spTwoColorBatcher* spTwoColorBatcher_create() { spTwoColorBatcher* batcher = MALLOC(spTwoColorBatcher, 1); batcher->shader = spShader_create(TWO_COLOR_TINT_VERTEX_SHADER, TWO_COLOR_TINT_FRAGMENT_SHADER); @@ -152,19 +204,16 @@ spTwoColorBatcher* _spTwoColorBatcher_create() { return batcher; } -void _spTwoColorBatcher_add(spTwoColorBatcher* batcher, spVertex* triangles, unsigned short* indices, uint32_t textureHandle, uint32_t srcBlend, uint32_t dstBlend) { +void spTwoColorBatcher_add(spTwoColorBatcher* batcher, spMeshPart* mesh) { } -void _spTwoColorBatcher_flush(spTwoColorBatcher* batcher) { +void spTwoColorBatcher_flush(spTwoColorBatcher* batcher) { } -void _spDisposeTwoColorBatcher(spTwoColorBatcher* batcher) { - glDeleteProgram(batcher->shader->program); - glDeleteShader(batcher->shader->vertexShader); - glDeleteShader(batcher->shader->fragmentShader); - FREE(batcher->shader); +void spDisposeTwoColorBatcher(spTwoColorBatcher* batcher) { + spShader_dispose(batcher->shader); glDeleteBuffers(1, &batcher->vertexBufferHandle); FREE(batcher->verticesBuffer); glDeleteBuffers(1, &batcher->indexBufferHandle); diff --git a/spine-cocos2d-objc/src/spine/TwoColorBatcher.h b/spine-cocos2d-objc/src/spine/GLUtils.h similarity index 68% rename from spine-cocos2d-objc/src/spine/TwoColorBatcher.h rename to spine-cocos2d-objc/src/spine/GLUtils.h index 44e0f48fd..f13ff4595 100644 --- a/spine-cocos2d-objc/src/spine/TwoColorBatcher.h +++ b/spine-cocos2d-objc/src/spine/GLUtils.h @@ -28,8 +28,8 @@ * POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -#ifndef TwoColorBatcher_h -#define TwoColorBatcher_h +#ifndef GLUtils_h +#define GLUtils_h #include @@ -40,12 +40,40 @@ typedef struct spVertex { float u, v; } spVertex; +typedef struct spMesh { + spVertex* vertices; + uint32_t numVertices; + uint32_t numAllocatedVertices; + unsigned short* indices; + uint32_t numIndices; + uint32_t numAllocatedIndices; +} spMesh; + +typedef struct spMeshPart { + spMesh* mesh; + uint32_t startVertex; + uint32_t numVertices; + uint32_t startIndex; + uint32_t numIndices; + uint32_t textureHandle; + uint32_t srcBlend; + uint32_t dstBlend; +} spMeshPart; + +spMesh* spMesh_create(uint32_t numVertices, uint32_t numIndices); +void spMesh_allocatePart(spMesh* mesh, spMeshPart* part, uint32_t numVertices, uint32_t numIndices, uint32_t textureHandle, uint32_t srcBlend, uint32_t dstBlend); +void spMesh_clearParts(spMesh* mesh); +void spMesh_dispose(spMesh* mesh); + typedef struct spShader { uint32_t program; uint32_t vertexShader; uint32_t fragmentShader; } spShader; +spShader* spShader_create(const char* vertexShaderSource, const char* fragmentShaderSource); +void spShader_dispose(spShader* shader); + typedef struct spTwoColorBatcher { spShader* shader; @@ -63,9 +91,9 @@ typedef struct spTwoColorBatcher { int32_t texCoordsAttributeLocation; } spTwoColorBatcher; -spTwoColorBatcher* _spTwoColorBatcher_create(); -void _spTwoColorBatcher_add(spTwoColorBatcher* batcher, spVertex* triangles, unsigned short* indices, uint32_t textureHandle, uint32_t srcBlend, uint32_t dstBlend); -void _spTwoColorBatcher_flush(spTwoColorBatcher* batcher); -void _spDisposeTwoColorBatcher(spTwoColorBatcher* batcher); +spTwoColorBatcher* spTwoColorBatcher_create(); +void spTwoColorBatcher_add(spTwoColorBatcher* batcher, spMeshPart* meshPart); +void spTwoColorBatcher_flush(spTwoColorBatcher* batcher); +void spDisposeTwoColorBatcher(spTwoColorBatcher* batcher); -#endif /* TwoColorBatcher_h */ +#endif /* GLUtils_h */ diff --git a/spine-cocos2d-objc/src/spine/SkeletonRenderer.h b/spine-cocos2d-objc/src/spine/SkeletonRenderer.h index 1b4a1d1f4..097062a50 100644 --- a/spine-cocos2d-objc/src/spine/SkeletonRenderer.h +++ b/spine-cocos2d-objc/src/spine/SkeletonRenderer.h @@ -29,7 +29,6 @@ *****************************************************************************/ #import -#import "TwoColorBatcher.h" #import "cocos2d.h" /** Draws a skeleton. */ @@ -39,6 +38,7 @@ bool _debugSlots; bool _debugBones; bool _premultipliedAlpha; + bool _twoColorTint; bool _skipVisibilityCheck; ccBlendFunc _blendFunc; CCDrawNode* _drawNode; @@ -46,7 +46,6 @@ spAtlas* _atlas; float* _worldVertices; CCBlendMode* screenMode; - spTwoColorBatcher* batcher; } + (id) skeletonWithData:(spSkeletonData*)skeletonData ownsSkeletonData:(bool)ownsSkeletonData; @@ -85,6 +84,7 @@ - (bool) setAttachment:(NSString*)slotName attachmentName:(NSString*)attachmentName; @property (nonatomic, readonly) spSkeleton* skeleton; +@property (nonatomic) bool twoColorTint; @property (nonatomic) bool debugSlots; @property (nonatomic) bool debugBones; @property (nonatomic) bool skipVisibilityCheck; diff --git a/spine-cocos2d-objc/src/spine/SkeletonRenderer.m b/spine-cocos2d-objc/src/spine/SkeletonRenderer.m index c122fa96c..2c693566b 100644 --- a/spine-cocos2d-objc/src/spine/SkeletonRenderer.m +++ b/spine-cocos2d-objc/src/spine/SkeletonRenderer.m @@ -31,9 +31,12 @@ #import #import #import +#import #import "CCDrawNode.h" static const unsigned short quadTriangles[6] = {0, 1, 2, 2, 3, 0}; +static spTwoColorBatcher* batcher = 0; +static spMesh* mesh = 0; @interface SkeletonRenderer (Private) - (void) initialize:(spSkeletonData*)skeletonData ownsSkeletonData:(bool)ownsSkeletonData; @@ -43,6 +46,7 @@ static const unsigned short quadTriangles[6] = {0, 1, 2, 2, 3, 0}; @synthesize skeleton = _skeleton; @synthesize rootBone = _rootBone; +@synthesize twoColorTint = _twoColorTint; @synthesize debugSlots = _debugSlots; @synthesize debugBones = _debugBones; @@ -59,6 +63,14 @@ static const unsigned short quadTriangles[6] = {0, 1, 2, 2, 3, 0}; } - (void) initialize:(spSkeletonData*)skeletonData ownsSkeletonData:(bool)ownsSkeletonData { + if (!batcher) { + batcher = spTwoColorBatcher_create(); + mesh = spMesh_create(64000, 32000); + [[CCDirector sharedDirector] addFrameCompletionHandler: ^{ + printf ("frame completed"); + }]; + } + _ownsSkeletonData = ownsSkeletonData; _worldVertices = MALLOC(float, 1000); // Max number of vertices per mesh. @@ -154,6 +166,8 @@ static const unsigned short quadTriangles[6] = {0, 1, 2, 2, 3, 0}; _skeleton->color.a = self.displayedOpacity; int blendMode = -1; + uint32_t srcBlend = GL_SRC_ALPHA; + uint32_t dstBlend = GL_ONE_MINUS_SRC_ALPHA; const float* uvs = 0; int verticesCount = 0; const unsigned short* triangles = 0; @@ -200,15 +214,23 @@ static const unsigned short quadTriangles[6] = {0, 1, 2, 2, 3, 0}; switch (slot->data->blendMode) { case SP_BLEND_MODE_ADDITIVE: [self setBlendMode:[CCBlendMode addMode]]; + srcBlend = !_premultipliedAlpha ? GL_SRC_ALPHA : GL_ONE; + dstBlend = GL_ONE; break; case SP_BLEND_MODE_MULTIPLY: [self setBlendMode:[CCBlendMode multiplyMode]]; + srcBlend = GL_DST_COLOR; + dstBlend = GL_ONE_MINUS_SRC_ALPHA; break; case SP_BLEND_MODE_SCREEN: [self setBlendMode:screenMode]; + srcBlend = GL_ONE; + dstBlend = GL_ONE_MINUS_SRC_COLOR; break; default: [self setBlendMode:_premultipliedAlpha ? [CCBlendMode premultipliedAlphaMode] : [CCBlendMode alphaMode]]; + srcBlend = !_premultipliedAlpha ? GL_SRC_ALPHA : GL_ONE; + dstBlend = GL_ONE_MINUS_SRC_ALPHA; } } if (_premultipliedAlpha) { @@ -227,16 +249,25 @@ static const unsigned short quadTriangles[6] = {0, 1, 2, 2, 3, 0}; GLKVector2 center = GLKVector2Make(size.width / 2.0, size.height / 2.0); GLKVector2 extents = GLKVector2Make(size.width / 2.0, size.height / 2.0); if (_skipVisibilityCheck || CCRenderCheckVisbility(transform, center, extents)) { - CCRenderBuffer buffer = [renderer enqueueTriangles:(trianglesCount / 3) andVertexes:verticesCount withState:self.renderState globalSortOrder:0]; - for (int i = 0; i * 2 < verticesCount; ++i) { - CCVertex vertex; - vertex.position = GLKVector4Make(_worldVertices[i * 2], _worldVertices[i * 2 + 1], 0.0, 1.0); - vertex.color = GLKVector4Make(r, g, b, a); - vertex.texCoord1 = GLKVector2Make(uvs[i * 2], 1 - uvs[i * 2 + 1]); - CCRenderBufferSetVertex(buffer, i, CCVertexApplyTransform(vertex, transform)); - } - for (int j = 0; j * 3 < trianglesCount; ++j) { - CCRenderBufferSetTriangle(buffer, j, triangles[j * 3], triangles[j * 3 + 1], triangles[j * 3 + 2]); + if (!self.twoColorTint) { + CCRenderBuffer buffer = [renderer enqueueTriangles:(trianglesCount / 3) andVertexes:verticesCount withState:self.renderState globalSortOrder:0]; + for (int i = 0; i * 2 < verticesCount; ++i) { + CCVertex vertex; + vertex.position = GLKVector4Make(_worldVertices[i * 2], _worldVertices[i * 2 + 1], 0.0, 1.0); + vertex.color = GLKVector4Make(r, g, b, a); + vertex.texCoord1 = GLKVector2Make(uvs[i * 2], 1 - uvs[i * 2 + 1]); + CCRenderBufferSetVertex(buffer, i, CCVertexApplyTransform(vertex, transform)); + } + for (int j = 0; j * 3 < trianglesCount; ++j) { + CCRenderBufferSetTriangle(buffer, j, triangles[j * 3], triangles[j * 3 + 1], triangles[j * 3 + 2]); + } + } else { + spMeshPart meshPart; + spMesh_allocatePart(mesh, &meshPart, verticesCount / 2, trianglesCount, self.texture.name, srcBlend, dstBlend); + + [renderer enqueueBlock:^{ + + } globalSortOrder:0 debugLabel: nil threadSafe: false]; } } }