将阴影添加到视差遮挡贴图

2024-01-07

我已经通过实现视差遮挡贴图学习OpenGL https://learnopengl.com/Advanced-Lighting/Parallax-Mapping, 现在我想添加自阴影,以便片段挤压在表面上投射阴影。我读过一些关于这个主题的论文,但我承认这对我来说有点先进。据我了解,它与视差遮挡贴图的过程相同,但从光线方向而不是视图方向进行。我尝试修改片段着色器,但阴影仍然不显示。

This is how I want it to look like.enter image description here http://www.cs.utah.edu/~sujin/courses/reports/cs6610/project-report/images/pom.png http://www.cs.utah.edu/~sujin/courses/reports/cs6610/project-report/images/pom.png

This is the result of the modified fragment shader. Nothing changed from when it was just the parallax occlusion map. What I have

这是修改后的片段着色器。我已经标记了添加到原始视差教程代码中的部分。

#version 330 core
in vec2 o_texCoord;
in vec3 o_worldPos;
in vec3 world_normal;
in vec3 world_tangent;

out vec4 fragColor;

uniform vec3 light_pos;
uniform sampler2D diffuseMap;
uniform sampler2D normalMap;
uniform sampler2D heightMap;
uniform vec3 viewPosition;
uniform float heightScale;

vec2 ParallaxMapping (vec2 texCoord, vec3 viewDir)
{
    float minLayers = 0;
    float maxLayers = 32;
    float numLayers = mix(maxLayers, minLayers, abs(dot(vec3(0.0, 0.0, 1.0), viewDir)));
    float layerDepth = 1.0 / numLayers;

    float currentLayerDepth = 0;

    vec2 P = viewDir.xy / viewDir.z * heightScale;

    vec2 deltaTexCoords = P / numLayers;

    vec2 currentTexCoords = texCoord;

    float currentDepthMapValue = texture(heightMap, currentTexCoords).r;

    while (currentLayerDepth < currentDepthMapValue)
    {
        currentTexCoords -= deltaTexCoords;
        currentDepthMapValue = texture(heightMap, currentTexCoords).r;
        currentLayerDepth += layerDepth;
    }

    vec2 prevTexCoords = currentTexCoords + deltaTexCoords;
    float afterDepth = currentDepthMapValue - currentLayerDepth;
    float beforeDepth = texture(heightMap, prevTexCoords).r - currentLayerDepth + layerDepth;

    float weight = afterDepth / (afterDepth - beforeDepth);

    vec2 finalTexCoords = prevTexCoords * weight + currentTexCoords * (1.0 - weight);

    return finalTexCoords;
}

// FUNCTION I ADDED FOR SHADOW CALCULATION
float ShadowCalc(vec2 texCoord, vec3 lightDir)
{
    float minLayers = 0;
    float maxLayers = 32;
    float numLayers = mix(maxLayers, minLayers, abs(dot(vec3(0.0, 0.0, 1.0), lightDir)));

    float layerDepth = 1.0 / numLayers;

    float currentLayerDepth = 0;

    vec2 P = lightDir.xy / lightDir.z * heightScale;

    vec2 deltaTexCoords = P / numLayers;

    vec2 currentTexCoords = texCoord;

    float currentDepthMapValue = texture(heightMap, currentTexCoords).r;

    while (currentLayerDepth < currentDepthMapValue)
    {
        currentTexCoords -= deltaTexCoords;
        currentDepthMapValue = texture(heightMap, currentTexCoords).r;
        currentLayerDepth += layerDepth;
    }

    float r = currentDepthMapValue > currentLayerDepth ? 0.0 : 1.0;

    return r;
}

void main()
{
    mat3 TBN_norm = transpose(mat3(normalize(world_tangent),
                                   normalize(cross(world_normal, world_tangent)),
                                   normalize(world_normal)));
    vec3 viewDir = TBN_norm * normalize(o_worldPos - viewPosition);
    vec2 currentTex = ParallaxMapping(o_texCoord, viewDir);
    if (currentTex.x > 1.0 || currentTex.y > 1.0 || currentTex.x < 0.0 || currentTex.y < 0.0)
    {
        discard;
    }
    vec3 normal = texture(normalMap, currentTex).rgb;
    normal = normalize(normal * 2.0 - 1.0);
    vec3 lightDir = normalize(TBN_norm * light_pos - TBN_norm * o_worldPos);
    float dc = max(0.0, dot(lightDir, normal));

    // STUFF I ADDED FOR SHADOWS
    float shadow = 0;
    if (dc > 0)
    {
        shadow = ShadowCalc(currentTex, lightDir);
    }

    fragColor = shadow * dc * texture(diffuseMap, currentTex);
}

