Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Per pixel lighting problemotes

Iniciado por misscelan, 06 de Diciembre de 2007, 11:51:39 AM

« anterior - próximo »

misscelan

Este es l vertex shader


varying vec3 normal;
varying vec4 ecPosition;
varying vec4 lightpos;
uniform vec3 lpos;
uniform mat4 NORM;

void main()
{
  //calcular la normal del vertice
  normal = gl_NormalMatrix * gl_Normal;

  //posicion del vertices
  ecPosition = gl_ModelViewMatrix *  gl_Vertex;

  //coordenadas de la textura
  gl_TexCoord[0] = gl_MultiTexCoord0;
  gl_TexCoord[1] = gl_MultiTexCoord1;

  gl_Position = ftransform();
}



Este es el fragment

varying vec3 normal;
varying vec4 lightpos;
varying vec4 ecPosition;

uniform sampler2D texture0;
uniform sampler2D texture1;

void main()
{
vec3 N, L, R, V, H;
       N                = normalize(normal);
       //direccion
       //vec3  direccion  = vec3(lightpos - ecPosition);
       vec3  direccion  = vec3(gl_LightSource[0].position - ecPosition);
       float distancia  = length(direccion);
       L                = normalize(direccion);
V                = vec3(normalize(-ecPosition));

//calculo de la luz ambiente
vec4 vAmbient  = gl_LightSource[0].ambient * gl_FrontMaterial.ambient;

//calculo de la luz difusa Id = Dl * Dm * LambertTerm
       //LambertTerm  = max( N dot L, 0.0)
       float LamberTerm = max( dot(N, L), 0.0);
vec4 vDiffuse  = gl_LightSource[0].diffuse  * gl_FrontMaterial.diffuse * LamberTerm;
       
       //Calculo de la especular
       H = (L + V)/2.0; //calculo del HalfVector
       float specular = max( dot(N,H) , 0.0);
       vec4 vSpecular = gl_LightSource[0].specular * gl_FrontMaterial.specular * specular;

       
       //vec3 suma      = texture2D(texture0,  vec2(gl_TexCoord[0])).xyz * texture2D(texture1,  vec2(gl_TexCoord[1])).xyz;  
//vec4 finalight = normalize((vAmbient + vDiffuse + vSpecular) * vec4(suma, 1));
vec4 finalight = normalize((vAmbient + vDiffuse + vSpecular));
gl_FragColor   = finalight;

     
}


Esto es como pongo la luz

       static GLfloat position[4] = {0.0, 0.0, 0.0, 1.0};
       static GLfloat LightAmb[4] = {0.0, 0.0, 0.0, 1.0};
       static GLfloat LightDif[4] = {0.5, 0.5, 0.5, 1.0};
       static GLfloat LightSpc[4] = {0.5, 0.5, 0.5, 1.0};
       //glPushMatrix();
      // glTranslatef(0,0,0);
       glLightfv(GL_LIGHT0, GL_POSITION, position);
       glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmb);
       glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDif);
       glLightfv(GL_LIGHT0, GL_SPECULAR, LightSpc);
      // glPopMatrix();



Y este es el resultado (la caja azul es la luz):



Preguntas:

Por qué la luz divide el escenario en dos partes un sombreada y otra iluminada?

Por qué las caras que no están mirando a la luz tienen la misma iluminación que las que no?

Por qué si cambio la posicion de la luz de (0,0,0,1) a (0,0,0,0) la iluminación se mueve con la cámara?

Alguién puede contestarme alguna pregunta????

Muchas gracias y un saludo.

BeRSeRKeR

No sé muy bien cómo pasa OpenGL las cosas a los shaders, pero parece que la luz que tiene coordenadas (0,0,0), siempre estará situada en la cámara, ya que en view-space (que parece que es en lo que estás calculando la iluminación), la cámara siempre está en el origen (de hecho la cámara es el mismo origen).

Si eso es así, ahora mismo, tal como calculas las cosas, L y V siempre coincidirán.

Lo que tendrías que hacer es pasar la posición de la luz a view-space. Pero bueno, no sé si eso es lo que quieres. Ni siquiera sé si es que OpenGL ya pasa la posición de la luz a view-space automáticamente.

