Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Abstraer Contexto De Renderizado

Iniciado por Minos, 26 de Diciembre de 2003, 01:11:07 PM

« anterior - próximo »

Minos

 Hola a todos, desde hace mucho tiempo llevo leyendo estoy foros sin haber escrito nada. Ultimamente se puede observar que el animo esta decayendo, o por lo menos ya no tienen tanta actividad como antes asi que he decidido participar activamente, que ya era hora.

Bueno, aqui una duda que siempre he tenido y mas o menos tengo mis ideas pero no se si seran las mas apropiadas.

¿Como abstraeis el contexto de renderizado en vuestros motores? es decir, dejando la opcion de que se pueda usar opengl, directx, software, un non-photorealistic etc, ¿creais una interfaz comun, no? de que modo la pasais los datos, (vertices, etc) cada objeto y despues los organiza y dibuja del tiron? los va dibujando? depende de que contexto se haya escogido?

se que hay miembros que lo han echo en sus motores, como Mars-Attack y Drakkar creo

es que estoy intentando hacer un motorcillo y ya que voy a empezar un poco en serio queria que estuviese bien estructurado desde la base, que si no.. ya sabeis...

muchas gracias y animo

Mars Attacks

 No es que decaiga, es que estamos hibernando XD

Yo no tengo ningún motor, soy grafistero. Drakkar, Ager y Haddd sí que están metidos en el tema.

Pasapalabra.

AgeR

 Tampoco soy el más indicado para responder, pero allá mi rollo por si puedes sacar algo en claro :

En primer lugar todo depende de cómo quieras estructurar tu motor. Puedes perfectemente crear un motor "exclusivo" para DirectX por ejemplo, aunque siempre es mejor, como dices, abstraer el API gráfico que se utilice.

Te puedo comentar mi caso. Hasta hace poco, mi motor era exclusivista XD, es decir, estaba pensado para DirectX. Después me dí cuenta de que con relativamente poco trabajo, se podía arreglar de modo que se pudiera separar el código de la parte gráfica del resto. Mi motor va a estar separado en una dll para lo relativo todo lo que no son gráficos y otra para la parte gráfica. En principio tendré solo la implementación en D3D, pero cuando quiera puedo hacer la de OpenGL. Luego en tiempo de ejecucion del motor, símplemente se cargaría la DLL que se desee usar.

Como bien dices, la idea es utilizar una interfaz común, vamos, que de cara al programador, las funciones a utilizar tengan el mismo interfaz.

Por aquí, el único que sé que lo tiene hecho es el señor Drakkar, así que supongo que te podrá comentar el tema con más precisión.

Saludos!

seryu

 Yo si qe no se nada del tema.

De todas formas, creo qe lo mejor es separar las distintas partes del motor como puedan ser input, sonido, control de memoria, maths, etc..  y para los dos distintos modos graficos, qe a dia de hoy serian ogl/d3d xqe en windows poco mas hay para elegir, hacer como dice ager dos dll con sus funciones respectivas y asi poder usar una u otra.

Aunqe si es para aprender igual no merece la pena hacerlo asi.

y suerte.

DraKKaR

 Minos, la estructuración de tu motor debe ser una decisión que tomes basandote en todos los pros y contras que te puedan surgir. Concretamente, sobre lo que dices de abstraer el contexto de render del motor, como bien dice AgeR puedes optar por diseñar tu motor de forma que esté construido directamente sobre un API en concreto (Direct3D/OpenGL/Glide/Software) o como tu bien dices crear una interfaz que se comunique con módulos externos y que estos implementen las funcinoes de render. El hecho de programar el motor directamente sobre Direct3D por ejemplo, tiene la ventaja de que el código y la estructura del motor se puede diseñar de forma que le saque más beneficio al API, almacenando las estructuras de datos y pasandoselas a la API de la forma más eficiente posible.
Por contra, si decides hacer una separación del renderer y del motor, esto te permitirá hacer módulos que hagan el proceso de dibujo env arios APIS sin tener que reescribir el código del motor. Aunque si eliges esta opción es un poco más complicada de dessaroolar, ya que tienes que ingeniartelas para crear una interfaz de render estándar y que sea lo suficientemente buena para los distintos APIS.

