Materials are now working in both Psychopath and PsychoBlend.

Except that Emit is still not properly supported, because it needs
special handling.
This commit is contained in:
Nathan Vegdahl 2017-08-03 20:32:07 -07:00
parent 516803e78a
commit ad55aa4f6d
3 changed files with 158 additions and 6 deletions

View File

@ -12,6 +12,7 @@ class Assembly:
self.objects = []
self.instances = []
self.material_names = set()
self.mesh_names = set()
self.assembly_names = set()
@ -119,10 +120,19 @@ class Assembly:
if should_export_mesh:
self.mesh_names.add(mesh_name)
self.objects += [Mesh(self.render_engine, ob, mesh_name)]
# Get materials
for ms in ob.material_slots:
if ms != None:
if ms.material.name not in self.material_names:
self.material_names.add(ms.material.name)
self.materials += [Material(self.render_engine, ms.material)]
return mesh_name
else:
return None
def get_sphere_lamp(self, ob, group_prefix):
name = group_prefix + "__" + escape_name(ob.name)
self.objects += [SphereLamp(self.render_engine, ob, name)]
@ -281,5 +291,46 @@ class Instance:
w.write("Data [$%s]\n" % self.data_name)
for mat in self.time_xforms:
w.write("Transform [%s]\n" % mat2str(mat.inverted()))
for ms in self.ob.material_slots:
if ms != None:
w.write("SurfaceShaderBind [$%s]\n" % escape_name(ms.material.name))
break
w.unindent()
w.write("}\n")
class Material:
def __init__(self, render_engine, material):
self.mat = material
def take_sample(self, render_engine, time, translation_offset):
# TODO: motion blur of material settings
pass
def export(self, render_engine, w):
render_engine.update_stats("", "Psychopath: Exporting %s" % self.mat.name)
w.write("SurfaceShader $%s {\n" % escape_name(self.mat.name))
w.indent()
if self.mat.psychopath.surface_shader_type == 'Emit':
w.write("Type [Emit]\n")
color = self.mat.psychopath.color
w.write("Color [%f %f %f]\n" % (color[0], color[1], color[2]))
elif self.mat.psychopath.surface_shader_type == 'Lambert':
w.write("Type [Lambert]\n")
color = self.mat.psychopath.color
w.write("Color [%f %f %f]\n" % (color[0], color[1], color[2]))
elif self.mat.psychopath.surface_shader_type == 'GTR':
w.write("Type [GTR]\n")
color = self.mat.psychopath.color
w.write("Color [%f %f %f]\n" % (color[0], color[1], color[2]))
w.write("Roughness [%f]\n" % self.mat.psychopath.roughness)
w.write("TailShape [%f]\n" % self.mat.psychopath.tail_shape)
w.write("Fresnel [%f]\n" % self.mat.psychopath.fresnel)
else:
raise "Unsupported surface shader type '%s'" % self.mat.psychopath.surface_shader_type
w.unindent()
w.write("}\n")
def cleanup(self):
pass

View File

@ -35,7 +35,30 @@ pub fn parse_surface_shader<'a>(
};
let shader = match type_name {
"Emit" => unimplemented!(),
"Emit" => {
let color = if let Some((_, contents, byte_offset)) =
tree.iter_leaf_children_with_type("Color").nth(0)
{
if let IResult::Done(_, color) =
closure!(tuple!(ws_f32, ws_f32, ws_f32))(contents.as_bytes())
{
// TODO: handle color space conversions properly.
// Probably will need a special color type with its
// own parser...?
XYZ::from_tuple(rec709_e_to_xyz(color))
} else {
// Found color, but its contents is not in the right format
return Err(PsyParseError::UnknownError(byte_offset));
}
} else {
return Err(PsyParseError::MissingNode(
tree.byte_offset(),
"Expected a Color field in Emit SurfaceShader.",
));
};
arena.alloc(SimpleSurfaceShader::Emit { color: color })
}
"Lambert" => {
let color = if let Some((_, contents, byte_offset)) =
tree.iter_leaf_children_with_type("Color").nth(0)
@ -60,7 +83,84 @@ pub fn parse_surface_shader<'a>(
arena.alloc(SimpleSurfaceShader::Lambert { color: color })
}
"GTR" => unimplemented!(),
"GTR" => {
// Color
let color = if let Some((_, contents, byte_offset)) =
tree.iter_leaf_children_with_type("Color").nth(0)
{
if let IResult::Done(_, color) =
closure!(tuple!(ws_f32, ws_f32, ws_f32))(contents.as_bytes())
{
// TODO: handle color space conversions properly.
// Probably will need a special color type with its
// own parser...?
XYZ::from_tuple(rec709_e_to_xyz(color))
} else {
// Found color, but its contents is not in the right format
return Err(PsyParseError::UnknownError(byte_offset));
}
} else {
return Err(PsyParseError::MissingNode(
tree.byte_offset(),
"Expected a Color field in GTR SurfaceShader.",
));
};
// Roughness
let roughness = if let Some((_, contents, byte_offset)) =
tree.iter_leaf_children_with_type("Roughness").nth(0)
{
if let IResult::Done(_, roughness) = ws_f32(contents.as_bytes()) {
roughness
} else {
return Err(PsyParseError::UnknownError(byte_offset));
}
} else {
return Err(PsyParseError::MissingNode(
tree.byte_offset(),
"Expected a Roughness field in GTR SurfaceShader.",
));
};
// TailShape
let tail_shape = if let Some((_, contents, byte_offset)) =
tree.iter_leaf_children_with_type("TailShape").nth(0)
{
if let IResult::Done(_, tail_shape) = ws_f32(contents.as_bytes()) {
tail_shape
} else {
return Err(PsyParseError::UnknownError(byte_offset));
}
} else {
return Err(PsyParseError::MissingNode(
tree.byte_offset(),
"Expected a TailShape field in GTR SurfaceShader.",
));
};
// Fresnel
let fresnel = if let Some((_, contents, byte_offset)) =
tree.iter_leaf_children_with_type("Fresnel").nth(0)
{
if let IResult::Done(_, fresnel) = ws_f32(contents.as_bytes()) {
fresnel
} else {
return Err(PsyParseError::UnknownError(byte_offset));
}
} else {
return Err(PsyParseError::MissingNode(
tree.byte_offset(),
"Expected a Fresnel field in GTR SurfaceShader.",
));
};
arena.alloc(SimpleSurfaceShader::GTR {
color: color,
roughness: roughness,
tail_shape: tail_shape,
fresnel: fresnel,
})
}
_ => unimplemented!(),
};

View File

@ -7,7 +7,7 @@ use scene::{Assembly, Object, InstanceType};
use surface::SurfaceIntersection;
use transform_stack::TransformStack;
use shading::{SurfaceShader, SimpleSurfaceShader};
use color::XYZ;
use color::{XYZ, rec709_to_xyz};
pub struct Tracer<'a> {
@ -185,8 +185,9 @@ impl<'a> TracerInner<'a> {
) {
match *obj {
Object::Surface(surface) => {
let unassigned_shader =
SimpleSurfaceShader::Lambert { color: XYZ::new(1.0, 0.0, 1.0) };
let unassigned_shader = SimpleSurfaceShader::Lambert {
color: XYZ::from_tuple(rec709_to_xyz((1.0, 0.0, 1.0))),
};
let shader = surface_shader.unwrap_or(&unassigned_shader);
surface.intersect_rays(