黑色背景上的Scenekit透明度

黑色背景上的Scenekit透明度,scenekit,Scenekit,我目前正在学习如何使用scenekit,在透明对象方面遇到了一些问题。我已经写了一个着色器来增加正面观察人脸时的透明度,当我选择白色背景时,一切都按预期进行 但当我选择黑色背景时,对象的行为就好像它是完全不透明的 这是我的视图控制器代码 import Cocoa import SceneKit import SceneKit.ModelIO struct shaderSettings { var Color: vector_float4 var minTransparency:

我目前正在学习如何使用scenekit,在透明对象方面遇到了一些问题。我已经写了一个着色器来增加正面观察人脸时的透明度,当我选择白色背景时,一切都按预期进行

但当我选择黑色背景时,对象的行为就好像它是完全不透明的

这是我的视图控制器代码

import Cocoa
import SceneKit
import SceneKit.ModelIO

struct shaderSettings {
    var Color: vector_float4
    var minTransparency: Float
}

class ViewController: NSViewController {

    var scnView: SCNView!
    var scnScene: SCNScene!

    override func viewDidLoad() {
        super.viewDidLoad()
        scnView = self.view as! SCNView
        scnScene = SCNScene()
        scnView.scene = scnScene
        scnView.allowsCameraControl = true
        scnView.backgroundColor = NSColor.black

        //load mesh
        let url = URL(fileURLWithPath: "monkey.obj")
        let monkey = MDLAsset(url: url).object(at: 0)
        let node = SCNNode(mdlObject: monkey)
        node.name = "monkey"

        //use metal shader
        let program = SCNProgram();
        program.vertexFunctionName = "vert";
        program.fragmentFunctionName = "frag";
        program.isOpaque = false

        //setup material
        var s = shaderSettings(Color: vector_float4(1, 0, 0, 1) ,minTransparency: 0.3)
        let mat = SCNMaterial();
        mat.program = program;
        mat.setValue(NSData(bytes: &s, length: MemoryLayout<shaderSettings>.stride), forKey: "s")
        mat.blendMode = SCNBlendMode.alpha
        mat.writesToDepthBuffer = false
        mat.readsFromDepthBuffer = false
        mat.cullMode = SCNCullMode.back

        //create node
        node.geometry!.firstMaterial = mat
        scnScene.rootNode.addChildNode(node)

    }

    override func viewDidDisappear() {
        //quit when window closes
        exit(0)
    }
}
导入可可粉
导入SceneKit
导入SceneKit.ModelIO
结构着色器设置{
变量颜色:向量_float4
var最小透明度:浮动
}
类ViewController:NSViewController{
var scnView:scnView!
变量scnScene:scnScene!
重写func viewDidLoad(){
super.viewDidLoad()
scnView=self.view as!scnView
scnScene=scnScene()
scnView.scene=scnScene
scnView.allowsCameraControl=true
scnView.backgroundColor=NSColor.black
//负荷网
让url=url(fileURLWithPath:“monkey.obj”)
让monkey=MDLAsset(url:url).object(位于:0)
let node=SCNNode(mdlObject:monkey)
node.name=“monkey”
//使用金属着色器
让程序=SCNProgram();
program.vertexFunctionName=“vert”;
program.fragmentFunctionName=“frag”;
program.isOpaque=false
//设置材料
var s=着色器设置(颜色:vector_float4(1,0,0,1),最小透明度:0.3)
设mat=SCNMaterial();
mat.program=程序;
mat.setValue(NSData(字节:&s,长度:MemoryLayout.stride),forKey:“s”)
mat.blendMode=SCNBlendMode.alpha
mat.writesToDepthBuffer=false
mat.readsFromDepthBuffer=false
mat.cullMode=SCNCullMode.back
//创建节点
node.geometry!.firstMaterial=mat
scnScene.rootNode.addChildNode(节点)
}
覆盖函数ViewDidDemouse(){
//窗口关闭时退出
出口(0)
}
}
虽然我认为问题不在这里,但这是我的着色器程序

#include <metal_stdlib>
using namespace metal;
#include <metal_geometric>
#include <metal_common>
#include <SceneKit/scn_metal>



struct settings {
    float4 Color;
    float minTransparency;
};


typedef struct {
    float4 pos [[ attribute(SCNVertexSemanticPosition) ]];
    float4 norm  [[ attribute(SCNVertexSemanticNormal) ]];
} Input;

typedef struct {
    float4 pos [[position]];
    float3 camDir;
    float3 norm;
} v2f;

struct nodeBuffer {
    float4x4 modelViewProjectionTransform;
    float4x4 modelViewTransform;
    float4x4 normalTransform;
};

vertex v2f vert(Input in [[ stage_in ]],
                constant SCNSceneBuffer& scn_frame [[buffer(0)]],
                constant nodeBuffer& scn_node [[buffer(1)]]) {
    v2f o;
    o.pos = scn_node.modelViewProjectionTransform * in.pos;
    o.norm = normalize(float3(scn_node.normalTransform * in.norm));
    o.camDir = normalize(float3(scn_node.modelViewTransform*in.pos));
    return o;
}

fragment half4 frag(v2f in [[stage_in]], constant settings& s [[buffer(2)]]) {
    float nDotCam = abs(dot(float3(in.norm), float3(-in.camDir)));
    half4 col;

    col.rgb = half3(s.Color.rgb);
    col.a = half(mix(s.Color.a, s.minTransparency, nDotCam));
    return col;
}
#包括
使用金属;
#包括
#包括
#包括
结构设置{
4色;
透明性;
};
类型定义结构{
float4 pos[[属性(SCNVertexSemanticPosition)];
float4范数[[属性(SCNVertexSemanticNormal)];
}输入;
类型定义结构{
浮动4位[[位置]];
camDir;
3常模;
}v2f;
结构nodeBuffer{
float4x4 modelViewProjectionTransform;
float4x4modelviewtransform;
浮动4x4法线变换;
};
顶点v2f顶点(在[[stage_in]]中输入),
恒定SCNSceneBuffer和scn_帧[[buffer(0)],
常量节点缓冲区和scn_节点[[缓冲区(1)]){
v2fo;
o、 pos=scn_node.modelViewProjectionTransform*in.pos;
o、 norm=normalize(float3(scn_node.normalTransform*in.norm));
o、 camDir=normalize(float3(scn_node.modelViewTransform*in.pos));
返回o;
}
碎片半4碎片(v2f在[[stage_in]],常数设置和s[[buffer(2)]){
float nDotCam=abs(点(float3(in.norm),float3(-in.camDir));
半4柱;
col.rgb=half3(s.Color.rgb);
col.a=一半(混合(s.Color.a,s.minTransparency,nDotCam));
返回列;
}
谢谢你的时间

我明白了。我读到scenekit假设字母是预乘的,所以我加了一句

col.rgb *= col.a;
在片段着色器中返回之前,现在可以正常工作