Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 将现有opengl纹理与scenekit结合使用_Objective C_Opengl_Scenekit - Fatal编程技术网

Objective c 将现有opengl纹理与scenekit结合使用

Objective c 将现有opengl纹理与scenekit结合使用,objective-c,opengl,scenekit,Objective C,Opengl,Scenekit,根据苹果的文档,您可以使用NSColor、NSImage和CALayer为SCN材质属性提供纹理 然而,我想知道是否有一种方法可以提供一个现有的OpenGL纹理,它是用glGenTextures创建的,并单独渲染成 我当然可以读取纹理的缓冲区,设置NSImage,并将其提供给SCNMaterialProperty;但出于性能原因,这显然不是最优的 通过覆盖材质的着色器程序来实现上述操作是有意义的,但用于实现此操作的文档似乎不存在。如果需要直接处理OpenGL并绑定自定义纹理,则可以使用SCNPr

根据苹果的文档,您可以使用NSColor、NSImage和CALayer为SCN材质属性提供纹理

然而,我想知道是否有一种方法可以提供一个现有的OpenGL纹理,它是用glGenTextures创建的,并单独渲染成

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


通过覆盖材质的着色器程序来实现上述操作是有意义的,但用于实现此操作的文档似乎不存在。

如果需要直接处理OpenGL并绑定自定义纹理,则可以使用SCNProgram或SCNNode的委托(MountainLion或更高)。如果您有Apple developer帐户,您将在此处找到示例代码:
在“WWDC 2013样本代码”下。查找“OS_X_SceneKit_Slides_WWDC2013”

您可以通过为材质创建指定SCN程序来覆盖着色器程序。然后,在
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;
}

最后是
…bindValueForSymbol:…
方法的实现,用于将纹理绑定到“yourTexture”统一


此外,出于调试目的,实现
program:handleError:
打印出任何着色器编译错误非常有用

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

不幸的是,您必须提供自己的着色器。此外,SceneKit本身就是山狮和更高的物种;)@Toyos你的电子邮件地址是什么?如果你不介意的话,我想给你发一封关于一个项目的电子邮件。终于有时间玩这个了,我只想再次对你说声谢谢!除了一个小的输入错误(顶点着色器中的一个_textureCoordinate)之外,它工作得非常好,并且比我以前一直使用新NSImage替换纹理的实现快得多。只是一个小问题;你怎么知道的?到目前为止,SceneKit的文档似乎非常有限。
- (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.
} 
- (void)program:(SCNProgram*)program handleError:(NSError*)error {
    // Log the shader compilation error
    NSLog(@"%@", error);
}