接下来更改一下顶点着色,让这个渲染器更漂亮
首先是数据结构

更改数据结构

typedef struct { point_t pos; color_t color; } vertex_t;

更改顶点输入

vertex_t mesh[8] = {{ { 1, -1,  1, 1 },{ 1.0f, 0.2f, 0.2f } },{ { -1, -1,  1, 1 },{ 0.2f, 1.0f, 0.2f } },{ { -1,  1,  1, 1 },{ 0.2f, 0.2f, 1.0f }},{ { 1,  1,  1, 1 },{ 1.0f, 0.2f, 1.0f } },{ { 1, -1, -1, 1 },{ 1.0f, 1.0f, 0.2f } },{ { -1, -1, -1, 1 },{ 0.2f, 1.0f, 1.0f } },{ { -1,  1, -1, 1 },{ 1.0f, 0.3f, 0.3f }},{ { 1,  1, -1, 1 },{ 0.2f, 1.0f, 0.3f } },
};

更改画三角形算法

void DrawTriangle(vertex_t ve1, vertex_t ve2, vertex_t ve3)
{point_t p1 = ve1.pos;point_t p2 = ve2.pos;point_t p3 = ve3.pos;point_t v1, v2, v3, c1, c2, c3;// 按照 Transform 变化transform_apply(&Transform, &c1, &p1);transform_apply(&Transform, &c2, &p2);transform_apply(&Transform, &c3, &p3);// 归一化transform_homogenize(&Transform, &v1, &c1);transform_homogenize(&Transform, &v2, &c2);transform_homogenize(&Transform, &v3, &c3);if (v1.x == v2.x&&v1.x == v3.x) return;if (v1.y == v2.y&&v1.y == v3.y) return;//DrawLine(v1, v2,c);//DrawLine(v2, v3,c);//DrawLine(v3, v1,c);vector<float> PointY{ v1.y,v2.y,v3.y };sort(PointY.begin(), PointY.end());float midY = PointY[1];float minY = PointY[0];float maxY = PointY[2];vertex_t MaxYPoint;vertex_t MidYPoint;vertex_t MinYPoint;if (midY != minY && midY != maxY){if (midY == v1.y){MidYPoint.pos = v1;MidYPoint.color = ve1.color;if (maxY == v2.y){MaxYPoint.pos= v2;MaxYPoint.color = ve2.color;MinYPoint.pos= v3;MinYPoint.color = ve3.color;}if (maxY == v3.y){MaxYPoint.pos= v3;MaxYPoint.color = ve3.color;MinYPoint.pos= v2;MinYPoint.color = ve2.color;}}else if (midY == v2.y){MidYPoint.pos = v2;MidYPoint.color = ve2.color;if (maxY == v1.y){MaxYPoint.pos = v1;MaxYPoint.color = ve1.color;MinYPoint.pos = v3;MinYPoint.color = ve3.color;}if (maxY == v3.y){MaxYPoint.pos = v3;MaxYPoint.color = ve3.color;MinYPoint.pos = v1;MinYPoint.color = ve1.color;}}else if (midY == v3.y){MidYPoint.pos = v3;MidYPoint.color = ve3.color;if (maxY == v1.y){MaxYPoint.pos = v1;MaxYPoint.color = ve1.color;MinYPoint.pos = v2;MinYPoint.color = ve2.color;}if (maxY == v2.y){MaxYPoint.pos = v2;MaxYPoint.color = ve2.color;MinYPoint.pos = v1;MinYPoint.color = ve1.color;}}vertex_t newV;float t = (midY - maxY) / (minY - maxY);newV.pos.x = interp(MaxYPoint.pos.x, MinYPoint.pos.x, t);newV.pos.y = midY;color_interp(newV.color,MaxYPoint.color, MinYPoint.color, t);DrawTriangle_ScanConversion(MaxYPoint, MidYPoint, newV);DrawTriangle_ScanConversion(MinYPoint, MidYPoint, newV);}else{if (v1.y == v2.y) DrawTriangle_ScanConversion(ve3, ve1, ve2);if (v1.y == v3.y) DrawTriangle_ScanConversion(ve2, ve1, ve3);if (v3.y == v2.y) DrawTriangle_ScanConversion(ve1, ve3, ve2);}
}

接下来更改画线算法,由于代码太多,就不一一贴出
加入画点函数

//画点
void DrawPoint(int x,int y,color_t c)
{glColor4f(c.r, c.g, c.b, c.a);//glColor4f(1, 1, 0,0.5);glVertex2i((int)x, (int)y);
}


