0
\$\begingroup\$

Right now I am trying to implement Specular lighting in my DirectX Engine. Whenever I create the DirectSpecularBRDF function in my .HLSL file, my program crashes. Can anybody help me? The problem is in DirectSpecularBRDF, I haven't called the function yet but when I comment out the function code everything works fine. DirectDiffuseBRDF works fine when I call it though. Here is my code:

effects.fx

#include "Common.hlsl"

struct Light
{
    float3 dir;
    float4 ambient;
    float4 diffuse;
};

cbuffer cbPerFrame
{
    Light light;
    float4x4 camPos;
    float Roughness;
    float Metalness;
};

cbuffer cbPerObject
{
    float4x4 WVP;
    float4x4 World;
};

Texture2D ObjTexture;
SamplerState ObjSamplerState
{
    Filter = ANISOTROPIC;
    MaxAnisotropy = 16;
    AddressU = Wrap;
    AddressV = Wrap;
};

struct VS_OUTPUT
{
    float4 Pos : SV_POSITION;
    float2 TexCoord : TEXCOORD;
    float3 normal : NORMAL;
};

float3 DirectDiffuseBRDF(float3 diffuseAlbedo, float nDotL)
{
    return (diffuseAlbedo * nDotL);
}

float3 DirectSpecularBRDF(float3 specularAlbedo, float3 positionWS, float3 normalWS, float3 lightDir)
{
    float3 viewDir = normalize(camPos - positionWS);
    float3 halfVec = normalize(viewDir + lightDir);

    float nDotH = saturate(dot(normalWS, halfVec));
    float nDotL = saturate(dot(normalWS, lightDir));
    float nDotV = max(dot(normalWS, viewDir), 0.0001f);

    float alpha2 = Roughness * Roughness;

    // Computes the distribution of the microfacets for the shaded surface.
    // Trowbridge-Reitz/GGX normal distribution function.
    float  D = alpha2 / (Pi * pow(nDotH * nDotH * (alpha2 - 1) + 1, 2.0f));

    // Computes the amount of light that reflects from a mirror surface given its index of refraction. 
    // Schlick's approximation.
    float3 F = Schlick_Fresnel(specularAlbedo, halfVec, lightDir);

    // Computes the shadowing from the microfacets.
    // Smith's approximation.
    float  G = G_Smith(Roughness, nDotV, nDotL);

    return D * F * G;
}

VS_OUTPUT VS(float4 inPos : POSITION, float2 inTexCoord : TEXCOORD, float3 normal : NORMAL)
{
    VS_OUTPUT output;

    output.Pos = mul(inPos, WVP);

    output.normal = mul(normal, World);

    output.TexCoord = inTexCoord;

    return output;
}

float4 PS(VS_OUTPUT input) : SV_TARGET
{
    input.normal = normalize(input.normal);

    float4 textureColor = ObjTexture.Sample(ObjSamplerState, input.TexCoord);
    float3 specularColor = float3(Metalness, Metalness, Metalness);

    float nDotL = saturate(dot(input.normal, light.dir));

    float3 diffuseLighting = textureColor * light.ambient * light.diffuse;

    diffuseLighting += saturate(DirectDiffuseBRDF(textureColor, nDotL));

    return float4(diffuseLighting, textureColor.a);
}

common.hlsl

//=================================================================================================
// Constant Variables
//=================================================================================================
static const float Pi       = 3.141592654f;
static const float Pi2      = 6.283185307f;
static const float Pi_2     = 1.570796327f;
static const float Pi_4     = 0.7853981635f;
static const float InvPi    = 0.318309886f;
static const float InvPi2   = 0.159154943f;

//=================================================================================================
// Sampler States
//=================================================================================================
SamplerState SamplerLinear
{
    Filter = MIN_MAG_MIP_LINEAR;
    AddressU = Wrap;
    AddressV = Wrap;
};

SamplerState SamplerAnisotropic
{
    Filter = ANISOTROPIC;
    MaxAnisotropy = 16;
    AddressU = Wrap;
    AddressV = Wrap;
};

// ===============================================================================================
// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
// ===============================================================================================
float2 Hammersley(uint i, uint N)
{
    float ri = reversebits(i) * 2.3283064365386963e-10f;
    return float2(float(i) / float(N), ri);
}

// ===============================================================================================
// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html
// ===============================================================================================
float GGX(float NdotV, float a)
{
    float k = a / 2;
    return NdotV / (NdotV * (1.0f - k) + k);
}

