Malkior

Bump Mapping Research

Recommended Posts

I've been curious ever since I found the "bumpmaptexture" string in the text field on the Hutt texture, so I finally opened the C_Hutt01b file in Photoshop and here's what I saw.

 

 

Now, I'm not too familiar with the NWN engine's complexities, but that looks like a proper Normal Map! This leads into my overall goal of possibly adding bumps to more texture geometry if someone could decipher whatever code is in the texture text under the preview window of the KotorTool. and then possibly try a different normal map and see if it works.

Perhaps when they add a different bumpmap to a different texture they can reference it using that code.

  • Like 1

Share this post


Link to post
Share on other sites

Fairly substantial amounts of work were done on this over at LF. Nothing has ever come of it.

Share this post


Link to post
Share on other sites

Fairly substantial amounts of work were done on this over at LF. Nothing has ever come of it.

 

Was it too unfeasible to implement or was it stalled due to a lack of interest?

Share this post


Link to post
Share on other sites

From my own experiments - even vanilla tpc's such as Rakghouls that use these - don't add geometry but create more complex (more than just alpha channel) shading effects. The difference is barely noticeable from my point of view. They probably ripped out support for this to make it X-box compatible, seeing that the X-box is way less powerful.

 

However, I'm going to experiment more and see what I can find.

Share this post


Link to post
Share on other sites

 

 


From my own experiments - even vanilla tpc's such as Rakghouls that use these - don't add geometry but create more complex (more than just alpha channel) shading effects. The difference is barely noticeable from my point of view. They probably ripped out support for this to make it X-box compatible, seeing that the X-box is way less powerful.

However, I'm going to experiment more and see what I can find.


And if anything relevant is out I will make bumpmaps. and specular ones as well.

Share this post


Link to post
Share on other sites

i heard something about that actually, was he also the guy who used the dds format instead of tga? that might help actually considering there are various options when saving as dds in ps, one of them, iirc, had to do with normal maps, or in the kotor engine, bumpmaps. we also have some information on the wiki about it though more info is being added.

Share this post


Link to post
Share on other sites

 

 


Was he also the guy who used the DDS format instead of TGA?


Yes, he was. However, most folks requested he change his files back to TGA. I think he used the DDS format for space-saving reasons, IIRC.

Share this post


Link to post
Share on other sites

Sorry, to resurrect this thread, but I felt this is a better place to put what I found than into a new thread. 

Where to begin? Well, I have found out something for sure, we can make bump maps, they have to be in grayscale, that means  not rgb mode but grayscale mode in photoshop, with no alpha channel

 

post-9663-0-81663000-1417055521_thumb.jpg

 

And as for dimensions,  they must be a power of 2 squared, (2x2, 4x4, 8x8, ... , 256x256, 512x512, 1024x1024, 2048x2048... etc.)

 

So now we have a texture that is considered a valid bumpmap, it won't crash your game, and will work when called/defined as a bumpmap.

 

In its txi there are some fields we can now fill namely:

isbumpmap 1 // Mandatory, without this it won't be treated as a bumpmap
bumpmapscaling 1 // this is for how high or low the bumps should be  (0.5, 0.75, 1, 2.25 etc.)

The following are some commands, from Never Winter Nights, that are in the kotor/tsl .exe but I haven't tested out in game yet

 

// Specify what kind of bumpmapping this bump map will do: specular, diffuse, or both.  These values are ignored if this texture is not a bump map.


isdiffusebumpmap  1
isspecularbumpmap 1


// Specify a color for specular bumpmap highlights (RGB). This value is modulated with the bumpmapping light's color to produce the final highlight color. 1=255, 0=0
specularcolor 0.5 0.5 0.8

So, here comes the theortical part.

How does kotor do bump maps? in two ways,

 

A from a grayscale texture then renders a tangent normal map,

post-9663-0-19461600-1417059648_thumb.jpg

 

B from a pre rendered tangent-space normal map.

post-9663-0-11968900-1417059675_thumb.jpg

 

Almost all the bumpmaps in kotor are prerendered, they come out in rgb when we extract the with ktool, but they also always crash the tpc viewer. It seems this is the more efficient way to do it, but it is not something currently we can do, (we can keep experimenting) but what was needed for efficiency in 2003, is a luxury, I'd say we can afford to take in 2014.

 

in the end the gpu get's the same thing from either method, (according to glintercept).

post-9663-0-80861000-1417059844_thumb.jpg

 

Lastly here is the experiment I ran, let's see what we can do now with bump maps!

my experiment:

post-9663-0-00000900-1417060060_thumb.jpg

  • Like 3

Share this post


Link to post
Share on other sites

OMG!  YOU DID IT!!!

That's an amazing find, DS. I think I can put it to good use;)

Share this post


Link to post
Share on other sites

You do realize many of our dreams can now be reality..

 

Basically Kotor's one big weakness graphically is how flat it looks. That is now quite likely a thing of the past.

 

 

I've a million ideas, but first I think fixing most of the clothes is in order. Also, you know, Sion...

  • Like 1

Share this post


Link to post
Share on other sites

You do realize many of our dreams can now be reality..

 

Basically Kotor's one big weakness graphically is how flat it looks. That is now quite likely a thing of the past.

 

 

I've a million ideas, but first I think fixing most of the clothes is in order. Also, you know, Sion...

And with the new cubemaps, you might replace CM_Baremetal in your Realistic Aliens and Eyes mod(s)...:D

Share this post


Link to post
Share on other sites

The bad/good news,

 

The good news:

the games both use bump maps the exact same way,

 

The bad news:

Not all models accept the bump maps, For example, I couldn't get any sort of custom bump map to work on any models that don't support it (space suit, robes, Nihilus, Mandalor,e etc.) Some that do for sure are the Twi'lek male head, the Quarren, the Rakghouls, etc.,  in TSL. In KotOR1, Hutts do too (for some reason Obsidian cut this for Vogga)  :(

 

I think this is something we need to edit models for, but that is far from my area of expertise. Help me [unknown super modder], you're my only hope!

Share this post


Link to post
Share on other sites

