LoginSignup
12
5

前のフレームのカメラ行列を使用した残像効果

Posted at

単純な残像効果ですが

昔から好きで多用しています。

output.gif

要するに

前のフレームのカメラ行列をシェーダに渡しているのですが、今回はGodotでの実装例を紹介します。

まずはGDScriptで

前回のカメラ座標を格納しておきます。この処理は最後に実行するようにします。

	self._prev_camera_transform = main_camera.get_camera_transform()

前のフレームで格納しておいたこの transform を Vector4 の配列に格納します。

func _process(delta:float) -> void:
	var prev_matrix:Array = [ Vector4(1, 0, 0, 0), Vector4(0, 1, 0, 0), Vector4(0, 0, 1, 0), Vector4(0, 0, 0, 1), ]
	var camera_transform_inverse := self._prev_camera_transform.inverse()
	var rot = camera_transform_inverse.basis
	var origin = camera_transform_inverse.origin;
	prev_matrix[0] = Vector4(rot.x.x, rot.x.y, rot.x.z, 0.0)
	prev_matrix[1] = Vector4(rot.y.x, rot.y.y, rot.y.z, 0.0)
	prev_matrix[2] = Vector4(rot.z.x, rot.z.y, rot.z.z, 0.0)
	prev_matrix[3] = Vector4(origin.x, origin.y, origin.z, 1.0)
	_material.set_shader_parameter("prev_matrix", prev_matrix)

次にシェーダ

shader_type spatial;
render_mode cull_disabled, blend_add, depth_draw_never, unshaded, specular_disabled, shadows_disabled, ambient_light_disabled, skip_vertex_transform;
uniform vec4 prev_matrix[4];

void vertex()
{
	mat4 prev_view;
	prev_view[0] = prev_matrix[0];
	prev_view[1] = prev_matrix[1];
	prev_view[2] = prev_matrix[2];
	prev_view[3] = prev_matrix[3];
	float elapsed_time = COLOR.a;
	float velocity = 8.0;
	vec4 p = MODEL_MATRIX * vec4(VERTEX + NORMAL*elapsed_time*velocity, 1);
    VERTEX = VERTEX_ID%2 != 0 ? (VIEW_MATRIX * p).xyz : (prev_view * p).xyz;
	COLOR.a = VERTEX_ID%2 != 0 ? 1.0 : 0.0;
}

void fragment()
{
	ALBEDO = COLOR.rgb;
	ALPHA = COLOR.a;
}

VERTEX =
の行で、VERTEX_ID がどちらかで通常の行列か、ひとつ前の行列かを切り替えます。 mesh topology を line に設定したモデルを渡しているので、扱う頂点は2つだけなので。

そんな小ネタでした

Advent Calendar がちょっと「弾幕薄いぞ」のように見えたので、援護射撃をば。

12
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
5