VSOutput MyVertexShader(const VSInput vsInput) {
VSOutput vsOutput;
// 여기서 여러가지 변환 가능
// vsOutput.position =
// RotateAboutX(
// RotateAboutY(vsInput.position * constants.transformation.scale,
// constants.transformation.rotationY),
// constants.transformation.rotationX) +
// constants.transformation.translation;
// 마지막에 1.0f 추가
Vector4 point = Vector4(vsInput.position.x, vsInput.position.y,
vsInput.position.z, 1.0f);
// point = ...;
point = Vector4::Transform(point, constants.modelMatrix);
vsOutput.position = Vector3(point.x, point.y, point.z);
// 주의: 노멀 벡터도 물체와 같이 회전시켜줘야 합니다.
// 더 편하게 구현할 방법은 없을까요?
// vsOutput.normal = RotateAboutX(
// RotateAboutX(
// RotateAboutY(vsInput.normal, constants.transformation.rotationY),
// constants.transformation.rotationX),
// constants.transformation.rotationX);
// 마지막에 0.0f 추가
Vector4 normal =
Vector4(vsInput.normal.x, vsInput.normal.y, vsInput.normal.z, 0.0f);
// Unon-uniform transformation인 경우에는 보정 필요
// normal = ...;
normal = Vector4::Transform(normal, constants.invTranspose);
normal.Normalize();
vsOutput.normal = Vector3(normal.x, normal.y, normal.z);
return vsOutput;
}
void Rasterization::Render(vector<Vector4> &pixels) {
// 깊이 버퍼 초기화
this->depthBuffer.resize(pixels.size());
// 깊이 버퍼의 초기값은 렌더링할 가장 먼 거리를 설정해준다는 의미도
// 있습니다. 즉, 그 거리보다 더 멀리있는 픽셀은 무시하게 됩니다.
// DirectX에서는 내부적으로 렌더링할 공간을 스케일해서 가장 먼
// 거리를 1.0f으로 만들기 때문에 보통 1.0으로 초기화하지만,
// 여기서는 편의상 1.0보다 큰 값(예: 10.0f)을 사용하겠습니다.
fill(this->depthBuffer.begin(), this->depthBuffer.end(), 10.0f);
for (const auto &mesh : this->meshes) {
// 렌더링 하기 전에 필요한 데이터를
// GPU 메모리로 복사하는 것처럼 생각해주세요.
// constants.transformation = mesh->transformation;
// Vertex Shader에서 변환에 사용했던 코드
// vsOutput.position =
// RotateAboutX(
// RotateAboutY(vsInput.position * constants.transformation.scale,
// constants.transformation.rotationY),
// constants.transformation.rotationX) +
// constants.transformation.translation;
// 여기서 GPU에게 보내줄 변환 행렬을 만들어줘야 합니다.
// constants.modelMatrix = ...;
// constants.invTranspose = ..;
constants.modelMatrix =
Matrix::CreateScale(mesh->transformation.scale) *
Matrix::CreateRotationY(mesh->transformation.rotationY) *
Matrix::CreateRotationX(mesh->transformation.rotationX) *
Matrix::CreateTranslation(mesh->transformation.translation);
constants.invTranspose = constants.modelMatrix;
constants.invTranspose.Translation(Vector3(0.0f));
constants.invTranspose = constants.invTranspose.Invert().Transpose();
// 모델 변환 이외에도 시점 변환, 프로젝션 변환을 행렬로 미리 계산해서
// 쉐이더로 보내줄 수 있습니다.
constants.material = mesh->material;
constants.light = light;
constants.lightType = this->lightType;
this->vertexBuffer.resize(mesh->vertexBuffer.size());
this->normalBuffer.resize(mesh->normalBuffer.size());
this->colorBuffer.resize(mesh->vertexBuffer.size());
// this->uvBuffer.resize(mesh->uvBuffer.size());
// GPU 안에서는 멀티쓰레딩으로 여러 버텍스를 한꺼번에 처리합니다.
for (size_t i = 0; i < mesh->vertexBuffer.size(); i++) {
VSInput vsInput;
vsInput.position = mesh->vertexBuffer[i];
vsInput.normal = mesh->normalBuffer[i];
// vsInput.color = mesh->colorBuffer[i];
// vsInput.uv = mesh->uvBuffer[i];
auto vsOutput = MyVertexShader(vsInput);
this->vertexBuffer[i] = vsOutput.position;
this->normalBuffer[i] = vsOutput.normal;
// this->colorBuffer[i] = vsOutput.color;
// this->uvBuffer[i] = vsOutput.uv;
}
this->indexBuffer = mesh->indexBuffer;
for (size_t i = 0; i < this->indexBuffer.size(); i += 3) {
DrawIndexedTriangle(i, pixels);
}
}
}