HDR Scene Trouble

Started by
7 comments, last by ZoBuzz 14 years ago
I'm trying to add HDR to my demo. So I create a texture in A16B16G16R16F as RenderTarget. Then I added a small ball as the light source , to generate hight luminance. So I rendered the ball with a simple ps shader, like: float4 PointLight():COLOR0 { return float4(1000.0f,1000.0f,1000.0f,1.0f); } Then I downsample the texture to caculate luminance, find out that the color isn't larger then 1.0f; I examed in PS,like: float3 vsample = tex2D(FullScreenSampler, t ); if(vsample.x>1.0f) { return float4(1,0,0,1); } Can any one help me with my trouble,sorry for my english.Thank u.
Advertisement
There's very little information here to go on.

How do you actually do the downsampling? And does the ball still appear to the render target if you render it with a conventional shader?

You could use PIX to inspect your render targets.

Niko Suni

well as nik said, there is not much info in order to know where your problem is.
but here is an example of 4x4 (1/4) downsampling :

float4 DownSample4x4_PS( float4 vPos : POSITION, float2 tCoord : TEXCOORD0 ) : COLOR0{	float4 result;	for( int i = 15; i >= 0; i-- )   {		result += tex2D(sTex, tCoord + sampleOffsets);	}	result /= 16;        return result;}


"sampleOffsets" is an Array of float2's sampling offsets which can be defined by application or in your shader.

and Here is a function for calculating sampling offsets from width and height of the render target :
void calculateDownSample4x4Offsets_nofilter( int width, int height, vector2 sampleOffsets[16] ){    assert( sampleOffsets );    float tU = 1.0f / float(width);    float tV = 1.0f / float(height);    // Sample from the 16 surrounding points. Since the center point will be in    // the exact center of 16 texels, a 0.5f offset is needed to specify a texel    // center.    int index = 0;    for( int y=0; y < 4; y++ )    {        for( int x=0; x < 4; x++ )        {            sampleOffsets[ index ].x = (x - 1.5f) * tU;            sampleOffsets[ index ].y = (y - 1.5f) * tV;                                                                  index ++;        }    }}


hope it helps

dark-hammer engine - http://www.hmrengine.com

I know how to do downsampling, been in the business for a long time [grin]

My point was, how does ZoBuzz do it? There may well be something wrong with his approach.

Also, you do integer division when you divide the accumulated values by 16 in your first snippet. In order for the code to work correctly in all shader profiles (especially those with discrete integer support), the divisor should be 16.0f so that the compiler generates a floating-point division. And in D3D10 and up you can leave the 0.5 shift out or - even better - you can directly apply pixel integer offsets in the sampler.

Niko Suni

Quote:Original post by Nik02
I know how to do downsampling, been in the business for a long time [grin]

My point was, how does ZoBuzz do it? There may well be something wrong with his approach.

Also, you do integer division when you divide the accumulated values by 16 in your first snippet. In order for the code to work correctly in all shader profiles (especially those with discrete integer support), the divisor should be 16.0f so that the compiler generates a floating-point division. And in D3D10 and up you can leave the 0.5 shift out or - even better - you can directly apply pixel integer offsets in the sampler.


Nik02,thanks for helping. I rendered the ball as lighting source to FullScreen RenderTarget in D3DFMT_A16B16G16R16,and I already see the ball on my rendertarget.Then I tried to downsample caculate luminace.Shader like:
static const float3 LUMINANCE_VECTOR  = float3(0.2125f, 0.7154f, 0.0721f);float4 SampleLumInitial( in float2 t : TEXCOORD0 ) : COLOR{    float3 vSample = 0.0f;    float  fLogLumSum = 0.0f;    for(int iSample = 0; iSample < 9; iSample++)    {        // Compute the sum of log(luminance) throughout the sample points        vSample = tex2D(FullScreenSampler, t + g_avSampleOffsets[iSample]);        fLogLumSum += log(dot(vSample, LUMINANCE_VECTOR)+0.0001f);    }        fLogLumSum /= 9;    return float4(fLogLumSum, fLogLumSum, fLogLumSum, 1.0f);}

I used hlsl function log() ,and sm 2_0,so I have to use 3x3DownSample,to avoid 64 instruction limit in PS.But the texure after the downsample is black.So I examed the FullScreenSampler,shader like:
float4 SampleLumInitial( in float2 t : TEXCOORD0 ) : COLOR{    float3 vSample = 0.0f;    float  fLogLumSum = 0.0f;    vSample = tex2D(FullScreenSampler, t );    if(vSample.x>1.1f)    {       return float4(1.0f,0.0f,0.0f,1.0f);    }    for(int iSample = 0; iSample < 9; iSample++)    {        vSample = tex2D(FullScreenSampler, t + g_avSampleOffsets[iSample]);        fLogLumSum += log(dot(vSample, LUMINANCE_VECTOR)+0.0001f);     }        fLogLumSum /= 9;    return float4(fLogLumSum, fLogLumSum, fLogLumSum, 1.0f);}

And there is no red ball apears,so I guess the color in FullScreenSampler is not larger then 1.0f,and log() makes it smaller,so I got a black texture.
Here is my approach , did I miss something in creating the D3DFMT_A16B16G16R16 texture,thanks again.

Did you use PIX to capture a frame and examine it? You can see the entire state of the device including your render target contents, and verify that your target contains data beyond 0...1 range.

Also, try to return just float4(vSample, 1) immediately after you do the sampling for the first time. Does it work?

Niko Suni

Quote:Original post by Nik02
Did you use PIX to capture a frame and examine it? You can see the entire state of the device including your render target contents, and verify that your target contains data beyond 0...1 range.

Also, try to return just float4(vSample, 1) immediately after you do the sampling for the first time. Does it work?


I'm not sure wether I used PIX correctly, I debuged my light source pixel ,found out that:
Alpha: 1.000
Red: 1.000
Green: 1.000
Blue: 1.000

Then I Pixed the demo in dxSDK (HDRLighting), and the result is the same, the texture fomat is indeed D3DFMT_A16B16G16R16...
The downsample is the first time I sampled my FullScreenRenderTarget, I am a little confusing now....
If the pixels of the render target texture are clamped to 0...1 even though you render 0...1000 to it, it means that the initial shader (with which you draw the "ball") itself is clamping the values.

Be sure to view the correct surface in PIX - the "render result" of the frame is not the contents of the intermediate render target, but the final frame image that is output during Present. You can open the other resources by double-clicking them on the resource list.

Try to run the shaders with a higher profile, such as 3.0. Although I don't have the impression that 2.0 would clamp the output values. 2.0b can definitely output colors beyond 0...1.

Niko Suni

Quote:Original post by Nik02
If the pixels of the render target texture are clamped to 0...1 even though you render 0...1000 to it, it means that the initial shader (with which you draw the "ball") itself is clamping the values.

Be sure to view the correct surface in PIX - the "render result" of the frame is not the contents of the intermediate render target, but the final frame image that is output during Present. You can open the other resources by double-clicking them on the resource list.

Try to run the shaders with a higher profile, such as 3.0. Although I don't have the impression that 2.0 would clamp the output values. 2.0b can definitely output colors beyond 0...1.


My net broke recent days,I've found my broblems.A stupid mistake , the texture format should be D3DFMT_A16B16G16R16F ,not D3DFMT_A16B16G16R16. Still thanks for your help.

This topic is closed to new replies.

Advertisement