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

opengl 教程(24) shadow mapping (2)

 
 
原帖地址:http://ogldev.atspace.co.uk/www/tutorial24/tutorial24.html

 

     本篇教程中,我们通过shadowmap来实现阴影渲染。
             
       我们知道shadow mapping是一个两趟渲染技术,在第一趟渲染过程中,光源位置作为视点,下面我们回顾一下第一趟渲染时候,顶点的z分量是如何变化的。
  1. 局部坐标空间中的顶点位置被传入vertex shader。
  2. 在vertex shader中,局部坐标的顶点值被转化为clip空间表示的顶点值。
  3. 执行透视除法,顶点被转化到归一化的clip空间,这个空间中x,y,z值的范围都是[-1,1],这个范围之外的顶点值都被clip掉。
  4. 光栅化时候映射x,y值到屏幕空间坐标系。(例如: 800x600, 1024x768, etc)。
  5. 光栅化阶段在屏幕空间中对三角形的顶点进行差值,得到该三角形覆盖的每个像素的x,y值。顶点的z值(仍在[-1,1]范围内)也被差值,结果放在深度缓冲中。
  6. 由于第一趟渲染中,禁止颜色写,所以fs(PS)不会被执行,但深度测试仍会进行,深度buffer也会更新。

在第二趟渲染中,视点在摄像机的位置,所以我们会得到一个不同的深度缓冲。两个缓冲都是需要的,一个用来保证物体渲染顺序,一个用来判断顶点是否在阴影内。 我们可以通过在第二趟渲染的vertex shader中传入两个WVP矩阵来做到这个。

  1. 内建的 gl_Position是摄像机WVP矩阵转化后得到的顶点位置。
  2. 另一个传输到下一个阶段的向量则是光源位置WVP矩阵转化后的顶点值。

向量gl_Position用作通常的渲染,另一个向量在光栅化阶段也被差值,每个fragment也有自己相应的值。 该向量的z值即为光源到该点的距离。该z值可以和shadow map中的深度值比较,决定该fragment是否在阴影内。

 

  1. 硬件会自动对gl_Position进行透视除法,但是对于我们传入的第二个向量,我们必须在fs(ps)中手工进行透视除法,以便把该向量转化为归一化clip空间中。
  2. 把[-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函数用来计算阴影因子。

相关文章:

  • jsp:include标签
  • Xcode7升级之后插件无法使用与不小心点击Skipbundle的解决办法
  • jsp:forward标签
  • jsp:include标签与include指令的区别
  • Xhprof php性能测试工具用法小结
  • jsp:forward标签与response.sendRedirect()的区别
  • linux 配置IP地址
  • Jsp中的request对象
  • curl使用
  • Jsp中的session对象
  • Jsp中的application对象
  • 3.5 Templates -- Binding Element Attributes(绑定元素属性)
  • Sequential projection learning for hashing阅读笔记
  • Jsp中的response对象
  • Jsp中的Cookie对象
  • .pyc 想到的一些问题
  • 《用数据讲故事》作者Cole N. Knaflic:消除一切无效的图表
  • 【108天】Java——《Head First Java》笔记(第1-4章)
  • co.js - 让异步代码同步化
  • iOS仿今日头条、壁纸应用、筛选分类、三方微博、颜色填充等源码
  • Javascript Math对象和Date对象常用方法详解
  • JavaScript-Array类型
  • java架构面试锦集:开源框架+并发+数据结构+大企必备面试题
  • js如何打印object对象
  • nginx 配置多 域名 + 多 https
  • React as a UI Runtime(五、列表)
  • supervisor 永不挂掉的进程 安装以及使用
  • TypeScript实现数据结构(一)栈,队列,链表
  • vue-router的history模式发布配置
  • vue学习系列(二)vue-cli
  • Webpack入门之遇到的那些坑,系列示例Demo
  • 阿里研究院入选中国企业智库系统影响力榜
  • 给新手的新浪微博 SDK 集成教程【一】
  • 基于Mobx的多页面小程序的全局共享状态管理实践
  • 前端每日实战:61# 视频演示如何用纯 CSS 创作一只咖啡壶
  • 前端面试之闭包
  • 前端相关框架总和
  • 前端性能优化——回流与重绘
  • 我看到的前端
  • 云大使推广中的常见热门问题
  • #100天计划# 2013年9月29日
  • #控制台大学课堂点名问题_课堂随机点名
  • #设计模式#4.6 Flyweight(享元) 对象结构型模式
  • #中的引用型是什么意识_Java中四种引用有什么区别以及应用场景
  • ( )的作用是将计算机中的信息传送给用户,计算机应用基础 吉大15春学期《计算机应用基础》在线作业二及答案...
  • (PHP)设置修改 Apache 文件根目录 (Document Root)(转帖)
  • (八)光盘的挂载与解挂、挂载CentOS镜像、rpm安装软件详细学习笔记
  • (附源码)springboot 基于HTML5的个人网页的网站设计与实现 毕业设计 031623
  • (附源码)ssm基于web技术的医务志愿者管理系统 毕业设计 100910
  • (十六)一篇文章学会Java的常用API
  • (十一)手动添加用户和文件的特殊权限
  • (一)RocketMQ初步认识
  • (一)基于IDEA的JAVA基础12
  • (转) Android中ViewStub组件使用
  • . Flume面试题