对openGLES的粗浅认识

BYCircleTextureFactory.h

//
//  BYCircleTextureFactory.h
//  SuperBalance1.1
//
//  Created by Bruce Yang on 8/1/11.
//  Copyright 2011 Home. All rights reserved.
//

#import "cocos2d.h"
#import "GameConfig.h"
#import "CirclePointsGenerator.h"
#import "BYTextureDef.h"
#import "BYSingle.h"


@interface BYCircleTextureFactory : NSObject {
	
}

+ (CCTexture2D*) genCircleTexture:(BYTextureDef*)textureDef;

@end

BYCircleTextureFactory.mm

//
//  BYCircleTextureFactory.mm
//  SuperBalance1.1
//
//  Created by Bruce Yang on 8/1/11.
//  Copyright 2011 Home. All rights reserved.
//

#import "BYCircleTextureFactory.h"


@implementation BYCircleTextureFactory

/**
 * 绘制出圆角多边形的轮廓,在内部填充颜色
 */
+ (void) glesDraw:(CGPoint*)vertices colors:(ccColor4F*)colors arrayLen:(int)arrayLen {
	// 第一件事情就是禁用GL_TEXTURE_2D 和 GL_TEXTURE_COORD_ARRA两个opengl状态,
	// 因为,我们接下来只需要绘制颜色---这与纹理无关。
	glDisable(GL_TEXTURE_2D);
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	
	
	// 将顶点(x, y)数组和颜色(r, g, b, a)数组传给opengl
	glVertexPointer(2, GL_FLOAT, 0, vertices);
	glColorPointer(4, GL_FLOAT, 0, colors);
	glDrawArrays(GL_TRIANGLE_STRIP, 0, (GLsizei)arrayLen);
	
	
	// 最后,我们重新激活GL_TEXTURE_COORD_ARRAY 和 GL_TEXTURE_2D两个状态,
	// 这样做的话是保持和之前调用的对称,并且不会破坏opengl状态机。
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	glEnable(GL_TEXTURE_2D);	
}


/**
 * 绘制1个像素的多边形圆角边框
 */
+ (void) drawOnePixelBorder:(CGPoint*)outBorderVetices verticesCount:(int)outBorderVeticesCount {
    // openGL就是一个状态机,使用得时候该有的状态必须有,不需要的状态必须 disable 掉!!! 
	glDisable(GL_TEXTURE_2D);
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	glDisableClientState(GL_COLOR_ARRAY);
	
	glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
	glVertexPointer(2, GL_FLOAT, 0, outBorderVetices);
	glDrawArrays(GL_LINE_LOOP, 0, outBorderVeticesCount);
	
	glEnableClientState(GL_COLOR_ARRAY);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	glEnable(GL_TEXTURE_2D);	
}


/**
 * 去除图片文件的后缀
 */
+ (NSString*) fileNameWithoutSuffix:(NSString*)fullName {
	NSMutableString *mutableString = [NSMutableString stringWithCapacity:50];	// 接收一下
	[mutableString appendString:fullName];
	
	NSString *suffix = [mutableString pathExtension];	// 获取文件后缀名
	NSString *handledSuffix = [NSString stringWithFormat:@"%@%@", @".", suffix];	// 使后缀名带上前面那个点儿
	NSRange suffixRange = [mutableString rangeOfString:handledSuffix];
	[mutableString deleteCharactersInRange:suffixRange];
	return mutableString;
}


/**
 * 将纹理、噪点图片与目标形状相混合,形状内的部分保留,形状外的部分剔除
 */
+ (void) textureOrNoiseBlend:(NSString*)imgName circleSize:(CGSize)circleSize {
	if(imgName != nil) {
		CCSprite *textureOrNoise;
		if([BYSingle getInstance].isIpad == NO) {
			textureOrNoise = [CCSprite spriteWithFile:imgName];
			textureOrNoise.position = ccp(circleSize.width/2, circleSize.height/2);
		} else {
			textureOrNoise = [CCSprite spriteWithFile:[NSString stringWithFormat:@"%@-hd.png", [self fileNameWithoutSuffix:imgName]]];
			textureOrNoise.position = ccp(circleSize.width, circleSize.height);
		}
		
		[textureOrNoise setBlendFunc:(ccBlendFunc){GL_DST_COLOR, GL_ZERO}];
		[textureOrNoise visit];	
	}
}


/**
 * 将texture的尺寸扩大为原来的四倍(因为这里是静态类,因此需将+改为-)~
 */
+ (CGPoint*) convert2RetinaSize:(CGPoint*)vertices verticesCount:(int)verticesCount {
	CGPoint *target = new CGPoint[verticesCount];
	for(int i = 0; i < verticesCount; i ++) {
		target[i] = ccpMult(vertices[i], 2.0f);
	}
	return target;
}


/**
 * 生成带边框的圆形纹理~
 */
