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