用DirectX实现动态纹理

简介:

什么是动态纹理

动态纹理是相对于常规的纹理而言的,通常的纹理都是静态的,而动态纹理就是模型保持不动,而纹理动态变化,凡是能够对模型应用的变换,也能作用于纹理,比如平移,旋转,缩放,投影,shear等都不在话下,使用动态纹理可以模拟很多现象,最常见的就是Dynamic cloud。

如何实现动态纹理

话说这个问题还是我在一次面试的时候遇到的。

面试官:怎样让一个纹理动起来

我:让模型动起来即可

面试官:如果不允许移动模型呢?只动纹理

我:。。。

其实这个问题并不难,只要明白一点,纹理也是有坐标的,既然有坐标,就可以改变位置,位置可以改变,就能做出动态效果来。普通的纹理坐标都是二维的,用(u, v)来表示,这里u表示横坐标,从左到右递增,v表示纵坐标,从上到下递增,如下图

 

纹理效果的本质无非是按照一定的规则动态变化uv坐标而已,由于这里的纹理都是二维的,所以变换矩阵是三维的(通常DX的变换矩阵都是四维的)。来看一下三个变换矩阵 

平移矩阵(沿着u坐标方向移动Tu距离,沿着v坐标方向移动Tv距离)

旋转矩阵(旋转角度:θ,旋转方向:逆时针。关于旋转方向,DX帮助文档中是这么描述的,Angles are measured clockwise when looking along the rotation axis toward the origin. 也就是沿着旋转轴朝原点看是顺时针方向,而Z轴指向屏幕内部的,所以我们看到的旋转就是逆时针方向)

 

缩放矩阵(u坐标缩放Su倍,v坐标缩放Sv倍)

代码

准备工作,设置纹理的渲染状态及寻址模式,为了使纹理能够循环显示,需要指定纹理的寻址方式为D3DTADDRESS_WRAP

// Texture state
g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR );
g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP );
g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP );

下面的函数是最关键的部分,所有的动态效果都在这里实现,平移是按照u方向进行的,也就是横坐标平移,旋转是绕z轴逆时针旋转,缩放是循环进行的,如果到达最大最小边界,则会反向缩放。这里我们把所有的变换都放到一个矩阵中,最后使用SetTransform应用这个矩阵即可,这和设置模型的世界矩阵是一个道理。

复制代码
void UpdateTextureCoordinates(float timeDelta)
{
g_pd3dDevice->SetTextureStageState(0,
D3DTSS_TEXTURETRANSFORMFLAGS,
D3DTTFF_COUNT2);

if (g_EffectFlag ==1) // Translation
{
// Translate
matTexture._31 += timeDelta /3 ;
}
elseif (g_EffectFlag ==2) // Rotation
{
angle += timeDelta ; // increasing total angle
matTexture._11 = cosf(angle) ;
matTexture._12 = sinf(angle) ;
matTexture._21 =-sinf(angle) ;
matTexture._22 = cosf(angle) ;
}
elseif (g_EffectFlag ==3) // Scaling
{
// if the picture is too small, increasing
if (matTexture._11 <0.2)
g_Factor =-g_Factor ;

// if the picture is too large, decreasing
if (matTexture._11 >5.0f)
g_Factor =-g_Factor ;

matTexture._11 += timeDelta * g_Factor;
matTexture._22 += timeDelta * g_Factor;
}

g_pd3dDevice->SetTransform(D3DTS_TEXTURE0, &matTexture) ;
}
复制代码

几个需要注意的问题

