Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Anaglyph o 3D rojo/azul

Iniciado por Hechelion, 21 de Noviembre de 2010, 01:24:26 AM

« anterior - próximo »

Hechelion

Para no escribir 2 veces la misma idea voy a copiar el contenido de la entrada de hoy en el blog de desarrollo.

Citar
Hoy a sido un día de pruebas, todo comenzó ayer, junto al periódico llegó un catalogo para televisores 3d (la moda) pero venía con la novedad que el propio catalogo era en 3D,  se basaba en esos lentes pasivos que filtran la imagen según el color, en este caso rojo y azul. Inmediatamente recordé antiguas películas y libros  que usaban el mismo sistema y sobre todo recordé el proyecto de un amigo que con la misma técnica creaba un cubo que parecía salir del monitor.

Aprovechando los lentes, quise recrear ese proyecto y encontré que la técnica es bastante simple, sólo se necesitan 2 imágenes ligeramente diferentes, simulando la diferencia que existe entre los ojos humanos y luego copiamos el canal rojo de la imagen izquierda sobre el canal de rojo de la imagen derecha. Así que me avoque a la idea de obtener esas imágenes cuando recordé que "Rescate en Dhu Nun" es un juego 2.5D, con lo cual obtener las imágenes era tan simple como sacar 2 capturas del juego pero variando ligeramente la posición de la cámara. Y acá tenemos el resultado:



Para verla en 3D se necesitan los lentes adecuados (esos con el lado derecho azul y el lado izquierdo rojo) y aunque debo reconocer que he hecho trampa pues la imagen está montada en Gimp, se me ocurrió que podría probar con las funciones de pixel de DxLib_32 para tratar de montar las imágenes directamente desde el juego, lo que en teoría debería generar un juego en tiempo real con Anaglyph. Por desgracia, el creados de la librería desaconseja el uso reiterado de esas rutinas porque consumen demasiado recurso, pero no dejaría de ser interesante tener un juego con está técnica, pues para ver  la imagen en 3D no necesitamos de un monitor especial, simplemente necesitamos de los lentes que se pueden conseguir o fabricar en casa por muy poco dinero.

http://www.deitec.cl/feudo/?p=45

Ahora que ya está clara mi idea viene mi pregunta, para conseguir unir los dos canales rojos, lo único que se me ocurre es crear todo sobre una superficie y luego trabajar a nivel de pixel para manipular pixel por pixel el canal rojo, sé que eso debe consumir mucho recursos por tus comentarios, pero me gustaría por lo menos hacer la prueba y si es factible dejar la opción de activar o desactivar el modo anaglyph.

Ya había leído un poco sobre trabajar con superficies (a medio camino una clase para cambiar colores), pero si tuvieras algunos ejemplos de como volcar los Draw sobre una superficie y luego volcar la superficie a pantalla te lo agradecería.




Edit:
Si usan los lentes, está imagen debería colocar el primer plano un poco más adelante que el monitor.

[EX3]

#1
Hacer 3D con dx_lib32, no dejare de asombrarme de ver lo que sois capaces de hacer con esta librería xDD

A ver, para esto deberias usar los render targets que en la ultima version parecer ser que consegui que fueran bien de rendimiento, de hecho lo estuve usando en mi motor haciendo pruebas para hacer inversion de la escena (un espejado) o rotacion de la misma (unas ideas para el juego plataformaas que estaba haciendo) y el rendimiento no iba demasiado mal, una resolución de 800x600 volcandose en un render target iba a unos 40fps que recuerde.

Sobre el como usar los render targets, es muy sencillo. A tener en cuenta:
- Para evitar artefactos y escalas incorrectas, tu superficie ha de tener un tamaño potencia de dos ya que luego la vas a volcar en una textura. Si tu resolución es de 800x600 tu superficie debera ser de 1024x1024.
- Que yo recuerde no tienes limitacion alguna a la hora de dibujar sobre un render target ya que se comporta exactamente igual que el backbuffer de pantalla. La unica limitacion es que solo podras trabajar con un render target a la vez.
- Dado que al final lo que pintaras sera una textura (el resultado del render target), yo te recomiendo que pintes primero, por debajo, un rectángulo de color blanco para que las operaciones con transparencias salgan correctas.

Te dejo por aquí el tutorial 2 modificado para que veas como funcionan los render targets. Puedes directamente abrir el tutorial 2 y pegar este código encima:
Option Explicit

Private Graphics As dx_GFX_Class ' Instancia del objeto grafico de dx_lib32.
Private Render As Boolean ' Controla el bucle de renderizado.
Private Texture As Long ' Identificador de la textura.

Private TextureTarget As Long  ' Identificador de la textura que usaremos como destino de las operaciones de dibujo del render target.
Private RenderTarget As Long ' Identificador de la instancia del render target.

