OpenGL中的常态是什么?

mk.*_*mk. 16 opengl colors light normals

我听说我应该使用法线而不是颜色,因为颜色已被弃用.(这是真的吗?)法线与光的反射有关,但我找不到清晰直观的解释.什么是正常的?

Thi*_*cke 21

正常一般是一个单位矢量,其方向垂直于表面,在一个特定的点.因此,它会告诉您表面朝向哪个方向.法线的主要用例是光照计算,您必须确定给定曲面点处的法线与朝向光源或摄像机的方向之间的角度(或实际上通常是其余弦).

  • 即使表面处于明显的位置,您仍需要提供该信息以便能够进行照明计算,而法线只是标准的方法.对于三角形网格的简单平面着色,您可以轻松地计算三角形顶点的法线. (3认同)
  • 感谢您的链接。如果表面所面向的方向应该很明显,为什么还需要法线呢?表面通常不是垂直的,还是这只是 OpenGL 不想处理的计算? (2认同)
  • 实际上,没有要求法向量是单位长度。这是一个很方便的属性,但根据最严格的定义,向量是法线,只要它在一点上垂直于表面的切线。当法线是单位长度时,它是一种特殊形式,称为“单位法线”。 (2认同)

Cir*_*四事件 7

glNormal 最小的例子

glNormal是不推荐使用的 OpenGL 2 方法,但它很容易理解,所以让我们研究一下。下面讨论现代着色器替代方案。

这个例子说明了如何glNormal使用漫射闪电的一些细节。

display函数的注释解释了每个三角形的含义。

4个红色三角形

#include <stdlib.h>

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>

/* 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 | GLUT_RGB);
    glutInitWindowSize(800, 200);
    glutInitWindowPosition(100, 100);
    glutCreateWindow(argv[0]);
    init();
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutMainLoop();
    return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)

理论

在 OpenGL 2 中,每个顶点都有自己关联的法线向量。

法线向量确定顶点的亮度,然后用于确定三角形的亮度。

OpenGL 2 使用Phong 反射模型,其中光被分成三个分量:环境光、漫反射和镜面反射。其中,漫反射和镜面反射分量受法线影响:

  • 如果漫射光垂直于表面,无论观察者在哪里,它都会变得更亮
  • 如果镜面反射光照射到表面,然后直接反射到观察者的眼睛中,那么该点会变得更亮

glNormal 设置当前法向量,用于所有后续顶点。

我们之前的法线的初始值glNormal0,0,1

法向量必须有范数 1,否则颜色会改变!glScale也会改变法线的长度!glEnable(GL_NORMALIZE);使 OpenGL 自动为我们将其范数设置为 1。这个 GIF精美地说明了这一点。

为什么每个顶点都有法线而不是每个面都有用

下面的两个球体具有相同数量的多边形。顶点法线看起来更平滑。

在此处输入图片说明

OpenGL 4 片段着色器

在较新的 OpenGL API 中,您将法线方向数据作为任意数据块传递给 GPU:GPU 不知道它代表法线。

然后你编写一个手写的片段着色器,它是一个在 GPU 中运行的任意程序,它读取你传递给它的普通数据,并实现你想要的任何闪电算法。如果您愿意,您可以通过手动计算一些点积来有效地实现 Phong。

这使您可以完全灵活地更改算法设计,这是现代 GPU 的主要功能。参见:https : //stackoverflow.com/a/36211337/895245

这方面的示例可以在任何“现代”OpenGL 4 教程中找到,例如https://github.com/opengl-tutorials/ogl/blob/a9fe43fedef827240ce17c1c0f07e83e2680909a/tutorial08_basic_shading/StandardShading#L4shading。

参考书目