難しいことではないんですがUIが変わったせいで見つけるのが大変
[Render]→[RenderEngine]→Cyclesを設定
名前がNode EditorからShader Editorに変更されました。
デフォルトで"Principled BSDF"が適用されています。
[Shift+A]のショートカットキーは健在なので、ノードを追加出来ます。
デフォルトでResolutionが100%になっているのでマシンスペックの低い人は注意してください。
SamplingのFinal↔Previewを変更するのは[Render]→[Sampling]のアイコンをクリックします。
注意 バグなのか仕様なのかはわからないけれど"Preview"とか"Final"をクリックした瞬間変わらないで、マウスを選択肢の外に出して一覧が消えた後で変わります。
実行は今までと同じようにRenderメニューからRender Imageを選択します。
レンダリングを開始するとレンダリング用のウィンドウが出ます。このウィンドウを消すとレンダリングが中断出来ます。
結果の確認はRenderingタブから。
保存は[Shift+S]でできます。
わからなくなったら[F3]を押してSaveとかそれっぽい単語を打ち込むと機能が出てくるかもしれません。
Blender 2.8からレイヤー機能がなくなり、Collection機能を使うことになります。
画面右上にあるアイコンからもCollectionの表示を切り替えられます
ショートカットキーは [Ctrl+H]です。
全てのCollectionを表示するショートカットキーは[Alt+H]です。ただし、私がやったときはアウトライナーウィンドウにマウスが置かれていないと動きませんでした。仕様かバグかはよくわかりません。
調べたところ、旧UIに戻す方法はないそうです。
最も混乱するところは、マウスの左ボタンでオブジェクトを選択します。
そしてショートカットキーがだいぶ変わっています。新たな機能、なくなった機能もあり気持ちはわかりますが覚え直しです。
あと全体的にレイアウトというより思想がだいぶ変わってるので違いを挙げるのは大変です(多すぎる)
続く・・・
ツリー構造を作っていた時にできた副産物です。改善の余地はありますが楽です。
case WM_CREATE: { menu_t::SetDefaultMII(); MyMenu m; m.root().set( L"Menu",0);//メニューのルート。表示されない m.root().push(L"File",100);// push(タイトル, ID)の順に記述 m.root().latest().push(L"Load" ,110);//latestはこの階層で最後にpushされたアイテム m.root().latest().push(L"Save" ,120); m.root().latest().push(L"Export",130); m.root().latest().push(L"Import",140); m.root().latest().push(L"Recent",150); m.root().latest().latest().push(L"file1",151); m.root().latest().latest().push(L"file2",152); m.root().latest().latest().push(L"file3",153); m.root().push(L"Edit",200); m.root().latest().push(L"Add" ,210); m.root().latest().push(L"Delete",220); m.root().latest().push(L"Select",230); m.root().push(L"View",300); m.root().latest().push(L"Vertical" ,310); m.root().latest().push(L"Horizonal",320); m.winSetMenu(hwnd); } return 0; case WM_COMMAND://メニューがクリックされた時の処理 switch (LOWORD(wp)) { case 110: MessageBox(hwnd,L"Load",0,0); break; case 120: MessageBox(hwnd,L"Save",0,0); break; } break;
#include <vector> #include<windows.h> struct menu_t{ static MENUITEMINFO defaultMII; MENUITEMINFO mii; std::vector< menu_t > m_submenues; HMENU hmenu_this; menu_t(){} menu_t(wchar_t* title,UINT id,MENUITEMINFO _mii = defaultMII);
//このメニュー項目を設定 void set( wchar_t* title,UINT id,MENUITEMINFO _mii = defaultMII);
//このメニュー項目にサブメニューの項目を追加 void push(wchar_t* title,UINT id,MENUITEMINFO _mii = defaultMII);
//このメニュー項目のサブメニューの末尾を取得 menu_t& latest(); static void SetDefaultMII(); }; //メニュー管理クラス class MyMenu{ menu_t m_root; HMENU hMenuTop;
//メニュー登録のエントリポイント。内部でSetMenuesを呼び出す HMENU defineMenu();
//登録作業の本体。InsertMenuItemを呼び出している void SetMenues(HMENU hmenu , menu_t& menu); public: menu_t& root(); MyMenu();
//Win32apiのSetMenuを呼び出し、実際にメニューを登録する BOOL winSetMenu(HWND hwnd); };
#include "nuWinMenu.h" MENUITEMINFO menu_t::defaultMII; menu_t::menu_t(wchar_t* title,UINT id,MENUITEMINFO _mii){ set(title,id,_mii); } void menu_t::set( wchar_t* title,UINT id,MENUITEMINFO _mii){
//このメニュー項目のタイトルとIDを設定 mii = _mii; mii.fMask = MIIM_ID | MIIM_STRING; mii.wID = id; mii.dwTypeData = title; } void menu_t::push(wchar_t* title,UINT id,MENUITEMINFO _mii){
//このメニュー項目のサブメニューにアイテムを追加 m_submenues.emplace_back(title,id,_mii); } menu_t& menu_t::latest(){
//このメニュー項目に最後に追加されたサブメニュー項目を取得 return m_submenues.back(); } void menu_t::SetDefaultMII(){ memset(&defaultMII, 0, sizeof(MENUITEMINFO)); defaultMII.cbSize = sizeof(MENUITEMINFO); defaultMII.fMask = MIIM_ID | MIIM_STRING; } ///////////////////////////////////////////////////////// HMENU MyMenu::defineMenu(){ hMenuTop = CreateMenu();//メニュー作成 for(size_t i = 0; i < m_root.m_submenues.size();i++){
//トップレベルのメニュー項目を登録する SetMenues(hMenuTop,m_root.m_submenues[i]); } m_root.hmenu_this = hMenuTop; return hMenuTop; } void MyMenu::SetMenues(HMENU hmenu , menu_t& menu){ if(menu.m_submenues.size()!=0){ HMENU submenu = CreatePopupMenu();//ポップアップメニュー作成 menu.mii.hSubMenu = submenu; menu.mii.fMask |= MIIM_SUBMENU;//この項目にサブメニューがあることを指示 InsertMenuItem(hmenu, menu.mii.wID, FALSE, &menu.mii);
//サブメニューの各項目を登録 for(size_t i = 0; i < menu.m_submenues.size();i++){ SetMenues(submenu,menu.m_submenues[i]); } } else{ InsertMenuItem(hmenu, menu.mii.wID, FALSE, &menu.mii); } menu.hmenu_this = hmenu; } menu_t& MyMenu::root(){ return m_root; } MyMenu::MyMenu(){ hMenuTop = 0; } BOOL MyMenu::winSetMenu(HWND hwnd){ return SetMenu( hwnd,defineMenu() ); }
#include <Windows.h> #include <tchar.h> struct rgb_t { unsigned char r; unsigned char g; unsigned char b; rgb_t(unsigned char R, unsigned char G, unsigned char B) :b(B), g(G), r(R) {} static const rgb_t White; static const rgb_t Black; }; void createDIBsection24( HBITMAP* hBitmap, HDC* hMemDC, BITMAPINFO* bmpInfo, rgb_t** m_lpPixel, LONG width, LONG height); void deleteDIBsection24(HDC hMemDC, HBITMAP hBitmap);
#include "dibsection.h" void createDIBsection24( HBITMAP* hBitmap, HDC* hMemDC, BITMAPINFO* bmpInfo, rgb_t** m_lpPixel, LONG width, LONG height) { //DIBの情報を設定する bmpInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmpInfo->bmiHeader.biWidth = width; bmpInfo->bmiHeader.biHeight = -height; //-を指定しないと上下逆になる bmpInfo->bmiHeader.biPlanes = 1; bmpInfo->bmiHeader.biBitCount = 24; bmpInfo->bmiHeader.biCompression = BI_RGB; HDC hdc = CreateDC(_T("DISPLAY"), 0, 0, 0); *hBitmap = CreateDIBSection(hdc, bmpInfo, DIB_RGB_COLORS, (void**)m_lpPixel, NULL, 0); *hMemDC = CreateCompatibleDC(hdc); DeleteDC(hdc); SelectObject(*hMemDC, *hBitmap); } void deleteDIBsection24(HDC hMemDC, HBITMAP hBitmap) { DeleteDC(hMemDC); DeleteObject(hBitmap); }
#include <Windows.h> void initGL(HGLRC *hRC,HDC hdc); bool DeInitGL(HGLRC hRC, HDC hdc);
ウィンドウに書き込む場合、PIXELFORMATDESCRIPTORのdwFlagsは:
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER
のようになるが、DIBに書き込む場合はPFD_DRAW_TO_WINDOWの代わりにPFD_DRAW_TO_BITMAPを使い、かつ、PFD_SUPPORT_GDIを使う。
#include "wingl.h" #include <Windows.h> void initGL(HGLRC *hRC, HDC hdc) { static PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_BITMAP | PFD_SUPPORT_GDI | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, PFD_TYPE_RGBA, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, //Z-Buffer 0, //Stencil Buffer 0, PFD_MAIN_PLANE, 0, //Reserved 0, 0, 0 }; SetPixelFormat(hdc, ChoosePixelFormat(hdc, &pfd), &pfd); *hRC = wglCreateContext(hdc); //レンダリングコンテキストの作成 wglMakeCurrent(hdc, *hRC); //hRCを有効にする } bool DeInitGL(HGLRC hRC, HDC hdc) { //解放コード wglMakeCurrent(hdc, hRC); //元に戻してやる wglDeleteContext(hRC); //いらなくなったレンダリングコンテキストの破棄 return true; }
HBITMAP dib_hBitmap; HDC dib_hMemDC; BITMAPINFO dib_bmpInf rgb_t* dib_lpPixel;
HGLRC wgl_hRC;
switch (msg) { case WM_CREATE: { //DIB Sectionを作成(24Bit) createDIBsection24( &dib_hBitmap, &dib_hMemDC, &dib_bmpInfo, &dib_lpPixel, width, height); //OpenGL初期化 initGL(&wgl_hRC, dib_hMemDC); draw(); break; }
case WM_PAINT: { // 画像を表示 PAINTSTRUCT ps; HDC hDC = BeginPaint(hwnd, &ps); BitBlt(hDC, 0, 0, width, height, dib_hMemDC, 0, 0, SRCCOPY); EndPaint(hwnd, &ps); break; } case WM_LBUTTONDOWN: //マウスをクリックしたら画像を更新して描画要求を出す draw(); InvalidateRect(hwnd, nullptr, FALSE); break;
void draw() { static int r = 0; wglMakeCurrent(dib_hMemDC, wgl_hRC); glClearColor(0, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT); glLoadIdentity(); glRotated(r += 10, 0, 1, 0); glBegin(GL_QUADS); glColor3d(1, 0, 0); glVertex3d(-0.7, -0.7, 0); glColor3d(0, 1, 0); glVertex3d(-0.7, 0.7, 0); glColor3d(0, 0, 1); glVertex3d(0.7, 0.7, 0); glColor3d(1, 1, 1); glVertex3d(0.7, -0.7, 0); glEnd(); glFlush(); SwapBuffers(dib_hMemDC); wglMakeCurrent(dib_hMemDC, 0); }
Step 4 - Rendering and Exporting [ 9:26~ ]
SmokeのFlowになっているオブジェクトを選択し、[Object]-[Cycles Settings]-[Ray Visibility]-Cameraのチェックを外す。これをしないとレンダリング結果に表示される。
加えて、ドメインの[Border Collisions]をCollide Allに設定する。これを設定しないとSmokeがDomainの外に出てしまってアニメーションとして面白みがなくなる。
Step 5 - Post Production in After Effects [12:17~ ]
以降はBlenderではなくAfter Effectsに入るので省略する。
Blender CyclesでSmokeのチュートリアルを試す (1)
Blender CyclesでSmokeのチュートリアルを試す (2)
Viewport ShadingをRenderedにする。ただし、表示が遅くなるため画面を1/4にする。
光源がレンダリングされないように、
[Object]-[Cycles Settings]-[Ray Visibility]-Cameraのチェックを外す
Blender CyclesでSmokeのチュートリアルを試す (1)
Blender CyclesでSmokeのチュートリアルを試す (2)
Cubeを選択し、Editモードへ行く。[W]→Subdivide Smoothを実行し、より自然な形状にする。
Temp. Diffを-1.0に設定する。環境との温度差が逆となり、煙が下に流れるようになる。
キーフレームにColorを指定することで、複雑な色のSmokeを作成出来る。
Blender CyclesでSmokeのチュートリアルを試す (1)
Blender CyclesでSmokeのチュートリアルを試す (2)
Blender CyclesでSmokeのチュートリアルを試す (3)
Blender CyclesでSmokeのチュートリアルを試す (4)
Smoke Simulation Tutorial - Blender Cycles
キューブを選択し、[Object]-[Quick Effects]-Quick Smokeを選択する。
Smokeの精度を上げるため、[Physics]→[Smoke]→[Domain]→[Resolution]→Divisionsを90など大きい値にする。
Divisionsを上げると表示が遅くなる。Smoke Adaptive Domainをチェックすると、計算範囲を限定しシミュレーションの速度が上がる。
Smokeのsubdivision modifierを Smoke High Resolutionという。
また、WaveletというノイズのStrengthのパラメータを0にしておく。
Blender CyclesでSmokeのチュートリアルを試す (1)
Blender CyclesでSmokeのチュートリアルを試す (2)
Blender Modelling Tutorial-DNA Helix
6:43のシンプルなチュートリアルですがDNAは需要多いのではないかと思います。
Addモディファイアを追加し、
Editモードへ行き、[A]で全選択。Remove Doubles で重複点を削除する
さらにObjectモードでX軸で90度回転する。最後に、適当な大きさに縮小しておく。
Editモードへ行き、一番下の段の、中央の点を選択し、[Shift+S]→Cursor to Selected で3Dカーソルを移動する。
先ほど指定した3Dカーソルの位置で、[Shift+A]→[Empty]→Plain Axisを追加
SimpleDeformモディファイアを追加し、Twistを選択、Axis,Originに追加したEmptyを設定、Angleに360を設定する。(動画ではFactorを10に設定している)
最後に、Editモードへ行き、[S]+[X]でX方向に伸ばす。