經過Python控制Blender進行三維建模和效果渲染

分享點有意思的 Python 小技巧,幫助你將工做中的一部分交給計算機自動化運行,沒有程序經驗也能學會,否則就不叫小技巧了!node

關於渲染和合成流程

舉個栗子,咱們用 Gooseberry 項目的盡頭1.2.1爲例,這是由 Hjalti 製做的一個片斷blenderget-一些實用的Python小技巧-開發 -1python

感謝 Blender 的庫和連接系統,這可使得我在爲場景設計燈光等工做的同時,不受 Hjalti 對場景或人物作任何修改後的影響,我只須要從新更新一下個人 blend 文件,或者從新打開一次,已經在 SVN 上提交後的最新文件就會自動在個人場景文件中更新了。不過若是你不知道什麼是 SVN,我能夠試着去以前的開源電影博客中找找相似的介紹文章,不過你也能試試搜索一下,網上有不少關於 SVN 的介紹。不過到後面等 Lukas 完成了新的資源管理系統開發,這種協同方式可能會有所調整,不過將來還將來,咱們先看看如今能夠作些什麼吧。程序員

當咱們完成了高模場景、完整的光照設計、渲染須要的霧效或各類隨機生成的石塊等網格物體,還包含 Victor 和 Franck 的動做文件,他們在被連接至合成 .comp 文件以後,屬性都將被鎖定起來,僅能在源文件中編輯修改,可是當咱們在測試渲染時,須要臨時改動大量的屬性,就可能須要對各個物體進行單獨調整。個人意思 是,這一步你能夠手工完成,固然,也能夠靠腳原本批量化執行,很明顯這是腳本最能體現其價值和優點的地方啦!express

有了腳本,如下這些工做只須要動動鼠標按鍵就能夠了:apache

  • 開啓/關閉各種設置中的屬性開關app

  • 爲各種設置中的數值屬性從新賦值socket

  • 隱藏一些不須要顯示的粒子系統,或者修改他們的粒子樹和隨機因子(這些修改絕對不會影響源文件的設置)編輯器

  • 重寫 Victor 的一些關鍵屬性,例如將他的頭變大兩倍!ide

  • 刪除掉導入至視頻編輯器中的一些無用參考視頻(將來的 BAM 系統將不會調用這些未使用到的片斷,不過如今不行)wordpress

  • 開啓並添加一些渲染印章信息,包括採樣數、渲染時間和渲染農場的節點名稱等,通通都打印出來

  • 其實還有不少啦!

好吧,如今開始正題。

讓 Python 能自動運行

我接下來會在Blender 的文本編輯器中新建兩個文件,分別以下(Shift + F11):

  1. settings.py – 這個腳本將用於修改渲染設置、用戶參數,以及場景或視圖中可優化的屬性,單擊菜單上的 「Run Script」便可運行。

  2. startup.py – 這個腳本將用於修改粒子系統的顯示,以及一些渲染印章的信息,這個腳本在每次打開 .blend 文件後將自動運行(主要用於渲染農場),因此這個腳本必須開啓註冊選項,即 ‘Register’ 須要被選中

settings.py 能夠命名爲任意名稱,由於他是一個自行執行的文件,但 startup.py 必須以 .py 結尾,不然將沒法被執行註冊執行(實際上,只有當文件以 .py 結尾, 「Register」 選項纔會顯示爲可開啓的狀態,不然爲灰色)。

文章最後你能夠下載到完整的腳本。


這裏再加一個小提示,那就是 Pablo 的 Amaranth 腳本是一個至關不錯的生產優化插件,點擊這裏查看器完整的功能列表。我最喜歡的其中一個功能,就是場景的調試選項,能夠幫你找到丟失的貼圖等。Amaranth 能夠由你自行編譯,也能夠在 Blender 的自動編譯版本中下載。


好了,接下來咱們就分別看看這兩個腳本是如何編寫的。

settings.py:

1. 屬性的定義申明

我喜歡在腳本的前面將一些我經常使用的參數作一個定義並賦值,這樣在腳本中直接調用這些變量便可,而不是滿屏幕的處處找這些屬性而後分別修改參數。腳本的註釋以 # 開頭,因此隨便寫什麼都不會印象代碼的運行。

專業的腳本都會有一些註釋規範,不過這篇文章不是寫給程序員的,因此你們就隨意吧

  ____                      _                          
 / ___| ___   ___  ___  ___| |__   ___ _ __ _ __ _   _ 
| |  _ / _ \ / _ \/ __|/ _ \ '_ \ / _ \ '__| '__| | | |
| |_| | (_) | (_) \__ \  __/ |_) |  __/ |  | |  | |_| |
 \____|\___/ \___/|___/\___|_.__/ \___|_|  |_|   \__, |
                                                 |___/
