Compare commits
3
Commits
936e326229
...
1f7720d54e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1f7720d54e | ||
|
|
dd72a8e3fd | ||
|
|
09eaa78ba1 |
@@ -14,13 +14,16 @@
|
||||
|
||||
#include <scene/dvc_scene.h>
|
||||
|
||||
int32_t g_screenWidth = 1024;
|
||||
int32_t g_screenHeight = 768;
|
||||
int32_t g_screenWidth = 2048;
|
||||
int32_t g_screenHeight = 1024;
|
||||
static SDL_Window* window = NULL;
|
||||
AdapterTexture g_adapterTexture;
|
||||
SDL_GLContext gl_context;
|
||||
davinci::RenderTarget g_renderTarget;
|
||||
davinci::AntiAliasingTech g_aaTech = davinci::AntiAliasingTech::AA_None;
|
||||
|
||||
int32_t g_canvasWidth = 1024;
|
||||
int32_t g_canvasHeight = 512;
|
||||
davinci::Scene g_scene;
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
@@ -99,7 +102,7 @@ SDL_AppResult SDL_AppInit(void** appstate, int argc, char* argv[])
|
||||
|
||||
// init davinci
|
||||
g_scene.init();
|
||||
g_renderTarget.init(512, 256);
|
||||
g_renderTarget.init(g_canvasWidth, g_canvasHeight);
|
||||
g_adapterTexture.updateTexture();
|
||||
|
||||
return SDL_APP_CONTINUE; /* carry on with the program! */
|
||||
@@ -153,7 +156,7 @@ SDL_AppResult SDL_AppIterate(void* appstate)
|
||||
|
||||
//draw render result
|
||||
g_adapterTexture.updateTexture(0, 0, g_renderTarget.getColorBuffer());
|
||||
g_adapterTexture.updateTexture(512, 0, g_renderTarget.getDepthBuffer());
|
||||
g_adapterTexture.updateTexture(g_canvasWidth, 0, g_renderTarget.getDepthBuffer());
|
||||
g_adapterTexture.draw();
|
||||
|
||||
//draw ui
|
||||
|
||||
@@ -21,6 +21,7 @@ SDL_Window* main_window;
|
||||
|
||||
extern davinci::Scene g_scene;
|
||||
extern davinci::RenderTarget g_renderTarget;
|
||||
extern davinci::AntiAliasingTech g_aaTech;
|
||||
|
||||
bool initMainUI(SDL_Window* window, SDL_GLContext gl_context, const char* glsl_version)
|
||||
{
|
||||
@@ -96,6 +97,8 @@ void drawMainUI()
|
||||
{
|
||||
davinci_utils::export_mesh_to_obj(g_scene);
|
||||
}
|
||||
const char* aaItem[] = { "None", "MSAA_2X2", "MSAA_4X4"};
|
||||
ImGui::Combo("AntiAliasing", (int*)(&g_aaTech), aaItem, IM_ARRAYSIZE(aaItem));
|
||||
if (ImGui::Button("Render"))
|
||||
{
|
||||
davinci::UniformBuffer uniformBuffer;
|
||||
@@ -112,7 +115,9 @@ void drawMainUI()
|
||||
queue.build(g_scene);
|
||||
|
||||
g_renderTarget.clear();
|
||||
queue.process(uniformBuffer, g_renderTarget);
|
||||
queue.process(g_aaTech, uniformBuffer, g_renderTarget);
|
||||
|
||||
davinci_utils::dump_render_target("d:\\rendertarget", g_renderTarget);
|
||||
}
|
||||
ImGui::End();
|
||||
|
||||
|
||||
@@ -112,6 +112,7 @@ set(DV_CORE_PIPE_INCLUDE_FILES
|
||||
include/pipe/dvc_render_step_IA.h
|
||||
include/pipe/dvc_render_step_VS.h
|
||||
include/pipe/dvc_render_step_PS.h
|
||||
include/pipe/dvc_render_step_OM.h
|
||||
)
|
||||
source_group("include/pipe" FILES ${DV_CORE_PIPE_INCLUDE_FILES})
|
||||
|
||||
@@ -122,6 +123,7 @@ set(DV_CORE_PIPE_SOURCE_FILES
|
||||
source/pipe/dvc_render_step_IA.cpp
|
||||
source/pipe/dvc_render_step_VS.cpp
|
||||
source/pipe/dvc_render_step_PS.cpp
|
||||
source/pipe/dvc_render_step_OM.cpp
|
||||
)
|
||||
source_group("source/pipe" FILES ${DV_CORE_PIPE_SOURCE_FILES})
|
||||
|
||||
|
||||
@@ -102,4 +102,12 @@ enum PixelFormat
|
||||
PF_UINT8_RGBA,
|
||||
};
|
||||
|
||||
enum AntiAliasingTech
|
||||
{
|
||||
AA_None,
|
||||
|
||||
AA_MSAA_2X2,
|
||||
AA_MSAA_4X4,
|
||||
};
|
||||
|
||||
DV_CORE_END_NAMESPACE
|
||||
|
||||
@@ -159,17 +159,19 @@ public:
|
||||
// special value
|
||||
static DV_CORE_API const ifloat64 kMax;
|
||||
static DV_CORE_API const ifloat64 kMin;
|
||||
static DV_CORE_API const ifloat64 kZero;
|
||||
static DV_CORE_API const ifloat64 kOne;
|
||||
static DV_CORE_API const ifloat64 kTwo;
|
||||
static DV_CORE_API const ifloat64 kThree;
|
||||
static DV_CORE_API const ifloat64 kFour;
|
||||
static DV_CORE_API const ifloat64 kHalf;
|
||||
static DV_CORE_API const ifloat64 kPi;
|
||||
static DV_CORE_API const ifloat64 kPi2;
|
||||
static DV_CORE_API const ifloat64 kPiHalf;
|
||||
static DV_CORE_API const ifloat64 kE;
|
||||
static DV_CORE_API const ifloat64 kNegOne;
|
||||
static DV_CORE_API const ifloat64 kZero; //0.0
|
||||
static DV_CORE_API const ifloat64 kOne; //1.0
|
||||
static DV_CORE_API const ifloat64 kTwo; //2.0
|
||||
static DV_CORE_API const ifloat64 kThree; //3.0
|
||||
static DV_CORE_API const ifloat64 kFour; //4.0
|
||||
static DV_CORE_API const ifloat64 kHalf; //0.5
|
||||
static DV_CORE_API const ifloat64 kQuater; //0.25
|
||||
static DV_CORE_API const ifloat64 kOneEighth; //0.125
|
||||
static DV_CORE_API const ifloat64 kPi; //3.14159265358979323846
|
||||
static DV_CORE_API const ifloat64 kPi2; //6.2831853071795
|
||||
static DV_CORE_API const ifloat64 kPiHalf; //1.57079632679489661923
|
||||
static DV_CORE_API const ifloat64 kE; //2.71828182845904523536
|
||||
static DV_CORE_API const ifloat64 kNegOne; // -1.0
|
||||
|
||||
public:
|
||||
ifloat64() : s3132(0) {}
|
||||
|
||||
@@ -10,6 +10,11 @@ class MathUtil
|
||||
public:
|
||||
static size_t ComponentSize(ComponentType ct);
|
||||
static size_t DataTypeSize(DataType dt);
|
||||
|
||||
//count the number of bits set in v
|
||||
static DV_CORE_API uint32_t popcount(uint8_t v);
|
||||
static DV_CORE_API uint32_t popcount(uint16_t v);
|
||||
static DV_CORE_API uint32_t popcount(uint32_t v);
|
||||
|
||||
static bool floatEqual(float a, float b,
|
||||
float tolerance = std::numeric_limits<float>::epsilon()) {
|
||||
|
||||
@@ -17,9 +17,11 @@ public:
|
||||
RenderableConstPtr getRenderable(size_t index) const;
|
||||
|
||||
void build(const Scene& scene);
|
||||
void process(UniformBuffer& uniformBuffer, RenderTarget& renderTarget);
|
||||
|
||||
void process(AntiAliasingTech aaTech, UniformBuffer& uniformBuffer, RenderTarget& renderTarget);
|
||||
|
||||
protected:
|
||||
AntiAliasingTech m_aaTech;
|
||||
std::vector<RenderableConstPtr> m_queue;
|
||||
|
||||
public:
|
||||
|
||||
@@ -23,11 +23,8 @@ public:
|
||||
|
||||
public:
|
||||
void process(const RenderQueue& renderQueue);
|
||||
const NodeArray& getNodes(void) const {
|
||||
return m_nodes;
|
||||
}
|
||||
|
||||
protected:
|
||||
public:
|
||||
NodeArray m_nodes;
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
#pragma once
|
||||
|
||||
#include "dvc_config.h"
|
||||
#include "dvc_render_step_PS.h"
|
||||
|
||||
DV_CORE_BEGIN_NAMESPACE
|
||||
|
||||
class OutputMergerStep
|
||||
{
|
||||
public:
|
||||
void process(const PixelShaderStep::StartOffsetArray& startOffsetArray, const PixelShaderStep::FragementArray& fragementArray,
|
||||
AntiAliasingTech aaTech, RenderTarget& renderTarget);
|
||||
|
||||
private:
|
||||
void mergeFragement_without_AA(int32_t x, int32_t y,
|
||||
const std::multimap<float32_t, int32_t>& fragementArrayMap,
|
||||
const PixelShaderStep::FragementArray& fragementArray, RenderTarget& renderTarget);
|
||||
|
||||
template<int32_t kSampleSize, uint32_t kSampleMask>
|
||||
void mergeFragement_with_AA(int32_t x, int32_t y,
|
||||
const std::multimap<float32_t, int32_t>& fragementArrayMap,
|
||||
const PixelShaderStep::FragementArray& fragementArray, RenderTarget& renderTarget);
|
||||
};
|
||||
|
||||
template<int32_t kSampleSize, uint32_t kSampleMask>
|
||||
void OutputMergerStep::mergeFragement_with_AA(int32_t x, int32_t y, const std::multimap<float32_t, int32_t>& fragementArrayMap,
|
||||
const PixelShaderStep::FragementArray& fragementArray, RenderTarget& renderTarget)
|
||||
{
|
||||
if (fragementArrayMap.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (fragementArrayMap.size() == 1)
|
||||
{
|
||||
const PixelShaderStep::Fragement& fragement = fragementArray[fragementArrayMap.begin()->second];
|
||||
|
||||
fVector4 finalColor = fragement.color;
|
||||
finalColor.w = MathUtil::popcount((uint16_t)(fragement.mask & kSampleMask)) / (float32_t)kSampleSize;
|
||||
|
||||
renderTarget.setPixel(x, y, finalColor, fragement.depth);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::array<int32_t, kSampleSize> samples;
|
||||
samples.fill(-1);
|
||||
|
||||
float finalDepth = 0;
|
||||
std::multimap<float32_t, int32_t>::const_iterator it, end = fragementArrayMap.end();
|
||||
for (it = fragementArrayMap.begin(); it != end; ++it)
|
||||
{
|
||||
const PixelShaderStep::Fragement& fragement = fragementArray[it->second];
|
||||
for (int32_t k = 0; k < kSampleSize; k++)
|
||||
{
|
||||
if ((fragement.mask & (1 << k)) != 0)
|
||||
{
|
||||
samples[k] = it->second;
|
||||
}
|
||||
}
|
||||
finalDepth = fragement.depth;
|
||||
}
|
||||
|
||||
fVector3 finalColor(0.f, 0.f, 0.f);
|
||||
int32_t bitCounts = 0;
|
||||
for (int32_t k = 0; k < kSampleSize; k++)
|
||||
{
|
||||
int32_t fragementID = samples[k];
|
||||
if (fragementID < 0 || fragementID >= fragementArray.size()) continue;
|
||||
|
||||
const PixelShaderStep::Fragement& fragement = fragementArray[fragementID];
|
||||
finalColor += fragement.color.xyz();
|
||||
bitCounts++;
|
||||
}
|
||||
|
||||
if (bitCounts == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (bitCounts > 1)
|
||||
{
|
||||
finalColor /= (float32_t)bitCounts;
|
||||
}
|
||||
float32_t finalAlpha = bitCounts / (float32_t)kSampleSize;
|
||||
renderTarget.setPixel(x, y, fVector4(finalColor, finalAlpha), finalDepth);
|
||||
}
|
||||
}
|
||||
|
||||
DV_CORE_END_NAMESPACE
|
||||
@@ -8,8 +8,23 @@ DV_CORE_BEGIN_NAMESPACE
|
||||
class PixelShaderStep
|
||||
{
|
||||
public:
|
||||
void process(const VertexShaderStep::NodeArray& vsNodeArray, RenderTarget& renderTarget);
|
||||
struct Fragement
|
||||
{
|
||||
float32_t depth;
|
||||
fVector4 color;
|
||||
uint32_t mask;
|
||||
int32_t next;
|
||||
};
|
||||
|
||||
typedef std::vector<int32_t> StartOffsetArray;
|
||||
typedef std::vector<Fragement> FragementArray;
|
||||
|
||||
public:
|
||||
void process(const VertexShaderStep::NodeArray& vsNodeArray, AntiAliasingTech aaTech, int32_t canvasWidth, int32_t canvasHeight);
|
||||
|
||||
public:
|
||||
StartOffsetArray m_startOffsetArray;
|
||||
FragementArray m_fragementArray;
|
||||
};
|
||||
|
||||
DV_CORE_END_NAMESPACE
|
||||
|
||||
@@ -20,15 +20,10 @@ public:
|
||||
};
|
||||
typedef std::vector<Node> NodeArray;
|
||||
|
||||
public:
|
||||
const NodeArray& getNodes() const {
|
||||
return m_nodes;
|
||||
}
|
||||
|
||||
public:
|
||||
void process(UniformBuffer& uniformBuffer, const InputAssemberStep::NodeArray& assembedNodeArray);
|
||||
|
||||
protected:
|
||||
public:
|
||||
NodeArray m_nodes;
|
||||
};
|
||||
|
||||
|
||||
@@ -10,7 +10,9 @@ class DV_CORE_API Rasterizer
|
||||
{
|
||||
//Draw Triangle with Larrabee
|
||||
public:
|
||||
typedef std::function<void(const std::pair<int32_t, int32_t>& pos, const fVector3& percent)> DrawTriangleCallback;
|
||||
typedef std::function<
|
||||
void(const std::pair<int32_t, int32_t>& pos, const fVector3& percent, uint32_t mask)
|
||||
> DrawTriangleCallback;
|
||||
|
||||
struct DebugParam
|
||||
{
|
||||
@@ -27,9 +29,10 @@ public:
|
||||
};
|
||||
|
||||
//Larrabee algorithm
|
||||
static void drawTriangleLarrabee(int32_t canvasWidth, int32_t canvasHeight,
|
||||
static void drawTriangleLarrabee(AntiAliasingTech aaTech, int32_t canvasWidth, int32_t canvasHeight,
|
||||
const fVector2& v0, const fVector2& v1, const fVector2& v2,
|
||||
DrawTriangleCallback callback, bool ccw=true, const DebugParam* debugParam=nullptr);
|
||||
DrawTriangleCallback callback, bool ccw=true,
|
||||
const DebugParam* debugParam=nullptr);
|
||||
|
||||
public:
|
||||
//BoundingBox algorithm
|
||||
|
||||
@@ -16,7 +16,7 @@ void RenderTarget::init(int32_t width, int32_t height)
|
||||
|
||||
void RenderTarget::clear()
|
||||
{
|
||||
m_colorBuffer.clear(fVector4::BLACK);
|
||||
m_colorBuffer.clear(fVector4(0.f, 0.f, 0.f, 0.f));
|
||||
m_depthBuffer.clear(std::numeric_limits<float32_t>::max());
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ void RenderTarget::setPixel(int32_t x, int32_t y, const fVector4& color, float32
|
||||
if (x < 0 || x >= m_width || y < 0 || y >= m_height) return;
|
||||
|
||||
if (depth > m_depthBuffer.getPixel(x, y)) {
|
||||
return;
|
||||
// return;
|
||||
}
|
||||
m_colorBuffer.setPixel(x, y, color);
|
||||
m_depthBuffer.setPixel(x, y, depth);
|
||||
|
||||
@@ -10,6 +10,8 @@ const ifloat64 ifloat64::kTwo{ INT64_C(2) << kShift };
|
||||
const ifloat64 ifloat64::kThree{ INT64_C(3) << ifloat64::kShift };
|
||||
const ifloat64 ifloat64::kFour{ INT64_C(4) << ifloat64::kShift };
|
||||
const ifloat64 ifloat64::kHalf{ INT64_C(1) << (ifloat64::kShift-1) };
|
||||
const ifloat64 ifloat64::kQuater{ INT64_C(1) << (ifloat64::kShift - 2) };
|
||||
const ifloat64 ifloat64::kOneEighth{ INT64_C(1) << (ifloat64::kShift - 3) };
|
||||
const ifloat64 ifloat64::kPi{ INT64_C(0x3243f6a89) }; //static_cast<int64_t>(std::round(M_PI * kFloatScale));
|
||||
const ifloat64 ifloat64::kPi2{ INT64_C(0x6487ed511) };
|
||||
const ifloat64 ifloat64::kPiHalf{ INT64_C(0x1921fb544) };
|
||||
|
||||
@@ -11,6 +11,31 @@ const float MathUtil::PI_DIV4 = float(0.25 * PI);
|
||||
const float MathUtil::fDeg2Rad = PI / float(180.0);
|
||||
const float MathUtil::fRad2Deg = float(180.0) / PI;
|
||||
|
||||
static const uint8_t kBitsSetTable256[256] =
|
||||
{
|
||||
#define B2(n) n, n+1, n+1, n+2
|
||||
#define B4(n) B2(n), B2(n+1), B2(n+1), B2(n+2)
|
||||
#define B6(n) B4(n), B4(n+1), B4(n+1), B4(n+2)
|
||||
|
||||
B6(0), B6(1), B6(1), B6(2)
|
||||
};
|
||||
|
||||
uint32_t MathUtil::popcount(uint8_t v)
|
||||
{
|
||||
return kBitsSetTable256[v];
|
||||
}
|
||||
|
||||
uint32_t MathUtil::popcount(uint16_t v)
|
||||
{
|
||||
return kBitsSetTable256[v & 0xff] + kBitsSetTable256[(v >> 8) & 0xff];
|
||||
}
|
||||
|
||||
uint32_t MathUtil::popcount(uint32_t v)
|
||||
{
|
||||
return kBitsSetTable256[v & 0xff] + kBitsSetTable256[(v >> 8) & 0xff] +
|
||||
kBitsSetTable256[(v >> 16) & 0xff] + kBitsSetTable256[v >> 24];
|
||||
}
|
||||
|
||||
size_t MathUtil::ComponentSize(ComponentType ct)
|
||||
{
|
||||
switch (ct)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "pipe/dvc_render_step_IA.h"
|
||||
#include "pipe/dvc_render_step_VS.h"
|
||||
#include "pipe/dvc_render_step_PS.h"
|
||||
#include "pipe/dvc_render_step_OM.h"
|
||||
#include "scene/component/dvc_camera_component.h"
|
||||
|
||||
DV_CORE_BEGIN_NAMESPACE
|
||||
@@ -38,19 +39,25 @@ void RenderQueue::build(const Scene& scene)
|
||||
scene.getRootSceneNode()->buildRenderQueue(fMatrix4::IDENTITY, *this);
|
||||
}
|
||||
|
||||
void RenderQueue::process(UniformBuffer& uniformBuffer, RenderTarget& renderTarget)
|
||||
void RenderQueue::process(AntiAliasingTech aaTech, UniformBuffer& uniformBuffer, RenderTarget& renderTarget)
|
||||
{
|
||||
m_aaTech = aaTech;
|
||||
|
||||
//Assembere input
|
||||
InputAssemberStep IA;
|
||||
IA.process(*this);
|
||||
|
||||
//Vertex shader
|
||||
VertexShaderStep VS;
|
||||
VS.process(uniformBuffer, IA.getNodes());
|
||||
VS.process(uniformBuffer, IA.m_nodes);
|
||||
|
||||
//Pixel shader
|
||||
PixelShaderStep PS;
|
||||
PS.process(VS.getNodes(), renderTarget);
|
||||
PS.process(VS.m_nodes, m_aaTech, renderTarget.getWidth(), renderTarget.getHeight());
|
||||
|
||||
//Output Merge
|
||||
OutputMergerStep OM;
|
||||
OM.process(PS.m_startOffsetArray, PS.m_fragementArray, m_aaTech, renderTarget);
|
||||
}
|
||||
|
||||
DV_CORE_END_NAMESPACE
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
#include "pipe/dvc_render_step_OM.h"
|
||||
|
||||
DV_CORE_BEGIN_NAMESPACE
|
||||
|
||||
void OutputMergerStep::process(const PixelShaderStep::StartOffsetArray& startOffsetArray, const PixelShaderStep::FragementArray& fragementArray,
|
||||
AntiAliasingTech aaTech, RenderTarget& renderTarget)
|
||||
{
|
||||
int32_t canvasWidth = renderTarget.getWidth();
|
||||
int32_t canvasHeight = renderTarget.getHeight();
|
||||
|
||||
for (int32_t y = 0; y < canvasHeight; y++)
|
||||
{
|
||||
for (int32_t x = 0; x < canvasWidth; x++)
|
||||
{
|
||||
int32_t fragementID = startOffsetArray[y * canvasWidth + x];
|
||||
std::multimap<float32_t, int32_t> fragementArrayMap;
|
||||
|
||||
while (fragementID >=0 && fragementID < (int32_t)fragementArray.size())
|
||||
{
|
||||
const PixelShaderStep::Fragement& fragement = fragementArray[fragementID];
|
||||
fragementArrayMap.insert(std::make_pair(-fragement.depth, fragementID));
|
||||
fragementID = fragement.next;
|
||||
}
|
||||
|
||||
if (aaTech == AntiAliasingTech::AA_None)
|
||||
{
|
||||
mergeFragement_without_AA(x, y, fragementArrayMap, fragementArray, renderTarget);
|
||||
}
|
||||
else if (aaTech == AntiAliasingTech::AA_MSAA_2X2)
|
||||
{
|
||||
mergeFragement_with_AA<4, 0xF>(x, y, fragementArrayMap, fragementArray, renderTarget);
|
||||
}
|
||||
else if (aaTech == AntiAliasingTech::AA_MSAA_4X4)
|
||||
{
|
||||
mergeFragement_with_AA<16, 0xFFFF>(x, y, fragementArrayMap, fragementArray, renderTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OutputMergerStep::mergeFragement_without_AA(int32_t x, int32_t y, const std::multimap<float32_t, int32_t>& fragementArrayMap,
|
||||
const PixelShaderStep::FragementArray& fragementArray, RenderTarget& renderTarget)
|
||||
{
|
||||
if (fragementArrayMap.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const PixelShaderStep::Fragement& firstFragement = fragementArray[fragementArrayMap.rbegin()->second];
|
||||
renderTarget.setPixel(x, y, firstFragement.color, firstFragement.depth);
|
||||
}
|
||||
|
||||
DV_CORE_END_NAMESPACE
|
||||
|
||||
@@ -6,17 +6,16 @@
|
||||
|
||||
DV_CORE_BEGIN_NAMESPACE
|
||||
|
||||
void PixelShaderStep::process(const VertexShaderStep::NodeArray& vsNodeArray, RenderTarget& renderTarget)
|
||||
void PixelShaderStep::process(const VertexShaderStep::NodeArray& vsNodeArray, AntiAliasingTech aaTech, int32_t canvasWidth, int32_t canvasHeight)
|
||||
{
|
||||
ShaderFileInterface* shaderInterface = davinci::LoadShaderFile("TestShader.dll");
|
||||
PixelShaderInterface* pixelShader = shaderInterface->getPixelShader("xxx");
|
||||
|
||||
int32_t targetWidth = renderTarget.getWidth();
|
||||
int32_t targetHeight = renderTarget.getHeight();
|
||||
|
||||
fMatrix4 view_trans =
|
||||
fMatrix4::makeTrans(targetWidth / 2.f, targetHeight / 2.f, 0.f) *
|
||||
fMatrix4::makeScale(targetWidth / 2.f, targetHeight / 2.f, 1.f);
|
||||
fMatrix4::makeTrans(canvasWidth / 2.f, canvasHeight / 2.f, 0.f) *
|
||||
fMatrix4::makeScale(canvasWidth / 2.f, canvasHeight / 2.f, 1.f);
|
||||
|
||||
m_startOffsetArray.resize(canvasWidth* canvasHeight, -1);
|
||||
|
||||
VertexShaderStep::NodeArray::const_iterator it, end = vsNodeArray.end();
|
||||
for (it = vsNodeArray.begin(); it != end; ++it)
|
||||
@@ -39,9 +38,10 @@ void PixelShaderStep::process(const VertexShaderStep::NodeArray& vsNodeArray, Re
|
||||
std::vector<float32_t> invZ = { node.invZ[i + 0], node.invZ[i + 1], node.invZ[i + 2] };
|
||||
std::vector<float32_t> vertexDepth = { node.depth[i+0], node.depth[i + 1], node.depth[i + 2]};
|
||||
|
||||
Rasterizer::drawTriangleLarrabee(targetWidth, targetHeight, pos0.xy(), pos1.xy(), pos2.xy(),
|
||||
[pixelShader, vertex0, vertex1, vertex2, invZ, vertexDepth, &node, &renderTarget]
|
||||
(const std::pair<int32_t, int32_t>& dot, const fVector3& percent)
|
||||
Rasterizer::drawTriangleLarrabee(aaTech,
|
||||
canvasWidth, canvasHeight, pos0.xy(), pos1.xy(), pos2.xy(),
|
||||
[this, canvasWidth, pixelShader, vertex0, vertex1, vertex2, invZ, vertexDepth, &node]
|
||||
(const std::pair<int32_t, int32_t>& dot, const fVector3& percent, uint32_t mask)
|
||||
{
|
||||
fVector3 percentCorrected(percent);
|
||||
|
||||
@@ -65,7 +65,16 @@ void PixelShaderStep::process(const VertexShaderStep::NodeArray& vsNodeArray, Re
|
||||
|
||||
int32_t x = dot.first;
|
||||
int32_t y = dot.second;
|
||||
renderTarget.setPixel(x, y, color, depth);
|
||||
int32_t currentOffset = m_startOffsetArray[x + y * canvasWidth];
|
||||
|
||||
m_startOffsetArray[x + y * canvasWidth] = (int32_t)(m_fragementArray.size());
|
||||
|
||||
Fragement newFragment;
|
||||
newFragment.color = color;
|
||||
newFragment.depth = depth;
|
||||
newFragment.mask = mask;
|
||||
newFragment.next = currentOffset;
|
||||
this->m_fragementArray.push_back(newFragment);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -20,22 +20,27 @@ inline bool operator==(const bool3_t& arr, bool value)
|
||||
|
||||
struct DrawTriangleParam
|
||||
{
|
||||
bool ccw;
|
||||
fVector2 verts[3];
|
||||
float32_t bbox_min_x;
|
||||
float32_t bbox_max_x;
|
||||
float32_t bbox_min_y;
|
||||
float32_t bbox_max_y;
|
||||
bool3_t tlBorder;
|
||||
float32_t area;
|
||||
iFloat3 edgesDX, edgesDY;
|
||||
iFloat3 halfEdge;
|
||||
AntiAliasingTech aaTech;
|
||||
bool ccw;
|
||||
fVector2 verts[3];
|
||||
float32_t bbox_min_x;
|
||||
float32_t bbox_max_x;
|
||||
float32_t bbox_min_y;
|
||||
float32_t bbox_max_y;
|
||||
bool3_t tlBorder;
|
||||
float32_t area;
|
||||
iFloat3 edgesDX, edgesDY;
|
||||
|
||||
iFloat3 halfEdge;
|
||||
iFloat3 quaterEdge;
|
||||
iFloat3 oneEighthEdge;
|
||||
|
||||
Rasterizer::DebugParam debugParam;
|
||||
};
|
||||
|
||||
enum { MIN_TILE_WIDTH_IN_PIXELS = 64 };
|
||||
|
||||
void _fillPixel(const DrawTriangleParam& param, int32_t xLB, int32_t yLB, Rasterizer::DrawTriangleCallback callback)
|
||||
void _fillPixel(const DrawTriangleParam& param, int32_t xLB, int32_t yLB, uint32_t mask, Rasterizer::DrawTriangleCallback callback)
|
||||
{
|
||||
fVector2 pixel(xLB + 0.5f, yLB + 0.5f);
|
||||
const fVector2 v0(param.verts[0]), v1(param.verts[1]), v2(param.verts[2]);
|
||||
@@ -46,42 +51,140 @@ void _fillPixel(const DrawTriangleParam& param, int32_t xLB, int32_t yLB, Raster
|
||||
|
||||
fVector3 t = fVector3(w0 / param.area, (param.ccw ? w1 : w2) / param.area, (param.ccw ? w2 : w1) / param.area);
|
||||
|
||||
callback(std::make_pair(xLB, yLB), t);
|
||||
callback(std::make_pair(xLB, yLB), t, mask);
|
||||
}
|
||||
|
||||
void _fillTile(const DrawTriangleParam& param, int32_t currentTileSize,
|
||||
int32_t xLB, int32_t yLB, Rasterizer::DrawTriangleCallback callback)
|
||||
{
|
||||
if (currentTileSize == 1)
|
||||
{
|
||||
_fillPixel(param, xLB, yLB, callback);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int32_t yIndex = yLB; yIndex < yLB + currentTileSize; yIndex++)
|
||||
{
|
||||
for (int32_t xIndex = xLB; xIndex < xLB + currentTileSize; xIndex++)
|
||||
{
|
||||
_fillPixel(param, xIndex, yIndex, callback);
|
||||
_fillPixel(param, xIndex, yIndex, ~0, callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _drawPixel(DrawTriangleParam& param,
|
||||
void _drawPixel_without_AA(DrawTriangleParam& param,
|
||||
int32_t xLB, int32_t yLB, const iFloat3& edgesLB, const bool3_t& intersectant,
|
||||
Rasterizer::DrawTriangleCallback callback)
|
||||
{
|
||||
iFloat3 centerEdges(edgesLB);
|
||||
centerEdges.add(param.halfEdge);
|
||||
|
||||
bool insideTriangle =
|
||||
bool insideTriangle =
|
||||
(centerEdges.x > 0 || (param.tlBorder[0] && centerEdges.x == 0)) &&
|
||||
(centerEdges.y > 0 || (param.tlBorder[1] && centerEdges.y == 0)) &&
|
||||
(centerEdges.z > 0 || (param.tlBorder[2] && centerEdges.z == 0));
|
||||
|
||||
if (insideTriangle)
|
||||
{
|
||||
_fillPixel(param, xLB, yLB, callback);
|
||||
_fillPixel(param, xLB, yLB, ~0, callback);
|
||||
}
|
||||
}
|
||||
|
||||
void _drawPixel_with_MSAA2X2(DrawTriangleParam& param,
|
||||
int32_t x, int32_t y, const iFloat3& edgesLB, const bool3_t& intersectant,
|
||||
Rasterizer::DrawTriangleCallback callback)
|
||||
{
|
||||
// 2x2 MSAA;
|
||||
iFloat3 sampleEdgesDX(param.edgesDX);
|
||||
sampleEdgesDX.mul(iFloat::kHalf);
|
||||
|
||||
iFloat3 sampleEdgesDY(param.edgesDY);
|
||||
sampleEdgesDY.mul(iFloat::kHalf);
|
||||
|
||||
iFloat3 firstSampleEdges(edgesLB);
|
||||
firstSampleEdges.add(param.quaterEdge); // 0.25f
|
||||
|
||||
iFloat3 rowEdges(firstSampleEdges);
|
||||
|
||||
uint32_t mask = 0;
|
||||
for (int32_t yIndex = 0; yIndex < 2; yIndex++)
|
||||
{
|
||||
iFloat3 sampleEdges(rowEdges);
|
||||
|
||||
for (int32_t xIndex = 0; xIndex < 2; xIndex++)
|
||||
{
|
||||
bool sampleInsideTriangle =
|
||||
(sampleEdges.x > 0 || (param.tlBorder[0] && sampleEdges.x == 0)) &&
|
||||
(sampleEdges.y > 0 || (param.tlBorder[1] && sampleEdges.y == 0)) &&
|
||||
(sampleEdges.z > 0 || (param.tlBorder[2] && sampleEdges.z == 0));
|
||||
|
||||
if (sampleInsideTriangle)
|
||||
{
|
||||
mask |= (1 << (yIndex * 2 + xIndex));
|
||||
}
|
||||
|
||||
sampleEdges.sub(sampleEdgesDY);
|
||||
}
|
||||
|
||||
rowEdges.add(sampleEdgesDX);
|
||||
}
|
||||
|
||||
_fillPixel(param, x, y, mask, callback);
|
||||
}
|
||||
|
||||
void _drawPixel_with_MSAA4X4(DrawTriangleParam& param,
|
||||
int32_t x, int32_t y, const iFloat3& edgesLB, const bool3_t& intersectant,
|
||||
Rasterizer::DrawTriangleCallback callback)
|
||||
{
|
||||
// 4x4 MSAA;
|
||||
iFloat3 sampleEdgesDX(param.edgesDX);
|
||||
sampleEdgesDX.mul(iFloat::kQuater);
|
||||
|
||||
iFloat3 sampleEdgesDY(param.edgesDY);
|
||||
sampleEdgesDY.mul(iFloat::kQuater);
|
||||
|
||||
iFloat3 firstSampleEdges(edgesLB);
|
||||
firstSampleEdges.add(param.oneEighthEdge); // 0.125f
|
||||
|
||||
iFloat3 rowEdges(firstSampleEdges);
|
||||
|
||||
uint32_t mask = 0;
|
||||
for (int32_t yIndex = 0; yIndex < 4; yIndex++)
|
||||
{
|
||||
iFloat3 sampleEdges(rowEdges);
|
||||
|
||||
for (int32_t xIndex = 0; xIndex < 4; xIndex++)
|
||||
{
|
||||
bool sampleInsideTriangle =
|
||||
(sampleEdges.x > 0 || (param.tlBorder[0] && sampleEdges.x == 0)) &&
|
||||
(sampleEdges.y > 0 || (param.tlBorder[1] && sampleEdges.y == 0)) &&
|
||||
(sampleEdges.z > 0 || (param.tlBorder[2] && sampleEdges.z == 0));
|
||||
|
||||
if (sampleInsideTriangle)
|
||||
{
|
||||
mask |= (1 << (yIndex * 4 + xIndex));
|
||||
}
|
||||
|
||||
sampleEdges.sub(sampleEdgesDY);
|
||||
}
|
||||
|
||||
rowEdges.add(sampleEdgesDX);
|
||||
}
|
||||
|
||||
_fillPixel(param, x, y, mask, callback);
|
||||
}
|
||||
|
||||
void _drawPixel(DrawTriangleParam& param,
|
||||
int32_t xLB, int32_t yLB, const iFloat3& edgesLB, const bool3_t& intersectant,
|
||||
Rasterizer::DrawTriangleCallback callback)
|
||||
{
|
||||
switch (param.aaTech)
|
||||
{
|
||||
case AntiAliasingTech::AA_MSAA_4X4:
|
||||
_drawPixel_with_MSAA4X4(param, xLB, yLB, edgesLB, intersectant, callback);
|
||||
break;
|
||||
|
||||
case AntiAliasingTech::AA_MSAA_2X2:
|
||||
_drawPixel_with_MSAA2X2(param, xLB, yLB, edgesLB, intersectant, callback);
|
||||
break;
|
||||
|
||||
case AntiAliasingTech::AA_None:
|
||||
default:
|
||||
_drawPixel_without_AA(param, xLB, yLB, edgesLB, intersectant, callback);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,7 +301,7 @@ void _drawTriangle_Tile(DrawTriangleParam& param, int32_t currentTileSize,
|
||||
}
|
||||
}
|
||||
|
||||
void Rasterizer::drawTriangleLarrabee(int32_t canvasWidth, int32_t canvasHeight,
|
||||
void Rasterizer::drawTriangleLarrabee(AntiAliasingTech aaTech, int32_t canvasWidth, int32_t canvasHeight,
|
||||
const fVector2& v0, const fVector2& v1, const fVector2& v2,
|
||||
DrawTriangleCallback callback, bool ccw, const DebugParam* debugParam)
|
||||
{
|
||||
@@ -225,6 +328,7 @@ void Rasterizer::drawTriangleLarrabee(int32_t canvasWidth, int32_t canvasHeight,
|
||||
tileSize /= 4;
|
||||
|
||||
DrawTriangleParam param;
|
||||
param.aaTech = aaTech;
|
||||
int32_t widthInTiles = canvasWidth / tileSize;
|
||||
|
||||
//Whether the three input vertices are in the agreed clockwise order or not,
|
||||
@@ -285,7 +389,10 @@ void Rasterizer::drawTriangleLarrabee(int32_t canvasWidth, int32_t canvasHeight,
|
||||
size_t v_end = (v + 1) % 3;
|
||||
param.edgesDX[v] = vertices[v_end].x - vertices[v].x;
|
||||
param.edgesDY[v] = vertices[v_end].y - vertices[v].y;
|
||||
|
||||
param.halfEdge[v] = (param.edgesDX[v]- param.edgesDY[v]) * iFloat::kHalf;
|
||||
param.quaterEdge[v] = (param.edgesDX[v] - param.edgesDY[v]) * iFloat::kQuater;
|
||||
param.oneEighthEdge[v] = (param.edgesDX[v] - param.edgesDY[v]) * iFloat::kOneEighth;
|
||||
|
||||
tileEdgesDX[v] = param.edgesDX[v] * tileSize;
|
||||
tileEdgesDY[v] = param.edgesDY[v] * tileSize;
|
||||
@@ -374,8 +481,6 @@ void Rasterizer::drawTriangleLarrabee(int32_t canvasWidth, int32_t canvasHeight,
|
||||
}
|
||||
|
||||
iFloat3 rowEdges(edgesFirstLB);
|
||||
|
||||
int32_t tile_row_start = first_tile_y * tileSize + first_tile_x;
|
||||
int32_t yLB = first_tile_y * tileSize;
|
||||
|
||||
for (int32_t tile_y = first_tile_y; tile_y <= last_tile_y; tile_y++)
|
||||
@@ -384,7 +489,6 @@ void Rasterizer::drawTriangleLarrabee(int32_t canvasWidth, int32_t canvasHeight,
|
||||
iFloat3 tileEdgesReject(edgesReject);
|
||||
iFloat3 tileEdgesAccept(edgesAccept);
|
||||
|
||||
int32_t tile_i = tile_row_start;
|
||||
int32_t xLB = first_tile_x * tileSize;
|
||||
|
||||
for (int32_t tile_x = first_tile_x; tile_x <= last_tile_x; tile_x++)
|
||||
@@ -414,7 +518,6 @@ void Rasterizer::drawTriangleLarrabee(int32_t canvasWidth, int32_t canvasHeight,
|
||||
edgesTileLB.sub(tileEdgesDY);
|
||||
tileEdgesReject.sub(tileEdgesDY);
|
||||
tileEdgesAccept.sub(tileEdgesDY);
|
||||
tile_i++;
|
||||
xLB += tileSize;
|
||||
}
|
||||
|
||||
@@ -422,7 +525,6 @@ void Rasterizer::drawTriangleLarrabee(int32_t canvasWidth, int32_t canvasHeight,
|
||||
rowEdges.add(tileEdgesDX);
|
||||
edgesReject.add(tileEdgesDX);
|
||||
edgesAccept.add(tileEdgesDX);
|
||||
tile_row_start += widthInTiles;
|
||||
yLB += tileSize;
|
||||
}
|
||||
|
||||
@@ -505,7 +607,7 @@ void Rasterizer::drawTriangleBoundingBox(int32_t canvasWidth, int32_t canvasHeig
|
||||
|
||||
fVector3 t = fVector3(w0 / area, (ccw ? w1 : w2) / area, (ccw ? w2 : w1) / area);
|
||||
|
||||
callback(std::make_pair(x, y), t);
|
||||
callback(std::make_pair(x, y), t, ~0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <map>
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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>();
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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();
|
||||
|
||||
|
||||
@@ -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
|
||||
);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -261,6 +261,30 @@ TEST(FixPoint64, Basic)
|
||||
EXPECT_EQ(a.to_float(), -1.f);
|
||||
EXPECT_EQ(a.to_int32(), -1);
|
||||
|
||||
a = iFloat64(0.25f);
|
||||
EXPECT_EQ(a, iFloat64::kQuater);
|
||||
EXPECT_EQ(a.s3132, iFloat64::kQuater.s3132);
|
||||
EXPECT_EQ(a.to_float(), 0.25f);
|
||||
EXPECT_EQ(a.to_int32(), 0);
|
||||
|
||||
a = iFloat64(-0.25f);
|
||||
EXPECT_EQ(a, -iFloat64::kQuater);
|
||||
EXPECT_EQ(a.s3132, -iFloat64::kQuater.s3132);
|
||||
EXPECT_EQ(a.to_float(), -0.25f);
|
||||
EXPECT_EQ(a.to_int32(), -1);
|
||||
|
||||
a = iFloat64(0.125f);
|
||||
EXPECT_EQ(a, iFloat64::kOneEighth);
|
||||
EXPECT_EQ(a.s3132, iFloat64::kOneEighth.s3132);
|
||||
EXPECT_EQ(a.to_float(), 0.125f);
|
||||
EXPECT_EQ(a.to_int32(), 0);
|
||||
|
||||
a = iFloat64(-0.125f);
|
||||
EXPECT_EQ(a, -iFloat64::kOneEighth);
|
||||
EXPECT_EQ(a.s3132, -iFloat64::kOneEighth.s3132);
|
||||
EXPECT_EQ(a.to_float(), -0.125f);
|
||||
EXPECT_EQ(a.to_int32(), -1);
|
||||
|
||||
a = iFloat64(M_PI); //3.14
|
||||
EXPECT_EQ(a, iFloat64::kPi);
|
||||
EXPECT_EQ(a.s3132, iFloat64::kPi.s3132);
|
||||
|
||||
@@ -76,4 +76,26 @@ TEST(MathUtil, Basic)
|
||||
EXPECT_EQ_4X4_T_APPROX(m1, gm1, std::numeric_limits<float>::epsilon() * 100);
|
||||
}
|
||||
}
|
||||
|
||||
//couting bit set
|
||||
{
|
||||
EXPECT_EQ(MathUtil::popcount((uint8_t)(0x0)), 0);
|
||||
EXPECT_EQ(MathUtil::popcount((uint8_t)(0xFF)), 8);
|
||||
EXPECT_EQ(MathUtil::popcount((uint16_t)(0x0)), 0);
|
||||
EXPECT_EQ(MathUtil::popcount((uint16_t)(0xFFFF)), 16);
|
||||
EXPECT_EQ(MathUtil::popcount((uint32_t)(0x0)), 0);
|
||||
EXPECT_EQ(MathUtil::popcount((uint32_t)(0xFFFFFFFF)), 32);
|
||||
|
||||
for(int32_t i=0; i<100; i++)
|
||||
{
|
||||
uint8_t v8 = (uint8_t)MathUtil::rangeRandom(0, 0xFF);
|
||||
EXPECT_EQ(MathUtil::popcount(v8), __popcnt(v8));
|
||||
|
||||
uint16_t v16 = (uint16_t)MathUtil::rangeRandom(0, 0xFFFF);
|
||||
EXPECT_EQ(MathUtil::popcount(v16), __popcnt(v16));
|
||||
|
||||
uint32_t v32 = (uint32_t)MathUtil::rangeRandom(0, 0x7FFFFF);
|
||||
EXPECT_EQ(MathUtil::popcount(v32), __popcnt(v32));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user