当前位置: 首页 > news >正文

shadow projection

1、概述

shadow projection,又可成为planar shadow, 这是一种非常简单的绘制阴影的方法。

主要应用的应用场景:物体在平面投射阴影。

主要思想:把阴影看作是物体在平面上的投影(projection),然后将该projection绘制出来即可。


2、具体方法

具体实现:
给定光源的位置L,物体上的任意一点V, 平面s的法向量N. 求V在平面s上的投影点P.


由简单的几何知识可知,

光源L和顶点V之间的光线方程为:

平面s的方程为 :, 其中Q为平面上的任意一点。

由图可知,投影点P是光线与平面的交点,所以

易知

 故

这样就得到了shadow matrix


3、代码

 

void shadowMatrix(GLfloat shadowMat[16], const GLfloat planeParameter[4], const GLfloat lightPos[4])
{
	GLfloat dot = planeParameter[0] * lightPos[0]
	+ planeParameter[1] * lightPos[1]
	+ planeParameter[2] * lightPos[2]
	+ planeParameter[3] * lightPos[3];


	shadowMat[0] = dot - lightPos[0] * planeParameter[0];
	shadowMat[4] = 0.0 - lightPos[0] * planeParameter[1];
	shadowMat[8] = 0.0 - lightPos[0] * planeParameter[2];
	shadowMat[12] = 0.0 - lightPos[0] * planeParameter[3];

	shadowMat[1] = 0.0 - lightPos[1] * planeParameter[0];
	shadowMat[5] = dot - lightPos[1] * planeParameter[1];
	shadowMat[9] = 0.0 - lightPos[1] * planeParameter[2];
	shadowMat[13] = 0.0 - lightPos[1] * planeParameter[3];

	shadowMat[2] = 0.0 - lightPos[2] * planeParameter[0];
	shadowMat[6] = 0.0 - lightPos[2] * planeParameter[1];
	shadowMat[10] = dot - lightPos[2] * planeParameter[2];
	shadowMat[14] = 0.0 - lightPos[2] * planeParameter[3];

	shadowMat[3] = 0.0 - lightPos[3] * planeParameter[0];
	shadowMat[7] = 0.0 - lightPos[3] * planeParameter[1];
	shadowMat[11] = 0.0 - lightPos[3] * planeParameter[2];
	shadowMat[15] = dot - lightPos[3] * planeParameter[3];

}


//Ax+By+Cz+D=0, (A, B, C) is the normal vector
void calculatePlane(GLfloat planeParameter[4], const GLfloat p0[3], const GLfloat p1[3], const GLfloat p2[3])
{
	GLfloat vec0[3], vec1[3];

	vec0[0] = p1[0] - p0[0];
	vec0[1] = p1[1] - p0[1];
	vec0[2] = p1[2] - p0[2];

	vec1[0] = p2[0] - p0[0];
	vec1[1] = p2[1] - p0[1];
	vec1[2] = p2[2] - p0[2];

	//cross product
	planeParameter[0] = vec0[1] * vec1[2] - vec0[2] * vec1[1];
	planeParameter[1] = vec0[2] * vec1[0] - vec0[0] * vec1[2];
	planeParameter[2] = vec0[0] * vec1[1] - vec0[1] * vec1[0];

	//normalize
	GLfloat len = sqrt(planeParameter[0] * planeParameter[0]
	+ planeParameter[1] * planeParameter[1]
	+ planeParameter[2] * planeParameter[2]);

	if (len != 0)
	{
		planeParameter[0] /= len;
		planeParameter[1] /= len;
		planeParameter[2] /= len;
	}
	else
	{
		planeParameter[0] = 1.0f;
		planeParameter[1] = 0.0f;
		planeParameter[2] = 0.0f;
	}

	planeParameter[3] = -(planeParameter[0] * p0[0] + planeParameter[1] * p0[1] + planeParameter[2] * p0[2]);

}

 

 

4、效果

 


      

5、优缺点

优势:易实现,跨平台