So, it is possible to get envmaps to work on those models. (I've done it before). Can't remember what I did, but I think it's best to cover as many bases as possible. Txi, appearance.2da, there's a property in the .mdl you need to make sure is set.... etc

Share this post


Link to post
Share on other sites

So, it is possible to get envmaps to work on those models. (I've done it before). Can't remember what I did, but I think it's best to cover as many bases as possible. Txi, appearance.2da, there's a property in the .mdl you need to make sure is set.... etc

well i can crossout txi & appearance 2da, so they're either hard coded, or they're in the model, i really doubt them being hard coded, in all the string-dumping i have done on swkotor2.exe i have only seen bumpmaps mentioned in the txi code.

Share this post


Link to post
Share on other sites

after doing some thinking i feel almost as if it's in the mdl of the file, specifically it has to do with materials, i think the game loads the model , the model gives it a list of textures, with various parameters, one of them having to do with bump mapping, for example the quarren, is all one model right? but we can only apply a functional bump map to his head. a visible example (not my screen btw, bottom right on the wall)

 

 

88702_2.jpg

 

 

notice how only the one texture/material has a bump map?, also when i tried earlier to bump map the dantooine cliff, nothing happened, but the water definitely has a bump map going on. iirc they are on the same model.

Share this post


Link to post
Share on other sites

after doing some thinking i feel almost as if it's in the mdl of the file, specifically it has to do with materials, i think the game loads the model , the model gives it a list of textures, with various parameters, one of them having to do with bump mapping, for example the quarren, is all one model right? but we can only apply a functional bump map to his head.

That makes sense to me. Once upon a time I modified the male Twilek head mdl (so that it doesn't have the neck sac and added mask and goggle hooks). Taina's replacer method never worked with that model, so I used VarsityPuppet's HeadFixer method. While I did get the head to work in game, it lost two important qualities: the edge smoothing groups was lost, and apparently the connection to the bump map was also lost. I suspect that it has more to do with exporting from 3DS Max rather than the HeadFixer, and it probably has more to do with the mdx not the mdl. I'd guess that since we need the NWN plugin to import Kotor models into Max, that we might also need some kind of plugin to export the model with ALL the correct info intact. Or maybe the problem is with MDLOps converting the ascii file into binary.

Share this post


Link to post
Share on other sites

That makes sense to me. Once upon a time I moified the male Twilek head mdl (so that it doesn't have the neck sac and added mask and goggle hooks). Taina's replacer method never worked with that model, so I used VarsityPuppet's HeadFixer method. While I did get the head to work in game, it lost two important qualities: the edge smoothing groups was lost, and apparently the connection to the bump map was also lost. I suspect that it has more to do with exporting from 3DS Max rather than the HeadFixer, and it probably has more to do with the mdx not the mdl. I'd guess that since we need the NWN plugin to import Kotor models into Max, that we might also need some kind of plugin to export the model with ALL the correct info intact. Or maybe the problem is with MDLOps converting the ascii file into binary.

 

I am offended! Haha, jk.

 

I think it may have to do with the ascii model. I exported my armored robes and those seemed to retain specular mapping (on the armor part at least, since that was the part of the model that originally used the specular mapping)

Share this post


Link to post
Share on other sites

so i have sent MagnusII a pm on LF, here is what he had to say:

 

This is what I know of the trimesh header structure of kotor's MDL files:


 public class TriMeshHeader
        {
            public static int KotorI_Size  = 332;
            public static int KotorII_Size = 340;

            #region Private Members
            private int _KotorVersion;
    /*0*/   private UInt32 _FunctionPointer0; /* 4216656 K1, 4216592 K1 SkinMesh, 4216640 K1 DanglyMesh
                                               * 4216880 K2, 4216816 K2 SkinMesh, 4216864 K2 DanglyMesh
                                               * */
            private UInt32 _FunctionPointer1; /* 4216672 K1, 4216608 K1 SkinMesh, 4216624 K1 DanglyMesh
                                               * 4216896 K2, 4216832 K2 SkinMesh, 4216848 K2 DanglyMesh
                                               * */
            private UInt32 _OffsetToFaces;
            private UInt32 _FacesCount;
            private UInt32 _DuplicateFacesCount;
            private KotorVertex _BoxMin;
            private KotorVertex _BoxMax;
            private float _Radius;
            private KotorVertex _AveragePoint;
   /*60*/   private float[] _DiffuseColor = new float[3];
            private float[] _AmbientColor = new float[3];
            private UInt32 _Shininess_Tentative;    /* 0 (mostly), 1, 2, 3, 4, 5, 7, 8, 13
                                                     * Blend Factor, SamplerStageStates, TextureOperation?
                                                     */
            private byte[] _Texture1Name = new byte[32];
  /*120*/   private byte[] _Texture2Name = new byte[32];
            private byte[] _Texture3Name = new byte[12];
            private byte[] _Texture4Name = new byte[12];
            private UInt32 _OffsetToVerticesIndexesCounts;
  /*180*/   private UInt32 _VerticesIndexesCountsCount;   // = 1
            private UInt32 _DuplicateVerticesIndexesCountsCount;
            private UInt32 _OffsetToVerticesOffsets;
            private UInt32 _VerticesOffsetsCount;         // = 1
            private UInt32 _DuplicateVerticesOffsetsCount;
 /*200*/    private UInt32 _OffsetToTrimeshInvertedCountersArray;
            private UInt32 _TrimeshInvertedCountersArrayItemsCount; /* 
                                                           * = 1, always one UInt32
                                                           * sequence goes like this: first
                                                           * trimesh node is 98, then:
                                                           * 98..00, 100
                                                           * 199..101, 200
                                                           * 399..?
                                                           */
            private UInt32 _DuplicateTrimeshInvertedCountersArrayItemsCount;
            private Int32[] _Unknown1 = new Int32[3];     // -1, -1, 0
  /*224*/   private byte _SaberUnknown1;   // 3 for non-saber
            private byte _SaberUnknown2;   // 0 for non-saber
            private byte _SaberUnknown3;   // 0 for non-saber
            private byte _SaberUnknown4;   // 0 for non-saber
            private byte _SaberUnknown5;   // 0 for non-saber
            private byte _SaberUnknown6;   // 0 for non-saber
            private byte _SaberUnknown7;   // 0 for non-saber
            private byte _SaberUnknown8;   // 0 for non-saber, 17 for sabers
            private Int32 _SparkleTentative; /* 0 for most, 1 for water and clouds and
                                              * one piece of the GUI
                                              * Maybe some sparkle or reflex effects,
                                              * or a specular lighting modifier?
                                              */
            private Rotation _UnknownRotation = null;
            private Int32 _MDXDataSize;  /* mostly 24, 32, 40, 76 with a smattering of other values
                                          * if textures = 0 almost always 24, except 15 models with -1 and 23 with 60
                                          * if textures = 1, almost always 32, with several 64 and 68, and a bunch of 100 and 0
                                          * if textures = 2, it's either 40 (mostly) or 76
                                          */
            private UInt32 _MDXDataBitmap; /* which data is present in MDX
                                            * according to MDXDatabits
                                            */
  /*260*/   private Int32 _OffsetToVerticesInMDX; // = 0 for most, -1 for lightsabers or when verticescount = 0
            private Int32 _OffsetToNormalsInMDX;  // = 12
            private Int32 _OffsetToUnknownInMDX;  // = -1, never present
            private Int32 _OffsetToUVsInMDX;      // = 24 if present
            private Int32 _OffsetToUV2sInMDX;     /* -1, 24, 32
                                   * if mdxdatasize = 24 then it's always -1
                                   * if mdxdatasize = 32 it's almost always -1 except for 14 models where it's 24
                                   * if mdxdatasize = 40 or 76 then it's always 32
                                   */
            private Int32 _OffsetToUV3sInMDX;  // = -1, never present
            private Int32 _OffsetToUV4sInMDX;  // = -1, never present
            private Int32 _OffsetToUnknownStructInMDX; /* -1, 24, 32, 40
                                   * if mdxdatasize = 24 or 32 or 40 then it's always -1
                                   * if mdxdatasize = 76 then it's always 40
                                   * this is basically whatever info is in the MDX
                                   * after the last texture UV coordinates and
                                   * before the bones. It is 36 bytes long.
                                   * the last three of these values seem to be some sort of
                                   * "weighted normals"... they definitely have something
                                   * to do with normals as at least one of these triplets
                                   * was equal to the normal in c_hutt --> eye01, and the others
                                   * have similar values
                                   */
            private Int32 _OffsetToUnusedMDXStructure1; // -1
            private Int32 _OffsetToUnusedMDXStructure2; // -1
  /*300*/   private Int32 _OffsetToUnusedMDXStructure3; // -1
            private UInt16 _VerticesCount;
            private UInt16 _TexturesCount;
            private UInt16 _HasLightmap;    //0, 1
            private UInt16 _Shadow;     // 0, 256
            private UInt16 _Render;     // 0, 256
            private UInt16 _Unknown2;   // ??
            private float _TotalArea;   // sum of faces' areas
  /*320*/   private UInt32 _Unknown4;   // = 0
            private UInt32 _Kotor2Unknown1;
            private UInt32 _Kotor2Unknown2;
            private UInt32 _OffsetToMDXData;
            private UInt32 _OffsetToVertices

As you can see from the comments in the code, there are several fields I never managed to fully decode. What I do know is that theoretically the thing supports up to 4 textures applied to the models. First one is the texture proper, second is the lightmap where present. I don't remember all that well since I've not touched this stuff in years but if I'm not mistaken I never found anything in either Kotor I or II having more than two textures applied to it.
A potential candidate for some sort of bump mapping info would be _OffsetToUnknownStructInMDX, a pointer to some kind of small data structure which I could never fully decipher.

 

 

i'd wager the four textures are, the base, the lightmap, the bumpmap and the environment map.

  • Thanks 1

Share this post


Link to post
Share on other sites

here's something interesting. I opened twilek_m01b.tpc and twilek_m01b.tga with a hex editor. The tpc had a bunch of empty bytes (is that correct term? they all say 00) for the first eight lines. Then at the end of the file came the isbumpmap 1 bumpmapscaling 1    xbox_downsample 128. The tga (converted by MDLOPs) only had one line of mostly 00 at the beginning, while at the end it had isbumpmap etc... then 76 hex digits, then it repeated isbumpmap etc... The result is that the tga had 18 extra hex digits over the tcp version.

 

Then, I opened the tga with Photoshop, and saved it as a copy tga. When I checked it with a hex editor, this version had 87534 fewer characters than the original version.

 

I have no idea what any of that means :question:. If you need some pixels or vertices pushed around, I'm your guy. If there is eldritch languages, call Robert Langdon to figure out the DaVinci Code :laughing:

 

I honestly wish I was more help :blush:

  • Haha 1

Share this post


Link to post
Share on other sites

here's something interesting. I opened twilek_m01b.tpc and twilek_m01b.tga with a hex editor. The tpc had a bunch of empty bytes (is that correct term? they all say 00) for the first eight lines. Then at the end of the file came the isbumpmap 1 bumpmapscaling 1    xbox_downsample 128. The tga (converted by MDLOPs) only had one line of mostly 00 at the beginning, while at the end it had isbumpmap etc... then 76 hex digits, then it repeated isbumpmap etc... The result is that the tga had 18 extra hex digits over the tcp version.

 

Then, I opened the tga with Photoshop, and saved it as a copy tga. When I checked it with a hex editor, this version had 87534 fewer characters than the original version.

 

I have no idea what any of that means :question:. If you need some pixels or vertices pushed around, I'm your guy. If there is eldritch languages, call Robert Langdon to figure out the DaVinci Code :laughing:

 

I honestly wish I was more help :blush:

actually your post over at LF sent me in the right direction, with the greyscale etc. so really you've been the biggest help yet :D you got me going on this, indirectly, but still.

Share this post


Link to post
Share on other sites

i'd wager the four textures are, the base, the lightmap, the bumpmap and the environment map.

I believe you're right. See, I tried to make a set of Sith Armors that have a different cube map for every color variant for testing purposes, but they all ended up using CM_BareMetal, even after I set the "envmaptexture" column (or whatever it was, something like that anyway) to DEFAULT for that appearance row. So it looks like the Sith soldier model has that info stored in somewhere.

 

Also, I tried to replace the water texture on Dantooine (LDA_water03) with another one, and dropped the changed file into the Override without a .txi file. It appeared just like it was if it had a .txi file that has all the same .txi info than the LDA_water03.tpc has.

Share this post


Link to post
Share on other sites

so i have sent MagnusII a pm on LF, here is what he had to say:

 

 

 

i'd wager the four textures are, the base, the lightmap, the bumpmap and the environment map.

 

Here are some tables from cchargin's site where he describes the binary .mdl and .mdx structure

http://home.comcast.net/~cchargin/kotor/mdl_info.html

 

Hopefully it will be useful to someone with more experience than I to make sense of it combined with MagnusII's info, so that the unknowns can be filled in.

Share this post


Link to post
Share on other sites

Here are some tables from cchargin's site where he describes the binary .mdl and .mdx structure

http://home.comcast.net/~cchargin/kotor/mdl_info.html

 

Hopefully it will be useful to someone with more experience than I to make sense of it combined with MagnusII's info, so that the unknowns can be filled in.

iirc you brought up the nwn binary format in the chat, it directly commented on bump mapping, we can do this guys! 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.