opengl 教程(24) shadow mapping (2)
原帖地址:http://ogldev.atspace.co.uk/www/tutorial24/tutorial24.html
本篇教程中,我们通过shadowmap来实现阴影渲染。
我们知道shadow mapping是一个两趟渲染技术,在第一趟渲染过程中,光源位置作为视点,下面我们回顾一下第一趟渲染时候,顶点的z分量是如何变化的。
- 局部坐标空间中的顶点位置被传入vertex shader。
- 在vertex shader中,局部坐标的顶点值被转化为clip空间表示的顶点值。
- 执行透视除法,顶点被转化到归一化的clip空间,这个空间中x,y,z值的范围都是[-1,1],这个范围之外的顶点值都被clip掉。
- 光栅化时候映射x,y值到屏幕空间坐标系。(例如: 800x600, 1024x768, etc)。
- 光栅化阶段在屏幕空间中对三角形的顶点进行差值,得到该三角形覆盖的每个像素的x,y值。顶点的z值(仍在[-1,1]范围内)也被差值,结果放在深度缓冲中。
- 由于第一趟渲染中,禁止颜色写,所以fs(PS)不会被执行,但深度测试仍会进行,深度buffer也会更新。
在第二趟渲染中,视点在摄像机的位置,所以我们会得到一个不同的深度缓冲。两个缓冲都是需要的,一个用来保证物体渲染顺序,一个用来判断顶点是否在阴影内。 我们可以通过在第二趟渲染的vertex shader中传入两个WVP矩阵来做到这个。
- 内建的 gl_Position是摄像机WVP矩阵转化后得到的顶点位置。
- 另一个传输到下一个阶段的向量则是光源位置WVP矩阵转化后的顶点值。
向量gl_Position用作通常的渲染,另一个向量在光栅化阶段也被差值,每个fragment也有自己相应的值。 该向量的z值即为光源到该点的距离。该z值可以和shadow map中的深度值比较,决定该fragment是否在阴影内。
- 硬件会自动对gl_Position进行透视除法,但是对于我们传入的第二个向量,我们必须在fs(ps)中手工进行透视除法,以便把该向量转化为归一化clip空间中。
- 把[-1,1]范围的x,y坐标转为到[0,1]范围,以便能够作为纹理坐标,来采样shadow map值。
- u = 0.5 * X + 0.5
- v = 0.5 * Y + 0.5
源码:
lighting_technique.h
class LightingTechnique : public Technique {
public:
...
void SetLightWVP(const Matrix4f& LightWVP);
void SetShadowMapTextureUnit(unsigned int TextureUnit);
...
private:
GLuint m_LightWVPLocation;
GLuint m_shadowMapLocation;
...
增加一个新的属性,用来表示光源位置作为视点的WVP矩阵。我们用texture unit 0表示通常的纹理,texture unit 1表示shadow map。
lighting.vs
#version 400
layout (location = 0) in vec3 Position;
layout (location = 1) in vec2 TexCoord;
layout (location = 2) in vec3 Normal;
uniform mat4 gWVP;
uniform mat4 gLightWVP;
uniform mat4 gWorld;
out vec4 LightSpacePos;
out vec2 TexCoord0;
out vec3 Normal0;
out vec3 WorldPos0;
void main()
{
gl_Position = gWVP * vec4(Position, 1.0);
LightSpacePos = gLightWVP * vec4(Position, 1.0);
TexCoord0 = TexCoord;
Normal0 = (gWorld * vec4(Normal, 0.0)).xyz;
WorldPos0 = (gWorld * vec4(Position, 1.0)).xyz;
}
lighting.fs:58
float CalcShadowFactor(vec4 LightSpacePos)
{
vec3 ProjCoords = LightSpacePos.xyz / LightSpacePos.w;
vec2 UVCoords;
UVCoords.x = 0.5 * ProjCoords.x + 0.5;
UVCoords.y = 0.5 * ProjCoords.y + 0.5;
float z = 0.5 * ProjCoords.z + 0.5;
float Depth = texture(gShadowMap, UVCoords).x;
if (Depth < (z + 0.00001))
return 0.5;
else
return 1.0;
}
上面这个shader函数用来计算阴影因子。
opengl 教程(24) shadow mapping (2)的更多相关文章
- OpenGL 阴影之Shadow Mapping和Shadow Volumes
先说下开发环境.VS2013,C++空项目,引用glut,glew.glut包含基本窗口操作,免去我们自己新建win32窗口一些操作.glew使我们能使用最新opengl的API,因winodw本身只 ...
- OpenGL阴影,Shadow Mapping(附源程序)
实验平台:Win7,VS2010 先上结果截图(文章最后下载程序,解压后直接运行BIN文件夹下的EXE程序): 本文描述图形学的两个最常用的阴影技术之一,Shadow Mapping方法(另一种是Sh ...
- OpenGL核心技术之Shadow Mapping改进版
笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者;已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D实战核心技术详解 ...
- OpenGL核心技术之Shadow Mapping
笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,国家专利发明人;已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D ...
- OpenGL阴影,Shadow Volumes(附源程序,使用 VCGlib )
实验平台:Win7,VS2010 先上结果截图: 本文是我前一篇博客:OpenGL阴影,Shadow Mapping(附源程序)的下篇,描述两个最常用的阴影技术中的第二个,Shadow Volu ...
- Tutorial - Deferred Rendering Shadow Mapping 转
http://www.codinglabs.net/tutorial_opengl_deferred_rendering_shadow_mapping.aspx Tutorial - Deferred ...
- NeHe OpenGL教程 第四十六课:全屏反走样
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- NeHe OpenGL教程 第三十五课:播放AVI
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- NeHe OpenGL教程 第三十二课:拾取游戏
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
随机推荐
- Ubuntu美化及配置,常见问题解决方案
安装符合审美观,并且具有可用性的Ubuntu桌面,需要耗费一些时间与精力不过,相信我,这值得去做,你会享受这中间的过程,以及最后的成果 首先,我推荐安装的软件列表如下,在安装前,需要先执行以下的步骤: ...
- Servlet接口、GenericServlet类、HttpServlet类
Servlet是最顶层的接口,其提供的方法有: init(ServletConfig config):void // 初始化 getServletConfig():ServletConfig // 取 ...
- CodeForces700E Cool Slogans
感谢dalaoWJZ的讲解. 我们对于每一个串a[i]相当于在他parent的right集合里找一个出现位置在id-len[x]+len[parent]到id[x]-1区间的 用主席树判存在性即可. ...
- 【HDU5909】Tree Cutting(FWT)
[HDU5909]Tree Cutting(FWT) 题面 vjudge 题目大意: 给你一棵\(n\)个节点的树,每个节点都有一个小于\(m\)的权值 定义一棵子树的权值为所有节点的异或和,问权值为 ...
- 【tarjan+SPFA】BZOJ1179-[Apio2009]Atm
[题目大意] 给出一张有点权的有向图,已知起点和可以作为终点的一些点,问由起点出发,每条边和每个点可以经过任意多次,经过点的权值总和最大为多少. [思路] 由于可以走任意多次,显然强连通分量可以缩点. ...
- @Transactional导致AbstractRoutingDataSource动态数据源无法切换的解决办法
上午花了大半天排查一个多数据源主从切换的问题,记录一下: 背景: 项目的数据库采用了读写分离多数据源,采用AOP进行拦截,利用ThreadLocal及AbstractRoutingDataSource ...
- Polly简介 — 3. 执行策略
执行策略 执行策略的常见方式是调用策略的Execute函数 var policy = Policy.Handle<TimeoutException>().Retry();policy.Ex ...
- TIMER门控模式控制PWM输出长度
TIMER门控模式控制PWM输出长度 参照一些网友代码做了些修改,由TIM4来控制TIM2的PWM输出长度, 采用主从的门控模式,即TIM4输出高时候TIM2使能输出 //TIM2 PWM输出,由TI ...
- IAR EWARM Checksum Technical Note
IELFTOOL Checksum - Basic actions EW targets: ARM, RH850, RX, SH, STM8 EW component: General issues ...
- 《Go学习笔记 . 雨痕》类型
一.基本类型 清晰完备的预定义基础类型,使得开发跨平台应用时无须过多考虑符合和长度差异. 类型 长度 默认值 说明 bool 1 false byte 1 0 uint8 int, uint 4, ...