投稿者 tel | 2013年3月18日

WebGLでフラットシェーディング

WebGLの拡張機能のOES_standard_derivativesについて調べていたら下記のサイトにフラットシェーディングする例があったので試してみた。

http://athile.net/library/blog/?p=970

フラットシェーディング

フラットシェーディングとはポリゴンの面が一様に同じ色でシェーディングされる方法。一様な色にするにはポリゴンの各頂点で法線がすべて同じ方向を向いていないといけない。

フラットシェーディングでなくても、立方体のように法線が1つのポリゴンですべて同じ方向を向いていて欲しい場合がある。立方体ではこのような法線をもたせるために、24頂点(各面に4頂点*6面)用意する必要がある。

OES_standard_derivativesの拡張機能を使うとフラグメントシェーダで勾配を計算するdFdxとdFdyが使えるようになる。これらをつかって法線をフラグメントシェーダで計算すれば、たくさんの頂点を用意することなくフラットシェーディングできる。

WebGLの拡張機能を有効にする

WebGLで拡張機能を有効にするにはglのコンテキストのメソッドのgetExtensionを使う。

if(!gl.getExtension('OES_standard_derivatives')) {
    throw 'extension not support';
}

返り値がnullの場合、その拡張機能は使えない。またフラグメントシェーダにマクロを書く必要がある。

#extension GL_OES_standard_derivatives : enable

MDNを見ながらやっていたけどどうやらGoogle Chromeだと上記のコードがなくても動いた。

WeGLの拡張機能一覧は以下のサイトに載っていた。

http://www.khronos.org/registry/webgl/extensions/

WebGLで実装

フラグメントシェーダ

#extension GL_OES_standard_derivatives : enable
precision highp float;

uniform vec4 diffuse;

varying vec3 vNormal;
varying vec3 vPosition;
varying vec3 vLightDirection;

void main() {
	vec3 dx = dFdx(vPosition);
	vec3 dy = dFdy(vPosition);
	vec3 n = normalize(cross(dx, dy));
	vec3 l = normalize(vLightDirection);
	vec3 d = max(dot(n, l), 0.0) * diffuse.xyz;
	gl_FragColor = vec4(d, 1.0);
}

頂点シェーダ

attribute vec3 aVertexPosition;
attribute vec3 aVertexNormal;

uniform mat4 mvMatrix;
uniform mat4 pMatrix;
uniform mat3 nMatrix;
uniform vec3 lightDirection;

varying vec3 vNormal;
varying vec3 vPosition;
varying vec3 vLightDirection;

void main() {
	vec3 pos = aVertexPosition;
	gl_Position = pMatrix * mvMatrix * vec4(pos, 1.0);
	vNormal = normalize(nMatrix * aVertexNormal);
	vPosition = (mvMatrix * vec4(pos, 1.0)).xyz;
	vLightDirection = normalize((mvMatrix * vec4(lightDirection, 1.0)).xyz - (mvMatrix * vec4(pos, 1.0)).xyz);
}

ライトの向きの計算が適当だけど気にしない。

flat_shading

http://jsdo.it/sapphire_al2o3/iN2s

球だとフラットに見えるが平面でやってみたら微妙にグラデーションがついていた。


Responses

  1. […] シェーダの方はちゃんとコピペしてきてもアウトラインとかが全然うまく表示されなかったのでいろいろ修正した。fwidthの拡張機能を使うのでシェーダの最初の方で有効にしている。(WebGLで拡張機能を有効にする方法) […]


コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

カテゴリー

%d人のブロガーが「いいね」をつけました。