网站建设php教程佛山公司建网站

张小明 2026/1/9 16:57:22
网站建设php教程,佛山公司建网站,开发公司成本部职责岗位职责和流程,微信企业网站上一篇#xff1a;材质系统 | 下一篇#xff1a;资源系统 | 返回目录 #x1f4da; 快速导航 #x1f4cb; 目录 引言学习目标几何体概念几何体数据结构几何体系统架构几何体配置与创建程序化几何体生成渲染器集成渲染包系统使用示例常见问题练习与挑战下一步 #x1f4d…上一篇材质系统 | 下一篇资源系统 | 返回目录 快速导航 目录引言学习目标几何体概念几何体数据结构几何体系统架构几何体配置与创建程序化几何体生成渲染器集成渲染包系统使用示例常见问题练习与挑战下一步 引言在前面的教程中我们实现了纹理系统和材质系统能够定义和管理物体的外观。但是要渲染一个3D物体我们还需要几何体数据顶点位置、纹理坐标、索引等。目前我们的渲染代码中顶点数据是硬编码的vertex_3d verts[4];verts[0].positionvec3(-0.5,-0.5,0);// ...u32 indices[6]{0,1,2,0,3,1};这种方式有诸多问题难以复用- 相同形状的物体需要重复定义无法管理- 不知道加载了哪些几何体内存浪费- 重复的几何体占用多份内存缺乏抽象- 几何体和材质没有关联几何体系统解决了这些问题提供了几何体的创建和管理引用计数和自动释放与材质系统的集成程序化几何体生成 学习目标目标描述 理解几何体概念掌握顶点、索引、材质的关系 实现几何体系统使用与纹理/材质相同的模式 程序化生成创建平面、立方体等基础形状 渲染包设计批量提交几何体到渲染器 系统集成连接几何体、材质、渲染器几何体概念什么是几何体几何体Geometry是3D物体的形状定义包含几何体 顶点数据 索引数据 材质 顶点数据 vertex[0] {position: (x, y, z), texcoord: (u, v)} vertex[1] {position: (x, y, z), texcoord: (u, v)} ... 索引数据 indices [0, 1, 2, 0, 2, 3] // 定义三角形 材质 指向material*的引用几何体 vs 网格 vs 模型模型Model ┌────────────────────────┐ │ 人物角色 │ ├────────────────────────┤ │ 网格0: 头部 │ 多个网格组成 │ 网格1: 身体 │ │ 网格2: 武器 │ └────────────────────────┘ 网格Mesh ┌────────────────────────┐ │ 头部网格 │ 一个逻辑单元 ├────────────────────────┤ │ 几何体0: LOD 0 (高精度)│ 不同LOD级别 │ 几何体1: LOD 1 (中精度)│ │ 几何体2: LOD 2 (低精度)│ └────────────────────────┘ 几何体Geometry ┌────────────────────────┐ │ 顶点缓冲区 │ GPU资源 │ 索引缓冲区 │ │ 材质引用 │ └────────────────────────┘在Kohi引擎中Geometry是最基础的可渲染单元。几何体数据流导出加载geometry_config创建上传绘制3D建模软件.obj/.fbx文件顶点/索引数组几何体系统geometry对象GPU缓冲区屏幕输出几何体数据结构几何体结构engine/src/resources/resource_types.h#defineGEOMETRY_NAME_MAX_LENGTH256/** * brief 几何体世界中的实际几何形状 * 通常但不总是与材质配对 */typedefstructgeometry{u32 id;// 几何体ID系统索引u32 internal_id;// 渲染器内部IDGPU资源u32 generation;// 版本号charname[GEOMETRY_NAME_MAX_LENGTH];// 几何体名称material*material;// 关联的材质}geometry;几何体配置engine/src/systems/geometry_system.h/** * brief 几何体配置用于创建几何体 */typedefstructgeometry_config{u32 vertex_count;// 顶点数量vertex_3d*vertices;// 顶点数组u32 index_count;// 索引数量u32*indices;// 索引数组charname[GEOMETRY_NAME_MAX_LENGTH];// 几何体名称charmaterial_name[MATERIAL_NAME_MAX_LENGTH];// 材质名称}geometry_config;顶点结构回顾typedefstructvertex_3d{vec3 position;// 位置 (x, y, z)vec2 texcoord;// 纹理坐标 (u, v)}vertex_3d;数据关系geometry plane_01 ├─ id: 5 ├─ internal_id: 12 (Vulkan顶点缓冲区偏移) ├─ name: plane_01 └─ material → material wood ├─ diffuse_colour: (0.6, 0.4, 0.2, 1.0) └─ diffuse_map → texture wood_diffuse └─ GPU纹理资源 渲染时 1. 从geometry获取material 2. 从material获取diffuse_colour和diffuse_map 3. 使用geometry.internal_id绘制顶点数据几何体系统架构几何体系统的设计延续了纹理和材质系统的模式。系统状态engine/src/systems/geometry_system.c/** * brief 几何体引用信息 */typedefstructgeometry_reference{u64 reference_count;// 引用计数geometry geometry;// 几何体数据直接嵌入而非指针b8 auto_release;// 是否自动释放}geometry_reference;/** * brief 几何体系统状态 */typedefstructgeometry_system_state{geometry_system_config config;// 配置geometry default_geometry;// 默认几何体四边形// 已注册几何体数组geometry_reference*registered_geometries;}geometry_system_state;staticgeometry_system_state*state_ptr0;配置结构typedefstructgeometry_system_config{/** * brief 最大几何体数量 * 注意应该远大于静态网格数量因为每个网格可能有多个几何体LOD等 */u32 max_geometry_count;}geometry_system_config;与纹理/材质系统的差异纹理系统 ┌──────────────────────────────┐ │ texture_reference[] │ │ - reference_count │ │ - handle (索引到texture[]) │ 间接引用 │ - auto_release │ └──────────────────────────────┘ ┌──────────────────────────────┐ │ texture[] │ 单独数组 │ - 纹理数据 │ └──────────────────────────────┘ 几何体系统 ┌──────────────────────────────┐ │ geometry_reference[] │ │ - reference_count │ │ - geometry (直接嵌入) │ 直接嵌入 │ - auto_release │ └──────────────────────────────┘为什么直接嵌入简化查找不需要二次索引减少内存碎片数据连续存储几何体数据较小不像纹理有大量像素数据系统内存布局Geometry System内存布局 ┌────────────────────────────────────────┐ │ geometry_system_state (结构体) │ ├────────────────────────────────────────┤ │ registered_geometries[4096] (数组) │ │ - geometry_reference 0 │ │ - reference_count │ │ - geometry (嵌入) │ │ - auto_release │ │ - geometry_reference 1 │ │ - ... │ │ - geometry_reference 4095 │ └────────────────────────────────────────┘ 注意没有哈希表 - 纹理/材质系统使用名称查找 - 几何体系统使用ID直接索引几何体配置与创建系统初始化b8geometry_system_initialize(u64*memory_requirement,void*state,geometry_system_config config){if(config.max_geometry_count0){KFATAL(geometry_system_initialize - config.max_geometry_count must be 0.);returnfalse;}// 计算内存需求u64 struct_requirementsizeof(geometry_system_state);u64 array_requirementsizeof(geometry_reference)*config.max_geometry_count;*memory_requirementstruct_requirementarray_requirement;if(!state){returntrue;// 第一次调用返回内存需求}state_ptrstate;state_ptr-configconfig;// 设置数组指针void*array_blockstatestruct_requirement;state_ptr-registered_geometriesarray_block;// 初始化所有几何体为无效u32 countstate_ptr-config.max_geometry_count;for(u32 i0;icount;i){state_ptr-registered_geometries[i].geometry.idINVALID_ID;state_ptr-registered_geometries[i].geometry.internal_idINVALID_ID;state_ptr-registered_geometries[i].geometry.generationINVALID_ID;}// 创建默认几何体if(!create_default_geometry(state_ptr)){KFATAL(Failed to create default geometry.);returnfalse;}returntrue;}从配置获取几何体/** * brief 从配置创建并获取几何体 * param config 几何体配置 * param auto_release 引用计数归零时是否自动释放 * return 几何体指针失败返回NULL */geometry*geometry_system_acquire_from_config(geometry_config config,b8 auto_release){geometry*g0;// 查找空闲槽位for(u32 i0;istate_ptr-config.max_geometry_count;i){if(state_ptr-registered_geometries[i].geometry.idINVALID_ID){// 找到空闲槽位state_ptr-registered_geometries[i].auto_releaseauto_release;state_ptr-registered_geometries[i].reference_count1;gstate_ptr-registered_geometries[i].geometry;g-idi;// ID就是数组索引break;}}if(!g){KERROR(Unable to obtain free slot for geometry. Adjust configuration.);return0;}// 创建几何体if(!create_geometry(state_ptr,config,g)){KERROR(Failed to create geometry.);return0;}returng;}通过ID获取几何体/** * brief 通过ID获取现有几何体 * param id 几何体ID * return 几何体指针失败返回NULL */geometry*geometry_system_acquire_by_id(u32 id){if(id!INVALID_IDstate_ptr-registered_geometries[id].geometry.id!INVALID_ID){state_ptr-registered_geometries[id].reference_count;returnstate_ptr-registered_geometries[id].geometry;}KERROR(geometry_system_acquire_by_id cannot load invalid geometry id.);return0;}释放几何体/** * brief 释放几何体引用 * param geometry 要释放的几何体 */voidgeometry_system_release(geometry*geometry){if(geometrygeometry-id!INVALID_ID){geometry_reference*refstate_ptr-registered_geometries[geometry-id];u32 idgeometry-id;if(ref-geometry.idgeometry-id){if(ref-reference_count0){ref-reference_count--;}// 引用计数归零且auto_releasetrue时销毁if(ref-reference_count1ref-auto_release){destroy_geometry(state_ptr,ref-geometry);ref-reference_count0;ref-auto_releasefalse;}}else{KFATAL(Geometry id mismatch. Check registration logic.);}return;}KWARN(geometry_system_release cannot release invalid geometry id.);}几何体创建与销毁/** * brief 创建几何体 */b8create_geometry(geometry_system_state*state,geometry_config config,geometry*g){// 将几何体发送到渲染器上传到GPUif(!renderer_create_geometry(g,config.vertex_count,config.vertices,config.index_count,config.indices)){// 创建失败无效化条目state-registered_geometries[g-id].reference_count0;state-registered_geometries[g-id].auto_releasefalse;g-idINVALID_ID;g-generationINVALID_ID;g-internal_idINVALID_ID;returnfalse;}// 获取材质if(string_length(config.material_name)0){g-materialmaterial_system_acquire(config.material_name);if(!g-material){g-materialmaterial_system_get_default();}}returntrue;}/** * brief 销毁几何体 */voiddestroy_geometry(geometry_system_state*state,geometry*g){// 销毁渲染器资源renderer_destroy_geometry(g);g-internal_idINVALID_ID;g-generationINVALID_ID;g-idINVALID_ID;string_empty(g-name);// 释放材质引用if(g-materialstring_length(g-material-name)0){material_system_release(g-material-name);g-material0;}}默认几何体b8create_default_geometry(geometry_system_state*state){vertex_3d verts[4];kzero_memory(verts,sizeof(vertex_3d)*4);constf32 f10.0f;// 创建一个四边形// 布局// 0────3// │ │// 2────1verts[0].position.x-0.5*f;verts[0].position.y-0.5*f;verts[0].texcoord.x0.0f;verts[0].texcoord.y0.0f;verts[1].position.x0.5*f;verts[1].position.y0.5*f;verts[1].texcoord.x1.0f;verts[1].texcoord.y1.0f;verts[2].position.x-0.5*f;verts[2].position.y0.5*f;verts[2].texcoord.x0.0f;verts[2].texcoord.y1.0f;verts[3].position.x0.5*f;verts[3].position.y-0.5*f;verts[3].texcoord.x1.0f;verts[3].texcoord.y0.0f;u32 indices[6]{0,1,2,0,3,1};// 上传到GPUif(!renderer_create_geometry(state-default_geometry,4,verts,6,indices)){KFATAL(Failed to create default geometry.);returnfalse;}// 获取默认材质state-default_geometry.materialmaterial_system_get_default();returntrue;}程序化几何体生成几何体系统提供了程序化生成基础形状的功能。平面生成器/** * brief 生成平面几何体配置 * param width 平面宽度 * param height 平面高度 * param x_segment_count X轴分段数 * param y_segment_count Y轴分段数 * param tile_x X轴纹理平铺次数 * param tile_y Y轴纹理平铺次数 * param name 几何体名称 * param material_name 材质名称 * return 几何体配置 */geometry_configgeometry_system_generate_plane_config(f32 width,f32 height,u32 x_segment_count,u32 y_segment_count,f32 tile_x,f32 tile_y,constchar*name,constchar*material_name){// 参数验证if(width0){KWARN(Width must be nonzero. Defaulting to one.);width1.0f;}if(height0){KWARN(Height must be nonzero. Defaulting to one.);height1.0f;}if(x_segment_count1){KWARN(x_segment_count must be positive. Defaulting to one.);x_segment_count1;}if(y_segment_count1){KWARN(y_segment_count must be positive. Defaulting to one.);y_segment_count1;}if(tile_x0){KWARN(tile_x must be nonzero. Defaulting to one.);tile_x1.0f;}if(tile_y0){KWARN(tile_y must be nonzero. Defaulting to one.);tile_y1.0f;}geometry_config config;// 计算顶点和索引数量// 每个分段需要4个顶点和6个索引2个三角形config.vertex_countx_segment_count*y_segment_count*4;config.verticeskallocate(sizeof(vertex_3d)*config.vertex_count,MEMORY_TAG_ARRAY);config.index_countx_segment_count*y_segment_count*6;config.indiceskallocate(sizeof(u32)*config.index_count,MEMORY_TAG_ARRAY);// 计算分段尺寸f32 seg_widthwidth/x_segment_count;f32 seg_heightheight/y_segment_count;f32 half_widthwidth*0.5f;f32 half_heightheight*0.5f;// 生成每个分段for(u32 y0;yy_segment_count;y){for(u32 x0;xx_segment_count;x){// 计算分段边界f32 min_x(x*seg_width)-half_width;f32 min_y(y*seg_height)-half_height;f32 max_xmin_xseg_width;f32 max_ymin_yseg_height;// 计算UV坐标f32 min_uvx(x/(f32)x_segment_count)*tile_x;f32 min_uvy(y/(f32)y_segment_count)*tile_y;f32 max_uvx((x1)/(f32)x_segment_count)*tile_x;f32 max_uvy((y1)/(f32)y_segment_count)*tile_y;// 顶点偏移u32 v_offset((y*x_segment_count)x)*4;vertex_3d*v0config.vertices[v_offset0];vertex_3d*v1config.vertices[v_offset1];vertex_3d*v2config.vertices[v_offset2];vertex_3d*v3config.vertices[v_offset3];// 生成4个顶点逆时针// v0──v3// │ │// v2──v1v0-position.xmin_x;v0-position.ymin_y;v0-texcoord.xmin_uvx;v0-texcoord.ymin_uvy;v1-position.xmax_x;v1-position.ymax_y;v1-texcoord.xmax_uvx;v1-texcoord.ymax_uvy;v2-position.xmin_x;v2-position.ymax_y;v2-texcoord.xmin_uvx;v2-texcoord.ymax_uvy;v3-position.xmax_x;v3-position.ymin_y;v3-texcoord.xmax_uvx;v3-texcoord.ymin_uvy;// 生成6个索引2个三角形u32 i_offset((y*x_segment_count)x)*6;config.indices[i_offset0]v_offset0;// 三角形1config.indices[i_offset1]v_offset1;config.indices[i_offset2]v_offset2;config.indices[i_offset3]v_offset0;// 三角形2config.indices[i_offset4]v_offset3;config.indices[i_offset5]v_offset1;}}// 设置名称if(namestring_length(name)0){string_ncopy(config.name,name,GEOMETRY_NAME_MAX_LENGTH);}else{string_ncopy(config.name,DEFAULT_GEOMETRY_NAME,GEOMETRY_NAME_MAX_LENGTH);}// 设置材质名称if(material_namestring_length(material_name)0){string_ncopy(config.material_name,material_name,MATERIAL_NAME_MAX_LENGTH);}else{string_ncopy(config.material_name,DEFAULT_MATERIAL_NAME,MATERIAL_NAME_MAX_LENGTH);}returnconfig;}平面生成示意图1x1分段平面最简单情况 v0────v3 │ ╱ │ │╱ │ v2────v1 顶点v0, v1, v2, v3 索引0,1,2, 0,3,1 2x2分段平面 v0──v3──v6──v9 │ ╱ │ ╱ │ ╱ │ v2──v5──v8──v11 │ ╱ │ ╱ │ ╱ │ v1──v4──v7──v10 │ ╱ │ ╱ │ ╱ │ v0──v3──v6──v9 4个分段 16个顶点24个索引 纹理平铺tile_x2, tile_y2 UV坐标会超过[0,1]范围触发纹理重复 ┌───┬───┐ │ T │ T │ T 纹理 ├───┼───┤ │ T │ T │ └───┴───┘ 渲染器集成渲染器接口更新engine/src/renderer/renderer_frontend.h// 几何体操作b8renderer_create_geometry(geometry*geometry,u32 vertex_count,constvertex_3d*vertices,u32 index_count,constu32*indices);voidrenderer_destroy_geometry(geometry*geometry);Vulkan后端实现几何体在Vulkan中对应顶点和索引缓冲区的偏移engine/src/renderer/vulkan/vulkan_backend.cb8vulkan_renderer_create_geometry(geometry*geometry,u32 vertex_count,constvertex_3d*vertices,u32 index_count,constu32*indices){if(!vertex_count||!vertices){KERROR(vulkan_renderer_create_geometry requires vertex data.);returnfalse;}// 检查是否有索引数据b8 is_indexedindex_count0indices;// 为几何体分配内部ID缓冲区偏移geometry-internal_idcontext.geometry_vertex_offset;// 上传顶点数据u32 sizesizeof(vertex_3d)*vertex_count;if(!upload_data_range(context,context.device.graphics_command_pool,0,context.device.graphics_queue,context.object_vertex_buffer,context.geometry_vertex_offset,size,vertices)){KERROR(Failed to upload geometry vertices.);returnfalse;}context.geometry_vertex_offsetvertex_count;// 上传索引数据if(is_indexed){sizesizeof(u32)*index_count;if(!upload_data_range(context,context.device.graphics_command_pool,0,context.device.graphics_queue,context.object_index_buffer,context.geometry_index_offset,size,indices)){KERROR(Failed to upload geometry indices.);returnfalse;}context.geometry_index_offsetindex_count;}returntrue;}voidvulkan_renderer_destroy_geometry(geometry*geometry){if(geometrygeometry-internal_id!INVALID_ID){// TODO: 回收顶点/索引缓冲区空间// 当前实现不回收只增长geometry-internal_idINVALID_ID;}}注意当前实现使用单个大缓冲区顶点和索引数据追加式上传。这是一个简化实现生产环境应该支持缓冲区回收和碎片整理。渲染包系统为了高效渲染多个几何体我们引入**渲染包Render Packet**概念。渲染包结构engine/src/renderer/renderer_types.inl/** * brief 几何体渲染数据 */typedefstructgeometry_render_data{mat4 model;// 模型变换矩阵geometry*geometry;// 几何体指针}geometry_render_data;/** * brief 渲染包一帧中要渲染的所有数据 */typedefstructrender_packet{f32 delta_time;// 帧间隔时间u32 geometry_count;// 几何体数量geometry_render_data*geometries;// 几何体数组}render_packet;渲染包使用流程游戏逻辑渲染器Vulkan后端准备render_packet添加几何体到packetgeometries[i] {model, geometry}loop[每个可见对象]renderer_draw_frame(packet)begin_frame()update_global_state(proj, view)draw_geometry(geom_data)更新材质UBOvkCmdDrawIndexed()loop[每个几何体]end_frame()vkQueueSubmit()游戏逻辑渲染器Vulkan后端更新渲染循环engine/src/renderer/renderer_frontend.cb8renderer_draw_frame(render_packet*packet){if(renderer_begin_frame(packet-delta_time)){// 更新全局状态state_ptr-backend.update_global_state(state_ptr-projection,state_ptr-view,vec3_zero(),vec4_one(),0);// 绘制所有几何体for(u32 i0;ipacket-geometry_count;i){state_ptr-backend.draw_geometry(packet-geometries[i]);}// 结束帧b8 resultrenderer_end_frame(packet-delta_time);if(!result){KERROR(renderer_end_frame failed.);returnfalse;}}returntrue;}后端绘制函数voidvulkan_renderer_draw_geometry(geometry_render_data data){// 更新材质着色器vulkan_material_shader_set_model(context,context.material_shader,data.model);vulkan_material_shader_apply_material(context,context.material_shader,data.geometry-material);// 绑定顶点和索引缓冲区VkDeviceSize offsets[1]{data.geometry-internal_id*sizeof(vertex_3d)};vkCmdBindVertexBuffers(command_buffer,0,1,context.object_vertex_buffer.handle,offsets);if(data.geometry-index_count0){vkCmdBindIndexBuffer(command_buffer,context.object_index_buffer.handle,data.geometry-internal_id*sizeof(u32),VK_INDEX_TYPE_UINT32);vkCmdDrawIndexed(command_buffer,data.geometry-index_count,1,0,0,0);}else{vkCmdDraw(command_buffer,data.geometry-vertex_count,1,0,0);}}使用示例示例1创建简单几何体voidcreate_simple_quad(){// 生成平面配置geometry_config configgeometry_system_generate_plane_config(10.0f,10.0f,// 宽度、高度1,1,// 1x1分段1.0f,1.0f,// 纹理平铺1次my_quad,// 几何体名称wood// 材质名称);// 获取几何体geometry*quadgeometry_system_acquire_from_config(config,true);// 使用几何体...// 释放geometry_system_release(quad);// 清理配置中分配的内存kfree(config.vertices,sizeof(vertex_3d)*config.vertex_count,MEMORY_TAG_ARRAY);kfree(config.indices,sizeof(u32)*config.index_count,MEMORY_TAG_ARRAY);}示例2渲染多个几何体voidrender_scene(render_packet*packet){packet-geometry_count3;packet-geometrieskallocate(sizeof(geometry_render_data)*3,MEMORY_TAG_ARRAY);// 地板packet-geometries[0].geometryfloor_geometry;packet-geometries[0].modelmat4_translation(vec3(0,-1,0));// 墙壁1packet-geometries[1].geometrywall_geometry;packet-geometries[1].modelmat4_translation(vec3(-5,0,0));// 墙壁2packet-geometries[2].geometrywall_geometry;packet-geometries[2].modelmat4_translation(vec3(5,0,0));renderer_draw_frame(packet);kfree(packet-geometries,sizeof(geometry_render_data)*3,MEMORY_TAG_ARRAY);}示例3程序化生成地形voidcreate_terrain(){// 生成大平面作为地形geometry_config configgeometry_system_generate_plane_config(100.0f,100.0f,// 100x100单位10,10,// 10x10分段100个四边形10.0f,10.0f,// 纹理平铺10次terrain,grass);geometry*terraingeometry_system_acquire_from_config(config,false);// 常驻不释放// 清理kfree(config.vertices,sizeof(vertex_3d)*config.vertex_count,MEMORY_TAG_ARRAY);kfree(config.indices,sizeof(u32)*config.index_count,MEMORY_TAG_ARRAY);}示例4共享几何体// 创建一个立方体几何体geometry*cube_geomcreate_cube_geometry();// 多个对象共享同一几何体但使用不同变换voidrender_cubes(render_packet*packet){packet-geometry_count10;packet-geometrieskallocate(sizeof(geometry_render_data)*10,MEMORY_TAG_ARRAY);for(u32 i0;i10;i){packet-geometries[i].geometrycube_geom;// 共享几何体packet-geometries[i].modelmat4_translation(vec3(i*2,0,0));// 不同位置}renderer_draw_frame(packet);}❓ 常见问题❓ 几何体和材质是如何关联的几何体结构中有一个material*指针typedefstructgeometry{// ...material*material;}geometry;在创建几何体时如果config中指定了材质名称系统会自动获取材质if(string_length(config.material_name)0){g-materialmaterial_system_acquire(config.material_name);}渲染时从几何体获取材质voiddraw_geometry(geometry_render_data data){material*matdata.geometry-material;// 使用材质的颜色和纹理...}❓ 为什么几何体系统没有哈希表设计差异纹理/材质系统通过名称查找“wood”, metal等需要哈希表name → handle → resource几何体系统通过ID直接索引数组访问registered_geometries[id]原因几何体通常不需要名称查找几何体经常动态创建程序化生成ID直接对应数组索引更高效如果需要名称查找可以自己维护一个映射hashtable geometry_name_to_id;u32 idhashtable_get(geometry_name_to_id,my_quad);geometry*ggeometry_system_acquire_by_id(id);❓ generate_plane_config为什么分配内存因为顶点和索引数组的大小是动态的config.vertex_countx_segment_count*y_segment_count*4;config.verticeskallocate(sizeof(vertex_3d)*config.vertex_count,...);调用者负责释放geometry_config configgeometry_system_generate_plane_config(...);geometry*ggeometry_system_acquire_from_config(config,true);// 几何体已上传到GPU可以释放CPU内存kfree(config.vertices,...);kfree(config.indices,...);为什么不在系统内部释放调用者可能需要修改配置调用者可能复用配置创建多个几何体遵循谁分配谁释放原则❓ internal_id是什么internal_id是几何体在GPU缓冲区中的偏移// 创建时geometry-internal_idcontext.geometry_vertex_offset;// 如0, 4, 8, ...// 绘制时VkDeviceSize offsetgeometry-internal_id*sizeof(vertex_3d);vkCmdBindVertexBuffers(...,offset);示例顶点缓冲区 ┌──────────┬──────────┬──────────┐ │ Quad (4) │ Cube (8) │Plane (16)│ ├──────────┼──────────┼──────────┤ │ Offset │ Offset │ Offset │ │ 0 │ 4 │ 12 │ └──────────┴──────────┴──────────┘ ↑ ↑ ↑ internal_id internal_id internal_id❓ 如何支持多个LOD级别LODLevel of Detail可以通过创建多个几何体实现typedefstructmesh{geometry*lod0;// 高精度geometry*lod1;// 中精度geometry*lod2;// 低精度}mesh;geometry*select_lod(mesh*m,f32 distance){if(distance10.0f)returnm-lod0;if(distance50.0f)returnm-lod1;returnm-lod2;}// 渲染时geometry*geomselect_lod(my_mesh,camera_distance);render_data.geometrygeom; 练习与挑战练习1实现立方体生成器创建一个函数生成立方体几何体geometry_configgeometry_system_generate_cube_config(f32 size,constchar*name,constchar*material_name);查看提示立方体有6个面每个面是2个三角形4顶点6索引// 总共24个顶点36个索引config.vertex_count24;config.index_count36;// 前面vertices[0-3]...indices[0-5]{0,1,2,0,2,3};// 后面vertices[4-7]...indices[6-11]{4,5,6,4,6,7};// ... 其他4个面练习2顶点去重generate_plane_config生成了重复顶点。实现一个函数去重voiddeduplicate_vertices(geometry_config*config);查看提示遍历所有顶点查找重复的顶点position和texcoord都相同建立旧索引到新索引的映射重新映射索引数组创建新的顶点数组for(u32 i0;iold_vertex_count;i){b8 foundfalse;for(u32 j0;jnew_vertex_count;j){if(vertices_equal(old_vertices[i],new_vertices[j])){index_map[i]j;foundtrue;break;}}if(!found){new_vertices[new_vertex_count]old_vertices[i];index_map[i]new_vertex_count;}}// 重新映射索引for(u32 i0;iindex_count;i){indices[i]index_map[indices[i]];}练习3从OBJ文件加载几何体实现一个简单的OBJ加载器b8load_obj_file(constchar*path,geometry_config*out_config);查看提示OBJ格式示例v 0.0 0.0 0.0 # 顶点位置 vt 0.0 0.0 # 纹理坐标 f 1/1 2/2 3/3 # 面索引从1开始解析步骤逐行读取文件识别v,vt,f开头的行提取数值并存储构建geometry_config 下一步在本教程中我们实现了完整的几何体系统✅ 几何体数据结构顶点索引材质✅ 几何体系统引用计数ID索引✅ 程序化生成平面生成器✅ 渲染包系统批量提交✅ 与材质系统集成几何体系统是渲染管线的最后一块拼图。现在我们有了纹理系统管理图像数据材质系统管理外观属性几何体系统管理形状数据下一步我们可以实现资源系统- 统一管理所有资源类型场景系统- 组织场景中的对象模型加载器- 从文件加载3D模型实例化渲染- 高效渲染大量相同几何体结语恭喜你完成了本教程几何体系统让我们可以高效管理和渲染3D形状。通过程序化生成、引用计数、渲染包等机制我们构建了一个灵活且高效的几何体管理系统。结合之前的纹理和材质系统Kohi引擎现在已经具备了渲染复杂3D场景的基础能力。关键要点回顾几何体 顶点 索引 材质ID索引比名称查找更适合几何体程序化生成可以创建基础形状渲染包支持批量提交几何体引用计数自动管理资源生命周期随着系统的成熟可以添加更多高级特性骨骼动画、变形目标、GPU实例化、LOD系统等。如果你有任何问题或建议欢迎在GitHub上提出issue。关注公众号获取更多引擎开发资讯觉得有帮助请作者喝杯咖啡 作者: 上手实验室 项目地址: https://github.com/travisvroman/kohi上一篇材质系统 | 下一篇资源系统
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

