簡體   English   中英

在Scenekit中將半透明圖像添加為紋理

[英]Adding semi-transparent images as textures in Scenekit

當我將半透明圖像( 樣本 )添加為SCNNode的紋理時,如何為圖像透明的節點指定顏色屬性。 由於我可以將顏色或圖像指定為材質屬性,因此無法為節點指定顏色值。 有沒有一種方法可以為材質屬性指定顏色和圖像,還是有解決此問題的方法。

如果要將圖像分配給transparent材質屬性的contents ,則可以將材質的transparencyMode更改為.AOne.RGBZero

  • .AOne表示透明度是從圖像alpha通道派生的。
  • .RGBZero表示透明度是從圖像中的亮度(紅色,綠色和藍色的總和)得出的。

如果沒有自定義着色器,則無法將任意顏色配置為透明。

但是,從示例圖像的外觀來看,我認為將示例圖像分配給transparent材料屬性contents並使用.AOne透明模式將為您提供所需的結果。

我將其發布為新答案,因為它與其他答案不同。


根據您的評論,我了解到您希望將具有透明度的圖像用作材質的漫反射內容,但是無論圖像是透明的,都使用背景色。 換句話說,你不會使用圖像的合成一種顏色為彌漫性內容。

使用UIImage

您可以通過幾種不同的方法來獲得此合成圖像。 最簡單且可能是最熟悉的解決方案是創建一個新的UIImage,以在顏色上繪制圖像。 此新圖像將具有與您的圖像相同的大小和比例,但是由於它具有純色的背景顏色,因此可以是不透明的。

func imageByComposing(image: UIImage, over color: UIColor) -> UIImage {
    UIGraphicsBeginImageContextWithOptions(image.size, true, image.scale)
    defer {
        UIGraphicsEndImageContext()
    }

    let imageRect = CGRect(origin: .zero, size: image.size)
    // fill with background color
    color.set()
    UIRectFill(imageRect)
    // draw image on top
    image.drawInRect(imageRect)

    return UIGraphicsGetImageFromCurrentImageContext()
}

使用此圖像作為漫反射材質屬性的內容,將為您帶來想要的效果。

使用明暗器修改器

如果發現自己不得不非常頻繁地更改顏色(可能需要對其進行動畫處理),則還可以使用自定義着色器或着色器修改器在顏色上合成圖像。

在這種情況下,要復合式 B色圖像A,以便輸出顏色(C O)為:

C O = C A + C B *(1-- A

通過將圖像作為漫反射內容傳遞,並將輸出分配給漫反射內容,可以將表達式簡化為:

Ç = C + C 顏色 *(1 - ɑ 擴散
Ç + = C 顏色 *(1 - ɑ 擴散

通常,輸出Alpha取決於A和B的Alpha,但是由於B(顏色)是不透明的(1),因此輸出Alpha也為1。

可以將其編寫為小的着色器修改器。 由於此解決方案的動機是能夠更改顏色,因此將顏色創建為可在代碼中更新的統一變量。

// Define a color that can be set/changed from code
uniform vec3 backgroundColor;
#pragma body
// Composit A (the image) over B (the color):
//  output = image + color * (1-alpha_image)
float alpha = _surface.diffuse.a;
_surface.diffuse.rgb += backgroundColor * (1.0 - alpha);
// make fully opaque (since the color is fully opaque)
_surface.diffuse.a = 1.0;

然后將從文件中讀取此着色器修改器,並在材質着色器修改器字典中進行設置

enum ShaderLoadingError: ErrorType {
    case FileNotFound, FailedToLoad
}

func shaderModifier(named shaderName: String, fileExtension: String = "glsl") throws -> String {
    guard let url = NSBundle.mainBundle().URLForResource(shaderName, withExtension: fileExtension) else {
        throw ShaderLoadingError.FileNotFound
    }

    do {
        return try String(contentsOfURL: url)
    } catch {
        throw ShaderLoadingError.FailedToLoad
    }
}

// later, in the code that configures the material ...

do {
    let modifier = try shaderModifier(named: "Composit") // the name of the shader modifier file (assuming 'glsl' file extension) 
    theMaterial.shaderModifiers = [SCNShaderModifierEntryPointSurface: modifier]
} catch {
    // Handle the error here
    print(error)
}

然后,您可以通過為材質的“ backgroundColor”設置新值來更改顏色。 注意,沒有初始值,因此必須設置一個。

let backgroundColor = SCNVector3Make(1.0, 0.0, 0.7) // r, g, b

// Set the color components as an SCNVector3 wrapped in an NSValue
// for the same key as the name of the uniform variable in the sahder modifier
theMaterial.setValue(NSValue(SCNVector3: backgroundColor), forKey: "backgroundColor")

如您所見,第一種解決方案比較簡單,如果適合您,我會推薦一種解決方案。 第二種解決方案更復雜,但是可以使背景色具有動畫效果。

以防萬一將來有人遇到此問題...對於某些任務,積解決方案可能是最簡單的。 就我而言,我想在映射到球體的圖像上方顯示網格。 我最初將圖像合成為一個圖像並加以應用,但是隨着時間的流逝,我變得越來越花哨,並且變得越來越復雜。 所以我做了兩個球,一個在另一個。 我將網格放在內部一個上,將圖像放在外部一個上,然后保存...

    let outSphereGeometry = SCNSphere(radius: 20)
    outSphereGeometry.segmentCount = 100
    let outSphereMaterial = SCNMaterial()
    outSphereMaterial.diffuse.contents = topImage
    outSphereMaterial.isDoubleSided = true
    outSphereGeometry.materials = [outSphereMaterial]
    outSphere = SCNNode(geometry: outSphereGeometry)
    outSphere.position = SCNVector3(x: 0, y: 0, z: 0)

    let sphereGeometry = SCNSphere(radius: 10)
    sphereGeometry.segmentCount = 100
    sphereMaterial.diffuse.contents = gridImage
    sphereMaterial.isDoubleSided = true
    sphereGeometry.materials = [sphereMaterial]
    sphere = SCNNode(geometry: sphereGeometry)
    sphere.position = SCNVector3(x: 0, y: 0, z: 0)

令我驚訝的是我不需要設置sphereMaterial.transparency,它似乎是自動獲取的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM