Skip to main content
GameDev.net gamedev.net
🔒 Locked

(SOLVED) Having problem setting the mipmap level

Started by GovardhanDGosavi Nov 23, 2014 at 6:27 AM 12 replies 6.3k views
Original Post
GovardhanDGosavi
GovardhanDGosavi

I have been trying to get the highest mipmap level to show for a long time now but nothing seems to work and the output always shows one of the lower mipmap levels. I tried creating a sampler state like this:


D3D11_SAMPLER_DESC samplerDesc;
	ZeroMemory(&samplerDesc, sizeof(D3D11_SAMPLER_DESC));

	samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; 
	samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
	samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
        samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
        samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
	samplerDesc.MipLODBias = 0.0f;
	samplerDesc.MinLOD = 0.0f;
	samplerDesc.MaxLOD = 0.0f;
	
	HRESULT HR = device->CreateSamplerState(&samplerDesc, &anisotropicSamplerState);
	if(FAILED(HR))
	{
		MessageBox( nullptr, TEXT("Failed to create rasterizer state"), TEXT("Error"), MB_OK );
		return false;
	} 

but changing that seems to toggle between the last two mip levels. I have also tried to do it in the shader


float4 baseColor = Albedo.SampleLevel(samplerState, IN.texCoord, 0);

This also does not have any effect. Am I doing it the right way or is there another method?

Irlan Robson
Irlan Robson

Try just Albedo.Sample(samplerState, IN.texCoord);

See if you're binding the Sampler to the correct place;

Use Intel GFA to Debug everything;

Create an DX11 Debug Layer;

GovardhanDGosavi
GovardhanDGosavi

I have tried Albedo.Sample(samplerState, IN.texCoord); as well and sampler is bound correctly. I am getting the correct output if I edit the dds texture file to contain only the highest mip level. I just want to be able to access the different mip levels in shader

GovardhanDGosavi
GovardhanDGosavi

So I have managed to track the problem to how the textures were created.


hr = DirectX::CreateDDSTextureFromFile( device, L"..\\data\\Cubemaps\\sunsetcube1024.dds", (ID3D11Resource**)&cubeMapTexture, nullptr, 0  );

By specifying the last parameter as 0 I can get the highest mip level but I am still not able to access the different mip levels in hlsl using SampleLevel. Changing the last parameter in SampleLevel does not seem to have any effect and specifying 10 as the last parameter in CreateDDSTextureFromFile gives only the 10th mip level

kauna
kauna

Can you show the part of the code which creates the shader resource view?

Cheers!

[edit] You don't seem to store the SRV pointer given by the CreateDDSTextureFromFile ? How do you bind your texture?

[edit 2] Copied from directxtex: If maxsize parameter non-zero, then all mipmap levels larger than the maxsize are ignored before creating the Direct3D 11 resource. This allows for load-time scaling. If '0', then if the attempt to create the Direct3D 11 resource fails and there are mipmaps present, it will retry assuming a maxsize based on the device's current feature level.

GovardhanDGosavi
GovardhanDGosavi

Sure:


D3D11_TEXTURE2D_DESC SMTextureDesc;
cubeMapTexture->GetDesc(&SMTextureDesc);

D3D11_SHADER_RESOURCE_VIEW_DESC SMViewDesc;
SMViewDesc.Format = SMTextureDesc.Format;
SMViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
SMViewDesc.TextureCube.MipLevels = SMTextureDesc.MipLevels;
SMViewDesc.TextureCube.MostDetailedMip = 0;

hr = device->CreateShaderResourceView(cubeMapTexture, &SMViewDesc, &mShaderResourceView);

Edit:

Yeah went through that earlier. So if I specify 0 then all the mip levels should be loaded which should allow SampleLevel to work but it does not in this case :(

kauna
kauna

Is there a reason not using the SRV from the loading function? (Although I can't see a problem with your SRV desc - you could use -1 for the MipLevels)

Cheers!

GovardhanDGosavi
GovardhanDGosavi

I did it separately in order to do D3D11_SRV_DIMENSION_TEXTURECUBE in the description. If I was creating the SRV at the same time as creating the texture I dont get to specify D3D11_SHADER_RESOURCE_VIEW_DESC


GovardhanDGosavi
GovardhanDGosavi

It seems the various mip levels are loaded correctly because I can set which one to use in the sampler state that I set in c++ using samplerDesc.MipLODBias = 0.0f;

kauna
kauna




I did it separately in order to do D3D11_SRV_DIMENSION_TEXTURECUBE in the description. If I was creating the SRV at the same time as creating the texture I dont get to specify D3D11_SHADER_RESOURCE_VIEW_DESC

The texture loading function should define the SRV_DESC correctly - I mean, I think that the loading function defines the SRV_DESC exactly as you do.

Well this starts to be a good mystery - can you show your whole shader code, part of c++ code which binds the sampler ?

GovardhanDGosavi
GovardhanDGosavi

Ok. Here is the vertex shader:


// sky vertex shader 
// data types

struct VertexShaderInput
{
    float3 position : POSITION;
};

struct VertexShaderOutput
{
	float4 position : SV_POSITION;
	float3 texCoord : TEXCOORD;
};

// things to set in application code

cbuffer PerFrame
{
    matrix wvp;
}

// shader logic

VertexShaderOutput main( VertexShaderInput IN )
{
    VertexShaderOutput OUT;

	OUT.position = mul( wvp, float4( IN.position, 1.0f ) ).xyww;
	OUT.texCoord = IN.position;
 
    return OUT;
}

The pixel shader:


// sky pixel shader 
// data types
struct PixelShaderInput
{
    float4 position : SV_POSITION;
	float3 texCoord : TEXCOORD;
};

// things to set in application code
SamplerState samplerState : register(s0);

TextureCube SkyMap : register( t0 );

// shader logic
half4 main( PixelShaderInput IN ) : SV_TARGET
{
	return SkyMap.SampleLevel(samplerState, IN.texCoord, 0);
}

The c++ draw code:


immediateContext->UpdateSubresource( mWVPConstantBuffer, 0, nullptr, &constantBuffer, 0, 0 );

immediateContext->IASetInputLayout(mInputLayout);
immediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

UINT stride = sizeof(MinimumVertex);
UINT offset = 0;
immediateContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &offset);
immediateContext->IASetIndexBuffer(mIndexBuffer,DXGI_FORMAT_R16_UINT, 0);

immediateContext->VSSetShader( mVertexShader, nullptr, 0 );
immediateContext->VSSetConstantBuffers(0, 1, &mWVPConstantBuffer );

immediateContext->PSSetShader( mPixelShader, nullptr, 0 );
immediateContext->PSSetSamplers( 0, 1, &mLinearSamplerState);
immediateContext->PSSetShaderResources( 0, 1, &mShaderResourceView);

immediateContext->RSSetState( mRSNoCull );
immediateContext->OMSetDepthStencilState(mDSSLast, 0);

immediateContext->DrawIndexed( mNumIndices, 0, 0 );

immediateContext->OMSetDepthStencilState(nullptr, 0);

Yeah I think you are right about the default texture loading but I did it separately just to be sure

kauna
kauna

- in the first part of code you use "anisotropicSamplerState" and in the last part of code "mLinearSamplerState" - are these 2 samplers the same?

- in the pixel shader

OUT.position = mul( wvp, float4( IN.position, 1.0f ) ).xyww;

have you tried xyzw and disabling depth writes?

Cheers!

GovardhanDGosavi
GovardhanDGosavi

That was the problem all along! The linear sampler state could sample correctly from the different mip levels but the anisotropic state could not. After reading your post I passed the correct sampler state and now it works. Thanks a lot! :)

kauna
kauna

Remember that when using anisotropic filtering you'll need to define the maxanisotropy value.

Cheers!

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.