I am trying to draw onto the viewport with some alpha values but don't get the expected value.
To test out I simply draw a white rectangle as background and on top of that I draw a black line with a varying alpha value. Basically building a gradient going from full transparency (top) to full opaque (bottom).
To compare to what would be expected I've drawn a Photoshop gradient at the right.
To me it seems the first N lines are not drawn at all, or their alpha value prevent the lines from being visible, while the rest of the "gradient" doesn't seem to be linear.
Main code of the "gradient"
for (Int32 i = 0; i <= 255; ++i)
{
clipMap->SetColor(0, 0, 0, i);
clipMap->Line(10, 10+i, width-10, 10+i);
}
This is the result with R20, but similar results obtained with R21. Have not tested more recent releases.
Am I missing something about the "gradient" implementation, or is there another setting missing?
Here's the full plugin implementation:
// ========================
// Cinema 4D C++ plugin
//
// PluginName: Test
// Dummy "empty" plugin
// ========================
// Main.cpp
#include "c4d.h"
#include "lib_clipmap.h"
// Dummy IDs - for demonstration purposes only
#define MYSCENEHOOK_PLUGIN_ID 1000000
Bool DrawTheStuff(BaseDraw *bd, Int32 x, Int32 y)
{
AutoAlloc<GeClipMap> clipMap;
if (!clipMap) return false;
Int32 width = 300;
Int32 height = 275;
// now the dimensions are known
// intialize clipmap for the actual drawing
if (clipMap->Init(width, height, 32) != IMAGERESULT::OK)
return false;
clipMap->BeginDraw();
// fill background with white
clipMap->SetColor(255, 255, 255, 255);
clipMap->FillRect(0, 0, width, height);
// draw black stripes over background with different alpha values,
// leaving a border of 10 pixels of background at each side
for (Int32 i = 0; i <= 255; ++i)
{
clipMap->SetColor(0, 0, 0, i);
clipMap->Line(10, 10+i, width-10, 10+i);
}
clipMap->EndDraw();
const BaseBitmap* bitmap = clipMap->GetBitmap();
if (bitmap)
{
maxon::Vector *positions;
iferr(positions = NewMem(maxon::Vector, 4))
return false;
maxon::Vector *colors = nullptr; // NewMem(maxon::Vector, 4);
maxon::Vector *normals = nullptr; // NewMem(maxon::Vector, 4);
maxon::Vector *uvcoords;
iferr(uvcoords = NewMem(maxon::Vector, 4))
{
DeleteMem(positions);
return false;
}
// center image on top of the point
x -= (width / 2);
y -= (height / 2);
positions[0] = maxon::Vector(x, y, 0);
positions[1] = maxon::Vector(x + width, y, 0);
positions[2] = maxon::Vector(x + width, y + height, 0);
positions[3] = maxon::Vector(x, y + height, 0);
uvcoords[0] = maxon::Vector(0, 0, 0);
uvcoords[1] = maxon::Vector(1, 0, 0);
uvcoords[2] = maxon::Vector(1, 1, 0);
uvcoords[3] = maxon::Vector(0, 1, 0);
// draw texture in screen space
const Matrix currentMg = bd->GetMg();
bd->SetMatrix_Screen();
bd->SetLightList(BDRAW_SETLIGHTLIST_NOLIGHTS);
const DRAW_ALPHA alpha = DRAW_ALPHA::NORMAL; //DRAW_ALPHA::NONE
#if API_VERSION < 23000
const DRAW_TEXTUREFLAGS texture = DRAW_TEXTUREFLAGS::NONE;
#else
const DRAW_TEXTUREFLAGS texture = DRAW_TEXTUREFLAGS::INTERPOLATION_NEAREST | DRAW_TEXTUREFLAGS::TEMPORARY;
#endif
bd->DrawTexture(bitmap, positions, colors, normals, uvcoords, 4, alpha, texture);
DeleteMem(positions);
//DeleteMem(colors);
//DeleteMem(normals);
DeleteMem(uvcoords);
// restore the matrix
bd->SetMatrix_Matrix(nullptr, currentMg);
}
return true;
}
// ====================================
// SceneHook
// ====================================
class MySceneHook : public SceneHookData
{
INSTANCEOF(MySceneHook, SceneHookData)
public:
MySceneHook();
virtual Bool Draw(BaseSceneHook *node, BaseDocument *doc, BaseDraw *bd, BaseDrawHelp *bh, BaseThread *bt, SCENEHOOKDRAW flags);
static NodeData *Alloc(void) { return NewObjClear(MySceneHook); }
};
MySceneHook::MySceneHook() : SceneHookData()
{
}
Bool MySceneHook::Draw(BaseSceneHook *node, BaseDocument *doc, BaseDraw *bd, BaseDrawHelp *bh, BaseThread *bt, SCENEHOOKDRAW flags)
{
if (!node || !doc || !bd || !bh)
return false;
if (flags != SCENEHOOKDRAW::DRAW_PASS)
return true;
Int32 lLeft, lTop, lRight, lBottom;
bd->GetFrame(&lLeft, &lTop, &lRight, &lBottom);
bd->SetMatrix_Screen();
DrawTheStuff(bd, SAFEINT32((lLeft + lRight) * 0.5), SAFEINT32((lTop + lBottom) * 0.5));
// restore basedraw matrix
bd->SetMatrix_Matrix(nullptr, Matrix());
return true;
}
// ====================================
// Plugin Main
// ====================================
Bool PluginStart(void)
{
ApplicationOutput("Test"_s);
RegisterSceneHookPlugin(MYSCENEHOOK_PLUGIN_ID, "MySceneHook"_s, 0, MySceneHook::Alloc, EXECUTIONPRIORITY_GENERATOR, 0);
return true;
}
void PluginEnd(void)
{
}
Bool PluginMessage(Int32 id, void * data)
{
switch (id) {
case C4DPL_INIT_SYS:
if (!g_resource.Init())
return false;
return true;
case C4DMSG_PRIORITY:
return true;
case C4DPL_BUILDMENU:
break;
case C4DPL_ENDACTIVITY:
return true;
}
return false;
}