对openGLES的粗浅认识

本文详细介绍了如何在Cocos2d-X中利用自定义工厂类BYCircleTextureFactory生成圆形纹理的过程,包括创建渲染纹理、绘制多边形轮廓、填充颜色、混合纹理和噪点图片等步骤,旨在实现高效、美观的圆形纹理效果。

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  

转载于:https://www.cnblogs.com/pengyingh/articles/2517010.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值