具有定向光正交投影的 OpenGL 3+

2024-03-21

我目前遇到来自移动(类似太阳)光源的定向光阴影贴图的问题。

当我最初实现时,光投影矩阵被计算为 3D,并且阴影贴图看起来很漂亮。然后我了解到,对于我想要做的事情,正交投影效果会更好,但我很难替换正确的投影矩阵。

正如人们所期望的那样,每次滴答声,太阳都会沿着圆周移动一定的距离。我使用自制的“lookAt”方法来确定正确的观察矩阵。例如,白天的时间是早上 6 点到下午 6 点。当太阳位于上午 9 点位置(45 度)时,它应该查看原点并将阴影贴图渲染到帧缓冲区。正交投影似乎发生的情况是它不会向原点“倾斜”。它只是继续沿着 Z 轴直视。上午 6 点和下午 6 点情况看起来不错,但例如中午 12 点,则完全没有任何显示。

我的设置方式如下:

原始3D投影矩阵:

Matrix4f projectionMatrix = new Matrix4f();
float aspectRatio = (float) width / (float) height;

float y_scale = (float) (1 / cos(toRadians(fov / 2f)));
float x_scale = y_scale / aspectRatio;
float frustum_length = far_z - near_z;

projectionMatrix.m00 = x_scale;
projectionMatrix.m11 = y_scale;
projectionMatrix.m22 = (far_z + near_z) / (near_z - far_z);
projectionMatrix.m23 = -1;
projectionMatrix.m32 = -((2 * near_z * far_z) / frustum_length);

观察方法:

public Matrix4f lookAt( float x, float y, float z,
                      float center_x, float center_y, float center_z ) {
  Vector3f forward = new Vector3f( center_x - x, center_y - y, center_z - z );
  Vector3f up      = new Vector3f( 0, 1, 0 );

  if ( center_x == x && center_z == z && center_y != y ) {
    up.y = 0;
    up.z = 1;
  }

  Vector3f side = new Vector3f();

  forward.normalise();

  Vector3f.cross(forward, up, side );
  side.normalise();

  Vector3f.cross(side, forward, up);
  up.normalise();

  Matrix4f multMatrix = new Matrix4f();
  multMatrix.m00 = side.x;
  multMatrix.m10 = side.y;
  multMatrix.m20 = side.z;
  multMatrix.m01 = up.x;
  multMatrix.m11 = up.y;
  multMatrix.m21 = up.z;
  multMatrix.m02 = -forward.x;
  multMatrix.m12 = -forward.y;
  multMatrix.m22 = -forward.z;

  Matrix4f translation = new Matrix4f();
  translation.m30 = -x;
  translation.m31 = -y;
  translation.m32 = -z;

  Matrix4f result = new Matrix4f();

  Matrix4f.mul( multMatrix, translation, result );
  return result;
}

正交投影(使用宽度 100,高度 75,近 1.0,远 100 )我已经尝试过使用许多不同的值:

Matrix4f projectionMatrix = new Matrix4f();

float r = width * 1.0f;
float l = -width;
float t = height * 1.0f;
float b = -height;

projectionMatrix.m00 = 2.0f / ( r - l );
projectionMatrix.m11 = 2.0f / ( t - b );
projectionMatrix.m22 = 2.0f / (far_z - near_z);
projectionMatrix.m30 = - ( r + l ) / ( r - l );
projectionMatrix.m31 = - ( t + b ) / ( t - b );
projectionMatrix.m32 = -(far_z + near_z) / (far_z - near_z);
projectionMatrix.m33 = 1;

阴影贴图顶点着色器:

#version 150 core

uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform mat4 modelMatrix;

in vec4 in_Position;

out float pass_Position;

void main(void) {
  gl_Position = projectionMatrix * viewMatrix * modelMatrix * in_Position;
  pass_Position = gl_Position.z;
}

阴影贴图片段着色器:

#version 150 core

in vec4 pass_Color;
in float pass_Position;

layout(location=0) out float fragmentdepth;

out vec4 out_Color;

void main(void) {
  fragmentdepth = gl_FragCoord.z;
}

我觉得我在这里错过了一些非常简单的东西。正如我所说,这对于 3D 投影矩阵来说效果很好,但我希望用户在世界各地旅行时阴影保持不变,这对于定向照明和正交投影来说很有意义。


