Need for Speed RIVALS

October 27, 2013

There will be more information soon

SuperSimple&Fake SSS [Sub Surface Scattering]

April 27, 2012

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. ['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
            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
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);
    float sssInterpolation = pow(max(dot(-IN.eyeVector,, 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"

More information here: