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); }
// Currently, Maya leaves lights in GL when you reduce the number of active lights in // your scene. It fills the GL light space from 0 with the visible lights, so, we simply // need to reset the potentially 'old' state of lights after the last one we know to be // visible. We'll put it all back as we found it though. For the moment, this assumes // Maya is filling GL consecutively, if they stop doing that, we'll need to get the // actual light indexes from the view. Its just a bit quicker to assume this, whilst we can. bool ProceduralHolderUI::cleanupLights( const MDrawRequest &request, M3dView &view, LightingState *s ) const { if( !(request.displayStyle()==M3dView::kFlatShaded || request.displayStyle()==M3dView::kGouraudShaded) ) { return false; } M3dView::LightingMode mode; view.getLightingMode(mode); if (mode == M3dView::kLightDefault) { s->numMayaLights = 1; } else { view.getLightCount( s->numMayaLights ); } int sGlMaxLights = 0; glGetIntegerv( GL_MAX_LIGHTS, &sGlMaxLights ); s->numGlLights = sGlMaxLights; if( s->numMayaLights >= s->numGlLights || s->numGlLights == 0 ) { return false; } unsigned int vectorSize = s->numGlLights - s->numMayaLights; s->diffuses.resize( vectorSize ); s->specs.resize( vectorSize ); s->ambients.resize( vectorSize ); static float s_defaultColor[] = { 0.0, 0.0, 0.0, 1.0 }; GLenum light; unsigned int j = 0; for( unsigned int i = s->numMayaLights; i < s->numGlLights; i++ ) { light = GL_LIGHT0 + i; glGetLightfv( light, GL_DIFFUSE, s->diffuses[j].getValue() ); glLightfv( light, GL_DIFFUSE, s_defaultColor ); glGetLightfv( light, GL_SPECULAR, s->specs[j].getValue() ); glLightfv( light, GL_SPECULAR, s_defaultColor ); glGetLightfv( light, GL_AMBIENT, s->ambients[j].getValue() ); glLightfv( light, GL_AMBIENT, s_defaultColor ); j++; } return true; }
/* override */ void apiSimpleShapeUI::draw( const MDrawRequest & request, M3dView & view ) const // // Description: // // Main (OpenGL) draw routine // // Arguments: // // request - request to be drawn // view - view to draw into // { // Get the token from the draw request. // The token specifies what needs to be drawn. // int token = request.token(); switch( token ) { case kDrawWireframe : case kDrawWireframeOnShaded : case kDrawVertices : drawVertices( request, view ); break; case kDrawSmoothShaded : break; // Not implemented, left as exercise case kDrawFlatShaded : // Not implemented, left as exercise break; } }
void UsdMayaGLBatchRenderer::ShapeRenderer::QueueShapeForDraw( MPxSurfaceShapeUI *shapeUI, MDrawRequest &drawRequest, const RenderParams ¶ms, bool drawShape, MBoundingBox *boxToDraw ) { // VP 1.0 Implementation // // In Viewport 1.0, we can use MDrawData to communicate between the // draw prep and draw call itself. Since the internal data is open // to the client, we choose to use a MUserData object, so that the // internal data will mimic the the VP 2.0 implementation. This // allow for more code reuse. // // The one caveat here is that VP 1.0 does not manage the data allocated // in the MDrawData object, so we must remember to delete the MUserData // object in our Draw call. MUserData* userData; QueueShapeForDraw( userData, params, drawShape, boxToDraw ); MDrawData drawData; shapeUI->getDrawData( userData, drawData ); drawRequest.setDrawData( drawData ); }
void ProceduralHolderUI::setWireFrameColors( MDrawRequest &request, M3dView::DisplayStatus status ) { // yes, this does use magic numbers for the color indices, and // no, i don't know how to get them properly. the quadricShape api // example is just doing this too. switch( status ) { case M3dView::kLead : request.setColor( 18, M3dView::kActiveColors ); break; case M3dView::kActive : request.setColor( 15, M3dView::kActiveColors ); break; case M3dView::kActiveAffected : request.setColor( 8, M3dView::kActiveColors ); break; case M3dView::kHilite : request.setColor( 17, M3dView::kActiveColors ); break; case M3dView::kTemplate : request.setColor( 2, M3dView::kDormantColors ); break; case M3dView::kActiveTemplate : request.setColor( 19, M3dView::kActiveColors ); break; default : // dormant request.setColor( 4, M3dView::kDormantColors ); break; } }
void UsdMayaGLBatchRenderer::Draw( const MDrawRequest& request, M3dView &view ) { // VP 1.0 Implementation // MDrawData drawData = request.drawData(); _BatchDrawUserData* batchData = static_cast<_BatchDrawUserData*>(drawData.geometry()); if( !batchData ) return; MMatrix projectionMat; view.projectionMatrix(projectionMat); MMatrix modelViewMat; view.modelViewMatrix(modelViewMat); if( batchData->_bounds ) { px_vp20Utils::RenderBoundingBox(*(batchData->_bounds), *(batchData->_wireframeColor), modelViewMat, projectionMat); } if( batchData->_drawShape && !_renderQueue.empty() ) { MMatrix viewMat( request.matrix().inverse() * modelViewMat ); unsigned int viewX, viewY, viewWidth, viewHeight; view.viewport(viewX, viewY, viewWidth, viewHeight); GfVec4d viewport(viewX, viewY, viewWidth, viewHeight); // Only the first call to this will do anything... After that the batch // queue is cleared. // _RenderBatches( NULL, viewMat, projectionMat, viewport ); } // Clean up the _BatchDrawUserData! delete batchData; }
void DrawableHolderUI::draw( const MDrawRequest &request, M3dView &view ) const { MDrawData drawData = request.drawData(); DrawableHolder *drawableHolder = (DrawableHolder *)drawData.geometry(); assert( drawableHolder ); IECoreGL::ConstScenePtr s = drawableHolder->scene(); if( !s ) { return; } view.beginGL(); // maya can sometimes leave an error from it's own code, // and we don't want that to confuse us in our drawing code. while( glGetError()!=GL_NO_ERROR ) { } // if we're being drawn as part of a selection operation we need // to make sure there's a name on the name stack, as the IECoreGL::NameStateComponent // expects to be able to load a name into it (it fails with an invalid operation if // there's no name slot to load into). if( view.selectMode() ) { view.pushName( 0 ); } try { // do the main render s->render( m_displayStyle.baseState( request.displayStyle() ) ); // do a wireframe render over the top if we're selected and we just did a solid // draw. bool selected = request.displayStatus()==M3dView::kActive || request.displayStatus()==M3dView::kLead; bool solid = request.displayStyle()==M3dView::kFlatShaded || request.displayStyle()==M3dView::kGouraudShaded; if( selected && solid ) { s->render( m_displayStyle.baseState( M3dView::kWireFrame ) ); } } catch( std::exception &e ) { IECore::msg( IECore::Msg::Error, "DrawableHolderUI::draw", e.what() ); } view.endGL(); }
void ProceduralHolderUI::draw( const MDrawRequest &request, M3dView &view ) const { MStatus s; MDrawData drawData = request.drawData(); ProceduralHolder *proceduralHolder = (ProceduralHolder *)drawData.geometry(); assert( proceduralHolder ); view.beginGL(); LightingState lightingState; bool restoreLightState = cleanupLights( request, view, &lightingState ); // maya can sometimes leave an error from it's own code, // and we don't want that to confuse us in our drawing code. while( glGetError()!=GL_NO_ERROR ) { } try { // draw the bound if asked if( request.token()==BoundDrawMode ) { IECoreGL::BoxPrimitive::renderWireframe( IECore::convert<Imath::Box3f>( proceduralHolder->boundingBox() ) ); } // draw the scene if asked if( request.token()==SceneDrawMode ) { resetHilites(); IECoreGL::ConstScenePtr scene = proceduralHolder->scene(); if( scene ) { IECoreGL::State *displayState = m_displayStyle.baseState( (M3dView::DisplayStyle)request.displayStyle() ); if ( request.component() != MObject::kNullObj ) { MDoubleArray col; s = MGlobal::executeCommand( "colorIndex -q 21", col ); assert( s ); IECoreGL::WireframeColorStateComponentPtr hilite = new IECoreGL::WireframeColorStateComponent( Imath::Color4f( col[0], col[1], col[2], 1.0f ) ); MFnSingleIndexedComponent fnComp( request.component(), &s ); assert( s ); int len = fnComp.elementCount( &s ); assert( s ); for ( int j = 0; j < len; j++ ) { int compId = fnComp.element(j); assert( proceduralHolder->m_componentToGroupMap.find( compId ) != proceduralHolder->m_componentToGroupMap.end() ); hiliteGroups( proceduralHolder->m_componentToGroupMap[compId], hilite, const_cast<IECoreGL::WireframeColorStateComponent *>( displayState->get< IECoreGL::WireframeColorStateComponent >() ) ); } } scene->render( displayState ); } } } catch( const IECoreGL::Exception &e ) { // much better to catch and report this than to let the application die IECore::msg( IECore::Msg::Error, "ProceduralHolderUI::draw", boost::format( "IECoreGL Exception : %s" ) % e.what() ); } if( restoreLightState ) { restoreLights( &lightingState ); } view.endGL(); }
void DrawableHolderUI::getDrawRequests( const MDrawInfo &info, bool objectAndActiveOnly, MDrawRequestQueue &requests ) { // it's easy if noone want to look at us if( !info.objectDisplayStatus( M3dView::kDisplayLocators ) ) { return; } // the node we're meant to be drawing DrawableHolder *drawableHolder = dynamic_cast<DrawableHolder *>( surfaceShape() ); if( !drawableHolder ) { return; } // do we actually want to draw it? MPlug pDraw( drawableHolder->thisMObject(), DrawableHolder::aDraw ); bool draw = true; pDraw.getValue( draw ); if( !draw ) { return; } // draw data encapsulating that node MDrawData drawData; getDrawData( drawableHolder, drawData ); MDrawRequest request = info.getPrototype( *this ); request.setDrawData( drawData ); // set correct drawing colour: switch( info.displayStatus() ) { case M3dView::kLead : request.setColor( 18, M3dView::kActiveColors ); break; case M3dView::kActive : request.setColor( 15, M3dView::kActiveColors ); break; case M3dView::kActiveAffected : request.setColor( 8, M3dView::kActiveColors ); break; case M3dView::kHilite : request.setColor( 17, M3dView::kActiveColors ); break; case M3dView::kTemplate : request.setColor( 2, M3dView::kDormantColors ); break; case M3dView::kActiveTemplate : request.setColor( 19, M3dView::kActiveColors ); break; default : // dormant request.setColor( 4, M3dView::kDormantColors ); break; } requests.add( request ); }
void SceneShapeUI::getDrawRequests( const MDrawInfo &info, bool objectAndActiveOnly, MDrawRequestQueue &requests ) { // it's easy if no one want to look at us if( !info.objectDisplayStatus( M3dView::kDisplayMeshes ) ) { return; } // the node we're meant to be drawing SceneShape *sceneShape = (SceneShape *)surfaceShape(); if( !sceneShape->getSceneInterface() ) { return; } // draw data encapsulating that node MDrawData drawData; getDrawData( sceneShape, drawData ); // a request for the bound if necessary MPlug pDrawBound( sceneShape->thisMObject(), SceneShape::aDrawRootBound ); bool drawBound; pDrawBound.getValue( drawBound ); if( drawBound ) { bool doDrawBound = true; // If objectOnly is true, check for an object. If none found, no need to add the bound request. MPlug pObjectOnly( sceneShape->thisMObject(), SceneShape::aObjectOnly ); bool objectOnly; pObjectOnly.getValue( objectOnly ); if( objectOnly && !sceneShape->getSceneInterface()->hasObject() ) { doDrawBound = false; } if( doDrawBound ) { MDrawRequest request = info.getPrototype( *this ); request.setDrawData( drawData ); request.setToken( BoundDrawMode ); request.setDisplayStyle( M3dView::kWireFrame ); setWireFrameColors( request, info.displayStatus() ); requests.add( request ); } } MPlug pDrawAllBounds( sceneShape->thisMObject(), SceneShape::aDrawChildBounds ); bool drawAllBounds = false; pDrawAllBounds.getValue( drawAllBounds ); // requests for the scene if necessary MPlug pGLPreview( sceneShape->thisMObject(), SceneShape::aDrawGeometry ); bool glPreview; pGLPreview.getValue( glPreview ); if( glPreview || drawAllBounds ) { if( info.displayStyle()==M3dView::kGouraudShaded || info.displayStyle()==M3dView::kFlatShaded ) { // make a request for solid drawing with a material MDrawRequest solidRequest = info.getPrototype( *this ); solidRequest.setDrawData( drawData ); MDagPath path = info.multiPath(); M3dView view = info.view(); MMaterial material = MPxSurfaceShapeUI::material( path ); if( !material.evaluateMaterial( view, path ) ) { MString pathName = path.fullPathName(); IECore::msg( IECore::Msg::Warning, "SceneShapeUI::getDrawRequests", boost::format( "Failed to evaluate material for \"%s\"." ) % pathName.asChar() ); } if( material.materialIsTextured() ) { material.evaluateTexture( drawData ); } solidRequest.setMaterial( material ); // set the transparency request. we don't have a decent way of finding out // if shaders applied by the procedural are transparent, so we've got a transparency // attribute on the procedural holder for users to use. maya materials may also say // they're transparent. if either asks for transparency then we'll ask for it here bool transparent = false; material.getHasTransparency( transparent ); solidRequest.setIsTransparent( transparent ); solidRequest.setToken( SceneDrawMode ); requests.add( solidRequest ); if( info.displayStatus()==M3dView::kActive || info.displayStatus()==M3dView::kLead || info.displayStatus()==M3dView::kHilite ) { MDrawRequest wireRequest = info.getPrototype( *this ); wireRequest.setDrawData( drawData ); wireRequest.setDisplayStyle( M3dView::kWireFrame ); wireRequest.setToken( SceneDrawMode ); setWireFrameColors( wireRequest, info.displayStatus() ); wireRequest.setComponent( MObject::kNullObj ); if ( !objectAndActiveOnly ) { if ( sceneShape->hasActiveComponents() ) { MObjectArray components = sceneShape->activeComponents(); MObject component = components[0]; wireRequest.setComponent( component ); } } requests.add( wireRequest ); } } else { MDrawRequest request = info.getPrototype( *this ); request.setDrawData( drawData ); setWireFrameColors( request, info.displayStatus() ); request.setToken( SceneDrawMode ); request.setComponent( MObject::kNullObj ); if ( !objectAndActiveOnly ) { if ( sceneShape->hasActiveComponents() ) { MObjectArray components = sceneShape->activeComponents(); MObject component = components[0]; request.setComponent( component ); } } requests.add( request ); } } }
void apiSimpleShapeUI::drawVertices( const MDrawRequest & request, M3dView & view ) const // // Description: // // Component (vertex) drawing routine // // Arguments: // // request - request to be drawn // view - view to draw into // { MDrawData data = request.drawData(); MVectorArray * geom = (MVectorArray*)data.geometry(); view.beginGL(); // Query current state so it can be restored // bool lightingWasOn = glIsEnabled( GL_LIGHTING ) ? true : false; if ( lightingWasOn ) { glDisable( GL_LIGHTING ); } float lastPointSize; glGetFloatv( GL_POINT_SIZE, &lastPointSize ); // Set the point size of the vertices // glPointSize( POINT_SIZE ); // If there is a component specified by the draw request // then loop over comp (using an MFnComponent class) and draw the // active vertices, otherwise draw all vertices. // MObject comp = request.component(); if ( ! comp.isNull() ) { MFnSingleIndexedComponent fnComponent( comp ); for ( int i=0; i<fnComponent.elementCount(); i++ ) { int index = fnComponent.element( i ); glBegin( GL_POINTS ); MVector& point = (*geom)[index]; glVertex3f( (float)point[0], (float)point[1], (float)point[2] ); glEnd(); char annotation[32]; sprintf( annotation, "%d", index ); view.drawText( annotation, point ); } } else { for ( unsigned int i=0; i<geom->length(); i++ ) { glBegin( GL_POINTS ); MVector point = (*geom)[ i ]; glVertex3f( (float)point[0], (float)point[1], (float)point[2] ); glEnd(); } } // Restore the state // if ( lightingWasOn ) { glEnable( GL_LIGHTING ); } glPointSize( lastPointSize ); view.endGL(); }
/// \todo We should be firing off a separate drawRequest for the components, then we can be done with the "hiliteGroups" mechanism. void ProceduralHolderUI::getDrawRequests( const MDrawInfo &info, bool objectAndActiveOnly, MDrawRequestQueue &requests ) { // it's easy if noone want to look at us if( !info.objectDisplayStatus( M3dView::kDisplayMeshes ) ) { return; } // the node we're meant to be drawing ProceduralHolder *proceduralHolder = (ProceduralHolder *)surfaceShape(); // draw data encapsulating that node MDrawData drawData; getDrawData( proceduralHolder, drawData ); // a request for the bound if necessary MPlug pDrawBound( proceduralHolder->thisMObject(), ProceduralHolder::aDrawBound ); bool drawBound = true; pDrawBound.getValue( drawBound ); if( drawBound ) { MDrawRequest request = info.getPrototype( *this ); request.setDrawData( drawData ); request.setToken( BoundDrawMode ); request.setDisplayStyle( M3dView::kWireFrame ); setWireFrameColors( request, info.displayStatus() ); requests.add( request ); } // requests for the scene if necessary MPlug pGLPreview( proceduralHolder->thisMObject(), ProceduralHolder::aGLPreview ); bool glPreview = false; pGLPreview.getValue( glPreview ); if( glPreview ) { if( info.displayStyle()==M3dView::kGouraudShaded || info.displayStyle()==M3dView::kFlatShaded ) { // make a request for solid drawing with a material MDrawRequest solidRequest = info.getPrototype( *this ); solidRequest.setDrawData( drawData ); MDagPath path = info.multiPath(); M3dView view = info.view(); MMaterial material = MPxSurfaceShapeUI::material( path ); if( !material.evaluateMaterial( view, path ) ) { MString pathName = path.fullPathName(); IECore::msg( IECore::Msg::Warning, "ProceduralHolderUI::getDrawRequests", boost::format( "Failed to evaluate material for \"%s\"." ) % pathName.asChar() ); } if( material.materialIsTextured() ) { material.evaluateTexture( drawData ); } solidRequest.setMaterial( material ); // set the transparency request. we don't have a decent way of finding out // if shaders applied by the procedural are transparent, so we've got a transparency // attribute on the procedural holder for users to use. maya materials may also say // they're transparent. if either asks for transparency then we'll ask for it here bool transparent = false; material.getHasTransparency( transparent ); if( !transparent ) { MPlug pT( proceduralHolder->thisMObject(), ProceduralHolder::aTransparent ); bool transparent = false; pT.getValue( transparent ); } solidRequest.setIsTransparent( transparent ); solidRequest.setToken( SceneDrawMode ); requests.add( solidRequest ); // and add another request for wireframe drawing if we're selected if( info.displayStatus()==M3dView::kActive || info.displayStatus()==M3dView::kLead || info.displayStatus()==M3dView::kHilite ) { MDrawRequest wireRequest = info.getPrototype( *this ); wireRequest.setDrawData( drawData ); wireRequest.setDisplayStyle( M3dView::kWireFrame ); wireRequest.setToken( SceneDrawMode ); setWireFrameColors( wireRequest, info.displayStatus() ); wireRequest.setComponent( MObject::kNullObj ); if ( !objectAndActiveOnly ) { if ( proceduralHolder->hasActiveComponents() ) { MObjectArray components = proceduralHolder->activeComponents(); MObject component = components[0]; // Should filter list wireRequest.setComponent( component ); } } requests.add( wireRequest ); } } else { MDrawRequest request = info.getPrototype( *this ); request.setDrawData( drawData ); setWireFrameColors( request, info.displayStatus() ); request.setToken( SceneDrawMode ); request.setComponent( MObject::kNullObj ); if ( !objectAndActiveOnly ) { if ( proceduralHolder->hasActiveComponents() ) { MObjectArray components = proceduralHolder->activeComponents(); MObject component = components[0]; // Should filter list request.setComponent( component ); } } requests.add( request ); } } }
void SceneShapeUI::draw( const MDrawRequest &request, M3dView &view ) const { MStatus s; MDrawData drawData = request.drawData(); SceneShape *sceneShape = (SceneShape *)drawData.geometry(); assert( sceneShape ); view.beginGL(); M3dView::LightingMode lightingMode; view.getLightingMode( lightingMode ); LightingState lightingState; bool restoreLightState = cleanupLights( request, view, &lightingState ); // maya can sometimes leave an error from it's own code, // and we don't want that to confuse us in our drawing code. while( glGetError()!=GL_NO_ERROR ) { } try { // draw the bound if asked if( request.token()==BoundDrawMode ) { IECoreGL::BoxPrimitive::renderWireframe( IECore::convert<Imath::Box3f>( sceneShape->boundingBox() ) ); } // draw the scene if asked if( request.token()==SceneDrawMode ) { resetHilites(); IECoreGL::ConstScenePtr scene = sceneShape->glScene(); if( scene ) { IECoreGL::State *displayState = m_displayStyle.baseState( (M3dView::DisplayStyle)request.displayStyle(), lightingMode ); if ( request.component() != MObject::kNullObj ) { MDoubleArray col; s = MGlobal::executeCommand( "colorIndex -q 21", col ); assert( s ); IECoreGL::WireframeColorStateComponentPtr hilite = new IECoreGL::WireframeColorStateComponent( Imath::Color4f( col[0], col[1], col[2], 1.0f ) ); MFnSingleIndexedComponent fnComp( request.component(), &s ); assert( s ); int len = fnComp.elementCount( &s ); assert( s ); std::vector<IECore::InternedString> groupNames; for ( int j = 0; j < len; j++ ) { int index = fnComp.element(j); groupNames.push_back( sceneShape->selectionName( index ) ); } // Sort by name to make sure we don't unhilite selected items that are further down the hierarchy std::sort( groupNames.begin(), groupNames.end() ); for ( std::vector<IECore::InternedString>::iterator it = groupNames.begin(); it!= groupNames.end(); ++it) { IECoreGL::GroupPtr group = sceneShape->glGroup( *it ); hiliteGroups( group, hilite, const_cast<IECoreGL::WireframeColorStateComponent *>( displayState->get< IECoreGL::WireframeColorStateComponent >() ) ); } } scene->render( displayState ); } } } catch( const IECoreGL::Exception &e ) { // much better to catch and report this than to let the application die IECore::msg( IECore::Msg::Error, "SceneShapeUI::draw", boost::format( "IECoreGL Exception : %s" ) % e.what() ); } if( restoreLightState ) { restoreLights( &lightingState ); } view.endGL(); }
void BaseShapeUI::draw( const MDrawRequest & request, M3dView & view ) const { if (s_drawData.failure) return; MStatus status; view.beginGL(); if (!s_drawData.initialized) initializeDraw(); BaseShape *shape = (BaseShape *) surfaceShape(); Model::Base base(MFnDagNode(shape->thisMObject()).parent(0, &status)); if (!status) { status.perror("MFnDagNode::parent"); return; } //MDagPath path = request.multiPath(); MMaterial material = request.material(); MColor color, borderColor; if (!(status = material.getDiffuse(color))) { status.perror("MMaterial::getDiffuse"); return; } bool wireframe = (M3dView::DisplayStyle) request.token() == M3dView::kWireFrame; if (wireframe) { glPushAttrib(GL_POLYGON_BIT); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); } glUseProgram(s_drawData.program); switch (request.displayStatus()) { case M3dView::kLead : borderColor = view.colorAtIndex( LEAD_COLOR); //glUniform1f(s_drawData.border_uniform, 1.0f); s_drawData.updateBorderUniform(1.0f); //glUniform3f(s_drawData.borderColor_uniform, borderColor.r, borderColor.g, borderColor.b); s_drawData.updateBorderColorUniform(borderColor.r, borderColor.g, borderColor.b); break; case M3dView::kActive : borderColor = view.colorAtIndex( ACTIVE_COLOR); //glUniform1f(s_drawData.border_uniform, 1.0f); s_drawData.updateBorderUniform(1.0f); //glUniform3f(s_drawData.borderColor_uniform, borderColor.r, borderColor.g, borderColor.b); s_drawData.updateBorderColorUniform(borderColor.r, borderColor.g, borderColor.b); break; case M3dView::kActiveAffected : borderColor = view.colorAtIndex( ACTIVE_AFFECTED_COLOR); //glUniform1f(s_drawData.border_uniform, 0.0f); s_drawData.updateBorderUniform(0.0f); break; case M3dView::kDormant : borderColor = view.colorAtIndex( DORMANT_COLOR, M3dView::kDormantColors); //glUniform1f(s_drawData.border_uniform, 0.0f); s_drawData.updateBorderUniform(0.0f); break; case M3dView::kHilite : borderColor = view.colorAtIndex( HILITE_COLOR); //glUniform1f(s_drawData.border_uniform, 1.0f); s_drawData.updateBorderUniform(1.0f); //glUniform3f(s_drawData.borderColor_uniform, borderColor.r, borderColor.g, borderColor.b); s_drawData.updateBorderColorUniform(borderColor.r, borderColor.g, borderColor.b); break; } //glUniform3f(s_drawData.color_uniform, color.r, color.g, color.b); s_drawData.updateColorUniform(color.r, color.g, color.b); glCallList(s_drawData.display_list); if (wireframe) glPopAttrib(); view.endGL(); }
/* 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 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; }
/* override */ void apiSimpleShapeUI::getDrawRequests( const MDrawInfo & info, bool objectAndActiveOnly, MDrawRequestQueue & queue ) // // Description: // // Add draw requests to the draw queue // // Arguments: // // info - current drawing state // objectsAndActiveOnly - no components if true // queue - queue of draw requests to add to // { // Get the data necessary to draw the shape // MDrawData data; apiSimpleShape* shape = (apiSimpleShape*) surfaceShape(); MVectorArray* geomPtr = shape->getControlPoints(); // This call creates a prototype draw request that we can fill // in and then add to the draw queue. // MDrawRequest request = info.getPrototype( *this ); // Stuff our data into the draw request, it'll be used when the drawing // actually happens getDrawData( geomPtr, data ); request.setDrawData( data ); // Decode the draw info and determine what needs to be drawn // M3dView::DisplayStyle appearance = info.displayStyle(); M3dView::DisplayStatus displayStatus = info.displayStatus(); switch ( appearance ) { case M3dView::kWireFrame : { request.setToken( kDrawWireframe ); M3dView::ColorTable activeColorTable = M3dView::kActiveColors; M3dView::ColorTable dormantColorTable = M3dView::kDormantColors; switch ( displayStatus ) { case M3dView::kLead : request.setColor( LEAD_COLOR, activeColorTable ); break; case M3dView::kActive : request.setColor( ACTIVE_COLOR, activeColorTable ); break; case M3dView::kActiveAffected : request.setColor( ACTIVE_AFFECTED_COLOR, activeColorTable ); break; case M3dView::kDormant : request.setColor( DORMANT_COLOR, dormantColorTable ); break; case M3dView::kHilite : request.setColor( HILITE_COLOR, activeColorTable ); break; default: break; } queue.add( request ); break; } case M3dView::kGouraudShaded : { // Create the smooth shaded draw request // request.setToken( kDrawSmoothShaded ); // Need to get the material info // MDagPath path = info.multiPath(); // path to your dag object M3dView view = info.view();; // view to draw to MMaterial material = MPxSurfaceShapeUI::material( path ); // Evaluate the material and if necessary, the texture. // if ( ! material.evaluateMaterial( view, path ) ) { cerr << "Couldnt evaluate\n"; } bool drawTexture = true; if ( drawTexture && material.materialIsTextured() ) { material.evaluateTexture( data ); } request.setMaterial( material ); // request.setDisplayStyle( appearance ); bool materialTransparent = false; material.getHasTransparency( materialTransparent ); if ( materialTransparent ) { request.setIsTransparent( true ); } queue.add( request ); // create a draw request for wireframe on shaded if // necessary. // if ( (displayStatus == M3dView::kActive) || (displayStatus == M3dView::kLead) || (displayStatus == M3dView::kHilite) ) { MDrawRequest wireRequest = info.getPrototype( *this ); wireRequest.setDrawData( data ); wireRequest.setToken( kDrawWireframeOnShaded ); wireRequest.setDisplayStyle( M3dView::kWireFrame ); M3dView::ColorTable activeColorTable = M3dView::kActiveColors; switch ( displayStatus ) { case M3dView::kLead : wireRequest.setColor( LEAD_COLOR, activeColorTable ); break; case M3dView::kActive : wireRequest.setColor( ACTIVE_COLOR, activeColorTable ); break; case M3dView::kHilite : wireRequest.setColor( HILITE_COLOR, activeColorTable ); break; default : break; } queue.add( wireRequest ); } break; } case M3dView::kFlatShaded : request.setToken( kDrawFlatShaded ); break; default: break; } // Add draw requests for components // if ( !objectAndActiveOnly ) { // Inactive components // if ( (appearance == M3dView::kPoints) || (displayStatus == M3dView::kHilite) ) { MDrawRequest vertexRequest = info.getPrototype( *this ); vertexRequest.setDrawData( data ); vertexRequest.setToken( kDrawVertices ); vertexRequest.setColor( DORMANT_VERTEX_COLOR, M3dView::kActiveColors ); queue.add( vertexRequest ); } // Active components // if ( surfaceShape()->hasActiveComponents() ) { MDrawRequest activeVertexRequest = info.getPrototype( *this ); activeVertexRequest.setDrawData( data ); activeVertexRequest.setToken( kDrawVertices ); activeVertexRequest.setColor( ACTIVE_VERTEX_COLOR, M3dView::kActiveColors ); MObjectArray clist = surfaceShape()->activeComponents(); MObject vertexComponent = clist[0]; // Should filter list activeVertexRequest.setComponent( vertexComponent ); queue.add( activeVertexRequest ); } } }
// 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; }
/* 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; }