Mercurial > xcodescriptingbridge
comparison Classes/MySampleProjectViewController.m @ 0:5ec52341f221
Initial commit
author | Eric Wing <ewing@anscamobile.com> |
---|---|
date | Fri, 29 Jul 2011 18:18:15 -0700 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:5ec52341f221 |
---|---|
1 // | |
2 // MySampleProjectViewController.m | |
3 // MySampleProject | |
4 // | |
5 // Created by Eric Wing on 7/29/11. | |
6 // Copyright 2011 __MyCompanyName__. All rights reserved. | |
7 // | |
8 | |
9 #import <QuartzCore/QuartzCore.h> | |
10 | |
11 #import "MySampleProjectViewController.h" | |
12 #import "EAGLView.h" | |
13 | |
14 // Uniform index. | |
15 enum { | |
16 UNIFORM_TRANSLATE, | |
17 NUM_UNIFORMS | |
18 }; | |
19 GLint uniforms[NUM_UNIFORMS]; | |
20 | |
21 // Attribute index. | |
22 enum { | |
23 ATTRIB_VERTEX, | |
24 ATTRIB_COLOR, | |
25 NUM_ATTRIBUTES | |
26 }; | |
27 | |
28 @interface MySampleProjectViewController () | |
29 @property (nonatomic, retain) EAGLContext *context; | |
30 @property (nonatomic, assign) CADisplayLink *displayLink; | |
31 - (BOOL)loadShaders; | |
32 - (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; | |
33 - (BOOL)linkProgram:(GLuint)prog; | |
34 - (BOOL)validateProgram:(GLuint)prog; | |
35 @end | |
36 | |
37 @implementation MySampleProjectViewController | |
38 | |
39 @synthesize animating, context, displayLink; | |
40 | |
41 - (void)awakeFromNib | |
42 { | |
43 #if USE_OPENGLES2 | |
44 EAGLContext* aContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; | |
45 #else | |
46 EAGLContext* aContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1]; | |
47 #endif | |
48 | |
49 if (!aContext) | |
50 NSLog(@"Failed to create ES context"); | |
51 else if (![EAGLContext setCurrentContext:aContext]) | |
52 NSLog(@"Failed to set ES context current"); | |
53 | |
54 self.context = aContext; | |
55 [aContext release]; | |
56 | |
57 [(EAGLView *)self.view setContext:context]; | |
58 [(EAGLView *)self.view setFramebuffer]; | |
59 | |
60 #if USE_OPENGLES2 | |
61 if ([context API] == kEAGLRenderingAPIOpenGLES2) | |
62 [self loadShaders]; | |
63 #endif | |
64 | |
65 animating = FALSE; | |
66 animationFrameInterval = 1; | |
67 self.displayLink = nil; | |
68 } | |
69 | |
70 - (void)dealloc | |
71 { | |
72 if (program) | |
73 { | |
74 glDeleteProgram(program); | |
75 program = 0; | |
76 } | |
77 | |
78 // Tear down context. | |
79 if ([EAGLContext currentContext] == context) | |
80 [EAGLContext setCurrentContext:nil]; | |
81 | |
82 [context release]; | |
83 | |
84 [super dealloc]; | |
85 } | |
86 | |
87 - (void)viewWillAppear:(BOOL)animated | |
88 { | |
89 [self startAnimation]; | |
90 | |
91 [super viewWillAppear:animated]; | |
92 } | |
93 | |
94 - (void)viewWillDisappear:(BOOL)animated | |
95 { | |
96 [self stopAnimation]; | |
97 | |
98 [super viewWillDisappear:animated]; | |
99 } | |
100 | |
101 - (void)viewDidUnload | |
102 { | |
103 [super viewDidUnload]; | |
104 | |
105 if (program) | |
106 { | |
107 glDeleteProgram(program); | |
108 program = 0; | |
109 } | |
110 | |
111 // Tear down context. | |
112 if ([EAGLContext currentContext] == context) | |
113 [EAGLContext setCurrentContext:nil]; | |
114 self.context = nil; | |
115 } | |
116 | |
117 - (NSInteger)animationFrameInterval | |
118 { | |
119 return animationFrameInterval; | |
120 } | |
121 | |
122 - (void)setAnimationFrameInterval:(NSInteger)frameInterval | |
123 { | |
124 /* | |
125 Frame interval defines how many display frames must pass between each time the display link fires. | |
126 The display link will only fire 30 times a second when the frame internal is two on a display that refreshes 60 times a second. The default frame interval setting of one will fire 60 times a second when the display refreshes at 60 times a second. A frame interval setting of less than one results in undefined behavior. | |
127 */ | |
128 if (frameInterval >= 1) | |
129 { | |
130 animationFrameInterval = frameInterval; | |
131 | |
132 if (animating) | |
133 { | |
134 [self stopAnimation]; | |
135 [self startAnimation]; | |
136 } | |
137 } | |
138 } | |
139 | |
140 - (void)startAnimation | |
141 { | |
142 if (!animating) | |
143 { | |
144 CADisplayLink *aDisplayLink = [[UIScreen mainScreen] displayLinkWithTarget:self selector:@selector(drawFrame)]; | |
145 [aDisplayLink setFrameInterval:animationFrameInterval]; | |
146 [aDisplayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; | |
147 self.displayLink = aDisplayLink; | |
148 | |
149 animating = TRUE; | |
150 } | |
151 } | |
152 | |
153 - (void)stopAnimation | |
154 { | |
155 if (animating) | |
156 { | |
157 [self.displayLink invalidate]; | |
158 self.displayLink = nil; | |
159 animating = FALSE; | |
160 } | |
161 } | |
162 | |
163 - (void)drawFrame | |
164 { | |
165 [(EAGLView *)self.view setFramebuffer]; | |
166 | |
167 // Replace the implementation of this method to do your own custom drawing. | |
168 static const GLfloat squareVertices[] = { | |
169 -0.5f, -0.33f, | |
170 0.5f, -0.33f, | |
171 -0.5f, 0.33f, | |
172 0.5f, 0.33f, | |
173 }; | |
174 | |
175 static const GLubyte squareColors[] = { | |
176 255, 255, 0, 255, | |
177 0, 255, 255, 255, | |
178 0, 0, 0, 0, | |
179 255, 0, 255, 255, | |
180 }; | |
181 | |
182 static float transY = 0.0f; | |
183 | |
184 glClearColor(0.5f, 0.5f, 0.5f, 1.0f); | |
185 glClear(GL_COLOR_BUFFER_BIT); | |
186 | |
187 #if USE_OPENGLES2 | |
188 // Use shader program. | |
189 glUseProgram(program); | |
190 | |
191 // Update uniform value. | |
192 glUniform1f(uniforms[UNIFORM_TRANSLATE], (GLfloat)transY); | |
193 transY += 0.075f; | |
194 | |
195 // Update attribute values. | |
196 glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, squareVertices); | |
197 glEnableVertexAttribArray(ATTRIB_VERTEX); | |
198 glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, 1, 0, squareColors); | |
199 glEnableVertexAttribArray(ATTRIB_COLOR); | |
200 | |
201 // Validate program before drawing. This is a good check, but only really necessary in a debug build. | |
202 // DEBUG macro must be defined in your debug configurations if that's not already the case. | |
203 #if defined(DEBUG) | |
204 if (![self validateProgram:program]) | |
205 { | |
206 NSLog(@"Failed to validate program: %d", program); | |
207 return; | |
208 } | |
209 #endif | |
210 #else | |
211 glMatrixMode(GL_PROJECTION); | |
212 glLoadIdentity(); | |
213 glMatrixMode(GL_MODELVIEW); | |
214 glLoadIdentity(); | |
215 glTranslatef(0.0f, (GLfloat)(sinf(transY)/2.0f), 0.0f); | |
216 transY += 0.075f; | |
217 | |
218 glVertexPointer(2, GL_FLOAT, 0, squareVertices); | |
219 glEnableClientState(GL_VERTEX_ARRAY); | |
220 glColorPointer(4, GL_UNSIGNED_BYTE, 0, squareColors); | |
221 glEnableClientState(GL_COLOR_ARRAY); | |
222 #endif | |
223 | |
224 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | |
225 | |
226 [(EAGLView *)self.view presentFramebuffer]; | |
227 } | |
228 | |
229 - (void)didReceiveMemoryWarning | |
230 { | |
231 // Releases the view if it doesn't have a superview. | |
232 [super didReceiveMemoryWarning]; | |
233 | |
234 // Release any cached data, images, etc. that aren't in use. | |
235 } | |
236 | |
237 - (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file | |
238 { | |
239 GLint status; | |
240 const GLchar *source; | |
241 | |
242 source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; | |
243 if (!source) | |
244 { | |
245 NSLog(@"Failed to load vertex shader"); | |
246 return FALSE; | |
247 } | |
248 | |
249 *shader = glCreateShader(type); | |
250 glShaderSource(*shader, 1, &source, NULL); | |
251 glCompileShader(*shader); | |
252 | |
253 #if defined(DEBUG) | |
254 GLint logLength; | |
255 glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); | |
256 if (logLength > 0) | |
257 { | |
258 GLchar *log = (GLchar *)malloc(logLength); | |
259 glGetShaderInfoLog(*shader, logLength, &logLength, log); | |
260 NSLog(@"Shader compile log:\n%s", log); | |
261 free(log); | |
262 } | |
263 #endif | |
264 | |
265 glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); | |
266 if (status == 0) | |
267 { | |
268 glDeleteShader(*shader); | |
269 return FALSE; | |
270 } | |
271 | |
272 return TRUE; | |
273 } | |
274 | |
275 - (BOOL)linkProgram:(GLuint)prog | |
276 { | |
277 GLint status; | |
278 | |
279 glLinkProgram(prog); | |
280 | |
281 #if defined(DEBUG) | |
282 GLint logLength; | |
283 glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); | |
284 if (logLength > 0) | |
285 { | |
286 GLchar *log = (GLchar *)malloc(logLength); | |
287 glGetProgramInfoLog(prog, logLength, &logLength, log); | |
288 NSLog(@"Program link log:\n%s", log); | |
289 free(log); | |
290 } | |
291 #endif | |
292 | |
293 glGetProgramiv(prog, GL_LINK_STATUS, &status); | |
294 if (status == 0) | |
295 return FALSE; | |
296 | |
297 return TRUE; | |
298 } | |
299 | |
300 - (BOOL)validateProgram:(GLuint)prog | |
301 { | |
302 GLint logLength, status; | |
303 | |
304 glValidateProgram(prog); | |
305 glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); | |
306 if (logLength > 0) | |
307 { | |
308 GLchar *log = (GLchar *)malloc(logLength); | |
309 glGetProgramInfoLog(prog, logLength, &logLength, log); | |
310 NSLog(@"Program validate log:\n%s", log); | |
311 free(log); | |
312 } | |
313 | |
314 glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); | |
315 if (status == 0) | |
316 return FALSE; | |
317 | |
318 return TRUE; | |
319 } | |
320 | |
321 - (BOOL)loadShaders | |
322 { | |
323 GLuint vertShader, fragShader; | |
324 NSString *vertShaderPathname, *fragShaderPathname; | |
325 | |
326 // Create shader program. | |
327 program = glCreateProgram(); | |
328 | |
329 // Create and compile vertex shader. | |
330 vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; | |
331 if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) | |
332 { | |
333 NSLog(@"Failed to compile vertex shader"); | |
334 return FALSE; | |
335 } | |
336 | |
337 // Create and compile fragment shader. | |
338 fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; | |
339 if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) | |
340 { | |
341 NSLog(@"Failed to compile fragment shader"); | |
342 return FALSE; | |
343 } | |
344 | |
345 // Attach vertex shader to program. | |
346 glAttachShader(program, vertShader); | |
347 | |
348 // Attach fragment shader to program. | |
349 glAttachShader(program, fragShader); | |
350 | |
351 // Bind attribute locations. | |
352 // This needs to be done prior to linking. | |
353 glBindAttribLocation(program, ATTRIB_VERTEX, "position"); | |
354 glBindAttribLocation(program, ATTRIB_COLOR, "color"); | |
355 | |
356 // Link program. | |
357 if (![self linkProgram:program]) | |
358 { | |
359 NSLog(@"Failed to link program: %d", program); | |
360 | |
361 if (vertShader) | |
362 { | |
363 glDeleteShader(vertShader); | |
364 vertShader = 0; | |
365 } | |
366 if (fragShader) | |
367 { | |
368 glDeleteShader(fragShader); | |
369 fragShader = 0; | |
370 } | |
371 if (program) | |
372 { | |
373 glDeleteProgram(program); | |
374 program = 0; | |
375 } | |
376 | |
377 return FALSE; | |
378 } | |
379 | |
380 // Get uniform locations. | |
381 uniforms[UNIFORM_TRANSLATE] = glGetUniformLocation(program, "translate"); | |
382 | |
383 // Release vertex and fragment shaders. | |
384 if (vertShader) | |
385 glDeleteShader(vertShader); | |
386 if (fragShader) | |
387 glDeleteShader(fragShader); | |
388 | |
389 return TRUE; | |
390 } | |
391 | |
392 @end |