gpt4 book ai didi

ios - SceneKit:使 block 更逼真或更像 3D

转载 作者:行者123 更新时间:2023-12-01 17:16:05 28 4
gpt4 key购买 nike

下面的代码用于在 SceneKit 中创建场景和创建 block 。根据我们的用户,这些 block 看起来很平,不够“3D”。屏幕截图 1-2 显示了我们的应用。

屏幕截图 3-5 显示了用户期望 block 的外观,更像 3D。

和不同的人交流后,对于如何渲染更像截图3-5的 block 有不同的看法。有人说使用环境遮挡,有人说使用体素照明,有人说使用聚光灯和使用阴影,或者定向照明。

我们之前尝试添加全向照明,但没有成功,因此被移除。正如您在代码中看到的那样,我们还对环境光节点进行了试验,但也没有产生正确的结果。

渲染 block 并获得与屏幕截图 3-5 相当的外观的最佳方式是什么?

注意:我们理解代码未针对性能进行优化,即显示了不应该显示的多边形。好的,可以。重点不在于性能,而在于实现更像 3D 的渲染。您可以对节点进行一些硬性限制,例如场景中不超过 1K 或 10K。

代码:

func createScene() {
// Set scene view
let scene = SCNScene()
sceneView.jitteringEnabled = true
sceneView.scene = scene

// Add camera node
sceneView.pointOfView = cameraNode

// Make delegate to capture screenshots
sceneView.delegate = self

// Set ambient lighting
let ambientLightNode = SCNNode()
ambientLightNode.light = SCNLight()
ambientLightNode.light!.type = SCNLightTypeAmbient
ambientLightNode.light!.color = UIColor(white: 0.50, alpha: 1.0)
//scene.rootNode.addChildNode(ambientLightNode)
//sceneView.autoenablesDefaultLighting = true

// Set floor
setFloor()

// Set sky
setSky()

// Set initial position for user node
userNode.position = SCNVector3(x: 0, y: Float(CameraMinY), z: Float(CameraZoom))

// Add user node
scene.rootNode.addChildNode(userNode)

// Add camera to user node
// zNear fixes white triangle bug while zFar fixes white line bug
cameraNode.camera = SCNCamera()
cameraNode.camera!.zNear = Double(0.1)
cameraNode.camera!.zFar = Double(Int.max)
cameraNode.position = SCNVector3(x: 0, y: 0, z: 0) //EB: Add some offset to represent the head
userNode.addChildNode(cameraNode)
}


private func setFloor() {
// Create floor geometry
let floorImage = UIImage(named: "FloorBG")!
let floor = SCNFloor()
floor.reflectionFalloffEnd = 0
floor.reflectivity = 0
floor.firstMaterial!.diffuse.contents = floorImage
floor.firstMaterial!.diffuse.contentsTransform = SCNMatrix4MakeScale(Float(floorImage.size.width)/2, Float(floorImage.size.height)/2, 1)
floor.firstMaterial!.locksAmbientWithDiffuse = true
floor.firstMaterial!.diffuse.wrapS = .Repeat
floor.firstMaterial!.diffuse.wrapT = .Repeat
floor.firstMaterial!.diffuse.mipFilter = .Linear

// Set node & physics
// -- Must set y-position to 0.5 so blocks are flush with floor
floorLayer = SCNNode(geometry: floor)
floorLayer.position.y = -0.5
let floorShape = SCNPhysicsShape(geometry: floor, options: nil)
let floorBody = SCNPhysicsBody(type: .Static, shape: floorShape)
floorLayer.physicsBody = floorBody
floorLayer.physicsBody!.restitution = 1.0

// Add to scene
sceneView.scene!.rootNode.addChildNode(floorLayer)
}


private func setSky() {
// Create sky geometry
let sky = SCNFloor()
sky.reflectionFalloffEnd = 0
sky.reflectivity = 0
sky.firstMaterial!.diffuse.contents = SkyColor
sky.firstMaterial!.doubleSided = true
sky.firstMaterial!.locksAmbientWithDiffuse = true
sky.firstMaterial!.diffuse.wrapS = .Repeat
sky.firstMaterial!.diffuse.wrapT = .Repeat
sky.firstMaterial!.diffuse.mipFilter = .Linear
sky.firstMaterial!.diffuse.contentsTransform = SCNMatrix4MakeScale(Float(2), Float(2), 1);

// Set node & physics
skyLayer = SCNNode(geometry: sky)
let skyShape = SCNPhysicsShape(geometry: sky, options: nil)
let skyBody = SCNPhysicsBody(type: .Static, shape: skyShape)
skyLayer.physicsBody = skyBody
skyLayer.physicsBody!.restitution = 1.0

// Set position
skyLayer.position = SCNVector3(0, SkyPosY, 0)

// Set fog
/*sceneView.scene?.fogEndDistance = 60
sceneView.scene?.fogStartDistance = 50
sceneView.scene?.fogDensityExponent = 1.0
sceneView.scene?.fogColor = SkyColor */

// Add to scene
sceneView.scene!.rootNode.addChildNode(skyLayer)
}


func createBlock(position: SCNVector3, animated: Bool) {
...

// Create box geometry
let box = SCNBox(width: 1.0, height: 1.0, length: 1.0, chamferRadius: 0.0)
box.firstMaterial!.diffuse.contents = curStyle.getContents() // "curStyle.getContents()" either returns UIColor or UIImage
box.firstMaterial!.specular.contents = UIColor.whiteColor()

// Add new block
let newBlock = SCNNode(geometry: box)
newBlock.position = position
blockLayer.addChildNode(newBlock)
}

