自定义着色器SCNProgram iOS 9 Scenekit

我试图在SceneKitSceneKit并教导自己。 基本上,我正在创build一个有3个矩形边和1个倾斜滑块的四边形。

我希望我的纹理能够在表面上伸展和变形/变形。

在线阅读一些东西,似乎我需要用自定义顶点和片段着色器来制作一个SCNProgram来获得效果。 但是,我似乎无法让纹理在表面上传播。 需要帮助,请。 (我是graphics编程新手,因此试图自己教)。

我的Swift代码创build的几何和纹理如下:

 func geometryCreate() -> SCNNode { let verticesPosition = [ SCNVector3Make(0.0, 0.0, 0.0), SCNVector3Make(5.0, 0.0, 0.0), SCNVector3Make(5.0, 5.0, 0.0), SCNVector3Make(0.0, 3.0, 0.0) ] let textureCord = [CGPoint (x: 0.0,y: 0.0), CGPoint(x: 1.0,y: 0.0), CGPoint(x: 1.0,y: 1.0), CGPoint(x: 0.0,y: 1.0)] let indices: [CInt] = [ 0, 2, 3, 0, 1, 2 ] let vertexSource = SCNGeometrySource(vertices: verticesPosition, count: 4) let srcTex = SCNGeometrySource(textureCoordinates: textureCord, count: 4) let date = NSData(bytes: indices, length: sizeof(CInt) * indices.count) let scngeometry = SCNGeometryElement(data: date, primitiveType: SCNGeometryPrimitiveType.Triangles, primitiveCount: 2, bytesPerIndex: sizeof(CInt)) let geometry = SCNGeometry(sources: [vertexSource,srcTex], elements: [scngeometry]) let program = SCNProgram() if let filepath = NSBundle.mainBundle().pathForResource("vertexshadertry", ofType: "vert") { do { let contents = try NSString(contentsOfFile: filepath, encoding: NSUTF8StringEncoding) as String program.vertexShader = contents } catch { print("**** happened loading vertex shader") } } if let fragmentShaderPath = NSBundle.mainBundle().pathForResource("fragshadertry", ofType:"frag") { do { let fragmentShaderAsAString = try NSString(contentsOfFile: fragmentShaderPath, encoding: NSUTF8StringEncoding) program.fragmentShader = fragmentShaderAsAString as String } catch { print("**** happened loading frag shader") } } program.setSemantic(SCNGeometrySourceSemanticVertex, forSymbol: "position", options: nil) program.setSemantic(SCNGeometrySourceSemanticTexcoord, forSymbol: "textureCoordinate", options: nil) program.setSemantic(SCNModelViewProjectionTransform, forSymbol: "modelViewProjection", options: nil) do { let texture = try GLKTextureLoader.textureWithCGImage(UIImage(named: "stripes")!.CGImage!, options: nil) geometry.firstMaterial?.handleBindingOfSymbol("yourTexture", usingBlock: { (programId:UInt32, location:UInt32, node:SCNNode!, renderer:SCNRenderer!) -> Void in glTexParameterf(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_WRAP_S), Float(GL_CLAMP_TO_EDGE) ) glTexParameterf(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_WRAP_T), Float(GL_CLAMP_TO_EDGE) ) glTexParameterf(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_MAG_FILTER), Float(GL_LINEAR) ) glTexParameterf(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_MIN_FILTER), Float(GL_LINEAR) ) glBindTexture(GLenum(GL_TEXTURE_2D), texture.name) }) } catch { print("Texture not loaded") } geometry.firstMaterial?.program = program let scnnode = SCNNode(geometry: geometry) return scnnode } 

我的顶点着色器是:

 attribute vec4 position; attribute vec2 textureCoordinate; uniform mat4 modelViewProjection; varying highp vec2 pos; varying vec2 texCoord; void main() { texCoord = vec2(textureCoordinate.s, 1.0 - textureCoordinate.t) ; gl_Position = modelViewProjection * position; pos = vec2(position.x, 1.0 - position.y); } 

我的片段着色器是:

 precision highp float; uniform sampler2D yourTexture; varying highp vec2 texCoord; varying highp vec2 pos; void main() { gl_FragColor = texture2D(yourTexture, vec2(pos.x, pos.y)); } 

我似乎无法得到在左下方展开的纹理。 能否请你帮忙?

这是我运行代码时呈现的内容

做一些手动顶点和碎片着色器杂耍,我可以得到的结果,但它感觉非常不雅,我敢肯定它不应该写这样的具体代码。

 attribute vec4 position; attribute vec2 textureCoordinate; uniform mat4 modelViewProjection; varying highp vec2 pos; varying vec2 texCoord; void main() { // Pass along to the fragment shader texCoord = vec2(textureCoordinate.s, 1.0 - textureCoordinate.t) ; // output the projected position gl_Position = modelViewProjection * position; pos = vec2(position.x, position.y); } 

对片段着色器的更改(其中0.4是四边形顶部的斜率):

 precision highp float; uniform sampler2D yourTexture; varying highp vec2 texCoord; varying highp vec2 pos; void main() { gl_FragColor = texture2D(yourTexture, vec2(pos.x/5.0, 1.0 - pos.y/(3.0+0.4*pos.x))); // gl_FragColor = vec4 (0.0, pos.y/5.0, 0.0, 1.0); } 

这正是我所要找的东西,但是却觉得这是非常错误的做事方式。

在这里输入图像说明

编辑:我正在使用posvariables,而不是texCoord作为texCoord给我奇怪的地狱结果,我不明白:(。

如果我要修改我的片段着色器:

 precision highp float; uniform sampler2D yourTexture; varying highp vec2 texCoord; varying highp vec2 pos; void main() { // gl_FragColor = texture2D(yourTexture, vec2(pos.x/5.0, 1.0 - pos.y/(3.0+0.4*pos.x))); gl_FragColor = texture2D(yourTexture, texCoord); // gl_FragColor = vec4 (0.0, pos.y/5.0, 0.0, 1.0); } 

我得到像下面的图片: 在这里输入图像说明

这对我说,我的纹理坐标定义有问题,但我不知道是什么?

编辑2:好的进展。 基于Lock在相关线程上给出的答案,我使用下面的方法重新定义了我的uvs:

 let uvSource = SCNGeometrySource(data: uvData, semantic: SCNGeometrySourceSemanticTexcoord, vectorCount: textureCord.count, floatComponents: true, componentsPerVector: 3, bytesPerComponent: sizeof(Float), dataOffset: 0, dataStride: sizeof(vector_float2)) 

现在当我在我的碎片着色器中使用texCoord时,它给了我这样一个结果:

在这里输入图像说明

它不如我在上面的纹理中获得的弯曲的畸形。 但其进展。 任何想法我怎么能得到它像图片2在这个大规模的问题?

请帮助。

在片段着色器中,必须使用texCoord而不是pos来对纹理进行采样。

另外请注意,你不需要一个程序来纹理任意的几何graphics。 您也可以使用常规材料来定制几何graphics。 如果你想做一些常规材料无法做到的事情,你也可以看一下着色器修改器,它比程序更容易使用,而且不需要你手动处理灯光。