Sign in to follow this  
Hyunkel

DX11 Procedural planets - floating point precision handling

Recommended Posts

Hyunkel    401
I'm making a lot of progress with my procedural planet project, which is part of my masters thesis.
At the moment I'm generating the terrain entirely on the gpu (using dx11 compute shaders) and I am quite pleased with the speed I am getting
using this method.

However I have noticed that I start to get precision issues when having the camera very close to the planet.
This doesn't come as a big surprise, after all I'm working with rather immense scales, but I'm unsure about how to approach the problem.

I'm currently running 16 divisions on 17x17 terrain patches at max lod's, and the geometry itself seems fine.
However when I move / rotate the camera when close to the terrain at this lod, the terrain starts to wobble.
I'm assuming this is because there is insufficient precision to properly multiply the terrain vertex position
with a WVP matrix.

What's a good way to lessen this problem?
I'm thinking about translating all scene objects so that the surface of the planet under the camera is close to the (0, 0, 0) point
where floating point precision is higher.
Is this worth trying or are there better methods?

Cheers,
Hyu

Share this post


Link to post
Share on other sites
RenHoek    119
Hi there

Your idea of translating everything to the 0,0,0 point seems fine
Its the method I've used before. ( and other packages I've worked on )

We stored our planet geometry in the CPU in worldspace doubles. ( it was an old project )
Then converted all the double-precision data to a 32bit camera=0,0,0 positioning scheme before sending to the card.

But if you're doing it using the compute shader then yea... I guess convert your matricies in a way that your data is still positioned relative to the camera rather than in world space.
Humas wrote an article in GPUPro 1 which describes how to handle matricies to minimize low-precision jittering.

Good luck, and I look forward to screenshots! :)

Ren

Share this post


Link to post
Share on other sites
Hyunkel    401
Fortunately I haven't had any Z-fighting yet, but I'm assuming that I will run into that soon.
I'll test out logarithmic z-buffers and the inverting planes technique as soon as I'll run into trouble.

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  

  • Similar Content

    • By lonewolff
      Hi Guys,
      I am presently trying to render a video frame to a quad in DirectX 11 using Microsoft Media Foundations. But I am having a problem with 'TransferVideoFrame'.
      m_spMediaEngine->TransferVideoFrame(texture, rect, rcTarget, &m_bkgColor); The call keeps returning 'invalid parameter'.
      Some googling revealed this - https://stackoverflow.com/questions/15711054/how-do-i-grab-frames-from-a-video-stream-on-windows-8-modern-apps
      Which explains that there is (was??) a bug with the NVidia drivers back in 2013. Other searches say this bug was fixed.
      The very odd thing is, if I run the application through Visual Studio Graphical debugger the video renders perfectly to the quad with no errors, so this would suggest that my code is sound.
      I can't do as the link suggests above and try to create the device as 9_x, as this is an extension that I am creating for GameMaker 2 and I don't have access to renderer creation (only the device handle - which is fine most of the time).
      I am presently downloading VS 2017 to see if it behaves better with more recent SDK's (as I am currently using VS 2015).
      Thanks in advance
       
       
    • By AlexWIN32
      Hello!
       
      A have an issue with my point light shadows realisation.

       
      First of all, the pixel shader path:
      //.... float3 toLight = plPosW.xyz - input.posW; float3 fromLight = -toLight; //... float depthL = abs(fromLight.x); if(depthL < abs(fromLight.y)) depthL = abs(fromLight.y); if(depthL < abs(fromLight.z)) depthL = abs(fromLight.z); float4 pH = mul(float4(0.0f, 0.0f, depthL, 1.0f), lightProj); pH /= pH.w; isVisible = lightDepthTex.SampleCmpLevelZero(lightDepthSampler, normalize(fromLight), pH.z).x;

      lightProj matrix creation
      Matrix4x4 projMat = Matrix4x4::PerspectiveFovLH(0.5f * Pi, 0.01f, 1000.0f, 1.0f);  
      thats how i create Depth cube texture
       
      viewport->TopLeftX = 0.0f; viewport->TopLeftY = 0.0f; viewport->Width = static_cast<float>(1024); viewport->Height = static_cast<float>(1024); viewport->MinDepth = 0.0f; viewport->MaxDepth = 1.0f; D3D11_TEXTURE2D_DESC textureDesc; textureDesc.Width = 1024; textureDesc.Height = 1024; textureDesc.MipLevels = 1; textureDesc.ArraySize = 6; textureDesc.Format = DXGI_FORMAT_R24G8_TYPELESS; textureDesc.SampleDesc.Count = 1; textureDesc.SampleDesc.Quality = 0; textureDesc.Usage = D3D11_USAGE_DEFAULT; textureDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE; textureDesc.CPUAccessFlags = 0; textureDesc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE; ID3D11Texture2D* texturePtr; HR(DeviceKeeper::GetDevice()->CreateTexture2D(&textureDesc, NULL, &texturePtr)); for(int i = 0; i < 6; ++i){ D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; dsvDesc.Flags = 0; dsvDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY; dsvDesc.Texture2DArray = D3D11_TEX2D_ARRAY_DSV{0, i, 1}; ID3D11DepthStencilView *outDsv; HR(DeviceKeeper::GetDevice()->CreateDepthStencilView(texturePtr, &dsvDesc, &outDsv)); edgeDsv = outDsv; } D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; srvDesc.Format = DXGI_FORMAT_R24_UNORM_X8_TYPELESS; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; srvDesc.TextureCube = D3D11_TEXCUBE_SRV{0, 1}; ID3D11ShaderResourceView *outSRV; HR(DeviceKeeper::GetDevice()->CreateShaderResourceView(texturePtr, &srvDesc, &outSRV));  
      then i create six target oriented cameras and finally draw scene to cube depth according to each camera
      Cameras creation code:  
      std::vector<Vector3> camDirs = { { 1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 0.0f, -1.0f, 0.0f}, { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, -1.0f}, }; std::vector<Vector3> camUps = { {0.0f, 1.0f, 0.0f}, // +X {0.0f, 1.0f, 0.0f}, // -X {0.0f, 0.0f, -1.0f}, // +Y {0.0f, 0.0f, 1.0f}, // -Y {0.0f, 1.0f, 0.0f}, // +Z {0.0f, 1.0f, 0.0f} // -Z }; for(size_t b = 0; b < camDirs.size(); b++){ edgesCameras.SetPos(pl.GetPos()); edgesCameras.SetTarget(pl.GetPos() + camDirs); edgesCameras.SetUp(camUps); edgesCameras.SetProjMatrix(projMat); }  
      I will be very gratefull for any help!
      P.s sorry for my poor English)
       
    • By isu diss
      HRESULT FBXLoader::Open(HWND hWnd, char* Filename) { HRESULT hr = S_OK; if (FBXM) { FBXIOS = FbxIOSettings::Create(FBXM, IOSROOT); FBXM->SetIOSettings(FBXIOS); FBXI = FbxImporter::Create(FBXM, ""); if (!(FBXI->Initialize(Filename, -1, FBXIOS))) MessageBox(hWnd, (wchar_t*)FBXI->GetStatus().GetErrorString(), TEXT("ALM"), MB_OK); FBXS = FbxScene::Create(FBXM, "MCS"); if (!FBXS) MessageBox(hWnd, TEXT("Failed to create the scene"), TEXT("ALM"), MB_OK); if (!(FBXI->Import(FBXS))) MessageBox(hWnd, TEXT("Failed to import fbx file content into the scene"), TEXT("ALM"), MB_OK); if (FBXI) FBXI->Destroy(); FbxNode* MainNode = FBXS->GetRootNode(); int NumKids = MainNode->GetChildCount(); FbxNode* ChildNode = NULL; for (int i=0; i<NumKids; i++) { ChildNode = MainNode->GetChild(i); FbxNodeAttribute* NodeAttribute = ChildNode->GetNodeAttribute(); if (NodeAttribute->GetAttributeType() == FbxNodeAttribute::eMesh) { FbxMesh* Mesh = ChildNode->GetMesh(); NumVertices = Mesh->GetControlPointsCount();//number of vertices MyV = new FBXVTX[NumVertices]; for (DWORD j = 0; j < NumVertices; j++) { FbxVector4 Vertex = Mesh->GetControlPointAt(j);//Gets the control point at the specified index. MyV[j].Position = XMFLOAT3((float)Vertex.mData[0], (float)Vertex.mData[1], (float)Vertex.mData[2]); } NumIndices = Mesh->GetPolygonVertexCount();//number of indices; for cube 20 MyI = new DWORD[NumIndices]; MyI = (DWORD*)Mesh->GetPolygonVertices();//index array NumFaces = Mesh->GetPolygonCount(); MyF = new FBXFACEX[NumFaces]; for (int l=0;l<NumFaces;l++) { MyF[l].Vertices[0] = MyI[4*l]; MyF[l].Vertices[1] = MyI[4*l+1]; MyF[l].Vertices[2] = MyI[4*l+2]; MyF[l].Vertices[3] = MyI[4*l+3]; } UV = new XMFLOAT2[NumIndices]; for (int i = 0; i < Mesh->GetPolygonCount(); i++)//polygon(=mostly rectangle) count { FbxLayerElementArrayTemplate<FbxVector2>* uvVertices = NULL; Mesh->GetTextureUV(&uvVertices); for (int j = 0; j < Mesh->GetPolygonSize(i); j++)//retrieves number of vertices in a polygon { FbxVector2 uv = uvVertices->GetAt(Mesh->GetTextureUVIndex(i, j)); UV[4*i+j] = XMFLOAT2((float)uv.mData[0], (float)uv.mData[1]); } } } } } else MessageBox(hWnd, TEXT("Failed to create the FBX Manager"), TEXT("ALM"), MB_OK); return hr; } I've been trying to load fbx files(cube.fbx) into my programme. but I get this. Can someone pls help me?
       

    • By lonewolff
      Hi Guys,
      I am having a bit of a problem with a dynamic texture.
      It is creating without error and I am attempting to initialize the first pixel to white to make sure I am mapping correctly. But when I draw the texture to the quad it displays the whole quad white (instead of just one pixel).
      This is how I am creating, mapping, and setting the first pixel to white. But as mentioned, when I draw the quad, the entire quad is white.
       
      // Create dynamic texture D3D11_TEXTURE2D_DESC textureDesc = { 0 }; textureDesc.Width = 2048; textureDesc.Height = 2048; textureDesc.MipLevels = 1; textureDesc.ArraySize = 1; textureDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; textureDesc.SampleDesc.Count = 1; textureDesc.Usage = D3D11_USAGE_DYNAMIC; textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; textureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; textureDesc.MiscFlags = 0; HRESULT result = d3dDevice->CreateTexture2D(&textureDesc, NULL, &textureDynamic); if (FAILED(result)) return -1; result = d3dDevice->CreateShaderResourceView(textureDynamic, 0, &textureRV); if (FAILED(result)) return -2; D3D11_MAPPED_SUBRESOURCE resource; if (FAILED(d3dContext->Map(textureDynamic, 0, D3D11_MAP_WRITE_DISCARD, 0, &resource))) return -1; memset(resource.pData, 255, 4); d3dContext->Unmap(textureDynamic, 0);  
      Hopefully I have just made an oversight somewhere.
      Any assistance would be greatly appreciated
      (If I change the 255 value to 128 the quad then turns grey, so the mapping is definitely doing something. Just can't work out why it is colouring the whole quad and not the first pixel)
    • By KaiserJohan
      Just a really quick question - is there any overhead to using DrawIndexedInstanced even for geometry you just render once vs using DrawIndexed? Or is the details obfuscated by the graphics driver?
      I would assume no but you never know  
  • Popular Now