Saludos.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!

ethernet

Seún pone en la documentación cuando especificas GL_POSITION de la luz es multiplicada por la modelview, lo que no sé es si cuando no estás con fixed pipeline lo hará. Según he visto por ahí parece que sigue siendo así porque para calcular la dirección de la luz usan:


vec3 vVertex = vec3(gl_ModelViewMatrix * gl_Vertex);
lightDir = vec3(gl_LightSource[0].position.xyz - vVertex);


esto es, el vértice transformado a view space y la posición de la luz sin tranformar (lo cual sugiere que ya ha sido transformada)

Si yo estuviera en tu caso haría lo siguiente:

Empezaría por poner la posición (o dirección) de la luz en un uniform pasándoselo desde el código en world space. Con ese valor quitar todo lo que tienes en el pixel shader y hacer sólamente un:


vec4 c  = vec4(0.3) + 0.7*vec4(max(dot(lightDir*normal),0.0);
c.z = 1.0;
gl_FragColor = c;


(un poco de ambient y solo la componente difusa) y una vez tengas eso funcionando bien meterte con más cosas.

Mola el screenshot, ya puedes enseñar algo más :D

misscelan

Gracias por la ayuda, tenía un problema pasando las normales del escenario.

Me di cuenta al testear el código de la normal y la dirección que pusiste.

Las imágenes son del juego con el que me comí los mocos este año en el art futura (el ocaso de sara), estoy metido con muchas batallas a la vez y ahora está un poco impresentable, cuando esté más pulido ya enseñaré algo. Se agradece el interés!!.

Un saludo!!.

misscelan

Aquí estoy de nuevo, con nuevos problemas...

Todo funcionaba de maravilla con el escenario y me las prometía muy felices, entonces metí el renderizado de modelos dentro y la liamos.

Os cuento. Cuando quiero pintar un modelo hago esto:

PosicionoLaCamara
PintoElEscenario

glPushMatrix() //guardo la matriz
glTranslatef //a la posición donde se pinta el modelo
glRotatef //para ponerlo mirando o donde debe
PintoElModelo
glPopMatrix()//recupero la matriz.


Pues la iluminación para el escenario sigue bien, pero para el modelo no.

y me surgen dudas:
1) si la luz, cuando se fija su posición es multiplicada por la ModelView actual (en este caso la que tenía al pintar el escenario), sería correcto aplicar la misma posición al modelo?

2)Las normales calculas del modelo están siempre mirando al eje z(tal como lo hice en milkshape) después de aplicar translaciones y rotaciones
multiplicándolas por gl_NormalMatrix estaría todo arreglado?

Muchas gracias y un saludo.

ethernet

Cita de: "misscelan"Aquí estoy de nuevo, con nuevos problemas...

Todo funcionaba de maravilla con el escenario y me las prometía muy felices, entonces metí el renderizado de modelos dentro y la liamos.

Os cuento. Cuando quiero pintar un modelo hago esto:

PosicionoLaCamara
PintoElEscenario

glPushMatrix() //guardo la matriz
glTranslatef //a la posición donde se pinta el modelo
glRotatef //para ponerlo mirando o donde debe
PintoElModelo
glPopMatrix()//recupero la matriz.


Pues la iluminación para el escenario sigue bien, pero para el modelo no.

y me surgen dudas:
1) si la luz, cuando se fija su posición es multiplicada por la ModelView actual (en este caso la que tenía al pintar el escenario), sería correcto aplicar la misma posición al modelo?

2)Las normales calculas del modelo están siempre mirando al eje z(tal como lo hice en milkshape) después de aplicar translaciones y rotaciones
multiplicándolas por gl_NormalMatrix estaría todo arreglado?

Muchas gracias y un saludo.

1.- Tú debes saber cuando fijas la posición de la luz en función de la modelview que tengas, esto es, pones la matriz de cámara, después la luz, después los objetos... si te das cuenta al final todos los objetos (incluida la luz) serán multiplicados tanto por la matriz de objeto como por la de cámara, con lo cual todos tienen una base común y por lo tanto su posición relativa es la misma sea cual sea la posición de la cámara.

