C语言画Mandelbrot和Julia集合(DX11常规加速版)
acmilan2017/09/18软件综合 IP:四川

之所以说是常规加速版,是因为DX11还有GPGPU计算加速功能Compute Shader,也就是所谓的DirectCompute,但是这里我们只用到了常规的图形流水线加速功能。

最低配置被设置为D3D_FEATURE_LEVEL_9_3和"ps_4_0_level_9_3"。如果将循环次数改多一点,由于"ps_4_0_level_9_3"不包含条件循环指令,循环操作实际上被展开了,指令数量很容易超过限制,这个时候就需要把最低配置改为D3D_FEATURE_LEVEL_10_0和"ps_4_0"。

<code class="language-hlsl">// shaders.txt

struct VS_OUTPUT
{
	float4 pos : SV_POSITION;
	float2 tex : TEXCOORD;
};

void vs_common(float3 pos : POSITION, float2 tex : TEXCOORD,
               out VS_OUTPUT vso)
{
	vso.pos = float4(pos, 1.0f);
	vso.tex = tex;
}

float4 ps_mandelbrot(VS_OUTPUT vso) : SV_TARGET
{
    float2 zvar = float2(0, 0);
    float i;
    for (i = 0; i < 16 && zvar.x * zvar.x + zvar.y * zvar.y <= 16 4; i++) { float2 zvar2="zvar;" zvar.x="zvar2.x" * zvar2.x - zvar2.y + vso.tex.x; zvar.y="zvar2.x" vso.tex.y; } return float4(i 16.0, 0.0f, 1.0f); float4 ps_julia(vs_output vso) : sv_target zvar="vso.tex;" float i; for (i="0;" i < && 0.4f; 0.3f; code></=></code>
<code class="language-c">// main.c - 使用了C99语法,可使用VS2013-2017编译

#undef UNICODE
#define UNICODE 1
#include <windows.h>
#include <assert.h>
#include <d3d11.h>
#include <d3dcompiler.h>
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "dxguid.lib")
#pragma comment(lib, "d3dcompiler.lib")

#define NOFAIL(x) assert(SUCCEEDED(x))
#define NOTZERO(x) assert(x)
#define CLEANUP(x) if (x) { (x)->lpVtbl->Release(x); (x) = NULL; }

HINSTANCE g_hinst;
HWND g_hmainwnd;

// DirectX
D3D_FEATURE_LEVEL g_fl;
ID3D11Device *g_dev;
ID3D11DeviceContext *g_immctx;
IDXGISwapChain *g_swpch;
ID3D11Texture2D *g_backbuffer;
ID3D11RenderTargetView *g_backbuffer_rtv;
// DirectX资源
ID3D11VertexShader *g_vs_common;
ID3D11PixelShader *g_ps_mandelbrot;
ID3D11PixelShader *g_ps_julia;
ID3D11PixelShader *g_ps_current;
ID3D11InputLayout *g_inlayout;
ID3D11Buffer *g_vertexbuffer;

LRESULT MainWnd_OnCreate(HWND hWnd, LPCREATESTRUCT lpcs)
{
	// 创建DirectX
	RECT rc;
	GetClientRect(hWnd, &rc);
	DXGI_MODE_DESC backbuf_mode_desc = {
		rc.right - rc.left, rc.bottom - rc.top, { 60, 1 },
		DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_MODE_SCALING_UNSPECIFIED,
		DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED,
	};
	DXGI_SWAP_CHAIN_DESC swpch_desc = {
		backbuf_mode_desc, { 1, 0 },
		DXGI_USAGE_RENDER_TARGET_OUTPUT, 1,
		hWnd, TRUE,
		DXGI_SWAP_EFFECT_DISCARD, 0,
	};
	D3D_FEATURE_LEVEL fllist[] = {
		D3D_FEATURE_LEVEL_11_0,
		D3D_FEATURE_LEVEL_10_1,
		D3D_FEATURE_LEVEL_10_0,
		D3D_FEATURE_LEVEL_9_3,
	};
	if (FAILED(D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0,
		fllist, sizeof fllist / sizeof fllist[0], D3D11_SDK_VERSION, &swpch_desc,
		&g_swpch, &g_dev, &g_fl, &g_immctx)))
	{
		NOFAIL(D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_WARP, NULL, 0,
			fllist, sizeof fllist / sizeof fllist[0], D3D11_SDK_VERSION, &swpch_desc,
			&g_swpch, &g_dev, &g_fl, &g_immctx));
	}
	IDXGIFactory *dxgifac;
	NOFAIL(g_swpch->lpVtbl->GetParent(g_swpch, &IID_IDXGIFactory, (void**)&dxgifac));
	NOFAIL(dxgifac->lpVtbl->MakeWindowAssociation(dxgifac, hWnd, DXGI_MWA_NO_ALT_ENTER));
	CLEANUP(dxgifac);
	NOFAIL(g_swpch->lpVtbl->GetBuffer(g_swpch, 0, &IID_ID3D11Texture2D, (void**)&g_backbuffer));
	NOFAIL(g_dev->lpVtbl->CreateRenderTargetView(g_dev,
		(ID3D11Resource *)g_backbuffer, NULL, &g_backbuffer_rtv));
	// 创建绘制资源
	// 读取shaders.txt
	static char shaders_txt[65536];
	memset(shaders_txt, 0, sizeof shaders_txt);
	HANDLE hfile = CreateFile(L"shaders.txt", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
	if (hfile == INVALID_HANDLE_VALUE)
	{
		MessageBox(hWnd, L"不能打开shader.txt文件", L"文件错误", MB_OK);
		DestroyWindow(hWnd);
		return 0;
	}
	DWORD dwret;
	ReadFile(hfile, shaders_txt, sizeof shaders_txt - 1, &dwret, NULL);
	CloseHandle(hfile);
	// 编译shaders.txt并创建相关资源
	ID3DBlob *bcode_ps_mandelbrot, *bcode_ps_julia, *bcode_vs_common, *errmsg;
	if (FAILED(D3DCompile(shaders_txt, strlen(shaders_txt), "shaders.txt", NULL, NULL,
			"ps_mandelbrot", "ps_4_0_level_9_3", 0, 0, &bcode_ps_mandelbrot, &errmsg)) ||
		FAILED(D3DCompile(shaders_txt, strlen(shaders_txt), "shaders.txt", NULL, NULL,
			"ps_julia", "ps_4_0_level_9_3", 0, 0, &bcode_ps_julia, &errmsg)) ||
		FAILED(D3DCompile(shaders_txt, strlen(shaders_txt), "shaders.txt", NULL, NULL,
			"vs_common", "vs_4_0_level_9_3", 0, 0, &bcode_vs_common, &errmsg)))
	{
		NOTZERO(errmsg);
		MessageBoxA(hWnd, errmsg->lpVtbl->GetBufferPointer(errmsg), "D3DCompile Error", MB_OK);
		CLEANUP(errmsg);
		CLEANUP(bcode_ps_mandelbrot);
		CLEANUP(bcode_ps_julia);
		CLEANUP(bcode_vs_common);
		DestroyWindow(hWnd);
		return 0;
	}
	NOFAIL(g_dev->lpVtbl->CreatePixelShader(g_dev,
		bcode_ps_mandelbrot->lpVtbl->GetBufferPointer(bcode_ps_mandelbrot),
		bcode_ps_mandelbrot->lpVtbl->GetBufferSize(bcode_ps_mandelbrot), NULL, &g_ps_mandelbrot));
	NOFAIL(g_dev->lpVtbl->CreatePixelShader(g_dev,
		bcode_ps_julia->lpVtbl->GetBufferPointer(bcode_ps_julia),
		bcode_ps_julia->lpVtbl->GetBufferSize(bcode_ps_julia), NULL, &g_ps_julia));
	NOFAIL(g_dev->lpVtbl->CreateVertexShader(g_dev,
		bcode_vs_common->lpVtbl->GetBufferPointer(bcode_vs_common),
		bcode_vs_common->lpVtbl->GetBufferSize(bcode_vs_common), NULL, &g_vs_common));
	D3D11_INPUT_ELEMENT_DESC inputelements[] = {
		{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
		{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
	};
	NOFAIL(g_dev->lpVtbl->CreateInputLayout(g_dev,
		inputelements, sizeof inputelements / sizeof inputelements[0],
		bcode_vs_common->lpVtbl->GetBufferPointer(bcode_vs_common),
		bcode_vs_common->lpVtbl->GetBufferSize(bcode_vs_common), &g_inlayout));
	CLEANUP(bcode_ps_mandelbrot);
	CLEANUP(bcode_ps_julia);
	CLEANUP(bcode_vs_common);
	float vertexdata[] = {
		-1.0f, -1.0f, 1.0f, -2.2f, -2.2f,
		-1.0f,  1.0f, 1.0f, -2.2f,  2.2f,
		 1.0f, -1.0f, 1.0f,  2.2f, -2.2f,
		 1.0f,  1.0f, 1.0f,  2.2f,  2.2f,
	};
	D3D11_BUFFER_DESC bd = { sizeof vertexdata, D3D11_USAGE_DEFAULT, 0, 0, 0 };
	D3D11_SUBRESOURCE_DATA srd = { vertexdata, 0, 0 };
	NOFAIL(g_dev->lpVtbl->CreateBuffer(g_dev, &bd, &srd, &g_vertexbuffer));
	g_ps_current = g_ps_mandelbrot;
	return 0;
}

LRESULT MainWnd_OnDestroy(HWND hWnd)
{
	if (g_immctx) g_immctx->lpVtbl->ClearState(g_immctx);
	// 清理资源
	CLEANUP(g_vertexbuffer);
	CLEANUP(g_inlayout);
	CLEANUP(g_vs_common);
	CLEANUP(g_ps_julia);
	CLEANUP(g_ps_mandelbrot);
	// 清理DirectX
	CLEANUP(g_backbuffer_rtv);
	CLEANUP(g_backbuffer);
	CLEANUP(g_swpch);
	CLEANUP(g_immctx);
	CLEANUP(g_dev);
	// 产生WM_QUIT消息,结束消息循环
	PostQuitMessage(0);
	return 0;
}

LRESULT MainWnd_OnSize(HWND hWnd, WPARAM wParam, POINTS pts)
{
	if (g_swpch && g_immctx && g_dev)
	{
		g_immctx->lpVtbl->ClearState(g_immctx);
		CLEANUP(g_backbuffer_rtv);
		CLEANUP(g_backbuffer);
		RECT rc;
		GetClientRect(hWnd, &rc);
		NOFAIL(g_swpch->lpVtbl->ResizeBuffers(g_swpch,
			1, rc.right - rc.left, rc.bottom - rc.top, DXGI_FORMAT_UNKNOWN, 0));
		NOFAIL(g_swpch->lpVtbl->GetBuffer(g_swpch, 0, &IID_ID3D11Texture2D, (void**)&g_backbuffer));
		NOFAIL(g_dev->lpVtbl->CreateRenderTargetView(g_dev, g_backbuffer, NULL, &g_backbuffer_rtv));
	}
	return 0;
}

LRESULT MainWnd_OnPaint(HWND hWnd)
{
	// GDI例行任务
	PAINTSTRUCT ps;
	HDC hdc = BeginPaint(hWnd, &ps);
	EndPaint(hWnd, &ps);
	// DirectX任务
	// 清除背景
	float backcolor[] = { 0.0f, 1.0f, 1.0f, 1.0f };
	g_immctx->lpVtbl->ClearRenderTargetView(g_immctx, g_backbuffer_rtv, backcolor);
	// 设置状态并绘图
	RECT rc;
	GetClientRect(hWnd, &rc);
	float ratio = (float)(rc.right - rc.left) / (float)(rc.bottom - rc.top);
	float vertexdata[] = {
		-1.0f, -1.0f, 1.0f, -2.2f * ratio, -2.2f,
		-1.0f,  1.0f, 1.0f, -2.2f * ratio,  2.2f,
		1.0f, -1.0f, 1.0f,  2.2f * ratio, -2.2f,
		1.0f,  1.0f, 1.0f,  2.2f * ratio,  2.2f,
	};
	g_immctx->lpVtbl->UpdateSubresource(g_immctx,
		(ID3D11Resource *)g_vertexbuffer, 0, NULL, vertexdata, 0, 0);
	UINT stride = sizeof(float) * 5, offset = 0;
	g_immctx->lpVtbl->IASetVertexBuffers(g_immctx, 0, 1, &g_vertexbuffer, &stride, &offset);
	g_immctx->lpVtbl->IASetInputLayout(g_immctx, g_inlayout);
	g_immctx->lpVtbl->IASetPrimitiveTopology(g_immctx, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
	g_immctx->lpVtbl->VSSetShader(g_immctx, g_vs_common, NULL, 0);
	D3D11_VIEWPORT viewport = { 0.0f, 0.0f, rc.right - rc.left, rc.bottom - rc.top, 0.0f, 1.0f };
	g_immctx->lpVtbl->RSSetViewports(g_immctx, 1, &viewport);
	g_immctx->lpVtbl->PSSetShader(g_immctx, g_ps_current, NULL, 0);
	g_immctx->lpVtbl->OMSetRenderTargets(g_immctx, 1, &g_backbuffer_rtv, NULL);
	g_immctx->lpVtbl->Draw(g_immctx, 4, 0);
	// 上屏
	NOFAIL(g_swpch->lpVtbl->Present(g_swpch, 0, 0));
	return 0;
}

LRESULT MainWnd_OnLButtonDown(HWND hWnd, WPARAM wParam, POINTS pts)
{
	g_ps_current = g_ps_mandelbrot;
	InvalidateRect(hWnd, NULL, FALSE);
	return 0;
}

LRESULT MainWnd_OnRButtonDown(HWND hWnd, WPARAM wParam, POINTS pts)
{
	g_ps_current = g_ps_julia;
	InvalidateRect(hWnd, NULL, FALSE);
	return 0;
}

LRESULT __stdcall WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg)
	{
	case WM_CREATE: return MainWnd_OnCreate(hWnd, (LPCREATESTRUCT)lParam);
	case WM_DESTROY: return MainWnd_OnDestroy(hWnd);
	case WM_SIZE: return MainWnd_OnSize(hWnd, wParam, MAKEPOINTS(lParam));
	case WM_LBUTTONDOWN: return MainWnd_OnLButtonDown(hWnd, wParam, MAKEPOINTS(lParam));
	case WM_RBUTTONDOWN: return MainWnd_OnRButtonDown(hWnd, wParam, MAKEPOINTS(lParam));
	case WM_PAINT: return MainWnd_OnPaint(hWnd);
	default: return DefWindowProc(hWnd, msg, wParam, lParam);
	}
}

int __stdcall wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR szCmdLine, int nShowCmd)
{
	WNDCLASSEX wcex = {
		sizeof wcex, CS_VREDRAW|CS_HREDRAW, WndProc, 0, 0, g_hinst = hInstance,
		LoadIcon(NULL, IDI_APPLICATION), LoadCursor(NULL, IDC_ARROW), NULL/*空画刷防闪烁*/,
		NULL, L"MainWndClass", LoadIcon(NULL, IDI_APPLICATION)
	};
	RegisterClassEx(&wcex);
	RECT rc = { 0, 0, 480, 480 };
	AdjustWindowRectEx(&rc, WS_OVERLAPPEDWINDOW, FALSE, 0);
	g_hmainwnd = CreateWindowEx(0, wcex.lpszClassName, L"D3D11主窗口", WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top,
		NULL, NULL, hInstance, NULL);
	ShowWindow(g_hmainwnd, nShowCmd);
	UpdateWindow(g_hmainwnd);
	MSG msg;
	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return (int)msg.wParam;
}
</d3dcompiler.h></d3d11.h></assert.h></windows.h></code>

[修改于 6年7个月前 - 2017/09/18 03:29:12]

来自:计算机科学 / 软件综合
0
已屏蔽 原因:{{ notice.reason }}已屏蔽
{{notice.noticeContent}}
~~空空如也

想参与大家的讨论?现在就 登录 或者 注册

所属专业
所属分类
上级专业
同级专业
acmilan
进士 学者 笔友
文章
461
回复
2934
学术分
4
2009/05/30注册,5年2个月前活动
暂无简介
主体类型:个人
所属领域:无
认证方式:邮箱
IP归属地:未同步
文件下载
加载中...
{{errorInfo}}
{{downloadWarning}}
你在 {{downloadTime}} 下载过当前文件。
文件名称:{{resource.defaultFile.name}}
下载次数:{{resource.hits}}
上传用户:{{uploader.username}}
所需积分:{{costScores}},{{holdScores}}下载当前附件免费{{description}}
积分不足,去充值
文件已丢失

当前账号的附件下载数量限制如下:
时段 个数
{{f.startingTime}}点 - {{f.endTime}}点 {{f.fileCount}}
视频暂不能访问,请登录试试
仅供内部学术交流或培训使用,请先保存到本地。本内容不代表科创观点,未经原作者同意,请勿转载。
音频暂不能访问,请登录试试
支持的图片格式:jpg, jpeg, png
插入公式
评论控制
加载中...
文号:{{pid}}
投诉或举报
加载中...
{{tip}}
请选择违规类型:
{{reason.type}}

空空如也

加载中...
详情
详情
推送到专栏从专栏移除
设为匿名取消匿名
查看作者
回复
只看作者
加入收藏取消收藏
收藏
取消收藏
折叠回复
置顶取消置顶
评学术分
鼓励
设为精选取消精选
管理提醒
编辑
通过审核
评论控制
退修或删除
历史版本
违规记录
投诉或举报
加入黑名单移除黑名单
查看IP
{{format('YYYY/MM/DD HH:mm:ss', toc)}}