【问题标题】:Retrieving normal after rotating an instance model in HLSL在 HLSL 中旋转实例模型后检索正常
【发布时间】:2016-06-04 17:00:16
【问题描述】:

我开始使用“实例化模型”技术来绘制场景,但法线的顶点有问题

我将 MATRIX(旋转/缩放/位置)提供给 HLSL 以绘制模型的每个实例,但旋转它们后我无法获得良好的法线。

应用 MATRIX 后,我的模型的 3D 计算工作正常,但是根据正常方向,光线真的很奇怪。

struct InstancingVSinput
{
    float4 Position : SV_POSITION0;
    float4 Norm : NORMAL0;
    float2 TexCoord : TEXCOORD0;
};

struct InstancingVSoutput
{
    float4 Position : POSITION0;
    float3 Norm : NORMAL0;
    float2 TexCoord : TEXCOORD0;
};

    InstancingVSoutput InstancingVS(InstancingVSinput input, 
                                    float4 InstPos : POSITION1, float4 InstTexCoord : TEXCOORD1,
                                    float4 Mat1 : POSITION2, float4 Mat2 : POSITION3, float4 Mat3 : POSITION4, float4 Mat4 : POSITION5)
    {
        InstancingVSoutput output;

        float4x4 O = float4x4(Mat1, Mat2, Mat3, Mat4);

        float4 pos = mul(input.Position,xWorld);
        pos = mul(input.Position, O);
        pos = InstPos + pos;

        O = transpose(O);

        float3 norm = normalize((float3)input.Norm);
        norm = mul(norm, (float3x3)O);

        pos = mul(pos, WVP);

        output.Position = pos;
        output.Norm = norm;

        output.TexCoord = float2((input.TexCoord.x / 2.0f) + (1.0f / 2.0f * InstTexCoord.x),
                                 (input.TexCoord.y / 2.0f) + (1.0f / 2.0f * InstTexCoord.y));
        return output;
    }

    float4 InstancingPS(InstancingVSoutput input) : COLOR0
    {
        float4 C = tex2D(TextureSampler, input.TexCoord);
        float3 N = input.Norm;
        C.rgb *= dot(float3(0, -1, -1), N);
        return C;
    }

您是否应该建议我在旋转后恢复正常的正确方法?

感谢

克里斯

【问题讨论】:

    标签: model xna hlsl normals geometry-instancing


    【解决方案1】:

    如果您的实例矩阵包含任何缩放,则需要在乘法之后对法线进行归一化。此外,如果缩放不均匀,则必须将输入法线乘以矩阵的inverse transpose。目前您只应用转置,而不应用反转。

    但是,计算矩阵的逆是一项昂贵的操作,因此请考虑在着色器之外预先计算它。

    【讨论】:

    • 谢谢你的回答,我去试试……会看到
    • 对不起,但是在尝试之后,它不起作用......似乎每个实例都被几何图形很好地旋转,但面被照亮,因为它们不会被旋转
    【解决方案2】:

    我修改了以下几行来表达您的解决方案:

    1 - 准备实例属性,只需添加一个新的逆转置矩阵(预先计算)

            Matrix MatRot = Matrix.CreateRotationX(3 - rnd.Next(6)) * 
                            Matrix.CreateRotationY(3 - rnd.Next(6)) * 
                            Matrix.CreateRotationZ(3 - rnd.Next(6));
            instances[i].Geometry = Matrix.CreateScale(0.5f + rnd.Next(2)) * MatRot;
            instances[i].Inverse = Matrix.Transpose(Matrix.Invert(MatRot));
    

    2 - 着色器接收这个新矩阵并将其用于每个模型的法线

    float4x4 WVP;
    float4x4 WV;
    float4x4 xLightView;
    float4x4 xLightProj;
    float4x4 xWorld;
    
    texture cubeTexture;
    sampler TextureSampler = sampler_state
    {
        texture = <cubeTexture>;
        mipfilter = LINEAR;
        minfilter = LINEAR;
        magfilter = LINEAR;
    };
    
    struct InstancingVSinput
    {
        float4 Position : SV_POSITION;
        float4 Norm : NORMAL0;
        float2 TexCoord : TEXCOORD0;
    };
    
    struct InstancingVSoutput
    {
        float4 Position : POSITION0;
        float4 Norm : NORMAL0;
        float2 TexCoord : TEXCOORD0;
    };
    
    InstancingVSoutput InstancingVS(InstancingVSinput input, 
                                    float4 InstPos : POSITION1, float4 InstTexCoord : TEXCOORD1,
                                    float4 Mat1 : POSITION2, float4 Mat2 : POSITION3, float4 Mat3 : POSITION4, float4 Mat4 : POSITION5,
                                    float4 Mat5 : POSITION6, float4 Mat6 : POSITION7, float4 Mat7 : POSITION8, float4 Mat8 : POSITION9)
    {
        InstancingVSoutput output;
    
        float4x4 O = float4x4(Mat1, Mat2, Mat3, Mat4);
        float4x4 I = float4x4(Mat5, Mat6, Mat7, Mat8);
    
        float4 pos = mul(input.Position,xWorld);
        pos = mul(input.Position, O);
        pos = InstPos + pos;
    
        pos = mul(pos, WVP);
        output.Position = pos;
    
        output.Norm = normalize(mul(input.Norm,I));
    
        output.TexCoord = float2((input.TexCoord.x / 2.0f) + (1.0f / 2.0f * InstTexCoord.x),
                                 (input.TexCoord.y / 2.0f) + (1.0f / 2.0f * InstTexCoord.y));
    
        return output;
    }
    
    float4 InstancingPS(InstancingVSoutput input) : COLOR0
    {
        float4 C = tex2D(TextureSampler, input.TexCoord);
    
        C.rgb *= dot(input.Norm , normalize(float3(0, -1, -1)));
        return C;
    }
    
    technique Instancing
    {
        pass Pass0
        {
            VertexShader = compile vs_5_0 InstancingVS();
            PixelShader = compile ps_5_0 InstancingPS();
        }
    }
    

    一个想法?

    【讨论】:

      【解决方案3】:

      如你所见,根据正常情况,我的脸没有很好的曝光度

      Click to see picture

      【讨论】:

        【解决方案4】:

        问题解决了,没关系。事实上,HLSL 代码很好……但由于顶点法线计算错误,问题一直存在。现在我的脸很好,光线方向很好。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多