Sign in to follow this  
Juliean

Higher resolution breaks hdr tonemapping

Recommended Posts

Hi,

today I got a new monitor with a resolution of 2560*1600. First thing I did was converting my project from 1920*1200 to the new resolution (no resolution select screen by now). Looks pretty cool, however my hdr tonemapper doesn't seem to be happy with the higher resolution. This happens:

new resolution:

[URL=http://s14.directupload.net/file/d/2671/o3g25ic8_jpg.htm][IMG]http://s14.directupload.net/images/111008/temp/o3g25ic8.jpg[/IMG][/URL]

old resolution:

[URL=http://s14.directupload.net/file/d/2671/3gbgjm4z_jpg.htm][IMG]http://s14.directupload.net/images/111008/temp/3gbgjm4z.jpg[/IMG][/URL]

As you can see, the new resolution makes everything a lot darker. Why this? I double-checked everything, the new resolution is correctly applied everywhere, there are no hard-coded 1920*1200-values anywhere. Here is my hdr-shader-code:

[code]


sampler FilterSampler = sampler_state
{
Texture = <Luminance>;
AddressU = CLAMP;
AddressV = CLAMP;
MinFilter = LINEAR;
MagFilter = LINEAR;
MipFilter = NONE;
SRGBTEXTURE = FALSE;
};

sampler LuminanceSampler = sampler_state
{
texture = <Luminance>;
AddressU = CLAMP;
AddressV = CLAMP;
MINFILTER = POINT;
MAGFILTER = POINT;
MIPFILTER = NONE;
SRGBTEXTURE = FALSE;
};

sampler BlurSampler = sampler_state
{
texture = <BlurTexture>;
AddressU = CLAMP;
AddressV = CLAMP;
MINFILTER = LINEAR;
MAGFILTER = LINEAR;
MIPFILTER = NONE;
SRGBTEXTURE = FALSE;
};

float4 psConvertLuminance(PS_INPUT_LIGHT i) : COLOR
{
float3 lightTransport = tex2D(ImageSampler, i.vTex0);

//convert to luminance
float lum = dot(lightTransport, float3(0.3086, 0.6094, 0.0820));
float logLum = log(0.0001 + lum); //used to prevent numerical underflow of log(0)

return float4(lum, logLum, 0.0, 0.0);
}

float4 psFilter(PS_INPUT_LIGHT i) : COLOR
{
float4 inTex = tex2D(FilterSampler, i.vTex0);

return float4(inTex.x, inTex.y, inTex.z, inTex.w);
}

float4 psAdaption(PS_INPUT_LIGHT i) : COLOR
{
float4 currFrame = tex2D(CurrentLumSampler, i.vTex0);
float4 prevFrame = tex2D(PrevLumSampler, i.vTex0);

float4 finalCol = lerp(currFrame, prevFrame, 0.99);

return finalCol;
}

float4 FilteredThresholdPS(PS_INPUT_LIGHT i) : COLOR
{
float4 inTex = tex2D(FilterSampler, i.vTex0);

if ( (inTex.x < 3.0) &&
(inTex.y < 3.0) &&
(inTex.z < 3.0) )
inTex = 0.0f;

return float4(inTex.x, inTex.y, inTex.z, inTex.w);
}

const float weights[8] = {
0.05,
0.08,
0.1,
0.15,
0.15,
0.1,
0.08,
0.05,
};

float4 BlurPS(PS_INPUT_LIGHT i) : COLOR
{
float3 sum = tex2D(BlurSampler, float2(i.vTex0.x, i.vTex0.y)) * 0.25;

for (int j = 0; j < 8; ++j)
{
sum += tex2D(BlurSampler, i.vTex0 + BlurOffset[j]) * weights[j];
}

return float4(sum, 1.0f);
}


float4 psToneMap(PS_INPUT_LIGHT i) : COLOR
{
float lum = tex2D(LuminanceSampler, i.vTex0).x;
float3 blur = tex2D(BlurSampler, i.vTex0);
float avg_loglum = exp(tex2D(AvgLuminanceSampler, float2(0.5, 0.5)).y)*5; //grab the first texel
float3 lightTransport = tex2D(ImageSampler, i.vTex0).xyz;

float key = max(0, 1.5f-(1.5f/(avg_loglum*0.5f+1.0f)));

float lum_scaled = (key*(lum))/avg_loglum;

float3 finalColor = lightTransport*((lum_scaled*(1+(lum_scaled/225.0f)))/(1 + lum_scaled));

return float4(finalColor, 1.0f);
}[/code]

Rendering happens that way:

[code] BlurSurface(m_RenderTarget, false);
//Convert to luminance
SetRenderTarget(0, m_Luminance);
m_Effect->SetTexture("ImageMap", m_RenderTarget);
m_Effect->SetTechnique("luminance");

RenderQuad();

//create filtered surface representing average luminance
m_Effect->SetTechnique("PassThroughFiltered");
m_Effect->Begin(NULL, 0);
m_Effect->BeginPass(0);
PlaneVertex Vertices[4];
for (unsigned int i = 0; i < m_ToneMaps.size(); ++i)
{
ClearTexture(m_ToneMaps[i], 0x00000000);
SetRenderTarget(0, m_ToneMaps[i]);

if (i==0)
m_Effect->SetTexture("Luminance", m_Luminance);
else
m_Effect->SetTexture("Luminance", m_ToneMaps[i - 1]);

m_lpDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
Vertices[0] = m_QuadVec[i*4];
Vertices[1] = m_QuadVec[i*4+1];
Vertices[2] = m_QuadVec[i*4+2];
Vertices[3] = m_QuadVec[i*4+3];
m_lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, Vertices, sizeof(PlaneVertex));

m_Effect->CommitChanges();
}
m_Effect->EndPass();
m_Effect->End();

LPDIRECT3DTEXTURE9 TempTex = m_LastLuminance;
m_LastLuminance = m_CurrLuminance;
m_CurrLuminance = TempTex;
TempTex = NULL;

m_Effect->SetTechnique("Adaptation");
SetRenderTarget(0, m_CurrLuminance);
ClearTexture(m_CurrLuminance, 0x00000000);
m_Effect->SetTexture("CurrentLum", m_ToneMaps[m_ToneMaps.size() - 1]);
m_Effect->SetTexture("PreviousLum", m_LastLuminance);

RenderQuad();

m_Effect->SetTechnique("ToneMap");
SetRenderTarget(0, m_FinalScene);
m_Effect->SetTexture("AvgLuminance", m_CurrLuminance);
m_Effect->SetTexture("Luminance", m_Luminance);
m_Effect->SetTexture("BlurTexture", m_BlurSurface);

RenderQuad();[/code]

Can someone help me? Thanks in advance!

Share this post


Link to post
Share on other sites
Are you testing every D3D return code for failure? Does the output log show any errors or warnings? My first thought is that your GPU doesn't support the higher resolution on some texture or render target and defaults back to black [i]somewhere[/i] in the pipeline.

Share this post


Link to post
Share on other sites
Yes, I tested every important (= used for hdr rendering) d3d return code for failure. No failure at all. Output log doesn't show anything, however I can't use the d3d-debug mode as my control panel is fucked up (switching modes is grayed out).
[quote]
My first thought is that your GPU doesn't support the higher resolution on some texture or render target and defaults back to black [i]somewhere[/i] in the pipeline. [/quote]

I used the Nvidia PerfHUD to check that out. There is no rendertarget that just gets black anywhere in the hdr rendering code (that would mean the scene would be too brigth and not too dark, anyway), BUT there is an other thing: The downfiltering for the average lum seems to be messed up. Everything is way too white, with the lower resolution you see a lot of detail in a rose color tone, but with the higher resolution I could barely even see any detail at all during down-filtering (there were some details from the scene, so nothing is wrong with the textures in first place). The last "mip" (1x1) is just a completely white pixel! Thats where the problem lays.. thanks for your help so far, do you (or someone else) know whats going on?

Share this post


Link to post
Share on other sites
[code]Not sure, but...
m_lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, Vertices, sizeof(PlaneVertex));
m_Effect->CommitChanges();
Shouldn't that be the other way round ? [/code]

Thank you so much, you were right! Flipping the order for these two commands actually got the whole thing working again. It also improved a lot of the issues I had with the tonemapper which I didn't know how to solve (small dark areas causing scene to light up too much; brigth scenes getting way to dark..). I wonder why it worked with the lower resolution anyway? Just out of curiousity, the problem is obviously solved, thanks again!

Share this post


Link to post
Share on other sites
[quote name='The King2' timestamp='1318073692' post='4870461']
I wonder why it worked with the lower resolution anyway? Just out of curiousity, ...
[/quote]
Just guessing: That averaging loop had the "correct" count (assuming ping-ponging of textures) with the lower resolution, so the "right" texture was bound again in the next frame.

Glad to hear it works, and since it does, investigating this bug is probably not worthwhile ;)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this