Hi Javier,

In the end, the fact that the shader generation code in phong.cpp was trying to access a plug that didn't exist for a blinn material wasn't the cause of the crash (the code is well guarded so it just returns an empty plug). Plus, that plug is never used anyways (the gl_FrontMaterial.shininess is used, and that was set according to my approximation in shader.cpp, so that should be fine). Still, I made the Blinn class anyways so it's a starting point if we ever want to refine it.

What I did to remove the crash (at least until we can find the real cause) is to disable optimization for the function where it crashes.

I also saw that one of the plugs was missing in phong.cpp, and even if it's empty, for completeness I added it.

So find the modified files attached. They all go in src/GLSL, except the CMakeLists.txt which goes into the root.

Thanks in advance,

J-S
--
______________________________________________________
Jean-Sebastien Guay    jean-sebastien.g...@cm-labs.com
                               http://www.cm-labs.com/
                    http://whitestar02.dyndns-web.com/
#    Maya2OSG - A toolkit for exporting Maya scenes to OpenSceneGraph
#    Copyright (C) 2010 Javier Taibo <javier.ta...@gmail.com>
#
#    This file is part of Maya2OSG.
#
#    Maya2OSG is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    Maya2OSG is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with Maya2OSG.  If not, see <http://www.gnu.org/licenses/>.
#

# Thanks to Diego/ScEngMan for some hints on the creation of this CMake script
#
# 
http://area.autodesk.com/forum/autodesk-maya/sdk/build-maya-plug-ins-using-cmake-40a-howto41
# http://crackart.org/wiki/HowTo/CMakeForMaya

CMAKE_MINIMUM_REQUIRED(VERSION 2.6)

PROJECT(Maya2OSG)

list( APPEND CMAKE_MODULE_PATH "${Maya2OSG_SOURCE_DIR}/CMakeModules" )

SET(VERSION_MAJOR 0)
SET(VERSION_MINOR 4)
SET(VERSION_RELEASE 2)
SET(VERSION_PATCH c)

################################################################################
# Platform specific definitions
IF(WIN32)
    IF(MSVC)
        # To enable /MP, parralel build on MSVC
        OPTION(WIN32_USE_MP "Set to OFF to diable /MP." ON)
        MARK_AS_ADVANCED(WIN32_USE_MP)
        IF(WIN32_USE_MP)
            SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
        ENDIF(WIN32_USE_MP)

        # Other MSVC compilation flags
        ADD_DEFINITIONS(-D_SCL_SECURE_NO_WARNINGS)
        ADD_DEFINITIONS(-D_CRT_SECURE_NO_DEPRECATE)

    ENDIF(MSVC)
ENDIF (WIN32)

# Set the Maya version and architecture (default values)
SET(MAYA_VERSION 2011 CACHE STRING "Maya Version")
SET(MAYA_ARCH x64 CACHE STRING "HW Architecture")

