OpenGL 影子彼得潘

2024-01-23

我通过执行两个绘制通道(一个到深度图,一个到普通帧缓冲区)向 OpenGL 中的场景添加阴影。

使用深度图时不使用偏置,会出现很多阴影痘痘。

这是通过在深度图检查中添加偏差来解决的。

然而,当光线移动到不同的角度时,这会导致阴影与物体“分离”。

我相信这种效应称为彼得平移,是由不同角度使用较大偏差引起的。

通常的解决办法似乎是在绘制阴影贴图时剔除背面的三角形,但是由于地板平面是 2D 对象,我不相信这会正常工作。

我使用的实际地形是按程序生成的,因此创建它的 3D 版本并不像这个简单示例中那样简单。

如何将彼得平移固定在像这样的 2D 对象上?


顶点着色器

#version 400

layout(location = 0) in vec3 position;
layout(location = 1) in vec3 normal;
layout(location = 2) in vec2 texture_coords;

out VS_OUT {
    vec4 position;
    vec3 normal;
    vec2 texture_coords;
    vec4 shadow_position;
} vs_out;

uniform mat4 model;
uniform mat4 model_view;
uniform mat4 model_view_perspective;
uniform mat3 normal_matrix;
uniform mat4 depth_matrix;

void main() {
    vec4 position_v4 = vec4(position, 1.0);

    vs_out.position = model_view * position_v4;
    vs_out.normal = normal_matrix * normal;
    vs_out.texture_coords = texture_coords;
    vs_out.shadow_position = depth_matrix * model * position_v4;

    gl_Position = model_view_perspective * position_v4;
}

片段着色器

#version 400

in VS_OUT {
    vec4 position;
    vec3 normal;
    vec2 texture_coords;
    vec4 shadow_position;
} fs_in;

out vec4 colour;

uniform mat4 view;
uniform mat4 model_view_perspective;
uniform vec3 light_position;
uniform vec3 emissive_light;
uniform float shininess;
uniform int textured;
uniform sampler2D tex;
uniform sampler2DShadow shadow_texture;

void main() {
    const vec3 specular_albedo = vec3(1.0, 0.8, 0.6);

    colour = vec4(0.8, 0.8, 0.8, 0.8);
    if(textured != 0) {
        colour = texture(tex, fs_in.texture_coords);
    }

    vec3 light_direction = normalize(light_position);
    vec3 normal = normalize(fs_in.normal);

    float visibility = 1.0;
    if(fs_in.shadow_position.z <= 1.0) {
        float bias = max(0.05 * (1.0 - dot(normal, light_direction)), 0.005);
        if(fs_in.shadow_position.z > texture(shadow_texture, fs_in.shadow_position.xyz, 0.0) + bias){
            visibility = 0.0;
        }
    }

    /* Ambient */
    vec3 ambient = colour.xyz * 0.1;

    /* Diffuse */
    vec3 diffuse = visibility * (clamp(dot(normal, light_direction), 0, 1) * colour.xyz);

    /* Specular */
    vec3 specular = vec3(0.0);
    if(dot(normal, light_direction) > 0) {
        vec3 V = normalize(-fs_in.position.xyz);
        vec3 half_dir = normalize(light_direction + V);
        specular = visibility * (pow(max(dot(normal, half_dir), 0.0), shininess) * specular_albedo.xyz);
    }

    colour = vec4(((ambient + diffuse) * colour.xyz) + specular + emissive_light, 1.0);
}

https://msdn.microsoft.com/en-us/library/windows/desktop/ee416324(v=vs.85).aspx https://msdn.microsoft.com/en-us/library/windows/desktop/ee416324(v=vs.85).aspx

计算紧近平面和远平面也有助于避免 Peter Panning。

斜率-尺度深度偏差

如前所述,自阴影可能会导致阴影痤疮。 添加太多偏见可能会导致彼得潘宁。此外, 具有陡坡(相对于光)的多边形受到的影响更大 投影锯齿比具有浅斜率的多边形(相对于 光)。因此,每个深度图值可能需要不同的 偏移量取决于多边形相对于光线的斜率。

Direct3D 10+ 硬件能够根据多边形的情况来偏置多边形 相对于观察方向的斜率。这有以下效果 对从侧面观察光线的多边形应用大偏差 方向,但不对面向光的多边形施加任何偏差 直接地。图 10 说明了两个相邻像素如何 测试时在阴影和无阴影之间交替 相同的无偏斜率。

