MFC实现三维图像绘制(5.1)光照模型

光照的实现主要是通过环境光,漫反射光,镜面反射光和材质属性的不同确定的,因此首先通过CLightSource类保存光源,CMaterial类保存材质属性,CLight类进行光照。

CLightSource类:

#include"P3.h"

class CLightSource
{
public:
	CLightSource(void);
	virtual ~CLightSource(void);
	void SetDiffuse(CRGB diffuse);//设置光源的漫反射光
	void SetSpecular(CRGB specular);//设置光源的镜面反射光
	void SetPosition(double x, double y, double z);//设置光源的位置
	void SetAttenuationFactor(double c0, double c1, double c2);//设置光强的衰减因子
	void SetOnOff(bool onoff);//设置光源开关状态	
public:
	CRGB L_Diffuse;//漫反射光颜色	
	CRGB L_Specular;//镜面反射光颜色
	CP3 L_Position;//光源位置
	double L_C0;//常数衰减因子
	double L_C1;//线性衰减因子
	double L_C2;//二次衰减因子
	bool L_OnOff;//光源开启或关闭
};

#include "pch.h"
#include "LightSource.h"

CLightSource::CLightSource(void)
{
	L_Diffuse = CRGB(1.0, 1.0, 1.0);//光源的漫反射颜色	
	L_Specular = CRGB(1.0, 1.0, 1.0);//光源镜面高光颜色
	L_Position.x = 1000.0, L_Position.y = 1000.0, L_Position.z = 1000.0;//光源位置直角坐标
	L_C0 = 1.0;//常数衰减系数
	L_C1 = 0.0;//线性衰减系数
	L_C2 = 0.0;//二次衰减系数
	L_OnOff = TRUE;//光源开启
}

CLightSource::~CLightSource(void)
{
}

void CLightSource::SetDiffuse(CRGB difuse)
{
	L_Diffuse = difuse;
}

void CLightSource::SetSpecular(CRGB specular)
{
	L_Specular = specular;
}

void CLightSource::SetPosition(double x, double y, double z)
{
	L_Position.x = x;
	L_Position.y = y;
	L_Position.z = z;
}

void CLightSource::SetOnOff(bool onoff)
{
	L_OnOff = onoff;
}

void CLightSource::SetAttenuationFactor(double c0, double c1, double c2)
{
	L_C0 = c0;
	L_C1 = c1;
	L_C2 = c2;
}

CMaterial类:

#include"RGB.h"

class CMaterial
{
public:
	CMaterial(void);
	virtual~CMaterial(void);
	void SetAmbient(CRGB c);//设置环境光的反射率	
	void SetDiffuse(CRGB c);//设置漫反射光的反射率
	void SetSpecular(CRGB c);//设置镜面反射光的反射率
	void SetExponent(double n);//设置高光指数
public:
	CRGB M_Ambient;//环境光的反射率
	CRGB M_Diffuse;//漫反射光的反射率
	CRGB M_Specular;//镜面反射光的反射率
	double M_n;//高光指数
};

#include "pch.h"
#include "Material.h"

CMaterial::CMaterial(void)
{
	M_Ambient = CRGB(0.175, 0.012, 0.012);//材质的环境反射率
	M_Diffuse = CRGB(0.614, 0.041, 0.041);//材质的漫反射率
	M_Specular = CRGB(0.728, 0.527, 0.527);//材质的镜面反射率
	M_n = 1.0;//高光指数
}

CMaterial::~CMaterial(void)
{
}

void CMaterial::SetAmbient(CRGB c)
{
	M_Ambient = c;
}

void CMaterial::SetDiffuse(CRGB c)
{
	M_Diffuse = c;
}

void CMaterial::SetSpecular(CRGB c)
{
	M_Specular = c;
}

void CMaterial::SetExponent(double n)
{
	M_n = n;
}

CLight类:

#include"LightSource.h"
#include"Material.h"
#include"Vector3.h"

class CLighting
{
public:
	CLighting(void);
	CLighting(int nLightNumber);
	virtual ~CLighting(void);
	void SetLightNumber(int nLightNumber);//设置光源数量
	void SetLightSource(CLightSource[]);//设置光源
	CRGB Illuminate(CP3 ViewPoint, CP3 Point, CVector3 ptNormal, CMaterial* pMaterial);//计算光照	
	void DeleteLight();//删除光源
public:
	int nLightNumber;//光源数量
	CLightSource* LightSource;//光源数组
	CRGB Ambient;//环境光
};

#include "pch.h"
#include "Lighting.h"


CLighting::CLighting(void)
{
	nLightNumber = 1;
	LightSource = new CLightSource[nLightNumber];
	Ambient = CRGB(0.3, 0.3, 0.3);//环境光是常数
}

CLighting::CLighting(int nLightNumber)
{
	this->nLightNumber = nLightNumber;
	LightSource = new CLightSource[nLightNumber];
	Ambient = CRGB(0.3, 0.3, 0.3);
}

CLighting::~CLighting(void)
{
}

void CLighting::SetLightNumber(int nLightNumber)
{
	if (LightSource != NULL)
		delete[]LightSource;
	this->nLightNumber = nLightNumber;
	LightSource = new CLightSource[nLightNumber];
}

void CLighting::SetLightSource(CLightSource LightSource[]) {
	for (int i = 0;i < this->nLightNumber;i++) {
		this->LightSource[i] = LightSource[i];
	}
}

CRGB CLighting::Illuminate(CP3 ViewPoint, CP3 Point, CVector3 ptNormal, CMaterial* pMaterial)
{
	CRGB ResultI = CRGB(0.0, 0.0, 0.0);//反射光强初始值
	for (int loop = 0; loop < nLightNumber; loop++)//检查光源开关状态
	{
		if (LightSource[loop].L_OnOff)//光源开
		{
			CRGB I = CRGB(0.0, 0.0, 0.0);// I代表“反射”光强
			CVector3 L(Point, LightSource[loop].L_Position);// L为光向量
			double d = L.Magnitude();// d为光传播的距离 
			L = L.Normalize();//规范化光向量
			CVector3 N = ptNormal;
			N = N.Normalize();//规范化法向量
			//第1步,加入漫反射光
			double NdotL = max(DotProduct(N, L), 0);
			I += LightSource[loop].L_Diffuse * pMaterial->M_Diffuse * NdotL;
			//第2步,加入镜面反射光
			CVector3 V(Point, ViewPoint);//V为观察向量
			V = V.Normalize();//规范化观察向量
			CVector3 H = (L + V) / (L + V).Magnitude();//H为中值向量
			double NdotH = max(DotProduct(N, H), 0);
			double Rs = pow(NdotH, pMaterial->M_n);
			I += LightSource[loop].L_Specular * pMaterial->M_Specular * Rs;
			//第3步,光强衰减
			double c0 = LightSource[loop].L_C0;//c0为常数衰减因子
			double c1 = LightSource[loop].L_C1;//c1为线性衰减因子
			double c2 = LightSource[loop].L_C2;//c2为二次衰减因子
			double f = (1.0 / (c0 + c1 * d + c2 * d * d));//光强衰减函数
			f = min(1.0, f);
			ResultI += I * f;
		}
		else
			ResultI += Point.c;//物体自身颜色
	}
	//第4步,加入环境光
	ResultI += Ambient * pMaterial->M_Ambient;
	//第5步,光强规范化到[0,1]区间
	ResultI.Normalize();
	//第6步,返回所计算顶点的最终的光强颜色
	return ResultI;
}

void CLighting::DeleteLight() {
	if (LightSource != NULL)
	{
		delete[]LightSource;
		LightSource = NULL;
	}
}

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值