加载中
加载中
表情图片
评为精选
鼓励
加载中...
分享
加载中...
文件下载
加载中...
修改排序
加载中...
C语言画Mandelbrot和Julia集合(DX9SM3加速版)
acmilan2017/06/19软件综合 IP:四川

本来打算用Shader Model 2.0,但是经过测试,Shader Model 2.0的功能太原始,连for循环都无法支持,最后只能改用Shader Model 3.0。由于使用了HLSL编译Shader Model 3.0,所以需要VS2002-2010和DirectX 9.0c SDK 2004-2010, 不能使用VC6和DirectX 9.0b SDK。

DX是DirectX的缩写,SM是Shader Model的缩写。

如果改写成DirectX 10/11版本的话,最低应该需要D3D_FEATURE_LEVEL_9_3和ps_4_0_level_9_3,同时还需要编写一个简易的vs_4_0_level_9_3,因为vertex shader和pixel shader在10/11中都不是可选的。

但是由于vs_4_0_level_9_3和ps_4_0_level_9_3不支持通用循环,需要把循环展开成多次条件判断,512的指令数很容易就用超了,对于较复杂的运算,最低建议使用D3D_FEATURE_LEVEL_10_0、vs_4_0和ps_4_0。

Other
vs_1_1 - 128指令 vs_2_0 - 256指令 vs_4_0_level_9_1 - 256指令 vs_2_x - 256指令 vs_4_0_level_9_3 - 256指令 vs_3_0 - 最少512指令,上限到D3DCAPS9.MaxVertexShader30InstructionSlots,支持通用循环 vs_4_0 - 无限制,支持通用循环 ps_2_0 - 32纹理指令+64算术指令 ps_4_0_level_9_1 - 32纹理指令+64算术指令 ps_2_x - 最少96指令,上限到D3DCAPS9.D3DPSHADERCAPS2_0.NumInstructionSlots ps_4_0_level_9_3 - 512指令 vs_3_0 - 最少512指令,上限到D3DCAPS9.MaxPixelShader30InstructionSlots,支持通用循环 vs_4_0 - 无限制,支持通用循环


attachment icon dxmandelbrot.zip 14.89MB ZIP 35次下载

GPU部分:

Other
// complexsets.txt float4 ps_mandelbrot(float2 tex : TEXCOORD0) : COLOR0 { 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 + tex.x; zvar.y="zvar2.x" tex.y; } return float4(i 16.0, 0.0f, 1.0f); float4 ps_julia(float2 tex : texcoord0) color0 zvar="tex;" float i; for (i="0;" i < && 0.4f; 0.3f; code></=>

CPU部分:

Other
// main.c #include <windows.h> #include <tchar.h> // DirectX 9.0c SDK or higher #include <d3d9.h> #include <d3dx9.h> #pragma comment(lib, "d3d9.lib") #pragma comment(lib, "d3dx9.lib") #pragma comment(linker, "/nodefaultlib:libcp") LPDIRECT3D9 g_pD3D = NULL; LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; LPDIRECT3DPIXELSHADER9 g_pPSmandelbrot = NULL; LPDIRECT3DPIXELSHADER9 g_pPSjulia = NULL; LPDIRECT3DPIXELSHADER9 g_pPS = NULL; typedef struct CUSTOMVERTEX { FLOAT x, y, z, rhw; FLOAT u, v; }CUSTOMVERTEX; #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_TEX1) HRESULT InitD3D(HWND hWnd) { D3DPRESENT_PARAMETERS d3dpp; if (NULL == (g_pD3D = Direct3DCreate9(D3D_SDK_VERSION))) return E_FAIL; ZeroMemory(&d3dpp, sizeof(d3dpp)); d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; if (FAILED(IDirect3D9_CreateDevice(g_pD3D, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice))) { return E_FAIL; } return S_OK; } HRESULT CompileAndCreatePS(LPCTSTR filename, LPSTR funcname, LPDIRECT3DPIXELSHADER9 *pps) { LPD3DXBUFFER psbuf = NULL, errmsg = NULL; HRESULT hr = S_OK; hr = D3DXCompileShaderFromFile(filename, NULL, NULL, funcname, "ps_3_0", 0, &psbuf, &errmsg, NULL); if (errmsg) { MessageBoxA(NULL, (char*)errmsg->lpVtbl->GetBufferPointer(errmsg), "err", MB_ICONERROR); errmsg->lpVtbl->Release(errmsg); return hr; } else if (FAILED(hr)) { return hr; } hr = IDirect3DDevice9_CreatePixelShader(g_pd3dDevice, (DWORD*)psbuf->lpVtbl->GetBufferPointer(psbuf), pps); psbuf->lpVtbl->Release(psbuf); return S_OK; } HRESULT InitRes() { CUSTOMVERTEX vertices[] = { { 0.0f, 0.0f, 0.5f, 1.0f, -2.2f, -2.2f, }, { 480.0f, 0.0f, 0.5f, 1.0f, 2.2f, -2.2f, }, { 0.0f, 480.0f, 0.5f, 1.0f, -2.2f, 2.2f, }, { 480.0f, 480.0f, 0.5f, 1.0f, 2.2f, 2.2f, }, }; HRESULT hr = S_OK; VOID* pVertices; hr = IDirect3DDevice9_CreateVertexBuffer(g_pd3dDevice, 4*sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL); if (FAILED(hr)) { return hr; } hr = IDirect3DVertexBuffer9_Lock(g_pVB, 0, sizeof(vertices), (void**)&pVertices, 0); if (FAILED(hr)) return hr; memcpy(pVertices, vertices, sizeof(vertices)); IDirect3DVertexBuffer9_Unlock(g_pVB); CompileAndCreatePS(_T("complexsets.txt"), "ps_mandelbrot", &g_pPSmandelbrot); CompileAndCreatePS(_T("complexsets.txt"), "ps_julia", &g_pPSjulia); g_pPS = g_pPSmandelbrot; return S_OK; } VOID Cleanup() { if (g_pPSjulia) IDirect3DPixelShader9_Release(g_pPSjulia); if (g_pPSmandelbrot) IDirect3DPixelShader9_Release(g_pPSmandelbrot); if (g_pVB != NULL) IDirect3DVertexBuffer9_Release(g_pVB); if (g_pd3dDevice != NULL) IDirect3DDevice9_Release(g_pd3dDevice); if (g_pD3D != NULL) IDirect3D9_Release(g_pD3D); } VOID Render() { IDirect3DDevice9_Clear(g_pd3dDevice, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0f, 0); if (SUCCEEDED(IDirect3DDevice9_BeginScene(g_pd3dDevice))) { IDirect3DDevice9_SetStreamSource(g_pd3dDevice, 0, g_pVB, 0, sizeof(CUSTOMVERTEX)); IDirect3DDevice9_SetFVF(g_pd3dDevice, D3DFVF_CUSTOMVERTEX); IDirect3DDevice9_SetPixelShader(g_pd3dDevice, g_pPS); IDirect3DDevice9_DrawPrimitive(g_pd3dDevice, D3DPT_TRIANGLESTRIP, 0, 2); IDirect3DDevice9_EndScene(g_pd3dDevice); } IDirect3DDevice9_Present(g_pd3dDevice, NULL, NULL, NULL, NULL); } LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_LBUTTONDOWN: g_pPS = g_pPSmandelbrot; return 0; case WM_RBUTTONDOWN: g_pPS = g_pPSjulia; return 0; case WM_DESTROY: Cleanup(); PostQuitMessage(0); return 0; } return DefWindowProc(hWnd, msg, wParam, lParam); } INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR szCmdLine, int nShowCmd) { WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L, hInst, LoadIcon(NULL, IDI_APPLICATION), LoadCursor(NULL, IDC_ARROW), NULL, NULL, _T("MainWndProc"), wc.hIcon }; RECT rc = { 0, 0, 480, 480 }; MSG msg; HWND hWnd; if (!RegisterClassEx(&wc)) return 0; AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE); hWnd = CreateWindow(wc.lpszClassName, _T("Mandelbrot and Julia"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, wc.hInstance, NULL); if (SUCCEEDED(InitD3D(hWnd))) { if (SUCCEEDED(InitRes())) { ShowWindow(hWnd, SW_SHOWDEFAULT); UpdateWindow(hWnd); 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; } </d3dx9.h></d3d9.h></tchar.h></windows.h>

