3D Math Primer: CocoaConf Chicago

76
The Day You Finally Use Algebra! Janie Clayton

Transcript of 3D Math Primer: CocoaConf Chicago

Page 1: 3D Math Primer: CocoaConf Chicago

The Day You Finally Use Algebra!

Janie Clayton

Page 2: 3D Math Primer: CocoaConf Chicago

About Me

Page 3: 3D Math Primer: CocoaConf Chicago

But math is hard! (Let’s go shopping!)

Page 4: 3D Math Primer: CocoaConf Chicago

Math is hard. But math is fun too.

Page 5: 3D Math Primer: CocoaConf Chicago

Demo

Page 6: 3D Math Primer: CocoaConf Chicago

Normalized Coordinate

Systems

Page 7: 3D Math Primer: CocoaConf Chicago

Cartesian Coordinates

Page 8: 3D Math Primer: CocoaConf Chicago

320

480

Page 9: 3D Math Primer: CocoaConf Chicago

320

480 or 568

Page 10: 3D Math Primer: CocoaConf Chicago
Page 11: 3D Math Primer: CocoaConf Chicago

1

1

Page 12: 3D Math Primer: CocoaConf Chicago

Normalized Coordinates

Normalized coordinates take values between 0.0 and 1.0

It maintains the proportion of the shape without necessarily maintaining the specific unit measurements

In graphics programming, we use triangles a lot. If you have a triangle where the hypotenuse is 3.4 centimeters and has a series of specific angles, you can calculate out the other parts of the triangle. With a normalized triangle, the hypotenuse would be 1.0, but all the angles and proportions would stay the same, so it would be “scaled” down.

Page 13: 3D Math Primer: CocoaConf Chicago

(0,0) (1,0)

(0,1) (1,1)

Page 14: 3D Math Primer: CocoaConf Chicago

(0,0) (1,0)

(0,1) (1,1)

Page 15: 3D Math Primer: CocoaConf Chicago

(0,0) (1,0)

(0,1) (1,1)

Page 16: 3D Math Primer: CocoaConf Chicago

self.size.width

self. size.

height

Page 17: 3D Math Primer: CocoaConf Chicago

- Colors, like the screen dimensions, are based on percentages rather than absolute values.

- If you come from a graphic design background, you need to convert your 255 scale to percentages.

Page 18: 3D Math Primer: CocoaConf Chicago

Algorithm Rosetta Stone

Page 19: 3D Math Primer: CocoaConf Chicago

Rosetta Stone- Had the same text in

Greek, demotic, and hieroglyphics. Was used to translate hieroglyphics

- Going to do similar thing, but with math algorithms, plain English, and code

Page 20: 3D Math Primer: CocoaConf Chicago

√-1 2ˆ3 ∑ π

Page 21: 3D Math Primer: CocoaConf Chicago

∑5

i = 1

4i

Algoritm

I have a starting value of one. I have an end value of five. I want to multiply each value by four and add them together.

Page 22: 3D Math Primer: CocoaConf Chicago

Plain English

I have a starting value of one. I have an end value of five. I want to multiply each value

by four and add them together.

Page 23: 3D Math Primer: CocoaConf Chicago

var x = 0

for index in 1…5 {

x += (4 * index)

}

Code

Page 24: 3D Math Primer: CocoaConf Chicago

√-1 2ˆ3 ∑ π…and it was delicious!

Walk through what each part actually is.

Page 25: 3D Math Primer: CocoaConf Chicago

i 8 sum pi…and it was delicious!

Page 26: 3D Math Primer: CocoaConf Chicago

Trigonometry

Page 27: 3D Math Primer: CocoaConf Chicago

Triangles

A shape with three sides where the angles add up to 180 degrees

Everything in our world comes back to triangles

The most stable shape

Foundation of 3D graphics

Page 28: 3D Math Primer: CocoaConf Chicago

Right Triangles

Page 29: 3D Math Primer: CocoaConf Chicago

Pythagorean Theorem

aˆ2 + bˆ2 = cˆ2

