hlsl点光源问题

发布于 2024-10-02 16:36:40 字数 4281 浏览 5 评论 0原文

几天来我一直在尝试在 HLSL 中创建一个简单的点光源,我一直在遵循这个指南: D3DBook:(照明)直接光源

具体来说是衰减函数和点光源部分。这是我的代码:

    //------------------------------------------------------------------------------------------------------
// Global params provided by the app
//------------------------------------------------------------------------------------------------------
uniform extern float4x4 gWVP;
uniform extern float4x4 gWorldViewIT; //for normals
uniform extern float4x4 gWorldView;//work out view vector from all vertices
uniform extern float4x4 gLightMatrix;//light in view space
uniform extern float4x4 gWorld;

uniform extern float4 gDiffuseMtrl;
uniform extern float4 gAmbMtrl;
uniform extern float4 gSpecMtrl;

//lights
uniform extern float4 gLightCol = {1, 1, 1, 1}; //set to white
//uniform extern float4 gLightPos[4];
uniform extern float4 gLightPos[4] = {{0,0,3,0},{0,0,-1,0},{0,100,1,0},{0,-100,0,0}};
uniform extern float gLightPow[4] = {25,25,0.1,0.1};//range of light


uniform extern float roughness;//roughness per object
uniform extern float ref;//reflectance at normal//used in fresnel calculation

//pi
const shared float pi= 3.14159f; 

//attenuation constants
const float a_a = 0.0f;
const float a_b = 0.1f;
const float a_c = 1.0f;


//calculate light attenuation
float atten( float distance, float range, float a, float b, float c)
{
    float atten = 1.0f / ((a * distance * distance) + (b * distance) + c );

    //step clamps to 0 if out of range
    return step(distance, range) * saturate( atten );
}


//---------------------------------------------------------------------------------------------------------------------------
// Input channel (vertex shader)
//---------------------------------------------------------------------------------------------------------------------------
struct InputVS
{
    float3 posL : POSITION0;
    float3 Norm : NORMAL;

};  
//---------------------------------------------------------------------------------------------------------------------------
// Output channel (vertex shader)
//---------------------------------------------------------------------------------------------------------------------------
struct OutputVS
{
    float4 posH     : POSITION0;
    float4 col      : COLOR0;
};

//vertex shader//passthrough
OutputVS gourardVS(InputVS input)
{
    float n = 1/roughness;
    //Zero out our output
    OutputVS outVS = (OutputVS)0;

    //Transform to homogeneous clipspace
    outVS.posH = mul(float4(input.posL, 1.0f), gWVP);

    float4 col_amb = gAmbMtrl*gLightCol;
    float4 col_diff = gDiffuseMtrl*gLightCol;
    float4 col_spec = gSpecMtrl*gLightCol;

    //ambient term  
    float4 ambient={0.2, 0.2, 0.2, 1.00f};

    float4 finalColour=0;

    float diff = 0;

    float3 pWorld = mul( float4( input.posL, 1.0f ), gWorld).xyz;

    //normal
    float3 N =normalize(mul(float4(input.Norm, 1.0f),gWorldViewIT));

    //point lights
    float attenu = atten(distance(pWorld, gLightPos[1]), gLightPow[1], a_a, a_b, a_c);

    float3 l_dir= normalize(gLightPos[1] - pWorld);

    //n dot l
    float dotNL =  max(0, dot(N, l_dir));

    finalColour = float4( attenu * dotNL * col_diff);
    //}
    outVS.col = finalColour;// + (ambient * col_amb);
    outVS.col.a = 1;


    //return 
    return outVS;
}
//---------------------------------------------------------------------------------------------------------------------------
// Input channel pixel shader
//---------------------------------------------------------------------------------------------------------------------------
struct InputPS{
    float4 posH     : POSITION0;
    float4 col      : COLOR0;
};

float4 noPS(InputPS input): COLOR
{
return input.col;
}

technique Phong{
    pass P0
    { 
            Lighting       = TRUE;
            SpecularEnable = TRUE;
        vertexShader = compile vs_3_0 gourardVS();
        pixelShader = compile ps_3_0 noPS();
        //specify render device states associated with the pass
        //FillMode = WireFrame;
        //ShadeMode = Gouraud;
    }
}

我很确定传入的矩阵是正确的,因为我已经从定向光示例中重新调整了它的用途,因此这只会使 HLSL 代码成为问题的根源。这会输出正确的顶点,但无论我在灯光位置和功率阵列上使用什么值,它们几乎都不会被照亮。

I have been trying to create a simple point light in HLSL for a couple of days now, I have been following this guide:
D3DBook:(Lighting) Direct Light Sources

Specifically the attenuation function and section on point lights. Here is my code:

    //------------------------------------------------------------------------------------------------------
// Global params provided by the app
//------------------------------------------------------------------------------------------------------
uniform extern float4x4 gWVP;
uniform extern float4x4 gWorldViewIT; //for normals
uniform extern float4x4 gWorldView;//work out view vector from all vertices
uniform extern float4x4 gLightMatrix;//light in view space
uniform extern float4x4 gWorld;

uniform extern float4 gDiffuseMtrl;
uniform extern float4 gAmbMtrl;
uniform extern float4 gSpecMtrl;

//lights
uniform extern float4 gLightCol = {1, 1, 1, 1}; //set to white
//uniform extern float4 gLightPos[4];
uniform extern float4 gLightPos[4] = {{0,0,3,0},{0,0,-1,0},{0,100,1,0},{0,-100,0,0}};
uniform extern float gLightPow[4] = {25,25,0.1,0.1};//range of light


uniform extern float roughness;//roughness per object
uniform extern float ref;//reflectance at normal//used in fresnel calculation

//pi
const shared float pi= 3.14159f; 

//attenuation constants
const float a_a = 0.0f;
const float a_b = 0.1f;
const float a_c = 1.0f;


//calculate light attenuation
float atten( float distance, float range, float a, float b, float c)
{
    float atten = 1.0f / ((a * distance * distance) + (b * distance) + c );

    //step clamps to 0 if out of range
    return step(distance, range) * saturate( atten );
}


//---------------------------------------------------------------------------------------------------------------------------
// Input channel (vertex shader)
//---------------------------------------------------------------------------------------------------------------------------
struct InputVS
{
    float3 posL : POSITION0;
    float3 Norm : NORMAL;

};  
//---------------------------------------------------------------------------------------------------------------------------
// Output channel (vertex shader)
//---------------------------------------------------------------------------------------------------------------------------
struct OutputVS
{
    float4 posH     : POSITION0;
    float4 col      : COLOR0;
};

//vertex shader//passthrough
OutputVS gourardVS(InputVS input)
{
    float n = 1/roughness;
    //Zero out our output
    OutputVS outVS = (OutputVS)0;

    //Transform to homogeneous clipspace
    outVS.posH = mul(float4(input.posL, 1.0f), gWVP);

    float4 col_amb = gAmbMtrl*gLightCol;
    float4 col_diff = gDiffuseMtrl*gLightCol;
    float4 col_spec = gSpecMtrl*gLightCol;

    //ambient term  
    float4 ambient={0.2, 0.2, 0.2, 1.00f};

    float4 finalColour=0;

    float diff = 0;

    float3 pWorld = mul( float4( input.posL, 1.0f ), gWorld).xyz;

    //normal
    float3 N =normalize(mul(float4(input.Norm, 1.0f),gWorldViewIT));

    //point lights
    float attenu = atten(distance(pWorld, gLightPos[1]), gLightPow[1], a_a, a_b, a_c);

    float3 l_dir= normalize(gLightPos[1] - pWorld);

    //n dot l
    float dotNL =  max(0, dot(N, l_dir));

    finalColour = float4( attenu * dotNL * col_diff);
    //}
    outVS.col = finalColour;// + (ambient * col_amb);
    outVS.col.a = 1;


    //return 
    return outVS;
}
//---------------------------------------------------------------------------------------------------------------------------
// Input channel pixel shader
//---------------------------------------------------------------------------------------------------------------------------
struct InputPS{
    float4 posH     : POSITION0;
    float4 col      : COLOR0;
};

float4 noPS(InputPS input): COLOR
{
return input.col;
}

technique Phong{
    pass P0
    { 
            Lighting       = TRUE;
            SpecularEnable = TRUE;
        vertexShader = compile vs_3_0 gourardVS();
        pixelShader = compile ps_3_0 noPS();
        //specify render device states associated with the pass
        //FillMode = WireFrame;
        //ShadeMode = Gouraud;
    }
}

I'm pretty sure the matrices being passed in are correct as I have repurposed this from a directional light example, so this only leaves the HLSL code as the source of the problem. This outputs the correct vertices but they are almost unlit no matter what values I use on the light position and Power arrays.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

回心转意 2024-10-09 16:36:40

我终于发现问题了,光线方向在世界空间中,而法线在视图空间中,我忘记了通过视图矩阵(gLightMatrix)来转换光线方向,这里是修改后的代码:

...
float3 l_dir= normalize(gLightPos[1] - pWorld);

float3 L=normalize(mul(l_dir, gLightMatrix));

//n dot l
float dotNL =  max(0, dot(N, L));

finalColour = float4( attenu * dotNL * col_diff);
...

无论如何,谢谢大家,每个人都有一个看。

I finally found the problem, the light direction is in world space while the normals are in View space, I had forgot to transform the light direction by the view matrix(gLightMatrix) here is the revised code:

...
float3 l_dir= normalize(gLightPos[1] - pWorld);

float3 L=normalize(mul(l_dir, gLightMatrix));

//n dot l
float dotNL =  max(0, dot(N, L));

finalColour = float4( attenu * dotNL * col_diff);
...

Thank you anyway, everyone who had a look.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文