设计自己的软渲染器-附代码相关
程序员文章站
2022-06-11 08:10:38
...
本系列github代码库地址
https://github.com/YIWANFENG/MiniRenderer
本系列可运行项目下载地址
http://download.csdn.net/download/hffhjh111/10210438
一些的参考资料
大牛Blog:
https://www.davrous.com/2013/06/13/tutorial-series-learning-how-to-write-a-3d-soft-engine-from-scratch-in-c-typescript-or-javascript/
http://www.cnblogs.com/QG-whz/p/4644213.html?utm_source=tuicool
加载从Blender导出的Json格式模型
将相应Jsoncpp的C++头文件与源文件加入工程后稍加调整,或者你自己配置Json库。
添加下列读取函数
int ReadJsonFromFile(const char* filename, Mesh &mesh)
{
Json::Reader reader;// 解析json用Json::Reader
Json::Value root; // Json::Value是一种很重要的类型,可以代表任意类型。如int, string, object, array
std::ifstream is;
is.open(filename, std::ios::binary);
if (reader.parse(is, root, 0))
{
std::string mesh_name;
//Mesh mesh;
int mesh_count = 0;
if (!root["meshes"].isNull()) // 访问节点,Access an object value by name, create a null member if it does not exist.
mesh_count = root["meshes"].size();
for (int i = 0; i < mesh_count; i++) {
int vertices_count = root["meshes"][i]["vertices"].size();
int faces_count = root["meshes"][i]["indices"].size();
int uvCount = root["meshes"][i]["uvCount"].asInt();
int ver_span = 1; //每个顶底跨距
int face_span = 3; //每个面跨距
switch (uvCount)
{
case 0:
ver_span = 6;
break;
case 1:
ver_span = 8;
break;
case 2:
ver_span = 10;
break;
}
mesh.face_count = faces_count / face_span;
mesh.vertex_count = vertices_count / ver_span;
mesh.vertices = new Vertex[mesh.vertex_count];
mesh.faces = new Face[mesh.face_count];
//解析顶点
Json::Value vertices = root["meshes"][i]["vertices"];
for (int j = 0; j < mesh.vertex_count; j++) {
// 加载Blender导出的顶点
mesh.vertices[j].WorldCoordinates.x = vertices[j*ver_span].asDouble();
mesh.vertices[j].WorldCoordinates.y = vertices[j*ver_span + 1].asDouble();
mesh.vertices[j].WorldCoordinates.z = vertices[j*ver_span + 2].asDouble();
mesh.vertices[j].WorldCoordinates.w = 1.0f;
// 加载Blender导出的顶点法线
mesh.vertices[j].Normal.x = vertices[j*ver_span + 3].asDouble();
mesh.vertices[j].Normal.y = vertices[j*ver_span + 4].asDouble();
mesh.vertices[j].Normal.z = vertices[j*ver_span + 5].asDouble();
mesh.vertices[j].Normal.w = 1.0f;
}
//解析面
Json::Value faces = root["meshes"][i]["indices"];
for (int j = 0; j < mesh.face_count; j++) {
mesh.faces[j].v1 = faces[j*face_span].asInt();
mesh.faces[j].v2 = faces[j*face_span + 1].asInt();
mesh.faces[j].v3 = faces[j*face_span + 2].asInt();
}
//解析设置的mesh位置
Json::Value js_position = root["meshes"][i]["position"];
int k = 0;
mesh.Position.x = js_position[k].asDouble();
mesh.Position.y = js_position[1].asDouble();
mesh.Position.z = js_position[2].asDouble();
}
}
is.close();
return 0;
}
加载纹理图片
使用opencv3
void Texture::Load(const char *filename) {
buf = cv::imread(filename);
width = buf.size().width;
height = buf.size().height;
//cv::imshow("buf", buf);
}
Color Texture::Map(float tu, float tv) {
Color re;
re.Set(0x00000000, 1.0f); //默认为黑
if (buf.empty()) return re;
int u = (int)(tu*width) % width; //%为防止复用
int v = (int)(tv*height) % height;
if (u<0 || v<0)
cout << tu << ' ' << tv << endl;
u = u >= 0 ? u : -u;
v = v >= 0 ? v : -v;
cv::Vec3b tex_w = buf.at<cv::Vec3b>(v, u); //U是X,V是Y
re.argb[3] = 0x00;
re.argb[0] = tex_w[0]; //B
re.argb[1] = tex_w[1]; //G
re.argb[2] = tex_w[2]; //R
return re;
}
PS:回到家里,真的是一点都不想再整理,所以就使用了原始的笔记。
考研结果如何,充满了纠结。
处在这种时间,真是尴尬。
推荐阅读