I'm trying to make a cloud system with random placement of square faces, each face have a random cloud texture.
I heard the integrated billboard class in irrlicht was too slow with a big number of objects, so I written a small vertex shader.
I have to use EMT_TRANSPARENT_ALPHA_CHANNEL material to construct my HightLevelMaterial.
But instead of drawing a blended face It give me an opaque face. Only the absolutly transparent (alpha=0.000000) pixels are transparent.
I tried some other tricks, like using EMT_ONETEXTURE_BLEND instead, setting manually material.MaterialTypeParam:
Code: Select all
material.MaterialTypeParam = video::pack_textureBlendFunc(video::EBF_SRC_ALPHA, video::EBF_ONE_MINUS_SRC_ALPHA,
video::EMFN_MODULATE_1X, video::EAS_TEXTURE | video::EAS_VERTEX_COLOR);
Code: Select all
class FaceNode : public scene::ISceneNode
{
core::aabbox3d<f32> Box;
video::S3DVertex Vertices[4];
video::SMaterial Material;
public:
FaceNode(scene::ISceneNode* parent, scene::ISceneManager* mgr)
: scene::ISceneNode(parent, mgr)
{
//Material.Wireframe = false;
// S3DVertex (f32 x, f32 y, f32 z, f32 nx, f32 ny, f32 nz, SColor c, f32 tu, f32 tv)
Vertices[0] = video::S3DVertex( 0,0,0, 0,0,-1, video::SColor(0,0,0,0), 0, 0);
Vertices[1] = video::S3DVertex( 0,1,0, 0,0,-1, video::SColor(0,0,0,0), 1, 0);
Vertices[2] = video::S3DVertex( 1,0,0, 0,0,-1, video::SColor(0,0,0,0), 0, 1);
Vertices[3] = video::S3DVertex( 1,1,0, 0,0,-1, video::SColor(0,0,0,0), 1, 1);
Box.reset(Vertices[0].Pos);
for (s32 i=1; i<4; ++i)
Box.addInternalPoint(Vertices[i].Pos);
}
virtual void OnRegisterSceneNode()
{
if (IsVisible)
SceneManager->registerNodeForRendering(this);
ISceneNode::OnRegisterSceneNode();
}
virtual void render()
{
u16 indices[] = {0,1,3, 0,3,2}; // order of indices of points decide the normal of the plane
video::IVideoDriver* driver = SceneManager->getVideoDriver();
driver->setMaterial(Material);
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
driver->drawVertexPrimitiveList(&Vertices[0], 4, &indices[0], 4, video::EVT_STANDARD, scene::EPT_TRIANGLES, video::EIT_16BIT);
}
virtual const core::aabbox3d<f32>& getBoundingBox() const
{ return Box; }
virtual u32 getMaterialCount() const
{ return 1; }
virtual video::SMaterial& getMaterial(u32 i)
{ return Material; }
};
Code: Select all
s32 matnum;
if (bCanDoGLSL_1_1)
{
matnum = gpu->addHighLevelShaderMaterialFromFiles(
"cloud.vert", "main", video::EVST_VS_1_1,
"cloud.frag", "main", video::EPST_PS_1_1,
0, video::EMT_TRANSPARENT_ALPHA_CHANNEL);
node->setMaterialType((video::E_MATERIAL_TYPE)matnum);
}
else
printf("no opengl support\n");
video::SMaterial material = node->getMaterial(0);
material.Lighting = false;
//material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
material.MaterialTypeParam = video::pack_textureBlendFunc(video::EBF_SRC_ALPHA, video::EBF_ONE_MINUS_SRC_ALPHA,
video::EMFN_MODULATE_1X, video::EAS_TEXTURE | video::EAS_VERTEX_COLOR);
// this is not working
// material.BackfaceCulling = false;
node->setMaterialFlag(video::EMF_BACK_FACE_CULLING, false);
material.setTexture(0, driver->getTexture("cloud-2.png"));
SOLUTION FOUND !
I just added the following line after the shader assignation. It now works as expected.
Code: Select all
node->setMaterialFlag(video::EMF_BLEND_OPERATION, true);