更新:支持Visual C++ 6.0和DirectX 9.0b SDK

通过DirectX 9.0c SDK的fxc将上述HLSL代码编译为Shader Model 3.0 ASM代码,即可支持DirectX 9.0b SDK。

ps_mandelbrot.txt:

Other
// ps_mandelbrot.txt ps_3_0 def c0, 0, 0, 4, 1 def c1, 0.0625, 0, 0, 0 defi i0, 16, 0, 0, 0 dcl_texcoord v0.xy mov r0.y, c0.y mov r0.z, c0.y mov r0.w, c0.y rep i0 mul r0.x, r0.z, r0.z mad r0.x, r0.y, r0.y, r0.x break_lt c0.z, r0.x mul r0.x, r0.z, r0.z mad r0.x, r0.y, r0.y, -r0.x add r0.x, r0.x, v0.x dp2add r0.z, r0.y, r0.z, v0.y add r0.w, r0.w, c0.w mov r0.y, r0.x endrep mul oC0.x, r0.w, c1.x mov oC0.yzw, c0.xyyw

ps_julia.txt

Other
// ps_julia.txt ps_3_0 def c0, 0, 0, 4, 0.400000006 def c1, 0.300000012, 1, 0.0625, 0 defi i0, 16, 0, 0, 0 dcl_texcoord v0.xy mov r0.y, v0.x mov r0.z, v0.y mov r0.w, c0.y rep i0 mul r0.x, r0.z, r0.z mad r0.x, r0.y, r0.y, r0.x break_lt c0.z, r0.x mul r0.x, r0.z, r0.z mad r0.x, r0.y, r0.y, -r0.x add r0.x, r0.x, c0.w dp2add r0.z, r0.y, r0.z, c1.x add r0.w, r0.w, c1.y mov r0.y, r0.x endrep mul oC0.x, r0.w, c1.z mov oC0.yzw, c1.xwwy

main.c