' La idea general del render target es crear una composicion permamente sobre una textura para evitar, por ejemplo, tener que
' redibujarlas continuamente de forma independiente. Definimos pues una bandera para controlar que generamos el contenido
' render target una sola vez:
Private SetContent As Boolean

Private Sub Form_Load()
    Me.Show ' Forzamos al formulario a mostrarse.
    Set Graphics = New dx_GFX_Class ' Creamos la instancia del objeto grafico.
    Render = Graphics.Init(Me.hWnd, 640, 480, 32, True) ' Inicializamos el objeto grafico y el modo de video.
    Texture = Graphics.MAP_Load(App.Path & "\texture.png", 0) ' Cargamos la textura para el sprite.
   
    TextureTarget = Graphics.MAP_Create(512, 512, True) ' Creamos la textura destino del render target.
    ' Al crearla con MAP_Create le indicamos en el 3º parametro que se usara para tal fin.
    ' Como se explica en la documentacion, los mapas o texturas trabajan internamente en tamaños o dimensiones de potencia 2
    ' por lo que no se le podria aplicar un tamaño irregular como 640x480 u 800x600 ya que al crearla se redimensionara
    ' automaticamente al siguiente tamaño o dimension que sea potencia 2 (640x480 -> 1024x512, 800x600 = 1024x1024).
   
    RenderTarget = Graphics.TARGET_Create(TextureTarget) ' Creamos la instancia del render target asignando la textura de destino que hemos creado.
       
    Do While Render
        If Not SetContent Then
            Graphics.TARGET_Open RenderTarget ' Abrimos el render target para capturar operaciones de dibujo.
            ' Solo se puede tener un render target abierto al mismo tiempo.
           
            ' Dibujamos unas cuantas cosas:
            Graphics.DRAW_Map Texture, 0, 0, 0, 0, 0
            Graphics.DRAW_Box 100, 100, 300, 300, 0, &HFFFF0000
            Graphics.DRAW_Line 0, 0, 512, 512, 0, &HFF00FF00
           
            Graphics.TARGET_Close ' Cerramos el render target.
           
            SetContent = True
        End If
       
        ' Dibujamos la textura del render target aplicando transformaciones (dibujamos a mitad de tamaño y rotado unos 26º):
        Graphics.DRAW_MapEx TextureTarget, Graphics.Screen.Width \ 2, Graphics.Screen.Height \ 2, 0, 256, 256, 26, Blendop_Color, &HFFFFFFFF, Mirror_None, Filter_Bilinear, True
        ' Una de las ventajas del render target es que se puede aplicar transformaciones a toda la composicion creada de la misma forma
        ' que una textura normal y corriente, que de hecho, el resultado es ese.
       
        Graphics.Frame ' Renderizamos la escena.
    Loop
End Sub

Private Sub Form_Unload(Cancel As Integer)
    Graphics.MAP_Unload Texture ' Descargamos la textura de memoria.
    Render = False ' Termina el bucle de renderizado.
    Graphics.Terminate ' Terminamos la ejecucion de la clase grafica y liberamos los recursos utilizados.
    Set Graphics = Nothing ' Destruimos la instancia del objeto grafico.
End Sub

Este ejemplo es estático, hace solo una pasada al render target, pero si quitas la comprobación del principio (el valor de la variable SetContent) harás que se repinte el render target en cada ciclo del bucle.

Como ves es sencillo de usar. Ya me contaras si te rinde bien, de hecho, con lo que estuvimos hablando ayer no creo que debieras tener mas problemas ;)

Lo que ya no veo que vaya ir bien es el tema de manipular la imagen pixel a pixel en cada ciclo :-/ Las ultimas versiones de dx_lib32 implementan un sistema mas optimo para leer y escribir valores a nivel de pixel, se obtiene en una llamada todo el array de pixeles que mediante las funciones diseñadas para tal fin permiten recorrerlo mediante coordenadas X e Y y después mediante una sola llamada volver a enviar todo el array modificado a la superficie. El problema es que en VB6.0 te va a caer el rendimiento a lo bestia como tengas que hacer cálculos por cada elemento del array. Prueba si quieres pero no creo que vayas a obtener resultados muy óptimos.

Salu2...
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt

Hechelion

Cuando tenga un tiempo hago las pruebas, sobre los pixel, lo que en realidad necesito es trabajar sobre el canal rojo dela imagen, si por ahí hay una función que me permita manipular solo el canal rojo (o alguna otra librería que se pueda usar en paralelo a la tuya) me vendría bien (y me ahorraría trabajar con los pixel),

Igual voy a probar manejar imágenes con el efecto anaglyph precalculado, a ver si así logro el mismo resultado final pero sin tener que editar en tiempo real el canal rojo de la imagen final.

Por cierto, si no tienes lentes, el efecto que consigo es similar al del i3DG.






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.