2013-09-05 85 views
6

根據蘋果的文檔,你可以使用NSColor,NSImage中和CALayer的提供紋理到SCNMaterialProperty。 SCNMaterialProperty利用現有的OpenGL紋理scenekit

不過我想知道是否有辦法提供一個已經用glGenTextures創建並分別渲染的現有OpenGL紋理。

我當然可以讀出的紋理的緩衝器,設置一個NSImage中,並提供一個到SCNMaterialProperty;但出於性能原因顯然不是最佳的。

它將使意義通過重寫我猜材料的着色器程序(一個或多個)實施以上,但這樣做的文件似乎是不存在的。

回答

8

您可以通過創建分配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; 
} 

而且

​​

最後爲...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:打印出任何着色器編譯錯誤

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

哇,非常感謝! – simonfi

+2

終於有一段時間來玩這個了,只想再說一聲謝謝!除少量錯字(a_textureCoordinate在頂點着色器),這非常完美,比我以前的實現,它不停地更換使用新NSImage中所有的時間紋理快得多。 只是一個小問題;你怎麼解決這個問題? SceneKit的文檔到目前爲止似乎非常有限。 – simonfi

1

如果需要直接處理的OpenGL和綁定您的自定義紋理然後SCNProgram或SCNNode的代表都去(MountainLion或更高)的方式。如果你有一個蘋果開發者賬號,你會發現這裏的示例代碼:在「WWDC 2013的示例代碼」 http://developer.apple.com/downloads/ 。尋找「OS_X_SceneKit_Slides_WWDC2013」​​

+0

非常有幫助不幸的是,你必須提供自己的着色器。此外,SceneKit本身就是山獅和更高;) –

+0

@Toyos什麼是你的電子郵件地址?如果你不介意的話,想給你發一封有關項目的電子郵件。 – Crashalot