您可以通过为材质创建并分配一个SCNProgram来覆盖着色程序。然后在SCNProgramDelegate的一个委托方法中,您可以绑定自己的纹理值(和其他uniform)。但是,您必须编写自己的着色器。
如果您习惯于Objective-C,则需要进行一些设置,但是当您考虑到相应的OpenGL代码时,这些设置其实并不多。
以下是一个示例着色器程序,它将纹理绑定到几何对象的表面。为简单起见,它不使用法线和光源进行着色。
请注意,我不知道您要如何绑定特定的纹理,因此在下面的代码中,我使用GLKit读取png文件并使用该纹理。
SCNMaterial *material = [SCNMaterial material];
SCNProgram *program = [SCNProgram program];
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];
program.vertexShader = vertexShader;
program.fragmentShader = fragmentShader;
[program setSemantic:SCNGeometrySourceSemanticVertex
forSymbol:@"position"
options:nil];
[program setSemantic:SCNGeometrySourceSemanticTexcoord
forSymbol:@"textureCoordinate"
options:nil];
[program setSemantic:SCNModelViewProjectionTransform
forSymbol:@"modelViewProjection"
options:nil];
program.delegate = self;
material.program = program;
yourGeometry.materials = @[material];
在这个例子中,着色器被编写为:
attribute vec4 position;
attribute vec2 textureCoordinate;
uniform mat4 modelViewProjection;
varying vec2 texCoord;
void main(void) {
texCoord = textureCoordinate;
gl_Position = modelViewProjection * position;
}
And
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"]) {
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;
}
return NO;
}
此外,为了调试目的,实现
program:handleError:
以打印出任何着色器编译错误非常有帮助。
- (void)program:(SCNProgram*)program handleError:(NSError*)error {
NSLog(@"%@", error);
}