Forum Replies Created
-
AuthorPosts
-
CheapMeowParticipant
用面积计算是合适的
比如我这里使用面积计算重心坐标,可以得到预期的效果
static std::tuple<float, float, float> computeBarycentric2D(float x, float y, const Vector4f* v){ Eigen::Vector2f p(x, y); Eigen::Vector2f tri_node_coords[3]; for (int i = 0; i < 3; ++i) { tri_node_coords[i] = v[i].head<2>(); } Eigen::Vector2f edge_1, edge_2; float s_sub_tri[3]; for (int i = 0; i < 3; ++i) { edge_1 = tri_node_coords[(i + 1) % 3] - p; edge_2 = tri_node_coords[(i + 2) % 3] - p; s_sub_tri[i] = edge_1.x() * edge_2.y() - edge_2.x() * edge_1.y(); } float s_sum = 0; for (int i = 0; i < 3; ++i) { s_sum += s_sub_tri[i]; } return { s_sub_tri[0] / s_sum, s_sub_tri[1] / s_sum, s_sub_tri[2] / s_sum }; }
如果担心计算出来的重心坐标为负会不会不正确,那么可以试着在 rasterize_triangle() 光栅化三角形的时候就剔除掉那些重心坐标为负的点
void rst::rasterizer::rasterize_triangle(const Triangle& t, const std::array<Eigen::Vector3f, 3>& view_pos) { int x_screen_min = width - 1; int x_screen_max = 0; int y_screen_min = height - 1; int y_screen_max = 0; for (int i = 0; i < 3; i++) { x_screen_min = std::min(x_screen_min, (int)t.v[i][0]); y_screen_min = std::min(y_screen_min, (int)t.v[i][1]); x_screen_max = std::max(x_screen_max, (int)t.v[i][0]); y_screen_max = std::max(y_screen_max, (int)t.v[i][1]); } // temp var Eigen::Vector3f interpolated_color; Eigen::Vector3f interpolated_normal; Eigen::Vector2f interpolated_texcoords; Eigen::Vector3f interpolated_shadingcoords; for (int x = x_screen_min; x <= x_screen_max; ++x) { for (int y = y_screen_min; y <= y_screen_max; ++y) { if (insideTriangle(x + 0.5f, y + 0.5f, t.v)) { auto [alpha, beta, gamma] = computeBarycentric2D(x + 0.5f, y + 0.5f, t.v); if (alpha < 0.0f || alpha > 1.0f) continue; if (beta < 0.0f || beta > 1.0f) continue; if (gamma < 0.0f || gamma > 1.0f) continue;
可见,在模型的每一个三角面的边上显示出缝隙
也就是说,重心坐标为负的点也可能位于三角形的边上
如果去掉了这些点,就相当于在三角形的边上没有颜色,那么渲染出来的就会在模型的每一个三角面的边上显示出缝隙
所以只要你的 insideTriangle() 写对了,就不需要考虑 computeBarycentric2D() 算出来的重心坐标为负还是为正
Attachments:
You must be logged in to view attached files.CheapMeowParticipant个人理解是,我们已经固定了:
摄像机的中心:世界坐标原点
摄像机的前方向 g:-Z 方向
摄像机的上方向 t:Y 方向
在计算光线的时候,我们就是默认相机是这样固定的,不然我们在考虑光线的时候,我们还需要把相机的位置和角度纳入计算中,更麻烦了
所以光线的计算是在观察空间中的,所以 viewspace_pos 是三角形顶点坐标经过 MV 变换之后的观察空间的坐标
而 shader 中的光源的位置就是写死了观察空间中的位置
感觉实际中光源的位置也是一个传入的值,或许也是需要经过变换的,但是在这个 shader 里为了简单就写死了
参考:
CheapMeowParticipant在 main 函数中,一开始定义了 pos 和 ind,然后 load 之后得到 pos_id 和 ind_id
之后的循环之中没有更改 pos_id 和 ind_id,那么显然,一开始得到的 pos_id 和 ind_id 就是三角形的 pos 和 ind
再看具体是怎么用这个 pos_id 和 ind_id 的,他是在光栅化器的 draw 函数中用的,用在 pos_buf 和 ind_buf
auto& buf = pos_buf[pos_buffer.pos_id]; auto& ind = ind_buf[ind_buffer.ind_id];
然后之后的功能都是根据这个取出来的 buf 和 ind
那么再看位置缓冲和顶点缓冲的定义:
std::map<int, std::vector<Eigen::Vector3f>> pos_buf; std::map<int, std::vector<Eigen::Vector3i>> ind_buf;
map 里面一个 id 对应一个 vector
对于 pos_buf 是一个 id 对应一个 std::vector<Eigen::Vector3f>,根据常识以及之前 main 函数中的初始化写法可以知道,这里就是给了三个点的坐标的值,坐标用 Eigen::Vector3f 表示
对于 ind_buf 同理,就是一个 id 对应三个顶点的序号
这就很容易理解了。对于只有一个三角形的情况,这里取出来的 buf 和 ind 就是第一个三角形三个点的坐标的值,三个顶点的序号
CheapMeowParticipant这个报错的意思是,不能列表初始化结构体。
感觉可能是因为你使用的 C++ 版本比较旧?
我也搜到了一些相关的描述:
https://www.cppblog.com/jinq0123/archive/2016/12/12/214479.html在这里提到了在结构体中初始化错误的理由:
https://www.geeksforgeeks.org/structures-in-cpp/当声明数据类型时,不会为其分配内存。仅在创建变量时分配内存。
但是在 C++ 中是可以这么写的
所以综合来看更像是不同 C++ 版本下的差异……?
- This reply was modified 1 year, 7 months ago by CheapMeow. Reason: Add discription for error
CheapMeowParticipant就像楼上说的,出错在 rasterizer.cpp 的 set_pixel
如果 x 和 y 同时为 0,ind 此时等于 height * width,但是数组范围为 [0, height * width – 1],因此出现了越界
解决方法是不允许 x 和 y 同时为 0,也就是把小于号改成小于等于号
void rst::rasterizer::set_pixel(const Eigen::Vector3f& point, const Eigen::Vector3f& color) { //old index: auto ind = point.y() + point.x() * width; if (point.x() <= 0 || point.x() >= width || point.y() <= 0 || point.y() >= height) return; // if point.x() == 0 and point.y() == 0 // then get ind == height * width // but size of frame_buf == height * width // so available index of frame_buf is [0, height * width - 1] // so don't allow point.x() == 0 and point.y() == 0 auto ind = (height-point.y())*width + point.x(); frame_buf[ind] = color; }
-
AuthorPosts