/// <summary> /// 实现了“基础光照模型”,在世界空间进行顶点光照处理 /// </summary> /// <param name="v"></param> private void Lighting(Matrix4x4 m, Vector3D worldEyePositon, ref Vertex v) { Vector3D worldPoint = v.point * m; //世界空间顶点位置 Vector3D normal = v.normal * m.Inverse().Transpose(); //模型空间法线乘以世界矩阵的逆转置得到世界空间法线 normal = normal.Normalize(); SoftRenderer.RenderData.Color emissiveColor = _mesh.material.emissive; //自发光 SoftRenderer.RenderData.Color ambientColor = _ambientColor * _mesh.material.ka; //环境光 Vector3D inLightDir = (_light.worldPosition - worldPoint).Normalize(); float diffuse = Vector3D.Dot(normal, inLightDir); if (diffuse < 0) { diffuse = 0; } SoftRenderer.RenderData.Color diffuseColor = _mesh.material.diffuse * diffuse * _light.lightColor;//漫反射 // Vector3D inViewDir = (worldEyePositon - worldPoint).Normalize(); Vector3D h = (inViewDir + inLightDir).Normalize(); float specular = 0; if (diffuse != 0) {//防止出现光源在物体背面产生高光的情况 specular = (float)System.Math.Pow(MathUntil.Range(Vector3D.Dot(h, normal), 0, 1), _mesh.material.shininess); } SoftRenderer.RenderData.Color specularColor = _mesh.material.specular * specular * _light.lightColor;//镜面高光 // v.lightingColor = emissiveColor + ambientColor + diffuseColor + specularColor; }
private float[,] _zBuff; //z缓冲,用来做深度测试 #endregion Fields #region Constructors public SoftRendererDemo() { //VectorMatrixTestCase.Test(); InitializeComponent(); try { System.Drawing.Image img = System.Drawing.Image.FromFile("../../Texture/texture.jpg"); _texture = new Bitmap(img, 256, 256); } catch(Exception) { _texture = new Bitmap(256, 256); initTexture(); } // _currentMode = RenderMode.Textured; _lightMode = LightMode.On; _textureFilterMode = TextureFilterMode.Bilinear; // _frameBuff = new Bitmap(this.MaximumSize.Width, this.MaximumSize.Height); _frameG = Graphics.FromImage(_frameBuff); _zBuff = new float[this.MaximumSize.Height, this.MaximumSize.Width]; _ambientColor = new RenderData.Color(1f, 1f, 1f); _mesh = new Mesh(CubeTestData.pointList, CubeTestData.indexs, CubeTestData.uvs, CubeTestData.vertColors, CubeTestData.norlmas, QuadTestData.mat); //_mesh = new Mesh(QuadTestData.pointList, QuadTestData.indexs, QuadTestData.uvs, QuadTestData.vertColors, QuadTestData.norlmas, QuadTestData.mat); //打开注释可以切换mesh //定义光照 _light = new Light(new Vector3D(50, 0, 0), new RenderData.Color(1, 1, 1)); //定义相机 _camera = new Camera(new Vector3D(0, 0, 0, 1), new Vector3D(0, 0, 1, 1), new Vector3D(0, 1, 0, 0), (float)System.Math.PI / 4, this.MaximumSize.Width / (float)this.MaximumSize.Height, 1f, 500f); System.Timers.Timer mainTimer = new System.Timers.Timer(1000 / 60f); mainTimer.Elapsed += new ElapsedEventHandler(Tick); mainTimer.AutoReset = true; mainTimer.Enabled = true; mainTimer.Start(); // }
private uint _showTrisCount; //测试数据,记录当前显示的三角形数 public SoftRendererDemo() { //VectorMatrixTestCase.Test(); InitializeComponent(); try { System.Drawing.Image img = System.Drawing.Image.FromFile("../../Texture/texture.jpg"); _texture = new Bitmap(img, 256, 256); } catch (Exception) { _texture = new Bitmap(256, 256); initTexture(); } // _currentMode = RenderMode.Textured; _lightMode = LightMode.On; _textureFilterMode = TextureFilterMode.Bilinear; // _frameBuff = new Bitmap(this.MaximumSize.Width, this.MaximumSize.Height); _frameG = Graphics.FromImage(_frameBuff); _zBuff = new float[this.MaximumSize.Height, this.MaximumSize.Width]; _ambientColor = new RenderData.Color(1f, 1f, 1f); _mesh = new Mesh(CubeTestData.pointList, CubeTestData.indexs, CubeTestData.uvs, CubeTestData.vertColors, CubeTestData.norlmas, QuadTestData.mat); //_mesh = new Mesh(QuadTestData.pointList, QuadTestData.indexs, QuadTestData.uvs, QuadTestData.vertColors, QuadTestData.norlmas, QuadTestData.mat); //打开注释可以切换mesh //定义光照 _light = new Light(new Vector3D(50, 0, 0), new RenderData.Color(1, 1, 1)); //定义相机 _camera = new Camera(new Vector3D(0, 0, 0, 1), new Vector3D(0, 0, 1, 1), new Vector3D(0, 1, 0, 0), (float)System.Math.PI / 4, this.MaximumSize.Width / (float)this.MaximumSize.Height, 1f, 500f); System.Timers.Timer mainTimer = new System.Timers.Timer(1000 / 60f); mainTimer.Elapsed += new ElapsedEventHandler(Tick); mainTimer.AutoReset = true; mainTimer.Enabled = true; mainTimer.Start(); // }
/// <summary> /// 扫描线填充 /// </summary> /// <param name="left">左端点,值已经经过插值</param> /// <param name="right">右端点,值已经经过插值</param> private void ScanlineFill(Vertex left, Vertex right, int yIndex) { float dx = right.point.x - left.point.x; float step = 1; if(dx != 0) { step = 1 / dx; } for (float x = left.point.x; x <= right.point.x; x += 0.5f) { int xIndex = (int)(x + 0.5f); if (xIndex >= 0 && xIndex < this.MaximumSize.Width) { float lerpFactor = 0; if (dx != 0) { lerpFactor = (x - left.point.x) / dx; } //1/z’与x’和y'是线性关系的 float onePreZ = MathUntil.Lerp(left.onePerZ, right.onePerZ, lerpFactor); if (onePreZ >= _zBuff[yIndex, xIndex])//使用1/z进行深度测试 {//通过测试 float w = 1 / onePreZ; _zBuff[yIndex, xIndex] = onePreZ; //uv 插值,求纹理颜色 float u = MathUntil.Lerp(left.u, right.u, lerpFactor) * w * (_texture.Width - 1); float v = MathUntil.Lerp(left.v, right.v, lerpFactor) * w * (_texture.Height - 1); //纹理采样 SoftRenderer.RenderData.Color texColor = new RenderData.Color(1,1,1); if(_textureFilterMode == TextureFilterMode.point) {//点采样 int uIndex = (int)System.Math.Round(u , MidpointRounding.AwayFromZero); int vIndex = (int)System.Math.Round(v , MidpointRounding.AwayFromZero); uIndex = MathUntil.Range(uIndex, 0, _texture.Width - 1); vIndex = MathUntil.Range(vIndex, 0, _texture.Height - 1); //uv坐标系采用dx风格 texColor = new RenderData.Color(ReadTexture(uIndex, vIndex));//转到我们自定义的color进行计算 } else if(_textureFilterMode == TextureFilterMode.Bilinear) {//双线性采样 float uIndex = (float)System.Math.Floor(u); float vIndex = (float)System.Math.Floor(v); float du = u - uIndex; float dv = v - vIndex; SoftRenderer.RenderData.Color texcolor1 = new RenderData.Color(ReadTexture((int)uIndex, (int)vIndex)) * (1 - du) * (1 - dv); SoftRenderer.RenderData.Color texcolor2 = new RenderData.Color(ReadTexture((int)uIndex + 1, (int)vIndex)) * du * (1 - dv); SoftRenderer.RenderData.Color texcolor3 = new RenderData.Color(ReadTexture((int)uIndex, (int)vIndex + 1)) * (1 - du) * dv; SoftRenderer.RenderData.Color texcolor4 = new RenderData.Color(ReadTexture((int)uIndex + 1, (int)vIndex + 1)) * du * dv; texColor = texcolor1 + texcolor2 + texcolor3 + texcolor4; } //插值顶点颜色 SoftRenderer.RenderData.Color vertColor = MathUntil.Lerp(left.vcolor, right.vcolor, lerpFactor) * w; //插值光照颜色 SoftRenderer.RenderData.Color lightColor = MathUntil.Lerp(left.lightingColor, right.lightingColor, lerpFactor) * w; ; if(_lightMode == LightMode.On) {//光照模式,需要混合光照的颜色 if (RenderMode.Textured == _currentMode) { SoftRenderer.RenderData.Color finalColor = texColor * lightColor; _frameBuff.SetPixel(xIndex, yIndex, finalColor.TransFormToSystemColor()); } else if (RenderMode.VertexColor == _currentMode) { SoftRenderer.RenderData.Color finalColor = vertColor * lightColor; _frameBuff.SetPixel(xIndex, yIndex, finalColor.TransFormToSystemColor()); } } else { if (RenderMode.Textured == _currentMode) { _frameBuff.SetPixel(xIndex, yIndex, texColor.TransFormToSystemColor()); } else if (RenderMode.VertexColor == _currentMode) { _frameBuff.SetPixel(xIndex, yIndex, vertColor.TransFormToSystemColor()); } } } } } }
/// <summary> /// 扫描线填充 /// </summary> /// <param name="left">左端点,值已经经过插值</param> /// <param name="right">右端点,值已经经过插值</param> private void ScanlineFill(Vertex left, Vertex right, int yIndex) { float dx = right.point.x - left.point.x; float step = 1; if (dx != 0) { step = 1 / dx; } for (float x = left.point.x; x <= right.point.x; x += 0.5f) { int xIndex = (int)(x + 0.5f); if (xIndex >= 0 && xIndex < this.MaximumSize.Width) { float lerpFactor = 0; if (dx != 0) { lerpFactor = (x - left.point.x) / dx; } //1/z’与x’和y'是线性关系的 float onePreZ = MathUntil.Lerp(left.onePerZ, right.onePerZ, lerpFactor); if (onePreZ >= _zBuff[yIndex, xIndex]) //使用1/z进行深度测试 { //通过测试 float w = 1 / onePreZ; _zBuff[yIndex, xIndex] = onePreZ; //uv 插值,求纹理颜色 float u = MathUntil.Lerp(left.u, right.u, lerpFactor) * w * (_texture.Width - 1); float v = MathUntil.Lerp(left.v, right.v, lerpFactor) * w * (_texture.Height - 1); //纹理采样 SoftRenderer.RenderData.Color texColor = new RenderData.Color(1, 1, 1); if (_textureFilterMode == TextureFilterMode.point) {//点采样 int uIndex = (int)System.Math.Round(u, MidpointRounding.AwayFromZero); int vIndex = (int)System.Math.Round(v, MidpointRounding.AwayFromZero); uIndex = MathUntil.Range(uIndex, 0, _texture.Width - 1); vIndex = MathUntil.Range(vIndex, 0, _texture.Height - 1); //uv坐标系采用dx风格 texColor = new RenderData.Color(ReadTexture(uIndex, vIndex));//转到我们自定义的color进行计算 } else if (_textureFilterMode == TextureFilterMode.Bilinear) {//双线性采样 float uIndex = (float)System.Math.Floor(u); float vIndex = (float)System.Math.Floor(v); float du = u - uIndex; float dv = v - vIndex; SoftRenderer.RenderData.Color texcolor1 = new RenderData.Color(ReadTexture((int)uIndex, (int)vIndex)) * (1 - du) * (1 - dv); SoftRenderer.RenderData.Color texcolor2 = new RenderData.Color(ReadTexture((int)uIndex + 1, (int)vIndex)) * du * (1 - dv); SoftRenderer.RenderData.Color texcolor3 = new RenderData.Color(ReadTexture((int)uIndex, (int)vIndex + 1)) * (1 - du) * dv; SoftRenderer.RenderData.Color texcolor4 = new RenderData.Color(ReadTexture((int)uIndex + 1, (int)vIndex + 1)) * du * dv; texColor = texcolor1 + texcolor2 + texcolor3 + texcolor4; } //插值顶点颜色 SoftRenderer.RenderData.Color vertColor = MathUntil.Lerp(left.vcolor, right.vcolor, lerpFactor) * w; //插值光照颜色 SoftRenderer.RenderData.Color lightColor = MathUntil.Lerp(left.lightingColor, right.lightingColor, lerpFactor) * w;; if (_lightMode == LightMode.On) {//光照模式,需要混合光照的颜色 if (RenderMode.Textured == _currentMode) { SoftRenderer.RenderData.Color finalColor = texColor * lightColor; _frameBuff.SetPixel(xIndex, yIndex, finalColor.TransFormToSystemColor()); } else if (RenderMode.VertexColor == _currentMode) { SoftRenderer.RenderData.Color finalColor = vertColor * lightColor; _frameBuff.SetPixel(xIndex, yIndex, finalColor.TransFormToSystemColor()); } } else { if (RenderMode.Textured == _currentMode) { _frameBuff.SetPixel(xIndex, yIndex, texColor.TransFormToSystemColor()); } else if (RenderMode.VertexColor == _currentMode) { _frameBuff.SetPixel(xIndex, yIndex, vertColor.TransFormToSystemColor()); } } } } } }