2016-08-13 37 views
1

不同變種和樣品,我試圖通過SCNShadable使用着色器,但我無法找到如何把事情的工作有什麼好的文檔。這裏是想我做到:SCNShadable - 從質地

func setup() { 
    // attach a video to a SpriteKit node that renders to my SceneKit node 
    // (might not be key to this question) 
    let player = videoPlayer 
    let item = player.currentItem! 
    let track = item.asset.tracks(withMediaType: AVMediaTypeVideo).first 
    let size = track.naturalSize 
    let node = SKVideoNode(avPlayer: player) 
    node.position = CGPoint(x: size.width/2, y: size.height/2) 
    node.size = size 
    let scene = SKScene(size: size) 
    scene.addChild(node) 
    videoGeometry.firstMaterial?.diffuse.contents = scene 

    let customProjection = getCustomProjection() 

    // use custom shaders to render 
    let vertexShader = "" + 
     "attribute mediump vec2 aVertexPosition; \n" + 
     "uniform mediump mat4 customProjection; \n" + 
     "varying mediump vec3 vDirection; \n" + 

     "void main(void) { \n" + 
      "gl_Position = vec4(aVertexPosition, 1.0, 1.0); \n" + 
      "mediump vec4 projective_direction = customProjection * gl_Position; \n" + 
      "vDirection = projective_direction.xyz/projective_direction.w; \n" + 
     "} \n" + 

    let fragmentShader = "" + 
     "varying mediump vec3 vDirection; \n" + 
     "uniform mediump float someUniformParam; \n" + 
     "uniform sampler2D uSampler; \n" + 

     "mediump vec4 directionToColor(mediump vec3 direction, mediump float someUniformParam) { \n" + 
      "... \n" + 
     "} \n" + 

     "void main(void) { \n" + 
      "gl_FragColor = directionToColor(vDirection, someUniformParam); \n" + 
     "} \n" + 


    videoGeometry.firstMaterial?.shaderModifiers = [ 
     "fragmentShader": fragmentShader, 
     "vertexShader": vertexShader, 
    ] 
} 

func beforeRender() { 
    // somehow pass uniforms values to the shaders 
    attachUniforms(customProjection, someUniformParam) 
} 

我無法弄清楚如何:

  • SCNShadableprotocol拆分那些着色器邏輯。聽起來像SCNShaderModifierEntryPointGeometry在頂點着色器中運行,並且3個其他入口點運行片段着色器。看起來我必須使用SCNShaderModifierEntryPointFragment作爲我的片段邏輯。
  • 參照內置制服,諸如頂點位置(即我命名aVertexPosition)和紋理(uSampler
  • 確保我的不同變量是從頂點傳遞到片段着色器
  • 通制服參數繪製場景之前的片段和頂點着色器。

回答

2

使用SCNShadable,您可以編寫包含在較大着色器文件中的着色器代碼片段。我寫了一篇關於如何使用它的中型文章:https://medium.com/@guillaumesabran/working-with-scnshadable-783b4bca20d3#.tcv7r11mj

所以這意味着我必須忘記控制整個着色器代碼,而是理解我的代碼片段將要運行的環境。

這些文件中提供的變量在蘋果公司的網站上很少記載,但是一旦你把手放在着色器代碼上(見頂點和片段),事情會變得更簡單。

例如,漫反射紋理被命名爲u_diffuseTexture所以在SCNShaderModifierEntryPointFragment我可以這樣做:

texture2D(u_diffuseTexture, vec2(0.5, 0.5)); 

傳遞不同變量從頂點到片段着色器工作正常。

關於校服,事情都OK,以及一旦你知道如何:

// in some SCNShaderModifierEntryPointFragment code 
#pragma arguments 
uniform int someUniformVariable; 

#pragma body 
... 

,然後我可以設置與統一的價值:

videoGeometry.firstMaterial?.setValue(1, forKey: "someUniformVariable") 
+0

如何傳遞不同的變量? – pailhead

+0

我認爲你在片段着色器中聲明它們(所以在SCNShaderModifierEntryPointGeometry中)就像'vary vec3 somePosition;'並在頂點着色器中指定它們(所以在其他入口點之一),比如'somePosition = vec3(1.0,1.0,1.0 );' – Guig

+1

這是'的#pragma arguments',我發現混亂,原來,這是沒有必要的呢?只要我有一個'#pragma body',剩下的代碼就以'main()'結尾,而我在沒有'#pragma arguments'的情況下得到了一個統一的和變化的地方(!?) – pailhead