Skip to content

Instantly share code, notes, and snippets.

@mackhowell
Created May 2, 2018 14:51
Show Gist options
  • Save mackhowell/e6b34f55aaa11226c5dc63a9f8fa9e5a to your computer and use it in GitHub Desktop.
Save mackhowell/e6b34f55aaa11226c5dc63a9f8fa9e5a to your computer and use it in GitHub Desktop.
Swift / iOS silhouette shader modifier
// Fragment Shader Modifier
// Implicit struct to use:
/*
struct SCNShaderOutput {
vec4 color;
} _output;
*/
varying vec3 varyingNormal;
uniform vec3 uniformFragToCamVector;
#pragma transparent
#pragma body
// Testing out outline code from here: https://stackoverflow.com/a/37260904/1751073
float cameraFacingPercentage = dot(normalize(vec4(-uniformFragToCamVector, 1.0)), (vec4(varyingNormal, 1.0) * u_inverseModelTransform));
vec4 outerColor = vec4(1.0, 0.0, 0.0, 1.0);
vec4 innerColor = vec4(0.0, 0.0, 0.0, 0.0);
_output.color = innerColor * cameraFacingPercentage + outerColor * (1.0 - cameraFacingPercentage);
// Vertex Shader Modifier
// Implicit struct to use:
// struct SCNShaderGeometry {
// vec3 position;
// vec3 normal;
// vec4 tangent;
// vec2 texcoords[kSCNTexcoordCount];
// } _geometry;
//
// // Implicit uniforms:
// u_time float - The current system time (in seconds) since SceneKit started rendering with the shader.
// u_boundingBox mat32 - The bounding box of the geometry being rendered, in model space.
// u_modelTransform mat4 - The transform matrices used for converting vertex positions and normals between model, world, view, and clip coordinate spaces.
// u_inverseModelTransform mat4 - The inverse matrices corresponding to each transform.
// u_diffuseTexture sampler2D or samplerCube - The texture contents of the corresponding material property. Declared only if the material property’s contents object provides a texture image.
varying vec3 varyingNormal;
#pragma transparent
#pragma body
varyingNormal = _geometry.normal;
private func handleShader(turn on: Bool) {
if on {
// attach shader snippets from text files
do {
let shaderFileName = "OutlineModifier"
model.geometry?.shaderModifiers = [
// geometry
SCNShaderModifierEntryPoint.geometry: try String(contentsOfFile: Bundle.main.path(forResource: shaderFileName, ofType: "vertex")!, encoding: String.Encoding.utf8),
// fragment
SCNShaderModifierEntryPoint.fragment: try String(contentsOfFile: Bundle.main.path(forResource: shaderFileName, ofType: "fragment")!, encoding: String.Encoding.utf8),
]
let sub = model.worldPosition - currentCamera!.worldPosition
let nsVal = NSValue(scnVector3: sub)
model.geometry?.setValue(nsVal, forKey: "uniformFragToCamVector")
} catch {
assert(false, "could not turn shaders into strings for .shaderModifiers dictionary...")
return
}
} else {
model.geometry?.shaderModifiers = nil
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment