Render MPxHwShaderNode


#1

I created a MPxHwShaderNode, overriding its geometry, and drawing with opengl.

  1. It works only with the legacy default viewport. I assume I need different nodes for the other viewports (high quality, 2.0)?

  2. None of the renderers (software, hardware, mentalray) render it. How can I make the renderers render it?


#2

For mayaSoftware you need to create a dependency node with appropriate attributes and classification. Have a look at the devkit examples. Once you have the correct maya software shader, you have to write the corresponding mentalray shader with the same attributes and the same name. If loaded in the correct order, the maya shader is automatically translated to the mentalray shader. For normal shaders and procedural textures, you can write an MPxSurfaceShadingNodeOverride or a MPxShadingNodeOverride for textures. This way you can make your shader usable for Viewport2.0.


#3

Okay, I’ll check them out.
BTW, isn’t the hardware renderer suppose to render my MPxHwShaderNode?
Also, the doc also says that if in the compute I’ll set an outColor, the s/w renderer will see it. But the outColor can be set only to a single color, and it doesn’t seem like it would accept free style opengl drawing.


#4

Ah, okay.
If I’m not completly mistaken, to get any effect in the software render, you have to override the default MPxNode methods like compute(). And you will need to add a bunch of attributes if you have a surface shader to use lighting and getting the correct normals etc.


#5

I went over the doc and I played with some of the devkit examples. I even took a peek at some of your experiments (I assume):

https://github.com/haggi/OpenMaya/tree/master/src/mayaToIndigo/src/shaders

They all usually have some compute method to override. This method gets a bunch of info (e.g. a normal), but it’s all for the specific point we want to render, and the return value is a single color value. The renderers can render this info.

The hardware shader (like the one I used) has a geometry method that enables custom opengl drawing, e.g. glBegin GL_TRIANGLES, and you draw some custom shape in the viewport. But I haven’t seen such a custom drawing that the renderer can use.

I think that (as I suspected before posting the question) my expectation from the pipeline is wrong. You can’t just tell the renderer to draw something arbitrary (at least not with the standard plugins). So any ideas, perhaps, how to save what I draw in opengl? I tried using the hardware render buffer, but it’s resolution is limited to my viewport size on the screen. I can also render to an off-screen buffer and save the buffer as an image. But then, it’s too manual, and I am missing the whole render settings interface.


#6

From what I know, you should go with the viewport 2.0 handling. There you can overwrite all necessary methods and everything what can be rendered in the viewport 2.0 can be rendered with hardware 2.0 as much as I know.


#7

I think you are right. There’s MPxDrawOverride which handles viewport 2 and is rendered by hardware renderer 2. For example, the apiMeshShape from the devkit. The doc is confusing when you click list all members including inherited, and you don’t see all of them such as draw:

doc

I need to work this out, or better yet, try to find a minimal example.


#8

I think the footstep example is a bit simpler to understand and contains some geometry overrides.


#9

Messy code. I installed the directx sdk in order to build it. I can see the foot print in viewport 2, but the hardware renderer 2 doesn’t see it.


#10

It seems that I missed it. MPxHwShaderNode can be seen by the hardware renderer and draw custom opengl. I just didn’t override all the methods. I patched the devkit sample hwPhongShader to be minimal and render a triangle with the hardware renderer.

hwPhongShader.h

#ifndef _hwPhongShader
#define _hwPhongShader

#include <maya/MPxHwShaderNode.h>
#include <maya/MPoint.h>

class hwPhongShader : public MPxHwShaderNode
{
public:
	// Interactive overrides
	//virtual MStatus		bind( const MDrawRequest& request,							  M3dView& view );
	//virtual MStatus		unbind( const MDrawRequest& request,								M3dView& view );
	virtual MStatus		geometry( const MDrawRequest& request,
								M3dView& view,
								int prim,
								unsigned int writable,
								int indexCount,
								const unsigned int * indexArray,
								int vertexCount,
								const int * vertexIDs,
								const float * vertexArray,
								int normalCount,
								const float ** normalArrays,
								int colorCount,
								const float ** colorArrays,
								int texCoordCount,
								const float ** texCoordArrays);

	// Batch overrides
	//virtual MStatus	glBind(const MDagPath& shapePath);
	//virtual MStatus	glUnbind(const MDagPath& shapePath);
	virtual MStatus	glGeometry( const MDagPath& shapePath,
                              int prim,
							  unsigned int writable,
							  int indexCount,
							  const unsigned int * indexArray,
							  int vertexCount,
							  const int * vertexIDs,
							  const float * vertexArray,
							  int normalCount,
							  const float ** normalArrays,
							  int colorCount,
							  const float ** colorArrays,
							  int texCoordCount,
							  const float ** texCoordArrays);

	MStatus			draw(
                              int prim,
							  unsigned int writable,
							  int indexCount,
							  const unsigned int * indexArray,
							  int vertexCount,
							  const int * vertexIDs,
							  const float * vertexArray,
							  int normalCount,
							  const float ** normalArrays,
							  int colorCount,
							  const float ** colorArrays,
							  int texCoordCount,
							  const float ** texCoordArrays);


    static  void *  creator();
    static  MStatus initialize();

	static  MTypeId id;
};

#endif /* _hwPhongShader */

hwPhongShader.cpp

/* Run:
loadPlugin hwPhongShader;
polyCube -w 1 -h 1 -d 1 -sx 1 -sy 1 -sz 1 -ax 0 1 0 -cuv 4 -ch 1;
createNode hwPhongShader;
select -r pCube1 ;
// right-click to assign existing material
*/

#ifdef WIN32
#pragma warning( disable : 4786 )		// Disable STL warnings.
#endif

#include <maya/MIOStream.h>
#include <math.h>

#include <maya/MString.h>
#include <maya/MFnPlugin.h>


#include <maya/MMatrix.h>

#if defined(OSMac_MachO_)
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#else
#include <windows.h> // Zohar: needed
#include <GL/gl.h>
#include <GL/glu.h>
#endif

#include "hwPhongShader.h"

static const MString sHWPhongShaderRegistrantId("HWPhongShaderRegistrantId");

MStatus initializePlugin( MObject obj )
{
	MStatus   status;

	//const MString& swatchName =	MHWShaderSwatchGenerator::initialize();
	const MString UserClassify("shader/surface/utility");

	MFnPlugin plugin( obj, PLUGIN_COMPANY, "4.5", "Any");
	status = plugin.registerNode( "hwPhongShader", hwPhongShader::id,
			                      hwPhongShader::creator, hwPhongShader::initialize,
								  MPxNode::kHwShaderNode, &UserClassify );
	if (!status) {
		status.perror("registerNode");
		return status;
	}

	return MS::kSuccess;
}

MStatus uninitializePlugin( MObject obj )
{
	MStatus   status;

	MFnPlugin plugin( obj );

	// Unregister all chamelion shader nodes
	plugin.deregisterNode( hwPhongShader::id );
	if (!status) {
		status.perror("deregisterNode");
		return status;
	}

	return MS::kSuccess;
}

MTypeId hwPhongShader::id( 0x00105449 );

void * hwPhongShader::creator()
{
    return new hwPhongShader();
}

MStatus hwPhongShader::initialize()
{
	return MStatus::kSuccess;
}

/* virtual */
MStatus	hwPhongShader::geometry( const MDrawRequest& request,
							    M3dView& view,
                                int prim,
								unsigned int writable,
								int indexCount,
								const unsigned int * indexArray,
								int vertexCount,
								const int * vertexIDs,
								const float * vertexArray,
								int normalCount,
								const float ** normalArrays,
								int colorCount,
								const float ** colorArrays,
								int texCoordCount,
								const float ** texCoordArrays)
{
	MStatus stat = MStatus::kSuccess;
//return stat;
		stat = draw( prim, writable, indexCount, indexArray, vertexCount,
				vertexIDs, vertexArray, normalCount, normalArrays, colorCount,
				colorArrays, texCoordCount, texCoordArrays);
	return stat;
}

/* virtual */
MStatus	hwPhongShader::glGeometry(const MDagPath & path,
                                int prim,
								unsigned int writable,
								int indexCount,
								const unsigned int * indexArray,
								int vertexCount,
								const int * vertexIDs,
								const float * vertexArray,
								int normalCount,
								const float ** normalArrays,
								int colorCount,
								const float ** colorArrays,
								int texCoordCount,
								const float ** texCoordArrays)
{
	MStatus stat = MStatus::kSuccess;
		stat = draw( prim, writable, indexCount, indexArray, vertexCount,
					vertexIDs, vertexArray, normalCount, normalArrays, colorCount,
					colorArrays, texCoordCount, texCoordArrays);
	return stat;
}

MStatus	hwPhongShader::draw(int prim,
							unsigned int writable,
							int indexCount,
							const unsigned int * indexArray,
							int vertexCount,
							const int * vertexIDs,
							const float * vertexArray,
							int normalCount,
							const float ** normalArrays,
							int colorCount,
							const float ** colorArrays,
							int texCoordCount,
							const float ** texCoordArrays)
{
	// Zohar: draw a triangle
	glBegin(GL_TRIANGLES);
        glColor4f(1.0, .5, .5, 1.0f); // Let's hope the background color isn't red...
	glVertex3d(0,0,0);
	glVertex3d(1,0,0);
	glVertex3d(0,1,0);
	glEnd();

	return MS::kSuccess;
}