79 lines
3.3 KiB
C++
79 lines
3.3 KiB
C++
#include "3DRenderer.hpp"
|
|
|
|
|
|
// Rendering order:
|
|
// model matrix (Object SRT) -> view matrix (camera matrix inverted) -> proj matrix -> clipping -> perspective divide -> viewport transformation -> Rasterizer (draw pixels inside projected triangles on 2D screen)
|
|
// object coordinate -> world coordinate -> camera coordinate -> clip/screen coordinate
|
|
//
|
|
// Rasterizer inputs elements:
|
|
// - texture-buffer (2D array of pixels color value)
|
|
// - z-buffer (2D array of float representing the nearest pixel's depth, all pixels beyond are ignored)
|
|
// - projected vertices-buffer on screen (using vertices-buffer and projection function)
|
|
//
|
|
// Refs:
|
|
// * https://en.wikipedia.org/wiki/3D_projection
|
|
// * https://www.scratchapixel.com/lessons/3d-basic-rendering/rasterization-practical-implementation/overview-rasterization-algorithm.html
|
|
|
|
Graphic3DRenderer::Graphic3DRenderer() {
|
|
if (mMainCamera == nullptr) {
|
|
mMainCamera = std::make_unique<Camera>();
|
|
mMainCamera->SetPosition(0.0f, 3.0f, -20.0f);
|
|
mMainCamera->SetFrustrum(90.0f, 1280.f/324.f, 1.0f, 100.f);
|
|
mMainCamera->UpdateCamView();
|
|
}
|
|
}
|
|
|
|
Graphic3DRenderer::~Graphic3DRenderer() {}
|
|
|
|
void Graphic3DRenderer::Draw(sf::RenderTexture& context) {
|
|
sf::BlendMode sBM = sf::BlendNone;
|
|
sf::RenderStates sRS(sBM);
|
|
sf::Color yep[] = {sf::Color::White, sf::Color::Blue, sf::Color::Green, sf::Color::Red, sf::Color::Magenta, sf::Color::Cyan, sf::Color::Yellow};
|
|
|
|
static float thetaAngle = 0.31f;
|
|
thetaAngle = thetaAngle >= 6.283185f ? -6.283185f : thetaAngle + 0.004f;
|
|
bool clipped = false;
|
|
|
|
M3D_MATRIX viewMat = mMainCamera->GetView();
|
|
M3D_MATRIX projMat = mMainCamera->GetProj();
|
|
M3D_MATRIX modelMat = M3D_MIdentity() * M3D_TransformMatrixScaling(10.0f, 10.0f, 10.0f) * M3D_TransformMatrixRotationX(thetaAngle) * M3D_TransformMatrixRotationZ(0.5f*thetaAngle) * M3D_TransformMatrixTranslate(0.0f, 0.0f, 5.0f);
|
|
M3D_MATRIX viewProjMat = (viewMat) * (projMat);
|
|
M3D_MATRIX MVPMat = modelMat * viewProjMat;
|
|
M3D_MATRIX viewportMat = M3D_TransformMatrixViewport(1280.0f, 324.f, 0.0f, 0.0f);
|
|
uint8_t v_cnt = 0, yep_cnt = 0;
|
|
sf::Vertex v_tri[4];
|
|
M3D_F3 _2dCoord;
|
|
|
|
for (const auto _v : testObj.mMesh) {
|
|
M3D_VECTOR _vV = M3D_V4LoadF3(&_v.pos);
|
|
M3D_VECTOR projV = M3D_V3Transform(_vV, MVPMat);
|
|
//projV = M3D_V3Transform(projV, viewProjMat);
|
|
|
|
// Clipping (simple)
|
|
if (M3D_V4GetZ(projV) <= 0)
|
|
clipped = true;
|
|
|
|
// Perspective divide
|
|
M3D_VECTOR _w = M3D_V4SplatW(projV);
|
|
projV = M3D_V4Divide(projV, _w);
|
|
|
|
// Viewport transform
|
|
projV = M3D_V3Transform(projV, (viewportMat));
|
|
M3D_V4StoreF3(&_2dCoord, projV);
|
|
v_tri[v_cnt].position.x = _2dCoord.x;
|
|
v_tri[v_cnt].position.y = _2dCoord.y;
|
|
//v_tri[v_cnt].position.z = ((far+near)/2)+((far-near)/2)*_2dCoord.z; //TODO: transform matrix is incomplete
|
|
v_tri[v_cnt].color = yep[yep_cnt % 5];
|
|
|
|
if (v_cnt++ >= 2) {
|
|
if (!clipped) {
|
|
v_tri[3] = v_tri[0];
|
|
context.draw(v_tri, 4, sf::LineStrip, sRS);
|
|
//context.draw(v_tri, 3, sf::Triangles, sRS);
|
|
}
|
|
v_cnt = 0;
|
|
yep_cnt++;
|
|
clipped = false;
|
|
}
|
|
}
|
|
} |