2011-02-13 5 views
6

Heyo, esta es mi primera vez haciendo una pregunta aquí así que perdóname si algo me lío> ~ <Busco optimizaciones que puedo hacer en un programa de edición de gráficos

que estoy trabajando un programa similar a openCanvas, los anteriores que permitieron a varias personas dibujar en el mismo lienzo en tiempo real a través de Internet. OC es muy defectuoso y tiene muchas limitaciones, por lo que quería escribir esto.

Lo tengo configurado para que el lienzo se extienda "indefinidamente" en todas las direcciones y se compone de 512x512 bloques de píxeles que no se activan hasta que se dibujan, lo que debería ser realmente fácil de hacer, y Estaba pensando en usar Direct3D para acelerar el hardware, por lo tanto, los 512 bloques cuadrados.

Mi problema viene cuando quiero usar capas, no estoy muy seguro de cómo puedo componer capas rápidamente y sin usar mucha memoria, ya que mi objetivo son las tarjetas de video compatibles con DirectX9 con 128m de memoria y un sistema con aproximadamente 3.2 ghz de potencia de CPU y entre 2 y 8 gigas de ram. Tenía algunos enfoques diferentes que estaba pensando usar y me preguntaba cuál sería probablemente el mejor, y si había algo que pudiera analizar para que funcione mejor.

Mi primera idea fue hacer que el hardware gfx hiciera tanto trabajo como fuera posible haciendo que todas las capas de todos los bloques funcionaran como texturas, y se actualizarían bloqueando el área modificada, actualizándolas en la CPU, y desbloquearlos. Los bloques que no se cambian actualmente se aplanan en una textura y las capas individuales se guardan en la memoria del sistema, lo que reduciría la memoria gfx utilizada, pero podría aumentar significativamente el uso de ancho de banda entre el sistema y la memoria gfx. Puedo ver que el bloqueo y desbloqueo constantes también ralentizan potencialmente el sistema. Otro posible problema es que he escuchado a algunas personas usando hasta 200 capas, y no puedo pensar en ninguna buena manera de optimizar eso dado lo anterior.

Mi otra idea era componer las texturas -completamente- en la memoria del sistema, escribirlas en una textura y copiar esa textura a la memoria gfx para representar en cada bloque. Esto parece eliminar muchos de los problemas con el otro método, pero al mismo tiempo estoy moviendo todo el trabajo a la CPU, en lugar de equilibrarlo. Sin embargo, esto no es gran cosa, siempre y cuando todavía funcione rápidamente. Nuevamente, sin embargo, existe la cuestión de tener un par de cientos de capas. Sin embargo, en este caso, probablemente solo podría actualizar los píxeles finales que realmente están cambiando, que es lo que creo que hacen los programas de nombres más grandes como Sai y Photoshop.

Principalmente estoy buscando recomendaciones, sugerencias que puedan mejorar lo anterior, mejores métodos o enlaces a artículos que puedan estar relacionados con dicho proyecto. Mientras lo escribo en C++, no tengo problemas para traducir desde otros idiomas. Gracias por su tiempo ~

+0

