- Main Page
- Related Pages
- Modules
- Classes
- Examples

# lightShader.cpp

    //-
    // ==========================================================================
    // Copyright 1995,2006,2008 Autodesk, Inc. All rights reserved.
    //
    // Use of this software is subject to the terms of the Autodesk
    // license agreement provided at the time of installation or download,
    // or which otherwise accompanies this software in either electronic
    // or hard copy form.
    // ==========================================================================
    //+

    #include <math.h>

    #include <maya/MPxNode.h>
    #include <maya/MIOStream.h>
    #include <maya/MString.h>
    #include <maya/MTypeId.h>
    #include <maya/MPlug.h>
    #include <maya/MDataBlock.h>
    #include <maya/MDataHandle.h>
    #include <maya/MFnNumericAttribute.h>
    #include <maya/MFnLightDataAttribute.h>
    #include <maya/MFloatVector.h>
    #include <maya/MFnPlugin.h>

    //
    // DESCRIPTION:
    class LightNode : public MPxNode
    {
        public:
                          LightNode();
        virtual           ~LightNode();

        virtual MStatus   compute( const MPlug&, MDataBlock& );
        virtual void      postConstructor();

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

        static MTypeId    id;

        private
    :
        // Inputs
        static MObject  aColor;
        static MObject  aPosition;
        static MObject  aInputDirection;
        static MObject  aInputAmbient;
        static MObject  aInputDiffuse;
        static MObject  aInputSpecular;
        static MObject  aIntensity;

    // Outputs
        static MObject  aLightDirection;
        static MObject  aLightIntensity;
        static MObject  aLightAmbient;
        static MObject  aLightDiffuse;
        static MObject  aLightSpecular;
        static MObject  aLightShadowFraction;
        static MObject  aPreShadowIntensity;
        static MObject  aLightBlindData;
        static MObject  aLightData;
    };

    MTypeId LightNode::id( 0x81010 );

    MObject  LightNode::aColor;
    MObject  LightNode::aPosition;
    MObject  LightNode::aInputDirection;
    MObject  LightNode::aInputAmbient;
    MObject  LightNode::aInputDiffuse;
    MObject  LightNode::aInputSpecular;
    MObject  LightNode::aIntensity;

    MObject  LightNode::aLightData;
    MObject  LightNode::aLightDirection;
    MObject  LightNode::aLightIntensity;
    MObject  LightNode::aLightAmbient;
    MObject  LightNode::aLightDiffuse;
    MObject  LightNode::aLightSpecular;
    MObject  LightNode::aLightShadowFraction;
    MObject  LightNode::aPreShadowIntensity;
    MObject  LightNode::aLightBlindData;

    void LightNode::postConstructor( )
    {
        setMPSafe(true);
    }

    //
    // DESCRIPTION:
    LightNode::LightNode()
    {
    }

    //
    // DESCRIPTION:
    LightNode::~LightNode()
    {
    }

    //
    // DESCRIPTION:
    void * LightNode::creator()
    {
        return new LightNode();
    }

    //
    // DESCRIPTION:
    MStatus LightNode::initialize()
    {
        MFnNumericAttribute nAttr;
        MFnLightDataAttribute lAttr;

        aColor = nAttr.createColor( "color", "c" );
        CHECK_MSTATUS ( nAttr.setKeyable(true) );
        CHECK_MSTATUS ( nAttr.setStorable(true) );
        CHECK_MSTATUS ( nAttr.setDefault(0.0f, 0.58824f, 0.644f) );

        aPosition = nAttr.createPoint( "position", "pos" );
        CHECK_MSTATUS ( nAttr.setKeyable(true) );
        CHECK_MSTATUS ( nAttr.setStorable(true) );

        aInputDirection = nAttr.createPoint( "inputDirection", "id" );
        CHECK_MSTATUS ( nAttr.setKeyable(true) );
        CHECK_MSTATUS ( nAttr.setStorable(true) );
        CHECK_MSTATUS ( nAttr.setDefault(-1.0f, 0.0f, 0.0f) );

        aInputAmbient = nAttr.create( "ambientOn", "an", MFnNumericData::kBoolean);
        CHECK_MSTATUS ( nAttr.setKeyable(true) );
        CHECK_MSTATUS ( nAttr.setStorable(true) );
        CHECK_MSTATUS ( nAttr.setHidden(false) );
        CHECK_MSTATUS ( nAttr.setDefault(true) );

        aInputDiffuse = nAttr.create( "diffuseOn", "dn", MFnNumericData::kBoolean);
        CHECK_MSTATUS ( nAttr.setKeyable(true) );
        CHECK_MSTATUS ( nAttr.setStorable(true) );
        CHECK_MSTATUS ( nAttr.setHidden(false) );
        CHECK_MSTATUS ( nAttr.setDefault(true) );

        aInputSpecular = nAttr.create( "specularOn", "sn", MFnNumericData::kBoolean);
        CHECK_MSTATUS ( nAttr.setKeyable(true) );
        CHECK_MSTATUS ( nAttr.setStorable(true) );
        CHECK_MSTATUS ( nAttr.setHidden(false) );
        CHECK_MSTATUS ( nAttr.setDefault(true) );

        aIntensity = nAttr.create( "intensity", "i", MFnNumericData::kFloat);
        CHECK_MSTATUS ( nAttr.setKeyable(true) );
        CHECK_MSTATUS ( nAttr.setStorable(true) );
        CHECK_MSTATUS ( nAttr.setHidden(false) );
        CHECK_MSTATUS ( nAttr.setDefault(1.0f) );

    // Outputs

        aLightDirection = nAttr.createPoint( "lightDirection", "ld" );
        CHECK_MSTATUS ( nAttr.setStorable(false) );
        CHECK_MSTATUS ( nAttr.setHidden(true) );
        CHECK_MSTATUS ( nAttr.setReadable(true) );
        CHECK_MSTATUS ( nAttr.setWritable(false) );
        CHECK_MSTATUS ( nAttr.setDefault(-1.0f, 0.0f, 0.0f) );

        aLightIntensity = nAttr.createColor( "lightIntensity", "li" );
        CHECK_MSTATUS ( nAttr.setStorable(false) );
        CHECK_MSTATUS ( nAttr.setHidden(true) );
        CHECK_MSTATUS ( nAttr.setReadable(true) );
        CHECK_MSTATUS ( nAttr.setWritable(false) );
        CHECK_MSTATUS ( nAttr.setDefault(1.0f, 0.5f, 0.2f) );

        aLightAmbient = nAttr.create( "lightAmbient", "la",
                                      MFnNumericData::kBoolean);
        CHECK_MSTATUS ( nAttr.setStorable(false) );
        CHECK_MSTATUS ( nAttr.setHidden(true) );
        CHECK_MSTATUS ( nAttr.setReadable(true) );
        CHECK_MSTATUS ( nAttr.setWritable(false) );
        nAttr.setDefault(true);

        aLightDiffuse = nAttr.create( "lightDiffuse", "ldf",
                                      MFnNumericData::kBoolean);
        CHECK_MSTATUS ( nAttr.setStorable(false) );
        CHECK_MSTATUS ( nAttr.setHidden(true) );
        CHECK_MSTATUS ( nAttr.setReadable(true) );
        CHECK_MSTATUS ( nAttr.setWritable(false) );
        CHECK_MSTATUS ( nAttr.setDefault(true) );

        aLightSpecular = nAttr.create( "lightSpecular", "ls",
                                       MFnNumericData::kBoolean);
        CHECK_MSTATUS ( nAttr.setStorable(false) );
        CHECK_MSTATUS ( nAttr.setHidden(true) );
        CHECK_MSTATUS ( nAttr.setReadable(true) );
        CHECK_MSTATUS ( nAttr.setWritable(false) );
        CHECK_MSTATUS ( nAttr.setDefault(true) );

        aLightShadowFraction = nAttr.create("lightShadowFraction","lsf",
                                            MFnNumericData::kFloat);
        CHECK_MSTATUS ( nAttr.setStorable(false) );
        CHECK_MSTATUS ( nAttr.setHidden(true) );
        CHECK_MSTATUS ( nAttr.setReadable(true) );
        CHECK_MSTATUS ( nAttr.setWritable(false) );
        CHECK_MSTATUS ( nAttr.setDefault(0.0f) );

        aPreShadowIntensity = nAttr.create("preShadowIntensity","psi",
                                           MFnNumericData::kFloat);
        CHECK_MSTATUS ( nAttr.setStorable(false) );
        CHECK_MSTATUS ( nAttr.setHidden(true) );
        CHECK_MSTATUS ( nAttr.setReadable(true) );
        CHECK_MSTATUS ( nAttr.setWritable(false) );
        CHECK_MSTATUS ( nAttr.setDefault(0.0f) );

        aLightBlindData = nAttr.createAddr("lightBlindData","lbld");
        CHECK_MSTATUS ( nAttr.setStorable(false) );
        CHECK_MSTATUS ( nAttr.setHidden(true) );
        CHECK_MSTATUS ( nAttr.setReadable(true) );
        CHECK_MSTATUS ( nAttr.setWritable(false) );

        aLightData = lAttr.create( "lightData", "ltd",
                                   aLightDirection, aLightIntensity,
                                   aLightAmbient,
                                   aLightDiffuse, aLightSpecular,
                                   aLightShadowFraction,
                                   aPreShadowIntensity, aLightBlindData);
        CHECK_MSTATUS ( nAttr.setReadable(true) );
        CHECK_MSTATUS ( nAttr.setWritable(false) );
        CHECK_MSTATUS ( lAttr.setStorable(false) );
        CHECK_MSTATUS ( lAttr.setHidden(true) );
        lAttr.setDefault(-1.0f, 0.0f, 0.0f, 1.0f, 0.5f, 0.2f, true, true,
                         true, 0.0f, 1.0f, NULL);

        CHECK_MSTATUS ( addAttribute(aColor) );
        CHECK_MSTATUS ( addAttribute(aPosition) );
        CHECK_MSTATUS ( addAttribute(aInputDirection) );
        CHECK_MSTATUS ( addAttribute(aInputAmbient) );
        CHECK_MSTATUS ( addAttribute(aInputDiffuse) );
        CHECK_MSTATUS ( addAttribute(aInputSpecular) );
        CHECK_MSTATUS ( addAttribute(aIntensity) );

        CHECK_MSTATUS ( addAttribute(aLightData) );

        CHECK_MSTATUS ( attributeAffects (aLightIntensity, aLightData) );
        CHECK_MSTATUS ( attributeAffects (aLightDirection, aLightData) );
        CHECK_MSTATUS ( attributeAffects (aLightAmbient, aLightData) );
        CHECK_MSTATUS ( attributeAffects (aLightDiffuse, aLightData) );
        CHECK_MSTATUS ( attributeAffects (aLightSpecular, aLightData) );
        CHECK_MSTATUS ( attributeAffects (aLightShadowFraction, aLightData) );
        CHECK_MSTATUS ( attributeAffects (aPreShadowIntensity, aLightData) );
        CHECK_MSTATUS ( attributeAffects (aLightBlindData, aLightData) );
        CHECK_MSTATUS ( attributeAffects (aLightData, aLightData) );

        CHECK_MSTATUS ( attributeAffects (aColor, aLightData) );
        CHECK_MSTATUS ( attributeAffects (aPosition, aLightData) );
        CHECK_MSTATUS ( attributeAffects (aInputDirection, aLightData) );
        CHECK_MSTATUS ( attributeAffects (aInputAmbient, aLightData) );
        CHECK_MSTATUS ( attributeAffects (aInputDiffuse, aLightData) );
        CHECK_MSTATUS ( attributeAffects (aInputSpecular, aLightData) );
        CHECK_MSTATUS ( attributeAffects (aIntensity, aLightData) );

        return MS::kSuccess;
    }

    //
    // DESCRIPTION:
    MStatus LightNode::compute(
    const MPlug&      plug,
          MDataBlock& block )
    {
        if ((plug != aLightData) && (plug.parent() != aLightData))
            return MS::kUnknownParameter;

        MFloatVector resultColor;

        // Real user input
        MFloatVector& LColor  = block.inputValue( aColor ).asFloatVector();
        // MFloatVector& Position  = block.inputValue( aPosition ).asFloatVector();
        float LIntensity  = block.inputValue( aIntensity ).asFloat();

        // Components to build LightData
        MFloatVector& LDirection  = block.inputValue( aInputDirection ).asFloatVector();
        bool  LAmbient  = block.inputValue( aInputAmbient ).asBool();
        bool  LDiffuse  = block.inputValue( aInputDiffuse ).asBool();
        bool  LSpecular = block.inputValue( aInputSpecular ).asBool();

    // float LShadowF = block.inputValue( aLightShadowFraction ).asFloat();

        resultColor = LColor * LIntensity;

        // set ouput color attribute
        MDataHandle outLightDataHandle = block.outputValue( aLightData );

        MFloatVector& outIntensity = outLightDataHandle.child(aLightIntensity).asFloatVector();
        outIntensity = resultColor;

        MFloatVector& outDirection = outLightDataHandle.child(aLightDirection).asFloatVector();

        outDirection = LDirection;

        bool& outAmbient = outLightDataHandle.child(aLightAmbient).asBool();
        outAmbient = LAmbient;
        bool& outDiffuse = outLightDataHandle.child(aLightDiffuse).asBool();
        outDiffuse = LDiffuse;
        bool& outSpecular = outLightDataHandle.child(aLightSpecular).asBool();
        outSpecular = LSpecular;

        float& outSFraction = outLightDataHandle.child(aLightShadowFraction).asFloat();
        outSFraction = 1.0f;

        float& outPSIntensity = outLightDataHandle.child(aPreShadowIntensity).asFloat();
        outPSIntensity = (resultColor[0] + resultColor[1] + resultColor[2]) / 3.0f;

        void*& outBlindData = outLightDataHandle.child(aLightBlindData).asAddr();
        outBlindData = NULL;

        outLightDataHandle.setClean();

        return MS::kSuccess;
    }

    //
    // DESCRIPTION:
    MStatus initializePlugin( MObject obj )
    {
       const MString UserClassify( "light" );

       MFnPlugin plugin( obj, PLUGIN_COMPANY, "4.5", "Any");
       CHECK_MSTATUS ( plugin.registerNode( "directLight", LightNode::id,
                             LightNode::creator, LightNode::initialize,
                             MPxNode::kDependNode, &UserClassify ) );

       return MS::kSuccess;
    }

    //
    // DESCRIPTION:
    MStatus uninitializePlugin( MObject obj )
    {
       MFnPlugin plugin( obj );
       CHECK_MSTATUS ( plugin.deregisterNode( LightNode::id ) );

       return MS::kSuccess;
    }