gpt4 book ai didi

objective-c - 将现有的 opengl 纹理与 scenekit 一起使用

转载 作者:太空狗 更新时间:2023-10-30 03:41:55 27 4
gpt4 key购买 nike

根据 Apple 的文档,您可以使用 NSColor、NSImage 和 CALayer 为 SCNMaterialProperty 提供纹理。 SCNMaterialProperty

不过,我想知道是否有一种方法可以提供现有的 OpenGL 纹理,该纹理是使用 glGenTextures 创建并单独渲染的。

我当然可以读取纹理缓冲区,设置一个 NSImage,并将其提供给 SCNMaterialProperty;但出于性能原因,这显然不是最优的。

我猜通过覆盖 Material 的着色器程序来实现上述内容是有意义的,但执行此操作的文档似乎不存在。

最佳答案

您可以通过创建将 SCNProgram 分配给 Material 来覆盖着色器程序。然后在 SCNProgramDelegate 的委托(delegate)方法之一中,您可以为纹理(和其他制服)绑定(bind)您自己的值。但是,您必须编写自己的着色器。

如果您习惯了 Objective-C,则需要进行一些设置,但当您想到相应的 OpenGL 代码时,实际上并没有那么多。

以下是一个示例着色器程序,它将纹理绑定(bind)到几何对象的表面。为简单起见,它不对法线和光源进行任何着色。

请注意,我不知道你想如何绑定(bind)你的特定纹理,所以在下面的代码中,我使用 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:... 方法的实现,用于将纹理绑定(bind)到“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: 以打印出任何着色器编译错误非常有帮助

- (void)program:(SCNProgram*)program handleError:(NSError*)error {
// Log the shader compilation error
NSLog(@"%@", error);
}

关于objective-c - 将现有的 opengl 纹理与 scenekit 一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18641434/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com