最終更新: mikk_ni3_92 2008年04月08日(火) 18:18:39履歴
現在地 >> メニュー >> サンプルコード::Cg >> Cg::uniform型? >> Cg::uniform型+構造体
Cg::頂点ライティング?のプログラムを変更して、以下のようなuniform型の構造体を作成し、
同じ結果となるようにせよ。
struct MATERIAL //各種係数
{
float3 Ke;
float3 Ka;
float3 Kd;
float3 Ks;
float shininess;
};
struct EYE_AND_LIGHT //光源と視点の設定
{
float3 lightColor;
float3 lightPos;
float3 eyePos;
};
/** 入力データ構造 **/
struct VERTEX_DATA_IN
{
float4 position : POSITION;
float3 normal : NORMAL;
};
/** 出力データ構造 **/
struct VERTEX_DATA_OUT
{
float4 position : POSITION;
float4 color : COLOR;
};
/* uniform用データ構造*/
struct MATERIAL //各種係数
{
float3 Ke;
float3 Ka;
float3 Kd;
float3 Ks;
float shininess;
};
struct EYE_AND_LIGHT //光源と視点の設定
{
float3 lightColor;
float3 lightPos;
float3 eyePos;
};
/******** メインエントリ関数 **********/
VERTEX_DATA_OUT Cg_Main(in VERTEX_DATA_IN IN ,
uniform float4x4 modelViewMatrix,
uniform float3 globalAmbient,
uniform EYE_AND_LIGHT Eye_And_Light,
uniform MATERIAL material
)
{
VERTEX_DATA_OUT OUT;
OUT.position = mul(modelViewMatrix, IN.position);//スクリーンの描画位置計算
float3 P = IN.position.xyz;
float3 N = IN.normal;
float3 emissive = material.Ke;//放射輝度
float3 ambient = material.Ka * globalAmbient; //環境光計算
float3 L = normalize(Eye_And_Light.lightPos - P); //ランバート反射の計算
float diffuseLight = max(dot(N, L), 0);
float3 diffuse = material.Kd * Eye_And_Light.lightColor * diffuseLight;
float3 V = normalize(Eye_And_Light.eyePos - P);//Blinのモデルで計算
float3 H = normalize(L + V);
float specularLight = pow(max(dot(N, H), 0), material.shininess);
if (diffuseLight <= 0) specularLight = 0;
float3 specular = material.Ks * Eye_And_Light.lightColor * specularLight;
OUT.color.xyz = emissive + ambient + diffuse + specular;
OUT.color.w = 1;
return OUT;
}
void Cg_Fragment_Main(in float4 in_color : COLOR,out float4 out_color : COLOR)
{
out_color = in_color;
}
#include <iostream>
#include <GL/glut.h>
#include <Cg/cg.h>
#include <Cg/cgGL.h>
using namespace std;
/*** プロトタイプ宣言 ***/
inline void SET_UP_CG_VERTEX();
inline void GET_AND_SET_PARAM();
void SET_UP_CG_FRAGMENT();
void display(void);
void reshape(int w, int h);
void DRAW_XYZ();
/**************[OpenGLの設定]**********************/
inline void GLUT_INIT()
{
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize(200,200);
}
inline void GLUT_CALL_FUNC()
{
glutDisplayFunc(display);
glutReshapeFunc(reshape);
}
inline void MY_INIT()
{
glClearColor(1.0, 1.0, 1.0, 1.0);
glEnable(GL_DEPTH_TEST);
}
/**************[Cgの設定]**********************/
/** Cg用変数 **/
CGcontext Cg_Cont;//コンテキスト
inline void CG_INIT()
{
/* コンテキスト */
Cg_Cont = cgCreateContext();
if(Cg_Cont == NULL)
{
cout << "Can't Create Context" << endl;
exit(0);
}
SET_UP_CG_VERTEX(); //頂点セットアップ
SET_UP_CG_FRAGMENT();//フラグメントセットアップ
}
/************* 頂点セットアップ ***************/
namespace{
CGprofile Vert_Prof;//プロファイル
CGprogram Vert_Prog;//プログラム
}
inline void SET_UP_CG_VERTEX()
{
/* プロファイルの設定 */
Vert_Prof = cgGLGetLatestProfile(CG_GL_VERTEX);
if(Vert_Prof == CG_PROFILE_UNKNOWN)
{
cout << "Invalid profile type" << endl;
exit(0);
}
cgGLSetOptimalOptions(Vert_Prof);
/* ファイルを読んでコンパイル */
Vert_Prog =
cgCreateProgramFromFile(
Cg_Cont,//コンテキスト
CG_SOURCE,//Cgソースコード
"vertex.cg", //「.cgファイル名」
Vert_Prof, //プロファイル
"Cg_Main", //「.cgファイル」で最初にいく関数
NULL); //NULLでよい
cgGLLoadProgram(Vert_Prog);
if(Vert_Prog==NULL)
{
CGerror Error = cgGetError();
cout << cgGetErrorString(Error) << endl;
exit(0);
}
GET_AND_SET_PARAM();//パラメータセットアップ
}
/* 無名名前空間 */
namespace
{
CGparameter modelview;//モデルビュー行列
CGparameter globalAmb;
CGparameter lightColor,lightPosition;//光源の色と位置
CGparameter eyePosition; //視点位置
CGparameter Ke,Ka,Kd,Ks,shininess;//各種係数など
float myGlobalAmb[3] = { 0.2, 0.2, 0.2 };
float myLightColor[3] = { 1,1,1 };
const float Emissive[3] = {0.0, 0.0, 0.0},
Ambient[3] = {0.24725, 0.1995, 0.0745},
Diffuse[3] = {0.75164, 0.60648 , 0.22648},
Specular[3] = {0.628281, 0.555802,0.366065},
Shininess = 51.2,
look_at[4] = {3,4,5,1},
light_position[4] ={-3,4,5,1};
}
inline void GET_AND_SET_PARAM()
{
/* 名前の関連付け */
modelview = cgGetNamedParameter(Vert_Prog, "modelViewMatrix");
globalAmb = cgGetNamedParameter(Vert_Prog, "globalAmbient");
lightColor = cgGetNamedParameter(Vert_Prog, "Eye_And_Light.lightColor");
lightPosition = cgGetNamedParameter(Vert_Prog, "Eye_And_Light.lightPos");
eyePosition = cgGetNamedParameter(Vert_Prog, "Eye_And_Light.eyePos");
Ke = cgGetNamedParameter(Vert_Prog, "material.Ke");
Ka = cgGetNamedParameter(Vert_Prog, "material.Ka");
Kd = cgGetNamedParameter(Vert_Prog, "material.Kd");
Ks = cgGetNamedParameter(Vert_Prog, "material.Ks");
shininess = cgGetNamedParameter(Vert_Prog, "material.shininess");
/* 値の設定*/
cgSetParameter3fv(globalAmb,myGlobalAmb);
/* 視点と光源の設定 */
cgSetParameter4fv(eyePosition, look_at);
cgSetParameter4fv(lightPosition, light_position);
cgSetParameter3fv(lightColor,myLightColor);
/* 材質パラメータ */
cgSetParameter3fv(Ke, Emissive);
cgSetParameter3fv(Ka, Ambient);
cgSetParameter3fv(Kd, Diffuse);
cgSetParameter3fv(Ks, Specular);
cgSetParameter1f(shininess, Shininess);
}
/********* フラグメントのセットアップ *************/
CGprofile Frag_Prof;//フラグメント
CGprogram Frag_Prog;
void SET_UP_CG_FRAGMENT()
{
Frag_Prof = cgGLGetLatestProfile(CG_GL_FRAGMENT);
if(Frag_Prof == CG_PROFILE_UNKNOWN)
{
cout << "Fragment : profile is unknown" << endl;
exit(0);
}
cgGLSetOptimalOptions(Frag_Prof);
Frag_Prog =
cgCreateProgramFromFile(
Cg_Cont,//コンテキスト
CG_SOURCE,//Cgソースコード
"fragment.cg", //「.cgファイル名」
Frag_Prof, //プロファイル
"Cg_Fragment_Main", //「.cgファイル」で最初にいく関数
NULL); //NULLでよい
cgGLLoadProgram(Frag_Prog);
if(Frag_Prog==NULL)
{
CGerror Error = cgGetError();
cout << cgGetErrorString(Error) << endl;
exit(0);
}
}
/************* [メイン関数] ***************/
int main(int argc,char **argv)
{
glutInit(&argc,argv);
GLUT_INIT();
glutCreateWindow("Cg with OpenGL");
GLUT_CALL_FUNC();
MY_INIT();
CG_INIT();//Cgセットアップ
glutMainLoop();
return 0;
}
/*********[ここから、各種コールバック]*************/
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(3.0, 4.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
cgGLSetStateMatrixParameter(modelview,CG_GL_MODELVIEW_PROJECTION_MATRIX,CG_GL_MATRIX_IDENTITY);
DRAW_XYZ();
/*Cgの有効化*/
cgGLBindProgram(Vert_Prog);
cgGLEnableProfile(Vert_Prof);
cgGLBindProgram(Frag_Prog);
cgGLEnableProfile(Frag_Prof);
glutSolidSphere(0.5,30,30);
cgGLDisableProfile(Vert_Prof);
cgGLDisableProfile(Frag_Prof);
glutSwapBuffers();
}
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(30.0, (double)w / (double)h, 1.0, 100.0);
glMatrixMode(GL_MODELVIEW);
}
/********** ここから、各種関数 ****************/
void DRAW_XYZ()
{
glBegin(GL_LINES);
glColor3d(0,1,0);//x
glVertex2d(-100,0);
glVertex2d(100, 0);
glColor3d(1,0,0);//y
glVertex2d(0,0);
glVertex2d(0,100);
glColor3d(0,0,1);//z
glVertex3d(0,0,-100);
glVertex3d(0,0, 100);
glEnd();
}
uniform型を構造体にまとめて引数にする場合、
[1]:構造体として普通に定義。
struct MATERIAL //各種係数
{
float3 Ke;
float3 Ka;
float3 Kd;
float3 Ks;
float shininess;
};
[2]:引数の時、uniformを追加する。
VERTEX_DATA_OUT Cg_Main(... ,uniform MATERIAL material, ...)
{
... ...
float3 ambient = material.Ka * globalAmbient; //環境光計算
... ...
}
また、「cppファイル」での名前の関連付けも以下のように「.cgファイル」で記述するものに合わせる必要がある。
Ke = cgGetNamedParameter(Vert_Prog, "material.Ke");
Ka = cgGetNamedParameter(Vert_Prog, "material.Ka");
Kd = cgGetNamedParameter(Vert_Prog, "material.Kd");
Ks = cgGetNamedParameter(Vert_Prog, "material.Ks");
shininess = cgGetNamedParameter(Vert_Prog, "material.shininess");
Cg::頂点ライティング?のプログラムを変更して、以下のようなuniform型の構造体を作成し、
同じ結果となるようにせよ。
struct MATERIAL //各種係数
{
float3 Ke;
float3 Ka;
float3 Kd;
float3 Ks;
float shininess;
};
struct EYE_AND_LIGHT //光源と視点の設定
{
float3 lightColor;
float3 lightPos;
float3 eyePos;
};
/** 入力データ構造 **/
struct VERTEX_DATA_IN
{
float4 position : POSITION;
float3 normal : NORMAL;
};
/** 出力データ構造 **/
struct VERTEX_DATA_OUT
{
float4 position : POSITION;
float4 color : COLOR;
};
/* uniform用データ構造*/
struct MATERIAL //各種係数
{
float3 Ke;
float3 Ka;
float3 Kd;
float3 Ks;
float shininess;
};
struct EYE_AND_LIGHT //光源と視点の設定
{
float3 lightColor;
float3 lightPos;
float3 eyePos;
};
/******** メインエントリ関数 **********/
VERTEX_DATA_OUT Cg_Main(in VERTEX_DATA_IN IN ,
uniform float4x4 modelViewMatrix,
uniform float3 globalAmbient,
uniform EYE_AND_LIGHT Eye_And_Light,
uniform MATERIAL material
)
{
VERTEX_DATA_OUT OUT;
OUT.position = mul(modelViewMatrix, IN.position);//スクリーンの描画位置計算
float3 P = IN.position.xyz;
float3 N = IN.normal;
float3 emissive = material.Ke;//放射輝度
float3 ambient = material.Ka * globalAmbient; //環境光計算
float3 L = normalize(Eye_And_Light.lightPos - P); //ランバート反射の計算
float diffuseLight = max(dot(N, L), 0);
float3 diffuse = material.Kd * Eye_And_Light.lightColor * diffuseLight;
float3 V = normalize(Eye_And_Light.eyePos - P);//Blinのモデルで計算
float3 H = normalize(L + V);
float specularLight = pow(max(dot(N, H), 0), material.shininess);
if (diffuseLight <= 0) specularLight = 0;
float3 specular = material.Ks * Eye_And_Light.lightColor * specularLight;
OUT.color.xyz = emissive + ambient + diffuse + specular;
OUT.color.w = 1;
return OUT;
}
void Cg_Fragment_Main(in float4 in_color : COLOR,out float4 out_color : COLOR)
{
out_color = in_color;
}
#include <iostream>
#include <GL/glut.h>
#include <Cg/cg.h>
#include <Cg/cgGL.h>
using namespace std;
/*** プロトタイプ宣言 ***/
inline void SET_UP_CG_VERTEX();
inline void GET_AND_SET_PARAM();
void SET_UP_CG_FRAGMENT();
void display(void);
void reshape(int w, int h);
void DRAW_XYZ();
/**************[OpenGLの設定]**********************/
inline void GLUT_INIT()
{
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize(200,200);
}
inline void GLUT_CALL_FUNC()
{
glutDisplayFunc(display);
glutReshapeFunc(reshape);
}
inline void MY_INIT()
{
glClearColor(1.0, 1.0, 1.0, 1.0);
glEnable(GL_DEPTH_TEST);
}
/**************[Cgの設定]**********************/
/** Cg用変数 **/
CGcontext Cg_Cont;//コンテキスト
inline void CG_INIT()
{
/* コンテキスト */
Cg_Cont = cgCreateContext();
if(Cg_Cont == NULL)
{
cout << "Can't Create Context" << endl;
exit(0);
}
SET_UP_CG_VERTEX(); //頂点セットアップ
SET_UP_CG_FRAGMENT();//フラグメントセットアップ
}
/************* 頂点セットアップ ***************/
namespace{
CGprofile Vert_Prof;//プロファイル
CGprogram Vert_Prog;//プログラム
}
inline void SET_UP_CG_VERTEX()
{
/* プロファイルの設定 */
Vert_Prof = cgGLGetLatestProfile(CG_GL_VERTEX);
if(Vert_Prof == CG_PROFILE_UNKNOWN)
{
cout << "Invalid profile type" << endl;
exit(0);
}
cgGLSetOptimalOptions(Vert_Prof);
/* ファイルを読んでコンパイル */
Vert_Prog =
cgCreateProgramFromFile(
Cg_Cont,//コンテキスト
CG_SOURCE,//Cgソースコード
"vertex.cg", //「.cgファイル名」
Vert_Prof, //プロファイル
"Cg_Main", //「.cgファイル」で最初にいく関数
NULL); //NULLでよい
cgGLLoadProgram(Vert_Prog);
if(Vert_Prog==NULL)
{
CGerror Error = cgGetError();
cout << cgGetErrorString(Error) << endl;
exit(0);
}
GET_AND_SET_PARAM();//パラメータセットアップ
}
/* 無名名前空間 */
namespace
{
CGparameter modelview;//モデルビュー行列
CGparameter globalAmb;
CGparameter lightColor,lightPosition;//光源の色と位置
CGparameter eyePosition; //視点位置
CGparameter Ke,Ka,Kd,Ks,shininess;//各種係数など
float myGlobalAmb[3] = { 0.2, 0.2, 0.2 };
float myLightColor[3] = { 1,1,1 };
const float Emissive[3] = {0.0, 0.0, 0.0},
Ambient[3] = {0.24725, 0.1995, 0.0745},
Diffuse[3] = {0.75164, 0.60648 , 0.22648},
Specular[3] = {0.628281, 0.555802,0.366065},
Shininess = 51.2,
look_at[4] = {3,4,5,1},
light_position[4] ={-3,4,5,1};
}
inline void GET_AND_SET_PARAM()
{
/* 名前の関連付け */
modelview = cgGetNamedParameter(Vert_Prog, "modelViewMatrix");
globalAmb = cgGetNamedParameter(Vert_Prog, "globalAmbient");
lightColor = cgGetNamedParameter(Vert_Prog, "Eye_And_Light.lightColor");
lightPosition = cgGetNamedParameter(Vert_Prog, "Eye_And_Light.lightPos");
eyePosition = cgGetNamedParameter(Vert_Prog, "Eye_And_Light.eyePos");
Ke = cgGetNamedParameter(Vert_Prog, "material.Ke");
Ka = cgGetNamedParameter(Vert_Prog, "material.Ka");
Kd = cgGetNamedParameter(Vert_Prog, "material.Kd");
Ks = cgGetNamedParameter(Vert_Prog, "material.Ks");
shininess = cgGetNamedParameter(Vert_Prog, "material.shininess");
/* 値の設定*/
cgSetParameter3fv(globalAmb,myGlobalAmb);
/* 視点と光源の設定 */
cgSetParameter4fv(eyePosition, look_at);
cgSetParameter4fv(lightPosition, light_position);
cgSetParameter3fv(lightColor,myLightColor);
/* 材質パラメータ */
cgSetParameter3fv(Ke, Emissive);
cgSetParameter3fv(Ka, Ambient);
cgSetParameter3fv(Kd, Diffuse);
cgSetParameter3fv(Ks, Specular);
cgSetParameter1f(shininess, Shininess);
}
/********* フラグメントのセットアップ *************/
CGprofile Frag_Prof;//フラグメント
CGprogram Frag_Prog;
void SET_UP_CG_FRAGMENT()
{
Frag_Prof = cgGLGetLatestProfile(CG_GL_FRAGMENT);
if(Frag_Prof == CG_PROFILE_UNKNOWN)
{
cout << "Fragment : profile is unknown" << endl;
exit(0);
}
cgGLSetOptimalOptions(Frag_Prof);
Frag_Prog =
cgCreateProgramFromFile(
Cg_Cont,//コンテキスト
CG_SOURCE,//Cgソースコード
"fragment.cg", //「.cgファイル名」
Frag_Prof, //プロファイル
"Cg_Fragment_Main", //「.cgファイル」で最初にいく関数
NULL); //NULLでよい
cgGLLoadProgram(Frag_Prog);
if(Frag_Prog==NULL)
{
CGerror Error = cgGetError();
cout << cgGetErrorString(Error) << endl;
exit(0);
}
}
/************* [メイン関数] ***************/
int main(int argc,char **argv)
{
glutInit(&argc,argv);
GLUT_INIT();
glutCreateWindow("Cg with OpenGL");
GLUT_CALL_FUNC();
MY_INIT();
CG_INIT();//Cgセットアップ
glutMainLoop();
return 0;
}
/*********[ここから、各種コールバック]*************/
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(3.0, 4.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
cgGLSetStateMatrixParameter(modelview,CG_GL_MODELVIEW_PROJECTION_MATRIX,CG_GL_MATRIX_IDENTITY);
DRAW_XYZ();
/*Cgの有効化*/
cgGLBindProgram(Vert_Prog);
cgGLEnableProfile(Vert_Prof);
cgGLBindProgram(Frag_Prog);
cgGLEnableProfile(Frag_Prof);
glutSolidSphere(0.5,30,30);
cgGLDisableProfile(Vert_Prof);
cgGLDisableProfile(Frag_Prof);
glutSwapBuffers();
}
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(30.0, (double)w / (double)h, 1.0, 100.0);
glMatrixMode(GL_MODELVIEW);
}
/********** ここから、各種関数 ****************/
void DRAW_XYZ()
{
glBegin(GL_LINES);
glColor3d(0,1,0);//x
glVertex2d(-100,0);
glVertex2d(100, 0);
glColor3d(1,0,0);//y
glVertex2d(0,0);
glVertex2d(0,100);
glColor3d(0,0,1);//z
glVertex3d(0,0,-100);
glVertex3d(0,0, 100);
glEnd();
}
uniform型を構造体にまとめて引数にする場合、
[1]:構造体として普通に定義。
struct MATERIAL //各種係数
{
float3 Ke;
float3 Ka;
float3 Kd;
float3 Ks;
float shininess;
};
[2]:引数の時、uniformを追加する。
VERTEX_DATA_OUT Cg_Main(... ,uniform MATERIAL material, ...)
{
... ...
float3 ambient = material.Ka * globalAmbient; //環境光計算
... ...
}
また、「cppファイル」での名前の関連付けも以下のように「.cgファイル」で記述するものに合わせる必要がある。
Ke = cgGetNamedParameter(Vert_Prog, "material.Ke");
Ka = cgGetNamedParameter(Vert_Prog, "material.Ka");
Kd = cgGetNamedParameter(Vert_Prog, "material.Kd");
Ks = cgGetNamedParameter(Vert_Prog, "material.Ks");
shininess = cgGetNamedParameter(Vert_Prog, "material.shininess");