2017-01-18 10 views
2

これは床面にトレイルを作成するために使用するサーフェスシェーダです。配列データをOpenGLシェーダの一様配列に渡しているときに、Scenekitがバッファサイズエラーを返す

#pragma arguments 
uniform vec2 trailPoints[5]; 
uniform float count; 

#pragma body 
float trailRadius = 10.0; 

float x = _surface.diffuseTexcoord.x; 
float x100 = float(x * 100); 

float y = _surface.diffuseTexcoord.y; 
float y100 = float(y * 100); 

for (int i = 0; i < int(count); i++) { 
    vec2 position = trailPoints[i]; 
    if ((x100 > position.x - trailRadius && x100 < position.x + trailRadius) && (y100 > position.y - trailRadius && y100 < position.y + trailRadius)) { 
     _surface.diffuse.rgb = vec3(0.0, 10.0 ,0.0); 
    } 
} 

これは、ベクトルデータをサーフェスシェーダに渡すために使用するスワイプサイドコードです。

  if let geometry = self.floorNode.geometry { 
       if let material = geometry.firstMaterial { 

        // this is the temporary data which I use to find the problem. 
        // this data will be dynamic later on. 
        let myValueArray:[float2] = [float2(x:80, y:80),float2(x:60, y:60),float2(x:40, y:40),float2(x:20, y:20),float2(x:0, y:0)] 

        // Passing array count to shader. There is no problem here. 
        var count = Float(myValueArray.count) 
        let countData = Data(buffer: UnsafeBufferPointer(start: &count, count: 1)) 
        material.setValue(countData, forKey: "count") 

        // and here is the problem start. 
        // myValueArray converted to data with its size. 
        let valueArrayData = Data(buffer: UnsafeBufferPointer(start: myValueArray, count: myValueArray.count)) 
        material.setValue(valueArrayData, forKey: "trailPoints")      
       }     
      } 

プロジェクトをビルドして実行すると、次のエラーが発生し、シェーダーの「trailPoints」にデータが渡されませんでした。

エラー:引数trailPoints:!NSDataのとバッファサイズ40の間のミスマッチ= 8

私はデータに配列を変換しながら、アレイが1にカウント変更、

let valueArrayData = Data(buffer: UnsafeBufferPointer(start: myValueArray, count: 1)) 

エラー消え去るが、配列の最初のメンバーだけがシェーダに渡される。

ので、問題は、私はシェーダにすべてのアレイメンバーを渡すことができますどのように、

のですか?

+0

は 'カウントされません:myValueArray.countの*のはsizeof(するfloat2を)':myValueArray.count'は 'カウントする必要がありますか? – solidpixel

+1

@solidpixelいいえ、すべてここで良いです。この高水準APIは、一様配列をサポートしていないようです。 NSDataオブジェクトには40バイト(10 32ビット浮動小数点数)が含まれていますが、エラーは8バイトを必要とするレポートを観察しているキー値から来ているようです。trailPointsをvec2として保存していると仮定するだけで2フロート(32ビット)バイト。私はこのAPIを純粋なOpenGLよりも使用することは考えていませんが、それを調べる限り、より低いレベルでシェーダ入力を操作する方法はありません。 –

+0

ありがとうMatic。私はあなたが言及した理由を疑ったが、わからなかった。どうやら、ScenekitのShader Modifier Entry Pointsを使ってシェーダーに配列を渡す機会はありません。 私はSCNProgramを純粋な希望で試してみます。 – ytur

答えて

1
私が思うに

、この質問の答えは、この:

私は最近実現し、the OpenGl ES 2.0 only allow the following array definitions

float myValue[3]; 
myValue[0] = 1.0; 
myValue[1] = 2.0; 
myValue[2] = 3.0; 

しかし、私の知る限り、でSCNShaderModifierEntryPointを使用して、これを行うことはできません次のようにします。

material.setValue (1.0, forKey: "myValue[0]") 
material.setValue (2.0, forKey: "myValue[1]") 
material.setValue (3.0, forKey: "myValue[2]") 

最後に、SCNProgram handleBindingメソッドを使ってフラグメントシェーダーに配列を渡す方法が見つかりました。

let myValue:[Float] = [1.0, 2.0, 3.0] 
material.handleBinding(ofSymbol:"myValue", handler: { (programId:UInt32, location:UInt32, node:SCNNode?, renderer:SCNRenderer) in 
     for (index, v) in myValue.enumerated() { 
      var v1 = v 
      let aLoc = glGetUniformLocation(programId, String(format: "myValue[%i]", index)) 
      glUniform1fv(GLint(aLoc), 1, &v1) 
     } 
}) 

しかし、SCNProgramは、デフォルトのスワイプシェイダープログラムを完全に削除して使用します。 swiftのデフォルトシェーダプログラムは非常に複雑で、多くのことをあなたのところで行います。

default vertex shader of swift

default fragment shader of swift

のみシェーダに配列を渡すためSCNProgramを使用するので、多分その良いアイデアではありません。

そして、もう一つ興味深いの、SCNProgram does not work on SCNFloor geometry.

関連する問題