Direct3D中的绘制

2023-05-16

顶点缓存与索引缓存

一个顶点缓存是一个包含顶点数据的连续内存空间,一个索引缓存是一个包含索引数据的连续内存空间,之所以使用顶点缓存和索引缓存而非数组来存储数据,是因为顶点缓存和索引缓存可以被放置在显存中,进行绘制时,使用显存中的数据将获得比使用系统内存中的数据快的多的绘制速度。代码中顶点缓存使用接口IDirect3DVertexBuffer9表示,索引缓存使用接口IDirect3DIndexBuffer9表示。

	 HRESULT IDirect3DDevice9::CreateVertexBuffer(
		 UINT Length,
		 DWORD Usage,
		 DWORD FVF,		 //存储在顶点缓存中顶点的灵活顶点格式	
		 D3DPOOL Pool,	 //容纳缓存的内存池
		 IDirect3DVertexBuffer9** ppVertexBuffer, //用于接收所创建的顶点缓存的指针
		 HANDLE* pSharedHandle //不使用,设置为0
	 );

    HRESULT IDirect3DDevice9::CreateIndexBuffer(
		 UINT Length,
		 DWORD Usage,
		 D3DFORMAT Format, 
		 D3DPOOL Pool,
		 IDirect3DIndexBuffer9** ppIndexBuffer, //用于接收所创建的索引缓存的指针
		 HANDLE* pSharedHandle
	 );

Length:为缓存分配的字节数,如果想让顶点缓存足够存储8个顶点,改参数需设为8*sizeof(Vertex),Vertex是定义顶点的结构

Usage:指定关于如何使用缓存的一些附加属性,该值为可为0(表示无需附加属性)或是一下标记中的某一个或某种组合
D3DUSAGE_DYNAMIC:将缓存设为动态缓存
D3DUSAGE_POINTS:规定缓存将用于存储点图元
D3DUSAGE_SOFTWAREPROCESSING:指定软件顶点运算方式
D3DUSAGE_WRITEONLY:规定应用程序对缓存的操作模式为"只写",这样驱动程序就可以将缓存放在最适合写操作的内存地址中,对使用该标记创建的缓存进行读操作将会出错。

Format:指定索引大小,设置为D3DFMT_INDEX16表示16为索引,设为D3DFMT_INDEX32表示32位索引,并非所有图形设备都支持32位索引,如需使用请检查硬件性能

静态缓存:创建缓存时未使用标记D3DUSAGE_DYNAMIC,则为静态缓存,静态缓存一般被放置在显存中,以保证存储于其中的数据得到最高效的处理,静态缓存是以牺牲对静态缓存读写操作的速度为代价的,这是因为访问显存的速度本身就很慢,所以我们用静态缓存来存储静态数据(那些不需要经常修改或访问的数据)。例如地形和城市建筑数据就很适合存储在静态缓存中,这类数据在程序运行时通常不需要进行修改,静态缓存必须在应用程序初始化时用几何体的数据进行填充。

动态缓存:创建缓存时使用标记D3DUSAGE_DYNAMIC,则为动态缓存,动态缓存一般放置在AGP存储区中,其内容可被迅速更新,动态缓存中数据的处理速度不像静态缓存那样快,这是因为在绘制前数据必须传输到显存中,但动态缓存的突出优点是其更新速度相当快(快速的CPU写操作)。所以如果需要频繁更新缓存中的内容,该缓存应设置为动态的。粒子系统就是使用动态缓存的一个很好例子,因为粒子是活动的,所以需要对每帧图像中粒子的几何布局进行更新。另外,对显存和AGP存储区进行读操作非常慢,所以需要在程序运行时读取几何数据,最好再系统内存中保留一份副本,然后在需要时对其进行读操作

