OpenGL: 平面阴影投射矩阵的推导

文章详细介绍了如何通过平面方程和光的方向推导出平面阴影投射矩阵,用于将3D模型压平到2D平面上,模拟物体在光照下的投影效果。通过矩阵运算,计算出点P沿着光L方向在平面上的投影点S,形成阴影。提供的源代码展示了在OpenGL中实现这一矩阵的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

OpenGL超级宝典(第五版)如下:

      在该书的第1章的Block例子中用到了平面阴影投射矩阵, 将模型视图矩阵压平, 所有被绘制的物体都将位于这个平面的二维世界中。不过这本书没有介绍该平面阴影投射矩阵是如何推导的。平面阴影投射矩阵可用于实现物体在光线下产生影子的效果,距离可参见:详解平面阴影 Planar Shadow (综合篇),这篇文章有很多影子的示例。
      假设平面方程 Ax + By + Cz + D = 0 已知, 光的方向L(Lx, Ly, Lz, 0)已知. 则模型视图空间的点 P(Px, Py, Pz, 1), 沿着光的方向投射到平面上的点为 S(Sx, Sy, Sz, 1). 其中我们设置向量 N(A, B, C, D). 现在我们需要求的是矩阵M, 使得 MP = S. 即 M左乘点P得到点S。由于点S是P沿着光的方向L到达的, 所以S、P、L之间满足线性关系,故可假设 S = P + KL (K >= 0)。

       因为点S是平面上的一点, 所以 A*Sx + B*Sy + C*Sz + D = 0. 即 S . N = 0。即S和N的点乘为0(说明:这里的 .  点号表示点乘,而不是数值相乘,数值相乘用星号*表示,下同)。

 由于 S = P + KL, 所以 (P + KL) . N = 0, 推导可得出 K = -(P . N) / L . N,即 K = -(A*Px + B*Py + C*Pz + D) / (A*Lx + B*Ly + C*Lz), 代入 S = P + KL,得:

Sx = Px + K*Lx = Px - (A*Px + B*Py + C*Pz + D)*Lx / (A*Lx + B*Ly + C*Lz) 
= [ Px*(B*Ly + C*Lz) - Py*(B*Lx) - Pz*(C*Lx) - 1*D*Lx ] / (A*Lx + B*Ly + C*Lz) 

把上述的Px、Py、Pz提取出来,用齐次坐标表示向量P,且用点乘来表示要简洁些,表示如下:
= P . ((B*Ly + C*Lz), -B*Lx, -C*Lx, -D*Lx)/(A*Lx + B*Ly + C*Lz) 

同理 
Sy = P .  (-A*Ly, (A*Lx + C*Lz), -C*Ly, -D*Ly)/(A*Lx + B*Ly + C*Lz) 
Sz = P .  (-A*Lz, -B*Lz, (A*LX + B*Ly), -D*Lx)/(A*Lx + B*Ly + C*Lz) 
Sw = P . (0, 0, 0, (A*Lx + B*Ly + C*Lz))/(A*Lx + B*Ly + C*Lz) 

注意:P前面是点乘符号,P为[Px, Py, Pz, 1]。
所以可得到矩阵M:

B*Ly + C*Lz-B*Lx-C*Lx-D*Lx
-A*LyA*Lx + C*Lz-C*Ly-D*Ly
-A*Lz-B*LzA*LX + B*Ly-D*Lx
000A*Lx + B*Ly + C*Lz

在OpenGL超级宝典(第五版)这本书的源代码里有该矩阵的实现代码, 位于文件 math3d.cpp 中, 可参考上面公式的实现 

// Creae a projection to "squish" an object into the plane.
// Use m3dGetPlaneEquationf(planeEq, point1, point2, point3);
// to get a plane equation.
void m3dMakePlanarShadowMatrix(M3DMatrix44f proj, const M3DVector4f planeEq, const M3DVector3f vLightPos)
	{
	// These just make the code below easier to read. They will be 
	// removed by the optimizer.	
	float a = planeEq[0];
	float b = planeEq[1];
	float c = planeEq[2];
	float d = planeEq[3];

	float dx = -vLightPos[0];
	float dy = -vLightPos[1];
	float dz = -vLightPos[2];

	// Now build the projection matrix
	proj[0] = b * dy + c * dz;
	proj[1] = -a * dy;
	proj[2] = -a * dz;
	proj[3] = 0.0;

	proj[4] = -b * dx;
	proj[5] = a * dx + c * dz;
	proj[6] = -b * dz;
	proj[7] = 0.0;

	proj[8] = -c * dx;
	proj[9] = -c * dy;
	proj[10] = a * dx + b * dy;
	proj[11] = 0.0;

	proj[12] = -d * dx;
	proj[13] = -d * dy;
	proj[14] = -d * dz;
	proj[15] = a * dx + b * dy + c * dz;
	// Shadow matrix ready
	}

 本文转自:OpenGL: 平面阴影投射矩阵的推导_Augusdi的博客-优快云博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值