首先,纹理空间中光源到片段的方向是:

vec3 lightDir = TBN_norm * normalize(o_worldPos - light_pos);
float dc = max(0.0, dot(-lightDir, normal));

要检查片段是否处于自阴影中,您必须从“视差”纹理像素开始跟踪到光源的光线。

float shadow = dc > 0.0 ? ShadowCalc(currentTex, lightDir) : 0.0;

初始高度(currentLayerDepth) 是当前片段的高度:

float currentDepthMapValue = texture(heightMap, currentTexCoords).r;
float currentLayerDepth = currentDepthMapValue;

由于深度 mao 是逆深度图(1.0 较低),因此如果任何层深度(currentLayerDepth) 小于或等于当前高度 (currentDepthMapValue)。如果达到最大深度(最小值 0.0),则必须中止采样。
请注意,深度会递减(currentLayerDepth -= layerDepth)并且纹理样本是在相反的方向上获取的(currentTexCoords += deltaTexCoords) 比较ParallaxMapping算法:

while (currentLayerDepth <= currentDepthMapValue && currentLayerDepth > 0.0)
{
    currentTexCoords += deltaTexCoords;
    currentDepthMapValue = texture(heightMap, currentTexCoords).r;
    currentLayerDepth -= layerDepth;
}
float r = currentLayerDepth > currentDepthMapValue ? 0.0 : 1.0;

由于除以 (P = lightDir.xy / lightDir.z), P因此deltaTexCoords,始终指向光源(当然是在投影到纹理时)。
如果 z 分量lightDir大于0.0,表面从背面照亮。这会导致提前中止的条件:

if ( lightDir.z >= 0.0 )
    return 0.0;

功能齐全ShadowCalc函数可能如下所示:

float ShadowCalc(vec2 texCoord, vec3 lightDir)
{
    if ( lightDir.z >= 0.0 )
        return 0.0;

    float minLayers = 0;
    float maxLayers = 32;
    float numLayers = mix(maxLayers, minLayers, abs(dot(vec3(0.0, 0.0, 1.0), lightDir)));

    vec2 currentTexCoords = texCoord;
    float currentDepthMapValue = texture(heightMap, currentTexCoords).r;
    float currentLayerDepth = currentDepthMapValue;

    float layerDepth = 1.0 / numLayers;
    vec2 P = lightDir.xy / lightDir.z * heightScale;
    vec2 deltaTexCoords = P / numLayers;

    while (currentLayerDepth <= currentDepthMapValue && currentLayerDepth > 0.0)
    {
        currentTexCoords += deltaTexCoords;
        currentDepthMapValue = texture(heightMap, currentTexCoords).r;
        currentLayerDepth -= layerDepth;
    }

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

将阴影添加到视差遮挡贴图 的相关文章

  • 具有不同大小结构的结构数组的 malloc()

    如果每个结构都包含一个大小不同的字符串数组 那么如何正确地 malloc 一个结构数组 因此每个结构可能有不同的大小 并且不可能 realloc 结构体数量 sizeof 结构体名称 after malloc 初始大小 sizeof 结构名
  • Subversion 和 Visual Studio 项目的最佳实践

    我最近开始在 Visual Studio 中处理各种 C 项目 作为大型系统计划的一部分 该系统将用于替换我们当前的系统 该系统是由用 C 和 Perl 编写的各种程序和脚本拼凑而成的 我现在正在进行的项目已经达到了颠覆的临界点 我想知道什
  • ASP.NET Core 与现有的 IoC 容器和环境?

    我想运行ASP NET 核心网络堆栈以及MVC在已托管现有应用程序的 Windows 服务环境中 以便为其提供前端 该应用程序使用 Autofac 来处理 DI 问题 这很好 因为它已经有一个扩展Microsoft Extensions D
  • 如何尝试/捕获所有异常

    我正在完成由其他人启动的 UWP 应用程序 该应用程序经常崩溃 我总是陷入困境应用程序 at if global System Diagnostics Debugger IsAttached global System Diagnostic
  • C# 正则表达式用于查找 中具有特定结尾的链接

    我需要一个正则表达式模式来查找字符串 带有 HTML 代码 中的链接 以获取文件结尾如 gif 或 png 的链接 示例字符串 a href site com folder picture png target blank picture
  • 将字符串中的“奇怪”字符转换为罗马字符

    我需要能够将用户输入仅转换为 a z 罗马字符 不区分大小写 所以 我感兴趣的角色只有26个 然而 用户可以输入他们想要的任何 形式 的字符 西班牙语 n 法语 e 和德语 u 都可以包含用户输入中的重音符号 这些重音符号会被程序删除 我已
  • mprotect 之后 malloc 导致分段错误

    在使用 mprotect 保护内存区域后第一次调用 malloc 时 我遇到分段错误 这是执行内存分配和保护的代码片段 define PAGESIZE 4096 void paalloc int size Allocates and ali
  • 将字符串转换为正确的 URI 格式?

    有没有简单的方法可以将电子邮件地址字符串转换为正确的 URI 格式 Input http mywebsite com validate email 3DE4ED727750215D957F8A1E4B117C38E7250C33 email
  • HttpWebRequest vs Webclient(特殊场景)

    我知道这个问题之前已经回答过thread https stackoverflow com questions 1694388 webclient vs httpwebrequest httpwebresponse 但我似乎找不到详细信息 在
  • 如何在 C++ 中将 CString 转换为 double?

    我如何转换CString to a double在 C 中 Unicode 支持也很好 Thanks A CString可以转换为LPCTSTR 这基本上是一个const char const wchar t 在 Unicode 版本中 知
  • 从 Code::Blocks 运行程序时出现空白控制台窗口 [重复]

    这个问题在这里已经有答案了 当我尝试在 Code Blocks 中构建并运行新程序时 控制台窗口弹出空白 我必须单击退出按钮才能停止它 它对我尝试过的任何新项目 包括 Hello world 都执行此操作 奇怪的是 它对于我拥有的任何旧项目
  • C++ 插件的“最适合”动态类型匹配

    我有一个几乎所有东西都是插件的架构 该架构以图形用户界面为基础 其中每个插件都由一个 表面 即用户可以通过其与插件交互的 UI 控件 表示 这些表面也是插件 每当添加新插件时 瘦主机都会自动确定哪个可用表面与其最匹配的 UI 如何在 C 中
  • C++11 动态线程池

    最近 我一直在尝试寻找一个用于线程并发任务的库 理想情况下 是一个在线程上调用函数的简单接口 任何时候都有 n 个线程 有些线程比其他线程完成得更快 并且到达的时间不同 首先我尝试了 Rx 它在 C 中非常棒 我还研究了 Blocks 和
  • asp.net网格分页的SQL查询

    我在用iBatis and SQLServer 使用偏移量和限制进行分页查询的最佳方法是什么 也许我添加该列ROW NUMBER OVER ORDER BY Id AS RowNum 但这只会阻止简单查询的数据访问 在某些情况下 我使用选择
  • 为什么要在 C++ 中使用 typedef?

    可以说我有 set
  • 使用 iTextSharp 5.3.3 和 USB 令牌签署 PDF

    我是 iTextSharp 和 StackOverFlow 的新手 我正在尝试使用外部 USB 令牌在 C 中签署 PDF 我尝试使用从互联网上挖掘的以下代码 Org BouncyCastle X509 X509CertificatePar
  • C 中带有指针的结构的内存开销[重复]

    这个问题在这里已经有答案了 我意识到当我的结构包含指针时 它们会产生内存开销 这里有一个例子 typedef struct int num1 int num2 myStruct1 typedef struct int p int num2
  • 如何引用解决方案之外的项目?

    我有一个 Visual Studio C 解决方案 其中包含一些项目 其中一个项目需要引用另一个不属于解决方案的项目 一开始我引用了dll
  • C#中为线程指定特殊的cpu

    我有 2 个线程 我想告诉其中一个在第一个 cpu 上运行 第二个在第二个 cpu 上运行 例如在具有两个 cpu 的机器中 我怎样才能做到这一点 这是我的代码 UCI UCIMain new UCI Thread UCIThread ne
  • 如何使用 C# 以低分辨率形式提供高分辨率图像

    尝试使用 300dpi tif 图像在网络上显示 目前 当用户上传图像时 我正在动态创建缩略图 如果创建的页面引用宽度为 500x500px 的高分辨率图像 我可以使用相同的功能即时转换为 gif jpg 吗 将创建的 jpg 的即将分辨率

随机推荐

  • 在 Django admin 中显示子级内联

    在 Django 1 11 中 我有 2 个模型 Foo and Bar class Foo models Model name models CharField class Bar models Model name models Cha
  • 在 html5 中将 div 放置在画布上

    我试图将 div 元素放置在页面中心的画布上 用于游戏 这是关于我想在开始游戏之前在画布上显示的开始屏幕 这个开始屏幕有 玩游戏 设置 等选项 问题是我无法完成这个工作 我在谷歌上搜索了很多 我看过很多例子 但它们似乎都不适合我 这是我的代
  • Spring Boot 2 - Webflux - Websocket - 激活压缩

    我在用着 Spring Boot 2 1 0 发布 Webflux 不是 MVC 网络套接字 反应式网络 我想用 GZIP 或任何其他压缩 压缩返回的有效负载 我尝试过 application yml 中的配置 server compres
  • 更改字典键的最佳方法

    我想知道是否有更好的方法来更改字典键 例如 var dic new Dictionary
  • SQLAlchemy/MySQL 在查询期间丢失与 MySQL 服务器的连接

    SQLAlchemy 0 9 8 和 mysql 5 6 21 osx10 8 x86 64 和 MAC OS X 10 3 3 Yosemite 我总是断断续续 InterfaceError InterfaceError 2013 Los
  • 宏编程中如何获取当前目录名称?

    我需要知道如何在宏编程中获取当前目录变量 我正在桌面上保存一个文件 如下所示 C Users deadlock Desktop data html 是否可以将 C Users deadlock Desktop 替换为当前的直接变量 这是我的
  • 执行相机意图时 Activity 被终止

    编辑 问题已解决 请参见我的答案 https stackoverflow com a 9791832 839965 below 在我的应用程序中 我调用系统相机拍照 然后处理结果onActivityResult 你知道 平常的 它曾经有效
  • Setuid 到 Perl 脚本

    我正在使用 Perl 脚本从 mqueue 文件夹中删除 sendmail 的数据 When I setuid到该 Perl 脚本并尝试从用户运行它 它会抛出以下消息 Insecure dependency in chdir while r
  • 如何通过标签查找并禁用内容控件以删除它及其内容?

    我有一个不幸的任务 被迫为我公司的单位设计一个基于Word 的电子生产卡 尽管我从未使用过VBA 我更愿意在 Excel 中完成此操作 因为我不必费力处理内容控制和页面上各种表格中难以找到的位置 但公司的文档系统强制这一特定的文档系统必须在
  • 如何在 CakePHP 中生成 MySQL IS NOT NULL 条件?

    我正在尝试获取结果的子集作为 virtualField 以在我的视图中使用 我什至可能不知道如何解决这个问题 但这是我到目前为止所做的 我在这里从这个问题开始 CakePHP virtualField 查找所有不为空 https stack
  • Typescript,从接口中提取多个调用签名[重复]

    这个问题在这里已经有答案了 鉴于以下情况 interface Foo attr string a string number a number number 如何创建一种仅选择函数重载的类型 这意味着 interface Bar a str
  • 错误:请通过更新 google-services 插件的版本来修复版本冲突

    我在使用 Google 服务插件时遇到问题 我将谷歌服务更新到最新版本 我从这个网站获得了依赖 https bintray com android android tools com google gms google services h
  • Keras、Tensorflow:将两个不同的模型输出合并为一个

    我正在研究一种深度学习模型 我试图将两种不同模型的输出结合起来 整体结构是这样的 所以第一个模型采用一个矩阵 例如 10 x 30 input 1 input text layers Input shape 1 dtype string e
  • net.snowflake.client.jdbc.SnowflakeChunkDownloader :等待下载 #chunk0 超时

    等待下载块错误超时 Snowflake JDBC 驱动程序版本 3 13 18 遇到错误 net snowflake client jdbc SnowflakeSQLException JDBC driver internal error
  • iPython magic for Zipline 找不到数据包

    我有一个 Python 2 7 脚本 可以在命令提示符下正常运行 Zipline 使用 bundle myBundle加载自定义数据包myBundle我已经注册使用extension py zipline run f myAlgo py b
  • 如何使用 HttpWebRequest 发布数据?

    我有这个HttpWebRequest var request HttpWebRequest Create http example com api Phrase GetJDTO request ContentType application
  • 在GUI中删除表中的数据

    我有一个问题 当用户输入密钥时 如何删除 GUI 中 jTable 中的所有数据 谢谢 您可以设置一个新的空数据模型 TableModel newModel new DefaultTableModel jtable setModel new
  • Mahout 堆空间不足

    我正在使用 Mahout 在一组推文上运行 NaiveBayes 两个文件 一个 100 MB 一个 300 MB 我将 JAVA HEAP MAX 更改为 JAVA HEAP MAX Xmx2000m 之前是 1000 但即便如此 mah
  • 自动过滤 SQLAlchemy 查询的正确方法?

    我刚刚使用 sqlalchemy 从 CRM 应用程序中反思了一个相当令人讨厌的模式 所有表上都有一个已删除的列 我想自动过滤所有标记为已删除的实体和关系 这是我想出的 class CustomizableQuery Query An ov
  • 将阴影添加到视差遮挡贴图

    我已经通过实现视差遮挡贴图学习OpenGL https learnopengl com Advanced Lighting Parallax Mapping 现在我想添加自阴影 以便片段挤压在表面上投射阴影 我读过一些关于这个主题的论文 但