IF(WIN32)
        SET( MAYA_USER_DIR $ENV{USERPROFILE}/Documents/maya CACHE PATH "Maya 
user home directory" )
        SET( MAYA_ROOT $ENV{PROGRAMFILES}/Autodesk/Maya${MAYA_VERSION} CACHE 
PATH "Maya installation directory" )
        SET( MAYA_SDK_DEFINITIONS "_AFXDLL;_MBCS;NT_PLUGIN;REQUIRE_IOSTREAM" )
ELSE()
        SET( MAYA_USER_DIR $ENV{HOME}/maya CACHE PATH "Maya user home 
directory" )
        SET( MAYA_ROOT /usr/autodesk/maya${MAYA_VERSION}-${MAYA_ARCH} )
ENDIF()

SET( MAYA_HEADERS_DIR ${MAYA_ROOT}/include )
SET( MAYA_LIBRARY_DIR ${MAYA_ROOT}/lib )
IF (EXISTS $ENV{MAYA_PLUG_IN_PATH})
        SET ( MAYA_PLUGINS_DIR $ENV{MAYA_PLUG_IN_PATH} CACHE PATH "Maya plug-in 
installation directory" )
ELSE ()
        SET( MAYA_PLUGINS_DIR ${MAYA_ROOT}/bin/plug-ins CACHE PATH "Maya 
plug-in installation directory" )
ENDIF ()

FIND_PACKAGE(OpenGL)
include( FindOSGHelper )

# Set all postfixes to nothing so we can compile other versions and they will
# be loaded instead of the release version by Maya.
SET(CMAKE_DEBUG_POSTFIX "")
SET(CMAKE_RELWITHDEBINFO_POSTFIX "")
SET(CMAKE_MINSIZEREL_POSTFIX "")

SET ( LOCAL_WARNING_FLAGS /W3 )
SET ( LOCAL_RTTI_FLAGS /GR )

SET(CMAKE_INSTALL_PREFIX ${MAYA_PLUGINS_DIR})
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)

SET ( TARGET "maya2osg" )

SET ( SOURCE_FILES 
                src/animation.cpp
                src/animation.h
                src/camera.cpp
                src/camera.h
                src/cameraanimation.cpp
                src/cameraanimation.h
                src/common.cpp
                src/common.h
                src/config.cpp
                src/config.h
                src/dagnode.cpp
                src/dagnode.h
                src/directionallight.cpp
                src/directionallight.h
                src/field.cpp
                src/field.h
                src/group.cpp
                src/group.h
                src/importervisitor.cpp
                src/importervisitor.h
                src/lights.cpp
                src/lights.h
                src/maya2osg.cpp
                src/maya2osg.h
                src/mesh.cpp
                src/mesh.h
                src/nparticle.cpp
                src/nparticle.h
                src/osg2maya.cpp
                src/osg2maya.h
                src/osgfiletranslator.cpp
                src/osgfiletranslator.h
                src/osgwrite.cpp
                src/osgwrite.h
                src/particle.cpp
                src/particle.h
                src/pointemitter.cpp
                src/pointemitter.h
                src/pointlight.cpp
                src/pointlight.h
                src/proxymaterials.cpp
                src/proxymaterials.h
                src/shader.cpp
                src/shader.h
                src/shadows.cpp
                src/shadows.h
                src/spotlight.cpp
                src/spotlight.h
                src/texture.cpp
                src/texture.h
                src/transform.cpp
                src/transform.h
                src/utility.h
                src/GLSL/blinn.cpp
                src/GLSL/blinn.h
                src/GLSL/bump2d.cpp
                src/GLSL/bump2d.h
                src/GLSL/bump2normal.cpp
                src/GLSL/bump2normal.h
                src/GLSL/filetexture.cpp
                src/GLSL/filetexture.h
                src/GLSL/flatshader.cpp
                src/GLSL/flatshader.h
                src/GLSL/glslutils.cpp
                src/GLSL/glslutils.h
                src/GLSL/lambert.cpp
                src/GLSL/lambert.h
                src/GLSL/phong.cpp
                src/GLSL/phong.h
                src/GLSL/shadingnetwork.cpp
                src/GLSL/shadingnetwork.h
                src/GLSL/shadingnode.cpp
                src/GLSL/shadingnode.h
                src/GLSL/shadingnodefactory.cpp
                src/GLSL/shadingnodefactory.h
                src/GLSL/surfaceshader.cpp
                src/GLSL/surfaceshader.h
                src/GLSL/texturingconfig.cpp
                src/GLSL/texturingconfig.h
        )

SET( MAYASDK_LIBRARIES "Foundation.lib" "OpenMaya.lib" "OpenMayaAnim.lib" 
"OpenMayaFX.lib" "OpenMayaRender.lib" )

INCLUDE_DIRECTORIES ( ${PUBLIC_INCLUDE_DIRS} ${MAYA_HEADERS_DIR} 
${OPENSCENEGRAPH_INCLUDE_DIRS} ${OPENGL_INCLUDE_DIR})
LINK_DIRECTORIES ( ${PUBLIC_LIBRARY_DIRS} ${MAYA_LIBRARY_DIR} )

ADD_LIBRARY ( ${TARGET} SHARED ${SOURCE_FILES} )
TARGET_LINK_LIBRARIES( ${TARGET} ${MAYASDK_LIBRARIES} 
${OPENSCENEGRAPH_LIBRARIES} ${OPENGL_LIBRARY})

SET_TARGET_PROPERTIES( ${TARGET} PROPERTIES COMPILE_DEFINITIONS 
"${MAYA_SDK_DEFINITIONS}" )
SET_TARGET_PROPERTIES( ${TARGET} PROPERTIES OUTPUT_NAME "maya2osg" )
SET_TARGET_PROPERTIES( ${TARGET} PROPERTIES SUFFIX ".mll" )
SET_TARGET_PROPERTIES( ${TARGET} PROPERTIES CLEAN_DIRECT_OUTPUT 1 )
SET_TARGET_PROPERTIES( ${TARGET} PROPERTIES LINK_FLAGS 
"/export:initializePlugin /export:uninitializePlugin" )

INSTALL( TARGETS ${TARGET} RUNTIME DESTINATION ${MAYA_PLUGINS_DIR} )
INSTALL( DIRECTORY ${CMAKE_SOURCE_DIR}/scripts DESTINATION 
${MAYA_USER_DIR}/${MAYA_VERSION} PATTERN ".svn" EXCLUDE PATTERN "*.mel" )
INSTALL( DIRECTORY ${CMAKE_SOURCE_DIR}/prefs/icons DESTINATION 
${MAYA_USER_DIR}/${MAYA_VERSION}/prefs PATTERN ".svn" EXCLUDE PATTERN "*.bmp" )
INSTALL( DIRECTORY ${CMAKE_SOURCE_DIR}/prefs/shelves DESTINATION 
${MAYA_USER_DIR}/${MAYA_VERSION}/prefs PATTERN ".svn" EXCLUDE PATTERN "*.mel" )
/**
    Maya2OSG - A toolkit for exporting Maya scenes to OpenSceneGraph
    Copyright (C) 2010 Javier Taibo <javier.ta...@gmail.com>

    This file is part of Maya2OSG.

    Maya2OSG is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Maya2OSG is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Maya2OSG.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "blinn.h"
#include "glslutils.h"
#include "shadingnetwork.h"
#include "../common.h"

#include <maya/MFnDependencyNode.h>
#include <maya/MPlug.h>

#define DISCARD_SELF_SHADOWED_BEFORE_BUMP_MAPPING


/**
 *  Constructor
 */
Blinn::Blinn( const MObject &shading_node, ShadingNetwork &shading_network ) :
    SurfaceShader( shading_node, shading_network ) 
{
}


/**
 *  Get the GLSL Codeblock for a plug
 */
ShadingNode::CodeBlock Blinn::getCodeBlock( const std::string &plug_name )
{
    // Build the GLSL code ...
    CodeBlock code_block;

    std::string variable_name;
    MFnDependencyNode dn(_mayaShadingNode);
    std::string maya_blinn_shader_name = dn.name().asChar();
    hygienizeName( maya_blinn_shader_name );

    // Check plug name and avoid duplicating code

    if ( plug_name == "fragmentOutput" ||
         plug_name == "outColor" || 
         plug_name == "outTransparency" ) 
    {
        variable_name = "sn_blinn_" + maya_blinn_shader_name + "_output";
        // Both color and transparency are stored in "color" variable.
        // if it is already declared, we omit all the GLSL code
        if ( !variableIsAvailable(variable_name) ) {

            // Supported Blinn input channels

            // Color (diffuse)
            Plug plug_color = getPlug("color");
            // Transparency
            Plug plug_transparency = getPlug("transparency");
            // Ambient Color
            Plug plug_ambient = getPlug("ambientColor");
            // Incandescence
            Plug plug_incandescence = getPlug("incandescence");
            // Bump map
            Plug plug_normal_camera;
            if ( hasBumpMap() ) {
                plug_normal_camera = getPlug("normalCamera");
            }
            // Diffuse (scalar)
            Plug plug_diffuse = getPlug("diffuse");
            // Eccentricity
            Plug plug_eccentricity = getPlug("eccentricity");
            // Specular Rolloff
            Plug plug_specular_rolloff = getPlug("specularRollOff");
            // Specular Color
            Plug plug_specular_color = getPlug("specularColor");

            // TO-DO ... Reflectivity, Reflected Color

            code_block.declarations = plug_color.codeBlock.declarations +
                                      plug_transparency.codeBlock.declarations +
                                      plug_ambient.codeBlock.declarations +
                                      plug_incandescence.codeBlock.declarations 
+
                                      plug_normal_camera.codeBlock.declarations 
+
                                      plug_diffuse.codeBlock.declarations + 
                                      plug_eccentricity.codeBlock.declarations +
                                      
plug_specular_rolloff.codeBlock.declarations +
                                      
plug_specular_color.codeBlock.declarations;

            code_block.functions = plug_color.codeBlock.functions +
                                   plug_transparency.codeBlock.functions +
                                   plug_ambient.codeBlock.functions +
                                   plug_incandescence.codeBlock.functions +
                                   plug_normal_camera.codeBlock.functions +
                                   plug_diffuse.codeBlock.functions +
                                   plug_eccentricity.codeBlock.functions +
                                   plug_specular_rolloff.codeBlock.functions +
                                   plug_specular_color.codeBlock.functions +
                                   getDirectionalLightFunction() +
                                   getPointLightFunction() +
                                   getSpotLightFunction();

            code_block.computeCode = plug_color.codeBlock.computeCode +
                                     plug_transparency.codeBlock.computeCode +
                                     plug_ambient.codeBlock.computeCode +
                                     plug_incandescence.codeBlock.computeCode +
                                     plug_normal_camera.codeBlock.computeCode +
                                     plug_diffuse.codeBlock.computeCode +
                                     plug_eccentricity.codeBlock.computeCode +
                                     
plug_specular_rolloff.codeBlock.computeCode +
                                     plug_specular_color.codeBlock.computeCode +
"\n" +
            GLSLUtils::backFaceCulling(_shadingNetwork.getStateSet());

            code_block.computeCode +=
"    // Clear the light intensity accumulators\n"
"    vec4 amb  = vec4(0.0);\n"
"    vec4 diff = vec4(0.0);\n"
"   vec4 spec = vec4(0.0);\n"
"\n"
"    // Loop through enabled lights, compute contribution from each\n"
"    int i;\n"
"    for (i = 0; i < NumEnabledLights; i++)\n"
"    {\n"
"        if (gl_LightSource[i].position.w == 0.0) {\n";
            // ----- DIRECTIONAL LIGHT
            if ( hasBumpMap() ) {
                code_block.computeCode +=
#ifdef DISCARD_SELF_SHADOWED_BEFORE_BUMP_MAPPING
"           if ( dot( nnormal, normalize(gl_LightSource[i].position.xyz) ) > 
0.0 )\n"
#endif
"           {\n"
"               vec3 lightDir;\n"
"               lightDir.x = dot(gl_LightSource[i].position.xyz, tangent);\n"
"               lightDir.y = dot(gl_LightSource[i].position.xyz, binormal);\n"
"               lightDir.z = dot(gl_LightSource[i].position.xyz, normal);\n"
"               vec3 halfVector;\n"
"               halfVector.x = dot(gl_LightSource[i].halfVector.xyz, 
tangent);\n"
"               halfVector.y = dot(gl_LightSource[i].halfVector.xyz, 
binormal);\n"
"               halfVector.z = dot(gl_LightSource[i].halfVector.xyz, normal);\n"
"                DirectionalLight(" + plug_normal_camera.codeBlock.accessCode + 
", \n"
"                                normalize(lightDir), \n"
"                                normalize(halfVector), \n"
"                                gl_LightSource[i].ambient, \n"
"                                gl_LightSource[i].diffuse, \n"
"                                gl_LightSource[i].specular, \n"
"                                gl_FrontMaterial.shininess, \n"
"                                amb, diff, spec); \n"
"           }\n";
            }
            else {
                code_block.computeCode +=
"            DirectionalLight(nnormal, \n"
"                            normalize(vec3(gl_LightSource[i].position)), \n"
"                            gl_LightSource[i].halfVector.xyz,\n"
"                            gl_LightSource[i].ambient, \n"
"                            gl_LightSource[i].diffuse, \n"
"                            gl_LightSource[i].specular, \n"
"                            gl_FrontMaterial.shininess, \n"
"                            amb, diff, spec);\n";
            }
            code_block.computeCode +=
"       }\n"
"        else if (gl_LightSource[i].spotCutoff == 180.0) {\n";
            // ----- POINT LIGHT
            if ( hasBumpMap() ) {
                code_block.computeCode +=
#ifdef DISCARD_SELF_SHADOWED_BEFORE_BUMP_MAPPING
"           if ( dot( nnormal, normalize(gl_LightSource[i].position.xyz - 
ecPosition3) ) > 0.0 )\n"
#endif
"           {\n"
"               vec3 lightPos;\n"
"               lightPos.x = dot(gl_LightSource[i].position.xyz, tangent);\n"
"               lightPos.y = dot(gl_LightSource[i].position.xyz, binormal);\n"
"               lightPos.z = dot(gl_LightSource[i].position.xyz, normal);\n"
"               vec3 surfPos;\n"
"               surfPos.x = dot(ecPosition3, tangent);\n"
"               surfPos.y = dot(ecPosition3, binormal);\n"
"               surfPos.z = dot(ecPosition3, normal);\n"
"               PointLight(surfPos, \n"
"                          " + plug_normal_camera.codeBlock.accessCode + ",\n"
"                          lightPos, \n"
"                          vec3( gl_LightSource[i].constantAttenuation, \n"
"                                gl_LightSource[i].linearAttenuation, \n"
"                                gl_LightSource[i].quadraticAttenuation ), \n"
"                          gl_LightSource[i].ambient, \n"
"                          gl_LightSource[i].diffuse, \n"
"                          gl_LightSource[i].specular, \n"
"                          gl_FrontMaterial.shininess, \n"
"                          amb, \n"
"                          diff, \n"
"                          spec);\n"
"           }\n";
            }
            else {
                code_block.computeCode +=
"            PointLight(ecPosition3, \n"
"                      nnormal, \n"
"                      gl_LightSource[i].position.xyz, \n"
"                      vec3( gl_LightSource[i].constantAttenuation, \n"
"                            gl_LightSource[i].linearAttenuation, \n"
"                            gl_LightSource[i].quadraticAttenuation ), \n"
"                      gl_LightSource[i].ambient, \n"
"                      gl_LightSource[i].diffuse, \n"
"                      gl_LightSource[i].specular, \n"
"                      gl_FrontMaterial.shininess, \n"
"                      amb, \n"
"                      diff, \n"
"                      spec);\n";
            }
            code_block.computeCode +=
