lukas-tonne
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    # Advanced Volume Support in Geometry Nodes Make volumes in geometry nodes more useful and flexible. - [ ] Incorporate feedback from Jacques, Hans, Dalai - [ ] Separate out examples and steps that require work beyond the MVP: Fluid and hair sim need a few specialized nodes. - [ ] Better illustration for "individual grids in volumes" vs. Volume geometry component. left->right train of thought, "there are multiple grids in the volume, but only one volume output" - [ ] Change node design for mesh/point conversion to include volume input+output (discussed in chat) - [ ] Describe meaning of position node in volume context - [ ] Picture comparing different mesh/point conversion resolution modes (Size, Amount, Copy) - [ ] Design a new grid resolution option to facilitate shared transforms between grids. ## Motivation: Use Cases for Volumes ![](https://hackmd.io/_uploads/SJ1Q0q-ea.png) (Generated using [mermaid.live](https://mermaid.live/edit#pako:eNp1VNtq20AQ_ZVlIWBDSh76JkrBjklbqKmx3PRFL5PVSFqyt-yloIb8e0e2Yq-UZF-0mnN25sxl95kLWyMvuJam1uAqw2jdW5U0htPPsPZoavTStBfTsO7szFBq-4gzjvQzyy2kEKXI3G9Jg3rjvdzczQwiKRff8P5ARM9C8g2IWajSQZSgWBAQ4yyBUuqkCLZmJlglWX-Ilk9Jhq5n2yEouQ5TeAeeUlPIfhjCZ-crc3VFn2VVVXzX9WGoAW0Xo52xxWJlpD6eWi7PVsY2vQFN7EFVZh61hpux7Bmwly0lsba1HNqYAd9B-rO_CXKrbOxexWaSXpszUTTKZwdr1Ttu8lbNg3_z1uo5UmYNyvPzIGIaBuhspk_em7PMtTrOKFs5FyZST50QUf7F46BNAtxLHxMNyMEmP83j4GXb4sy4x4ErNbJzozIJ9_sscFEUCnybh9sl5zDiPM3Pm7xcpw4cwZ_WtKyTIVrfZ-aikMKaRQOsgU8P1j4uM3BnHdXGy5DN3hhp7WWk2WXuRGEu9KKzyrY9gxQ766kKpmfr9A8uB_cYELzoMk-_DMOmwWNFDYbw5cHffAVTswZhaFaYclcp2qFUggmPb1X9DpMD4xAdmdSwiKIz8im9wykj3S9sya9TYMz5bmeUlW_pHTOR0cvmcsI4tpeqoWFDBg4c-sy-Ra9B1vya63FX8OcBr3jsUGPFC9rW4B8rXpkX4lElbdkbwYvoE17z5GpSuZHQetC8aOjFwJf_1xSKUw)) Volumes have properties that make it a unique tool in the box: - Spatial lookups are fast, great for processing lots of data. - Finding neighboring cells is very cheap, allows fast filtering and convolution. - Store sparse volumes efficiently. - Improved accuracy for positions using cell coordinates. In short: Volumes can do many things faster than other geometry, and some things that are (almost) impossible otherwise. Some improvements to expect: - Faster simulations without loss of visual detail. - Describe semi-transparent media efficiently. - Costly SDF functions can be computed in real time. - Smoothing/blurring/diffusion is faster and resolution-independent. ### Examples - Construct mesh surface from a SDF volume - Create SDF grid from point cloud - Convert to mesh surface - Output - Remove density from a fog volume - Geometry input containing fog grid - _Named Attribute_ node for "density" grid - Vector math distance node using a utility object location and grid cell position - Map distance to some 0..1 range - Math node multiplying density with the distance factor - _Store Named Attribute_ using modified density and store as "new_density" ![](https://hackmd.io/_uploads/B10PmD2lp.png) - Combining and rendering SDF operations Make holes in cheese: - Cheese wheel mesh - Mesh to SDF Volume - Erode SDF, then distribute points in volume (so bubbles don't poke through the surface) - Points to SDF Volume - Difference of mesh SDF and points SDF - Volume to Mesh makes a cheese with holes Links: - SDF surface rendering in a shader. Shows boolean combination functions. https://www.shadertoy.com/view/lt3BW2 - Detailed tutorial with a 2D case. https://www.ronja-tutorials.com/post/034-2d-sdf-basics/#rectangle - Mesh-Mesh booleans using SDF. http://www.gradientspace.com/tutorials/2017/11/21/signed-distance-fields-tutorial - Basic FLIP fluids (with point cloud sampling) - Particle dynamics: add gravity to velocity attribute - Velocity grid from particles (new node?) - Divergence grid from velocity (new node) - Pressure solve outputs scalar pressure grid - New velocity from pressure gradient - Apply velocity by sampling at particle locations Links: - 10 Minute Physics: How to write a FLIP Water Simulator https://youtu.be/XmzBREkK8kY - Hair self-collision using volumes Links: - Anisotropic Elastoplasticity for Cloth, Knit and Hair Frictional Contact https://dl.acm.org/doi/pdf/10.1145/3072959.3073623 - Volumetric Methods for Simulation and Rendering of Hair https://graphics.pixar.com/library/Hair/paper.pdf ## Volumes in Blender 4.0 Geometry Nodes currently has only very basic volume support for conversions to and from other geometry. With the experimental "New Volume Nodes" enabled there are a few more nodes for sampling and SDF manipulation. Volumes are treated largely as "black boxes": - Converting meshes or point clouds to volumes - Generating a mesh surface from a density grid - Scattering points in a density grid - Sampling a grid at arbitrary points - Basic SDF operations (offset, filter) - Volume "primitives": sphere, cube with variable density ![](https://hackmd.io/_uploads/B1pZitbgT.png) Volumes can already store multiple distinct grids, e.g. when loading from `.vdb` files. These are not accessible individually, nodes have to use the "active" grid index and special names to find which grids to operate on. ![](https://hackmd.io/_uploads/rkD0JoWlT.png) Combining grids is not supported currently. This would be a frequent occurrence e.g. in SDF modeling. Without access to individual grids it's not obvious which grids should be combined. ![](https://hackmd.io/_uploads/Bks6A9-g6.png) Some interaction with grids is possible using sampling and conversion to other geometry, but it's not very efficient. Many useful features of grids can't be utilized this way, e.g. spatial lookups of neighboring points. <!-- Grid operators are mathematical tools that can generate useful spatial information, for example: - Gradient: the direction in which density increases. - Divergence: vector flow into or out of an area. - Laplacian: describes density in physics simulations. We can't generate these currently since there is no way to output a single grid. --> ## Improved Grid Data Access ### Attribute Support Volume geometry gets attribute support. Each attribute represents a named or anonymous grid in the volume. The `Voxel` domain represents grid cells, which are the main elements of grids. ![](https://hackmd.io/_uploads/BkM_J2blT.png) ## MVP Goal is to provide necessary features to unlock volume geometry access. Later tools and simulations can build on top of this initial stage. <!-- - Volume geometry gets attribute support. Each attribute represents a named or anonymous grid in the volume. - Field evaluation with grid inputs produces grid outputs, which can be stored or captured. - Multifunctions, like math or color mixing, work on voxel values. - Rules for combining grids with different topology (spatial extent and/or transform) - Reimplement volume nodes with individual grid outputs instead of a single Volume geometry. Users can apply math functions to voxel values directly (without converting to points and back or similar hacks). Basic SDF operations with grids are now possible by simply adding grid fields and modifying falloff functions. Some grid-based simulations can be implemented (point grids will allow more advanced simulation later). With node tools grids could be used in modeling or sculpting. --> ### Conversion Node Outputs Conversion from mesh and point geometry will output a **density** grid (fog volume) or **distance** grid (SDF volume) in addition to the Volume geometry. This is an anonymous attribute of the volume, rather than a named attribute as is currently the case. ![](https://hackmd.io/_uploads/rJRvGFKxp.png) ### Grid Info Node A new **Grid Info** node provides additional information about a grid: - **Scale**: Size of each voxel in object space. - **Origin**: Translation of the grid voxels relative to object origin. - **Staggered**: For vector grids only: The grid values are split by component and located on face centers (typically used for velocity grids). ### Domain Size The **Domain Size** node in _Voxel_ domain mode returns the number of _active voxels_ of the grid. ### Transform Geometry for Grids The **Transform** node for grids simply changes the voxel scale and origin. The actual grid data is local to grid cells, there is no position attribute that needs to be calculated. ### Resample Grid Change the voxel scale or origin and generate a new grid by interpolating the old grid values. This generally comes with a loss of precision and potential aliasing artifacts, same as when resampling images. [Higher-order sampling methods](https://www.openvdb.org/documentation/doxygen/Interpolation_8h.html) can be used to reduce some of these artifacts. ### Sample Volume **Sample Volume** already has a "Grid" input, but this is a hack: it expects an arbitrary named field and then uses the same name to find a volume grid internally. This will no longer be necessary, the input itself becomes a grid field that can be sampled directly. ### Sample Grid This is a variation of the _Sample Index_ node. The usual element index of points, faces, edges, etc. does not work well with grids, since voxel indices depend very much on grid topology. Instead a grid is typically indexed using _coordinates_ `(i,j,k)`. Unlike the _Sample Volume_ node The _Sample Volume_ node is one way of reading grid data, but its position input includes the grid transform. A new "Evaluate at Coordinate" node provides direct access based on integer coordinates, ignoring the grid scale. ![](https://hackmd.io/_uploads/BkTmEaZga.png) ### Field Evaluation Field evaluation with grid inputs produces grid outputs, which can be stored or captured. Multifunctions, like math or color mixing, work on voxel values. Each output voxel value is computed by evaluating inputs at the voxel location. > **Implementation Note:** When input grids in a field graph have different transforms the evaluator needs to resample the grids, which causes artificial smoothing and reduces performance. Using the same grid transform is preferable because node graphs can be evaluated per leaf buffer as simple multifunctions. ![](https://hackmd.io/_uploads/SkP6Ua-ga.png) ### Voxel Size and Grid Transforms Each volume grid has a _transform_ which determines the size of voxels. For example a grid with a scale of 0.25 has a voxel size of 0.25 units. A volume component has a **default transform**, which is the transform of the active grid. Nodes that construct a grid from a mesh, point cloud, cube or sphere all have one or both of the following options: - _Size_: Voxels have fixed size, amount of voxels computed to cover the extent of the geometry. - _Amount_: Fixed amount of voxels on the longest axis (or all 3 axes for the cube), voxel size is based on geometry bounds. A _Volume Info_ node will provide the transform of an existing volume so it can be copied by other nodes. Using consistent transforms between grids improves performance and avoid loss of precision due to interpolation. It should be the preferred option when creating new grids to reuse an existing transform. ### Grid Topology Behavior For conventional fields in geometry nodes the size of buffers is directly defined by the domain, with the possible use of selection as a filter. For grids the situation is more complicated: Each grid has, by design, its own extent and topology (which voxels are active). When combining multiple grids in a function, say an "Add" math node, the result will usually be a _union_ of the active grid cells. The input grids have a _background value_ that is used when a voxel is inactive. ![](https://hackmd.io/_uploads/SyD6fOYlT.png) Some special cases need to be considered: - > **Empty Input Case:** Some field inputs are not grids themselves but abstract functions, like the "Voxel Center" input. These fields do not have a concrete set of voxels. When all input fields are abstract the resulting grid would be empty. A fallback for this case could be to use the "active grid" topology, or provide a user-defined default grid. --------------------------------------------------------------------- ## Future Steps Not part of the MVP ### Spreadsheet Integration The spreadsheet shows grid attributes for debugging purposes. Each colume contains values in a grid. Each row contains attributes for the same voxel, identified by its grid coordinates `(i,j,k)`. Unlike existing geometry components the Volume attributes are grids, which can have different topology and voxel count. A voxel may be active in some grids but not others, so a spreadsheet row can have gaps when the voxel it represents is not active in the column for a grid. > **Implementation Note:** The index of a voxel depends on the overall voxel count, it should not be stored or used for sampling. ### Volume Viewer Nodes Viewport display for volumes is not very useful for viewer nodes at this point. The viewport can only display float value grids as a density-style fog volume. Viewport rendering of volume should take more grid types into account, as well as other settings such as the staggered grid class for vector grids. Additional techniques for visualizing useful grid information: - Wireframe cell display: useful for gauging voxel size and how it relates to other scene elements. - Slices: Clear picture of interior grid values. There is a feature on volume objects, but its very limited. Where to put a slice exactly requires user control. ### Point Grids OpenVDB has a specialized grid type for storing large point clouds efficiently and with better accuracy than the current Point Cloud geometry ([OpenVDB overview](https://www.openvdb.org/documentation/doxygen/points.html)). This `PointDataGrid` forms the basis of fluid simulations. - PointCloud gets an internal grid representation. - Can switch between both point cloud representations automatically, e.g. a simulation can convert an input point cloud to grid mode. - Point cloud attributes can read/write directly to the `PointDataGrid`. - New set of nodes to enable fluid simulations: - **Divergence** and **Gradient** operators - Pressure solver for incompressible fluids (**Poisson solver**) - Point **advection** with a velocity vector grid - Obstacle grids generated from meshes or other sources (including manual authoring) <!-- FEEDBACK THREAD JacquesLucke17:21 Lukas Tönne I'm looking at your volume nodes document right now. One thing I wonder is how is the transform of the new grid in the Store Named Attribute node determined? Lukas Tönne @LukasTonne17:23 my understanding is that we want all grids in a volume to share the same transform of course that just moves the question to: what is the transform when there isn't any grid in the volume yet ... Hans Goudey @HooglyBoogly17:24 The identity, no? Lukas Tönne @LukasTonne17:25 in my branch right now i have a domain_transform function for components Hans Goudey identity transform means each voxel has a size of 1 unit that's not usually what we want Hans Goudey @HooglyBoogly17:26 Ah right, of course. I think nodes that create volumes from scratch would have to specify the size and resolution combo The "Voxel Center" is just the position input node, right? JacquesLucke17:27 Ok, then my next question is, how do we deal with volumes with grids that are not aligned (as they can be when importing an vdb file afaik) Lukas Tönne @LukasTonne17:28 The "Voxel Center" is just the position input node, right? yeah it would be used pretty much the same way as position. But you said these grid functions shouldn't be treated as attributes, and the position is an AttributeInputField, so have a separate node might be better. not sure Hans Goudey @HooglyBoogly17:29 Field contexts can override specific field inputs, I'd imagine that happening here (like the volume cube field context does now) When combining multiple grids in a function, say an “Add” math node, the result will usually be a union of the active grid cells I'd imagine the result would just be the topology from the grid that defines the field context. For a union, an explicit node should be used probably JacquesLucke17:30 Regarding grid transforms, we also need some answer for what to do when using the join geometry node with multiple volumes with different transforms. Lukas Tönne @LukasTonne17:31 how do we deal with volumes with grids that are not aligned the evaluator can use a generic accessor or sampler for evaluating grids where the transform doesn't match. but it might be better to have explicit sampling nodes for that, which would be consistent with other geometry when combining different volumes I'd imagine the result would just be the topology from the grid that defines the field context. For a union, an explicit node should be used probably yeah it's probably going to need a "domain mask" like that, possibly the active grid or setting it in the nodes Hans Goudey @HooglyBoogly17:35 Not so different from the existing field evaluation mask already I guess, except that it has to handle a separate mask on the other grids too Lukas Tönne @LukasTonne17:37 yes existing field eval gets a array size from the domain (with a round trip converting to a default IndexMask and getting the "min array size" from that) all good points, i'll make sure to clarify things Hans Goudey @HooglyBoogly17:45 Mesh/Point to Volume outputs a grid field instead of a volume Seems like it needs to output both, since there needs to be a geometry that the field refers to. That lets you use further volume nodes on the volume like sampling another attribute or changing densities based on some field evaluation Lukas Tönne @LukasTonne17:47 true, these nodes generate their own grid transform, so they should go into a new volume JacquesLucke17:48 I wonder at which level nodes for inflation/deflation would work. Hans Goudey @HooglyBoogly17:48 I think topology-changing operations have to be geometry nodes (with a volume input and output, and some way to select which grid(s?!) to affect) Lukas Tönne @LukasTonne17:49 if i want to combine these output volumes with other volumes i'll then have to use a sampler (which can be optimized away if transforms match) for example using mesh-to-volume and then put that in a fluid sim as an obstacle I think topology-changing operations have to be geometry nodes It should work without a volume in/out as long as the transform remains the same JacquesLucke17:51 I think topology-changing operations have to be geometry nodes I'm not so sure about that anymore right now. Could also be part of field evaluation Hans Goudey @HooglyBoogly17:51 I don't think fields can "own" grids though JacquesLucke17:52 Fields can own whatever they want, but I'm not surer why that matters here. Lukas Tönne @LukasTonne17:53 such operations are sort of on the edge of what could be called a multifunction, but they filter over neighboring voxels JacquesLucke17:53 well, they are not multi-functions for sure Lukas Tönne @LukasTonne17:53 maybe akin to the accumulate field node? Hans Goudey @HooglyBoogly17:53 Hmm, I guess the distinction of "topology changing" might mean a bit less here? JacquesLucke17:54 maybe akin to the accumulate field node? right, or the blur node the field evaluation implementation still kinda assumes that it just does a multi-function evaluation, but that's only because we haven't refactored it in a long time and moved everything that's not a multi-function evaluation into field inputs. Lukas Tönne @LukasTonne17:57 if you add elements to an array it doesn't match the previous context any more, so it has to become a new GeometrySet. With grids it's possible to have different topologies in the same geometry. JacquesLucke17:58 Yeah, one could also argue that it's still all the same topology in coordinate space. Lukas Tönne @LukasTonne18:02 "same topology" in openvdb terms means that grids have the same active voxels. dilate/erode are changing topology (even if just a little bit by growing/shrinking the boundary). JacquesLucke18:03 Yeah I know, I was using a different definition of topology there. Lukas Tönne @LukasTonne18:04 yeah, just wanted to clarify, there is some overlap with existing blender terms -->

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully