UltraTex Render Views (second pass)
How pass two starts from pass one without the two fighting
- prep
- source_prep
- source_views
- bake_state
- init_views
- keep_mask
The 45° pass is the trick that fills in the sides, and this node is the hinge that makes it not look like a second grader painted over the first.
Here's the problem in one sentence: the four in-between views sit at angles pass one never saw, so if you generate them fresh the model invents slightly different colours and details - and you get visible bands in the final texture wherever the two passes meet.
The fix is to make pass two a refinement of pass one rather than a second opinion. And to do that, you need pass one's content expressed in pass two's cameras. That's all this node is.
What it does
It takes the rotated rig (prep, from UltraTex Rotate Rig), the original prep (source_prep), and pass one's six source_views. Internally it bakes those views into a texture on the shared UV layout, then renders that texture back out from the rotated cameras at resolution. What you get is six images that show pass one's answer as seen from the new angles - geometric re-projection, no diffusion involved, seconds of work.
Alongside it produces the keep mask, which is the more interesting half. The baker also returns a per-texel confidence, and the mask is built from it: regions pass one saw reasonably head-on get keep values near 1, and grazing regions fade out. That confidence is fed to the sampler as keep_mask, which pulls those tokens back toward the init content after every step (a RePaint-style constraint). So the second pass keeps what the first pass genuinely knew, and invents only where the first pass was guessing.
The two numbers
keep_above is the cosine threshold for "head-on enough to trust" - 0.75 by default, which works out to roughly 41° off-axis. Raise it and you trust less of pass one (more of the surface gets re-generated); set it to 1.01 and you keep nothing, which turns this into a plain denoise-and-refine with no protection at all. For reference, the default is chosen so that the four new views can actually do their job: pass one only covers about 44-60% of the surface inside 45°, and the whole point is to raise that number.
keep_feather (0.1) is the softness of the transition, in cosine units. This is the one that shows up in the final bake - too small and you get a hard seam ring where kept content meets generated content; too large and you're protecting regions the first pass had no business claiming.
Inputs and the alternative source
Besides prep, source_prep and source_views, there's bake_state - the UltraTex Bake Texture node's sixth output - which lets you skip source_views entirely and use the already-baked textures instead. That's useful if you baked, looked at the result, and decided you want more coverage: you can run the second pass off the bake you already made. texture picks which one, albedo or metallic_roughness, and appears only in that mode.
Outputs
init_views → UltraTex Sampler's init_views, keep_mask → its keep_mask, with denoise around 0.6. At 25 steps that means roughly 11 steps actually run, so pass two costs about 45% of what pass one did.
Errors you'll actually hit
- "prep must be UltraTex Rotate Rig applied to source_prep." You've crossed preps - a rotated rig derived from something other than the prep you're calling the source. It compares vertex counts and UVs, so it catches this even when the mesh is the same object.
- "init_views do not match this prep's camera rig." That's the sampler's check, and it fires when
init_viewscame from the wrong rig. Almost always because someone wired pass one'sviewsstraight into pass two. They're seen from the other rig; they need to come through here. - "bake_state comes from a different mesh / UV layout than prep." Your bake and your rotated rig disagree about UVs. Re-derive the rig from the prep the bake used.
- "the bake has no metallic-roughness texture." You asked for
texture = metallic_roughnesson a bake that only produced albedo. Run the MR sampler and bake first, or switch the dropdown.
Install
Manager → ComfyUI-UltraTex, or:
cd ComfyUI/custom_nodes
git clone https://github.com/visualbruno/ComfyUI-UltraTex
Requirements: trimesh, moderngl, xatlas, scipy. Triton if you want the sampler's sparse attention on the refinement pass, same as pass one.
Is it worth it
Yes, if your asset has an interesting object with real curvature - a figure, a boot, a prop with detail on the flanks. The measured coverage of head-on surface goes from 44% to 58% and 60% to 75% on the author's test meshes, and that's exactly where multi-view texturing normally falls apart. It's also roughly half again the wall time of a single pass, so on a 1024 lean run it's cheap, and on a 2048 bulky one it's another five minutes. Your call, but I'd run it on anything you mean to keep.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| prep | ULTRATEX_PREP | The rotated rig (output of UltraTex Rotate Rig). | |
| source_prep | ULTRATEX_PREP | The prep the first-pass views were generated with (UltraTex Prep). | |
| source_views | IMAGE | The 6 views of the first UltraTex Sampler (NOT directly usable as init_views: they are seen from the other rig). | |
| resolution | INT | 2048256–4096 | Use the resolution of the sampler that refines these views. |
| keep_above | FLOAT | 0.750–1.01 | Keep regions the first pass saw at least this head-on (cosine of the view angle, 0.75 ~ 41 deg). 1.01 = keep nothing (plain refine). |
| keep_feather | FLOAT | 0.100–0.5 | Soft transition width of the keep mask, in cosine units. |
| bake_stateopt | ULTRATEX_BAKE | Alternative source: bake_state of a first UltraTex Bake Texture (used instead of source_views). | |
| textureopt | COMBO | Which bake_state texture to render (only with bake_state). |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| init_views | IMAGE | — |
| keep_mask | MASK | — |