Maya API开发【2】硬件渲染节点

硬件渲染插件概述       
         一个硬件渲染的节点插件是当做maya的DG节点来写的。基本的硬件渲染节点包含被当做input和output的属性;每个渲染节点必须有output,能在DG中被连接。硬件渲染节点也要重载资源创建,删除,绘制的函数。这些虚函数在下列情况调用。当maya检测到和几何图元关联的硬件渲染节点,并且指定使用此shader。可以在硬件渲染节点中使用多种方法来控制maya的最终显示,例如,实现标准的OpenGL渲染,扩展,像素、顶点shader,多通道渲染等。
        Maya场景的视口支持硬件渲染插件,场景视口有高质量交互渲染模式,硬件渲染器,UV编辑器。Maya支持的图元类型如下:
  • 网格图形全都支持。
  • Nurbs曲面仅在高质量渲染模式和使用gl接口的硬件渲染器 情况下支持。
        开发硬件渲染插件,继承MPxHwShaderNode并重载相应的虚函数即可。MPxHwShaderNode中有很多虚函数。最重要的就是执行绑定、绘制、去绑定的。这些函数在资源分配,绘制,资源重分配上很重要,并有两个版本。
        原始接口如下:
        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 float** normalArrays, int colorCount, 
                                                      const float** colorArrays, int texCoordCount, 
                                                      const float** texCoordArrays);
        第二接口或者gl方法如下:
        virtual MStatus glBind( const MDagPath& shapePath );
        virtual MStatus glUnbind( const MDagPath& shapePath);
        virtual MStatus glGemetry( const MDagPath& shapePath, int glPrim, unsigned int writeMask, 
                                                        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);
        当比较函数参数时会发现这些接口很相似。最大的区别就是原始接口参数列表中的MDrawRequest和M3dView在第二接口中被替换成了MDagPath。如果硬件渲染节点不需要绘制信息(MDrawRequest object),建议实现功能更强大的gl版。
        注意: 默认情况下,bind(),geometry(),unbind()会调用对应的gl版本接口。

实现硬件渲染插件
        MPxHwShaderNode中有两个接口可以用来实现渲染器的硬件渲染节点。当对比参数时,你会发现这两个接口很像,但调用的方式却截然不同。
  1. bind/geometry/unbind接口
    • 实现bind(),geometry()和unbind()方法就可以让maya场景显示器渲染硬件节点。三个方法的目的如下:
      • bind用来设置OpenGL的状态和资源。
      • geometry用来渲染效果。
      • unbind用于保存OpenGL的状态和清理资源。

    • 在此模式下仅支持mesh图形,以下步骤用于绘制:
      • maya访问每个DAG节点,收集绘制请求。
      • 绘制请求被保存在“透明”和“不透明”队列中。
      • maya执行不透明绘制,无需排序。
      • maya根据深度排序透明物体,执行绘制。

    • maya绘制信息的请求响应如下:
      • mesh图形接到绘制请求。
      • 图形检测材质是否为硬件shader。
      • 如果是硬件渲染节点,图元打包传送给节点的虚函数。
      • 硬件渲染节点根据传进来的信息决定如何在屏幕上显示。

    • 接口调用循序如下:
      • for every shape
                      bind(...)
                      geometry(...)
                      unbind(...)
    • 这种调用模式的结果是OpenGL的状态在bind()中设置,在geometry()中使用,在unbind()中存储。

    • 此接口中会被传入M3dView,此参数用来设置绘制所用的图形内容。接口中实际操作要在beginGL()和endGL()中间实现。如下:
MStatus hwShader::bind( const MDrawRequest& request, M3dView& view)
{
        view.beginGL();
        // oprations.... 
        view.endGL();
这些接口调用失败会导致程序崩溃。

2.  glbind/glGeometry/glUnbind接口
实现上面三个方法,可以让maya视口显示硬件渲染的内容。三个接口的目的:
  • glBind 用来设置插件状态和资源。
  • glGeometry用来设置OpenGL状态,渲染shader特效,存储OpenGL状态。
  • glUnbind用于存储插件的状态和资源。
接口中,虚函数调用循序如下:
for every pass // 一个更新可能有多个pass
{
for every object
{
if glBind() has not been called for this refresh
// 如果此更新没有调用glBind()
glBind(...)
glGeometry(....)
}
}
for every object
glUnbind(...)

        接口调用顺序的改动,会造成多方面的影响。使用这个接口,OpenGL的接口必须在glGeometry()中设置,而不是在glBind()中。现在glBind()仅用来加载资源,处理glGeometry()所用到的属性。

3. 控制传入geometry、glGeometry的信息
        geometry()和glGeometry()有很长的参数列表,包含描述渲染当前几何体必选和可选的顶点,面的shader。下面的方法控制哪些可选数据能传入shader。
virtual int normalsVertex();
virtual int colorsPerVertex();
virtual int getColorSetNames( MStringArray& names);
virtual int texCoordsPerVertex();
virtual int getTexCoordSetNames( MStringArray& names);
virtual bool provideVertexIDs();
重要提示,如果请求的信息不存在,Null就会被传给shader。硬件渲染插件应该检测参数信息确保数据有效,避免Null。

4. 透明盒硬件渲染节点
当shader中有透明物体时,maya会对渲染信息进行排序。如果硬件渲染节点不支持透明,就重载下面的函数,返回false。
virtual bool hasTransparency();
5. 索引和geometry(),glGeometry()使用的稀疏数组

数据通过索引机制传给这些方法,这些方法有:
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);
 
   
virtual MStatus glGeometry( const MDagPath& shapePath, int glPrim, unsigned int writeMask, 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);
    用来索引的参数是 indexCount, 其包含indexArray的长度。保存在indexArray中的索引是在存取其他数据,例如,顶点,颜色,法线时用的。
    传入geometry()的好几个参数是数组的数组。其是指向指针的指针。这些数组可能是稀疏的。当一条信息请求的信息比实际有的还多时,就会发生稀疏现象。例如,getTexCoordSetNames()可以请求3个UV集合,但仅第一和第三个存在。这种情况,第二位置的数组就是空的,那么检测NUll确保数据有效就很重要。

        6. blind data
                        硬件渲染节点使用baked的顶点网格数据来渲染是一种很有用的技术。这对两个geometry方法都有效。硬件渲染节点需实现    provideVertexIDs()来返回true。这步完成后,vertexIDs数组就包含了请求数据信息,vertexCount包含数组长度。如果使用MDrawRequest,可以用下面的方法来获取数据:
                        request.multiPath.node();
                        在gl版本的接口中,shapePath这个参数保存了mesh。联合使用vertex IDs和shape就可以使用MFnMesh获取blind data了。
        7. 和maya其他部分互动
                        使用MPxHwShaderNode类就可以让硬件渲染节点和maya的其他部分互动了。请看下节。
        8. 软件渲染和shader 样本
                        你实现硬件渲染节点的时候,可以采用能给软件渲染和属性编辑器中的shader样本一个合适输出的方式。基本方法就是实现compute()函数来影响 outColor属性。此步完成后,软件渲染和shader样本就不会是默认的黑色了。
                        可选方案,实现一个特殊的虚函数来直接绘制shader样本,方法如下:
                       virtual MStatus renderSwatchImage(MImage& image);
                        这个函数需要下面样本定义:
                        const MString UserClassify(“shader/surface/utility/:swatch/" + swatchName);
                        当插件调用MFnPlugin::registerNode()时,字符串就传给了maya。
        9. UV贴图编辑器
                        类MPxHwShaderNode中有一个票函数来帮助硬件渲染节点和UV贴图编辑器交互。方法如下:
                        virtual MStatus getAvailableImages( const MString& uvSetName, MStringArray& imageNames);
                        virtual MStatus renderImage( const MString& imageName, const float region[2][2], int& imageWidth, int& imageHeight);
                        第一个方法getAvailableImages()是用来提供UV通道的列表,就可以在UV编辑器里看了。第二个方法renderImage(),当在UV编辑器里面选中一个通道时,就会调用。然后这个程序就会绘制图像了。
                        如果硬件渲染节点采用maya标准纹理,就没有必要实现此方法了。标准maya纹理,可以字节在纹理编辑器里查看。
        10. HyperShade 窗口上的图标
                        你可以给硬件渲染节点提供一个图标,这样就可以在hypershade窗口显示。如果没有指定图标,默认图标是黑色的。想指定图标,做法如下:
                        创建名为render_nodeName.xpm的icon,例如render_hwPhongShader.xpm
                        将icon放在环境变量XBMLANGPATH路径下。
        11. 拖动,放置动作
                        可以利用MPxDragAndDropBehavior来实现drap和drop行为。此类提供了很多方法在hypershade菜单里支持此功能。具体实现请查看hwPhongShaderBehavior.cpp

一个具体的例子

        hwPhoneShader节点插件可以在Maya API Devkit中找到。这个例子中,用一张立方体环境贴图来实现每像素的phong渲染。当前,光源方向被固定在视角方向。
        1. 加载和卸载插件
                加载插件的过程很直接。 加载过程中,会构建样本分类字符串,同时需要drag和drop行为类。注意,drop和drag类并不需要唯一的MTypeId。 给一个字符串命名就足够了。
 MStatus initializePlugin( MObject obj )
{
MStatus status;
const MString& swatchName = MHWShaderSwatchGenerator::initialize();
const MString UserClassify( "shader/surface/utility/:swatch/"+swatchName );
MFnPlugin plugin( obj, "Autodesk", "4.5", "Any");
status = plugin.registerNode( "hwPhongShader", hwPhongShader::id,
hwPhongShader::creator, hwPhongShader::initialize,
MPxNode::kHwShaderNode, &UserClassify );
if (!status)
{
status.perror("registerNode");
return status;
}
plugin.registerDragAndDropBehavior("hwPhongShaderBehavior", 
hwPhongShaderBehavior::creator);
return MS::kSuccess;
}
 
 
 
                卸载插件,注销Phong节点和drag、drop行为:
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;
	}
 
  
	plugin.deregisterDragAndDropBehavior("hwPhongShaderBehavior");
 
  
	return MS::kSuccess;
}
    2. 初始化节点
        硬件shader插件的initialize()中被DG用到的属性都是提前定义好的。添加标准颜色属性,基于其工作目的给于标记。首先,创建attribute,然后添加,最后设置attributes间的连接关系。此例子中为了性能将attribute设置为cached和内部的。