// ===============================================================================================
// Geometry Term
// -----------------------------------------------------------------------------------------------
// Defines the shadowing from the microfacets.
//
// Smith approximation:
// http://blog.selfshadow.com/publications/s2013-shading-course/rad/s2013_pbs_rad_notes.pdf
// http://graphicrants.blogspot.fr/2013/08/specular-brdf-reference.html
//
// ===============================================================================================
float G_Smith(float a, float nDotV, float nDotL)
{
    return GGX(nDotL, a * a) * GGX(nDotV, a * a);
}

// ================================================================================================
// Fresnel
// ------------------------------------------------------------------------------------------------
// The Fresnel function describes the amount of light that reflects from a mirror surface 
// given its index of refraction. 
//
// Schlick's approximation:
// http://blog.selfshadow.com/publications/s2013-shading-course/rad/s2013_pbs_rad_notes.pdf
// http://graphicrants.blogspot.fr/2013/08/specular-brdf-reference.html
//
// ================================================================================================
float3 Schlick_Fresnel(float3 f0, float3 h, float3 l)
{
    return f0 + (1.0f - f0) * pow((1.0f - dot(l, h)), 5.0f);
}

// ===============================================================================================
// http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf 
// ===============================================================================================
float3 ImportanceSampleGGX(float2 Xi, float Roughness, float3 N)
{
    float a = Roughness * Roughness; // DISNEY'S ROUGHNESS [see Burley'12 siggraph]

    float Phi = 2 * Pi * Xi.x;
    float CosTheta = sqrt((1 - Xi.y) / (1 + (a * a - 1) * Xi.y));
    float SinTheta = sqrt(1 - CosTheta * CosTheta);

    float3 H;
    H.x = SinTheta * cos(Phi);
    H.y = SinTheta * sin(Phi);
    H.z = CosTheta;

    float3 UpVector = abs(N.z) < 0.999 ? float3(0, 0, 1) : float3(1, 0, 0);
    float3 TangentX = normalize(cross(UpVector, N));
    float3 TangentY = cross(N, TangentX);

    // Tangent to world space
    return TangentX * H.x + TangentY * H.y + N * H.z;
}
\$\endgroup\$
  • \$\begingroup\$ How does it crash, what's the error message? \$\endgroup\$ – SurvivalMachine Oct 9 '16 at 15:12
  • \$\begingroup\$ Since I'm using the .FX framework in Visual Studio 2015 (the .FX framework is now deprecated) I don't get any error message. What I do find out is that it crashes as soon as it get's to the create Vertex Shader on the C++ side. The specific error is Exception thrown: read access violation. VS_Buffer was nullptr. \$\endgroup\$ – Arjan Singh Oct 9 '16 at 15:36
2
\$\begingroup\$

If you use the latest version of Effects 11 using D3DX11CompileEffectFromFile, in the Debug configuration it dumps all the HLSL compiler error/warning output to the debug window.

You can also try directly compiling your file using the FXC command-line compiler by opening a VS 2015 Command Prompt:

fxc /T fx_5_0 effects.fx

If you do, you'll see the following output:

effects.fx(47,32-50): error X3020: type mismatch
effects.fx(47,22-51): error X3013: 'normalize': no matching 1 parameter intrinsic function
effects.fx(47,22-51): error X3013: Possible intrinsic functions are:
effects.fx(47,22-51): error X3013:     normalize(floatM|halfM|min10floatM|min16floatM)

You have camPos defined as a float4x4 which is a matrix, not a float3 position.

\$\endgroup\$
  • \$\begingroup\$ Thanks for the response. How could I enable the Debug Window in my project? Do I add something to my code or enable something in Visual Studio? \$\endgroup\$ – Arjan Singh Oct 10 '16 at 5:37
  • \$\begingroup\$ See MSDN \$\endgroup\$ – Chuck Walbourn Oct 10 '16 at 16:10
  • \$\begingroup\$ I don't seem to get anything regarding the .FX file in the output window, only from the C++ side of things. I also forgot to mention the way I'm editing my effects.fx code is by opening it in Visual Studio but not having it included in the Visual Studio Project but the actual file is kept in the Project Directory (hopefully that makes sense). I've read somewhere online that VS2015 has gotten rid of the .FX debugger or something like that. Is that true? If so what are my options to get a debugger working? \$\endgroup\$ – Arjan Singh Oct 10 '16 at 16:17
  • \$\begingroup\$ The latest version of the Effects 11 framework from GitHub will emit all the warnings found during compilation to the debug window in the Debug configuration. You can and should have VS 2015 build your FX files (it currently supports fx_5_0). You can either also build them again at runtime via D3DX11CompileEffectFromFile or you can load the prebuilt cso files using D3DX11CreateEffectFromFile. See the wiki. See also this thread. \$\endgroup\$ – Chuck Walbourn Oct 11 '16 at 2:53

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.