<p>I've actually managed to find problem thanks to @PaulHK, thanks!
I decided to pass which face I am currently working on and setting then coordinates manually per face. It is awful but it works rather good and since it is prefiltered and not done in runtime I found it good enough:</p>

<pre><code>[branch] if (g_upVectorVal.z == 1.0f)
{
    input.position.z = -1.0f;
}
[branch] if (g_upVectorVal.z == -1.0f)
{
    input.position.z = 1.0f;
}
[branch] if (g_upVectorVal.x == 1.0f)
{
    input.position.z = input.position.x;
    input.position.x = -1.0f;
}
[branch] if (g_upVectorVal.x == -1.0f)
{
    input.position.z = -input.position.x;
    input.position.x = 1.0f;
}
[branch] if (g_upVectorVal.y == 1.0f)
{
    input.position.z = -input.position.y;
    input.position.y = -1.0f;
}
[branch] if (g_upVectorVal.y == -1.0f)
{
    input.position.z = -input.position.y;
    input.position.y = 1.0f;
}
</code></pre>

<p>About discarding z coordinate too early - since I decided to pass my data through g_upVectorVal variable I has no need for view/projection space so I discarded them fully. I am just using code below for my vertex shader:</p>

<pre><code>PixelInputType ColorVertexShader(VertexInputType input)
{
    PixelInputType output;

    output.position = input.position;
    input.position.w = 1.0f;

    output.positionSV = mul(input.position, worldMatrix).xyww;

    return output;
}
</code></pre>

<p><a href="https://i.sstatic.net/WQnGP.jpg" rel="nofollow noreferrer"><img src="https://i.sstatic.net/WQnGP.jpg" alt="IBL Diffuse"></a></p>

CC BY-SA 4.0
2019-02-25T21:26:38.327Z
2019-02-25T21:26:38.327Z
DirectX_Programmer
<p>I have problem with creating diffuse irradiance map. As reference I am using <a href="https://learnopengl.com/PBR/IBL/Diffuse-irradiance" rel="nofollow noreferrer">https://learnopengl.com/PBR/IBL/Diffuse-irradiance</a> and <a href="https://github.com/TheEvilBanana/PhysicallyBasedRendering/blob/master/Game.cpp#L490" rel="nofollow noreferrer">https://github.com/TheEvilBanana/PhysicallyBasedRendering/blob/master/Game.cpp#L490</a>.</p>

<p>My map convolution looks not as it is supposed. I have black dot on every face. I use 2048x2048 which I render to 256x256 Texture2D and save each face which I then assemble. Below debug image. Up is +Y, Down is -Y, Middle is from the left -X, -Z, +X, +Z. What can I do to fix it? Also it looks like I am rendering same face twice somehow because +(plus) faces looks same like their -(minus) faces. </p>

<p><a href="https://i.sstatic.net/0NZGq.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/0NZGq.png" alt="Skybox / irradiance map"></a></p>

<p><strong>Render to texture method:</strong></p>