"       }\n"
"        else {\n";
            // ----- SPOT LIGHT
            if ( hasBumpMap() ) {
                code_block.computeCode +=
#ifdef DISCARD_SELF_SHADOWED_BEFORE_BUMP_MAPPING
"           if ( dot( nnormal, normalize(gl_LightSource[i].position.xyz - 
ecPosition3) ) > 0.0 )\n"
#endif
"           {\n"
"               vec3 lightPos;\n"
"               lightPos.x = dot(gl_LightSource[i].position.xyz, tangent);\n"
"               lightPos.y = dot(gl_LightSource[i].position.xyz, binormal);\n"
"               lightPos.z = dot(gl_LightSource[i].position.xyz, normal);\n"
"               vec3 surfPos;\n"
"               surfPos.x = dot(ecPosition3, tangent);\n"
"               surfPos.y = dot(ecPosition3, binormal);\n"
"               surfPos.z = dot(ecPosition3, normal);\n"
"               vec3 spotDir;\n"
"               spotDir.x = dot(gl_LightSource[i].spotDirection, tangent);\n"
"               spotDir.y = dot(gl_LightSource[i].spotDirection, binormal);\n"
"               spotDir.z = dot(gl_LightSource[i].spotDirection, normal);\n"
"               SpotLight(surfPos, \n"
"                         " + plug_normal_camera.codeBlock.accessCode + ",\n"
"                         lightPos, \n"
"                         vec3( gl_LightSource[i].constantAttenuation, \n"
"                               gl_LightSource[i].linearAttenuation, \n"
"                               gl_LightSource[i].quadraticAttenuation ), \n"
"                         spotDir, \n"
"                         gl_LightSource[i].spotCosCutoff, \n"
"                         gl_LightSource[i].spotExponent, \n"
"                         gl_LightSource[i].ambient, \n"
"                         gl_LightSource[i].diffuse, \n"
"                         gl_LightSource[i].specular, \n"
"                         gl_FrontMaterial.shininess, \n"
"                         amb, \n"
"                         diff, \n"
"                         spec);\n"
"           }\n";
            }
            else {
                code_block.computeCode +=
"            SpotLight(ecPosition3, \n"
"                     nnormal, \n"
"                     gl_LightSource[i].position.xyz, \n"
"                     vec3( gl_LightSource[i].constantAttenuation, \n"
"                           gl_LightSource[i].linearAttenuation, \n"
"                           gl_LightSource[i].quadraticAttenuation ), \n"
"                     gl_LightSource[i].spotDirection, \n"
"                     gl_LightSource[i].spotCosCutoff, \n"
"                     gl_LightSource[i].spotExponent, \n"
"                     gl_LightSource[i].ambient, \n"
"                     gl_LightSource[i].diffuse, \n"
"                     gl_LightSource[i].specular, \n"
"                     gl_FrontMaterial.shininess, \n"
"                     amb, \n"
"                     diff, \n"
"                     spec);\n";
            }
            code_block.computeCode +=
