Skip to content

Commit 8b9d073

Browse files
author
Keunhong Park
committed
Fix SpecularGlossinessMaterial
1 parent 1cb07d9 commit 8b9d073

File tree

4 files changed

+198
-45
lines changed

4 files changed

+198
-45
lines changed

pyrender/material.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -659,12 +659,12 @@ def specularFactor(self, value):
659659
def glossinessFactor(self):
660660
"""float : The glossiness of the material.
661661
"""
662-
return self.glossinessFactor
662+
return self._glossinessFactor
663663

664664
@glossinessFactor.setter
665665
def glossinessFactor(self, value):
666-
if value < 0 or value > 1:
667-
raise ValueError('glossiness factor must be in range [0,1]')
666+
if value < 0:
667+
raise ValueError('glossiness factor must be non-zero')
668668
self._glossinessFactor = float(value)
669669

670670
@property

pyrender/mesh.py

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55
"""
66
import numpy as np
77
import trimesh
8+
import trimesh.visual
89

910
from .primitive import Primitive
1011
from .constants import GLTF
11-
from .material import MetallicRoughnessMaterial
12+
from .material import MetallicRoughnessMaterial, SpecularGlossinessMaterial
1213

1314

1415
class Mesh(object):
@@ -305,9 +306,31 @@ def _get_trimesh_props(mesh, smooth=False):
305306
alphaCutoff=mat.alphaCutoff
306307
)
307308
elif isinstance(mat, trimesh.visual.texture.SimpleMaterial):
308-
material = MetallicRoughnessMaterial(
309+
glossiness = mat.kwargs.get('Ns', 1.0)
310+
if isinstance(glossiness, list):
311+
glossiness = float(glossiness[0])
312+
roughness = (2 / (glossiness + 2)) ** (1.0/4.0)
313+
# material = MetallicRoughnessMaterial(
314+
# alphaMode='BLEND',
315+
# roughnessFactor=roughness,
316+
# baseColorTexture=mat.image,
317+
# baseColorFactor=rgba_to_float(mat.diffuse),
318+
# )
319+
material = SpecularGlossinessMaterial(
309320
alphaMode='BLEND',
310-
baseColorTexture=mat.image
321+
diffuseTexture=mat.image,
322+
emissiveFactor=rgba_to_float(mat.ambient),
323+
diffuseFactor=rgba_to_float(mat.diffuse),
324+
specularFactor=rgba_to_float(mat.specular),
325+
glossinessFactor=glossiness,
326+
doubleSided=True,
311327
)
312328

313329
return colors, texcoords, material
330+
331+
332+
def rgba_to_float(rgba):
333+
if rgba is None:
334+
return None
335+
336+
return rgba.astype(np.float) / 255.0

pyrender/renderer.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -949,7 +949,7 @@ def _get_primitive_program(self, primitive, flags, program_flags):
949949
defines['HAS_SPECULAR_GLOSSINESS_TEX'] = 1
950950
if isinstance(primitive.material, MetallicRoughnessMaterial):
951951
defines['USE_METALLIC_MATERIAL'] = 1
952-
elif isinstance(material, SpecularGlossinessMaterial):
952+
elif isinstance(primitive.material, SpecularGlossinessMaterial):
953953
defines['USE_GLOSSY_MATERIAL'] = 1
954954

955955
program = self._program_cache.get_program(

pyrender/shaders/mesh.frag

Lines changed: 168 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ vec3 get_normal()
177177
#ifdef NORMAL_LOC
178178
vec3 ng = normalize(frag_normal);
179179
#else
180-
vec3 = cross(pos_dx, pos_dy);
180+
vec3 ng = cross(pos_dx, pos_dy);
181181
#endif
182182

183183
t = normalize(t - ng * dot(ng, t));
@@ -262,6 +262,25 @@ vec3 compute_brdf(vec3 n, vec3 v, vec3 l,
262262
return color;
263263
}
264264

265+
266+
vec3 compute_blinn_phong_brdf(vec3 n, vec3 v, vec3 l, float glossiness,
267+
vec3 diffuse, vec3 specular, vec3 radiance)
268+
{
269+
vec3 h = normalize(l+v);
270+
float nl = clamp(dot(n, l), 0.001, 1.0);
271+
float nv = clamp(abs(dot(n, v)), 0.001, 1.0);
272+
float nh = clamp(dot(n, h), 0.0, 1.0);
273+
float lh = clamp(dot(l, h), 0.0, 1.0);
274+
float vh = clamp(dot(v, h), 0.0, 1.0);
275+
276+
vec3 diffuse_contrib = diffuse * nl / PI;
277+
vec3 spec_contrib = specular * pow(nh, glossiness);
278+
279+
vec3 color = radiance * (diffuse_contrib + spec_contrib);
280+
return color;
281+
}
282+
283+
265284
float texture2DCompare(sampler2D depths, vec2 uv, float compare) {
266285
return compare > texture(depths, uv.xy).r ? 1.0 : 0.0;
267286
}
@@ -308,36 +327,29 @@ float shadow_calc(mat4 light_matrix, sampler2D shadow_map, float nl)
308327
return shadow;
309328
}
310329

311-
///////////////////////////////////////////////////////////////////////////////
312-
// MAIN
313-
///////////////////////////////////////////////////////////////////////////////
314-
void main()
315-
{
316330

317-
vec4 color = vec4(vec3(0.0), 1.0);
318-
///////////////////////////////////////////////////////////////////////////////
319-
// Handle Metallic Materials
320-
///////////////////////////////////////////////////////////////////////////////
321331
#ifdef USE_METALLIC_MATERIAL
332+
vec4 compute_metallic_color() {
333+
vec4 color = vec4(vec3(0.0), 1.0);
322334

323335
// Compute metallic/roughness factors
324336
float roughness = material.roughness_factor;
325337
float metallic = material.metallic_factor;
326-
#ifdef HAS_METALLIC_ROUGHNESS_TEX
338+
#ifdef HAS_METALLIC_ROUGHNESS_TEX
327339
vec2 mr = texture(material.metallic_roughness_texture, uv_0).rg;
328340
roughness = roughness * mr.r;
329341
metallic = metallic * mr.g;
330-
#endif
342+
#endif
331343
roughness = clamp(roughness, min_roughness, 1.0);
332344
metallic = clamp(metallic, 0.0, 1.0);
333345
// In convention, material roughness is perceputal roughness ^ 2
334346
float alpha_roughness = roughness * roughness;
335347

336348
// Compute albedo
337349
vec4 base_color = material.base_color_factor;
338-
#ifdef HAS_BASE_COLOR_TEX
350+
#ifdef HAS_BASE_COLOR_TEX
339351
base_color = base_color * srgb_to_linear(texture(material.base_color_texture, uv_0));
340-
#endif
352+
#endif
341353

342354
// Compute specular and diffuse colors
343355
vec3 dialectric_spec = vec3(min_roughness);
@@ -359,18 +371,18 @@ void main()
359371

360372
// Compute outbound color
361373
vec3 res = compute_brdf(n, v, l, roughness, metallic,
362-
f0, c_diff, base_color.rgb, radiance);
374+
f0, c_diff, base_color.rgb, radiance);
363375

364376
// Compute shadow
365-
#ifdef DIRECTIONAL_LIGHT_SHADOWS
377+
#ifdef DIRECTIONAL_LIGHT_SHADOWS
366378
float nl = clamp(dot(n,l), 0.0, 1.0);
367379
float shadow = shadow_calc(
368-
directional_lights[i].light_matrix,
369-
directional_lights[i].shadow_map,
370-
nl
380+
directional_lights[i].light_matrix,
381+
directional_lights[i].shadow_map,
382+
nl
371383
);
372384
res = res * (1.0 - shadow);
373-
#endif
385+
#endif
374386
color.xyz += res;
375387
}
376388

@@ -386,7 +398,7 @@ void main()
386398

387399
// Compute outbound color
388400
vec3 res = compute_brdf(n, v, l, roughness, metallic,
389-
f0, c_diff, base_color.rgb, radiance);
401+
f0, c_diff, base_color.rgb, radiance);
390402
color.xyz += res;
391403
}
392404
for (int i = 0; i < n_spot_lights; i++) {
@@ -407,50 +419,168 @@ void main()
407419

408420
// Compute outbound color
409421
vec3 res = compute_brdf(n, v, l, roughness, metallic,
410-
f0, c_diff, base_color.rgb, radiance);
411-
#ifdef SPOT_LIGHT_SHADOWS
422+
f0, c_diff, base_color.rgb, radiance);
423+
#ifdef SPOT_LIGHT_SHADOWS
412424
float nl = clamp(dot(n,l), 0.0, 1.0);
413425
float shadow = shadow_calc(
414426
spot_lights[i].light_matrix,
415427
spot_lights[i].shadow_map,
416-
nl
417-
);
428+
nl);
418429
res = res * (1.0 - shadow);
419-
#endif
430+
#endif
420431
color.xyz += res;
421432
}
422433
color.xyz += base_color.xyz * ambient_light;
423434

424435
// Calculate lighting from environment
425-
#ifdef USE_IBL
436+
#ifdef USE_IBL
426437
// TODO
427-
#endif
438+
#endif
428439

429440
// Apply occlusion
430-
#ifdef HAS_OCCLUSION_TEX
441+
#ifdef HAS_OCCLUSION_TEX
431442
float ao = texture(material.occlusion_texture, uv_0).r;
432443
color.xyz *= ao;
433-
#endif
444+
#endif
434445

435446
// Apply emissive map
436447
vec3 emissive = material.emissive_factor;
437-
#ifdef HAS_EMISSIVE_TEX
448+
#ifdef HAS_EMISSIVE_TEX
438449
emissive *= srgb_to_linear(texture(material.emissive_texture, uv_0)).rgb;
439-
#endif
450+
#endif
440451
color.xyz += emissive * material.emissive_factor;
441452

442-
#ifdef COLOR_0_LOC
453+
#ifdef COLOR_0_LOC
443454
color *= color_multiplier;
455+
#endif
456+
457+
return clamp(vec4(pow(color.xyz, vec3(1.0/2.2)), color.a * base_color.a), 0.0, 1.0);
458+
}
444459
#endif
445460

446-
frag_color = clamp(vec4(pow(color.xyz, vec3(1.0/2.2)), color.a * base_color.a), 0.0, 1.0);
461+
#ifdef USE_GLOSSY_MATERIAL
462+
vec4 compute_glossy_color() {
463+
vec4 color = vec4(vec3(0.0), 1.0);
447464

448-
#else
449-
// TODO GLOSSY MATERIAL BRDF
465+
// Compute metallic/roughness factors
466+
float glossiness = material.glossiness_factor;
467+
#ifdef HAS_SPECULAR_GLOSSINESS_TEX
468+
glossiness = glossiness * texture(material.specular_glossiness, uv_0).r;
469+
#endif
470+
471+
// Compute albedo
472+
vec4 diffuse_color = material.diffuse_factor;
473+
vec4 specular_color = vec4(material.specular_factor, 1.0);
474+
#ifdef HAS_DIFFUSE_TEX
475+
diffuse_color = diffuse_color * srgb_to_linear(texture(material.diffuse_texture, uv_0));
476+
#endif
477+
478+
// Compute normal
479+
vec3 n = normalize(get_normal());
480+
481+
// Loop over lights
482+
for (int i = 0; i < n_directional_lights; i++) {
483+
vec3 direction = directional_lights[i].direction;
484+
vec3 v = normalize(cam_pos - frag_position); // Vector towards camera
485+
vec3 l = normalize(-1.0 * direction); // Vector towards light
486+
487+
// Compute attenuation and radiance
488+
float attenuation = directional_lights[i].intensity;
489+
vec3 radiance = attenuation * directional_lights[i].color;
490+
491+
// Compute outbound color
492+
vec3 res = compute_blinn_phong_brdf(
493+
n, v, l, glossiness, diffuse_color.rgb, specular_color.rgb, radiance);
494+
495+
// Compute shadow
496+
#ifdef DIRECTIONAL_LIGHT_SHADOWS
497+
float nl = clamp(dot(n,l), 0.0, 1.0);
498+
float shadow = shadow_calc(
499+
directional_lights[i].light_matrix,
500+
directional_lights[i].shadow_map,
501+
nl);
502+
res = res * (1.0 - shadow);
503+
#endif
504+
color.xyz += res;
505+
}
506+
507+
for (int i = 0; i < n_point_lights; i++) {
508+
vec3 position = point_lights[i].position;
509+
vec3 v = normalize(cam_pos - frag_position); // Vector towards camera
510+
vec3 l = normalize(position - frag_position); // Vector towards light
511+
512+
// Compute attenuation and radiance
513+
float dist = length(position - frag_position);
514+
float attenuation = point_lights[i].intensity / (dist * dist);
515+
vec3 radiance = attenuation * point_lights[i].color;
516+
517+
// Compute outbound color
518+
vec3 res = compute_blinn_phong_brdf(
519+
n, v, l, glossiness, diffuse_color.rgb, specular_color.rgb, radiance);
520+
color.xyz += res;
521+
}
522+
for (int i = 0; i < n_spot_lights; i++) {
523+
vec3 position = spot_lights[i].position;
524+
vec3 v = normalize(cam_pos - frag_position); // Vector towards camera
525+
vec3 l = normalize(position - frag_position); // Vector towards light
526+
527+
// Compute attenuation and radiance
528+
vec3 direction = spot_lights[i].direction;
529+
float las = spot_lights[i].light_angle_scale;
530+
float lao = spot_lights[i].light_angle_offset;
531+
float dist = length(position - frag_position);
532+
float cd = clamp(dot(direction, -l), 0.0, 1.0);
533+
float attenuation = clamp(cd * las + lao, 0.0, 1.0);
534+
attenuation = attenuation * attenuation * spot_lights[i].intensity;
535+
attenuation = attenuation / (dist * dist);
536+
vec3 radiance = attenuation * spot_lights[i].color;
537+
538+
// Compute outbound color
539+
vec3 res = compute_blinn_phong_brdf(
540+
n, v, l, glossiness, diffuse_color.rgb, specular_color.rgb, radiance);
541+
#ifdef SPOT_LIGHT_SHADOWS
542+
float nl = clamp(dot(n,l), 0.0, 1.0);
543+
float shadow = shadow_calc(
544+
spot_lights[i].light_matrix,
545+
spot_lights[i].shadow_map,
546+
nl);
547+
res = res * (1.0 - shadow);
548+
#endif
549+
color.xyz += res;
550+
}
551+
552+
// Apply occlusion
553+
#ifdef HAS_OCCLUSION_TEX
554+
float ao = texture(material.occlusion_texture, uv_0).r;
555+
color.xyz *= ao;
556+
#endif
557+
558+
// Apply emissive map
559+
vec3 emissive = material.emissive_factor;
560+
#ifdef HAS_EMISSIVE_TEX
561+
emissive *= srgb_to_linear(texture(material.emissive_texture, uv_0)).rgb;
562+
#endif
563+
color.xyz += emissive * material.emissive_factor;
564+
565+
#ifdef COLOR_0_LOC
566+
color *= color_multiplier;
567+
#endif
568+
569+
return clamp(vec4(pow(color.xyz, vec3(1.0/2.2)), color.a), 0.0, 1.0);
570+
}
450571
#endif
451572

452573
///////////////////////////////////////////////////////////////////////////////
453-
// Handle Glossy Materials
574+
// MAIN
454575
///////////////////////////////////////////////////////////////////////////////
455-
576+
void main()
577+
{
578+
#ifdef USE_METALLIC_MATERIAL
579+
frag_color = compute_metallic_color();
580+
#elif USE_GLOSSY_MATERIAL
581+
// TODO GLOSSY MATERIAL BRDF
582+
frag_color = compute_glossy_color();
583+
#else
584+
frag_color = vec4(1.0, 0.0, 1.0, 1.0);
585+
#endif
456586
}

0 commit comments

Comments
 (0)