Skip to content

Commit

Permalink
libgui|ModelDrawable: Rendering pass mask; fixed drawing
Browse files Browse the repository at this point in the history
An optional bit array can now be passed to ModelDrawable::draw()
to specify which rendering passes are enabled.

Drawing without a shader program will now throw an exception.
  • Loading branch information
skyjake committed Oct 15, 2015
1 parent 93198a1 commit 600f7df
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 31 deletions.
20 changes: 18 additions & 2 deletions doomsday/sdk/libgui/include/de/graphics/modeldrawable.h
Expand Up @@ -59,6 +59,9 @@ class LIBGUI_PUBLIC ModelDrawable : public AssetGroup
/// An error occurred during the loading of the model data. @ingroup errors
DENG2_ERROR(LoadError);

/// There was a shader program related problem. @ingroup errors
DENG2_ERROR(ProgramError);

enum TextureMap // note: enum values used as indices internally
{
Diffuse = 0, ///< Surface color and opacity.
Expand Down Expand Up @@ -248,8 +251,7 @@ class LIBGUI_PUBLIC ModelDrawable : public AssetGroup
{
enum Flag
{
Enabled = 0x1,
DefaultFlags = Enabled
DefaultFlags = 0
};
Q_DECLARE_FLAGS(Flags, Flag)

Expand Down Expand Up @@ -422,8 +424,22 @@ class LIBGUI_PUBLIC ModelDrawable : public AssetGroup

GLProgram *program() const;

/**
* Draws the model.
*
* @param animation Animation state.
* @param drawPasses Rendering passes. If omitted, all meshes are drawn
* with normal alpha blending.
* @param passMask Sets a mask that specifies which rendering passes are
* enabled. Each bit in the array corresponds to an
* element in @a drawPasses. An empty mask (size zero)
* means that all passes are enabled.
* @param programCallback
* @param passCallback
*/
void draw(Animator const *animation = nullptr,
Passes const *drawPasses = nullptr,
QBitArray const &passMask = QBitArray(),
ProgramBindingFunc programCallback = ProgramBindingFunc(),
RenderingPassFunc passCallback = RenderingPassFunc()) const;

Expand Down
79 changes: 50 additions & 29 deletions doomsday/sdk/libgui/src/graphics/modeldrawable.cpp
Expand Up @@ -690,7 +690,7 @@ DENG2_PIMPL(ModelDrawable)
needMakeBuffer = true;
}

// Bone & Mesh Setup ----------------------------------------------------------------
//- Bone & Mesh Setup -------------------------------------------------------------------

void clearBones()
{
Expand Down Expand Up @@ -921,7 +921,7 @@ DENG2_PIMPL(ModelDrawable)
buffer->setIndices(gl::Triangles, indx, gl::Static);
}

// Animation ------------------------------------------------------------------------
//- Animation ---------------------------------------------------------------------------

struct AccumData
{
Expand Down Expand Up @@ -1059,10 +1059,11 @@ DENG2_PIMPL(ModelDrawable)
anim.mNumPositionKeys));
}

// Drawing --------------------------------------------------------------------------
//- Drawing -----------------------------------------------------------------------------

GLProgram *drawProgram = nullptr;
Pass const *drawPass = nullptr;
QBitArray passMask;
ProgramBindingFunc programCallback;
RenderingPassFunc passCallback;

Expand Down Expand Up @@ -1102,7 +1103,6 @@ DENG2_PIMPL(ModelDrawable)
{
if(drawProgram)
{
drawProgram->endUse();
drawProgram->unbind(uBoneMatrices);
if(programCallback)
{
Expand All @@ -1119,7 +1119,6 @@ DENG2_PIMPL(ModelDrawable)
programCallback(*drawProgram, AboutToBind);
}
drawProgram->bind(uBoneMatrices);
drawProgram->beginUse();
}
}

Expand Down Expand Up @@ -1157,39 +1156,59 @@ DENG2_PIMPL(ModelDrawable)
{
preDraw(animation);

GLBuffer::DrawRanges ranges;
for(Pass const &pass : passes)
try
{
if(!pass.flags.testFlag(Pass::Enabled))
GLBuffer::DrawRanges ranges;
for(int i = 0; i < passes.size(); ++i)
{
continue;
}
Pass const &pass = passes.at(i);

drawPass = &pass;
setDrawProgram(pass.program? pass.program : program);
// Is this pass disabled?
if(!passMask.isEmpty() && !passMask.testBit(i))
{
continue;
}

DENG2_ASSERT(drawProgram != nullptr);
drawPass = &pass;
setDrawProgram(pass.program? pass.program : program);
if(!drawProgram)
{
throw ProgramError("ModelDrawable::draw",
QString("Rendering pass %1 (\"%2\") has no shader program")
.arg(i).arg(pass.name));
}

if(passCallback)
{
passCallback(pass, PassBegun);
}
if(passCallback)
{
passCallback(pass, PassBegun);
}

ranges.clear();
initRanges(ranges, pass.meshes);
drawProgram->beginUse();

GLState::push()
.setBlendFunc(pass.blendFunc)
.setBlendOp(pass.blendOp)
.apply();
buffer->draw(&ranges);
GLState::pop();
ranges.clear();
initRanges(ranges, pass.meshes);

if(passCallback)
{
passCallback(pass, PassEnded);
GLState::push()
.setBlendFunc(pass.blendFunc)
.setBlendOp(pass.blendOp)
.apply();
buffer->draw(&ranges);
GLState::pop();

drawProgram->endUse();

if(passCallback)
{
passCallback(pass, PassEnded);
}
}
}
catch(Error const &er)
{
LOG_GL_ERROR("Failed to draw model \"%s\": %s")
<< sourcePath
<< er.asText();
}

postDraw();
}
Expand Down Expand Up @@ -1396,13 +1415,15 @@ GLProgram *ModelDrawable::program() const

void ModelDrawable::draw(Animator const *animation,
Passes const *passes,
QBitArray const &passMask,
ProgramBindingFunc programCallback,
RenderingPassFunc passCallback) const
{
const_cast<ModelDrawable *>(this)->glInit();

if(isReady() && d->program && d->atlas)
if(isReady() && d->atlas)
{
d->passMask = passMask;
d->programCallback = programCallback;
d->passCallback = passCallback;

Expand Down

0 comments on commit 600f7df

Please sign in to comment.