3d Graphics On Iphone

  • June 2020
  • PDF

This document was uploaded by user and they confirmed that they have the permission to share it. If you are author or own the copyright of this book, please report to us by using this DMCA report form. Report DMCA


Overview

Download & View 3d Graphics On Iphone as PDF for free.

More details

  • Words: 1,401
  • Pages: 89
3D Graphics on iPhone Douglass Turner [email protected] @dugla #iphonemeetup3dtalkacton

A talk in three acts ...

• • •

Intro to Computer Graphics Computer Graphics in OpenGL OpenGL and CocoaTouch Playing Nice Together

Intro to Computer Graphics (a trip down the graphics pipeline)

Build and Tesselate Model Copyright Steve Jubinville

Pose Model Copyright Steve Jubinville

Aim Camera

Design Appearance. Light Scene. Copyright © 2006 Holger Schömann

Design Appearance. Light Scene. Copyright © 2006 Florian Wild

Design Appearance. Light Scene. Copyright © 2006 Jack Qiao

Render Scene

Cull & clip model triangles to viewing frustrum.

Rasterize From models to pixels. Scanline interpolation.

• Depth Comparison • Apply Appearance - Vertex level. Pixel level. • Composite Elements

Present Image

Update Model State

Rinse, repeat.

Computer Graphics in OpenGL

OpenGL

Cocoa

OpenGL is old school

You are flipping levers on a state machine.

float foo[]

glPushMatrix() and glPopMatrix()

Data Structures are for wimps.

OpenGL is a dragster. Not a Prius. Just buckle up ...

... and enjoy the ride, baby!

iPhone 3GS by the Numbers (via AnandTech http://bit.ly/1pQaJO)



~7M triangles / second





~230,000 realtime triangles (30fps)





iPhone display: 320 * 480 = 153,600 pixels





230,000 / 153,600 = ~1.5 realtime-triangles / pixel

;-)

OpenGL websites are a bit different than Cocoa websites ...

Isn’t that sweet ...

Um... WTF?

Can’t you just feel the love?

Dude. I think my eyes are bleeding.

No worries. safari.oreilly.com is your friend

Hierarchical Modeling. Transformation Stacks. Coordinate Frames.

Pose Model

Pose Model

You are already familiar with hierarchical modeling and coordinate frames.

[self.parentView addSubview:childView];

or ...

for (UIView *v in self.containerView.subviews) { CGRect bounds = [v convertRect:v.bounds toView:scrollView]; if (CGRectIntersectsRect(bounds, scrollView.bounds)) { NSLog(@"View %d is visible", v.tag); } else { NSLog(@"View %d is hidden", v.tag); } } // for (self.containerView.subviews)

You are already familiar with hierarchical modeling and coordinate frames.

- (void)setTransform:(CGAffineTransform)newValue { // Scale along x-axis only CGAffineTransform constrainedTransform = CGAffineTransformScale(CGAffineTransformIdentity, newValue.a, 1.0); }

newValue.a = constrainedTransform.a; newValue.b = constrainedTransform.b; newValue.c = constrainedTransform.c; newValue.d = constrainedTransform.d; [super setTransform:newValue];

You are already already familiar with transformations.

HelloTeapot Demo

Source: http://github.com/turner/HelloTeapot

HelloTeapot Code Walkthrough

http://github.com/turner/HelloTeapot/blob/master/Classes/GLViewController.[hm]





// Position Camera glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glLoadMatrixf(_openGLCameraInverseTransform);





// Position Light glPushMatrix(); glMultMatrixf(_cameraTransform);

glPopMatrix();



// Position Model glPushMatrix();



JLMMatrix3DSetZRotationUsingDegrees(rotation, -45.0f); JLMMatrix3DSetScaling(scale, sx, sy, sz); JLMMatrix3DMultiply(rotation, scale, concatenation); glMultMatrixf(concatenation);



// Render for(int i = 0; i < num_teapot_indices; i += new_teapot_indicies[i] + 1) {





} // for (num_teapot_indices)

glPopMatrix();

glEnable(GL_LIGHT3); glLightfv(GL_LIGHT3, GL_DIFFUSE, spotLight);

