在SceneKit中模拟折射
我正在尝试为一个项目创建一个ios 9应用程序,它将使用这些特殊类型的理论镜头(称为glenses)来显示3D场景。
一个名为TIM的光线跟踪程序已经从头开始编写,用于模拟这些格伦特等等,但简单地将其移植到ios是不可行的。
我从搜索网站(即这个答案以及许多其他关于着色器)的理解是它应该是可能的,但我很难获得所需的效果。
我决定在开始进行更复杂的glens类型折射之前首先实现一种更简单的折射forms:
我能够使用SCNTechnique
在相机上使用桶形失真(鱼眼镜头)效果,但是看起来你只能在相机或整个场景上使用技术,而不是单个几何体。
之后,我尝试通过使用SCNMaterial
的shaderModifiers
属性注入opengl代码来获得应用于几何体的桶形失真效果:
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]
我在这里使用了稍加修改的着色器:
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(py, px); float radius = length(p); radius = pow(radius, barrelPower); px = radius * cos(theta); py = 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);
这些着色器编译并加载到场景中的对象上,但什么都不做; 如果没有注入的着色器,它几乎是透明的,对象是不透明和白色的, #pragma transparent
指令应该使它透明。
为了说清楚,我在这里想要实现的是在场景中有一个3D镜头,你可以通过它看到另一边的任何东西的折射图像。
任何帮助将非常感谢!
如果您想使用自己的顶点和片段着色器而不是SceneKit默认着色器程序,那么您也使用SCNProgram而不是SCNShaderModifierEntryPoint。
SCNShaderModifierEntryPoints仅允许修改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
- 如何在存在的图像上添加水印
- 帮助确定为什么XCode“无法上传MyApp.app”到我的iPad
- 在UIAlertController SWIFT中为每个图像添加一个animation图像
- NSUTF8StringEncoding给了我这个%0A%20%20%20%20%22http://example.com/example.jpg%22%0A
- 布局问题,Autolayout启用,但似乎没有工作
- 使用非公开API的应用程序将被拒绝
- Apple iPhone X即将发布。 您的应用程序准备好了吗?
- 在iOS上使用SecCertificateCreateWithData创build证书
- ios – 将一个UIButton连接到2个赛段