Jos*_*eph 4 ios scenekit swift
我正在开发一个关于太阳系的应用程序.我试图关闭发射纹理,光线照射到行星表面.但问题是,默认情况下,发射纹理总是显示发射点,无论光线是否存在.
我的要求简而言之:(我想隐藏发光点,在光线照射到表面的地方) 
override func viewDidLoad() {
super.viewDidLoad()
let scene = SCNScene()
let earth = SCNSphere(radius: 1)
let earthNode = SCNNode()
let earthMaterial = SCNMaterial()
earthMaterial.diffuse.contents = UIImage(named: "earth.jpg")
earthMaterial.emission.contents = UIImage(named: "earthEmission.jpg")
earth.materials = [earthMaterial]
earthNode.geometry = earth
scene.rootNode.addChildNode(earthNode)
let lightNode = SCNNode()
lightNode.light = SCNLight()
lightNode.light?.type = .omni
lightNode.position = SCNVector3(x: 0, y: 10, z: 5)
scene.rootNode.addChildNode(lightNode)
sceneView.scene = scene
}
Run Code Online (Sandbox Code Playgroud)
SceneKit的着色器修改器非常适合这种任务.
您可以在此处查看最终结果的镜头.
我们可以使用_lightingContribution.diffuse(RGB(vec3)颜色表示应用于漫反射的灯光)来确定被照亮的对象(在本例中为地球)的区域,然后使用它来掩盖片段着色器修改器中的发射纹理.
你使用它的方式取决于你.这是我提出的最简单的解决方案(使用GLSL语法,但Metal如果你使用它将在运行时自动转换)
uniform sampler2D emissionTexture;
vec3 light = _lightingContribution.diffuse;
float lum = max(0.0, 1 - (0.2126*light.r + 0.7152*light.g + 0.0722*light.b)); // 1
vec4 emission = texture2D(emissionTexture, _surface.diffuseTexcoord) * lum; // 2, 3
_output.color += emission; // 4
Run Code Online (Sandbox Code Playgroud)
_lightingContribution.diffuse(如果照明不是纯白色)这就是着色器部分,现在让我们通过Swift方面的东西.
首先,我们不会使用emission.contents材料的属性,而是需要创建自定义SCNMaterialProperty
let emissionTexture = UIImage(named: "earthEmission.jpg")!
let emission = SCNMaterialProperty(contents: emissionTexture)
Run Code Online (Sandbox Code Playgroud)
并使用它将其设置为材料 setValue(_:forKey:)
earthMaterial.setValue(emission, forKey: "emissionTexture")
Run Code Online (Sandbox Code Playgroud)
密切关注键 - 它应该与着色器修改器中的制服相同.此外,您不需要自己保留材质属性,setValue创建强大的参考.
剩下要做的就是将片段着色器修改器设置为材质:
let shaderModifier =
"""
uniform sampler2D emissionTexture;
vec3 light = _lightingContribution.diffuse;
float lum = max(0.0, 1 - (0.2126*light.r + 0.7152*light.g + 0.0722*light.b));
vec4 emission = texture2D(emissionTexture, _surface.diffuseTexcoord) * lum;
_output.color += emission;
"""
earthMaterial.shaderModifiers = [.fragment: shaderModifier]
Run Code Online (Sandbox Code Playgroud)
这是运动中着色器修改器的素材.
请注意,光源必须非常明亮,否则会在"地球"周围看到昏暗的灯光.我必须lightNode.light?.intensity在你的设置中设置至少2000才能按预期工作.您可能希望尝试计算发光度并应用于发射以获得更好结果的方式.
如果你可能需要它,_lightingContribution是有也有片段着色器修改现有的结构ambient和specular成员(以下是Metal语法):
struct SCNShaderLightingContribution {
float3 ambient;
float3 diffuse;
float3 specular;
} _lightingContribution;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1118 次 |
| 最近记录: |