Using an existing opengl texture with a script

According to Apple's documentation, you can use NSColor, NSImage and CALayer to provide the SCNMaterialProperty texture. SCNMaterialProperty

I am wondering if there is a way to provide an existing OpenGL texture that was created using glGenTextures and displayed separately.

I can, of course, read the texture buffer, configure NSImage and provide it with SCNMaterialProperty; but for performance reasons, which is obviously not optimal.

It would be wise to implement the above by redefining the shader program of the material, which, I think, but the documentation for this seems to be non-existent.

+6
source share
2 answers

You can redefine shader programs by creating SCNProgram material for this. Then, in one of the delegate methods for SCNProgramDelegate you can bind your own values ​​for the texture (and other uniforms). However, you will write your own shaders.

There are few options if you are used to Objective-C, but it really isn’t that much if you think about the appropriate OpenGL code.

The following is an example of a shader program that associates a texture with the surface of a geometry object. For simplicity, it does not do any shading with normals and light sources.

Note that I don’t know how you want to bind your specific texture, so in the code below I read png using GLKit and use this texture.

 // 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]; 

In this example, shaders are written as

 // 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; } 

and

 // yourShader.frag uniform sampler2D yourTexture; varying vec2 texCoord; void main(void) { gl_FragColor = texture2D(yourTexture, texCoord); } 

Finally, the implementation of the method ...bindValueForSymbol:... to bind the texture to the "yourTexture" format.

 - (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. } 

In addition, for debugging purposes, it is very useful to implement program:handleError: to print any shader compilation errors

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

if you need to directly deal with OpenGL and associate your custom textures, then SCNProgram or the SCNNode delegate are transition methods (MountainLion or more). If you have an Apple developer account, you will find sample code here: http://developer.apple.com/downloads/ in the "WWDC 2013 Sample Code" section. Find "OS_X_SceneKit_Slides_WWDC2013"

+1
source

Source: https://habr.com/ru/post/953259/


All Articles