• 开源一个简单的c++软光栅渲染器


         本文由zhangbaochong原创,转载请注明出处http://www.cnblogs.com/zhangbaochong/p/5751111.html

         由于开学就大四面临找工作了,为了整理下项目,最近又把上学期练手写的一个c++软光栅渲染demo拿出来重新改了改,稍微优化了一下,顺便增加了光照。虽然写的比较简单,但还是拿出来分享一下,希望能起个抛砖引玉的作用吧,也欢迎指点批评O(∩_∩)O~

      (ps :项目代码只有4000行左右,性能方面也比较渣,高性能的光栅渲染可以看空明大大的SALVIAhttp://www.cnblogs.com/lingjingqiu/)

         

    1.主要模块功能

    1.1数学库

      向量、矩阵的实现与变换(矩阵平移、旋转、转置、行列式、逆矩阵);

          视角矩阵、投影矩阵和屏幕坐标转换矩阵;

      一些常用函数(插值、RGB颜色转UINT、角度弧度转换、求反射向量).

    1.2后缓冲区

          设置像素,我一开始采用SetPixel()函数,发现速度慢的不忍直视。后来改成用CreateDIBSections创建位图,直接向内存中写像素颜色值,完了后一块BitBlt到窗口就行了。

    1.3模型标准

      由于之前一直在写directx11的代码,所以这里也采用标准d3d的坐标模型,左手系+world view proj三矩阵

    1.4几何阶段

          顶点从模型空间到世界空间到相机空间到齐次裁剪空间,对应的主要是三个矩阵world view proj,数学库中提供了相应方法。

          图元装配,也就是将顶点以一定顺序组装成三角形,本项目中采用顶点索引的方式来组织顶点,并且三角形顺时针顺序对应的法线朝向外面。之所以规定好顺序,是为了法线方向的一致性,只有这样才能进行后面的背面消隐。

          投影后的坐标再进行透视除法,让顶点坐标位于cvv中(x[-1,1],y[-1,1],z[0,1]),裁剪过后再将cvv坐标转化为屏幕中对应的坐标。

    1.4三角形光栅化

         线框模型使用的bresenham画线算法。

         三角形光栅算法:http://blog.csdn.net/cppyin/article/details/6232453

         填充三角形使用的扫描线。

    1.5背面消隐

         可以参考:http://blog.csdn.net/cppyin/article/details/6207206

    1.6简单CVV裁剪

    1.7支持纹理

      纹理uv坐标同d3d,纹理坐标寻址同d3d的wrap方式,贴图在物体表面重复,类似于我们设置桌面是图片的平铺方式。当坐标大于1时,通过去掉整数部分,根据得到的小数部分来得到纹理值;坐标小于0,则加上一个最小正数,让坐标大于0。

    1.8简单光照

      phong光照模型,实现平行光、点光源与聚光灯三种。

    1.9简单着色器

         写了一个着色器类,有VS和PS两个函数对应顶点着色器和像素着色器,部分代码如下:

     1 VertexOut BoxShader::VS(const VertexIn& vin)
     2 {
     3     VertexOut out;
     4     out.posH = vin.pos * m_worldViewProj;
     5     
     6     out.posTrans = vin.pos * m_world;
     7     out.normal = out.normal * m_worldInvTranspose;
     8 
     9      out.color = vin.color;
    10      out.tex = vin.tex;
    11 
    12     return out;
    13 }
    14 
    15 ZCVector BoxShader::PS(VertexOut& pin)
    16 {
    17     //单位化法线
    18     pin.normal.Normalize();
    19 
    20     //纹理采样
    21     ZCVector texColor = m_tex.Sample(pin.tex);
    22 
    23     //顶点到观察点向量
    24     ZCVector toEye = (m_eyePos - pin.posTrans).Normalize();
    25 
    26     //初始化颜色值全部为0
    27     ZCVector ambient(0.f, 0.f, 0.f, 0.f);
    28     ZCVector diffuse(0.f, 0.f, 0.f, 0.f);
    29     ZCVector specular(0.f, 0.f, 0.f, 0.f);
    30 
    31     //光源计算后得到的环境光、漫反射 、高光
    32     ZCVector A, D, S;
    33 
    34     Lights::ComputeDirectionalLight(m_material, m_dirLight, pin.normal, toEye, A, D, S);
    35 
    36     ambient = ambient + A;
    37     diffuse = diffuse + D;
    38     specular = specular + S;
    39 
    40 
    41     //纹理+光照计算公式: 纹理*(环境光+漫反射光)+高光
    42     ZCVector litColor = texColor * (ambient + diffuse) + specular;
    43 
    44     //最终颜色透明度使用漫反射光的透明度
    45     litColor.w = m_material.diffuse.w * texColor.w;
    46 
    47     return litColor;
    48 }
    View Code

    2.截图效果

    2.1线框模型

    2.2顶点色

    2.3纹理+光照

    图片本身是木纹材质,显得比较粗糙/(ㄒoㄒ)/~~

    3.源码

         项目托管到Github上了:https://github.com/zhangbaochong/Tiny3D

         等有时间我会再优化一下,比如采用SIMD加速等等。最近应该没时间搞这个了,d3d最近都没怎么看,为了开学找工作得把算法数据结构再复习下!

  • 相关阅读:
    Python第二天 (数据类型,变量 )
    python第一天(安装运行python)
    Linux shell 整数运算 let [ ] (( )) expr以及 浮点数 bc用法(转)
    2018年3月大事件
    2018年2月大事件
    项目假设与制约因素
    调用微信红包接口,本地可以服务器不可以。 请求被中止: 未能创建 SSL/TLS 安全通道
    【转】AddMvcCore,AddControllers,AddControllersWithViews,AddRazorPages的区别
    sql server create table 给字段添加注释说明
    HttpContext.SignInAsync 失效(表面解决了问题,未深入到.net core 源码去找问题,记录一下,等有时间翻一下.net core 源码试试能不能找到根本原因)
  • 原文地址:https://www.cnblogs.com/zhangbaochong/p/5751111.html
Copyright © 2020-2023  润新知