//创建一个可容纳8个Vertex类型的顶点静态顶点缓存
	IDirect3DVertexBuffer9* vb;
	Device->CreateVertexBuffer(
		8 * sizeof(Vertex),
		0,
		D3DFVF_XYZ,
		D3DPOOL_MANAGED,
		&vb,
		0);

	//创建可容纳36个16位索引的动态索引缓存
	IDirect3DIndexBuffer9* ib;
	Device->CreateIndexBuffer(
		36 * sizeof(WORD),
		D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY,
		D3DFMT_INDEX16,
		D3DPOOL_MANAGED,
		&ib,
		0);

访问缓存内容

为了访问缓存中的数据,需要获得指向缓存内部存储区的指针,可以借助方法Lock来获取指向缓存内容的指针,对缓存访问完毕后,必须对缓存进行解锁unlock,只要获取了指向缓存内容的指针,就可以对其内容进行读写操作(如果使用了D3DUSAGE_WRITEONLY标记,则无法对该缓存进行读操作,否则会导致读取失败)。

	HRESULT IDirect3DVertexBuffer9::Lock(
		UINT OffsetToLock,
		UINT SizeToLock,
		void** ppbData,
		DWORD Flags
	);

	HRESULT IDirect3DIndexBuffer9::Lock(
		UINT OffsetToLock,
		UINT SizeToLock,
		void** ppbData,
		DWORD Flags
	);

OffsetToLock:自缓存的起始点开始锁定的位置的偏移量,单位为字节
SizeToLock:所要锁定的字节数
ppbData:指向被锁定的存储区起始位置的指针
Flags:该标记描述了锁定的方式,可以是0,也可是下列标记之一或某种组合
D3DLOCK_DISCARD:该标记仅用于动态缓存它指示硬件将缓存内容丢弃,并返回一个指向重新分配的缓存的指针,该标记十分有用,因为这允许在我们访问新分配的内存时,硬件能够继续使用被丢弃的缓存中的数据进行绘制,这样硬件的绘制就不会中止。
D3DLOCK_NOOVERWRITE:该标记仅用于动态缓存,使用该标记后,数据只能以追加方式写入缓存,即不能覆盖当前用于绘制的存储区中任何内容,这十分有用,因为它可保证在往缓存中增加数据时,硬件仍可持续进行绘制。
D3DLOCK_READONLY:该标记表示对于锁定的缓存只可读而不可写,利用这一点可以作一些内部优化。

标记D3DLOCK_DISCARDD3DLOCK_NOOVERWRITE表明缓存区的某一部分在锁定之后可以使用(用于绘制),如果环境(硬件配置)允许使用这些标记,在对缓存进行锁定时,其他操作就不会中断

获取顶点缓存和索引缓存的信息

	D3DVERTEXBUFFER_DESC vbDescription;
	vertexBuffer->GetDesc(&vbDescription);  //get vb info

	D3DINDEXBUFFER_DESC ibDescription;
	indexBuffer->GetDesc(&ibDescription);	//get ib info
/* Vertex Buffer Description */
typedef struct _D3DVERTEXBUFFER_DESC
{
    D3DFORMAT           Format;
    D3DRESOURCETYPE     Type;
    DWORD               Usage;
    D3DPOOL             Pool;
    UINT                Size;

    DWORD               FVF;

} D3DVERTEXBUFFER_DESC;

/* Index Buffer Description */
typedef struct _D3DINDEXBUFFER_DESC
{
    D3DFORMAT           Format;
    D3DRESOURCETYPE     Type;
    DWORD               Usage;
    D3DPOOL             Pool;
    UINT                Size;
} D3DINDEXBUFFER_DESC;

绘制状态

Direct3D封装了多种绘制状态,这些绘制状态将影响几何体的绘制方式,各种绘制状态都有默认值,自指定某种绘制状态起,直至该状态被修改,该状态始终有效。

	HRESULT IDirect3DDevice9::SetRenderState(
		D3DRENDERSTATETYPE State,	//绘制状态枚举
		DWORD Value					//状态对应的具体枚举值
	);

绘制的准备工作

