GLSLによるジオメトリシェーダ
をテンプレートにして作成
[
トップ
|
新規
|
一覧
|
検索
|
最終更新
|
ヘルプ
]
開始行:
GLSLを用いて単純なジオメトリシェーダを用いたプログラムを...
----
#contents
----
*ジオメトリシェーダとは [#w154145c]
ジオメトリシェーダはバーテックスシェーダとフラグメントシ...
バーテックスシェーダは頂点ごとの処理,フラグメントシェー...
この二つだけでは,例えば,入力された三角形ポリゴンから点...
ポリゴンのテッセレーション,ディスプレースメントマップな...
これらの処理のためにはプリミティブごとの処理を行い,かつ...
これがジオメトリシェーダである.
例えば,ポリゴンのテッセレーションを行いたい場合,1ポリゴ...
ジオメトリシェーダ内で新しい複数のポリゴンを生成して出力...
このとき,ジオメトリシェーダへの入力,出力はポリゴンとな...
また,ポリゴンから点群を生成したい場合,1ポリゴンをプリミ...
ジオメトリシェーダ内で新しい点群を生成して出力する.
このときの入力はポリゴンで出力は点となる.
このように,ジオメトリシェーダを用いる場合,その入力と出...
シェーダプログラムのパラメータとして入力,出力を設定しな...
*ジオメトリシェーダのビルド [#f540f5ad]
[[GLSLについて]]で述べているように,シェーダのビルドを行...
ジオメトリシェーダのコンパイルは,targetにGL_GEOMETRY_SHA...
他のシェーダ(頂点シェーダ,フラグメントシェーダ)と同じで...
他のシェーダとビルドにおいて異なるのがシェーダへの入出力...
これはシェーダオブジェクト登録(glAttachShader)とプログラ...
入出力設定には[[glProgramParameter:http://www.opengl.org/...
void glProgramParameteri(GLuint program, GLenum pname, G...
programにglCreateProgramで作ったプログラムオブジェクト,p...
-GL_GEOMETRY_VERTICES_OUT_EXT : 1つのジオメトリシェーダが...
その値はglGetIntegervにGL_MAX_GEOMETRY_OUTPUT_VERTICES_EX...
-GL_GEOMETRY_INPUT_TYPE_EXT : ジオメトリシェーダへの入力...
|value|プリミティブの種類|glBeginに指定される値|入力頂点...
|GL_POINTS| 点 | GL_POINTS | 1 |
|GL_LINES| ライン(エッジ) | GL_LINES,GL_LINE_STRIP,GL_LIN...
|GL_LINES_ADJACENCY_EXT| 近傍の情報を含むライン(エッジ) |...
|GL_TRIANGLES | 三角形ポリゴン | GL_TRIANGLES,GL_TRIANGLE...
|GL_TRIANGLES_ADJACENCY_EXT | 近傍の情報を含む三角形ポリ...
-GL_GEOMETRY_OUTPUT_TYPE_EXT : ジオメトリシェーダへの出力...
--GL_POINTS : 点.
--GL_LINES : ライン(エッジ).
--GL_TRIANGLES : 三角形ポリゴン.
ジオメトリシェーダを含むプログラムのリンクを行う関数の例...
#code(C){{
/*!
* バーテックス/ジオメトリ/フラグメントシェーダで構成され...
* @param[in] vs バーテックスシェーダオブジェクト
* @param[in] gs ジオメトリシェーダオブジェクト
* @param[in] fs フラグメントシェーダオブジェクト
* @param[in] input_type ジオメトリシェーダへの入力タイプ
* @param[in] output_type ジオメトリシェーダからの出力タ...
* @param[in] vertex_out ジオメトリシェーダの最大出力頂点数
* @return GLSLプログラムオブジェクト
*/
inline GLuint LinkGLSLProgram(GLuint vs, GLuint gs, GLuin...
{
// プログラムオブジェクト作成
GLuint program = glCreateProgram();
// シェーダオブジェクトを登録
glAttachShader(program, vs);
glAttachShader(program, gs);
glAttachShader(program, fs);
// ジオメトリシェーダへの入出力
glProgramParameteriEXT(program, GL_GEOMETRY_INPUT_TYPE_E...
glProgramParameteriEXT(program, GL_GEOMETRY_OUTPUT_TYPE_...
glProgramParameteriEXT(program, GL_GEOMETRY_VERTICES_OUT...
// プログラムのリンク
glLinkProgram(program);
// エラー出力
GLint charsWritten, infoLogLength;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLeng...
char * infoLog = new char[infoLogLength];
glGetProgramInfoLog(program, infoLogLength, &charsWritte...
printf(infoLog);
delete [] infoLog;
// リンカテスト
GLint linkSucceed = GL_FALSE;
glGetProgramiv(program, GL_LINK_STATUS, &linkSucceed);
if(linkSucceed == GL_FALSE){
glDeleteProgram(program);
return 0;
}
return program;
}
}}
シェーダソースファイルからコンパイル,リンクを行う関数の...
返値はrxGLSL型の変数となっており,シェーダファイル名,プ...
#code(C){{
struct rxGLSL
{
string VertProg; //!< 頂点プログラムファイル名
string GeomProg; //!< ジオメトリプログラムファイル名
string FragProg; //!< フラグメントプログラムファイル名
string Name; //!< シェーダ名
GLuint Prog; //!< シェーダID
};
/*!
* GLSLのコンパイル・リンク(ファイルより,ジオメトリシェー...
* @param[in] vs 頂点シェーダファイルパス
* @param[in] gs ジオメトリシェーダファイルパス
* @param[in] fs フラグメントシェーダファイルパス
* @param[in] name プログラム名
* @param[in] input_type ジオメトリシェーダへの入力タイプ
* @param[in] output_type ジオメトリシェーダからの出力タ...
* @param[in] vertex_out ジオメトリシェーダの最大出力頂点数
* @return GLSLオブジェクト
*/
inline rxGLSL CreateGLSLFromFile(const string &vs, const ...
GLint input_type, GLint output_type, GLint verte...
{
rxGLSL glsl;
glsl.VertProg = vs;
glsl.GeomProg = gs;
glsl.FragProg = fs;
glsl.Name = name;
GLuint v, g, f;
v = CompileGLSLShaderFromFile(GL_VERTEX_SHADER, vs.c_str...
g = CompileGLSLShaderFromFile(GL_GEOMETRY_SHADER, gs.c_s...
f = CompileGLSLShaderFromFile(GL_FRAGMENT_SHADER, fs.c_s...
if(vertex_out < 0){
glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES, &vertex_...
}
glsl.Prog = LinkGLSLProgram(v, g, f, input_type, output_...
return glsl;
}
}}
もし,vertex_outに負の値を指定したらシステムの最大出力頂...
*最大出力頂点数について [#qb36625f]
上記のCreateGLSLFromFileではGL_MAX_GEOMETRY_OUTPUT_VERTIC...
ジオメトリシェーダでは最大出力頂点数の他に最大出力要素数(...
最大出力要素数,最大出力頂点数を調べて出力するコード例を以...
GLint nc, nv;
glGetIntegerv(GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS, &...
cout << "maximum number of components : " << nc << endl;
glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES, &nv);
cout << "max output vertices : " << nv << endl;
GeForce GTX 480を持つPC上で実行した結果を以下に示す(OpenG...
OpenGL Ver. 4.1.0
Glew Ver. 1.5.7
maximum number of components : 1024
max output vertices : 1024
最大出力要素数における要素とは頂点における座標や色のこと...
通常1頂点は8つの要素(4つの位置要素と4つの色要素)を持つ.
そうすると,この環境上では最大出力頂点数は1024となってい...
128(=1024/8)に制限される.位置要素のみにした場合でも256(=...
*ジオメトリシェーダのビルドイン変数と関数 [#k0e7b339]
頂点シェーダのgl_PositionやglTexCoord[]のようにジオメトリ...
頂点シェーダとフラグメントシェーダのみの場合は,これらの...
ジオメトリシェーダでは頂点シェーダで処理された複数の頂点...
そのため,in変数とout変数で異なるものが定義されている.
例えば,頂点シェーダでgl_Positionに設定された値は,
ジオメトリシェーダ側からはgl_PositionIn[]配列を用いてアク...
この配列の大きさは変数gl_VerticesInで定義され,gl_Vertice...
これらの値を用いてジオメトリシェーダの出力用変数gl_Positi...
ラスタライザに頂点座標が出力される.
ビルドイン変数,関数を以下に示す.
varying in vec4 gl_FrontColorIn[gl_VerticesIn];
varying in vec4 gl_BackColorIn[gl_VerticesIn];
varying in vec4 gl_FrontSecondaryColorIn[gl_VerticesIn];
varying in vec4 gl_BackSecondaryColorIn[gl_VerticesIn];
varying in vec4 gl_TexCoordIn[gl_VerticesIn][];
varying in float gl_FogFragCoordIn[gl_VerticesIn];
varying in vec4 gl_PositionIn[gl_VerticesIn];
varying in float gl_PointSizeIn[gl_VerticesIn];
varying in vec4 gl_ClipVertexIn[gl_VerticesIn];
varying out vec4 gl_FrontColor;
varying out vec4 gl_BackColor;
varying out vec4 gl_FrontSecondaryColor;
varying out vec4 gl_BackSecondaryColor;
varying out vec4 gl_TexCoord[];
varying out float gl_FogFragCoord;
void EmitVertex();
void EndPrimitive();
具体的な使い方は下記のコード例を参照.
*ユーザ定義のvarying変数 [#k9824864]
ビルドイン変数と同様にユーザ定義の変数を用いて頂点シェー...
ジオメトリシェーダからラスタライザを介してフラグメントシ...
注意として,頂点シェーダとフラグメントシェーダのみの場合...
明示的に指定する必要がある.また,頂点シェーダの出力とジ...
ジオメトリシェーダ側の変数は同じ変数名の配列となる.
例えば,頂点シェーダ側で
varying float Alpha;
varying vec3 Nrm;
とした場合,ジオメトリシェーダでは,
varying in float Alpha[3];
varying in vec3 Nrm[3];
とする.ただし,ここでは入力としてGL_TRIANGLESが指定され...
フラグメントシェーダに出力する場合,ジオメトリシェーダで...
varying out vec3 LightPos;
のようにし,これをEmitVertex()する各頂点で値を設定する.
LightPos = ...
EmitVertex();
フラグメントシェーダでは,
varying vec3 LightPos;
として受け取る.
*ジオメトリシェーダの例 [#ea6c7a9b]
ジオメトリシェーダを用いた単純な例として,入力された三角...
三角形の重心を縮小の中心として利用する.
頂点シェーダだけでは重心を求めることができないためジオメ...
まず,頂点シェーダではPhong反射モデルに基づき頂点色を決定...
#code(C){{
/*!
@file simple.vs
@brief GLSL頂点シェーダ
- ジオメトリシェーダのテスト
@author Makoto Fujisawa
@date 2011
*/
#version 120
uniform vec3 eyePosition;
void main(void)
{
// 光源
vec3 La = gl_LightSource[0].ambient.xyz; // ライト環境光
vec3 Ld = gl_LightSource[0].diffuse.xyz; // ライト拡散反...
vec3 Ls = gl_LightSource[0].specular.xyz; // ライト鏡面...
vec3 Lp = gl_LightSource[0].position.xyz; // ライト位置
// 材質
vec3 Ke = gl_FrontMaterial.emission.xyz; // 放射色
vec3 Ka = gl_FrontMaterial.ambient.xyz; // 環境光
vec3 Kd = gl_FrontMaterial.diffuse.xyz; // 拡散反射
vec3 Ks = gl_FrontMaterial.specular.xyz; // 鏡面反射
float shine = gl_FrontMaterial.shininess;
vec3 P = (gl_ModelViewMatrix*gl_Vertex).xyz;
vec3 V = normalize(-P); // 視線ベクトル
vec3 N = normalize(gl_NormalMatrix*gl_Normal); // 法線ベ...
vec3 L = normalize(Lp-P); // ライトベクトル
// 放射色の計算
vec3 emissive = Ke;
// 環境光の計算
vec3 ambient = Ka*La;
// 拡散反射の計算
float diffuseLight = max(dot(L, N), 0.0);
vec3 diffuse = Kd*Ld*diffuseLight;
// 鏡面反射の計算
vec3 H = normalize(L+V);
float specularLight = pow(max(dot(H, N), 0.0), shine);
if(diffuseLight <= 0.0) specularLight = 0.0;
vec3 specular = Ks*Ls*specularLight;
gl_FrontColor = vec4(emissive+ambient+diffuse+specular, ...
gl_Position = gl_Vertex;
}
}}
ジオメトリシェーダでは頂点の情報をビルドイン変数の
varying in vec4 gl_PositionIn[gl_VerticesIn];
から取得して,三角形ポリゴンの重心を算出し,さらに,
varying in vec4 gl_FrontColorIn[gl_VerticesIn];
にから頂点色を取得して設定する.
重心座標に基づき縮小したポリゴン頂点座標を計算して,gl_Po...
gl_FrontColor, gl_Positionに頂点情報を設定したら,ジオメ...
void EmitVertex();
を呼び出して,頂点の設定を完了する.これを三角形ポリゴン...
void EndPrimitive();
を呼び出して,プリミティブ(ここでは三角形ポリゴン)の設定...
#code(C){{
/*!
@file simple.gs
@brief GLSLジオメトリシェーダ
- ジオメトリシェーダのテスト
@author Makoto Fujisawa
@date 2011
*/
#version 120
#extension GL_EXT_geometry_shader4 : enable
void main(void)
{
// 三角形ポリゴンの重心
vec3 mg = vec3(0.0);
for(int i = 0; i < gl_VerticesIn; ++i){
mg += gl_PositionIn[i].xyz;
}
mg /= float(gl_VerticesIn);
// 重心を原点としてポリゴンを縮小して描画
vec3 v, p;
for(int i = 0; i < gl_VerticesIn; ++i){
gl_FrontColor = gl_FrontColorIn[i];
v = mg-gl_PositionIn[i].xyz;
p = gl_PositionIn[i].xyz+0.2*v;
gl_Position = gl_ModelViewProjectionMatrix*vec4(p, 1);
EmitVertex();
}
EndPrimitive();
}
}}
フラグメントシェーダでは単純に色をピクセルに渡すだけであ...
#code(C){{
/*!
@file simple.fs
@brief GLSLフラグメントシェーダ
- ジオメトリシェーダのテスト
@author Makoto Fujisawa
@date 2011
*/
#version 120
void main(void)
{
gl_FragColor = gl_Color;
}
}}
**レンダリング結果 [#ycf28163]
レンダリング結果を以下に示す.
#ref(geometry_shader1.jpg)
**ソースコード [#cb46a2f7]
#ref(glsl_geometry.zip)
終了行:
GLSLを用いて単純なジオメトリシェーダを用いたプログラムを...
----
#contents
----
*ジオメトリシェーダとは [#w154145c]
ジオメトリシェーダはバーテックスシェーダとフラグメントシ...
バーテックスシェーダは頂点ごとの処理,フラグメントシェー...
この二つだけでは,例えば,入力された三角形ポリゴンから点...
ポリゴンのテッセレーション,ディスプレースメントマップな...
これらの処理のためにはプリミティブごとの処理を行い,かつ...
これがジオメトリシェーダである.
例えば,ポリゴンのテッセレーションを行いたい場合,1ポリゴ...
ジオメトリシェーダ内で新しい複数のポリゴンを生成して出力...
このとき,ジオメトリシェーダへの入力,出力はポリゴンとな...
また,ポリゴンから点群を生成したい場合,1ポリゴンをプリミ...
ジオメトリシェーダ内で新しい点群を生成して出力する.
このときの入力はポリゴンで出力は点となる.
このように,ジオメトリシェーダを用いる場合,その入力と出...
シェーダプログラムのパラメータとして入力,出力を設定しな...
*ジオメトリシェーダのビルド [#f540f5ad]
[[GLSLについて]]で述べているように,シェーダのビルドを行...
ジオメトリシェーダのコンパイルは,targetにGL_GEOMETRY_SHA...
他のシェーダ(頂点シェーダ,フラグメントシェーダ)と同じで...
他のシェーダとビルドにおいて異なるのがシェーダへの入出力...
これはシェーダオブジェクト登録(glAttachShader)とプログラ...
入出力設定には[[glProgramParameter:http://www.opengl.org/...
void glProgramParameteri(GLuint program, GLenum pname, G...
programにglCreateProgramで作ったプログラムオブジェクト,p...
-GL_GEOMETRY_VERTICES_OUT_EXT : 1つのジオメトリシェーダが...
その値はglGetIntegervにGL_MAX_GEOMETRY_OUTPUT_VERTICES_EX...
-GL_GEOMETRY_INPUT_TYPE_EXT : ジオメトリシェーダへの入力...
|value|プリミティブの種類|glBeginに指定される値|入力頂点...
|GL_POINTS| 点 | GL_POINTS | 1 |
|GL_LINES| ライン(エッジ) | GL_LINES,GL_LINE_STRIP,GL_LIN...
|GL_LINES_ADJACENCY_EXT| 近傍の情報を含むライン(エッジ) |...
|GL_TRIANGLES | 三角形ポリゴン | GL_TRIANGLES,GL_TRIANGLE...
|GL_TRIANGLES_ADJACENCY_EXT | 近傍の情報を含む三角形ポリ...
-GL_GEOMETRY_OUTPUT_TYPE_EXT : ジオメトリシェーダへの出力...
--GL_POINTS : 点.
--GL_LINES : ライン(エッジ).
--GL_TRIANGLES : 三角形ポリゴン.
ジオメトリシェーダを含むプログラムのリンクを行う関数の例...
#code(C){{
/*!
* バーテックス/ジオメトリ/フラグメントシェーダで構成され...
* @param[in] vs バーテックスシェーダオブジェクト
* @param[in] gs ジオメトリシェーダオブジェクト
* @param[in] fs フラグメントシェーダオブジェクト
* @param[in] input_type ジオメトリシェーダへの入力タイプ
* @param[in] output_type ジオメトリシェーダからの出力タ...
* @param[in] vertex_out ジオメトリシェーダの最大出力頂点数
* @return GLSLプログラムオブジェクト
*/
inline GLuint LinkGLSLProgram(GLuint vs, GLuint gs, GLuin...
{
// プログラムオブジェクト作成
GLuint program = glCreateProgram();
// シェーダオブジェクトを登録
glAttachShader(program, vs);
glAttachShader(program, gs);
glAttachShader(program, fs);
// ジオメトリシェーダへの入出力
glProgramParameteriEXT(program, GL_GEOMETRY_INPUT_TYPE_E...
glProgramParameteriEXT(program, GL_GEOMETRY_OUTPUT_TYPE_...
glProgramParameteriEXT(program, GL_GEOMETRY_VERTICES_OUT...
// プログラムのリンク
glLinkProgram(program);
// エラー出力
GLint charsWritten, infoLogLength;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLeng...
char * infoLog = new char[infoLogLength];
glGetProgramInfoLog(program, infoLogLength, &charsWritte...
printf(infoLog);
delete [] infoLog;
// リンカテスト
GLint linkSucceed = GL_FALSE;
glGetProgramiv(program, GL_LINK_STATUS, &linkSucceed);
if(linkSucceed == GL_FALSE){
glDeleteProgram(program);
return 0;
}
return program;
}
}}
シェーダソースファイルからコンパイル,リンクを行う関数の...
返値はrxGLSL型の変数となっており,シェーダファイル名,プ...
#code(C){{
struct rxGLSL
{
string VertProg; //!< 頂点プログラムファイル名
string GeomProg; //!< ジオメトリプログラムファイル名
string FragProg; //!< フラグメントプログラムファイル名
string Name; //!< シェーダ名
GLuint Prog; //!< シェーダID
};
/*!
* GLSLのコンパイル・リンク(ファイルより,ジオメトリシェー...
* @param[in] vs 頂点シェーダファイルパス
* @param[in] gs ジオメトリシェーダファイルパス
* @param[in] fs フラグメントシェーダファイルパス
* @param[in] name プログラム名
* @param[in] input_type ジオメトリシェーダへの入力タイプ
* @param[in] output_type ジオメトリシェーダからの出力タ...
* @param[in] vertex_out ジオメトリシェーダの最大出力頂点数
* @return GLSLオブジェクト
*/
inline rxGLSL CreateGLSLFromFile(const string &vs, const ...
GLint input_type, GLint output_type, GLint verte...
{
rxGLSL glsl;
glsl.VertProg = vs;
glsl.GeomProg = gs;
glsl.FragProg = fs;
glsl.Name = name;
GLuint v, g, f;
v = CompileGLSLShaderFromFile(GL_VERTEX_SHADER, vs.c_str...
g = CompileGLSLShaderFromFile(GL_GEOMETRY_SHADER, gs.c_s...
f = CompileGLSLShaderFromFile(GL_FRAGMENT_SHADER, fs.c_s...
if(vertex_out < 0){
glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES, &vertex_...
}
glsl.Prog = LinkGLSLProgram(v, g, f, input_type, output_...
return glsl;
}
}}
もし,vertex_outに負の値を指定したらシステムの最大出力頂...
*最大出力頂点数について [#qb36625f]
上記のCreateGLSLFromFileではGL_MAX_GEOMETRY_OUTPUT_VERTIC...
ジオメトリシェーダでは最大出力頂点数の他に最大出力要素数(...
最大出力要素数,最大出力頂点数を調べて出力するコード例を以...
GLint nc, nv;
glGetIntegerv(GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS, &...
cout << "maximum number of components : " << nc << endl;
glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES, &nv);
cout << "max output vertices : " << nv << endl;
GeForce GTX 480を持つPC上で実行した結果を以下に示す(OpenG...
OpenGL Ver. 4.1.0
Glew Ver. 1.5.7
maximum number of components : 1024
max output vertices : 1024
最大出力要素数における要素とは頂点における座標や色のこと...
通常1頂点は8つの要素(4つの位置要素と4つの色要素)を持つ.
そうすると,この環境上では最大出力頂点数は1024となってい...
128(=1024/8)に制限される.位置要素のみにした場合でも256(=...
*ジオメトリシェーダのビルドイン変数と関数 [#k0e7b339]
頂点シェーダのgl_PositionやglTexCoord[]のようにジオメトリ...
頂点シェーダとフラグメントシェーダのみの場合は,これらの...
ジオメトリシェーダでは頂点シェーダで処理された複数の頂点...
そのため,in変数とout変数で異なるものが定義されている.
例えば,頂点シェーダでgl_Positionに設定された値は,
ジオメトリシェーダ側からはgl_PositionIn[]配列を用いてアク...
この配列の大きさは変数gl_VerticesInで定義され,gl_Vertice...
これらの値を用いてジオメトリシェーダの出力用変数gl_Positi...
ラスタライザに頂点座標が出力される.
ビルドイン変数,関数を以下に示す.
varying in vec4 gl_FrontColorIn[gl_VerticesIn];
varying in vec4 gl_BackColorIn[gl_VerticesIn];
varying in vec4 gl_FrontSecondaryColorIn[gl_VerticesIn];
varying in vec4 gl_BackSecondaryColorIn[gl_VerticesIn];
varying in vec4 gl_TexCoordIn[gl_VerticesIn][];
varying in float gl_FogFragCoordIn[gl_VerticesIn];
varying in vec4 gl_PositionIn[gl_VerticesIn];
varying in float gl_PointSizeIn[gl_VerticesIn];
varying in vec4 gl_ClipVertexIn[gl_VerticesIn];
varying out vec4 gl_FrontColor;
varying out vec4 gl_BackColor;
varying out vec4 gl_FrontSecondaryColor;
varying out vec4 gl_BackSecondaryColor;
varying out vec4 gl_TexCoord[];
varying out float gl_FogFragCoord;
void EmitVertex();
void EndPrimitive();
具体的な使い方は下記のコード例を参照.
*ユーザ定義のvarying変数 [#k9824864]
ビルドイン変数と同様にユーザ定義の変数を用いて頂点シェー...
ジオメトリシェーダからラスタライザを介してフラグメントシ...
注意として,頂点シェーダとフラグメントシェーダのみの場合...
明示的に指定する必要がある.また,頂点シェーダの出力とジ...
ジオメトリシェーダ側の変数は同じ変数名の配列となる.
例えば,頂点シェーダ側で
varying float Alpha;
varying vec3 Nrm;
とした場合,ジオメトリシェーダでは,
varying in float Alpha[3];
varying in vec3 Nrm[3];
とする.ただし,ここでは入力としてGL_TRIANGLESが指定され...
フラグメントシェーダに出力する場合,ジオメトリシェーダで...
varying out vec3 LightPos;
のようにし,これをEmitVertex()する各頂点で値を設定する.
LightPos = ...
EmitVertex();
フラグメントシェーダでは,
varying vec3 LightPos;
として受け取る.
*ジオメトリシェーダの例 [#ea6c7a9b]
ジオメトリシェーダを用いた単純な例として,入力された三角...
三角形の重心を縮小の中心として利用する.
頂点シェーダだけでは重心を求めることができないためジオメ...
まず,頂点シェーダではPhong反射モデルに基づき頂点色を決定...
#code(C){{
/*!
@file simple.vs
@brief GLSL頂点シェーダ
- ジオメトリシェーダのテスト
@author Makoto Fujisawa
@date 2011
*/
#version 120
uniform vec3 eyePosition;
void main(void)
{
// 光源
vec3 La = gl_LightSource[0].ambient.xyz; // ライト環境光
vec3 Ld = gl_LightSource[0].diffuse.xyz; // ライト拡散反...
vec3 Ls = gl_LightSource[0].specular.xyz; // ライト鏡面...
vec3 Lp = gl_LightSource[0].position.xyz; // ライト位置
// 材質
vec3 Ke = gl_FrontMaterial.emission.xyz; // 放射色
vec3 Ka = gl_FrontMaterial.ambient.xyz; // 環境光
vec3 Kd = gl_FrontMaterial.diffuse.xyz; // 拡散反射
vec3 Ks = gl_FrontMaterial.specular.xyz; // 鏡面反射
float shine = gl_FrontMaterial.shininess;
vec3 P = (gl_ModelViewMatrix*gl_Vertex).xyz;
vec3 V = normalize(-P); // 視線ベクトル
vec3 N = normalize(gl_NormalMatrix*gl_Normal); // 法線ベ...
vec3 L = normalize(Lp-P); // ライトベクトル
// 放射色の計算
vec3 emissive = Ke;
// 環境光の計算
vec3 ambient = Ka*La;
// 拡散反射の計算
float diffuseLight = max(dot(L, N), 0.0);
vec3 diffuse = Kd*Ld*diffuseLight;
// 鏡面反射の計算
vec3 H = normalize(L+V);
float specularLight = pow(max(dot(H, N), 0.0), shine);
if(diffuseLight <= 0.0) specularLight = 0.0;
vec3 specular = Ks*Ls*specularLight;
gl_FrontColor = vec4(emissive+ambient+diffuse+specular, ...
gl_Position = gl_Vertex;
}
}}
ジオメトリシェーダでは頂点の情報をビルドイン変数の
varying in vec4 gl_PositionIn[gl_VerticesIn];
から取得して,三角形ポリゴンの重心を算出し,さらに,
varying in vec4 gl_FrontColorIn[gl_VerticesIn];
にから頂点色を取得して設定する.
重心座標に基づき縮小したポリゴン頂点座標を計算して,gl_Po...
gl_FrontColor, gl_Positionに頂点情報を設定したら,ジオメ...
void EmitVertex();
を呼び出して,頂点の設定を完了する.これを三角形ポリゴン...
void EndPrimitive();
を呼び出して,プリミティブ(ここでは三角形ポリゴン)の設定...
#code(C){{
/*!
@file simple.gs
@brief GLSLジオメトリシェーダ
- ジオメトリシェーダのテスト
@author Makoto Fujisawa
@date 2011
*/
#version 120
#extension GL_EXT_geometry_shader4 : enable
void main(void)
{
// 三角形ポリゴンの重心
vec3 mg = vec3(0.0);
for(int i = 0; i < gl_VerticesIn; ++i){
mg += gl_PositionIn[i].xyz;
}
mg /= float(gl_VerticesIn);
// 重心を原点としてポリゴンを縮小して描画
vec3 v, p;
for(int i = 0; i < gl_VerticesIn; ++i){
gl_FrontColor = gl_FrontColorIn[i];
v = mg-gl_PositionIn[i].xyz;
p = gl_PositionIn[i].xyz+0.2*v;
gl_Position = gl_ModelViewProjectionMatrix*vec4(p, 1);
EmitVertex();
}
EndPrimitive();
}
}}
フラグメントシェーダでは単純に色をピクセルに渡すだけであ...
#code(C){{
/*!
@file simple.fs
@brief GLSLフラグメントシェーダ
- ジオメトリシェーダのテスト
@author Makoto Fujisawa
@date 2011
*/
#version 120
void main(void)
{
gl_FragColor = gl_Color;
}
}}
**レンダリング結果 [#ycf28163]
レンダリング結果を以下に示す.
#ref(geometry_shader1.jpg)
**ソースコード [#cb46a2f7]
#ref(glsl_geometry.zip)
ページ名: