Ir al contenido

publicidad

Foto

Ejemplo de iluminacion con linternas -y otros equivalentes-


Este tema ha sido archivado. Esto significa que no puedes responder en este tema.
No hay respuestas en este tema

#1

Escrito 18 junio 2009 - 12:38

Buenos dias.

Hace poco hice una pequeña test room del juego que voy a hacer proximamente en el que probaba como funcionaba la linterna que tendria el protagonista para ver en la oscuridad.

Asi que os pongo el resultado. No es un juego en si, aqui quiero explicaros como lo he hecho, que veais el resultado y si os sirve que lo podais adaptar a vuestros programas.


Link de descarga: http://www.megaupload.com/?d=U8WGUWWF
Nombre del archivo: Aplication.zip
Tamaño: 1,66 MB
Contenido: Fichero autoejecutable. No necesita instalacion.

Controles del programa: Flechas direccionales para mover la camara. Shift para encender/apagar la luz.

Imagen Enviada

Si, ya lo se, es muy sencillo: 5 bolas flotando por ahi y una luz fijada a la camara pero para ajustar los valores de la linterna y ver como se ven los objetos con ella tengo de sobra. Hacer algo asi no lleva ni 5 minutos.

El lenguaje en el que esta escrito esto es DarkBasic Pro.

El codigo explicado:

Primero configuramos la escena.

[code:1]color backdrop rgb(0,0,0)[/code]
Con este comando ponemos el color de fondo de la pantalla el negro.

[code:1]
make object sphere 1,1
position object 1,0,0,3

make object cube 2,1
hide object 2

make object sphere 3,1
position object 3, 5,0,5

make object sphere 4,1
position object 4, -2,0,-3

make object sphere 5,1
position object 5, 1,1,0
[/code]

Aqui creamos todos los objetos 3d que vamos a usar: Las 5 esferas que vemos y un cubo que nos ayudará a calcular donde apunta la linterna.

Los parametros de Make object son: Nº de identificacion del objeto 3d a crear, tamaño de este objeto -el diametro de la esfera y el ancho/lado/alto del cubo, que es el mismo numero. En otros como la caja esto cambia y te permite poner distintos valores de tamaño-

Position object coloca el objeto en las coordenadas dadas: nº del objeto a colocar, coordenadas x donde se pone, coordenadas y, coordenadas z.

Hide object hace que el objeto indicado no se renderize por lo que aparece invisible, pero sigue estando disponible para moverlo y si lo quieres para que colisione.

Luego ponemos la camara:

[code:1]position camera 0,0,-1
point camera 0,0,3[/code]

Por defecto DarkBasic siempre crea una camara que, a no ser que lo controles con el comando "autocam off", siempre se coloca en frente del ultimo objeto creado. Por eso al principio la colocamos en las coordenadas 0,0,1

Y para asegurarnos de que apunte a donde queremos hacemos que apunte a las coordenadas 0,0,3 -donde se encuentra la esfera 1-

Podemos hallar esas coordenadas con otros comandos pero sabiendolas al principio y estando pregenerado no veo necesario escribir mas y dar mas carga al ordenador -aunque hoy en dia no importa mucho eso-

Al haber solo la camara predeterminada no hace falta indicar el indice de la camara a modificar. Si hubiera creado mas camaras tendria que indicarlo. El indice de la camara predeterminada es 0.

Controlamos la luminosidad:

[code:1]set ambient light 0
hide light 0

make light 1
set spot light 1,20,70

set light range 1, 20[/code]

Al principio hay dos fuentes de luz predeterminadas: La luz ambiental y una luz omnidireccional.

Con set ambient light 0 apagamos la luz ambiental, que no se puede borrar.
Con hide light 0 apagamos la luz omnidireccional inicial.

Podriamos modificar la luz 0 para que fuese la linterna pero decidí crear otra luz con otro indice, pues el codigo de aqui lo reutilizaré mas adelante en otro proyecto y ahi quizas si use la luz 0 como fuente de luz.

Asi que creamos la luz 1 con make light 1
De entre todos los tipos de luz que nos ofrece el motor de DarkBasic, el spot light es la mas indicada para lo que queremos hacer.

