13.1 使用DirectX9绘图引擎

这篇具有很好参考价值的文章主要介绍了13.1 使用DirectX9绘图引擎。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

DirectX 9 是由微软开发的一组多媒体应用程序接口API,用于创建和运行基于Windows平台的多媒体应用程序,尤其是游戏。它是DirectX系列中的一个版本,于2002年发布,是DirectX系列中的一个重要版本,DirectX 9在其发布时引入了许多新的功能和性能优化,成为当时PC游戏开发的主要标准,许多经典的PC游戏使用了DX9作为其图形和音频渲染引擎。虽然后续出现了更多强大的引擎,但本质上都是可以兼容Dx9的。

在使用Dx9引擎之前读者需要自行下载该绘制库,当然在课件中笔者已经为大家准备了绿色版,读者可自行解压到指定目录下,在目录下有一个Developer Runtime其内部是引擎运行时所需要的运行环境,读者可根据不同的需求安装对应位数的运行库,安装成功后则可配置开发目录,一般而言我们只需要关注Include引入目录,以及Lib库目录即可。

读者可自行打开属性页面,并选中VC++目录自行配置,如下图所示;

13.1 使用DirectX9绘图引擎

13.1.1 初始化变量

在开始使用绘制库之前我们需要一个可被自由绘制的画布程序,该程序必须使用D3Dx9引擎生成以便于后续文章的测试工作,一般而言,使用DirectX 9绘制图形的流程包括初始化、创建资源、设置渲染状态和顶点格式、更新数据、绘制图形、渲染和清理资源构成,在使用之前读者需要引入Dx9的头文件以及所需定义部分,如下所示;

#include <windows.h> 
#include <tchar.h> 
#include <d3d9.h>
#pragma comment( lib, "d3d9.lib") 

#define null NULL
#define RETURN return
#define FVF ( D3DFVF_XYZRHW | D3DFVF_DIFFUSE ) 

LPDIRECT3D9             g_pD3D = NULL;
LPDIRECT3DDEVICE9       g_pd3dDevice = NULL;
LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL;

struct CUSTOMVERTEX
{
    float x, y, z, rhw;
    DWORD color;
};

13.1.2 LPDIRECT3D9

其中定义的全局指针LPDIRECT3D9DX9中的一个指针类型,表示一个Direct3D 9的顶层对象。顶层对象是Direct3D对象模型的顶级结构,它为应用程序提供了一组方法来进行3D图形渲染。LPDIRECT3D9接口可以用来创建和操作Direct3D 9设备对象IDirect3DDevice9以及其他与图形渲染相关的对象。在使用DX9进行图形渲染之前,必须通过调用Direct3DCreate9函数来创建一个IDirect3D9接口的实例,并通过LPDIRECT3D9类型的指针进行访问和操作。例如,使用下面的代码可以创建一个LPDIRECT3D9对象:

LPDIRECT3D9 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);

这将创建一个指向Direct3D 9的顶层对象的指针,并将其分配给变量d3d9。通过这个LPDIRECT3D9对象,应用程序就可以执行各种与图形渲染相关的操作,如创建顶点缓存、纹理对象等。在程序结束时,应用程序必须通过调用LPDIRECT3D9对象的Release方法来释放所有创建的Direct3D对象,以防止内存泄漏。

d3d9->Release();

13.1.3 LPDIRECT3DDEVICE9

第二个全局变量LPDIRECT3DDEVICE9DirectX 9中表示3D设备的指针类型,它是使用Direct3D进行3D渲染的关键对象。LPDIRECT3DDEVICE9对象表示着本次渲染中的3D对象在硬件上的运算环境,通过它可以对3D对象进行变换、光照和纹理等操作。通过LPDIRECT3D9对象创建的步骤通常包括以下几个步骤:

1.创建一个LPDIRECT3D9对象,通过Direct3DCreate9函数创建,如下所示:

LPDIRECT3D9 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);

2.使用LPDIRECT3D9对象创建一个IDirect3DDevice9对象,可以通过调用LPDIRECT3D9对象的CreateDevice方法来创建,如下所示:

LPDIRECT3DDEVICE9 d3dDevice;

D3DPRESENT_PARAMETERS presentParams = {0};
presentParams.Windowed = TRUE;
presentParams.SwapEffect = D3DSWAPEFFECT_DISCARD;

d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &presentParams, &d3dDevice);

这个代码片段创建了一个窗口化的3D设备并将其存储到变量d3dDevice中。其中D3DADAPTER_DEFAULTD3DDEVTYPE_HAL参数表示选择默认显示适配器和硬件抽象层,hWnd参数为窗口句柄,D3DCREATE_HARDWARE_VERTEXPROCESSING表示使用硬件进行顶点计算,&presentParams为一个D3DPRESENT_PARAMETERS结构体指针,用于配置呈现参数。

3.初始化3D设备对象,可以设置一些统一的设备状态,如渲染状态、混合模式等,它将禁用光照计算。如下所示:

d3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);

4.在进行有效的渲染之前,必须在每一帧开始时调用BeginScene方法,以告知Direct3D实例开始渲染,如下所示:

d3dDevice->BeginScene();

5.渲染3D对象,通过LPDIRECT3DDEVICE9对象进行绘制,并进行相应的3D数据应用操作,如下所示:

d3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1);

渲染结束后,可以调用EndScene方法通知Direct3D实例结束渲染并显示图像,如下所示:

d3dDevice->EndScene();

最后,使用SwapChain显示图像,如下所示:

d3dDevice->Present(NULL, NULL, NULL, NULL);

在程序退出时,借助于LPDIRECT3DDEVICE9对象的Release方法释放所有创建的Direct3D对象,以避免内存泄漏。

d3dDevice->Release();

13.1.4 LPDIRECT3DVERTEXBUFFER9

LPDIRECT3DVERTEXBUFFER9是DirectX 9中表示顶点缓冲区的指针类型,它被用来存储3D网格的顶点数据,是Direct3D游戏开发中的一个重要概念之一。顶点缓冲区是一个可以包含顶点数据的内存块,它可以存储可绘制的几何体(三角形、四边形等)的顶点数据。

使用LPDIRECT3DVERTEXBUFFER9对象存储顶点数据,可以充分利用硬件加速能力,提高渲染效率和图形性能,优化游戏性能。

顶点缓冲区由顶点格式和顶点数据两部分组成:

  • 顶点格式(Vertex Format): 表示顶点数据的结构和排列方式。使用D3DVertexElement9D3DVertexDeclaration9等API进行创建、声明以及管理。
  • 顶点数据(Vertex Data): 包含了网格的所有顶点数据,如坐标、法线、颜色、纹理坐标等。可以使用LPDIRECT3DVERTEXBUFFER9对象存储,同时还可以使用其他缓冲区类型如索引缓冲区(LPDIRECT3DINDEXBUFFER9)来存储索引数据,方便后续渲染处理。

创建LPDIRECT3DVERTEXBUFFER9对象的步骤通常如下:

首先,声明并创建一个顶点缓冲区对象。在创建LPDIRECT3DVERTEXBUFFER9对象时,需要指定缓冲区大小、缓冲区用法等参数。

LPDIRECT3DVERTEXBUFFER9 pVertexBuffer = NULL;

device->CreateVertexBuffer(vertexBufferSize, D3DUSAGE_WRITEONLY, FVF, D3DPOOL_MANAGED, &pVertexBuffer, NULL);

写入顶点数据到顶点缓冲区,使用Lock方法可以将顶点缓冲区锁定,返回已锁定的顶点缓冲区指针,并且允许应用程序与锁定的数据进行读写操作,然后使用Unlock方法来解锁。

float* pBuffer = NULL;

pVertexBuffer->Lock(0, 0, (void**)&pBuffer, 0);

memcpy(pBuffer, vertices, vertexBufferSize);

pVertexBuffer->Unlock();

绘制几何体时,可以使用SetStreamSource方法指定顶点缓冲区、顶点格式以及偏移量。最后调用DrawPrimitive方法进行绘制。

device->SetFVF(FVF);
device->SetStreamSource(0, pVertexBuffer, 0, sizeof(Vertex));
device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, numTriangles);

13.1.5 初始化绘图引擎

接着我们来看一下我们是如何初始化一个D3D引擎的,InitD3D函数会在游戏程序启动时被调用,以初始化3D设备和相关环境,为后续的3D图形渲染操作做好准备。初始化部分答题可总结为三步,首先调用Direct3DCreate9用于创建一个Dx9引擎画布,接着填充D3DPRESENT_PARAMETERS结构,最后通过使用CreateDevice实现对设备的创建,当创建成功则会将指针保存在LPDIRECT3D9这个全局结构指针内。

HRESULT InitD3D(HWND hWnd)
{
  g_pD3D = Direct3DCreate9(D3D_SDK_VERSION);
  D3DPRESENT_PARAMETERS d3dpp;
  ZeroMemory(&d3dpp, sizeof(d3dpp));
  d3dpp.Windowed = TRUE;
  d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
  d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
  g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice);
  return S_OK;
}