一旦我们创建了顶点缓存以及索引缓存(可选),基本上已经可以准备对其所存储的内容进行绘制了,在绘制前还有3个步骤需要完成。

1.指定数据流输入源:将顶点缓存和数据流进行链接,实质上是将几何体的信息传输到绘制流水线中。

	HRESULT IDirect3DDevice9::SetStreamSource(
		UINT StreamNumber, 
		IDirect3DVertexBuffer9* pStreamData, 
		UINT OffsetInBytes, 
		UINT Stride
	);

StreamNumber:标识与顶点缓存建立链接的数据流,如果不使用多个流,则设置为0即可
pStreamData:指向我们希望与给定数据流建立链接的顶点缓存的指针
OffsetInBytes:自数据流的起始点算起的一个偏移量,单位为字节,指定了将被传输至绘制流水线的顶点数据的起始位置,如果想将该参数设为某一个非0值,请务必检查D3DCAPS9结构中的D3DDEVCAPS2_STREAMOFFSET标记,已判断设备是否支持该功能(顶点运算功能校验)。
Stride:将要链接到数据流的顶点缓存中每个元素的大小,单位为字节

Device->SetStreamSource(0, vb, 0, sizeof(Vertex));

2.设置顶点格式:在这里指定后续绘制调用中使用的顶点格式

Device->SetFVF(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1);

3.设置顶点缓存:如果我们想使用索引缓存,必须对后续绘制操作中所要使用的索引缓存进行设置,任意时刻只允许使用一个索引缓存,如果要使用一个不同的索引缓存绘制物体时,必须进行切换

Device->SetIndices(_ib); //参数为IDirect3DIndexBuffer9指针

使用顶点缓存和索引缓存进行绘制

缓存创建完毕且准备工作完成后,便可对几何体进行绘制,也就是使用DrawPrimitiveDrawIndexedPrimitive方法将待绘制几何体的信息通过绘制流水线传输,这两个方法从顶点顶点数据流中获取顶点信息,并从当前设定的索引缓存中提取索引信息。

HRESULT IDirect3DDevice9::DrawPrimitive(
		D3DPRIMITIVETYPE PrimitiveType, 
		UINT StartVertex, 
		UINT PrimitiveCount
	);

PrimitiveType:所要绘制的图元类型,绘制三角形则使用D3DPT_TRIANGLELIST,除此之外还可以绘制点和线。
StartVertex:顶点数据流中标识顶点数据读取起点的元素索引,该参数赋予了我们一定自由度,使得我们可以只对顶点缓存中的某一部分进行绘制
PrimitiveCount:所要绘制的图元数量

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