实际上,谁告诉您使用正交投影矩阵对于阴影贴图来说是个好主意?这可能适用于像太阳这样的物体,它们实际上是无限远的,但对于局部灯光来说透视是非常相关的。不过,您必须小心使用透视投影和阴影贴图,因为采样频率随距离而变化,并且您最终会在某些距离上获得很高的精度,而在其他距离上则不够,除非您通常使用级联或透视变形之类的东西;不过,这可能超出了您目前应该考虑的范围:)

此外,正交投影矩阵与透视图一样都是 3D 的,因为它们通过将 3D“图像”投影到 2D 观看平面上来工作……它们与透视图之间的唯一区别是平行线保持平行。换句话说,(x,y,near) 和 (x,y,far) 理想地在正交投影中投影到屏幕上的同一位置。


您的使用gl_FragCoord.z在片段着色器中是不寻常的。由于这是写入深度缓冲区的值,因此您不妨编写NOTHING在片段着色器中并重新使用深度缓冲区。除非您的实现不支持浮点深度缓冲区,否则您会将深度写入两个位置,从而浪费内存带宽。仅深度传递glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE)在构建阴影贴图时通常会获得更高的吞吐量。

如果您实际使用了pass_Position(这是剪辑空间中的非透视校正 Z 坐标),我可以看到使用单独的颜色附件来编写此内容,但您正在编写透视校正深度范围调整深度(gl_FragDepth) 现在。



无论如何,当太阳直接位于头顶并且您使用正交投影时,预计不会投射任何阴影。这又回到了我之前解释过的属性,即平行线保持平行。由于物体与太阳的距离对物体的投影位置(正交)没有影响,因此如果物体位于正上方,您将不会看到任何阴影。尝试沿着球体而不是圆跟踪太阳的位置,以尽量减少这种情况。

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

具有定向光正交投影的 OpenGL 3+ 的相关文章

  • 我们可以在java中放弃已经签名的jar吗?

    I ve a jar文件具有旧签名 并希望使用新签名重新签名 是否可以 如果可能的话 怎么做 如果签名不是您拥有的 您需要先解压 jar 像这样 假设是unix 否则翻译成dos jar xvf JarName jar rm rf META
  • JTree 避免重新加载后崩溃

    我正在尝试找到解决崩溃问题的方法JTree重新加载后 情况 JTree Office A Office A 1 Office A 1 1 Office A 1 2 Office B Office B 1 Office B 1 1 Offic
  • 视频文件转换/转码 Google App Engine

    我想启动一个云计算项目 其简单任务是 接收上传的视频文件 对它们进行一些转码 转换 允许用户下载 流式传输生成的文件 我刚在想ffmpeg作为集成在的外部命令行工具Java Google App engine Application 由于很
  • Spring批量写入器限制

    我正在工作 Spring Batch 项目 从数据库读取记录然后写入rabbitmq 然后发送到HTTP消息网关 网关有150TPS我需要将我的应用程序限制为 150TPS 有没有办法带弹簧批的油门或者还有其他更好的方法吗 你能行的 在 S
  • 声纳要求将这一领域定为最终目标

    我的程序中有以下代码 在与 Maven 集成后 我正在运行 SonarQube 5 对其进行代码质量检查 我面临这个错误 将此 public static processStatus 字段设为最终字段 将此 public static pr
  • 如何在不使用反射的情况下查看对象是否是数组?

    在Java中如何在不使用反射的情况下查看对象是否是数组 如何在不使用反射的情况下迭代所有项目 我使用 Google GWT 所以不允许我使用反射 我很想在不使用反射的情况下实现以下方法 private boolean isArray fin
  • 最终类中的静态函数是否隐式最终?

    我的问题基本上与this https stackoverflow com q 8766476 3882565一 但这是否也适用于static功能 我想了解 编译器是否处理所有static函数在一个final类为final 是否添加final
  • MongoDb Spring 在嵌套对象中查找

    我正在使用 Spring Data Mongodb 和这样的文档 id ObjectId 565c5ed433a140520cdedd7f attributes 565c5ed433a140520cdedd73 333563851 list
  • SQLite 64位整数在jooq中被识别为int

    我有一个与 jOOQ 一起使用的 SQLite 数据库 当我使用 jOOQ 的代码生成工具时 它会按预期构建所有表和记录类 然而 所有的 SQLiteINTEGER列变成java lang Integer生成的代码中的字段 问题是 SQLi
  • 如何在 Java 中读取/转换 InputStream 为字符串?

    如果你有一个java io InputStream对象 您应该如何处理该对象并生成一个String 假设我有一个InputStream包含文本数据 我想将其转换为String 例如我可以将其写入日志文件 最简单的方法是什么InputStre
  • 检查对象是否为空

    我有一个链表 其中第一个节点包含空对象 表示firstNode data等于null firstNode nextPointer null firstNode previousPointer null 我想检查firstNode 是否为空
  • oracle.jdbc.driver.OracleDriver ClassNotFoundException

    这是我收到错误的代码 我的classes12 jar已作为外部 jar 导入 import java io IOException import java io PrintWriter import java sql Connection
  • Spring portlet mvc:@Valid 似乎不起作用

    我创建了一个 bean 类并在我的控制器中使用它 但它似乎不起作用 也就是说 即使我输入了无效的年龄 result hasErrors仍然是假的 豆类 public class User Min 13 private int age pri
  • 我有什么理由应该嘲笑?

    我也是 Mockito 和 PowerMockito 的新手 我发现我无法使用纯 Mockito 测试静态方法 因此我需要使用 PowerMockito 对吗 我有一个非常简单的类 名为 Validate 使用这个非常简单的方法 publi
  • 抛出 UnsupportedOperationException

    因此其中一种方法的描述如下 public BasicLinkedList addToFront T data 该操作无效 对于排序列表 将生成 UnsupportedOperationException 使用消息 排序列表的操作无效 我的代
  • 使用mapstruct映射不同类型列表的元素

    我们正在映射一个对象 该对象具有一个对象列表 这些对象都实现了父接口 但可能具有不同的实现 但当我们映射列表时 似乎只有来自 ParentClass 的值被映射 而不是来自子类的值 但直接映射子进程就可以了 public class Par
  • 如何强制 Spark 执行代码?

    我如何强制 Spark 执行对 map 的调用 即使它认为由于其惰性求值而不需要执行它 我试过把cache 与地图调用 但这仍然没有解决问题 我的地图方法实际上将结果上传到 HDFS 所以 它并非无用 但 Spark 认为它是无用的 简短回
  • 我的代码线程不安全吗?

    我编写了代码来理解 CyclicBarrier 我的应用程序模拟选举 每轮选出得票少的候选人 该候选人从竞争中淘汰以获得胜利 source class ElectoralCommission public volatile boolean
  • FocusEvent 没有获取 JFormattedTextField 的最后一个值,我如何获取它?

    我有两个JFormattedTextField我的物体JFrame目的 我想要通过这些值进行基本数学 加法 JFormattedTextField对象 我希望当焦点丢失第一个或第二个文本字段时发生这种情况 但当 focusLost 事件没有
  • Encog:BasicNetwork:无需预先构建数据集的在线学习

    我正在尝试使用 encog 库作为强化学习问题的函数逼近器 更准确地说 我正在尝试启动并运行多层感知器 BasicNetwork 由于我的代理将根据我选择的任何 RL 算法以某种方式探索世界 因此我无法预先构建任何 BasicNeuralD

随机推荐

  • 在 Swift 中使用 obj-c typedef

    我有一个 typedef 如下 typedef NSString VMVideoCategoryType extern VMVideoCategoryType const VMVideoCategoryType MusicVideo ext
  • 组合两个 Runnable 对象

    举例来说 我有一个名为 RunnableA 的 Runnable 它可以执行某些操作 我还有一个名为 RunnableB 的 Runnable 它可以执行其他操作 有没有办法可以将这两个 Runnable 组合起来 以便它们在同一个线程中运
  • Ironpython:函数在 CPython 中工作,IronPython 中神秘的空指针异常

    我正在尝试做一些看起来非常简单的事情 并且属于标准 python 的范围 以下函数接受集合的集合 并返回两个或多个集合中包含的所有项目 为此 虽然集合的集合不为空 但它只是从集合中弹出一个集合 将其与其余集合相交 并更新落在这些交集之一中的
  • 在 React 中测试 mapbox-gl 时如何修复“window.URL.createObjectURL 不是函数”?

    我正在使用 Mapbox material ui 和自定义样式测试 React 组件 我使用 Jest Enzyme 进行测试 我有问题 window URL createObjectURL 不是函数 我读过类似的问题 github com
  • 如何自定义引导侧边栏/sidenav?

    I need to make use of Twitter Bootstrap Sidebar for creating a menu in my web application Highlighted in red To create a
  • 隐藏键盘ios [重复]

    这个问题在这里已经有答案了 我有一些文本输入 每当我触摸背景时 我都可以隐藏键盘 但只有当我输入第一个文本框名称 textField1 时 现在这段代码应该很简单 但我似乎无法理解它 IBAction backgroundTouched i
  • 如何在Python中将词云保存为.png?

    我正在尝试基于字符串创建词云 然后将其导入到报告文档中 我正在使用 python docx matplotlib 和词云 这是我的一个简短的总结 from wordcloud import WordCloud import matplotl
  • 获取 Flask 中的当前用户 ID

    我对 Python 还很陌生 老实说 我对一般编程也很陌生 我目前正在制定一种待办事项列表 我需要它将待办事项放入适当的课程中 所有这些都与教育内容相关 所以 问题很简单 我将其作为 Flask 驱动的路线 app route add co
  • 方案单词列表 eq?

    我有一个问题 我需要查找列表是否等于第二个列表 例如 set eq 1 2 3 1 2 3 gt t set eq 1 2 3 2 3 4 gt f 这些例子在我的程序中是正确的 但这个例子不是 set eq quote quote one
  • 如何使用GridView从服务器获取JSON数据--Flutter

    我参考过食谱 https flutter dev docs cookbook networking fetch data https flutter dev docs cookbook networking fetch data 示例代码是
  • VueJS 自定义 Props 验证功能

    我是 VueJS 的新手 所以我一直在关注他们的官方指南 https v2 vuejs org v2 guide components html Prop Validation 我能够触发前 5 个属性验证器 但我似乎无法触发最后一个示例
  • 在 Firefox 中读取多行内容可编辑文本

    让我们读取一个 contenteditable 元素 span This is editable br Yes it is span 就在您在文本末尾手动添加两个空格之后 I get textContent gt This is edita
  • C++ 中的“new”运算符何时调用构造函数

    自从我开始学习 C 以来 我一直读到 new 运算符在返回指向分配内存的指针之前调用对象的构造函数 因此 出于好奇 我检查了 new 的源代码 并在以下位置找到了以下内容 GLIBCXX WEAK DEFINITION void opera
  • 使用一组字符而不是一个字符的序列对齐算法

    Summary 我从一些有关对齐算法的细节开始 最后我提出了我的问题 如果您了解对齐算法 请从头开始 考虑我们有两个字符串 例如 ACCGAATCGA ACCGGTATTAAC 有一些算法 例如 史密斯 沃特曼 https en wikip
  • R 绘图自定义数据格式变体

    我正在尝试访问customdata通过javascrit分配给每个数据点 例如为每个点分配一个超链接 然而 我注意到数据格式从一个图变为另一个图 这看起来很奇怪 这在本例中完美运行 基于this https stackoverflow co
  • WordPress:single.php 不显示 the_content()

    我正在创建一个自定义 WordPress 主题 但我似乎无法让 single php 模板正常工作 下面是我写的代码 标题出现了 但内容没有出现 有什么想法为什么不是吗 div div id post gt h2 a href title
  • 为什么要对 List< 进行泛型转换?将 Set..> 扩展为 List 在 Sun JDK 6 上成功,但在 Oracle JDK 7 上编译失败?

    下面的代码 class GenericCompilationFailureDemo List
  • 类型 IUserStore`1 没有可访问的构造函数

    我想使用 Unity 3 设置 MVC5 应用程序 我从标准模板创建了一个默认的 Web mvc5 应用程序 然后添加了 unity 当我访问 AccountController 中的注册操作时 出现以下异常 类型 IUserStore 1
  • 使用对象元素作为参数的 Firestore 查询

    我在项目中使用 Firestore 作为数据库 并且我有一个表 我需要在对象内执行查询 foo data bar data exObject dataToQuery value 这是一个结构示例 我想在对象内部进行查询 一个如下所示的查询
  • 具有定向光正交投影的 OpenGL 3+

    我目前遇到来自移动 类似太阳 光源的定向光阴影贴图的问题 当我最初实现时 光投影矩阵被计算为 3D 并且阴影贴图看起来很漂亮 然后我了解到 对于我想要做的事情 正交投影效果会更好 但我很难替换正确的投影矩阵 正如人们所期望的那样 每次滴答声