Hola
Hoy aunque breve, me gustaría hablar sobre una idea que me ha sobresaltado mientras pensaba en esto del HDR. Y aparte voy a probar de paso esto del particionado de la noticia.
Hola
Hoy aunque breve, me gustaría hablar sobre una idea que me ha sobresaltado mientras pensaba en esto del HDR. Y aparte voy a probar de paso esto del particionado de la noticia.
Hola
Continuando con los experimentos de HDR, os quería mostrar lo que hablaba el otro día sobre esos ‘dos rangos’ en los que se dividía la luz.
Bien, en la imagen, podéis ver píxeles con color en el rango LDR [0.0f – 1.0f] y pixeles HDR que son de color rojo (son así porque he puesto un if en le shader para distinguirlos). La manera de interpretar esta imagen es la siguiente:
- Todos los píxeles que no son rojos, son píxeles que tienen rango LDR pero no tienen nada de HDR.
- Todos los píxeles ROJOS son píxeles que aparte de tener LDR tienen HDR.
Por lo tanto, solo el rango HDR será el que pasara a los filtros de glow y demás. Todos los otros píxeles se quedaran igual.
También comente de que si hacíamos dos salidas de píxeles, una en un render target, y otra en otro render target, es posible que perdiésemos el Anti Aliasing por hardware, y así es como es, lo perdemos, pero que no cunda el pánico, pues existen unos filtros de detección de bordes que nos permitirán aplicar un blur sobre esos píxeles y hacer nosotros mismos el Anti Aliasing.
Un saludo
Hola
Para el que no lo sepa, existe una herramienta que se llama 3D Ripper DX que cuando se ejecuta se coloca entre la aplicación y el driver de DirectX. Una vez dentro de la aplicación ejecutada, el Ripper DX nos permite apretar F12 y exportar la escena 3D que estuviésemos observando a un formato que 3D Studio MAX puede entender.
También nos proporciona aparte de las mallas, las texturas que usaba esa aplicación.
Esta herramienta es excelente para poder obtener recursos de modelos y texturas de juegos de PC para nuestras pruebas de renders.
La podéis encontrar AQUÍ.
Un saludo
Hola
Hoy os quería mostrar otra manera de hacer los cálculos de un render HDR un poco diferentes a los que se utilizan en otras aplicaciones como juegos de ordenador.
Debo comentar que no voy a explicar el proceso completo, porque el proceso completo incluye cálculos de tonemapping y blur que ahora no tocaremos.
Concretamente lo que vamos a explicar es como hacer los cálculos de la luz para que no se vean restringidos a un rango de [0.0f – 1.0f].
Bien, la iluminación con HDR según podemos encontrar en tutoriales por internet (como por ejemplo AQUÍ) parte de la base de que todos los cálculos se deben realizar sin ningún tipo de limitador de rangos, es decir, el color no tiene porque ir de 0.0f a 1.0f sino que puede ir de 0.0f a 1000.0f o más.
El caso es que las texturas también tendrían que estar en ese formato, pero como una textura en HDR ocupa una barbaridad, utilizaremos las de toda la vida.
Normalmente en el cálculo de HDR se calculan las ecuaciones sin ningún tipo de limitación entre los parámetros de la luz, por lo tanto acabamos obteniendo valores de color que sobrepasan los rangos de color que un monitor puede ofrecer.
Es aquí donde entra el ser humano y hace una división en los rangos, es decir, el programador coge el valor resultante de ese cálculo sin limitación y especifica 2 campos. El color que va desde [0.0f – 1.0f] y el color que va desde [1.0f-n].
Esta ‘división’ en mi caso es un tanto diferente a como se realiza en otras aplicaciones. Es decir, en otras aplicaciones renderizan en HDR y los resultados los compactan en un float para que no se pierdan los valores exactos y sin limitar de la propia ecuación. Este float es guardado en un Render Target con formato de floats (32R) para su posterior uso.
Lo que yo hago es hacer el cálculo sin limitaciones aparentes (a excepción de los pixeles de las texturas) y al final del pixel shader divido los rangos en LDR y HDR. Recordemos que LDR = [0.0f – 1.0f] y HDR [1.0f – n].
Una vez hecha esta división de rangos, saco en un render target el LDR y en otro el HDR, así el HDR está listo para poder ser objetivo de diferentes post-procesos como blur y demás.
A la izquierda rango LDR, a la derecha rango HDR.
Lo que me queda por descubrir es si una de las salidas de los multi render targets puede ser el Back Buffer. De no ser así tendríamos un problema porque nos quedamos sin Anti Aliasing por hardware.
Un saludo
Hola
Hace ya tiempo que quería implementar una especie de generador de funciones simples para controlar animaciones periódicas de algunos parámetros de las luces al igual como de los materiales.
Concretamente me he implementado una clase que dependiendo del tipo de onda especificado, amplitud y periodicidad, es capaz de devolver en tiempo real los valores de la función deseada.
A continuación tenéis el código de las funciones que tengo implementadas:
//---------------------------------------------------------------------------------
// USE: Updatea
// IN: float - Valor de entrada
// OUT: Void
//---------------------------------------------------------------------------------
void CWaveGenerator::UpdateNone(float inTime)
{
m_fValue = 0.0f;
}
//---------------------------------------------------------------------------------
// USE: Updatea
// IN: float - Valor de entrada
// OUT: Void
//---------------------------------------------------------------------------------
void CWaveGenerator::UpdateOne(float inTime)
{
m_fValue = 1.0f;
}
//---------------------------------------------------------------------------------
// USE: Updatea
// IN: float - Valor de entrada
// OUT: Void
//---------------------------------------------------------------------------------
void CWaveGenerator::UpdateHalfSawTooth(float inTime)
{
m_fTime += inTime;
m_fTime = fmodf(m_fTime,m_fPeriodic);
m_fValue = m_fTime / m_fPeriodic;
m_fValue *= m_fAmplitude;
}
//---------------------------------------------------------------------------------
// USE: Updatea
// IN: float - Valor de entrada
// OUT: Void
//---------------------------------------------------------------------------------
void CWaveGenerator::UpdateSawTooth(float inTime)
{
m_fTime += inTime;
m_fTime = fmodf(m_fTime,m_fPeriodic);
if(m_fTime > (m_fPeriodic / 2.0f) )
{
m_fValue = 1.0f - (m_fTime / m_fPeriodic);
}
else
{
m_fValue = m_fTime / m_fPeriodic;
}
m_fValue *= m_fAmplitude;
}
//---------------------------------------------------------------------------------
// USE: Updatea
// IN: float - Valor de entrada
// OUT: Void
//---------------------------------------------------------------------------------
void CWaveGenerator::UpdateSquare(float inTime)
{
m_fTime += inTime;
m_fTime = fmodf(m_fTime,m_fPeriodic);
if(m_fTime > (m_fPeriodic / 2.0f) )
{
m_fValue = 1.0f;
}
else
{
m_fValue = 0.0f;
}
m_fValue *= m_fAmplitude;
}
Esta clase está destinada a proporcionar los valores de parámetros como la intensidad de la luz o la intensidad de la componente Self-Ilumination de los materiales.
Un saludo
Holas
Hoy os traigo algo interesante con relación a la componente especular.
Normalmente nosotros definimos la cantidad de especular que va a tener un material y nos quedamos tan anchos. Pero las cosas en la vida real son un poco diferentes, y aquí os traigo una idea que estoy desarrollando partiendo de lo que en su día hicieron los chicos de Valve con su ecuación grafica.
El caso es que una superficie con mucha especular (muy brillante), es brillante cuando en casi cualquier ángulo que formemos entre nosotros y la luz. El problema radica en las superficies que NO son brillantes, concretamente las mates, que si las miramos de frente son mates, PERO si estas superficies se ponen en paralelo a nuestro vector de visión y formando ángulo para el brillo con la luz, entonces se vuelven brillantes.
Esto es lo que comentan en la wiki de Valve software, yo concretamente antes de implementarlo lo he probado con una superficie mate y sí que es verdad.
Para ello, nos ayudamos de un parámetro que se llama fresnel. El fresnel es simplemente un producto escalar entre nuestro vector de visión y la normal del píxel. Este valor de fresnel multiplicado por la componente especular nos proporciona “aproximadamente” ese efecto que comentábamos antes.
Yo lo he implementado recientemente en los materiales y la verdad es que cumple su cometido casi a la perfección, aunque el algoritmo no sea idéntico al que utilizan en Valve software.
Un saludo a todos.
P.D: Las imágenes son de la wiki de Valve, las he puesto porque ayuda a entender el concepto que explico.
Holas
Hoy no he podido actualizar debido a que he estado presentando por la mañana el proyecto iL-engine en la universidad, concluyendo así más de un año de desarrollo y cerrando el círculo que me acredita como ingeniero superior, como curiosidad, el proyecto tiene una nota de Matricula de Honor.
Como el proyecto ya esta entregado, hago público el código entero del proyecto como ya comente hace tiempo, aunque también me gustaría comentar ciertas cosas del código a modo de precaución:
- Se tiene que ir con mucho cuidado a la hora de compilar el código debido a que las librerías DXUT pueden dar problemas. Yo concretamente he intentado portar el código de un PC a otro PC y me han dado problemas de compilación. Según parece, el motivo es que hay posibles diferencias entre el SDK de un PC a otro. Por lo tanto os recomiendo que si no os compila de esta manera. Substituyáis las librerías DXUT por las de vuestro SDK.
- Recuerdo a todo el mundo de que este engine NO está diseñado para ser portable o para ofrecer una solución profesional (de momento). Por tanto es necesario entender de que debe ser visto como una ayuda en vuestro desarrollo personal el cual os pueda aportar ideas, trozos de código, etc.
Un saludo y que disfrutéis con el destripe del engine. El código lo podreis encontrar en la sección de Downloads.
Hola
Hoy empiezo mostrando el efecto que he conseguido mediante un sistema de luz ambiente. Concretamente se consigue mediante un objeto llamado CAmbientVolume, que es precisamente el código que os dije en el que estaba experimentando del cubemap simplificado.
Como podéis observar en la fotografía, tenemos una columna con un multi-material observada desde dos puntos de vista. En cada punto de vista podemos observar una tonalidad diferente, la de la izquierda tiene una tonalidad azul, la de la derecha tiene una tonalidad roja. Debemos recordar que la luz ambiente es solo una tonalidad aplicada al objeto, algo muy suave.
Por otro lado tengo una errata que comentar pues en el código de la idea del Cubemap simplificado faltan unas instrucciones, sino no funciona el proceso. Aquí tenéis el nuevo código:
D3DXVECTOR3 vDir = D3DXVECTOR3(GetCameraActive()->GetTarget()); D3DXVECTOR3 vNormDir; D3DXVec3Normalize(&vNormDir,&vDir); D3DXVECTOR3 vColX = Lerp(D3DXVECTOR3(m_vNegX.r,m_vNegX.g,m_vNegX.b),D3DXVECTOR3(m_vPosX.r,m_vPosX.g,m_vPosX.b),(vNormDir.x + 1.0f)*0.5f);// * Abs(vNormDir.x); D3DXVECTOR3 vColY = Lerp(D3DXVECTOR3(m_vNegY.r,m_vNegY.g,m_vNegY.b),D3DXVECTOR3(m_vPosY.r,m_vPosY.g,m_vPosY.b),(vNormDir.y + 1.0f)*0.5f);// * Abs(vNormDir.y); D3DXVECTOR3 vColZ = Lerp(D3DXVECTOR3(m_vNegZ.r,m_vNegZ.g,m_vNegZ.b),D3DXVECTOR3(m_vPosZ.r,m_vPosZ.g,m_vPosZ.b),(vNormDir.z + 1.0f)*0.5f);// * Abs(vNormDir.z); D3DXVECTOR3 vColTmp = Lerp(vColY,vColX,Abs(vNormDir.x)); vColTmp = Lerp(vColTmp,vColZ,Abs(vNormDir.z));
Nótese las dos instrucciones Abs(…) añadidas.
Un saludo
Hola
En la sección de Downloads teneis la memoria que presente para el Proyecto Final de Carrera (PFC). Es una documentación no técnica, es decir, es como una visión general de todo el proyecto, aunque esta el codigo de las ecuaciones de iluminación, etc.
Un saludo