支持抗锯齿

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
@@ -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 -3
View File
@@ -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
+19 -10
View File
@@ -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);
}
}
}