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

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

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

  (ps :项目代码只有3000行左右,性能方面也比较渣,高性能的光栅渲染可以看空明大大的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 }

2.截图效果

2.1线框模型

2.2顶点色

2.3纹理+光照

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

3.源码

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

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

时间: 2024-10-26 20:45:47

开源一个简单的c++软光栅渲染器的相关文章

分享并开源一个简单粗暴的redmine测试报告系统

背景 软件测试的最后有一道比较繁琐的工作,就是编写测试报告.手写测试报告在数据统计和分析上面要耗费比较大的事件和精力.之前工作室使用mantis管理bug缺陷.公司有内部有个系统,可以直接从mantis上面获取数据并进行统计,生成一份测试报告.后来换了一个工作室,bug缺陷管理平台也从原来的mantis 换成了redmine (http://www.redmine.org/ ). 然后走上了一条手写测试报告的不归路(测试人员前期还是推荐手写测试报告的).搞游戏的都知道,平时加班加点压力就够大的.

哪种缓存效果高?开源一个简单的缓存组件j2cache

背景 现在的web系统已经越来越多的应用缓存技术,而且缓存技术确实是能实足的增强系统性能的.我在项目中也开始接触一些缓存的需求. 开始简单的就用jvm(java托管内存)来做缓存,这样对于单个应用服务器来说很好. 为了系统的可用性,需要做灾备,那么就要多准备一套系统环境,这时就会有一些共享资源的问题,比如Tomcat的session共享出来 几个系统会公用一套缓存数据,这样就变成一个共享池 需求的增长也就带来了系统的变化,也正为这种变化我开始思考怎么让这些代码兼容,并为以后的系统模块提供比较统一

cJSON: 一个用c写的一个简单好用的JSON解析器

转自:http://blog.csdn.net/chenzhongjing/article/details/9188347 下载地址: http://sourceforge.net/projects/cjson/files/?source=navbar 实例1: 创建一个简单的学生信息数组 cJSON* pRoot = cJSON_CreateObject(); cJSON* pArray = cJSON_CreateArray(); cJSON_AddItemToObject(pRoot, "

开源一个简单的react-native 菜单栏抽屉组件,带缩放效果

效果如图所示,源码地址:https://github.com/pofabs/PoSideMenu

一个简单的C语言语法检查器的实现

我自己的实现方法的核心过程:首先用一个非终结符代表所有要检查的程序代码,然后根据文法将这个整体的符号不断展开,以拼凑成按检查的程序的顺序排列的终结符序列,能成功说明语法正确,否则有错误. 关键词:分词:First集:Select集: 目前还存在的问题: 1.因为同一个非终结符->终结符的转化可能有多种解释,所以目前我的非终结符展开这里是用递归写的,因此不能定位具体错在哪里. 2.int a={1,2};int a[2]={1,'b'};这种该出错的地方不会出错.这个比较致命,但目前还没想好怎么解

android篇-如何做一个简单的安卓源码查看器

1,网页源码查看器: Httpurlconnection:用于发送或接收数据 Mainactivity篇: import java.io.InputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import android.os.Bundle; import android.os.Handler; import android.os.Lo

一个简单有趣的Python音乐播放器

(赠新手,老鸟绕行0.0) Python版本:3.5.2 源码如下: __Author__ = "Lance#" # -*- coding = utf-8 -*- #导入相应模块 from pygame import mixer from pynput import keyboard from pynput.keyboard import Key #音量初始值(范围是 0~1 ) value = 0.5 #混音器初始化.加载音乐.播放音乐 mixer.init() mixer.musi

基于OpenGL编写一个简易的2D渲染框架-11 重构渲染器-Renderer

假如要渲染一个纯色矩形在窗口上,应该怎么做? 先确定顶点的格式,一个顶点应该包含位置信息 vec3 以及颜色信息 vec4,所以顶点的结构体定义可以这样: struct Vertex { Vec3 position; Vec4 color; }; 然后填充矩形四个顶点是数据信息: Vertex* data = ( Vertex* ) malloc(sizeof( Vertex ) * 4); data[0].position.set(0, 0, 0); data[1].position.set(

Python学习 - 编写一个简单的web框架(二)

在上一篇日志中已经讨论和实现了根据url执行相应应用,在我阅读了bottle.py官方文档后,按照bottle的设计重写一遍,主要借鉴大牛们的设计思想. 一个bottle.py的简单实例 来看看bottle是如何使用的,代码来自http://www.bottlepy.org/docs/0.12/index.html: from bottle import route, run, template @route('/hello/<name>') def index(name): return t