Other
// main.c #include <windows.h> #include <tchar.h> #include <d3d9.h> #include <d3dx9.h> #pragma comment(lib, "d3d9.lib") #pragma comment(lib, "d3dx9.lib") LPDIRECT3D9 g_pD3D = NULL; LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; LPDIRECT3DPIXELSHADER9 g_pPSmandelbrot = NULL; LPDIRECT3DPIXELSHADER9 g_pPSjulia = NULL; LPDIRECT3DPIXELSHADER9 g_pPS = NULL; typedef struct CUSTOMVERTEX { FLOAT x, y, z, rhw; FLOAT u, v; }CUSTOMVERTEX; #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_TEX1) HRESULT InitD3D(HWND hWnd) { D3DPRESENT_PARAMETERS d3dpp; if (NULL == (g_pD3D = Direct3DCreate9(D3D_SDK_VERSION))) return E_FAIL; ZeroMemory(&d3dpp, sizeof(d3dpp)); d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; if (FAILED(IDirect3D9_CreateDevice(g_pD3D, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice))) { return E_FAIL; } return S_OK; } HRESULT AssembleAndCreatePS(LPCTSTR filename, LPDIRECT3DPIXELSHADER9 *pps) { LPD3DXBUFFER psbuf = NULL, errmsg = NULL; HRESULT hr = S_OK; hr = D3DXAssembleShaderFromFile(filename, NULL, NULL, 0, &psbuf, &errmsg); if (errmsg) { MessageBoxA(NULL, (char*)errmsg->lpVtbl->GetBufferPointer(errmsg), "err", MB_ICONERROR); errmsg->lpVtbl->Release(errmsg); return hr; } else if (FAILED(hr)) { return hr; } hr = IDirect3DDevice9_CreatePixelShader(g_pd3dDevice, (DWORD*)psbuf->lpVtbl->GetBufferPointer(psbuf), pps); psbuf->lpVtbl->Release(psbuf); return S_OK; } HRESULT InitRes() { CUSTOMVERTEX vertices[] = { { 0.0f, 0.0f, 0.5f, 1.0f, -2.2f, -2.2f, }, { 480.0f, 0.0f, 0.5f, 1.0f, 2.2f, -2.2f, }, { 0.0f, 480.0f, 0.5f, 1.0f, -2.2f, 2.2f, }, { 480.0f, 480.0f, 0.5f, 1.0f, 2.2f, 2.2f, }, }; HRESULT hr = S_OK; VOID* pVertices; hr = IDirect3DDevice9_CreateVertexBuffer(g_pd3dDevice, 4*sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL); if (FAILED(hr)) { return hr; } hr = IDirect3DVertexBuffer9_Lock(g_pVB, 0, sizeof(vertices), (void**)&pVertices, 0); if (FAILED(hr)) return hr; memcpy(pVertices, vertices, sizeof(vertices)); IDirect3DVertexBuffer9_Unlock(g_pVB); AssembleAndCreatePS(_T("ps_mandelbrot.txt"), &g_pPSmandelbrot); AssembleAndCreatePS(_T("ps_julia.txt"), &g_pPSjulia); g_pPS = g_pPSmandelbrot; return S_OK; } VOID Cleanup() { if (g_pPSjulia) IDirect3DPixelShader9_Release(g_pPSjulia); if (g_pPSmandelbrot) IDirect3DPixelShader9_Release(g_pPSmandelbrot); if (g_pVB != NULL) IDirect3DVertexBuffer9_Release(g_pVB); if (g_pd3dDevice != NULL) IDirect3DDevice9_Release(g_pd3dDevice); if (g_pD3D != NULL) IDirect3D9_Release(g_pD3D); } VOID Render() { IDirect3DDevice9_Clear(g_pd3dDevice, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0f, 0); if (SUCCEEDED(IDirect3DDevice9_BeginScene(g_pd3dDevice))) { IDirect3DDevice9_SetStreamSource(g_pd3dDevice, 0, g_pVB, 0, sizeof(CUSTOMVERTEX)); IDirect3DDevice9_SetFVF(g_pd3dDevice, D3DFVF_CUSTOMVERTEX); IDirect3DDevice9_SetPixelShader(g_pd3dDevice, g_pPS); IDirect3DDevice9_DrawPrimitive(g_pd3dDevice, D3DPT_TRIANGLESTRIP, 0, 2); IDirect3DDevice9_EndScene(g_pd3dDevice); } IDirect3DDevice9_Present(g_pd3dDevice, NULL, NULL, NULL, NULL); } LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_LBUTTONDOWN: g_pPS = g_pPSmandelbrot; return 0; case WM_RBUTTONDOWN: g_pPS = g_pPSjulia; return 0; case WM_DESTROY: Cleanup(); PostQuitMessage(0); return 0; } return DefWindowProc(hWnd, msg, wParam, lParam); } INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR szCmdLine, int nShowCmd) { WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L, hInst, LoadIcon(NULL, IDI_APPLICATION), LoadCursor(NULL, IDC_ARROW), NULL, NULL, _T("MainWndProc"), wc.hIcon }; RECT rc = { 0, 0, 480, 480 }; MSG msg; HWND hWnd; if (!RegisterClassEx(&wc)) return 0; AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE); hWnd = CreateWindow(wc.lpszClassName, _T("Mandelbrot and Julia"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, wc.hInstance, NULL); if (SUCCEEDED(InitD3D(hWnd))) { if (SUCCEEDED(InitRes())) { ShowWindow(hWnd, SW_SHOWDEFAULT); UpdateWindow(hWnd); 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; } </d3dx9.h></d3d9.h></tchar.h></windows.h>

[修改于 8年1个月前 - 2017/08/11 21:27:30]

来自:计算机科学 / 软件综合
1
新版本公告
~~空空如也
zx-16533
8年0个月前 IP:广东
839548

写了个cuda版的

Other
#include <stdio.h> #include <stdlib.h> #include <cuda_runtime.h> #define grid 10 #define block 1024 bool InitCUDA() { int count; cudaGetDeviceCount(&count); if (count == 0) { fprintf(stderr, "There is no device.\n"); return false; } int i; for (i = 0; i < count; i++) { cudaDeviceProp prop; cudaGetDeviceProperties(&prop, i); if (cudaGetDeviceProperties(&prop, i) == cudaSuccess) { if (prop.major >= 1) { break; } } } if (i == count) { fprintf(stderr, "There is no device supporting CUDA 1.x.\n"); return false; } cudaSetDevice(i); return true; } struct complex{ float r; float i; }; __device__ float mod(struct complex a){ return sqrt(a.r*a.r+a.i*a.i); } __device__ struct complex add(struct complex a,struct complex b){ struct complex c; c.r=a.r+b.r; c.i=a.i+b.i; return c; } __device__ struct complex square(struct complex a){ struct complex b; b.r=a.r*a.r-a.i*a.i; b.i=2*a.r*a.i; return b; } #define maxx 1000 __global__ void man(struct complex *p,int *o,int tol,int pixels) { int id=blockIdx.x*blockDim.x+threadIdx.x; int i,j,k; struct complex z,c; for(i=0;i*tol+id<pixels;i++){ z.r="0;" z.i="0;" c="p[i*tol+id];" k="maxx;" for(j="1;j<maxx;j++){" z="add(square(z),c);" if((k="=maxx)&&(mod(z)">2.0f)){ k=j; } } o[i*tol+id]=k; } } #define height 2000 #define width 3000 #define xstart -2.0f #define xend 1.0f #define ystart -1.0f #define yend 1.0f int main() { if (!InitCUDA()) { return 0; } struct complex* pic=(struct complex*)malloc(sizeof(struct complex)*width*height); int i,j; for(i=0;i<width;i++){ for(j="0;j<height;j++){" pic[i*height+j].r="xstart+(xend-xstart)*i/width;" pic[i*height+j].i="ystart+(yend-ystart)*j/height;" } struct complex* picd; int *o="(int*)malloc(sizeof(int)*width*height);" *od; cudamalloc(&picd,sizeof(struct complex)*width*height); cudamemcpy(picd,pic,sizeof(struct complex)*width*height,cudamemcpyhosttodevice); cudamalloc(&od,sizeof(int)*width*height); man<<<grid,block>>>(picd,od,grid*block,height*width); cudaMemcpy(o,od,sizeof(int)*width*height,cudaMemcpyDeviceToHost); FILE *fp=fopen("./out.ppm","w"); fprintf(fp,"P3\n%d %d\n255\n",width,height); int r,g,b,col; for(i=0;i<height;i++){ for(j="0;j<width;j++){" col="o[j*height+i];" if(col="=maxx){" r="0;" g="0;" b="0;" }else{ } fprintf(fp,"%d %d ",r,g,b); fprintf(fp,"\n"); fclose(fp); free(pic); free(o); cudafree(picd); cudafree(od); cudadevicereset(); return 0; < code></height;i++){></width;i++){></pixels;i++){></cuda_runtime.h></stdlib.h></stdio.h>

out.ppm.png

引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论

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

所属专业
所属分类
上级专业
同级专业
acmilan
进士 学者 笔友
文章
461
回复
2934
学术分
4
2009/05/30注册,6年7个月前活动
暂无简介
主体类型:个人
所属领域:无
认证方式:邮箱
IP归属地:未同步
插入公式
评论控制
加载中...
文号:{{pid}}
投诉或举报
加载中...
{{tip}}
请选择违规类型:
{{reason.type}}

空空如也

笔记
{{note.content}}
{{n.user.username}}
{{fromNow(n.toc)}} {{n.status === noteStatus.disabled ? "已屏蔽" : ""}} {{n.status === noteStatus.unknown ? "正在审核" : ""}} {{n.status === noteStatus.deleted ? '已删除' : ''}}
  • 编辑
  • 删除
  • {{n.status === 'disabled' ? "解除屏蔽" : "屏蔽" }}
我也是有底线的