d3d12龙书阅读----Direct3D的初始化

这篇具有很好参考价值的文章主要介绍了d3d12龙书阅读----Direct3D的初始化。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

d3d12龙书阅读----Direct3D的初始化

使用d3d我们可以对gpu进行控制与编程,以硬件加速的方式来完成3d场景的渲染,d3d层与硬件驱动会将相应的代码转换成gpu可以执行的机器指令,与之前的版本相比,d3d12大大减少了cpu的开销,同时也改进了对多线程的支持,但是使用的api也更加复杂。
接下来,我们将先介绍在d3d初始化中一些重要的概念,之后通过具体的代码进行介绍。

组件对象模型(com)

COM 在 D3D 编程中提供了一种结构化和标准化的方式来处理对象和接口,有助于简化图形编程的复杂性,并提高代码的兼容性和可维护性
在使用com对象时,com对象会统计其引用次数,因此,在使用完com接口之后,我们需要使用它的release方法,当com对象的引用次数为0时,它将自己释放它所占的内存。
为了辅助管理com对象的生存周期,我们可以使用Microsoft::WRL::ComPtr类,我们可以把它当做是com对象的智能指针,当一个ComPtr超出了作用域的范围,它便会自动调用相应Com对象的release方法,免去了我们手动调用的麻烦。

定义举例:

//DXGI接口
Microsoft::WRL::ComPtr<IDXGIFactory4> mdxgiFactory;
Microsoft::WRL::ComPtr<IDXGISwapChain> mSwapChain;
//D3D接口
Microsoft::WRL::ComPtr<ID3D12Device> md3dDevice;

Microsoft::WRL::ComPtr<ID3D12Fence> mFence;
UINT64 mCurrentFence = 0;

Microsoft::WRL::ComPtr<ID3D12CommandQueue> mCommandQueue;
Microsoft::WRL::ComPtr<ID3D12CommandAllocator> mDirectCmdListAlloc;
Microsoft::WRL::ComPtr<ID3D12GraphicsCommandList> mCommandList;

static const int SwapChainBufferCount = 2;
int mCurrBackBuffer = 0;
Microsoft::WRL::ComPtr<ID3D12Resource> mSwapChainBuffer[SwapChainBufferCount];
Microsoft::WRL::ComPtr<ID3D12Resource> mDepthStencilBuffer;

Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> mRtvHeap;
Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> mDsvHeap;

comptr的常用方法:

1.Get方法:返回一个指向此底层com接口的指针 一般将原始的接口指针作为参数传递给函数
Microsoft::WRL::ComPtr<ID3D12CommandQueue> mCommandQueue;
ThrowIfFailed(mdxgiFactory->CreateSwapChain(
	mCommandQueue.Get(),
	&sd, 
	mSwapChain.GetAddressOf()));
2.GetAddress方法:返回指向此底层com接口指针的地址 凭借此方法可利用函数参数返回接口指针
Microsoft::WRL::ComPtr<IDXGISwapChain> mSwapChain;
ThrowIfFailed(mdxgiFactory->CreateSwapChain(
	mCommandQueue.Get(),
	&sd, 
	mSwapChain.GetAddressOf()));
3.Reset方法:将comptr设置为nullptr并且释放与之相关的所有引用
Microsoft::WRL::ComPtr<ID3D12Resource> mDepthStencilBuffer;
mDepthStencilBuffer.Reset();

纹理

在本书中,纹理涉及的范围较广,可以把它看成是由数据元素构成的矩阵(1D/2D/3D),可以存储贴图信息与缓冲区信息等等。

缓冲区包括前台缓冲区,后台缓冲区,深度缓冲区,模版缓冲区等等。
其中前台与后台缓冲区,前台缓冲区存储的是当前显示在屏幕上的图像数据,而下一帧的图像数据绘制在后台缓冲区中,当后台缓冲区绘制完成之后,两种缓冲区的角色互换,只需交换两个缓冲区的指针即可,如下图所示:
d3d12龙书阅读----Direct3D的初始化

这种方法又被称为双缓冲,而还有一种方法被叫做三缓冲,是为了解决gpu渲染速度与显示器的刷新率之间的矛盾:
在三重缓冲中,有一个正在显示的缓冲区,一个等待显示的缓冲区,和一个正在由 GPU 渲染的缓冲区。当 GPU 完成渲染时,它会将渲染好的帧移到等待显示的缓冲区。当显示器准备好刷新时,它会显示等待中的帧,并将之前显示的帧移动到渲染队列。这样,GPU 可以继续渲染下一帧,而不必等待显示器的刷新。

对于纹理而言,其中存储的数据格式并不是固定的,而是受到一定的限制,常用的设置数据格式有:
d3d12龙书阅读----Direct3D的初始化

描述符

描述符是d3d中的又一重要概念,在发出绘制命令之前,我们需要将本次draw call的相应资源绑定到渲染流水线上,但是这一过程并不是直接将资源绑定,而是通过描述符来完成。
通过中间层描述符,有几大好处:

  1. 不同的描述符可以指定不同的资源
  2. 通过描述符可以为GPU解释资源 将资源使用到渲染流水线的不同阶段 告知资源如何使用(我们可以为一个资源创建两个不同的描述符)
  3. 可以使用描述符来绑定资源的局部数据
  4. 资源在创建时采用了无类型格式,描述符可以为其指明具体的类型
    常用的描述符可分为以下几类:
    d3d12龙书阅读----Direct3D的初始化
    描述符堆中存有一系列描述符,本质上是存放某种特定类型描述符的一块内存:
//描述符堆的描述符的定义
 Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> mRtvHeap;
 Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> mDsvHeap;
 D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc;
 rtvHeapDesc.NumDescriptors = SwapChainBufferCount;
 rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
 rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
 rtvHeapDesc.NodeMask = 0;
 ThrowIfFailed(md3dDevice->CreateDescriptorHeap(
    &rtvHeapDesc, IID_PPV_ARGS(mRtvHeap.GetAddressOf())));
//描述符的定义
 Microsoft::WRL::ComPtr<ID3D12Resource> mDepthStencilBuffer;
 D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc;
 dsvDesc.Flags = D3D12_DSV_FLAG_NONE;
 dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
 dsvDesc.Format = mDepthStencilFormat;
 dsvDesc.Texture2D.MipSlice = 0;
 md3dDevice->CreateDepthStencilView(mDepthStencilBuffer.Get(), &dsvDesc, DepthStencilView());

CPU与GPU的交互

命令列表,命令队列与命令分配器

每个gpu都会至少维护一个命令队列(本质上是一个ring buffer,环形缓冲区),cpu可利用命令列表将其中的命令提交给gpu执行,同时命令列表里面的命令存储于命令分配器上,命令队列是从命令分配器中来提取命令。
总结一下:

 在头文件中加入相应com接口的定义
 //命令队列
 Microsoft::WRL::ComPtr<ID3D12CommandQueue> mCommandQueue;
 //命令分配器
 Microsoft::WRL::ComPtr<ID3D12CommandAllocator> mDirectCmdListAlloc;
 //命令列表
 Microsoft::WRL::ComPtr<ID3D12GraphicsCommandList> mCommandList;
之后进行初始化
void D3DApp::CreateCommandObjects()
{
	//填写命令队列结构体
	D3D12_COMMAND_QUEUE_DESC queueDesc = {};
	queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
	queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
	//创建命令队列
	//IID_PPV_ARGS 将COM ID类型转换为void**类型 作为函数参数
	ThrowIfFailed(md3dDevice->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&mCommandQueue)));
    
	//创建命令分配器
	ThrowIfFailed(md3dDevice->CreateCommandAllocator(
		D3D12_COMMAND_LIST_TYPE_DIRECT,
		IID_PPV_ARGS(mDirectCmdListAlloc.GetAddressOf())));
    
	//创建命令列表
	ThrowIfFailed(md3dDevice->CreateCommandList(
		0,
		D3D12_COMMAND_LIST_TYPE_DIRECT,
		mDirectCmdListAlloc.Get(), // 关联命令分配器
		nullptr,                   
		IID_PPV_ARGS(mCommandList.GetAddressOf())));

	//起始时让命令列表处于关闭状态 因为我们在使用命令列表前需要对其进行reset操作(安全地复用旧列表所占用的底层内存)而在reset之前需要关闭命令列表
	mCommandList->Close();
}
向命令列表中加入命令
mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(),
	D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET));
