@Pigmon 2016-12-01T12:07:18.000000Z 字数 11670 阅读 237

# 图形学参考大作业3

上课

## 如果不知道怎么整合到cgcourse-examples里

https://www.zybuluo.com/Pigmon/note/582224

• 加贴图
• 换投影体
• 多光源

## 程序

/*-----------------------------------------------------------------------This source file is part of "cgcourse-examples"(Examples for Computer Graphics Course of CCCE GUCAS.)Copyright (C) 2011 Xue Jian (jian.xue.cn@gmail.com)This program is free software: you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation, either version 3 of the License, or(at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program.  If not, see <http://www.gnu.org/licenses/>.-----------------------------------------------------------------------*/#include <stdlib.h>#include <stdio.h>#include <vector>#include <GL/glut.h>#include <GL/glext.h>#include "camera.h"#include "trackball.h"#define LIST_NAME_TRIANGLE 1#define LIST_NAME_PLANE 2typedef GLfloat POSITION[3];GLuint g_plan_tex_id;int g_window_width = 512;int g_window_height = 512;// lightGLfloat g_light_ambient[] = { 1.0f, 1.0f, 1.0f, 1.0f };GLfloat g_light_diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };GLfloat g_light_position[] = { 2.0f, 4.0f, 3.0f, 1.0f };GLfloat g_light_direction[] = { 1.0f, 0.0f, 1.0f, 0.0f };GLfloat g_light_rot = 0.0f;GLfloat g_light_rot_speed = 0.2f;// materialGLfloat g_material_ambient[] = { 1.0f, 0.8f, 0.8f, 1.0f };GLfloat g_material_diffuse[] = { 0.8f, 0.8f, 0.8f, 1.0f };GLfloat g_material_specular[] = { 0.33f, 0.33f, 0.52f, 0.0f };GLfloat g_material_emission[] = { 0.0f, 0.0f, 0.0f, 0.0f };GLfloat g_material_specular_power = 80.0f;GLfloat g_material_ambient_2[] = { 0.0f, 1.0f, 1.0f, 1.0f };GLfloat g_material_diffuse_2[] = { 1.0f, 0.5f, 0.25f, 0.5f };GLfloat g_material_specular_2[] = { 0.33f, 0.33f, 0.52f, 0.0f };GLfloat g_material_emission_2[] = { 0.0f, 0.0f, 0.0f, 0.0f };GLfloat g_material_specular_power_2 = 80.0f;// bg colorGLfloat g_color_background[] = { 0.0f, 0.0f, 0.0f, 0.0f };GLfloat g_color_foreground[] = { 1.0f - g_color_background[0], 1.0f - g_color_background[1], 1.0f - g_color_background[2], 1.0f };Cameraf g_cam;float g_z = 10.0f;float const Z_STEP = 0.1f;POSITION triangle[3] = { { 0, 1, 0 },{ 2, 1, 0 },{ 0, 3, 0 } };POSITION lightPosition = { g_light_position[0], g_light_position[1], g_light_position[2] };GLfloat g_pot_position[] = { 0.5f, -0.5f, -3.0f, 1.0f };bool b_volum = false;// --------------------------------------------------------// 鼠标转动 -->// --------------------------------------------------------bool g_left_button_down = false;bool g_middle_button_down = false;bool g_right_button_down = false;int g_last_x = 0;int g_last_y = 0;GLint g_viewport[4];TrackBallf g_trackball(1.5f);Matrixf g_rotm;// --------------------------------------------------------// 鼠标转动 <--// --------------------------------------------------------void set_material_scene(){    GLenum face = GL_FRONT_AND_BACK;    glMaterialfv(face, GL_AMBIENT, g_material_ambient);    glMaterialfv(face, GL_DIFFUSE, g_material_diffuse);    glMaterialfv(face, GL_SPECULAR, g_material_specular);    glMaterialfv(face, GL_EMISSION, g_material_emission);    glMaterialf(face, GL_SHININESS, g_material_specular_power);}void set_material_light(){    GLenum face = GL_FRONT;    glMaterialfv(face, GL_AMBIENT, g_material_ambient_2);    glMaterialfv(face, GL_DIFFUSE, g_material_diffuse_2);    glMaterialfv(face, GL_SPECULAR, g_material_specular_2);    glMaterialfv(face, GL_EMISSION, g_material_emission_2);    glMaterialf(face, GL_SHININESS, g_material_specular_power_2);}bool init(){    g_rotm.IdentityMatrix();    glEnable(GL_LIGHTING);    glClearColor(g_color_background[0], g_color_background[1], g_color_background[2], g_color_background[3]);               // Black Background    glClearDepth(1.0f);                                 // Depth Buffer Setup    glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, 1.0f);    glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, 0.0f);    glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, 0.0f);    glLightfv(GL_LIGHT1, GL_DIFFUSE, g_light_diffuse);      // Setup The Diffuse Light    glLightfv(GL_LIGHT1, GL_SPECULAR, g_light_diffuse);    glLightfv(GL_LIGHT1, GL_POSITION, g_light_position);    // Position The Light    glEnable(GL_LIGHT1);                                // Enable Light One    return true;                                        // Initialization Went OK}/// 建立场景，一个地板和一个三角形void init_lists(){    glNewList(LIST_NAME_TRIANGLE, GL_COMPILE);    glColor3f(1.0f, 1.0f, 1.0f);    glBegin(GL_TRIANGLES);    glVertex3f(triangle[0][0], triangle[0][1], triangle[0][2]);    glVertex3f(triangle[1][0], triangle[1][1], triangle[1][2]);    glVertex3f(triangle[2][0], triangle[2][1], triangle[2][2]);    glEnd();    glEndList();    glNewList(LIST_NAME_PLANE, GL_COMPILE);    glBegin(GL_QUADS);    glVertex3f(-10.0f, -1.0f, -10.0f); // tl                                       //glTexCoord2f(1.0f, 0.0f);     glVertex3f(10.0f, -1.0f, -10.0f);   // tr                                        //glTexCoord2f(1.0f, 1.0f);     glVertex3f(10.0f, -1.5f, 10.0f);    // br                                        //glTexCoord2f(0.0f, 1.0f);     glVertex3f(-10.0f, -1.5f, 10.0f); // bl         glEnd();    glDisable(GL_TEXTURE_2D);    glEndList();}void keyboard(unsigned char key, int x, int y){    switch (key)    {    case 27:        exit(0);        break;    case 's':        b_volum = !b_volum;        break;    }}// --------------------------------------------------------// 鼠标转动 -->// --------------------------------------------------------void motion(int x, int y){    if (g_left_button_down)    {        g_last_x = x;        g_last_y = y;        g_trackball.Update((float)(2.0*(x - g_viewport[0]) / g_viewport[2] - 1), (float)(2.0*(g_viewport[3] - y - 1 - g_viewport[1]) / g_viewport[3] - 1));        g_trackball.BuildRotMatrix(g_rotm);        glutPostRedisplay();    }}void mouse(int button, int state, int x, int y){    bool down = (state == GLUT_DOWN);    switch (button)    {    case GLUT_LEFT_BUTTON: g_left_button_down = down; break;    case GLUT_MIDDLE_BUTTON: g_middle_button_down = down; break;    case GLUT_RIGHT_BUTTON: g_right_button_down = down; break;    }    if (g_left_button_down)    {        g_trackball.Start((float)(2.0*(x - g_viewport[0]) / g_viewport[2] - 1), (float)(2.0*(g_viewport[3] - y - 1 - g_viewport[1]) / g_viewport[3] - 1));    }    g_last_x = x;    g_last_y = y;}// --------------------------------------------------------// 鼠标转动 <--// --------------------------------------------------------/// <summary>/// extendVolume : 参考论文中附录提供的生成Shadow Volume的函数/// </summary>/// <param name="n">投影体需要考虑的定点数</param>/// <param name="localLight">是否点光源，1 - 点光源， 0 - 平行光</param>/// <param name="lightPosition">光源位置</param>/// <param name="extendDistance">Shadow Volum的最大长度</param>/// <returns>void</returns>void extendVolume(int n, POSITION v[], int localLight, POSITION lightPosition, float extendDistance){    POSITION extendedVectex, extendDirection;    int i;    // If light source is infinite (directional)    if (!localLight)    {        // compute direction opposite from light source direction        extendDirection[0] = -lightPosition[0];        extendDirection[1] = -lightPosition[1];        extendDirection[2] = -lightPosition[2];    }    glBegin(GL_QUAD_STRIP);    // If light source is local (positional)    if (localLight)    {        for (i = 0; i < n; i++)        {            glVertex3fv(v[i]);            // Compute per-vertex direction from vertex away from the light source            extendDirection[0] = v[i][0] - lightPosition[0];            extendDirection[1] = v[i][1] - lightPosition[1];            extendDirection[2] = v[i][2] - lightPosition[2];            // Compute extend vertex            extendedVectex[0] = v[i][0] + extendDirection[0] * extendDistance;            extendedVectex[1] = v[i][1] + extendDirection[1] * extendDistance;            extendedVectex[2] = v[i][2] + extendDirection[2] * extendDistance;            glVertex3fv(extendedVectex);        }        // Repeate initial 2 vertices to close the quad strip loop        glVertex3fv(v[0]);        extendDirection[0] = v[0][0] - lightPosition[0];        extendDirection[1] = v[0][1] - lightPosition[1];        extendDirection[2] = v[0][2] - lightPosition[2];        extendedVectex[0] = v[0][0] + extendDirection[0] * extendDistance;        extendedVectex[1] = v[0][1] + extendDirection[1] * extendDistance;        extendedVectex[2] = v[0][2] + extendDirection[2] * extendDistance;        glVertex3fv(extendedVectex);    }    else // otherwise, light source is infinite (directional)    {        for (i = 0; i < n; i++)        {            glVertex3fv(v[i]);            // Compute extend vertex            extendedVectex[0] = v[i][0] + extendDirection[0] * extendDistance;            extendedVectex[1] = v[i][1] + extendDirection[1] * extendDistance;            extendedVectex[2] = v[i][2] + extendDirection[2] * extendDistance;            glVertex3fv(extendedVectex);        }        // Repeate initial 2 vertices to close the quad strip loop        extendedVectex[0] = v[0][0] + extendDirection[0] * extendDistance;        extendedVectex[1] = v[0][1] + extendDirection[1] * extendDistance;        extendedVectex[2] = v[0][2] + extendDirection[2] * extendDistance;        glVertex3fv(extendedVectex);    }    glEnd();}/// 渲染场景中的除阴影体以外的一切模型void renderScene(){    set_material_scene();    {        // 地面        glCallList(LIST_NAME_PLANE);        // 茶壶        glTranslatef(g_pot_position[0], g_pot_position[1], g_pot_position[2]);        glutSolidTeapot(0.6);        glTranslatef(-1 * g_pot_position[0], -1 * g_pot_position[1], -1 * g_pot_position[2]);    }    set_material_light();    {        // 投影体        glCallList(LIST_NAME_TRIANGLE);        // Shadow Volume 外观        if (b_volum)        {            glEnable(GL_BLEND);            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);            extendVolume(3, triangle, 1, lightPosition, 100000.0f);            glDisable(GL_BLEND);        }        // 画代表光源的球        glTranslatef(g_light_position[0], g_light_position[1], g_light_position[2]);        glutSolidSphere(0.2f, 10, 10);        glTranslatef(-1 * g_light_position[0], -1 * g_light_position[1], -1 * g_light_position[2]);    }}/// <summary>/// 参考论文正文中的，得到阴影体内部的模版值的函数/// </summary>void drawShadowVolumePolygons(){    //glDisable(GL_CULL_FACE);    glDisable(GL_LIGHTING); // lighting not needed    glEnable(GL_DEPTH_TEST);    glDepthFunc(GL_LESS);    glDepthMask(0); // do not disturb depth buffer    glColorMask(0, 0, 0, 0); // do not disturb color buffer    glStencilMask(~0u);    glEnable(GL_CULL_FACE); // use face culling    glCullFace(GL_BACK); // increment for front facing fragments    glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); // that pass the depth test    extendVolume(3, triangle, 1, lightPosition, 100000.0f);    //for (i = 0; i<numPolygonsInScene; i++) // for every polygon in the scene    //  renderShadowVolumeForPolygon(i); // call extendVolume for ith polygon    glCullFace(GL_FRONT); // decrement for back facing fragments    glStencilOp(GL_KEEP, GL_KEEP, GL_DECR); // that pass the depth test    extendVolume(3, triangle, 1, lightPosition, 100000.0f);    //for (i = 0; i<numPolygonsInScene; i++) // for every polygon in the scene    //  renderShadowVolumeForPolygon(i); // call extendVolume for ith polygon    glDisable(GL_CULL_FACE);}void display(){    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    glMatrixMode(GL_MODELVIEW);    glLoadIdentity();    g_cam.LookAt(-10.0f, 10.0f, g_z, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);    // 鼠标转动    glMultMatrixf(g_rotm);    glEnable(GL_LIGHTING);    ///// 参考论文正文中渲染阴影的主要步骤    /// step 1    /// 渲染一遍场景，得到深度值    glEnable(GL_LIGHT0); // enable light source    glEnable(GL_DEPTH_TEST); // standard depth testing    glDepthFunc(GL_LEQUAL);    glDepthMask(1);    glDisable(GL_STENCIL_TEST); // no stencil testing (this pass)    glColorMask(1, 1, 1, 1); // update color buffer    glClearStencil(0); // clear stencil to zero    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);    renderScene();    /// step 2    /// 分别渲染阴影体的正面和背面，阴影体内部的面模板值为1    glDisable(GL_LIGHTING); // do not waste time lighting       glEnable(GL_DEPTH_TEST);    glDepthFunc(GL_LESS);    glDepthMask(0); // do not disturb the depth buffer                      glEnable(GL_STENCIL_TEST);    glStencilFunc(GL_ALWAYS, 0, 0);    glStencilMask(0x1); // just write least significant stencil bit    glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT); // invert stencil bit if depth pass                                             glColorMask(0, 0, 0, 0); // do not disturb the color buffer                          drawShadowVolumePolygons();    /// step 3    /// 根据上面的模板值将阴影绘制出来    glEnable(GL_LIGHTING); // use lighting    glDisable(GL_LIGHT0); // just not the shadowed light    glEnable(GL_DEPTH_TEST);    glDepthFunc(GL_EQUAL); // must match depth from 1st step    glDepthMask(0);    glEnable(GL_STENCIL_TEST); // and use stencil to update only    glStencilFunc(GL_EQUAL, 0x1, 0x1); // pixels tagged as    glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // “in the shadow volume”    glColorMask(1, 1, 1, 1);    renderScene();    glutSwapBuffers();}void reshape(int width, int height){    if (height == 0)    {        height = 1;    }    glViewport(0, 0, width, height);    glGetIntegerv(GL_VIEWPORT, g_viewport);    g_cam.Perspective(45.0f, (float)(width) / (float)(height), 1.1f, 100.0f);}int main(int argc, char *argv[]){    glutInit(&argc, argv);    glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);    glutInitWindowPosition(100, 100);    glutInitWindowSize(g_window_width, g_window_height);    glutCreateWindow("参考大作业3");    if (!init()) return -1;    init_lists();    glutDisplayFunc(display);    glutReshapeFunc(reshape);    glutKeyboardFunc(keyboard);    glutMouseFunc(mouse);    glutMotionFunc(motion);    glutIdleFunc(display);    glutMainLoop();    return 0;}

• 私有
• 公开
• 删除