OpenGL since 1.0 -- lighting and surface rendering functions

Perform perspective projection on the objects of the scene, and then generate natural lighting effects on the visible surface, which can realize the realistic display of the scene. It is useless to say more, looking at an example is the most direct method (the example code comes from http://blog.csdn.net/timidsmile/article/details/7017197 ).
write picture description here

#include <gl/glut.h>  
#define WIDTH 400  
#define HEIGHT 400  
static GLfloat angle = 0.0f;
void myDisplay(void)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity();  
    gluPerspective(90.0f, 1.0f, 1.0f, 20.0f);
    glMatrixMode(GL_MODELVIEW);  
    glLoadIdentity();
    gluLookAt(0.0, 5.0, -10.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); 
    // 定义太阳光源,它是一种白色的光源  
    {
        GLfloat sun_light_position[] = { 0.0f, 0.0f, 0.0f, 1.0f };
        GLfloat sun_light_ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f };
        GLfloat sun_light_diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
        GLfloat sun_light_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
        glLightfv(GL_LIGHT0, GL_POSITION, sun_light_position); //指定第0号光源的位置   
        glLightfv(GL_LIGHT0, GL_AMBIENT, sun_light_ambient); //GL_AMBIENT表示各种光线照射到该材质上,经过很多次反射后最终遗留在环境中的光线强度(颜色)  
        glLightfv(GL_LIGHT0, GL_DIFFUSE, sun_light_diffuse); //漫反射后~~  
        glLightfv(GL_LIGHT0, GL_SPECULAR, sun_light_specular);//镜面反射后~~~  
        glEnable(GL_LIGHT0); //使用第0号光照  
        glEnable(GL_LIGHTING); //在后面的渲染中使用光照  
        glEnable(GL_DEPTH_TEST); //这句是启用深度测试,这样,在后面的物体会被挡着,例如房子后面有棵树,如果不启用深度测试,你先画了房子再画树,树会覆盖房子的;但启用深度测试后无论你怎么画,树一定在房子后面(被房子挡着)   
    }
    // 定义太阳的材质并绘制太阳  
    {
        GLfloat sun_mat_ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f };
        GLfloat sun_mat_diffuse[] = { 0.0f, 0.0f, 0.0f, 1.0f };
        GLfloat sun_mat_specular[] = { 0.0f, 0.0f, 0.0f, 1.0f };
        GLfloat sun_mat_emission[] = { 0.5f, 0.0f, 0.0f, 1.0f };
        GLfloat sun_mat_shininess = 0.0f;
        glMaterialfv(GL_FRONT, GL_AMBIENT, sun_mat_ambient); //定义材料的前面采用 "多次反射"  
        glMaterialfv(GL_FRONT, GL_DIFFUSE, sun_mat_diffuse); //材料的前面为 漫反射  
        glMaterialfv(GL_FRONT, GL_SPECULAR, sun_mat_specular); //定义材料的前面为 镜面反射  
        glMaterialfv(GL_FRONT, GL_EMISSION, sun_mat_emission); //定义材料的前面为 镜面指数  
        glMaterialf(GL_FRONT, GL_SHININESS, sun_mat_shininess); //材料的前面 采用 的颜色  
        glutSolidSphere(2.0, 40, 32);
    }
    // 定义地球的材质并绘制地球  
    {
        GLfloat earth_mat_ambient[] = { 0.0f, 0.0f, 0.5f, 1.0f };
        GLfloat earth_mat_diffuse[] = { 0.0f, 0.0f, 0.5f, 1.0f };
        GLfloat earth_mat_specular[] = { 0.0f, 0.0f, 1.0f, 1.0f };
        GLfloat earth_mat_emission[] = { 0.0f, 0.0f, 0.0f, 1.0f };
        GLfloat earth_mat_shininess = 30.0f;
        glMaterialfv(GL_FRONT, GL_AMBIENT, earth_mat_ambient);
        glMaterialfv(GL_FRONT, GL_DIFFUSE, earth_mat_diffuse);
        glMaterialfv(GL_FRONT, GL_SPECULAR, earth_mat_specular);
        glMaterialfv(GL_FRONT, GL_EMISSION, earth_mat_emission);
        glMaterialf(GL_FRONT, GL_SHININESS, earth_mat_shininess);
        glRotatef(angle, 0.0f, -1.0f, 0.0f);
        glTranslatef(5.0f, 0.0f, 0.0f);
        //如果使用glutSolidSphere函数来绘制球体,则该函数会自动的指定这些法线向量,  
        //不必再手工指出。如果是自己指定若干的顶点来绘制一个球体,则需要自己指定法线向量。  
        glutSolidSphere(2.0, 40, 32);
    }
    glutSwapBuffers(); //交换缓冲区  
}
void myIdle(void)
{
    angle += 1.0f;
    if (angle >= 360.0f)
        angle = 0.0f;
    myDisplay();
}
int main(int argc, char* argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
    glutInitWindowPosition(200, 200);
    glutInitWindowSize(WIDTH, HEIGHT);
    glutCreateWindow("OpenGL光照演示");
    glutDisplayFunc(&myDisplay);
    glutIdleFunc(&myIdle);
    glutMainLoop();
    return 0;
}

