支持抗锯齿

This commit is contained in:
2025-08-23 12:19:28 +08:00
parent dd72a8e3fd
commit 1f7720d54e
23 changed files with 879 additions and 183 deletions
+2
View File
@@ -8,6 +8,8 @@ add_executable(dvt_rasterization WIN32
dvr_main.cpp
dvr_triangle.h
dvr_triangle.cpp
dvr_canvas.h
dvr_canvas.cpp
)
set_property(TARGET dvt_rasterization PROPERTY FOLDER "test")
+83
View File
@@ -0,0 +1,83 @@
#include "dvr_canvas.h"
#include <array>
#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
#include <SDL3/SDL.h>
void Canvas::reset(int32_t width, int32_t height)
{
m_width = width;
m_height = height;
m_pixels.resize(m_width * m_height);
for (int32_t i = 0; i < m_width * m_height; i++)
{
m_pixels[i].fragementID = -1;
m_pixels[i].mask = 0;
m_pixels[i].color = 0;
}
m_fragementArray.clear();
}
void Canvas::_insertTriangle(const Triangle& triangle)
{
for (size_t i = 0; i < triangle.m_pixels.size(); i++)
{
const Triangle::Pixel trianglePixel = triangle.m_pixels[i];
Pixel& pixel = m_pixels[trianglePixel.y * m_width + trianglePixel.x];
Fragement newFragement;
newFragement.id = (int32_t)m_fragementArray.size();
newFragement.color = triangle.m_pixelColor;
newFragement.mask = trianglePixel.mask;
newFragement.next = pixel.fragementID;
pixel.fragementID = newFragement.id;
m_fragementArray.push_back(newFragement);
}
}
void Canvas::_update_without_AA()
{
for (size_t i = 0; i < m_pixels.size(); i++)
{
Pixel& pixel = m_pixels[i];
if (pixel.fragementID < 0) continue;
const Fragement& fragement = m_fragementArray[pixel.fragementID];
pixel.mask = fragement.mask;
pixel.color = fragement.color;
pixel.alpha = 1.f;
}
}
void Canvas::update(davinci::AntiAliasingTech aaTech, const TriangleArray& triangleArray, const Triangle* pActionTriangle)
{
reset(m_width, m_height);
for (size_t i = 0; i < triangleArray.size(); i++)
{
const Triangle& triangle = triangleArray[i];
_insertTriangle(triangle);
}
if (pActionTriangle != nullptr)
{
_insertTriangle(*pActionTriangle);
}
if (aaTech == davinci::AntiAliasingTech::AA_None)
{
_update_without_AA();
}
else if (aaTech == davinci::AntiAliasingTech::AA_MSAA_2X2)
{
_update_with_AA<4>();
}
else if ( aaTech == davinci::AntiAliasingTech::AA_MSAA_4X4)
{
_update_with_AA<16>();
}
}
+108
View File
@@ -0,0 +1,108 @@
#pragma once
#include "dvr_triangle.h"
#include "math/dvc_vector4.h"
class Canvas
{
public:
struct Pixel
{
davinci::fVector3 color;
float alpha;
uint32_t mask;
int32_t fragementID;
};
typedef std::vector<Pixel> PixelArray;
struct Fragement
{
int32_t id;
davinci::fVector3 color;
uint32_t mask;
int32_t next;
};
typedef std::vector<Fragement> FragementArray;
public:
int32_t width() const { return m_width; }
int32_t height() const { return m_height; }
const Pixel& pixel(int32_t x, int32_t y) const
{
return m_pixels[y * m_width + x];
}
void reset(int32_t width, int32_t height);
void update(davinci::AntiAliasingTech aaTech, const TriangleArray& riangleArray, const Triangle* pActionTriangle = nullptr);
private:
void _insertTriangle(const Triangle& triangle);
void _update_without_AA();
template<int32_t kSampleSize>
void _update_with_AA()
{
for (size_t i = 0; i < m_pixels.size(); i++)
{
Pixel& pixel = m_pixels[i];
if (pixel.fragementID < 0) continue;
FragementArray pixelFragements;
int32_t fragementID = pixel.fragementID;
while (fragementID >= 0 && fragementID < m_fragementArray.size())
{
const Fragement& fragement = m_fragementArray[fragementID];
pixelFragements.insert(pixelFragements.begin(), fragement);
fragementID = fragement.next;
}
if (pixelFragements.size() == 0) continue;
else if (pixelFragements.size() == 1)
{
const Fragement& fragement = pixelFragements[0];
pixel.mask = fragement.mask;
pixel.color = fragement.color;
pixel.alpha = davinci::MathUtil::popcount((uint16_t)(fragement.mask)) / (float32_t)kSampleSize;
}
else
{
std::array<int32_t, kSampleSize> samples;
samples.fill(-1);
for (size_t j = 0; j < pixelFragements.size(); j++)
{
const Fragement& fragement = pixelFragements[j];
for (int32_t k = 0; k < kSampleSize; k++)
{
if ((fragement.mask & (1 << k)) != 0)
{
samples[k] = fragement.id;
}
}
}
pixel.mask = 0;
int32_t bitCounts = 0;
for (int32_t k = 0; k < kSampleSize; k++)
{
int32_t fragementID = samples[k];
if (fragementID < 0 || fragementID>m_fragementArray.size()) continue;
const Fragement& fragement = m_fragementArray[fragementID];
pixel.mask |= (1 << k);
pixel.color += fragement.color;
bitCounts++;
}
if (bitCounts > 1) {
pixel.color /= (float32_t)bitCounts;
}
pixel.alpha = bitCounts / (float32_t)kSampleSize;
}
}
}
private:
int32_t m_width;
int32_t m_height;
PixelArray m_pixels; // final pixels in the canvas
FragementArray m_fragementArray;
};
+286 -99
View File
@@ -12,6 +12,8 @@
#include "math/dvc_vector3.h"
#include "dvr_triangle.h"
#include "dvr_canvas.h"
#include "rasterizer/dvc_rasterizer_triangle.h"
using namespace davinci;
@@ -19,53 +21,57 @@ enum MouseAction
{
MT_NULL,
MT_FIRST_LINE,
MT_TRIANGLE
MT_TRIANGLE,
MT_PAN,
};
const float MIN_SCALE = 4.f;
const float MAX_SCALE = 60.f;
const float MAX_SCALE = 120.f;
const float TRIANGLE_BORDER_WIDTH = 1.5f;
const float ACTION_WIDTH = 1.f;
const fVector3 GRID_BORDER_COLOR = fVector3(0.f, 0.f, 0.f);
const fVector3 GRID_CROSS_COLOR = fVector3(0.8f, 0.8f, 0.8f);
const fVector3 GRID_CROSS_COLOR = fVector3(0.1f, 0.1f, 0.1f);
const fVector3 TRIANGLE_BORDER_COLOR = fVector3(0.f, 0.f, 0.f);
const fVector3 ACTION_COLOR = fVector3(1.f, 0.f, 0.f);
const int32_t CANVAS_WIDTH = 512;
const int32_t CANVAS_HEIGHT = 256;
int32_t g_viewWidth = 2048;
int32_t g_viewHeight = 1440;
int32_t g_canvasWidth;
int32_t g_canvasHeight;
float32_t g_scale = MAX_SCALE;
float32_t g_scale = MAX_SCALE/2.0f;
int32_t g_lbCorner_x = 20;
int32_t g_lbCorner_y = 20;
int32_t g_nDrawGridLevel = 0; //0:all 1:fine+coarse+tile 2:coarse+tile 3: tile
int32_t g_screenMousePosX = 0, g_screenMousePosY = 0;
float32_t g_mousePosX, g_mousePosY;
bool g_bSnapMode = true;
float g_fSnapSize = 0.25f;
MouseAction g_currentAction = MT_NULL;
bool g_bDrawExtension = false;
Triangle g_currentTriangle;
TriangleVector g_allTriangles;
int32_t g_nStartPanX, g_nStartPanY;
int32_t g_nPanX, g_nPanY;
Triangle g_currentTriangle(INT_MAX, ACTION_COLOR);
TriangleArray g_allTriangles;
Canvas g_canvas;
AntiAliasingTech g_aaTech = AntiAliasingTech::AA_None;
SDL_Window* g_window = NULL;
SDL_Renderer* g_renderer = NULL;
#define trans_w2s_x(x) ((float32_t)(x) * g_scale + g_lbCorner_x)
#define trans_w2s_y(y) ((float32_t)g_viewHeight - ((float32_t)(y) * g_scale + g_lbCorner_y))
#define trans_w2s_x(x) ((float32_t)(x) * g_scale + g_lbCorner_x + g_nPanX)
#define trans_w2s_y(y) ((float32_t)g_viewHeight - ((float32_t)(y) * g_scale + g_lbCorner_y + g_nPanY))
#define trans_s2w_x(x) ((float32_t)(x - g_lbCorner_x) / g_scale)
#define trans_s2w_y(y) ((float32_t)(g_viewHeight - y - g_lbCorner_y) / g_scale)
#define trans_s2w_x(x) ((float32_t)(x - g_lbCorner_x - g_nPanX) / g_scale)
#define trans_s2w_y(y) ((float32_t)(g_viewHeight - y - g_lbCorner_y - g_nPanY) / g_scale)
void _onFramebufferSize(int32_t w, int32_t h)
{
g_viewWidth = w;
g_viewHeight = h > 0 ? h : 1;
g_canvasWidth = ((int32_t)floorf(g_viewWidth / (g_scale * 64)) + 1) * 64;
g_canvasHeight = ((int32_t)floorf(g_viewHeight / (g_scale * 64)) + 1) * 64;
if (g_scale < 10.f) g_nDrawGridLevel = 3;
else if (g_scale < 20.f) g_nDrawGridLevel = 2;
else if (g_scale < 50.f) g_nDrawGridLevel = 1;
@@ -77,11 +83,28 @@ static void _drawGrid(void)
int32_t horLength = (int32_t)floorf(g_viewWidth / g_scale);
int32_t verLength = (int32_t)floorf(g_viewHeight / g_scale);
// draw canvas background
SDL_FRect rect;
rect.x = trans_w2s_x(0);
rect.y = trans_w2s_y(0);
rect.w = g_canvas.width() * g_scale;
rect.h = -g_canvas.height() * g_scale;
SDL_SetRenderDrawColorFloat(g_renderer, 255, 255, 255, SDL_ALPHA_OPAQUE_FLOAT);
SDL_RenderFillRect(g_renderer, &rect);
fVector3 lineColor[] = { fVector3(0.f, 0.f, 0.f), fVector3(0.5f, 0.5f, 0.5f), fVector3(0.7f,0.7f,0.7f), fVector3(0.9f, 0.9f,0.9f) };
// Horizontal lines
for (int i = 0; i <= verLength; i++) {
int level = 3;
for (int32_t i = (int32_t)trans_s2w_y(0); ; i--)
{
if (i > g_canvas.height()) continue;
if (i < 0) break;
float32_t screenY = trans_w2s_y(i);
if (screenY < 0) continue;
if (screenY > g_viewHeight) break;
int32_t level = 3;
if (i % 64 == 0)level = 0;
else if (i % 16 == 0) level = 1;
@@ -89,13 +112,20 @@ static void _drawGrid(void)
if (level > 3 - g_nDrawGridLevel) continue;
SDL_SetRenderDrawColorFloat(g_renderer, lineColor[level].x, lineColor[level].y, lineColor[level].z, SDL_ALPHA_OPAQUE_FLOAT);
SDL_RenderLine(g_renderer, trans_w2s_x(0), trans_w2s_y(i), trans_w2s_x(horLength), trans_w2s_y(i));
SDL_RenderLine(g_renderer, trans_w2s_x(0), screenY, trans_w2s_x(g_canvas.width()), screenY);
}
// Vertical lines
for (int j = 0; j <= horLength; j++) {
int level = 3;
for (int32_t j = (int32_t)trans_s2w_x(0); ; j++)
{
if (j < 0) continue;
if (j > g_canvas.width()) break;
float32_t screenX = trans_w2s_x(j);
if (screenX < 0) continue;
if (screenX > g_viewWidth) break;
int32_t level = 3;
if (j % 64 == 0)level = 0;
else if (j % 16 == 0) level = 1;
@@ -103,47 +133,7 @@ static void _drawGrid(void)
if (level > 3 - g_nDrawGridLevel) continue;
SDL_SetRenderDrawColorFloat(g_renderer, lineColor[level].x, lineColor[level].y, lineColor[level].z, SDL_ALPHA_OPAQUE_FLOAT);
SDL_RenderLine(g_renderer, trans_w2s_x(j), trans_w2s_y(0), trans_w2s_x(j), trans_w2s_y(verLength));
}
//cross
if (g_nDrawGridLevel < 3)
{
SDL_SetRenderDrawColorFloat(g_renderer, GRID_CROSS_COLOR.x, GRID_CROSS_COLOR.y, GRID_CROSS_COLOR.z, SDL_ALPHA_OPAQUE_FLOAT);
float crossLength = 0.2f;
for (int i = 0; i < verLength; i++)
{
for (int j = 0; j < horLength; j++)
{
SDL_RenderLine(g_renderer,
trans_w2s_x(j + 0.5f - crossLength), trans_w2s_y(i + 0.5f - crossLength),
trans_w2s_x(j + 0.5f + crossLength), trans_w2s_y(i + 0.5f + crossLength)
);
SDL_RenderLine(g_renderer,
trans_w2s_x(j + 0.5f - crossLength), trans_w2s_y(i + 0.5f + crossLength),
trans_w2s_x(j + 0.5f + crossLength), trans_w2s_y(i + 0.5f - crossLength)
);
}
}
}
}
static void _drawTrianglePixel(const Triangle& triangle)
{
SDL_SetRenderDrawBlendMode(g_renderer, SDL_BLENDMODE_BLEND);
SDL_SetRenderDrawColorFloat(g_renderer, triangle.pixelColor[0], triangle.pixelColor[1], triangle.pixelColor[2], 0.5f);
for (const auto& dot : triangle.pixels)
{
SDL_FRect rect;
rect.x = trans_w2s_x(dot.first);
rect.y = trans_w2s_y(dot.second);
rect.w = g_scale;
rect.h = -g_scale;
SDL_RenderFillRect(g_renderer, &rect);
SDL_RenderLine(g_renderer, screenX, trans_w2s_y(0), screenX, trans_w2s_y(g_canvas.height()));
}
}
@@ -152,22 +142,42 @@ void _drawTriangleBorder(const Triangle& triangle, const fVector3& color, float
SDL_SetRenderDrawColorFloat(g_renderer, color[0], color[1], color[2], SDL_ALPHA_OPAQUE_FLOAT);
SDL_FPoint points[4] = {
{trans_w2s_x(triangle.p0.x), trans_w2s_y(triangle.p0.y)},
{trans_w2s_x(triangle.p1.x), trans_w2s_y(triangle.p1.y)},
{trans_w2s_x(triangle.p2.x), trans_w2s_y(triangle.p2.y)},
{trans_w2s_x(triangle.p0.x), trans_w2s_y(triangle.p0.y)}
{trans_w2s_x(triangle.m_p0.x), trans_w2s_y(triangle.m_p0.y)},
{trans_w2s_x(triangle.m_p1.x), trans_w2s_y(triangle.m_p1.y)},
{trans_w2s_x(triangle.m_p2.x), trans_w2s_y(triangle.m_p2.y)},
{trans_w2s_x(triangle.m_p0.x), trans_w2s_y(triangle.m_p0.y)}
};
SDL_RenderLines(g_renderer, points, 4);
}
void _drawCanvasPixel()
{
SDL_SetRenderDrawBlendMode(g_renderer, SDL_BLENDMODE_BLEND);
for (int32_t y = 0; y < g_canvas.height(); y++)
{
for (int32_t x = 0; x < g_canvas.width(); x++)
{
const Canvas::Pixel& pixel = g_canvas.pixel(x, y);
if (pixel.fragementID < 0) continue;
SDL_FRect rect;
rect.x = trans_w2s_x(x);
rect.y = trans_w2s_y(y);
rect.w = g_scale;
rect.h = -g_scale;
SDL_SetRenderDrawColorFloat(g_renderer, pixel.color.x, pixel.color.y, pixel.color.z, pixel.alpha);
SDL_RenderFillRect(g_renderer, &rect);
}
}
}
void _drawTriangles(void)
{
for (const auto& triangle : g_allTriangles) {
_drawTrianglePixel(triangle);
}
_drawCanvasPixel();
for (const auto& triangle : g_allTriangles) {
for (const auto& triangle : g_allTriangles)
{
_drawTriangleBorder(triangle, TRIANGLE_BORDER_COLOR, TRIANGLE_BORDER_WIDTH);
}
}
@@ -210,9 +220,12 @@ void _drawAction(void)
if (g_bDrawExtension) {
SDL_SetRenderDrawColorFloat(g_renderer, ACTION_COLOR.x/2.f, ACTION_COLOR.y/2.f, ACTION_COLOR.z/2.f, SDL_ALPHA_OPAQUE_FLOAT);
_drawSegmentInAABB(g_currentTriangle.p0.xy(), g_currentTriangle.p1.xy(), 0, (float)g_canvasWidth, 0, (float)g_canvasHeight);
_drawSegmentInAABB(g_currentTriangle.p1.xy(), g_currentTriangle.p2.xy(), 0, (float)g_canvasWidth, 0, (float)g_canvasHeight);
_drawSegmentInAABB(g_currentTriangle.p2.xy(), g_currentTriangle.p0.xy(), 0, (float)g_canvasWidth, 0, (float)g_canvasHeight);
_drawSegmentInAABB(g_currentTriangle.m_p0.xy(), g_currentTriangle.m_p1.xy(),
0, (float)g_canvas.width(), 0, (float)g_canvas.height());
_drawSegmentInAABB(g_currentTriangle.m_p1.xy(), g_currentTriangle.m_p2.xy(),
0, (float)g_canvas.width(), 0, (float)g_canvas.height());
_drawSegmentInAABB(g_currentTriangle.m_p2.xy(), g_currentTriangle.m_p0.xy(),
0, (float)g_canvas.width(), 0, (float)g_canvas.height());
}
SDL_SetRenderDrawColorFloat(g_renderer, ACTION_COLOR.x, ACTION_COLOR.y, ACTION_COLOR.z, SDL_ALPHA_OPAQUE_FLOAT);
@@ -221,17 +234,14 @@ void _drawAction(void)
case MT_FIRST_LINE:
{
SDL_RenderLine(g_renderer,
trans_w2s_x(g_currentTriangle.p0.x), trans_w2s_y(g_currentTriangle.p0.y),
trans_w2s_x(g_currentTriangle.p1.x), trans_w2s_y(g_currentTriangle.p1.y)
trans_w2s_x(g_currentTriangle.m_p0.x), trans_w2s_y(g_currentTriangle.m_p0.y),
trans_w2s_x(g_currentTriangle.m_p1.x), trans_w2s_y(g_currentTriangle.m_p1.y)
);
}
break;
case MT_TRIANGLE:
{
g_currentTriangle.build(ACTION_COLOR, g_canvasWidth, g_canvasHeight);
_drawTrianglePixel(g_currentTriangle);
_drawTriangleBorder(g_currentTriangle, ACTION_COLOR, ACTION_WIDTH);
}
break;
@@ -241,9 +251,110 @@ void _drawAction(void)
}
}
void _drawPixelSample()
{
const float crossLength = 0.2f;
//sample cross
if (g_nDrawGridLevel < 3)
{
SDL_SetRenderDrawColorFloat(g_renderer, GRID_CROSS_COLOR.x, GRID_CROSS_COLOR.y, GRID_CROSS_COLOR.z, SDL_ALPHA_OPAQUE_FLOAT);
for (int32_t i = 0; i < g_canvas.height(); i++)
{
for (int32_t j = 0; j < g_canvas.width(); j++)
{
const Canvas::Pixel& pixel = g_canvas.pixel(j, i);
if (pixel.fragementID < 0) continue;
if (g_aaTech == AntiAliasingTech::AA_None)
{
SDL_RenderLine(g_renderer,
trans_w2s_x(j + 0.5f - crossLength), trans_w2s_y(i + 0.5f - crossLength),
trans_w2s_x(j + 0.5f + crossLength), trans_w2s_y(i + 0.5f + crossLength)
);
SDL_RenderLine(g_renderer,
trans_w2s_x(j + 0.5f - crossLength), trans_w2s_y(i + 0.5f + crossLength),
trans_w2s_x(j + 0.5f + crossLength), trans_w2s_y(i + 0.5f - crossLength)
);
}
else if (g_aaTech == AntiAliasingTech::AA_MSAA_2X2)
{
for (int32_t ii = 0; ii < 2; ii++)
{
for (int32_t jj = 0; jj < 2; jj++)
{
int32_t maskOffset = ii * 2 + jj;
if (((pixel.mask >> maskOffset) & 1) == 0U) continue;
SDL_RenderLine(g_renderer,
trans_w2s_x(j + 0.25f + jj * 0.5f - crossLength / 2), trans_w2s_y(i + 0.25f + ii * 0.5f - crossLength / 2),
trans_w2s_x(j + 0.25f + jj * 0.5f + crossLength / 2), trans_w2s_y(i + 0.25f + ii * 0.5f + crossLength / 2)
);
SDL_RenderLine(g_renderer,
trans_w2s_x(j + 0.25f + jj * 0.5f - crossLength / 2), trans_w2s_y(i + 0.25f + ii * 0.5f + crossLength / 2),
trans_w2s_x(j + 0.25f + jj * 0.5f + crossLength / 2), trans_w2s_y(i + 0.25f + ii * 0.5f - crossLength / 2)
);
}
}
}
else if (g_aaTech == AntiAliasingTech::AA_MSAA_4X4)
{
for (int32_t ii = 0; ii < 4; ii++)
{
for (int32_t jj = 0; jj < 4; jj++)
{
int32_t maskOffset = ii * 4 + jj;
if (((pixel.mask >> maskOffset) & 1) == 0U) continue;
SDL_RenderLine(g_renderer,
trans_w2s_x(j + 0.125f + jj * 0.25f - crossLength/4), trans_w2s_y(i + 0.125f + ii * 0.25f - crossLength/4),
trans_w2s_x(j + 0.125f + jj * 0.25f + crossLength/4), trans_w2s_y(i + 0.125f + ii * 0.25f + crossLength/4)
);
SDL_RenderLine(g_renderer,
trans_w2s_x(j + 0.125f + jj * 0.25f - crossLength/4), trans_w2s_y(i + 0.125f + ii * 0.25f + crossLength/4),
trans_w2s_x(j + 0.125f + jj * 0.25f + crossLength/4), trans_w2s_y(i + 0.125f + ii * 0.25f - crossLength/4)
);
}
}
}
}
}
//for (int32_t i = (int32_t)trans_s2w_y(0); ; i--)
//{
// if (i > g_canvas.height()) continue;
// if (i < 0) break;
//}
//float crossLength = 0.2f;
//for (int i = 0; i < verLength; i++)
//{
// for (int j = 0; j < horLength; j++)
// {
// SDL_RenderLine(g_renderer,
// trans_w2s_x(j + 0.5f - crossLength), trans_w2s_y(i + 0.5f - crossLength),
// trans_w2s_x(j + 0.5f + crossLength), trans_w2s_y(i + 0.5f + crossLength)
// );
// SDL_RenderLine(g_renderer,
// trans_w2s_x(j + 0.5f - crossLength), trans_w2s_y(i + 0.5f + crossLength),
// trans_w2s_x(j + 0.5f + crossLength), trans_w2s_y(i + 0.5f - crossLength)
// );
// }
//}
}
}
void _drawMouseCursor(void)
{
if (g_bSnapMode)
if (g_bSnapMode && g_currentAction!=MT_PAN)
{
SDL_SetRenderDrawColorFloat(g_renderer, 0, 0, 0, SDL_ALPHA_OPAQUE_FLOAT);
@@ -268,8 +379,8 @@ void _drawDebugText()
SDL_SetRenderDrawColorFloat(g_renderer, 0, 0, 0, SDL_ALPHA_OPAQUE_FLOAT);
SDL_SetRenderScale(g_renderer, 1.5f, 1.5f);
SDL_RenderDebugText(g_renderer, g_lbCorner_x, g_lbCorner_y, "Press 'S' to turn on/off snap mode.");
SDL_RenderDebugText(g_renderer, g_lbCorner_x, g_lbCorner_y+TextHeight, "Click 'LeftMouseButton' to draw new triangle.");
SDL_RenderDebugText(g_renderer, 20, 20, "Press 'S' to turn on/off snap mode.");
SDL_RenderDebugText(g_renderer, 20, 20 + TextHeight, "Click 'LeftMouseButton' to draw new triangle.");
SDL_SetRenderScale(g_renderer, 1.0f, 1.0f);
}
@@ -287,13 +398,15 @@ inline float _snapPosition(float pos)
}
}
void _onMouseMove(float32_t x, float32_t y)
{
g_screenMousePosX = (int32_t)x;
g_screenMousePosY = (int32_t)y;
g_mousePosX = trans_s2w_x(x);
g_mousePosY = trans_s2w_y(y);
if (g_bSnapMode) {
if (g_bSnapMode && g_currentAction != MT_PAN)
{
g_mousePosX = _snapPosition(g_mousePosX);
g_mousePosY = _snapPosition(g_mousePosY);
}
@@ -302,13 +415,23 @@ void _onMouseMove(float32_t x, float32_t y)
{
case MT_FIRST_LINE:
{
g_currentTriangle.p1 = fVector3(g_mousePosX, g_mousePosY, 0);
g_currentTriangle.m_p1 = fVector3(g_mousePosX, g_mousePosY, 0);
}
break;
case MT_TRIANGLE:
{
g_currentTriangle.p2 = fVector3(g_mousePosX, g_mousePosY, 0);
g_currentTriangle.m_p2 = fVector3(g_mousePosX, g_mousePosY, 0);
g_currentTriangle.build(g_canvas.width(), g_canvas.height(), g_aaTech);
g_canvas.update(g_aaTech, g_allTriangles, &g_currentTriangle);
}
break;
case MT_PAN:
{
g_nPanX = g_screenMousePosX - g_nStartPanX;
g_nPanY = -(g_screenMousePosY - g_nStartPanY);
}
break;
@@ -331,6 +454,29 @@ void _onKeyDown(SDL_Keycode key)
{
g_bSnapMode = !g_bSnapMode;
}
else if (SDLK_A == key)
{
if (g_currentAction == MT_NULL)
{
if (g_aaTech == AntiAliasingTech::AA_None)
{
g_aaTech = AntiAliasingTech::AA_MSAA_2X2;
}
else if (g_aaTech == AntiAliasingTech::AA_MSAA_2X2)
{
g_aaTech = AntiAliasingTech::AA_MSAA_4X4;
}
else if (g_aaTech == AntiAliasingTech::AA_MSAA_4X4)
{
g_aaTech = AntiAliasingTech::AA_None;
}
for (auto& triangle : g_allTriangles)
{
triangle.build(g_canvas.width(), g_canvas.height(), g_aaTech);
}
g_canvas.update(g_aaTech, g_allTriangles);
}
}
else if (SDLK_ESCAPE == key)
{
g_currentAction = MT_NULL;
@@ -338,7 +484,22 @@ void _onKeyDown(SDL_Keycode key)
}
}
void _onMouseClick(Uint8 button)
void _onMouseDown(Uint8 button)
{
if (button == SDL_BUTTON_MIDDLE)
{
if (g_currentAction == MT_NULL)
{
g_currentAction = MT_PAN;
g_nStartPanX = g_screenMousePosX;
g_nStartPanY = g_screenMousePosY;
g_nPanX = g_nPanY = 0;
}
}
}
void _onMouseUp(Uint8 button)
{
if (button == SDL_BUTTON_LEFT)
{
@@ -346,7 +507,7 @@ void _onMouseClick(Uint8 button)
{
case MT_NULL:
{
g_currentTriangle.p0 = g_currentTriangle.p1 = fVector3(g_mousePosX, g_mousePosY, 0);
g_currentTriangle.m_p0 = g_currentTriangle.m_p1 = fVector3(g_mousePosX, g_mousePosY, 0);
g_currentAction = MT_FIRST_LINE;
g_bDrawExtension = false;
}
@@ -354,7 +515,7 @@ void _onMouseClick(Uint8 button)
case MT_FIRST_LINE:
{
g_currentTriangle.p1 = g_currentTriangle.p2 = fVector3(g_mousePosX, g_mousePosY, 0);
g_currentTriangle.m_p1 = g_currentTriangle.m_p2 = fVector3(g_mousePosX, g_mousePosY, 0);
g_currentAction = MT_TRIANGLE;
g_bDrawExtension = true;
}
@@ -362,14 +523,17 @@ void _onMouseClick(Uint8 button)
case MT_TRIANGLE:
{
g_currentTriangle.p2 = fVector3(g_mousePosX, g_mousePosY, 0);
g_currentTriangle.m_p2 = fVector3(g_mousePosX, g_mousePosY, 0);
g_currentAction = MT_NULL;
//build triangle
fVector3 randColor = fVector3(rand() * 0.8f / RAND_MAX, rand() * 0.8f / RAND_MAX, rand() * 0.8f / RAND_MAX);
g_currentTriangle.build(randColor, g_canvasWidth, g_canvasHeight, true);
g_allTriangles.push_back(g_currentTriangle);
Triangle newTriangle(Triangle::nextID(), Triangle::randomColor());
newTriangle.m_p0 = g_currentTriangle.m_p0;
newTriangle.m_p1 = g_currentTriangle.m_p1;
newTriangle.m_p2 = g_currentTriangle.m_p2;
newTriangle.build(g_canvas.width(), g_canvas.height(), g_aaTech);
g_allTriangles.push_back(std::move(newTriangle));
g_canvas.update(g_aaTech, g_allTriangles);
g_bDrawExtension = true;
}
break;
@@ -382,6 +546,17 @@ void _onMouseClick(Uint8 button)
{
g_currentAction = MT_NULL;
g_bDrawExtension = false;
g_canvas.update(g_aaTech, g_allTriangles);
}
else if (button == SDL_BUTTON_MIDDLE)
{
if (g_currentAction == MT_PAN)
{
g_currentAction = MT_NULL;
g_lbCorner_x += g_nPanX;
g_lbCorner_y += g_nPanY;
g_nPanX = g_nPanY = 0;
}
}
}
@@ -412,10 +587,12 @@ void _buildDemoTriangles(void)
fVector3 p0(triangleData[i * 6 + 0], triangleData[i * 6 + 1], 0.f);
fVector3 p1(triangleData[i * 6 + 2], triangleData[i * 6 + 3], 0.f);
fVector3 p2(triangleData[i * 6 + 4], triangleData[i * 6 + 5], 0.f);
fVector3 randColor = fVector3(rand() * 0.8f / RAND_MAX, rand() * 0.8f / RAND_MAX, rand() * 0.8f / RAND_MAX);
Triangle triangle(p0, p1, p2);
triangle.build(randColor, g_canvasWidth, g_canvasHeight, false);
Triangle triangle(Triangle::nextID(), Triangle::randomColor());
triangle.m_p0 = p0;
triangle.m_p1 = p1;
triangle.m_p2 = p2;
triangle.build(g_canvas.width(), g_canvas.height(), g_aaTech);
g_allTriangles.emplace_back(triangle);
}
}
@@ -437,9 +614,13 @@ SDL_AppResult SDL_AppInit(void** appstate, int argc, char* argv[])
return SDL_APP_FAILURE;
}
g_canvas.reset(CANVAS_WIDTH, CANVAS_HEIGHT);
_onFramebufferSize(g_viewWidth, g_viewHeight);
_buildDemoTriangles();
g_canvas.update(g_aaTech, g_allTriangles);
return SDL_APP_CONTINUE; /* carry on with the program! */
}
@@ -476,9 +657,14 @@ SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event)
}
break;
case SDL_EVENT_MOUSE_BUTTON_DOWN:
{
_onMouseDown(event->button.button);
}
break;
case SDL_EVENT_MOUSE_BUTTON_UP:
{
_onMouseClick(event->button.button);
_onMouseUp(event->button.button);
}
break;
}
@@ -489,12 +675,13 @@ SDL_AppResult SDL_AppIterate(void* appstate)
{
SDL_FRect rect;
SDL_SetRenderDrawColor(g_renderer, 255, 255, 255, SDL_ALPHA_OPAQUE);
SDL_SetRenderDrawColor(g_renderer, 0, 99, 177, SDL_ALPHA_OPAQUE);
SDL_RenderClear(g_renderer);
_drawGrid();
_drawTriangles();
_drawAction();
_drawPixelSample();
_drawMouseCursor();
_drawDebugText();
+23 -10
View File
@@ -1,23 +1,36 @@
#include "dvr_triangle.h"
#include "rasterizer/dvc_rasterizer_triangle.h"
void Triangle::build(const davinci::fVector3& _pixelColor, int32_t canvasWidth, int32_t canvasHeight, bool debug)
int32_t Triangle::nextID()
{
pixelColor = _pixelColor;
pixels.clear();
static int32_t id = 0;
return id++;
}
davinci::fVector3 Triangle::randomColor()
{
return davinci::fVector3(rand() * 0.8f / RAND_MAX, rand() * 0.8f / RAND_MAX, rand() * 0.8f / RAND_MAX);
}
void Triangle::build(int32_t canvasWidth, int32_t canvasHeight, davinci::AntiAliasingTech aaTech)
{
m_pixels.clear();
//make sure it's cw
bool ccw = false;
if ((p2 - p1).crossProduct(p0 - p2).z > 0) {
if ((m_p2 - m_p1).crossProduct(m_p0 - m_p2).z > 0) {
ccw = true;
}
//build pixel data
davinci::Rasterizer::drawTriangleLarrabee(canvasWidth, canvasHeight,
p0.xy(), p1.xy(), p2.xy(),
[this](std::pair<int32_t, int32_t> pos, const davinci::fVector3& t)
davinci::Rasterizer::drawTriangleLarrabee(aaTech,
canvasWidth, canvasHeight,
m_p0.xy(), m_p1.xy(), m_p2.xy(),
[this](std::pair<int32_t, int32_t> pos, const davinci::fVector3& t, uint32_t mask)
{
pixels.push_back(pos);
Pixel pixel;
pixel.x = pos.first;
pixel.y = pos.second;
pixel.mask = mask;
m_pixels.push_back(pixel);
},
ccw
);
+21 -8
View File
@@ -1,21 +1,34 @@
#pragma once
#include "math/dvc_vector3.h"
#include "rasterizer/dvc_rasterizer_triangle.h"
struct Triangle
{
public:
davinci::fVector3 p0, p1, p2;
davinci::fVector3 pixelColor;
std::vector< std::pair<int32_t, int32_t> > pixels;
int32_t m_id;
davinci::fVector3 m_p0, m_p1, m_p2;
davinci::fVector3 m_pixelColor;
struct Pixel
{
int32_t x, y;
uint32_t mask; // 0xFFFFFFFF for full pixel, 0x00000000 for empty pixel
};
typedef std::vector<Pixel> PixelArray;
PixelArray m_pixels;
public:
Triangle(){}
Triangle(const davinci::fVector3& _p0, const davinci::fVector3& _p1, const davinci::fVector3& _p2) : p0(_p0), p1(_p1), p2(_p2) { }
Triangle(const Triangle& other) : p0(other.p0), p1(other.p1), p2(other.p2), pixelColor(other.pixelColor), pixels(other.pixels) {}
static int32_t nextID();
static davinci::fVector3 randomColor();
Triangle(int32_t id, const davinci::fVector3& pixelColor)
: m_id(id)
, m_pixelColor(pixelColor)
{
}
public:
void build(const davinci::fVector3& _pixelColor, int32_t canvasWidth, int32_t canvasHeight, bool debug = false);
void build(int32_t canvasWidth, int32_t canvasHeight, davinci::AntiAliasingTech aaTech);
};
typedef std::vector<Triangle> TriangleVector;
typedef std::vector<Triangle> TriangleArray;
+2 -2
View File
@@ -297,7 +297,7 @@ static bool _triangleRasterizationRules(Canvas& canvas, const Triangle& triangle
canvas.clear();
Rasterizer::drawTriangleLarrabee(canvas.getWidth(), canvas.getHeight(),
Rasterizer::drawTriangleLarrabee(AntiAliasingTech::AA_None, canvas.getWidth(), canvas.getHeight(),
triangle.p1, triangle.p2, triangle.p3,
razFunc, ccw);
@@ -429,7 +429,7 @@ TEST(Rasterizer, Delaunay)
uint32_t randCol = 0xFF000000 + ((uint32_t)(rand() / 240) << 16) + ((uint32_t)(rand() / 240) << 8) + ((uint32_t)(rand() / 240));
auto razFunc = std::bind(&Canvas::razFunction, &canvas, std::placeholders::_1, std::placeholders::_2, randCol);
Rasterizer::drawTriangleLarrabee(canvas.getWidth(), canvas.getHeight(),
Rasterizer::drawTriangleLarrabee(AntiAliasingTech::AA_None, canvas.getWidth(), canvas.getHeight(),
triangle.p1, triangle.p2, triangle.p3,
razFunc, false);
}