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

GAMES202-高质量实时渲染(homework1)

目录

  • Homework1
    • shadow Map
    • PCF(Percentage Closer Filter)
    • PCSS(Percentage Closer Soft Shadow)

GitHub主页:https://github.com/sdpyy1
作业实现:https://github.com/sdpyy1/CppLearn/tree/main/games202

Homework1

shadow Map

首先需要完成MVP矩阵的构造,在这里的mvp用来表示如果一个模型在shadowmap视角下的位置

    CalcLightMVP(translate, scale) {let lightMVP = mat4.create();let modelMatrix = mat4.create();let viewMatrix = mat4.create();let projectionMatrix = mat4.create();// Model transformmat4.translate(modelMatrix,modelMatrix,translate);mat4.scale(modelMatrix,modelMatrix,scale);// View transformmat4.lookAt(viewMatrix, this.lightPos, this.focalPoint, this.lightUp);// Projection transformmat4.ortho(projectionMatrix, -100,100,-100,100,0.1,400); // 实测far要得400可以覆盖到整个平面mat4.multiply(lightMVP, projectionMatrix, viewMatrix);mat4.multiply(lightMVP, lightMVP, modelMatrix);return lightMVP;}

他在顶点着色器中使用,目的是传递每个顶点位置在光源视角下坐标 vPositionFromLight = uLightMVP * vec4(aVertexPosition, 1.0);
在片段着色器中,先实现比较的函数

float useShadowMap(sampler2D shadowMap, vec4 shadowCoord){// shadowmap中存储的深度float lightDepth = unpack(texture2D(shadowMap, shadowCoord.xy));// 着色点深度float shadowDepth = shadowCoord.z;float visibility = 1.0;// 被挡住了if (shadowDepth > lightDepth) {visibility = 0.0;}return visibility;
}

在主函数中,需要先对光源坐标处理一下,因为它是经过透视投影处理后的NDC坐标,而shadowMap上取值其实需要的是UV坐标(0,1)之间,所以需要先转到[0,1]之间
⚠️:透视除法在透视投影时才需要,我看别的博客都写了,其实是不需要的

  float visibility = 1.0;// 透视投影时才需要// vec3 shadowCoord = vPositionFromLight.xyz / vPositionFromLight.w;vec3 shadowCoord = (vPositionFromLight.xyz+1.0)/2.0;visibility = useShadowMap(uShadowMap, vec4(shadowCoord, 1.0));

请添加图片描述
居然没出现自阴影问题,我们手动创建一个,首先光源位置修改在engine.js中lightPos

	// Add lights// light - is open shadow map == truelet lightPos = [0, 90, 80];let focalPoint = [0, 0, 0];let lightUp = [0, 1, 0]const directionLight = new DirectionalLight(5000, [1, 1, 1], lightPos, focalPoint, lightUp, true, renderer.gl);renderer.addLight(directionLight);

把光源变斜一点,就会发现场景从远到近逐渐出现自阴影现象
y = 40
请添加图片描述
y=30请添加图片描述
y=20
请添加图片描述
y=10这时候整个地板都出错了
请添加图片描述
加一个自偏移,就解决了

  if (shadowDepth  > lightDepth + 0.01) {visibility = 0.0;}

请添加图片描述
下面是偏移量改为0.05的效果,效果就太差了,偏移量应该根据光照的角度动态调整
请添加图片描述

走样的情况,下面就用PCF来解决~
请添加图片描述

PCF(Percentage Closer Filter)

简单理解就是不只判断shadowmap的一个位置,而是一圈位置的平均。
作业中提供了两种采样,它的作用就是减少计算量,没必要真的一个一个便利来取均值,偏移记录在了vec2 poissonDisk[NUM_SAMPLES];
下面是我的实现

float PCF(sampler2D shadowMap, vec4 coords) {poissonDiskSamples(coords.xy);// 采样数float numSamples = 0.0;// 没有遮挡的采样数float numUnBlock = 0.0;// 过滤核大小float filterSize = 5.0;float mapSize = 2048.0;// 过滤核范围float filterRange = filterSize / mapSize;for(int i = 0;i<NUM_SAMPLES;i++){vec2 samplexCoor = coords.xy + poissonDisk[i] * filterRange;// 采样时可能会越界if(samplexCoor.x > 0.0 && samplexCoor.x < 1.0 && samplexCoor.y > 0.0 && samplexCoor.y < 1.0) {numSamples++;if(useShadowMap(shadowMap,vec4(samplexCoor,coords.z,1.0)) == 1.0) {numUnBlock++;}}}return numUnBlock/numSamples;
}

锯齿位置的变化(过滤核大小为5)
请添加图片描述
当改为20时
请添加图片描述
改为100时,出现了大量噪点
请添加图片描述

PCSS(Percentage Closer Soft Shadow)

用PCF来做软阴影,一句话来说就是动态修改过滤核的尺寸,达到不同的因子区域不同的软硬程度

第一步需要在一定范围内搜索深度比着色点进的点,从而得到一个平均深度

float findBlocker( sampler2D shadowMap,  vec2 uv, float zReceiver ) {int numSamples = 0;float sumDepth = 0.0;float searchSize = 15.0;float mapSize = 2048.0;float searchRange = searchSize / mapSize;for( int i = 0; i < BLOCKER_SEARCH_NUM_SAMPLES; i ++ ) {vec2 sampleCoor = uv + poissonDisk[i] * searchRange;// 采样时可能会越界if(sampleCoor.x > 0.0 && sampleCoor.x < 1.0 && sampleCoor.y > 0.0 && sampleCoor.y < 1.0) {float depth = unpack(texture2D(shadowMap, sampleCoor));if(depth < zReceiver) {sumDepth += depth;numSamples++;}}}if(numSamples > 0) {return sumDepth / float(numSamples);} else {return zReceiver;}
}

下来就计算半影尺寸并把它作为过滤核尺寸来进行PCF

float PCSS(sampler2D shadowMap, vec4 coords){uniformDiskSamples(coords.xy);// STEP 1: avgblocker depthfloat avgBlockerDepth = findBlocker(shadowMap, coords.xy, coords.z);// STEP 2: penumbra size// 假设光源尺寸为50float Wlight = 50.0;float penumbraSize = (coords.z - avgBlockerDepth) * Wlight / avgBlockerDepth;// STEP 3: filtering// 把半影尺寸当做过滤核大小return PCF(shadowMap, coords,penumbraSize);
}

光源尺寸越大,阴影软硬区分程度越大,因为计算出的过滤核尺寸区分度越大
Wlight = 50
请添加图片描述
Wlight = 100
请添加图片描述
设置过小时,反而看不出什么效果
请添加图片描述

相关文章:

  • Web前端开发:CSS Float(浮动)与 Positioning(定位)
  • Pydantic :基于 Python 类型注解(type hints)的数据验证和数据解析库
  • 《电商业务分析终极框架:从数据到决策的标准化路径》
  • cuda学习2:cuda编程基本概念
  • LeetCode12_整数转罗马数字
  • 人机鉴权和机机鉴权
  • 【算法应用】基于灰狼算法求解DV-Hop定位问题
  • 面试:结构体默认是对齐的嘛?如何禁止对齐?
  • 【每日随笔】文化属性 ① ( 天机 | 强势文化与弱势文化 | 文化属性的形成与改变 | 强势文化 具备的特点 )
  • 利用脚本搭建私有云平台,部署云平台,发布云主机并实现互连和远程连接
  • AI发展史
  • MySQL索引优化与实战 - Java架构师面试解析
  • springboot logback 默认加载配置文件顺序
  • 构建事件驱动的云原生后端系统 —— 从设计到实践
  • ecovadis认证评估标准?ecovadis审核目的?
  • 教育培训平台源码选型避坑指南:如何避免二次开发的高成本?
  • JavaScript基础(七)之web APIs
  • 基于Qt5的蓝牙打印开发实战:从扫描到小票打印的全流程
  • 20.压敏电阻的特性与使用注意事项
  • 【Git】初始Git及入门命令行
  • 杭州6宗涉宅用地收金125.76亿元,萧山区地块楼面价冲破5万元/平米
  • 瞄准“美丽健康”赛道,上海奉贤如何打造宜居宜业之城?
  • 上海质子重离子医院已收治8000例患者,基本覆盖国内常见恶性肿瘤
  • 加拿大温哥华一车辆冲撞人群,造成多人伤亡
  • 106岁东江纵队老战士、四川省侨联名誉主席邱林逝世
  • 伊朗港口爆炸已造成281人受伤