-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
225 changed files
with
10,926 additions
and
151 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
--- | ||
--- | ||
|
||
{{< list limit=10 cardView=true title="Technical Posts" where="Type" value="tech">}} | ||
{{< list limit=100 cardView=true title="Technical Posts" where="Type" value="tech">}} | ||
|
||
{{< list limit=10 cardView=true title="Art" where="Type" value="art">}} | ||
{{< list limit=100 cardView=true title="Art" where="Type" value="art">}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,70 +1,42 @@ | ||
--- | ||
title: Characters and Animation | ||
title: My First Character Models | ||
type: art | ||
layout: "simple" | ||
--- | ||
|
||
{{<video "showcase.webm">}} | ||
|
||
I have yet to spend a _ton_ of time character modeling. These characters are the | ||
best of what I've made so far. | ||
These are a few of the first things I ever made in Blender. It turns out | ||
characters are way harder than hard surface. | ||
|
||
## Legfish | ||
### Legfish | ||
|
||
![legfish wireframe](legfish-wire.png) | ||
|
||
The first character I made. Inspired by a figurine my wife made with some | ||
leftover clay. | ||
|
||
![skin workflow](skin.png) | ||
|
||
For this, I used a [Skin | ||
Literally the first completed model I ever made in Blender. For this, I used a [Skin | ||
Modifier](https://docs.blender.org/manual/en/latest/modeling/modifiers/generate/skin.html) | ||
and [Subdivision | ||
Surface](https://docs.blender.org/manual/en/latest/modeling/modifiers/generate/subdivision_surface.html) | ||
based workflow. Joey Carlino has some great | ||
[tutorials](https://www.youtube.com/watch?v=DAAwy_l4jw4&t=2s) for this on | ||
YouTube. | ||
|
||
The significant advantage is that we only work with a skeleton instead of actual | ||
geometry until the modifier is applied. This approach delays the need to think | ||
about topology, which was very helpful as this project was one of my first ever | ||
in Blender. The branch merging behavior confused me, so I avoided this workflow | ||
to have 100% control of the topology. In the future, I want to revisit this | ||
approach. Now, I am confident I can fix things by hand as needed. | ||
|
||
## Cat Knight | ||
|
||
{{<video "cat-run.webm">}} | ||
YouTube. A nice starting point, but a bit finnicky. | ||
|
||
My first run/walk cycle! I'm proud of it. At first, I was resigned to using | ||
[Mixamo](https://www.mixamo.com/#/) because animation is too hard. Their library | ||
wasn't compatible with my stylized characters' oversized heads. The animations | ||
were too "real" as well. The model is cartoony, and the motion should be too. | ||
### Cat Knight | ||
|
||
I read the first few chapters of [The Animator's Survival | ||
Kit](http://www.theanimatorssurvivalkit.com/) because winging it produced | ||
unsatisfying results. While my focus will never be animation, learning the basic | ||
concepts went a long way. | ||
Kit](http://www.theanimatorssurvivalkit.com/) because Mixamo animations look | ||
pretty bad on stylized characters, and winging it produced wasn't working | ||
either. I'm never going to be a professional animator, but it's nice to be able | ||
to throw things together for my own use. So this is my first run cycle. | ||
|
||
![cat wireframe](cat-wire.png) | ||
|
||
I box-modeled this mesh instead of generating it with the skin modifier. To make | ||
things smoother, I used Catmull-Clark Subdivision and then used the | ||
[Un-Subdivide](https://docs.blender.org/manual/en/latest/modeling/meshes/editing/edge/unsubdivide.html) | ||
operator to keep the amount of geometry manageable while still getting a bit | ||
more smoothness/roundness in the mesh. I got to try out some topology tricks at | ||
the knees and elbows to help them deform properly. | ||
|
||
I just copied the head and cut out some parts to make the helmet. Same with the | ||
boots. I lifted the armor from the [Synty Fantasy | ||
Hero](https://syntystore.com/products/polygon-modular-fantasy-hero-characters) | ||
asset pack and played with the scale until it fit the character. I don't plan to | ||
keep it long-term , but it looks good enough for now. | ||
|
||
## Gobgob | ||
|
||
![gobgob](gobgob.png) | ||
### Gobgob | ||
|
||
Because I already had a stylized biped base rigged, I reused that, modeled a new | ||
head, and stitched that on. After extruding the ears, I learned a bit about | ||
rerouting edge/face flow. I like him a lot. | ||
|
||
{{< gallery >}} | ||
<img src="legfish-wire.png" class="grid-w50"> | ||
<img src="skin.png" class="grid-w50"> | ||
<img src="cat-wire.png" class="grid-w50"> | ||
<video src="cat-run.webm" class="grid-w50" autoplay muted loop></video> | ||
<img src="gobgob.png" class="grid-w50"> | ||
{{< /gallery >}} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
--- | ||
title: Kopitiam | ||
type: art | ||
showTableOfContents: false | ||
layout: "simple" | ||
--- | ||
|
||
{{< gallery >}} | ||
|
||
<img src="kopitiam_ext.png" class="rounded-2xl grid-w100" /> | ||
<img src="kopitiam_int.png" class="rounded-2xl grid-w100" /> | ||
|
||
{{< /gallery >}} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
--- | ||
title: Non-Destructive Terrain Editor | ||
type: tech | ||
--- | ||
|
||
I am not a good artist. One of the reason 3D is a bit more | ||
attractive to me is that I can usually build something rather | ||
than draw it or sculpt it. Digital art gives you an "undo" | ||
button, but being able to undo or redo things out of order makes | ||
it even easier to experiment. | ||
|
||
Most of the terrain tools out there have a destructive workflow. Using various | ||
brushes, you write directly to a heightmap. Including the concept of "layers" | ||
can help here, but I want something closer to modeling. | ||
|
||
What I've built is a way to take `Node3D`s tagged as `ShapeInstance`s and | ||
compose them onto the heightmap. Their `y` position is their height, and their | ||
`y` scale is the steepness of the shape. Other transform properties work normally (except for rotation on `x` and `z`). | ||
|
||
{{<video "terrain.webm">}} | ||
|
||
A couple of custom properties are `roundness` so that rectancular shapes don't | ||
have sharp corners, and a `shape` ID. The currently supported shapes are | ||
`recatangle`, `circle` and `ramp`. In the future, I'd like to get rid of `ramp` | ||
and instead support rotation on the horizontal axes for creating slopes. | ||
|
||
## SDFs | ||
|
||
Signed distance functions are an easy way to describe shapes using math. This | ||
could be in either 2D or 3D. [Inigo | ||
Quilez](https://iquilezles.org/articles/distfunctions/) has a nice library of | ||
functions for different shapes on his website. They have all sorts of uses in | ||
graphics; you can [render them directly](https://www.youtube.com/watch?v=BNZtUB7yhX4) | ||
with a ray marcherwith them direclty, they can be used in [global | ||
illumination](https://docs.godotengine.org/en/stable/tutorials/3d/global_illumination/using_sdfgi.html), | ||
and they are probably in many other ways. | ||
|
||
The SDFs of each shape are composed onto a single heightmap in a compute shader that looks roughly like this: | ||
|
||
```glsl | ||
layout(set = 0, binding = 0, std430) buffer ParamsBuffer { | ||
int n_shapes; | ||
int resolution; | ||
float world_size; | ||
vec2 world_offset; | ||
} | ||
params; | ||
layout(set = 0, binding = 2, std430) buffer ShapesBuffer { | ||
ShapeData data[MAX_SHAPES]; | ||
} shapes; | ||
layout(local_size_x = 32, local_size_y = 32, local_size_z = 1) in; | ||
void main() { | ||
vec2 uv = gl_GlobalInvocationID.xy; | ||
float height = -999999999.0; | ||
for (uint i = 0; i < params.n_shapes; i++) { | ||
ShapeData shape = shapes.data[i]; | ||
shape.position = world_to_shader(shape.position); | ||
shape.size *= shader_scale(); | ||
shape.steepness *= shader_scale(); | ||
float shapeHeight = heightmapFromDistance(shape, uv, sdf(shape, uv)); | ||
if (shapeHeight >= height) { | ||
height = shapeHeight; | ||
maxInfluence = int(i); | ||
} | ||
} | ||
int heightIdx = toIndex(uv); | ||
heightmap.data[heightIdx] = max(height, 0.0) / MAX_HEIGHT; | ||
} | ||
``` | ||
|
||
## Clipmap | ||
|
||
One difficult issue with large terrains is stitching the borders of chunks. | ||
Instead of dealing with that, we can use a wandering | ||
[clipmap](https://developer.nvidia.com/gpugems/gpugems2/part-i-geometric-complexity/chapter-2-terrain-rendering-using-gpu-based-geometry). | ||
A massive plane that has more subdivisions towards the center, and fewer on the | ||
edges gives us some basic LOD. As the player moves through the world, we | ||
peridically recenter the clipmap at their position so the stuff they can see | ||
closely has higher detail. | ||
|
||
{{<video "clipmap.webm">}} | ||
|
||
This technique works _especially_ well with the way we generate the heightmap. | ||
We don't even need to create chunks of the heightmap, or be concerned with | ||
artifacts due to sampling along the borders of two chunks. Instead, we can just | ||
center the heightmap's world space offset along with the clipmap, and only | ||
include the `Node3D` shapes that would be visible at this offset. To avoid | ||
regenerating the heightmap everytime we move the clipmap, we can generate the | ||
heightmap to be 2 times as big in world space. When we move outside some | ||
margin, the heightmap gets recentered. | ||
|
||
|
||
## Cursor Selection | ||
|
||
In the editor, a `Node3D` with no collisions is a bit annoying to select in the | ||
tree rather than visually. Writing the shape index that is actually influencing the | ||
heightmap at some point lets us give the heighmap its own collider, and based on the `xz` | ||
coordinate, we can sample that "influence map" to select the right shape. | ||
|
||
![influence map](influence_map.png) | ||
|
||
|
||
## Splat Mapping | ||
|
||
It would be pretty boring to only have the grass, cliff and beach textures | ||
based on normals and height. Paths, grass, plazas and other interesting details | ||
should be available. | ||
|
||
{{<video "splatmap.webm">}} | ||
|
||
With a few modifications, we can use the very same code for terrain generation | ||
for splatmap generation as well. Using these primitive shapes is pretty | ||
unwieldy , so in the future I'd like to be able to use the `Path3D` node to | ||
create paths and roads on the splatmap, as well as a free form drawing brush. | ||
Maybe noise texture overlays as well with masking. |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Oops, something went wrong.