Repository navigation
Expand file tree
/
Copy pathRenderer.cpp
More file actions
125 lines (111 loc) · 5.14 KB
/
Copy pathRenderer.cpp
File metadata and controls
125 lines (111 loc) · 5.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include <cmath>
#include <tuple>
#include <limits>
#include <cstdlib>
#include <random>
#include "RenderObjects.h"
#include "Shaders.h"
int main(int argc, char** argv)
{
TGAColor bgColor = { 200, 200, 200, 255 };
TGAImage framebuffer(width, height, TGAImage::RGB, bgColor);
Viewport(width, height, 0, 0);
zbuffer.resize(width * height, -std::numeric_limits<double>::max());
init_zbuffer(width, height);
const ConstantBuffer& cb{ Vector3(-1, 0, 2), Vector3(0, 0, 0), Vector3(0, 1, 0) };
std::vector<double> shadowBuffer(width * height, -std::numeric_limits<double>::max());
std::vector<double> cameraZBuffer(width * height, -std::numeric_limits<double>::max());
// 获取光源空间矩阵
auto lightSpaceMatrix = ShadowTransform::GetLightSpaceMatrix(cb.lightDir, cb.lightCenter, cb.lightUp);
std::vector<RenderObjects> sceneObjects;
//加载第一个模型
RenderObjects diablo;
if (diablo.Load("Models/diablo3_pose/", "diablo3_pose"))
sceneObjects.push_back(std::move(diablo)); // 使用 std::move 避免深拷贝,提高性能
//加载第二个模型
RenderObjects floor;
if (floor.Load("Models/floor/", "floor"))
sceneObjects.push_back(std::move(floor));
if (sceneObjects.empty())
{
std::cerr << "No scene models loaded. Run from the repository root and provide the "
"OBJ files documented in README.md.\n";
return EXIT_FAILURE;
}
std::fill(zbuffer.begin(), zbuffer.end(), -1000.0);
for (const auto& obj : sceneObjects)
{
const auto& render_buffer = obj.mesh.GetRenderBuffer();
Shader_Depth depthShader(obj.mesh, lightSpaceMatrix);
for (int i = 0; i < render_buffer.size(); i += 3)
{
std::array<Vector4, 3> clip = depthShader.vertex(i);
rasterize(clip, depthShader, framebuffer);
}
}
// 所有物体画完后,统一保存阴影图
shadowBuffer = zbuffer;
std::fill(zbuffer.begin(), zbuffer.end(), -1000.0);
//遍历所有模型
for (const auto& obj : sceneObjects)
{
const auto& render_buffer = obj.mesh.GetRenderBuffer();
//清空全局 zbuffer,准备为玩家相机使用
Shader_NormalMap shader(
obj.mesh,
render_buffer,
obj.material.normalMap,
obj.material.diffuseMap,
obj.material.specMap,
obj.material.glowMap,
cb, lightSpaceMatrix,
shadowBuffer);
LookAt(shader.cb.eye, shader.cb.center, shader.cb.up);
Perspective(length(shader.cb.eye - shader.cb.center));
for (int i = 0; i < render_buffer.size(); i += 3)
{
std::array<Vector4, 3> clip = shader.vertex(i);
//同时更新 framebuffer 和 zbuffer
rasterize(clip, shader, framebuffer);
}
}
//随机值生成器,用于SSAO采样
constexpr double ao_radius = .1; // ssao ball radius in normalized device coordinates
constexpr int nsamples = 128; // number of samples in the ball
auto smoothstep = [](double edge0, double edge1, double x)
{ // smoothstep returns 0 if the input is less than the left edge,
double t = std::clamp((x - edge0) / (edge1 - edge0), 0., 1.); // 1 if the input is greater than the right edge,
return t * t * (3 - 2 * t); // Hermite interpolation inbetween. The derivative of the smoothstep function is zero at both edges.
};
#pragma omp parallel for
//SSAO采样
for (int y = 0; y < height; ++y)
{
// Each row owns its RNG; results do not depend on OpenMP scheduling.
std::mt19937 gen(static_cast<std::mt19937::result_type>(y));
std::uniform_real_distribution<double> dist(-ao_radius, ao_radius);
for (int x = 0; x < width; ++x)
{
double z = zbuffer[x + y * width];
if (z < -100) continue;
Vector4 pos = viewportInverse * Vector4(x, y, z, 1.0f);
double vote = 0;
double voters = 0;
for (int i = 0; i < nsamples; ++i)
{
Vector4 samplePos = viewport * (pos + Vector4(dist(gen), dist(gen), dist(gen), 0));
if (samplePos.x < 0 || samplePos.x >= width || samplePos.y < 0 || samplePos.y >= height) continue;
double d = zbuffer[int(samplePos.x) + int(samplePos.y) * width];
if (z + 5 * ao_radius < d) continue;
voters++;
vote += d > samplePos.z;
}
double ssao = voters > 0 ? smoothstep(0, 1, 1 - vote / voters * .4) : 1.0;
TGAColor c = framebuffer.get(x, y);
//framebuffer.set(x, y, {static_cast<unsigned char>(ssao * 255), static_cast<unsigned char>(ssao * 255), static_cast<unsigned char>(ssao * 255), c[3]});
framebuffer.set(x, y, { static_cast<unsigned char>(c[0] * ssao), static_cast<unsigned char>(c[1] * ssao), static_cast<unsigned char>(c[2] * ssao), c[3] });
}
}
const char* outputPath = argc > 1 ? argv[1] : "framebuffer.tga";
return framebuffer.write_tga_file(outputPath) ? EXIT_SUCCESS : EXIT_FAILURE;
}