屏幕截图 1-2(我们的应用):

enter image description here enter image description here

屏幕截图 3-5( block 的理想视觉表示):

enter image description here enter image description here enter image description here

最佳答案

我仍然认为您可以做一些简单的事情,这将对场景的渲染方式产生重大影响。很抱歉没有使用你的代码,这个例子是我身边的东西。

现在您的场景仅由环境光照亮。

let aLight = SCNLight()
aLight.type = SCNLightTypeAmbient
aLight.color = UIColor(red: 0.2, green: 0.2, blue: 0.2, alpha: 1.0)
let aLightNode = SCNNode()
aLightNode.light = aLight
scene.rootNode.addChildNode(aLightNode)

如果我在我的场景中只使用这盏灯,我会看到以下内容。请注意,无论面朝哪个方向,所有面的光照都是一样的。有些游戏确实很好地体现了这种美学。

enter image description here

以下代码块向该场景添加了定向光。在此灯光中应用的变换对您的场景无效,请务必根据您希望灯光从哪里来定位灯光。

let dLight = SCNLight()
dLight.type = SCNLightTypeDirectional
dLight.color = UIColor(red: 0.6, green: 0.6, blue: 0.6, alpha: 1.0)

let dLightNode = SCNNode()
dLightNode.light = dLight
var dLightTransform = SCNMatrix4Identity
dLightTransform = SCNMatrix4Rotate(dLightTransform, -90 * Float(M_PI)/180, 1, 0, 0)
dLightTransform = SCNMatrix4Rotate(dLightTransform, 37 * Float(M_PI)/180, 0, 0, 1)
dLightTransform = SCNMatrix4Rotate(dLightTransform, -20 * Float(M_PI)/180, 0, 1, 0)
dLightNode.transform = dLightTransform
scene.rootNode.addChildNode(dLightNode)

现在我们根据相对于光线方向的角度对每个面进行着色。

enter image description here

目前 SceneKit 仅在您使用 SCNLightTypeSpot 时支持阴影。使用聚光灯意味着我们需要定向(根据定向光)并定位它。我用它来代替定向光。

let sLight = SCNLight()
sLight.castsShadow = true
sLight.type = SCNLightTypeSpot
sLight.zNear = 50
sLight.zFar = 120
sLight.spotInnerAngle = 60
sLight.spotOuterAngle = 90

let sLightNode = SCNNode()
sLightNode.light = sLight
var sLightTransform = SCNMatrix4Identity
sLightTransform = SCNMatrix4Rotate(sLightTransform, -90 * Float(M_PI)/180, 1, 0, 0)
sLightTransform = SCNMatrix4Rotate(sLightTransform, 65 * Float(M_PI)/180, 0, 0, 1)
sLightTransform = SCNMatrix4Rotate(sLightTransform, -20 * Float(M_PI)/180, 0, 1, 0)
sLightTransform = SCNMatrix4Translate(sLightTransform, -20, 50, -10)
sLightNode.transform = sLightTransform
scene.rootNode.addChildNode(sLightNode)

在上面的代码中,我们首先告诉聚光灯转换阴影,默认情况下场景中的所有节点都会转换阴影(可以更改)。 zNearzFar 设置也很重要,必须指定,以便转换阴影的节点在距光源的距离范围内。此范围外的节点不会转换阴影。

enter image description here

在着色/阴影之后,您可以轻松应用许多其他效果。景深效果为 available for the camera .雾同样很容易包含在内。

scene.fogColor = UIColor.blackColor()
scene.fogStartDistance = 10
scene.fogEndDistance = 110
scenekitView.backgroundColor = UIColor(red: 0.2, green: 0.2, blue: 0.2, alpha: 1.0)

enter image description here

更新事实证明,您可以从定向光中获得阴影。通过更改其类型和设置 orthographicScale 修改上面的聚光灯代码。 orthographicScale 的默认值似乎是 1.0,显然不适合大于 1 的场景。

let dLight = SCNLight()
dLight.castsShadow = true
dLight.type = SCNLightTypeDirectional
dLight.zNear = 50
dLight.zFar = 120
dLight.orthographicScale = 30

let dLightNode = SCNNode()
dLightNode.light = dLight
var dLightTransform = SCNMatrix4Identity
dLightTransform = SCNMatrix4Rotate(dLightTransform, -90 * Float(M_PI)/180, 1, 0, 0)
dLightTransform = SCNMatrix4Rotate(dLightTransform, 65 * Float(M_PI)/180, 0, 0, 1)
dLightTransform = SCNMatrix4Rotate(dLightTransform, -20 * Float(M_PI)/180, 0, 1, 0)
dLightTransform = SCNMatrix4Translate(dLightTransform, -20, 50, -10)
dLightNode.transform = dLightTransform
scene.rootNode.addChildNode(dLightNode)

生成以下图像。 Directional light with shadows

场景大小为 60x60,因此在本例中将正交比例设置为 30 会为靠近光源的物体产生阴影。由于渲染阴影贴图时使用的投影(正交与透视)不同,定向光阴影看起来与聚光灯不同。

关于ios - SceneKit:使 block 更逼真或更像 3D,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38215784/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com