Higher resolution breaks hdr tonemapping

Started by
4 comments, last by unbird 12 years, 6 months ago
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:

o3g25ic8.jpg

old resolution:

3gbgjm4z.jpg

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:




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);
}


Rendering happens that way:

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, 0x00000000);
SetRenderTarget(0, m_ToneMaps);

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();


Can someone help me? Thanks in advance!
Advertisement
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 somewhere in the pipeline.
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).

My first thought is that your GPU doesn't support the higher resolution on some texture or render target and defaults back to black somewhere 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?
Not sure, but...

m_lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, Vertices, sizeof(PlaneVertex));
m_Effect->CommitChanges();

Shouldn't that be the other way round ?
Not sure, but...
m_lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, Vertices, sizeof(PlaneVertex));
m_Effect->CommitChanges();
Shouldn't that be the other way round ?


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!

I wonder why it worked with the lower resolution anyway? Just out of curiousity, ...

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 ;)

This topic is closed to new replies.

Advertisement