macos - Usar funciones de fusión en Scenekit
opengl (2)
Por lo que puedo decir después de varias horas de experimentación, no hay forma de establecer realmente el modo de mezcla utilizado para renderizar una pieza de geometría, o para controlar el modo de combinación general utilizado para renderizar usando SCNTechnique.
SceneKit parece tener solo dos modos de fusión diferentes, uno donde la mezcla está desactivada, si considera que el material es opaco, y un modo de fusión "transparente" (GL_ONE, GL_ONE_MINUS_SRC_ALPHA) cuando considera que un material es transparente. Estas son malas noticias si quieres renderizar cosas como "resplandores", porque no parece posible obtener un modo de combinación (GL_ONE, GL_ONE) que quieras para emitir haces de luz o brillar.
Sin embargo, he encontrado un truco para evitar esto que no te da el control adecuado sobre la mezcla, pero que funciona si quieres renderizar cosas brillantes como rayos de luz:
Debido a que SceneKit utiliza el modo de fusión GL_ONE, GL_ONE_MINUS_SRC_ALPHA, todo lo que debe hacer es renderizar su geometría con un canal alfa de 0. Lamentablemente, no es tan simple porque el sombreador SceneKit predeterminado descarta fragmentos con un canal alfa de 0, por lo que nada realmente prestado Una solución rápida y sucia es utilizar un mapa de color difuso que tiene un canal alfa de 1 (suponiendo un mapa de 8 bits por canal con valores de 1-255). Debido a que el canal alfa es casi 0, casi toda la imagen de fondo se mostrará a través de. Esto funciona principalmente, pero debido a que el alfa no es bastante cero, todavía producirá artefactos visibles en áreas brillantes.
Para evitar este problema, puede usar un mapa de textura estándar con un canal alfa sólido, pero adjunte un modificador de sombreado a "SCNShaderModifierEntryPointFragment", que simplemente establece el canal alfa del color de salida en cero. Esto funciona porque los modificadores del sombreador de fragmentos vienen después de la eliminación de alfa cero.
aquí está ese modificador de sombreado en su totalidad:
#pragma transparent
#pragma body
_output.color.a = 0;
tenga en cuenta la declaración "#pragma transparent" en la primera línea; esto es necesario para obligar a SceneKit a usar su modo de fusión transparente, incluso cuando no lo haría de otra manera.
Esta no es una solución completa, porque no es un control real sobre la mezcla (solo es un truco útil para producir brillos de luz, etc.) y el proceso de sombreado ciertamente no es tan óptimo como podría ser, pero funciona bien en este caso.
No veo una manera obvia de cambiar la función de fusión (glBlendFunc) por un nodo o geometría de kit de escena: no parece ser parte del material, y no es muy obvio a partir de la documentación del kit de escena cómo organiza pases de render ¿Necesito hacer un delegado de Render para el nodo que solo cambia el modo GLblending, o debo configurar de alguna manera diferentes pases de renderizado, etc. (No es obvio en la documentación cómo controlo cosas como pases de renderizado)?
¿Va a mezclar? - SceneKit
¡Sí! En iOS 9 y OS X 10.11 (actualmente en beta), blendMode
es un atributo de los materiales, por lo que puede representar cualquier contenido de SceneKit con mezclas aditivas, multiplicativas u otras.
Pero mientras todavía soporte versiones anteriores de OS ... SceneKit en iOS 8.x y OS X 10.8 a 10.10 no ofrece API para modos de fusión.
Hay un par de opciones que puede ver para solucionar esto.
1. Configure el estado GL usted mismo
Si llama a glBlendFunc
y a sus amigos antes de dibujar SceneKit, SceneKit lo renderizará utilizando el estado de mezcla que haya seleccionado. El truco es establecer el estado en un momento apropiado para dibujar su contenido mezclado y dejar el estado como espera SceneKit para el contenido no mezclado.
Si configura su estado GL en el renderer:willRenderScene:atTime:
y lo renderer:didRenderScene:atTime:
en el renderer:didRenderScene:atTime:
aplicará la mezcla a toda la escena. Probablemente no es lo que quieres. Y no puede usar un delegado de renderizador de nodos solo para el nodo que desea mezclar porque entonces SceneKit no procesará el contenido de su nodo.
Sin embargo, si puede encontrar una buena manera de encapsular esas llamadas, deberían funcionar. Intenta renderizar nodos relacionados con un programa personalizado y establece tu estado en handleBindingOfSymbol:usingBlock:
¿quizás?
2. Utilice la combinación programable (solo iOS)
El hardware de gráficos en dispositivos iOS admite la lectura del valor de color de un fragmento de destino en el sombreador. Puede combinar este valor con el color que desea escribir de muchas maneras; por ejemplo, puede crear modos de fusión estilo Photoshop .
En SceneKit, puede usar esto con un modificador de sombreado de fragmento: lea desde gl_LastFragData
y escriba a _output
. El ejemplo aquí usa eso para hacer una mezcla aditiva simple.
#pragma transparent
#extension GL_EXT_shader_framebuffer_fetch : require
#pragma body
_output.color = gl_LastFragData[0] + _output.color;