Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
A category for Sparrow that allows erasing of a SPRenderTexture.
//
// SPRenderTexture+Erase.h
// Sparrow
//
// Created by Shilo White on 11/10/11.
// Copyright (c) 2011 Shilocity Productions. All rights reserved.
//
#import "SPRenderTexture.h"
@class SPDisplayObject;
@class SPRectangle;
@interface SPRenderTexture (Erase)
- (void)eraseWithObject:(SPDisplayObject *)object;
- (void)eraseWithRectangle:(SPRectangle *)rectangle;
- (void)eraseWithEllipseInRectangle:(SPRectangle *)rectangle;
- (void)eraseWithDrawingBlock:(SPDrawingBlock)block;
- (float)averagePixelAlphaForRectangle:(SPRectangle *)rectangle;
@end
//
// SPRenderTexture+Erase.m
// Sparrow
//
// Created by Shilo White on 11/10/11.
// Copyright (c) 2011 Shilocity Productions. All rights reserved.
//
#import "SPRenderTexture+Erase.h"
#import "SPDisplayObject.h"
#import "SPRectangle.h"
#import "SPImage.h"
#import "SPRenderSupport.h"
#import "SPMacros.h"
@interface SPRenderTexture (Methods)
- (void)renderToFramebuffer:(SPDrawingBlock)block;
@end
@interface SPImage (Erase)
- (void)renderAsEraser:(SPRenderSupport *)support;
@end
@implementation SPImage (Erase)
- (void)renderAsEraser:(SPRenderSupport *)support {
static float texCoords[8];
static uint colors[4];
float alpha = self.alpha;
[support bindTexture:mTexture];
[mTexture adjustTextureCoordinates:mTexCoords saveAtTarget:texCoords numVertices:4];
for (int i=0; i<4; ++i)
colors[i] = [support convertColor:mVertexColors[i] alpha:alpha];
SPRectangle *frame = mTexture.frame;
if (frame) {
glTranslatef(-frame.x, -frame.y, 0.0f);
glScalef(mTexture.width / frame.width, mTexture.height / frame.height, 1.0f);
}
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
glVertexPointer(2, GL_FLOAT, 0, mVertexCoords);
glColorPointer(4, GL_UNSIGNED_BYTE, 0, colors);
glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
}
@end
@implementation SPRenderTexture (Erase)
- (void)eraseWithObject:(SPDisplayObject *)object {
[self renderToFramebuffer:^
{
BOOL isImage = [object isKindOfClass:[SPImage class]];
if (!isImage) glDisable(GL_BLEND);
glPushMatrix();
[SPRenderSupport transformMatrixForObject:object];
if (isImage) {
[(SPImage *)object renderAsEraser:mRenderSupport];
} else {
float curAlpha = object.alpha;
object.alpha = 0;
[object render:mRenderSupport];
object.alpha = curAlpha;
}
glPopMatrix();
if (!isImage) glEnable(GL_BLEND);
}];
}
- (void)eraseWithRectangle:(SPRectangle *)rectangle {
[self renderToFramebuffer:^
{
glDisable(GL_BLEND);
glPushMatrix();
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, (GLfloat[8]){0.0f, 0.0f, rectangle.width, 0.0f, 0.0f, rectangle.height, rectangle.width, rectangle.height});
glColorPointer(4, GL_UNSIGNED_BYTE, 0, (GLuint[4]){0x0, 0x0, 0x0, 0x0});
glTranslatef(rectangle.x, rectangle.y, 0.0f);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glPopMatrix();
glEnable(GL_BLEND);
}];
}
- (void)eraseWithEllipseInRectangle:(SPRectangle *)rectangle {
[self renderToFramebuffer:^
{
GLfloat vertices[724];
GLuint colors[362];
GLfloat widthRadius = rectangle.width/2;
GLfloat heightRadius = rectangle.height/2;
vertices[0] = widthRadius;
vertices[1] = heightRadius;
colors[0] = colors[361] = 0x0;
for (int i=0; i<360*2+1; i+=2) {
vertices[i+2] = cos(SP_D2R(i/2)) * widthRadius + widthRadius;
vertices[i+3] = sin(SP_D2R(i/2)) * heightRadius + heightRadius;
if (i<361 && i>1) colors[i] = colors[i-1] = 0x0;
}
glDisable(GL_BLEND);
glPushMatrix();
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, vertices);
glColorPointer(4, GL_UNSIGNED_BYTE, 0, colors);
glTranslatef(rectangle.x, rectangle.y, 0.0f);
glDrawArrays(GL_TRIANGLE_FAN, 0, 362);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glPopMatrix();
glEnable(GL_BLEND);
}];
}
- (void)eraseWithDrawingBlock:(SPDrawingBlock)block {
[self renderToFramebuffer:^
{
glDisable(GL_BLEND);
glPushMatrix();
block();
glPopMatrix();
glEnable(GL_BLEND);
}];
}
- (float)averagePixelAlphaForRectangle:(SPRectangle *)rectangle {
__block float averageAlpha = 0;
[self renderToFramebuffer:^
{
int pixelCount = rectangle.width*rectangle.height;
int bufferLength = pixelCount*4;
unsigned char buffer[bufferLength];
int totalAlpha = 0;
glReadPixels(rectangle.x, rectangle.y, rectangle.width, rectangle.height, GL_RGBA, GL_UNSIGNED_BYTE, &buffer);
for (int i=3; i<bufferLength; i+=4) {
totalAlpha += buffer[i];
}
averageAlpha = (totalAlpha/pixelCount)/255.0f;
}];
return averageAlpha;
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.