Direct3D中的绘制 的相关文章

  • Direct3D中的绘制

    顶点缓存与索引缓存 一个顶点缓存是一个包含顶点数据的连续内存空间 xff0c 一个索引缓存是一个包含索引数据的连续内存空间 xff0c 之所以使用顶点缓存和索引缓存而非数组来存储数据 xff0c 是因为顶点缓存和索引缓存可以被放置在显存 中
  • cuda学习笔记之异步并行执行

    异步函数使得主机端与设备端并行执行 控制在设备还没有完成前就被返回给主机线程 包括 kernel启动 以Async为后缀的内存拷贝函数 device到device内存拷贝函数 存储器初始化函数 比如cudaMemset cudaMemset
  • DirectX11 顶点和顶点布局

    顶点和顶点布局 1 如何描述顶点 5 5 1节已经讲过 在Direct3D中 顶点由空间位置和各种附加属性组成 Direct3D可以让我们灵活地建立属于我们自己的顶点格式 换句话说 它允许我们定义顶点的分量 要创建一个自定义的顶点格式 我们
  • 没有找到 d3dx11.lib?

    我使用 Windows 8 Visual Studio 2012 C 11 和 Direct3D 11 进行开发 我包含这样的 Direct3D 库 pragma comment lib dxgi lib pragma comment li
  • 在c#中捕获游戏屏幕截图最快的方法?(每秒超过20张图像)

    如何快速截取整个游戏屏幕 大约每秒 20 30 次 我想将它们转换为视频 1 我尝试过 WMEncoder 结果是 WMEncoder 只能使用一组预配置的编解码器以视频格式 wma 捕获屏幕和屏幕区域 29 fps 最佳编码结果 WMEn
  • 用于非游戏相关 3D 图形编程的托管 Direct3D 或 XNA?

    哪种是进行 NET 3D 图形编程的首选方法 Direct3D 或 XNA 似乎是当前的技术 但哪一种最适合非游戏相关的编程 另外 Managed Direct 3D 是否已经停止 XNA 似乎并不真正适合非游戏开发 是的 可惜 MS 停止
  • Opengl 和 Webgl:从附加到当前帧缓冲区的纹理中采样

    我有一个带有两个纹理的帧缓冲区t0 and t1随附的 在第一遍中 我使用多个片段着色器输出渲染它们 在第二遍之前 我执行以下操作 打开仅具有一个输出的着色器 Bind t1到纹理单元 调用 glDrawBuffers 禁用写入t1的附件
  • 使用“乘法”混合模式和 Alpha 的 Direct3D 渲染 2D 图像

    我正在尝试将 Photoshop 滤镜与 Direct3D 相乘 我一直在阅读和谷歌搜索不同的渲染状态 并且效果几乎可以正常工作 问题是它忽略了纹理的 alpha 值 这是解释这种情况的图像 http www kloonigames com
  • 如何提高 Direct3D 流纹理性能?

    我正在尝试加速全屏纹理的绘制 该纹理会改变每一帧 在我的系统上 使用 GDI 和 BitBlt 可以获得大约 1000 FPS 但我认为可以通过使用 Direct3D 和动态纹理来提高性能 相反 我只能获得 250 FPS 左右 我在配备
  • 在 DirectX 中显示视频

    在使用 XAudio2 和 Direct3D9 10 的应用程序中显示视频 带声音 的最佳 最简单方法是什么 至少它需要能够传输可能更大的视频 并考虑到窗口宽高比可能与视频不同的事实 例如通过添加信箱 尽管理想情况下我希望能够将视频嵌入到3
  • 使用 SlimDX 设置常量缓冲区

    我一直在关注 Microsoft Direct3D11 教程 但使用 C 和 SlimDX 我正在尝试设置常量缓冲区 但不确定如何创建或设置它 我只是尝试使用常量缓冲区设置三个矩阵 世界 视图和投影 但我在每个阶段 创建 数据输入并将其传递
  • Direct3D 中的 COM 对象

    正如 Microsoft 文档中提到的 有两种创建 COM 对象的方法 实现该对象的模块可能提供专门设计用于创建该对象的实例的函数 或者 COM 提供了一个通用创建函数 名为CoCreateInstance 在 direct3D 中 您可以
  • 如何使用 D3DPT_TRIANGLESTRIP 基元类型在 DirectX 中绘制两个分离的矩形

    我是 DirectX 新手 我正在尝试使用以下命令在一个场景中绘制两个矩形D3DPT TRIANGLESTRIP 一个矩形没问题 但两个矩形则完全不同 是的 我可以使用用 绘制的四个三角形来绘制它们D3DPT TRIANGLELIST原始类
  • 当我每帧向单个顶点缓冲区写入数千次时,如何提高 Direct3D 的性能?

    我正在尝试编写一个 OpenGL 包装器 它允许我使用所有现有的图形代码 为 OpenGL 编写 并将 OpenGL 调用路由到 Direct3D 等效项 到目前为止 这种方法的效果出人意料地好 只是性能被证明是一个很大的问题 现在 我承认
  • 将纹理复制到纹理

    我已经完成了 2 个使用共享资源的程序 在 SlimDX 和 DirectX10 上运行 一个程序将在 3D 网格上显示共享纹理 第二个程序将加载图像作为纹理 到目前为止 每次从新图像更新纹理时 我都需要传递共享处理 现在 有没有一种方法可
  • Direct3D 10 是否有 COM 暴露

    先生们 尊敬的女士们 我在 Code Project 的 COM 论坛上发布了这个问题 并得到了一个傲慢的回复 希望对您有所帮助 我看到 Microsoft 有一个用于 Direct3D 9 的 COM 库 其 GUID 为 81BDCBC
  • DirectX/OpenGL 中的三角形绘制顺序

    3D API 中绘制三角形的顺序是否保证与其在索引缓冲区中的顺序相同 例如 如果我在一次绘制调用中有两个重叠的三角形 并且禁用深度测试 那么第一个或第二个三角形最终是否可见 或者我是否需要发出单独的绘制调用以确保第二个三角形出现在第一个三角
  • 将按钮控件嵌入到现有 Direct3D 应用程序中

    我想将自己的内容覆盖在 Direct3D v9 游戏 由第三方制作 之上 叠加互动按钮 具体来说 我想覆盖一个可点击的按钮控件 就像 Steam 所做的那样 尽管我正在尝试一个更简单的界面 理想情况下 我能够覆盖 WPF 按钮或 Windo
  • 超出 CreateConstantBufferView 处虚拟地址的末尾

    我正在遵循 使用 DirectX12 进行游戏编程 ch 6 代码 但在 ID3DDevice CreateConstantBufferView 中 我发现 D3D12 错误 D3D12 错误 ID3D12Device CreateCons
  • XNA中窗口系统的渲染策略(RenderTarget性能)

    我目前正在从头开始为 XNA 游戏创建一个窗口系统 我主要针对 Windows 进行开发 但谁知道我将来可能支持哪些平台 如果您知道本机 Direct3D 的这一点 请随意回答 因为性能语义应该类似 如果可能 请考虑如果目标平台是 X Bo

随机推荐

  • Linux系统tcp连接设置

    目录 net ipv4 tcp syn retriesnet ipv4 ip local port rangenet core somaxconnnet ipv4 tcp max syn backlognet core netdev max
  • 一种简单有效的锂电池充电均衡电路

    一种简单有效的锂电池充电均衡电路 这个均衡电路用的是三个一模一样的并联稳压电路组成的 xff0c 每个电池上并一个 电路原理图如下 xff1a 每个稳压电源都调节到4 2V 均衡的原理是 xff0c 当电池电压都小于4 2V时 xff0c
  • 【嵌入式开发工具】Makefile和Cmake

    工具配置 首先 xff0c 方便代码编辑 xff0c 安装sublime和vim xff0c 其中安装sublime过程见下 https blog csdn net yunna520 article details 114021153 注意
  • Arduino Uno PWM和IRremote库冲突问题

    问题发生环境 xff1a Arduino UNO R3控制板 xff0c 用两个L298N驱动板驱动4轮小车 xff0c 然后通过控制4路PWM来控制4个轮子的速度 xff0c 遥控方式为红外遥控 xff0c 使用的红外库是IRremote
  • [ERROR] 两个jar包中存在Qualified Name完全相同的引用冲突问题 解决方案

    分析 最近在搞Jedis xff0c 在引入jedis 2 9 0 jar和commons pool2 2 4 2 jar后初始化JedisPoolConfig时 xff0c 发现很多属性无法设置 xff08 如最大空闲连接等 xff09
  • 如何使用Visual studio C++(VC++)编译C?图解,详!!!

    如何使用Visual studio C 43 43 xff08 VC 43 43 xff09 编译C xff1f 图解 xff0c 详 xff01 xff01 xff01 之前在网上找过关于这方面的东西 xff0c 但是一直都没有看到有详细
  • 头文件与类的声明

    我们在开始学习C 43 43 时 xff0c 就应该养成规范大气的编程习惯 xff0c 头文件 header 的布局就是其中很重要的一个点 我们需要知道头文件中的防卫式声明 ifndef COMPLEX define COMPLEX 前置声
  • ubuntu C++ 和windows C# socket TCP通信

    TCP客户端代码 windows C https www cnblogs com sunev archive 2012 08 05 2604189 html using System using System Net using Syste
  • 多进程和多线程的优缺点

    在Linux下编程多用多进程编程少用多线程编程 IBM有个家伙做了个测试 xff0c 发现切换线程context的时候 xff0c windows比linux快一倍多 进出最快的锁 xff08 windows2k的 critical sec
  • 【C语言】链表及单链表基本操作

    1 什么是链表 xff1f 链表的分类 xff1f 链表是一种物理存储结构上非连续 非顺序的存储结构 xff0c 数据元素的逻辑顺序是通过链表中的指针链接次序实现的 数据结构中 xff1a 2 链表的分类 共有8种链表结构 3 单链表的基本
  • 14串聚合物锂电池保护板和电路图(带均衡功能)

    转载自 xff1a http bbs mydigit cn read php tid 61 746827 之前发过14串三元锂组装的帖子 xff0c 有坛友对保护板感兴趣 xff0c 还有的说串联充电 xff0c 早死早超生 xff0c 哈
  • HTTP的长连接和短连接

    一 什么是长连接 HTTP1 1规定了默认保持长连接 xff08 HTTP persistent connection xff0c 也有翻译为持久连接 xff09 xff0c 数据传输完成了保持TCP连接不断开 xff08 不发RST包 不
  • libcurl库的异步用法

    multi接口的使用会比easy 接口稍微复杂点 xff0c 毕竟multi接口是依赖easy接口的 xff0c 首先粗略的讲下其使用流程 xff1a curl multi init初始化一个multi curl对象 xff0c 为了同时进
  • 在ubantu16.04 配置ROS开发realsense435功能包

    本文主要对intel的一款实感相机realsense435 进行配置 xff0c 将ROS对realsense435支持的功能包进行安装 一 安装SDK 1 简要介绍 鉴于自己安装过程中出现的问题 xff0c 现在在安装之前先确认几件事情
  • 提高C++程序运行效率,减少运行时间的方法

    大致方法 xff1a 1 优化业务逻辑 xff0c 尽量少做事情 2 减少网络访问 xff0c IO等对外操作 3 如果有数据库 xff0c 优化SQL和数据库结构 4 优化算法 xff0c 比如冒泡排序改成快排等 5 优化代码的编写 这个
  • 常量引用、非常量引用、临时对象

    转载自 xff1a https www cnblogs com littleant archive 2012 08 01 2618846 html https www cnblogs com BensonLaur p 5234555 htm
  • 字符串string中“\0“与‘\0‘的打印、拼接问题

    1 34 0 34 为字符串长度为0的字符串指针 xff0c 它与 34 34 等价 2 打印 34 0 34 与 39 0 39 相同 xff0c cout输出时都会显示为空 39 0 39 在string的初始化和拼接中size大小的不
  • Direct3D的初始化

    1 获取接口IDirect3D9 的指针 xff0c 该接口用于获取系统中物理硬件设备的信息并创建接口IDirect3DDevice9 xff0c 该接口是一个C 43 43 对象 xff0c 代表了我们用来显示3D图形的物理硬件设备 使用
  • 绘制流水线

    顶点结构与顶点格式 在Direct3D中 xff0c 顶点除了包含空间信息外 xff0c 还可以包含其他的附加属性 xff0c 例如顶点可以有颜色属性 xff0c 也可以有法线属性 xff0c Direct3D赋予了我们自定义顶点格式的自由
  • Direct3D中的绘制

    顶点缓存与索引缓存 一个顶点缓存是一个包含顶点数据的连续内存空间 xff0c 一个索引缓存是一个包含索引数据的连续内存空间 xff0c 之所以使用顶点缓存和索引缓存而非数组来存储数据 xff0c 是因为顶点缓存和索引缓存可以被放置在显存 中