Shade personnalisé SCNProgram iOS 9 Scenekit

J'essaie de me SceneKit dans SceneKit et je m'y apprends. Fondamentalement, je crée un quad avec 3 côtés rectangulars et 1 glissière inclinée.

Je veux que ma texture s'étire et se déforme / se déforme sur la surface.

En lisant certaines choses en ligne, il semble que je SCNProgram faire un SCNProgram avec des vertex et des shaders fragmentés pour get l'effet. Mais, je ne peux pas sembler get la texture pour s'étendre à travers la surface. Besoin d'aide s'il vous plaît. (Je suis nouveau à la programmation graphique donc essayer de me l'enseigner à moi-même).

Mon code Swift pour créer la geometry et la texture est le suivant:

 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 NSSsortingng(contentsOfFile: filepath, encoding: NSUTF8SsortingngEncoding) as Ssortingng program.vertexShader = contents } catch { print("**** happened loading vertex shader") } } if let fragmentShaderPath = NSBundle.mainBundle().pathForResource("fragshadertry", ofType:"frag") { do { let fragmentShaderAsASsortingng = try NSSsortingng(contentsOfFile: fragmentShaderPath, encoding: NSUTF8SsortingngEncoding) program.fragmentShader = fragmentShaderAsASsortingng as Ssortingng } 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: "ssortingpes")!.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 } 

Mon shader Vertex est:

 atsortingbute vec4 position; atsortingbute 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); } 

Mon fragment de shader est:

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

Je n'arrive tout simplement pas à get la texture en bas à gauche étalée sur la surface. S'il te plait peux-tu aider?

C'est ce qui est rendu quand je lance le code

En faisant un peu de vertex manuel et de jonglage des shaders, je peux get le résultat mais il me semble très inélégant et je suis sûr qu'il ne devrait pas écrire de code spécifique comme celui-ci.

 atsortingbute vec4 position; atsortingbute 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); } 

Modifications du fragment shader (où 0.4 est la pente du sumt du quad):

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

Ce qui me donne exactement ce que je cherche, mais c'est une très mauvaise façon de faire les choses.

entrez la description de l'image ici

EDIT: J'utilise la variable pos au lieu de texCoord car le texCoord me donne des résultats bizarres en enfer que je ne peux pas vraiment comprendre :(.

Si je devais modifier mon fragment shader comme:

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

Je reçois quelque chose comme la photo ci-dessous: entrez la description de l'image ici

Ce qui me dit qu'il y a quelque chose qui ne va pas avec la définition de mes coordonnées de texture mais je ne peux pas comprendre quoi?

EDIT2: OK les progrès. Basé sur une réponse que Lock a donné sur un sujet connexe, j'ai redéfini mes uvs en utilisant la méthode ci-dessous:

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

Maintenant, ça me donne un résultat comme ça quand j'utilise texCoord dans mon fragment de shader:

entrez la description de l'image ici

Ce n'est pas aussi grand que les déformations incurvées que j'ai dans la texture ci-dessus. Mais son progrès. Des idées comment puis-je get pour lisser comme pic 2 dans cette question massive?

Aide aimablement.

Dans le fragment shader vous devez utiliser texCoord au lieu de pos pour texCoord votre texture.

Notez également que vous n'avez pas besoin d'un programme pour texturer une geometry arbitraire. Vous pouvez également utiliser du matériel standard pour les geometrys personnalisées. Si vous voulez faire quelque chose qui n'est pas possible avec un matériel standard, vous pouvez aussi regarder les modificateurs de shaders, ils sont plus faciles à utiliser que les programmes et ne nécessitent pas de manipuler manuellement les lumières par exemple.