"       }\n"
"    }\n"
"\n"
            // Channel : Diffuse color
"    vec3 diffuse_color = " + getPlugValue(plug_color) + " * " + 
getPlugValue(plug_diffuse) + ";\n"
            // Channel : Ambient color
"    vec3 ambient_color = " + getPlugValue(plug_ambient) + ";\n"
            // Channel : Emissive color
"    vec3 emissive_color = " + getPlugValue(plug_incandescence) + ";\n"
            // Channel : Specular color
"    vec3 specular_color = " + getPlugValue(plug_specular_color) + ";\n"
"\n";

    code_block.computeCode +=
"    vec4 " + variable_name + " = vec4( emissive_color +\n"
"                (amb.rgb + gl_LightModel.ambient.rgb) * ambient_color +\n"
"                 diff.rgb * diffuse_color +\n"
"                 spec.rgb * specular_color, 1.0 - " + 
getPlugValue(plug_transparency) + " );\n";

            _computedVariables.insert(variable_name);
        }
        // Access code
        if ( plug_name == "fragmentOutput" ) {  // special code for fragment 
output (RGBA)
            code_block.accessCode = variable_name;
        }
        else if ( plug_name == "outColor" ) {
            code_block.accessCode = variable_name + ".rgb";
        }
        else if ( plug_name == "outTransparency" ) {
            code_block.accessCode = "(1.0 - " + variable_name + ".a)";
        }
    }
    else {
        std::cerr << "WARNING: Unsupported plug " << plug_name << " in Lambert 
shader " << dn.name().asChar() << std::endl;
        // throw exception ??? !!! FIXME!!!
    }

    return code_block;
}


/**
 *    GLSL function for computing the contribution of a directional light
 */
std::string Blinn::getDirectionalLightFunction()
{
    std::string shader_src =
"void DirectionalLight(in vec3 normal,\n"
"                      in vec3 lightDir,\n"
"                      in vec3 halfVector,\n"
"                      in vec4 lightAmbient,\n"
"                      in vec4 lightDiffuse,\n"
"                      in vec4 lightSpecular,\n"
"                      in float shininess,\n"
"                      inout vec4 ambient,\n"
"                      inout vec4 diffuse,\n"
"                      inout vec4 specular)\n"
"{\n"
"    float NdotL;         // normal . light direction\n"
"    float NdotHV;        // normal . half vector\n"
"    float pf;            // power factor\n"
"\n"
"    NdotL = max(0.0, dot(normal,\n"
"                 lightDir));\n"
"    NdotHV = max(0.0, dot(normal, \n"
"               halfVector));\n"
"\n"
"    if ( NdotHV == 0.0 )\n"
"        pf = 0.0;\n"
"    else\n"
"        pf = pow(NdotHV, shininess);\n"
"\n"
"    ambient  += lightAmbient;\n"
"    diffuse  += lightDiffuse * NdotL;\n"
"    specular += lightSpecular * pf;\n"
"}\n"
;
    return shader_src;
}


/**
 *    GLSL function for computing the contribution of a point light
 */
std::string Blinn::getPointLightFunction()
{
    std::string shader_src = 
"void PointLight(in vec3 surfacePos,\n"
"                in vec3 normal,\n"
"                in vec3 lightPos,\n"
"                in vec3 lightAttenuation,\n"
"                in vec4 lightAmbient,\n"
"                in vec4 lightDiffuse,\n"
"                in vec4 lightSpecular,\n"
"                in float shininess,\n"
"                inout vec4 ambient,\n"
"                inout vec4 diffuse,\n"
"                inout vec4 specular)\n"
"{\n"
"    float NdotL;          // normal . light direction\n"
"    float NdotHV;         // normal . half vector\n"
"    float pf;             // power factor\n"
"    float attenuation;    // computed attenuation factor\n"
"    float d;              // distance from surface to light source\n"
"    vec3 lightDir;        // direction from surface to light position\n"
"    vec3 halfVector;      // direction of maximum highlights\n"
"\n"
"    // Compute vector from surface to light position\n"
"    lightDir = vec3(lightPos) - surfacePos;\n"
"\n"
"    // Compute distance between surface and light position\n"
"    d = length(lightDir);\n"
"\n"
"    // Normalize the vector from surface to light position\n"
"    lightDir = normalize(lightDir);\n"
"\n"
"    // Compute attenuation\n"
"    attenuation = 1.0 / (lightAttenuation.x +\n"
"                         lightAttenuation.y * d +\n"
"                         lightAttenuation.z * d * d);\n"
"\n"
"    halfVector = normalize(lightDir - normalize(surfacePos));\n"
"\n"
"    NdotL = max(0.0, dot(normal, lightDir));\n"
"    NdotHV = max(0.0, dot(normal, halfVector));\n"
"\n"
"    if ( NdotL == 0.0 )\n"
"        pf = 0.0;\n"
"    else\n"
"        pf = pow(NdotHV, shininess);\n"
"\n"
"    ambient += lightAmbient * attenuation;\n"
"    diffuse += lightDiffuse * NdotL * attenuation;\n"
"    specular += lightSpecular * pf * attenuation;\n"
"}\n";
    return shader_src;
}


/**
 *    GLSL function for computing the contribution of a spot light
 */