上述流程具体分析,步骤如下:

使用Direct3DCreate9函数创建一个LPDIRECT3D9对象,该对象表示顶层Direct3D对象,负责管理和控制DX操作。

g_pD3D = Direct3DCreate9(D3D_SDK_VERSION);

创建并配置D3DPRESENT_PARAMETERS结构体,该结构体用于描述渲染设备的一些基本属性,如窗口模式、后台缓冲区格式、交换模式等。

D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = TRUE;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;

在上述代码中,使用ZeroMemory()函数将d3dpp对象中除第1个成员外所有成员的值都重置为0。还设置了窗口模式(Windowed = TRUE,表示窗口化模式),后台缓冲区格式(BackBufferFormat = D3DFMT_UNKNOWN,表示使用默认格式),以及交换模式(SwapEffect = D3DSWAPEFFECT_DISCARD,表示丢弃当前帧并替换为下一帧)。

使用CreateDevice函数创建一个IDirect3DDevice9对象,并保存在变量g_pd3dDevice中。

g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice);

在这里,第1个参数(D3DADAPTER_DEFAULT)表示使用默认显示适配器;第2个参数(D3DDEVTYPE_HAL)指定使用硬件抽象层,表示硬件加速;第3个参数(hWnd)是窗口句柄;第4个参数(D3DCREATE_HARDWARE_VERTEXPROCESSING)表示使用硬件进行顶点处理。最后,使用&d3dpp、&g_pd3dDevice参数传递设备创建信息。最后,返回S_OK表示函数执行成功。

初始化部分的第二步则是调用InitVB这个函数,该函数用于创建顶点缓冲区,可以用于存储3D网格的顶点数据,方便后续的渲染处理;

HRESULT InitVB()
{
  CUSTOMVERTEX v[] =
  {
    100, 000, 0, 1, 0xffff0000,
    300, 50, 0, 1, 0xff00ff00,
    500, 400, 0, 1, 0xff0000ff
  };

  g_pd3dDevice->CreateVertexBuffer(3 * sizeof(v), 0, FVF, D3DPOOL_DEFAULT, &g_pVB, 0);

  void* vb;
  g_pVB->Lock(0, 0, (void**)&vb, 0);
  memcpy(vb, v, sizeof(v));
  g_pVB->Unlock();
  return S_OK;
}

上述代码中,首先声明一个CUSTOMVERTEX类型的数组v,并将其作为输入参数,其中每一个元素表示一个自定义的顶点,包括位置坐标和颜色。

CUSTOMVERTEX v[] =
{
    100, 000, 0, 1, 0xffff0000,
    300, 50, 0, 1, 0xff00ff00,
    500, 400, 0, 1, 0xff0000ff
};

在代码中,每个元素都包含了顶点的x、y、z坐标、齐次坐标w,以及顶点的颜色。

调用CreateVertexBuffer函数,创建一个顶点缓冲区对象,并将其保存在变量g_pVB中。该函数的第1个参数表示缓冲区大小,即存储顶点数据的字节数,这里是3个顶点乘以每个顶点40个字节(即一个CUSTOMVERTEX类型的大小);第2个参数是填充字节的数值,设为0表示不填充;第3个参数是顶点格式,表示每个顶点包含的信息,和CUSTOMVERTEX数据结构一致;第4个参数是缓冲区类型,表示缓冲区的使用方式,D3DPOOL_DEFAULT表示缓存区将用于GPU读写操作。最后,&g_pVB是返回的顶点缓冲区对象。

g_pd3dDevice->CreateVertexBuffer(3 * sizeof(v), 0, FVF, D3DPOOL_DEFAULT, &g_pVB, 0);

对顶点缓冲区进行锁定,使用Lock函数使缓冲区可读写,并将顶点数据写入缓冲区中。这里使用void*类型的指针vb指向顶点缓冲区中的第一个元素,并使用memcpy()函数将顶点数组的数据拷贝到顶点缓冲区中。并使用Unlock()函数解除顶点缓冲区的锁定。最后返回S_OK,作为函数执行成功的标志。

void* vb;
g_pVB->Lock(0, 0, (void**)&vb, 0);
memcpy(vb, v, sizeof(v));
g_pVB->Unlock();

接着对窗口中的图形进行着色及初始化,