mCommandList->RSSetViewports(1, &mScreenViewport);
mCommandList->RSSetScissorRects(1, &mScissorRect);
将命令列表提交给命令队列 然后执行
ID3D12CommandList* cmdsLists[] = { mCommandList.Get() };
mCommandQueue->ExecuteCommandLists(_countof(cmdsLists), cmdsLists);

CPU与GPU之间的同步

为了实现cpu与gpu之间的同步,我们需要强制cpu等待 直到gpu完成所有命令的处理,d3d通过围栏实现这一点:

//定义围栏com接口 以及相应的围栏点
 Microsoft::WRL::ComPtr<ID3D12Fence> mFence;
 UINT64 mCurrentFence = 0;
//创建围栏对象
ThrowIfFailed(md3dDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE,
	IID_PPV_ARGS(&mFence)));
//使cpu与gpu同步
void D3DApp::FlushCommandQueue()
{
	//增加围栏点的值
    mCurrentFence++;

    //设置新的围栏点
    ThrowIfFailed(mCommandQueue->Signal(mFence.Get(), mCurrentFence));

	// 直到gpu处理完围栏点之前的命令 围栏点的值才会增加 循环才会结束
    if(mFence->GetCompletedValue() < mCurrentFence)
	{
		HANDLE eventHandle = CreateEventEx(nullptr, false, false, EVENT_ALL_ACCESS);
        ThrowIfFailed(mFence->SetEventOnCompletion(mCurrentFence, eventHandle));
		WaitForSingleObject(eventHandle, INFINITE);
        CloseHandle(eventHandle);
	}
}

资源转换

有时候我们可能需要对一个资源先进行写操作,然后再进行读操作进行显示,为了防止在进行写操作的时候读,d3d设置了一组资源状态属性,防止类似上述这种资源冒险的情况发生,例如:

mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(),
	D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT));
上述代码将资源从渲染目标状态转换为呈现状态

D3D的初始化

接下来的部分只是大致介绍一下流程 以及重要函数
至于每个函数 每个描述子结构体的参数的详细介绍 可自行查阅

创建设备

进行d3d初始化首先要创建d3d设备

启动调试层
#if defined(DEBUG) || defined(_DEBUG) 
{
	ComPtr<ID3D12Debug> debugController;
	ThrowIfFailed(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)));
	debugController->EnableDebugLayer();
}
#endif

	ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(&mdxgiFactory)));

	尝试创建显示适配器(显卡)
	HRESULT hardwareResult = D3D12CreateDevice(
		nullptr,             // default adapter
		D3D_FEATURE_LEVEL_11_0,
		IID_PPV_ARGS(&md3dDevice));

	// 创建失败回退到warp设备
	if(FAILED(hardwareResult))
	{
		ComPtr<IDXGIAdapter> pWarpAdapter;
		ThrowIfFailed(mdxgiFactory->EnumWarpAdapter(IID_PPV_ARGS(&pWarpAdapter)));

		ThrowIfFailed(D3D12CreateDevice(
			pWarpAdapter.Get(),
			D3D_FEATURE_LEVEL_11_0,
			IID_PPV_ARGS(&md3dDevice)));
	}

创建围栏

这一点前面已经说明

检测对4x msaa的支持

    首先填写质量等级的结构体 设置为4x 然后使用checkfeaturesupport来检测硬件是否支持
	D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS msQualityLevels;
	msQualityLevels.Format = mBackBufferFormat;
	msQualityLevels.SampleCount = 4;
	msQualityLevels.Flags = D3D12_MULTISAMPLE_QUALITY_LEVELS_FLAG_NONE;
	msQualityLevels.NumQualityLevels = 0;
	ThrowIfFailed(md3dDevice->CheckFeatureSupport(
		D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS,
		&msQualityLevels,
		sizeof(msQualityLevels)));

    m4xMsaaQuality = msQualityLevels.NumQualityLevels;
	assert(m4xMsaaQuality > 0 && "Unexpected MSAA quality level.");

创建命令队列与列表

描述并创建交换链

void D3DApp::CreateSwapChain()
{
    释放之前创建的交换链
    mSwapChain.Reset();
    填写对应的描述子
    DXGI_SWAP_CHAIN_DESC sd;
    sd.BufferDesc.Width = mClientWidth;
    sd.BufferDesc.Height = mClientHeight;
    sd.BufferDesc.RefreshRate.Numerator = 60;
    sd.BufferDesc.RefreshRate.Denominator = 1;
    sd.BufferDesc.Format = mBackBufferFormat;
    sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
    sd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
    sd.SampleDesc.Count = m4xMsaaState ? 4 : 1;
    sd.SampleDesc.Quality = m4xMsaaState ? (m4xMsaaQuality - 1) : 0;
    sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    sd.BufferCount = SwapChainBufferCount;
    sd.OutputWindow = mhMainWnd;
    sd.Windowed = true;
	sd.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
    sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;

    ThrowIfFailed(mdxgiFactory->CreateSwapChain(
		mCommandQueue.Get(),
		&sd, 
		mSwapChain.GetAddressOf()));
}

创建描述符堆

我们需要创建描述符堆来存储相应的描述符

一个堆用于存储rtv 即交换链的两个缓冲区
 D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc;
 rtvHeapDesc.NumDescriptors = SwapChainBufferCount;
 rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
 rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
	rtvHeapDesc.NodeMask = 0;
 ThrowIfFailed(md3dDevice->CreateDescriptorHeap(
     &rtvHeapDesc, IID_PPV_ARGS(mRtvHeap.GetAddressOf())));

一个腿用于存储dsv 即深度缓冲区
 D3D12_DESCRIPTOR_HEAP_DESC dsvHeapDesc;
 dsvHeapDesc.NumDescriptors = 1;
 dsvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV;
 dsvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
	dsvHeapDesc.NodeMask = 0;
 ThrowIfFailed(md3dDevice->CreateDescriptorHeap(
     &dsvHeapDesc, IID_PPV_ARGS(mDsvHeap.GetAddressOf())));

创建渲染目标视图 rtv

在之前创建了交换链的缓冲区之后 我们还需要创建相应的描述子/视图 才能将其绑定到渲染流水线进行输出

CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHeapHandle(mRtvHeap->GetCPUDescriptorHandleForHeapStart());
for (UINT i = 0; i < SwapChainBufferCount; i++)
{
	ThrowIfFailed(mSwapChain->GetBuffer(i, IID_PPV_ARGS(&mSwapChainBuffer[i])));
	md3dDevice->CreateRenderTargetView(mSwapChainBuffer[i].Get(), nullptr, rtvHeapHandle);
	rtvHeapHandle.Offset(1, mRtvDescriptorSize);
}

创建深度缓冲区及其视图 dsv

填写深度缓冲区描述符然后使用CreateCommittedResource创建
 D3D12_RESOURCE_DESC depthStencilDesc;
 depthStencilDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
 depthStencilDesc.Alignment = 0;
 depthStencilDesc.Width = mClientWidth;
 depthStencilDesc.Height = mClientHeight;
 depthStencilDesc.DepthOrArraySize = 1;
 depthStencilDesc.MipLevels = 1;
 depthStencilDesc.SampleDesc.Count = m4xMsaaState ? 4 : 1;
 depthStencilDesc.SampleDesc.Quality = m4xMsaaState ? (m4xMsaaQuality - 1) : 0;
 depthStencilDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
 depthStencilDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;

 D3D12_CLEAR_VALUE optClear;
 optClear.Format = mDepthStencilFormat;
 optClear.DepthStencil.Depth = 1.0f;
 optClear.DepthStencil.Stencil = 0;
 ThrowIfFailed(md3dDevice->CreateCommittedResource(
     &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
		D3D12_HEAP_FLAG_NONE,
     &depthStencilDesc,
		D3D12_RESOURCE_STATE_COMMON,
     &optClear,
     IID_PPV_ARGS(mDepthStencilBuffer.GetAddressOf())));

 //创建深度视图 用于绑定资源
	D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc;
	dsvDesc.Flags = D3D12_DSV_FLAG_NONE;
	dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
	dsvDesc.Format = mDepthStencilFormat;
	dsvDesc.Texture2D.MipSlice = 0;
 md3dDevice->CreateDepthStencilView(mDepthStencilBuffer.Get(), &dsvDesc, DepthStencilView());

 // 将深度缓冲区资源设置为depth buffer 涉及到之前提到的资源的转换
	mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(mDepthStencilBuffer.Get(),
		D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_DEPTH_WRITE));

设置视口与裁剪矩形

可以先设置视口与裁剪矩形的范围:

mScreenViewport.TopLeftX = 0;
mScreenViewport.TopLeftY = 0;
mScreenViewport.Width    = static_cast<float>(mClientWidth);
mScreenViewport.Height   = static_cast<float>(mClientHeight);
mScreenViewport.MinDepth = 0.0f;
mScreenViewport.MaxDepth = 1.0f;

mScissorRect = { 0, 0, mClientWidth, mClientHeight };

之后我们可以在实际渲染过程中设置视口与裁剪矩形:文章来源地址https://www.toymoban.com/news/detail-839056.html

mCommandList->RSSetViewports(1, &mScreenViewport);
mCommandList->RSSetScissorRects(1, &mScissorRect);

本结示例代码

void InitDirect3DApp::Draw(const GameTimer& gt)
{
    //reset命令分配器 注意这里要保证里面的命令已经全部被gpu执行完毕
	ThrowIfFailed(mDirectCmdListAlloc->Reset());
   //reset命令列表
    ThrowIfFailed(mCommandList->Reset(mDirectCmdListAlloc.Get(), nullptr));

	//将资源从呈现状态转换到渲染目标状态 读到写
	mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(),
		D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET));

    //reset视口与裁剪矩形 每次reset命令列表都要reset
    mCommandList->RSSetViewports(1, &mScreenViewport);
    mCommandList->RSSetScissorRects(1, &mScissorRect);

    //清空后台缓冲区与深度缓冲区
	mCommandList->ClearRenderTargetView(CurrentBackBufferView(), Colors::LightSteelBlue, 0, nullptr);
	mCommandList->ClearDepthStencilView(DepthStencilView(), D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, 1.0f, 0, 0, nullptr);
	
    // 指明我们要写入的缓冲区
	mCommandList->OMSetRenderTargets(1, &CurrentBackBufferView(), true, &DepthStencilView());
	
    // 将后台缓冲区从渲染目标状态转换到呈现状态
	mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(),
		D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT));

    // 关闭命令列表
	ThrowIfFailed(mCommandList->Close());
 
    // 执行命令
	ID3D12CommandList* cmdsLists[] = { mCommandList.Get() };
	mCommandQueue->ExecuteCommandLists(_countof(cmdsLists), cmdsLists);
	
	// 交换前后缓冲区
	ThrowIfFailed(mSwapChain->Present(0, 0));
	mCurrBackBuffer = (mCurrBackBuffer + 1) % SwapChainBufferCount;

	// 等待gpu执行完所有命令 保证同步
	FlushCommandQueue();
}

