2015-05-23 6 views
3

Я пытался создать сцену с набором сюжетов, в которой указанный объект всегда находится перед другими, несмотря на то, что он фактически находится за другими объектами. Аналогичный эффект для этого используется в blender.Есть ли способ рисовать SCNNode всегда перед другими?

Видимо, blender использует графический интерфейс и много математики для преобразования в противном случае 2D-объектов, но мне нужен этот эффект в SCNNode с SCNGeometry, другими словами, 3D-объект в настоящее время находится в сцене.

Я рассмотрел использование масок категорий, но после прочтения документации Apple я понял, что не работает для эффекта, который я ищу.

Кто-нибудь знает способ сделать это в SceneKit? Или еще лучше, возможно ли это сделать?

Спасибо вам всем заблаговременно, на данный момент и за любую другую помощь, которую я получил от StackExchange!

ответ

3

Таким образом, получается, я нашел ответ на мой вопрос (с помощью mnuages). Я просто хотел опубликовать полный ответ.

Final result
Как предложил mnuages, я попытался установить как readsFromDepthBuffer и writesToDepthBuffer ложь и установка узла renderingOrder в большом количестве. Это сработало неправильно. Вместо того, чтобы быть всегда впереди, он всегда находился за каждым объектом. Способ получить результат, показанный на картинке, заключается в том, чтобы установить только readsFromDepthBuffer в значение false и установить куба в -1, иначе его невозможно будет нарисовать.

Поскольку куб и материалы других узлов имеют readsFromDepthBuffer и writesToDepthBuffer значения по умолчанию true, он все равно будет находиться в передней части позади объектов, и за объектами перед ним, другими словами, это будет нормально, только стрелки будут вести себя так, как мы хотим.

Как видно на рисунке, видны части линий перед кубом. То же самое нельзя сказать о части за ней.

+0

Это соответствует [документации Apple] (https://developer.apple.com/library/prerelease/ios/documentation/SceneKit/Reference/SCNMaterial_Class/index.html#//apple_ref/occ/instp/ SCNMaterial/writeToDepthBuffer) для 'writeToDepthBuffer' и' readsFromDepthBuffer'. Основной вариант использования 'writeToDepthBuffer', по-видимому, предназначен для обработки прозрачности. Я обнаружил, что объект с прозрачностью может привести к тому, что объекты за ним исчезнут с некоторых углов, если для параметра 'writeToDepthBuffer' установлено значение false для SCNMaterial прозрачного объекта. Даже тогда я видел несколько сбоев, но это определенно помогло. –

+1

Возможно, это немного походит на тему, чтобы добавить к моему предыдущему комментарию, но оказывается, что установка 'renderingOrder' в -1 на моем прозрачном объекте фиксирует оставшиеся проблемы с рендерингом. –

+0

Это немного бессмысленно для меня, я имею в виду, что документация предполагает, что просто установка «renderOrder» объекта на большее число и объединение его с правильной настройкой буфера глубины будет работать, но, по-видимому, объект с набором свойств 'readFromDepthBuffer' своего материала false будет только перед другими объектами, если указанные объекты имеют отрицательный 'renderOrder'. –

1

SCNMaterial выставляет writesToDepthBuffer и readsFromDepthBuffer, что позволит вам сделать это (в сочетании с SCNNode «s renderingOrder при необходимости)

+1

Я, наконец, удалось узнать, что вы сказали. Фактически, установка параметров, которые вы указали из его значения True по умолчанию для False, похоже, является решением, так как мне удалось заставить мой объект заняться всегда перед некоторыми другими, но не все. Мне еще предстоит выяснить, как работать с порядком рендеринга, потому что есть что-то, что я делаю неправильно. Но спасибо :) –

0

Ответ на readsFromDepthBuffer может работать для угла в показанном изображении, но если вы должны вращаться и смотреть на разные углы, вы увидите, что ось гизмо неправильно перекрывается с некоторых углов. Другими словами, какая-то ось будет за другим, когда она должна быть перед ней, в зависимости от того, какой порядок обрабатываются гранями. Это очевидно из-за того, что объект (материал) не читает буфер глубины, в том числе для частей, которые он уже сам визуализировал.

В общем, простым решением для визуализации SCNNode перед основной сценой является использование SK3DNode (с его собственной сценой и глубиной буфера) в overlaySKScene сцены. Для сценария, показанного на рисунке в ответе, для этого потребуется дополнительный код для поворота и точное расположение SK3DNode, так что, вероятно, это не то, что искали OP, но это может помочь другим, кто находит этот вопрос.

0

