Author Topic: Stealing an idea from hardware to make normalmapping more feasible  (Read 2845 times)

0 Members and 1 Guest are viewing this topic.

Offline Stonemonkey

  • Pentium
  • *****
  • Posts: 1315
  • Karma: 96
    • View Profile
A problem I had previously with normal mapping was the size of the maps, using floats meant the maps used 12 bytes per pixel. Been thinking of ways to reduce that and remembered that dot3 in opengl used the 8 bit colour channels so I've come up with this:

Code: [Select]
option explicit

sub normalise(byref x as single,byref y as single,byref z as single)
    dim as single d=1.0/sqr(x*x+y*y+z*z)
    x*=d
    y*=d
    z*=d
end sub

function int_dot(byval vx as integer,byval vy as integer,byval vz as integer,byval map as integer)
    return (vx*((map shl 8)shr 24)+vy*((map shl 16)shr 24)+vz*((map shl 24)shr 24))shr 23
end function

'set up a couple of random vectors for test
randomize timer
dim as single vx0=rnd*100.0-50.0,vy0=rnd*100.0-50.0,vz0=rnd*100.0-50.0
dim as single vx1=rnd*100.0-50.0,vy1=rnd*100.0-50.0,vz1=rnd*100.0-50.0
normalise vx0,vy0,vz0
normalise vx1,vy1,vz1

print "float_dot = ";(vx0*vx1+vy0*vy1+vz0*vz1)*127.0
print


dim as integer ivx=vx0*127.0
dim as integer ivy=vy0*127.0
dim as integer ivz=vz0*127.0
'v0=read integer value from normal map
dim as integer v0=((ivx and &hff) shl 16)or((ivy and &hff) shl 8)or (ivz and &hff)

'ivx,ivy,ivz=interpolated fixed point normalised light vector (don't renormalise inside pixel loop for speed)
ivx=(vx1*127.0)shl 16
ivy=(vy1*127.0)shl 16
ivz=(vz1*127.0)shl 16

'calculate the dot product for normal mapping
print "int_dot =";int_dot(ivx,ivy,ivz,v0)

sleep
end

Cheers, Fryer.
« Last Edit: November 13, 2007 by Stonemonkey »

Offline Stonemonkey

  • Pentium
  • *****
  • Posts: 1315
  • Karma: 96
    • View Profile
Also got a spare 8 bits, thinking I could use for some sort of specular map.

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
In Direct3D, many of the bump maps only have 2 components per pixel - the normal is recreated from these and, IIRC, only has a hemisphere as the range instead of the full sphere.
Might want to start here http://msdn2.microsoft.com/en-us/library/bb172558.aspx at Mixed Formats, and do some searching.

Jim
Challenge Trophies Won:

Offline Stonemonkey

  • Pentium
  • *****
  • Posts: 1315
  • Karma: 96
    • View Profile
Cheers Jim, I think I could get some ideas from that. I've thought about using 2 values before but afaics it would involve calculating the 3rd value using a sqrt which would explain the hemisphere, unless I'm completely off track on that and it's doing something else.

Fryer.

EDIT:
just noticed on that page:
D3DFMT_CxV8U8 117 16-bit normal compression format. The texture sampler computes the C channel from: C = sqrt(1 - U2 - V2).

which is along the lines I'd been thinking, so is:
D3DFMT_L6V5U5 61 16-bit bump-map format with luminance using 6 bits for luminance, and 5 bits each for v and u.
something different?

EDIT again:
ah that's for bumpmapping where it adds some offset to the texture coordinates.
« Last Edit: November 13, 2007 by Stonemonkey »