MStatus hwPhongShader::initialize()
{
 MFnNumericAttribute nAttr; 
 // Create input attributes
 aColor = nAttr.createColor( "color", "c");
 nAttr.setStorable(true);
 nAttr.setKeyable(true);
 nAttr.setDefault(0.1f, 0.1f, 0.1f);
 nAttr.setCached( true );
 nAttr.setInternal( true );
 aDiffuseColor = nAttr.createColor( "diffuseColor", "dc" );
 nAttr.setStorable(true);
 nAttr.setKeyable(true);
 nAttr.setDefault(1.f, 0.5f, 0.5f);
 nAttr.setCached( true );
 nAttr.setInternal( true );
 aSpecularColor = nAttr.createColor( "specularColor", "sc" );
 nAttr.setStorable(true);
 nAttr.setKeyable(true);
 nAttr.setDefault(0.5f, 0.5f, 0.5f);
 nAttr.setCached( true );
 nAttr.setInternal( true );
 // This is defined as a point, so that users can easily enter
 // values beyond 1.
 aShininess = nAttr.createPoint( "shininess", "sh" );
 nAttr.setStorable(true);
 nAttr.setKeyable(true);
 nAttr.setDefault(100.0f, 100.0f, 100.0f);
 nAttr.setCached( true );
 nAttr.setInternal( true );
 aGeometryShape = nAttr.create( "geometryShape", "gs", MFnNumericData::kInt );
 nAttr.setStorable(true);
 nAttr.setKeyable(true);
 nAttr.setDefault(0);
 nAttr.setCached( true );
 nAttr.setInternal( true );
 // create output attributes here
 // outColor is the only output attribute and it is inherited
 // so we do not need to create or add it.
 //
 // Add the attributes here
 addAttribute(aColor);
 addAttribute(aDiffuseColor);
 addAttribute(aSpecularColor);
 addAttribute(aShininess);
 addAttribute(aGeometryShape);
 attributeAffects (aColor,			outColor);
 attributeAffects (aDiffuseColor,	outColor);
 attributeAffects (aSpecularColor,	outColor);
 attributeAffects (aShininess,		outColor);
 return MS::kSuccess;
}
    3. 计算方法
        下面简单介绍compute()方法的实现。此方法仅处理outColor属性。其他传入的属性会直接返回MS::kUnkownParameter,这样maya就会处理这些属性。否则,aDiffuseColor可以从datablock访问,这是用来设置输出颜色的。