2.- No entiendo lo de las normales al eje Z... te refires a un terreno?

misscelan

Primero, muchas gracias por la ayuda.

Creo que me has aclarado la primera duda.

Te pongo un gráfico a ver si me xplico mejor con la segunda.


El cuadrado es el modelo cuando lo creo en el editor, la normal de esa cara cuando la almaceno en el archivo sería (0,0,1). En el lado derecho cuando cargo el modelo y le aplico las transformaciones, la normal que tengo almacenada seguiría mirando a (0,0,1) (azul) pero debería estar mirando a otro sitio (rojo).

Lo que quería saber es si yo debería recalcular esas normales o basta con multiplicarlas por gl_NormalMatrix???, porque entonces me quedo sin ideas de donde puede estar el error.

Gracias y un saludo.

Prompt

joer que lio macho... o llego a entender bien las situaciones de los problemas ( a ver si voy a dormir ya.... xD )

La normal de los cuadrados está chunga, eso está claro. Lo rojo que es?

Tu código no debería ser:

PosicionoLaCamara

miShader.begin();
glPushMatrix() //guardo la matriz
PintoElEscenario
glPopMatrix()//recupero la matriz.

glPushMatrix() //guardo la matriz
glTranslatef //a la posición donde se pinta el modelo
glRotatef //para ponerlo mirando o donde debe
PintoElModelo
glPopMatrix()//recupero la matriz.

miShader.end();


Si haces begin y end del shader solo para el terreno, normal q el modelo no se ilumine, esto se que es obvio... pero no he creido entender que lo hicieras.

Respecto al Shader, no me queda claro si lo calculas todo en coordenadas de munto, locales en espacio de vista, en proyección o en ventana.

Cuando haces esto:
vec3  direccion  = vec3(gl_LightSource[0].position - ecPosition);

La luz está en coordenadas de mundo, ya que lo asignas por fixed pipelines y ecPosition, es la camara en coordenadas de VISTA, view space o eye space ( como te guste mas :). A mi me parece que hay incoherencias por ahí aunque no he mirado detalladamente el shader.

Yo opino, que borres el shader y lo hagas otra vez, poco a poco, consensuando cosas.

( voya dormir, no se si te he ayudado, pero ahí queda! :D )

Mirate esto: http://colectivoguma.com/recursos.php?rec=18

misscelan

Buenas,

No tienes sueño!! s qre trenjo plmemas des esprexiom....

El modelo se ilumina pero por donde no debe, como si la luz le llegase de otro sitio o como si las normales estuviesen apuntando mal.

Lo primero dices que guarde la matriz antes de pintar el escenario, no lo he explicado bien (mea culpa) pero es que el escenario lo pinto sin realizar ninguna transformación, luego supongo que daría igual hacer eso.

Lo del tema de la luz, yo tenía la misma duda, pero creo haber leído  y ethernet pensó lo mismo, que en el momento en que fijas la posición de la luz ésta se multiplica por la modelview que exista en el momento. Luego la luz ya debería estar transformada, en caso contrario no funcionaría para el escenario.

Repecto a las normales, el color rojo es la normal que debería ser y el azul la normal sin recalcular. Pero tengo la duda de si se recalcula o no, porque las normales salen guardadas tal como orientas el modelo en el programa donde lo creas (que sería el lado izquierdo del dibujo). Si yo roto el modelo debería rotar las normales (dibujo del lado derecho). Pero por lo que he leído gl_NormalMatrix se encargaría de hacer eso por mí,

Así que me he quedado sin ideas y todas las noches le rezo a Carmack a ver si me susurra algo.

De cualquier manera, muchas gracias!!!

Un saludo.

Prompt

Cita de: "misscelan"Lo primero dices que guarde la matriz antes de pintar el escenario, no lo he explicado bien (mea culpa) pero es que el escenario lo pinto sin realizar ninguna transformación, luego supongo que daría igual hacer eso.

Solo lo he codeado así, yo lo haría con todo lo que pinto... porque quizas en un momento determinado al generar el terreno tomas como punto inicial el 0,0 pero luego te da por poner el 0,0 en el centro del mapa...