En mi caso, tengo el motor y la parte de render físicamente separadas. Para mi motor el renderer es un plugin, que implementa las funciones de interfaz necesarias para comunicarse con el motor. Además, para resolver el problema del almacenamiento óptimo de datos para pasarselos a la API, he optado por dejar que esto lo implemente la parte del plugin-renderer. Es decir, el motor le dice al renderer que quiere almacenar el vértice 200 de una malla como (0,1,3) y el renderer se ocupa de almacenarlo como mejor vaya a ser para pasarselo a la API para dibujarlo. En resumen, el motor se desentiende de las cosas que atañen tan básicamente al renderer.

Esta forma de abstraerte del render, además de poder hacer 2 renderers diferentes (Direct3D y OpenGL) para mi motor y elegir en cualquier momento cual usar, permite además que se puedan hacer diferentes implementaciones del renderer incluso usando el mismo API, pero usando técnicas de render distintas para aprobechar en concreto unas capacidades de las aceleradoras u otras. Concretamente haciendo pruebas, tengo hechos los siguientes renderers:
- OpenGL_LM - Usa opengl con iluminación mediante lightmaps e iluminación por vértice
- Direct3D3 - Usa direct3d con iluminación mediante lightmaps e iluminación por vértice
- OpenGL2 - usa opengl con iluminacioón por pixel sin uso de shaders.
- OpenGL-sh1 - usa opengl con iluminación por pixel usando vertex programs y fragment programs.

Además me guistarái contactar con fiero porque se que está haciendo un motor de render por software, y me gustaria implementar un plugin-renderer para mi motor que hiciera el renderer por software.

Como verás, a mi personalmente me gusta más la idea de hacer la separación en distintos módulos. Ya que así, además de todo lo anterior te permite que terceras personas ajenas al motor, peudan implementar sus propios renderers personalizados. Como el de un amigo (Schaffer) que estaba implementando un renderer que use NPR.

Ale, espero que te sirva para aclararte las ideas (XD) y que no te haya rallado con mis divagaciones.

Saludos.

PD: Haddd, también me gustaría hablar contigo para ver si podemos hacer un renderer con tu motor de render, que he visto que te estava quedando bastante bien, y tu implementación en direct3d será más eficiente que la mia XD.

Loover

 Bueno te voy a comentar lo que tengo, y tb lo que tengo pensado hacer.

Actualmente tengo un motorcillo 2d que funciona tanto en OpenGl como en Direct3d. Por lo menos la parte que tengo hecha, jeje, pues no está terminado.
Este motor, que en realidad no es un motor sino una Api gráfica tiene de momento una serie de funciones que se puede usar desde fuera (es una dll).
Así que, un aplicación externa que use esta dll bastará con hacer un:
LOV_Render = new LOV_RenderGL;
o
LOV_Render = new LOV_RenderD3D;

Para usar el render de Opengl o de Direct3d.

Igualmente, tengo otros objetos que actuan de forma similar.
Por ejemplo esta: (que es un gestor de superficies, aunque no las típicas de D3D sino imagenes cortadas
en texturas para poder renderizar las que no son potencia de 2 a cualquier tamaño)
LOV_SurfaceManager = new LOV_SurfaceManagerGL;
o
LOV_SurfaceManager = new LOV_SurfaceManagerD3d;

Por otro lado, tengo objetos que por su naturaleza pueden ser totalmente ajenos a OGL o D3D por lo que van por libre. Como:

LOV_Window, LOV_ImageManager (usa Devil), etc

¿Cómo se hace lo de arriba? Pues utilizando métodos virtuales para hacer uso del polimorfismo.

Pero bueno, para el momento actual, en que desarrollo bajo Windows, me conviente tenerlo así. Pero sinembargo si cambiara a linux tendría que quitar todo lo referente a D3D pues no compilaría. Pero eso es muy facil, tan solo tendría que suprimir todos los objetos D3D. No habría que tocar ni una sola linea de código, tan solo suprimer los .cpp y .h.

Una vez terminada esta Api gráfica (2d de momento). Lo que tengo pensado es crear otra dll, pero esta vez que me proporcione mecanismos para gestionar estos recursos y hacer un juego facilmente. Hablando en plata, voy a hacer algo como el cDiv, que te permite mediante templates programar al más puro estilo div. Pues me encanta ese estilo de programación basado en procesos.

Un saludo!

IndieLib Libreria 2.5d utilizando aceleración por hardware para la programación de juegos 2d.
Indie Rover The monkeys are reading!