std::string Blinn::getSpotLightFunction()
{
    std::string shader_src = 
"void SpotLight(in vec3 surfacePos,\n"
"               in vec3 normal,\n"
"               in vec3 lightPos,\n"
"               in vec3 lightAttenuation,\n"
"               in vec3 spotDirection,\n"
"               in float spotCosCutoff,\n"
"               in float spotExponent,\n"
"               in vec4 lightAmbient,\n"
"               in vec4 lightDiffuse,\n"
"               in vec4 lightSpecular,\n"
"               in float shininess,\n"
"               inout vec4 ambient,\n"
"               inout vec4 diffuse,\n"
"               inout vec4 specular)\n"
"{\n"
"    float NdotL;            // normal . light direction\n"
"    float NdotHV;           // normal . half vector\n"
"    float pf;               // power factor\n"
"    float spotDot;          // cosine of angle between spotlight\n"
"    float spotAttenuation;  // spotlight attenuation factor\n"
"    float attenuation;      // computed attenuation factor\n"
"    float d;                // distance from surface to light source\n"
"    vec3 lightDir;          // direction from surface to light position\n"
"    vec3 halfVector;        // direction of maximum highlights\n"
"\n"
"    // Compute vector from surface to light position\n"
"    lightDir = lightPos - surfacePos;\n"
"\n"
"    // Compute distance between surface and light position\n"
"    d = length(lightDir);\n"
"\n"
"    // Normalize the vector from surface to light position\n"
"    lightDir = normalize(lightDir);\n"
"\n"
"    // Compute attenuation\n"
"    attenuation = 1.0 / (lightAttenuation.x +\n"
"                         lightAttenuation.y * d +\n"
"                         lightAttenuation.z * d * d);\n"
"\n"
"    // See if point on surface is inside cone of illumination\n"
"    spotDot = dot(-lightDir, normalize(spotDirection));\n"
"\n"
"    if (spotDot < spotCosCutoff)\n"
"        spotAttenuation = 0.0; // light adds no contribution\n"
"    else\n"
"        spotAttenuation = pow(spotDot, spotExponent);\n"
"\n"
"    // Combine the spotlight and distance attenuation.\n"
"    attenuation *= spotAttenuation;\n"
"\n"
"    halfVector = normalize(lightDir - normalize(surfacePos));\n"
"\n"
"    NdotL = max(0.0, dot(normal, lightDir));\n"
"    NdotHV = max(0.0, dot(normal, halfVector));\n"
"\n"
"    if ( NdotL == 0.0 )\n"
"        pf = 0.0;\n"
"    else\n"
"        pf = pow(NdotHV, shininess);\n"
"\n"
"    ambient  += lightAmbient * attenuation;\n"
"    diffuse  += lightDiffuse * NdotL * attenuation;\n"
"    specular += lightSpecular * pf * attenuation;\n"
"}\n"
;
    return shader_src;
}
/**
    Maya2OSG - A toolkit for exporting Maya scenes to OpenSceneGraph
    Copyright (C) 2010 Javier Taibo <javier.ta...@gmail.com>

    This file is part of Maya2OSG.

    Maya2OSG is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Maya2OSG is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Maya2OSG.  If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _BLINN_H_
#define _BLINN_H_

#include "surfaceshader.h"

#include <string>


class Blinn : public SurfaceShader {

public:

    /// Constructor
    Blinn( const MObject &shading_node, ShadingNetwork &shading_network );

    /// Get the GLSL Codeblock for a plug
    virtual CodeBlock getCodeBlock( const std::string &plug_name );

private:

        std::string getDirectionalLightFunction();
        std::string getPointLightFunction();
        std::string getSpotLightFunction();

};

#endif //_BLINN_H_
/**
    Maya2OSG - A toolkit for exporting Maya scenes to OpenSceneGraph
    Copyright (C) 2010 Javier Taibo <javier.ta...@gmail.com>

    This file is part of Maya2OSG.

    Maya2OSG is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Maya2OSG is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Maya2OSG.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "phong.h"
#include "glslutils.h"
#include "shadingnetwork.h"
#include "../common.h"

#include <maya/MFnDependencyNode.h>
#include <maya/MPlug.h>

#define DISCARD_SELF_SHADOWED_BEFORE_BUMP_MAPPING


/**
 *  Constructor
 */
Phong::Phong( const MObject &shading_node, ShadingNetwork &shading_network ) :
    SurfaceShader( shading_node, shading_network ) 
{
}


/**
 *  Get the GLSL Codeblock for a plug
 */
ShadingNode::CodeBlock Phong::getCodeBlock( const std::string &plug_name )
{
    // Build the GLSL code ...
    CodeBlock code_block;

    std::string variable_name;
    MFnDependencyNode dn(_mayaShadingNode);
    std::string maya_phong_shader_name = dn.name().asChar();
    hygienizeName( maya_phong_shader_name );

    // Check plug name and avoid duplicating code

    if ( plug_name == "fragmentOutput" ||
         plug_name == "outColor" || 
         plug_name == "outTransparency" ) 
    {
        variable_name = "sn_phong_" + maya_phong_shader_name + "_output";
        // Both color and transparency are stored in "color" variable.
        // if it is already declared, we omit all the GLSL code
        if ( !variableIsAvailable(variable_name) ) {

            // Supported Phong input channels

            // Color (diffuse)
            Plug plug_color = getPlug("color");
            // Transparency
            Plug plug_transparency = getPlug("transparency");
            // Ambient Color
            Plug plug_ambient = getPlug("ambientColor");
            // Incandescence
            Plug plug_incandescence = getPlug("incandescence");
            // Bump map
            Plug plug_normal_camera;
            if ( hasBumpMap() ) {
                plug_normal_camera = getPlug("normalCamera");
            }
            // Diffuse (scalar)
            Plug plug_diffuse = getPlug("diffuse");
            // Cosine Power
            Plug plug_cos_power = getPlug("cosinePower");
            // Specular Color
            Plug plug_specular_color = getPlug("specularColor");

            // TO-DO ... Reflectivity, Reflected Color

            code_block.declarations = plug_color.codeBlock.declarations +
                                      plug_transparency.codeBlock.declarations +
                                      plug_ambient.codeBlock.declarations +
                                      plug_incandescence.codeBlock.declarations 
+
                                      plug_normal_camera.codeBlock.declarations 
+
                                      plug_diffuse.codeBlock.declarations + 
                                      plug_cos_power.codeBlock.declarations +
                                      
plug_specular_color.codeBlock.declarations;

            code_block.functions = plug_color.codeBlock.functions +
                                   plug_transparency.codeBlock.functions +
                                   plug_ambient.codeBlock.functions +
                                   plug_incandescence.codeBlock.functions +
                                   plug_normal_camera.codeBlock.functions +
                                   plug_diffuse.codeBlock.functions +
                                   plug_cos_power.codeBlock.functions +
                                   plug_specular_color.codeBlock.functions +
                                   getDirectionalLightFunction() +
                                   getPointLightFunction() +
                                   getSpotLightFunction();

            code_block.computeCode = plug_color.codeBlock.computeCode +
                                     plug_transparency.codeBlock.computeCode +
                                     plug_ambient.codeBlock.computeCode +
                                     plug_incandescence.codeBlock.computeCode +
                                     plug_normal_camera.codeBlock.computeCode +
                                     plug_diffuse.codeBlock.computeCode +
                                     plug_cos_power.codeBlock.computeCode +
                                     plug_specular_color.codeBlock.computeCode +
"\n" +
            GLSLUtils::backFaceCulling(_shadingNetwork.getStateSet());

            code_block.computeCode +=
"    // Clear the light intensity accumulators\n"
"    vec4 amb  = vec4(0.0);\n"
"    vec4 diff = vec4(0.0);\n"
"   vec4 spec = vec4(0.0);\n"
"\n"
"    // Loop through enabled lights, compute contribution from each\n"
"    int i;\n"
"    for (i = 0; i < NumEnabledLights; i++)\n"
"    {\n"
"        if (gl_LightSource[i].position.w == 0.0) {\n";
            // ----- DIRECTIONAL LIGHT
            if ( hasBumpMap() ) {
                code_block.computeCode +=
#ifdef DISCARD_SELF_SHADOWED_BEFORE_BUMP_MAPPING
"           if ( dot( nnormal, normalize(gl_LightSource[i].position.xyz) ) > 
0.0 )\n"
#endif
"           {\n"
"               vec3 lightDir;\n"
"               lightDir.x = dot(gl_LightSource[i].position.xyz, tangent);\n"
"               lightDir.y = dot(gl_LightSource[i].position.xyz, binormal);\n"
"               lightDir.z = dot(gl_LightSource[i].position.xyz, normal);\n"
"               vec3 halfVector;\n"
"               halfVector.x = dot(gl_LightSource[i].halfVector.xyz, 
tangent);\n"
"               halfVector.y = dot(gl_LightSource[i].halfVector.xyz, 
binormal);\n"
"               halfVector.z = dot(gl_LightSource[i].halfVector.xyz, normal);\n"
"                DirectionalLight(" + plug_normal_camera.codeBlock.accessCode + 
", \n"
"                                normalize(lightDir), \n"
"                                normalize(halfVector), \n"
"                                gl_LightSource[i].ambient, \n"
"                                gl_LightSource[i].diffuse, \n"
"                                gl_LightSource[i].specular, \n"
"                                gl_FrontMaterial.shininess, \n"
"                                amb, diff, spec); \n"
"           }\n";
            }
            else {
                code_block.computeCode +=
"            DirectionalLight(nnormal, \n"
"                            normalize(vec3(gl_LightSource[i].position)), \n"
"                            gl_LightSource[i].halfVector.xyz,\n"
"                            gl_LightSource[i].ambient, \n"
"                            gl_LightSource[i].diffuse, \n"
"                            gl_LightSource[i].specular, \n"
"                            gl_FrontMaterial.shininess, \n"
"                            amb, diff, spec);\n";
            }
            code_block.computeCode +=