glDrawElements(GL_TRIANGLE_STRIP, indices[i], GL_UNSIGNED_SHORT, &indices[i+1]);

http://github.com/turner/HelloTeapot/blob/master/Classes/GLViewController.[hm]





// Position Camera glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glLoadMatrixf(_openGLCameraInverseTransform);





// Position Light glPushMatrix(); glMultMatrixf(_cameraTransform);

glPopMatrix();



// Position Model glPushMatrix();



JLMMatrix3DSetZRotationUsingDegrees(rotation, -45.0f); JLMMatrix3DSetScaling(scale, sx, sy, sz); JLMMatrix3DMultiply(rotation, scale, concatenation); glMultMatrixf(concatenation);



// Render for(int i = 0; i < num_teapot_indices; i += new_teapot_indicies[i] + 1) {





} // for (num_teapot_indices)

glPopMatrix();

Pose Model

glEnable(GL_LIGHT3); glLightfv(GL_LIGHT3, GL_DIFFUSE, spotLight);

glDrawElements(GL_TRIANGLE_STRIP, indices[i], GL_UNSIGNED_SHORT, &indices[i+1]);

http://github.com/turner/HelloTeapot/blob/master/Classes/GLViewController.[hm]





// Position Camera glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glLoadMatrixf(_openGLCameraInverseTransform);





// Position Light glPushMatrix(); glMultMatrixf(_cameraTransform);

glPopMatrix();



// Position Model glPushMatrix();



JLMMatrix3DSetZRotationUsingDegrees(rotation, -45.0f); JLMMatrix3DSetScaling(scale, sx, sy, sz); JLMMatrix3DMultiply(rotation, scale, concatenation); glMultMatrixf(concatenation);



// Render for(int i = 0; i < num_teapot_indices; i += new_teapot_indicies[i] + 1) {





} // for (num_teapot_indices)

glPopMatrix();

Light Scene

glEnable(GL_LIGHT3); glLightfv(GL_LIGHT3, GL_DIFFUSE, spotLight);

glDrawElements(GL_TRIANGLE_STRIP, indices[i], GL_UNSIGNED_SHORT, &indices[i+1]);

http://github.com/turner/HelloTeapot/blob/master/Classes/GLViewController.[hm]





// Position Camera glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glLoadMatrixf(_openGLCameraInverseTransform);





// Position Light glPushMatrix(); glMultMatrixf(_cameraTransform);

glPopMatrix();



// Position Model glPushMatrix();



JLMMatrix3DSetZRotationUsingDegrees(rotation, -45.0f); JLMMatrix3DSetScaling(scale, sx, sy, sz); JLMMatrix3DMultiply(rotation, scale, concatenation); glMultMatrixf(concatenation);



// Render for(int i = 0; i < num_teapot_indices; i += new_teapot_indicies[i] + 1) {





} // for (num_teapot_indices)

glPopMatrix();

glEnable(GL_LIGHT3); glLightfv(GL_LIGHT3, GL_DIFFUSE, spotLight);

Aim Camera ... Dude, where is the camera ...?

glDrawElements(GL_TRIANGLE_STRIP, indices[i], GL_UNSIGNED_SHORT, &indices[i+1]);

http://github.com/turner/HelloTeapot/blob/master/Classes/GLViewController.[hm]

camera

teapot

wTc

wTt

world

cT t

camera

teapot

?

glMatrixMode(GL_MODELVIEW); glLoadMatrixf(_openGLCameraInverseTransform);

cT t

camera

(wTc)

teapot

-1

wTt

world

cT t

=

cT w

* wTt

cT t

=

cT w

* wTt





// Position Camera glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glLoadMatrixf(_openGLCameraInverseTransform);





// Position Light glPushMatrix(); glMultMatrixf(_cameraTransform);

glPopMatrix();



// Position Model glPushMatrix();



JLMMatrix3DSetZRotationUsingDegrees(rotation, -45.0f); JLMMatrix3DSetScaling(scale, sx, sy, sz); JLMMatrix3DMultiply(rotation, scale, concatenation); glMultMatrixf(concatenation);