注意纹理的缩放与普通模型的缩放是不同的,确切的说是完全相反,因为纹理的缩放完全是靠u,v坐标来实现的,所以坐标值越大,纹理反而越小,坐标值越小,纹理反而越大。(为什么?

旋转貌似只能沿着XOY平面进行,其他的情况我还没有试过,因为纹理坐标是二维的,且位于XOY面,故二维纹理只能绕Z轴旋转。

旋转和缩放都是以纹理坐标原点(0, 0)点为参照的(通常是纹理图片的左上角),如果要以矩形纹理的中心为旋转点,则需要先平移,在旋转,最后再平移回去。 

效果 

原始图

平移效果

旋转效果

缩放效果

上面的图片都是静态的,不是很直观,大家可以下载下面的程序看看动态效果

示例程序下载(使用方法,T键-平移,R键-旋转,S键-缩放)

Happy Coding!

== The End ==


本文转自zdd博客园博客,原文链接:http://www.cnblogs.com/graphics/archive/2010/12/19/1910172.html,如需转载请自行联系原作者

相关文章
|
存储 Kubernetes 监控
基于Kubernetes的电商平台部署:实现高可用、弹性伸缩与容器化管理
基于Kubernetes的电商平台部署:实现高可用、弹性伸缩与容器化管理
|
11月前
|
人工智能 前端开发 PyTorch
【AI系统】动态图与静态图转换
从 TensorFlow、PyTorch 到 PaddlePaddle、MindSpore、MegEngine,主流 AI 框架经历了动静分离、动静结合到动静统一的发展过程。这些框架通过动态图转静态图技术,实现了计算效率与灵活性的平衡,显著提升了 AI 开发效率和产品应用的便利性。
380 14
网络中的半双工与全双工
【8月更文挑战第24天】
2391 0
|
数据采集 Web App开发 监控
高效爬取B站评论:Python爬虫的最佳实践
高效爬取B站评论:Python爬虫的最佳实践
|
JavaScript 前端开发 测试技术
精通Selenium:从基础到高级的网页自动化测试策略
【10月更文挑战第6天】随着Web应用变得越来越复杂,手动进行功能和兼容性测试变得既耗时又容易出错。自动化测试因此成为了现代软件开发不可或缺的一部分。Selenium是一个强大的工具集,它支持多种编程语言(包括Python),允许开发者编写脚本来模拟用户与Web页面的交互。本文将带领读者从Selenium的基础知识出发,逐步深入到高级的应用场景,通过丰富的代码示例来展示如何高效地进行网页自动化测试。
1976 5
|
C++
C++ 多线程之线程管理函数
这篇文章介绍了C++中多线程编程的几个关键函数,包括获取线程ID的`get_id()`,延时函数`sleep_for()`,线程让步函数`yield()`,以及阻塞线程直到指定时间的`sleep_until()`。
293 0
C++ 多线程之线程管理函数
|
消息中间件 Ubuntu Java
Ubuntu系统上安装Apache Kafka
Ubuntu系统上安装Apache Kafka
|
测试技术 C# 图形学
掌握Unity调试与测试的终极指南:从内置调试工具到自动化测试框架,全方位保障游戏品质不踩坑,打造流畅游戏体验的必备技能大揭秘!
【9月更文挑战第1天】在开发游戏时,Unity 引擎让创意变为现实。但软件开发中难免遇到 Bug,若不解决,将严重影响用户体验。调试与测试成为确保游戏质量的最后一道防线。本文介绍如何利用 Unity 的调试工具高效排查问题,并通过 Profiler 分析性能瓶颈。此外,Unity Test Framework 支持自动化测试,提高开发效率。结合单元测试与集成测试,确保游戏逻辑正确无误。对于在线游戏,还需进行压力测试以验证服务器稳定性。总之,调试与测试贯穿游戏开发全流程,确保最终作品既好玩又稳定。
915 4
|
传感器 人机交互 vr&ar
VR技术的基本原理与发展历程:探索虚拟现实的无限可能
【8月更文挑战第24天】VR技术作为一项具有广阔前景和巨大潜力的技术,正在不断改变着我们的世界。让我们共同期待VR技术在未来的更多精彩表现吧!
3691 2
|
Java 测试技术 图形学
UE Actor生命周期
UE Actor生命周期