Simplemente por coherencia de que todo objeto en el escenario tenga su propia matriz. Yo en mi caso tengo un Resource Manager y tengo, instancias y mapas. Tengo un mapa base... pero y si quiero crearme uno generado en 0,0 pero ponerlo debajo de tierra? Como no lo sé y es coherente que todo objeto pueda moverse y rotarse, lo pongo. Pero en tu caso específico no hace falta.

Cita de: "misscelan"El modelo se ilumina pero por donde no debe, como si la luz le llegase de otro sitio o como si las normales estuviesen apuntando mal.
Porque no calculas bien la dirección de la camara con la dirección de la luz, incidiendo en la posición del vertice ( o fragmento ) del objeto :) posiblemente el problema esté en que no has codeado el shader coherentemente teniendo en cuenta que todos los calculos estén en coordenadas de mundo, vista, screen, objeto o persectiva. Sea como sea todo tiene que tener coherencia, porque si tienes q la posición del vertice es en coordenadas de objeto y todo lo demás en mundo ( como estás haciendo creo, y yo por ejemplo hago ) en cuanto muevas del 0,0,0 la matriz del objeto ya no cuadra nada!

Para probar si es esto, coloca los objetos en la posición 0,0,0 :)

Cita de: "misscelan"
Lo del tema de la luz, yo tenía la misma duda, pero creo haber leído y ethernet pensó lo mismo, que en el momento en que fijas la posición de la luz ésta se multiplica por la modelview que exista en el momento. Luego la luz ya debería estar transformada, en caso contrario no funcionaría para el escenario.

La posición de la luz está en coordenadas de mundo, asignadas directamente desde fixed pipelines. Con lo cual si tu sistema de referencia en el shader es con coordenadas de mundo, no tendras que transformar nada. No es por ninguna otra razón.

Cita de: "misscelan"
Repecto a las normales, el color rojo es la normal que debería ser y el azul la normal sin recalcular. Pero tengo la duda de si se recalcula o no, porque las normales salen guardadas tal como orientas el modelo en el programa donde lo creas (que sería el lado izquierdo del dibujo). Si yo roto el modelo debería rotar las normales (dibujo del lado derecho). Pero por lo que he leído gl_NormalMatrix se encargaría de hacer eso por mí,

Así que me he quedado sin ideas y todas las noches le rezo a Carmack a ver si me susurra algo.

No le reces, que es un bruto! ( referencia graciosa a sus implementaciones acertadas a fuerza bruta, vease guardar en cada nodo del BSP lo que se ve, de forma pregenerada para no calcular nada en tiempo real. Vease de nuevo que esto lo hace con todo lo que puede, como es lógico )

Veamos! para un modelo de iluminación avanzado no necesitaras hacer eso con la normal sino posicionarla en mundo ( por ejemplo, como todo lo demás ) y normalizarla para luego obtener el vertor de dirección de la luz multiplicando por TBN ( Tangente Binormal Normal ).

Te he remitido a un tutorial que explica los conceptos básicos pero, creo que te deberias plantear si realmente quieres ese modelo de iluminación. ¿Por qué quieres iluminación por pixel? es costoso. Depende de lo que quieras obtener.

Lo normal es tener diferentes tipos de iluminación para tener un buen set de configuración para que tu juego vaya bien en diferentes maquinas, y con esto me refiero a:
* Todo va con Gloss Map ( en alpha no refleja la componente de luz especular )
- Iluminación por Vertice.
- Iluminación por pixel.
- Iluminación por pixel + bump mapping ( normal map )
- Iluminación por pixel + parallax mapping ( normal map + height map )

Es que del tirón te veo metiendo iluminación por pixel con calzador. Deberias ver primeros otros modelos de iluminación mas sencillos e ir progresando, ya que el de vertice y pixel son iguales solo que te llevas al calculo al fragment shader.

Intenta comprender todo lo que pongas en el shader, porque si el día de mañana quieres currar haciendo shaders vas a estar perdido :P. A no ser que eso te de igual. Y quieras ser programador de Game Play.

Saludetes!

misscelan

Ya está!!! tres padre Carmack han bastado.

Resulta que milkshape almacena las x y z de las normales al revés de como yo lo almacenaba.

Gracias y un saludete!!.






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.