diff --git a/bxdf/volume.py b/bxdf/volume.py
index e31cbce..de7e337 100644
--- a/bxdf/volume.py
+++ b/bxdf/volume.py
@@ -7,6 +7,7 @@
import os
import numpy as np
import taichi as ti
+import taichi.math as tm
import xml.etree.ElementTree as xet
from typing import Tuple
@@ -134,15 +135,33 @@ def setup_volume(self, path:str):
@staticmethod
def make_colorful_volume(density_grid: np.ndarray, xres: int, yres: int, zres: int):
- z_coords = np.linspace(0, 4.0, zres, dtype = np.float32).reshape(-1, 1, 1, 1) + 0.1
- y_coords = np.linspace(0, 0.5, yres, dtype = np.float32).reshape(1, -1, 1, 1) + 0.1
- x_coords = np.linspace(0, 0.1, xres, dtype = np.float32).reshape(1, 1, -1, 1) + 0.01
density_grid = np.concatenate([
- density_grid * z_coords,
- density_grid * y_coords,
- density_grid * x_coords,
+ density_grid,
+ density_grid,
+ density_grid
], axis = -1)
- return density_grid
+
+ # 创建一个从0到1的渐变数组,表示x轴从左到右
+ half_x = zres // 3
+ grad_l = np.linspace(1, 0, half_x, dtype = np.float32) ** 0.25
+ grad_r = np.linspace(0, 1, zres - half_x, dtype = np.float32) ** 0.1
+
+ # 前半部分,从红色(1, 0, 0)到白色(1, 1, 1)
+ left_half = np.zeros((half_x, 3), dtype = np.float32)
+ left_half[:, 0] = 1 # 红色通道保持1
+ left_half[:, 1] = 1 - grad_l # 绿色通道从0到1
+ left_half[:, 2] = 1 - grad_l # 蓝色通道从0到1
+
+ # 后半部分,从白色(1, 1, 1)到蓝色(0, 0, 1)
+ right_half = np.zeros((zres - half_x, 3), dtype = np.float32)
+ right_half[:, 0] = 1 - grad_r # 红色通道从1到0
+ right_half[:, 1] = 1 - grad_r # 绿色通道从1到0
+ right_half[:, 2] = 1 # 蓝色通道保持1
+
+ # 将两个部分组合在一起
+ color_gradient = np.vstack((left_half, right_half))
+
+ return density_grid * color_gradient[:, None, None, :]
def get_shape(self) -> Tuple[int, int, int]:
return (self.zres, self.yres, self.xres)
@@ -298,6 +317,25 @@ def density_lookup_3d(self, grid: ti.template(), index: vec3, u_offset: vec3) ->
val = grid[idx[2], idx[1], idx[0]]
return val
+ @ti.func
+ def density_lookup_lerp_3d(self, grid: ti.template(), index: vec3, u_offset: vec3) -> vec3:
+ """ Stochastic lookup of density (mono-chromatic volume) """
+ coord = index + (u_offset - 0.5)
+ idx = ti.cast(ti.floor(coord), int)
+ coord -= idx
+ val = ZERO_V3
+ if (idx >= 0).all() and (idx <= self.max_idxs - 1).all():
+ v1 = tm.mix(grid[idx[2], idx[1], idx[0]], grid[idx[2], idx[1], idx[0] + 1], coord[0])
+ v2 = tm.mix(grid[idx[2] + 1, idx[1], idx[0]], grid[idx[2] + 1, idx[1], idx[0] + 1], coord[0])
+ v3 = tm.mix(grid[idx[2], idx[1] + 1, idx[0]], grid[idx[2], idx[1] + 1, idx[0] + 1], coord[0])
+ v4 = tm.mix(grid[idx[2] + 1, idx[1] + 1, idx[0]], grid[idx[2] + 1, idx[1] + 1, idx[0] + 1], coord[0])
+
+ v1 = tm.mix(v1, v2, coord[2])
+ v3 = tm.mix(v3, v4, coord[2])
+
+ val = tm.mix(v1, v3, coord[1])
+ return val
+
@ti.func
def sample_new_rays(self, incid: vec3):
ret_spec = vec3([1, 1, 1])
@@ -345,7 +383,7 @@ def sample_distance_delta_tracking_3d(self,
t = near_far[0] - ti.log(1.0 - ti.random(float)) * inv_maj
while t < near_far[1]:
- d = self.density_lookup_3d(grid, ray_ol + t * ray_dl, vec3([
+ d = self.density_lookup_lerp_3d(grid, ray_ol + t * ray_dl, vec3([
ti.random(float), ti.random(float), ti.random(float)
]))
# Scatter upon real collision
@@ -404,7 +442,7 @@ def eval_tr_ratio_tracking_3d(self,
if t >= near_far[1]: break
# for mono-chromatic medium, this is 1
- d = self.density_lookup_3d(grid, ray_ol + t * ray_dl, vec3([
+ d = self.density_lookup_lerp_3d(grid, ray_ol + t * ray_dl, vec3([
ti.random(float), ti.random(float), ti.random(float)
]))
diff --git a/scenes/cbox/cbox-rgbvol.xml b/scenes/cbox/cbox-rgbvol.xml
index 57c36ae..8791cc8 100644
--- a/scenes/cbox/cbox-rgbvol.xml
+++ b/scenes/cbox/cbox-rgbvol.xml
@@ -50,13 +50,13 @@
-
+
-
+
@@ -69,7 +69,7 @@
-
+
@@ -114,14 +114,14 @@
-
+
-
-
-
+
+
+
diff --git a/scenes/cbox/cbox-volgrid.xml b/scenes/cbox/cbox-volgrid.xml
index 4fd8d3e..e0e42f9 100755
--- a/scenes/cbox/cbox-volgrid.xml
+++ b/scenes/cbox/cbox-volgrid.xml
@@ -9,7 +9,7 @@
-
+
@@ -17,10 +17,11 @@
-
+
+
+
-
@@ -66,19 +67,19 @@
-
+
-
+
-
+
@@ -104,14 +105,14 @@
-
+
@@ -160,9 +161,9 @@
-
+
-
+