How do I add transparency with a shader in SceneKit?

I would like to have a transparent effect on the image, now I am just testing with a torus, but the shader doesn't seem to work with alpha. From what I understood from this thread ( Using Related Functions in Scenekit ) and this wiki link on transparency: ( http://en.wikibooks.org/wiki/GLSL_Programming/GLUT/Transparency ) is GLBlendFunc

replaced with pragma transparency

in SceneKit.

Do you know what is wrong with this code?

I created a new project using SceneKit and I changed the ship's mesh for the torus.


EDIT:
I'm trying with a plane, but the image below doesn't appear inside the plane, instead I get an image with red and brownish rectangles below.

My image with alpha:

enter image description here

Result (the image with alpha should replace the brownish color):

enter image description here

let plane = SCNPlane(width: 2, height: 2)
var texture = SKTexture(imageNamed:"small")
texture.filteringMode = SKTextureFilteringMode.Nearest
plane.firstMaterial?.diffuse.contents = texture
let ship = SCNNode(geometry: plane) //SCNTorus(ringRadius: 1, pipeRadius: 0.5)
ship.position = SCNVector3(x: 0, y: 0, z: 15)
scene.rootNode.addChildNode(ship)

let myscale : CGFloat = 10
let box = SCNBox(width: myscale, height: myscale, length: myscale, chamferRadius: 0)
box.firstMaterial?.diffuse.contents = UIColor.redColor()
let theBox = SCNNode(geometry: box)
theBox.position = SCNVector3(x: 0, y: 0, z: 5)
scene.rootNode.addChildNode(theBox)


let scnView = self.view as SCNView
scnView.scene = scene
scnView.backgroundColor = UIColor.blackColor()


var shaders = NSMutableDictionary()
shaders[SCNShaderModifierEntryPointFragment] = String(contentsOfFile: NSBundle.mainBundle().pathForResource("test", ofType: "shader")!, encoding: NSUTF8StringEncoding, error: nil)
var material = SCNMaterial()
material.shaderModifiers = shaders
ship.geometry?.materials = [material]

      

Shader:

#pragma transparent
#pragma body
_output.color.rgba = vec4(0.0, 0.2, 0.0, 0.2);

      

+3


source to share


3 answers


SceneKit uses pre-multiplied alpha values ​​( r

, g

and b

), which must be multiplied by the desired a

):



vec4(0.0, 0.2, 0.0, 0.2); // `vec4(0.0, 1.0, 0.0, 1.0) * alpha` with alpha = 0.2

      

+3


source


Adding transparency can easily be done at the insertion point of a SCNShadable

surface or fragment

Access point version SCNShaderModifierEntryPointSurface

#pragma transparent
#pragma body

_surface.diffuse.a = 0.5;

      



SCN entry point versionShaderModifierEntryPointFragment

#pragma transparent
#pragma body

_output.color.a = 0.5;

      

+2


source


I was struggling with this problem too. Finally I found out that for the C # pragma transparent to work, I had to add it in a different shader than the one my transparency code is doing.

For example, I added transparency code to the surface shader and added '#pragma transparent' to the geometry shader. Apple API doc also added "#pragma transparent" to geometry shader, don't know if they were designed for that.

NSString *geometryScript = @""
"#pragma transparent";

NSString *surfaceScript = @""
//"#pragma transparent" // You must not put it together with the transparency code
"float a = 0.1;"
"_surface.diffuse = vec4(_surface.diffuse.rgb * a, a);";

// This works for the transparency code in surface shader too.
//NSString *fragmentScript = @""
//"#pragma transparent";

yourMaterial.shaderModifiers = @{SCNShaderModifierEntryPointGeometry:geometryScript,
SCNShaderModifierEntryPointSurface:surfaceScript};

      

This code works in iOS 11.2, Xcode 9.2.

This rule also applies to the SCNShaderModifierEntryPointFragment shader. Likewise, if you want to change the transparency there, you can add '#pragma transparent' to the geometry or surface shader. I have not tested the SCNShaderModifierEntryPointLightingModel shader.

If you don't add "transparent" # pragma to the shader, the black background can be blended with transparent pixels.

+2


source







All Articles