This example simulates a scenario where the Earth revolves around the sun, with the red sun emitting white light illuminating the blue Earth. Let's explain the functions inside.
The sun is a point light source. We use glLightfv to set various properties of the light source, including light source position GL_POSITION, light source color (ambient light GL_AMBIENT, diffuse light GL_DIFFUSE, specular light GL_SPECULAR), radiant intensity attenuation coefficient, etc.

glLightfv(GL_LIGHT0, GL_POSITION, sun_light_position);//第一个参数为光源名,第二个参数指定属性,第三个参数为属性值

In addition to the point light source, we can also set the directional light source (projection light source), that is, to simulate the lighting of the desk lamp, the center light is the strongest, and the edge light intensity is the lowest.

glLightfv(GL_LIGHT0, GL_SPOT_POSITION, sun_light_position);//圆锥轴方向
glLightfv(GL_LIGHT0, GL_SPOT_CUTOFF, 30.0);//光源到圆锥轴的夹角被限制在30度的范围内
glLightfv(GL_LIGHT0, GL_SPOT_EXPONENT, 2.5);//从中心到边缘的衰减系数

Several OpenGL lighting parameters can be specified at the global level.

glLightModel*(paramName,paramValve);//两个参数分别指定参数名和参数值

In addition to the color of the light source, the lighting effect is also inseparable from the reflection characteristics of the object surface. The reflection coefficient and other optional properties of the surface are set with the following functions:

glMaterialf(surfFace,surfProperty,propertyValue);

surfFace assigns one of the symbolic constants GL_FRONT, GL_BACK, GL_FRONT_AND_BACK to specify the face to be described, and surfProperty specifies the attribute name (scattering color gL_EMISSION, GL_SHININESS, etc.).
Before applying a light source, the light source needs to be activated and lit.

glEnable(lightName);//点亮光源
glEnable(GL_LIGHTING);//激活光源

We can also use fog effects to simulate real environments.

glEnable(GL_FOG);//激活雾气
glFogf(atmoParameter,paramValue);//设置雾气属性,例如颜色GL_FOG_COLOR,雾气衰减GL_FOG_DENSITY等等

In order to better deal with the light and dark changes of the surface of the primitive, the corresponding surface drawing method can be specified for interpolation processing.

glShadeModel(surfRenderingMethod);

The parameter specifies the surface drawing method. If GL_FLAT specifies the constant intensity surface drawing method, no processing is performed. GL_SMOOTH specifies the Gouraud surface rendering method. In this mode, a normal vector needs to be specified for each plane.

glBegin(GL_TRIANGLES):
glNormal3fv(normalVector1);
glVertex3fv(vertex1);
glNormal3fv(normalVector2);
glVertex3fv(vertex2);
glNormal3fv(normalVector3);
glVertex3fv(vertex3);

We can normalize normal vectors to speed up OpenGL efficiency

glEnable(GL_NORMALIZE);

and vertex arrays. Like an array of colors, we can also specify an array of normals:

glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(dataType,offset,normalArray);

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325525951&siteId=291194637