美文网首页
ARKit中通过GLSL渲染平面

ARKit中通过GLSL渲染平面

作者: 浪淘沙008 | 来源:发表于2023-04-09 09:29 被阅读0次

在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;

相关文章

网友评论

      本文标题:ARKit中通过GLSL渲染平面

      本文链接:https://www.haomeiwen.com/subject/eeqbddtx.html