问题
I am trying to set the background contents of a scene to a skybox effect using about array of 6 images.
I have created the array of images in the correct order, I know I need to then use
+ (instancetype) materialPropertyWithContents:(id)contents
However I'm struggling to work out how and where exactly I use that class method to return the property containing the cube map.
回答1:
SCNScene's "background" property is of the SCNMaterialProperty class. So you can directly set it's contents to an array of 6 images to setup your skybox (see SCNScene.h).
aScene.background.contents = @[@"Right.png", @"Left.png", @"Top.png", @"Bottom.png", @"Back.png", @"Front.png"];
Make sure your 6 images are square and with the same dimensions.
回答2:
HERES my awakeFromNib for a ScnView subclass
yes its confusing as the value assigned to content is id and theres so few samples.
HERES my awakeFromNib for a ScnView subclass
Use any 6 images of same size. TGA not required.
Google skybox to find examples.
This sample makes a skybox and also applys the same images to a cube which make it seem to mirror the sky.
Camera control is on so just move your mouse to rotate what looks like a mirrored cube
//
// SkyBoxSceneView.h
// SceneKit_Skybox
//
// Created by Brian Clear on 12/06/2014.
// Copyright (c) 2014 Brian Clear. All rights reserved.
//
#import <SceneKit/SceneKit.h>
@interface SkyBoxSceneView : SCNView
@end
//
// SkyBoxSceneView.m
// SceneKit_Skybox
//
// Created by Brian Clear on 12/06/2014.
// Copyright (c) 2014 Brian Clear. All rights reserved.
//
#import "SkyBoxSceneView.h"
@implementation SkyBoxSceneView
-(void)awakeFromNib
{
// create a new scene
SCNScene *scene = [SCNScene scene];
//-----------------------------------------------------------------------------------
//SET THE SKYBOX
//-----------------------------------------------------------------------------------
//it took me a while to get it working
//"APPLE IF YOU WANT SCENE KIT TO SUCCEED YOU NEED A FULL BLOWN GUIDE!!"
//-----------------------------------------------------------------------------------
//FIRST ISSUE - Error:scene.background is readonly
// I misread the help as "to set skybox set the scene.background"
/*
scene.background = ; //INCORRECT
scene.background.contents = ; //OK
*/
//I should have read it as "to set skybox set the scene.background content e.g. scene.background.contents"
//-----------------------------------------------------------------------------------
//ONLY EXAMPLE OF setting material.reflective DOESNT WORK for scene.background.content
/*
I couldnt get sky box to work for ages because the only example of using reflective property I found was in
in the 2014 sample code
AAPLSlideMaterialLayer.m
https://developer.apple.com/library/prerelease/mac/samplecode/SceneKitWWDC2014/Listings/Scene_Kit_Session_WWDC_2014_Sources_Slides_AAPLSlideMaterialLayer_m.html#//apple_ref/doc/uid/TP40014551-Scene_Kit_Session_WWDC_2014_Sources_Slides_AAPLSlideMaterialLayer_m-DontLinkElementID_62
_material.reflective.contents = @[@"right.tga", @"left.tga", @"top.tga", @"bottom.tga", @"back.tga", @"front.tga"];
so I tried it on scene.background.contents =
but didnt work
*/
//WRONG
//scene.background.contents = @[@"right.png", @"left.png", @"top.png", @"bottom.png", @"back.png", @"front.png"];
//-----------------------------------------------------------------------------------
//ATTEMPT 3 - I changed all tga to png but still nothing
//-----------------------------------------------------------------------------------
//ATTEMPT 4 - Note this is very wrong. I was way off here
//when I saw this
// _material.reflective.contents = @[@"right.tga", @"left.tga", @"top.tga", @"bottom.tga", @"back.tga", @"front.tga"];
//I then saw this
//scene.background.contents = ...
//I made the mistake of presuming that both "content" properties were the same
//SceneKit take a lot of id properties so WITHOUT A GUIDE you have to guess what goes into thes id properties
//I though scene.background was a SCNMaterialProperty cos it had scene.background.content
//same as material.reflective.content - reflective is a SCNMaterialProperty
//-----------------------------------------------------------------------------------
//tried it with SCNMaterialProperty.content
//but would never work as scene.background isnt a SCNMaterialProperty.content
// SCNMaterialProperty *scnMaterialProperty = [SCNMaterialProperty materialPropertyWithContents: @[@"right.tga", @"left.tga", @"top.tga", @"bottom.tga", @"back.tga", @"front.tga"]];
//-----------------------------------------------------------------------------------
//tried with png but same issue
// SCNMaterialProperty *scnMaterialProperty = [SCNMaterialProperty materialPropertyWithContents: @[@"right.png", @"left.png", @"top.png", @"bottom.png", @"back.png", @"front.png"]];
//-----------------------------------------------------------------------------------
//I had tried passing NSImage instead of NSString for material which worked
//boxNode.geometry.firstMaterial.reflective.contents = @[[NSImage imageNamed:@"right.tga"],....
//so tried that for scne.background.content
//but was doomed as not a SCNMaterialProperty
// SCNMaterialProperty *scnMaterialProperty = [SCNMaterialProperty materialPropertyWithContents: @[[NSImage imageNamed:@"right.tga"],
// [NSImage imageNamed:@"left.tga"],
// [NSImage imageNamed:@"top.tga"],
// [NSImage imageNamed:@"bottom.tga"],
// [NSImage imageNamed:@"back.tga"],
// [NSImage imageNamed:@"front.tga"]]];
//-----------------------------------------------------------------------------------
//Test 4 - try with one image
//WORKS - set whole background to one image
//scene.background.contents = [NSImage imageNamed:@"left.tga"];//OK
//this proved that the image does load
//-----------------------------------------------------------------------------------
//use same one image in a SCNMaterialProperty
//DOESNT WORK - so issue is the SCNMaterialProperty
// SCNMaterialProperty *scnMaterialProperty = [SCNMaterialProperty materialPropertyWithContents:[NSImage imageNamed:@"right.tga"]];
// scnMaterialProperty.intensity = 0.7;
// scene.background.contents = scnMaterialProperty;//OK
//-----------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------
//SKYBOX WORKS!!!!
//-----------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------
//version3 - pass array in directly (NOT through SCNMaterialProperty!!!!)
scene.background.contents = @[[NSImage imageNamed:@"right.tga"],
[NSImage imageNamed:@"left.tga"],
[NSImage imageNamed:@"top.tga"],
[NSImage imageNamed:@"bottom.tga"],
[NSImage imageNamed:@"back.tga"],
[NSImage imageNamed:@"front.tga"]];
//-----------------------------------------------------------------------------------
//DOESNT WORK
//scene.background.contents = @"frozen.mov";//
//-----------------------------------------------------------------------------------
//CAMERA and CUBE
//-----------------------------------------------------------------------------------
// 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, 2);
// create and add a 3d box to the scene
SCNNode *boxNode = [SCNNode node];
boxNode.geometry = [SCNBox boxWithWidth:1 height:1 length:1 chamferRadius:0.02];
[scene.rootNode addChildNode:boxNode];
//-----------------------------------------------------------------------------------
// create and configure a material
// SCNMaterial *material = [SCNMaterial material];
// material.diffuse.contents = [NSColor brownColor];//= [NSImage imageNamed:@"texture"];
// material.specular.contents = [NSColor brownColor];
// material.specular.intensity = 0.2;
// material.locksAmbientWithDiffuse = YES;
//
// //material.reflective.contents = @[@"right.tga", @"left.tga", @"top.tga", @"bottom.tga", @"back.tga", @"front.tga"];
// material.reflective.contents = @[@"right.png", @"left.png", @"top.png", @"bottom.png", @"back.png", @"front.png"];
//
// material.diffuse.contents = [NSColor blackColor];
//
//
// // set the material to the 3d object geometry
// boxNode.geometry.firstMaterial = material;
//
// earth-reflective.jpg
// boxNode.geometry.firstMaterial.reflective.intensity = 0.7;
//
//boxNode.geometry.firstMaterial.reflective.contents = [NSImage imageNamed:@"earth-reflective"];
// boxNode.geometry.firstMaterial.reflective.contents = @[@"right.tga", @"left.tga", @"top.tga", @"bottom.tga", @"back.tga", @"front.tga"];
//-----------------------------------------------------------------------------------
//CUBE MATERIAL
//-----------------------------------------------------------------------------------
//make the cube reflect the sky
//the sky isnt really being reflected comment out line above "scene.background.contents = ...."
//and cube will still reflect the sky
//also comment out both of these lines "boxNode.geometry.firstMaterial.reflective
//and sky box will still work
//-----------------------------------------------------------------------------------
//VERSION 1 - ALSO WORKS!
boxNode.geometry.firstMaterial.reflective.contents = @[[NSImage imageNamed:@"right.tga"],
[NSImage imageNamed:@"left.tga"],
[NSImage imageNamed:@"top.tga"],
[NSImage imageNamed:@"bottom.tga"],
[NSImage imageNamed:@"back.tga"],
[NSImage imageNamed:@"front.tga"]];
boxNode.geometry.firstMaterial.reflective.intensity = 0.7;
//-----------------------------------------------------------------------------------
//VERSION 2 - ALSO WORKS!
//this uses same image for all sides of the cube
//boxNode.geometry.firstMaterial.reflective.contents = [NSImage imageNamed:@"right.tga"];//ok
//boxNode.geometry.firstMaterial.reflective.intensity = 0.7;
//-----------------------------------------------------------------------------------
//VERSION 3 - BLACK 2010 a space odyssey shiny cube
//get the earth-reflective.jpg from
//https://developer.apple.com/library/mac/samplecode/SceneKit_Slides_WWDC2013/Introduction/Intro.html
// boxNode.geometry.firstMaterial.reflective.contents = [NSImage imageNamed:@"earth-reflective"];
// boxNode.geometry.firstMaterial.reflective.intensity = 0.7;
//-----------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------
//REQUIRED else above reflections look weird
boxNode.geometry.firstMaterial.diffuse.contents = [NSColor blackColor];
boxNode.geometry.firstMaterial.specular.intensity = 0.0;
//-----------------------------------------------------------------------------------
// animate the 3d object - camera control is on so cube spins with the sky
//comment in to animate cube
// CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"rotation"];
// animation.toValue = [NSValue valueWithSCNVector4:SCNVector4Make(1, 1, 0, M_PI*2)];
// animation.duration = 5;
// animation.repeatCount = MAXFLOAT; //repeat forever
// [boxNode addAnimation:animation forKey:nil];
// set the scene to the view
self.scene = scene;
// allows the user to manipulate the camera
self.allowsCameraControl = YES;
// show statistics such as fps and timing information
self.showsStatistics = YES;
}
@end
来源:https://stackoverflow.com/questions/24356070/how-to-set-contents-of-scenekit-background-to-cube-map