到了这里,关于d3d12龙书阅读----Direct3D的初始化的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • D3D11和D3D12共享资源

    最近碰到个伪需求: 游戏串流。 游戏引擎用D3D12渲染, 再把游戏画面做视频编码, 通过网络发送到远端做解码显示。 第一反应就是走全GPU的流程, 不要用CPU把显存里的数据拷来拷去。 所以先获取渲染完的D3D12的frame buffer, 然后送给Intel MediaSDK去做编码。 查了一下MediaSDK文档

    2024年02月04日
    浏览(70)
  • Direct3D 12——灯光——光照模型的概述

    将之前所述的所有光照内容都结合起来,即表面反射的光量相当于环境反射光、漫反射光以及 镜面反射光的光量总和。 1.环境光 C a :模拟经表面反射的间接光量。 2.漫反射光 C d :对进入介质内部,又经过表面下吸收而最终散射岀表面的光进行模拟。由于对表 面下的散射光

    2023年04月16日
    浏览(44)
  • Direct3D 12——模板——平面镜效果

    1.将实物照常渲染到后台缓冲区内(不包括镜子)。注意,此步骤不修改模 板缓冲区。 2.清理模板缓冲区,将其整体置零。 将实物都绘制到后台缓冲区中,并将模板缓冲区清理为0 (用浅灰色来表示)。 绘制在模板缓冲区中的黑色轮廊线条反映的是:后台缓冲区与模板缓冲区

    2023年04月21日
    浏览(37)
  • Direct3D 12——计算着色器——计算着色器概念

    计算着色器虽然是一种可编程的着色器,但Direct3D并没有将它直接归为渲染流水线中的一部分。虽然如此,但位于流水线之外的计算着色器却可以读写GPU资源。从本质上来说,计算着 色器能够使我们访问GPU来实现数据并行算法,而不必渲染出任何图形。由于计算着色器是Dir

    2024年02月03日
    浏览(40)
  • 【C/C++】使用C++和Direct3D (d3d)获取屏幕截图并根据传入分辨率进行缩放图片大小

    目录 一,函数清单 1.Direct3DCreate9 函数 2.IDirect3D9::CreateDevice 方法 3.IDirect3DDevice9::GetDisplayMode 方法 4.IDirect3DDevice9::CreateOffscreenPlainSurface 方法 5.IDirect3DDevice9::GetFrontBufferData 方法 6.IDirect3DDevice9::D3DXLoadSurfaceFromSurface 方法 7. D3DXSaveSurfaceToFile 函数 二,关键代码实现 三,最终实现

    2024年01月18日
    浏览(48)
  • DirectX12(D3D12)基础教程(二十一)—— PBR:IBL 的数学原理(1/5)

      2023年来了,令人闹心伤身的疫情也暂告一段落了。感慨之余,其实我也挺惆怅,这个系列教程还能继续下去吗?或者我自己还能坚持多久,我不知道。因为我也天天徘徊在失业的边缘,年纪大了被人嫌弃,学历低被人嫌弃,身体稍差也被人嫌弃,忽然发现我已不是当初那

    2023年04月08日
    浏览(57)
  • DirectX12_Windows_GameDevelop_3:Direct3D的初始化

    查看龙书时发现, 第四章介绍预备知识的代码不太利于学习 。因为它不像是LearnOpenGL那样从头开始一步一步教你敲代码,导致你没有一种整体感。 如果你把它当作某一块的代码进行学习,你跟着敲会发现,总有几个变量是没有定义的。这是因为书上的代码都是把框架里的某

    2024年02月08日
    浏览(44)
  • DirectX12(D3D12)基础教程(二十一)—— PBR:IBL 的数学原理(5/5)镜面反射积分项2及光照合成

    3.5.4、根据 Epic 近似假设进一步拆分积分项为两部分之积   通过之前的步骤,实际上以及得到了我们想要的镜面反射项的蒙特卡洛积分重要性采样的形式,并且根据我们的假设认为视方向等于法线方向,实际上以及可以编码实现这个积分计算过程,而且依据假设我们不再需

    2023年04月08日
    浏览(50)
  • Direct3D光照

    光照的组成 环境光:这种类型的光经其他表面反射到达物体表面,并照亮整个场景,要想以较低代价粗略模拟这类反射光,环境光是一个很好的选择 漫射光:这种类型光沿着特定的方向传播。当它到达某一表面时,将沿着各个方向均匀反射,无论从哪个方位观察,表面亮度

    2024年02月09日
    浏览(37)
  • Direct3D融合技术

    该技术能使我们将当前要进行光栅化的像素的颜色与先前已已光栅化并处于同一位置的像素的颜色进行合成,即将正在处理的图元颜色值与存储在后台缓存中的像素颜色值进行合成(混合),利用该技术我们可得到各种各样的效果,尤其是透明效果。 在融合运算时需要遵循:首

    2024年02月07日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包