Skip to content

Instantly share code, notes, and snippets.

@seflless
Created November 7, 2010 00:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save seflless/665829 to your computer and use it in GitHub Desktop.
Save seflless/665829 to your computer and use it in GitHub Desktop.
Code for converting a Normal to a color for Normal Mapping Purposes
// Encodes a float with range [-1.0,1.0] into a color channel with range [0,255]
function encodeFloat(f){
if(f<0.0){
f = -f;
return Math.min(Math.floor((1.0-f)*127.0),127);
}
else{
return 128+Math.min(Math.floor(f*128.0),128);
}
}
// Encode a normal into a color
function normalToColor(n){
var c = new THREE.Color(0x000000); // No way to create a color with an r,g,b of range [0,1] or [0,255]?
c.setRGBA(encodeFloat(n.x)/255, encodeFloat(n.y)/255, encodeFloat(n.z)/255,1);
return c;
}
// So when you go to draw an element do something like this.
color = normalToColor(element.normalWorld);
@mrdoob
Copy link

mrdoob commented Nov 15, 2010

Mmh, I've reduced it to this... is it still right?

function normalToComponent( normal ) {

    return normal < 0 ? Math.min( 1 + normal, 0.5 ) : 0.5 + Math.min( normal, 0.5 );

}

if ( material instanceof THREE.MeshNormalMaterial ) {

    _color.setRGBA( normalToComponent( element.normalWorld.x ), normalToComponent( element.normalWorld.y ), normalToComponent( element.normalWorld.z ), 1 );

}

@seflless
Copy link
Author

// In function normalToComponent( normal ), should be:
{ return normal < 0 ? Math.min( (1 + normal)_0.5, 0.5 ) : 0.5 + Math.min( normal_0.5, 0.5 ); }

// Oh and the way I used to setup lighting in 3D Studios popped into my head yesterday. I don't think it matters, because unless you can support Negative Magnitude Lights, there are better ways to do it:
// 1) In software Renderer you can more easily and efficiently do as you are doing with a custom Material
// 2) Using WebGL you can make a Vertex or Pixel Shader that does it better, including having Phong or Gourard shading to create smooth normal maps. Ps. you might have noticed that in my Diffuse+Normal Map Rendering Demo that the normals are less blocky than the other meshes. I actually just used a Gaussian Blur in Photoshop and it worked to make it look smoother (A benefit of using an image based form of Normals. You can even paint in normals given a Semi Sphere Paletter sample, this is actually what I did for my Cereal Demo: Created the Normals after I had already taken the picture of the Box)

@seflless
Copy link
Author

// Made a typo due to Markdown not using * as a literal
{ return normal < 0 ? Math.min( (1 + normal)*0.5, 0.5 ) : 0.5 + Math.min( normal*0.5, 0.5 ); }

@mrdoob
Copy link

mrdoob commented Nov 15, 2010

@seflless
Copy link
Author

Sweet, I started cleaning up my code. Have a clean incremental Normal Map generator going. But I need to clean up the rendering code to make it more compose-able to let people build things I never thought of. If I ever get it finished, I'll write up an Article and send you a link to promote in any demos you make of the normal map renderer.

@seflless
Copy link
Author

Example of new API for Generating Normal Maps from Photos
http://endergen.com/labs/normal_mapping/demos/generate_beth.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment