ARKit中通过GLSL渲染平面

在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)
    }
}

效果图:

shader材质.gif
shader材质1.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;
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,490评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,581评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,830评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,957评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,974评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,754评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,464评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,357评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,847评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,995评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,137评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,819评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,482评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,023评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,149评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,409评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,086评论 2 355