<pre><code>bool GraphicsClass::ConvoluteShader(ID3D11ShaderResourceView * srcTex, RenderTextureClass * dstTex)
{
ifstream skyboxFile;
skyboxFile.open("Skyboxes/conv_cubemap.dds");
if (skyboxFile.fail() == false)
    return true;

XMMATRIX worldMatrix, viewMatrix, projectionMatrix;
bool result;

XMFLOAT3 position = XMFLOAT3(0, 0, 0);
XMFLOAT3 up[] = { XMFLOAT3(0, 1, 0), XMFLOAT3(0, 0, 1), XMFLOAT3(1, 0, 0), XMFLOAT3(0, -1, 0), XMFLOAT3(0, 0, -1), XMFLOAT3(-1, 0, 0) };
wchar_t* filenames[] = { L"S﻿kyboxes/conv_posx.dds", L"Skyboxes/conv_posy.dds" , L"Skyboxes/conv_posz.dds", L"Skyboxes/conv_negx.dds", L"Skyboxes/conv_negy.dds", L"Skyboxes/conv_negz.dds" };
for (int i = 0; i &lt; 6; i++)
{
    dstTex-&gt;SetRenderTarget(m_D3D-&gt;GetDeviceContext(), m_D3D-&gt;GetDepthStencilView());
    dstTex-&gt;ClearRenderTarget(m_D3D-&gt;GetDeviceContext(), m_D3D-&gt;GetDepthStencilView(), 1.0f, 0.0f, 0.0f, 1.0f);

    m_Camera-&gt;Render();
    m_Camera-&gt;GetViewMatrix(viewMatrix);
    m_D3D-&gt;GetWorldMatrix(worldMatrix);
    m_D3D-&gt;GetProjectionMatrix(projectionMatrix);

    m_convoluteShader-&gt;SetUpVector(up[i]);

    m_D3D-&gt;ChangeRasterizerCulling(D3D11_CULL_BACK);
    m_D3D-&gt;ChangeDepthStencilComparison(D3D11_COMPARISON_LESS_EQUAL);

    m_quadModel-&gt;Render(m_D3D-&gt;GetDeviceContext());
    m_convoluteShader-&gt;Render(m_D3D-&gt;GetDeviceContext(), m_quadModel-&gt;GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix);

    m_D3D-&gt;ChangeRasterizerCulling(D3D11_CULL_BACK);
    m_D3D-&gt;ChangeDepthStencilComparison(D3D11_COMPARISON_LESS);

    m_D3D-&gt;SetBackBufferRenderTarget();
    m_D3D-&gt;ResetViewport();

    m_renderTexturePreview-&gt;BindTexture(dstTex-&gt;GetShaderResourc﻿eView());

    SaveDDSTextureToFile(m_D3D-&gt;GetDeviceContext(), dstTex-&gt;GetShaderResource(), filenames[i]);
}

system("texassemble cube -w 256 -h 256 -f R8G8B8A8_UNORM -o Skyboxes/conv_cubemap.dds Skyboxes/conv_posx.dds Skyboxes/conv_negx.dds Skyboxes/conv_posy.dds Skyboxes/conv_negy.dds Skyboxes/conv_posz.dds Skyboxes/conv_negz.dds");
</code></pre>

<p><strong>Vertex shader:</strong></p>

<pre><code>cbuffer MatrixBuffer
{
    matrix worldMatrix;
    matrix viewMatrix;
    matrix projectionMatrix;
};

struct VertexInputType
{
    float4 position : POSITION;    
};

struct PixelInputType
{
    float4 positionSV : SV_POSITION;
    float4 position : POSITION;
};


PixelInputType ColorVertexShader(VertexInputType input)
{
    PixelInputType output;

    output.position = input.position;
    input.position.w = 1.0f;

    output.positionSV = mul(input.position, worldMatrix).xyww;
    output.positionSV = mul(output.positionSV, viewMatrix).xyww;
    output.positionSV = mul(output.positionSV, projectionMatrix).xyww;

    return output;
}
</code></pre>

<p><strong>Pixel Shader:</strong></p>

<pre><code>TextureCube shaderTexture;
SamplerState SampleType;

cbuffer UpVectorBuffer
{
    float3 g_upVectorVal;
    float g_upVectorPadding;
};

struct PixelInputType
{
    float4 positionSV : SV_POSITION;
    float4 position : POSITION;
};

static const float PI = 3.14159265359f;

float4 ColorPixelShader(PixelInputType input) : SV_TARGET
{
    float3 normal = normalize(input.position.xyz);

    float3 irradiance = float3(0.0f, 0.0f, 0.0f);

    float3 up = g_upVectorVal;
    float3 right = cross(up, normal);
    up = cross(normal, right);

    float sampleDelta = 0.025f;
    float nrSamples = 0.0f;
    for (float phi = 0.0f; phi &lt; 2.0 * PI; phi += sampleDelta)
    {
        for (float theta = 0.0f; theta &lt; 0.5 * PI; theta += sampleDelta)
        {
            float3 tangentSample = float3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta));
            float3 sampleVec = (tangentSample.x * right) + (tangentSample.y * up) + (tangentSample.z * normal);

            irradiance += shaderTexture.Sample(SampleType, sampleVec).rgb * cos(theta) * sin(theta);
            nrSamples++;
        }
    }
    irradiance = PI * irradiance * (1.0f / nrSamples);
    return float4(irradiance, 1.0f);
}
</code></pre>

CC BY-SA 4.0
2019-02-20T12:23:13.167Z
output.positionSV = mul(input.position, worldMatrix).xyww;  << Should this not be xyzw ?
PaulHK
CC BY-SA 4.0
2019-02-20T19:14:19.473Z
Unfortunatelly it isn't helpful. I believe that xyww component is needed because we are forcing 'z position' to be equal to 1 to make sure that object is a indefinetely far skybox which isn't moving.
DirectX_Programmer
CC BY-SA 4.0
2019-02-21T02:00:26.577Z
These are 3d coordinates and I am guessing you are projecting 6 sides of a cube, so Z=1 is only true for one of the faces ? Or am I misunderstanding the vertex inputs ? One thing you could try is to output the world space coordinates of each pixel as a RGB colour (e.g. R=X, G=Y, B=Z) to test at least the 3d inputs are correct
PaulHK
CC BY-SA 4.0
2019-02-25T08:16:55.507Z
@PaulHK is right, you are discarding `z` far too early. View and projection matrix don't apply correctly due to that. Also, you have a numerical issue, `up` and `normal` are parallel for the center of two of the surfaces.
Ext3h
<pbr><directx11><directx><ibl>
Weirdly looking diffuse irradiance map
DirectX_Programmer
# Weirdly looking diffuse irradiance map