"       }\n"
"        else if (gl_LightSource[i].spotCutoff == 180.0) {\n";
            // ----- POINT LIGHT
            if ( hasBumpMap() ) {
                code_block.computeCode +=
#ifdef DISCARD_SELF_SHADOWED_BEFORE_BUMP_MAPPING
"           if ( dot( nnormal, normalize(gl_LightSource[i].position.xyz - 
ecPosition3) ) > 0.0 )\n"
#endif
"           {\n"
"               vec3 lightPos;\n"
"               lightPos.x = dot(gl_LightSource[i].position.xyz, tangent);\n"
"               lightPos.y = dot(gl_LightSource[i].position.xyz, binormal);\n"
"               lightPos.z = dot(gl_LightSource[i].position.xyz, normal);\n"
"               vec3 surfPos;\n"
"               surfPos.x = dot(ecPosition3, tangent);\n"
"               surfPos.y = dot(ecPosition3, binormal);\n"
"               surfPos.z = dot(ecPosition3, normal);\n"
"               PointLight(surfPos, \n"
"                          " + plug_normal_camera.codeBlock.accessCode + ",\n"
"                          lightPos, \n"
"                          vec3( gl_LightSource[i].constantAttenuation, \n"
"                                gl_LightSource[i].linearAttenuation, \n"
"                                gl_LightSource[i].quadraticAttenuation ), \n"
"                          gl_LightSource[i].ambient, \n"
"                          gl_LightSource[i].diffuse, \n"
"                          gl_LightSource[i].specular, \n"
"                          gl_FrontMaterial.shininess, \n"
"                          amb, \n"
"                          diff, \n"
"                          spec);\n"
"           }\n";
            }
            else {
                code_block.computeCode +=
"            PointLight(ecPosition3, \n"
"                      nnormal, \n"
"                      gl_LightSource[i].position.xyz, \n"
"                      vec3( gl_LightSource[i].constantAttenuation, \n"
"                            gl_LightSource[i].linearAttenuation, \n"
"                            gl_LightSource[i].quadraticAttenuation ), \n"
"                      gl_LightSource[i].ambient, \n"
"                      gl_LightSource[i].diffuse, \n"
"                      gl_LightSource[i].specular, \n"
"                      gl_FrontMaterial.shininess, \n"
"                      amb, \n"
"                      diff, \n"
"                      spec);\n";
            }
            code_block.computeCode +=
"       }\n"
"        else {\n";
            // ----- SPOT LIGHT
            if ( hasBumpMap() ) {
                code_block.computeCode +=
#ifdef DISCARD_SELF_SHADOWED_BEFORE_BUMP_MAPPING
"           if ( dot( nnormal, normalize(gl_LightSource[i].position.xyz - 
ecPosition3) ) > 0.0 )\n"
#endif
"           {\n"
"               vec3 lightPos;\n"
"               lightPos.x = dot(gl_LightSource[i].position.xyz, tangent);\n"
"               lightPos.y = dot(gl_LightSource[i].position.xyz, binormal);\n"
"               lightPos.z = dot(gl_LightSource[i].position.xyz, normal);\n"
"               vec3 surfPos;\n"
"               surfPos.x = dot(ecPosition3, tangent);\n"
"               surfPos.y = dot(ecPosition3, binormal);\n"
"               surfPos.z = dot(ecPosition3, normal);\n"
"               vec3 spotDir;\n"
"               spotDir.x = dot(gl_LightSource[i].spotDirection, tangent);\n"
"               spotDir.y = dot(gl_LightSource[i].spotDirection, binormal);\n"
"               spotDir.z = dot(gl_LightSource[i].spotDirection, normal);\n"
"               SpotLight(surfPos, \n"
"                         " + plug_normal_camera.codeBlock.accessCode + ",\n"
"                         lightPos, \n"
"                         vec3( gl_LightSource[i].constantAttenuation, \n"
"                               gl_LightSource[i].linearAttenuation, \n"
"                               gl_LightSource[i].quadraticAttenuation ), \n"
"                         spotDir, \n"
"                         gl_LightSource[i].spotCosCutoff, \n"
"                         gl_LightSource[i].spotExponent, \n"
"                         gl_LightSource[i].ambient, \n"
"                         gl_LightSource[i].diffuse, \n"
"                         gl_LightSource[i].specular, \n"
"                         gl_FrontMaterial.shininess, \n"
"                         amb, \n"
"                         diff, \n"
"                         spec);\n"
"           }\n";
            }
            else {
                code_block.computeCode +=
"            SpotLight(ecPosition3, \n"
"                     nnormal, \n"
"                     gl_LightSource[i].position.xyz, \n"
"                     vec3( gl_LightSource[i].constantAttenuation, \n"
"                           gl_LightSource[i].linearAttenuation, \n"
"                           gl_LightSource[i].quadraticAttenuation ), \n"
"                     gl_LightSource[i].spotDirection, \n"
"                     gl_LightSource[i].spotCosCutoff, \n"
"                     gl_LightSource[i].spotExponent, \n"
"                     gl_LightSource[i].ambient, \n"
"                     gl_LightSource[i].diffuse, \n"
"                     gl_LightSource[i].specular, \n"
"                     gl_FrontMaterial.shininess, \n"
"                     amb, \n"
"                     diff, \n"
"                     spec);\n";
            }
            code_block.computeCode +=
