OpenGL中的常态是什么?

问题描述 投票:15回答:3

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

opengl colors light normals
3个回答
21
投票

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


4
投票

glNormal最小的例子

glNormal是一个弃用的OpenGL 2方法,但它很容易理解,所以让我们来看看它。下面讨论现代着色器替代方案。

这个例子说明了glNormal如何与漫射闪电一起工作的一些细节。

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

4 red triangles

#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;
}

理论

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

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

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

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

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

在我们所有glNormal之前的正常的初始值是glNormal

法向量必须具有范数1,否则颜色会发生变化! 0,0,1也改变了法线的长度! glScale让OpenGL自动将他们的标准设置为1。 glEnable(GL_NORMALIZE);说明了这一点。

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

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

This GIF

OpenGL 4片段着色器

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

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

这使您可以完全灵活地更改算法设计,这是现代GPU的主要功能。见:enter image description here

这种情况的例子可以在任何“现代”OpenGL 4教程中找到,例如https://stackoverflow.com/a/36211337/895245

参考书目


3
投票

现在很多东西都被弃用了,包括法线和颜色。这只意味着你必须自己实现它们。使用法线可以遮挡物体。这取决于你进行计算,但是有许多教程可以用来进行计算。 Gouraud / Phong阴影。

编辑:有两种类型的法线:面法线和顶点法线。面法线指向远离三角形的点,顶点法线指向远离顶点的点。使用顶点法线可以获得更好的质量,但是对于面法线也有很多用途,例如:它们可用于碰撞检测和阴影卷。

© www.soinside.com 2019 - 2024. All rights reserved.