Haddd

 Eso de hacerlo independiente OGL/D3D está muy bien, pero..¿teneis tanto tiempo para poder hacer las 2 versiones? Yo apenas puedo con D3D. Además, hay cosas en D3D que no se pueden hacer que en OGL sí las haces, o es muchísimo más sencillo. Y al revés, a ver si existen las clases de D3DX en OGL. No, no existen, aunque por supuestísimo se pueden hacer, pero..¿y el tiempo...?

Yo opté por D3D, después pasé a OGL y volví a D3D. He cambiado montones de veces las clases principales, y la forma de trabajar el motor, y no me puedo ni imaginar lo que habría tardado si lo hiciera con 2 API.

Evidentemente lo mejor es hacerlo por separado, pero...¿tendrás tiempo?

Es mi experiencia, pero espero que te sirva...

Loover

 Eso depende de como te lo tomes Hadd. Para mi no es más que un hobby, una afición, como cuando voy al cine. No tengo prisa, no tengo que responder ante nadie, si lo dejo a medias me da igual, no tengo en mente ningún juego, y un largo etc.
Pero está claro, que si lo que quieres es hacer un motor para venderlo, o hacer un juego, hay que dejarse de chorradas e ir a lo práctico.
Cuando me dió por hacer un juego, ni siquiera intenté hacer un motor. Cogí fenix, hice el juego y ale, a correr.
Ahora me apetece perder el tiempo un añico o dos experimentando con esto.

Un saludo!
IndieLib Libreria 2.5d utilizando aceleración por hardware para la programación de juegos 2d.
Indie Rover The monkeys are reading!

AgeR

 Desde luego depende del caso. Por ejemplo haddd, teniendo la filosofía de siempre estar a la última, pues hace bien centrándose en Direct3D exclusivamente.
Yo por el contrario intento que mi motor vaya en el máximo de ordenadores posible, aunque no esté tecnológicamente hablando ni a la altura de los tobillos del de haddd.
Son dos filosofías distintas, pero perfectamente válidas.

Por ejemplo, para haddd resultaría algo titánico hacer un renderer para OpenGL. Para mí, seguramente, menos ya que no uso nada del "nuevo mundo".

Además, no creo que nadie pretenda vender su motor a nadie, porque sinceramente no creo que pudiera. Incluso haddd creo recordar que propuso desarrollar su motor entre todos (o algo así).

Saludos!

Minos

 La verdad es que me ha quedado todo lo de abstraer mucho mas claro. Pero me habeis liado mas con los pros y los contras  :D .
Lo mas seguro que me dedique solo a una API por que tiempo no hay, lo que pasa es que quiero que el motor este diseñado de manera que si quiero pasarme a otra, hacer un non-photorealistic, etc,  no tenga que andar reaciendo el codigo. Asi que las hare lo mas independientes que pueda con funciones lo mas genericas posibles.
El mayor pero que veo es que programar algunas funciones utiles de DirectX llevaria muchas lineas en OpenGL, como hacer toda la clase de vectores por decir alguna, y muchas mas (carga de archivos etc). Pero al tener pensado que el motor tb tiene que ir en linux no me queda mas remedio  :)

Bueno, muchas gracias a todos por aclararmelo

Loover

 Planteatelo de forma que solo haya lineas de la Api justo donde deba haberlas. Por ejemplo, la clase ventana no tiene porque tener ni usa sola linea de la Api 3d. Basta con pasarle luego a la clase render un puntero a un objeto ventana a la hora de inicializarlo.
Luego, donde no haya más remedio, por la naturaleza del objeto, de que este implementado con una api u otra utiliza métodos virtuales y polimorfismo.

Por ejemplo. SurfaceManager.h puede ser una clase normal y corriente con un método virtual.

virtual bool AddImage (....);

Luego tienes, para cada api, clases derivadas (Ejemplo: class SurfaceManagerD3D : public SurfaceManager) de esa clase:

- SurfaceManagerOGL.cpp y SurfaceManagerOGL.h (Opengl)
- SurfaceManagerD3D.cpp y SurfaceManagerD3d.h (Direct3d)

Y cada una de ellas tiene a su vez un método público llamado:

bool AddImage (....);

De forma que si luego quieres usar el SurfaceManager de D3d haces:
SurfaceManager *s = new SurfaceManagerD3d;

No sé si con esta explicación te habré liado más, pero así es como lo hago yo. Si te interesa puedo mandarte un ejemplo.

