Games202作业1

本文详细介绍了在GAMES202课程中如何基于ShadowMap实现硬阴影和PCF、PCSS软阴影,包括模型加载、光源MVP矩阵计算、ShadowMap的使用与优化,以及PCSS的原理和性能挑战。

Games202课程的作业一,内容是基于ShadowMap实现硬阴影和PCF、PCSS的软阴影。

一、作业框架

作业框架与作业0基本相同,可以参考GAMES202 作业1框架代码结构分析 - 知乎 (zhihu.com)这篇文章,个人觉得非常详细,当然,框架其实并不复杂,花点时间就能搞懂。下面主要说一下需要注意的几点:

  1. 模型加载不出来,与作业0的问题相同,解决方法可参考我的上一篇博客Games202作业0及优化部分-优快云博客
  2. WebGL中的矩阵所采用的是列优先存储,这是其与大多数图形API不同的地方,在做矩阵操作需要注意,否则会得到意想不到的结果
  3. ShadowMap的存储采用的是RGBA四个通道,虽然每个通道都是一个float,但只有一个字节有效,也就是每个通道相当于只有一个字节,每个通道分别存储了深度值(float)的一个字节的精度,所以精度仍然不变,为32bit。将深度值拆解为颜色向量的pack函数位于shadowFragment.glsl中,pack函数采用了一系列位运算操作提取深度值的第 1 2 3 4 个字节并以vec4的形式返回,实现如下:
    // pack函数用于将深度值的浮点数按照字节分别存储在RGBA中
    vec4 pack (float depth) {
        // 使用rgba 4字节共32位来存储z值,1个字节精度为1/256
        const vec4 bitShift = vec4(1.0, 256.0, 256.0 * 256.0, 256.0 * 256.0 * 256.0);
        const vec4 bitMask = vec4(1.0/256.0, 1.0/256.0, 1.0/256.0, 0.0);
        // gl_FragCoord:片元的坐标,fract():返回数值的小数部分
        vec4 rgbaDepth = fract(depth * bitShift);
        rgbaDepth -= rgbaDepth.gbaa * bitMask; // 分别提取第1234个字节的内容, 并存储在RGBA的第一个字节中
        return rgbaDepth;
    }

    相对应的unpack函数位于phongFragment.glsl中,实现如下:

    float unpack(vec4 rgbaDepth) {
        const vec4 bitShift = vec4(1.0, 1.0/256.0, 1.0/(256.0*256.0), 1.0/(256.0*256.0*256.0));
        return dot(rgbaDepth, bitShift);
    }

    其原理也就不难理解了。

二、ShadowMapping实现

ShadowMap采用经典的two-pass方法实现,即先从光源出发对场景做一次模拟渲染,将得到的深度缓冲保存在阴影贴图中,然后再从相机出发进行渲染,在渲染时比较片元在light space下的深度与阴影贴图中的深度,从而判断该片元是否应该渲染为阴影。对于shadow acne现象,通过添加一个偏置进行缓解。

1.实现光源的MVP矩阵

在DirectionalLight.js中完善CalcLightMVP函数:


                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值