简单的shader渲染带纹理的OBJ文件

鉴于网上的资料较为零散,这里总结一个自用的文章好了。

1.一些基础操作

这个博客介绍的非常详细,学习或者查阅可以翻看。

http://blog.csdn.net/wangdingqiaoit/article/details/51457675

2.这里介绍一个网上写的工具类GLFundamentals.hpp,里面有很多定义好的功能,很方便,我等下上传到这里

 2.1 读写shader

方法一。使用工具类

直接包含就可以了,当然openGL的环境自己配置好

GLuint program = gl::init_program("vertex.glsl", "fragment.glsl")

这里vertex.glsl和fragment.glsl是单独的shader文本文件,上面的一句话直接实现了①指针指向shader ②compile shader ③创建program ④link shader ⑤返回当前program

方法二。将shader简单直接写到cpp文件中,适合简单的shader脚本。举个栗子

#define VPROG_SRC_TEX(ver)									\
	ver											\
	"layout(location = 0) in vec3 pos1;\n"							\
	"layout(location = 2) in vec2 vTexCoord;\n"						\
	"\n"											\
	" out vec2 fTexCoord;\n"								\
	"\n"											\
	"uniform mat4 worldMatrix;\n"								\
	"uniform mat4 projMatrix;\n"								\
	"\n"											\
	"void main()\n"										\
	"{\n"											\
	"	gl_Position = (projMatrix * worldMatrix) * vec4(pos1,1);\n"	                \
	"	fTexCoord = vTexCoord;\n"							\
	"}\n"											\

static const char* kGlesVProgTex	= VPROG_SRC_TEX("#version 330\n");

#undef VPROG_SRC_TEX

#define FSHADER_SRC_TEX(ver)						\
	ver								\
	"uniform sampler2D DiffuseTexture;\n"				\
	"in vec2 fTexCoord;\n"						\
	" out vec4 fragColor;\n"					\
	"\n"								\
	"void main()\n"							\
	"{\n"								\
	"vec4 tD = texture(DiffuseTexture,  fTexCoord);\n"\
	"fragColor.rgb = vec3(tD);\n"					\
	"fragColor.a = tD.a;\n"						\
	"}\n"								\

static const char* kGlesFShaderTex	= FSHADER_SRC_TEX("#version 330\n");
#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 \ncode: %s\n",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,唔准确说是只读取diffuseTexture,像什么高光啊之类的自己再多读取并绑定一下就好了

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\n");
	//将图像内存用作纹理信息
	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\n");
	return texture_ID;
}
上面的是读取图片、绑定并返回ID。用到了openCV来读取的,当然也可以用SOIL,devIL之类的都可以,只要能获得图像指针就ok。

接下来解析OBJ,并绑定到buffer中

tag3DModel ImportOBJModel(string objName){
    // LogToFile::log("errorcpp.txt","start do ImportOBJModel\n");
    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\n",tinfo.strName.c_str());
                GLuint texture_ID = LoadModelTexture(tinfo.strName);
                // LogToFile::log("errorcpp.txt","end u\n");
                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\n",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\n",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\n",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\n",newNormal.x,newNormal.y,newNormal.z);
                    t3DModel.m_normal.push_back(newNormal);
                }
                break;
            }
            case 'f':{  //v/t/n
                //LogToFile::log("errorcpp.txt","f\n");
                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\n",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\n",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\n",tIdx,sTemp.c_str());
                sTemp = s1.substr(pos1+1);
                nIdx = atoi(sTemp.c_str());
                //LogToFile::log("errorcpp.txt","%d %s\n",nIdx,sTemp.c_str());
                //LogToFile::log("errorcpp.txt","f %d/%d/%d ",vIdx,tIdx,nIdx);
                 //LogToFile::log("errorcpp.txt","m_pos size = %d\n",t3DModel.m_pos.size());
                std::map<tVertInfo, unsigned int>::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<tVertInfo, unsigned int>::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 \n",vIdx,tIdx,nIdx);
                 std::map<tVertInfo, unsigned int>::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\n");
    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’的时候代码不优美,改成循环处理就可以了,我是不会告诉你我懒得改了,hiahiahia~~~然后里面的结构体可以自己随便定义,包含想要的信息就好了。

调用只需要短短的2步:

tag3DModel t3DModel = ImportOBJModel("textured.obj");
drawModel(t3DModel,g_Word2Cam,g_ProjMat);

4.TIPS

写shader时候出错很难检查,建议用glGetShaderInfoLog来检查,事半功倍。然后LogToFile文件是写的一个将error写进文本文件的一个辅助类工具,大家可以删掉直接cout或print

读取纹理的UV时,由于坐标系不同的原因,V坐标是相反的,所以读取时候需要1-V

MyOpenGLUtil.h

LogToFile.h


差不多了,有什么遗漏的以后再补。。。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值