5
// Created by döme on 03.08.2009.
9
* Copyright (c) 2009 Doemoetoer Gulyas.
10
* All rights reserved.
12
* Redistribution and use in source and binary forms, with or without
13
* modification, are permitted provided that the following conditions
15
* 1. Redistributions of source code must retain the above copyright
16
* notice, this list of conditions and the following disclaimer.
17
* 2. Redistributions in binary form must reproduce the above copyright
18
* notice, this list of conditions and the following disclaimer in the
19
* documentation and/or other materials provided with the distribution.
20
* 3. The name of the author may not be used to endorse or promote products
21
* derived from this software without specific prior written permission.
23
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38
#import <QuartzCore/QuartzCore.h>
39
#import <OpenGLES/EAGLDrawable.h>
40
#import <CoreGraphics/CoreGraphics.h>
43
#import "VertexArray.h"
47
@interface ESShader (GLESView)
48
+ (void) setShaderAPI: (EAGLRenderingAPI) api;
52
@implementation GLESView
56
return [CAEAGLLayer class];
59
- (void) lineGradientTexture: (GLuint*) texname red: (float) r green: (float) g blue: (float) b
61
uint8_t* spriteData = calloc(1, 256 * 4);
62
for (int i = 0; i < 256; ++i)
64
spriteData[4*i+0] = r*(float)i;
65
spriteData[4*i+1] = g*(float)i;
66
spriteData[4*i+2] = b*(float)i;
67
spriteData[4*i+3] = i;
70
glGenTextures(1, texname);
71
glBindTexture(GL_TEXTURE_2D, *texname);
73
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, spriteData);
75
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
76
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
78
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
80
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
85
- (void) doubleGradientTexture: (GLuint*) texname red: (float) r green: (float) g blue: (float) b
87
uint8_t* spriteData = calloc(1, 512 * 4);
88
for (int i = 0; i < 256; ++i)
90
spriteData[4*i+0] = r*(float)i;
91
spriteData[4*i+1] = g*(float)i;
92
spriteData[4*i+2] = b*(float)i;
93
spriteData[4*i+3] = i;
96
for (int i = 256; i < 512; ++i)
98
spriteData[4*i+0] = r*(float)(511-i);
99
spriteData[4*i+1] = g*(float)(511-i);
100
spriteData[4*i+2] = b*(float)(511-i);
101
spriteData[4*i+3] = (511-i);
105
glGenTextures(1, texname);
106
glBindTexture(GL_TEXTURE_2D, *texname);
108
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 512, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, spriteData);
110
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
111
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
113
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
115
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
121
- (void) textureFromCgImage: (CGImageRef) img texName: (GLuint*) texname width: (size_t) width height: (size_t) height repeat: (BOOL) doRepeat mipmap: (BOOL) doMipmap filter: (BOOL) doFilter
123
void* spriteData = malloc(width * height * 4);
127
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
128
CGContextRef spriteContext = CGBitmapContextCreate(spriteData, width, height, 8, width * 4, colorSpace, kCGImageAlphaPremultipliedLast);
129
CGColorSpaceRelease(colorSpace);
131
CGContextDrawImage(spriteContext, CGRectMake(0.0, 0.0, (CGFloat)width, (CGFloat)height), img);
132
CGContextRelease(spriteContext);
134
glGenTextures(1, texname);
135
glBindTexture(GL_TEXTURE_2D, *texname);
137
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, spriteData);
141
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, doRepeat ? GL_REPEAT : GL_CLAMP_TO_EDGE);
142
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, doRepeat ? GL_REPEAT : GL_CLAMP_TO_EDGE);
145
glGenerateMipmap(GL_TEXTURE_2D);
146
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, doFilter ? (doMipmap ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR) : GL_NEAREST);
148
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, doFilter ? GL_LINEAR : GL_NEAREST);
151
- (void) loadTextureFromBitmapNamed: (NSString*) name texName: (GLuint*) texname repeat: (BOOL) doRepeat mipmap: (BOOL) doMipmap filter: (BOOL) doFilter
154
// Creates a Core Graphics image from an image file
155
CGImageRef spriteImage = [UIImage imageNamed: name].CGImage;
156
// Get the width and height of the image
157
size_t width = CGImageGetWidth(spriteImage);
158
size_t height = CGImageGetHeight(spriteImage);
161
[self textureFromCgImage: spriteImage texName: texname width: width height: height repeat: doRepeat mipmap: doMipmap filter: doFilter];
165
static CGImageRef CreateCGImageFromPDFPage(CGPDFDocumentRef document, size_t pageNumber, int width, int height)
168
CGPDFPageRef page = CGPDFDocumentGetPage(document, pageNumber);
172
// CGRect pageRect = CGPDFPageGetBoxRect(page, kCGPDFMediaBox);
174
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
175
// void* data = malloc(4*width*height);
176
CGContextRef bitmapContext = CGBitmapContextCreate(NULL, width, height, 8, width * 4, colorSpace, kCGImageAlphaPremultipliedLast);
177
CGColorSpaceRelease(colorSpace);
185
CGAffineTransform M = CGPDFPageGetDrawingTransform(page, kCGPDFMediaBox, CGRectMake(0.0f, 0.0f, width, height), 0, NO);
187
CGContextConcatCTM(bitmapContext, M);
188
CGContextDrawPDFPage(bitmapContext, page);
189
CGImageRef pdfImage = CGBitmapContextCreateImage(bitmapContext);
190
CFRelease(bitmapContext);
196
static CGImageRef CreateImageFromPDFNamed(NSString* name, int width, int height)
198
CFURLRef url = CFURLCreateWithFileSystemPath(NULL, (CFStringRef) [[NSBundle mainBundle] pathForResource: name ofType: nil], 0, NO);
199
CGPDFDocumentRef pdfDoc = CGPDFDocumentCreateWithURL(url);
203
CGImageRef img = CreateCGImageFromPDFPage(pdfDoc, 1, width, height);
205
CGPDFDocumentRelease(pdfDoc);
211
- (void) loadTextureFromPDFNamed: (NSString*) name texName: (GLuint*) texname width: (size_t) width height: (size_t) height repeat: (BOOL) doRepeat mipmap: (BOOL) doMipmap filter: (BOOL) doFilter
214
CGImageRef img = CreateImageFromPDFNamed(name, width, height);
215
[self textureFromCgImage: img texName: texname width: width height: height repeat: doRepeat mipmap: doMipmap filter: doFilter];
220
//The GL view is stored in the nib file. When it's unarchived it's sent -initWithCoder:
221
- (id)initWithCoder:(NSCoder*)coder {
223
if (!(self = [super initWithCoder:coder]))
226
CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
228
eaglLayer.opaque = YES;
229
eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
231
context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES2];
233
context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES1];
235
if (!context || ![EAGLContext setCurrentContext: context])
241
animationInterval = 1.0 / 100.0;
243
[self setupGraphicsForApi: [context API]];
248
- (id)initWithFrame:(CGRect)frame {
250
if (!(self = [super initWithFrame:frame]))
253
CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
255
eaglLayer.opaque = YES;
256
eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
258
context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES2];
260
context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES1];
262
if (!context || ![EAGLContext setCurrentContext: context])
268
animationInterval = 1.0 / 100.0;
270
[self setupGraphicsForApi: [context API]];
277
- (void) setupGraphicsForApi: (EAGLRenderingAPI) glApi
279
glClearColor(0.0,0.0,1.0,1.0);
285
[self stopAnimation];
287
if ([EAGLContext currentContext] == context)
288
[EAGLContext setCurrentContext:nil];
295
- (void) setupViewDrawing
297
[EAGLContext setCurrentContext:context];
299
glBindFramebuffer(GL_FRAMEBUFFER, viewFramebuffer);
300
glViewport(0, 0, backingWidth, backingHeight);
302
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
305
- (void) finishViewDrawing
307
glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);
308
[context presentRenderbuffer: GL_RENDERBUFFER];
310
GLenum err = glGetError();
312
NSLog(@"OpenGL error %d occured", err);
317
[self setupViewDrawing];
319
[self finishViewDrawing];
323
- (void)drawRect:(CGRect)rect
325
[super drawRect: rect];
329
// [[UIColor clearColor] set];
333
- (void)animationCallback
339
- (void)startAnimation
341
animationTimer = [NSTimer scheduledTimerWithTimeInterval:animationInterval target:self selector:@selector(animationCallback) userInfo:nil repeats:YES];
345
- (void)stopAnimation
347
animationTimer = nil;
351
- (void)setAnimationTimer:(NSTimer *)newTimer
353
[animationTimer invalidate];
354
animationTimer = newTimer;
358
- (void)setAnimationInterval:(NSTimeInterval)interval
361
animationInterval = interval;
362
if (animationTimer) {
363
[self stopAnimation];
364
[self startAnimation];
370
- (BOOL)createFramebuffer {
372
glGenFramebuffers(1, &viewFramebuffer);
373
glGenRenderbuffers(1, &viewRenderbuffer);
375
glBindFramebuffer(GL_FRAMEBUFFER, viewFramebuffer);
376
glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);
377
[context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer*)self.layer];
378
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, viewRenderbuffer);
380
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &backingWidth);
381
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &backingHeight);
383
if (USE_DEPTH_BUFFER) {
384
glGenRenderbuffers(1, &depthRenderbuffer);
385
glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
386
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, backingWidth, backingHeight);
387
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderbuffer);
390
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
392
NSLog(@"failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER));
393
NSLog(@"%f %f %f %f", self.frame.origin.x, self.frame.origin.y, self.frame.size.width, self.frame.size.height);
401
- (void)destroyFramebuffer {
403
glDeleteFramebuffers(1, &viewFramebuffer);
405
glDeleteRenderbuffers(1, &viewRenderbuffer);
406
viewRenderbuffer = 0;
408
if(depthRenderbuffer)
410
glDeleteRenderbuffers(1, &depthRenderbuffer);
411
depthRenderbuffer = 0;
415
- (void)layoutSubviews {
416
[EAGLContext setCurrentContext:context];
417
[self destroyFramebuffer];
418
[self createFramebuffer];
422
@synthesize animationInterval;