发现了几个问题

1.立方体的某些本应被遮挡住的面被绘制在了这个立方体其他面之上,学过opengl,Direct的应该知道些,我们还缺少z缓冲也就是深度信息,
2.如果一直按f会出现视角中物体无法改变的现象

增加视锥裁剪,裁剪不在摄像头视锥内的物体

// 检查齐次坐标同 cvv 的边界用于视锥裁剪
int transform_check_cvv(const vector_t *v) {float w = v->w;int check = 0;if (v->z < 0.0f) check |= 1;if (v->z >  w) check |= 2;if (v->x < -w) check |= 4;if (v->x >  w) check |= 8;if (v->y < -w) check |= 16;if (v->y >  w) check |= 32;return check;
}
void DrawTriangle(vertex_t ve1, vertex_t ve2, vertex_t ve3)
{point_t p1 = ve1.pos;point_t p2 = ve2.pos;point_t p3 = ve3.pos;point_t v1, v2, v3, c1, c2, c3;// 按照 Transform 变化transform_apply(&Transform, &c1, &p1);transform_apply(&Transform, &c2, &p2);transform_apply(&Transform, &c3, &p3);// 裁剪,注意此处可以完善为具体判断几个点在 cvv内以及同cvv相交平面的坐标比例// 进行进一步精细裁剪,将一个分解为几个完全处在 cvv内的三角形if (transform_check_cvv(&c1) != 0) return;if (transform_check_cvv(&c2) != 0) return;if (transform_check_cvv(&c3) != 0) return;// 归一化transform_homogenize(&Transform, &v1, &c1);transform_homogenize(&Transform, &v2, &c2);transform_homogenize(&Transform, &v3, &c3);


裁剪成功

增加深度缓存

博主选择了一种可能非常高耗的方法,就是用vector存储深度信息和颜色信息

//缓存
typedef struct { color_t c = {0 ,0,0,1 }; float depth=INT_MAX; }Buffer_t;
vector<vector<Buffer_t>> _buffer;
void BufferInit()
{Buffer_t _b;vector<Buffer_t> t(SCREEN_WIDTH * 2,_b);_buffer = vector<vector<Buffer_t>>(SCREEN_HEIGHT * 2, t);
}
void BufferUpdate()
{for (int i = 0; i <= SCREEN_HEIGHT; i++){for (int j = 0; j <= SCREEN_WIDTH; j++){_buffer[i][j].depth = INT_MAX;}}
}

缓存初始化

//<<<<<<<<<<<<<<<<<<<<<<<< main >>>>>>>>>>>>>>>>>>>>>>
void main(int argc, char **argv)
{BufferInit();

接下来在重绘函数中加入缓存更新函数

// 重绘函数
void myDisplay(void)
{BufferUpdate();

接下来更改画三角形的算法,需要z,w值传给画线算法以及最终的画点函数

void DrawTrigngleCH(vertex_t &M,point_t v1,point_t c1,vertex_t ve1)
{M.pos = v1;M.pos.z = v1.z;M.pos.w = c1.w;M.color = ve1.color;
}
void DrawTriangle(vertex_t ve1, vertex_t ve2, vertex_t ve3)
{point_t p1 = ve1.pos;point_t p2 = ve2.pos;point_t p3 = ve3.pos;point_t v1, v2, v3, c1, c2, c3;// 按照 Transform 变化transform_apply(&Transform, &c1, &p1);transform_apply(&Transform, &c2, &p2);transform_apply(&Transform, &c3, &p3);// 裁剪,注意此处可以完善为具体判断几个点在 cvv内以及同cvv相交平面的坐标比例// 进行进一步精细裁剪,将一个分解为几个完全处在 cvv内的三角形if (transform_check_cvv(&c1) != 0) return;if (transform_check_cvv(&c2) != 0) return;if (transform_check_cvv(&c3) != 0) return;// 归一化transform_homogenize(&Transform, &v1, &c1);transform_homogenize(&Transform, &v2, &c2);transform_homogenize(&Transform, &v3, &c3);if (v1.x == v2.x&&v1.x == v3.x) return;if (v1.y == v2.y&&v1.y == v3.y) return;//DrawLine(v1, v2,c);//DrawLine(v2, v3,c);//DrawLine(v3, v1,c);vector<float> PointY{ v1.y,v2.y,v3.y };sort(PointY.begin(), PointY.end());float midY = PointY[1];float minY = PointY[0];float maxY = PointY[2];vertex_t MaxYPoint;vertex_t MidYPoint;vertex_t MinYPoint;if (midY != minY && midY != maxY){if (midY == v1.y){/*  MidYPoint.pos = v1;MidYPoint.pos.z = c1.z;MidYPoint.color = ve1.color;*/DrawTrigngleCH(MidYPoint,v1,c1, ve1);if (maxY == v2.y){DrawTrigngleCH(MaxYPoint, v2, c2, ve2);DrawTrigngleCH(MinYPoint, v3, c3, ve3);}if (maxY == v3.y){DrawTrigngleCH(MaxYPoint, v3, c3, ve3);DrawTrigngleCH(MinYPoint, v2, c2, ve2);}}else if (midY == v2.y){DrawTrigngleCH(MidYPoint, v2, c2, ve2);if (maxY == v1.y){DrawTrigngleCH(MaxYPoint, v1, c1, ve1);DrawTrigngleCH(MinYPoint, v3, c3, ve3);}if (maxY == v3.y){DrawTrigngleCH(MaxYPoint, v3, c3, ve3);DrawTrigngleCH(MinYPoint, v1, c1, ve1);}}else if (midY == v3.y){DrawTrigngleCH(MidYPoint, v3, c3, ve3);if (maxY == v1.y){DrawTrigngleCH(MaxYPoint, v1, c1, ve1);DrawTrigngleCH(MinYPoint, v2, c2, ve2);}if (maxY == v2.y){DrawTrigngleCH(MaxYPoint, v2, c2, ve2);DrawTrigngleCH(MinYPoint, v1, c1, ve1);}}vertex_t newV;float t = (midY - maxY) / (minY - maxY);newV.pos.x = interp(MaxYPoint.pos.x, MinYPoint.pos.x, t);newV.pos.z= interp(MaxYPoint.pos.z, MinYPoint.pos.z, t);newV.pos.y = midY;newV.pos.w = interp(MaxYPoint.pos.w, MinYPoint.pos.w, t);color_interp(newV.color, MaxYPoint.color, MinYPoint.color, t);DrawTriangle_ScanConversion(MaxYPoint, MidYPoint, newV);DrawTriangle_ScanConversion(MinYPoint, MidYPoint, newV);}else{ve1.pos.z = v1.z;ve2.pos.z = v2.z;ve3.pos.z = v3.z;ve1.pos.w= c1.w;ve2.pos.w= c2.w;ve3.pos.w= c3.w;if (v1.y == v2.y) DrawTriangle_ScanConversion(ve3, ve1, ve2);if (v1.y == v3.y) DrawTriangle_ScanConversion(ve2, ve1, ve3);if (v3.y == v2.y) DrawTriangle_ScanConversion(ve1, ve3, ve2);}
}

画线里也要更新z,w值并传给画点函数由于代码太多就不一一贴出
,接下来是画点函数

还记得视锥裁剪算法吗

// 检查齐次坐标同 cvv 的边界用于视锥裁剪
int transform_check_cvv(const vector_t *v) {float w = v->w;int check = 0;if (v->z < 0.0f) check |= 1;if (v->z >  w) check |= 2;if (v->x < -w) check |= 4;if (v->x >  w) check |= 8;if (v->y < -w) check |= 16;if (v->y >  w) check |= 32;return check;
}

所谓的深度就是w-z

//画点
void DrawPoint(int x,int y,color_t c,float z,float w)
{float d = w - z*w;//glColor4f(1, 1, 0,0.5);if (_buffer[x][y].depth <d){c = _buffer[x][y].c;return;}else{_buffer[x][y].depth =d;_buffer[x][y].c = c;}glColor4f(c.r, c.g, c.b, c.a);glVertex2i(x, y);}

最后上图

暂时想不到别的方法,但先做出来再说,如果大家有什么好的方法,希望能在评论区留言

光栅渲染器(六)着色准备和深度缓存实现相关推荐

  1. [从零构建光栅渲染器] 6. 顶点和片元着色器的工作原理

    [从零构建光栅渲染器] 6. 顶点和片元着色器的工作原理 非常感谢和推荐Sokolov的教程,Sokolov使用500行C++代码实现一个光栅渲染器.教程学习过程非常平滑,从画点.线和三角形开始教学, ...

  2. 光栅渲染器(五)2d-3d坐标系

    前面我们基本完成了光栅渲染器的2d部分,接下来开始光栅渲染器的3d部分吧.不过前面的2d光栅渲染器实际上还有优化的空间,建议大家自己完善一下(实际上,由于博主迫切地想玩3d,实际上漏了很多算法的实现和 ...

  3. 从零开始实现3D软光栅渲染器 (1) 简介

    如何在2D屏幕上表示3D物体?这是学习3D编程必须要搞明白的事情.大家都知道,调用OpenGL的函数,给定三角形的3个顶点位置,颜色,就能在屏幕上画一个三角形,再加载一幅图片,就可以给这个三角形附上纹 ...

  4. [从零构建光栅渲染器] 3.隐藏面剃除 z-buffer(深度缓冲)

    非常感谢和推荐Sokolov的教程,Sokolov使用500行C++代码实现一个光栅渲染器.教程学习过程非常平滑,从画点.线和三角形开始教学,在逐步深入三维变换,投影,再到顶点着色器,片段着色器等等. ...

  5. 用C# Bitmap作为画布写个3D软渲染器

    文章目录 Recoards 记录 图元光栅 Bitmap.SetPixel优化成LockBits/UnlockBits指针操作 Blend Projection 投影 Wireframe 线框 Sci ...

  6. 计算机图形学-光栅渲染概述

    开篇 本篇主要讲的是计算机图形学中比较重要的主题之一,渲染,并且着重于讲述光栅化的渲染方式. 当然,我们要了解光栅渲染这个细分领域(当然这个领域也是及其庞大的),就应该知道它在整个的知识框架中是出于一 ...

  7. SoftRendererRenderPipeline(从迷你光栅化软渲染器的实现看渲染流水线)

    简介 这是可能一篇没有什么实际作用的文章,因为没有任何shader效果实现,整篇文章到最后,我只实现了一个旋转的立方体(o(╯□╰)o,好弱),和游戏引擎渲染的万紫千红的3D世界显得有很大落差,仿佛一 ...

  8. Nvidia发布基于插值光栅化的微分渲染器(DIB-R)生成3D对象模型

    Nvidia研究人员将于本月在温哥华举行的年度神经信息处理系统会议(NeurIPS)上介绍他们的模型. 他们提出了一个完整的基于光栅化的微分渲染器,可以通过分析来计算梯度.当包裹在神经网络周围时,他们 ...

  9. 用C#实现一个简易的软件光栅化渲染器

    这是一个用C#+winform实现的软件光栅化渲染器,今天拿出来与大家分享一下,希望能起到抛砖引玉的作用,给新人一点启发(结构比较简单,注释比较详细^_^),也欢迎司机们拍砖指点和交流~ 目的: 巩固 ...

最新文章

  1. typeScripy-番外篇之命名空间和模块
  2. 计算机等级考试二级vb大纲,2009年全国计算机等级考试二级VB大纲考纲
  3. PDF.NET数据开发框架实体类操作实例(for PostgreSQL,并且解决自增问题)
  4. 在线机房改造类项目建设难点的研究
  5. 1.13 Predicate操作Collection集合
  6. c# datetime._C#| DateTime.AddTicks()方法与示例
  7. HEVC将会取代H.264的原因
  8. 单片机拟真电路图软件_DIY AT89S52单片机编程器
  9. 计算机专业我的生涯规划档案,大学生学业生涯规划登记表11.doc
  10. javascript小案例-----tab栏切换
  11. 评四女作家的×龙戏凤 (原版)
  12. 楚留香获取服务器信息未响应,楚留香手游后期输出乏力解决方法分享
  13. NOIP201205Vigenère密码
  14. [个人记录]半月板撕裂及SLAP损伤
  15. 严蔚敏版数据结构(C语言版)算法实现代码
  16. 暨南大学计算机研究生进腾讯,腾讯内容开放平台
  17. OBJ2GLTF使用,将obj格式模型转换为gltf
  18. RegexBuddy、RegexMagic、EditPad官方绿色版
  19. ps2摇杆android图形编程,ROC-RK3308-CC开发实例总结--PS2 Joystick摇杆模块
  20. 硬件比软件难,那为什么硬件工程师待遇还不如软件?

热门文章

  1. VulnHub - Pluck靶机
  2. Mysql 创建新用户授予root权限 或 最高权限
  3. 我所知道的金融数据库
  4. 两个非常不错的在线pdf转epub的网站,没有上传大小限制
  5. CSS的压缩 方法与解压
  6. 【合新通信】SFP GPON ONU Stick With MAC
  7. 人不怕不满足,就怕不知足
  8. 微信小程序获取地理位置信息
  9. 领英linkedin使用手册—领英好友人脉搜索方式方法
  10. iis7.5如何将应用程序池的启动模式(startMode)从onDemand(需要时)更改为AlwaysRunning(一直运行)?