De esta forma puedes empezar a hacerlo solo con una api. Y más tarde añadirle otras.

Un saludo!
IndieLib Libreria 2.5d utilizando aceleración por hardware para la programación de juegos 2d.
Indie Rover The monkeys are reading!

Minos

 Pues la verdad es que te agradeceria que me enviases la interfaz general de la clase de render,solo el h, es que estoy haciendola y no se que funciones poner y de que manera (ya la he reecho 4 veces...). perdona las molestias

Loover

 Ningún problema. Te mandaré la clase ventana. Y tb la clase render tanto de d3d como de ogl. Los .cpp tb hombre :D

Lo preparo para que se pueda compilar quitándole includes de otras partes y te lo mando cuando vuelva, que ahora voy a echar una pachanga. ciao!
IndieLib Libreria 2.5d utilizando aceleración por hardware para la programación de juegos 2d.
Indie Rover The monkeys are reading!

Minos

 Okis, muchisimas gracias, me has alegrado el dia  :D , cuando puedas que no hay prisa.
Cuando lo tenga le ehcare un vistazo para aprender y ya te comento. byez

Loover

 Ale ya he vuelto, toy hecho un crack, mejor que el "becan".

Te he preparao la clase LOV_Window (ventana de win3d), y los dos renders LOV_RenderD3d y LOV_RenderGL accedidos mediante polimorfismo y métodos virtuales desde LOV_Render. Que feo suena eso, ¿verdad? Pero cuando lo veas verás que está chupao. Ya de paso te he metido una clase más, la DebugApi que es un bonito debug (no tan bonito como ese de Ager en html pero es vistoso). El debug te sacará en un fichero información de tu tarjeta y tal y cual.

He colgado todo aquí:
http://galeon.com/loover/Render.rar

Lo pondría como código de la semana pero me da vergüenza  :rolleyes:

Espero que te sirva de ayuda, para cualquier cosas que no entiendas dame un toque. Un saludo!

Si todo va bien debería salirte la ventana en negro con los fps arriba y aparte un Debug.log tal que así (en este caso el de OGL)
Citar
[Debug.log]: (Martes, 30 de Diciembre del 2003)

[19:42:38] [ BEGIN ] -- Creando la ventana --
                     {
           [  OK   ]    Clase de la ventana registrada
           [  OK   ]    Ventana creada
           [ INFO  ]    Modo: Ventana
                     }
[19:42:38] [  END  ] Ventana OK [Tiempo tardado = 0.016 seg]
---------------------------------------------------------------------
[19:42:38] [ BEGIN ] -- Inicializando OpenGL --
                     {
           [  OK   ]    Obteniendo el device context de la ventana
           [  OK   ]    Eligiendo el formato de pixel
           [  OK   ]    Configurando el formato de pixel
           [  OK   ]    Creando el rendering context
           [  OK   ]    Activando el rendering context
           [ INFO  ]    Modo de video: 640 x 480 x 32
                     }
