概述
前言
上一篇文章我们已经对三角形进行了坐标变换,今天准备渲染几个立方体,渲染立方体就会比平面的三角形看起来更意思了。
渲染一个线框立方体
咱们现在可以渲染一个三角形了,那么也就意味着我们可以渲染任何物体了,因为任何物体都可以划分为三角形,那么咱们今天就先从比较简单的立方体开始。上一篇文章的坐标变换部分有点乱,今天对它们进行了封装,具体可以看代码。
// 引用EasyX图形库头文件
#include <graphics.h>
#include <conio.h>
//glm数学相关头文件
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <iostream>
#include <vector>
#define ScreenWidth 800
#define ScreenHeight 600
//插值
std::vector<float> Interpolate(float i0, float d0, float i1, float d1)
{
std::vector<float> values;
if (glm::abs(i0 - i1) < 1e-6)
{
values.push_back(d0);
return values;
}
float a = (d1 - d0) / (i1 - i0);
float d = d0;
for (int i = i0;i < i1;i++)
{
values.push_back(d);
d = d + a;
}
return values;
}
//画线
void DrawLine(glm::vec2 P0, glm::vec2 P1, COLORREF color)
{
if (glm::abs(P1.x - P0.x) > glm::abs(P1.y - P0.y))
{
if (P0.x > P1.x)
{
std::swap(P0, P1);
}
std::vector<float> ys = Interpolate(P0.x, P0.y, P1.x, P1.y);
for (int x = P0.x;x < P1.x;x++)
{
putpixel(x, ys[x - P0.x], color);
}
}
else
{
if (P0.y > P1.y)
{
std::swap(P0, P1);
}
std::vector<float> xs = Interpolate(P0.y, P0.x, P1.y, P1.x);
for (int y = P0.y;y < P1.y;y++)
{
putpixel(xs[y - P0.y], y, color);
Sleep(1);
}
}
}
//画线框三角形
void DrawWireframeTriangle(glm::vec2 P0, glm::vec2 P1, glm::vec2 P2, COLORREF color)
{
DrawLine(P0, P1, color);
DrawLine(P1, P2, color);
DrawLine(P2, P0, color);
}
//画填充三角形
void DrawFilledTriangle(glm::vec2 P0, glm::vec2 P1, glm::vec2 P2, COLORREF color)
{
//排序顶点 P0.y <= P1.y <= P2.y
if (P1.y < P0.y) { std::swap(P1, P0); }
if (P2.y < P0.y) { std::swap(P2, P0); }
if (P2.y < P1.y) { std::swap(P2, P1); }
//------------------P2|
//--------------------|
//--------------------| P1
//--------------------| /
//--------------------| /
//------------------P0|/
//P0P1边x坐标数组
std::vector<float> x01 = Interpolate(P0.y, P0.x, P1.y, P1.x);
//P1P2边x坐标数组
std::vector<float> x12 = Interpolate(P1.y, P1.x, P2.y, P2.x);
//P0P2边x坐标数组
std::vector<float> x02 = Interpolate(P0.y, P0.x, P2.y, P2.x);
//【注意】去掉重复坐标,P0P1和P1P2重复了P1
//x01.pop_back();
//x012=x01+x12 x012代表P0P1和P1P2两条边的x坐标数组
x01.insert(x01.end(), x12.begin(), x12.end());
std::vector<float> x012(x01);
float m = glm::floor(x012.size() / 2);
std::vector<float> x_left;
std::vector<float> x_right;
//-------第一种情况
//---------P2|
//-----------|
//-----------| P1
//-----------| /
//-----------| /
//---------P0|/
if (x02[m] < x012[m])
{
x_left = x02;
x_right = x012;
}
//-------第二种情况
//----------/|P2
//---------/ |
//------p1/ |
//-------- |
//--------- |
//----------|P0
else
{
x_left = x012;
x_right = x02;
}
//从左到右填充
for (int y = P0.y;y < P2.y;y++)
{
for (int x = x_left[y - P0.y];x < x_right[y - P0.y];x++)
{
putpixel(x, y, color);
}
}
}
struct Vertex
{
glm::vec4 position;
float color;
};
struct Triangle
{
glm::vec3 index;
COLORREF color;
};
//画着色三角形
void DrawShadedTriangle(Vertex P0, Vertex P1, Vertex P2, COLORREF color)
{
BYTE r = GetRValue(color);
BYTE g = GetGValue(color);
BYTE b = GetBValue(color);
//排序顶点 P0.y <= P1.y <= P2.y
if (P1.position.y < P0.position.y) { std::swap(P1, P0); }
if (P2.position.y < P0.position.y) { std::swap(P2, P0); }
if (P2.position.y < P1.position.y) { std::swap(P2, P1); }
//------------------P2|
//--------------------|
//--------------------| P1
//--------------------| /
//--------------------| /
//------------------P0|/
//P0P1边x坐标数组
std::vector<float> x01 = Interpolate(P0.position.y, P0.position.x, P1.position.y, P1.position.x);
std::vector<float> h01 = Interpolate(P0.position.y, P0.color, P1.position.y, P1.color);
//P1P2边x坐标数组
std::vector<float> x12 = Interpolate(P1.position.y, P1.position.x, P2.position.y, P2.position.x);
std::vector<float> h12 = Interpolate(P1.position.y, P1.color, P2.position.y, P2.color);
//P0P2边x坐标数组
std::vector<float> x02 = Interpolate(P0.position.y, P0.position.x, P2.position.y, P2.position.x);
std::vector<float> h02 = Interpolate(P0.position.y, P0.color, P2.position.y, P2.color);
//【注意】去掉重复坐标,P0P1和P1P2重复了P1
//x01.pop_back();
//x012=x01+x12 x012代表P0P1和P1P2两条边的x坐标数组
x01.insert(x01.end(), x12.begin(), x12.end());
std::vector<float> x012(x01);
h01.insert(h01.end(), h12.begin(), h12.end());
std::vector<float> h012(h01);
float m = glm::floor(x012.size() / 2);
std::vector<float> x_left;
std::vector<float> x_right;
std::vector<float> h_left;
std::vector<float> h_right;
//-------第一种情况
//---------P2|
//-----------|
//-----------| P1
//-----------| /
//-----------| /
//---------P0|/
if (x02[m] < x012[m])
{
x_left = x02;
x_right = x012;
h_left = h02;
h_right = h012;
}
//-------第二种情况
//----------/|P2
//---------/ |
//------p1/ |
//-------- |
//--------- |
//----------|P0
else
{
x_left = x012;
x_right = x02;
h_left = h012;
h_right = h02;
}
//从左到右填充
for (int y = P0.position.y; y < P2.position.y; y++)
{
float x_l = x_left[y - P0.position.y];
float x_r = x_right[y - P0.position.y];
std::vector<float> h_segment = Interpolate(x_l, h_left[y - P0.position.y], x_r, h_right[y - P0.position.y]);
for (int x = x_left[y - P0.position.y]; x < x_right[y - P0.position.y]; x++)
{
COLORREF shaded_color = RGB(r * h_segment[x - x_l], g * h_segment[x - x_l], b * h_segment[x - x_l]);
putpixel(x, y, shaded_color);
}
}
}
//渲染一个三角形
void RenderTriangle(Triangle triangle, std::vector<Vertex> vertices)
{
DrawWireframeTriangle(vertices[triangle.index.x].position,
vertices[triangle.index.y].position,
vertices[triangle.index.z].position,
triangle.color);
}
//渲染一个物体
void RenderObject(std::vector<Vertex> vertices, std::vector<Triangle> triangles)
{
for (int i = 0; i < triangles.size(); i++)
{
RenderTriangle(triangles[i], vertices);
}
}
glm::mat4 GetModel(glm::vec3 s = { 1.0f, 1.0f, 1.0f }, glm::vec4 r = { 0,1,0,60.0f }, glm::vec3 t = { 0, 0, 5 })
{
glm::mat4 sm = glm::scale(glm::mat4(1.0f), s);
glm::mat4 rm = glm::rotate(glm::mat4(1.0f), glm::radians(r.w), glm::vec3(r));
glm::mat4 tm = glm::translate(glm::mat4(1.0f), t);
//构造模型矩阵
return tm * rm * sm;
}
glm::mat4 GetView(glm::vec3 eye=glm::vec3(0,0,0),glm::vec3 center=glm::vec3(0,0,1),glm::vec3 up=glm::vec3(0,1,0))
{
return glm::lookAt(eye, center, up);
}
glm::mat4 GetPerspective(float fov=glm::radians(90.0f),float aspect= ScreenWidth/ScreenHeight,float n=0.1f,float f=100.0f)
{
return glm::perspective(fov, aspect, n, f);
}
glm::mat4 GetMVP(glm::mat4 model, glm::mat4 view, glm::mat4 perspective)
{
return perspective * view * model;
}
int main()
{
initgraph(ScreenWidth, ScreenHeight); // 创建绘图窗口,大小为 640x480 像素
std::vector<Vertex> Vertices;
Vertices.resize(8);
Vertices[0].position = { 1,1,1 ,1 };
Vertices[1].position = { -1,1,1,1 };
Vertices[2].position = { -1,-1,1 ,1 };
Vertices[3].position = { 1,-1,1 ,1 };
Vertices[4].position = { 1,1,-1 ,1 };
Vertices[5].position = { -1,1,-1 ,1 };
Vertices[6].position = { -1,-1,-1 ,1 };
Vertices[7].position = { 1,-1,-1 ,1 };
Vertices[0].color = 1.0f;
Vertices[1].color = 1.0f;
Vertices[2].color = 0.5f;
Vertices[3].color = 0.5f;
Vertices[4].color = 0.5f;
Vertices[5].color = 0.5f;
Vertices[6].color = 1.0f;
Vertices[7].color = 1.0f;
std::vector<Triangle> triangles;
triangles.resize(12);
triangles[0].index = { 0,1,2 };
triangles[0].color = RED;
triangles[1].index = { 0,2,3 };
triangles[1].color = RED;
triangles[2].index = { 4,0,3 };
triangles[2].color = GREEN;
triangles[3].index = { 4,3,7 };
triangles[3].color = GREEN;
triangles[4].index = { 5,4,7 };
triangles[4].color = BLUE;
triangles[5].index = { 5,7,6 };
triangles[5].color = BLUE;
triangles[6].index = { 1,5,6 };
triangles[6].color = YELLOW;
triangles[7].index = { 1,6,2 };
triangles[7].color = YELLOW;
triangles[8].index = { 4,5,1 };
triangles[8].color = WHITE;
triangles[9].index = { 4,1,0 };
triangles[9].color = WHITE;
triangles[10].index = { 2,6,7 };
triangles[10].color = CYAN;
triangles[11].index = { 2,7,3 };
triangles[11].color = CYAN;
{
//构造模型矩阵
glm::mat4 model =GetModel();
//构造视图矩阵
glm::mat4 view = GetView();
//构造透视投影矩阵
glm::mat4 perspective =GetPerspective();
//构造MVP矩阵
glm::mat4 mvp = GetMVP(model,view,perspective);
for (int i = 0; i < Vertices.size(); i++)
{
//对顶点进行MVP矩阵变换
Vertices[i].position = mvp * Vertices[i].position;
//透视除法
float reciprocalW = 1 / Vertices[i].position.w;
//屏幕映射
Vertices[i].position.x = (Vertices[i].position.x * reciprocalW + 1.0f) * 0.5f * ScreenWidth;
Vertices[i].position.y = (1.0f - Vertices[i].position.y * reciprocalW) * 0.5f * ScreenHeight;
}
}
RenderObject(Vertices, triangles);
_getch();
closegraph(); // 关闭绘图窗口
return 0;
}
结果
渲染多个线框立方体
// 引用EasyX图形库头文件
#include <graphics.h>
#include <conio.h>
//glm数学相关头文件
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <iostream>
#include <vector>
#define ScreenWidth 800
#define ScreenHeight 600
//插值
std::vector<float> Interpolate(float i0, float d0, float i1, float d1)
{
std::vector<float> values;
if (glm::abs(i0 - i1) < 1e-6)
{
values.push_back(d0);
return values;
}
float a = (d1 - d0) / (i1 - i0);
float d = d0;
for (int i = i0;i < i1;i++)
{
values.push_back(d);
d = d + a;
}
return values;
}
//画线
void DrawLine(glm::vec2 P0, glm::vec2 P1, COLORREF color)
{
if (glm::abs(P1.x - P0.x) > glm::abs(P1.y - P0.y))
{
if (P0.x > P1.x)
{
std::swap(P0, P1);
}
std::vector<float> ys = Interpolate(P0.x, P0.y, P1.x, P1.y);
for (int x = P0.x;x < P1.x;x++)
{
putpixel(x, ys[x - P0.x], color);
}
}
else
{
if (P0.y > P1.y)
{
std::swap(P0, P1);
}
std::vector<float> xs = Interpolate(P0.y, P0.x, P1.y, P1.x);
for (int y = P0.y;y < P1.y;y++)
{
putpixel(xs[y - P0.y], y, color);
//Sleep(1);
}
}
}
//画线框三角形
void DrawWireframeTriangle(glm::vec2 P0, glm::vec2 P1, glm::vec2 P2, COLORREF color)
{
DrawLine(P0, P1, color);
DrawLine(P1, P2, color);
DrawLine(P2, P0, color);
}
//画填充三角形
void DrawFilledTriangle(glm::vec2 P0, glm::vec2 P1, glm::vec2 P2, COLORREF color)
{
//排序顶点 P0.y <= P1.y <= P2.y
if (P1.y < P0.y) { std::swap(P1, P0); }
if (P2.y < P0.y) { std::swap(P2, P0); }
if (P2.y < P1.y) { std::swap(P2, P1); }
//------------------P2|
//--------------------|
//--------------------| P1
//--------------------| /
//--------------------| /
//------------------P0|/
//P0P1边x坐标数组
std::vector<float> x01 = Interpolate(P0.y, P0.x, P1.y, P1.x);
//P1P2边x坐标数组
std::vector<float> x12 = Interpolate(P1.y, P1.x, P2.y, P2.x);
//P0P2边x坐标数组
std::vector<float> x02 = Interpolate(P0.y, P0.x, P2.y, P2.x);
//【注意】去掉重复坐标,P0P1和P1P2重复了P1
//x01.pop_back();
//x012=x01+x12 x012代表P0P1和P1P2两条边的x坐标数组
x01.insert(x01.end(), x12.begin(), x12.end());
std::vector<float> x012(x01);
float m = glm::floor(x012.size() / 2);
std::vector<float> x_left;
std::vector<float> x_right;
//-------第一种情况
//---------P2|
//-----------|
//-----------| P1
//-----------| /
//-----------| /
//---------P0|/
if (x02[m] < x012[m])
{
x_left = x02;
x_right = x012;
}
//-------第二种情况
//----------/|P2
//---------/ |
//------p1/ |
//-------- |
//--------- |
//----------|P0
else
{
x_left = x012;
x_right = x02;
}
//从左到右填充
for (int y = P0.y;y < P2.y;y++)
{
for (int x = x_left[y - P0.y];x < x_right[y - P0.y];x++)
{
putpixel(x, y, color);
}
}
}
struct Vertex
{
glm::vec4 position;
float color;
};
struct Triangle
{
glm::vec3 index;
COLORREF color;
};
struct Model
{
std::string name;
std::vector<Vertex> vertices;
std::vector<Triangle> triangles;
};
struct Transform
{
glm::vec3 translate;
glm::vec4 rotation;
glm::vec3 scale3D;
};
struct Instance
{
Model model;
Transform transform;
};
struct Scene
{
std::vector<Instance> instances;
};
glm::vec4 ApplyTransform(glm::vec4 pos, Transform transform)
{
glm::mat4 sm = glm::scale(glm::mat4(1.0f), transform.scale3D);
glm::mat4 rm = glm::rotate(glm::mat4(1.0f), glm::radians(transform.rotation.z), glm::vec3(transform.rotation));
glm::mat4 tm = glm::translate(glm::mat4(1.0f), transform.translate);
//构造模型矩阵
glm::mat4 model = tm * rm * sm;
return model * pos;
}
//画着色三角形
void DrawShadedTriangle(Vertex P0, Vertex P1, Vertex P2, COLORREF color)
{
BYTE r = GetRValue(color);
BYTE g = GetGValue(color);
BYTE b = GetBValue(color);
//排序顶点 P0.y <= P1.y <= P2.y
if (P1.position.y < P0.position.y) { std::swap(P1, P0); }
if (P2.position.y < P0.position.y) { std::swap(P2, P0); }
if (P2.position.y < P1.position.y) { std::swap(P2, P1); }
//------------------P2|
//--------------------|
//--------------------| P1
//--------------------| /
//--------------------| /
//------------------P0|/
//P0P1边x坐标数组
std::vector<float> x01 = Interpolate(P0.position.y, P0.position.x, P1.position.y, P1.position.x);
std::vector<float> h01 = Interpolate(P0.position.y, P0.color, P1.position.y, P1.color);
//P1P2边x坐标数组
std::vector<float> x12 = Interpolate(P1.position.y, P1.position.x, P2.position.y, P2.position.x);
std::vector<float> h12 = Interpolate(P1.position.y, P1.color, P2.position.y, P2.color);
//P0P2边x坐标数组
std::vector<float> x02 = Interpolate(P0.position.y, P0.position.x, P2.position.y, P2.position.x);
std::vector<float> h02 = Interpolate(P0.position.y, P0.color, P2.position.y, P2.color);
//【注意】去掉重复坐标,P0P1和P1P2重复了P1
//x01.pop_back();
//x012=x01+x12 x012代表P0P1和P1P2两条边的x坐标数组
x01.insert(x01.end(), x12.begin(), x12.end());
std::vector<float> x012(x01);
h01.insert(h01.end(), h12.begin(), h12.end());
std::vector<float> h012(h01);
float m = glm::floor(x012.size() / 2);
std::vector<float> x_left;
std::vector<float> x_right;
std::vector<float> h_left;
std::vector<float> h_right;
//-------第一种情况
//---------P2|
//-----------|
//-----------| P1
//-----------| /
//-----------| /
//---------P0|/
if (x02[m] < x012[m])
{
x_left = x02;
x_right = x012;
h_left = h02;
h_right = h012;
}
//-------第二种情况
//----------/|P2
//---------/ |
//------p1/ |
//-------- |
//--------- |
//----------|P0
else
{
x_left = x012;
x_right = x02;
h_left = h012;
h_right = h02;
}
//从左到右填充
for (int y = P0.position.y; y < P2.position.y; y++)
{
float x_l = x_left[y - P0.position.y];
float x_r = x_right[y - P0.position.y];
std::vector<float> h_segment = Interpolate(x_l, h_left[y - P0.position.y], x_r, h_right[y - P0.position.y]);
for (int x = x_left[y - P0.position.y]; x < x_right[y - P0.position.y]; x++)
{
COLORREF shaded_color = RGB(r * h_segment[x - x_l], g * h_segment[x - x_l], b * h_segment[x - x_l]);
putpixel(x, y, shaded_color);
}
}
}
//渲染一个三角形
void RenderTriangle(Triangle triangle, std::vector<Vertex> vertices)
{
DrawWireframeTriangle(vertices[triangle.index.x].position,
vertices[triangle.index.y].position,
vertices[triangle.index.z].position,
triangle.color);
}
//渲染一个物体
void RenderObject(std::vector<Vertex> vertices, std::vector<Triangle> triangles)
{
for (int i = 0; i < triangles.size(); i++)
{
RenderTriangle(triangles[i], vertices);
}
}
//渲染一个实例
void RenderInstance(Instance instances)
{
Model model = instances.model;
for (int i = 0;i < model.vertices.size();i++)
{
model.vertices[i].position = ApplyTransform(model.vertices[i].position, instances.transform);
}
for (int j = 0;j < model.triangles.size();j++)
{
RenderTriangle(model.triangles[j], model.vertices);
}
}
//渲染一个场景
void RenderScene(Scene s)
{
for (int i = 0; i < s.instances.size(); i++)
{
RenderInstance(s.instances[i]);
}
}
glm::mat4 GetModel(glm::vec3 s = { 1.0f, 1.0f, 1.0f }, glm::vec4 r = { 0,1,0,60.0f }, glm::vec3 t = { 0, 0, 5 })
{
glm::mat4 sm = glm::scale(glm::mat4(1.0f), s);
glm::mat4 rm = glm::rotate(glm::mat4(1.0f), glm::radians(r.w), glm::vec3(r));
glm::mat4 tm = glm::translate(glm::mat4(1.0f), t);
//构造模型矩阵
return tm * rm * sm;
}
glm::mat4 GetView(glm::vec3 eye=glm::vec3(0,0,0),glm::vec3 center=glm::vec3(0,0,1),glm::vec3 up=glm::vec3(0,1,0))
{
return glm::lookAt(eye, center, up);
}
glm::mat4 GetPerspective(float fov=glm::radians(90.0f),float aspect= ScreenWidth/ScreenHeight,float n=0.1f,float f=100.0f)
{
return glm::perspective(fov, aspect, n, f);
}
glm::mat4 GetMVP(glm::mat4 model, glm::mat4 view, glm::mat4 perspective)
{
return perspective * view * model;
}
int main()
{
initgraph(ScreenWidth, ScreenHeight); // 创建绘图窗口,大小为 640x480 像素
std::vector<Vertex> Vertices;
Vertices.resize(8);
Vertices[0].position = { 1,1,1 ,1 };
Vertices[1].position = { -1,1,1,1 };
Vertices[2].position = { -1,-1,1 ,1 };
Vertices[3].position = { 1,-1,1 ,1 };
Vertices[4].position = { 1,1,-1 ,1 };
Vertices[5].position = { -1,1,-1 ,1 };
Vertices[6].position = { -1,-1,-1 ,1 };
Vertices[7].position = { 1,-1,-1 ,1 };
Vertices[0].color = 1.0f;
Vertices[1].color = 1.0f;
Vertices[2].color = 0.5f;
Vertices[3].color = 0.5f;
Vertices[4].color = 0.5f;
Vertices[5].color = 0.5f;
Vertices[6].color = 1.0f;
Vertices[7].color = 1.0f;
std::vector<Triangle> triangles;
triangles.resize(12);
triangles[0].index = { 0,1,2 };
triangles[0].color = RED;
triangles[1].index = { 0,2,3 };
triangles[1].color = RED;
triangles[2].index = { 4,0,3 };
triangles[2].color = GREEN;
triangles[3].index = { 4,3,7 };
triangles[3].color = GREEN;
triangles[4].index = { 5,4,7 };
triangles[4].color = BLUE;
triangles[5].index = { 5,7,6 };
triangles[5].color = BLUE;
triangles[6].index = { 1,5,6 };
triangles[6].color = YELLOW;
triangles[7].index = { 1,6,2 };
triangles[7].color = YELLOW;
triangles[8].index = { 4,5,1 };
triangles[8].color = WHITE;
triangles[9].index = { 4,1,0 };
triangles[9].color = WHITE;
triangles[10].index = { 2,6,7 };
triangles[10].color = CYAN;
triangles[11].index = { 2,7,3 };
triangles[11].color = CYAN;
{
//构造模型矩阵
glm::mat4 model =GetModel();
//构造视图矩阵
glm::mat4 view = GetView();
//构造透视投影矩阵
glm::mat4 perspective =GetPerspective();
//构造MVP矩阵
glm::mat4 mvp = GetMVP(model,view,perspective);
for (int i = 0; i < Vertices.size(); i++)
{
//对顶点进行MVP矩阵变换
Vertices[i].position = mvp * Vertices[i].position;
//透视除法
float reciprocalW = 1 / Vertices[i].position.w;
//屏幕映射
Vertices[i].position.x = (Vertices[i].position.x * reciprocalW + 1.0f) * 0.5f * ScreenWidth;
Vertices[i].position.y = (1.0f - Vertices[i].position.y * reciprocalW) * 0.5f * ScreenHeight;
}
}
Scene s;
Instance instance1;
instance1.model.name = "1";
instance1.model.vertices = Vertices;
instance1.model.triangles = triangles;
instance1.transform.translate = { 30,0,1 };
instance1.transform.rotation = { 0,1,0,0.0f };
instance1.transform.scale3D = { 1,1,1 };
Instance instance2;
instance2.model.name = "2";
instance2.model.vertices = Vertices;
instance2.model.triangles = triangles;
instance2.transform.translate = { -30,0,1 };
instance2.transform.rotation = { 0,1,0,-0.0f };
instance2.transform.scale3D = { 1,1,1 };
s.instances.push_back(instance1);
s.instances.push_back(instance2);
RenderScene(s);
_getch();
closegraph(); // 关闭绘图窗口
return 0;
}
结果
渲染填充三角形
咱们只需要把画线框三角形的方法换成画填充三角形的方法就可以画填充立方体了。
// 引用EasyX图形库头文件
#include <graphics.h>
#include <conio.h>
//glm数学相关头文件
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <iostream>
#include <vector>
#define ScreenWidth 800
#define ScreenHeight 600
//插值
std::vector<float> Interpolate(float i0, float d0, float i1, float d1)
{
std::vector<float> values;
if (glm::abs(i0 - i1) < 1e-6)
{
values.push_back(d0);
return values;
}
float a = (d1 - d0) / (i1 - i0);
float d = d0;
for (int i = i0;i < i1;i++)
{
values.push_back(d);
d = d + a;
}
return values;
}
//画线
void DrawLine(glm::vec2 P0, glm::vec2 P1, COLORREF color)
{
if (glm::abs(P1.x - P0.x) > glm::abs(P1.y - P0.y))
{
if (P0.x > P1.x)
{
std::swap(P0, P1);
}
std::vector<float> ys = Interpolate(P0.x, P0.y, P1.x, P1.y);
for (int x = P0.x;x < P1.x;x++)
{
putpixel(x, ys[x - P0.x], color);
}
}
else
{
if (P0.y > P1.y)
{
std::swap(P0, P1);
}
std::vector<float> xs = Interpolate(P0.y, P0.x, P1.y, P1.x);
for (int y = P0.y;y < P1.y;y++)
{
putpixel(xs[y - P0.y], y, color);
//Sleep(1);
}
}
}
//画线框三角形
void DrawWireframeTriangle(glm::vec2 P0, glm::vec2 P1, glm::vec2 P2, COLORREF color)
{
DrawLine(P0, P1, color);
DrawLine(P1, P2, color);
DrawLine(P2, P0, color);
}
//画填充三角形
void DrawFilledTriangle(glm::vec2 P0, glm::vec2 P1, glm::vec2 P2, COLORREF color)
{
//排序顶点 P0.y <= P1.y <= P2.y
if (P1.y < P0.y) { std::swap(P1, P0); }
if (P2.y < P0.y) { std::swap(P2, P0); }
if (P2.y < P1.y) { std::swap(P2, P1); }
//------------------P2|
//--------------------|
//--------------------| P1
//--------------------| /
//--------------------| /
//------------------P0|/
//P0P1边x坐标数组
std::vector<float> x01 = Interpolate(P0.y, P0.x, P1.y, P1.x);
//P1P2边x坐标数组
std::vector<float> x12 = Interpolate(P1.y, P1.x, P2.y, P2.x);
//P0P2边x坐标数组
std::vector<float> x02 = Interpolate(P0.y, P0.x, P2.y, P2.x);
//【注意】去掉重复坐标,P0P1和P1P2重复了P1
//x01.pop_back();
//x012=x01+x12 x012代表P0P1和P1P2两条边的x坐标数组
x01.insert(x01.end(), x12.begin(), x12.end());
std::vector<float> x012(x01);
float m = glm::floor(x012.size() / 2);
std::vector<float> x_left;
std::vector<float> x_right;
//-------第一种情况
//---------P2|
//-----------|
//-----------| P1
//-----------| /
//-----------| /
//---------P0|/
if (x02[m] < x012[m])
{
x_left = x02;
x_right = x012;
}
//-------第二种情况
//----------/|P2
//---------/ |
//------p1/ |
//-------- |
//--------- |
//----------|P0
else
{
x_left = x012;
x_right = x02;
}
//从左到右填充
for (int y = P0.y;y < P2.y;y++)
{
for (int x = x_left[y - P0.y];x < x_right[y - P0.y];x++)
{
putpixel(x, y, color);
}
Sleep(1);
}
}
struct Vertex
{
glm::vec4 position;
float color;
};
struct Triangle
{
glm::vec3 index;
COLORREF color;
};
struct Model
{
std::string name;
std::vector<Vertex> vertices;
std::vector<Triangle> triangles;
};
struct Transform
{
glm::vec3 translate;
glm::vec4 rotation;
glm::vec3 scale3D;
};
struct Instance
{
Model model;
Transform transform;
};
struct Scene
{
std::vector<Instance> instances;
};
glm::vec4 ApplyTransform(glm::vec4 pos, Transform transform)
{
glm::mat4 sm = glm::scale(glm::mat4(1.0f), transform.scale3D);
glm::mat4 rm = glm::rotate(glm::mat4(1.0f), glm::radians(transform.rotation.z), glm::vec3(transform.rotation));
glm::mat4 tm = glm::translate(glm::mat4(1.0f), transform.translate);
//构造模型矩阵
glm::mat4 model = tm * rm * sm;
return model * pos;
}
//画着色三角形
void DrawShadedTriangle(Vertex P0, Vertex P1, Vertex P2, COLORREF color)
{
BYTE r = GetRValue(color);
BYTE g = GetGValue(color);
BYTE b = GetBValue(color);
//排序顶点 P0.y <= P1.y <= P2.y
if (P1.position.y < P0.position.y) { std::swap(P1, P0); }
if (P2.position.y < P0.position.y) { std::swap(P2, P0); }
if (P2.position.y < P1.position.y) { std::swap(P2, P1); }
//------------------P2|
//--------------------|
//--------------------| P1
//--------------------| /
//--------------------| /
//------------------P0|/
//P0P1边x坐标数组
std::vector<float> x01 = Interpolate(P0.position.y, P0.position.x, P1.position.y, P1.position.x);
std::vector<float> h01 = Interpolate(P0.position.y, P0.color, P1.position.y, P1.color);
//P1P2边x坐标数组
std::vector<float> x12 = Interpolate(P1.position.y, P1.position.x, P2.position.y, P2.position.x);
std::vector<float> h12 = Interpolate(P1.position.y, P1.color, P2.position.y, P2.color);
//P0P2边x坐标数组
std::vector<float> x02 = Interpolate(P0.position.y, P0.position.x, P2.position.y, P2.position.x);
std::vector<float> h02 = Interpolate(P0.position.y, P0.color, P2.position.y, P2.color);
//【注意】去掉重复坐标,P0P1和P1P2重复了P1
//x01.pop_back();
//x012=x01+x12 x012代表P0P1和P1P2两条边的x坐标数组
x01.insert(x01.end(), x12.begin(), x12.end());
std::vector<float> x012(x01);
h01.insert(h01.end(), h12.begin(), h12.end());
std::vector<float> h012(h01);
float m = glm::floor(x012.size() / 2);
std::vector<float> x_left;
std::vector<float> x_right;
std::vector<float> h_left;
std::vector<float> h_right;
//-------第一种情况
//---------P2|
//-----------|
//-----------| P1
//-----------| /
//-----------| /
//---------P0|/
if (x02[m] < x012[m])
{
x_left = x02;
x_right = x012;
h_left = h02;
h_right = h012;
}
//-------第二种情况
//----------/|P2
//---------/ |
//------p1/ |
//-------- |
//--------- |
//----------|P0
else
{
x_left = x012;
x_right = x02;
h_left = h012;
h_right = h02;
}
//从左到右填充
for (int y = P0.position.y; y < P2.position.y; y++)
{
float x_l = x_left[y - P0.position.y];
float x_r = x_right[y - P0.position.y];
std::vector<float> h_segment = Interpolate(x_l, h_left[y - P0.position.y], x_r, h_right[y - P0.position.y]);
for (int x = x_left[y - P0.position.y]; x < x_right[y - P0.position.y]; x++)
{
COLORREF shaded_color = RGB(r * h_segment[x - x_l], g * h_segment[x - x_l], b * h_segment[x - x_l]);
putpixel(x, y, shaded_color);
}
}
}
//渲染一个三角形
void RenderTriangle(Triangle triangle, std::vector<Vertex> vertices)
{
DrawFilledTriangle(vertices[triangle.index.x].position,
vertices[triangle.index.y].position,
vertices[triangle.index.z].position,
triangle.color);
}
//渲染一个物体
void RenderObject(std::vector<Vertex> vertices, std::vector<Triangle> triangles)
{
for (int i = 0; i < triangles.size(); i++)
{
RenderTriangle(triangles[i], vertices);
}
}
//渲染一个实例
void RenderInstance(Instance instances)
{
Model model = instances.model;
for (int i = 0;i < model.vertices.size();i++)
{
model.vertices[i].position = ApplyTransform(model.vertices[i].position, instances.transform);
}
for (int j = 0;j < model.triangles.size();j++)
{
RenderTriangle(model.triangles[j], model.vertices);
}
}
//渲染一个场景
void RenderScene(Scene s)
{
for (int i = 0; i < s.instances.size(); i++)
{
RenderInstance(s.instances[i]);
}
}
glm::mat4 GetModel(glm::vec3 s = { 1.0f, 1.0f, 1.0f }, glm::vec4 r = { 0,1,0,60.0f }, glm::vec3 t = { 0, 0, 5 })
{
glm::mat4 sm = glm::scale(glm::mat4(1.0f), s);
glm::mat4 rm = glm::rotate(glm::mat4(1.0f), glm::radians(r.w), glm::vec3(r));
glm::mat4 tm = glm::translate(glm::mat4(1.0f), t);
//构造模型矩阵
return tm * rm * sm;
}
glm::mat4 GetView(glm::vec3 eye=glm::vec3(0,0,0),glm::vec3 center=glm::vec3(0,0,1),glm::vec3 up=glm::vec3(0,1,0))
{
return glm::lookAt(eye, center, up);
}
glm::mat4 GetPerspective(float fov=glm::radians(90.0f),float aspect= ScreenWidth/ScreenHeight,float n=0.1f,float f=100.0f)
{
return glm::perspective(fov, aspect, n, f);
}
glm::mat4 GetMVP(glm::mat4 model, glm::mat4 view, glm::mat4 perspective)
{
return perspective * view * model;
}
int main()
{
initgraph(ScreenWidth, ScreenHeight); // 创建绘图窗口,大小为 640x480 像素
std::vector<Vertex> Vertices;
Vertices.resize(8);
Vertices[0].position = { 1,1,1 ,1 };
Vertices[1].position = { -1,1,1,1 };
Vertices[2].position = { -1,-1,1 ,1 };
Vertices[3].position = { 1,-1,1 ,1 };
Vertices[4].position = { 1,1,-1 ,1 };
Vertices[5].position = { -1,1,-1 ,1 };
Vertices[6].position = { -1,-1,-1 ,1 };
Vertices[7].position = { 1,-1,-1 ,1 };
Vertices[0].color = 1.0f;
Vertices[1].color = 1.0f;
Vertices[2].color = 0.5f;
Vertices[3].color = 0.5f;
Vertices[4].color = 0.5f;
Vertices[5].color = 0.5f;
Vertices[6].color = 1.0f;
Vertices[7].color = 1.0f;
std::vector<Triangle> triangles;
triangles.resize(12);
triangles[0].index = { 0,1,2 };
triangles[0].color = RED;
triangles[1].index = { 0,2,3 };
triangles[1].color = RED;
triangles[2].index = { 4,0,3 };
triangles[2].color = GREEN;
triangles[3].index = { 4,3,7 };
triangles[3].color = GREEN;
triangles[4].index = { 5,4,7 };
triangles[4].color = BLUE;
triangles[5].index = { 5,7,6 };
triangles[5].color = BLUE;
triangles[6].index = { 1,5,6 };
triangles[6].color = YELLOW;
triangles[7].index = { 1,6,2 };
triangles[7].color = YELLOW;
triangles[8].index = { 4,5,1 };
triangles[8].color = WHITE;
triangles[9].index = { 4,1,0 };
triangles[9].color = WHITE;
triangles[10].index = { 2,6,7 };
triangles[10].color = CYAN;
triangles[11].index = { 2,7,3 };
triangles[11].color = CYAN;
{
//构造模型矩阵
glm::mat4 model =GetModel();
//构造视图矩阵
glm::mat4 view = GetView();
//构造透视投影矩阵
glm::mat4 perspective =GetPerspective();
//构造MVP矩阵
glm::mat4 mvp = GetMVP(model,view,perspective);
for (int i = 0; i < Vertices.size(); i++)
{
//对顶点进行MVP矩阵变换
Vertices[i].position = mvp * Vertices[i].position;
//透视除法
float reciprocalW = 1 / Vertices[i].position.w;
//屏幕映射
Vertices[i].position.x = (Vertices[i].position.x * reciprocalW + 1.0f) * 0.5f * ScreenWidth;
Vertices[i].position.y = (1.0f - Vertices[i].position.y * reciprocalW) * 0.5f * ScreenHeight;
}
}
Scene s;
Instance instance1;
instance1.model.name = "1";
instance1.model.vertices = Vertices;
instance1.model.triangles = triangles;
instance1.transform.translate = { 30,0,1 };
instance1.transform.rotation = { 0,1,0,0.0f };
instance1.transform.scale3D = { 1,1,1 };
Instance instance2;
instance2.model.name = "2";
instance2.model.vertices = Vertices;
instance2.model.triangles = triangles;
instance2.transform.translate = { -30,0,1 };
instance2.transform.rotation = { 0,1,0,-0.0f };
instance2.transform.scale3D = { 1,1,1 };
s.instances.push_back(instance1);
s.instances.push_back(instance2);
RenderScene(s);
_getch();
closegraph(); // 关闭绘图窗口
return 0;
}
结果
为什么会出现这种情况?因为我们并没有处理物体的深度问题,如果首先绘制了近处的物体,那么后面绘制远处的物体的时候就会覆盖掉前面绘制的近处的物体。这个时候就需要深度缓存出现了,我们把每一个像素的深度保存起来,到最后就只绘制最近处的像素。
结尾
如果你遇到了问题可以在评论区告诉我哦
光栅化渲染器:渲染一个场景欢迎去我的个人网站留言
项目地址
最后
以上就是舒适菠萝为你收集整理的光栅化渲染器:渲染一个场景前言渲染一个线框立方体渲染多个线框立方体渲染填充三角形结尾的全部内容,希望文章能够帮你解决光栅化渲染器:渲染一个场景前言渲染一个线框立方体渲染多个线框立方体渲染填充三角形结尾所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复