HIT해
[iOS/Swift] SceneKit Shadow 그림자 적용하기 - 1 본문
https://developer.apple.com/documentation/scenekit/scnlight
SCNLight | Apple Developer Documentation
A light source that can be attached to a node to illuminate the scene.
developer.apple.com
예시사진
위 사진과 같이 모델 아랫 부분에 그림자가 생성되게 만들어야한다.
기존 조명중 특정한 조명에 그림자가 지게 설정해주면 된다고 한다!
castsShadow를 활용해서 만들어보자.
https://stackoverflow.com/questions/59818131/scenekit-and-arkit-soft-shadows-or-blurred-shadows
SceneKit and ARKit – Soft shadows or blurred shadows
I have set up shadow in ARKit, But it's not satisfied results, we have required the same shade as quick view in safari. Please help me how to set up it. We have attached two images. Code var ligh...
stackoverflow.com
여기서 코드를 참고해서 만들어보았다.
답변으로 방향성 조명보다 spotlight 조명을 사용하고 2미터 정도 떨어지면 자연스럽게 연출이 가능하다고 했다.
func makeSpotLight() -> SCNNode{
let spotLightNode = SCNNode()
let spotLight = SCNLight()
spotLight.type = .spot
spotLight.intensity = 1000
spotLight.color = UIColor(white: 1.0, alpha: 1.0) // 빛의 색상 원색
// 그림자 설정
spotLight.castsShadow = true
spotLight.automaticallyAdjustsShadowProjection = true
spotLight.maximumShadowDistance = 20.0 // 그림자가 보이는 최대 거리
spotLight.orthographicScale = 10.0 // 조명 투영의 크기 (상황에 맞게 조정)
spotLight.shadowMapSize = CGSize(width: 2048, height: 2048) // 그림자 맵 해상도
spotLight.shadowMode = .deferred // 그림자 모드 설정
spotLight.shadowSampleCount = 128 // 그림자 샘플 수 (더 높은 수치일수록 품질이 향상됨)
spotLight.shadowRadius = 20.0 // 그림자의 흐림 정도
spotLight.shadowBias = 5.0 // 그림자 편향 (섬세하게 조정하여 그림자 부풀림을 방지)
spotLight.zNear = 1 // 그림자의 시작 거리
spotLight.zFar = 1000 // 그림자의 끝 거리
spotLight.shadowColor = UIColor.black.withAlphaComponent(0.36)// 그림자의 색상과 투명도
spotLight.spotInnerAngle = 30
spotLight.spotOuterAngle = 60
spotLightNode.light = spotLight
spotLightNode.name = "spotLight"
// 조명을 모델 위쪽 배치
spotLightNode.position = SCNVector3(x: 0, y: 10, z: 0) // 모델 아래쪽에 위치하도록 설정
spotLightNode.look(at: SCNVector3(x: 0, y: 0, z: 0)) // 모델의 중앙을 향하도록 설정
return spotLightNode
}
일반 조명들처럼 모델 윗부분에 광택이 지긴 했지만 바닥에 그림자가 생기지는 않았다.
그래서 모델의 노드를 순환하며 그림자 cast가 가능하도록 설정해주었다.
for node in scene.rootNode.childNodes {
node.scale = SCNVector3(x: 1, y: 1, z: 1) // 스케일 값을 조정하여 모델의 크기를 조절
node.castsShadow = true
}
여전히 보이지 않았다.
이건 중요하지 않은 문제였던 것 같다.
왜일까 생각을 해보았다. 스택오버플로우 상에서는 위의 설정들만으로도 그림자가 지는데 어째서 앱상에서의 3D 모델은 그림자가 지지 않는걸까.
혹시 바닥이 없어서 그런걸까..? 싶어서 바닥을 추가해주었다.
func addFloor(to scene: SCNScene) {
let floor = SCNPlane(width: 2, height: 2)
let floorNode = SCNNode(geometry: floor)
floorNode.position = SCNVector3(x: 0, y: -0.66, z: 0) // 모델 아래에 배치
floorNode.eulerAngles = SCNVector3(-Float.pi / 2, 0, 0) // 바닥이 수평을 유지하도록 설정
floorNode.name = "floor"
// 바닥의 재질 설정
let material = SCNMaterial()
material.diffuse.contents = UIColor.gray // 바닥을 보이지 않게 설정
material.specular.contents = UIColor.clear
material.transparency = 1.0 // 불투명하게 설정
floor.materials = [material]
floorNode.castsShadow = true // 바닥이 그림자를 받을 수 있도록 설정
scene.rootNode.addChildNode(floorNode)
}
결과화면
그랬다. AR 공간 상에서는 바닥을 인식해서 그림자가 생기게 해주지만 SCNView에 불러올때는 바닥이 따로 존재하지 않아서 그림자가 지지 않았던 것이었다.
그런데 원하는 요구사항은 투명한 공간에 그림자가 지는 것이었다.
바닥의 색을 clear로 바꿔주어보자.
func addFloor(to scene: SCNScene) {
let floor = SCNPlane(width: 2, height: 2)
let floorNode = SCNNode(geometry: floor)
floorNode.position = SCNVector3(x: 0, y: -0.66, z: 0) // 모델 아래에 배치
floorNode.eulerAngles = SCNVector3(-Float.pi / 2, 0, 0) // 바닥이 수평을 유지하도록 설정
floorNode.name = "floor"
// 바닥의 재질 설정
let material = SCNMaterial()
material.diffuse.contents = UIColor.clear // 바닥을 보이지 않게 설정
material.specular.contents = UIColor.clear // 반사광
material.transparency = 1.0 // 불투명하게 설정
floor.materials = [material]
floorNode.castsShadow = true // 바닥이 그림자를 받을 수 있도록 설정
scene.rootNode.addChildNode(floorNode)
}
바닥을 투명하게 바꾸어주었더니 그림자가 생기지 않았다..
그도 그럴것이 투명한 바닥이니 당연히 그림자가 지지 않는 것도 당연했다.
불투명도를 주면 보일까 싶었지만 보이지 않았다.
블렌더 상에서는 Shadow Catcher를 사용해 그림자가 지게 할 수 있지만 SceneKit에는 존재하지 않았다.
물론 AR환경에서 3D 모델 그림자를 만들고자 하는 개발자들은 위의 코드만으로도 쉽게 구현이 가능할 것이다.
다음 포스팅에서 다른 해결방법으로 그림자를 지게 만들어보겠다..
'Swift > UIKit 개발 노트' 카테고리의 다른 글
[iOS/SwiftUI] 스크린샷 감지 TCA (0) | 2024.08.30 |
---|---|
[iOS/SceneKit] defaultCameraController 알아보기 (0) | 2024.08.29 |
[iOS/SceneKit] 다른 모델의 노드를 추가해보자 (0) | 2024.08.26 |
[iOS/SwiftUI] UI가 마음대로 움직여요. (1) | 2024.08.25 |
[iOS/Swift] Generic enum allCases 사용하기 (0) | 2024.08.23 |