(Asked by: username_0 on 2019-02-18)

I have problem with creating diffuse irradiance map. As reference I am using <https://learnopengl.com/PBR/IBL/Diffuse-irradiance> and <https://github.com/TheEvilBanana/PhysicallyBasedRendering/blob/master/Game.cpp#L490>.

My map convolution looks not as it is supposed. I have black dot on every face. I use 2048x2048 which I render to 256x256 Texture2D and save each face which I then assemble. Below debug image. Up is +Y, Down is -Y, Middle is from the left -X, -Z, +X, +Z. What can I do to fix it? Also it looks like I am rendering same face twice somehow because +(plus) faces looks same like their -(minus) faces.

[![Skybox / irradiance map](https://i.sstatic.net/0NZGq.png)](https://i.sstatic.net/0NZGq.png)

**Render to texture method:**

```
bool GraphicsClass::ConvoluteShader(ID3D11ShaderResourceView * srcTex, RenderTextureClass * dstTex)
{
ifstream skyboxFile;
skyboxFile.open("Skyboxes/conv_cubemap.dds");
if (skyboxFile.fail() == false)
    return true;

XMMATRIX worldMatrix, viewMatrix, projectionMatrix;
bool result;

XMFLOAT3 position = XMFLOAT3(0, 0, 0);
XMFLOAT3 up[] = { XMFLOAT3(0, 1, 0), XMFLOAT3(0, 0, 1), XMFLOAT3(1, 0, 0), XMFLOAT3(0, -1, 0), XMFLOAT3(0, 0, -1), XMFLOAT3(-1, 0, 0) };
wchar_t* filenames[] = { L"S﻿kyboxes/conv_posx.dds", L"Skyboxes/conv_posy.dds" , L"Skyboxes/conv_posz.dds", L"Skyboxes/conv_negx.dds", L"Skyboxes/conv_negy.dds", L"Skyboxes/conv_negz.dds" };
for (int i = 0; i < 6; i++)
{
    dstTex->SetRenderTarget(m_D3D->GetDeviceContext(), m_D3D->GetDepthStencilView());
    dstTex->ClearRenderTarget(m_D3D->GetDeviceContext(), m_D3D->GetDepthStencilView(), 1.0f, 0.0f, 0.0f, 1.0f);

    m_Camera->Render();
    m_Camera->GetViewMatrix(viewMatrix);
    m_D3D->GetWorldMatrix(worldMatrix);
    m_D3D->GetProjectionMatrix(projectionMatrix);

    m_convoluteShader->SetUpVector(up[i]);

    m_D3D->ChangeRasterizerCulling(D3D11_CULL_BACK);
    m_D3D->ChangeDepthStencilComparison(D3D11_COMPARISON_LESS_EQUAL);

    m_quadModel->Render(m_D3D->GetDeviceContext());
    m_convoluteShader->Render(m_D3D->GetDeviceContext(), m_quadModel->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix);

    m_D3D->ChangeRasterizerCulling(D3D11_CULL_BACK);
    m_D3D->ChangeDepthStencilComparison(D3D11_COMPARISON_LESS);

    m_D3D->SetBackBufferRenderTarget();
    m_D3D->ResetViewport();

    m_renderTexturePreview->BindTexture(dstTex->GetShaderResourc﻿eView());

    SaveDDSTextureToFile(m_D3D->GetDeviceContext(), dstTex->GetShaderResource(), filenames[i]);
}

system("texassemble cube -w 256 -h 256 -f R8G8B8A8_UNORM -o Skyboxes/conv_cubemap.dds Skyboxes/conv_posx.dds Skyboxes/conv_negx.dds Skyboxes/conv_posy.dds Skyboxes/conv_negy.dds Skyboxes/conv_posz.dds Skyboxes/conv_negz.dds");

```

**Vertex shader:**

```
cbuffer MatrixBuffer
{
    matrix worldMatrix;
    matrix viewMatrix;
    matrix projectionMatrix;
};

struct VertexInputType
{
    float4 position : POSITION;    
};

struct PixelInputType
{
    float4 positionSV : SV_POSITION;
    float4 position : POSITION;
};

PixelInputType ColorVertexShader(VertexInputType input)
{
    PixelInputType output;

    output.position = input.position;
    input.position.w = 1.0f;

    output.positionSV = mul(input.position, worldMatrix).xyww;
    output.positionSV = mul(output.positionSV, viewMatrix).xyww;
    output.positionSV = mul(output.positionSV, projectionMatrix).xyww;

    return output;
}

```

**Pixel Shader:**

```
TextureCube shaderTexture;
SamplerState SampleType;

cbuffer UpVectorBuffer
{
    float3 g_upVectorVal;
    float g_upVectorPadding;
};

struct PixelInputType
{
    float4 positionSV : SV_POSITION;
    float4 position : POSITION;
};

static const float PI = 3.14159265359f;

float4 ColorPixelShader(PixelInputType input) : SV_TARGET
{
    float3 normal = normalize(input.position.xyz);

    float3 irradiance = float3(0.0f, 0.0f, 0.0f);

    float3 up = g_upVectorVal;
    float3 right = cross(up, normal);
    up = cross(normal, right);

    float sampleDelta = 0.025f;
    float nrSamples = 0.0f;
    for (float phi = 0.0f; phi < 2.0 * PI; phi += sampleDelta)
    {
        for (float theta = 0.0f; theta < 0.5 * PI; theta += sampleDelta)
        {
            float3 tangentSample = float3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta));
            float3 sampleVec = (tangentSample.x * right) + (tangentSample.y * up) + (tangentSample.z * normal);

            irradiance += shaderTexture.Sample(SampleType, sampleVec).rgb * cos(theta) * sin(theta);
            nrSamples++;
        }
    }
    irradiance = PI * irradiance * (1.0f / nrSamples);
    return float4(irradiance, 1.0f);
}

```

**Tags:** pbr, directx11, directx, ibl

> **Comments:**
> **username_1**: output.positionSV = mul(input.position, worldMatrix).xyww;  << Should this not be xyzw ?  
> **username_0**: Unfortunatelly it isn't helpful. I believe that xyww component is needed because we are forcing 'z position' to be equal to 1 to make sure that object is a indefinetely far skybox which isn't moving.  
> **username_1**: These are 3d coordinates and I am guessing you are projecting 6 sides of a cube, so Z=1 is only true for one of the faces ? Or am I misunderstanding the vertex inputs ? One thing you could try is to output the world space coordinates of each pixel as a RGB colour (e.g. R=X, G=Y, B=Z) to test at least the 3d inputs are correct  
> **username_2**: @username_1 is right, you are discarding `z` far too early. View and projection matrix don't apply correctly due to that. Also, you have a numerical issue, `up` and `normal` are parallel for the center of two of the surfaces.  

---

## 1 answers

### Answer by username_0 on 2019-02-25. Score: 1 | Accepted answer

I've actually managed to find problem thanks to @username_1, thanks!
I decided to pass which face I am currently working on and setting then coordinates manually per face. It is awful but it works rather good and since it is prefiltered and not done in runtime I found it good enough:

```
[branch] if (g_upVectorVal.z == 1.0f)
{
    input.position.z = -1.0f;
}
[branch] if (g_upVectorVal.z == -1.0f)
{
    input.position.z = 1.0f;
}
[branch] if (g_upVectorVal.x == 1.0f)
{
    input.position.z = input.position.x;
    input.position.x = -1.0f;
}
[branch] if (g_upVectorVal.x == -1.0f)
{
    input.position.z = -input.position.x;
    input.position.x = 1.0f;
}
[branch] if (g_upVectorVal.y == 1.0f)
{
    input.position.z = -input.position.y;
    input.position.y = -1.0f;
}
[branch] if (g_upVectorVal.y == -1.0f)
{
    input.position.z = -input.position.y;
    input.position.y = 1.0f;
}

```

About discarding z coordinate too early - since I decided to pass my data through g\_upVectorVal variable I has no need for view/projection space so I discarded them fully. I am just using code below for my vertex shader:

```
PixelInputType ColorVertexShader(VertexInputType input)
{
    PixelInputType output;

    output.position = input.position;
    input.position.w = 1.0f;

    output.positionSV = mul(input.position, worldMatrix).xyww;

    return output;
}

```

[![IBL Diffuse](https://i.sstatic.net/WQnGP.jpg)](https://i.sstatic.net/WQnGP.jpg)


---

