iOS+SceneKit: How to apply toon shader on texture? - ios

I want to use a toon-shader with SceneKit on iOS8+ to render a sphere with an Earth texture on it. I also want to add a toon shader for rendering the Earth. So far the shader works on the lighting, but the texture isn't shaded by the toon-shader (cp. to the image below, the texture should also be "tooned").
Someone any ideas?
Here's my view controller code (self.sceneKitView is an instance of SCNView):
#implementation ToonViewController
- (void)viewDidLoad {
[super viewDidLoad];
SCNScene *scene = [SCNScene scene];
// create and add a camera to the scene
SCNNode *cameraNode = [SCNNode node];
cameraNode.camera = [SCNCamera camera];
[scene.rootNode addChildNode:cameraNode];
// place the camera
cameraNode.position = SCNVector3Make(0, 0, 15);
// create and add a light to the scene
SCNNode *lightNode = [SCNNode node];
lightNode.light = [SCNLight light];
lightNode.light.type = SCNLightTypeOmni;
lightNode.position = SCNVector3Make(0, 10, 10);
[scene.rootNode addChildNode:lightNode];
// create and add an ambient light to the scene
SCNNode *ambientLightNode = [SCNNode node];
ambientLightNode.light = [SCNLight light];
ambientLightNode.light.type = SCNLightTypeAmbient;
ambientLightNode.light.color = [UIColor darkGrayColor];
[scene.rootNode addChildNode:ambientLightNode];
// set up the scene
self.sceneKitView.scene = scene;
self.sceneKitView.allowsCameraControl = YES;
self.sceneKitView.showsStatistics = NO;
self.sceneKitView.backgroundColor = [UIColor clearColor];
NSMutableDictionary* shaders = [[NSMutableDictionary alloc] init];
shaders[SCNShaderModifierEntryPointLightingModel] = [[NSString alloc] initWithContentsOfURL:[[NSBundle mainBundle] URLForResource:#"fixed_toon" withExtension:#"shader"]
encoding:NSUTF8StringEncoding
error:nil];
SCNNode* earth = [SCNNode nodeWithGeometry:[SCNSphere sphereWithRadius:5.0]];
earth.position = SCNVector3Make(0.0, 0.0, 0.0);
[scene.rootNode addChildNode:earth];
[earth runAction:[SCNAction repeatActionForever:[SCNAction rotateByX:0.0 y:0.25 z:0.0 duration:1.0]]];
SCNMaterial* earthMaterial = [SCNMaterial material];
earthMaterial.diffuse.contents = [UIImage imageNamed:#"Earth.png"];
earthMaterial.specular.contents = [UIColor whiteColor];
earthMaterial.specular.intensity = 0.2;
earthMaterial.locksAmbientWithDiffuse = NO;
earthMaterial.shaderModifiers = shaders;
earth.geometry.firstMaterial = earthMaterial;
}
#end
And this is the fixed_toon.shader file:
vec3 lDir = normalize(vec3(0.1, 1.0, 1.0));
float dotProduct = dot(_surface.normal, lDir);
_lightingContribution.diffuse += (dotProduct*dotProduct*_light.intensity.rgb);
_lightingContribution.diffuse = floor(_lightingContribution.diffuse*4.0)/3.0;
vec3 halfVector = normalize(lDir + _surface.view);
dotProduct = max(0.0, pow(max(0.0, dot(_surface.normal, halfVector)), _surface.shininess));
dotProduct = floor(dotProduct*3.0)/3.0;
//_lightingContribution.specular += (dotProduct*_light.intensity.rgb);
_lightingContribution.specular = vec3(0,0,0);

The shader you have is only a lighting shader. If you want the earth to be tooned, you need a fragment shader.
Look at the shader file all of the math is related to light. You need something that will adjust the pixel color of the texture. Then connect it using the SCNShaderModifierEntryPointFragment entry point.

Related

How to zoom-out object in SceneKit?

I am creating cube in scene kit. this is output.
You can see images are not size to fit in SceneView.
Here is my code :
SCNScene *scene = [[SCNScene alloc]init];
float X = 0.0;
float Radius = 1.0;
for (int i = 0; i<3; i++) {
SCNBox *Box = [SCNBox boxWithWidth:3.0 height:3.0 length:3.0 chamferRadius:Radius];
self.cubeNode = [SCNNode nodeWithGeometry:Box];
[ArrBoxNode addObject:self.cubeNode];
self.sceneView.backgroundColor = [UIColor grayColor];
self.view.backgroundColor = [UIColor grayColor];
self.cubeNode.position = SCNVector3Make(X,.00,0.0);
[scene.rootNode addChildNode:self.cubeNode];
self.sceneView.scene = scene;
[self.sceneView sizeToFit];
self.sceneView.contentScaleFactor = 0.0;
}
Can you please help me?i am stuck in this issue.

Position of SCNode Object infront of Camera With ARKit

I am trying to add Bullet in my Scene with ARKit.
Here is what i have done to add bullet in my Scene
{
SCNNode* systemNode = [SCNNode new];
SCNSphere *sphere = [SCNSphere sphereWithRadius:0.01];
systemNode.geometry = sphere;
systemNode.renderingOrder = 1;
SCNPhysicsShape *shape = [SCNPhysicsShape shapeWithGeometry:sphere options:nil];
systemNode.physicsBody = [SCNPhysicsBody bodyWithType:SCNPhysicsBodyTypeDynamic shape:shape];
systemNode.physicsBody.mass = 0.05;
systemNode.physicsBody.friction = 0.01;
systemNode.physicsBody.affectedByGravity = NO;
SCNScene *modelScene = [SCNScene sceneNamed:#"Cartridge45.scn" inDirectory:#"art.scnassets/models" options:nil];
Bullet *bulletNode = [Bullet new];
bulletNode = (Bullet *) [modelScene.rootNode childNodeWithName:#"cartridge" recursively:YES];
bulletNode.scale = SCNVector3Make(1.0, 1.0, 1.0);
bulletNode.renderingOrder = 1;
Bullet *bulletNode1 = [Bullet new];
bulletNode1 = (Bullet *) [modelScene.rootNode childNodeWithName:#"cartridge_1" recursively:YES];
bulletNode1.scale = SCNVector3Make(1.0, 1.0, 1.0);
bulletNode1.renderingOrder = 1;
SCNVector3 min, max;
[bulletNode getBoundingBoxMin:&min max:&max];
CGFloat collisionCapsuleRadius = 0.01;
CGFloat collisionCapsuleHeight = 0.1;
NSLog(#"El Bouncing Box. El min es collisionCapsuleRadius:%f collisionCapsuleHeight:%f", collisionCapsuleRadius, collisionCapsuleHeight);
SCNNode *bColNode = [SCNNode node];
NSString *nameCube = [NSString stringWithFormat:#"BulletB%d", rand()];
bColNode.name =nameCube;
bColNode.position = SCNVector3Make(0.0, 0.0, 1.2);// a bit too high to not hit the floor
bColNode.physicsBody = [SCNPhysicsBody bodyWithType:SCNPhysicsBodyTypeKinematic shape:[SCNPhysicsShape shapeWithGeometry:[SCNCapsule capsuleWithCapRadius:collisionCapsuleRadius height:collisionCapsuleHeight] options:nil]];
bColNode.physicsBody.categoryBitMask = CollisionCategoryBullet;
bColNode.physicsBody.contactTestBitMask = CollisionCategoryInvader;
[systemNode addChildNode:bColNode];
ARFrame *frame = self.sceneView.session.currentFrame;
SCNVector3 direction;
SCNVector3 position;
if (frame != nil) {
SCNMatrix4 mat = SCNMatrix4FromMat4(frame.camera.transform);
direction = SCNVector3Make(mat.m41, mat.m42, mat.m43);
position = SCNVector3Make(mat.m31*-1, mat.m32*-1, mat.m33*-1);
}
else {
direction = SCNVector3Make(0,0,-0.11);
position = SCNVector3Make(0,0,-0.1);
}
systemNode.position = SCNVector3Make(0,0,0);
bulletNode.position = position;
bulletNode1.position = position;
systemNode.name=#"bullet";
[systemNode addChildNode:bulletNode];
[systemNode addChildNode:bulletNode1];
SCNMatrix4 transform = SCNMatrix4FromMat4(frame.camera.transform);
SCNVector4 force = SCNVector4Make(0, 0,-5, 0);
SCNVector3 rotatedForce = [self to3:[self multiplyVector:transform :force]];
[systemNode.physicsBody applyForce:rotatedForce impulse:YES];
[self.sceneView.scene.rootNode addChildNode:systemNode];
}
The bullet is getting added at same direction disregards of view of camera in real world.

SK3DNode not rotating

I have a 3D sphere model saved as a dae file and loaded to xcode.
Problem is I cannot get it spinning/rotating - it just stays static... I've tried several ways, even tried to get the camera to move around it.
SCNScene *model = [SCNScene sceneNamed:#"model3.dae"];
SK3DNode *node = [[SK3DNode alloc] initWithViewportSize:CGSizeMake(50, 50)];
//workaround
id s1 = [node valueForKey:#"_scnRenderer"];
NSLog(#"%#", s1);
node.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:node.frame.size.width/2];
node.physicsBody.affectedByGravity = NO;
node.physicsBody.allowsRotation = YES;
node.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
[node setScnScene:model];
//THIS IS THE PART! I cannot get it to spin around
CABasicAnimation *rotationAnimation = [CABasicAnimation animationWithKeyPath:#"rotation"];
rotationAnimation.toValue = [NSValue valueWithSCNVector4:SCNVector4Make(1, 2, 3, M_PI * 2)];
rotationAnimation.duration = 1;
rotationAnimation.repeatCount = FLT_MAX;
[model.rootNode addAnimation:rotationAnimation forKey:nil];
//camera
SCNCamera *camera = [SCNCamera camera];
camera.xFov = 0;
camera.yFov = 0;
camera.zNear = 0.0;
camera.zFar = 10.0;
SCNNode *cameraNode = [SCNNode node];
cameraNode.camera = camera;
cameraNode.position = SCNVector3Make(0, 0, 5);
[model.rootNode addChildNode:cameraNode];
node.pointOfView = cameraNode;
[world addChild:node];
Any ideas? Basically I want to try get the 3D model moving around inside the SK3DNode. Hope this makes sense. Think spinning planet.
Thanks in advance,
Alex
modifying the transform (by adding an animation, for instance) of the root node of a scene has no effect because the camera is held by a child node of that root node. The relative transform between the sphere and the camera stays the same. You should add an animation to the camera node or to the sphere node instead.

scenekit model from sketchup disappears

I am playing around with scene kit.
I do not know a lot about modeling but i created a very basic Sketchup model with no materials or textures.
I exported the model from ketchup and imported it into the scene.
As i move the camera around towards one end of the model the rear disappears and vice versa. As the camera rotates towards the front the rear gets shadowed in black.
What is the reason for this?
Lighting? Here is the code for the scene. Its a basic Xcode game project
// create a new scene
SCNScene *scene = [SCNScene sceneNamed:#"ship_transport.dae"];
// create and add a camera to the scene
SCNNode *cameraNode = [SCNNode node];
cameraNode.camera = [SCNCamera camera];
[scene.rootNode addChildNode:cameraNode];
// place the camera
cameraNode.position = SCNVector3Make(0, 0, 100);
// create and add an ambient light to the scene
SCNNode *ambientLightNode = [SCNNode node];
ambientLightNode.light = [SCNLight light];
ambientLightNode.light.type = SCNLightTypeAmbient
ambientLightNode.light.color = [UIColor whiteColor];
[scene.rootNode addChildNode:ambientLightNode];
// retrieve the ship node
SCNNode *ship = [scene.rootNode childNodeWithName:#"ship" recursively:YES];
ship.geometry.firstMaterial.diffuse.contents = [UIColor redColor];
ship.geometry.firstMaterial.specular.contents = [UIColor whiteColor];
SCNVector3 vector = SCNVector3Make(.1, .1, .1);
[ship setScale:vector];
//[scene.rootNode addChildNode:lightNode];
// animate the 3d object
[ship runAction:[SCNAction repeatActionForever:[SCNAction rotateByX:0 y:0 z:0 duration:1]]];
// retrieve the SCNView
SCNView *scnView = (SCNView *)self.view;
scnView.autoenablesDefaultLighting = true;
// set the scene to the view
scnView.scene = scene;
// allows the user to manipulate the camera
scnView.allowsCameraControl = YES;
// show statistics such as fps and timing information
scnView.showsStatistics = YES;
// configure the view
scnView.backgroundColor = [UIColor darkGrayColor];
Try setting the zFar property on the camera. Other related properties to try changing would be the xFov and yFov.

How to change anchor point?

I'm working with SceneKit. The object SCNNode is rotated relative to the center. How to change anchor point of the SCNNode?
SCNScene *scene = [SCNScene new];
SCNBox *boxGeometry = [SCNBox boxWithWidth:384.f height:512.f length:20.f chamferRadius:0];
SCNMaterial *material = [SCNMaterial new];
material.diffuse.contents = [UIImage imageNamed:#"material"];
SCNNode *boxNode = [SCNNode nodeWithGeometry:boxGeometry];
boxNode.geometry.firstMaterial = material;
boxNode.pivot = SCNMatrix4MakeTranslation(0.5f, 0.5f, 0.5f);
[scene.rootNode addChildNode:boxNode];
self.sceneView.scene = scene;
self.sceneView.allowsCameraControl = YES;
Your pivot transform translation is very small compared to the size of your box. It's not normalized.
If you want to translate around one of the corners you should translate half of the side in all directions.
boxNode.pivot = SCNMatrix4MakeTranslation(384.0/2.0, 512.0/2.0, 20.0/2.0);
As a simple example :
yourSceneNode.pivot = SCNMatrix4MakeTranslation(0.5, 0.5, 0.5),
where you change the node's position, rotation and scale properties.
SCNNode class reference explains this nicely

Resources