专栏首页图形学与OpenGL机械版CG 实验6 简单光照明模型实现

机械版CG 实验6 简单光照明模型实现

CG实验指导八 简单光照明模型实现

1.实验目的:

了解简单光照明模型的基本原理,实现物体的真实感图形显示效果。

2.实验内容:

(1) 结合示范代码了解简单光照明模型的基本原理与实现;

(2) 调试、编译、修改示范程序,给出不同光照系数,观察验证显示效果。

3.实验原理:

Phong光照明模型是由物体表面上一点P反射到视点的光强I为环境光的反射光强Ie、理想漫反射光强Id、和镜面反射光Is的总和,即

其中R,V,N为单位矢量;Ip为点光源发出的入射光强;Ia为环境光的漫反射光强;Ka环境光的漫反射系数;Kd漫反射系数取决于表面的材料;Ks镜面反射系数;n幂次,用以模拟反射光的空间分布,表面越光滑,n越大。

在用Phong模型进行真实感图形计算时,对物体表面上的每个点P,均需计算光线的反射方向R,再由V计算。为减少计算量,我们可以作如下假设:a)光源在无穷远处,即光线方向L为常数;b)视点在无穷远处,即视线方向V为常数;c)用近似。这里HLV的角平分向量,。在这种简化下,由于对所有的点总共只需计算一次H的值,节省了计算时间。结合RGB颜色模型,Phong光照明模型最终有如下的形式:

本次实验中,光源在无穷远处,光线方向为单位向量L(0.5, 0.5, 0.707),视点在无穷远处,视线方向V为(0, 0, 1)。

4.实验代码:

#include <GL/glut.h>

#include <stdio.h>

#include <stdlib.h>

#include <math.h>

struct Vector

{

float fx, fy, fz;

};

struct Color

{

float Ir, Ig, Ib;

};

float KaIa;//环境光强度

float Kd, n;

Vector H,light;

Color mLight, mColor;

GLboolean bLight = false;

//利用圆的八向对称性生成圆上的点

void CirclePt(int x0, int y0, int x, int y, Color mColor)

{

glColor3ub (mColor.Ir, mColor.Ig, mColor.Ib);

glBegin(GL_POINTS);

glVertex2i ( x+x0, y+y0);//x,y

glVertex2i ( -x+x0, y+y0);//-x,y

glVertex2i ( x+x0, -y+y0);//x, -y

glVertex2i ( -x+x0, -y+y0);//-x, -y

glVertex2i ( y+x0, x+y0);//y, x

glVertex2i ( y+x0, -x+y0);//y, -x

glVertex2i ( -y+x0, x+y0);//-y, x

glVertex2i ( -y+x0,-x+y0);//-y, -x

glEnd();

}

//中点圆生成算法

void MidCircle(int x0, int y0, int r, Color mColor)

{

int x,y,deltax,deltay,d;

x = 0;

y = r;

deltax = 3;

deltay = 5-r-r;

d = 1-r;

CirclePt( x0, y0, x, y, mColor);

while(x<y)

       {

if(d<0)

              {

d += deltax;

deltax += 2;

deltay += 2;

x++;

              }

else

              {

d += deltay;

deltax += 2;

deltay += 4;

x++;

y--;

              }

CirclePt( x0, y0, x, y, mColor);

       }

}

//根据中点圆算法填充圆域

void FlatCircle(int x0, int y0, int r, Color mColor)

{

int x,y,deltax,deltay,d;

x = 0;

y = r;

deltax = 3;

deltay = 5-r-r;

d = 1-r;

glColor3ub (mColor.Ir, mColor.Ig, mColor.Ib);

glBegin(GL_POINTS);

       {

for(int i=-x;i<=x;i++)

              {

glVertex2i (i+x0,y+y0);

glVertex2i (i+x0,-y+y0);

              }

for(i=-y;i<=y;i++)

              {

glVertex2i (i+x0,x+y0);

glVertex2i (i+x0,-x+y0);

              }

while(x<y)

              {

if(d<0)

                     {

d += deltax;

deltax += 2;

deltay += 2;

x++;

                     }

else

                     {

d += deltay;

deltax += 2;

deltay += 4;

x++;

y--;

                     }

for(i=-x;i<=x;i++)

                     {

glVertex2i (i+x0,y+y0);

glVertex2i (i+x0,-y+y0);

                     }

for(i=-y;i<=y;i++)

                     {

glVertex2i (i+x0,x+y0);

glVertex2i (i+x0,-x+y0);

                     }

              }

       }

glEnd();

}

//初始化设定

void Init()

{

float mo;

Vector eye;

mLight.Ir = 0;

mLight.Ig = 175;

mLight.Ib = 0;

KaIa=80;

Kd = 1;

n = 10;

light.fx=0.50;light.fy=0.50;

light.fz = sqrt(1-(light.fx*light.fx)-(light.fy*light.fy));

eye.fx=0;eye.fy=0;eye.fz=1;

H.fx=light.fx+eye.fx;

H.fy=light.fy+eye.fy;

H.fz=light.fz+eye.fz;

mo=sqrt(H.fx*H.fx+H.fy*H.fy+H.fz*H.fz);

H.fx=(H.fx/mo);H.fy=(H.fy/mo);H.fz=(H.fz/mo);

H.fx=(H.fx/mo);H.fy=(H.fy/mo);H.fz=(H.fz/mo);

glClearColor(0.0, 0.0, 0.0, 0.0);

glShadeModel(GL_SMOOTH);

}

//根据Phong模型计算光强

Color Phong(int x0, int y0, int r, int x, int y)

{

Vector N;

float z,alpha,theta,Ks;

Ks=1.0-Kd;

z=sqrt((float)(r*r-(x-x0)*(x-x0)-(y-y0)*(y-y0)));

N.fx=(x-x0)*1.0/r;

N.fy=(y-y0)*1.0/r;

N.fz = z*1.0/r;

theta = N.fx * light.fx + N.fy * light.fy + N.fz * light.fz;

if(theta<0)

theta=0;

alpha=H.fx*N.fx+H.fy*N.fy+H.fx*N.fz;

if(alpha<0)

alpha=0;

mColor.Ir=KaIa+mLight.Ir*Kd*theta+mLight.Ir*Ks*pow(alpha,n);

mColor.Ig=KaIa+mLight.Ig*Kd*theta+mLight.Ig*Ks*pow(alpha,n);

mColor.Ib=KaIa+mLight.Ib*Kd*theta+mLight.Ib*Ks*pow(alpha,n);

return mColor;

}

//根据计算的光强按球体的结果着色

void Sphere(int x0, int y0, int r)

{

int x,y,deltax,deltay,d;

x = 0;

y = r;

deltax = 3;

deltay = 5-r-r;

d = 1-r;

glBegin(GL_POINTS);

       {

for(int i=-x;i<=x;i++)

              {

mColor=Phong(x0,y0,r,i+x0,y+y0);

glColor3ub (mColor.Ir, mColor.Ig, mColor.Ib);   glVertex2i (i+x0,y+y0);

glColor3ub (mColor.Ir, mColor.Ig, mColor.Ib);   glVertex2i (i+x0,-y+y0);

              }

for(i=-y;i<=y;i++)

              {

mColor=Phong(x0,y0,r,i+x0,x+y0);

glColor3ub (mColor.Ir, mColor.Ig, mColor.Ib);   glVertex2i (i+x0,x+y0);

glColor3ub (mColor.Ir, mColor.Ig, mColor.Ib);   glVertex2i (i+x0,-x+y0);

              }

while(x<y)

              {

if(d<0)

                     {

d += deltax;

deltax += 2;

deltay += 2;

x++;

                     }

else

                     {

d += deltay;

deltax += 2;

deltay += 4;

x++;

y--;

                     }

for(i=-x;i<=x;i++)

                     {

mColor=Phong(x0,y0,r,i+x0,y+y0);

glColor3ub (mColor.Ir, mColor.Ig, mColor.Ib);   glVertex2i (i+x0,y+y0);

glColor3ub (mColor.Ir, mColor.Ig, mColor.Ib);   glVertex2i (i+x0,-y+y0);

                     }

for(i=-y;i<=y;i++)

                     {

mColor=Phong(x0,y0,r,i+x0,x+y0);

glColor3ub (mColor.Ir, mColor.Ig, mColor.Ib);   glVertex2i (i+x0,x+y0);

glColor3ub (mColor.Ir, mColor.Ig, mColor.Ib);   glVertex2i (i+x0,-x+y0);

                     }

              }

       }

glEnd();

}

