FAKE SSS for 3DS MAX Viewport
Code over here:
http://www.aardolino.com/blog/
or
Playing Remedy’s Alan Wake for Xbox, and feeling lost seeing its marvelous forest environment, wondering about how to procedurally animate trees and vegetation using vertex colors, the idea of SS&F-SSS came out: use mesh thickness to modulate a SSS color. [Yes…it’s not related to trees and vegetations actually]
I’m confident that this approach was discovered a lot of time ago, but I implemented it as coding exercise.
As first step I developed a maxscript function to evaluate the mesh thickness; the function casts a ray for every vertex normal (inverting their direction) and store the collision distance in the vertex’s color. After that some tuning is needed to get better results; this tune is usually a couple of blur passes.
This is the maxscript code to find the mesh thickness:
--convert a value to 0-255 range
fn UT_to255 _min _max n =
(
local result = ((n + (-1*_min))/float(_max))*255
return int(ceil(result))
)
--cast a ray for every mesh vertex and store the ray distance in the vertex color
--NOTE: a vertex color tune is needed!! use the vertexPaint modifier
fn aa_bakeMeshThickness theMesh =
(
local rm = RayMeshGridIntersect()
rm.Initialize 10 --init. the voxel grid size to 10x10x10
rm.addNode theMesh
rm.buildGrid() --build the grid data (collecting faces into the grid voxels)
local theGSMesh = snapshotasmesh theMesh
local theColorArray = #()
for v = 1 to theGSMesh.numverts do --go through all verts of the Geosphere
(
local thePos = getVert theGSMesh v --get the position of the vertex
local theNormal = -(getNormal theGSMesh v) --get the normal of the vertex, reverse direction
local theHitsCount = rm.intersectRay thePos theNormal true --intersect the ray with the sphere
if theHitsCount > 0 then --if have hit anything...
(
local theIndex = rm.getClosestHit() --get the index of the closest hit by the ray
local theFace = rm.getHitFace theIndex --get the face index corresponding to that indexed hit
--append theFacesArray theFace --add to the face array to select the face...
--find the distance from the current verte to the hit point
local theFaceID = rm.getHitFace theIndex
local theFaceCenter = meshop.getFaceCenter $ theFaceID
local theDist = distance theFaceCenter thePos
append theColorArray theDist
--print theDist
)
else
format "The Ray % Missed\n" v
)
--assign the vertex colors
local vMin = amin theColorArray
local vMax = amax theColorArray
for v = 1 to theGSMesh.numverts do --go through all verts of the Geosphere
(
local vColor = 255 - (UT_to255 vMin vMax theColorArray[v])
--print vColor
meshop.setVertColor theMesh 0 v ((color vColor vColor vColor))
)
--vertex color tuning
local vPaint = VertexPaint()
addModifier theMesh vPaint
)
--run
global curMesh = $
if(classof curMesh != Editable_mesh) then convertToMesh curMesh
aa_bakeMeshThickness curMesh
curMesh.showVertexColors = on
curMesh.vertexColorsShaded = off
curMesh.vertexColorType = 0
And the HLSL code to use this information is:
float4 sssColor = float4(0,0,0,0);
if(g_sssEnable)
{
float sssInterpolation = pow(max(dot(-IN.eyeVector, IN.LightVec.xyz), 0), 2);
sssColor = lerp(float4(0,0,0,1), g_SSSColor, sssInterpolation) * float4(IN.vertColor, 1) * g_sssMultiplier;
}
Finally I simply add the sssColor to the output pixel.
dinamically load .net assemblies in 3dsMax
April 10, 2012
During intensive 3dsMax+C# development, a really annoyng issue is the blocking loading of .dll assemblies performed by 3dsMax.
The technique by Denis Trofimov solves the issue:
assemblyPath = @"\\aardolino\aa_imageMosaic.dll"
assembly = (dotnetclass "System.Reflection.Assembly").Load ((dotnetclass "System.IO.File").ReadAllBytes assemblyPath)
imgMosaic = dotNetObject "aa_imageMosaic_namespace.aa_imageMosaic_class"
imgMos.showForm()
More information here: http://forums.cgsociety.org/showpost.php?p=6864094&postcount=480