想要代码可以下载我上传的资源:
华南理工大学实验——OpenGL Shader导入3D模型OBJ文件的代码!-CSDN下载 http://download.csdn.net/download/tanshengjunjun/10168498
实 验 报 告 一
(2017-2018学年第一学期)
计算机图形学
(Computer Graphics)
学生姓名:谭声俊 |
学号:201430613253 |
年级,班级:2014级软件1班 |
成绩: |
任课教师签名: |
日期: |
实验题目:OpenGL中的建模和视图显示功能 |
||
目录: 1. 实验内容描述,即模型名称和特点 2. 实验功能算法描述,即模型是如何建立、如何载入、如何观察的 3. 实验shader程序描述,即vertex shader和fragment shader的程序代码及说明 4. 实验结果,要贴实验结果图 5. 心得体会 |
||
实验报告: 1. 模型名称:3D立方体,特点:表面有对角线,有png图片纹理,场景有电光源。 2. 建立:模型通过Blender软件设计完成,导出为OBJ格式文件; 载入:通过ASSIMP:open assimp import library库把OBJ文件对应的点信息转化为OPENGL能读取的顶点和纹理光照材质等信息。 观察方式:相机观察,通过移动鼠标/按键WASD可以观察物体各面或者放大缩小 3. vertex shader的程序代码及说明: #version 330 core layout (location = 0) in vec3 pos;//点数组 layout (location = 1) in vec3 color;//颜色数组 layout (location = 2) in vec2 texCoord;//纹理数组
uniform mat4 model; uniform mat4 view; uniform mat4 projection;
out vec3 color1;//将COLOR传递到fragment shader out vec2 texCoord1;//将textCoord传递到fragment shader
void main()//取色或取位置 { gl_Position =projection * view * model * vec4(pos,1.0); color1 = color; texCoord1 = texCoord; }
fragment shader的程序代码及说明: #version 330 core
in vec3 color1; in vec2 texCoord1;
out vec4 fColor;
uniform sampler2D mytexture;
void main()//取色 { fColor = vec4(color1,1.0) * texture2D(mytexture,texCoord1); } 4. 实验结果图:
5. 心得体会: 学习OPENGL涉及的方面比较多,环境的配置:附加库的复制粘贴,VS2013上环境的配置(链接器输入的库链接到项目),库包含语句。掌握OPENGL shader着色器语言,initshader着色器,以及模型导入源代码。通过BLENDER构建3D图形并导出OBJ文件及其中数据信息的了解。顶点信息的转换。VS BUG、断点工具的使用,程序的调试。 |
实 验 报 告 二
(2017-2018学年第一学期)
计算机图形学
(Computer Graphics)
学生姓名:谭声俊 |
学号:201430613253 |
年级,班级:2014级软件1班 |
成绩: |
任课教师签名: |
日期:2017.11.16 |
实验题目:OpenGL中的光照和纹理功能 |
||
目录: 1. 实验内容描述,即使用的纹理光照描述和特点 2. 实验功能算法描述,即纹理光照材质是如何建立、如何载入、如何使用的 3. 实验shader程序描述,即vertex shader和fragment shader的程序代码及说明 4. 实验结果,要贴实验结果图 5. 心得体会 |
||
实验报告: 1. 纹理使用的是cat_ghost.dds图片,是DDS格式的,是一个顶着白布的小猫,使用的光照为点光源。特点是整张cat_ghost图覆盖立方体的6表面,每个面显示图片的部分。 2. 先用blender软件制作出包含纹理坐标的cube(在其上按步骤添加图片纹理),加入点光源,输出为cube.obj文件,然后往photoshop8.0加入DDS插件,用PS8.0将cat_ghost.png输出为DDS文件存储cat_ghost.dds;在loadObj.cpp主函数中调用自定义的ObjLoader类中的loadFromFile加载cube.obj文件。 //Section1 从obj文件加载数据 std::vector<Vertex> vertData; if (!ObjLoader::loadFromFile("cube.obj", vertData)) { std::cerr << "Could not load obj model, exit now."; std::system("pause"); exit(-1); } 用自定义的texture.h中定义的TextureHelper的loadDDS类加载纹理图片cat_ghost.dds。
下面给出自定义的texture.h中定义的TextureHelper的loadDDS类。 // Section2 准备纹理 GLint textureId = TextureHelper::loadDDS("cat_ghost.dds");//这里注释了这行 static GLuint loadDDS(const char * filename){
/* try to open the file */ std::ifstream file(filename, std::ios::in | std::ios::binary); if (!file){ std::cout << "Error::loadDDs, could not open:" << filename << "for read." << std::endl; return 0; }
/* verify the type of file */ char filecode[4]; file.read(filecode, 4); if (strncmp(filecode, "DDS ", 4) != 0) { std::cout << "Error::loadDDs, format is not dds :" << filename << std::endl; file.close(); return 0; }
/* get the surface desc */ char header[124]; file.read(header, 124);
unsigned int height = *(unsigned int*)&(header[8]); unsigned int width = *(unsigned int*)&(header[12]); unsigned int linearSize = *(unsigned int*)&(header[16]); unsigned int mipMapCount = *(unsigned int*)&(header[24]); unsigned int fourCC = *(unsigned int*)&(header[80]);
char * buffer = NULL; unsigned int bufsize; /* how big is it going to be including all mipmaps? */ bufsize = mipMapCount > 1 ? linearSize * 2 : linearSize; buffer = new char[bufsize]; file.read(buffer, bufsize); /* close the file pointer */ file.close();
unsigned int components = (fourCC == FOURCC_DXT1) ? 3 : 4; unsigned int format; switch (fourCC) { case FOURCC_DXT1: format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; break; case FOURCC_DXT3: format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; break; case FOURCC_DXT5: format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break; default: delete[] buffer; return 0; }
// Create one OpenGL texture GLuint textureID; glGenTextures(1, &textureID);
// "Bind" the newly created texture : all future texture functions will modify this texture glBindTexture(GL_TEXTURE_2D, textureID); glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
unsigned int blockSize = (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) ? 8 : 16; unsigned int offset = 0;
/* load the mipmaps */ for (unsignedint level = 0; level < mipMapCount && (width || height); ++level) { unsigned int size = ((width + 3) / 4)*((height + 3) / 4)*blockSize; glCompressedTexImage2D(GL_TEXTURE_2D, level, format, width, height, 0, size, buffer + offset);
offset += size; width /= 2; height /= 2;
// Deal with Non-Power-Of-Two textures. This code is not included in the webpage to reduce clutter. if (width < 1) width = 1; if (height < 1) height = 1;
}
delete[] buffer;
return textureID; }
3. cube.vertex: #version 330 core
layout(location = 0) in vec3 position;//顶点 layout(location = 1) in vec2 textCoord;//纹理 layout(location = 2) in vec3 normal;//法向量
uniform mat4 projection; uniform mat4 view; uniform mat4 model;
out vec2 TextCoord;
void main() { gl_Position = projection * view * model * vec4(position, 1.0); TextCoord = textCoord; } Cube.frag: #version 330 core
in vec2 TextCoord;//纹理 uniform sampler2D tex;
out vec4 color;
void main() { color = texture(tex, TextCoord); }
4. 实验结果截图:
5.心得体会: 通过这次纹理和光照3D建模过程坎坷,但收获颇多。 首先通过借鉴opengl前辈的csdn博客让自己对技术类博客更为喜爱,同时关注了几位技术前辈。 掌握了配置opengl环境和vs中链接库的操作。 对代码的文件分离编码,组合成同一个项目有了更深的体会,了解了一个文件传输到另一个文件的方法(C++)。进一步掌握了CPP和H文件。 OpenGL建立3D模型作为游戏建模及载入的其中一种思路,对以后大型游戏的开发思想做了一次准备工作。 |
实 验 报 告 三
(2017-2018学年第一学期)
计算机图形学
(Computer Graphics)
小组学生姓名:谭声俊、游镕江 |
||
成绩: |
任课教师签名: |
日期: |
实验题目:OpenGL中的复杂场景和交互功能 |
||
目录: 1. 实验内容描述,即场景名称和特点 2. 实验功能算法描述,即多个模型是如何建立、如何载入、如何观察的 3. 实验shader程序描述,即vertex shader和fragment shader的程序代码及说明 4. 实验结果,要贴实验结果图 5. 心得体会 |
||
实验报告: 1. 实验内容描述: 场景名称:阳光照耀下的圣诞老人盒子和星球(Santa Claus boxes and planets in the sun)。 特点:空间中有10个贴图为圣诞老人的立方体盒子,散乱分布在空间的各个方位,这是第一个OBJ模型,第二个OBJ模型是一个金黄色的球体:星球。 光源处在圣诞老人盒子和星球之间,采用了环境光、漫反射、镜面反射。 由于有点光源,所以模型中不能被点光源直射的部位比能被直射到的部位颜色暗淡些。 2. 实验功能算法描述: 模型建立:都是使用Blender软件建立3D模型,并在其上搞定纹理贴图,输出2个含有纹理坐标的OBJ模型文件(小组两个人各自有1个模型)。 如何载入: 两次调用LoadObjModel.h头文件中定义好的方法ObjLoader::loadFromFile("ballwithtexturecoordinate.obj", vertData), ObjLoader::loadFromFile("圣诞老人盒子.obj", vertData)。
而后,两次调用绘制模型的方法。mesh.draw(shader); // 绘制物体
在空间中绘制出了两个模型物体。 两个模型在空间中共同使用同一个点光源,其中使用了环境光、漫反射、镜面反射 glUniform3f(lightAmbientLoc, 0.5f, 0.5f, 0.5f);//环境光 glUniform3f(lightDiffuseLoc, 0.7f, 0.7f, 0.7f);//漫反射 glUniform3f(lightSpecularLoc, 1.0f, 1.0f, 1.0f);//镜面反射 观察方式: 相对于对象标架移动照相机。 glm::mat4 projection = glm::perspective(camera.mouse_zoom, (GLfloat)(WINDOW_WIDTH) / WINDOW_HEIGHT, 1.0f, 100.0f);//投影矩阵 glm::mat4 view = camera.getViewMatrix();//视变换矩阵 3.vertex shader和fragment shader的程序代码及说明 cube.frag: #version 330
in vec3 FragPos; in vec2 TextCoord; in vec3 FragNormal;
out vec4 color;
// 材质属性结构体 struct MaterialAttr { sampler2D diffuseMap; // 使用纹理对象根据片元位置取不同的材质属性 sampler2D specularMap; float shininess; //镜面高光系数 }; // 光源属性结构体 struct LightAttr { vec3 position; vec3 ambient; vec3 diffuse; vec3 specular;
float constant; // 衰减常数 float linear; // 衰减一次系数 float quadratic; // 衰减二次系数 };
uniform MaterialAttr material; uniform LightAttr light; uniform vec3 viewPos;
void main() { // 环境光成分 vec3 ambient = light.ambient * vec3(texture(material.diffuseMap, TextCoord));
// 漫反射光成分 此时需要光线方向为指向光源 vec3 lightDir = normalize(light.position - FragPos); vec3 normal = normalize(FragNormal); float diffFactor = max(dot(lightDir, normal), 0.0); vec3 diffuse = diffFactor * light.diffuse * vec3(texture(material.diffuseMap, TextCoord));
// 镜面反射成分 此时需要光线方向为由光源指出 float specularStrength = 0.5f; vec3 reflectDir = normalize(reflect(-lightDir, normal)); vec3 viewDir = normalize(viewPos - FragPos); float specFactor = pow(max(dot(reflectDir, viewDir), 0.0), material.shininess); vec3 specular = specFactor * light.specular * vec3(texture(material.specularMap, TextCoord));
// 计算衰减因子 float distance = length(light.position - FragPos); // 在世界坐标系中计算距离 float attenuation = 1.0f / (light.constant + light.linear * distance + light.quadratic * distance * distance);
vec3 result = (ambient + diffuse + specular) * attenuation; color = vec4(result , 1.0f); }
cube.vertex: #version 330
layout(location = 0) in vec3 position; layout(location = 1) in vec2 textCoord; layout(location = 2) in vec3 normal;
out vec3 FragPos; out vec2 TextCoord; out vec3 FragNormal;
uniform mat4 projection; uniform mat4 view; uniform mat4 model;
void main() { gl_Position = projection * view * model * vec4(position, 1.0); FragPos = vec3(model * vec4(position, 1.0)); // 在世界坐标系中指定片元位置 TextCoord = textCoord; mat3 normalMatrix = mat3(transpose(inverse(model))); FragNormal = normalMatrix * normal; // 计算法向量经过模型变换后值 }
Lamp.frag: #version 330
out vec4 color;
void main() { color = vec4(1.0); }
lamp.vertex: #version 330
layout(location = 0) in vec3 position;
uniform mat4 projection; uniform mat4 view; uniform mat4 model;
void main() { gl_Position = projection * view * model * vec4(position, 1.0); }
4.实验结果,要贴实验结果图 背景黑色能更明显地看清点光源照射到物体的效果,下面的是换成紫色画布背景的: |
||
5实验心得: 一开始还在想怎么整合两个模型(不通过在BLENDER或其他软件上先把模型整合再用程序载入) 而后尝试通过两次调用OBJ文件载入方法成功载入了两个模型,而光源就采用其中一个模型的光源就好,两个模型自己就能共用一个点光源。 同时,模型载入后,绘制模型的方法也是要调用两次,这里在上面的实验报告第1步已经详细说明。 除了这两个地方是需要两次调用已经定义的方法,其它代码都是复用其中一个模型的代码:包括视角变换、窗体调用代码等。 实验3 OpenGL中的复杂场景和交互功能 在前两次实验的基础上,以小组为单位,将小组成员的模型放在一个场景中,要求不同同学的模型的坐标定义要统一,场景有一个地面或环境,场景的灯光也要统一定义,再增加一些交互功能,如鼠标键盘控制视点变化,或菜单控制模型变化(显示或隐藏部分模型),或用Idle回调函数实现动画等。 这个实验的整个代码文件都在解决方案openGL-practice3中“OPENGL实验3整合”的成功整合实现,具体代码可参考该文件夹中的代码或者对应课程文件夹中的代码文件。 PS:非常感谢:http://blog.csdn.net/wangdingqiaoit/article/details/51879737中各个章节对OPENGL知识的深入讲解。 前辈对于OPENGL的讲解对我理解OPENGL建模及贴图、光照等运用有很大的帮助,助我和小组成员成功完成计算机图形学实验。 |
计算机图形学实验123对应代码详见:
https://github.com/tanshengjunjun/-OPENGL-123-