void myDisplay()

{

glClear(GL_COLOR_BUFFER_BIT);

glColor3f (1.0f, 1.0f, 1.0f);

Color clr;

clr.Ir = 180, clr.Ig = 180, clr.Ib = 180;

MidCircle(80, 240, 70, clr);

FlatCircle(280, 240, 70, clr);

Sphere(540, 240, 70);

glFlush();

}

void Reshape(int w, int h)

{

glViewport(0, 0, (GLsizei) w, (GLsizei) h);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

gluOrtho2D(0.0, (GLdouble) w, 0.0, (GLdouble) h);

}

int main(int argc, char *argv[])

{

glutInit(&argc, argv);

glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);

glutInitWindowPosition(100, 100);

glutInitWindowSize(640, 480);

glutCreateWindow("Hello World!");

Init();

glutDisplayFunc(myDisplay);

glutReshapeFunc(Reshape);

glutMainLoop();

return 0;

}

5.实验思考题

尝试绘制一个平面或正方体的简单光照效果。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • CG实验6 简单光照与材质

    (1) 阅读和修改示范代码中的有关参数,产生不同光照效果,观察显示效果。挑选两张修改的效果图保存为图1-2,与对应修改的代码一起保存至word实验文档中(15分...

    步行者08
  • 实验3 直线裁剪算法

    本次实验主要结合鼠标画线程序来验证编码裁剪算法和实现梁友栋-Barsky裁剪算法,具体步骤如下:

    步行者08
  • 实验4 编码裁剪算法

    了解二维图形裁剪的原理(点的裁剪、直线的裁剪、多边形的裁剪),利用VC+OpenGL实现直线的裁剪算法。

    步行者08
  • 「特殊节日使用」全站增加灰色滤镜通用代码

    今年12月13日是第五个南京大屠杀死难者国家公祭日,每年的这一天,我们以国家之名祭奠,共同铭记历史

    沈唁
  • 使用ELK分析Windows事件日志

    这是ELK入门到实践系列的第三篇文章,分享如何使用ELK分析Windows事件日志。

    Bypass
  • 探究网站变灰色那点事

    缅怀的同时,突然冒出一个问题,怎么做到的?难不成一个个调整图片,调整对应的控件色值?

    HLQ_Struggle
  • 51Nod-1803-森林直径

    ACM模版 描述 ? 题解 根据题目,我们知道,数据是随机建树的,所以树的深度不会特别大,约摸 lg nlg\ n,所以我们可以树归搞搞,亲测,数据随机建树深度...

    f_zyj
  • 击穿JVM虚拟机

    首先我们需要了解什么是虚拟机,为什么虚拟机可以实现夸平台,虚拟机在计算机中扮演一个什么样的角色。

    兜兜毛毛
  • mongodb 更新删除内嵌list字段值

    查询结果如下,现在需要把 “证券代码” =》 “code” ; “发行人中文名称” =》 “COMP_NAME”

    周小董
  • 服务器攻防·禁止穷举邮箱密码

    本文节选自《Netkiller Linux 手札》 下面是一个脚本你可以放在crontab中运行,每个一定时间运行一次。 #!/bin/bash #######...

    netkiller old

扫码关注云+社区

领取腾讯云代金券