-2
\$\begingroup\$

I started to make a small game in XNA . And recently i tried to add a "fog" on "pixel shader HLSL" with the class Effect from XNA . I search online about some tutorial and found many sample. But nothing want work on my game :-( . Before i already add a "fog" effect in my game and everything work, because i used the class "BasicEffect" but with the class "Effect" and HLSL, it's really more complicated. If somebody have an idea, it's will be wonderfull.

Thanks again.

Here is my code HLSL, i use.

// Both techniques share this same pixel shader.
float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
    //return tex2D(Sampler, input.TextureCoordinate) * input.Color;

    float d = length(input.TextureCoordinate - cameraPos);
    float l = saturate((d-fogNear)/(fogFar-fogNear));

    float fogFactory = clamp((d - fogNear) / (fogFar - fogNear), 0, 1) * l; 

    return tex2D(Sampler, input.TextureCoordinate) * lerp(input.Color, fogColor, fogFactory);
}

Thanks to the big boss user => @ClassicThunder

THE FINAL CODE HLSL ANSWER IS :

//-----------------------------------------------------------------------------
// WorldEffect.fx
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
// ARCADIA Game
//-----------------------------------------------------------------------------


// Camera settings.
float4x4 World;
float4x4 View;
float4x4 Projection;


// This sample uses a simple Lambert lighting model.
float3 LightDirection = normalize(float3(-1, -1, -1));
float3 DiffuseLight = 1.25;
float3 AmbientLight = 0.25;
uniform const float3    DiffuseColor = 1;
uniform const float     Alpha = 1;
uniform const float3    EmissiveColor = 0;
uniform const float3    SpecularColor = 1;
uniform const float     SpecularPower = 16;
uniform const float3    EyePosition;
// FOG attribut
uniform const float     FogEnabled;
uniform const float     FogStart;
uniform const float     FogEnd;
uniform const float3    FogColor;
float3 cameraPos : CAMERAPOS;

texture Texture;

sampler Sampler = sampler_state
{
    Texture = (Texture);
};




struct CommonVSOutput
{
    float4  Pos_ws;
    float4  Pos_ps;
    float4  Diffuse;
    float3  Specular;
    float   FogFactor;
};
struct VertexLightingVSOutputTx
{
    float4  PositionPS  : POSITION;     // Position in projection space
    float4  Diffuse     : COLOR0;
    float4  Specular    : COLOR1;
    float2  TexCoord    : TEXCOORD0;
};
struct VertexLightingPSInputTx
{
    float4  Diffuse     : COLOR0;
    float4  Specular    : COLOR1;
    float2  TexCoord    : TEXCOORD0;
};
struct VSInputTx
{
    float4  Position    : POSITION;
    float2  TexCoord    : TEXCOORD0;
};
//Vertex Shader Bits
float ComputeFogFactor(float d)
{
    //d is the distance to the geometry sampling from the camera
    //this simply returns a value that interpolates from 0 to 1 
    //with 0 starting at FogStart and 1 at FogEnd 
    return clamp((d - FogStart) / (FogEnd - FogStart), 0, 1) * FogEnabled;
}

CommonVSOutput ComputeCommonVSOutput(float4 position)
{
    CommonVSOutput vout;

    float4 pos_ws = mul(position, World);
        float4 pos_vs = mul(pos_ws, View);
        float4 pos_ps = mul(pos_vs, Projection);

        vout.Pos_ws = pos_ws;
    vout.Pos_ps = pos_ps;

    vout.Diffuse = float4(DiffuseColor.rgb + EmissiveColor, Alpha);
    vout.Specular = 0;
    vout.FogFactor = ComputeFogFactor(length(EyePosition - pos_ws));

    return vout;
}

VertexLightingVSOutputTx VSBasicTx(VSInputTx vin)
{
    VertexLightingVSOutputTx vout;

    CommonVSOutput cout = ComputeCommonVSOutput(vin.Position);

    vout.PositionPS = cout.Pos_ps;
    vout.Diffuse = cout.Diffuse;
    vout.Specular = float4(cout.Specular, cout.FogFactor);
    vout.TexCoord = vin.TexCoord;

    return vout;
}

float4 PSBasicTx(VertexLightingPSInputTx pin) : COLOR
{
    float4 color = tex2D(Sampler, pin.TexCoord) * pin.Diffuse + float4(pin.Specular.rgb, 0);
    color.rgb = lerp(color.rgb, FogColor, pin.Specular.w);
    return color;
}