##############################################################
#
#                                                                     SETTINGS
Samples = 50
Depth_of_field = 0.006

開頭的符號文字能夠在右側連接中生成: ASCII 生成器


2. 導入 Blender Python 並定義當前場景

腳本開頭要這麼寫就好了:

##############################################################
#
#                                                                        SCRIPT
import bpy
Scene = bpy.context.scene

3. 開啓簡化選項,設置細分數爲0,而後開啓 Amaranth 的非簡化渲染

咱們在本文中涉及到的大部分代碼和方法均可以在 Blender 的界面上找到,你只須要將鼠標移動到某個參數上面,就會看到下圖中得相似提示,雖然你看到的也許根本就不是最後實際調用的方法,但至少能夠給你一些編寫提示:

blenderget-一些實用的Python小技巧-開發 -2

接着單擊 Shift + F4 進入 Python 控制檯,而後敲入:bpy.data.sce… 並單擊組合鍵 CTRL + Space 來獲取代碼自動提示,再按一次進入下一個提示。若是要清除當前輸入,能夠單擊 Shift + Enter。咱們能夠試試 bpy.data.scenes[‘Scene’].render.use_simplify 而後再按回車,控制檯就會根據當前系統設置顯示出對應的結果,若是咱們但願對參數作出修改,能夠先單擊方向上鍵調出上一次輸入的代碼,而後在後面跟上 = True」 (或者是 1),回車後看看面板上參數的變化吧!

看到了吧,已經被腳本修改了,漂亮!

blenderget-一些實用的Python小技巧-開發 -3

這樣,咱們就已經大體找到了用腳本控制參數的方法,剩下的事情就簡單了,你只須要按照相似方式書寫便可:

Scene.render.use_simplify = True
Scene.render.simplify_subdivision = 0
Scene.use_unsimplify_render = True

完成編輯後,單擊 ‘Run Script’ 按鈕便可運行當前腳本,並且是批量執行的哦!

學會了吧,咱們繼續。


4. 切換渲染爲全屏,而且鎖定界面和後期處理計算

blenderget-一些實用的Python小技巧-開發 -4

# Render Display Mode:
Scene.render.display_mode = ‘SCREEN’
Scene.render.use_lock_interface = True
# Uncheck Post Processing:
Scene.render.use_compositing = False
Scene.render.use_sequencer = False

你能夠看到場景的命名 ‘SCREEN’ 實際上是你能夠手動在頁面佈局菜單上設置的,固然也可使用腳原本批量統一重命名,使用下面的命名能夠查看當前激活場景的名稱:

blenderget-一些實用的Python小技巧-開發 -5


5. 攝像機的參數修改

變量 Depth_of_field 在腳本的最開頭已經作了賦值,因此這裏直接調用便可。

# Camera settings:
Scene.camera.data.cycles.aperture_size = Depth_of_field
Scene.camera.data.cycles.aperture_ratio = 2
Scene.camera.data.show_name = True

6. 根據幀來添加採樣數

這裏的代碼是可使用腳原本爲渲染添加一個驅動,讓每一幀的採樣均可以不一樣(固然你能夠手動爲某一幀添加採樣因子)。

注意:這裏咱們假定場景中沒有其餘的渲染驅動(場景等級和角色的骨骼驅動不算),因此咱們使用的代碼是默認從0開始 Scene.animation_data.drivers[0],若是你場景中有現成的驅動,那麼就須要根據狀況增長驅動樹字,例如 Scene: [1], [2], 等等。

# Sampling seed to 「#frame」:
Scene.cycles.driver_add(‘seed’)
Scene.animation_data.drivers[0].driver.expression = ‘frame’

7. 圖片格式設置

我常用 JPEG 來保存個人測試渲染,可是在發送到渲染農場 Flamenco以後,我但願渲染輸出爲 PNG 格式。

# Output to JPEG 100% (for easy test render saving):
Scene.render.image_settings.file_format = ‘JPEG’
Scene.render.image_settings.quality = 100

8. 渲染印章設置

渲染的印章數據通常會被寫入到圖片的元數據中,因此咱們其實並不須要開啓渲染結果的印章顯示(但印章參數依然須要被激活)。在另一個 startup.py 腳本中,咱們再定義這些參數的輸出格式(例如渲染農場中的節點名稱,或者是採樣數等等)

若是你但願將這些參數打印出來,只須要激活 use_stamp 的值便可,參考閱讀 《如何配置渲染圖章的顯示

# Disable burned-in stamp:
Scene.render.use_stamp = False
# Enable needed stamp values for metadata:
Scene.render.use_stamp_time = True
Scene.render.use_stamp_date = True
Scene.render.use_stamp_render_time = True
Scene.render.use_stamp_frame = True
Scene.render.use_stamp_camera = True
Scene.render.use_stamp_lens = True
Scene.render.use_stamp_filename = True
Scene.render.use_stamp_marker = True
Scene.render.use_stamp_note = True

9. 關閉預覽範圍和照明設置

這些設置對咱們頗有用,但未必適合大家,例如在 Gooseberry 中得洗衣房場景中,洗衣機上有大量的反射材質,這在室內看上去效果很棒,可是若是場景切換至海島上,這些反光效果基本上不可能被注意到了,因此爲了節約資源咱們選擇關掉。

# Use Preview Range OFF:
Scene.use_preview_range = False
# Sampling:
Scene.cycles.samples = Samples
Scene.cycles.sample_clamp_direct = 11
Scene.cycles.sample_clamp_indirect = 5
Scene.cycles.volume_step_size = 1
Scene.cycles.volume_max_steps = 1024
# Light Paths:
Scene.cycles.transparent_max_bounces = 8
Scene.cycles.transparent_min_bounces = 8
Scene.cycles.max_bounces = 2
Scene.cycles.min_bounces = 1
Scene.cycles.diffuse_bounces = 2
Scene.cycles.glossy_bounces = 2
Scene.cycles.transmission_bounces = 2
Scene.cycles.volume_bounces = 1
Scene.cycles.caustics_reflective = False
Scene.cycles.caustics_refractive = False
Scene.cycles.blur_glossy = 2

10. 毛髮設置

這裏經過調整 Cycles 的毛髮細分參數來控制關聯的毛髮對象,而且設置是基於整個場景的,因此不會影響到導入的源文件自己。咱們能夠根據鏡頭來分別調整,讓他們在近景時看上去更茂密,可是在遠鏡頭的時候就適當減小細分等級,優化渲染時間。

# Hair settings:
Scene.cycles_curves[‘primitive’] = 2
Scene.cycles_curves.subdivisions = 4
Scene.cycles_curves[‘shape’] = 0

11. 最後,刪掉視頻編輯器上的這些片斷

我說實話我也不知道爲何他們會出如今這裏,由於一旦導入以後,就會自動加載到序列編輯器上,咱們須要手動進入全選而後刪除掉。這對於小文件來講沒 什麼,可是咱們須要將這些文件發送到渲染農場,那麼系統會將這些文件也一塊兒打包傳上去,那麼問題就大了,由於文件會增大不少,不事後面的 BAM 系統將優化這一塊的功能。

若是你但願完成更多功能的腳本,那麼我建議你能夠到問答社區 Blender Stack Exchange 中看看,或者找找你周圍有沒有相似 Pablo 這樣優秀脾氣又好的程序員幫忙吧。

# Remove Sequencer Strips:
class SequencerStripSlayer(bpy.types.Operator):
    「」」Delete All Strips」」」
    bl_idname = 「sequencer.strip_slayer」
    bl_label = 「Sequencer Strip Slayer」
    def execute(self, context):
        # Save which editor are we in when we run the operator
        where = bpy.context.area.type
        # Temporary switch to the Sequencer to get context data
        bpy.context.area.type = ‘SEQUENCE_EDITOR’
        # Build the context to override
        override = {
            「window」: bpy.context.window,
            「screen」: bpy.context.screen,
            「scene」: context.scene,
            「area」: bpy.context.area,
            「region」: bpy.context.area.regions[0],
            「blend_data」: context.blend_data}
        # Check if we have sequences at all
        if context.scene.sequence_editor and context.scene.sequence_editor.sequences_all:
            i = 0
            # loop through all the strips
            for s in context.scene.sequence_editor.sequences_all:
                # select them!
                s.select = True
                # this is just to count them (for the report message)
                i += 1
            # DIE DIE DIE!
            bpy.ops.sequencer.delete(override)
            # Report, if we have more than 0
            if i != 0:
                self.report({「INFO」}, 「BAM! {0} Strips Destroyed!」.format(i))
            else:
                self.report({「INFO」}, 「No strips to murder」)
        else:
            self.report({「INFO」}, 「No sequences」)
        # Go back to the area we were before
        bpy.context.area.type = where
        return {‘FINISHED’}

下面的代碼將做爲整個腳本的結尾,用於實現註冊,若是你要加什麼新功能,請務必加載如下代碼以前。

def register():
    bpy.utils.register_class(SequencerStripSlayer)
def unregister():
    bpy.utils.unregister_class(SequencerStripSlayer)
if __name__ == 「__main__」:
    register()
# Now actually run the operator. By commenting this line below, the delete operator will not run, but it will be registered. So you can find it via Space bar search and use it when needed.
bpy.ops.sequencer.strip_slayer()

 

startup.py:

1. 腳本前的定義和申明

##############################################################
#
#                                                                      SETTINGS
# Define some names to the stamp note:
Animator = ‘Hjalti’
Compositor = ‘Manu’