// Render for(int i = 0; i < num_teapot_indices; i += new_teapot_indicies[i] + 1) {





} // for (num_teapot_indices)

glPopMatrix();

cT t

=

cT w

* wTt

glEnable(GL_LIGHT3); glLightfv(GL_LIGHT3, GL_DIFFUSE, spotLight);

glDrawElements(GL_TRIANGLE_STRIP, indices[i], GL_UNSIGNED_SHORT, &indices[i+1]);

http://github.com/turner/HelloTeapot/blob/master/Classes/GLViewController.[hm]

- (void)placeCameraAtLocation:(M3DVector3f)location target:(M3DVector3f)target up:(M3DVector3f)up;

http://github.com/turner/HelloTeapot/blob/master/Classes/GLViewController.[hm]

Render float teapot_vertices [] = { 0.0663, 0.1178, 0.0, 0.0672, 0.1152, 0.0, 0.0639, 0.1178, 0.0178043, ... }; float teapot_normals[] = {















};

-0.987635, -0.156768, 0, -0.902861, -0.429933, 0, -0.953562, -0.156989, -0.257047, ...

short indicies[] = { // howmany vertices in vertex strip 26, // vertex strip indices 1122, 1243, 1272, 1242, ... ,1283, 1199, ... };

http://github.com/turner/HelloTeapot/blob/master/teapot.h

Render

glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3 ,GL_FLOAT, 0, teapot_vertices); glEnableClientState(GL_NORMAL_ARRAY); glNormalPointer(GL_FLOAT, 0, teapot_normals); glEnable(GL_NORMALIZE);

http://github.com/turner/HelloTeapot/blob/master/Classes/GLViewController.[hm]





// Position Camera glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glLoadMatrixf(_openGLCameraInverseTransform);





// Position Light glPushMatrix(); glMultMatrixf(_cameraTransform);

glPopMatrix();



// Position Model glPushMatrix();



JLMMatrix3DSetZRotationUsingDegrees(rotation, -45.0f); JLMMatrix3DSetScaling(scale, sx, sy, sz); JLMMatrix3DMultiply(rotation, scale, concatenation); glMultMatrixf(concatenation);



// Render for(int i = 0; i < num_teapot_indices; i += indicies[i] + 1) {





} // for (num_teapot_indices)

glPopMatrix();

Render

glEnable(GL_LIGHT3); glLightfv(GL_LIGHT3, GL_DIFFUSE, spotLight);

glDrawElements(GL_TRIANGLE_STRIP, indices[i], GL_UNSIGNED_SHORT, &indices[i+1]);

http://github.com/turner/HelloTeapot/blob/master/Classes/GLViewController.[hm]

http://github.com/turner/HelloTeapot/blob/master/Classes/GLViewController.[hm]

invert( camera_transform ) red_light green_light blue_light push() camera_transform white_spotlight pop() push() teapot_transform draw() pop()

You’ll want to understand this stuff if you intend to do AR* apps like all the cool kids.

*Augmented

Reality - See http://layar.com

Design Appearance

Mipmapped textures are your friend. They will become your workhorse for visual complexity.

Texture Everything Copyright © Douglass Turner







glGenTextures(1, &_name); glBindTexture(GL_TEXTURE_2D, _name); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, glColor, _w, _h, 0, glColor, glFormat, data); glGenerateMipmapOES(GL_TEXTURE_2D);

Method initWithTextureFile:mipmap:

Class github.com/turner/HelloTexture/blob/master/Classes/TEITexture.[h,m]

HelloTexture Demo

Source: http://github.com/turner/HelloTexture

Two Words Texture. Atlas.

t

s

Texture Space

t

s

Texture Space

HelloParticleSystem Demo texture atlas hacks

OpenGL ES 2.0 == GLSL

Shaders Take it to Another Level

Copyright © Douglass Turner

Shaders Take it to Another Level

Copyright © Douglass Turner

Shaders Take it to Another Level

ZBrush Modeling Daniel Lieske

Shaders Take it to Another Level

ZBrush Modeling Daniel Lieske Material Design Ralf Stumpf

Shaders Take it to Another Level

ZBrush Modeling Daniel Lieske Material Design Ralf Stumpf

Shaders Take it to Another Level

Copyright: Stephen Molyneaux

GLSL is cool. Sadly, OpenGL ES 2.0 (iPhone 3Gs) does not support hardware anti-aliasing. Stick with mipmapped textures until you really know what you are doing. Or don’t care about aliasing artifacts ...

1 sample per pixel

4 jittered/filtered samples per pixel

Remember the iPhone Imperitive Your app will be beautiful.

OpenGL and Cocoa Touch Playing Nice Together

MVC OpenGL is M. Keep V dumb. Lots of chatter between M and V. • GLGravity | http://bit.ly/2dS8YI • Jeff LaMarche OpenGL ES Template | http://bit.ly/2IvZtV

Touch Sequence & Accelerometer

HelloParticleSystem Demo Particle system. Touch. Acceleration

Touch Sequence

Initialize model state touchesBegan:withEvent:

Evolve model state touchesMoved:withEvent:

Clean up model state touchesEnded:withEvent: touchesCancelled:withEvent:

Accelerometer

- (void)accelerometer:(UIAccelerometer*)accelerometer didAccelerate:(UIAcceleration*)acceleration { // Compute "G". Use low-pass filter to attenuate instantaneous acceleration. self.accelerationValueX = acceleration.x * kFilteringFactor + self.accelerationValueX * (1.0 - kFilteringFactor); self.accelerationValueY = acceleration.y * kFilteringFactor + self.accelerationValueY * (1.0 - kFilteringFactor); self.accelerationValueZ = acceleration.z * kFilteringFactor + self.accelerationValueZ * (1.0 - kFilteringFactor); // ParticleSystem particles live in flatland. Use x and y compoments of "G". [ParticleSystem setGravity:CGPointMake(self.accelerationValueX, self.accelerationValueY)]; }

UIAccelerometerDelegate

+ (void)setGravity:(CGPoint)gravityVector { // Normalize 2D “G” vector. Only care about direction. float length = sqrtf(gravityVector.x * gravityVector.x + gravityVector.y * gravityVector.y); ParticleSystemGravity.x = gravityVector.x / length; ParticleSystemGravity.y = gravityVector.y / length; // Flip y-component of gravity vector to be consistent with screen space coordinate // system used in ParticleSystem. ParticleSystemGravity.y = -(ParticleSystemGravity.y); }

ParticleSystem - Class State





// dv = dv/dt * dt float dv_x = (ParticleSystemGravity.x * gravityScaleFactor * dt); float dv_y = (ParticleSystemGravity.y * gravityScaleFactor * dt); particle.velocity = CGPointMake(particle.velocity.x + dv_x, particle.velocity.y + dv_y); // dx = dx/dt * dt float dx = particle.velocity.x * dt; float dy = particle.velocity.y * dt; // x = x_old * dx particle.location = CGPointMake(particle.location.x + dx, particle.location.y + dy);

ParticleSystem - Instance State



CoreAnimation: [myView setNeedsDisplay] & [myView drawRect]

OpenGL: - (void)startAnimation { animationTimer = [NSTimer scheduledTimerWithTimeInterval:animationInterval target:self selector:@selector(drawView) userInfo:nil repeats:YES]; }

iPhone is an Expression Platform You Must See: Stanford cs 193p Lecture 17 Video | On iTunes: http://bit.ly/PUrGj Creating New Expressive Social Mediums on the iPhone Ge Wang | CCO & CTO | Smule

iPhone is a general purpose sensing platform • Touch • Sound • Proximity • Cloud • Camera • INU (almost) • Geography

iPhone encourages plausible, hyper-real, extensions of human experience. Be interesting. Be brilliant.

Resources • @dugla - search on #iphonemeetup3dtalkacton • http://theelasticimage.posterous.com • This presentation on SlideShare: http://bit.ly/4wC4Mu

Douglass Turner @dugla #iphonemeetup3dtalkacton [email protected] Copyright © Douglass Turner

Related Documents