@Pigmon
2016-12-01T20:07:18.000000Z
字数 11670
阅读 1060
上课
老师的Cgcourse-examples环境的配置方法 (pdf)
链接:http://pan.baidu.com/s/1jI2ToUE 密码:yxea
拼凑大作业指南+参考大作业1指南
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 modify
it under the terms of the GNU General Public License as published by
the 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 of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along 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 2
typedef GLfloat POSITION[3];
GLuint g_plan_tex_id;
int g_window_width = 512;
int g_window_height = 512;
// light
GLfloat 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;
// material
GLfloat 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 color
GLfloat 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;
}