SCNShadable - 从纹理变化var和样本

时间:2016-08-13 19:28:16

标签: ios swift shader scenekit

我正在尝试通过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)
}

我无法弄清楚如何:

  • SCNShadable protocol中拆分这些着色器逻辑。听起来SCNShaderModifierEntryPointGeometry在顶点着色器中运行,其他3个入口点运行片段着色器。看起来我必须使用SCNShaderModifierEntryPointFragment作为我的片段逻辑。
  • 对内置制服的引用,例如顶点位置(我命名为aVertexPosition)和纹理(uSampler
  • 确保我的变量变量从顶点传递到片段着色器
  • 在绘制场景之前将制服参数传递给片段和顶点着色器。

1 个答案:

答案 0 :(得分:2)

使用SCNShadable,您可以编写包含在较大着色器文件中的着色器代码片段。我写了一篇关于我如何使用它的中篇文章:https://medium.com/@guillaumesabran/working-with-scnshadable-783b4bca20d3#.tcv7r11mj

这意味着我不得不忘记控制整个着色器代码,而是要了解我的代码片段将要运行的环境。

这些文件中可用的变量在Apple的网站上记录得很少,但是一旦你把手放在着色器代码上(参见顶点和片段),事情会变得容易一些。

例如,漫反射贴图的名称为u_diffuseTexture,所以在SCNShaderModifierEntryPointFragment我可以这样做:

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

将变量从顶点传递到片段着色器工作正常。

关于制服,一旦你知道如何,事情也没问题:

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

#pragma body
...

然后我可以用:

设置制服的值
videoGeometry.firstMaterial?.setValue(1, forKey: "someUniformVariable")