热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

opengl旋转矩阵和纹理坐标相乘_OpenGLRotatingPoints

全球图形学领域教育的领先者、自研引擎的倡导者、底层技术研究领域的技术公开者,东汉书院在致力于使得更多人群具备内核级竞争力的道路上,将带给小伙伴们更多的公

全球图形学领域教育的领先者、自研引擎的倡导者、底层技术研究领域的技术公开者,东汉书院在致力于使得更多人群具备内核级竞争力的道路上,将带给小伙伴们更多的公开技术教学和视频,感谢一路以来有你的支持。我们正在用实际行动来帮助小伙伴们构建一套成体系的图形学知识架构,你在我们这里获得的不止于那些毫无意义的代码,我们这里更多的是代码背后的故事,以及精准、透彻的理解。我们不会扔给人们一本书或者给个思路让人们去自学,我们是亲自来设计出好的课程,让人们明白到底背后还有哪些细节。

这里插播一个引擎大赛的消息,感兴趣的同学可以看一眼,这也是东汉书院的立项使命:

东汉书院:自研引擎大赛​zhuanlan.zhihu.com
82bb566dbca9ce4ff65405f0bf2a1294.png

Because points in OpenGL are rendered as axis-aligned squares, rotating the point sprite must be done by modifying the texture coordinates used to read the sprite’s texture or to analytically calculate its shape. To do this, you can simply create a 2D rotation matrix in the fragment shader and multiply it by gl_PointCoord to rotate it around the z axis. The angle of rotation could be passed from the vertex or geometry shader to the fragment shader as an interpolated variable. The value of the variable can, in turn, be calculated in the vertex or geometry shader or be supplied through a vertex attribute. Listing 9.34 shows a slightly more complex point sprite fragment shader that allows the point to be rotated around its center.

由于OpenGL在绘制点精灵的时候会按照轴对齐的方式去绘制四边形,所以如果你想旋转一个点精灵的话就必须要修改点精灵的纹理坐标或者去亲手计算它的形状。为了做到这一点,你可以简单粗暴的创建一个2D的 旋转矩阵,然后在fragment shader中使用它与gl_PointCoord相乘来让点精灵绕z轴旋转。输入的旋转角度可以从vertex shader或者是geometry shader中传入,然后插值得到。这样一来,这个变量的值就可以在 vertex shader计算得到或者geometry shader计算得到或者通过顶点的属性提供。清单9.34展示了一个相对更复杂一点的点精灵的fragment shader,它使得点精灵可以绕着它的中心点旋转。

#version 450 core
uniform sampler2D sprite_texture;
in float angle;
out vec4 color;
void main(void)
{const float sin_theta = sin(angle);const float cos_theta = cos(angle);const mat2 rotation_matrix = mat2(cos_theta, sin_theta, -sin_theta, cos_theta);const vec2 pt = gl_PointCoord - vec2(0.5);color = texture(sprite_texture, rotation_matrix * pt + vec2(0.5));
}

Listing 9.34: Naïve rotated point sprite fragment shader

This example allows you to generate rotated point sprites. However, the value of angle will not change from one fragment to another within the point sprite. That means sin_theta and cos_theta will be constant and the resulting rotation matrix constructed from them will be the same for every fragment in the point. It is therefore much more efficient to calculate sin_theta and cos_theta in the vertex shader and pass them as a pair of variables into the fragment shader rather than calculating them at every fragment. Here’s an updated vertex and fragment shader that allows you to draw rotated point sprites. First, the vertex shader is shown in Listing 9.35.

这个例子允许你去生成旋转的点精灵。然而,这个角度的值不会因为点精灵上所在像素位置的变化而变化。也就是说sin ——theta和cos_theta将是常量并且产生的结果旋转矩阵对于每个点上的所有像素来说都是一样的。 因此,相比在fragment shader中进行计算,在vertex shader中计算出sin_theta和cos_theta的值然后把它们传入fragment shader会更加的高效。下面展示了新版本的vertex shader和fragment shader的代码。首先, 清单9.35展示了vertex shader的代码。

#version 450 core
uniform matrix mvp;
in vec4 position;
in float angle;flat out float sin_theta;
flat out float cos_theta;
void main(void)
{sin_theta = sin(angle);cos_theta = cos(angle);gl_Position = mvp * position;
}

Listing 9.35: Rotated point sprite vertex shader

Next, the fragment shader is shown in Listing 9.36.

紧接着,清单9.36展示了fragment shader的代码

#version 450 core
uniform sampler2D sprite_texture;
flat in float sin_theta;
flat in float cos_theta;
out vec4 color;
void main(void)
{mat2 rotation_matrix = mat2(cos_theta, sin_theta, -sin_theta, cos_theta);vec2 pt = gl_PointCoord - vec2(0.5);color = texture(sprite_texture, rotation_matrix * pt + vec2(0.5));
}

Listing 9.36: Rotated point sprite fragment shader

As you can see, the potentially expensive sin and cos functions have been moved out of the fragment shader and into the vertex shader. If the point size is large, this pair of shaders performs much better than the earlier, brute-force approach of calculating the rotation matrix in the fragment shader.

