Contamos con la respuesta a esta incógnita, al menos eso pensamos. Si sigues con alguna duda déjanoslo saber en un comentario y con placer te ayudaremos
Solución:
Una normal en general es un vector unitario cuya dirección es perpendicular a una superficie en un punto específico. Por lo tanto, le dice en qué dirección se enfrenta una superficie. El caso de uso principal para las normales son los cálculos de iluminación, donde debe determinar el ángulo (o prácticamente a menudo su coseno) entre la normal en un punto de superficie dado y la dirección hacia una fuente de luz o una cámara.
glNormal
ejemplo mínimo
glNormal
es un método OpenGL 2 obsoleto, pero es fácil de entender, así que analicémoslo. La alternativa de sombreado moderno se analiza a continuación.
Este ejemplo ilustra algunos detalles de cómo glNormal
trabaja con relámpago difuso.
Los comentarios del display
función explica lo que significa cada triángulo.
#include
#include
#include
#include
/* Triangle on the x-y plane. */
static void draw_triangle()
glBegin(GL_TRIANGLES);
glVertex3f( 0.0f, 1.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 0.0f);
glVertex3f( 1.0f, -1.0f, 0.0f);
glEnd();
/* A triangle tilted 45 degrees manually. */
static void draw_triangle_45()
glBegin(GL_TRIANGLES);
glVertex3f( 0.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, 0.0f);
glVertex3f( 1.0f, -1.0f, 0.0f);
glEnd();
static void display(void)
glColor3f(1.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix();
/*
Triangle perpendicular to the light.
0,0,1 also happens to be the default normal if we hadn't specified one.
*/
glNormal3f(0.0f, 0.0f, 1.0f);
draw_triangle();
/*
This triangle is as bright as the previous one.
This is not photorealistic, where it should be less bright.
*/
glTranslatef(2.0f, 0.0f, 0.0f);
draw_triangle_45();
/*
Same as previous triangle, but with the normal set
to the photorealistic value of 45, making it less bright.
Note that the norm of this normal vector is not 1,
but we are fine since we are using `glEnable(GL_NORMALIZE)`.
*/
glTranslatef(2.0f, 0.0f, 0.0f);
glNormal3f(0.0f, 1.0f, 1.0f);
draw_triangle_45();
/*
This triangle is rotated 45 degrees with a glRotate.
It should be as bright as the previous one,
even though we set the normal to 0,0,1.
So glRotate also affects the normal!
*/
glTranslatef(2.0f, 0.0f, 0.0f);
glNormal3f(0.0, 0.0, 1.0);
glRotatef(45.0, -1.0, 0.0, 0.0);
draw_triangle();
glPopMatrix();
glFlush();
static void init(void)
GLfloat light0_diffuse[] = 1.0, 1.0, 1.0, 1.0;
/* Plane wave coming from +z infinity. */
GLfloat light0_position[] = 0.0, 0.0, 1.0, 0.0;
glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_SMOOTH);
glLightfv(GL_LIGHT0, GL_POSITION, light0_position);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glColorMaterial(GL_FRONT, GL_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_NORMALIZE);
static void reshape(int w, int h)
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1.0, 7.0, -1.0, 1.0, -1.5, 1.5);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
int main(int argc, char** argv)
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE
Teoría
En OpenGL 2, cada vértice tiene su propio vector normal asociado.
El vector normal determina qué tan brillante es el vértice, que luego se usa para determinar qué tan brillante es el triángulo.
OpenGL 2 utilizó el modelo de reflexión Phong, en el que la luz se divide en tres componentes: ambiental, difusa y especular. De ellos, los componentes difusos y especulares se ven afectados por lo normal:
- si la luz difusa es perpendicular a la superficie, hace que sea más brillante, sin importar dónde esté el observador
- Si la luz especular golpea la superficie y rebota directamente en el ojo del observador, ese punto se vuelve más brillante.
glNormal
establece el vector normal actual, que se utiliza para todos los vértices siguientes.
El valor inicial de lo normal antes de que todos glNormal
es 0,0,1
.
Vectores normales debe tiene la norma 1, o de lo contrario los colores cambian! glScale
¡también altera la longitud de las normales! glEnable(GL_NORMALIZE);
hace que OpenGL establezca automáticamente su norma en 1 para nosotros. Este GIF lo ilustra maravillosamente.
Por qué es útil tener normales por vértices en lugar de por caras
Ambas esferas siguientes tienen el mismo número de polígonos. El que tiene normales en los vértices se ve mucho más suave.
Sombreadores de fragmentos OpenGL 4
En las API de OpenGL más nuevas, pasa los datos de dirección normal a la GPU como un fragmento arbitrario de datos: la GPU no sabe que representa las normales.
Luego, escribe un sombreador de fragmentos escrito a mano, que es un programa arbitrario que se ejecuta en la GPU, que lee los datos normales que le pasa e implementa cualquier algoritmo de relámpago que desee. Puede implementar Phong de manera eficiente si lo desea, calculando manualmente algunos productos punto.
Esto le brinda total flexibilidad para cambiar el diseño del algoritmo, que es una de las principales características de las GPU modernas. Ver: https://stackoverflow.com/a/36211337/895245
Se pueden encontrar ejemplos de esto en cualquiera de los tutoriales “modernos” de OpenGL 4, por ejemplo, https://github.com/opengl-tutorials/ogl/blob/a9fe43fedef827240ce17c1c0f07e83e2680909a/tutorial08_basic_shading/StandardShading.fragmentshader#L42
Bibliografía
- https://gamedev.stackexchange.com/questions/50653/opengl-why-do-i-have-to-set-a-normal-with-glnormal
- https://www.opengl.org/sdk/docs/man2/xhtml/glNormal.xml
- http://www.tomdalling.com/blog/modern-opengl/06-diffuse-point-lighting/
- http://learnopengl.com/#!Advanced-Lighting/Normal-Mapping
Muchas cosas están ahora en desuso, incluidas las normales y los colores. Eso solo significa que debe implementarlos usted mismo. Con normales puedes sombrear tus objetos. Depende de usted hacer los cálculos, pero hay muchos tutoriales sobre, por ejemplo, el sombreado de Gouraud / Phong.
Editar: Hay dos tipos de normales: normales de cara y normales de vértice. Las normales de cara apuntan lejos del triángulo, las normales de vértice apuntan lejos del vértice. Con las normales de vértice puede lograr una mejor calidad, pero también hay muchos usos para las normales de cara, por ejemplo, se pueden usar en la detección de colisiones y los volúmenes de sombras.
Si te ha resultado provechoso este post, sería de mucha ayuda si lo compartes con más juniors de esta manera nos ayudas a extender este contenido.