OpenTK 矩阵变换

2023-12-01

这是顶点着色器:

uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;

void main(void)
{
    gl_Position = projection * view * model * gl_Vertex;
    gl_TexCoord[0] = gl_MultiTexCoord0;
}

我的理解是,使用各种变换,模型空间最终会变成剪辑空间,这是一个由每个轴中的每个单元绑定的盒子,直接绘制到视口,即(-1, 1,0)处的东西位于顶部视口的左侧。当我从着色器中删除所有矩阵变换时,

gl_Position = gl_Vertex;

并传入一个简单的四边形作为模型

public Vector3[] verts = new Vector3[] {
    new Vector3(-1f, -1f, 0),
    new Vector3(1f, -1f, 0),
    new Vector3(1f, 1f, 0),
    new Vector3(-1f, 1f, 0),
};

public Vector2[] coords = new Vector2[] {
    new Vector2(0, 1f),
    new Vector2(1f, 1f),
    new Vector2(1f, 0f),
    new Vector2(0f, 0f),
};

public uint[] indices = new uint[] {
    0,1,2,
    0,2,3,
};

我得到了预期的全屏图像。当我应用转换时,图像显示为 正如您所期望的,屏幕中央的一个小方块。当我尝试在 CPU 上的剪辑坐标中计算模型顶点的位置时,出现了问题:

public Vector4 testMult(Vector4 v, Matrix4 m)
{
    return new Vector4(
        m.M11 * v.X + m.M12 * v.Y + m.M13 * v.Z + m.M14 * v.W,
        m.M21 * v.X + m.M22 * v.Y + m.M23 * v.Z + m.M24 * v.W,
        m.M31 * v.X + m.M32 * v.Y + m.M33 * v.Z + m.M34 * v.W,
        m.M41 * v.X + m.M42 * v.Y + m.M43 * v.Z + m.M44 * v.W);
}

Matrix4 test = (GlobalDrawer.projectionMatrix * GlobalDrawer.viewMatrix) * modelMatrix;

Vector4 testv = (new Vector4(1f, 1f, 0, 1));
Console.WriteLine("Test Input: " + testv);
Console.WriteLine("Test Output: " + Vector4.Transform(testv, test));
Vector4 testv2 = testMult(testv, test);
Console.WriteLine("Test Output: " + testv2);
Console.WriteLine("Test Output division: " + testv2 / testv2.W);

(传入的矩阵与传递给着色器的矩阵相同)

然后程序继续在剪辑空间之外给出输出,除以 W 导致除以 0:

Test Input: (1, 1, 0, 1)
Test Output: (0.9053301, 1.207107, -2.031746, 0)
Test Output: (0.9053301, 1.207107, -1, 0)
Test Output division: (Infinity, Infinity, -Infinity, NaN)

矩阵创建如下:

projectionMatrix = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, window.Width / (float)window.Height, 1.0f, 64.0f);
projectionMatrix =
(1.81066, 0, 0, 0)
(0, 2.414213, 0, 0)
(0, 0, -1.031746, -1)
(0, 0, -2.031746, 0)

viewMatrix = Matrix4.LookAt(new Vector3(0,0,4), -Vector3.UnitZ, Vector3.UnitY);
viewMatrix = 
(1, 0, 0, 0)
(0, 1, 0, 0)
(0, 0, 1, 0)
(0, 0, -4, 1)

modelMatrix = 
(0.5, 0  , 0  , 0)
(0  , 0.5, 0  , 0)
(0  , 0  , 1  , 0)
(0  , 0  , 0  , 1)

所以,问题是为什么;我究竟做错了什么?


Edit (添加评论中的真实答案)

默认情况下,您的 OpenTK 矩阵是转置的。它看起来使用行向量而不是列向量。因此,您需要将乘法计算为 (model * view * proj),而不是 (proj * view * model)。或者在上传之前转置所有矩阵。


实际上剪辑空间不是从-1到1,而是从-W到W,其中W是剪辑空间向量的第四个分量。

你可能想到的叫做标准化设备坐标,每个轴上的范围为 -1 到 1。通过将剪辑空间向量的 X、Y 和 Z 坐标除以剪辑空间 W 分量即可获得该值。这个部门被称为透视划分.

这是在将剪辑空间坐标传递给 gl_Position 后在幕后完成的。