如你所见到的一样,sin和cos函数已经从fragment shader中移到了vertex shader中去了。如果点的大小很大的话,这组shader的性能相对于之前的那个简单粗暴的在fragment shader中计算旋转矩阵会更好一点。

Even though you are rotating the coordinates you derived from gl_PointCoord, the point itself is still square. If your texture or analytic shape spills outside the unit diameter circle inside the point, you will need to make your point sprite larger and scale your texture coordinate down accordingly to get the shape to fit within the point under all angles of rotation. Of course, if your texture is essentially round, you don’t need to worry about this at all.

即便你旋转从gl_PointCoord中推导出来的纹理坐标,点精灵本身依然是一个矩形。如果你的纹理或者形状玩到了点精灵的外面,你需要把点精灵弄大一点并且给它一个缩放,让它的形状适应当前点精灵的旋转角度。当然 如果你的纹理基本上是个圆的的话,你不需要担心这个事情。

我们核心关注和讨论的领域是引擎的底层技术以及商业化方面的信息,可能并不适合初级入门的同学。官方相关信息主要包括了对市面上的引擎的各种视角的分析以及宏观方面的技术讨论,相关领域感兴趣的同学可以关注东汉书院以及图形之心公众号。

只言片语,无法描绘出整套图形学领域的方方面面,只有成体系的知识结构,才能够充分理解和掌握一门科学,这是艺术。我们已经为你准备好各式各样的内容了,东汉书院,等你来玩。



推荐阅读
  • 本文将介绍如何编写一些有趣的VBScript脚本,这些脚本可以在朋友之间进行无害的恶作剧。通过简单的代码示例,帮助您了解VBScript的基本语法和功能。 ... [详细]
  • 使用 Azure Service Principal 和 Microsoft Graph API 获取 AAD 用户列表
    本文介绍了一段通用代码示例,该代码不仅能够操作 Azure Active Directory (AAD),还可以通过 Azure Service Principal 的授权访问和管理 Azure 订阅资源。Azure 的架构可以分为两个层级:AAD 和 Subscription。 ... [详细]
  • DNN Community 和 Professional 版本的主要差异
    本文详细解析了 DotNetNuke (DNN) 的两种主要版本:Community 和 Professional。通过对比两者的功能和附加组件,帮助用户选择最适合其需求的版本。 ... [详细]
  • 本文详细介绍了Akka中的BackoffSupervisor机制,探讨其在处理持久化失败和Actor重启时的应用。通过具体示例,展示了如何配置和使用BackoffSupervisor以实现更细粒度的异常处理。 ... [详细]
  • Android 渐变圆环加载控件实现
    本文介绍了如何在 Android 中创建一个自定义的渐变圆环加载控件,该控件已在多个知名应用中使用。我们将详细探讨其工作原理和实现方法。 ... [详细]
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • Explore how Matterverse is redefining the metaverse experience, creating immersive and meaningful virtual environments that foster genuine connections and economic opportunities. ... [详细]
  • 本文详细介绍了如何在Linux系统上安装和配置Smokeping,以实现对网络链路质量的实时监控。通过详细的步骤和必要的依赖包安装,确保用户能够顺利完成部署并优化其网络性能监控。 ... [详细]
  • 1.如何在运行状态查看源代码?查看函数的源代码,我们通常会使用IDE来完成。比如在PyCharm中,你可以Ctrl+鼠标点击进入函数的源代码。那如果没有IDE呢?当我们想使用一个函 ... [详细]
  • 本文详细介绍了Java中org.eclipse.ui.forms.widgets.ExpandableComposite类的addExpansionListener()方法,并提供了多个实际代码示例,帮助开发者更好地理解和使用该方法。这些示例来源于多个知名开源项目,具有很高的参考价值。 ... [详细]
  • 在前两篇文章中,我们探讨了 ControllerDescriptor 和 ActionDescriptor 这两个描述对象,分别对应控制器和操作方法。本文将基于 MVC3 源码进一步分析 ParameterDescriptor,即用于描述 Action 方法参数的对象,并详细介绍其工作原理。 ... [详细]
  • 前言--页数多了以后需要指定到某一页(只做了功能,样式没有细调)html ... [详细]
  • XNA 3.0 游戏编程:从 XML 文件加载数据
    本文介绍如何在 XNA 3.0 游戏项目中从 XML 文件加载数据。我们将探讨如何将 XML 数据序列化为二进制文件,并通过内容管道加载到游戏中。此外,还会涉及自定义类型读取器和写入器的实现。 ... [详细]
  • 本文介绍了如何在C#中启动一个应用程序,并通过枚举窗口来获取其主窗口句柄。当使用Process类启动程序时,我们通常只能获得进程的句柄,而主窗口句柄可能为0。因此,我们需要使用API函数和回调机制来准确获取主窗口句柄。 ... [详细]
  • 本文详细解析了Python中的os和sys模块,介绍了它们的功能、常用方法及其在实际编程中的应用。 ... [详细]
author-avatar
mobiledu2502875393
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有