我在SKTexture上写了一个渐变生成函数作为类别。它在1x屏幕上运行良好,但视网膜使纹理太大,双倍宽度和双倍高度,即错误的比例。我一直试图通过在像素和点之间进行切换来做到正确,但无法做到正确。有人能帮帮我吗?
+(SKTexture*)gradientWithSize:(const CGSize)SIZE colors:(NSArray*)colors {
// Hopefully this function would be platform independent one day.
// Correct way to find scale?
DLog(@"backingScaleFactor: %f", [[NSScreen mainScreen] backingScaleFactor]);
const CGFloat SCALE = [[NSScreen mainScreen] backingScaleFactor];
//const size_t WIDTH_PIXELS = SIZE.width * SCALE;
//const size_t HEIGHT_PIXELS = SIZE.height * SCALE;
CGContextRef cgcontextref = MyCreateBitmapContext(SIZE.width, SIZE.height, SCALE);
NSAssert(cgcontextref != NULL, @"Failed creating context!");
// CGBitmapContextCreate(
// NULL, // let the OS handle the memory
// WIDTH_PIXELS,
// HEIGHT_PIXELS,
CAGradientLayer* gradient = CAGradientLayer.layer;
//gradient.contentsScale = SCALE;
gradient.frame = CGRectMake(0, 0, SIZE.width, SIZE.height);
NSMutableArray* convertedcolors = [NSMutableArray array];
for (SKColor* skcolor in colors) {
[convertedcolors addObject:(id)skcolor.CGColor];
}
gradient.colors = convertedcolors;
[gradient renderInContext:cgcontextref];
CGImageRef imageref = CGBitmapContextCreateImage(cgcontextref);
DLog(@"imageref pixel size: %zu %zu", CGImageGetWidth(imageref), CGImageGetHeight(imageref));
SKTexture* texture1 = [SKTexture textureWithCGImage:imageref];
DLog(@"size of gradient texture: %@", NSStringFromSize(texture1.size));
CGImageRelease(imageref);
CGContextRelease(cgcontextref);
return texture1;
}
CGContextRef MyCreateBitmapContext(const size_t POINTS_W, const size_t POINTS_H, const CGFloat SCALE) {
CGContextRef context = NULL;
CGColorSpaceRef colorSpace;
void * bitmapData;
//int bitmapByteCount;
size_t bitmapBytesPerRow;
const size_t PIXELS_W = POINTS_W * SCALE;
const size_t PIXELS_H = POINTS_H * SCALE;
bitmapBytesPerRow = (PIXELS_W * 4);// 1
//bitmapByteCount = (bitmapBytesPerRow * pixelsHigh);
colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);// 2
bitmapData = NULL;
#define kBitmapInfo kCGImageAlphaPremultipliedLast
//#define kBitmapInfo kCGImageAlphaPremultipliedFirst
//#define kBitmapInfo kCGImageAlphaNoneSkipFirst
// According to http://stackoverflow.com/a/18921840/129202 it should be safe to just cast
CGBitmapInfo bitmapinfo = (CGBitmapInfo)kBitmapInfo; //kCGImageAlphaNoneSkipFirst; //0; //kCGBitmapAlphaInfoMask; //kCGImageAlphaNone; //kCGImageAlphaNoneSkipFirst;
context = CGBitmapContextCreate (bitmapData,// 4
PIXELS_W,
PIXELS_H,
8, // bits per component
bitmapBytesPerRow,
colorSpace,
bitmapinfo
);
if (context == NULL) {
free (bitmapData);// 5
fprintf (stderr, "Context not created!");
return NULL;
}
CGColorSpaceRelease( colorSpace );// 6
// TEST!!
// CGContextClipToRect(context, CGRectMake(0, 0, POINTS_W, POINTS_H));
CGContextClipToRect(context, CGRectMake(0, 0, PIXELS_W, PIXELS_H));
CGContextScaleCTM(context, SCALE, SCALE);
return context;// 7
}
所以,总而言之,我希望使用SIZE点来调用+(SKTexture*)gradientWithSize:(const CGSize)SIZE colors:(NSArray*)colors
。
答案 0 :(得分:0)
根据LearnCocos2D的建议更新了以下代码。何时缩放而不是令人困惑(因为在文档中,CGBitmapContextCreate
明确地采用 PIXELS 中的宽度和高度),但这似乎也在视网膜屏幕上具有正确的大小。我仍然不知道渲染的分辨率是否真的是视网膜 - 但这很难用眼睛确认,因为毕竟这是一个渐变......我仍在使用相同的上下文创建纹理转发器的功能(启用使用colorWithPatternImage with Sprite Kit)。也许我以后有时间尝试使用这个新版本重复的详细纹理......
同时打开或关闭gradient.contentsScale = SCALE;
也不会产生明显的差异。
+(SKTexture*)gradientWithSize:(const CGSize)SIZE colors:(NSArray*)colors {
// Hopefully this function would be platform independent one day.
CGContextRef cgcontextref = MyCreateBitmapContext(SIZE.width, SIZE.height);
NSAssert(cgcontextref != NULL, @"Failed creating context!");
CAGradientLayer* gradient = CAGradientLayer.layer;
DLog(@"gradient.contentScale: %f", gradient.contentsScale);
//gradient.contentsScale = SCALE;
DLog(@"gradient.contentScale: %f", gradient.contentsScale);
gradient.frame = CGRectMake(0, 0, SIZE.width, SIZE.height);
NSMutableArray* convertedcolors = [NSMutableArray array];
for (SKColor* skcolor in colors) {
[convertedcolors addObject:(id)skcolor.CGColor];
}
gradient.colors = convertedcolors;
[gradient renderInContext:cgcontextref];
CGImageRef imageref = CGBitmapContextCreateImage(cgcontextref);
DLog(@"imageref pixel size: %zu %zu", CGImageGetWidth(imageref), CGImageGetHeight(imageref));
SKTexture* texture1 = [SKTexture textureWithCGImage:imageref];
DLog(@"size of gradient texture: %@", NSStringFromSize(texture1.size));
CGImageRelease(imageref);
CGContextRelease(cgcontextref);
return texture1;
}
CGContextRef MyCreateBitmapContext(const size_t POINTS_W, const size_t POINTS_H/*, const CGFloat SCALE*/) {
CGContextRef context = NULL;
CGColorSpaceRef colorSpace;
void * bitmapData;
size_t bitmapBytesPerRow;
bitmapBytesPerRow = (POINTS_W * 4);
colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
bitmapData = NULL;
#define kBitmapInfo kCGImageAlphaPremultipliedLast
// According to https://stackoverflow.com/a/18921840/129202 it should be safe to just cast
CGBitmapInfo bitmapinfo = (CGBitmapInfo)kBitmapInfo;
context = CGBitmapContextCreate (bitmapData,
POINTS_W,
POINTS_H,
8,
bitmapBytesPerRow,
colorSpace,
bitmapinfo
);
if (context == NULL) {
free (bitmapData);
fprintf (stderr, "Context not created!");
return NULL;
}
CGColorSpaceRelease(colorSpace);
return context;
}
以下结果。左边只是一个使用SKSpriteNode创建的黄色矩形。右边是使用从上面的函数生成的纹理创建的矩形。两个矩形位于相同的位置,并且具有相同的点大小,只是不同的anchorPoints。
SKColor* color1 = SKColor.blueColor;
SKColor* color2 = [SKColor colorWithCalibratedRed:1 green:0 blue:0 alpha:0.5];
SKTexture* textureGradient = [SKTexture gradientWithSize:SIZE colors:@[color1, color2]];
SKSpriteNode* spriteGradient = [SKSpriteNode spriteNodeWithTexture:textureGradient];
1x分辨率
2x分辨率(视网膜)