问题是确定阴影中每个深度的最佳偏移 地图。如果应用的偏移量不够,深度冲突仍然会存在。 如果你应用非常大的偏移量,那么彼得·潘宁将变成 显。偏移量应取决于阴影贴图的精度,并且 在表面相对于光源方向的斜率上。

OpenGL 可以自动计算并添加偏移量到以下值: 存储在 Z 缓冲区中。您可以使用 glPolygonOffset 设置偏移量 功能。有两个参数可用: 偏移乘数 取决于表面的坡度,以及决定量的值 额外的最小可能偏移(取决于阴影的格式 地图):

https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glPolygonOffset.xhtml https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glPolygonOffset.xhtml

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

OpenGL 影子彼得潘 的相关文章

  • 更新面板工作速度非常慢

    我正在编写一个用户可以注册的应用程序 注册时 可以选择多个选项 并根据这些注册字段可见或不可见以及是否必需 我想出了一个想法 所有字段都将位于 updatePanel 中 当用户更改注册选项时 我将在服务器端设置这些字段的可见性 它可以工作
  • 使用 CMake 时如何导出 Emscripten 中的 C 函数

    In 本教程 https emscripten org docs porting connecting cpp and javascript Interacting with code html interacting with code
  • Grpc - 将消息从一个客户端发送到连接到同一服务器的另一个客户端

    是否可以将消息从一个客户端发送到连接到同一服务器的另一个客户端 我想将数据从一个客户端发送到服务器然后发送到特定客户端 我想我需要获取客户端 ID 但我不知道如何获取此 ID 以及如何从服务器将此消息发送到该客户端 我这里有一个样本 这是一
  • 从复选框列表中选择循环生成的复选框中的一个复选框

    抱歉我的英语不好 在我的 ASP NET 网站上 我从 SQL 表导入软件列表 看起来像这样 但实际上要长得多 Microsoft Application Error Reporting br br Microsoft Applicatio
  • 无法注册时间触发的后台任务

    对于 Windows 8 应用程序 在 C Xaml 中 我尝试注册后台任务 很难说 但我想我的后台任务已正确注册 但是当我单击调试位置工具栏上的后台任务名称时 我的应用程序停止工作 没有任何消息 我查看了事件查看器上的日志 得到 具有入口
  • 如何将 .txt 文件中的数据转换为 xml? C#

    我在一个文本文件中有数千行数据 我想通过将其转换为更容易搜索的内容来轻松搜索 我希望 XML 或其他类型的大型数据结构 尽管我不确定它是否是最好的对于我的想法 每行的数据如下所示 第 31 册 托马斯 乔治 32 34 154 每本书都不是
  • 语音识别编程问题入门

    所以 你们可能都看过 钢铁侠 其中托尼与一个名为贾维斯的人工智能系统进行交互 演示剪辑here http www youtube com watch v Go8zsh1Ev6Y 抱歉 这是广告 我非常熟悉 C C 和 Visual Basi
  • C++中判断unicode字符是全角还是半角

    我正在编写一个终端 控制台 应用程序 该应用程序应该包装任意 unicode 文本 终端通常使用等宽 固定宽度 字体 因此要换行文本 只需计算字符数并观察单词是否适合一行并采取相应的操作 问题是 Unicode 表中的全角字符在终端中占用了
  • 如何使用 x64 运行 cl?

    我遇到了和这里同样的问题致命错误 C1034 windows h 未设置包含路径 https stackoverflow com questions 931652 fatal error c1034 windows h no include
  • 不可变类与结构

    以下是类与 C 中的结构的唯一区别 如果我错了 请纠正我 类变量是引用 而结构变量是值 因此在赋值和参数传递中复制结构的整个值 类变量是存储在堆栈上的指针 指向堆上的内存 而结构变量作为值存储在堆上 假设我有一个不可变的结构 该结构的字段一
  • memcpy/memmove 到联合成员,这是否设置“活动”成员?

    重要说明 一些评论者似乎认为我是从工会抄袭的 仔细看memcpy 它从普通旧地址复制uint32 t 它不包含在联合中 另外 我正在复制 通过memcpy 到工会的特定成员 u a16 or u x in a union 不直接到整个联盟本
  • 如何在 C# 中创建异步方法?

    我读过的每一篇博客文章都会告诉您如何在 C 中使用异步方法 但由于某些奇怪的原因 从未解释如何构建您自己的异步方法来使用 所以我现在有这段代码使用我的方法 private async void button1 Click object se
  • 模板类的模板构造函数的 C++ 显式模板特化

    我有一个像这样的课程 template
  • 模板类中的无效数据类型生成编译时错误?

    我正在使用 C 创建一个字符串类 我希望该类仅接受数据类型 char 和 wchar t 并且我希望编译器在编译时使用 error 捕获任何无效数据类型 我不喜欢使用assert 我怎样才能做到这一点 您可以使用静态断言 促进提供一个 ht
  • 使动态创建的链接标签在 Winforms 中可点击

    我正在制作一个程序 允许用户单击由动态链接标签创建的公司名称 在我想知道如何做到这一点之前 我从未在 C 中使用过链接标签 可为特定用户生成的业务数量各不相同 因此每个用户的链接标签数量并不相同 然后我想捕获业务 ID 以进行 Json 调
  • 如何解压 msgpack 文件?

    我正在将 msgpack 编码的数据写入文件 在编写时 我只是使用 C API 的 fbuffer 如 我为示例删除了所有错误处理 FILE fp fopen filename ab msgpack packer pk msgpack pa
  • 在 Win32 控制台应用程序中设置光标位置

    如何在 Win32 控制台应用程序中设置光标位置 最好 我想避免制作句柄并使用 Windows 控制台功能 我花了整个早上沿着那条黑暗的小巷跑 它产生的问题比它解决的问题还要多 我似乎记得当我在大学时使用 stdio 做这件事相对简单 但我
  • 没有“对 *this”功能的右值引用的解决方法

    我有一个围绕可移动对象的代理容器类 并希望代理能够隐式生成对底层对象的右值引用 但仅当代理本身被移动时 我相信我将能够按照提案 n2439 实施此行为 将移动语义扩展到 this http www open std org jtc1 sc2
  • 在 System.Type 上使用条件断点时出错

    这是函数 public void Init System Type Type this Type Type BuildFieldAttributes BuildDataColumns FieldAttributes 我在第一行设置了一个断点
  • 我可以使用 lambda 函数或 std::function 对象来代替函数指针吗?

    我有一个需要使用的库 它定义了以下内容 typedef void CallbackFunction const int i 并且有一个注册回调的函数 如下所示 void registerCallback CallbackFunction p