+ (CCTexture2D*) genCircleTexture:(BYTextureDef*)textureDef {
	
	// 1: Create new CCRenderTexture
	CGPoint sizePoint = textureDef.polygonVertexs[0];
	CGSize circleSize = CGSizeMake(sizePoint.x, sizePoint.y);
	CCRenderTexture *rt;
	if([BYSingle getInstance].isIpad == NO) {
		rt = [CCRenderTexture renderTextureWithWidth:circleSize.width height:circleSize.width];		
	} else {
		rt = [CCRenderTexture renderTextureWithWidth:circleSize.width*2 height:circleSize.width*2];
	}
	
    // 颜色为黑色(白色等其他颜色亦可,因为不透明度为0)
	ccColor4F bgColor1 = (ccColor4F){0.95f, 1.0f, 0.33f, 0.0f};
	
	// 就因为没有加上下面这句代码,害我足足找了两天,记住曝出的错误:OpenGL error 0x0504 in -[EAGLView swapBuffers]
	// 疯了,在网上查了下,说是什么 “堆栈下溢”,原来指的就是没有给 纹理打上底色??!
	[rt beginWithClear:bgColor1.r g:bgColor1.g b:bgColor1.b a:bgColor1.a];
	
	
	CGPoint *finalResult = [CirclePointsGenerator genCirclePoints:circleSize];
	
	
	// 多边形的顶点数~
	int circleVertexCount = CIRCLE_SEGEMENTS_COUNT;
	
	// opengles绘制多边形边框总共的顶点数~
	int borderTotalCount = circleVertexCount * 2 + 2;
	CGPoint borderVertexs[borderTotalCount];
	ccColor4F borderColors[borderTotalCount];
	
	// 又有新的需求,不需要渐变边框,只需要圆角+1px的外框
	int outBorderVeticesCount = CIRCLE_SEGEMENTS_COUNT + 1;
	CGPoint outBorderVetices[outBorderVeticesCount];
	
	
	// ************************* 对4代做修正~ *********************************
	if([BYSingle getInstance].isRetinaSupported) {
		finalResult = [self convert2RetinaSize:finalResult verticesCount:borderTotalCount];
	}
	if([BYSingle getInstance].isIpad == YES) {
		finalResult = [self convert2RetinaSize:finalResult verticesCount:borderTotalCount];
	}
	// ************************* 对4代做修正~ *********************************
	
	
	int k = 0;
	for(int i = 0; i < borderTotalCount; i ++) {
		borderVertexs[i] = finalResult[i];
		borderColors[i] = (ccColor4F){1.0f, 1.0f, 1.0f, 1.0f};
		if(i%2 == 0) {
			outBorderVetices[k] = finalResult[i];
			k += 1;
		}
	}
	outBorderVetices[k] = outBorderVetices[0];
	
	// --------------------------------- 蛋疼的分割线 ---------------------------------
	
	// opengles绘制多边形内容物总共的顶点数~
	int contentTotalCount;
	if(circleVertexCount%2 == 1) {
		// 如果是顶点数为奇数的多边形
		contentTotalCount = 3 + (circleVertexCount-3)/2*3;
	} else {
		// 如果是顶点数为偶数的多边形
		contentTotalCount = 5 + (circleVertexCount-4)/2*3;
	}
	CGPoint originalContentVertexs[circleVertexCount];
	CGPoint contentVertexs[contentTotalCount];
	ccColor4F contentColors[contentTotalCount];
	
	for(int i = 0; i < circleVertexCount; i ++) {
		originalContentVertexs[i] = finalResult[i * 2 + 1];
	}
	
	// 内部3角形的颜色,需一致设置为不透明度为1.0f的白色,便于与纹理图片 blend 获得纹理~
	ccColor4F contentColor = (ccColor4F){1.0f, 1.0f, 1.0f, 1.0f};
	
	int j = 1;
	for(int i = 0; i < contentTotalCount; i ++) {
		if(i%3 == 0) {
			contentVertexs[i] = originalContentVertexs[0];
		} else {
			contentVertexs[i] = originalContentVertexs[j];
			j = j + 1;
		}
		contentColors[i] = contentColor;
	}
	
	// 释放内存,避免野指针的存在(使用完毕之后立即回收在堆上new出来的内存)~
	delete finalResult;
	
	
	// 4: Draw into the texture
	// 一。首先以纯白填充多边形内容物,为绘制纹理和噪点做准备
	[self glesDraw:contentVertexs colors:contentColors arrayLen:contentTotalCount];
	
	
	// 二。绘制多边形边框
	[self glesDraw:borderVertexs colors:borderColors arrayLen:borderTotalCount];	
	
	// 三。混合木质纹理~
	[self textureOrNoiseBlend:textureDef.textureImgName circleSize:circleSize];
	
	
	// 四。混合噪点图片~
	[self textureOrNoiseBlend:textureDef.noiseImgName circleSize:circleSize];
	
    // 五。绘制1个像素宽度的外部边框~
//	[self drawOnePixelBorder:outBorderVetices verticesCount:outBorderVeticesCount];
	
	
	// 至此 textureDef 所占据的堆内存可以释放掉了!!
	// 搞死哥了,哥在后面又用到过这个东西,结果总是曝出 EXC_BAD_ACCESS
	// 不过虽然 delete 掉了 textureDef,但奇怪的是,有时候依然还是能够访问到多边形顶点数组的数据~
	delete textureDef;

	
	// 5: Call CCRenderTexture:end
	[rt end];
	
    // 6: Create a new Sprite from the texture
    return rt.sprite.texture;
}

@end


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值