Tom van Zummeren
Tom van Zummeren

Reputation: 9220

Render an SCNGeometry as a wireframe

I'm using SceneKit on iOS and I have a geometry I want to render as a wireframe. So basically I want to draw only the lines, so no textures.

I figured out that I could use the shaderModifiers property of the used SCNMaterial to accomplish this. Example of a shader modifier:

material.shaderModifiers = [
    SCNShaderModifierEntryPointFragment: "_output.color.rgb = vec3(1.0) - _output.color.rgb;"
]

This example apparently simply inverts the output colors. I know nothing about this 'GLSL' language I have to use for the shader fragment.

Can anybody tell me what code I should use as the shader fragment to only draw near the edges, to make the geometry look like a wireframe?

Or maybe there is a whole other approach to render a geometry as a wireframe. I would love to hear it.

Upvotes: 12

Views: 7518

Answers (3)

fferri
fferri

Reputation: 18940

Now it is possible (at least in Cocoa) with:

gameView.debugOptions.insert(SCNDebugOptions.showWireframe)

or you can do it interactively if enabling the statistics with:

gameView.showsStatistics = true

(gameView is an instance of SCNView)

Upvotes: 9

Morty
Morty

Reputation: 1484

Try setting the material fillMode to .lines (iOS 11+, and macOS 10.13+):

sphereNode.geometry?.firstMaterial?.fillMode = .lines

Upvotes: 23

rickster
rickster

Reputation: 126117

This is not (quite) an answer, because this a question without an easy answer.

Doing wireframe rendering entirely in shader code is a lot more difficult than it seems like it should be, especially on mobile where you don't have a geometry shader. The problem is that the vertex shader (and subsequently the fragment shader) just doesn't have the information needed to know where polygon edges are.

I know nothing about this 'GLSL' language I have to use for the shader fragment.

If you really want to tackle this problem, you'll need to learn some more about GLSL (the OpenGL Shading Language). There are loads of books and tutorials out there for that.

Once you've got some GLSL under your belt, take a look at some of the questions (like this one pulled from the Related sidebar) and other stuff people have written about the problem. (Note that when you're looking for mobile-specific limitations, OpenGL ES has the same limitations as WebGL on the desktop.)

With SceneKit, you have the additional wrinkle that you probably don't have a barycentric-coordinates vertex attribute (aka SCNGeometrySource) for the geometry you're working with, and you probably don't want to do the hard work of generating one. In OS X, you can use an SCNProgram with a geometryShader to add barycentric coordinates before the vertex/fragment shaders run — but then you have to do your own shading (i.e. you can't piggyback on the SceneKit shading like you can with shader modifiers). And that isn't available in iOS — the hardware there doesn't do geometry shaders. You might be able to fake it using texture coordinates if those happen to be lined up right in your geometry.


It might be easier to just draw the object using lines — try making a new SCNGeometry from the sources and elements of your original (solid) geometry, but when recreating the SCNGeometryElement, use SCNPrimitiveTypeLine.

Upvotes: 3

Related Questions