// For rendering without instancing.
technique NoInstancing
{
    pass Pass0
    {
        //VertexShader = compile vs_2_0 NoInstancingVertexShader();
        VertexShader = compile vs_2_0 VSBasicTx();
        PixelShader = compile ps_2_0 PSBasicTx();
    }
}

Here is the screenShot

With effect enter image description here Without effect enter image description here

\$\endgroup\$
3
\$\begingroup\$

So as a warning I'm quite rusty with regards to shaders, but lets take a look at the BasicEffect's source code and see how Microsoft did it.

Overview of the shader pipeline. Most interesting bits below. For a fog shader BasicEffect utilizes the below 2 components.

  • A vertex shader performs per-vertex processing such as transformations, skinning, vertex displacement, and calculating per-vertex material attributes. Tessellation of higher-order primitives should be done before the vertex shader executes. As a minimum, a vertex shader must output vertex position in homogeneous clip space. Optionally, the vertex shader can output texture coordinates, vertex color, vertex lighting, fog factors, and so on.

  • A pixel shader performs per-pixel processing such as texture blending, lighting model computation, and per-pixel normal and/or environmental mapping. Pixel shaders work in concert with vertex shaders; the output of a vertex shader provides the inputs for a pixel shader.

Here is the code in BasicEffect's related to displaying the fog. You probably want to compare your PixelShaderFunction to the math in PSBasicTx. You have no depth in the PixelShader so this line doesn't make much sense float d = length(input.TextureCoordinate - cameraPos);. You should calculate the depth when you have access to the vertex information.

//Needed Variables
uniform const float     FogEnabled      : register(c0);
uniform const float     FogStart        : register(c1);
uniform const float     FogEnd          : register(c2);
uniform const float3    FogColor        : register(c3);

//Vertex Shader Bits
float ComputeFogFactor(float d) 
{
    //d is the distance to the geometry sampling from the camera
    //this simply returns a value that interpolates from 0 to 1 
    //with 0 starting at FogStart and 1 at FogEnd 
    return clamp((d - FogStart) / (FogEnd - FogStart), 0, 1) * FogEnabled;
}

CommonVSOutput ComputeCommonVSOutput(float4 position)
{
    CommonVSOutput vout;

    float4 pos_ws = mul(position, World);
    float4 pos_vs = mul(pos_ws, View);
    float4 pos_ps = mul(pos_vs, Projection);

    vout.Pos_ws = pos_ws;
    vout.Pos_ps = pos_ps;

    vout.Diffuse    = float4(DiffuseColor.rgb + EmissiveColor, Alpha);
    vout.Specular   = 0;
    vout.FogFactor  = ComputeFogFactor(length(EyePosition - pos_ws ));

    return vout;
}

VertexLightingVSOutputTx VSBasicTx(VSInputTx vin)
{
    VertexLightingVSOutputTx vout;

    CommonVSOutput cout = ComputeCommonVSOutput(vin.Position);

    vout.PositionPS = cout.Pos_ps;
    vout.Diffuse    = cout.Diffuse;
    vout.Specular   = float4(cout.Specular, cout.FogFactor);
    vout.TexCoord   = vin.TexCoord;

    return vout;
}

float4 PSBasicTx(VertexLightingPSInputTx pin) : COLOR
{
    float4 color = tex2D(TextureSampler, pin.TexCoord) * pin.Diffuse + float4(pin.Specular.rgb, 0);
    color.rgb = lerp(color.rgb, FogColor, pin.Specular.w);
    return color;
}
\$\endgroup\$
  • \$\begingroup\$ Waouhh ! Thank you so much . look like you take a lot of time for me :-) . I appreciate that. I go try to understand and use this . And come back give my results. It's a nice idea to look at the BasicEffect's source code. +1 \$\endgroup\$ – Mehdi Bugnard Aug 20 '14 at 19:13
  • \$\begingroup\$ Hi i come back now. Thank you again big boss !! Finally i check the link of BasicEffect source code than microsoft used here : xbox.create.msdn.com/en-US/education/catalog/utility/… and ajust my code !! Everything work now. I add the final answer in my description \$\endgroup\$ – Mehdi Bugnard Aug 21 '14 at 8:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.