首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么在定制的SCNGeometry中黑色的颜色比在SCNSphere中要轻

为什么在定制的SCNGeometry中黑色的颜色比在SCNSphere中要轻
EN

Stack Overflow用户
提问于 2021-09-23 02:05:57
回答 1查看 89关注 0票数 0

在这个场景中

左边的球面列是用SCNSphere()

  • the创建的,右边的“圆圈”列是用SCNGeometry()创建的,使用的是.point

  • 只是一个环境光源,

  • 所有的几何图形都使用.constant照明模型

  • ,每个球体使用相同的RGB值来定义颜色。H 214f 215

为什么最后两对圆圈的黑色阴影比它们的等距球体要轻呢?

完整的操场代码来复制这些图像:

创造场景

代码语言:javascript
复制
import UIKit
import SceneKit
import PlaygroundSupport

// Constants I'm using for the darkest grey colour
let B_RED: CGFloat = 0.05
let B_GREEN: CGFloat = 0.05
let B_BLUE: CGFloat = 0.05
let B_ALPHA: CGFloat = 1.0

let BLACK_COLOUR = UIColor(red: B_RED, green: B_GREEN, blue: B_BLUE, alpha: B_ALPHA)

let scene: SCNScene = {
    let s = SCNScene()
    return s
}()

let sceneView: SCNView = {
    let v = SCNView(frame: CGRect(x: 0, y: 0, width: 600, height: 800))
    v.scene = scene
    v.backgroundColor = UIColor(white: 0.66, alpha: 1.0)
    v.allowsCameraControl = true
    v.debugOptions = [SCNDebugOptions.showLightInfluences]
    v.backgroundColor
    return v
}()

let ambientLigntNode: SCNNode = {
    let n = SCNNode()
    n.light = SCNLight()
    n.light!.type = SCNLight.LightType.ambient
    n.light!.color = UIColor(white: 1, alpha: 1.0)
    return n
}()

PlaygroundPage.current.liveView = sceneView

// a camera
var cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
cameraNode.simdPosition = simd_float3(0,0,8)

scene.rootNode.addChildNode(cameraNode)
scene.rootNode.addChildNode(ambientLigntNode)

球柱

代码语言:javascript
复制
// ----------------------------------------------------
// White Sphere
let whiteSphere = SCNSphere(radius: 0.3)
let whiteMaterial = SCNMaterial()
whiteMaterial.diffuse.contents = simd_float3(1,1,1)

whiteMaterial.lightingModel = .constant
whiteSphere.materials = [whiteMaterial]

let whiteSphereNode = SCNNode(geometry: whiteSphere)
whiteSphereNode.simdPosition = simd_float3(-1,2,0)

scene.rootNode.addChildNode(whiteSphereNode)

// ----------------------------------------------------
// Black Sphere
let blackSphere = SCNSphere(radius: 0.3)
let blackMaterial = SCNMaterial()
blackMaterial.diffuse.contents = BLACK_COLOUR

blackMaterial.lightingModel = .constant
blackSphere.materials = [blackMaterial]

let blackSphereNode = SCNNode(geometry: blackSphere)
blackSphereNode.simdPosition = simd_float3(-1,-2,0)

scene.rootNode.addChildNode(blackSphereNode)

// ----------------------------------------------------
// Red Sphere
let redSphere = SCNSphere(radius: 0.3)
let redMaterial = SCNMaterial()
redMaterial.diffuse.contents = UIColor(
    red: 1.0,
    green: 0.0,
    blue: 0.0,
    alpha: 1.0
)

redMaterial.lightingModel = .constant
redSphere.materials = [redMaterial]

let redSphereNode = SCNNode(geometry: redSphere)
redSphereNode.simdPosition = simd_float3(-1, 1, 0)

scene.rootNode.addChildNode(redSphereNode)

// ----------------------------------------------------
// Green Sphere
let greenSphere = SCNSphere(radius: 0.3)
let greenMaterial = SCNMaterial()
greenMaterial.diffuse.contents = UIColor(
    red: 0.0,
    green: 1.0,
    blue: 0.0,
    alpha: 1.0
)

greenMaterial.lightingModel = .constant
greenSphere.materials = [greenMaterial]

let greenSphereNode = SCNNode(geometry: greenSphere)
greenSphereNode.simdPosition = simd_float3(-1, 0, 0)

scene.rootNode.addChildNode(greenSphereNode)

// ----------------------------------------------------
// Blue Sphere
let blueSphere = SCNSphere(radius: 0.3)
let blueMaterial = SCNMaterial()
blueMaterial.diffuse.contents = UIColor(
    red: 0.0,
    green: 0.0,
    blue: 1.0,
    alpha: 1.0
)

blueMaterial.lightingModel = .constant
blueSphere.materials = [blueMaterial]

let blueSphereNode = SCNNode(geometry: blueSphere)
blueSphereNode.simdPosition = simd_float3(-1, -1, 0)

scene.rootNode.addChildNode(blueSphereNode)

// ----------------------------------------------------
// Grey Sphere
let greySphere = SCNSphere(radius: 0.3)
let greyMaterial = SCNMaterial()
greyMaterial.diffuse.contents = UIColor(
    red: 0.5,
    green: 0.5,
    blue: 0.5,
    alpha: 1.0
)

greyMaterial.lightingModel = .constant
greySphere.materials = [greyMaterial]

let greySphereNode = SCNNode(geometry: greySphere)
greySphereNode.simdPosition = simd_float3(-1, -3, 0)

scene.rootNode.addChildNode(greySphereNode)

圆柱形

代码语言:javascript
复制
// ----------------------------------------------------
// Custom SCNGeometry using vertex data
struct Vertex {
    let x: Float
    let y: Float
    let z: Float
    let r: Float
    let g: Float
    let b: Float
    let a: Float
}

