owl-project / NVISII

Apache License 2.0
319 stars 27 forks source link

Vertex colors not being used #133

Open nezix opened 2 years ago

nezix commented 2 years ago

Setting colors per vertex does not seem to work on 1.1.72 / Windows 10

Here is a simple example script to try:

import nvisii
import numpy as np 
import open3d as o3d

opt = lambda: None
opt.spp = 100
opt.width = 1920
opt.height = 1080 
opt.denoise = True
opt.out = 'TestVertexColor.png'
opt.path_obj = 'MYPATH.obj' #Change that !

interactive = True
# # # # # # # # # # # # # # # # # # # # # # # # #
if not interactive:
    nvisii.initialize(headless = True, verbose = True)
else:
    nvisii.initialize()
    nvisii.resize_window(1920, 1080)

if opt.denoise: 
    nvisii.enable_denoiser()

camera = nvisii.entity.create(
    name = "camera",
    transform = nvisii.transform.create("camera"),
    camera = nvisii.camera.create(
        name = "camera",  
        aspect = float(opt.width)/float(opt.height)
    )
)

camera.get_transform().look_at(
    at = (0,0,0),
    up = (0,0,1),
    eye = (0.0,6.0,-3),
)
nvisii.set_camera_entity(camera)

nvisii.set_dome_light_intensity(0.8)

# # # # # # # # # # # # # # # # # # # # # # # # #

o3dmesh = o3d.io.read_triangle_mesh(opt.path_obj)

if not o3dmesh.has_vertex_normals():            
    o3dmesh.compute_vertex_normals()

id_mesh = 0
mycolors = []

for i in range(len(o3dmesh.vertices)):
    mycolors += [1.0, 0.0, 0.0]
# Try with vector4 colors
#for i in range(len(o3dmesh.vertices)):
#   mycolors += [1.0, 0.0, 0.0, 1.0]

mesh = nvisii.mesh.create_from_data(
    'obj_mesh'+str(id_mesh),
    position_dimensions=3,
    normal_dimensions=3,
    color_dimensions=3,
    #color_dimensions=4,
    positions=np.asarray(o3dmesh.vertices).flatten(),
    normals=np.asarray(o3dmesh.vertex_normals).flatten(),
    colors=np.asarray(mycolors),#Set vertex colors here !
    indices=np.asarray(o3dmesh.triangles).flatten()
)
obj_entity = nvisii.entity.create(
    name="obj_entity"+str(id_mesh),
    mesh = mesh,
    transform = nvisii.transform.create("obj_entity"+str(id_mesh),
        scale=(2.5, 2.5, 2.5)
    ),
    material = nvisii.material.create("obj_entity"+str(id_mesh))
)

obj_entity.get_material().set_base_color((1.0, 1.0, 1.0))  

obj_entity.get_material().set_roughness(0.7)
obj_entity.get_material().set_specular(0)   
obj_entity.get_material().set_sheen(1)

if interactive:
    import time
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        print('interrupted!')
        nvisii.deinitialize()
else:
    nvisii.render_to_file(width=int(opt.width), height=int(opt.height), samples_per_pixel=int(opt.spp),file_path=f"{opt.out}")
    nvisii.deinitialize()
    print("Finished rendering to ",opt.out)

I expect to have a red dodecahedron but the mesh is white: image

natevm commented 2 years ago

Hi @nezix ,

I actually forgot the mesh create from data function accepted vertex colors. Your mesh above is white because nvisii is reading your material component, which has its base color set to white. We don’t currently read per-vertex colors during rendering.

What I don’t like about vertex colors is that there’s an ambiguity here between whether to use the material base color or the mesh vertex colors. Those ambiguities tend to result in ill defined behavior like you’re seeing here.

My solution here would probably be to remove that vertex color input from the mesh creation function, since it isn’t used. Do you have a specific reason why you’re using per-vertex colors rather than the material base color?

nezix commented 2 years ago

Hi, Thanks for your answer. It's pretty common in my field (molecular visualization) to procedurally generate meshes and vertex coloring is an easy way to color meshes dynamically based on an atom property. We generally blend the two colors together (baseColor x vertexColor). The alternative is more involved as it requires to proceduraly create a texture. I tried not to set the base_color but it does not seem to take vertex colors into account anyway.

natevm commented 2 years ago

Gotcha. Yeah, that could work. If both material base color and vertex color are accounted for, then there’s no longer this Ill-defined behavior issue.

I’ll mark this as an enhancement, since your use case makes sense to me.