Beispiel #1
0
		void BaseShapeUI::getDrawRequests( const MDrawInfo & info, bool objectAndActiveOnly, MDrawRequestQueue & requests ) {
			MStatus status;

			MDrawData data;

			BaseShape *shape = (BaseShape *) surfaceShape();
			MDrawRequest request = info.getPrototype(*this);
			M3dView view = info.view();

			getDrawData(shape, data);

			request.setDrawData(data);

			MDagPath path = request.multiPath();
			MMaterial material = MPxSurfaceShapeUI::material(path);

			if (!(status = material.evaluateMaterial(view, path)))
				status.perror("MMaterial::evaluateMaterial");

			if (!(status = material.evaluateDiffuse()))
				status.perror("MMaterial::evaluateDiffuse");

			request.setMaterial(material);
			request.setToken(info.displayStyle());
	
			requests.add(request);
		}
// Load the file textures for the cube maps.
//
MStatus	hwRefractReflectShader_NV20::loadTextures(const MDrawRequest& request, M3dView& view)
{
	// Get the cube map file names
	//
	MStringArray	decalNames;
	MString			decalName;

	// Find the cubemap textures by tracing through the connection from the color atttribute
	//
	ShadingConnection	colorConnection(thisMObject(), request.multiPath().partialPathName(), "color");

	// If the color attribute is ultimately connected to a environment, 
	// find its filenames, otherwise use the default color texture.
	//
	bool gotAllEnvironmentMaps = TRUE;
	if (colorConnection.type() == ShadingConnection::TEXTURE &&
		colorConnection.texture().hasFn(MFn::kEnvCube))
	{
		// Get the filenames of the texture.
		MFnDependencyNode textureNode(colorConnection.texture());
		MString attributeName;
		MString envNames[6] = { "top", "bottom", "left", "right", "front", "back" };

		// Scan for connected file textures to the environment map node
		//
		for (int i=0; i<6; i++)
		{
			ShadingConnection conn(colorConnection.texture(), request.multiPath().partialPathName(), 
							envNames[i]);

			if (conn.type() == ShadingConnection::TEXTURE &&
				conn.texture().hasFn(MFn::kFileTexture))
			{
				MFnDependencyNode envNode(conn.texture());
				MPlug filenamePlug( conn.texture(), envNode.attribute(MString("fileTextureName")) );

				filenamePlug.getValue(decalName);

				if (decalName.length() == 0)	decalName = "internalDefaultTexture";

				// Append next environment map name
				decalNames.append( decalName );
			}

			// If any of the environment maps are not mapped put in a fake texture
			else
			{
				decalName = "internalDefaultTexture";
				decalNames.append( decalName );
			}
		}
	}
	else
	{
		// Put in a fake texture for each side
		decalName = "internalDefaultTexture";
		for (int i=0; i<6; i++)
		{
			decalNames.append( decalName );
		}
	}

	// Reload cube maps if the name of the textures
	// for any of the cube maps changes
	//
	bool reload = FALSE;
	for (int i=0; i<6; i++)
	{
		if (currentTextureNames[i] != decalNames[i])
		{
			reload = TRUE;
			break;
		}
	}

	view.beginGL();
	{
		if ( reload )
		{
			MString	ypTexName(decalNames[0]);	// y+ == top
			MString	ynTexName(decalNames[1]);	// y- == bottom
			MString	xpTexName(decalNames[2]);	// x+ == left
			MString	xnTexName(decalNames[3]);	// x- == right
			MString	zpTexName(decalNames[4]);	// z+ == front
			MString	znTexName(decalNames[5]);	// z- == back

			MStatus stat;
			if (! (stat = theImage_XP.readFromFile(xpTexName)) )	return MS::kFailure;
			if (! (stat = theImage_XN.readFromFile(xnTexName)) )	return MS::kFailure;
			if (! (stat = theImage_YP.readFromFile(ypTexName)) )	return MS::kFailure;
			if (! (stat = theImage_YN.readFromFile(ynTexName)) )	return MS::kFailure;
			if (! (stat = theImage_ZP.readFromFile(zpTexName)) )	return MS::kFailure;
			if (! (stat = theImage_ZN.readFromFile(znTexName)) )	return MS::kFailure;

			// Only create texture names the first time
			if (fTextureName == -1) 	glGenTextures(1, &fTextureName);

			glBindTexture( GL_TEXTURE_CUBE_MAP_ARB, fTextureName );
			glEnable( GL_TEXTURE_CUBE_MAP_ARB );

			// The cubeMap textures have to have the same size
			//
			unsigned int width, height;
			stat = theImage_XP.getSize( width, height );

			glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,
				0, GL_RGBA8, width,	height, 0, GL_RGBA,	GL_UNSIGNED_BYTE, theImage_XP.pixels() );
			glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB,
				0, GL_RGBA8, width,	height,	0, GL_RGBA,	GL_UNSIGNED_BYTE, theImage_XN.pixels() );
			glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,
				0, GL_RGBA8, width,	height,	0, GL_RGBA,	GL_UNSIGNED_BYTE, theImage_YP.pixels() );
			glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,
				0, GL_RGBA8, width,	height,	0, GL_RGBA,	GL_UNSIGNED_BYTE, theImage_YN.pixels() );
			glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,
				0, GL_RGBA8, width,	height,	0, GL_RGBA,	GL_UNSIGNED_BYTE, theImage_ZP.pixels() );
			glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB,
				0, GL_RGBA8, width,	height,	0, GL_RGBA,	GL_UNSIGNED_BYTE, theImage_ZN.pixels() );

			glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
			glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
			glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
			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);

			for (i=0; i<6; i++)		currentTextureNames[i] = decalNames[i];
		}

		// stage 0 -- cubeMap texture for the refraction
		//
		glActiveTextureARB( GL_TEXTURE0_ARB );
		glBindTexture( GL_TEXTURE_CUBE_MAP_ARB, fTextureName );
		glEnable( GL_TEXTURE_CUBE_MAP_ARB );

		// stage 1 -- cubeMap texture for the reflection
		//
		glActiveTextureARB( GL_TEXTURE1_ARB );
		glBindTexture( GL_TEXTURE_CUBE_MAP_ARB, fTextureName );
		glEnable( GL_TEXTURE_CUBE_MAP_ARB );
	}
	view.endGL();

	return MS::kSuccess;
}
Beispiel #3
0
/* virtual */
MStatus	hwUnlitShader::bind(const MDrawRequest& request,
							M3dView& view)
{
	MStatus status;

	// white, opaque.
	float bgColor[4] = {1,1,1,1};

	// Get path of current object in draw request
	currentObjectPath = request.multiPath();
	MString currentPathName( currentObjectPath.partialPathName() );

	updateTransparencyFlags(currentPathName);

	// Get decal texture name
	MString decalName = "";
	ShadingConnection colorConnection(thisMObject(), currentPathName, "color");

	// If the color attribute is ultimately connected to a file texture, find its filename.
	// otherwise use the default color texture.
	if (colorConnection.type() == ShadingConnection::TEXTURE &&
		colorConnection.texture().hasFn(MFn::kFileTexture))
	{
		// Get the filename of the texture.
		MFnDependencyNode textureNode(colorConnection.texture());
		MPlug filenamePlug( colorConnection.texture(), textureNode.attribute(MString("fileTextureName")) );
		filenamePlug.getValue(decalName);
		if (decalName == "")
			getFloat3(color, bgColor);
	}
	else
	{
		decalName = "";
		getFloat3(color, bgColor);
	}
	
	assert(glGetError() == GL_NO_ERROR);

	view.beginGL();

	glPushAttrib( GL_ALL_ATTRIB_BITS );
	glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);

	// Set the standard OpenGL blending mode.
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	
	// Change the constant alpha value. 
	float alpha = 1.0f - fConstantTransparency;

	// Set a color (with alpha). This color will be used directly if
	// the shader is not textured. Otherwise, the texture will get modulated
	// by the alpha.
	glColor4f(bgColor[0], bgColor[1], bgColor[2], alpha);


	// If the shader is textured...
	if (decalName.length() != 0)
	{
		// Enable 2D texturing.
		glEnable(GL_TEXTURE_2D);

		assert(glGetError() == GL_NO_ERROR);

		// Bind the 2D texture through the texture cache. The cache will keep
		// the texture around, so that it will only be loaded in video
		// memory once. In this example, the third parameter (mipmapping) is
		// false, so no mipmaps are generated. Note that mipmaps only work if
		// the texture has even dimensions.

		if(m_pTextureCache)
			m_pTextureCache->bind(colorConnection.texture(), MTexture::RGBA, false);	
		
		// Set minification and magnification filtering to linear interpolation.
		// For better quality, you could enable mipmapping while binding and
		// use GL_MIPMAP_LINEAR_MIPMAP in for minification filtering.
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
	}

	// Disable lighting.
	glDisable(GL_LIGHTING);

	view.endGL();

	return MS::kSuccess;
}
Beispiel #4
0
/* virtual */
MStatus	pnTriangles::bind(const MDrawRequest& request, M3dView& view)
//
// Description:
//		This bind demonstrates the usage of internal material
//		and texture properties. This shader must be connected
//		to the "hardwareShader" attribute of a lambert derived
//		shader.
//
{
	// Setup the view
	view.beginGL();
	glPushAttrib( GL_ALL_ATTRIB_BITS );
	glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);

	MColor diffuse(1.0F, 1.0F, 0.0F, 1.0F);
	MColor specular(1.0F, 1.0F, 1.0F, 1.0F);
	MColor emission(0.0F, 0.0F, 0.0F, 1.0F);
	MColor ambient(0.2F, 0.2F, 0.2F, 1.0F);

	// Get the diffuse and specular colors
	//
	float shininess;
	bool hasTransparency = false;

	MMaterial material = request.material();
	fInTexturedMode = material.materialIsTextured();

	// Setting this to true will get the default "green" material back
	// since it will try and evaluate this shader, which internally
	// Maya does not understand -> thus giving the "green" material back
	bool useInternalMaterialSetting = false;
	
	if (!useInternalMaterialSetting)
	{
		material.getEmission( emission );
		material.getSpecular( specular );
		shininess = 13.0;
	}
	material.getHasTransparency( hasTransparency );	

	if (!fInTexturedMode)
	{
		if (!fTestVertexProgram && !useInternalMaterialSetting)
			material.getDiffuse( diffuse );
	}
	// In textured mode. Diffuse material is always white
	// for texture blends
	else
	{
		if (!useInternalMaterialSetting)
			diffuse.r = diffuse.g = diffuse.b = diffuse.a = 1.0;
	}

	// Use a vertex program to set up shading
	//
	if (fTestVertexProgram)
	{
		bindVertexProgram(diffuse, specular, emission, ambient);
	}
	else if (fTestFragmentProgram)
	{
		bindFragmentProgram();
	}

	// Don't use a vertex program to set up shading
	//
	else
	{
		// Set up the material state
		//
		glEnable(GL_COLOR_MATERIAL);
		glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
		glColor4fv(&ambient.r);

		if (fInTexturedMode)
		{
			glEnable( GL_TEXTURE_2D );
			MDrawData drawData = request.drawData();
			material.applyTexture( view, drawData );

			float scaleS, scaleT, translateS, translateT, rotate;

			material.getTextureTransformation(scaleS, scaleT, translateS,
											  translateT, rotate);

			rotate = DEG_TO_RAD(-rotate);
			float c = cosf(rotate);
			float s = sinf(rotate);
			translateS += ((c+s)/2.0F);
			translateT += ((c-s)/2.0F);

			glMatrixMode(GL_TEXTURE);
			glPushMatrix();
			glLoadIdentity();

			if(scaleS != 1.0f || scaleT != 1.0f)
				glScalef(1.0f/scaleS, 1.0f/scaleT, 1.0f);
			if(translateS != 0.0f || translateT != 0.0f)
				glTranslatef(0.5f-translateS, 0.5f-translateT, 0.0f);
			else
				glTranslatef(0.5f, 0.5f, 0.0f);

			if(rotate != 0.0f)
				glRotatef(-rotate, 0.0f, 0.0f, 1.0f);

			glMatrixMode(GL_MODELVIEW);
		}

		if (!useInternalMaterialSetting)
		{
			glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
			glColor4fv(&diffuse.r);
			glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
			glColor4fv(&specular.r);
			glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
			glColor4fv(&emission.r);
			glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess);
		}
		else
		{
			const MDagPath dagPath =  request.multiPath();
			material.evaluateMaterial( view, dagPath );
			material.setMaterial(dagPath, hasTransparency);
		}
	}

	// Do PN triangles in hardware, or do nothing
	// if LOD = 0
	if (fExtensionSupported[kPNTriangesEXT] || (fSubdivisions == 0))
	{
		if (fSubdivisions != 0)
		{
			glEnable( GL_PN_TRIANGLES_ATI );

			// Set point mode
			//
			if (fPointMode == kPointLinear)
				glPNTrianglesiATI( GL_PN_TRIANGLES_POINT_MODE_ATI, 
								   GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI);
			else
				glPNTrianglesiATI( GL_PN_TRIANGLES_POINT_MODE_ATI, 
								   GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI);

			// Set normal mode
			//
			if (fNormalMode == kNormalLinear)
				glPNTrianglesiATI( GL_PN_TRIANGLES_NORMAL_MODE_ATI, 
								   GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI);
			else
				glPNTrianglesiATI( GL_PN_TRIANGLES_NORMAL_MODE_ATI, 
								   GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI);

			// Set tessellation level
			//
			glPNTrianglesiATI( GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI,
							  fSubdivisions );
		}
	}

	view.endGL();

	return MS::kSuccess;
}
/* virtual */
MStatus	hwDecalBumpShader_NV20::bind(const MDrawRequest& request, M3dView& view)
{
	MStatus status;

	// Get the diffuse color
	//
	float diffuse_color[4];
	status = getFloat3(color, diffuse_color);
	diffuse_color[3] = 1.0;
	if (!status)
        return status;

	// Get the light color
	//
	float light_color[4];
	light_color[3] = 1.0f;
	status = getFloat3(lightColor, light_color);
	if (!status)
        return status;

	// Get the light direction (for directionalLight)
	//
	status = getFloat3(light, &lightRotation[0]);
	if (!status)
        return status;

	// Get the bumpScale value
	//
	float	bumpScaleValue = 2.0f;

	// Get the bumpMap type
	//
	bool	isHeightFieldMap = true;


	// Direction of the directional light
	//
	// Convert the light direction (which is assumed in originally be in world space, in euler coordinates) 
	// into an eye space vector.
	//
	double	scale = M_PI/180.0;		// Internal rotations are in radian and not in degrees
	MEulerRotation	lightRot( lightRotation[0] * scale, lightRotation[1] * scale, lightRotation[2] * scale );
	MVector	light_v = MVector(0, 0, -1).rotateBy( lightRot );	// WS light vector

	MDagPath camDag;
	view.getCamera(camDag);

	light_v = light_v * camDag.inclusiveMatrixInverse();
	lightRotation[0] = (float) light_v[0];
	lightRotation[1] = (float) light_v[1];
	lightRotation[2] = (float) light_v[2];


	// Get the camera position
	//
	status = getFloat3(camera, &cameraPos[0]);
	if (!status)
        return status;

	// Get the decal and bump map file names
	//
	MString decalName = "";
	MString bumpName  = "";

	ShadingConnection colorConnection(thisMObject(), request.multiPath().partialPathName(), "color");
	ShadingConnection bumpConnection (thisMObject(), request.multiPath().partialPathName(), "bump");

	// If the color attribute is ultimately connected to a file texture, find its filename.
	// otherwise use the default color texture.
	if (colorConnection.type() == ShadingConnection::TEXTURE &&
		colorConnection.texture().hasFn(MFn::kFileTexture))
	{
		// Get the filename of the texture.
		MFnDependencyNode textureNode(colorConnection.texture());
		MPlug filenamePlug( colorConnection.texture(), textureNode.attribute(MString("fileTextureName")) );
		filenamePlug.getValue(decalName);
	}

	// If the bump attribute is ultimately connected to a file texture, find its filename.
	// otherwise use the default bump texture.
	if (bumpConnection.type() == ShadingConnection::TEXTURE &&
		bumpConnection.texture().hasFn(MFn::kFileTexture))
	{
		// Get the filename of the texture.
		MFnDependencyNode textureNode(colorConnection.texture());
		MPlug filenamePlug( bumpConnection.texture(), textureNode.attribute(MString("fileTextureName")) );
		filenamePlug.getValue(bumpName);
	}

	// Fail safe quit
	//
	if (bumpName.length() == 0 ||
		decalName.length() == 0)
	{
		view.beginGL();
		glPushAttrib( GL_ALL_ATTRIB_BITS );		// This might be too conservative
		glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
		glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
		glEnable(GL_COLOR_MATERIAL);
		glColor4fv(diffuse_color);
		view.endGL();
		return MS::kSuccess;
	}

	view.beginGL();

	glPushAttrib( GL_ALL_ATTRIB_BITS );
	glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);

    /* Starts Here... */
	glEnable(GL_TEXTURE_SHADER_NV);
	
	// stage 0 -- decal map
	glActiveTextureARB( GL_TEXTURE0_ARB );
	if(m_pTextureCache)
		m_pTextureCache->bind(colorConnection.texture(), MTexture::RGBA, false);
	glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
	
    // stage 1 -- bumpped normal map
	glActiveTextureARB( GL_TEXTURE1_ARB );
	// We need to be able to pass the bumpScaleValue
	// to the texture cache and rebuild the bump or normal map
	if( isHeightFieldMap ) {
		// convert the HeightField to the NormalMap
		if(m_pTextureCache)
			m_pTextureCache->bind(bumpConnection.texture(), MTexture::NMAP, false);
	}
	else {
		if(m_pTextureCache)
			m_pTextureCache->bind(bumpConnection.texture(), MTexture::RGBA, false);
	}
   	glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
	
	// stage 2 -- dot product (diffuse component)
	glActiveTextureARB( GL_TEXTURE2_ARB );
	glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_DOT_PRODUCT_NV);
	glTexEnvi(GL_TEXTURE_SHADER_NV, GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV, GL_EXPAND_NORMAL_NV);
	glTexEnvi(GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE1_ARB);

	// stage 3 -- dot product (specular component)
	glActiveTextureARB( GL_TEXTURE3_ARB );
	bind_lookup_table();	// 2D texture to get the diffuse and specular illumination
	glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_DOT_PRODUCT_TEXTURE_2D_NV);
	glTexEnvi(GL_TEXTURE_SHADER_NV, GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV, GL_EXPAND_NORMAL_NV);
	glTexEnvi(GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE1_ARB);
	
	// With light color and intensity
	//
	glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, diffuse_color);
	glCombinerParameterfvNV(GL_CONSTANT_COLOR1_NV, light_color);

	// The register combiner will do the multiplication between
	// the illumination and the decal color
	//
	glEnable(GL_REGISTER_COMBINERS_NV);

	
#ifndef DEBUGGING_VERTEX_PROGRAM
	glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, 2);
#else
	// For testing, only use one general register combiner.
	glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, 1);
#endif

	float constColor0[4];
	constColor0[0] = constColor0[1] = constColor0[2] = constColor0[3] = 1.0;
	glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, constColor0);

#ifndef DEBUGGING_VERTEX_PROGRAM
	// Combiner stage 0 does the illumination modulation on the surface decal color
	//
	glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_A_NV, GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
	glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_B_NV, GL_TEXTURE3_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
	glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_C_NV, GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
	glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_D_NV, GL_TEXTURE3_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);

	glCombinerOutputNV(GL_COMBINER0_NV, GL_RGB, GL_DISCARD_NV, GL_DISCARD_NV, GL_SPARE1_NV, 
					   GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE);

	// Combiner stage 1, modulate the surface color by the light color
	//
	glCombinerInputNV(GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_A_NV, GL_SPARE1_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
	glCombinerInputNV(GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_B_NV, GL_CONSTANT_COLOR1_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);

	glCombinerOutputNV(GL_COMBINER1_NV, GL_RGB, GL_DISCARD_NV, GL_DISCARD_NV, GL_SPARE1_NV, 
					   GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE);
#else
	// Simplified register combiners to help debugging vertex program.
	glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_A_NV, GL_PRIMARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
	glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_B_NV, GL_CONSTANT_COLOR0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
	glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_C_NV, GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
	glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_D_NV, GL_TEXTURE3_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);

	glCombinerOutputNV(GL_COMBINER0_NV, GL_RGB, GL_SPARE1_NV, GL_DISCARD_NV, GL_DISCARD_NV, 
					   GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE);
#endif // DEBUGGING_VERTEX_PROGRAM

	// The final Combiner just pass through
	//
	glFinalCombinerInputNV(GL_VARIABLE_A_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
	glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
	glFinalCombinerInputNV(GL_VARIABLE_C_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
	glFinalCombinerInputNV(GL_VARIABLE_D_NV, GL_SPARE1_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);

	view.endGL();

	return MS::kSuccess;
}