Normal Map aus Bump-Map berechnen



  • Hallo,
    ich habe einen HLSL Shader, der aus einer Bump Map eine Normal-Map berechen soll:

    //--------------------------------------------------------------------------------------
    // Global variables
    //--------------------------------------------------------------------------------------
    cbuffer cb0
    {
    	float4 g_MaterialAmbientColor;      // Material's ambient color
    	float4 g_MaterialDiffuseColor;      // Material's diffuse color
    	float3 g_vLightDir;                  // Light's direction in world space
    	float4 g_LightDiffuse;              // Light's diffuse color
    
    	float    g_fTime;                   // App's time in seconds
    	float4x4 g_mWorld;                  // World matrix for object
    	float4x4 g_mWorldViewProjection;    // World * View * Projection matrix
    
    	    //Für Full-Screen-Rendering    
        float4 QuadPositionTexCoordsFullScreen[] = 
        {
    	    float4(-1,-1,0,1),
    	    float4(-1,+1,0,0),
    	    float4(+1,-1,1,1),
    	    float4(+1,+1,1,0),
        };
    }
    
    Texture2D g_MeshTexture;                // Color texture for mesh
    
    //--------------------------------------------------------------------------------------
    // Texture samplers
    //--------------------------------------------------------------------------------------
    SamplerState MeshTextureSampler
    {
        Filter = MIN_MAG_MIP_LINEAR;
        AddressU = Wrap;
        AddressV = Wrap;
    };
    
    //--------------------------------------------------------------------------------------
    // Vertex shader output structure
    //--------------------------------------------------------------------------------------
    struct VS_OUTPUT
    {
        float4 Position   : SV_Position;   // vertex position 
        float4 Diffuse    : COLOR0;     // vertex diffuse color (note that COLOR0 is clamped from 0..1)
        float2 TextureUV  : TEXCOORD0;  // vertex texture coords 
    };
    
    VS_OUTPUT RenderWithTextureFullScreenVS(uint VertexId: SV_VertexID)
    {
        VS_OUTPUT Output = (VS_OUTPUT)0;
        Output.Position = float4(QuadPositionTexCoordsFullScreen[VertexId].xy, 0, 1);
    
        Output.Diffuse.rgb = float3(0.5f, 0.5f, 1.0f);   
        Output.Diffuse.a = 1.0f; 
    
    Output.TextureUV = QuadPositionTexCoordsFullScreen[VertexId].zw;
    
        return Output;
    }
    
    float4 RenderScenePS( VS_OUTPUT In ) : SV_Target
    { 
    float4 normalTap = g_MeshTexture.Sample(MeshTextureSampler, In.TextureUV);
    float3 tanNormal = normalTap.xyz * 2.0 - float3( 1.0, 1.0, 1.0 );
    
    float mapSize = 512.0;
    float bumpHeight = 2.0;
    
    float normalTapOver = g_MeshTexture.Sample(MeshTextureSampler, In.TextureUV+ float2( 1.0 / mapSize, 0.0 )) * 2.0 - 1.0;
    float normalTapUp = g_MeshTexture.Sample(MeshTextureSampler, In.TextureUV + float2( 0.0, 1.0 / mapSize ) ) * 2.0 - 1.0;
    
    tanNormal *= bumpHeight;
    normalTapOver *= bumpHeight;
    normalTapUp *= bumpHeight;
    
    float3 eugTanNormal = normalize( float3( tanNormal.x - normalTapOver, ( tanNormal.x - normalTapUp ), 1.0 ) );
    
      tanNormal = eugTanNormal;
      return float4(tanNormal, 1);
    }
    
    technique11 RenderSceneX
    {
        pass P0
        {       
    	SetVertexShader( CompileShader(vs_4_0, RenderWithTextureFullScreenVS() ) );
            SetGeometryShader( NULL );
            SetPixelShader( CompileShader(ps_4_0, RenderScenePS() ) );
        }
    }
    

    Wenn ich ihn mit dieser Bump-Map ausführe:
    http://imageshack.us/photo/my-images/10/bumpdq.png/

    Kommt das bei raus:
    http://imageshack.us/photo/my-images/263/rttmr.png/

    Aber eigentlich sollte so etwas rauskommen:
    http://imageshack.us/photo/my-images/849/bumpn.png/ (mit GIMP erzeugt)

    Was mache ich falsch?



  • Ich habe das mal auf die Schnelle ausprobiert und meine Vermutung bestätigt.

    Das soll-Bild verwendet nur die obere Hälfte des Farbberreiches. Also Anstelle des ganzen RGBA Bereiches 0 - 255 (bzw. 0.0 - 1.0), den Bereich 128 - 255 (bzw. 0.5 - 1.0).

    Entweder die Berrechnungen darauf umstellen, oder am Ende korrigieren:
    R = R / 2 + 0.5
    G = G / 2 + 0.5
    B = B / 2 + 0.5
    A = A / 2 + 0.5

    Und anschließend noch einen einfachen Weichzeichner (oder Antialiasing) wie auch immer du dass nenen möchtest.



  • Ok, es funktioniert. 🙂
    Danke!!! 😉


Anmelden zum Antworten