material preview support
parent
40114792c9
commit
ada5d996a3
|
@ -49,6 +49,7 @@ protected:
|
|||
Float m_gamma, m_exposure;
|
||||
std::string m_toneMappingMethod;
|
||||
Float m_reinhardKey, m_reinhardBurn;
|
||||
int m_compressionRate;
|
||||
public:
|
||||
PNGFilm(const Properties &props) : Film(props) {
|
||||
m_pixels = new Pixel[m_cropSize.x * m_cropSize.y];
|
||||
|
@ -68,6 +69,8 @@ public:
|
|||
m_reinhardBurn = props.getFloat("reinhardBurn", 0.0f);
|
||||
/* Reinhard "key" parameter */
|
||||
m_reinhardKey = props.getFloat("reinhardKey", 0.18f);
|
||||
/* Compression rate (1=low, 9=high) */
|
||||
m_compressionRate = props.getInteger("compressionRate", 1);
|
||||
|
||||
if (m_toneMappingMethod != "gamma" && m_toneMappingMethod != "reinhard")
|
||||
Log(EError, "Unknown tone mapping method specified (must be 'gamma' or 'reinhard')");
|
||||
|
@ -95,6 +98,7 @@ public:
|
|||
m_reinhardKey = stream->readFloat();
|
||||
m_reinhardBurn = stream->readFloat();
|
||||
m_exposure = stream->readFloat();
|
||||
m_compressionRate = stream->readInt();
|
||||
m_gamma = 1.0f / m_gamma;
|
||||
m_pixels = new Pixel[m_cropSize.x * m_cropSize.y];
|
||||
}
|
||||
|
@ -109,6 +113,7 @@ public:
|
|||
stream->writeFloat(m_reinhardKey);
|
||||
stream->writeFloat(m_reinhardBurn);
|
||||
stream->writeFloat(m_exposure);
|
||||
stream->writeInt(m_compressionRate);
|
||||
}
|
||||
|
||||
virtual ~PNGFilm() {
|
||||
|
@ -403,7 +408,7 @@ public:
|
|||
Log(EInfo, "Writing image to \"%s\" ..", filename.leaf().c_str());
|
||||
ref<FileStream> stream = new FileStream(filename, FileStream::ETruncWrite);
|
||||
bitmap->setGamma(m_gamma);
|
||||
bitmap->save(Bitmap::EPNG, stream, 1);
|
||||
bitmap->save(Bitmap::EPNG, stream, m_compressionRate);
|
||||
}
|
||||
|
||||
bool destinationExists(const fs::path &baseName) const {
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
import os
|
||||
|
||||
bl_addon_info = {
|
||||
"name": "Mitsuba",
|
||||
"author": "Wenzel Jakob",
|
||||
|
@ -30,6 +32,8 @@ bl_addon_info = {
|
|||
"tracker_url": "https://www.mitsuba-renderer.org/bugtracker/projects/mitsuba",
|
||||
"category": "Render"}
|
||||
|
||||
def plugin_path():
|
||||
return os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
from .core import RENDERENGINE_mitsuba
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ from extensions_framework.engine import engine_base
|
|||
from extensions_framework import util as efutil
|
||||
|
||||
# Mitsuba-related classes
|
||||
from mitsuba import plugin_path
|
||||
from mitsuba.properties.engine import mitsuba_engine
|
||||
from mitsuba.properties.lamp import mitsuba_lamp
|
||||
from mitsuba.properties.texture import mitsuba_texture, \
|
||||
|
@ -41,6 +42,7 @@ from mitsuba.properties.material import mitsuba_material, \
|
|||
from mitsuba.operators import MITSUBA_OT_preset_engine_add, EXPORT_OT_mitsuba
|
||||
from mitsuba.outputs import MtsLog, MtsFilmDisplay
|
||||
from mitsuba.export.adjustments import MtsAdjustments
|
||||
from mitsuba.export import translate_id
|
||||
from mitsuba.export.film import resolution
|
||||
from mitsuba.export import get_instance_materials
|
||||
from mitsuba.ui import render_panels
|
||||
|
@ -133,13 +135,61 @@ class RENDERENGINE_mitsuba(bpy.types.RenderEngine, engine_base):
|
|||
return
|
||||
|
||||
tempdir = efutil.temp_directory()
|
||||
matpreview_file = os.path.join(tempdir, "matpreview_materials.xml")
|
||||
matfile = os.path.join(tempdir, "matpreview_materials.xml")
|
||||
output_file = os.path.join(tempdir, "matpreview.png")
|
||||
scene_file = os.path.join(os.path.join(plugin_path(),
|
||||
"matpreview"), "matpreview.xml")
|
||||
pm = likely_materials[0]
|
||||
adj = MtsAdjustments(matpreview_file, tempdir,
|
||||
adj = MtsAdjustments(matfile, tempdir,
|
||||
bpy.data.materials, bpy.data.textures)
|
||||
adj.writeHeader()
|
||||
adj.exportMaterial(pm)
|
||||
adj.writeFooter()
|
||||
(mts_path, tail) = os.path.split(bpy.path.abspath(scene.mitsuba_engine.binary_path))
|
||||
mitsuba_binary = os.path.join(mts_path, "mitsuba")
|
||||
env = copy.copy(os.environ)
|
||||
mts_render_libpath = os.path.join(mts_path, "src/librender")
|
||||
mts_core_libpath = os.path.join(mts_path, "src/libcore")
|
||||
mts_hw_libpath = os.path.join(mts_path, "src/libhw")
|
||||
env['LD_LIBRARY_PATH'] = mts_core_libpath + ":" + mts_render_libpath + ":" + mts_hw_libpath
|
||||
(width, height) = resolution(scene)
|
||||
refresh_interval = 1
|
||||
mitsuba_process = subprocess.Popen(
|
||||
[mitsuba_binary, '-r%i' % refresh_interval,
|
||||
'-o', output_file, '-Dmatfile=%s' % matfile,
|
||||
'-Dmatname=%s' % translate_id(pm.name),
|
||||
'-Dwidth=%i' % width,
|
||||
'-Dheight=%i' % height,
|
||||
'-q',
|
||||
'-o', output_file, scene_file],
|
||||
env = env,
|
||||
cwd = tempdir
|
||||
)
|
||||
framebuffer_thread = MtsFilmDisplay({
|
||||
'resolution': resolution(scene),
|
||||
'RE': self,
|
||||
'output_file': output_file
|
||||
})
|
||||
framebuffer_thread.set_kick_period(refresh_interval)
|
||||
framebuffer_thread.start()
|
||||
while mitsuba_process.poll() == None and not self.test_break():
|
||||
self.render_update_timer = threading.Timer(1, self.process_wait_timer)
|
||||
self.render_update_timer.start()
|
||||
if self.render_update_timer.isAlive(): self.render_update_timer.join()
|
||||
|
||||
# If we exit the wait loop (user cancelled) and mitsuba is still running, then send SIGINT
|
||||
if mitsuba_process.poll() == None:
|
||||
# Use SIGTERM because that's the only one supported on Windows
|
||||
mitsuba_process.send_signal(subprocess.signal.SIGTERM)
|
||||
|
||||
# Stop updating the render result and load the final image
|
||||
framebuffer_thread.stop()
|
||||
framebuffer_thread.join()
|
||||
|
||||
if mitsuba_process.poll() != None and mitsuba_process.returncode != 0:
|
||||
MtsLog("MtsBlend: Rendering failed -- check the console")
|
||||
else:
|
||||
framebuffer_thread.kick(render_end=True)
|
||||
|
||||
|
||||
def render(self, scene):
|
||||
|
@ -196,17 +246,18 @@ class RENDERENGINE_mitsuba(bpy.types.RenderEngine, engine_base):
|
|||
cwd = self.output_dir
|
||||
)
|
||||
elif scene.mitsuba_engine.render_mode == 'cli':
|
||||
self.output_file = efutil.export_path[:-4] + ".png"
|
||||
output_file = efutil.export_path[:-4] + ".png"
|
||||
|
||||
mitsuba_process = subprocess.Popen(
|
||||
[mitsuba_binary, '-r', '%d' % scene.mitsuba_engine.refresh_interval,
|
||||
'-o', self.output_file, efutil.export_path],
|
||||
'-o', output_file, efutil.export_path],
|
||||
env = env,
|
||||
cwd = self.output_dir
|
||||
)
|
||||
framebuffer_thread = MtsFilmDisplay({
|
||||
'resolution': resolution(scene),
|
||||
'RE': self,
|
||||
'output_file': output_file
|
||||
})
|
||||
framebuffer_thread.set_kick_period(scene.mitsuba_engine.refresh_interval)
|
||||
framebuffer_thread.start()
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,80 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="no" ?>
|
||||
<!--
|
||||
|
||||
Automatically converted from COLLADA
|
||||
|
||||
-->
|
||||
<scene>
|
||||
<integrator id="integrator" type="direct"/>
|
||||
<include filename="$matfile"/>
|
||||
|
||||
<camera id="Camera-camera" type="perspective">
|
||||
<float name="fov" value="28.8415"/>
|
||||
<boolean name="mapSmallerSide" value="true"/>
|
||||
|
||||
<transform name="toWorld">
|
||||
<matrix value="0.68588 -0.31737 -0.654862 3.69558 0.727634 0.312469 0.610666 -3.46243 -0.0108168 0.895343 -0.445245 3.25463 0 0 0 1"/>
|
||||
</transform>
|
||||
|
||||
<sampler type="ldsampler">
|
||||
<integer name="sampleCount" value="16"/>
|
||||
</sampler>
|
||||
|
||||
<film id="film" type="pngfilm">
|
||||
<integer name="width" value="$width"/>
|
||||
<integer name="height" value="$height"/>
|
||||
<boolean name="alpha" value="false"/>
|
||||
<boolean name="banner" value="false"/>
|
||||
<rfilter type="gaussian"/>
|
||||
</film>
|
||||
</camera>
|
||||
|
||||
<luminaire id="Area_002-light" type="envmap">
|
||||
<string name="filename" value="envmap.exr"/>
|
||||
<transform name="toWorld">
|
||||
<matrix value="-0.224951 -0.000001 -0.974370 0.000000 -0.974370 0.000000 0.224951 0.000000 0.000000 1.000000 -0.000001 8.870000 0.000000 0.000000 0.000000 1.000000 "/>
|
||||
</transform>
|
||||
<float name="intensityScale" value="1.540006"/>
|
||||
</luminaire>
|
||||
|
||||
<bsdf id="Material_001" type="lambertian">
|
||||
<rgb name="reflectance" value="0.5 0.5 0.5"/>
|
||||
</bsdf>
|
||||
|
||||
<texture id="Checkerboard_Texture" type="checkerboard">
|
||||
<rgb name="darkColor" value="0.20000000298 0.20000000298 0.20000000298"/>
|
||||
<rgb name="brightColor" value="0.40000000596 0.40000000596 0.40000000596"/>
|
||||
<float name="uscale" value="30.0"/>
|
||||
<float name="vscale" value="30.0"/>
|
||||
<float name="uoffset" value="0.0"/>
|
||||
<float name="voffset" value="0.0"/>
|
||||
</texture><bsdf id="Plane_Material" type="lambertian">
|
||||
<ref id="Checkerboard_Texture" name="reflectance"/>
|
||||
</bsdf><shape id="Interior-mesh_0" type="serialized">
|
||||
<string name="filename" value="matpreview.Scene.00010.serialized"/>
|
||||
<integer name="shapeIndex" value="0"/>
|
||||
<transform name="toWorld">
|
||||
<matrix value="1 0 0 0 0 1 0 0 0 0 1 0.0252155 0 0 0 1"/>
|
||||
</transform>
|
||||
<ref id="Material_001" name="bsdf"/>
|
||||
</shape>
|
||||
|
||||
<shape id="Exterior-mesh_0" type="serialized">
|
||||
<string name="filename" value="matpreview.Scene.00010.serialized"/>
|
||||
<integer name="shapeIndex" value="1"/>
|
||||
<transform name="toWorld">
|
||||
<matrix value="0.614046 0.614047 0 -1.78814e-07 -0.614047 0.614046 0 2.08616e-07 0 0 0.868393 1.02569 0 0 0 1"/>
|
||||
</transform>
|
||||
<ref id="$matname" name="bsdf"/>
|
||||
</shape>
|
||||
|
||||
<shape id="Plane-mesh_0" type="serialized">
|
||||
<string name="filename" value="matpreview.Scene.00010.serialized"/>
|
||||
<integer name="shapeIndex" value="2"/>
|
||||
<transform name="toWorld">
|
||||
<matrix value="20 0 0 -10 0 20 0 10 0 0 20 0 0 0 0 1"/>
|
||||
</transform>
|
||||
<ref id="Plane_Material" name="bsdf"/>
|
||||
</shape>
|
||||
|
||||
</scene>
|
|
@ -27,12 +27,12 @@ class MtsFilmDisplay(TimerThread):
|
|||
MtsLog('Updating render result %ix%i' % (xres,yres))
|
||||
|
||||
result = self.LocalStorage['RE'].begin_result(0, 0, int(xres), int(yres))
|
||||
if os.path.exists(self.LocalStorage['RE'].output_file):
|
||||
if os.path.exists(self.LocalStorage['output_file']):
|
||||
bpy.ops.ef.msg(msg_text='Updating RenderResult')
|
||||
lay = result.layers[0]
|
||||
lay.load_from_file(self.LocalStorage['RE'].output_file)
|
||||
lay.load_from_file(self.LocalStorage['output_file'])
|
||||
else:
|
||||
err_msg = 'ERROR: Could not load render result from %s' % self.LocalStorage['RE'].output_file
|
||||
err_msg = 'ERROR: Could not load render result from %s' % self.LocalStorage['output_file']
|
||||
MtsLog(err_msg)
|
||||
bpy.ops.ef.msg(msg_type='ERROR', msg_text=err_msg)
|
||||
self.LocalStorage['RE'].end_result(result)
|
||||
|
|
Loading…
Reference in New Issue