Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Render Por Software

Iniciado por Pogacha, 11 de Octubre de 2004, 02:21:07 PM

« anterior - próximo »

Pogacha

 En este momento se me ocurre que se podria hacer render por software con mucho exito.
Se me ocurre un metodo pero no tengo coraje como para implementarlo todavia, por eso espero criticas:


Estructuras:

struct TWColor {
Word r,g,b;
}

struct TWVector {
Word x,y,z;
}

struct TPixel {
 TWVector Posicion, Normal;
 TWColor Difusa, Especular, Iluminacion;
 Word IZ;
};


TPixel Pantanlla[x*y];


void Rasterizar( TPixel *p, int c, ...)
{
...
 while(c--)
{
    if(IZ < iz)
   {
         p->Posicion= Pos;
         p->Normal= TexturaNormal->Texels[ u * TexturaNormal->x + v ];
         p->Difusa= TexturaDifusa->Texels[ u * TexturaDifusa->x + v ];
         p->Especular= TexturaEspecular->Texels[ u * TexturaDifusa->x + v ];

   }
 }
...
}

Estoy editanco ...

Pogacha

 Bien me pase de los quince minutos...

struct TWColor {
Word r,g,b;
}

struct TWVector {
Word x,y,z;
}

struct TPixel {
TWVector Posicion, Normal;
TWColor Difusa, Especular, Iluminacion;
Word IZ;
};


TPixel Pantanlla[x*y];


void Rasterizar( TPixel *p, int c, ...)
{
...
while(c--)
{
if(IZ < iz)
{
p->Posicion= Pos;
p->Normal= TexturaNormal->Texels[ u * TexturaNormal->x + v ];
p->Difusa= TexturaDifusa->Texels[ u * TexturaDifusa->x + v ];
p->Especular= TexturaEspecular->Texels[ u * TexturaDifusa->x + v ];

}
}
...
}

Y despues uso un

float DepthBuffer [6][X][Y]; como un cube map

void RenderDepthToCubeMap(float x, float y, float z)
{
 if(x>y && x>z) DepthBuffer[0][(y/x + 0.5) *X][(z/x + 0.5) *Y] = x*X+y*y+z*z;
   else ...
}

float GetDepthToCubeMap(float x, float y, float z)
{
 if(x>y && x>z) return DepthBuffer[0][(y/x + 0.5) *X][(z/x + 0.5) *Y];
   else ...
}

Y asi hago algo como un shadow mapping pero con un CubeMap.

Despues renderizo todos los poligonos utilizando la funcion de arriba.

por cada luz escribo su depthbuffer rasterizando poligonos sobre sus caras. Solo los poligonos que estan adentro de la caja de incidencia de la luz. Previamente escribo con un imposible todo el depthmap

Para cada punto del recuadro de la pantalla donde la luz tiene incidencia, comparando x^2 + y^2 + z^2 de la estructura pixel con su proyeccion en el cube map determino sombra, y calcula la luz por pixel.

Despues termino la ecuacion de iluminasion y genero un rgb que vuelco en la pantalla verdadera.

Creo que esto debe ser rapido, usando todas las optimizaciones que se pueden hacer por software, las cuales son muchas, mmx, 3dnow y demas creo que se puede hacer algo que funciones, no me he puesto a calcular el tiempo pero seguramente sera lento (comparado con las placas de video).

Todavia no estoy convecido como para lanzarme a hacerlo, estoy esperando darme cuenta que no se puede y no conviene o que salga GL_RENDER_TO_DEPTH_CUBE_MAP_POGACHAEXT y GL_CUBE_SHADOW_MAP_POGACHAEXT entendiendose por POGACHAEXT que yo propuse la extencion  ;) .

Algun comentario?

fiero

 No sé si te he entendido bien. ¿Te refieres a un render normal, como lo hace una tarjeta aceleradora, es decir, pintando todas las scanlines de los triangulos? ¿o a una especie de raytracer?

Si es lo primero, no es tan facil como parece. Mi función de render de una malla tiene más de 1500 lineas de ensamblador, y con mmx. Hay que hacer recorte de polígonos, unos recortes se hacen con las coordenadas 3D del triangulo (frustum) para recortar el triangulo según el near y el far plane, otros recortes se hacen en 2D, una vez convertidas las coordenadas a pantalla. Después, si vas a renderizar los polígonos con corrección de perspectiva, o con algún filtro bilinear, o haciendo los degradados de luz a lo largo del polígono, etc. O sea, que la cosa al final se complica...

un saludo
www.videopanoramas.com Videopanoramas 3D player

Pogacha

 Previamente a aprender  OpenGL, yo hacia muy gustosamente render por software (estilo quake I/II) semi-optimisado en ensamblador hacia el inner-loop lineal (no conocía mmx) la correccion de perspeciva la hacia en C, usaba span-buffers y z-buffer para renderizar el arbol bsp y usaba poligonos, no triangulos, para aprovechar la estuctura del medio borde en el sbuffer y demas, para los .mdl si usaba triangulos pero usaba interpolacion lineal sin correccion de perspectiva. Tambien  Filtrado usaba filtrado bilineal en 8, 15, 16, 24 y 32 bits, en 8 bits volaba en un pentium 3 700mhz, pero despues me enamore del OpenGL y abandone el render por software.

Sobre el tipo de render, me referia al mismo que haces tu, pero en vez de tener un framebuffer, tengo un datosbuffer, un arreglo bidimencional de estructuras con informacion de ese pìxel (posicion en camara-space, normal en camara-space, y propiedades de iluminacion (color difuso, especular, ambiente ).
Estaba obviando los metodos de renderizado común y hacia incapie en las tecnicas nuevas que proponía.
¿Por que semejante cosa?
Cuando hago iluminación por pixel practicamente tengo que hacer un render por luz. En cambio puedo almacenar todos estos datos que son comunes para cada luz y luego hacer una pasada por cada una de ellas y calcular mas tarde la ecuación de iluminación, pero en vez de utilizar stencil-shadows que implica aproximadamente 3 render por luz, usar un sistema de renderizado directo (un shadow map cubico) y bajo a 2 render por luz, pero solo debo llenar un z-buffer con lo que puedo hacer algo mas optimo, ademas el tamaño de este cube-depth-map que propongo puede ir en función de la distancia de la camara a la luz y el álcanze de la luz.
La idea de esto es tiempo real, pero me parece que aun que sea un solo render fuerte de igual manera sería un asesinato al CPU, estos son mis cuentas:
640x480 Pixels
x una constante relativa de (4 Texturas x 3 canales * interpolacion 3-lineal + Zbuffer + Posicion ) = 40x
Pentium 2.4 (Supongamos 2 instrucciones por vez) / 640x480x40x60 Frames por segundo = 6,5 ciclos por pixel.
El costo de mi inner loop lineal sin ningun filtro era de 2 ciclos por pixel ( sin usar MMX ), y la verdad es que no creo que esto sea extendible a 4 texturas  <_< .
Con lo que creo que debe ser imposible ¿verdad?, tu eres el experto en MMX y demas tecnicas  B).

Pero aun así sigo pensando en estas dos cosas:
1 - Render a un cube-depth-map, la cual deberia proponerla en algun lado, que en realidad es renderizar en 6 zbuffers con esto crear un cube-depth-map el cual contenga tenga como elementos float32.
De esta manera, es lo mismo que un shadow-map pero seria omni-direccional.

2 - Hacer una pasada primera donde recolecto información de cada pixel de la pantalla y no tengo que hacer multiples pasadas donde calculo lo mismo cada vez. Se me ocurrio hace un rato que podia hacer multiples render por hardware (primero la difusa, luego la especular, luego los normales) creando asi muchas pbuffer que uso como texuras de entrada para el shader de iluminacion, todo usando el mismo zbuffer, pero me parece que pierdo dinamismo en hacer multiples render. He estado viendo algo sobre multiples objetivos, pero mi placa no tiene esa capacidad.

Todo esto nace en realidad, por intentar reducir mi fragment-program que para calcular la iluminación tiene 13 instrucciones, pero 7 son para extraer y arreglar datos que pudiera tener precalculados.

Por eso mi nostalgia al render por software.

fiero

 ahá! Perdona, pensaba que no tenias la experiencia que tienes en el tema, por eso decía que no es tan facil como parece.

La verdad es que creo que no merece la pena que lo hagas por soft. Quizás la técnica que comentas la puedes realizar por hardware con mejores resultados. Tirar de CPU es demasiado lastre para el relleno de polígonos.

La única razón de que yo siga con el render por soft es para bajar los requerimientos mínimos de mi programa, ya que no requiere ni DX ni OpenGL ni tarjeta aceleradora. Pero yo solo renderizo objetos simples, sin sombras y además pocos y con las mallas lo más simples posibles.

La verdad es que las mmx para los inner loops son una maravilla, puedes meter un montón de instrucciones en el bucle sin que apenas se aprecie una bajada de velocidad. Lo que pasa es que para hacer las cosas con cierta calidad, hay que usar muchos calculos con numeros flotantes y eso al copro si que le cuesta. Quizás con 3Dnow o SSE se pueda acelerar más, pero tampoco será una diferencia abismal.

Resumiendo, la mezcla de render hard-soft :huh: no me parece buena idea cuando se busca velocidad  

un saludo

PD:

CitarEl costo de mi inner loop lineal sin ningun filtro era de 2 ciclos por pixel ( sin usar MMX ),

:blink: Como hacias eso?

Porque a mi sin ningun filtrado me consume mucho más. Simplemente el incremento del puntero de video "add edi,4" (en el caso del escritorio a 32bits) ya me supone esos dos ciclos
www.videopanoramas.com Videopanoramas 3D player

Pogacha

 add edi,4
Es ineficiente incrementar el puntero de 4, lo mejor es usar una
[/CODE]mov dword ptr  [base + ecx *4], eax
con ecx que cuenta para atras. Pero mejor aun es un

[CODE]
bucle:
...
... ; calculo las variables de correccion de perspectiva
...
push ecx;
mov ecx, tabladesalto[ecx]
jmp [base+ecx]
escribe_16_pixel:
...
pop ecx
sub ecx, 16
jnz repetir bucle
jmp fin
...
...
escribe_seis_pixel:
...
jmp fin
escribe_cinco_pixel:
...
jmp fin
escribe_cuatro_pixel
...
jmp fin
escribe_tres_pixel
...
jmp fin
escribe_dos_pixel
...
jmp fin
escribe_un_pixel:
...
jmp fin
base:
fin:

Y esto es mejor que el codigo automodificable, pero tienes que tener ganas de escribir 16 codigos diferentes.
Aparte de esto el innerloop del que te hable es para texturas de 256x256x8 bits y tiras de 16 pixels con interpolacion lineal o sea, cálculo de la correccion de perspectiva cada 16 pixels.

Saludos

MChiz

 Hola!

Creo que lo que quieres ya existe por hard. Se llama 'deferred shading'. Una tecnica realmente interesante =)

Pogacha

 Si... lo vi en un documento de NVidia o por ahí ... <_< , y bueno ... pense que habia descubierto algo, incluso revisando el shadow mapping con el cube map tambien lo encontré en un codigo de un motor en pascal, o sea ... no encontre nada nuevo y ambas implementaciones se pueden hacer por hardware con toda comodidad.
Saludos.






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.