private System.Drawing.Color ReadTexture(int uIndex, int vIndex) { int u = MathUntil.Range(uIndex, 0, _texture.Width - 1); int v = MathUntil.Range(vIndex, 0, _texture.Height - 1); return(_texture.GetPixel(u, v)); }
private float rota = 0;//旋转 private void Tick(object sender, ElapsedEventArgs e) { lock (_frameBuff) { clearBuff(); rota += 0.05f; //获取旋转矩阵 Matrix4x4 rotaX = MathUntil.GetRotateX(rota); Matrix4x4 rotaY = MathUntil.GetRotateY(rota); Matrix4x4 translate = MathUntil.GetTranslate(0, 0, 10); Matrix4x4 m = rotaX * rotaY * translate; //计算相机视矩阵 Matrix4x4 v = MathUntil.GetView(_camera.pos, _camera.lookAt, _camera.up); //投影矩阵 Matrix4x4 p = MathUntil.GetProjection(_camera.fov, _camera.aspect, _camera.zn, _camera.zf); Draw(m, v, p); if (_frameG2 == null) { _frameG2 = CreateGraphics(); } _frameG2.Clear(System.Drawing.Color.Black); _frameG2.DrawImage(_frameBuff, 0, 0); } }
/// <summary> /// 平底,p1为上顶点,p2,p3 /// </summary> /// <param name="p1"></param> /// <param name="p2"></param> /// <param name="p3"></param> private void DrawTriangleBottom(Vertex p1, Vertex p2, Vertex p3) { for (float y = p1.point.y; y <= p2.point.y; y += 0.5f) { int yIndex = (int)(System.Math.Round(y, MidpointRounding.AwayFromZero)); if (yIndex >= 0 && yIndex < this.MaximumSize.Height) { float xl = (y - p1.point.y) * (p2.point.x - p1.point.x) / (p2.point.y - p1.point.y) + p1.point.x; float xr = (y - p1.point.y) * (p3.point.x - p1.point.x) / (p3.point.y - p1.point.y) + p1.point.x; float dy = y - p1.point.y; float t = dy / (p2.point.y - p1.point.y); //插值生成左右顶点 Vertex new1 = new Vertex(); new1.point.x = xl; new1.point.y = y; MathUntil.ScreenSpaceLerpVertex(ref new1, p1, p2, t); // Vertex new2 = new Vertex(); new2.point.x = xr; new2.point.y = y; MathUntil.ScreenSpaceLerpVertex(ref new2, p1, p3, t); //扫描线填充 if (new1.point.x < new2.point.x) { ScanlineFill(new1, new2, yIndex); } else { ScanlineFill(new2, new1, yIndex); } } } }
/// <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(); RenderData.Color emissiveColor = _mesh.material.emissive; //自发光 RenderData.Color ambientColor = _ambientColor * _mesh.material.ka; //环境光 Vector3D inLightDir = (_light.worldPosition - worldPoint).Normalize(); float diffuse = Vector3D.Dot(normal, inLightDir); if (diffuse < 0) { diffuse = 0; } 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); } RenderData.Color specularColor = _mesh.material.specular * specular * _light.lightColor;//镜面高光 // v.lightingColor = emissiveColor + ambientColor + diffuseColor + specularColor; }
/// <summary> /// 扫描线填充 /// </summary> /// <param name="left">左端点,值已经经过插值</param> /// <param name="right">右端点,值已经经过插值</param> private void ScanlineFill(CVertex left, CVertex right, int yIndex) { float dx = right.point.x - left.point.x; for (float x = left.point.x; x <= right.point.x; x++) { int xIndex = (int)(System.Math.Round(x, MidpointRounding.AwayFromZero)); 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); int uIndex = (int)(u + 0.5f); int vIndex = (int)(v + 0.5f); uIndex = MathUntil.Range(uIndex, 0, _texture.Width - 1); vIndex = MathUntil.Range(vIndex, 0, _texture.Height - 1); //uv坐标系采用dx风格 System.Drawing.Color textrueColor = _texture.GetPixel(vIndex, uIndex); //插值顶点颜色 float r = MathUntil.Lerp(left.color.r, right.color.r, lerpFactor) * w * 255; float g = MathUntil.Lerp(left.color.g, right.color.g, lerpFactor) * w * 255; float b = MathUntil.Lerp(left.color.b, right.color.b, lerpFactor) * w * 255; //更新渲染模式渲染 if (RenderMode.Textured == _currentMode) { _frameBuff.SetPixel(xIndex, yIndex, textrueColor); } else if (RenderMode.VertexColor == _currentMode) { _frameBuff.SetPixel(xIndex, yIndex, System.Drawing.Color.FromArgb((int)r, (int)g, (int)b)); } } } } }
private void Tick(object sender, EventArgs e) { lock (_frameBuff) { ClearBuff(); rot += 0.05f; Matrix4x4 m = MathUntil.GetRotateX(rot) * MathUntil.GetRotateY(rot) * MathUntil.GetTranslate(0, 0, 10); Matrix4x4 v = MathUntil.GetView(_camera.pos, _camera.lookAt, _camera.up); Matrix4x4 p = MathUntil.GetProjection(_camera.fov, _camera.aspect, _camera.zn, _camera.zf); // Draw(m, v, p); if (g == null) { g = this.CreateGraphics(); } g.Clear(System.Drawing.Color.Black); g.DrawImage(_frameBuff, 0, 0); } }
private void timer1_Tick(object sender, EventArgs e) { lock (_frameBuff) { ClearBuff(); CMatrix4x4 m = new CMatrix4x4(); m.Identity(); m[3, 2] = 5; rot += 0.1f; m = MathUntil.GetRotateY(rot) * m; CMatrix4x4 v = MathUntil.GetView(new CVector3D(0, 0, 0, 1), new CVector3D(0, 0, 1, 1), new CVector3D(0, 1, 0, 1)); CMatrix4x4 p = MathUntil.GetProjection((float)System.Math.PI / 4, this.MaximumSize.Width / (float)this.MaximumSize.Height, 1f, 500f); // Draw(m, v, p); // if (g1 == null) { g1 = this.CreateGraphics(); } g1.Clear(System.Drawing.Color.Black); g1.DrawImage(_frameBuff, 0, 0); } this.Invalidate(); }
/// <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); //纹理采样 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; RenderData.Color texcolor1 = new RenderData.Color(ReadTexture((int)uIndex, (int)vIndex)) * (1 - du) * (1 - dv); RenderData.Color texcolor2 = new RenderData.Color(ReadTexture((int)uIndex + 1, (int)vIndex)) * du * (1 - dv); RenderData.Color texcolor3 = new RenderData.Color(ReadTexture((int)uIndex, (int)vIndex + 1)) * (1 - du) * dv; RenderData.Color texcolor4 = new RenderData.Color(ReadTexture((int)uIndex + 1, (int)vIndex + 1)) * du * dv; texColor = texcolor1 + texcolor2 + texcolor3 + texcolor4; } //插值顶点颜色 RenderData.Color vertColor = MathUntil.Lerp(left.vcolor, right.vcolor, lerpFactor) * w; //插值光照颜色 RenderData.Color lightColor = MathUntil.Lerp(left.lightingColor, right.lightingColor, lerpFactor) * w;; if (_lightMode == LightMode.ON) {//光照模式,需要混合光照的颜色 if (RenderMode.Textured == _currentMode) { RenderData.Color finalColor = texColor * lightColor; _frameBuff.SetPixel(xIndex, yIndex, finalColor.TransFormToSystemColor()); } else if (RenderMode.VertexColor == _currentMode) { 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> private void TriangleRasterization(Vertex p1, Vertex p2, Vertex p3) { if (p1.point.y == p2.point.y) { if (p1.point.y < p3.point.y) {//平顶 DrawTriangleTop(p1, p2, p3); } else {//平底 DrawTriangleBottom(p3, p1, p2); } } else if (p1.point.y == p3.point.y) { if (p1.point.y < p2.point.y) {//平顶 DrawTriangleTop(p1, p3, p2); } else {//平底 DrawTriangleBottom(p2, p1, p3); } } else if (p2.point.y == p3.point.y) { if (p2.point.y < p1.point.y) {//平顶 DrawTriangleTop(p2, p3, p1); } else {//平底 DrawTriangleBottom(p1, p2, p3); } } else {//分割三角形 Vertex top; Vertex bottom; Vertex middle; if (p1.point.y > p2.point.y && p2.point.y > p3.point.y) { top = p3; middle = p2; bottom = p1; } else if (p3.point.y > p2.point.y && p2.point.y > p1.point.y) { top = p1; middle = p2; bottom = p3; } else if (p2.point.y > p1.point.y && p1.point.y > p3.point.y) { top = p3; middle = p1; bottom = p2; } else if (p3.point.y > p1.point.y && p1.point.y > p2.point.y) { top = p2; middle = p1; bottom = p3; } else if (p1.point.y > p3.point.y && p3.point.y > p2.point.y) { top = p2; middle = p3; bottom = p1; } else if (p2.point.y > p3.point.y && p3.point.y > p1.point.y) { top = p1; middle = p3; bottom = p2; } else { //三点共线 return; } //插值求中间点x float middlex = (middle.point.y - top.point.y) * (bottom.point.x - top.point.x) / (bottom.point.y - top.point.y) + top.point.x; float dy = middle.point.y - top.point.y; float t = dy / (bottom.point.y - top.point.y); //插值生成左右顶点 Vertex newMiddle = new Vertex(); newMiddle.point.x = middlex; newMiddle.point.y = middle.point.y; MathUntil.ScreenSpaceLerpVertex(ref newMiddle, top, bottom, t); //平底 DrawTriangleBottom(top, newMiddle, middle); //平顶 DrawTriangleTop(newMiddle, middle, bottom); } }
public Color(System.Drawing.Color c) { this._r = MathUntil.Range((float)c.R / 255, 0, 1); this._g = MathUntil.Range((float)c.G / 255, 0, 1); this._b = MathUntil.Range((float)c.B / 255, 0, 1); }
public Color(float r, float g, float b) { this._r = MathUntil.Range(r, 0, 1); this._g = MathUntil.Range(g, 0, 1); this._b = MathUntil.Range(b, 0, 1); }