"       }\n"
"    }\n"
"\n"
            // Channel : Diffuse color
"    vec3 diffuse_color = " + getPlugValue(plug_color) + " * " + 
getPlugValue(plug_diffuse) + ";\n"
            // Channel : Ambient color
"    vec3 ambient_color = " + getPlugValue(plug_ambient) + ";\n"
            // Channel : Emissive color
"    vec3 emissive_color = " + getPlugValue(plug_incandescence) + ";\n"
            // Channel : Specular color
"    vec3 specular_color = " + getPlugValue(plug_specular_color) + ";\n"
"\n";

    code_block.computeCode +=
"    vec4 " + variable_name + " = vec4( emissive_color +\n"
"                (amb.rgb + gl_LightModel.ambient.rgb) * ambient_color +\n"
"                 diff.rgb * diffuse_color +\n"
"                 spec.rgb * specular_color, 1.0 - " + 
getPlugValue(plug_transparency) + " );\n";

            _computedVariables.insert(variable_name);
        }
        // Access code
        if ( plug_name == "fragmentOutput" ) {  // special code for fragment 
output (RGBA)
            code_block.accessCode = variable_name;
        }
        else if ( plug_name == "outColor" ) {
            code_block.accessCode = variable_name + ".rgb";
        }
        else if ( plug_name == "outTransparency" ) {
            code_block.accessCode = "(1.0 - " + variable_name + ".a)";
        }
    }
    else {
        std::cerr << "WARNING: Unsupported plug " << plug_name << " in Lambert 
shader " << dn.name().asChar() << std::endl;
        // throw exception ??? !!! FIXME!!!
    }

    return code_block;
}


/**
 *    GLSL function for computing the contribution of a directional light
 */
std::string Phong::getDirectionalLightFunction()
{
    std::string shader_src =
"void DirectionalLight(in vec3 normal,\n"
"                      in vec3 lightDir,\n"
"                      in vec3 halfVector,\n"
"                      in vec4 lightAmbient,\n"
"                      in vec4 lightDiffuse,\n"
"                      in vec4 lightSpecular,\n"
"                      in float shininess,\n"
"                      inout vec4 ambient,\n"
"                      inout vec4 diffuse,\n"
"                      inout vec4 specular)\n"
"{\n"
"    float NdotL;         // normal . light direction\n"
"    float NdotHV;        // normal . half vector\n"
"    float pf;            // power factor\n"
"\n"
"    NdotL = max(0.0, dot(normal,\n"
"                 lightDir));\n"
"    NdotHV = max(0.0, dot(normal, \n"
"               halfVector));\n"
"\n"
"    if ( NdotHV == 0.0 )\n"
"        pf = 0.0;\n"
"    else\n"
"        pf = pow(NdotHV, shininess);\n"
"\n"
"    ambient  += lightAmbient;\n"
"    diffuse  += lightDiffuse * NdotL;\n"
"    specular += lightSpecular * pf;\n"
"}\n"
;
    return shader_src;
}


/**
 *    GLSL function for computing the contribution of a point light
 */
std::string Phong::getPointLightFunction()
{
    std::string shader_src = 
"void PointLight(in vec3 surfacePos,\n"
"                in vec3 normal,\n"
"                in vec3 lightPos,\n"
"                in vec3 lightAttenuation,\n"
"                in vec4 lightAmbient,\n"
"                in vec4 lightDiffuse,\n"
"                in vec4 lightSpecular,\n"
"                in float shininess,\n"
"                inout vec4 ambient,\n"
"                inout vec4 diffuse,\n"
"                inout vec4 specular)\n"
"{\n"
"    float NdotL;          // normal . light direction\n"
"    float NdotHV;         // normal . half vector\n"
"    float pf;             // power factor\n"
"    float attenuation;    // computed attenuation factor\n"
"    float d;              // distance from surface to light source\n"
"    vec3 lightDir;        // direction from surface to light position\n"
"    vec3 halfVector;      // direction of maximum highlights\n"
"\n"
"    // Compute vector from surface to light position\n"
"    lightDir = vec3(lightPos) - surfacePos;\n"
"\n"
"    // Compute distance between surface and light position\n"
"    d = length(lightDir);\n"
"\n"
"    // Normalize the vector from surface to light position\n"
"    lightDir = normalize(lightDir);\n"
"\n"
"    // Compute attenuation\n"
"    attenuation = 1.0 / (lightAttenuation.x +\n"
"                         lightAttenuation.y * d +\n"
"                         lightAttenuation.z * d * d);\n"
"\n"
"    halfVector = normalize(lightDir - normalize(surfacePos));\n"
"\n"
"    NdotL = max(0.0, dot(normal, lightDir));\n"
"    NdotHV = max(0.0, dot(normal, halfVector));\n"
"\n"
"    if ( NdotL == 0.0 )\n"
"        pf = 0.0;\n"
"    else\n"
"        pf = pow(NdotHV, shininess);\n"
"\n"
"    ambient += lightAmbient * attenuation;\n"
"    diffuse += lightDiffuse * NdotL * attenuation;\n"
"    specular += lightSpecular * pf * attenuation;\n"
"}\n";
    return shader_src;
}


/**
 *    GLSL function for computing the contribution of a spot light
 */
