Add naiive SSAA for primitive triangles only

This commit is contained in:
Doyle Thai 2017-06-14 12:22:14 +10:00
parent 92953e9d7c
commit 371ece0ce3
4 changed files with 67 additions and 14 deletions

View File

@ -904,8 +904,9 @@ extern "C" void DTR_Update(PlatformRenderBuffer *const platformRenderBuffer,
// Init Assets
////////////////////////////////////////////////////////////////////////
DTRAsset_InitGlobalState();
const f32 FONT_SIZE = 14;
DTRAsset_LoadFontToBitmap(input->api, &memory->mainStack, tempStack, &state->font,
"Roboto-bold.ttf", DqnV2i_2i(256, 256), DqnV2i_2i(' ', '~'), 12);
"Roboto-bold.ttf", DqnV2i_2i(256, 256), DqnV2i_2i(' ', '~'), FONT_SIZE);
DTRAsset_LoadBitmap(input->api, assetStack,
tempStack, &state->bitmap, "tree00.bmp");
@ -959,7 +960,7 @@ extern "C" void DTR_Update(PlatformRenderBuffer *const platformRenderBuffer,
////////////////////////////////////////////////////////////////////////////
// Update and Render
////////////////////////////////////////////////////////////////////////////
DTRRender_Clear(&renderBuffer, DqnV3_3f(0.5f, 0.0f, 1.0f));
DTRRender_Clear(&renderBuffer, DqnV3_3f(0.0f, 0.0f, 0.0f));
#if 1
DqnV4 colorRed = DqnV4_4f(0.8f, 0, 0, 1);
@ -980,14 +981,17 @@ extern "C" void DTR_Update(PlatformRenderBuffer *const platformRenderBuffer,
DqnV3 t4[3] = {DqnV3_3i(100, 150, 0), DqnV3_3i(200, 150, 0), DqnV3_3i(200, 250, 0)};
DqnV3 t5[3] = {DqnV3_3i(300, 150, 0), DqnV3_3i(201, 150, 0), DqnV3_3i(200, 250, 0)};
DTRRenderTransform rotatingXform = DTRRender_DefaultTriangleTransform();
rotatingXform.rotation = rotation;
if (1)
{
DTRRenderTransform rotatingXform = DTRRender_DefaultTriangleTransform();
rotatingXform.rotation = rotation * 0.25f;
DTRDebug_BeginCycleCount("DTR_Update_RenderPrimitiveTriangles",
DTRDebugCycleCount_DTR_Update_RenderPrimitiveTriangles);
DTRRenderTransform scaleXform = DTRRender_DefaultTriangleTransform();
scaleXform.scale = DqnV3_1f(5);
DTRRender_Triangle(&renderBuffer, t0[0], t0[1], t0[2], colorRed);
DTRRender_Triangle(&renderBuffer, t1[0], t1[1], t1[2], colorRed);
DTRRender_Triangle(&renderBuffer, t3[0], t3[1], t3[2], colorRed, rotatingXform);
@ -997,7 +1001,7 @@ extern "C" void DTR_Update(PlatformRenderBuffer *const platformRenderBuffer,
DTRDebug_EndCycleCount(DTRDebugCycleCount_DTR_Update_RenderPrimitiveTriangles);
}
if (1)
if (0)
{
LOCAL_PERSIST bool runTinyRendererOnce = false;
if (1 && runTinyRendererOnce)
@ -1016,7 +1020,7 @@ extern "C" void DTR_Update(PlatformRenderBuffer *const platformRenderBuffer,
DqnV3 modelP = DqnV3_3f(0, 0, 0);
LOCAL_PERSIST f32 modelRotation = 0;
modelRotation += (input->deltaForFrame * 20.0f);
modelRotation += (input->deltaForFrame * 80.0f);
DqnV3 axis = DqnV3_3f(0, 1, 0);
DTRRenderTransform transform = DTRRender_DefaultTransform();

View File

@ -216,7 +216,7 @@ void DTRDebug_Update(DTRState *const state,
debug->renderBuffer = renderBuffer;
debug->input = input;
debug->font = &state->font;
debug->displayColor = DqnV4_4f(1, 1, 1, 1);
debug->displayColor = DqnV4_4f(1, 1, 1, 0.85f);
if (debug->font->bitmap && debug->renderBuffer)
{
debug->displayYOffset = -(i32)(state->font.sizeInPt + 0.5f);

View File

@ -1146,10 +1146,45 @@ FILE_SCOPE void SlowTriangle(DTRRenderBuffer *const renderBuffer, const DqnV3 p1
for (i32 bufferX = min.x; bufferX < max.x; bufferX++)
{
if (signedArea1 >= 0 && signedArea2 >= 0 && signedArea3 >= 0)
// TODO(doyle): Use signedArea1/2/3 and subsample increments from the signedAreaDeltas
const u32 NUM_SAMPLES_ALONG_AXIS = 2;
const u32 SAMPLES_PER_PIXEL = DQN_SQUARED(NUM_SAMPLES_ALONG_AXIS);
DQN_ASSERT((NUM_SAMPLES_ALONG_AXIS & 1) == 0);
const f32 SAMPLE_COVERAGE_INCREMENT = 1 / (f32)SAMPLES_PER_PIXEL;
const f32 SAMPLE_XY_INCREMENT = 1 / (f32)NUM_SAMPLES_ALONG_AXIS;
f32 subsampleCoverage = 0;
for (i32 sampleY = 0; sampleY < NUM_SAMPLES_ALONG_AXIS; sampleY++)
{
for (i32 sampleX = 0; sampleX < NUM_SAMPLES_ALONG_AXIS; sampleX++)
{
f32 granularX = sampleX * SAMPLE_XY_INCREMENT;
f32 granularY = sampleY * SAMPLE_XY_INCREMENT;
DqnV2 subsample = DqnV2_2f((f32)bufferX + granularX, (f32)bufferY + granularY);
f32 subsampleSignedArea1 = Triangle2TimesSignedArea(p2.xy, p3.xy, subsample);
f32 subsampleSignedArea2 = Triangle2TimesSignedArea(p3.xy, p1.xy, subsample);
f32 subsampleSignedArea3 = Triangle2TimesSignedArea(p1.xy, p2.xy, subsample);
if (subsampleSignedArea1 >= 0 && subsampleSignedArea2 >= 0 &&
subsampleSignedArea3 >= 0)
{
subsampleCoverage += SAMPLE_COVERAGE_INCREMENT;
}
}
}
DQN_ASSERT(subsampleCoverage >= 0.0f && subsampleCoverage <= 1.0f);
// TODO(doyle): Crashes when using meshes, since we are now sampling
// outside the actual specified mesh, (i.e. pixels just before it
// for SSAA) the barycentric coordinates sample outside the texture.
// Naiive workarounds will cause color artifacts or gaps in rendered
// meshes.
if (subsampleCoverage > 0)
{
DEBUG_SLOW_AUTO_CHOOSE_BEGIN_CYCLE_COUNT(Triangle_RasterisePixel);
f32 barycentricA = signedArea1 * invSignedAreaParallelogram;
f32 barycentricB = signedArea2 * invSignedAreaParallelogram;
f32 barycentricC = signedArea3 * invSignedAreaParallelogram;
@ -1158,18 +1193,28 @@ FILE_SCOPE void SlowTriangle(DTRRenderBuffer *const renderBuffer, const DqnV3 p1
f32 currZValue = renderBuffer->zBuffer[zBufferIndex];
DQN_ASSERT(zBufferIndex < (renderBuffer->width * renderBuffer->height));
if (pixelZValue > currZValue)
if (pixelZValue >= currZValue)
{
renderBuffer->zBuffer[zBufferIndex] = pixelZValue;
DqnV4 finalColor = color;
DQN_ASSERT(finalColor.x >= 0);
// NOTE: Multiply everything by the coverage alpha since
// colors need to be premultiplied alpha.
finalColor *= subsampleCoverage;
DQN_ASSERT(finalColor.x >= 0);
if (!ignoreLight)
{
DqnV3 light = (p1Light * barycentricA) + (p2Light * barycentricB) +
f32 barycentricA = signedArea1 * invSignedAreaParallelogram;
DqnV3 light = (p1Light * barycentricA) + (p2Light * barycentricB) +
(p3Light * barycentricC);
finalColor.rgb *= light;
DQN_ASSERT(finalColor.x >= 0);
}
DQN_ASSERT(finalColor.x >= 0);
if (texture)
{
DqnV2 uv = uv1 + (uv2SubUv1 * barycentricB) + (uv3SubUv1 * barycentricC);
@ -1200,9 +1245,13 @@ FILE_SCOPE void SlowTriangle(DTRRenderBuffer *const renderBuffer, const DqnV3 p1
color1 *= INV_255;
color1 = DTRRender_SRGB1ToLinearSpaceV4(color1);
finalColor *= color1;
DQN_ASSERT(finalColor.x >= 0);
}
SetPixel(renderBuffer, bufferX, bufferY, finalColor, ColorSpace_Linear);
int breakhere = 5;
}
DEBUG_SLOW_AUTO_CHOOSE_END_CYCLE_COUNT(Triangle_RasterisePixel);
}
@ -1306,7 +1355,7 @@ FILE_SCOPE void TexturedTriangleInternal(DTRRenderBuffer *const renderBuffer,
////////////////////////////////////////////////////////////////////////////
// SIMD/Slow Path
////////////////////////////////////////////////////////////////////////////
if (globalDTRPlatformFlags.canUseSSE2)
if (globalDTRPlatformFlags.canUseSSE2 && 0)
{
SIMDTriangle(renderBuffer, p1, p2, p3, uv1, uv2, uv3, lightIntensity1, lightIntensity2,
lightIntensity3, ignoreLight, texture, color, min, max);

View File

@ -39,7 +39,7 @@ REM wd4100 unused argument parameters
REM wd4201 nonstandard extension used: nameless struct/union
REM wd4189 local variable is initialised but not referenced
REM wd4505 unreferenced local function not used will be removed
set CompileFlags=-EHsc -GR- -Oi -MT -Z7 -W4 -wd4100 -wd4201 -wd4189 -wd4505 -O2 -FAsc /I..\src\external\
set CompileFlags=-EHsc -GR- -Oi -MT -Z7 -W4 -wd4100 -wd4201 -wd4189 -wd4505 -Od -FAsc /I..\src\external\
set DLLFlags=/Fm%ProjectName% /Fo%ProjectName% /Fa%ProjectName% /Fe%ProjectName%
set Win32Flags=/FmWin32DTRenderer /FeWin32DTRenderer