随机推荐

  • 如何根据现有地图中的值创建新地图

    有下一张原始地图 G1 7 8 45 6 9 G2 3 9 34 2 1 65 G3 6 5 9 1 67 5 其中 G1 G2 和 G3 是人的年龄组 我如何创建这样的新地图 45 7 8 45 6 9 65 3 9 34 2 1 65
  • Matlab 中的动态结构生成

    我有一个字段名称列表 想要生成一个嵌套结构 我试过这个 fn1 a b c fn2 d e f s struct for n1 fn1 for n2 fn2 s n1 n2 0 end end 但 Matlab 抱怨符号 fieldname
  • 在所有数据库的所有对象中查找表名

    我有一个包含多个数据库和客户端应用程序的系统 所有数据库都位于一个 SQL Server 实例中 它们是由不同的人在不同的时间开发的 因此 如果发生某些错误 则很难找到数据在哪个过程或触发器中被修改 现在我使用这个脚本 我在这个网站上找到了
  • 如何将ggplot图标题居中

    在 ggplot 中居中对齐绘图标题的 lege artis 方式 绘图标题 element text hjust 0 5 https stackoverflow com questions 40675778 center plot tit
  • 谷歌人工智能平台与机器学习引擎

    我做了很多搜索 但我不明白它们之间有什么区别google ai platform and ml engine 看起来它们都可以用于训练和部署模型 其他诸如 google cloud automl google ai hub 之类的词也很令人
  • 如何获取R中当前的工作目录?

    如何获取当前工作目录 我想应该有一个像 getcwd 这样的命令 但是 我在文档中找不到类似的命令 如何更改到另一个目录 启动R时如何设置默认工作目录 版本 平台 x86 64 w64 mingw32拱门x86 64操作系统 mingw32
  • 为什么我的代码只使用字符串替换方法替换某些字符?

    对于我的作业 我必须编写代码来编码 解码消息 当我开始发现每当我键入消息时 程序仅替换某些字符时 我已接近尾声 翻译相当简单 要编码 您将 a 更改为字母表中相反的字母 即 z b 到 y c 到 x d 到 w 等 作业如下 该项目涉及编
  • 在 jetpack compose 中使用 LaunchedEffect 与 SideEffect

    大家好 我正在学习项目中的副作用 我想知道我什么时候应该使用LaunchedEffect and SideEffect在什么场景下 我正在添加一些使用这两种效果的代码 如果我在这里做错了 请让我知道 第一次使用 LaunchedEffect
  • Collections.synchronizedlist() 在从末尾迭代时删除元素[重复]

    这个问题在这里已经有答案了 我在用Collections Synchronizedlist 使我的arraylist线程安全 我想问的是以下代码是线程安全的 即在从末尾迭代列表时删除 pendingExecutionList Collect
  • 从 Google Chrome 扩展程序中的通知切换当前选项卡

    我在 Chrome 中遗漏了什么吗选项卡文档 http code google com chrome extensions tabs html或者有没有办法让扩展程序更改当前活动的选项卡 我有一个扩展 一旦选项卡完成加载 就会弹出一个通知
  • 在 BreezeJS 客户端中解析元数据时出现异常

    前传和版本信息 BreezeJS客户端版本 1 5 2 通过设计时 EntityFramework 模型在自定义服务器上生成的元数据 6 1 2 BreezeLabs EdmBuilder 1 0 5 生成元数据时也遇到问题 可以在此处阅读
  • 更改O365邮件服务器后SSRS报告订阅错误

    我们有一个订阅服务 它会向每位顾问发送一封邮件 说明他们未来几周的计划 两周前 我们已从本地邮件服务器更改为 O365 邮件服务器 自从这一变化以来 我注意到一些顾问没有收到他们应该收到的邮件 这让我查看了 RS 日志 两周前我有 6 个人
  • 如何在桌面上的文件夹中创建文本文件

    我的项目有问题 我的桌面上有一个项目文件夹 我想创建一个文本文件并写入包含该文本文件的内容 这是我的代码 ofstream example Users sample Desktop save txt 但我希望它可以在另一台Mac上运行 我不
  • Android:使图库无限循环图像

    我在我的项目中使用一个画廊 其中添加了四个图像 并且我希望它从右侧和左侧都是无限的 我该如何实现这个目标 主要思想是在你的getView方法 你必须使用 position position imagesArray length if pos
  • org.javafxports 有什么区别 » jfxmobile-plugin 1.3.16 和 2.0.30

    org javafxports jfxmobile plugin 1 3 16 和 2 0 30 有什么区别 我尝试将版本 1 3 16 更新到 2 0 30 但无法编译项目 jfxmobile plugin 是一个 gradle 插件 它
  • 如何在Oracle sqlplus中编写for循环?

    我正在尝试在 Oracle sqlplus 接口中编写一个 for 循环 当编写循环语句并按 Enter 键时 出现错误 SQL gt for i in 1 10 loop SP2 0734 unknown command beginnin
  • OmniAuth Facebook 令牌过期错误

    我正在使用 OmniAuth 在我的应用程序中访问 Facebook 我正在使用 fb graph gem https github com nov fb graph https github com nov fb graph发布到 Fac
  • 使用 Imagemagick - PHP 计算 PDF 文件中的页数

    我在用PHP 5 与 Apache in my Windows Vista 电脑 我有Imagemagick已经安装并配置 我想使用以下方法计算 pdf 文件中的总页数imagick 我找到了一个解决方案here https stackov
  • 需要用百分比符号Java替换字符串内的空格

    我需要用 符号替换字符串内的空格 但我遇到了一些问题 我尝试的是 imageUrl imageUrl replace 20 但它在替换功能中给了我一个错误 Then imageUrl imageUrl replace 20 但它仍然在替换功
  • OpenGL 影子彼得潘

    我通过执行两个绘制通道 一个到深度图 一个到普通帧缓冲区 向 OpenGL 中的场景添加阴影 使用深度图时不使用偏置 会出现很多阴影痘痘 这是通过在深度图检查中添加偏差来解决的 然而 当光线移动到不同的角度时 这会导致阴影与物体 分离 我相