Primero indicamos la luz que queremos convertir en "spot". los siguientes valores son el angulo interno y el angulo externo. Desde el origen de la luz hasta que se abra el angulo interno la luz no pierde intensidad. Desde el angulo interno al angulo externo va haciendo un degradado perdiendo intensidad. Cuando se ha abierto mas del angulo externo no da luz.

Para que os hagais a la idea:

Imagen Enviada
La linea central es el angulo 0.

Las lineas rosas que delimitan la zona blanca con la gris es el angulo interno

Las lineas rosas que delimitan el gris y el negro es el angulo externo.

La zona blanca es donde la luz no pierde intensidad.

En la zona gris va perdiendo intensidad

En la zona negra no hay luz.

Una vez hecho eso, la luz pierde intensidad al abrise, pero tiene la misma intensidad tanto cerca como lejos, y como sabemos que una linterna apuntando lejos no tiene fuerza y no ilumina apenas, ponemos niebla para apoyar ese efecto.

Asi que el comando set light range "1, 20" hace que la luz 1 solo llegue hasta 20 coordenadas hacia el frente perdiendo intensidad paulatinamente.


Con todo eso tenemos el escenario preparado. Pasamos a hacer la logica del juego:

[code:1]do
if leftkey() then yrotate camera (camera angle y()-0.1)
if rightkey() then yrotate camera (camera angle y()+0.1)
if upkey() then move camera 0.01
if downkey() then move camera -0.01

if shiftkey()
if light visible (1) = 1
hide light 1
else
show light 1
endif
wait 250
endif

position object 2, camera position x() ,camera position y() ,camera position z()
rotate object 2, camera angle x(), camera angle y(), camera angle z()
move object 2,5
position light 1, camera position x() ,camera position y() ,camera position z()
point light 1,object position x(2), object position y(2), object position z(2)
loop[/code]

Lo primero que hacemos en la parte de aqui es coger los controles:
[code:1]if leftkey() then yrotate camera (camera angle y()-0.1)
if rightkey() then yrotate camera (camera angle y()+0.1)
if upkey() then move camera 0.01
if downkey() then move camera -0.01 [/code]

Leftkey(), rightkey(), etc... indican si la tecla indicada esta pulsada. Darkbasic cuenta con algunas teclas predefinidas como las flechas direccionales, mayus, control, alt, intro, espacio... que nos ahorran el tener que buscar el indice que controla esa tecla y todo eso. Por eso lo hago asi, si los controles fuesen configurables usaria mejor los indices.

Asi que si se pulsa la tecla izquierda o derecha, la camara gira sobre su eje y.

El comando yrotate camera gira la camara. SOlo tiene un parametro: El angulo al que se gira.
El angulo que gira lo hacemos cogiendo el angulo actual de la camara -Comando "Camera angle y( identificador de la camara )- y le sumamos el angulo que queremos añadir: 0.1

Eso hace que en un momento del bucle si el angulo es 0, en el siguiente sea 0+ 0.1, en el siguiente 0.1 + 0.1, el sigueinte 0.2 + 0.1... y eso da el efecto de que se gira sobre si mismo.

Las flechas arriba y abajo mueven la camara hacia donde esta mirando con el comando "Move camera". Los parametros son el indice -si no hay mas camaras no hace falta, por eso no aparece en este ejemplo- y la cantidad que quieres que se desplace. El programa te calcula automaticamente el vector y te ahorra todo.

Controlamos el encendido/apagado de la linterna:
[code:1]if shiftkey()
if light visible (1) = 1
hide light 1
else
show light 1
endif
wait 250
endif[/code]

Si se pulsa mayusculas(shift) comprueba si la luz esta encendida -es visible- o no -esta escondida-.

Si es visible la esconde, si no es visible la muestra.

Hecho esto hace algo que no debeis hacer fuera de las testroom: Interrumpir el programa. El comando wait detiene todo unos instantes. Aqui lo hago para que al pulsar mayus te encienda y apague constantemente la linterna de forma muy rapida en poco tiempo sin ser precisa. Por eso se le da algo de retardo antes de que vuelva a poderse encender o apagar.

