Buenash! Pues veréis, yo dibujo muchas primitivas con 4 vértices formando un cubo. Tenemos los 4 muros, rotados 0, 90, 180 y 270º respecto al eje z, pero nada más (100% verticales), luego la primitiva del techo, mirando hacia arriba, y la del suelo, hacia abajo. Son 6 primitivas cuadradas formando un cubo, para simplificar el problema. Todo el tema de la iluminación ya lo tengo montado y funciona, yo pongo varias luces puntuales en el escenario e ilumina las caras. Aquí viene el problema...
Supongamos, para ejemplificar, el cubo centrado en 0,0,0, y las caras a 100 píxeles de distancia (la arista sería de 200)
Quiero, para cada primitiva (para cada cara del cubo), decir si está "lo suficientemente iluminada". Yo tengo acceso a cada cara y sé cuál de ellas es. Por ejemplo, para la cara superior, que estaría en z=100 (hacia arriba), si yo pongo una luz en 0,0,200, la cara está totalmente iluminada. Si la luz está en 100,0,200, la iluminaría parcialmente, pues no viene de frente.
Y así para cada cara. El objetivo es, para cada cara, teniendo en cuenta todas las luces del escenario (cada una es un objeto que puedes ubicar en el espacio), darle a ESA cara un número entre 0 (totalmente oscura) y 255 (totalmente iluminada). Poder decir la cantidad de luz que recibe esa cara teniendo en cuenta todos los focos de luz, ya que después necesitaré filtrar aquellas que estén bastante oscuras (por ejemplo por debajo de 30) para usarlas en el gameplay (digamos que el prota tiene un poder especial si está mirando a una pared o techo "poco iluminado", es decir, por debajo de 30)
He probado a hacerlo manualmente, pero me he hecho un lío. El tema es que quizás hay una forma más sencilla y rápida de encontrarlo. Quizás relacionado con las matrices de transformación o iluminación, las normales de los vértices... algo. Al fin y al cabo Game Maker coge, para cada vértice, su normal, y la ilumina acorde al ángulo que forma con TODOS los focos de luz. Quizás puedo aprovechar lo que hace y coger ese número y ya. Alguna idea?
Hola,
La iluminación para un vertice se calcula haciendo el producto punto entre los vectores de la normal y la dirección de la luz (muy simple de hecho), pero por lo general esto se hace en los shaders directamente para poder dibujar con iluminación los vertices. Si quieres hacer uso de esos valores tendrías que calcularlo manualmente:
El producto punto es el coseno del angulo formado entre los dos vectores, supongamos que tienes dos vectores A(0.70, 0.70) y B(1.0, 0.0) entonces el producto punto es (Ax*Bx+Ay*By) y el resultado es 0.70 que es también el coseno de 45°. con GMS existe la función "dot_product_3d(x1,y1,z1,x2,y2,z2)" para hacer este calculo...
Ahora bien supongamos que vamos a calcular la cantidad de luz que recibe la cara superior que tiene la normal (x:0,y:0,z:1) (suponiendo que el arriba es el eje z) y que estas usando una luz direccional cuya dirección es: (x:0,y:0,z:-1) entonces lo primero que debemos hacer (o deberiamos hacer) es invertir la dirección de la luz para el calculo de este modo nuestros 2 vectores (que por cierto deben estar normalizados) quedan:
normal: (0,0,1)
luz: (0,0,1)
el producto punto es: 0*0 + 0*0 + 1*1 = 1; 1 significa que la superficie esta totalmente iluminada, menor o igual de 0 significa que no recibe luz y cualquier valor entre 0 y 1 es parcialmente iluminada.
si la dirección de la luz fuera (-1,-1,-1) o (-0.57, -0.57, -0.57) normalizada entonces el resultado sería
normal: (0,0,1)
luz: (0.57,0.57,0.57) //invertida
y el producto punto es: 0*0.57 + 0*0.57 + 1 * 0.57 = 0.57 osea que la superficie esta parcialmente iluminada.
Ahora esto puedes repetirlo para todas las luces que tengas y sumar sus resultados para obtener la cantidad de luz final.
Si quieres hacerlo para luces en un punto (es decir que la cantidad de luz varia en la superficie) el procedimiento es el mismo solo que la dirección se calcula restando la posición de la luz de la posición del pixel que estas evaluando.
Cabe mencionar que hacer esto fuera de los shaders puede ser un poco overkill así que manejalo con prudencia :)
Saludos
EDIT: cambié el 0.69 por 0.57 (mal calculo :-[ )
Gracias! Después de mucho trastear funciona, ha costado xD Genial la explicación y los detalles, doy el tema por resuelto