let vertices: [Vertex] = [
    Vertex(x: 0.0, y: 2.0, z: 0.0, r: 1.0, g: 1.0, b: 1.0, a: 1.0),  // white
    Vertex(x: 0.0, y: 1.0, z: 0.0, r: 1.0, g: 0.0, b: 0.0, a: 1.0),  // red
    Vertex(x: 0.0, y: 0.0, z: 0.0, r: 0.0, g: 1.0, b: 0.0, a: 1.0),  // green
    Vertex(x: 0.0, y: -1.0, z: 0.0, r: 0.0, g: 0.0, b: 1.0, a: 1.0), // blue
    Vertex(x: 0.0, y: -3.0, z: 0.0, r: 0.5, g: 0.5, b: 0.5, a: 1.0), // rgb
    Vertex(
        x: 0.0, y: -2.0, z: 0.0,
        r: Float(B_RED), g: Float(B_GREEN), b: Float(B_BLUE), a: Float(B_ALPHA)
    )
]

let vertexData = Data(
    bytes: vertices,
    count: MemoryLayout<Vertex>.size * vertices.count
)

let positionSource = SCNGeometrySource(
    data: vertexData,
    semantic: SCNGeometrySource.Semantic.vertex,
    vectorCount: vertices.count,
    usesFloatComponents: true,
    componentsPerVector: 3,
    bytesPerComponent: MemoryLayout<Float>.size,
    dataOffset: 0,
    dataStride: MemoryLayout<Vertex>.size
)
let colourSource = SCNGeometrySource(
    data: vertexData,
    semantic: SCNGeometrySource.Semantic.color,
    vectorCount: vertices.count,
    usesFloatComponents: true,
    componentsPerVector: 4,
    bytesPerComponent: MemoryLayout<Float>.size,
    dataOffset: MemoryLayout<Float>.size * 3,
    dataStride: MemoryLayout<Vertex>.size
)

let elements = SCNGeometryElement(
    data: nil,
    primitiveType: .point,
    primitiveCount: vertices.count,
    bytesPerIndex: MemoryLayout<Int>.size
)

elements.pointSize = 100
elements.minimumPointScreenSpaceRadius = 100
elements.maximumPointScreenSpaceRadius = 100

let spheres = SCNGeometry(
    sources: [positionSource, colourSource],
    elements: [elements]
)
let sphereNode = SCNNode(geometry: spheres)

let sphereMaterial = SCNMaterial()
sphereMaterial.lightingModel = .constant


spheres.materials = [sphereMaterial]

sphereNode.simdPosition = simd_float3(0,0,0)
scene.rootNode.addChildNode(sphereNode)

根据已接受的答案更新。从sRGB转换到LinearRGB的结果是相同的

代码语言:javascript
复制
func srgbToLinear(x: Float) -> Float {
    if x <= 0.04045 {
        return x / 12.92;
    }
    return powf((x + 0.055) / 1.055, 2.4)
}

let vertices: [Vertex] = [
    Vertex(x: 0.0, y: 2.0, z: 0.0, r: 1.0, g: 1.0, b: 1.0, a: 1.0),  // white
    Vertex(x: 0.0, y: 1.0, z: 0.0, r: 1.0, g: 0.0, b: 0.0, a: 1.0),  // red
    Vertex(x: 0.0, y: 0.0, z: 0.0, r: 0.0, g: 1.0, b: 0.0, a: 1.0),  // green
    Vertex(x: 0.0, y: -1.0, z: 0.0, r: 0.0, g: 0.0, b: 1.0, a: 1.0), // blue
    Vertex(x: 0.0, y: -3.0, z: 0.0, r: srgbToLinear(x: 0.5), g: srgbToLinear(x: 0.5), b: srgbToLinear(x: 0.5), a: 1.0), // rgb
    Vertex(
        x: 0.0, y: -2.0, z: 0.0,
        r: srgbToLinear(x: Float(B_RED)),
        g: srgbToLinear(x: Float(B_GREEN)),
        b: srgbToLinear(x: Float(B_GREEN)),
        a: 1.0
    )
]

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-09-23 02:50:34

如果在不同的颜色空间中生成两种类型的图形,就会出现这种情况。例如,如果球的灰色被解释为位于sRGB中的颜色空间,而圆圈被解释为通用的RGB空间,那么您将看到颜色值的不同。

考虑以下操场守则:

代码语言:javascript
复制
//: A UIKit based Playground for presenting user interface
  
import UIKit
import PlaygroundSupport
import CoreGraphics

class MyViewController : UIViewController {
    override func loadView() {
        let view = CustomView()
        view.backgroundColor = UIColor.darkGray

        self.view = view
    }
}

class CustomView : UIView {
    override func draw(_ rect: CGRect) {
        if let cgContext = UIGraphicsGetCurrentContext() {

            cgContext.saveGState()

            let gray : [CGFloat] = [0.5, 0.5, 0.5, 1.0]


            let srgbGray = CGColor(
                colorSpace: CGColorSpace(name: CGColorSpace.sRGB)!, components: gray)!

            cgContext.setFillColor(srgbGray)
            cgContext.fillEllipse(in: CGRect(x:10, y:20, width:72, height: 72))

            let genericGray = CGColor(colorSpace: CGColorSpace(name: CGColorSpace.genericRGBLinear)!, components: gray)!
            cgContext.setFillColor(genericGray)
            cgContext.fillEllipse(in: CGRect(x:110, y:20, width:72, height: 72))


            cgContext.restoreGState()

        }
    }
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()

它所产生的效果几乎与你所看到的效果相同。我怀疑圆圈是在假定一个通用颜色空间的情况下绘制的,而球面则是假定为sRGB绘制的。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69293176

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档