一般来说,绘图目前有两种方式,一种是Quartz绘图,另一种就是强大的OpenGL绘图了.
昨天刚和老师敲定 毕设题目:"使用OpenGL 实现巷道的设计与实现".哎,真的很巧.不过我今天练习了这个项目之后,我终于明白了,这个OpenGL 可真是复杂啊.
好了,闲话先到这,我们就从Quartz绘图到OpenGL绘图吧.
1.OpenGL ES 绘图很大部分都是上节的文件,除了我们的绘图文件 替换成了 BIDGLFunView.相应的,我们也需要把我们 的view所控制的类改为这个.同时,我们也导入了四个关于OpenGL ES 的API.
OpenGLES2DView
和Texture2D.
2.下面是我们定义的BIDGLFunView 的绘图类,通过这个类,我们基本就明白了OpenGL的复杂了.
首先是.h文件,多声明了一个属性.
@property(nonatomic,strong)Texture2D *sprite;这个属性主要是定义Image的.在viewdidload中就会发现.
#import "OpenGLES2DView.h"
#import "BIDCOstants.h"
@class Texture2D;
@interface BIDGLFunView : OpenGLES2DView
@property CGPoint firstTouch;
@property CGPoint lastTouch;
@property (nonatomic,strong)UIColor *currentColor;
@property BOOL useRandomColor;
@property ShapeType shapeType;
@property(nonatomic,strong)Texture2D *sprite;
@end
下面看看.m文件
我们引入了API,然后看到了sprite的初始化了么 ?
#import "BIDGLFunView.h"
#import "Texture2D.h"
#import "UIColor+BIDRandom.h"
@implementation BIDGLFunView
@synthesize lastTouch,firstTouch,currentColor,useRandomColor,shapeType,sprite;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
//firstTouch.x = 0;
// Initialization code
}
return self;
}
-(id)initWithCoder:(NSCoder *)aDecoder
{
if (self = [super initWithCoder:aDecoder]) {
self.currentColor = [UIColor redColor];
useRandomColor = NO;
sprite = [[Texture2D alloc]initWithImage:[UIImage imageNamed:@"screen.png"]];
glBindTexture(GL_TEXTURE_2D, sprite.name);
//http://blog.csdn.net/houdy/article/details/125234
}
return self;
}
Texture Object的主要思想是用Texture Object来维护某些纹理状态,在渲染阶段将Texture Object和某个Texture Target(OpenGL维护三个Texture Target:GL_TEXTURE_1D,GL_TEXTURE_2D,GL_TEXTURE_3D)绑定,此过程就相当于将此Texture Object维护的纹理状态选入到OpenGL状态机中,这样此Texture Object维护的状态才会起作用。
Texture Object维护的某些纹理状态包括:
Texture image(s); //纹理图案
Texture Parameter; //由glTexParameter*()函数控制的参数
注意:其他的纹理相关的状态,如Texture Environment和Texture coordinate generation mode并不包含在Texture Objects中。
每个Texture Object的标识符是用一个unsigned int值来表示的,为了确保每个Texture Object的“名字“是唯一的,OpenGL提供了glGenTexture()函数。每个Texture Object在创建的时候,需要调用glBindTexture()将Texture Object和Texture Target(GL_TEXTURE_1D, GL_TEXTURE_2D)连接起来,在使用Texture Object阶段,仍然需要调用glBindTexture()来"激活"此Texture Object.下面用代码演示如何使用Texture Object:
1.创建一个Texture Object:
GLuint uiTextureID;
glGenTexture( 1, &uiTextureID ); //第一个参数指定表明获取多少个连续的纹理标识符
glBindTexture( GL_TEXTURE_2D, uiTextureID ); //
完整的链接已经放在代码里了,你可以点击查看.
3.下面就主要看看draw方法,就了解了两种绘图方法的区别之大了.
- (void)draw {
glLoadIdentity();
glClearColor(0.78f, 0.78f, 0.78f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
CGColorRef color = currentColor.CGColor;
const CGFloat *components = CGColorGetComponents(color);
CGFloat red = components[0];
CGFloat green = components[1];
CGFloat blue = components[2];
glColor4f(red,green, blue, 1.0);
switch (shapeType) {
case kLineShape: {
glDisable(GL_TEXTURE_2D);
GLfloat vertices[4];
// Convert coordinates
vertices[0] = firstTouch.x;
vertices[1] = self.frame.size.height - firstTouch.y;
vertices[2] = lastTouch.x;
vertices[3] = self.frame.size.height - lastTouch.y;
glLineWidth(2.0);
glVertexPointer(2, GL_FLOAT, 0, vertices);
glDrawArrays (GL_LINES, 0, 2);
break;
}
case kRectShape: {
glDisable(GL_TEXTURE_2D);
// Calculate bounding rect and store in vertices
GLfloat vertices[8];
GLfloat minX = (firstTouch.x > lastTouch.x) ?
lastTouch.x : firstTouch.x;
GLfloat minY = (self.frame.size.height - firstTouch.y >
self.frame.size.height - lastTouch.y) ?
self.frame.size.height - lastTouch.y :
self.frame.size.height - firstTouch.y;
GLfloat maxX = (firstTouch.x > lastTouch.x) ?
firstTouch.x : lastTouch.x;
GLfloat maxY = (self.frame.size.height - firstTouch.y >
self.frame.size.height - lastTouch.y) ?
self.frame.size.height - firstTouch.y :
self.frame.size.height - lastTouch.y;
vertices[0] = maxX;
vertices[1] = maxY;
vertices[2] = minX;
vertices[3] = maxY;
vertices[4] = minX;
vertices[5] = minY;
vertices[6] = maxX;
vertices[7] = minY;
glVertexPointer (2, GL_FLOAT , 0, vertices);
glDrawArrays (GL_TRIANGLE_FAN, 0, 4);
break;
}
case kEllipseShape: {
glDisable(GL_TEXTURE_2D);
GLfloat vertices[720];
GLfloat xradius = fabsf((firstTouch.x - lastTouch.x) / 2);
GLfloat yradius = fabsf((firstTouch.y - lastTouch.y) / 2);
for (int i = 0; i <= 720; i += 2) {
GLfloat xOffset = (firstTouch.x > lastTouch.x) ?
lastTouch.x + xradius : firstTouch.x + xradius;
GLfloat yOffset = (firstTouch.y < lastTouch.y) ?
self.frame.size.height - lastTouch.y + yradius :
self.frame.size.height - firstTouch.y + yradius;
vertices[i] = (cos(degreesToRadian(i / 2))*xradius) + xOffset;
vertices[i+1] = (sin(degreesToRadian(i / 2))*yradius) +
yOffset;
}
glVertexPointer(2, GL_FLOAT , 0, vertices);
glDrawArrays (GL_TRIANGLE_FAN, 0, 360);
break;
}
case kImageShape:
glEnable(GL_TEXTURE_2D);
[sprite drawAtPoint:CGPointMake(lastTouch.x,
self.frame.size.height - lastTouch.y)];
break;
default:
break;
}
glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
[context presentRenderbuffer:GL_RENDERBUFFER_OES];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
if (useRandomColor)
self.currentColor = [UIColor randomColor];
UITouch* touch = [[event touchesForView:self] anyObject];
firstTouch = [touch locationInView:self];
lastTouch = [touch locationInView:self];
[self draw];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
lastTouch = [touch locationInView:self];
[self draw];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
lastTouch = [touch locationInView:self];
[self draw];
}
下面的就是关于touch的操作了.不多解释了.