![](/img/trans.png)
[英]Using shader modifiers to animate texture in SceneKit leads to jittery textures over time
[英]Using existing opengl texture with scenekit
根据Apple的文档,您可以使用NSColor,NSImage和CALayer为SCNMaterialProperty提供纹理。 SCNMaterialProperty
然而,我想知道是否有办法提供现有的OpenGL纹理,该纹理是用glGenTextures创建的并单独渲染。
我当然可以读取纹理的缓冲区,设置NSImage,并将其提供给SCNMaterialProperty; 但出于性能原因,这显然不是最佳的。
通过覆盖我猜想的材料的着色器程序来实现上述内容是有意义的,但是这样做的文档似乎不存在。
您可以通过创建为材质指定SCNProgram来覆盖着色器程序。 然后在SCNProgramDelegate
一个委托方法中,您可以为纹理(和其他制服)绑定自己的值。 但是,您将编写自己的着色器。
如果您已经习惯了Objective-C,那么可以进行一些设置,但是当您想到相应的OpenGL代码时,它确实没那么多。
以下是一个示例着色器程序,它将纹理绑定到几何对象的表面。 为简单起见,它不会对法线和光源进行任何着色。
请注意,我不知道你想如何绑定你的特定纹理,所以在下面的代码中我使用GLKit读取一个png并使用该纹理。
// Create a material
SCNMaterial *material = [SCNMaterial material];
// Create a program
SCNProgram *program = [SCNProgram program];
// Read the shader files from your bundle
NSURL *vertexShaderURL = [[NSBundle mainBundle] URLForResource:@"yourShader" withExtension:@"vert"];
NSURL *fragmentShaderURL = [[NSBundle mainBundle] URLForResource:@"yourShader" withExtension:@"frag"];
NSString *vertexShader = [[NSString alloc] initWithContentsOfURL:vertexShaderURL
encoding:NSUTF8StringEncoding
error:NULL];
NSString *fragmentShader = [[NSString alloc] initWithContentsOfURL:fragmentShaderURL
encoding:NSUTF8StringEncoding
error:NULL];
// Assign the shades
program.vertexShader = vertexShader;
program.fragmentShader = fragmentShader;
// Bind the position of the geometry and the model view projection
// you would do the same for other geometry properties like normals
// and other geometry properties/transforms.
//
// The attributes and uniforms in the shaders are defined as:
// attribute vec4 position;
// attribute vec2 textureCoordinate;
// uniform mat4 modelViewProjection;
[program setSemantic:SCNGeometrySourceSemanticVertex
forSymbol:@"position"
options:nil];
[program setSemantic:SCNGeometrySourceSemanticTexcoord
forSymbol:@"textureCoordinate"
options:nil];
[program setSemantic:SCNModelViewProjectionTransform
forSymbol:@"modelViewProjection"
options:nil];
// Become the program delegate so that you get the binding callback
program.delegate = self;
// Set program on geometry
material.program = program;
yourGeometry.materials = @[material];
在此示例中,着色器被编写为
// yourShader.vert
attribute vec4 position;
attribute vec2 textureCoordinate;
uniform mat4 modelViewProjection;
varying vec2 texCoord;
void main(void) {
// Pass along to the fragment shader
texCoord = textureCoordinate;
// output the projected position
gl_Position = modelViewProjection * position;
}
和
// yourShader.frag
uniform sampler2D yourTexture;
varying vec2 texCoord;
void main(void) {
gl_FragColor = texture2D(yourTexture, texCoord);
}
最后执行...bindValueForSymbol:...
方法将纹理绑定到“yourTexture”制服。
- (BOOL) program:(SCNProgram *)program
bindValueForSymbol:(NSString *)symbol
atLocation:(unsigned int)location
programID:(unsigned int)programID
renderer:(SCNRenderer *)renderer
{
if ([symbol isEqualToString:@"yourTexture"]) {
// I'm loading a png with GLKit but you can do your very own thing
// here to bind your own texture.
NSError *error = nil;
NSString *imagePath = [[NSBundle mainBundle] pathForResource:@"sampleImage" ofType:@"png"];
GLKTextureInfo *texture = [GLKTextureLoader textureWithContentsOfFile:imagePath options:nil error:&error];
if(!texture) {
NSLog(@"Error loading file: %@", [error localizedDescription]);
}
glBindTexture(GL_TEXTURE_2D, texture.name);
return YES; // indicate that the symbol was bound successfully.
}
return NO; // no symbol was bound.
}
此外,出于调试目的,实现program:handleError:
非常有用program:handleError:
打印出任何着色器编译错误
- (void)program:(SCNProgram*)program handleError:(NSError*)error {
// Log the shader compilation error
NSLog(@"%@", error);
}
如果您需要直接处理OpenGL并绑定自定义纹理,那么SCNProgram或SCNNode的委托是要走的路(MountainLion或更高版本)。 如果您有Apple开发人员帐户,可以在此处找到示例代码: http : //developer.apple.com/downloads/在“WWDC 2013示例代码”下。 寻找“OS_X_SceneKit_Slides_WWDC2013”
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.