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 // Init Assets
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
DTRAsset_InitGlobalState(); DTRAsset_InitGlobalState();
const f32 FONT_SIZE = 14;
DTRAsset_LoadFontToBitmap(input->api, &memory->mainStack, tempStack, &state->font, 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, DTRAsset_LoadBitmap(input->api, assetStack,
tempStack, &state->bitmap, "tree00.bmp"); tempStack, &state->bitmap, "tree00.bmp");
@ -959,7 +960,7 @@ extern "C" void DTR_Update(PlatformRenderBuffer *const platformRenderBuffer,
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// Update and Render // 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 #if 1
DqnV4 colorRed = DqnV4_4f(0.8f, 0, 0, 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 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)}; 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) if (1)
{ {
DTRRenderTransform rotatingXform = DTRRender_DefaultTriangleTransform();
rotatingXform.rotation = rotation * 0.25f;
DTRDebug_BeginCycleCount("DTR_Update_RenderPrimitiveTriangles", DTRDebug_BeginCycleCount("DTR_Update_RenderPrimitiveTriangles",
DTRDebugCycleCount_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, t0[0], t0[1], t0[2], colorRed);
DTRRender_Triangle(&renderBuffer, t1[0], t1[1], t1[2], colorRed); DTRRender_Triangle(&renderBuffer, t1[0], t1[1], t1[2], colorRed);
DTRRender_Triangle(&renderBuffer, t3[0], t3[1], t3[2], colorRed, rotatingXform); 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); DTRDebug_EndCycleCount(DTRDebugCycleCount_DTR_Update_RenderPrimitiveTriangles);
} }
if (1) if (0)
{ {
LOCAL_PERSIST bool runTinyRendererOnce = false; LOCAL_PERSIST bool runTinyRendererOnce = false;
if (1 && runTinyRendererOnce) if (1 && runTinyRendererOnce)
@ -1016,7 +1020,7 @@ extern "C" void DTR_Update(PlatformRenderBuffer *const platformRenderBuffer,
DqnV3 modelP = DqnV3_3f(0, 0, 0); DqnV3 modelP = DqnV3_3f(0, 0, 0);
LOCAL_PERSIST f32 modelRotation = 0; LOCAL_PERSIST f32 modelRotation = 0;
modelRotation += (input->deltaForFrame * 20.0f); modelRotation += (input->deltaForFrame * 80.0f);
DqnV3 axis = DqnV3_3f(0, 1, 0); DqnV3 axis = DqnV3_3f(0, 1, 0);
DTRRenderTransform transform = DTRRender_DefaultTransform(); DTRRenderTransform transform = DTRRender_DefaultTransform();

View File

@ -216,7 +216,7 @@ void DTRDebug_Update(DTRState *const state,
debug->renderBuffer = renderBuffer; debug->renderBuffer = renderBuffer;
debug->input = input; debug->input = input;
debug->font = &state->font; 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) if (debug->font->bitmap && debug->renderBuffer)
{ {
debug->displayYOffset = -(i32)(state->font.sizeInPt + 0.5f); 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++) 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); DEBUG_SLOW_AUTO_CHOOSE_BEGIN_CYCLE_COUNT(Triangle_RasterisePixel);
f32 barycentricA = signedArea1 * invSignedAreaParallelogram;
f32 barycentricB = signedArea2 * invSignedAreaParallelogram; f32 barycentricB = signedArea2 * invSignedAreaParallelogram;
f32 barycentricC = signedArea3 * invSignedAreaParallelogram; f32 barycentricC = signedArea3 * invSignedAreaParallelogram;
@ -1158,18 +1193,28 @@ FILE_SCOPE void SlowTriangle(DTRRenderBuffer *const renderBuffer, const DqnV3 p1
f32 currZValue = renderBuffer->zBuffer[zBufferIndex]; f32 currZValue = renderBuffer->zBuffer[zBufferIndex];
DQN_ASSERT(zBufferIndex < (renderBuffer->width * renderBuffer->height)); DQN_ASSERT(zBufferIndex < (renderBuffer->width * renderBuffer->height));
if (pixelZValue > currZValue) if (pixelZValue >= currZValue)
{ {
renderBuffer->zBuffer[zBufferIndex] = pixelZValue; renderBuffer->zBuffer[zBufferIndex] = pixelZValue;
DqnV4 finalColor = color; 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) if (!ignoreLight)
{ {
DqnV3 light = (p1Light * barycentricA) + (p2Light * barycentricB) + f32 barycentricA = signedArea1 * invSignedAreaParallelogram;
DqnV3 light = (p1Light * barycentricA) + (p2Light * barycentricB) +
(p3Light * barycentricC); (p3Light * barycentricC);
finalColor.rgb *= light; finalColor.rgb *= light;
DQN_ASSERT(finalColor.x >= 0);
} }
DQN_ASSERT(finalColor.x >= 0);
if (texture) if (texture)
{ {
DqnV2 uv = uv1 + (uv2SubUv1 * barycentricB) + (uv3SubUv1 * barycentricC); 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 *= INV_255;
color1 = DTRRender_SRGB1ToLinearSpaceV4(color1); color1 = DTRRender_SRGB1ToLinearSpaceV4(color1);
finalColor *= color1; finalColor *= color1;
DQN_ASSERT(finalColor.x >= 0);
} }
SetPixel(renderBuffer, bufferX, bufferY, finalColor, ColorSpace_Linear); SetPixel(renderBuffer, bufferX, bufferY, finalColor, ColorSpace_Linear);
int breakhere = 5;
} }
DEBUG_SLOW_AUTO_CHOOSE_END_CYCLE_COUNT(Triangle_RasterisePixel); DEBUG_SLOW_AUTO_CHOOSE_END_CYCLE_COUNT(Triangle_RasterisePixel);
} }
@ -1306,7 +1355,7 @@ FILE_SCOPE void TexturedTriangleInternal(DTRRenderBuffer *const renderBuffer,
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// SIMD/Slow Path // SIMD/Slow Path
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
if (globalDTRPlatformFlags.canUseSSE2) if (globalDTRPlatformFlags.canUseSSE2 && 0)
{ {
SIMDTriangle(renderBuffer, p1, p2, p3, uv1, uv2, uv3, lightIntensity1, lightIntensity2, SIMDTriangle(renderBuffer, p1, p2, p3, uv1, uv2, uv3, lightIntensity1, lightIntensity2,
lightIntensity3, ignoreLight, texture, color, min, max); 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 wd4201 nonstandard extension used: nameless struct/union
REM wd4189 local variable is initialised but not referenced REM wd4189 local variable is initialised but not referenced
REM wd4505 unreferenced local function not used will be removed 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 DLLFlags=/Fm%ProjectName% /Fo%ProjectName% /Fa%ProjectName% /Fe%ProjectName%
set Win32Flags=/FmWin32DTRenderer /FeWin32DTRenderer set Win32Flags=/FmWin32DTRenderer /FeWin32DTRenderer