Hi not sure if this is suited in this part of the forum or not, but here goes:
Im using www and loading textures and shaders on the fly. All going well, but the bumpmap I’m using is in greyscale rather than normalmap purple. Is there a way to do the conversion on the fly?
The only way to do it, is through TextureImporter, which is an EditorClass and that means, you can’t use in runtime…
I don’t see real restrictions why this isn’t allowed to do it in runtime, but the function for that isn’t exposed…
But you could do it yourself, I mean you could create a new texture on runtime which would be your normal map, and create it from your heightmap/or greyscale texture.
I’m already creating a new texture then replacing it with the bumpmap, but how would I programmatically do that? Is it something remotely like this: http://forum.unity3d.com/viewtopic.php?p=43884
?
Thanks for that advice Daniel, your endorsement of that thread was helpful. I am making good progress, though I dont really understand how it ends up purple…?
I actually don’t understand this either (even though it may be different things of this we don’t understand).
If you convert a uniform greyscale image (0.5,0.5,0.5) into normals (to make normals pointing straight from the surface) in photoshop for instance, they will end up as pixels with the values (0.5,0.5,1.0).
That doesn’t look like normalized vectors to me (they are longer than 1). And they also point in some 45 degree angled direction, not really fitting my internal view of a vector pointing in some 90 degree angle compared to the vertex tangent and binormal. I really haven’t the basics right in this, and I would love someone to clear out where I do it wrong. To really being creative with this stuff means to be able to visualize the technical details in your head, which I really can’t, it seems…
I’ve stalled on this for now, and I am completely out of my depth here anyway, but I was wondering if the shallow effect generated was due to making one pass at it? maybe for the three RGB channels the function has to be run three times? That might be a ludicrious suggestion but I was going to try that next- its a bit like wearing a blind fold and swinging at a pinata.
Also the built in Unity adaption has the slider for bump map height, so I wonder where that variable fits in to all of this?
I guess statistically when people make guesses every so often they actually guess correct.
Colour channels can only hold values in the range [0,1]. Components of normals need to have values between [-1,1]. To deal with this, normal values are scaled and biased by the following formula:
textureNormal = normal*0.5 + 0.5
And recovered from a normal map with:
normal = (textureNormal - 0.5)*2
So normal map with colour (0.5,0.5,1.0) is actually holding the normal (0, 0, 1), which is what you want for a flat surface.
I know this sounds facetious, but bump map height is the height of the bumps your data is supposed to represent. My guess is that right now you’re assuming that bumps range in height [0,1] with a distance of 1.0 between each pixel and its orthogonal neighbours. This means that you can have at most a 22.5 degree slope caused by opposite neighbours being black and white. The grayscale value should be multiplied by your bump height in order to give it a larger range. Bump height probably shouldn’t be more than 10 at the extreme, though.
Hi, I had a similar task where I needed to convert a downloaded grayscale texture into a normal map in purple, similar to the ones Unity generates during asset import. Below is the code that does this conversion. I hope it’s helpful to someone.
public static Texture2D ConvertToNormalMap(Texture2D sourceTexture, float heightmapScale = 0.25f)
{
int width = sourceTexture.width;
int height = sourceTexture.height;
Texture2D normalMap = new Texture2D(width, height, TextureFormat.RGBA32, true);
Color[] sourcePixels = sourceTexture.GetPixels();
Color[] normalPixels = new Color[width * height];
// Adapting the code to ensure proper depth enhancement
// Increasing heightmapScale to amplify the gradient effect
heightmapScale = Mathf.Clamp(heightmapScale, 0.0f, .3f) * 100f;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
int index = y * width + x;
var gs = sourcePixels[index].grayscale;
float xLeft = x > 0 ? sourcePixels[index - 1].grayscale : gs;
float xRight = x < width - 1 ? sourcePixels[index + 1].grayscale : gs;
float yUp = y > 0 ? sourcePixels[index - width].grayscale : gs;
float yDown = y < height - 1 ? sourcePixels[index + width].grayscale : gs;
// Calculate the gradient taking into account heightmapScale
float xGradient = (xRight - xLeft) * heightmapScale;
float yGradient = (yDown - yUp) * heightmapScale;
// Normalize the normal vector using the amplified gradient
Vector3 normal = new Vector3(-xGradient, -yGradient, 1.0f).normalized;
// Convert the normalized vector back to color, where each component lies in the range [0, 1]
normalPixels[index] = new Color(normal.x * 0.5f + 0.5f, normal.y * 0.5f + 0.5f,
normal.z * 0.5f + 0.5f, 1.0f);
}
}
normalMap.SetPixels(normalPixels);
normalMap.Apply();
// Set texture parameters for use as a normal map
normalMap.wrapMode = TextureWrapMode.Repeat;
normalMap.filterMode = FilterMode.Trilinear;
normalMap.anisoLevel = 1;
return normalMap;
}