[{"data":1,"prerenderedAt":274},["ShallowReactive",2],{"i-lucide:sun-moon":3,"i-simple-icons:github":8,"i-simple-icons:linkedin":10,"i-lucide:mail":13,"i-lucide:arrow-up-right":15,"post-\u002Fwriting\u002Fsynapse-60fps-engine-render":17,"i-lucide:arrow-left":270,"i-lucide:lightbulb":272},{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":7},0,24,false,"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 2v2m2.837 12.385a6 6 0 1 1-7.223-7.222c.624-.147.97.66.715 1.248a4 4 0 0 0 5.26 5.259c.589-.255 1.396.09 1.248.715M16 12a4 4 0 0 0-4-4m7-3l-1.256 1.256M20 12h2\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":9},"\u003Cpath fill=\"currentColor\" d=\"M12 .297c-6.63 0-12 5.373-12 12c0 5.303 3.438 9.8 8.205 11.385c.6.113.82-.258.82-.577c0-.285-.01-1.04-.015-2.04c-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729c1.205.084 1.838 1.236 1.838 1.236c1.07 1.835 2.809 1.305 3.495.998c.108-.776.417-1.305.76-1.605c-2.665-.3-5.466-1.332-5.466-5.93c0-1.31.465-2.38 1.235-3.22c-.135-.303-.54-1.523.105-3.176c0 0 1.005-.322 3.3 1.23c.96-.267 1.98-.399 3-.405c1.02.006 2.04.138 3 .405c2.28-1.552 3.285-1.23 3.285-1.23c.645 1.653.24 2.873.12 3.176c.765.84 1.23 1.91 1.23 3.22c0 4.61-2.805 5.625-5.475 5.92c.42.36.81 1.096.81 2.22c0 1.606-.015 2.896-.015 3.286c0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":11,"hidden":12},"\u003Cpath fill=\"currentColor\" d=\"M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037c-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85c3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.06 2.06 0 0 1-2.063-2.065a2.064 2.064 0 1 1 2.063 2.065m1.782 13.019H3.555V9h3.564zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0z\"\u002F>",true,{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":14},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"m22 7l-8.991 5.727a2 2 0 0 1-2.009 0L2 7\"\u002F>\u003Crect width=\"20\" height=\"16\" x=\"2\" y=\"4\" rx=\"2\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":16},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M7 7h10v10M7 17L17 7\"\u002F>",{"id":18,"title":19,"body":20,"canonical":252,"date":253,"description":254,"draft":6,"extension":255,"featured":6,"kind":256,"lang":257,"meta":258,"navigation":12,"path":259,"readingTime":260,"seo":261,"stem":262,"summary":263,"tags":264,"__hash__":269},"writing\u002Fwriting\u002Fsynapse-60fps-engine-render.md","60 FPS trong một khe synapse: vì sao vật lý và hình vẽ phải sống tách nhau",{"type":21,"value":22,"toc":240},"minimark",[23,35,40,43,56,70,74,81,88,100,104,107,110,137,144,152,156,163,166,173,177,184,199,202,207,211,217,220,227,231,237],[24,25,26,27,34],"p",{},"Đây là ghi chú kỹ thuật của ",[28,29,33],"a",{"href":30,"rel":31},"https:\u002F\u002Fgithub.com\u002Faniadev\u002Fbio-synapse-visual",[32],"nofollow","bio-synapse-visual"," - một công cụ ảo hoá động học synapse ở cấp phân tử, chạy thẳng trong trình duyệt. Kể lại bằng ví dụ đời thường, không cần biết code vẫn theo được.",[36,37,39],"h2",{"id":38},"bài-toán-vẽ-một-nhà-máy-hoá-sinh-thu-nhỏ-60-lần-mỗi-giây","Bài toán: vẽ một \"nhà máy hoá sinh\" thu nhỏ, 60 lần mỗi giây",[24,41,42],{},"Một khe synapse rộng chừng 10-40 nanomet. Trong khoảng không tí hon đó, mỗi khi tế bào thần kinh \"bắn\" một xung, hàng loạt việc xảy ra gần như cùng lúc: kênh calci mở, ion Ca²⁺ ùa vào, các bọc chứa chất dẫn truyền vỡ ra, hàng ngàn phân tử lao đi hỗn loạn qua khe, va vào thụ thể bên kia.",[24,44,45,46,50,51,55],{},"Muốn cho người xem ",[47,48,49],"em",{},"thấy"," cảnh đó - chứ không phải đọc một phương trình - thì phải vẽ lại toàn bộ, ",[52,53,54],"strong",{},"60 lần mỗi giây",". Chậm hơn, mắt người bắt được độ giật, và ảo giác \"đang nhìn qua kính hiển vi\" tan biến ngay.",[57,58,59],"blockquote",{},[24,60,61,62,65,66,69],{},"Vấn đề không phải vẽ ",[47,63,64],{},"đẹp",". Vấn đề là vẽ ",[47,67,68],{},"kịp",".",[36,71,73],{"id":72},"sai-lầm-đầu-tiên-để-khung-hình-tự-nghĩ","Sai lầm đầu tiên: để khung hình tự nghĩ",[24,75,76,77,80],{},"Vue - công cụ dựng giao diện của dự án - có một thói quen rất tốt trong đời thường mà lại rất tệ ở đây: nó ",[52,78,79],{},"theo dõi mọi thứ",". Bạn đổi một con số, nó tự dò xem chỗ nào trên màn hình liên quan rồi vẽ lại. Tiện vô cùng cho một cái form đăng ký.",[24,82,83,84,87],{},"Nhưng thử tưởng tượng bạn thuê một trợ lý cực kỳ chu đáo, và cứ mỗi khi ",[47,85,86],{},"một"," trong số hàng ngàn hạt ion nhích một chút, anh ta lại chạy đi kiểm tra lại toàn bộ căn phòng xem có gì cần đổi không. Nhân cảnh đó với hàng ngàn hạt, sáu mươi lần một giây. Trợ lý kiệt sức. Khung hình rớt.",[24,89,90,91,94,95,99],{},"Cách sửa là bảo Vue: ",[47,92,93],{},"\"Chỗ này đừng theo dõi. Cứ để tôi lo.\""," Trong dự án, đám dữ liệu mô phỏng được cất trong một ngăn \"miễn theo dõi\" (",[96,97,98],"code",{},"shallowRef",") - Vue biết có nó, nhưng không rình từng hạt. Việc rình-và-vẽ giao cho một tay chuyên nghiệp hơn.",[36,101,103],{"id":102},"lằn-ranh-cứu-cả-dự-án-engine-tính-render-vẽ","Lằn ranh cứu cả dự án: engine tính, render vẽ",[24,105,106],{},"Đây là quyết định gốc, và mọi thứ khác mọc ra từ nó.",[24,108,109],{},"Hình dung hai phòng ban tách bạch:",[111,112,113,124],"ul",{},[114,115,116,119,120,123],"li",{},[52,117,118],{},"Phòng Vật lý (engine)."," Nơi duy nhất được phép ",[47,121,122],{},"tính",". Ở đây có luật sinh học, có trạng thái từng hạt, có bộ sinh số ngẫu nhiên. Nó không quan tâm màu gì, to nhỏ ra sao. Nhiệm vụ: giữ một bảng số luôn đúng với hiện thực sinh lý.",[114,125,126,119,129,132,133,136],{},[52,127,128],{},"Phòng Hoạ (render).",[47,130,131],{},"vẽ",". Nó đọc bảng số từ phòng Vật lý rồi dựng thành hình bằng WebGL - thứ nói chuyện thẳng với card đồ hoạ. Nó ",[52,134,135],{},"không được"," sửa một con số nào của mô phỏng. Không được \"làm tròn cho đẹp\", không được \"nhích hạt cho cân\".",[24,138,139,140,143],{},"Vì sao lằn ranh này quý đến vậy? Vì mỗi phòng giờ chỉ có một việc, và có thể tối ưu điên cuồng cho đúng một việc đó. Phòng Hoạ đẩy hàng ngàn hạt xuống card đồ hoạ trong một lượt - thứ nó sinh ra để làm. Phòng Vật lý thì đủ ",[47,141,142],{},"sạch"," để đem ra kiểm tra như một bài toán thuần tuý.",[145,146,149],"callout",{"title":147,"type":148},"Nguyên tắc dẫn đường","insight",[24,150,151],{},"\"Cái đẹp phục tùng sinh lý.\" Nghe như khẩu hiệu, nhưng thật ra đây là một ràng buộc kiến trúc: khi hình vẽ và con số cãi nhau, con số luôn thắng. Phòng Hoạ không có quyền phủ quyết.",[36,153,155],{"id":154},"trật-tự-nhân-quả-không-được-phép-đảo","Trật tự nhân-quả không được phép đảo",[24,157,158,159,162],{},"Bên trong phòng Vật lý có một nhịp tim: vòng lặp trung tâm, mỗi bước tíc-tắc chạy đúng một chuỗi việc - và ",[52,160,161],{},"thứ tự là bất khả xâm phạm",", vì sinh học vốn vậy:",[24,164,165],{},"Xung lan tới cúc tận cùng → kênh calci mở, Ca²⁺ tràn vào → bọc chất dẫn truyền vỡ ra → các phân tử khuếch tán qua khe → gắn vào thụ thể bên kia → màng sau cộng dồn dòng điện, tính ra điện thế.",[24,167,168,169,172],{},"Đảo bất kỳ hai bước nào là ra một sinh học sai. Nên vòng lặp được viết cứng theo đúng dòng chảy này - không phải vì code gọn hơn, mà vì đó là ",[47,170,171],{},"luật của thế giới đang mô phỏng",". Giữ đúng trật tự nhân-quả chính là thứ tách một mô phỏng khỏi một màn trình diễn hoạt hình đẹp mắt nhưng vô nghĩa.",[36,174,176],{"id":175},"chạy-lại-y-hệt-mẻ-ngẫu-nhiên-nhưng-lặp-lại-được","Chạy lại y hệt: mẻ ngẫu nhiên nhưng lặp lại được",[24,178,179,180,183],{},"Có một nghịch lý dễ chịu ở đây. Sinh học thật thì đầy ngẫu nhiên - cùng một xung, lần này bọc vỡ, lần sau lại \"trượt\". Muốn trung thực thì phải giữ cái ngẫu nhiên đó. Nhưng làm nghiên cứu thì lại cần ",[52,181,182],{},"chạy lại y hệt"," để so sánh.",[24,185,186,187,190,191,194,195,198],{},"Lời giải: sự ngẫu nhiên ở đây là ",[47,188,189],{},"ngẫu nhiên có hạt giống",". Toàn bộ số ngẫu nhiên sinh ra từ một cỗ máy nhỏ (",[96,192,193],{},"mulberry32","), khởi động bằng một con \"hạt giống\" (seed). Cùng một hạt giống, cùng một bộ tham số → tái hiện ",[52,196,197],{},"100%"," mọi sự kiện, đến từng hạt vỡ đúng thời điểm cũ.",[24,200,201],{},"Thế là được cả hai: trông thì hỗn loạn như thật, nhưng bấm lại nút là cuộn phim chạy y nguyên. Xuất luôn được cả cấu hình lẫn hạt giống ra một file JSON - gửi cho người khác, họ mở lên thấy đúng cảnh bạn thấy.",[57,203,204],{},[24,205,206],{},"Ngẫu nhiên để trung thực. Có hạt giống để kiểm chứng. Không phải chọn một.",[36,208,210],{"id":209},"phần-thưởng-bất-ngờ-phòng-vật-lý-tự-kiểm-tra-được","Phần thưởng bất ngờ: phòng Vật lý tự kiểm tra được",[24,212,213,214,69],{},"Vì phòng Vật lý không dính gì tới hình vẽ, nó trở thành một hộp số thuần tuý: đưa vào tham số, nhận ra con số. Mà con số thì ",[52,215,216],{},"kiểm tra được bằng máy",[24,218,219],{},"Luật giải phóng có đúng đường cong không? Điện thế màng có vọt lên rồi reset đúng ngưỡng không? Mỗi câu hỏi thành một bài kiểm tra tự động (Vitest) chạy trong tích tắc - không cần mở trình duyệt, không cần căng mắt nhìn hạt. Nếu ai đó lỡ tay làm sai một luật sinh lý, bài kiểm tra đỏ ngay, trước khi cái sai kịp lên màn hình.",[24,221,222,223,226],{},"Lợi thế này chỉ có được ",[47,224,225],{},"nhờ"," lằn ranh ở trên. Trộn vật lý vào hình vẽ thì không kiểm tra kiểu này nổi - vì để hỏi \"con số đúng chưa\" bạn buộc phải dựng cả cảnh WebGL lên.",[36,228,230],{"id":229},"chốt-lại","Chốt lại",[24,232,233,234],{},"Cả kiến trúc gói gọn trong một câu: ",[52,235,236],{},"một nơi được tính, một nơi được vẽ, và hai bên không chạm vào việc của nhau.",[24,238,239],{},"Nghe đơn giản đến mức dễ xem thường. Nhưng chính lằn ranh mảnh đó là thứ giữ được 60 FPS, giữ được sinh học đúng, và mở ra chuyện tái hiện-y-hệt lẫn kiểm-tra-tự-động - ba thứ tưởng chừng phải đánh đổi lẫn nhau. Không phải nhờ một mẹo thần kỳ nào, mà nhờ chịu khó vẽ ra ranh giới ngay từ dòng code đầu tiên, rồi tôn trọng nó tới dòng cuối.",{"title":241,"searchDepth":242,"depth":242,"links":243},"",3,[244,246,247,248,249,250,251],{"id":38,"depth":245,"text":39},2,{"id":72,"depth":245,"text":73},{"id":102,"depth":245,"text":103},{"id":154,"depth":245,"text":155},{"id":175,"depth":245,"text":176},{"id":209,"depth":245,"text":210},{"id":229,"depth":245,"text":230},null,"2026-06-12","Đây là ghi chú kỹ thuật của bio-synapse-visual - một công cụ ảo hoá động học synapse ở cấp phân tử, chạy thẳng trong trình duyệt. Kể lại bằng ví dụ đời thường, không cần biết code vẫn theo được.","md","engineering","vi",{},"\u002Fwriting\u002Fsynapse-60fps-engine-render",7,{"title":19,"description":254},"writing\u002Fsynapse-60fps-engine-render","Chuyện dựng bio-synapse-visual: một \"kính hiển vi tính toán\" chạy trong trình duyệt, mô phỏng hàng ngàn hạt ion khuếch tán ngẫu nhiên mà không giật hình. Bí quyết không nằm ở card đồ hoạ - mà ở một lằn ranh: engine tính, render vẽ, hai bên không được chạm vào việc của nhau.",[265,266,267,268],"simulation","webgl","vue","kiến-trúc","_DSm_6Yf1mfz0dwlqxePO4myhZUuAn96-gUSUzwMeNk",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":271},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"m12 19l-7-7l7-7m7 7H5\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":273},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M15 14c.2-1 .7-1.7 1.5-2.5c1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5c.7.7 1.3 1.5 1.5 2.5m0 4h6m-5 4h4\"\u002F>",1790138980677]