缺点:(1)投影到曲面上很难处理

            (2)阴影的颜色不好控制


6、参考资料

http://excelsior.cs.ucsb.edu/courses/cs180/discussion/Shadows.pdf

http://www.cse.ohio-state.edu/~whmin/courses/cse5542-2013-spring/19-shadow.pdf

http://www.ia.hiof.no/~borres/cgraph/explain/shadow/p-shadow.html

http://math.stackexchange.com/questions/320527/projecting-a-point-on-a-plane-through-a-matrix

 

相关文章:

  • STM32学习笔记(5):通用定时器PWM输出
  • 产品经理如何在技术人员面前更有说服力?
  • PHP autoload机制详解
  • linux系统编程之文件与IO:文件描述符、open,close
  • Knockout 新版应用开发教程之创建view models与监控属性
  • 将不确定变为确定~DateTime.MinValue和MaxValue引发的异常
  • java文件操作源码
  • linux,windows 修改 网卡MTU 值
  • 测试程序运行耗时
  • [置顶] 使用严苛模式打破Android4.0以上平台应用中UI主线程的“独断专行”
  • 基于linux和虚拟化的禅道管理操作系统1.0发布了!
  • DataUml Design 教程2-实体建模
  • Spring3整合Hibernate4-我们到底能走多远系列(30)
  • 【连载】《linux入门很简单》电子版——作者:刘金鹏(1.4G大叔)
  • 为uBoot添加命令自动补全功能
  • DOM的那些事
  • egg(89)--egg之redis的发布和订阅
  • Java面向对象及其三大特征
  • PHP面试之三:MySQL数据库
  • 关于for循环的简单归纳
  • 模型微调
  • 如何优雅地使用 Sublime Text
  • - 语言经验 - 《c++的高性能内存管理库tcmalloc和jemalloc》
  • 这几个编码小技巧将令你 PHP 代码更加简洁
  • 智能合约开发环境搭建及Hello World合约
  • 蚂蚁金服CTO程立:真正的技术革命才刚刚开始
  • 容器镜像
  • 数据可视化之下发图实践
  • ​业务双活的数据切换思路设计(下)
  • # .NET Framework中使用命名管道进行进程间通信
  • #if #elif #endif
  • #include<初见C语言之指针(5)>
  • #设计模式#4.6 Flyweight(享元) 对象结构型模式
  • #使用清华镜像源 安装/更新 指定版本tensorflow
  • (14)学习笔记:动手深度学习(Pytorch神经网络基础)
  • (ZT)北大教授朱青生给学生的一封信:大学,更是一个科学的保证
  • (翻译)Entity Framework技巧系列之七 - Tip 26 – 28
  • (附源码)apringboot计算机专业大学生就业指南 毕业设计061355
  • (附源码)spring boot北京冬奥会志愿者报名系统 毕业设计 150947
  • (转)微软牛津计划介绍——屌爆了的自然数据处理解决方案(人脸/语音识别,计算机视觉与语言理解)...
  • .NET 4 并行(多核)“.NET研究”编程系列之二 从Task开始
  • .NET 反射的使用
  • .NET 实现 NTFS 文件系统的硬链接 mklink /J(Junction)
  • .NET/C# 使窗口永不激活(No Activate 永不获得焦点)
  • .NET/C# 在代码中测量代码执行耗时的建议(比较系统性能计数器和系统时间)
  • .NET连接MongoDB数据库实例教程
  • @Autowired @Resource @Qualifier的区别
  • @Not - Empty-Null-Blank
  • @SuppressWarnings(unchecked)代码的作用
  • [@Controller]4 详解@ModelAttribute
  • [20180312]进程管理其中的SQL Server进程占用内存远远大于SQL server内部统计出来的内存...
  • [ASP.NET 控件实作 Day7] 设定工具箱的控件图标
  • [BUUCTF]-PWN:[极客大挑战 2019]Not Bad解析
  • [C++]:for循环for(int num : nums)
  • [element-ui] el-dialog 中的内容没有预先加载,因此无法获得内部元素的ref 的解决方案