2015-12-05 103 views
11

我試圖在SceneKit左右,並教我自己。基本上,我正在創建一個具有3個矩形邊和1個傾斜滑塊的四邊形。自定義着色器SCNProgram iOS 9 Scenekit

我希望我的紋理能夠在表面上伸展和變形/變形。

在線閱讀一些東西,似乎我需要製作一個SCNProgram自定義頂點和片段着色器來獲得效果。但是,我似乎無法讓紋理在表面上傳播。需要幫助。 (我是圖形編程的新手,因此試圖教給自己)。

我斯威夫特代碼來創建幾何形狀和質地是如下:

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

我只是似乎無法獲得左下角的紋理在整個表面展開。能否請你幫忙?

This is what is rendered when I run the code

做一些手工的頂點和片段着色器雜耍,我可以得到的結果,但它給人的感覺非常不雅,我敢肯定它不應該被寫入特定的代碼是這樣的。

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

這給了我正是我期待的,但感覺做事情非常錯誤的方式。

enter image description here

編輯:我使用的是pos變量而不是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); 
} 

我得到的東西像下面的圖片: enter image description here

這對我說,我的紋理座標定義出了問題,但我找不出什麼?

EDIT2:確定進度。在此基礎上鎖定了一個相關的線程我重新定義了我的UV使用下面的方法的答案:

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

現在,它給了我這樣的結果,我在我的frag着色器使用texCoord:

enter image description here

它不如我在上面的紋理中獲得的彎曲變形。但其進展。任何想法如何在這個大規模的問題中得到它像圖片2一樣平滑?

請幫忙。

+1

不錯的作品@AdiTheExplorer。你只需要調整左上角的紋理座標,而不是0,1,它將在0,0.6(3/5)處停止變形。 FWIW,我沒有看到你用來生成紋理座標的代碼有什麼問題,但顯然有些東西並不完全正確。 – lock

+1

Thanks @lock。但是我實際上希望它能像這個線程中的圖片2那樣變形,以便在紋理中獲得好的曲線?它在兩個三角形上均勻變形。 你一直很好的幫助。不能沒有它:) – AdiTheExplorer

+1

不夠公平。在這種情況下,它可能是你想要調整的右上角座標,使得這個y座標更低會將其拉伸。它可能仍然不會給你在圖2中看到的變形,這是你計算紋理座標的一個創造性方程。你可以使用uv來複制它,現在它們沒問題了('gl_FragColor = texture2D(yourTexture,vec2(texCoord.x,texCoord.y /(0.4 * texCoord.x)));''也許......)。但是,通常你的紋理圖像會有變形,允許使用標準着色器。 – lock

回答

7

在片段着色器中,您必須使用texCoord而不是pos來對您的紋理進行採樣。

另請注意,您不需要程序來紋理任意幾何圖形。您也可以使用常規材料製作自定義幾何圖形。如果你想做一些常規材料無法做到的事情,你也可以看看着色器修改器,它們比程序更易於使用,並且不需要你手動處理燈光。

+1

我用過,但它給了我奇怪的結果...... pos變量似乎更好地工作。從最初編寫代碼的時候texCoord就在那裏,失敗:( – AdiTheExplorer

+2

仍然卡在這:( – AdiTheExplorer