Как объяснялось в моем предыдущем ответе, принятый ответ не является оптимальным и работает правильно только для рекламных щитов, хаусов и других вообще плоских объектов (не обязательно полностью 2D). При использовании 3D-объектов и отключении чтения из буфера глубины и объектов, подобных изображению выше, оно не будет отображаться правильно со всех сторон. Я.e 3D-объект нуждается в для чтения из буфера глубины для определения собственных пикселей и глубины. Это все сказанное, я представляю правильный ответ:

SCNTechnique

Короче говоря, делают 2 дополнительных проходов. Один для контрольной гизмо (DRAW_NODE) ​​и один для смешивания вместе со сценой другим проходом (DRAW_QUAD с шейдером, который использует предыдущие проходы в качестве входов).

Ниже scntec.plist содержимое techique в:

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 
<plist version="1.0"> 
<dict> 
    <key>passes</key> 
    <dict> 
     <key>gizmoonly</key> 
     <dict> 
      <key>colorStates</key> 
      <dict> 
       <key>clear</key> 
       <true/> 
       <key>clearColor</key> 
       <string>0.5 0.5 0.5 0.0</string> 
      </dict> 
      <key>depthStates</key> 
      <dict> 
       <key>clear</key> 
       <true/> 
      </dict> 
      <key>inputs</key> 
      <dict> 
       <key>colorSampler</key> 
       <string>COLOR</string> 
      </dict> 
      <key>outputs</key> 
      <dict> 
       <key>color</key> 
       <string>gizmonode</string> 
      </dict> 
      <key>draw</key> 
      <string>DRAW_NODE</string> 
      <key>node</key> 
      <string>movegizmo</string> 
     </dict> 
     <key>quadscene</key> 
     <dict> 
      <key>colorStates</key> 
      <dict> 
       <key>clear</key> 
       <true/> 
       <key>clearColor</key> 
       <string>sceneBackground</string> 
      </dict> 
      <key>depthStates</key> 
      <dict> 
       <key>clear</key> 
       <true/> 
      </dict> 
      <key>inputs</key> 
      <dict> 
       <key>totalSceneO</key> 
       <string>COLOR</string> 
       <key>a_texcoord</key> 
       <string>a_texcoord-symbol</string> 
       <key>gizmoNodeO</key> 
       <string>gizmonode</string> 
      </dict> 
      <key>outputs</key> 
      <dict> 
       <key>color</key> 
       <string>COLOR</string> 
      </dict> 
      <key>draw</key> 
      <string>DRAW_QUAD</string> 
      <key>program</key> 
      <string>gizmo</string> 
     </dict> 
    </dict> 
    <key>sequence</key> 
    <array> 
     <string>gizmoonly</string> 
     <string>quadscene</string> 
    </array> 
    <key>targets</key> 
    <dict> 
     <key>totalscene</key> 
     <dict> 
      <key>type</key> 
      <string>color</string> 
     </dict> 
     <key>gizmonode</key> 
     <dict> 
      <key>type</key> 
      <string>color</string> 
     </dict> 
    </dict> 
    <key>symbols</key> 
    <dict> 
     <key>a_texcoord-symbol</key> 
     <dict> 
      <key>semantic</key> 
      <string>texcoord</string> 
     </dict> 
     <key>vertexSymbol</key> 
     <dict> 
      <key>semantic</key> 
      <string>vertex</string> 
     </dict> 
    </dict> 
</dict> 
</plist> 

Ниже приводится вершинные шейдеры для второго прохода:

attribute vec4 a_position; 
varying vec2 uv; 

void main() { 
    gl_Position = a_position; 
    uv = (a_position.xy + 1.0) * 0.5; 
} 

Фрагмент шейдер для второго прохода:

uniform sampler2D totalSceneO; 
uniform sampler2D gizmoNodeO; 

varying vec2 uv; 

void main() { 
    vec4 t0 = texture2D(totalSceneO, uv); 
    vec4 t1 = texture2D(gizmoNodeO, uv); 
    gl_FragColor = (1.0 - t1.a) * t0 + t1.a * t1; 
} 

Быстрый код:

if let path = NSBundle.mainBundle().pathForResource("scntec", ofType: "plist") { 
      if let dico1 = NSDictionary(contentsOfFile: path) { 
       let dico = dico1 as! [String : AnyObject] 

       let technique = SCNTechnique(dictionary:dico) 
       scnView.technique = technique 
      } 
} 

код Objective-C:

NSURL *url = [[NSBundle mainBundle] URLForResource:@"scntec" withExtension:@"plist"]; 
SCNTechnique *technique = [SCNTechnique techniqueWithDictionary:[NSDictionary dictionaryWithContentsOfURL:url]]; 
    self.myView.technique = technique; 

Установить имя узла гизмо:

theGizmo.name = @"movegizmo"; 
Смежные вопросы