在ARKit框架中通过GLSL渲染材质表面,代码如下:
class ViewController: UIViewController {
@IBOutlet weak var segment: UISegmentedControl!
var scnView: ARSCNView!
var planMaterial:SCNMaterial!
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
self.scnView = ARSCNView(frame: view.frame)
// 设置配置模式为WorldTracking
let config = ARWorldTrackingConfiguration()
config.planeDetection = .horizontal // 设置识别水平平面
self.scnView.session.run(config)
self.view.addSubview(self.scnView)
let orthographicCameraNode = SCNNode()
orthographicCameraNode.camera = SCNCamera()
orthographicCameraNode.camera?.usesOrthographicProjection = true
orthographicCameraNode.position = SCNVector3(0, 0, 1)
makePlane()
let titles = ["rainbowSwirlFragment", "warpLineFragment", "morphGridFragment", "waterColorFragmet", "polarCoordinatesFragment", "textureFragment", "scanImageFragment"]
for i in 0..<7 {
segment.setTitle(titles[i], forSegmentAt: i)
}
self.view.bringSubviewToFront(segment)
}
// 创建展示材质的平面
func makePlane() {
let plane = SCNPlane(width: 0.5, height: 0.5)
let planeNode = SCNNode(geometry: plane)
planMaterial = planeNode.geometry!.firstMaterial
planeNode.position = SCNVector3(0, -0.5, -1)
setDefaultShader()
self.scnView.scene.rootNode.addChildNode(planeNode)
}
func setDefaultShader() {
let mapFragment = try! String(contentsOf: Bundle.main.url(forResource: "rainbowSwirlFragment", withExtension: "shader")!, encoding: String.Encoding.utf8)
let shaderModifiers = [SCNShaderModifierEntryPoint.fragment:mapFragment];
planMaterial?.shaderModifiers = shaderModifiers
}
@IBAction func segmentValueChanged(_ sender: UISegmentedControl) {
// 根据segment加载对应的shader
switch sender.selectedSegmentIndex {
case 0:
// 加载相应的shader并设置到平面材质上
let mapFragment = try! String(contentsOf: Bundle.main.url(forResource: "rainbowSwirlFragment", withExtension: "shader")!, encoding: String.Encoding.utf8)
let shaderModifiers = [SCNShaderModifierEntryPoint.fragment:mapFragment];
planMaterial?.shaderModifiers = shaderModifiers
case 1:
let mapFragment = try! String(contentsOf: Bundle.main.url(forResource: "warpLineFragment", withExtension: "shader")!, encoding: String.Encoding.utf8)
let shaderModifiers = [SCNShaderModifierEntryPoint.fragment:mapFragment];
planMaterial?.shaderModifiers = shaderModifiers
case 2:
let mapFragment = try! String(contentsOf: Bundle.main.url(forResource: "morphGridFragment", withExtension: "shader")!, encoding: String.Encoding.utf8)
let shaderModifiers = [SCNShaderModifierEntryPoint.fragment:mapFragment];
planMaterial?.shaderModifiers = shaderModifiers
case 3:
let mapFragment = try! String(contentsOf: Bundle.main.url(forResource: "waterColorFragmet", withExtension: "shader")!, encoding: String.Encoding.utf8)
let shaderModifiers = [SCNShaderModifierEntryPoint.fragment:mapFragment];
planMaterial?.shaderModifiers = shaderModifiers
case 4:
let mapFragment = try! String(contentsOf: Bundle.main.url(forResource: "polarCoordinatesFragment", withExtension: "shader")!, encoding: String.Encoding.utf8)
let shaderModifiers = [SCNShaderModifierEntryPoint.fragment:mapFragment];
planMaterial?.shaderModifiers = shaderModifiers
case 5:
let mapFragment = try! String(contentsOf: Bundle.main.url(forResource: "textureFragment", withExtension: "shader")!, encoding: String.Encoding.utf8)
let shaderModifiers = [SCNShaderModifierEntryPoint.fragment:mapFragment];
let img1 = UIImage(named: "uv_grid.jpg")
let img2 = UIImage(named: "ChristmasTreeOrnament02_col.jpg")
planMaterial?.shaderModifiers = shaderModifiers
// 根据shader中的id传入相应的图片
planMaterial?.setValue(SCNMaterialProperty(contents: img1!), forKey: "texture1")
planMaterial?.setValue(SCNMaterialProperty(contents: img2!), forKey: "texture2")
case 6:
let mapFragment = try! String(contentsOf: Bundle.main.url(forResource: "scanImageFragment", withExtension: "shader")!, encoding: String.Encoding.utf8)
let shaderModifiers = [SCNShaderModifierEntryPoint.fragment:mapFragment];
let img = UIImage(named: "ChristmasTreeOrnament02_col.jpg")
planMaterial?.shaderModifiers = shaderModifiers
planMaterial?.setValue(SCNMaterialProperty(contents: img!), forKey: "texture")
default:
return
}
}
private func image(named imageName: String) -> UIImage {
return UIImage(named: imageName, in: Bundle.main, compatibleWith: nil)!
}
private func shaderModifier(named shaderModifierName: String) -> String {
return try! String(contentsOfFile: Bundle.main.path(forResource: shaderModifierName, ofType: "shader")!, encoding: String.Encoding.utf8)
}
}
效果图:
![](https://img.haomeiwen.com/i2200575/9da785f0e613b388.gif)
![](https://img.haomeiwen.com/i2200575/bda4607ea5a45171.gif)
对应的shader:
vec2 coord = fract(_surface.diffuseTexcoord);
vec3 color = vec3(0.0);
float angle = atan((-coord.y + 0.25)/(coord.x - 0.5)) * 0.1;
float len = length(coord - vec2(0.5, 0.25));
color.r += sin(len * 40.0 + angle * 40.0 + u_time);
color.g += cos(len * 30.0 + angle * 60.0 - u_time);
color.b += sin(len * 50.0 + angle * 40.0 + u_time);
_output.color.rgb = color;
vec2 coord = vec2(1.0) - _surface.diffuseTexcoord;
float color = 0.0;
color += sin(coord.x * 50.0 + cos(u_time + coord.y * 10.0 + sin(coord.x * 50.0 + u_time))) * 2.0;
color += cos(coord.x * 20.0 + sin(u_time + coord.y * 10.0 + cos(coord.x * 50.0 + u_time))) * 2.0;
color += sin(coord.x * 30.0 + cos(u_time + coord.y * 10.0 + sin(coord.x * 50.0 + u_time))) * 2.0;
color += cos(coord.x * 10.0 + sin(u_time + coord.y * 10.0 + cos(coord.x * 50.0 + u_time))) * 2.0;
_output.color.rgb = vec3(color + coord.y, color + coord.x, color);
float random2d(vec2 coord)
{
return fract(sin(dot(coord.xy, vec2(12.9898, 78.233))) * 43758.5453);
}
#pragma transparent
#pragma arguments
#pragma body
vec2 coord = (_surface.diffuseTexcoord / vec2(0.2));
coord -= u_time + vec2(sin(coord.y), cos(coord.x));
vec3 color = vec3(0.0);
float rand01 = fract(random2d(floor(coord)) + u_time / 60.0);
float rand02 = fract(random2d(floor(coord)) + u_time / 40.0);
rand01 *= 0.4 - length(fract(coord));
_output.color.rgb = vec3(rand01 * 4.0, rand02 * rand01 * 4.0, 0.0);
vec2 coord = 6.0 * _surface.diffuseTexcoord;
for(int n = 1; n < 10; n++) {
float i = float(n);
coord += vec2(0.7 / i * sin(i * coord.y + u_time + 0.3 * i) + 0.8, 0.4 / i * sin(coord.x + u_time + 0.3 * i) + 1.6);
}
// coord *= vec2(0.7 / sin(coord.y + u_time + 0.3) + 0.8, 0.4 / sin(coord.x + u_time + 0.3) + 1.6);
vec3 color = vec3(0.5 * sin(coord.x) + 0.5, 0.5 * sin(coord.y) + 0.5, sin(coord.x + coord.y));
gl_FragColor = vec4(color, 1.0);
vec2 coord = _surface.diffuseTexcoord;
vec4 color = vec4(0.0);
vec2 pos = vec2(0.5) - coord;
float r = length(pos) * 2.0;
float a = atan(pos.y / pos.x);
float f = cos(a * 6.0);
color = vec4(1.0 - smoothstep(f, f + 0.01, r));
gl_FragColor = color;
#pragma arguments
texture2d<float, access::sample> texture1;
texture2d<float, access::sample> texture2;
#pragma body
constexpr sampler smp(filter::linear, address::repeat);
float4 color1 = texture1.sample(smp, _surface.diffuseTexcoord);
float4 color2 = texture2.sample(smp, _surface.diffuseTexcoord);
float mixValue = 0.5 + scn_frame.sinTime * 0.5;
_output.color.rgba = mix(color1, color2, mixValue);
#pragma transparent
#pragma arguments
texture2d<float, access::sample> texture;
#pragma body
float size = 6.0;
float speed = -3.0;
constexpr sampler smp(filter::linear, address::repeat);
float4 color = texture.sample(smp, _surface.diffuseTexcoord);
color.a = sin(floor(_surface.diffuseTexcoord.x * size) - scn_frame.time * speed);
_output.color.rgba = color;
网友评论