テクスチャ付きOBJファイルを簡単なshaderでレンダリング
14833 ワード
ネット上の資料がばらばらであることを考慮して、ここでは自分で使う文章をまとめたほうがいい.
1.いくつかの基礎操作
このブログはとても詳しくて、勉強したり調べたりして見ることができます.
http://blog.csdn.net/wangdingqiaoit/article/details/51457675
2.ここではネット上で書かれたツール類GLFundamentals.hppを紹介します.定義された機能がたくさん入っていて、便利です.後でここにアップロードします.
2.1リードライトシェーダー
方法1.ツールクラスの使用
直接含めるだけでいいです.もちろんopenGLの環境は自分で配置します.
ここでvertex.glslとfragment.glslは別々のshaderテキストファイルであり、上記の一言で直接①ポインタがshaderを指す②compile shader③プログラムを作成する④link shader⑤現在のプログラムに戻る
方法2.shaderをcppファイルに簡単に直接書き、簡単なshaderスクリプトに適しています.くりを一つあげる
フォーマットはやや醜いが,次は本文だ
3.OBJの読み出し
OBJというフォーマットは分かりやすく、ネットでも詳しく説明されています.簡単なmeshであれば、頂点posとindexだけを読めばいいのですが、次は私が書いたUtilで、テクスチャ付きのOBJを読めます.
次にOBJを解析し、bufferにバインドします.
「f」を扱うときはコードが美しくなく、ループ処理に変えればいいのですが、私は直すのがおっくうだとは言いません.hiahiiahia~~~そして中の構造体は自分で勝手に定義して、欲しい情報を含んでいればいいのです.
呼び出しにはわずか2ステップしかかかりません.
4.TIPS
シェーダーを書くときにエラーをチェックするのは難しいので、glGetShaderInfoLogでチェックすることをお勧めします.それからLogToFileファイルはerrorをテキストファイルに書く補助クラスツールで、直接coutやprintを削除することができます.
テクスチャのUVを読み取る場合、座標系が異なるため、V座標は逆になりますので、1-Vが必要です
MyOpenGLUtil.h
LogToFile.h
差は多くありませんが、何か漏れがあったら後で補充します...
1.いくつかの基礎操作
このブログはとても詳しくて、勉強したり調べたりして見ることができます.
http://blog.csdn.net/wangdingqiaoit/article/details/51457675
2.ここではネット上で書かれたツール類GLFundamentals.hppを紹介します.定義された機能がたくさん入っていて、便利です.後でここにアップロードします.
2.1リードライトシェーダー
方法1.ツールクラスの使用
直接含めるだけでいいです.もちろんopenGLの環境は自分で配置します.
GLuint program = gl::init_program("vertex.glsl", "fragment.glsl")
ここでvertex.glslとfragment.glslは別々のshaderテキストファイルであり、上記の一言で直接①ポインタがshaderを指す②compile shader③プログラムを作成する④link shader⑤現在のプログラムに戻る
方法2.shaderをcppファイルに簡単に直接書き、簡単なshaderスクリプトに適しています.くりを一つあげる
#define VPROG_SRC_TEX(ver) \
ver \
"layout(location = 0) in vec3 pos1;
" \
"layout(location = 2) in vec2 vTexCoord;
" \
"
" \
" out vec2 fTexCoord;
" \
"
" \
"uniform mat4 worldMatrix;
" \
"uniform mat4 projMatrix;
" \
"
" \
"void main()
" \
"{
" \
" gl_Position = (projMatrix * worldMatrix) * vec4(pos1,1);
" \
" fTexCoord = vTexCoord;
" \
"}
" \
static const char* kGlesVProgTex = VPROG_SRC_TEX("#version 330
");
#undef VPROG_SRC_TEX
#define FSHADER_SRC_TEX(ver) \
ver \
"uniform sampler2D DiffuseTexture;
" \
"in vec2 fTexCoord;
" \
" out vec4 fragColor;
" \
"
" \
"void main()
" \
"{
" \
"vec4 tD = texture(DiffuseTexture, fTexCoord);
"\
"fragColor.rgb = vec3(tD);
" \
"fragColor.a = tD.a;
" \
"}
" \
static const char* kGlesFShaderTex = FSHADER_SRC_TEX("#version 330
");
#undef FSHADER_SRC_TEX
このようにshaderのポインタを直接得て、それからいつものやり方ですstatic GLuint CreateShader(GLenum type, const char* text)
{
GLuint ret = glCreateShader(type);
glShaderSource(ret, 1, &text, NULL);
glCompileShader(ret);
GLint compileResult = GL_TRUE;
glGetShaderiv(ret,GL_COMPILE_STATUS,&compileResult);
if(compileResult == GL_FALSE){
char szLog[1024] = {0};
GLsizei logLen = 0;
glGetShaderInfoLog(ret,1024,&logLen,szLog);
LogToFile::log("shaderError.txt","log: %s
code: %s
",szLog,text);
}
return ret;
}
g_VProg_tex = CreateShader(GL_VERTEX_SHADER, kGlesVProgTex);
g_FShader_tex = CreateShader_temp(GL_FRAGMENT_SHADER, kGlesFShaderTex);
g_Program_tex = glCreateProgram();
//glBindAttribLocation(g_Program_tex, 0, "pos1");
//glBindAttribLocation(g_Program_tex, 2, "fTexCoord");
glAttachShader(g_Program_tex, g_VProg_tex);
glAttachShader(g_Program_tex, g_FShader_tex);
//glBindFragDataLocation(g_Program_tex, 0, "fragColor");
glLinkProgram(g_Program_tex);
フォーマットはやや醜いが,次は本文だ
3.OBJの読み出し
OBJというフォーマットは分かりやすく、ネットでも詳しく説明されています.簡単なmeshであれば、頂点posとindexだけを読めばいいのですが、次は私が書いたUtilで、テクスチャ付きのOBJを読めます.
GLuint LoadModelTexture(string filename){
GLuint texture_ID;
Mat I = imread(filename);
//
int width = I.cols;
int height = I.rows;
//
GLubyte* pixels;
//
int pixellength = width*height * 3;
pixels = new GLubyte[pixellength];
memcpy(pixels, I.data, pixellength*sizeof(char));
// texture_ID 2D
glGenTextures(1, &texture_ID);
glBindTexture(GL_TEXTURE_2D, texture_ID);
//
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//LogToFile::log("errorcpp.txt","LoadModelTexture1
");
//
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, pixels);
// free(pixels);
delete [] pixels;
//LogToFile::log("errorcpp.txt","LoadModelTexture2
");
return texture_ID;
}
の上には、画像を読み取り、バインドしてIDを返します.OpenCVを使って読み取ったものは、もちろんSOIL、devILなどでもいいですが、画像ポインタが得られればOKです.次にOBJを解析し、bufferにバインドします.
tag3DModel ImportOBJModel(string objName){
// LogToFile::log("errorcpp.txt","start do ImportOBJModel
");
tag3DModel t3DModel;
std::ifstream fin(objName.c_str());
char chkeyword = 0;
string s,s1,s2,s3;
while (getline(fin, s)){
istringstream in(s);
string sNAN;
chkeyword = s[0];
switch(chkeyword){
case 'm':
{
t3DModel.bIsTextured = true;
break;
}
case 'u':{
t3DObject t3DObj;
//
string s1 = s.substr(7); //"usemtl "
tagMaterialInfo tinfo;
tinfo.strName = "textured_" + s1 + "_map_Kd.png";
//LogToFile::log("errorcpp.txt","strName = %s
",tinfo.strName.c_str());
GLuint texture_ID = LoadModelTexture(tinfo.strName);
// LogToFile::log("errorcpp.txt","end u
");
tinfo.ID = texture_ID;
t3DModel.tMatInfoVec.push_back(tinfo);
t3DObj.nMaterialID = texture_ID;
t3DModel.t3DObjVec.push_back(t3DObj);
t3DModel.objCount++;
break;
}
case 'v':{
chkeyword = s[1];
if(chkeyword == ' '){
vec3 vNewVert;
in>>sNAN>>s1>>s2>>s3;
//LogToFile::log("errorcpp.txt","%s %s %s
",s1.c_str(),s2.c_str(),s3.c_str());
vNewVert.x = atof(s1.c_str());
vNewVert.y = -atof(s2.c_str());
vNewVert.z = -atof(s3.c_str());
// LogToFile::log("errorcpp.txt","v %f %f %f
",vNewVert.x,vNewVert.y,vNewVert.z);
t3DModel.m_pos.push_back(vNewVert);
}else if(chkeyword == 't'){
in>>sNAN>>s1>>s2;
vec2 newTex;
newTex.u = atof(s1.c_str());
newTex.v =1.0 - atof(s2.c_str());
//LogToFile::log("errorcpp.txt","vt %f %f
",newTex.u,newTex.v);
t3DModel.m_texcoord.push_back(newTex);
}else if(chkeyword == 'n'){
in>>sNAN>>s1>>s2>>s3;
vec3 newNormal;
newNormal.x = atof(s1.c_str());
newNormal.y = atof(s2.c_str());
newNormal.z = atof(s3.c_str());
//LogToFile::log("errorcpp.txt","vn %f %f %f
",newNormal.x,newNormal.y,newNormal.z);
t3DModel.m_normal.push_back(newNormal);
}
break;
}
case 'f':{ //v/t/n
//LogToFile::log("errorcpp.txt","f
");
t3DObject *pCurObj = &t3DModel.t3DObjVec[t3DModel.objCount-1];
unsigned int vIdx = 0, tIdx = 0, nIdx = 0;
vec3 vPosVert;
vec2 vTexcoord;
vec3 vNormal;
size_t nDistance = 0;
in>>sNAN>>s1>>s2>>s3;
string pattern = "/";
//LogToFile::log("errorcpp.txt","%s %s %s
",s1.c_str(),s2.c_str(),s3.c_str());
int pos = s1.find(pattern.c_str(),0);
string sTemp = s1.substr(0,pos);
vIdx = atoi(sTemp.c_str());
// LogToFile::log("errorcpp.txt","%d %s
",vIdx,sTemp.c_str());
int pos1 = s1.find(pattern.c_str(),pos+1);
sTemp = s1.substr(pos+1,pos1-pos-1);
tIdx = atoi(sTemp.c_str());
//LogToFile::log("errorcpp.txt","%d %s
",tIdx,sTemp.c_str());
sTemp = s1.substr(pos1+1);
nIdx = atoi(sTemp.c_str());
//LogToFile::log("errorcpp.txt","%d %s
",nIdx,sTemp.c_str());
//LogToFile::log("errorcpp.txt","f %d/%d/%d ",vIdx,tIdx,nIdx);
//LogToFile::log("errorcpp.txt","m_pos size = %d
",t3DModel.m_pos.size());
std::map::iterator pFindPos
= t3DModel.m_VObjectIndexMap.find(tVertInfo(t3DModel.m_pos[vIdx - 1], t3DModel.m_texcoord[tIdx - 1], t3DModel.m_normal[nIdx - 1]));
if(t3DModel.m_VObjectIndexMap.end() != pFindPos)
{
pCurObj->Indexes.push_back(pFindPos->second);
}else{
pCurObj->PosVerts.push_back(t3DModel.m_pos[vIdx - 1]);
pCurObj->Texcoords.push_back (t3DModel.m_texcoord[tIdx - 1]);
pCurObj->Normals.push_back(t3DModel.m_normal[nIdx - 1]);
pCurObj->Indexes.push_back(pCurObj->PosVerts.size()-1);
}
pos = s2.find(pattern.c_str(),0);
sTemp = s2.substr(0,pos);
vIdx = atoi(sTemp.c_str());
pos1 = s2.find(pattern.c_str(),pos+1);
sTemp = s2.substr(pos+1,pos1-pos-1);
tIdx = atoi(sTemp.c_str());
sTemp = s2.substr(pos1+1);
nIdx = atoi(sTemp.c_str());
// pCurObj->PosVerts.push_back(t3DModel.m_pos[vIdx - 1]);
// pCurObj->Texcoords.push_back (t3DModel.m_texcoord[tIdx - 1]);
// pCurObj->Normals.push_back(t3DModel.m_normal[nIdx - 1]);
// pCurObj->Indexes.push_back(pCurObj->PosVerts.size()-1);
//LogToFile::log("errorcpp.txt"," %d/%d/%d ",vIdx,tIdx,nIdx);
std::map::iterator pFindPos1
= t3DModel.m_VObjectIndexMap.find(tVertInfo(t3DModel.m_pos[vIdx - 1], t3DModel.m_texcoord[tIdx - 1], t3DModel.m_normal[nIdx - 1]));
if(t3DModel.m_VObjectIndexMap.end() != pFindPos1)
{
pCurObj->Indexes.push_back(pFindPos1->second);
}else{
pCurObj->PosVerts.push_back(t3DModel.m_pos[vIdx - 1]);
pCurObj->Texcoords.push_back (t3DModel.m_texcoord[tIdx - 1]);
pCurObj->Normals.push_back(t3DModel.m_normal[nIdx - 1]);
pCurObj->Indexes.push_back(pCurObj->PosVerts.size()-1);
}
pos = s3.find(pattern.c_str(),0);
sTemp = s3.substr(0,pos);
vIdx = atoi(sTemp.c_str());
pos1 = s3.find(pattern.c_str(),pos+1);
sTemp = s3.substr(pos+1,pos1-pos-1);
tIdx = atoi(sTemp.c_str());
sTemp = s3.substr(pos1+1);
nIdx = atoi(sTemp.c_str());
// pCurObj->PosVerts.push_back(t3DModel.m_pos[vIdx - 1]);
// pCurObj->Texcoords.push_back (t3DModel.m_texcoord[tIdx - 1]);
// pCurObj->Normals.push_back(t3DModel.m_normal[nIdx - 1]);
// pCurObj->Indexes.push_back(pCurObj->PosVerts.size()-1);
//LogToFile::log("errorcpp.txt"," %d/%d/%d
",vIdx,tIdx,nIdx);
std::map::iterator pFindPos2
= t3DModel.m_VObjectIndexMap.find(tVertInfo(t3DModel.m_pos[vIdx - 1], t3DModel.m_texcoord[tIdx - 1], t3DModel.m_normal[nIdx - 1]));
if(t3DModel.m_VObjectIndexMap.end() != pFindPos2)
{
pCurObj->Indexes.push_back(pFindPos2->second);
}else{
pCurObj->PosVerts.push_back(t3DModel.m_pos[vIdx - 1]);
pCurObj->Texcoords.push_back (t3DModel.m_texcoord[tIdx - 1]);
pCurObj->Normals.push_back(t3DModel.m_normal[nIdx - 1]);
pCurObj->Indexes.push_back(pCurObj->PosVerts.size()-1);
}
break;
}
}
}
//LogToFile::log("errorcpp.txt","allocate buffer
");
for(unsigned int i = 0; i < t3DModel.t3DObjVec.size(); i++)
{
glGenBuffers(1, &t3DModel.t3DObjVec[i].nPosVBO);
glBindBuffer(GL_ARRAY_BUFFER, t3DModel.t3DObjVec[i].nPosVBO);
glBufferData(GL_ARRAY_BUFFER, t3DModel.t3DObjVec[i].PosVerts.size() * sizeof(vec3),
(GLvoid*)&t3DModel.t3DObjVec[i].PosVerts[0], usage);
glGenBuffers(1, &t3DModel.t3DObjVec[i].nNormVBO);
glBindBuffer(GL_ARRAY_BUFFER, t3DModel.t3DObjVec[i].nNormVBO);
glBufferData(GL_ARRAY_BUFFER, t3DModel.t3DObjVec[i].Normals.size() * sizeof(vec3),
(GLvoid*)&t3DModel.t3DObjVec[i].Normals[0], usage);
glGenBuffers(1, &t3DModel.t3DObjVec[i].nTexcoordVBO);
glBindBuffer(GL_ARRAY_BUFFER, t3DModel.t3DObjVec[i].nTexcoordVBO);
glBufferData(GL_ARRAY_BUFFER, t3DModel.t3DObjVec[i].Texcoords.size() * sizeof(vec2),
(GLvoid*)&t3DModel.t3DObjVec[i].Texcoords[0], usage);
glGenBuffers(1, &t3DModel.t3DObjVec[i].nIndexVBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, t3DModel.t3DObjVec[i].nIndexVBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, t3DModel.t3DObjVec[i].Indexes.size() * sizeof(unsigned int),
(GLvoid*)&t3DModel.t3DObjVec[i].Indexes[0], usage);
t3DModel.t3DObjVec[i].nNumIndexes = t3DModel.t3DObjVec[i].Indexes.size();
}
return t3DModel;
}
「f」を扱うときはコードが美しくなく、ループ処理に変えればいいのですが、私は直すのがおっくうだとは言いません.hiahiiahia~~~そして中の構造体は自分で勝手に定義して、欲しい情報を含んでいればいいのです.
呼び出しにはわずか2ステップしかかかりません.
tag3DModel t3DModel = ImportOBJModel("textured.obj");
drawModel(t3DModel,g_Word2Cam,g_ProjMat);
4.TIPS
シェーダーを書くときにエラーをチェックするのは難しいので、glGetShaderInfoLogでチェックすることをお勧めします.それからLogToFileファイルはerrorをテキストファイルに書く補助クラスツールで、直接coutやprintを削除することができます.
テクスチャのUVを読み取る場合、座標系が異なるため、V座標は逆になりますので、1-Vが必要です
MyOpenGLUtil.h
LogToFile.h
差は多くありませんが、何か漏れがあったら後で補充します...