昆明市住房和城乡建设局网站上看的jquery网页设计作业

第一章:从零开始认识Open-AutoGLM与移动应用测试新范式随着人工智能技术的深入发展,自动化测试领域迎来了新的变革。Open-AutoGLM 作为一种基于大语言模型(LLM)驱动的开源自动化测试框架,正在重新定义移动应用测试的工…

张小明 2026/1/7 3:08:30 网站建设

广州网站建设需要多少费用网站群建设目标

TFS 敏捷项目管理:从规划到执行 在敏捷项目管理中,TFS(Team Foundation Server)提供了强大的功能来支持项目的各个阶段。下面我们将详细介绍如何利用 TFS 进行敏捷项目管理,包括冲刺规划、发布计划、时间和成本估算等方面。 1. TFS 冲刺规划的容量评估 TFS 的冲刺规划功…

张小明 2026/1/7 9:57:00 网站建设

手机网站静态模板公司网站代码模板下载

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 创建一个最简单的Flowable流程示例:员工报销流程。要求:1.员工填写报销单(金额、类别、票据) 2.直接主管审批 3.财务付款。只需要生成最基础的BPMN流程图和对…

张小明 2026/1/7 8:27:58 网站建设

参考文献网站开发做网站域名

Vivado环境下ego1开发板大作业调试实战指南:从“灯不亮”到波形可见 你有没有过这样的经历? RTL代码写得逻辑清晰,ModelSim仿真波形完美对齐,信心满满地生成比特流下载到 ego1开发板 上——结果LED不闪、VGA无输出、按键毫无反…

张小明 2026/1/9 1:33:52 网站建设

创办一个网站需要多少钱怎么提升网站的排名

文章目录一、2025:在技术浪潮中淬炼核心能力二、2026:技能升级的三维攻坚战(一)深度:构建AI增强型开发体系(二)广度:打通云网边端技术栈(三)温度:…

张小明 2026/1/7 21:18:07 网站建设

做中英文网站多少钱网站怎么申请百度小程序

第一章:Open-AutoGLM云手机方案概述Open-AutoGLM 是一种基于云端虚拟移动设备架构的自动化智能交互系统,旨在通过大语言模型驱动安卓环境中的复杂操作任务。该方案将自然语言理解能力与移动端UI自动化技术深度融合,实现无需人工干预的应用操控…

张小明 2026/1/9 12:34:48 网站建设