ライト
目次
陰と影
hgimg4のライトについて調べてみました。ライトでゲームの雰囲気が変わりますし、暗いダンジョンの探索や派手な演出などでもライトを使いたいですよね。
ライトを知る前に、まずはカゲについて理解しておく必要があります。 カゲは2種類に分けて取り扱います。陰(かげ、shade、シェード)と影(かげ、shadow、シャドウ)です。どちらも「カゲ」ですが明確な使い分けがされています。
陰と影を知ってワンランク上のデッサンへ
https://dessinlaboratory.com/shade/shadow01.html
物体表面の光があたっていな部分が陰で、 物体に光が遮られて地面に落ちている暗い部分の方を影と言います。 CG用語でも同様の使い分けが行われていて、カゲを作る仕組みもそれぞれ異なります。
そしてここからが重要です。 現在(HSP3.6、3.7β1、3.7β2)のhgimg4では、影(シャドウ)を作る機能がついていません。 ライトでは陰(シェード)を作る事ができますが、影はできません。
ライトの種類
hgimg4では3種類の光源を作成できます。
項目 | ディレクショナルライト | ポイントライト | スポットライト |
---|---|---|---|
機能 | 方向のみを持った光源 | 座標と影響範囲を持った光源 | 座標と方向、影響範囲を持った光源 |
説明 | 平行光。 無限遠に光源がある場合の光。光源が遠いと光はほぼ平行に降り注ぐ。ただし3D-CGの場合は「ほぼ」ではなく完全な平行です。 |
点光源。 光源が1点で、全方位に光を放射する。 |
指向性を持つ点光源。 点光源の光の放射を制限して、ある方向にだけ光を放射している。 |
現実での例 | 太陽光 | ロウソクなど | 球場、ステージのスポットライト、懐中電灯など |
GPU負荷 | 低 | 中 | 高 |
上限個数 | 1~10個(初期値1) | 0~10個(初期値0) | 0~10個(初期値0) |
備考 |
|
アンビエントカラー
アンビエントカラーは、環境光(アンビエントライト)とか呼ばれるものです。
現実においては、光が直接当たらない部分(影、陰)であっても真っ黒になることはありません。少し明るさがあります。 これは周囲のさまざまな物体や床や壁に当たった光が複雑に反射して、暗い部分に光を届けているためです。
光が届く経路は複雑で、反射は1回とは限らず複数反射していることもあります。 このように複雑な反射をCGの世界で正確に再現しようとすると計算時間が足りなくなってしまいます。 そこでCGでは、環境光という空間全体を照らす照明を使ってカゲが明るくなる現象を再現しています。
アンビエントカラーは、ディレクショナルライトに設定して使用します。 複数のディレクショナルライトを使用する場合は、カレントライトのライトオブジェクトのインデックス0番に指定した1つのアンビエントカラーだけが有効になります。 カタカナばっかりでわかりにくいですね。複数個準備できますが、実際に有効にできるアンビエントカラーは 1 個だけということです。
ディレクショナルライトのサンプル
ディレクショナルライトを使ったサンプルを作ってみました。
#include "hgimg4.as"
title "HGIMG4 Test"
; ディレクショナルライト
; ・光の方向を変える
; ・アンビエントカラー
;
gpreset
; ライト
;gpresetlight 1
setcls CLSMODE_SOLID, $404040 ; 背景色
setcolor GPOBJ_LIGHT, 0.3,0.3,0.3 ; 標準ライトカラーを設定
setang GPOBJ_LIGHT, deg2rad(-45)
; 標準アンビエントカラー
amb = 0.1
setdir GPOBJ_LIGHT, amb, amb, amb
; カメラ
setpos GPOBJ_CAMERA, 0,2 ,6 ; カメラ位置を設定
gplookat GPOBJ_CAMERA, 0,0.3,0 ; カメラから指定した座標を見る
; 3Dモデルを生成
; (生成される3Dモデルはカレントライトの影響を受けます)
gpbox id_model, 1 ; 箱ノードを生成する
setpos id_model, 0, 0.5, 0
setang id_model, 0, deg2rad(45)
gpfloor id_floor, 40,40, $808080 ; 床ノードを追加
*main
stick key,15+256
if key&128 : end
redraw 0 ; 描画開始
; サンプル
if 1 {
; ディレクショナルライト サンプル
; 光源の向きを回転
addang GPOBJ_LIGHT, 0, 0.02, 0
} else {
; アンビエントカラー サンプル
; アンビエントカラーをゆっくり変更
setdir GPOBJ_LIGHT, amb, 0, 0
amb += 0.005
if amb > 1.0 : amb = 0.0
}
gpdraw ; シーンの描画
color 255,255,255
pos 8,8:mes "HGIMG4 sample"
; アンビエントカラー
mes "アンビエントカラー:" + int(amb*255) + ", 0, 0"
redraw 1 ; 描画終了
await 1000/60 ; 待ち時間
goto *main
斜め上から当てているディレクショナルライトの向きをY軸中心に回転させています。 光源の初期の向きは -Z方向であるようです。
次のように修正すると、アンビエントカラーのサンプルになります。
; サンプル
; if 1 {
if 0 {
; ディレクショナルライト サンプル
; 光源の向きを回転
addang GPOBJ_LIGHT, 0, 0.02, 0
} else {
; アンビエントカラー サンプル
; アンビエントカラーをゆっくり変更
setdir GPOBJ_LIGHT, amb, 0, 0
amb += 0.005
if amb > 1.0 : amb = 0.0
}
空間全体を照らす赤い光(アンビエントカラー)を徐々に強くしています。 光があたっている部分や陰になっている部分など、場所にかかわらずアンビエントカラーの赤い光があたっています。ただし背景は影響を受けないようですね。
さらにこんなふうに書き換えると、アンビエントカラーがまったくない状態を確認できます。 まずディレクショナルライトのサンプルに戻して、上の方に書いてあるアンビエントカラーの設定を次のように書き換えます。
; 標準アンビエントカラー
amb = 0.0 ;0.1
setdir GPOBJ_LIGHT, amb, amb, amb
今までそれなりに明るかった陰の部分は真っ黒になります。アンビエントカラーの効果がよくわかると思います。
ライト作成手順
ライトはノードとは違って、作って配置すればいいというものではないようです。 基本的には次のような手順が必要です。
- シーンを作り始めたときに、使う個数を決める。
- カレントライトを作る。
- カレントライトをオブジェクトに関連付ける。
カレントライトは、実際に使用する1個以上のライトのセットです。 カレントライトに登録していないライトは使用されません。
シーン作成後に何もしなければ、ディレクショナルライト1個がカレントライトになり、この後作成されるすべてのノードオブジェクトに適用されます。 いつもライトを設定して無くても明るさがあったのは、前述の手順を自動でやってくれていたわけです。
ライトを増やしたりポイントライトを使ったりしたい場合は、上記の作業が必要になります。 もう少し細かく手順を見てみます。
- シーンを初期化するとライトの設定もデフォルト設定に戻ります。
- 使用するライトを初期化(
gpresetlight
)
使用するライトの個数を宣言します。 - ノードを作る(
gpnull
など) - ノードをライトに設定する(
gplight
) - 使いたいライトをカレントライトに登録(
gpuselight
)
この後にノードオブジェクトを作成すると、現在のカレントライトが適用されます。
ノードオブジェクトを作成した後にカレントライトを変更した場合は、setobjlight
でオブジェクトにカレントライトを再設定する必要があります。
サンプルで使い方を確認してみます。
#include "hgimg4.as"
title "HGIMG4 Test"
; カレントライト
;
gpreset
setcls CLSMODE_SOLID, $404040 ; 背景色
sdim comment, 64, 4
; --------------------
; ライト
; --------------------
gpresetlight 3
; 標準ライトカラーを設定
;setcolor GPOBJ_LIGHT, 0.8, 0.8, 0.8
; 白
gpnull LIGHT_W
gplight LIGHT_W, GPOBJ_LGTOPT_NORMAL
setcolor LIGHT_W, 0.8, 0.8, 0.8
setang LIGHT_W, deg2rad(-60), deg2rad(0)
; setdir LIGHT_W, 0, 0, 0
; 赤
gpnull LIGHT_R
gplight LIGHT_R, GPOBJ_LGTOPT_NORMAL
setcolor LIGHT_R, 0.8, 0, 0
setang LIGHT_R, deg2rad(-60), deg2rad(90)
; setdir LIGHT_R, 0, 0, 0
; 緑
gpnull LIGHT_G
gplight LIGHT_G, GPOBJ_LGTOPT_NORMAL
setcolor LIGHT_G, 0, 0.8, 0
setang LIGHT_G, deg2rad(-60), deg2rad(0)
; setdir LIGHT_G, 0, 0, 0
; 青
gpnull LIGHT_B
gplight LIGHT_B, GPOBJ_LGTOPT_NORMAL
setcolor LIGHT_B, 0, 0, 0.8
setang LIGHT_B, deg2rad(-60), deg2rad(-90)
; setdir LIGHT_B, 0, 0, 0
; 黒
gpnull LIGHT_BL
gplight LIGHT_BL, GPOBJ_LGTOPT_NORMAL
setcolor LIGHT_BL, 0, 0, 0
; setdir LIGHT_BL, 0, 0, 0
; 真っ黒
; アンビエントカラーも黒にする
gpnull LIGHT_BL2
gplight LIGHT_BL2, GPOBJ_LGTOPT_NORMAL
setcolor LIGHT_BL2, 0, 0, 0
setdir LIGHT_BL2, 0, 0, 0 ; アンビエントカラー
; --------------------
; カメラ
; --------------------
setpos GPOBJ_CAMERA, 0,2 ,7 ; カメラ位置を設定
gplookat GPOBJ_CAMERA, 0,0.3,0 ; カメラから指定した座標を見る
; --------------------
; 標準ライト
; --------------------
; 3Dモデルを生成
; (生成される3Dモデルはカレントライトの影響を受けます)
gpbox id_box, 1 ; 箱ノードを生成する
setpos id_box, -3, 0.5, 0
; setang id_box, 0, deg2rad(45)
; --------------------
; カレントライトを作った後にオブジェクトを作成
; --------------------
; 赤と青と緑
; ライトオブジェクトをカレントライトに登録
gpuselight LIGHT_R, 0
gpuselight LIGHT_G, 1
gpuselight LIGHT_B, 2
gpclone id_boxc(0), id_box
setpos id_boxc(0), -1.5, 0.5, 0
comment(0) = "赤\n緑\n青"
; --------------------
; カレントライトを変更後にオブジェクトを作成
; --------------------
; 赤と青
gpuselight LIGHT_R, 0
gpuselight LIGHT_BL, 1
gpuselight LIGHT_B, 2
gpclone id_boxc(1), id_box
setpos id_boxc(1), 0, 0.5, 0
comment(1) = "赤\n青"
; --------------------
; オブジェクト作成後にカレントライトを変更
; --------------------
; 緑と青
gpclone id_boxc(2), id_box
setpos id_boxc(2), 1.5, 0.5, 0
; ライトを適用
gpuselight LIGHT_BL, 0
gpuselight LIGHT_G, 1
gpuselight LIGHT_B, 2
setobjlight id_boxc(2)
comment(2) = "青\n緑"
; --------------------
; 真っ黒
; --------------------
; アンビエントカラーも黒
gpuselight LIGHT_BL2, 0 ; 個の色のアンビエントカラーが有効になる
gpuselight LIGHT_BL, 1 ; LIGHT_BL2でもいい
gpuselight LIGHT_BL, 2 ; LIGHT_BL2でもいい
gpclone id_boxc(3), id_box
setpos id_boxc(3), 3, 0.5, 0
comment(3) = "真っ黒"
; --------------------
; 床
; --------------------
; ライトの設定を元に戻したい。
; gpuselight GPOBJ_LIGHT, 0 ; エラー
gpuselight LIGHT_W, 0
gpuselight LIGHT_BL, 1
gpuselight LIGHT_BL, 2
gpfloor id_floor, 40,40, $808080 ; 床ノードを追加
; オブジェクトに適用後にライトの設定を変更
;setcolor LIGHT_BL2, 1, 1, 1
;setdir LIGHT_BL2, 0.2, 0.2, 0.2
;setang LIGHT_BL2, 0, deg2rad(45), deg2rad(60)
*main
stick key,15+256
if key&128 : end
redraw 0 ; 描画開始
; 箱を回転
addang id_box, 0, 0.02, 0
addang id_boxc(0), 0, 0.02, 0
addang id_boxc(1), 0, 0.02, 0
addang id_boxc(2), 0, 0.02, 0
addang id_boxc(3), 0, 0.02, 0
gpdraw ; シーンの描画
color 255,255,255
pos 8,8:mes "HGIMG4 sample"
; 説明を表示
color
getpos id_box, px, py, pz
gpcnvaxis vx, vy, vz, px, py, pz, 0
pos vx, vy+100
mes "標準ライト"
repeat 4
getpos id_boxc(cnt), px, py, pz
gpcnvaxis vx, vy, vz, px, py, pz, 0
pos vx, vy+100
mes comment(cnt)
loop
redraw 1 ; 描画終了
await 1000/60 ; 待ち時間
goto *main
実行すると箱が5つ表示されます。 箱はすべて同じ色で、それぞれ別々のカレントライトを適用しています。 ライトの色と方向を箱で確認することができるようになっています。
カレントライトに登録できるライトの上限数は、gpresetlight
命令で設定します。
gplight
で作成するライトの個数ではありません。
上限数がそれぞれ 10 個までとか少なすぎーとか思われるかもしれませんが、
ライトは負荷が高い処理です。個数制限はやむを得ません。
ライト作成手順サンプルの解説
最初にシーン内で使用するライトとして、ディレクショナルライトを3つ確保します。 ライトは負荷が高い部類の処理になるのだそうで、あまりたくさん設定することが出来ないような作りになっています。
gpresetlight 3
次に gpnull
, gplight
を使ってライトオブジェクトを作ります。
ライト色は、setcolor
命令でノードに設定された色がそのまま使用されます。
作成したライトの一覧表です。
オブジェクトID | 色 | アンビエントカラー |
---|---|---|
GPOBJ_LIGHT | 白(デフォルト) | デフォルト |
LIGHT_W | 白 | デフォルト |
LIGHT_R | 赤 | デフォルト |
LIGHT_G | 緑 | デフォルト |
LIGHT_B | 青 | デフォルト |
LIGHT_BL | 黒 | デフォルト |
LIGHT_BL2 | 黒 | 黒 |
サンプルの一番左の箱は、標準ライト(GPOBJ_LIGHT
)をそのまま使用しています。
左から2番目と3番目は、gpuselight
でカレントライトを新しく作った後にオブジェクトを作成しています。
2番目は3色の光、3番目は2色の光(3個中の1個のライトを黒にしている)を当てています。
; --------------------
; カレントライトを作った後にオブジェクトを作成
; --------------------
; 赤と青と緑
; ライトオブジェクトをカレントライトに登録
gpuselight LIGHT_R, 0
gpuselight LIGHT_G, 1
gpuselight LIGHT_B, 2
gpclone id_boxc(0), id_box
setpos id_boxc(0), -1.5, 0.5, 0
comment(0) = "赤\n緑\n青"
; --------------------
; カレントライトを変更後にオブジェクトを作成
; --------------------
; 赤と青
gpuselight LIGHT_R, 0
gpuselight LIGHT_BL, 1
gpuselight LIGHT_B, 2
gpclone id_boxc(1), id_box
setpos id_boxc(1), 0, 0.5, 0
comment(1) = "赤\n青"
左から4番目は、ノードオブジェクトを作成後にカレントライトを作成して適用しています。
setobjlight
命令でノードオブジェクトに現在のカレントライトを適用し直しています。
; --------------------
; オブジェクト作成後にカレントライトを変更
; --------------------
; 緑と青
gpclone id_boxc(2), id_box
setpos id_boxc(2), 1.5, 0.5, 0
; ライトを適用
gpuselight LIGHT_BL, 0
gpuselight LIGHT_G, 1
gpuselight LIGHT_B, 2
setobjlight id_boxc(2)
comment(2) = "青\n緑"
一番右は、アンビエントカラーの影響を確認しています。 「登録するライトオブジェクトのインデックス」を0にしたライトのアンビエントカラーが適用されるようです。
; --------------------
; 真っ黒
; --------------------
; アンビエントカラーも黒
gpuselight LIGHT_BL2, 0 ; 個の色のアンビエントカラーが有効になる
gpuselight LIGHT_BL, 1 ; LIGHT_BL2でもいい
gpuselight LIGHT_BL, 2 ; LIGHT_BL2でもいい
gpclone id_boxc(3), id_box
setpos id_boxc(3), 3, 0.5, 0
comment(3) = "真っ黒"
完全に真っ黒になりましたね。コナンの犯人もびっくりの黒さです。 うまく応用するとなにかに使えそうですね。何かはわかりませんが。
何だかわからなくなってきましたね。整理します。
左から | 0 | 1 | 2 |
---|---|---|---|
1番目 | GPOBJ_LIGHT | ||
2番目 | LIGHT_R | LIGHT_G | LIGHT_B |
2番目 | LIGHT_R | LIGHT_BL | LIGHT_B |
4番目 | LIGHT_BL | LIGHT_G | LIGHT_B |
5番目 | LIGHT_BL2 | LIGHT_BL | LIGHT_BL |
なお、オブジェクトにカレントライトを適用したあとでもライトの調整は可能です。 色や向き、アンビエントカラーが変更できます。 カレントライトの適用は、オブジェクトに適用するライトの割当を決める作業というイメージでよさそうですね。
; オブジェクトに適用後にライトの設定を変更
setcolor LIGHT_BL2, 1, 1, 1
setdir LIGHT_BL2, 0.2, 0.2, 0.2
setang LIGHT_BL2, 0, deg2rad(45), deg2rad(60)
サンプルではコメントにしているので、コメント解除していろいろ試してみてください。
ポイントライトのサンプル
ポイントライトは、点光源です。
作り方は基本的にディレクショナルライトと同じですが、gplight
命令で「range(1) : 影響範囲パラメーター」を指定できます。
この引数は、光が届く半径を指定する値です。この半径より遠い場所は、光が届きません。
光の届き具合や調整方法を確認するサンプルです。
#include "hgimg4.as"
title "HGIMG4 Test"
; ポイントライト
;
gpreset
; ライト
gpresetlight 1, 4
setcls CLSMODE_SOLID, $404040 ; 背景色
setcolor GPOBJ_LIGHT, 0,0,0 ; 標準ライトカラーを設定
; 標準アンビエントカラー
amb = 0.0 ; 数値を大きくするとノードオブジェクトの配置が見やすくなります。
setdir GPOBJ_LIGHT, amb, amb, amb
; カメラ
setpos GPOBJ_CAMERA, 0,2 ,6 ; カメラ位置を設定
gplookat GPOBJ_CAMERA, 0,0.3,0 ; カメラから指定した座標を見る
; ライトを生成
x = -2.0 , 0.0, 2.0 ; 配置
h = 0.05, 0.5, 0.5 ; 高さ
r = 0.5 , 0.5, 1.0 ; 影響半径
repeat 3
gpnull id_light(cnt)
gplight id_light(cnt), GPOBJ_LGTOPT_POINT, r(cnt)
setcolor id_light(cnt), 1, 1, 1
setpos id_light(cnt), x(cnt), h(cnt), 0.55
; 壁側面のすぐ近くに配置(ギリギリよりも少し離したほうが中心部が明るい)
gpuselight id_light(cnt), cnt
loop
; 箱を光源に設定
gpbox id_boxL, 0.2
;setcolor id_boxL, 1, 0.5, 0.5 ; setcolorはgplightの前に設定しても光の色にならない。
gplight id_boxL, GPOBJ_LGTOPT_POINT, 3
setpos id_boxL, 0, 2, 1
setcolor id_boxL, 1, 0.5, 0.5
setcolor id_boxL, 0, 0, 0 ; この行をコメントにすると光ります。
gpuselight id_boxL, 3
; 3Dモデルを生成
; 箱ノード(壁)を生成
gpbox id_box, 1
setscale id_box, 10, 1, 1
setpos id_box, 0, 0.5, 0
; 床ノードを追加
gpfloor id_floor, 40,40, $808080
*main
stick key,15+256
if key&128 : end
redraw 0 ; 描画開始
gpdraw ; シーンの描画
color 255,255,255
pos 8,8:mes "HGIMG4 sample"
redraw 1 ; 描画終了
await 1000/60 ; 待ち時間
goto *main
結果を確認しやすくするために、環境光をゼロにしています。 また光の確認と寸法の目印として高さ 1 の壁を設置しています。
はじめにライトの個数を指定します。 環境光を設定したいのでディレクショナルライト1個。 スポットライトは4個使います。
gpresetlight 1, 4
あとはディレクショナルライトを作るのとほぼ同じです。 あまり難しくはないですね。ちなみに光源の座標を壁の中に設定しても地面に光があたります。 違和感ありますがそういうものです。この光はオブジェクトを突き抜けて届く光です。影できませんしね。
さて光源はヌルノードに限らず、gpbox
で作った箱などのノードオブジェクトに設定できます。
といってもオブジェクト自身が光るのではなく、オブジェクトの中心座標に点光源が配置されるだけのようです。
; 箱を光源に設定
gpbox id_boxL, 0.2
;setcolor id_boxL, 1, 0.5, 0.5 ; setcolorはgplightの前に設定しても光の色にならない。
gplight id_boxL, GPOBJ_LGTOPT_POINT, 3
setpos id_boxL, 0, 2, 1
setcolor id_boxL, 1, 0.5, 0.5
; setcolor id_boxL, 0, 0, 0 ; この行をコメントにすると光ります。
gpuselight id_boxL, 3
黒い箱が赤い光を放っています。 箱の中心(内部)に光源があるだけで、箱表面は光っていません。
スポットライトのサンプル
スポットライトは…スポットライト状の光です。点光源の光の範囲を円すい状に制限したような感じのものです。
作り方はポイントライトとほぼ同じですが、gplight
命令で「inner(0.5): 内側の減衰パラメーター」と「outer(1) : 外側の減衰パラメーター」を指定できます。
この引数は、どちらも光の広がり角度を指定する値です。境界をぼやけた感じにするため、内側と外側でそれぞれ範囲角度を設定できるようになっています。
角度については後述するので、まずはサンプルで使い方を確認してみます。
#include "hgimg4.as"
title "HGIMG4 Test"
; スポットライト
;
gpreset
; ライト
gpresetlight 1, , 3
setcls CLSMODE_SOLID, $404040 ; 背景色
setcolor GPOBJ_LIGHT, 0,0,0 ; 標準ライトカラーを設定
; 標準アンビエントカラー
amb = 0.10 ; 数値を大きくするとノードオブジェクトの配置が見やすくなります。
setdir GPOBJ_LIGHT, amb, amb, amb
; カメラ
setpos GPOBJ_CAMERA, 0,2 ,6 ; カメラ位置を設定
gplookat GPOBJ_CAMERA, 0,0.3,0 ; カメラから指定した座標を見る
; ライトを生成
x = -2.0, 0.0, 2.0 ; 配置
h = 0.5, 1.0, 1.0 ; 高さ
r = 1.0, 1.0, 2.0 ; 影響半径
i = 0.5, 0.5, 0.5 ; 内側の減衰
o = 1.0, 1.0, 1.0 ; 外側の減衰
repeat 3
gpnull id_light(cnt)
gplight id_light(cnt), GPOBJ_LGTOPT_SPOT, r(cnt), i(cnt), o(cnt)
setcolor id_light(cnt), 1, 1, 1
setpos id_light(cnt), x(cnt), h(cnt), 0.55
; 壁側面のすぐ近くに配置(ギリギリよりも少し離したほうが中心部が明るい)
setang id_light(cnt), deg2rad(-90)
gpuselight id_light(cnt), cnt
loop
; 3Dモデルを生成
; 箱ノード(壁)を生成
gpbox id_box, 1
setscale id_box, 10, 2, 1
setpos id_box, 0, 1.0, 0
; 床ノードを追加
gpfloor id_floor, 40,40, $808080
*main
stick key,15+256
if key&128 : end
redraw 0 ; 描画開始
gpdraw ; シーンの描画
color 255,255,255
pos 8,8:mes "HGIMG4 sample"
redraw 1 ; 描画終了
await 1000/60 ; 待ち時間
goto *main
壁際にスポットライトを設置しています。それぞれ設置位置と、影響の半径を変えたものを並べています。 スポットライトの照射方向は -Z 方向を向いているようなので、X軸方向に -90 度回転させて照射方向を下に向けています。
setang id_light(cnt), deg2rad(-90)
あとはうまく調整してください。
スポットライトの調整
うまく調整と言っても、パラメーターの意味が不明瞭では困りますね。
gplight
命令でスポットライト作成する際のパラメーターを図にしてみました。
- range(1) : 影響範囲パラメーター
- 光が届く距離。光源からの距離(半径)で指定する。
- inner(0.5): 内側の減衰パラメーター
- 扇形の開き角度を中央からの角度で指定する。単位はラジアン。πのとき全方向、π/2のとき半分。 この角の内側では光の強さは変わらない。この角度より外側に行くほど光が弱くなる。
- outer(1) : 外側の減衰パラメーター
- 扇形の開き角度を中央からの角度で指定する。単位はラジアン。πのとき全方向、π/2のとき半分。 この角度の外側に光は届かない。
動作を確認するためのサンプルです。 ←,→で調整する項目を選択して、↑,↓で数値調整してください。 最初は「影響範囲」を大きくして光を床面に十分届かせてから、他のパラメーターを変更した方がいいでしょう。
#include "hgimg4.as"
title "HGIMG4 Test"
; ポイントライト
; ←,→で調整する項目を選択
; ↑,↓で数値調整
;
gpreset
; ライト
gpresetlight 1, , 1
setcls CLSMODE_SOLID, $404040 ; 背景色
setcolor GPOBJ_LIGHT, 0,0,0 ; 標準ライトカラーを設定
; 標準アンビエントカラー
amb = 0.10 ; 数値を大きくするとノードオブジェクトの配置が見やすくなります。
setdir GPOBJ_LIGHT, amb, amb, amb
; カメラ
setpos GPOBJ_CAMERA, 0,2 ,6 ; カメラ位置を設定
gplookat GPOBJ_CAMERA, 0,0.3,0 ; カメラから指定した座標を見る
; ライトを生成
gpnull id_light
gplight id_light, GPOBJ_LGTOPT_SPOT
setcolor id_light, 1, 1, 1
setpos id_light, 0.0, 1.5, 0.55
setang id_light, deg2rad(-90)
gpuselight id_light, 0
; 3Dモデルを生成
; 箱ノード(壁)を生成
gpbox id_box, 1
setscale id_box, 10, 2, 1
setpos id_box, 0, 1.0, 0
; 床ノードを追加
; gpfloorで作ったオブジェクトは、setobjlightに使用できないようです。
; gpfloor id_floor, 40,40, $808080
gpbox id_floor, 1, $808080
setscale id_floor, 10.0, 0.1, 10.0
setpos id_floor, 0, 0.05, 0
; パラメータ
range = 1.0 ; 影響範囲
inner = 0.5 ; 内側の減衰
outer = 1.0 ; 外側の減衰
select = 0
mode = "", "", "", ""
*main
stick key,2+8+256
if key&128 : end
; 選択
; ←,→で調整する項目を選択
if key & 1 : select-- ;←
if key & 4 : select++ ;→
if select > 3 : select = 0
if select < 0 : select = 3
mode = "", "", "", ""
mode(select) = "←"
; 数値調整
; ↑,↓で数値調整
v = 0.0
if key & 2 : v = 0.01 ;↑
if key & 8 : v = -0.01 ;↓
if select = 0 : range += v
if select = 1 : inner += v
if select = 2 : outer += v
if select = 3 {
; 内側の減衰と外側の減衰を同じ比率で調整
; z = outer / inner
; inner += v
; outer = inner * z
; 内側の減衰と外側の減衰の差を維持したまま調整
z = outer - inner
inner += v
outer = inner + z
}
redraw 0 ; 描画開始
; スポットライトを再設定
gplight id_light, GPOBJ_LGTOPT_SPOT, range, inner, outer
gpuselight id_light, 0
setobjlight id_box
setobjlight id_floor
gpdraw ; シーンの描画
color 255,255,255
pos 8,8:mes "HGIMG4 sample"
mes "←,→キーで数値を変更する項目を選んでください。\n↑,↓キーで数値を変更できます。\r\n"
mes "影響範囲 :" + range + " " + mode(0)
mes "内側の減衰:" + inner + " " + mode(1)
mes "外側の減衰:" + outer + " " + mode(2)
mes "内外連動 " + mode(3)
redraw 1 ; 描画終了
await 1000/60 ; 待ち時間
goto *main
内側と外側の減衰の値が逆転すると、光る範囲が反転しておもしろいですね。 数値をマイナスや3.14を超える値にしてみて動きを確認してみてください。 また「内外連動」は、内側と外側の減衰の値の差を維持したまま同時に変更します。
変更したパラメーターは、gplight
で再設定します。
gplight
で変更してしまうと、カレントライトに登録し直してsetobjlight
でオブジェクトに再設定するまで変更結果が反映されません。
; スポットライトを再設定
gplight id_light, GPOBJ_LGTOPT_SPOT, range, inner, outer
gpuselight id_light, 0
setobjlight id_box
setobjlight id_floor
そしてここで注意点。
gpfloor
で作成したオブジェクトは、setobjlight
に使用できないようです。(バグかな?)
このサンプルでは、gpbox
で床を作って代用しています。
まとめ
ライトの種類
ディレクショナルライト | 平行光 |
ポイントライト | 点光源 |
スポットライト | 指向性をもたせた点光源 |
カレントライトに登録できる個数には制限があります。上手に節約して使いましょう。
ライトの作り方
gpreset
でシーンをリセットするとライトもリセットされるgpresetlight
で個数を指定- ライトにするノードを作る(ヌルノード、箱ノードなど)
gplight
でノードをライトにするgpuselight
でカレントライトを設定する。カレントライトには、gpresetlight
で指定した個数のライトが設定できる。- ノードを作るとカレントライトの影響を受けるノードになる。
すでにノードを作成済みなら、
setobjlight
で新しいカレントライトをノードに適用する。
こんな感じでしょうか。カレントライトの取り扱いが少し難しいですね。 しかしノードオブジェクトごとにまったく違う光を当てたりできるので、うまく使うとおもしろい効果が得られそうな気もします。 例えば…影とか?