不过你的剪辑空间坐标是 0,这对我来说似乎不正确。

这里还有一些更多细节:OpenGL 常见问题解答:转换.

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

OpenTK 矩阵变换 的相关文章

  • 创建并使用我自己的纹理图集的 mipmap

    我目前正在使用自动 mipmap 生成 C OpenTK GL GenerateMipmap GenerateMipmapTarget Texture2D 我使用的纹理平铺为 16px 的块 所以我的问题是 是否可以使用不会缩小至 1x1
  • 计算数组中接下来的 n 个元素的乘积

    我想计算下一个的乘积n矩阵的相邻元素 号码n要相乘的元素数应在函数的输入中给出 例如 对于此输入 我应该从第一个开始计算每 3 个连续元素的乘积 p ind max product 1 2 2 1 3 1 3 这给出了 1 2 2 2 2
  • 使用 numpy tensordot 进行张量乘法

    我有一个张量 U 由 n 个维度 d k 的矩阵和一个维度 k n 的矩阵 V 组成 我想将它们相乘 以便结果返回一个维度为 d n 的矩阵 其中 j 列是 U 的矩阵 j 与 V 的 j 列之间的矩阵乘法的结果 获得此信息的一种可能方法是
  • MATLAB 中最有效的矩阵求逆

    在 MATLAB 中计算某个方阵 A 的逆矩阵时 使用 Ai inv A should be the same as Ai A 1 MATLAB 通常会通知我这不是最有效的求逆方法 那么什么是更有效率的呢 如果我有一个方程系统 可能会使用
  • WGL:没有双缓冲 + 多重采样 = 失败?

    我通常使用创建像素格式wglChoosePixelFormatARB 与这些论点 除其他外 WGL DOUBLE BUFFER ARB GL TRUE WGL SAMPLE BUFFERS ARB GL TRUE WGL SAMPLES A
  • 无法在 QGLWidget 中设置所需的 OpenGL 版本

    我正在尝试在 Qt 4 8 2 中使用 QGLWidget 我注意到 QGLWidget 创建的默认上下文不显示 OpenGL 3 1 以上的任何输出 Qt wiki 有一个教程 http qt project org wiki How t
  • MPI - 发送和接收列

    我需要从一个进程发送矩阵列并从另一个进程接收它 我尝试运行以下程序 但得到了一个奇怪的结果 至少我这么认为 仅复制矩阵的第一个元素 某些矩阵元素会发生意外变化 include
  • 使用 gl_FragColor 与 vec4 颜色?

    似乎有很多不明确的地方gl FragColor被弃用 例如 它缺失在GLSL 4 40 规范 https www khronos org registry OpenGL specs gl GLSLangSpec 4 40 pdf 但它包含在
  • Windows 上的 OpenGL SDK

    我正在尝试编写一个 OpenGL 应用程序 因此我安装了 Windows 7 SDK 然而 它似乎是OpenGL 1 1 define GL VERSION 1 1 1 如何找到我安装的 OpenGL 版本 dll 以及在哪里可以找到较新的
  • 使用普通画布/文本输出更新LayeredWindow

    有没有一种方法可以使用画布在表单上绘图 然后使用 updatelayeredwindow 这样表单就不可见 但文本可见 就像只显示文本的半透明表单一样 如果没有 那么有没有办法只用画布 opengl directx 制作某种半透明形式 我想
  • 仅在发布模式下使用 glGenBuffer 时出现未处理的异常 - QT

    我在 Windows 7 上使用 Qt 4 8 发布模式编译项目时遇到了一些问题 调试时一切正常 但在发布时我收到未处理的异常 0xC0000005 访问冲突 我将范围缩小到发生这种情况的行 即生成像素缓冲区的时间 我的第一个猜测是 DLL
  • 用 R 代码编写 Householder QR 分解函数

    我正在编写一段代码来查找 R 中矩阵的 QR 分解 X lt structure c 0 8147 0 9058 0 127 0 9134 0 6324 0 0975 0 2785 0 5469 0 9575 0 9649 0 1576 0
  • R矩阵右除

    在 R 中进行左右矩阵除法的最简洁 最快 数值最稳定 最 R 惯用的方法是什么 我理解左除法inv A B通常是用solve a b 但是怎么样B inv A 确实是最好的计算方法t solve t A t B It is B solve
  • R 中的自定义对比:对比系数矩阵或对比矩阵/编码方案?以及如何到达那里?

    自定义对比在分析中应用非常广泛 例如 这个三水平因子的第 1 级和第 3 级的 DV 值是否有显着差异 直观上 这种对比用单元均值表示为 c 1 0 1 这些对比中的一个或多个 以列的形式绑定 形成对比系数矩阵 例如 mat matrix
  • 是否可以在 Mac OS X 上构建 FreeGLUT?

    我正在做一些关于 OpenGL 的教程 http www arcsynthesis org gltut Basics Tutorial 2001 html那个使用FreeGLUT http freeglut sourceforge net
  • 更快的四元数向量乘法不起作用

    我的数学库需要一个更快的四元数向量乘法例程 现在我正在使用规范v qv q 1 它产生的结果与向量乘以由四元数组成的矩阵相同 所以我对它的正确性充满信心 到目前为止 我已经实现了 3 种替代 更快 的方法 1 我不知道我从哪里得到这个 v
  • 如何找到平面和 3d 矩阵之间的交平面

    如果我有一堆图像并且尺寸如下 size M 256 256 124 我有 3 个点 它们的坐标是 coor a 100 100 124 coor b 256 156 0 coor c 156 256 0 如何创建 M 与这 3 个点定义的平
  • R::bigmemory - 如何创建角色big.matrix?

    我尝试使用bigmemory封装在R我一开始就陷入困境 我愿意 temp lt matrix paste a 1 10 5 2 并得到一个字符矩阵 没关系 但后来我尝试 x lt as big matrix temp type char 我
  • (C) 获取矩阵中一行的 3 个最小元素,并随机选择一个

    我有一个 8x8 矩阵 在选择我想要的行后 我想获得它的三个最小元素 并随机选择这三个元素之一 问题是我不知道如何处理这三个要素 我只知道如何获取最小元素 即下面的代码 int piezas 8 8 0 2 2 5 3 2 1 1 0 4
  • 在OpenGL中,我可以在坐标(5, 5)处精确地绘制一个像素吗?

    我所说的 5 5 正是指第五行第五列 我发现使用屏幕坐标来绘制东西非常困难 OpenGL 中的所有坐标都是相对的 通常范围从 1 0 到 1 0 为什么阻止程序员使用屏幕坐标 窗口坐标如此严重 最简单的方法可能是通过以下方式设置投影以匹配渲

随机推荐

  • 使用 LibreOffice(soffice.exe) 作为 Process.Start() 从代码隐藏不能在 IIS 服务器上工作

    我使用 LibreOffice 作为命令行将 docx 转换为 pdf 我正在使用下面的代码片段 using Process pdfprocess new Process pdfprocess StartInfo UseShellExecu
  • 如何在 vue js 2 上将变量放入 href 中?

    当我运行这个时 nextPage 结果 http chelseashop dev search result page 2 但是当我输入这样的 href 时
  • 返回函数 c 中的结构

    我正在尝试返回一个struct来自一个函数 看起来是这样的 struct read struct returnera returnDuo struct vara varuArray char varunr LISTNUMBER varuna
  • 在本地开发时在 Cloud Run 中模拟事件驱动设计?

    我正在开发一个在 Google Cloud Run 完全托管 上 运行的微服务架构应用程序 我想将事件通信添加到我的服务中 据我所知 唯一的选择是使用 Eventarc 我很好奇在本地开发时重现事件驱动设计的最佳方法是什么 以及如何使部署尽
  • 如何在 Scala Spark 中从 Excel(xls、xlsx)文件构造 Dataframe?

    我有一个大Excel xlsx and xls 包含多个工作表的文件 我需要将其转换为RDD or Dataframe以便它可以连接到其他dataframe之后 我正在考虑使用阿帕奇兴趣点并将其另存为CSV然后阅读csv in datafr
  • 如何在没有注解的情况下使用Spring Data JDBC?

    我正在开发一个新项目 使用干净架构等概念 保护我的模型和业务规则免受外部依赖项和框架的影响 另外 我不喜欢使用传统的 ORM 库 如 JPA Hibernate 而是选择使用纯 jdbc 通过 spring jdbctemplate 一切进
  • 如何按添加顺序绘制 X、Y 坐标?

    我想按照我输入的顺序连接 X 和 Y 坐标以形成一个圆 我找到了一个用Java绘制X Y坐标的程序 然后我添加了圆的数据 但程序连接了最近的 X Y 坐标 而不是排序 X Y public Graph final String title
  • SQLAlchemy ORM 无法使用复合外键

    我正在尝试使用几个相关模型构建一个示例 如下所示 我们有一个模型 B 与模型 C 具有 1 n 关系 那么我们就有一个模型 A 与 B 之间存在 n 1 关系 与 C 之间存在 n 1 关系 C 有 2 列主键 我尝试了这段代码 class
  • 按键在 Mozilla Firefox 中不起作用

    我有一项任务限制文本框的字母值 只能使用浮点值 小数点后我们必须写出两位数 我这样做了 但它在 Mozilla Firefox 中不起作用 我怎么解决这个问题 我的脚本是 function name bind paste function
  • 如何使用正则表达式提取大括号中的单词?

    我想提取全部words用花括号括起来 所以我有这样的表达式 foo bar moo mar 要匹配的字符串可能有任意数量的这些单词 但我开始认为我正在以错误的方式处理这个问题 我的尝试 我尝试将大括号中的单词提取到组中 以便我可以使用每个匹
  • Cocoa:隐藏其他应用程序和自身

    我需要一种方法让应用程序与所有其他应用程序一起隐藏自身 我目前隐藏了其他应用程序 但我的应用程序保持打开状态 我通过单击按钮并将其拖动到实用程序中的 应用程序 区域来完成此操作 然后我选择 隐藏其他应用程序 好的 所以 如果你只是想show
  • 在 React 和 Next.js 构造函数中,我收到“引用错误:本地存储未定义”

    我在 React 中创建了一个系统 jsonwebtoken 并使用 Next js 在浏览器中运行代码时发现一个问题 那就是 本地存储未定义 我该如何修复它 这是我在文件中的代码AuthStudentContext js import R
  • 如何翻译/移动 numpy 数组?

    我不确定要搜索什么关键字 因此如果已被询问 请链接响应并关闭此线程 我试图按固定方向移动 numpy 数组的非零条目 例如 假设我有一个二维数组 0 1 2 0 0 3 0 0 0 0 0 0 0 0 0 0 将其移位 1 1 将产生以下数
  • 海龟图形在自身上绘制

    这应该是一个非常简单的问题 然而 事实证明这对我来说很难 我对海龟图形相当陌生 因此 我正在尝试完成简单的绘图 我的乌龟会画一行 拿起笔 向上移动一个像素 放下笔 然后继续绘画 到目前为止 这是我的代码 for y in range hei
  • 如何从 spring mvc multipartfile 进入 zipinputstream

    我有一个 Spring MVC 控制器 它接受 MultipartFile 它将是一个 zip 文件 问题是我似乎无法从那里转到 ZipInputStream 或 ZipFile 以便我可以浏览条目 它要么提前关闭流 生成一个空文件 要么像
  • 如何在从服务器获取数据的动态表的每一行中添加下拉列表?

    我想添加静态下拉列表到从服务器获取数据的动态表的每一行 我将如何做到这一点 我想做同样的像这样 请检查下拉列表类型 但它也会从服务器获取数据 并且每一行列都会有下拉列表 以下是更新和工作代码 感谢 angu 下拉列表的结构
  • C++中的输出流什么时候必须刷新?

    我明白cout lt lt n 优先于cout lt lt endl but cout lt lt n 不刷新输出流 何时应该刷新输出流以及何时出现问题 究竟什么是潮红 刷新强制输出流写入任何缓冲的字符 读取流式输入 输出 这取决于您的应用
  • 如何解决带有日期值的 h:inputText 中的“‘null Converter’的转换错误设置值‘2013-10-26’”?

    当我按下插入按钮时 标题上显示错误 空转换器 的转换错误设置值 2013 10 26
  • 为什么我不能先定义 main(),然后再定义它调用的函数?

    如果我将 main 放在源文件的顶部并调用一些自定义函数 它会告诉我找不到这些函数 但如果我将 main 放在源文件的底部 它将起作用 为什么 是不是因为编译器从上到下解析程序并在main的定义处中断 和main没有关系 C 编译器从上到下
  • OpenTK 矩阵变换

    这是顶点着色器 uniform mat4 projection uniform mat4 view uniform mat4 model void main void gl Position projection view model gl