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