Object extern and materials


photo

Recommended Posts

Hi,

I need to create an object extern (derived from Unigine::ObjectExternBase) which renders Unigine::MeshDynamic with a specific Unigine material (and its shaders). So what I do to create this is:

Unigine::ObjectExternPtr Create(const Unigine::MaterialPtr &material)
{
	auto objExtern = Unigine::ObjectExtern::create(PRECIPITATION_OBJECT_EXTERN_CLASS_ID);
	auto* my = static_cast<MyObjectExtern*>(objExtern->getObjectExtern());
	auto node = my->getNode();
	node->setEnabled(true);

	// Material setup.
	precipitationObjectExtern->setMaterialNodeType(Unigine::Node::TYPE::OBJECT_MESH_DYNAMIC); // Mark as accepting materials for dynamic objects.
	Unigine::ObjectPtr ungObject = my->getObject();
	auto ret = ungObject->setMaterial(material, 0);
	assert(ret != 0);

      ...
      
	// Render all the time, without culling, so setup a very big bounding box.
	Unigine::Math::vec3 min(-FLT_MAX), max(FLT_MAX);
	my->_boundBox.set(min, max);
	my->_boundSphere.set(_boundBox);

    // Create the dyn mesh...
      
	Unigine::MeshDynamic::Attribute attributes[1] = 
	{
		{ 0, Unigine::MeshDynamic::TYPE_FLOAT, 4 }
	};

	my->_dynMesh = Unigine::MeshDynamic::create(0);
	my->_dynMesh->setVertexFormat(attributes, 1);

	// A single quad made up of two triangles.
	my->_dynMesh->addVertexFloat4(0, -1, -1, 0, 1);
	my->_dynMesh->addVertexFloat4(0, 1, -1, 0, 1);
	my->_dynMesh->addVertexFloat4(0, 1, 1, 0, 1);
	my->_dynMesh->addVertexFloat4(0, -1, 1, 0, 1);	
	my->_dynMesh->addIndices(0, 1, 2);
	my->_dynMesh->addIndices(0, 2, 3);

	my->_dynMesh->flushVertex();
	my->_dynMesh->flushIndices();
      
      ...

Then when I render I do something like:

void MyObjectExtern::render(Unigine::Render::PASS pass, int surface)
{
	// Check render pass
	if (pass != Unigine::Render::PASS_AMBIENT)
		return; // Only transparent pass.

	// Bind states specific to us.
	Unigine::RenderState::setBlendFunc(Unigine::RenderState::BLEND_ONE, Unigine::RenderState::BLEND_ONE_MINUS_SRC_ALPHA);

	// Material setup...
	Unigine::ObjectPtr ungObject = getObject();
	auto mat = ungObject->getMaterial(0);

	// Bind the shader for our pass.
	auto shader = mat->fetchShader(Unigine::Render::PASS::PASS_AMBIENT, Unigine::Node::TYPE::OBJECT_MESH_DYNAMIC);
	assert(shader.get());

	shader->bind();

	// Set the transform (is this really needed?)
	int id = shader->findParameter("s_transform");
	if (id != -1)
	{
		Unigine::Math::vec4 transforms[3];
		Unigine::Math::Mat4 modelView = Unigine::Renderer::getModelview() * getNode()->getWorldTransform();
		transforms[0] = Unigine::Math::vec4(modelView.getRow(0));
		transforms[1] = Unigine::Math::vec4(modelView.getRow(1));
		transforms[2] = Unigine::Math::vec4(modelView.getRow(2));
		shader->setParameterArrayFloat4(id, transforms, 3);
	}
	shader->flushParameters();	

	// Bind diffuse texture.
	auto diffuse = mat->getTexture(0);
	if(diffuse)
		diffuse->bindFragment(0);

	// Render the instances.
	_dynMesh->bind();
	_dynMesh->renderInstancedSurface(Unigine::MeshDynamic::MODE_TRIANGLES, _instancesCount);

	// Clean up state...
	diffuse->unbindFragment(0);
	shader->unbind();
	_dynMesh->unbind();
}

So basically rendering the dynamic mesh. What I notice is that parameters from material are not ending up into the shader. For example if this is the material in the example above.

<?xml version="1.0" encoding="utf-8"?>
<base_material name="snow_flakes" editable="1" version="2.9.0.2">
	<options order="40" depth_mask="1" transparent="2"/>
	<state name="instances_override" type="switch">0</state>
	<blend src="src_alpha" dest="one_minus_src_alpha"/>
	<shader defines="FLAKES" pass="ambient" node="object_mesh_dynamic" vertex="Common/Materials/vertex_stateless_particles.shader" fragment="Common/Materials/fragment_stateless_particles.shader"/>
        <float4 name="posTime" shared="1">0 0 0 0</float4
        <float4 name="flakeScale" shared="1">0.2 0.2 0.2 0.2</float4>
        <float name="simplexNoiseSourceScale" shared="1">0.1</float>
        <float4 name="diffuseColor" shared="1">1 1 1 1</float4>
		<texture unit="0" name="ambient" pass="ambient">Common/Textures/SnowFlake001_A_128.dds</texture>
</base_material>

I think things like diffuseColor, flakeScale etc, are not setup per shader even if shared is 1. 

To make all the above work I need to load from disk (from an xml) another Unigine dynamic mesh node using the same material. Then somehow the shader constants buffers are ok.

Is this the way to go when using materials and object externs? Or do I have to manually set the parameter, flush them etc?

To be noted that the rendering call happens, but nothing shows (as probably shaders have constants all zero/undefined). Once I just load another node using that material, everything works, even if I don't render that node.

Kind Regards,

Adrian L.

 

 

 

Link to post

Hi Adrian,

Is it possible to get the full sources for the test sample? It would be faster if we can also build and debug it on our side.

Thanks!

How to submit a good bug report
---
FTP server for test scenes and user uploads:

Link to post

Hi Slient and thank you for the quick response. I will post more details as the private support ticket. I will send some more files, but cannot send something that fully compiles as a standalone sample.

Link to post

Ticket 4225 was added. Thanks!

Link to post