pregunta realmente genial! Me hace querer codificar la misma aplicación por el mero hecho de hacerlo, pero desafortunadamente no tengo tiempo; ( –

Respuesta

4

Estructura de Datos
Definitivamente, usted debe utilizar un árbol de cuatro ramas (u otra estructura de datos jerárquica) para almacenar su lienzo y sus nodos debe contener mucho bloques menores a 512x512 píxeles. Tal vez no sea tan pequeño como 1x1 píxeles, porque entonces la carga jerárquica te mataría, encontrarás un buen equilibrio a través de las pruebas.

Dibujo
Vamos a los usuarios sólo se basan en uno (el más alto) resolución. Imagine una cuadrícula uniforme infinitamente grande (matriz bidimensional). Como conoce la posición del mouse y la cantidad que sus usuarios han desplazado desde el origen, puede derivar coordenadas absolutas. Atraviese el quadtree en esa región (eventualmente agregue nuevos nodos) e inserte los bloques (por ejemplo, 32x32) a medida que el usuario los dibuje en el árbol cuadriculado.Me gustaría almacenar lo que el usuario dibuja en una matriz 2D (por ejemplo, tan grande como su resolución de pantalla) y usar un hilo separado para atravesar/alterar el árbol y copiar los datos del buffer para evitar retrasos.

representación
Recorriendo el árbol cuádruple y la copia de todos los azulejos a una textura y enviarlo a la GPU? ¡No! Verá, enviar una textura que es tan grande como la resolución de la pantalla no es el problema (ancho de banda). Pero atravesar el quadtree y ensamblar la imagen final es (al menos si quieres muchos fps). La respuesta es almacenar el quadtree en la memoria del sistema y transmitirlo desde la GPU. Medios: de forma asíncrona, otro subproceso realiza el recorrido y copia los datos vistos actualmente en la GPU en fragmentos tan rápido como sea posible. Si su usuario no ve el lienzo en resolución completa, no tiene que atravesar el árbol a nivel de hoja, lo que le proporciona un nivel de detalle automático (LOD).

algunos pensamientos al azar con respecto a la estrategia propuesta

  • El enfoque árbol cuádruple es grande, ya que es muy eficiente de la memoria.
  • La idea de transmisión se puede extender a la unidad de disco duro ... SeaDragon
  • Una implementación sofisticada requeriría algo como CUDA.
  • Si su GPU no ofrece el rendimiento/programabilidad necesario, simplemente implemente el recorrido transversal en la CPU: un poco más de retraso hasta que la imagen se muestre completamente, pero debería ser aceptable. No te olvides de programar asincrónicamente usando múltiples hilos para que la pantalla no se congele mientras esperas en la CPU. Puedes jugar con diferentes efectos: mostrar toda la imagen a la vez, borroso al principio y aumentar lentamente los detalles (búsqueda por ancho de primera fila (BFS)) o renderizarlo por mosaico (búsqueda en profundidad por profundidad (DFS)): tal vez mezclado con algunos efectos geniales .
  • La implementación del software debería ser bastante fácil, cuando solo permite ver el lienzo a máxima resolución. Si uno puede alejarse en pasos, eso es un cambio menor en el recorrido. Si uno puede hacer zoom sin problemas, eso requerirá una interpolación lineal entre los mosaicos de los nodos quadtree vecinos, ya no trivial, pero factible.
  • Capas: El quadtree debe proporcionarle un consumo de memoria suficientemente bajo, lo que le permite simplemente almacenar un quadtree por capa. Pero cuando tenga muchas capas necesitará algunas optimizaciones para quedarse en tiempo real: no puede ensamblar 200 texturas por cuadro y enviarlas a la GPU. Tal vez (no estoy del todo seguro de si esa es la mejor solución) para cada capa eliminando todos los nodos de cuadrigas debajo de esa capa cuyos píxeles están completamente cubiertos por la capa anterior. Eso tendría que hacerse en tiempo de ejecución mientras se dibuja y se requiere un buffer de profundidad. Si ofrece una herramienta de borrador, no puede eliminar los nodos, pero tiene que marcarlos como "invisibles" para que puedan omitirse durante el recorrido.

..en la parte superior de mi cabeza. Si tiene más preguntas, ¡hágamelo saber!

+0

El Quadtree parece una estructura de datos realmente genial para los gráficos 2. Creo que lo usaré en mi próximo proyecto! – Cam

+0

@Cam :-) Si los píxeles de color se distribuyen de forma muy dispersa/irregular, es más eficiente en cuanto a la memoria que una matriz 2D. Si cada píxel está cubierto, al menos ofrece un LOD automático (bueno cuando se trata de imágenes enormes). Pero si la resolución que maneja es ~ <4kx4k píxeles, simplemente use matrices 2D. –

+1

Nada menos que una respuesta impresionante, debo decir. Nunca consideré un quadtree, que encajaría extremadamente bien. ¿Tendría alguna idea de cómo maneja Photoshop y otros programas tan sofisticados? – Addi

Cuestiones relacionadas