Hay otras formas de hacer lo mismo que no interrumpen el programa, pero siendo una testroom y tener este comando tan sencillo no pude resistirme ^^.

Para finalizar, recolocamos las cosas:

[code:1]position object 2, camera position x() ,camera position y() ,camera position z()
rotate object 2, camera angle x(), camera angle y(), camera angle z()
move object 2,5
position light 1, camera position x() ,camera position y() ,camera position z()
point light 1,object position x(2), object position y(2), object position z(2)[/code]

Colocamos el cubo ayudante que hicimos invisible al principio en la posicion donde actualmente se encuentra la camara despues de que esta se haya movido/rotado.

Con position object 2 colocamos el cubo. Camera position x nos da las coordenadas x de la camara, y asi el resto de estos comandos. Con eso decimos que coloque el cubo en las coordenadas de la camara.
Con rotate object giramos (rotamos) el cubo para que mire en la posicion de la camara. Cogemos los angulos de esta y se los aplicamos al cubo.

Con move object, el cubo se mueve hacia donde esta mirando -que mira al mismo sitio que la camara- 5 coordenadas, el comando nos calcula automaticamente el vector y lo coloca ahi.

Luego colocamos la luz en la camara. Terminamos haciendo que la luz apunte hacia el cubo que se encuentra ahora 5 coordenadas por enfrente de la camara. El comando point light hace que la luz apunte a un punto en concreto, le pasamos las coordenadas del cubo -que tiene el indice 2-.

Si no usasemos el "cubo ayudante" tendriamos que lidiar con varios calculos de vectores, trigonometria, etc...

En los juegos antiguos el cubo ayudante era algo prohibido por hacer al juego calcular mas. En la epoca actual da bastante mas igual y el trabajo que nos ahorra merece el poco pc que nos consumen estos comandos.


Eso ha sido todo. Recordad que aunque este escrito en DarkBasic lo podeis adaptar a vuestros programas "traduciendo" el codigo y ademas teneis aqui cual es el planteamiento de todo esto por si no hallais el comando equivalente o no exista en vuestro lenguaje.

Recordad que si usais C++ el motor DarkGDK es gratuito y añade los comandos del DarkBasic al c++ ayudando a que tengais esto en vuestro lenguaje.

Espero que a los novatos os sirva de algo y a los que buscais incorporar esta tecnologia -ya bastante antigua- en vuestros juegos tambien.





Am, si , y se me olvidaba comentar una cosilla. Esto es solo el efecto de iluminacion de la linterna. Para que parezca mas realista aparte deberiais crear un cono que tenga la punta en el origen de la luz y se abra hacia donde apunte esta, hacerlo semitransparente y pintarlo de amarillo. O haceros una textura con canal alpha que sea totalmente amarilla o del color de la luz al principio del cono y que segun se vaya abriendo vaya haciendose mas invisible.

Con eso, si ajustais el tamaño del cono a los angulos de la luz os queda un efecto muy bueno.

Si la linterna es para usarla en primera persona no hace falta mucho hacer este efecto, pero es recomendable.

Aun asi, en 3º persona el cono es casi imprescindible si quieres algo decente.

Ejemplo:
Imagen Enviada

Aqui vemos la escena con la luz de foco que tenemos, un objeto en 3d haciendo de linterna, un objeto 3d haciendo de cono de luz -Si lo analizais veis que es una textura blanca en el origen y que va añadiendo alpha (transparencia) al abrirse.

La sombra sobre la pared se hace con un shader. El darkbasic por si solo crea una sombra muy simple y te viene con este shader si quieres dar iluminacion mas realista.

El modelo 3d del zombi tiene como textura mapa de colores, mapa de normales y mapa difuso que indica que partes reflejan mas y que partes reflejan menos luz.

En Darkbasic tienes de serie el de colores y el de normales. El difuso va por shaders.


Un saludo.
Visita mi blog:
http://blogs.gamefilia.com/ellolo17


Este tema ha sido archivado. Esto significa que no puedes responder en este tema.
publicidad