Saying that the Pythagorean Theorem just calculates a hypotenuse is like saying programming is just managing 1s and 0s. It is a small building block you can use to build increasingly more complex things.

Page 30: 3D Math Primer: CocoaConf Chicago

Circle Formulas

Circumference: 2πr

Area: πrˆ2

Page 31: 3D Math Primer: CocoaConf Chicago

So What Can We Do Knowing This?

Change the direction a character is moving in

Check to see if the user is hitting a target area on the screen

Draw shapes and filters in specific configurations

Page 32: 3D Math Primer: CocoaConf Chicago

Linear Algebra

Google “Better Explained Rotation” Matrices Complex numbers Show how to use linear algebra to do more efficient affine transforms rotation through matrix multiplications

Page 33: 3D Math Primer: CocoaConf Chicago

– BetterExplained.com

“The survivors of linear algebra classes are physicists, graphics programmers and other

masochists.”

Page 34: 3D Math Primer: CocoaConf Chicago

What is Linear Algebra?

Linear Algebra allows you to perform an action on many values at the same time.

This action must be consistent across all values, such as multiplying every value by two.

Page 35: 3D Math Primer: CocoaConf Chicago

What is Linear Algebra?

Values are placed in an object called a matrix and the actions performed on the values are called transforms

Linear algebra is optimized for parallel mathematical operations.

Page 36: 3D Math Primer: CocoaConf Chicago

Vector Data Types

vec2, vec3, vec4: 2D, 3D, and 4D floating point vector objects.

vec2: (x, y)

vec3: (x, y, z)

vec4: (r, g, b, a)

Page 37: 3D Math Primer: CocoaConf Chicago

Vectors

9

33√10

Page 38: 3D Math Primer: CocoaConf Chicago

Demo

Page 39: 3D Math Primer: CocoaConf Chicago

Enter the Matrix

Page 40: 3D Math Primer: CocoaConf Chicago

Matrix Data Types

mat2, mat3, mat4: 2, 3, and 4 element matrices.

mat2: Holds a 2 X 2 number matrix

mat3: Holds a 3 X 3 number matrix, used for 2D linear algebra

mat4: Holds a 4 X 4 number matrix, used for 3D linear algebra

Page 41: 3D Math Primer: CocoaConf Chicago

1.0 1.0 1.0 0 1.0 1.0 1.0 0 1.0 1.0 1.0 0 1.0 1.0 1.0 0

Column

Row

Page 42: 3D Math Primer: CocoaConf Chicago

mat4 genericMatrix = mat4(

1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0, 0, 0, 0

);

Column

Row

Column major vs Row major?? Comment about the semi-colon because this is GLSL and not Swift!!!

Page 43: 3D Math Primer: CocoaConf Chicago

vec4 firstColumn = vec4(1.0, 1.0, 1.0, 1.0);

vec4 secondColumn = vec4(1.0, 1.0, 1.0, 1.0);

vec4 thirdColumn = vec4(1.0, 1.0, 1.0, 1.0);

vec4 fouthColumn = vec4(0, 0, 0, 0);

mat4 myMatrix = mat4( firstColumn, SecondColumn, thirdColumn, FourthColumn

);

Talk about the topography map project where I gave names to the coordinates based on location because processing them was a pain in the ass!

Page 44: 3D Math Primer: CocoaConf Chicago

CGAffineTransform

Page 45: 3D Math Primer: CocoaConf Chicago

Demo

Page 46: 3D Math Primer: CocoaConf Chicago