std::string Phong::getSpotLightFunction()
{
    std::string shader_src = 
"void SpotLight(in vec3 surfacePos,\n"
"               in vec3 normal,\n"
"               in vec3 lightPos,\n"
"               in vec3 lightAttenuation,\n"
"               in vec3 spotDirection,\n"
"               in float spotCosCutoff,\n"
"               in float spotExponent,\n"
"               in vec4 lightAmbient,\n"
"               in vec4 lightDiffuse,\n"
"               in vec4 lightSpecular,\n"
"               in float shininess,\n"
"               inout vec4 ambient,\n"
"               inout vec4 diffuse,\n"
"               inout vec4 specular)\n"
"{\n"
"    float NdotL;            // normal . light direction\n"
"    float NdotHV;           // normal . half vector\n"
"    float pf;               // power factor\n"
"    float spotDot;          // cosine of angle between spotlight\n"
"    float spotAttenuation;  // spotlight attenuation factor\n"
"    float attenuation;      // computed attenuation factor\n"
"    float d;                // distance from surface to light source\n"
"    vec3 lightDir;          // direction from surface to light position\n"
"    vec3 halfVector;        // direction of maximum highlights\n"
"\n"
"    // Compute vector from surface to light position\n"
"    lightDir = lightPos - surfacePos;\n"
"\n"
"    // Compute distance between surface and light position\n"
"    d = length(lightDir);\n"
"\n"
"    // Normalize the vector from surface to light position\n"
"    lightDir = normalize(lightDir);\n"
"\n"
"    // Compute attenuation\n"
"    attenuation = 1.0 / (lightAttenuation.x +\n"
"                         lightAttenuation.y * d +\n"
"                         lightAttenuation.z * d * d);\n"
"\n"
"    // See if point on surface is inside cone of illumination\n"
"    spotDot = dot(-lightDir, normalize(spotDirection));\n"
"\n"
"    if (spotDot < spotCosCutoff)\n"
"        spotAttenuation = 0.0; // light adds no contribution\n"
"    else\n"
"        spotAttenuation = pow(spotDot, spotExponent);\n"
"\n"
"    // Combine the spotlight and distance attenuation.\n"
"    attenuation *= spotAttenuation;\n"
"\n"
"    halfVector = normalize(lightDir - normalize(surfacePos));\n"
"\n"
"    NdotL = max(0.0, dot(normal, lightDir));\n"
"    NdotHV = max(0.0, dot(normal, halfVector));\n"
"\n"
"    if ( NdotL == 0.0 )\n"
"        pf = 0.0;\n"
"    else\n"
"        pf = pow(NdotHV, shininess);\n"
"\n"
"    ambient  += lightAmbient * attenuation;\n"
"    diffuse  += lightDiffuse * NdotL * attenuation;\n"
"    specular += lightSpecular * pf * attenuation;\n"
"}\n"
;
    return shader_src;
}
/**
    Maya2OSG - A toolkit for exporting Maya scenes to OpenSceneGraph
    Copyright (C) 2010 Javier Taibo <javier.ta...@gmail.com>

    This file is part of Maya2OSG.

    Maya2OSG is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Maya2OSG is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Maya2OSG.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "shadingnode.h"
#include "shadingnetwork.h"
#include "shadingnodefactory.h"

#include "../shader.h"

#include <maya/MFnDependencyNode.h>
#include <maya/MPlug.h>

#include <sstream>


/// Constructor
ShadingNode::ShadingNode( const MObject &shading_node, ShadingNetwork 
&shading_network ) :
    _mayaShadingNode(shading_node),
    _shadingNetwork(shading_network)
{
}


/**
 *  Check if a variable was already computed (and so, its available to include 
it in GLSL code)
 */
bool ShadingNode::variableIsAvailable( const std::string &variable_name )
{
    return _computedVariables.find(variable_name) != _computedVariables.end();
}


// TODO: For an unknown reason, if this part of the code is compiled with 
// optimization enabled, it makes the plugin crash Maya. I couldn't find the
// reason for this. For now optimization is disabled.
#pragma optimize( "", off )

/**
 *  Get the plug info for a channel of this Shading Node
 */
ShadingNode::Plug ShadingNode::getPlug(const std::string &channel)
{
    Plug plug;
    plug.channel = channel;
    plug.connectedShadingNode = NULL;
    if ( Shader::connectedChannel( _mayaShadingNode, channel) ){
        MObject node;
        Shader::getNodeConnectedToChannel( _mayaShadingNode, channel, node );
        plug.connectedShadingNode = ShadingNodeFactory::build( node, 
_shadingNetwork );
    }
    if ( plug.connectedShadingNode.valid() ){
        // Get the plug connected to plug
        MPlug remote_plug;
        Shader::getPlugConnectedToChannel( _mayaShadingNode, channel, 
remote_plug );
        std::string rp_name = remote_plug.partialName(false, false, false, 
false, false, true).asChar();
        plug.codeBlock = plug.connectedShadingNode->getCodeBlock( rp_name );
    }
    return plug;
}

// Re-enable optimization for the rest of the file.
#pragma optimize( "", on )


/**
 *  Get the plug value, whether networked or not
 */
std::string ShadingNode::getPlugValue( Plug &plug )
{
    std::stringstream glsl_code;

    if ( plug.connectedShadingNode.valid() ) {
        return plug.codeBlock.accessCode;
    }
    else {
        MFnDependencyNode dn(_mayaShadingNode);
        MPlug maya_plug = dn.findPlug(plug.channel.c_str());
        if ( maya_plug.isCompound() ) {
            glsl_code << "vec" << maya_plug.numChildren() << "(";
            float val;
            maya_plug.child(0).getValue(val);
            glsl_code << val;
            for( int i=1 ; i < maya_plug.numChildren() ; i++ ) {
                maya_plug.child(i).getValue(val);
                glsl_code << "," << val;
            }
            glsl_code << ")";
        }
        else {
            float val;
            maya_plug.getValue( val );
            glsl_code << val;
        }
        return glsl_code.str();
    }
}
/**
    Maya2OSG - A toolkit for exporting Maya scenes to OpenSceneGraph
    Copyright (C) 2010 Javier Taibo <javier.ta...@gmail.com>

    This file is part of Maya2OSG.

    Maya2OSG is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Maya2OSG is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Maya2OSG.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "shadingnodefactory.h"
#include "shadingnetwork.h"

#include <maya/MFnDependencyNode.h>

// This should use clonation and autoregistering of shading nodes to the factory
#include "lambert.h"
#include "phong.h"
#include "blinn.h"
#include "flatshader.h"

#include "filetexture.h"
#include "bump2d.h"
#include "../config.h"

/**
 *  Build a shading node
 */
ShadingNode *ShadingNodeFactory::build( const MObject &node, ShadingNetwork 
&shading_network )
{
    MFnDependencyNode dn(node);
    std::string node_name = dn.name().asChar();

    osg::ref_ptr<ShadingNode> sn = shading_network.getShadingNode(node_name);

    if ( sn.valid() ) {
        return sn.get();
    }

    if ( node.hasFn( MFn::kPhong ) ) {
        sn = new Phong( node, shading_network );
    }
    else if ( node.hasFn( MFn::kBlinn ) ) {
        sn = new Blinn( node, shading_network );
    }
    else if ( node.hasFn( MFn::kLambert ) ) {
        sn = new Lambert( node, shading_network );
    }
    else if ( node.hasFn( MFn::kSurfaceShader ) ) {
        sn = new FlatShader( node, shading_network );
    }
    else if ( node.hasFn( MFn::kFileTexture ) ) {
        sn = new FileTexture( node, shading_network );
    }
    else if ( node.hasFn( MFn::kBump ) ) {
                if ( Config::instance()->getEnableBumpMapping() ) {
                sn = new Bump2D( node, shading_network );
                }
                else {
                        std::cerr << "Bump mapping disabled in the exporter 
configuration" << std::endl;
                }
    }
    // *** ... TO-DO: CHECK FOR OTHER SHADING NODES...
    else {
        std::cerr << "ERROR: Unsupported shading node : " << node.apiTypeStr() 
<< std::endl;
    }

    if ( sn.valid() ) {
        shading_network.registerShadingNode( sn.get(), node_name );
    }

    return sn.get();
}
_______________________________________________
osg-users mailing list
osg-users@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to