MStatus hwPhongShader::compute(
const MPlug& plug,
 MDataBlock& block ) 
{ 
 if ((plug != outColor) && (plug.parent() != outColor))
		return MS::kUnknownParameter;
 MFloatVector & color = block.inputValue( aDiffuseColor ).asFloatVector();
 // set output color attribute
 MDataHandle outColorHandle = block.outputValue( outColor );
 MFloatVector& outColor = outColorHandle.asFloatVector();
 outColor = color;
 outColorHandle.setClean();
 return MS::kSuccess;
}
    通过实现这个方法,硬件渲染节点就可以在软件渲染里面实现了。如果不需要软件渲染,就不必实现了。
    4. bind, draw, unbind方法
        bind()和glBind()遵从下面的策略。 如果所需属性改变了或者Phong纹理没有设置,那么就会初始化Phong纹理。
MStatus	hwPhongShader::bind(const MDrawRequest& request, M3dView& view)
{
	if (mAttributesChanged || (phong_map_id == 0))
	{
		init_Phong_texture ();
	}
	return MS::kSuccess;
}
MStatus	hwPhongShader::glBind(const MDagPath&)
{
	if ( mAttributesChanged || (phong_map_id == 0))
	{
		init_Phong_texture ();
	}
	return MS::kSuccess;
}
    上面的例子中unbind()和glUnbind()方法仅仅返回了MS::kSucess,还有其他可选方法释放资源。在hwPhongShader例子中,消息是通过API检测的,资源会在新建文件,打开文件,打开文件索引等事件之前释放,具体内容请查看完整代码。
    MStatus	hwPhongShader::unbind(const MDrawRequest& request, M3dView& view)
{
 // The texture may have been allocated by the draw; it's kept
 // around for use again. When scene new or open is performed this
 // texture will be released in releaseEverything().
 return MS::kSuccess;
}
MStatus	hwPhongShader::glUnbind(const MDagPath&)
{
 // The texture may have been allocated by the draw; it's kept
 // around for use again. When scene new or open is performed this
 // texture will be released in releaseEverything().
 return MS::kSuccess;
}
    geometry()和glGeometry()的设置很相似。为了避免复制代码,每个接口都调用独立接口draw()。
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;
	if (mGeometryShape != 0)
		drawDefaultGeometry();
	else
		stat = draw( prim, writable, indexCount, indexArray, vertexCount,
				vertexIDs, vertexArray, normalCount, normalArrays,
				colorCount, colorArrays, 
				texCoordCount, texCoordArrays);
	return stat;
}
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;
	if (mGeometryShape != 0)
		drawDefaultGeometry();
	else
		stat = draw( prim, writable, indexCount, indexArray, vertexCount,
				vertexIDs, vertexArray, normalCount, normalArrays,
				colorCount, colorArrays, 
				texCoordCount, texCoordArrays);
	return stat;
}
    5. 绘制drawing
        draw()函数的参数是为了将信息传送给OpenGL渲染用的。请注意indexArray是其他数组用来读取数据用的。
    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)
{
	if ( prim != GL_TRIANGLES && prim != GL_TRIANGLE_STRIP)	{
 return MS::kFailure;
 }
 {
		glPushAttrib ( GL_ENABLE_BIT );
		glDisable ( GL_LIGHTING );
		glDisable ( GL_TEXTURE_1D );
		glDisable ( GL_TEXTURE_2D );
		// Setup cube map generation
		glEnable ( GL_TEXTURE_CUBE_MAP_EXT );
		glBindTexture ( GL_TEXTURE_CUBE_MAP_EXT, phong_map_id );
		glEnable ( GL_TEXTURE_GEN_S );
		glEnable ( GL_TEXTURE_GEN_T );
		glEnable ( GL_TEXTURE_GEN_R );
		glTexGeni ( GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_EXT );
		glTexGeni ( GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_EXT );
		glTexGeni ( GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_EXT );
		glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_WRAP_S, GL_CLAMP);
		glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_WRAP_T, GL_CLAMP);
		glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexEnvi ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
		// Could modify the texture matrix here to do light tracking...
		glMatrixMode ( GL_TEXTURE );
		glPushMatrix ();
		glLoadIdentity ();
		glMatrixMode ( GL_MODELVIEW );
 }
 // Draw the surface.
 //
 {
		glPushClientAttrib ( GL_CLIENT_VERTEX_ARRAY_BIT );
		glEnableClientState( GL_VERTEX_ARRAY );
		glEnableClientState( GL_NORMAL_ARRAY );
		glVertexPointer ( 3, GL_FLOAT, 0, &vertexArray[0] );
		glNormalPointer ( GL_FLOAT, 0, &normalArrays[0][0] );
		
		glDrawElements ( prim, indexCount, GL_UNSIGNED_INT, indexArray );
		
		// The client attribute is already being popped. You
		glPopClientAttrib();
 }
 {
		glMatrixMode ( GL_TEXTURE );
		glPopMatrix ();
		glMatrixMode ( GL_MODELVIEW );
		glDisable ( GL_TEXTURE_CUBE_MAP_EXT );
		glDisable ( GL_TEXTURE_GEN_S );
		glDisable ( GL_TEXTURE_GEN_T );
		glDisable ( GL_TEXTURE_GEN_R );
		glPopAttrib();
 }
	return MS::kSuccess;
}
    6. 绘制样本
        绘制样本会调用虚函数renderSwatchImage()的具体实现,并利用MHardwareRenderer类来和MGeometryData,OpenGL协作来绘制图像。传送给renderSwatchImage()的MImage包含输出必须的width和height。
        MStatus hwPhongShader::renderSwatchImage( MImage & outImage )
{
	MStatus status = MStatus::kFailure;
	// Get the hardware renderer utility class
	MHardwareRenderer *pRenderer = MHardwareRenderer::theRenderer();
	if (pRenderer)
	{
		const MString& backEndStr = pRenderer->backEndString();
		// Get geometry
		// ============
		unsigned int* pIndexing = 0;
		unsigned int numberOfData = 0;
		unsigned int indexCount = 0;
		MHardwareRenderer::GeometricShape gshape =
 MHardwareRenderer::kDefaultSphere;
		if (mGeometryShape == 2)
		{
			gshape = MHardwareRenderer::kDefaultCube;
		}
		else if (mGeometryShape == 3)
		{
			gshape = MHardwareRenderer::kDefaultPlane;
		}
		MGeometryData* pGeomData =
			pRenderer->referenceDefaultGeometry( gshape, numberOfData, pIndexing, indexCount );
		if( !pGeomData )
		{
			return MStatus::kFailure;
		}
		// Make the swatch context current
		// ===============================
		//
		unsigned int width, height;
		outImage.getSize( width, height );
		unsigned int origWidth = width;
		unsigned int origHeight = height;
		MStatus status2 = pRenderer->makeSwatchContextCurrent( backEndStr,
 width, height );
		if( status2 == MS::kSuccess )
		{
			// NOTE: Must be called after makeSwatchContextCurrent()
			glPushAttrib ( GL_ALL_ATTRIB_BITS );
			// Get camera
			// ==========
			{
				// Get the camera frustum from the API
				double l, r, b, t, n, f;
				pRenderer->getSwatchOrthoCameraSetting( l, r, b, t, n, f );
				glMatrixMode(GL_PROJECTION);
				glLoadIdentity();
				glOrtho( l, r, b, t, n, f );
				glMatrixMode(GL_MODELVIEW);
				glLoadIdentity();
				// Rotate the cube a bit so we don't see it head on
				if (gshape == MHardwareRenderer::kDefaultCube)
					glRotatef( 45, 1.0, 1.0, 1.0 );
				else if (gshape == MHardwareRenderer::kDefaultPlane)
					glScalef( 1.5, 1.5, 1.5 );
				else
					glScalef( 1.0, 1.0, 1.0 );
			}
			// Draw The Swatch
			// ===============
			drawTheSwatch( pGeomData, pIndexing, numberOfData, indexCount );
			// Read pixels back from swatch context to MImage
			// ==============================================
			pRenderer->readSwatchContextPixels( backEndStr, outImage );
			// Double check the outing going image size as image resizing
			// was required to properly read from the swatch context
			outImage.getSize( width, height );
			if (width != origWidth || height != origHeight)
			{
				status = MStatus::kFailure;
			}
			else
			{
				status = MStatus::kSuccess;
			}
			glPopAttrib();
		}
		else
		{
			pRenderer->dereferenceGeometry( pGeomData, numberOfData );
		}
	}
	return status;
}
        方法drawTheSwatch()在renderSwatchImage()中调用。其执行OpenGL来绘制图像。
        void			
hwPhongShader::drawTheSwatch( MGeometryData* pGeomData,
			unsigned int* pIndexing,
			unsigned int numberOfData,
			unsigned int indexCount )
{
	MHardwareRenderer *pRenderer = MHardwareRenderer::theRenderer();
	if( !pRenderer )	return;
	if ( mAttributesChanged || (phong_map_id == 0))
	{
		init_Phong_texture ();
	}
	// Get the default background color
	float r, g, b, a;
	MHWShaderSwatchGenerator::getSwatchBackgroundColor( r, g, b, a );
	glClearColor( r, g, b, a );
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glShadeModel(GL_SMOOTH);
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
	glDisable ( GL_LIGHTING );
	glDisable ( GL_TEXTURE_1D );
	glDisable ( GL_TEXTURE_2D );
	{
		glEnable ( GL_TEXTURE_CUBE_MAP_EXT );
		glBindTexture ( GL_TEXTURE_CUBE_MAP_EXT, phong_map_id );
		glEnable ( GL_TEXTURE_GEN_S );
		glEnable ( GL_TEXTURE_GEN_T );
		glEnable ( GL_TEXTURE_GEN_R );
		glTexGeni ( GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_EXT );
		glTexGeni ( GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_EXT );
		glTexGeni ( GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_EXT );
		glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_WRAP_S, GL_CLAMP);
		glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_WRAP_T, GL_CLAMP);
		glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexEnvi ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
		// Could modify the texture matrix here to do light tracking...
		glMatrixMode ( GL_TEXTURE );
		glPushMatrix ();
		glLoadIdentity ();
		glRotatef( 5.0, -1.0, 0.0, 0.0 );
		glRotatef( 10.0, 0.0, 1.0, 0.0 );
		glMatrixMode ( GL_MODELVIEW );
	}
	// Draw default geometry
	{
		if (pGeomData)
		{
			glPushClientAttrib ( GL_CLIENT_VERTEX_ARRAY_BIT );
			float *vertexData = (float *)( pGeomData[0].data() );
			if (vertexData)
			{
				glEnableClientState( GL_VERTEX_ARRAY );
				glVertexPointer ( 3, GL_FLOAT, 0, vertexData );
			}
			float *normalData = (float *)( pGeomData[1].data() );
			if (normalData)
			{
				glEnableClientState( GL_NORMAL_ARRAY );
				glNormalPointer ( GL_FLOAT, 0, normalData );
			}
			if (vertexData && normalData && pIndexing )
				glDrawElements ( GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, pIndexing );
			glPopClientAttrib();
			// Release data references
			pRenderer->dereferenceGeometry( pGeomData, numberOfData );
		}
	}
	{
		glMatrixMode ( GL_TEXTURE );
		glPopMatrix ();
		glMatrixMode ( GL_MODELVIEW );
		glDisable ( GL_TEXTURE_CUBE_MAP_EXT );
		glDisable ( GL_TEXTURE_GEN_S );
		glDisable ( GL_TEXTURE_GEN_T );
		glDisable ( GL_TEXTURE_GEN_R );
	}
}

Improving the performance of hardware shaders
    MPxHwShaderNode包含的supportsBatching()方法,控制着是否将材质的绘制调用捆绑起来以减少渲染状态的转换。通过实现这个方法,并返回true,MPxHwShaderNode的每个前(bind/glBind)和后(unbind/glUnbind)每帧都会调用此方法,而不是每个图形每帧。默认情况下,此方法为了和以前的插件兼容会返回false。更多信息请查看此函数的文档。





















































































  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值