void Render()
{
  g_pd3dDevice->Clear(0, 0, D3DCLEAR_TARGET, D3DCOLOR_XRGB(176, 196, 222), 1, 0);
  // 设置背景色 黑色
  // g_pd3dDevice->Clear(0, 0, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1, 0);

  g_pd3dDevice->BeginScene();
  g_pd3dDevice->SetStreamSource(0, g_pVB, 0, sizeof(CUSTOMVERTEX));
  g_pd3dDevice->SetFVF(FVF);
  //g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 10);
  g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 4, 0, 4);
  g_pd3dDevice->EndScene();

  g_pd3dDevice->Present(0, 0, 0, 0);
}

使用Clear函数清除背景,并设置新的背景色。这里使用D3DCOLOR_XRGB(176, 196, 222),表示颜色值为R:176, G:196, B:222的浅蓝色。

g_pd3dDevice->Clear(0, 0, D3DCLEAR_TARGET, D3DCOLOR_XRGB(176, 196, 222), 1, 0);

使用BeginScene函数开始渲染场景。

g_pd3dDevice->BeginScene();

设置顶点着色器的输入数据源。使用SetStreamSource函数设置使用的顶点缓冲区,其中第1个参数是流编号,第2个参数是顶点缓冲区对象,第3个参数是缓冲区内顶点数据的起始点,第4个参数是顶点结构体的大小。

g_pd3dDevice->SetStreamSource(0, g_pVB, 0, sizeof(CUSTOMVERTEX));

设置顶点格式。使用SetFVF函数描述顶点的结构,这里的FVF常量是一个结构体标记符号,用于描述顶点的类型和结构。

g_pd3dDevice->SetFVF(FVF);

使用DrawPrimitive函数或DrawIndexedPrimitive函数绘制图形,这里使用的是后者。该函数绘制在缓冲区中的三角形列表,根据输入的位置在缓冲区中查找三角形点,再连接相邻的三角形点,形成3D图形。第1个参数(D3DPT_TRIANGLELIST)表示三角形列表,第2个参数是起始顶点索引,第3个参数是最小顶点索引,第4个参数是被绘制的总顶点数,第5个参数(0)表示要跳过的数据数量,第6个参数(4)表示每个图元的顶点数。

g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 4, 0, 4);

使用EndScene函数结束本次渲染。

g_pd3dDevice->EndScene();

使用Present函数展示渲染结果到窗口中。

g_pd3dDevice->Present(0, 0, 0, 0);

当有了上述初始化函数的封装后,接着我们就可以在主函数内通过CreateWindow函数创建一个窗体,并在初始化流程内通过调用InitD3D(hWnd)以及InitVB()对D3D引擎初始化,初始化后进入到该程序的消息循环内,在消息循环内除了通过TranslateMessage捕获消息外,还需要不间断的调用Render()用于动态刷新D3D窗体显示,这样则可实现动态绘制一个完整窗体并加载绘图引擎的目的;

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    message == WM_CLOSE ? PostQuitMessage(0) : (void)0;
    return DefWindowProc(hWnd, message, wParam, lParam);
}

int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE, PTSTR, int)
{
    wchar_t cn[] = L"LySharkGame";
    WNDCLASS wc;
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = cn;
    RegisterClass(&wc);

    DWORD cxScreen = GetSystemMetrics(SM_CXSCREEN);
    DWORD cyScreen = GetSystemMetrics(SM_CYSCREEN);

    HWND hWnd = CreateWindow(cn, TEXT("LySharkGame"), WS_OVERLAPPEDWINDOW, (cxScreen - 1024) / 2, (cyScreen - 768) / 2, 1024, 768, NULL, NULL, hInstance, NULL);
    ShowWindow(hWnd, SW_SHOW);

    InitD3D(hWnd);
    InitVB();

    MSG msg;
    ZeroMemory(&msg, sizeof(msg));
    while (msg.message != WM_QUIT)
    {
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else
        {
            Render();
        }
    }
    return 0;
}

至此我们就得到了一个具有D3D功能的窗体,当读者打开该窗体时即可看到一个标题为LySharkGame的窗体,该窗体大小为标准的1024x768这个窗体输出效果如下图所示;

13.1 使用DirectX9绘图引擎文章来源地址https://www.toymoban.com/news/detail-710553.html

到了这里,关于13.1 使用DirectX9绘图引擎的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 解决 vmware 虚拟机无法安装 macos13.1

    win11 专业版 VMware workstation 17 pro macos13.1 ios镜像 unlocker 4.2.5 新建虚拟机的时候可以看到没有选择macos系统的那一项 所以需要使用 unlocker 软件来进行解锁,下载地址:https://github.com/DrDonk/unlocker/releases 找到最新版本压缩包下载,当前最新版本是4.2.5 解压出来,然后把 iso 文件夹中

    2024年02月12日
    浏览(47)
  • Quartus II 13.1——VWF文件 仿真报错

    报错类型: Error: (vsim-19) Failed to access library \\\"cyclone_ver\\\" at \\\"cyclone_ver\\\". 报错原因: 库文件未能加载到指定文件夹。 解决办法: ①点击顶部菜单栏得“Tools”选项; ②再选择“Launch Simulation Library Compiler”; ③底部“Output directory”这里选择 ‘simulation’ 文件夹下的 ‘qsim’ 文件

    2024年02月08日
    浏览(49)
  • Quartus II 13.1与Modelsim SE的安装

    软件资源下载链接:提取码:38ny 注册资源下载链接(用于Quartus II):提取码:zbho 注册资源下载链接(用于Modelsim):提取码:hi5b 在文件 QuartusII_13.1 文件下,解压 QuartusSetup-13.1.0.162.rar ,: 解压后得到: 运行这个可执行程序: 点击next: 之后勾选对应选项并点击next: 之后

    2024年02月06日
    浏览(50)
  • STM32串口printf调试输出(SSCOM V5.13.1)

    PC与CPU相互通信就是通过USB Type_C接口和USB电平转换实现的。 我们可以看到,CPU通过管脚USART1连接CH340C芯片将USB转串口,实现PC与CPU之间的通信。 当然,这里用的是CH340的芯片,我们就需要安装ch340串口。 按住Ctrl+s生成代码。 在usart.h中添加头文件stdio.h 标准库的 printf函数 能方

    2024年02月12日
    浏览(50)
  • 13.1 linux命令行查看控制串口(uart)全攻略

    本文主要内容: 1 串口启动驱动打印 2 sys目录下的串口信息 3 proc目录下的串口信息 4 etc目录下的串口信息 5 dev目录下的串口信息 6 stty控制具体的串口 7 命令行控制串口读写 8 串口数据解析

    2024年02月06日
    浏览(36)
  • 微软软件运行库下载 (DirectX,.NET Framework,VC++库..)

    运行库是程序在运行时所需要的库文件,运行库中一般包括编程时常用的函数,如字符串操作、文件操作、界面等内容。不同的语言所支持的函数通常是不同的,所以使用的库也是完全不同的,这就是为什么有VB运行库、C运行库、Delphi运行库之分的原因。即使都是C++语言,也

    2024年02月11日
    浏览(50)
  • Quartus 13.1与Modelsim或Modelsim Altera进行波形联合仿真

    Quartus II 13.1软件自10.0版本以后,便不再自带波形仿真工具,需要借助Modelsim进行波形仿真。一般安装Quartus II的时候,会默认安装Modelsim Altera,如果需要用到Modelsim软件的话,需要额外再安装一下。本文将介绍一下Quartus II 13.1软件与Modelsim(需要提前安装好)或Modelsim Altera进行

    2024年02月11日
    浏览(47)
  • 复制13.1MB的文本文件java仅用18毫秒(速度很OK)

    //记录一下! BufferedInputStream和BufferedOutputStream是Java标准库中的两个I/O类,它们提供了对输入和输出流的 缓冲功能 ,以提高I/O性能。 BufferedInputStream 是InputStream的子类,它使用内部缓冲区来读取输入流的数据。当使用BufferedInputStream读取数据时,它会尽可能多地从底层输入流中

    2024年02月10日
    浏览(27)
  • FPGA-Quartus II 13.1画逻辑门电路图的详细步骤

            作为学习FPGA的小白一枚,总是在看论文的时候发现大牛们的内容中包含逻辑设计图也就是门电路的截图,而我自己在学习的时候看正点原子或者野火视频的时候没有发现这一部分(也有可能有,但我没全部看完系列视频,所以也就没发现),就上网搜索了这一部

    2024年02月12日
    浏览(90)
  • 巨神奇,2013年的老Mac,竟直接装上macOS Ventura 13.1 Beta版

    上期这篇文章《终于,老Mac可以跨级安装macOS Ventura了》中,我说了通过OpenCore Legacy Patcher可以跨级安装macOS Ventura,但却没给出一个切实的解决方法。本期我就说一下跨级安装的方法。 官方的安装方法是USB抹盘安装的,特别麻烦,不用听它的,其实还有更优的解决方法。 首先

    2024年02月05日
    浏览(48)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包