Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update water volume shader #384

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
34 changes: 29 additions & 5 deletions infinigen/assets/materials/water.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
# Acknowledgment: This file draws inspiration from https://www.youtube.com/watch?v=X3LlsdddMLo by Kev Binge


import logging

import bpy
import gin
import numpy as np
Expand All @@ -23,6 +25,7 @@
mod_name = "geo_water"
name = "water"
info = {}
logger = logging.getLogger(__name__)


@gin.configurable("geo")
Expand Down Expand Up @@ -237,11 +240,13 @@ def shader(
asset_paths,
coastal,
color=("color_category", "water"),
scatter_color=("color_category", "water_scatter"),
enable_scatter=True,
colored=False,
emissive_foam=False,
volume_density=("uniform", 0.07, 0.09),
anisotropy=("clip_gaussian", 0.75, 0.2, 0.5, 1),
scatter_density=("uniform", 0.0005, 0.002),
mix_surface=False,
random_seed=0,
):
Expand All @@ -250,6 +255,7 @@ def shader(
# Code generated using version 2.3.1 of the node_transpiler (partly)
with FixedSeed(random_seed):
color = rg(color)
scatter_color = rg(scatter_color)
light_path = nw.new_node(Nodes.LightPath)

if colored:
Expand Down Expand Up @@ -332,15 +338,33 @@ def shader(

rgb = nw.new_node(Nodes.RGB)
rgb.outputs[0].default_value = color
principled_volume = nw.new_node(
Nodes.PrincipledVolume,

volume_density = rg(volume_density)
volume_absorption = nw.new_node(
Nodes.VolumeAbsorption,
input_kwargs={
"Color": rgb,
"Absorption Color": rgb,
"Density": rg(volume_density) if enable_scatter else 0,
"Anisotropy": rg(anisotropy),
"Density": volume_density,
},
)
logger.debug(f"Water Volume Absorption: color {color}, density: {volume_density}")

scatter_rgb = nw.new_node(Nodes.RGB)
scatter_density = rg(scatter_density) if enable_scatter else 0
scatter_anisotropy = rg(anisotropy)
scatter_rgb.outputs[0].default_value = scatter_color
volume_scatter = nw.new_node(
Nodes.VolumeScatter,
input_kwargs={
"Color": scatter_rgb,
"Density": scatter_density,
"Anisotropy": scatter_anisotropy,
},
)
logger.debug(f"Water Volume Scattering: color {scatter_color}, density: {scatter_density}, anistropy: {scatter_anisotropy}")
#volume_scatter.phase = "FOURNIER_FORAND" # for Blender 4.3

principled_volume = nw.new_node(Nodes.AddShader, [volume_absorption, volume_scatter])

material_output = nw.new_node(
Nodes.MaterialOutput,
Expand Down
3 changes: 3 additions & 0 deletions infinigen/core/nodes/node_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,11 +224,14 @@ class Nodes:

# Shaders
MixShader = "ShaderNodeMixShader"
AddShader = "ShaderNodeAddShader"
DiffuseBSDF = "ShaderNodeBsdfDiffuse"
PrincipledBSDF = "ShaderNodeBsdfPrincipled"
TranslucentBSDF = "ShaderNodeBsdfTranslucent"
TransparentBSDF = "ShaderNodeBsdfTransparent"
PrincipledVolume = "ShaderNodeVolumePrincipled"
VolumeAbsorption = "ShaderNodeVolumeAbsorption"
VolumeScatter = "ShaderNodeVolumeScatter"
PrincipledHairBSDF = "ShaderNodeBsdfHairPrincipled"
Emission = "ShaderNodeEmission"
Fresnel = "ShaderNodeFresnel"
Expand Down
72 changes: 51 additions & 21 deletions infinigen/core/rendering/render.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,32 @@
# - Hei Law - Initial version


import json
import logging
import os
import time
from pathlib import Path
import shutil

import bpy
import gin
import numpy as np
from imageio import imwrite
import cv2

from infinigen.core import init, surface
from infinigen.core.nodes.node_wrangler import Nodes, NodeWrangler
from infinigen.core.placement import camera as cam_util
from infinigen.core.rendering.post_render import (
colorize_depth,
colorize_flow,
colorize_int_array,
colorize_normals,
load_depth,
load_flow,
load_normals,
load_seg_mask,
load_uniq_inst,

Check failure on line 35 in infinigen/core/rendering/render.py

View workflow job for this annotation

GitHub Actions / checks

Ruff (F401)

infinigen/core/rendering/render.py:35:5: F401 `infinigen.core.rendering.post_render.load_uniq_inst` imported but unused
)
from infinigen.core.util import blender as butil
from infinigen.core.util.logging import Timer
Expand Down Expand Up @@ -225,25 +227,56 @@


def shader_random(nw: NodeWrangler):
# Code generated using version 2.4.3 of the node_transpiler
# Code generated using version 2.6.5 of the node_transpiler
object_info_1 = nw.new_node(Nodes.ObjectInfo_Shader)

object_info = nw.new_node(Nodes.ObjectInfo_Shader)
value = nw.new_node(Nodes.Value)
value.outputs[0].default_value = 10

white_noise_texture = nw.new_node(
Nodes.WhiteNoiseTexture, input_kwargs={"Vector": object_info.outputs["Random"]}
)
divide = nw.new_node(Nodes.Math, input_kwargs={0: 1.0000, 1: value}, attrs={'operation': 'DIVIDE'})

divide_1 = nw.new_node(Nodes.Math, input_kwargs={0: object_info_1.outputs["Random"], 1: divide},
attrs={'operation': 'DIVIDE'})

floor = nw.new_node(Nodes.Math, input_kwargs={0: divide_1}, attrs={'operation': 'FLOOR'})

multiply = nw.new_node(Nodes.Math, input_kwargs={0: floor, 1: divide}, attrs={'operation': 'MULTIPLY'})

divide_2 = nw.new_node(Nodes.Math, input_kwargs={0: object_info_1.outputs["Random"], 1: divide},
attrs={'operation': 'DIVIDE'})

fract = nw.new_node(Nodes.Math, input_kwargs={0: divide_2}, attrs={'operation': 'FRACT'})

divide_3 = nw.new_node(Nodes.Math, input_kwargs={0: fract, 1: divide}, attrs={'operation': 'DIVIDE'})

floor_1 = nw.new_node(Nodes.Math, input_kwargs={0: divide_3}, attrs={'operation': 'FLOOR'})

multiply_1 = nw.new_node(Nodes.Math, input_kwargs={0: floor_1, 1: divide}, attrs={'operation': 'MULTIPLY'})

divide_4 = nw.new_node(Nodes.Math, input_kwargs={0: divide_2, 1: divide}, attrs={'operation': 'DIVIDE'})

fract_1 = nw.new_node(Nodes.Math, input_kwargs={0: divide_4}, attrs={'operation': 'FRACT'})

divide_5 = nw.new_node(Nodes.Math, input_kwargs={0: fract_1, 1: divide}, attrs={'operation': 'DIVIDE'})

floor_2 = nw.new_node(Nodes.Math, input_kwargs={0: divide_5}, attrs={'operation': 'FLOOR'})

multiply_2 = nw.new_node(Nodes.Math, input_kwargs={0: floor_2, 1: divide}, attrs={'operation': 'MULTIPLY'})

combine_color = nw.new_node(Nodes.CombineColor,
input_kwargs={'Red': multiply, 'Green': multiply_1, 'Blue': multiply_2})

emission = nw.new_node(
"ShaderNodeEmission", input_kwargs={"Color": combine_color, "Strength": 0.5})
_ = nw.new_node(Nodes.MaterialOutput, input_kwargs={'Surface': emission})

nw.new_node(
Nodes.MaterialOutput,
input_kwargs={"Surface": white_noise_texture.outputs["Color"]},
)


def global_flat_shading():
for obj in bpy.context.scene.view_layers["ViewLayer"].objects:
if "fire_system_type" in obj and obj["fire_system_type"] == "volume":
continue
if obj.name.lower() in {"atmosphere", "atmosphere_fine"}:
if obj.name.lower() in {"atmosphere", "atmosphere_fine", "liquid", "liquid_fine"}:
bpy.data.objects.remove(obj)
elif obj.active_material is not None:
nw = obj.active_material.node_tree
Expand All @@ -252,6 +285,7 @@
vol_socket = node.inputs["Volume"]
if len(vol_socket.links) > 0:
nw.links.remove(vol_socket.links[0])
bpy.context.view_layer.update()

for obj in bpy.context.scene.view_layers["ViewLayer"].objects:
if obj.type != "MESH":
Expand All @@ -278,7 +312,7 @@
nw.links.remove(link)


def postprocess_blendergt_outputs(frames_folder, output_stem):
def postprocess_blendergt_outputs(frames_folder, output_stem, frame, tmp_dir):
# Save flow visualization
flow_dst_path = frames_folder / f"Vector{output_stem}.exr"
flow_array = load_flow(flow_dst_path)
Expand Down Expand Up @@ -325,15 +359,11 @@

# Save unique instances visualization
uniq_inst_path = frames_folder / f"UniqueInstances{output_stem}.exr"
uniq_inst_array = load_uniq_inst(uniq_inst_path)
np.save(
flow_dst_path.with_name(f"InstanceSegmentation{output_stem}.npy"),
uniq_inst_array,
)
imwrite(
uniq_inst_path.with_name(f"InstanceSegmentation{output_stem}.png"),
colorize_int_array(uniq_inst_array),
)
#uniq_inst_array = load_uniq_inst(uniq_inst_path)
uniq_inst_tmp_path = f"{tmp_dir}/{frame:04d}.png"
uniq_inst_array = cv2.imread(uniq_inst_tmp_path)
np.save(flow_dst_path.with_name(f"InstanceSegmentation{output_stem}.npy"), uniq_inst_array)
shutil.copy(uniq_inst_tmp_path, str(flow_dst_path.with_name(f"InstanceSegmentation{output_stem}.png")))
uniq_inst_path.unlink()


Expand Down Expand Up @@ -475,7 +505,7 @@
if flat_shading:
bpy.context.scene.frame_set(frame)
suffix = get_suffix(dict(frame=frame, **indices))
postprocess_blendergt_outputs(frames_folder, suffix)
postprocess_blendergt_outputs(frames_folder, suffix, frame, tmp_dir)
else:
cam_util.save_camera_parameters(
camera,
Expand Down
11 changes: 10 additions & 1 deletion infinigen/core/util/color.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,16 @@ def N(m, std, **kwargs):
"water": (U(0.2, 0.6), N(0.5, 0.1), U(0.7, 1)),
"darker_water": (U(0.2, 0.6), N(0.5, 0.1), U(0.2, 0.3)),
"under_water": (U(0.5, 0.7), U(0.7, 0.95), U(0.7, 1)),
"eye_schlera": (U(0.05, 0.15), U(0.2, 0.8), U(0.05, 0.5)),
"water_scatter": (
N(0.474, 0.05),
N(0.8, 0.1),
N(0.9, 0.1)
),
"seawater": (
N(0.453, 0.03),
N(0.95, 0.05),
N(0.5, 0.1)
), "eye_schlera": (U(0.05, 0.15), U(0.2, 0.8), U(0.05, 0.5)),
"eye_pupil": (U(0, 1), U(0.1, 0.9), U(0.1, 0.9)),
"beak": (U(0, 0.13), U(0, 0.9), U(0.1, 0.6)),
"fur": (U(0, 0.11), U(0.5, 0.95), U(0.02, 0.9)),
Expand Down
12 changes: 7 additions & 5 deletions infinigen_examples/configs_nature/scene_types/coral_reef.gin
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
include 'infinigen_examples/configs_nature/scene_types/under_water.gin'

compose_nature.kelp_chance = 0.1
compose_nature.urchin_chance = 0.1
compose_nature.kelp_chance = 0.0
compose_nature.urchin_chance = 0.0

compose_nature.corals_chance = 1.
compose_nature.seaweed_chance = 0.2
compose_nature.seashell_chance = 0.7
compose_nature.seaweed_chance = 0.0
compose_nature.seashell_chance = 0.0
compose_nature.jellyfish_chance = 0.0

water.geo.with_waves=True
water.geo.with_waves=True

water.shader.color = ("color_category", "under_water")
Loading