[{"data":1,"prerenderedAt":1692},["ShallowReactive",2],{"doc-\u002Fdocs\u002Ftutorial\u002Feduwin-d3d":3},{"id":4,"title":5,"body":6,"description":16,"extension":1686,"meta":1687,"navigation":381,"path":1688,"seo":1689,"stem":1690,"__hash__":1691},"content\u002Fdocs\u002Ftutorial\u002Feduwin-d3d.md","eduwin 3D 渲染教程",{"type":7,"value":8,"toc":1662},"minimark",[9,13,17,20,24,53,55,59,64,77,87,94,98,104,107,152,156,163,169,175,178,182,189,251,258,273,288,292,299,305,310,321,346,350,357,399,464,468,479,519,595,599,605,608,610,614,618,812,816,911,921,925,940,943,963,966,981,985,991,1071,1081,1101,1104,1143,1145,1149,1156,1160,1455,1459,1462,1466,1553,1557,1567,1620,1626,1628,1632,1658],[10,11,5],"h1",{"id":12},"eduwin-3d-渲染教程",[14,15,16],"p",{},"本文从零讲解 3D 渲染的基础概念，然后步进到 eduwin D3D 封装的使用。",[18,19],"hr",{},[21,22,23],"h2",{"id":23},"目录",[25,26,27,35,41,47],"ol",{},[28,29,30],"li",{},[31,32,34],"a",{"href":33},"#1-3d-%E6%B8%B2%E6%9F%93%E7%9A%84%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5","3D 渲染的基本概念",[28,36,37],{},[31,38,40],{"href":39},"#2-eduwin-%E7%9A%84-d3d-%E5%B0%81%E8%A3%85","eduwin 的 D3D 封装",[28,42,43],{},[31,44,46],{"href":45},"#3-%E6%9E%84%E5%BB%BA%E7%AC%AC%E4%B8%80%E4%B8%AA-3d-%E7%A8%8B%E5%BA%8F","构建第一个 3D 程序",[28,48,49],{},[31,50,52],{"href":51},"#4-%E8%BF%9B%E4%B8%80%E6%AD%A5%E9%98%85%E8%AF%BB","进一步阅读",[18,54],{},[21,56,58],{"id":57},"_1-3d-渲染的基本概念","1. 3D 渲染的基本概念",[60,61,63],"h3",{"id":62},"_11-坐标系","1.1 坐标系",[14,65,66,67,71,72,76],{},"3D 渲染使用",[68,69,70],"strong",{},"三维坐标系","来表示空间中的位置。每个点用 ",[73,74,75],"code",{},"(x, y, z)"," 三个坐标表示。",[78,79,84],"pre",{"className":80,"code":82,"language":83},[81],"language-text","  y\n  |\n  |___ x\n \u002F\nz\n","text",[73,85,82],{"__ignoreMap":86},"",[14,88,89,90,93],{},"D3D11 使用",[68,91,92],{},"左手系","：伸出左手，食指朝上（Y），拇指朝右（X），中指朝前（Z）。Z 正方向指向屏幕内部。",[60,95,97],{"id":96},"_12-顶点","1.2 顶点",[14,99,100,103],{},[68,101,102],{},"顶点","是 3D 模型的基本单元。一个顶点包含位置信息，还可以包含颜色、法线、纹理坐标等属性。",[14,105,106],{},"在 eduwin 中，顶点包含位置 + 法线 + UV + 顶点色：",[78,108,112],{"className":109,"code":110,"language":111,"meta":86,"style":86},"language-c shiki shiki-themes github-light github-dark","typedef struct {\n    float x, y, z;       \u002F\u002F 位置坐标\n    float nx, ny, nz;    \u002F\u002F 法线\n    float u, v;          \u002F\u002F 纹理坐标\n    float r, g, b, a;    \u002F\u002F 顶点色 (红绿蓝透明度，范围 0~1)\n} dx_vertex;\n","c",[73,113,114,122,128,134,140,146],{"__ignoreMap":86},[115,116,119],"span",{"class":117,"line":118},"line",1,[115,120,121],{},"typedef struct {\n",[115,123,125],{"class":117,"line":124},2,[115,126,127],{},"    float x, y, z;       \u002F\u002F 位置坐标\n",[115,129,131],{"class":117,"line":130},3,[115,132,133],{},"    float nx, ny, nz;    \u002F\u002F 法线\n",[115,135,137],{"class":117,"line":136},4,[115,138,139],{},"    float u, v;          \u002F\u002F 纹理坐标\n",[115,141,143],{"class":117,"line":142},5,[115,144,145],{},"    float r, g, b, a;    \u002F\u002F 顶点色 (红绿蓝透明度，范围 0~1)\n",[115,147,149],{"class":117,"line":148},6,[115,150,151],{},"} dx_vertex;\n",[60,153,155],{"id":154},"_13-三角形和索引","1.3 三角形和索引",[14,157,158,159,162],{},"三个顶点构成一个",[68,160,161],{},"三角形","（3D 渲染的最小图元）。一堆三角形拼起来就是 3D 模型。",[14,164,165,168],{},[68,166,167],{},"索引","的作用是复用顶点。例如一个矩形需要 2 个三角形（6 个顶点），但如果用索引，只需 4 个顶点 + 6 个索引：",[78,170,173],{"className":171,"code":172,"language":83},[81],"顶点: [A, B, C, D]\n索引: [0,1,2,  0,2,3]  →  三角形1: A-B-C, 三角形2: A-C-D\n",[73,174,172],{"__ignoreMap":86},[14,176,177],{},"eduwin 使用 16 位无符号整数索引。",[60,179,181],{"id":180},"_14-变换矩阵","1.4 变换矩阵",[14,183,184,185,188],{},"3D 中的位置变换通过 ",[68,186,187],{},"4×4 矩阵"," 计算。最基本的变换有三种：",[190,191,192,208],"table",{},[193,194,195],"thead",{},[196,197,198,202,205],"tr",{},[199,200,201],"th",{},"变换",[199,203,204],{},"作用",[199,206,207],{},"示例",[209,210,211,225,238],"tbody",{},[196,212,213,219,222],{},[214,215,216],"td",{},[68,217,218],{},"平移 (Translation)",[214,220,221],{},"移动位置",[214,223,224],{},"把物体从原点移到 (10, 0, 0)",[196,226,227,232,235],{},[214,228,229],{},[68,230,231],{},"旋转 (Rotation)",[214,233,234],{},"绕轴旋转",[214,236,237],{},"物体绕 Y 轴转 45°",[196,239,240,245,248],{},[214,241,242],{},[68,243,244],{},"缩放 (Scale)",[214,246,247],{},"放大缩小",[214,249,250],{},"把物体放大 2 倍",[14,252,253,254,257],{},"矩阵可以",[68,255,256],{},"相乘组合","：先旋转再平移 = 旋转矩阵 × 平移矩阵。",[14,259,260,261,264,265,268,269,272],{},"eduwin 使用 ",[68,262,263],{},"row-major"," 矩阵存储，与 ",[73,266,267],{},"D3DMATRIX"," 和 HLSL 的 ",[73,270,271],{},"row_major float4x4"," 约定一致：",[78,274,276],{"className":109,"code":275,"language":111,"meta":86,"style":86},"typedef struct { float m[16]; } dx_mat4;\n\u002F\u002F m[row*4+col] — m[0]=_11, m[1]=_12, m[4]=_21, m[12]=_41\n",[73,277,278,283],{"__ignoreMap":86},[115,279,280],{"class":117,"line":118},[115,281,282],{},"typedef struct { float m[16]; } dx_mat4;\n",[115,284,285],{"class":117,"line":124},[115,286,287],{},"\u002F\u002F m[row*4+col] — m[0]=_11, m[1]=_12, m[4]=_21, m[12]=_41\n",[60,289,291],{"id":290},"_15-世界-视图-投影","1.5 世界 → 视图 → 投影",[14,293,294,295,298],{},"3D 渲染的核心管线需要",[68,296,297],{},"三个矩阵","：",[78,300,303],{"className":301,"code":302,"language":83},[81],"顶点位置 → 世界矩阵 → 视图矩阵 → 投影矩阵 → 屏幕坐标\n         (模型摆哪)  (相机看哪)  (透视效果)\n",[73,304,302],{"__ignoreMap":86},[306,307,309],"h4",{"id":308},"世界矩阵-world-matrix","世界矩阵 (World Matrix)",[14,311,312,313,316,317,320],{},"把模型从",[68,314,315],{},"模型坐标系","（原点在模型中心）变换到",[68,318,319],{},"世界坐标系","（模型在场景中的位置）。",[78,322,324],{"className":109,"code":323,"language":111,"meta":86,"style":86},"\u002F\u002F 物体在原点绕 Y 轴旋转\ndx_mat4 world;\ndx_mat4_rotation_y(&world, angle);\ndx_set_world(world);\n",[73,325,326,331,336,341],{"__ignoreMap":86},[115,327,328],{"class":117,"line":118},[115,329,330],{},"\u002F\u002F 物体在原点绕 Y 轴旋转\n",[115,332,333],{"class":117,"line":124},[115,334,335],{},"dx_mat4 world;\n",[115,337,338],{"class":117,"line":130},[115,339,340],{},"dx_mat4_rotation_y(&world, angle);\n",[115,342,343],{"class":117,"line":136},[115,344,345],{},"dx_set_world(world);\n",[306,347,349],{"id":348},"视图矩阵-view-matrix","视图矩阵 (View Matrix)",[14,351,352,353,356],{},"把世界坐标变换到",[68,354,355],{},"相机坐标系","（以相机为原点）。",[78,358,360],{"className":109,"code":359,"language":111,"meta":86,"style":86},"float eye[] = {0, 3, -5};  \u002F\u002F 相机位置\nfloat at[]  = {0, 0, 0};   \u002F\u002F 观察目标\nfloat up[]  = {0, 1, 0};   \u002F\u002F 上方向\n\ndx_mat4 view;\ndx_mat4_look_at_lh(&view, eye, at, up);\ndx_set_view(view);\n",[73,361,362,367,372,377,383,388,393],{"__ignoreMap":86},[115,363,364],{"class":117,"line":118},[115,365,366],{},"float eye[] = {0, 3, -5};  \u002F\u002F 相机位置\n",[115,368,369],{"class":117,"line":124},[115,370,371],{},"float at[]  = {0, 0, 0};   \u002F\u002F 观察目标\n",[115,373,374],{"class":117,"line":130},[115,375,376],{},"float up[]  = {0, 1, 0};   \u002F\u002F 上方向\n",[115,378,379],{"class":117,"line":136},[115,380,382],{"emptyLinePlaceholder":381},true,"\n",[115,384,385],{"class":117,"line":142},[115,386,387],{},"dx_mat4 view;\n",[115,389,390],{"class":117,"line":148},[115,391,392],{},"dx_mat4_look_at_lh(&view, eye, at, up);\n",[115,394,396],{"class":117,"line":395},7,[115,397,398],{},"dx_set_view(view);\n",[190,400,401,414],{},[193,402,403],{},[196,404,405,408,411],{},[199,406,407],{},"参数名",[199,409,410],{},"含义",[199,412,413],{},"示例值",[209,415,416,432,448],{},[196,417,418,423,426],{},[214,419,420],{},[73,421,422],{},"eye",[214,424,425],{},"相机坐标",[214,427,428,431],{},[73,429,430],{},"{0, 3, -5}"," 即头顶稍后",[196,433,434,439,442],{},[214,435,436],{},[73,437,438],{},"at",[214,440,441],{},"观察目标点",[214,443,444,447],{},[73,445,446],{},"{0, 0, 0}"," 看向原点",[196,449,450,455,458],{},[214,451,452],{},[73,453,454],{},"up",[214,456,457],{},"世界\"向上\"方向",[214,459,460,463],{},[73,461,462],{},"{0, 1, 0}"," Y 轴向上",[306,465,467],{"id":466},"投影矩阵-projection-matrix","投影矩阵 (Projection Matrix)",[14,469,470,471,474,475,478],{},"把 3D 坐标变换到 ",[68,472,473],{},"2D 屏幕","（Clip Space），实现",[68,476,477],{},"近大远小","的透视效果。",[78,480,482],{"className":109,"code":481,"language":111,"meta":86,"style":86},"dx_mat4 proj;\ndx_mat4_perspective_fov_lh(&proj,\n    DX_PI\u002F3,           \u002F\u002F FOV: 60°\n    800.0f\u002F600.0f,     \u002F\u002F Aspect: 宽\u002F高\n    0.1f,              \u002F\u002F Near: 近裁剪面\n    100.0f);           \u002F\u002F Far: 远裁剪面\ndx_set_projection(proj);\n",[73,483,484,489,494,499,504,509,514],{"__ignoreMap":86},[115,485,486],{"class":117,"line":118},[115,487,488],{},"dx_mat4 proj;\n",[115,490,491],{"class":117,"line":124},[115,492,493],{},"dx_mat4_perspective_fov_lh(&proj,\n",[115,495,496],{"class":117,"line":130},[115,497,498],{},"    DX_PI\u002F3,           \u002F\u002F FOV: 60°\n",[115,500,501],{"class":117,"line":136},[115,502,503],{},"    800.0f\u002F600.0f,     \u002F\u002F Aspect: 宽\u002F高\n",[115,505,506],{"class":117,"line":142},[115,507,508],{},"    0.1f,              \u002F\u002F Near: 近裁剪面\n",[115,510,511],{"class":117,"line":148},[115,512,513],{},"    100.0f);           \u002F\u002F Far: 远裁剪面\n",[115,515,516],{"class":117,"line":395},[115,517,518],{},"dx_set_projection(proj);\n",[190,520,521,532],{},[193,522,523],{},[196,524,525,527,529],{},[199,526,407],{},[199,528,410],{},[199,530,531],{},"典型值",[209,533,534,550,565,580],{},[196,535,536,541,544],{},[214,537,538],{},[73,539,540],{},"fov_y",[214,542,543],{},"Y 方向视场角（弧度）",[214,545,546,549],{},[73,547,548],{},"π\u002F3","（60°）",[196,551,552,557,560],{},[214,553,554],{},[73,555,556],{},"aspect",[214,558,559],{},"屏幕宽高比",[214,561,562],{},[73,563,564],{},"800\u002F600 = 1.333",[196,566,567,572,575],{},[214,568,569],{},[73,570,571],{},"zn",[214,573,574],{},"近裁剪面",[214,576,577],{},[73,578,579],{},"0.1f",[196,581,582,587,590],{},[214,583,584],{},[73,585,586],{},"zf",[214,588,589],{},"远裁剪面",[214,591,592],{},[73,593,594],{},"100.0f",[60,596,598],{"id":597},"_16-渲染管线","1.6 渲染管线",[78,600,603],{"className":601,"code":602,"language":83},[81],"顶点输入 ─→ 顶点着色器 ─→ 光栅化 ─→ 像素着色器 ─→ 输出合并\n              (VS)                 (PS)\n",[73,604,602],{"__ignoreMap":86},[14,606,607],{},"eduwin 内嵌的 HLSL 顶点着色器用世界\u002F视图\u002F投影三个矩阵变换顶点位置，像素着色器计算顶点色 + 光照结果。",[18,609],{},[21,611,613],{"id":612},"_2-eduwin-的-d3d-封装","2. eduwin 的 D3D 封装",[60,615,617],{"id":616},"_21-主要函数一览","2.1 主要函数一览",[190,619,620,630],{},[193,621,622],{},[196,623,624,627],{},[199,625,626],{},"函数",[199,628,629],{},"用途",[209,631,632,642,652,662,672,682,692,702,712,722,732,742,752,762,772,782,792,802],{},[196,633,634,639],{},[214,635,636],{},[73,637,638],{},"dx_init(hwnd, w, h)",[214,640,641],{},"初始化 D3D11",[196,643,644,649],{},[214,645,646],{},[73,647,648],{},"dx_shutdown()",[214,650,651],{},"销毁所有资源",[196,653,654,659],{},[214,655,656],{},[73,657,658],{},"dx_begin(r,g,b,a)",[214,660,661],{},"开始一帧",[196,663,664,669],{},[214,665,666],{},[73,667,668],{},"dx_end()",[214,670,671],{},"结束一帧，交换缓冲",[196,673,674,679],{},[214,675,676],{},[73,677,678],{},"dx_set_world(m)",[214,680,681],{},"设置世界矩阵",[196,683,684,689],{},[214,685,686],{},[73,687,688],{},"dx_set_view(m)",[214,690,691],{},"设置视图矩阵",[196,693,694,699],{},[214,695,696],{},[73,697,698],{},"dx_set_projection(m)",[214,700,701],{},"设置投影矩阵",[196,703,704,709],{},[214,705,706],{},[73,707,708],{},"dx_create_geometry(v,c,i,c)",[214,710,711],{},"创建自定义几何体",[196,713,714,719],{},[214,715,716],{},[73,717,718],{},"dx_create_box(w,h,d, r,g,b,a)",[214,720,721],{},"创建立方体",[196,723,724,729],{},[214,725,726],{},[73,727,728],{},"dx_create_sphere(r, r,g,b,a)",[214,730,731],{},"创建球体",[196,733,734,739],{},[214,735,736],{},[73,737,738],{},"dx_create_cylinder(r,h, r,g,b,a)",[214,740,741],{},"创建圆柱体",[196,743,744,749],{},[214,745,746],{},[73,747,748],{},"dx_create_pyramid(w,h,d, r,g,b,a)",[214,750,751],{},"创建棱锥",[196,753,754,759],{},[214,755,756],{},[73,757,758],{},"dx_create_plane(w,h, r,g,b,a)",[214,760,761],{},"创建平面",[196,763,764,769],{},[214,765,766],{},[73,767,768],{},"dx_draw_geometry(g,c,s,b)",[214,770,771],{},"绘制几何体",[196,773,774,779],{},[214,775,776],{},[73,777,778],{},"dx_free_geometry(g)",[214,780,781],{},"释放几何体",[196,783,784,789],{},[214,785,786],{},[73,787,788],{},"dx_set_ambient_light(r,g,b,i)",[214,790,791],{},"设置环境光",[196,793,794,799],{},[214,795,796],{},[73,797,798],{},"dx_set_directional_light(dx,dy,dz, r,g,b,i)",[214,800,801],{},"设置方向光",[196,803,804,809],{},[214,805,806],{},[73,807,808],{},"dx_set_point_light(px,py,pz, r,g,b,i, range)",[214,810,811],{},"设置点光源",[60,813,815],{"id":814},"_22-矩阵辅助函数","2.2 矩阵辅助函数",[190,817,818,826],{},[193,819,820],{},[196,821,822,824],{},[199,823,626],{},[199,825,629],{},[209,827,828,838,851,861,871,881,891,901],{},[196,829,830,835],{},[214,831,832],{},[73,833,834],{},"dx_mat4_identity(&m)",[214,836,837],{},"单位矩阵",[196,839,840,845],{},[214,841,842],{},[73,843,844],{},"dx_mat4_mul(&o,&a,&b)",[214,846,847,848],{},"矩阵乘法 ",[73,849,850],{},"o = a × b",[196,852,853,858],{},[214,854,855],{},[73,856,857],{},"dx_mat4_rotation_x(&m, a)",[214,859,860],{},"绕 X 轴旋转",[196,862,863,868],{},[214,864,865],{},[73,866,867],{},"dx_mat4_rotation_y(&m, a)",[214,869,870],{},"绕 Y 轴旋转",[196,872,873,878],{},[214,874,875],{},[73,876,877],{},"dx_mat4_rotation_z(&m, a)",[214,879,880],{},"绕 Z 轴旋转",[196,882,883,888],{},[214,884,885],{},[73,886,887],{},"dx_mat4_translation(&m, x,y,z)",[214,889,890],{},"平移",[196,892,893,898],{},[214,894,895],{},[73,896,897],{},"dx_mat4_look_at_lh(&m, e,a,u)",[214,899,900],{},"观察矩阵（左手系）",[196,902,903,908],{},[214,904,905],{},[73,906,907],{},"dx_mat4_perspective_fov_lh(&m, f,a,n,f)",[214,909,910],{},"透视投影（左手系）",[912,913,914],"blockquote",{},[14,915,916,917],{},"更多细节见 ",[31,918,920],{"href":919},"\u002Fcontent\u002Fdocs\u002Fapi\u002Feduwin-d3d-api.md","eduwin D3D API 文档",[60,922,924],{"id":923},"_23-相机封装","2.3 相机封装",[78,926,928],{"className":109,"code":927,"language":111,"meta":86,"style":86},"void dx_camera_init(dx_camera *cam, float px, float py, float pz, float aspect);\nvoid dx_camera_update(dx_camera *cam);\n",[73,929,930,935],{"__ignoreMap":86},[115,931,932],{"class":117,"line":118},[115,933,934],{},"void dx_camera_init(dx_camera *cam, float px, float py, float pz, float aspect);\n",[115,936,937],{"class":117,"line":124},[115,938,939],{},"void dx_camera_update(dx_camera *cam);\n",[14,941,942],{},"用法：",[78,944,946],{"className":109,"code":945,"language":111,"meta":86,"style":86},"dx_camera cam;\ndx_camera_init(&cam, 0, 3, -5, 800.0f \u002F 600.0f);  \u002F\u002F 位置 + 宽高比\ndx_camera_update(&cam);                             \u002F\u002F 每帧更新\n",[73,947,948,953,958],{"__ignoreMap":86},[115,949,950],{"class":117,"line":118},[115,951,952],{},"dx_camera cam;\n",[115,954,955],{"class":117,"line":124},[115,956,957],{},"dx_camera_init(&cam, 0, 3, -5, 800.0f \u002F 600.0f);  \u002F\u002F 位置 + 宽高比\n",[115,959,960],{"class":117,"line":130},[115,961,962],{},"dx_camera_update(&cam);                             \u002F\u002F 每帧更新\n",[14,964,965],{},"窗口 resize 时改 aspect：",[78,967,969],{"className":109,"code":968,"language":111,"meta":86,"style":86},"cam.aspect = 1024.0f \u002F 768.0f;\ndx_camera_update(&cam);\n",[73,970,971,976],{"__ignoreMap":86},[115,972,973],{"class":117,"line":118},[115,974,975],{},"cam.aspect = 1024.0f \u002F 768.0f;\n",[115,977,978],{"class":117,"line":124},[115,979,980],{},"dx_camera_update(&cam);\n",[60,982,984],{"id":983},"_24-网格mesh-geometry-material-transform","2.4 网格（Mesh = Geometry + Material + Transform）",[14,986,987,990],{},[73,988,989],{},"dx_mesh"," 把几何体 + 材质 + 变换打包，隐藏矩阵操作，仿 Three.js Mesh：",[78,992,994],{"className":109,"code":993,"language":111,"meta":86,"style":86},"typedef struct {\n    dx_geometry *geometry;  \u002F* 顶点数据 *\u002F\n    dx_material *material;  \u002F* 材质（可 NULL） *\u002F\n    float position[3];      \u002F* 平移 *\u002F\n    float rotation[3];      \u002F* 旋转（XYZ 欧拉角） *\u002F\n    float scale[3];         \u002F* 缩放 *\u002F\n} dx_mesh;\n\ndx_mesh* dx_create_mesh(dx_geometry *geo, dx_material *mat);\nvoid     dx_mesh_set_position(dx_mesh *m, float x, float y, float z);\nvoid     dx_mesh_set_rotation(dx_mesh *m, float x, float y, float z);\nvoid     dx_mesh_set_scale(dx_mesh *m, float x, float y, float z);\nvoid     dx_mesh_draw(dx_mesh *m);\nvoid     dx_free_mesh(dx_mesh *m);\n",[73,995,996,1000,1005,1010,1015,1020,1025,1030,1035,1041,1047,1053,1059,1065],{"__ignoreMap":86},[115,997,998],{"class":117,"line":118},[115,999,121],{},[115,1001,1002],{"class":117,"line":124},[115,1003,1004],{},"    dx_geometry *geometry;  \u002F* 顶点数据 *\u002F\n",[115,1006,1007],{"class":117,"line":130},[115,1008,1009],{},"    dx_material *material;  \u002F* 材质（可 NULL） *\u002F\n",[115,1011,1012],{"class":117,"line":136},[115,1013,1014],{},"    float position[3];      \u002F* 平移 *\u002F\n",[115,1016,1017],{"class":117,"line":142},[115,1018,1019],{},"    float rotation[3];      \u002F* 旋转（XYZ 欧拉角） *\u002F\n",[115,1021,1022],{"class":117,"line":148},[115,1023,1024],{},"    float scale[3];         \u002F* 缩放 *\u002F\n",[115,1026,1027],{"class":117,"line":395},[115,1028,1029],{},"} dx_mesh;\n",[115,1031,1033],{"class":117,"line":1032},8,[115,1034,382],{"emptyLinePlaceholder":381},[115,1036,1038],{"class":117,"line":1037},9,[115,1039,1040],{},"dx_mesh* dx_create_mesh(dx_geometry *geo, dx_material *mat);\n",[115,1042,1044],{"class":117,"line":1043},10,[115,1045,1046],{},"void     dx_mesh_set_position(dx_mesh *m, float x, float y, float z);\n",[115,1048,1050],{"class":117,"line":1049},11,[115,1051,1052],{},"void     dx_mesh_set_rotation(dx_mesh *m, float x, float y, float z);\n",[115,1054,1056],{"class":117,"line":1055},12,[115,1057,1058],{},"void     dx_mesh_set_scale(dx_mesh *m, float x, float y, float z);\n",[115,1060,1062],{"class":117,"line":1061},13,[115,1063,1064],{},"void     dx_mesh_draw(dx_mesh *m);\n",[115,1066,1068],{"class":117,"line":1067},14,[115,1069,1070],{},"void     dx_free_mesh(dx_mesh *m);\n",[14,1072,1073,1076,1077,1080],{},[73,1074,1075],{},"dx_mesh_draw"," 内部自动计算 ",[73,1078,1079],{},"world = S × Rx × Ry × Rz × T","，绑定材质，绘制几何体。\n可直接读写字段：",[78,1082,1084],{"className":109,"code":1083,"language":111,"meta":86,"style":86},"mesh->position[0] = 2;    \u002F* X 位置 *\u002F\nmesh->rotation[1] = 0.5f; \u002F* Y 旋转 *\u002F\nmesh->scale[0] = 2.0f;    \u002F* 水平拉长 2 倍 *\u002F\n",[73,1085,1086,1091,1096],{"__ignoreMap":86},[115,1087,1088],{"class":117,"line":118},[115,1089,1090],{},"mesh->position[0] = 2;    \u002F* X 位置 *\u002F\n",[115,1092,1093],{"class":117,"line":124},[115,1094,1095],{},"mesh->rotation[1] = 0.5f; \u002F* Y 旋转 *\u002F\n",[115,1097,1098],{"class":117,"line":130},[115,1099,1100],{},"mesh->scale[0] = 2.0f;    \u002F* 水平拉长 2 倍 *\u002F\n",[14,1102,1103],{},"位置是固有属性，初始化设一次，每帧只改变化的旋转：",[78,1105,1107],{"className":109,"code":1106,"language":111,"meta":86,"style":86},"\u002F\u002F 初始化（一次）\ndx_mesh *obj = dx_create_mesh(geo, NULL);\ndx_mesh_set_position(obj, 0, 0.5f, 0);\n\n\u002F\u002F 每帧\nobj->rotation[1] = angle;\ndx_mesh_draw(obj);\n",[73,1108,1109,1114,1119,1124,1128,1133,1138],{"__ignoreMap":86},[115,1110,1111],{"class":117,"line":118},[115,1112,1113],{},"\u002F\u002F 初始化（一次）\n",[115,1115,1116],{"class":117,"line":124},[115,1117,1118],{},"dx_mesh *obj = dx_create_mesh(geo, NULL);\n",[115,1120,1121],{"class":117,"line":130},[115,1122,1123],{},"dx_mesh_set_position(obj, 0, 0.5f, 0);\n",[115,1125,1126],{"class":117,"line":136},[115,1127,382],{"emptyLinePlaceholder":381},[115,1129,1130],{"class":117,"line":142},[115,1131,1132],{},"\u002F\u002F 每帧\n",[115,1134,1135],{"class":117,"line":148},[115,1136,1137],{},"obj->rotation[1] = angle;\n",[115,1139,1140],{"class":117,"line":395},[115,1141,1142],{},"dx_mesh_draw(obj);\n",[18,1144],{},[21,1146,1148],{"id":1147},"_3-构建第一个-3d-程序","3. 构建第一个 3D 程序",[14,1150,1151,1152,1155],{},"下面以 ",[73,1153,1154],{},"samples\u002Fd3d_light_demo\u002F"," 为蓝本，一步步构建一个带光照的 3D 场景。",[60,1157,1159],{"id":1158},"_31-完整代码","3.1 完整代码",[78,1161,1163],{"className":109,"code":1162,"language":111,"meta":86,"style":86},"#include \"eduwin.h\"\n#include \u003Cmath.h>\n\nstatic dx_mesh *g_box, *g_ground;\nstatic dx_camera g_cam;\nstatic float g_light_angle = 0;\n\nstatic void on_frame(void)\n{\n    float px, py, pz;\n\n    if (g_box) g_box->rotation[1] += 0.01f;      \u002F* 立方体自转 *\u002F\n\n    \u002F* 点光源绕立方体旋转 *\u002F\n    g_light_angle += 0.015f;\n    px = 2.5f * cosf(g_light_angle);\n    pz = 2.5f * sinf(g_light_angle);\n    py = 1.5f;\n\n    dx_camera_update(&g_cam);\n    dx_begin(0.12f, 0.12f, 0.2f, 1);     \u002F* 深蓝背景 *\u002F\n\n    \u002F* 设置光照 *\u002F\n    dx_set_ambient_light(0.4f, 0.4f, 0.4f, 1);\n    dx_set_directional_light(0.5f, -0.707f, 0.5f, 1, 1, 1, 1);\n    dx_set_point_light(px, py, pz, 1, 0.6f, 0.1f, 0.8f, 5);\n\n    dx_mesh_draw(g_ground);               \u002F* 地面 *\u002F\n    dx_mesh_draw(g_box);                  \u002F* 立方体 *\u002F\n\n    dx_end();\n}\n\nint main(void)\n{\n    if (init_app() != 0) { log_error(L\"init失败\"); return 1; }\n    HWND win = create_window(L\"3D 光照演示\", 800, 600);\n    if (!win) return 1;\n    show_window(win);\n    if (!dx_init(win, 800, 600)) return 1;\n\n    \u002F* 创建物体 *\u002F\n    g_box    = dx_create_mesh(dx_create_box(1.2f, 1.2f, 1.2f, 0.85f, 0.15f, 0.15f, 1), NULL);\n    g_ground = dx_create_mesh(dx_create_plane(8, 8, 0.5f, 0.5f, 0.5f, 1), NULL);\n    dx_mesh_set_position(g_box,    0, 0, 0);\n    dx_mesh_set_position(g_ground, 0, -0.8f, 0);\n\n    dx_camera_init(&g_cam, 0, 1, -3.5f, 800.0f \u002F 600.0f);\n\n    run_app_frame(on_frame);\n    dx_shutdown();\n    return 0;\n}\n",[73,1164,1165,1170,1175,1179,1184,1189,1194,1198,1203,1208,1213,1217,1222,1226,1231,1237,1243,1249,1255,1260,1266,1272,1277,1283,1289,1295,1301,1306,1312,1318,1323,1329,1335,1340,1346,1351,1357,1363,1369,1375,1381,1386,1392,1398,1404,1410,1416,1421,1427,1432,1438,1444,1450],{"__ignoreMap":86},[115,1166,1167],{"class":117,"line":118},[115,1168,1169],{},"#include \"eduwin.h\"\n",[115,1171,1172],{"class":117,"line":124},[115,1173,1174],{},"#include \u003Cmath.h>\n",[115,1176,1177],{"class":117,"line":130},[115,1178,382],{"emptyLinePlaceholder":381},[115,1180,1181],{"class":117,"line":136},[115,1182,1183],{},"static dx_mesh *g_box, *g_ground;\n",[115,1185,1186],{"class":117,"line":142},[115,1187,1188],{},"static dx_camera g_cam;\n",[115,1190,1191],{"class":117,"line":148},[115,1192,1193],{},"static float g_light_angle = 0;\n",[115,1195,1196],{"class":117,"line":395},[115,1197,382],{"emptyLinePlaceholder":381},[115,1199,1200],{"class":117,"line":1032},[115,1201,1202],{},"static void on_frame(void)\n",[115,1204,1205],{"class":117,"line":1037},[115,1206,1207],{},"{\n",[115,1209,1210],{"class":117,"line":1043},[115,1211,1212],{},"    float px, py, pz;\n",[115,1214,1215],{"class":117,"line":1049},[115,1216,382],{"emptyLinePlaceholder":381},[115,1218,1219],{"class":117,"line":1055},[115,1220,1221],{},"    if (g_box) g_box->rotation[1] += 0.01f;      \u002F* 立方体自转 *\u002F\n",[115,1223,1224],{"class":117,"line":1061},[115,1225,382],{"emptyLinePlaceholder":381},[115,1227,1228],{"class":117,"line":1067},[115,1229,1230],{},"    \u002F* 点光源绕立方体旋转 *\u002F\n",[115,1232,1234],{"class":117,"line":1233},15,[115,1235,1236],{},"    g_light_angle += 0.015f;\n",[115,1238,1240],{"class":117,"line":1239},16,[115,1241,1242],{},"    px = 2.5f * cosf(g_light_angle);\n",[115,1244,1246],{"class":117,"line":1245},17,[115,1247,1248],{},"    pz = 2.5f * sinf(g_light_angle);\n",[115,1250,1252],{"class":117,"line":1251},18,[115,1253,1254],{},"    py = 1.5f;\n",[115,1256,1258],{"class":117,"line":1257},19,[115,1259,382],{"emptyLinePlaceholder":381},[115,1261,1263],{"class":117,"line":1262},20,[115,1264,1265],{},"    dx_camera_update(&g_cam);\n",[115,1267,1269],{"class":117,"line":1268},21,[115,1270,1271],{},"    dx_begin(0.12f, 0.12f, 0.2f, 1);     \u002F* 深蓝背景 *\u002F\n",[115,1273,1275],{"class":117,"line":1274},22,[115,1276,382],{"emptyLinePlaceholder":381},[115,1278,1280],{"class":117,"line":1279},23,[115,1281,1282],{},"    \u002F* 设置光照 *\u002F\n",[115,1284,1286],{"class":117,"line":1285},24,[115,1287,1288],{},"    dx_set_ambient_light(0.4f, 0.4f, 0.4f, 1);\n",[115,1290,1292],{"class":117,"line":1291},25,[115,1293,1294],{},"    dx_set_directional_light(0.5f, -0.707f, 0.5f, 1, 1, 1, 1);\n",[115,1296,1298],{"class":117,"line":1297},26,[115,1299,1300],{},"    dx_set_point_light(px, py, pz, 1, 0.6f, 0.1f, 0.8f, 5);\n",[115,1302,1304],{"class":117,"line":1303},27,[115,1305,382],{"emptyLinePlaceholder":381},[115,1307,1309],{"class":117,"line":1308},28,[115,1310,1311],{},"    dx_mesh_draw(g_ground);               \u002F* 地面 *\u002F\n",[115,1313,1315],{"class":117,"line":1314},29,[115,1316,1317],{},"    dx_mesh_draw(g_box);                  \u002F* 立方体 *\u002F\n",[115,1319,1321],{"class":117,"line":1320},30,[115,1322,382],{"emptyLinePlaceholder":381},[115,1324,1326],{"class":117,"line":1325},31,[115,1327,1328],{},"    dx_end();\n",[115,1330,1332],{"class":117,"line":1331},32,[115,1333,1334],{},"}\n",[115,1336,1338],{"class":117,"line":1337},33,[115,1339,382],{"emptyLinePlaceholder":381},[115,1341,1343],{"class":117,"line":1342},34,[115,1344,1345],{},"int main(void)\n",[115,1347,1349],{"class":117,"line":1348},35,[115,1350,1207],{},[115,1352,1354],{"class":117,"line":1353},36,[115,1355,1356],{},"    if (init_app() != 0) { log_error(L\"init失败\"); return 1; }\n",[115,1358,1360],{"class":117,"line":1359},37,[115,1361,1362],{},"    HWND win = create_window(L\"3D 光照演示\", 800, 600);\n",[115,1364,1366],{"class":117,"line":1365},38,[115,1367,1368],{},"    if (!win) return 1;\n",[115,1370,1372],{"class":117,"line":1371},39,[115,1373,1374],{},"    show_window(win);\n",[115,1376,1378],{"class":117,"line":1377},40,[115,1379,1380],{},"    if (!dx_init(win, 800, 600)) return 1;\n",[115,1382,1384],{"class":117,"line":1383},41,[115,1385,382],{"emptyLinePlaceholder":381},[115,1387,1389],{"class":117,"line":1388},42,[115,1390,1391],{},"    \u002F* 创建物体 *\u002F\n",[115,1393,1395],{"class":117,"line":1394},43,[115,1396,1397],{},"    g_box    = dx_create_mesh(dx_create_box(1.2f, 1.2f, 1.2f, 0.85f, 0.15f, 0.15f, 1), NULL);\n",[115,1399,1401],{"class":117,"line":1400},44,[115,1402,1403],{},"    g_ground = dx_create_mesh(dx_create_plane(8, 8, 0.5f, 0.5f, 0.5f, 1), NULL);\n",[115,1405,1407],{"class":117,"line":1406},45,[115,1408,1409],{},"    dx_mesh_set_position(g_box,    0, 0, 0);\n",[115,1411,1413],{"class":117,"line":1412},46,[115,1414,1415],{},"    dx_mesh_set_position(g_ground, 0, -0.8f, 0);\n",[115,1417,1419],{"class":117,"line":1418},47,[115,1420,382],{"emptyLinePlaceholder":381},[115,1422,1424],{"class":117,"line":1423},48,[115,1425,1426],{},"    dx_camera_init(&g_cam, 0, 1, -3.5f, 800.0f \u002F 600.0f);\n",[115,1428,1430],{"class":117,"line":1429},49,[115,1431,382],{"emptyLinePlaceholder":381},[115,1433,1435],{"class":117,"line":1434},50,[115,1436,1437],{},"    run_app_frame(on_frame);\n",[115,1439,1441],{"class":117,"line":1440},51,[115,1442,1443],{},"    dx_shutdown();\n",[115,1445,1447],{"class":117,"line":1446},52,[115,1448,1449],{},"    return 0;\n",[115,1451,1453],{"class":117,"line":1452},53,[115,1454,1334],{},[60,1456,1458],{"id":1457},"_32-运行效果","3.2 运行效果",[14,1460,1461],{},"运行后你会看到一个灰色地面 + 一个红色立方体在旋转。一个暖色（橙红）点光源围绕立方体旋转，立方体表面光影随之变化，同时有一个方向光从固定方向照射。",[60,1463,1465],{"id":1464},"_33-关键点回顾","3.3 关键点回顾",[190,1467,1468,1478],{},[193,1469,1470],{},[196,1471,1472,1475],{},[199,1473,1474],{},"知识点",[199,1476,1477],{},"说明",[209,1479,1480,1495,1512,1528,1542],{},[196,1481,1482,1485],{},[214,1483,1484],{},"几何体创建",[214,1486,1487,1490,1491,1494],{},[73,1488,1489],{},"dx_create_box"," \u002F ",[73,1492,1493],{},"dx_create_plane"," 自动生成顶点",[196,1496,1497,1500],{},[214,1498,1499],{},"对象系统",[214,1501,1502,1505,1506,1505,1509],{},[73,1503,1504],{},"dx_create_mesh"," + ",[73,1507,1508],{},"dx_mesh_set_position",[73,1510,1511],{},"mesh->rotation[1]",[196,1513,1514,1517],{},[214,1515,1516],{},"光照",[214,1518,1519,1505,1522,1505,1525],{},[73,1520,1521],{},"dx_set_ambient_light",[73,1523,1524],{},"dx_set_directional_light",[73,1526,1527],{},"dx_set_point_light",[196,1529,1530,1533],{},[214,1531,1532],{},"相机",[214,1534,1535,1538,1539],{},[73,1536,1537],{},"dx_camera_init"," + 每帧 ",[73,1540,1541],{},"dx_camera_update",[196,1543,1544,1547],{},[214,1545,1546],{},"帧循环",[214,1548,1549,1552],{},[73,1550,1551],{},"run_app_frame(on_frame)"," 非阻塞消息循环",[60,1554,1556],{"id":1555},"_34-调试技巧","3.4 调试技巧",[14,1558,1559,1560,1563,1564,298],{},"eduwin D3D 的日志通过 ",[73,1561,1562],{},"log_error"," 写入 exe 同目录的 ",[73,1565,1566],{},"log.txt",[190,1568,1569,1578],{},[193,1570,1571],{},[196,1572,1573,1576],{},[199,1574,1575],{},"日志内容",[199,1577,410],{},[209,1579,1580,1590,1600,1610],{},[196,1581,1582,1587],{},[214,1583,1584],{},[73,1585,1586],{},"[d3d] VS: ...",[214,1588,1589],{},"顶点着色器编译错误",[196,1591,1592,1597],{},[214,1593,1594],{},[73,1595,1596],{},"[d3d] PS: ...",[214,1598,1599],{},"像素着色器编译错误",[196,1601,1602,1607],{},[214,1603,1604],{},[73,1605,1606],{},"[d3d] CreateDevice",[214,1608,1609],{},"D3D11 设备创建失败",[196,1611,1612,1617],{},[214,1613,1614],{},[73,1615,1616],{},"[main] D3D11 初始化失败",[214,1618,1619],{},"dx_init 返回 0",[14,1621,1622,1623,1625],{},"运行时查看 ",[73,1624,1566],{},"，无内容 = 一切正常。",[18,1627],{},[21,1629,1631],{"id":1630},"_4-进一步阅读","4. 进一步阅读",[1633,1634,1635,1640,1646,1652],"ul",{},[28,1636,1637,1639],{},[31,1638,920],{"href":919}," — 函数参考",[28,1641,1642],{},[31,1643,1645],{"href":1644},"\u002Fcontent\u002Fdocs\u002Fsamples\u002Fd3d_light_demo.md","samples\u002Fd3d_light_demo — 动态光照演示",[28,1647,1648],{},[31,1649,1651],{"href":1650},"\u002Fcontent\u002Fdocs\u002Fsamples\u002Fd3d_shape_demo.md","samples\u002Fd3d_shape_demo — 基本体形状展示",[28,1653,1654],{},[31,1655,1657],{"href":1656},"\u002Fcontent\u002Fdocs\u002Fsamples\u002Fd3d_material_demo.md","samples\u002Fd3d_material_demo — 纹理材质演示",[1659,1660,1661],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":86,"searchDepth":124,"depth":124,"links":1663},[1664,1665,1673,1679,1685],{"id":23,"depth":124,"text":23},{"id":57,"depth":124,"text":58,"children":1666},[1667,1668,1669,1670,1671,1672],{"id":62,"depth":130,"text":63},{"id":96,"depth":130,"text":97},{"id":154,"depth":130,"text":155},{"id":180,"depth":130,"text":181},{"id":290,"depth":130,"text":291},{"id":597,"depth":130,"text":598},{"id":612,"depth":124,"text":613,"children":1674},[1675,1676,1677,1678],{"id":616,"depth":130,"text":617},{"id":814,"depth":130,"text":815},{"id":923,"depth":130,"text":924},{"id":983,"depth":130,"text":984},{"id":1147,"depth":124,"text":1148,"children":1680},[1681,1682,1683,1684],{"id":1158,"depth":130,"text":1159},{"id":1457,"depth":130,"text":1458},{"id":1464,"depth":130,"text":1465},{"id":1555,"depth":130,"text":1556},{"id":1630,"depth":124,"text":1631},"md",{},"\u002Fdocs\u002Ftutorial\u002Feduwin-d3d",{"title":5,"description":16},"docs\u002Ftutorial\u002Feduwin-d3d","Bjye55_goubyyOcUuWRG6h3XYOAdprkq-BBP9j72lMM",1782488679845]