[19:42:40] [  END  ] OpenGL OK [Tiempo tardado = 1.5 seg]
---------------------------------------------------------------------
[19:42:40] [ BEGIN ] -- Información del hardware --
                     {
           [ INFO  ]    Versión OpenGl: 1.3.4010 WinXP Release
           [ INFO  ]    Marca: ATI Technologies Inc.
           [ INFO  ]    Chip: RADEON 7200 SDR x86/MMX/3DNow!/SSE
           [ INFO  ]    Tamaño máximo de textura: 2048 x 2048
[19:42:40] [ BEGIN ]    -- Extensiones soportadas --
                        {
           [  OK   ]       GL_ARB_multitexture
           [  OK   ]       GL_EXT_texture_env_add
           [  OK   ]       GL_EXT_compiled_vertex_array
           [  OK   ]       GL_S3_s3tc
           [  OK   ]       GL_ARB_occlusion_query
           [  OK   ]       GL_ARB_texture_border_clamp
           [  OK   ]       GL_ARB_texture_compression
           [  OK   ]       GL_ARB_texture_cube_map
           [  OK   ]       GL_ARB_texture_env_add
           [  OK   ]       GL_ARB_texture_env_combine
           [  OK   ]       GL_ARB_texture_env_crossbar
           [  OK   ]       GL_ARB_texture_env_dot3
           [  OK   ]       GL_ARB_texture_mirrored_repeat
           [  OK   ]       GL_ARB_transpose_matrix
           [  OK   ]       GL_ARB_vertex_blend
           [  OK   ]       GL_ARB_vertex_buffer_object
           [  OK   ]       GL_ARB_window_pos
           [  OK   ]       GL_ATI_envmap_bumpmap
           [  OK   ]       GL_ATI_map_object_buffer
           [  OK   ]       GL_ATI_texture_env_combine3
           [  OK   ]       GL_ATI_texture_mirror_once
           [  OK   ]       GL_ATI_vertex_array_object
           [  OK   ]       GL_ATI_vertex_streams
           [  OK   ]       GL_ATIX_texture_env_combine3
           [  OK   ]       GL_ATIX_texture_env_route
           [  OK   ]       GL_EXT_abgr
           [  OK   ]       GL_EXT_bgra
           [  OK   ]       GL_EXT_clip_volume_hint
           [  OK   ]       GL_EXT_draw_range_elements
           [  OK   ]       GL_EXT_fog_coord
           [  OK   ]       GL_EXT_multi_draw_arrays
           [  OK   ]       GL_EXT_packed_pixels
           [  OK   ]       GL_EXT_point_parameters
           [  OK   ]       GL_EXT_rescale_normal
           [  OK   ]       GL_EXT_secondary_color
           [  OK   ]       GL_EXT_separate_specular_color
           [  OK   ]       GL_EXT_stencil_wrap
           [  OK   ]       GL_EXT_texgen_reflection
           [  OK   ]       GL_EXT_texture3D
           [  OK   ]       GL_EXT_texture_compression_s3tc
           [  OK   ]       GL_EXT_texture_cube_map
           [  OK   ]       GL_EXT_texture_edge_clamp
           [  OK   ]       GL_EXT_texture_env_combine
           [  OK   ]       GL_EXT_texture_env_dot3
           [  OK   ]       GL_EXT_texture_filter_anisotropic
           [  OK   ]       GL_EXT_texture_lod_bias
           [  OK   ]       GL_EXT_texture_object
           [  OK   ]       GL_EXT_texture_rectangle
           [  OK   ]       GL_EXT_vertex_array
           [  OK   ]       GL_HP_occlusion_test
           [  OK   ]       GL_NV_texgen_reflection
           [  OK   ]       GL_NV_blend_square
           [  OK   ]       GL_NV_occlusion_query
           [  OK   ]       GL_SGI_color_matrix
           [  OK   ]       GL_SGIS_texture_edge_clamp
           [  OK   ]       GL_SGIS_texture_border_clamp
           [  OK   ]       GL_SGIS_texture_lod
           [  OK   ]       GL_SGIS_generate_mipmap
           [  OK   ]       GL_SGIS_multitexture
           [  OK   ]       GL_SUN_multi_draw_arrays
           [  OK   ]       GL_WIN_swap_hint
           [  OK   ]       WGL_EXT_extensions_string
           [  OK   ]       WGL_EXT_swap_control
[19:42:40] [ BEGIN ]       -- Chequeo de extensiones utilizadas --
                           {
           [ INFO  ]          Soportada: GL_texture_edge_clamp
           [  OK   ]          Se podrá hacer uso de filtros LINEAR
                           }
[19:42:40] [  END  ]       Chequeo OK [Tiempo tardado = 0 seg]
                        }
[19:42:40] [  END  ]    Extensiones OK [Tiempo tardado = 0 seg]
                     }
[19:42:40] [  END  ] Hardware Ok [Tiempo tardado = 0 seg]
---------------------------------------------------------------------
[19:42:41] [ BEGIN ] -- Terminando OpenGL --
                     {
           [  OK   ]    Terminando RC
           [  OK   ]    Terminando DC
                     }
[19:42:41] [  END  ] OpenGL terminado  [Tiempo tardado = 0.156 seg]
---------------------------------------------------------------------
[19:42:41] [ BEGIN ] -- Destruyendo la ventana --
                     {
           [  OK   ]    Eliminando ventana
           [  OK   ]    Quitando el registro a la clase ventana
                     }
[19:42:41] [  END  ] Ventana destruida [Tiempo tardado = 0.125 seg]
---------------------------------------------------------------------
IndieLib Libreria 2.5d utilizando aceleración por hardware para la programación de juegos 2d.
Indie Rover The monkeys are reading!






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.