Skip to content

Commit

Permalink
Fix SpecularGlossinessMaterial
Browse files Browse the repository at this point in the history
  • Loading branch information
Keunhong Park committed Aug 22, 2019
1 parent 1cb07d9 commit 8b9d073
Show file tree
Hide file tree
Showing 4 changed files with 198 additions and 45 deletions.
6 changes: 3 additions & 3 deletions pyrender/material.py
Original file line number Diff line number Diff line change
Expand Up @@ -659,12 +659,12 @@ def specularFactor(self, value):
def glossinessFactor(self):
"""float : The glossiness of the material.
"""
return self.glossinessFactor
return self._glossinessFactor

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

@property
Expand Down
29 changes: 26 additions & 3 deletions pyrender/mesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@
"""
import numpy as np
import trimesh
import trimesh.visual

from .primitive import Primitive
from .constants import GLTF
from .material import MetallicRoughnessMaterial
from .material import MetallicRoughnessMaterial, SpecularGlossinessMaterial


class Mesh(object):
Expand Down Expand Up @@ -305,9 +306,31 @@ def _get_trimesh_props(mesh, smooth=False):
alphaCutoff=mat.alphaCutoff
)
elif isinstance(mat, trimesh.visual.texture.SimpleMaterial):
material = MetallicRoughnessMaterial(
glossiness = mat.kwargs.get('Ns', 1.0)
if isinstance(glossiness, list):
glossiness = float(glossiness[0])
roughness = (2 / (glossiness + 2)) ** (1.0/4.0)
# material = MetallicRoughnessMaterial(
# alphaMode='BLEND',
# roughnessFactor=roughness,
# baseColorTexture=mat.image,
# baseColorFactor=rgba_to_float(mat.diffuse),
# )
material = SpecularGlossinessMaterial(
alphaMode='BLEND',
baseColorTexture=mat.image
diffuseTexture=mat.image,
emissiveFactor=rgba_to_float(mat.ambient),
diffuseFactor=rgba_to_float(mat.diffuse),
specularFactor=rgba_to_float(mat.specular),
glossinessFactor=glossiness,
doubleSided=True,
)

return colors, texcoords, material


def rgba_to_float(rgba):
if rgba is None:
return None

return rgba.astype(np.float) / 255.0
2 changes: 1 addition & 1 deletion pyrender/renderer.py
Original file line number Diff line number Diff line change
Expand Up @@ -949,7 +949,7 @@ def _get_primitive_program(self, primitive, flags, program_flags):
defines['HAS_SPECULAR_GLOSSINESS_TEX'] = 1
if isinstance(primitive.material, MetallicRoughnessMaterial):
defines['USE_METALLIC_MATERIAL'] = 1
elif isinstance(material, SpecularGlossinessMaterial):
elif isinstance(primitive.material, SpecularGlossinessMaterial):
defines['USE_GLOSSY_MATERIAL'] = 1

program = self._program_cache.get_program(
Expand Down
206 changes: 168 additions & 38 deletions pyrender/shaders/mesh.frag
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ vec3 get_normal()
#ifdef NORMAL_LOC
vec3 ng = normalize(frag_normal);
#else
vec3 = cross(pos_dx, pos_dy);
vec3 ng = cross(pos_dx, pos_dy);
#endif

t = normalize(t - ng * dot(ng, t));
Expand Down Expand Up @@ -262,6 +262,25 @@ vec3 compute_brdf(vec3 n, vec3 v, vec3 l,
return color;
}


vec3 compute_blinn_phong_brdf(vec3 n, vec3 v, vec3 l, float glossiness,
vec3 diffuse, vec3 specular, vec3 radiance)
{
vec3 h = normalize(l+v);
float nl = clamp(dot(n, l), 0.001, 1.0);
float nv = clamp(abs(dot(n, v)), 0.001, 1.0);
float nh = clamp(dot(n, h), 0.0, 1.0);
float lh = clamp(dot(l, h), 0.0, 1.0);
float vh = clamp(dot(v, h), 0.0, 1.0);

vec3 diffuse_contrib = diffuse * nl / PI;
vec3 spec_contrib = specular * pow(nh, glossiness);

vec3 color = radiance * (diffuse_contrib + spec_contrib);
return color;
}


float texture2DCompare(sampler2D depths, vec2 uv, float compare) {
return compare > texture(depths, uv.xy).r ? 1.0 : 0.0;
}
Expand Down Expand Up @@ -308,36 +327,29 @@ float shadow_calc(mat4 light_matrix, sampler2D shadow_map, float nl)
return shadow;
}

///////////////////////////////////////////////////////////////////////////////
// MAIN
///////////////////////////////////////////////////////////////////////////////
void main()
{

vec4 color = vec4(vec3(0.0), 1.0);
///////////////////////////////////////////////////////////////////////////////
// Handle Metallic Materials
///////////////////////////////////////////////////////////////////////////////
#ifdef USE_METALLIC_MATERIAL
vec4 compute_metallic_color() {
vec4 color = vec4(vec3(0.0), 1.0);

// Compute metallic/roughness factors
float roughness = material.roughness_factor;
float metallic = material.metallic_factor;
#ifdef HAS_METALLIC_ROUGHNESS_TEX
#ifdef HAS_METALLIC_ROUGHNESS_TEX
vec2 mr = texture(material.metallic_roughness_texture, uv_0).rg;
roughness = roughness * mr.r;
metallic = metallic * mr.g;
#endif
#endif
roughness = clamp(roughness, min_roughness, 1.0);
metallic = clamp(metallic, 0.0, 1.0);
// In convention, material roughness is perceputal roughness ^ 2
float alpha_roughness = roughness * roughness;

// Compute albedo
vec4 base_color = material.base_color_factor;
#ifdef HAS_BASE_COLOR_TEX
#ifdef HAS_BASE_COLOR_TEX
base_color = base_color * srgb_to_linear(texture(material.base_color_texture, uv_0));
#endif
#endif

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

// Compute outbound color
vec3 res = compute_brdf(n, v, l, roughness, metallic,
f0, c_diff, base_color.rgb, radiance);
f0, c_diff, base_color.rgb, radiance);

// Compute shadow
#ifdef DIRECTIONAL_LIGHT_SHADOWS
#ifdef DIRECTIONAL_LIGHT_SHADOWS
float nl = clamp(dot(n,l), 0.0, 1.0);
float shadow = shadow_calc(
directional_lights[i].light_matrix,
directional_lights[i].shadow_map,
nl
directional_lights[i].light_matrix,
directional_lights[i].shadow_map,
nl
);
res = res * (1.0 - shadow);
#endif
#endif
color.xyz += res;
}

Expand All @@ -386,7 +398,7 @@ void main()

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

// Compute outbound color
vec3 res = compute_brdf(n, v, l, roughness, metallic,
f0, c_diff, base_color.rgb, radiance);
#ifdef SPOT_LIGHT_SHADOWS
f0, c_diff, base_color.rgb, radiance);
#ifdef SPOT_LIGHT_SHADOWS
float nl = clamp(dot(n,l), 0.0, 1.0);
float shadow = shadow_calc(
spot_lights[i].light_matrix,
spot_lights[i].shadow_map,
nl
);
nl);
res = res * (1.0 - shadow);
#endif
#endif
color.xyz += res;
}
color.xyz += base_color.xyz * ambient_light;

// Calculate lighting from environment
#ifdef USE_IBL
#ifdef USE_IBL
// TODO
#endif
#endif

// Apply occlusion
#ifdef HAS_OCCLUSION_TEX
#ifdef HAS_OCCLUSION_TEX
float ao = texture(material.occlusion_texture, uv_0).r;
color.xyz *= ao;
#endif
#endif

// Apply emissive map
vec3 emissive = material.emissive_factor;
#ifdef HAS_EMISSIVE_TEX
#ifdef HAS_EMISSIVE_TEX
emissive *= srgb_to_linear(texture(material.emissive_texture, uv_0)).rgb;
#endif
#endif
color.xyz += emissive * material.emissive_factor;

#ifdef COLOR_0_LOC
#ifdef COLOR_0_LOC
color *= color_multiplier;
#endif

return clamp(vec4(pow(color.xyz, vec3(1.0/2.2)), color.a * base_color.a), 0.0, 1.0);
}
#endif

frag_color = clamp(vec4(pow(color.xyz, vec3(1.0/2.2)), color.a * base_color.a), 0.0, 1.0);
#ifdef USE_GLOSSY_MATERIAL
vec4 compute_glossy_color() {
vec4 color = vec4(vec3(0.0), 1.0);

#else
// TODO GLOSSY MATERIAL BRDF
// Compute metallic/roughness factors
float glossiness = material.glossiness_factor;
#ifdef HAS_SPECULAR_GLOSSINESS_TEX
glossiness = glossiness * texture(material.specular_glossiness, uv_0).r;
#endif

// Compute albedo
vec4 diffuse_color = material.diffuse_factor;
vec4 specular_color = vec4(material.specular_factor, 1.0);
#ifdef HAS_DIFFUSE_TEX
diffuse_color = diffuse_color * srgb_to_linear(texture(material.diffuse_texture, uv_0));
#endif

// Compute normal
vec3 n = normalize(get_normal());

// Loop over lights
for (int i = 0; i < n_directional_lights; i++) {
vec3 direction = directional_lights[i].direction;
vec3 v = normalize(cam_pos - frag_position); // Vector towards camera
vec3 l = normalize(-1.0 * direction); // Vector towards light

// Compute attenuation and radiance
float attenuation = directional_lights[i].intensity;
vec3 radiance = attenuation * directional_lights[i].color;

// Compute outbound color
vec3 res = compute_blinn_phong_brdf(
n, v, l, glossiness, diffuse_color.rgb, specular_color.rgb, radiance);

// Compute shadow
#ifdef DIRECTIONAL_LIGHT_SHADOWS
float nl = clamp(dot(n,l), 0.0, 1.0);
float shadow = shadow_calc(
directional_lights[i].light_matrix,
directional_lights[i].shadow_map,
nl);
res = res * (1.0 - shadow);
#endif
color.xyz += res;
}

for (int i = 0; i < n_point_lights; i++) {
vec3 position = point_lights[i].position;
vec3 v = normalize(cam_pos - frag_position); // Vector towards camera
vec3 l = normalize(position - frag_position); // Vector towards light

// Compute attenuation and radiance
float dist = length(position - frag_position);
float attenuation = point_lights[i].intensity / (dist * dist);
vec3 radiance = attenuation * point_lights[i].color;

// Compute outbound color
vec3 res = compute_blinn_phong_brdf(
n, v, l, glossiness, diffuse_color.rgb, specular_color.rgb, radiance);
color.xyz += res;
}
for (int i = 0; i < n_spot_lights; i++) {
vec3 position = spot_lights[i].position;
vec3 v = normalize(cam_pos - frag_position); // Vector towards camera
vec3 l = normalize(position - frag_position); // Vector towards light

// Compute attenuation and radiance
vec3 direction = spot_lights[i].direction;
float las = spot_lights[i].light_angle_scale;
float lao = spot_lights[i].light_angle_offset;
float dist = length(position - frag_position);
float cd = clamp(dot(direction, -l), 0.0, 1.0);
float attenuation = clamp(cd * las + lao, 0.0, 1.0);
attenuation = attenuation * attenuation * spot_lights[i].intensity;
attenuation = attenuation / (dist * dist);
vec3 radiance = attenuation * spot_lights[i].color;

// Compute outbound color
vec3 res = compute_blinn_phong_brdf(
n, v, l, glossiness, diffuse_color.rgb, specular_color.rgb, radiance);
#ifdef SPOT_LIGHT_SHADOWS
float nl = clamp(dot(n,l), 0.0, 1.0);
float shadow = shadow_calc(
spot_lights[i].light_matrix,
spot_lights[i].shadow_map,
nl);
res = res * (1.0 - shadow);
#endif
color.xyz += res;
}

// Apply occlusion
#ifdef HAS_OCCLUSION_TEX
float ao = texture(material.occlusion_texture, uv_0).r;
color.xyz *= ao;
#endif

// Apply emissive map
vec3 emissive = material.emissive_factor;
#ifdef HAS_EMISSIVE_TEX
emissive *= srgb_to_linear(texture(material.emissive_texture, uv_0)).rgb;
#endif
color.xyz += emissive * material.emissive_factor;

#ifdef COLOR_0_LOC
color *= color_multiplier;
#endif

return clamp(vec4(pow(color.xyz, vec3(1.0/2.2)), color.a), 0.0, 1.0);
}
#endif

///////////////////////////////////////////////////////////////////////////////
// Handle Glossy Materials
// MAIN
///////////////////////////////////////////////////////////////////////////////

void main()
{
#ifdef USE_METALLIC_MATERIAL
frag_color = compute_metallic_color();
#elif USE_GLOSSY_MATERIAL
// TODO GLOSSY MATERIAL BRDF
frag_color = compute_glossy_color();
#else
frag_color = vec4(1.0, 0.0, 1.0, 1.0);
#endif
}

0 comments on commit 8b9d073

Please sign in to comment.