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

[WIP] Implement SpecularGlossinessMaterial #64

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
15 changes: 12 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,17 @@ 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])
material = SpecularGlossinessMaterial(
alphaMode='BLEND',
baseColorTexture=mat.image
diffuseTexture=mat.image,
emissiveFactor=mat.ambient,
diffuseFactor=mat.diffuse,
specularFactor=mat.specular,
glossinessFactor=glossiness,
doubleSided=True,
)

return colors, texcoords, material
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
}