2016-11-02 14 views
6

Tôi đang cố gắng tạo ứng dụng ios 9 cho một dự án sẽ hình dung cảnh 3D với các loại ống kính lý thuyết đặc biệt này được gọi là glenses.Mô phỏng khúc xạ trong SceneKit

Một chương trình dò ​​tia được gọi là TIM đã được viết từ đầu để mô phỏng các kính lúp này và hơn thế nữa, nhưng không thể chỉ đơn giản là chuyển cổng này sang ios.

Sự hiểu biết của tôi khi tìm kiếm trang web (tức là this câu trả lời và nhiều người khác trên trình đổ bóng) là điều đó có thể thực hiện được nhưng tôi gặp khó khăn trong việc đạt được hiệu quả mong muốn.

tôi quyết định rằng tôi sẽ bắt đầu bằng cách thực hiện một hình thức đơn giản của khúc xạ đầu tiên trước khi chuyển sang glens loại phức tạp hơn khúc xạ:

tôi đã có thể để có được một hình ảnh bị méo (ống kính mắt cá) có hiệu lực làm việc trên máy ảnh sử dụng SCNTechnique, tuy nhiên có vẻ như bạn chỉ có thể sử dụng các kỹ thuật trên máy ảnh hoặc toàn cảnh, không phải từng phần hình học.

Sau đó tôi đã cố gắng để có được hiệu quả hình ảnh bị méo áp dụng cho các hình học bằng cách tiêm đang OpenGL sử dụng shaderModifiers tài sản 's SCNMaterial:

var shaders = [SCNShaderModifierEntryPoint: String]() 

    try! shaders[SCNShaderModifierEntryPoint.fragment] = String(contentsOfFile: Bundle.main.path(forResource: "FishEye", ofType: "fsh")!, encoding: String.Encoding.utf8) 

    try! shaders[SCNShaderModifierEntryPoint.geometry] = String(contentsOfFile: Bundle.main.path(forResource: "FishEye", ofType: "vsh")!, encoding: String.Encoding.utf8) 

    let material = SCNMaterial() 
    material.shaderModifiers = shaders 
    object.geometry?.materials = [material] 
shaders

Tôi đã sử dụng một chút thay đổi thấy here:

fisheye.vsh

varying vec2 uv; 

#pragma body 

gl_Position = a_position; 
uv = a_position.xy; 

fisheye.fsh

uniform sampler2D colorSampler; 
const float PI = 3.1415926535; 
const float barrelPower = 0.5; 
uniform vec2 rg; 
uniform vec2 uv2; 
varying vec2 uv; 
uniform float d; 
uniform vec2 xy; 
uniform vec2 Vertex_UV; 

vec2 Distort(vec2 p) 
{ 
    float theta = atan(p.y, p.x); 
    float radius = length(p); 
    radius = pow(radius, barrelPower); 
    p.x = radius * cos(theta); 
    p.y = radius * sin(theta); 
    return 0.5 * (p + 1.0); 
} 

#pragma body 
#pragma transparent 

vec2 xy = 2.0 * Vertex_UV.xy - 1.0; 
vec2 rg = 2.0 * uv.xy - 1.0; 
vec2 uv2; 
float d = length(xy); 
if (d < 1.0){ 
    uv2 = Distort(xy); 
}else{ 
    uv2 = uv.xy; 
} 

gl_FragColor = texture2D(colorSampler, uv2); 

Các trình biên dịch này được biên dịch và được tải lên đối tượng của tôi trong cảnh nhưng không làm gì cả; đối tượng là đục và trắng khi nó gần như trong suốt mà không có các bóng đổ được tiêm, và chỉ thị #pragma transparent sẽ làm cho nó trong suốt.

Để làm cho nó rõ ràng, những gì tôi đang cố gắng để đạt được ở đây là có một ống kính 3D trong một cảnh mà bạn có thể xem xét và nhìn thấy hình ảnh khúc xạ của bất cứ điều gì là ở phía bên kia.

Mọi trợ giúp sẽ được đánh giá rất nhiều!

+0

Bạn có thể hiển thị cho tôi hình ảnh về kết quả mong muốn không? Liên kết bạn cung cấp cho kính mắt chỉ là lý thuyết. Tôi là hình ảnh. – Confused

+0

Bạn không thể có kỹ thuật cho mỗi nút thực sự, nhưng có thể bạn có thể sử dụng nút categoryBitmask để lọc nút để hiển thị "bình thường" và các nút có khúc xạ. Vì vậy, có đi như: [drawScene (loại trừ đối tượng khúc xạ), drawScene (chỉ refracted đối tượng + shader tùy chỉnh cho khúc xạ)] – Toyos

+0

@Confused Nếu bạn nhìn vào phần 6 của giấy glens có một số hình ảnh của loại điều tôi ' m cố gắng đạt được kết quả trong TIM. Đã chỉnh sửa liên kết, vì vậy nó sẽ đưa bạn trực tiếp đến một tệp PDF của bài báo. – Cruthe93

Trả lời

2

Nếu bạn muốn sử dụng đổ bóng và phân đoạn của riêng mình thay vì chương trình đổ bóng mặc định của SceneKit, bạn đã sử dụng SCNProgram thay vì SCNShaderModifierEntryPoint.

SCNShaderModifierEntryPoints chỉ cho phép sửa đổi chương trình đổ bóng mặc định của Swift.

let material = SCNMaterial() 
      let program:SCNProgram = SCNProgram() 
      do { 
       program.vertexShader = try String(contentsOfFile: Bundle.main.path(forResource: "fisheye", ofType: "vsh")!, encoding: String.Encoding.utf8) 
      } catch let error { 
       print("shaderReadingError:\(error)") 
      } 
      do { 
       program.fragmentShader = try String(contentsOfFile: Bundle.main.path(forResource: "fisheye", ofType: "fsh")!, encoding: String.Encoding.utf8) 
      } catch let error { 
       print("shaderReadingError:\(error)") 
      } 

    // and also your vertex shader has lack. 
    // You have to add some geometry source and transformation matrix to the vertex shader first with setSemantic method. 

      program.setSemantic(SCNGeometrySource.Semantic.vertex.rawValue, forSymbol: "vPosition", options: nil) 
      program.setSemantic(SCNGeometrySource.Semantic.texcoord.rawValue, forSymbol: "uv", options: nil) 
      program.setSemantic(SCNModelViewProjectionTransform, forSymbol: "uMVPMatrix", options: nil) 





    // and also your fragment shader expect some realtime data like 
    // colorSampler, rg, uv2, d, xy, Vertex_UV 
    // you have to use handleBinding block to update this values before rendering the object. 
      material.handleBinding(ofSymbol: "resolution", handler: { (programId:UInt32, location:UInt32, node:SCNNode?, renderer:SCNRenderer) in 


      }) 


      material.program = program 
      yourNode.geometry.firstMaterial = material