[cocos2d-objc] More two color tinting work.

This commit is contained in:
badlogic 2017-03-14 13:14:23 +01:00
parent cc9fdf3f1f
commit 3ed9290c6f
7 changed files with 149 additions and 36 deletions

View File

@ -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));

View File

@ -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);
}

View File

@ -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 = "<group>"; };
765A2EF51D7D7A08003FB779 /* goblins.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = goblins.png; path = Resources/goblins.png; sourceTree = "<group>"; };
76BF7E051E66ED9C00485998 /* TwoColorBatcher.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = TwoColorBatcher.c; path = src/spine/TwoColorBatcher.c; sourceTree = "<group>"; };
76BF7E061E66ED9C00485998 /* TwoColorBatcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TwoColorBatcher.h; path = src/spine/TwoColorBatcher.h; sourceTree = "<group>"; };
76BF7E051E66ED9C00485998 /* GLUtils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = GLUtils.c; path = src/spine/GLUtils.c; sourceTree = "<group>"; };
76BF7E061E66ED9C00485998 /* GLUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GLUtils.h; path = src/spine/GLUtils.h; sourceTree = "<group>"; };
76F28CF41DEC810200CDE54D /* Animation.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Animation.c; path = "../spine-c/spine-c/src/spine/Animation.c"; sourceTree = "<group>"; };
76F28CF51DEC810300CDE54D /* AnimationState.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = AnimationState.c; path = "../spine-c/spine-c/src/spine/AnimationState.c"; sourceTree = "<group>"; };
76F28CF61DEC810300CDE54D /* AnimationStateData.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = AnimationStateData.c; path = "../spine-c/spine-c/src/spine/AnimationStateData.c"; sourceTree = "<group>"; };
@ -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 = "<group>";
@ -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 */,

View File

@ -28,7 +28,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#include "TwoColorBatcher.h"
#include "GLUtils.h"
#include <spine/extension.h>
@ -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);

View File

@ -28,8 +28,8 @@
* POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef TwoColorBatcher_h
#define TwoColorBatcher_h
#ifndef GLUtils_h
#define GLUtils_h
#include <stdint.h>
@ -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 */

View File

@ -29,7 +29,6 @@
*****************************************************************************/
#import <spine/spine.h>
#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;

View File

@ -31,9 +31,12 @@
#import <spine/SkeletonRenderer.h>
#import <spine/spine-cocos2d-objc.h>
#import <spine/extension.h>
#import <spine/GLUtils.h>
#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];
}
}
}