POV-Ray : Newsgroups : povray.advanced-users : Using POV-Ray to generate an RGB normal map? : Re: Using POV-Ray to generate an RGB normal map? Server Time
4 May 2024 02:23:21 EDT (-0400)
  Re: Using POV-Ray to generate an RGB normal map?  
From: Slime
Date: 7 Sep 2006 00:03:38
Message: <44ff9a1a$1@news.povray.org>
> Has anybody experimented with creating RGB normal maps in POV-Ray? Is it
> possible?

Yes, I've been finding POV-Ray quite useful for the task. I have the
following in an include file:

#macro DisplayTexture(Texture)
 camera {
  orthographic
  location <.5,.5,-1>
  right x
  up y
  direction z
 }

 light_source {
  <-.7,1,-.7>*999
  rgb 1
 }

 sky_sphere {
  pigment {checker rgb 0 rgb 1}
  scale .1
 }

 plane {
  -z,0
  texture {
   Texture
  }
 }
#end

#macro DisplayPig(Pigment)
 camera {
  orthographic
  location <.5,.5,-1>
  right x
  up y
  direction z
 }

 plane {
  -z,0
  pigment {
   Pigment
  }
  finish {ambient 1 diffuse 0}
 }
#end

#macro Normal(BasePigment, ZScale, Accuracy)
 #local PigmentBase = function {pigment{BasePigment}}
 #local Base = function {PigmentBase(x,y,z).grey}

 #local acc = Accuracy;

 #local BaseX = function // dx
 {
  (Base(x + acc,y,z) - Base(x - acc,y,z)) / (2*acc) * ZScale
 }
 #local BaseY = function // dy
 {
  (Base(x,y + acc,z) - Base(x,y - acc,z)) / (2*acc) * ZScale
 }
 #local BaseXY = function // full horizontal derivative
 {
  sqrt(pow(BaseX(x,y,z),2) + pow(BaseY(x,y,z),2))
 }
 #local XYCalc = function(x)
 {
  ((-x/sqrt(1+x*x)) + 1)/2 // take slope and convert to horizontal component
of normal; then scale to the range 0 to 1
 }
 #local Red = function
 {
  XYCalc(BaseX(x,y,z))
 }
 #local Green = function
 {
  //Base(x,y,z)
  XYCalc(BaseY(x,y,z))
 }
 #local ZCalc = function(x)
 {
  sqrt(1-x*x) // take slope and convert to vertical component of normal
 }
 #local Blue = function
 {
  ZCalc(
   BaseXY(x,y,z)
  )
  //Base(x,y,z)
 }

 DisplayPig (
  pigment {
   average
   pigment_map {
    [1 function {Red(x,y,z)  } color_map{[0 rgb 0] [1 rgb 3*x]}]
    [1 function {Green(x,y,z)} color_map{[0 rgb 0] [1 rgb 3*y]}]
    [1 function {Blue(x,y,z) } color_map{[0 rgb 0] [1 rgb 3*z]}]
   }
  }
 )
#end

#macro Normalize(BasePigment)
 #local PigmentBase = function {pigment{BasePigment}}

 #local Len = function {sqrt(x*x+y*y+z*z)}

 #local Magnitude = function {

Len(PigmentBase(x,y,z).x*2-1,PigmentBase(x,y,z).y*2-1,PigmentBase(x,y,z).z)
 }

 #local Red = function {(PigmentBase(x,y,z).x*2-1)/Magnitude(x,y,z) * .5 +
.5}
 #local Green = function {(PigmentBase(x,y,z).y*2-1)/Magnitude(x,y,z) * .5 +
.5}
 #local Blue = function {PigmentBase(x,y,z).z/Magnitude(x,y,z)}

 DisplayPig (
  pigment {
   average
   pigment_map {
    [1 function {Red(x,y,z)  } color_map{[0 rgb 0] [1 rgb 3*x]}]
    [1 function {Green(x,y,z)} color_map{[0 rgb 0] [1 rgb 3*y]}]
    [1 function {Blue(x,y,z) } color_map{[0 rgb 0] [1 rgb 3*z]}]
   }
  }
 )
#end




I use it like this:

#declare bumpy = pigment {bumps scale .1}
Normal(bumpy, .1, .0001) // height of .1, sample width of .0001

Also handy is the Normalize function, which takes an existing normal map
(possibly from an external texture) and normalizes each pixel.

 - Slime
 [ http://www.slimeland.com/ ]


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.