root/trunk/x42view.net/Helpers.TextureUtils.cs

Revision 493, 4.0 kB (checked in by phill, 1 year ago)

o Fixed normal map mipmapping.

Line 
1 /******************************************************************************
2         x42view.net - .x42 viewer and auditing tool
3         Copyright (C) 2007 HermitWorks Entertainment Corporation
4
5         This program is free software; you can redistribute it and/or modify it
6         under the terms of the GNU General Public License as published by the Free
7         Software Foundation; either version 2 of the License, or (at your option)
8         any later version.
9
10         This program is distributed in the hope that it will be useful, but
11         WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12         or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13         for more details.
14
15         You should have received a copy of the GNU General Public License along
16         with this program; if not, write to the
17        
18                 Free Software Foundation, Inc.
19                 51 Franklin Street, Fifth Floor
20                 Boston, MA  02110-1301, USA.
21 ******************************************************************************/
22
23 using System;
24 using System.Collections.Generic;
25 using System.Drawing;
26 using System.IO;
27
28 using Microsoft.DirectX;
29 using Microsoft.DirectX.Direct3D;
30
31 namespace x42view
32 {
33         partial class Helpers
34         {
35                 private static Vector3 UnpackVector( byte x, byte y, byte z )
36                 {
37                         const float s = 1.0F / 0xFF;
38
39                         return new Vector3(
40                                 x * s * 2 - 1,
41                                 y * s * 2 - 1,
42                                 z * s * 2 - 1 );
43                 }
44
45                 private static unsafe void DownsampleSurface( byte *dst, int dstPitch,
46                         byte *src, int srcPitch, int dstW, int dstH, int cx, int cy, int cz,
47                         int ca, int nc )
48                 {
49                         for( int y = 0; y < dstH; y++ )
50                         {
51                                 byte* dstR = dst + dstPitch * y;
52
53                                 byte* srcR0 = src + srcPitch * (y * 2 + 0);
54                                 byte* srcR1 = src + srcPitch * (y * 2 + 1);
55
56                                 for( int x = 0; x < dstW; x++ )
57                                 {
58                                         byte* d = dstR + nc * x;
59
60                                         byte* s0 = srcR0 + nc * (x * 2 + 0);
61                                         byte* s1 = srcR0 + nc * (x * 2 + 1);
62                                         byte* s2 = srcR1 + nc * (x * 2 + 0);
63                                         byte* s3 = srcR1 + nc * (x * 2 + 1);
64
65                                         Vector3 sv0 = UnpackVector( s0[cx], s0[cy], s0[cz] );
66                                         Vector3 sv1 = UnpackVector( s1[cx], s1[cy], s1[cz] );
67                                         Vector3 sv2 = UnpackVector( s2[cx], s2[cy], s2[cz] );
68                                         Vector3 sv3 = UnpackVector( s3[cx], s3[cy], s3[cz] );
69
70                                         Vector3 avgV = Vector3.Normalize( sv0 + sv1 + sv2 + sv3 ) *
71                                                 0.5F + new Vector3( 0.5F, 0.5F, 0.5F );
72
73                                         const float s = 0xFF;
74
75                                         d[cx] = (byte)(avgV.X * s);
76                                         d[cy] = (byte)(avgV.Y * s);
77                                         d[cz] = (byte)(avgV.Z * s);
78
79                                         if( ca != -1 )
80                                         {
81                                                 int avgA = (int)s0[ca] + (int)s1[ca] + (int)s2[ca] + (int)s3[ca];
82                                                 avgA /= 4;
83
84                                                 d[ca] = (byte)avgA;
85                                         }
86                                 }
87                         }
88                 }
89
90                 public static unsafe void GenerateNormalMapMips( Texture tex )
91                 {
92                         int cx, cy, cz, ca, nc;
93                         SurfaceDescription desc = tex.GetLevelDescription( 0 );
94
95                         switch( desc.Format )
96                         {
97                         case Format.A8R8G8B8:
98                                 cx = 2;
99                                 cy = 1;
100                                 cz = 0;
101                                 ca = 3;
102                                 nc = 4;
103                                 break;
104
105                         case Format.A8B8G8R8:
106                                 cx = 0;
107                                 cy = 1;
108                                 cz = 2;
109                                 ca = 3;
110                                 nc = 4;
111                                 break;
112
113                         case Format.R8G8B8:
114                                 cx = 0;
115                                 cy = 1;
116                                 cz = 2;
117                                 ca = -1;
118                                 nc = 3;
119                                 break;
120
121                         case Format.X8R8G8B8:
122                                 cx = 1;
123                                 cy = 2;
124                                 cz = 3;
125                                 ca = -1;
126                                 nc = 4;
127                                 break;
128
129                         default:
130                                 throw new NotSupportedException( "Unsupported normal map format." );
131                         }
132
133                         int w = desc.Width;
134                         int h = desc.Height;
135
136                         for( int i = 1; i < tex.LevelCount; i++ )
137                         {
138                                 w = Math.Max( w / 2, 1 );
139                                 h = Math.Max( h / 2, 1 );
140
141                                 using( Surface dst = tex.GetSurfaceLevel( i ) )
142                                 using( Surface src = tex.GetSurfaceLevel( i - 1 ) )
143                                 {                       
144                                         int dstPitch;
145                                         GraphicsStream sDst = dst.LockRectangle( LockFlags.None, out dstPitch );
146
147                                         int srcPitch;
148                                         GraphicsStream sSrc = src.LockRectangle( LockFlags.None, out srcPitch );
149
150                                         try
151                                         {
152                                                 DownsampleSurface( (byte*)sDst.InternalDataPointer, dstPitch,
153                                                         (byte*)sSrc.InternalDataPointer, srcPitch, w, h, cx, cy, cz, ca, nc );
154                                         }
155                                         finally
156                                         {
157                                                 src.UnlockRectangle();
158                                                 dst.UnlockRectangle();
159                                         }
160                                 }
161                         }
162                 }
163         }
164 }
Note: See TracBrowser for help on using the browser.