Affine, Wha?? :(A transform is any function that alters the size, position, or rotation of an object on your screen.

Four types: Identity, Translate, Rotation, and Scale.

For a transform to be affine, the lines in your shape must be parallel.

Page 47: 3D Math Primer: CocoaConf Chicago
Page 48: 3D Math Primer: CocoaConf Chicago

CGAffine Transform Methods

CGAffineTransformMakeRotation (GLFloat angle);

CGAffineTransformMakeScale (CGFLoat sx, CGFloat sy);

CGAffineTransformMakeTranslation (CGFloat tx, CGFloat ty);

Affine Transform Rotate Talk about chaining transforms CGAffineTransform

Page 49: 3D Math Primer: CocoaConf Chicago

struct CGAffineTransform { CGFloat a; GLFloat b; CGFloat c; CGFloat d; CGFloat tx; CGFloat ty

}

a = b = c = d =

Page 50: 3D Math Primer: CocoaConf Chicago

[x y 1][a b 0 c d 0 tx ty 0]

X =

[x’ y’ 1]

Show the matrix of the vector and the actual math around it

Page 51: 3D Math Primer: CocoaConf Chicago

let pointX = a * x + c * y + tx

let pointY = b * x + d * y + ty

Explain that I don’t really understand how this works, but I don’t have to. The computer knows and it gets abstracted away from me and I don’t have to know what it does.

Page 52: 3D Math Primer: CocoaConf Chicago

CGAffineTransformMakeRotation(45)

CGAffineTransformMakeScale(2,2)

Page 53: 3D Math Primer: CocoaConf Chicago

rotate 45 degrees

Double Size

Page 54: 3D Math Primer: CocoaConf Chicago

Refraction Fragment Shader Example

Page 55: 3D Math Primer: CocoaConf Chicago

void main() { highp vec2 textureCoordinateToUse = vec2(textureCoordinate.x, (textureCoordinate.y * aspectRatio + 0.5 - 0.5 * aspectRatio)); highp float distanceFromCenter = distance(center, textureCoordinateToUse); lowp float checkForPresenceWithinSphere = step(distanceFromCenter, radius); distanceFromCenter = distanceFromCenter / radius; highp float normalizedDepth = radius * sqrt(1.0 - distanceFromCenter * distanceFromCenter); highp vec3 sphereNormal = normalize(vec3(textureCoordinateToUse - center, normalizedDepth)); highp vec3 refractedVector = 2.0 * refract(vec3(0.0, 0.0, -1.0), sphereNormal, refractiveIndex); refractedVector.xy = -refractedVector.xy; highp vec3 finalSphereColor = texture2D(inputImageTexture, (refractedVector.xy + 1.0) * 0.5).rgb; // Grazing angle lighting highp float lightingIntensity = 2.5 * (1.0 - pow(clamp(dot(ambientLightPosition, sphereNormal), 0.0, 1.0), 0.25)); finalSphereColor += lightingIntensity; // Specular lighting lightingIntensity = clamp(dot(normalize(lightPosition), sphereNormal), 0.0, 1.0); lightingIntensity = pow(lightingIntensity, 15.0); finalSphereColor += vec3(0.8, 0.8, 0.8) * lightingIntensity; gl_FragColor = vec4(finalSphereColor, 1.0) * checkForPresenceWithinSphere; }

So what this calculation does is it adjusts for a non-square aspect ratio of the image. The image aspect ratio is passed in as a uniform, and this adjusts the normally 0.0-1.0 texture coordinate for the Y axis to instead be from 0.0-1.0*(imageHeight/imageWidth). It has to expand the Y axis coordinate about its center point (0.5), thus the weird addition and subtraction in there. If you don’t do this, your sphere turns into an egg in non-square images.

Page 56: 3D Math Primer: CocoaConf Chicago

highp vec2 textureCoordinateToUse = vec2(textureCoordinate.x, (textureCoordinate.y * aspectRatio + 0.5 - 0.5 * aspectRatio));

So what this calculation does is it adjusts for a non-square aspect ratio of the image. The image aspect ratio is passed in as a uniform, and this adjusts the normally 0.0-1.0 texture coordinate for the Y axis to instead be from 0.0-1.0*(imageHeight/imageWidth). It has to expand the Y axis coordinate about its center point (0.5), thus the weird addition and subtraction in there. If you don’t do this, your sphere turns into an egg in non-square images.

Page 57: 3D Math Primer: CocoaConf Chicago
Page 58: 3D Math Primer: CocoaConf Chicago

highp float distanceFromCenter = distance(center, textureCoordinateToUse);

This is a Pythagorean distance calculation to determine how far the current pixel (texture coordinate) is from the center that we’ve provided as a uniform. It’s a sqrt(xdiff^2 + ydiff^2) calculation.

Page 59: 3D Math Primer: CocoaConf Chicago
Page 60: 3D Math Primer: CocoaConf Chicago

lowp float checkForPresenceWithinSphere = step(distanceFromCenter, radius);

The step() function returns 1 if the second value is greater than the first, 0 if not. I use these to avoid if() statements, which are expensive in fragment shaders (branching does not work well in massively parallel operations).

Page 61: 3D Math Primer: CocoaConf Chicago

No, the simulator does not have the clap.

Page 62: 3D Math Primer: CocoaConf Chicago

distanceFromCenter = distanceFromCenter / radius;

This normalizes the distance from the center to be 0.0 for a value at the center of the sphere, and 1.0 for a value at the edge of the sphere. Values outside that range will get filtered out by the product of the above step() calculation later on.

Page 63: 3D Math Primer: CocoaConf Chicago
Page 64: 3D Math Primer: CocoaConf Chicago

highp float normalizedDepth = radius * sqrt(1.0 - distanceFromCenter * distanceFromCenter);

This is where we calculate the Z height that a sphere, cut in half, would extend above the plane of the image. This is another geometrical calculation based on knowing the distance of our point from the center of the sphere.

Page 65: 3D Math Primer: CocoaConf Chicago
Page 66: 3D Math Primer: CocoaConf Chicago

highp vec3 sphereNormal = normalize(vec3(textureCoordinateToUse - center, normalizedDepth));

Once we know the height of the spherical cap at that point, we can calculate the normal for that point on the sphere’s surface. Think of it as a ray that extends from the center of the sphere to the surface at this X, Y coordinate. The normal is based on the center of the sphere, so we subtract our aspect-ratio-adjusted-coordinate from the center to get the relative X, Y coordinate from the center of the sphere. The Z component is the height of the sphere we just calculated.

Page 67: 3D Math Primer: CocoaConf Chicago
Page 68: 3D Math Primer: CocoaConf Chicago

highp vec3 refractedVector = refract(vec3(0.0, 0.0, -1.0), sphereNormal, refractiveIndex);

With the normal, we can calculate the refraction of light from that point on the sphere’s surface. The refraction calculation uses the surface normal, the refractiveIndex (a material property that you pass in, I think I use glass’s here), and a ray direction. I believe the ray direction here is from the eye going into the screen, although I can never remember positive/negative Z directions in OpenGL. This then generates a refracted vector, pointing in the direction light would as it refracts through a sphere.

Page 69: 3D Math Primer: CocoaConf Chicago
Page 70: 3D Math Primer: CocoaConf Chicago

 gl_FragColor = texture2D(inputImageTexture, (refractedVector.xy + 1.0) * 0.5) * checkForPresenceWithinSphere;

We then take this refracted vector, which is in the -1.0-1.0 coordinate space, and adjust it to the 0.0-1.0 coordinate space for texture sampling. We read the texture color at the location pointed to by that vector. The earlier step() function to determine if a point was within the sphere comes into play here, where we only display a color if the point was within the sphere. If it was not, we output 0.0, 0.0, 0.0, 0.0 as an RGBA color because that’s the result of multiplying with 0.

Page 71: 3D Math Primer: CocoaConf Chicago
Page 72: 3D Math Primer: CocoaConf Chicago

Objc-io Article

http://www.objc.io/issue-21/gpu-accelerated-image-processing.html

Page 73: 3D Math Primer: CocoaConf Chicago

Best resources we currently have. Can be kind of hard to get through. Someone should really write a math book for programmers…

Page 74: 3D Math Primer: CocoaConf Chicago
Page 75: 3D Math Primer: CocoaConf Chicago
Page 76: 3D Math Primer: CocoaConf Chicago

The End