這裏的命名儘可能不要和選項中的名稱相同,不然你本身均可能分不出哪一個是變量哪一個是屬性了。


2. 導入 Python 和接口

##############################################################
#
#                                                                          SCRIPT
import bpy
import socket

接口主要用於檢測渲染結點的名稱,方便後面打印到元數據中。


3. 修改導入的粒子系統

肯定腳本中使用最佳參數的方法,就是在控制檯中一邊調,一邊在視圖中查看效果啦:

blenderget-一些實用的Python小技巧-開發 -6

你能夠看到,在這個例子中,咱們刻意向你展現了,若是粒子系統沒有作合理命名,那麼在腳本調用中,查找對應的粒子是多麼的痛苦。因此對於粒子的相關 設置,務必要有一個良好的命名規範,包括粒子的修改器等。將來若是粒子的系統引擎得意優化以後,整個粒子的調用應該會更簡單,不過這不是我說了算,仍是先 看看如今該怎麼作吧。

這個範例中的代碼並不是通用,而是徹底根據你的文件結構來實現,因此你也許還須要打開源文件來一一對比查找(在 Amaranth 中卻是十分的輕鬆,方法和以前 settings.py 中提到的相似。

# Particle systems:
bpy.data.objects[‘GEO-cliff_ground_high’].modifiers[‘ParticleSystem 3′].show_viewport = 1
bpy.data.particles[‘cliff_grass.001′].count = 12000
bpy.data.particles[‘cliff_grass.001′].hair_length = 200

如下代碼是用於關閉某些粒子系統的渲染輸出,以及修改一些粒子的隨機因子參數(其實就是用來調整效果啦):

bpy.data.objects[‘GEO-cliff_ground_high’].modifiers[‘ParticleSystem 3′].show_render = 0
bpy.data.objects[‘GEO-cliff_ground_high’].particle_systems[‘island_plants_small_dead’].seed = 16

4. 渲染印章的元數據輸出

下面你能夠找到用於自定義輸出渲染印章的元數據代碼,它們在 Blender 運行的開始就將收集所須要的信息,例如渲染節點的名稱。

另外,印章數據還能夠包含採樣數,攝像機的景深參數,Blender 的版本號以及誰在修改當前源文件(這個在腳本的開始已經作了定義)

當渲染啓動以後,你就可使用一個專用軟件來查看完整信息,我用的是  XnView MP 以及 ExifTool ,咱們的 gooseberry 項目團隊使用的有 nomacs Image Lounge (Win/Mac/Linux),在其 2.4.5 的開發版本中,其已經能夠完美支持 Blender 的 PNG 元數據查看啦!(點這裏下載 Nomacs 2.4.5 .deb installer for a 64-bit Ubuntu based OS – 但請記住,這不是一個穩定的版本哦!)

blenderget-一些實用的Python小技巧-開發 -7

你其實還能夠用 Blender 的圖片查看器來查看元數據。

# Stamp note script:
def stamp_set(scene):
    render = scene.render
    is_cycles = (render.engine == ‘CYCLES’)
    render.use_stamp_note = True
    render.stamp_note_text = (
        「Samples: {samples}  |  「
        「Aperture Radius: {aperture:.4f}  |  「
        「Blender {ver} {branch} {hash}  |  「
        「Animator: {anim}  |  「
        「Compositor: {comp}  |  「
        「Rendernode: {hostname}」
    ).format(
        samples=scene.cycles.samples if is_cycles else render.antialiasing_samples,
        aperture=scene.camera.data.cycles.aperture_size if is_cycles else 「NONE」,
        ver=bpy.app.version_string,
        branch=bpy.app.build_branch,
        hash=bpy.app.build_hash,
        hostname=socket.gethostname(),
        anim=Animator,
        comp=Compositor,
        )
bpy.app.handlers.render_pre.append(stamp_set)

5. 覆蓋掉一些數據

下面的腳本將覆蓋掉導入的某些參數,例如 Victor 的骨骼控制器。這裏將演示如何切換 Victor的頭髮粒子系統開關,讓其在載入時就直接關閉掉,不過其自己依然擁有以前開啓的動畫屬性。

# Override keyed PARTICLES_TOGGLE value:
from bpy.app.handlers import persistent
@persistent
def load_handler(dummy):
 bpy.data.objects[‘victor_high_proxy.001′].pose.bones[‘properties’][‘PARTICLES_TOGGLE’] = 0
bpy.app.handlers.render_pre.append(load_handler)

還有,你能夠靜默掉一些動畫通道,例如關閉攝像機的晃動曲線:

bpy.data.objects[‘camera’].animation_data.action.fcurves[0].mute = True
#(or False)

控制其餘通道只須要修改數字下標便可。

相關文章
相關標籤/搜索