Jump to content
  • Advertisement

KaiserJohan

Member
  • Content Count

    434
  • Joined

  • Last visited

Community Reputation

2319 Excellent

About KaiserJohan

  • Rank
    Member

Personal Information

  • Role
    Programmer
  • Interests
    Programming

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. KaiserJohan

    Non-uniform patch terrain tessellation

    Interesting; do you have a github link for reference? I see, it's like how I do it currently, then. Just to be sure, you build & cull nodes on the CPU right? Also, how deep do you determine the quadtree should be, where do you stop splitting nodes? I have it set to 32x32 but is there a reason to do anything else? Given that there is quite abit of memory footprint on the CPU for each height in the quadtree Not quite sure I understand this part. Which size limit do you refer to? And what is the external storage media? Isn't it enough to do a unit-sized quad and then provide a scaling/translation transform for each patch? Thanks alot for the answers! πŸ™‚
  2. That's it! I sampled only the red channel by mistake. Good catch, works now as expected, big thanks! πŸ™‚
  3. I have a large heightmap, split into X-sized patches (e.g 32), inserted into a quad-tree for view culling on the CPU. All rendered as instanced drawing of a simple 4-vertex quad with each patch has it's own world-transform (with uniform scale for all). The tessellation of each chunk depends on it's height variance & screen-space size. Fair enough, that works mostly fine, although there are two cases that are problematic: Performance, when zoomed out far enough that nearly all patches are visible Loss of detail, when not in a top-down view or very very zoomed in So I'm thinking of doing non-uniform sized patches like this image: A quad-tree like this is different from mine as it's built from the camera as the root so I need to change that. As for determining when to merge smaller patches into a larger one, is there a smart metric to use? The most simple one I can think of is measure distance from camera in absolute world units, but I would prefer something more adaptive perhaps, to handle really large & small terrains, and not dependent on such static boundaries. Any ideas?
  4. The transform is the same, whether I compute it or sample the normals πŸ€” Is there anything that could happen under the hood when sampling? The texture is bound correctly (as seen in RenderDoc). Is the sampler object the problem?
  5. [domain("quad")] DomainOut ds_main(PatchTess patchTess, float2 uv : SV_DomainLocation, const OutputPatch<HullOut, 4> quad) { DomainOut ret; float2 topMidpointWorld = lerp( quad[ 0 ].mWorldPosition.xz, quad[ 1 ].mWorldPosition.xz, uv.x ); float2 bottomMidpointWorld = lerp( quad[ 3 ].mWorldPosition.xz, quad[ 2 ].mWorldPosition.xz, uv.x ); float2 midPointWorld = lerp( topMidpointWorld, bottomMidpointWorld, uv.y ); float2 topMidpointTexcoord = lerp( quad[ 0 ].mTexcoord, quad[ 1 ].mTexcoord, uv.x ); float2 bottomMidpointTexcoord = lerp( quad[ 3 ].mTexcoord, quad[ 2 ].mTexcoord, uv.x ); float2 midPointTexcoord = lerp( topMidpointTexcoord, bottomMidpointTexcoord, uv.y ); const int2 offset = 0; const int mipmap = 0; ret.mNormal = gNormalMap.SampleLevel( gLinearSampler, midPointTexcoord, mipmap, offset ).r; ret.mNormal *= 2.0; ret.mNormal -= 1.0; ret.mNormal = normalize( ret.mNormal ); ret.mNormal.y = -ret.mNormal.y; ret.mNormal = mul( ( float3x3 )gFrameView, ( float3 )ret.mNormal ); ret.mNormal = normalize( ret.mNormal ); float y = quad[ 0 ].mWorldPosition.y + ( SampleHeightmap( midPointTexcoord ) * gHeightModifier ); ret.mPosition = float4( midPointWorld.x, y, midPointWorld.y, 1.0 ); ret.mPosition = mul( gFrameViewProj, ret.mPosition ); ret.mTexcoord = midPointTexcoord; return ret; } This is the full domain shader - if I output the texcoord to an output texture in a pixel shader I see it does go from [0,1] for the whole terrain. The normal map is the same size and all as the heightmap. I do use RenderDoc (it's awesome) for debugging stuff like this πŸ™‚ The vertex shader that computes the texture coordinate & vertex positions are like this: VertexOut vs_main(VertexIn input) { VertexOut ret; const uint transformIndex = gTransformOffset + input.mInstanceID; // silly that we have to transpose this... const float4x4 worldTransform = transpose( gWorldTransforms.Load( transformIndex ) ); ret.mWorldPosition = mul( worldTransform, float4( input.mPosition, 1 ) ).xyz; ret.mTexcoord = ( ret.mWorldPosition.xz - gWorldMin ) / ( gWorldMax - gWorldMin ); ret.mTexcoord = clamp( ret.mTexcoord, 0.0f, 1.0f ); return ret; }
  6. I am doing terrain tessellation and I have two ways of approaching normals: 1) Compute the normal in the domain shader using a Sobel filter 2) Precompute normals in a compute shader with the same Sobel filter and then sample it in the domain shader. Texture format is R10G10B10A2_UNORM This is the normals (in view space) from 1), which looks correct This is normals when sampled from the precomputed normal map: This is what the computed normal map looks like This is the sobel filter I use in the compute shader float3 SobelFilter( int3 texCoord ) { float h00 = gHeightmap.Load( texCoord, int2( -1, -1 ) ).r; float h10 = gHeightmap.Load( texCoord, int2( 0, -1 ) ).r; float h20 = gHeightmap.Load( texCoord, int2( 1, -1 ) ).r; float h01 = gHeightmap.Load( texCoord, int2( -1, 0 ) ).r; float h21 = gHeightmap.Load( texCoord, int2( 1, 0 ) ).r; float h02 = gHeightmap.Load( texCoord, int2( -1, 1 ) ).r; float h12 = gHeightmap.Load( texCoord, int2( 0, 1 ) ).r; float h22 = gHeightmap.Load( texCoord, int2( 1, 1 ) ).r; float Gx = h00 - h20 + 2.0f * h01 - 2.0f * h21 + h02 - h22; float Gy = h00 + 2.0f * h10 + h20 - h02 - 2.0f * h12 - h22; // generate missing Z float Gz = 0.01f * sqrt( max( 0.0f, 1.0f - Gx * Gx - Gy * Gy ) ); return normalize( float3( 2.0f * Gx, Gz, 2.0f * Gy ) ); } The simple compute shader itself: [numthreads(TERRAIN_NORMAL_THREADS_AXIS, TERRAIN_NORMAL_THREADS_AXIS, 1)] void cs_main(uint3 groupID : SV_GroupID, uint3 dispatchTID : SV_DispatchThreadID, uint3 groupTID : SV_GroupThreadID, uint groupIndex : SV_GroupIndex) { float3 normal = SobelFilter( int3( dispatchTID.xy, 0) ); normal += 1.0f; normal *= 0.5f; gNormalTexture[ dispatchTID.xy ] = normal; } The snippet in the domain shader that samples the normal map: const int2 offset = 0; const int mipmap = 0; ret.mNormal = gNormalMap.SampleLevel( gLinearSampler, midPointTexcoord, mipmap, offset ).r; ret.mNormal *= 2.0; ret.mNormal -= 1.0; ret.mNormal = normalize( ret.mNormal ); ret.mNormal.y = -ret.mNormal.y; ret.mNormal = mul( ( float3x3 )gFrameView, ( float3 )ret.mNormal ); ret.mNormal = normalize( ret.mNormal ); ----------------------------------------------- Now, if I compute the normals directly in the domain shader, different sampling method in the Sobel filter float3 SobelFilter( float2 uv ) { const int2 offset = 0; const int mipmap = 0; float h00 = gHeightmap.SampleLevel( gPointSampler, uv, mipmap, int2( -1, -1 ) ).r; float h10 = gHeightmap.SampleLevel( gPointSampler, uv, mipmap, int2( 0, -1 ) ).r; float h20 = gHeightmap.SampleLevel( gPointSampler, uv, mipmap, int2( 1, -1 ) ).r; float h01 = gHeightmap.SampleLevel( gPointSampler, uv, mipmap, int2( -1, 0 ) ).r; float h21 = gHeightmap.SampleLevel( gPointSampler, uv, mipmap, int2( 1, 0 ) ).r; float h02 = gHeightmap.SampleLevel( gPointSampler, uv, mipmap, int2( -1, 1 ) ).r; float h12 = gHeightmap.SampleLevel( gPointSampler, uv, mipmap, int2( 0, 1 ) ).r; float h22 = gHeightmap.SampleLevel( gPointSampler, uv, mipmap, int2( 1, 1 ) ).r; float Gx = h00 - h20 + 2.0f * h01 - 2.0f * h21 + h02 - h22; float Gy = h00 + 2.0f * h10 + h20 - h02 - 2.0f * h12 - h22; // generate missing Z float Gz = 0.01f * sqrt( max( 0.0f, 1.0f - Gx * Gx - Gy * Gy ) ); return normalize( float3( 2.0f * Gx, Gz, 2.0f * Gy ) ); } And then just computing it in the domain shader: ret.mNormal = SobelFilter( midPointTexcoord ); ret.mNormal = mul( ( float3x3 )gFrameView, ( float3 )ret.mNormal ); ret.mNormal = normalize( ret.mNormal ); I am sure there is a simple answer to this and I am missing something... but what? Whether I sample a precomputed value or compute it in the shader, it should be the same?
  7. Alright so I've localized the issue. It happens when I compile the hull shader with the optimization flag turned on - if I disable it, it works perfectly fine πŸ€” All other shaders are compiled with optimization flag and they work fine. Looking at the diff between the textfiles I find some things like this- What is this immediate constant buffer? What are these values inside? I'm attaching the full shader code aswell if it helps: #ifndef TERRAIN_HULL_HLSL #define TERRAIN_HULL_HLSL #include "TerrainCommon.hlsl" float3 ComputePatchMidpoint( float3 corner1, float3 corner2, float3 corner3, float3 corner4 ) { return ( corner1 + corner2 + corner3 + corner4 ) / 4.0f; } float CalculateTessellationfactor( float3 worldPatchMidpoint ) { float cameraToPatchDistance = distance( gWorldEyePos, worldPatchMidpoint ); float scaledDistance = ( cameraToPatchDistance - gMinZ ) / ( gMaxZ - gMinZ ); scaledDistance = clamp( scaledDistance, 0.0f, 1.0f ); return pow( 2, lerp( 6.0f, 2.0f, scaledDistance ) ); } PatchTess PatchHS( InputPatch<VertexOut, 12> inputVertices ) { PatchTess patch; float3 midPatchMidpoint = ComputePatchMidpoint( inputVertices[ 0 ].mWorldPosition, inputVertices[ 1 ].mWorldPosition, inputVertices[ 2 ].mWorldPosition, inputVertices[ 3 ].mWorldPosition ); float3 edgePatchMidpoint[] = { ComputePatchMidpoint( inputVertices[ 0 ].mWorldPosition, inputVertices[ 1 ].mWorldPosition, inputVertices[ 4 ].mWorldPosition, inputVertices[ 5 ].mWorldPosition ), ComputePatchMidpoint( inputVertices[ 1 ].mWorldPosition, inputVertices[ 2 ].mWorldPosition, inputVertices[ 6 ].mWorldPosition, inputVertices[ 7 ].mWorldPosition ), ComputePatchMidpoint( inputVertices[ 2 ].mWorldPosition, inputVertices[ 3 ].mWorldPosition, inputVertices[ 8 ].mWorldPosition, inputVertices[ 9 ].mWorldPosition ), ComputePatchMidpoint( inputVertices[ 3 ].mWorldPosition, inputVertices[ 0 ].mWorldPosition, inputVertices[ 10 ].mWorldPosition, inputVertices[ 11 ].mWorldPosition ) }; float midPatchTessFactor = CalculateTessellationfactor( midPatchMidpoint ); float edgePatchTessFactors[] = { CalculateTessellationfactor( edgePatchMidpoint[ 3 ] ), CalculateTessellationfactor( edgePatchMidpoint[ 0 ] ), CalculateTessellationfactor( edgePatchMidpoint[ 1 ] ), CalculateTessellationfactor( edgePatchMidpoint[ 2 ] ) }; patch.mEdgeTess[ 0 ] = min( midPatchTessFactor, edgePatchTessFactors[ 0 ] ); patch.mEdgeTess[ 1 ] = min( midPatchTessFactor, edgePatchTessFactors[ 1 ] ); patch.mEdgeTess[ 2 ] = min( midPatchTessFactor, edgePatchTessFactors[ 2 ] ); patch.mEdgeTess[ 3 ] = min( midPatchTessFactor, edgePatchTessFactors[ 3 ] ); patch.mInsideTess[ 0 ] = midPatchTessFactor; patch.mInsideTess[ 1 ] = midPatchTessFactor; return patch; } [domain("quad")] [partitioning("fractional_odd")] [outputtopology("triangle_ccw")] [outputcontrolpoints(4)] [patchconstantfunc("PatchHS")] HullOut hs_main( InputPatch<VertexOut, 12> verticeData, uint index : SV_OutputControlPointID ) { HullOut ret; ret.mWorldPosition = verticeData[ index ].mWorldPosition; ret.mTexcoord = verticeData[ index ].mTexcoord; return ret; } #endif #ifndef TERRAIN_COMMON_HLSL #define TERRAIN_COMMON_HLSL #include "Common.hlsl" // TODO: move to common perframe CB cbuffer PerFrameConstants : register(CBUFFER_REGISTER_DOMAIN) { float gMinDistance; float gMaxDistance; float gMinFactor; float gMaxFactor; } cbuffer PerTerrainConstants : register(CBUFFER_REGISTER_EXTRA) { float gHeightModifier; float gVariationScale; float gWorldMinX; float gWorldMinZ; float gWorldMaxX; float gWorldMaxZ; } struct PatchTess { float mEdgeTess[4] : SV_TessFactor; float mInsideTess[2] : SV_InsideTessFactor; }; struct VertexOut { float3 mWorldPosition : POSITION; float2 mTexcoord : TEXCOORD; }; struct DomainOut { float4 mPosition : SV_POSITION; float3 mNormal : NORMAL; float2 mTexcoord : TEXCOORD; }; struct HullOut { float3 mWorldPosition : POSITION; float2 mTexcoord : TEXCOORD; }; #endif #ifndef CONSTANTS_HLSL #define CONSTANTS_HLSL #define CBUFFER_SLOT_VERTEX 0 #define CBUFFER_SLOT_PIXEL 1 #define CBUFFER_SLOT_COMPUTE 2 #define CBUFFER_SLOT_DOMAIN 3 #define CBUFFER_SLOT_HULL 4 #define CBUFFER_SLOT_PER_FRAME 5 #define CBUFFER_SLOT_EXTRA 6 #define CBUFFER_REGISTER_VERTEX b0 #define CBUFFER_REGISTER_PIXEL b1 #define CBUFFER_REGISTER_COMPUTE b2 #define CBUFFER_REGISTER_DOMAIN b3 #define CBUFFER_REGISTER_HULL b4 #define CBUFFER_REGISTER_PER_FRAME b5 #define CBUFFER_REGISTER_EXTRA b6 #define SAMPLER_SLOT_ANISOTROPIC 0 #define SAMPLER_SLOT_POINT 1 #define SAMPLER_SLOT_POINT_COMPARE 2 #define SAMPLER_SLOT_LINEAR 3 #define SAMPLER_SLOT_LINEAR_WRAP 4 #define SAMPLER_REGISTER_ANISOTROPIC s0 #define SAMPLER_REGISTER_POINT s1 #define SAMPLER_REGISTER_POINT_COMPARE s2 #define SAMPLER_REGISTER_LINEAR s3 #define SAMPLER_REGISTER_LINEAR_WRAP s4 #define TEXTURE_SLOT_DIFFUSE 0 #define TEXTURE_SLOT_NORMAL 1 #define TEXTURE_SLOT_DEPTH 2 #define TEXTURE_SLOT_PERLIN 3 #define TEXTURE_SLOT_EXTRA 4 #define SBUFFER_SLOT_BONE_TRANSFORMS 4 #define SBUFFER_SLOT_EXTRA 5 #define TEXTURE_REGISTER_DIFFUSE t0 #define TEXTURE_REGISTER_NORMAL t1 #define TEXTURE_REGISTER_DEPTH t2 #define TEXTURE_REGISTER_PERLIN t3 #define TEXTURE_REGISTER_EXTRA t4 #define SBUFFER_REGISTER_BONE_TRANSFORMS t4 #define SBUFFER_REGISTER_EXTRA t5 #define UAV_SLOT 0 #define UAV_REGISTER u0 #define SDSM_THREAD_GROUP_SIZE 16 #define SDSM_NUM_THREADS (SDSM_THREAD_GROUP_SIZE * SDSM_THREAD_GROUP_SIZE) #define NUM_BONES_PER_VERTEX 4 #define LUM_MAP_WIDTH 1024 #define LUM_MAP_HEIGHT 1024 #endif I've attached both compiled shaders - is there something obvious wrong? TerrainHull_not_optimized.h TerrainHull_optimized.h
  8. This is only when a variable would not align itself to the 16byte boundary though right? C++: struct PerFrameCB { Mat4 mViewProj; Mat4 mView; Mat4 mInvView; Mat4 mInvProj; Vec3 mWorldEyePos; float mMinZ; float mMaxZ; float __padding[ 3 ]; }; HLSL: cbuffer PerFrameCB : register(CBUFFER_REGISTER_PER_FRAME) { float4x4 gFrameViewProj; float4x4 gFrameView; float4x4 gFrameInvView; float4x4 gFrameInvProj; float3 gWorldEyePos; float gMinZ; float gMaxZ; }; gMinZ should appear on the same 16-byte aligned row as gWorldEyePos and gMaxZ on a new row and thus it's fine? If I had like float2 gMinMaxZ I would need padding between them, but not like this? Also when I bind the CBuffer, it is entirely kocher to bind the same cbuffer to several shader stages on the same bindslot, right? For example I expose the per-frame data to all the shaderstages: void DX11ConstantBuffer::Bind() { mContext->VSSetConstantBuffers( mConstantBufferSlot, 1, &mConstantBuffer.p ); mContext->PSSetConstantBuffers( mConstantBufferSlot, 1, &mConstantBuffer.p ); mContext->CSSetConstantBuffers( mConstantBufferSlot, 1, &mConstantBuffer.p ); mContext->DSSetConstantBuffers( mConstantBufferSlot, 1, &mConstantBuffer.p ); mContext->HSSetConstantBuffers( mConstantBufferSlot, 1, &mConstantBuffer.p ); }
  9. I'm gonna double-check so that the padding is correct (as per https://docs.microsoft.com/sv-se/windows/desktop/direct3dhlsl/dx-graphics-hlsl-packing-rules) for all the cbuffers πŸ™‚
  10. No luck sadly. The struct that is normally mapped looks like this: struct PerFrameCB { Mat4 mViewProj; Mat4 mView; Mat4 mInvView; Mat4 mInvProj; Vec3 mWorldEyePos; float mMinZ; float mMaxZ; float __padding[ 3 ]; PerFrameCB() {} PerFrameCB( const Mat4& viewProj, const Mat4& view, const Mat4& invView, const Mat4& invProj, const Vec3& worldEyePos, float minZ, float maxZ ) : mViewProj(viewProj), mView(view), mInvView(invView), mInvProj(invProj), mWorldEyePos( worldEyePos ), mMinZ( minZ ), mMaxZ( maxZ ) { } }; I tried your suggested changes to the shader and changed the struct accordingly: struct PerFrameCB { Mat4 mViewProj; Mat4 mView; Mat4 mInvView; Mat4 mInvProj; Vec4 mWorldEyePos; Vec4 mMinZ_mMaxZ; PerFrameCB() {} PerFrameCB( const Mat4& viewProj, const Mat4& view, const Mat4& invView, const Mat4& invProj, const Vec3& worldEyePos, float minZ, float maxZ ) : mViewProj(viewProj), mView(view), mInvView(invView), mInvProj(invProj), mWorldEyePos( worldEyePos, 0.0f ), mMinZ_mMaxZ( minZ, maxZ, 0.0f, 0.0f ) { } }; Still the same πŸ™ This CBuffer is set at the beginning of every frame only.
  11. Also for reference this is how I set my constant buffer data, which should work fine on x64 aswell template <typename ContentType> DX11ConstantBuffer(ID3D11DevicePtr device, ID3D11DeviceContextPtr context, const CONSTANT_BUFFER_SLOT cbufferSlot) : mContext(context), mConstantBuffer(nullptr), mConstantBufferSlot(cbufferSlot) { D3D11_BUFFER_DESC bufferDescription; ZeroMemory(&bufferDescription, sizeof(D3D11_BUFFER_DESC)); bufferDescription.ByteWidth = static_cast<uint32_t>( sizeof(ContentType) ); bufferDescription.Usage = D3D11_USAGE_DYNAMIC; bufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER; bufferDescription.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; DXCALL(device->CreateBuffer(&bufferDescription, NULL, &mConstantBuffer)); } template <typename ContentType> void SetData(const ContentType& content) { D3D11_MAPPED_SUBRESOURCE mappedResource; ZeroMemory(&mappedResource, sizeof(D3D11_MAPPED_SUBRESOURCE)); DXCALL(mContext->Map(mConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource)); std::memcpy(mappedResource.pData, &content, sizeof(ContentType)); mContext->Unmap(mConstantBuffer, 0); }
  12. Some more imagines to describe the problem: Notice the wierd mix of tessellated and completely non-tessellated patches in the image. And then at the end frame, everything is non-tessellated: I am not sure how reliable RenderDoc is on the matter though... but the problem remains. After some more testing, the tearing stops and everything seems to work if I hardcode the tessellation factor in the shader. This is what it looks like without it, captured sample in renderdoc: float CalculateTessellationfactor( float3 worldPatchMidpoint ) { //float cameraToPatchDistance = distance( gWorldEyePos, worldPatchMidpoint ); float scaledDistance = 0.12f;// ( cameraToPatchDistance - gMinZ ) / ( gMaxZ - gMinZ ); scaledDistance = clamp( scaledDistance, 0.0f, 1.0f ); return pow( 2, lerp( 6.0f, 2.0f, scaledDistance ) ); } And then working sample: This is just crazy wierd. Here is the complete hull-shader without the edit-fix: #ifndef TERRAIN_HULL_HLSL #define TERRAIN_HULL_HLSL #include "TerrainCommon.hlsl" #include "Common.hlsl" float3 ComputePatchMidpoint( float3 corner1, float3 corner2, float3 corner3, float3 corner4 ) { return ( corner1 + corner2 + corner3 + corner4 ) / 4.0f; } float CalculateTessellationfactor( float3 worldPatchMidpoint ) { float cameraToPatchDistance = distance( gWorldEyePos, worldPatchMidpoint ); float scaledDistance = ( cameraToPatchDistance - gMinZ ) / ( gMaxZ - gMinZ ); scaledDistance = clamp( scaledDistance, 0.0f, 1.0f ); return pow( 2, lerp( 6.0f, 2.0f, scaledDistance ) ); } PatchTess PatchHS( InputPatch<VertexOut, 12> inputVertices ) { PatchTess patch; float3 midPatchMidpoint = ComputePatchMidpoint( inputVertices[ 0 ].mWorldPosition, inputVertices[ 1 ].mWorldPosition, inputVertices[ 2 ].mWorldPosition, inputVertices[ 3 ].mWorldPosition ); float3 edgePatchMidpoint[] = { ComputePatchMidpoint( inputVertices[ 0 ].mWorldPosition, inputVertices[ 1 ].mWorldPosition, inputVertices[ 4 ].mWorldPosition, inputVertices[ 5 ].mWorldPosition ), ComputePatchMidpoint( inputVertices[ 1 ].mWorldPosition, inputVertices[ 2 ].mWorldPosition, inputVertices[ 6 ].mWorldPosition, inputVertices[ 7 ].mWorldPosition ), ComputePatchMidpoint( inputVertices[ 2 ].mWorldPosition, inputVertices[ 3 ].mWorldPosition, inputVertices[ 8 ].mWorldPosition, inputVertices[ 9 ].mWorldPosition ), ComputePatchMidpoint( inputVertices[ 3 ].mWorldPosition, inputVertices[ 0 ].mWorldPosition, inputVertices[ 10 ].mWorldPosition, inputVertices[ 11 ].mWorldPosition ) }; float midPatchTessFactor = CalculateTessellationfactor( midPatchMidpoint ); float edgePatchTessFactors[] = { CalculateTessellationfactor( edgePatchMidpoint[ 3 ] ), CalculateTessellationfactor( edgePatchMidpoint[ 0 ] ), CalculateTessellationfactor( edgePatchMidpoint[ 1 ] ), CalculateTessellationfactor( edgePatchMidpoint[ 2 ] ) }; patch.mEdgeTess[ 0 ] = min( midPatchTessFactor, edgePatchTessFactors[ 0 ] ); patch.mEdgeTess[ 1 ] = min( midPatchTessFactor, edgePatchTessFactors[ 1 ] ); patch.mEdgeTess[ 2 ] = min( midPatchTessFactor, edgePatchTessFactors[ 2 ] ); patch.mEdgeTess[ 3 ] = min( midPatchTessFactor, edgePatchTessFactors[ 3 ] ); patch.mInsideTess[ 0 ] = midPatchTessFactor; patch.mInsideTess[ 1 ] = midPatchTessFactor; return patch; } [domain("quad")] [partitioning("fractional_odd")] [outputtopology("triangle_ccw")] [outputcontrolpoints(4)] [patchconstantfunc("PatchHS")] HullOut hs_main( InputPatch<VertexOut, 12> verticeData, uint index : SV_OutputControlPointID ) { HullOut ret; ret.mWorldPosition = verticeData[ index ].mWorldPosition; ret.mTexcoord = verticeData[ index ].mTexcoord; return ret; } #endif cbuffer PerFrameCB : register(CBUFFER_REGISTER_PER_FRAME) { float4x4 gFrameViewProj; float4x4 gFrameView; float4x4 gFrameInvView; float4x4 gFrameInvProj; float3 gWorldEyePos; float gMinZ; float gMaxZ; }; and inspecting the constant-buffer it looks like this: The contents looks legit. Again, the problem seems localized to this shader, but it might very well be a well-obscured problem.. it's bizare because I use constant buffers all the time and they work just fine. The same constant buffer contains other data like transformation matrices that work just fine.
  13. I have a renderer project that I recently upgraded from VS2015 x86 -> VS2019 x64 and got a new, more powerful computer aswell. I got maybe a 2-3x FPS increase. However I ran into a few problems: Screen-tearing. The less intense the gamescene, the more FPS, and the more visible tearing. One of my per-frame constant buffers appears to have garbage contents (more on that later) Inspecting the backbuffer in RenderDoc in captured sample it appears to have several different frames depending on at what point you inspect it (might be a renderdoc bug but maybe not) When I enable VSync the screen tearing is less but not completely gone. I believe the old compiler and/or my older computer hid these issues before. So I must be something wrong with my swapchain setup or somesuch. My swapchain creation: ZeroMemory(&mSwapchainDesc, sizeof(DXGI_SWAP_CHAIN_DESC)); mSwapchainDesc.BufferCount = 2; mSwapchainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; mSwapchainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; mSwapchainDesc.OutputWindow = mWindowHandle; mSwapchainDesc.SampleDesc.Count = 1; mSwapchainDesc.Windowed = true; DXCALL(D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, 0, deviceFlags, &featureLevel, numFeatureLevels, D3D11_SDK_VERSION, &mSwapchainDesc, &mSwapchain, &mDevice, nullptr, &mContext)); I am using deferred rendering and use a light accumulation buffer as the RTV when doing shadows/lights. I then do tonemapping on it and output it to the backbuffer in sRGB format. Then I copy the backbuffer texture to use it as input to a FXAA shader which renders into the backbuffer again. After that I optionally do a bunch of debug passes directly into the backbuffer aswell before I call present(). (I also read the depth texture during a depth reduction pass but I don't think thats relevant to these problems) On point 2) I have a very simple way to calculate tessellation factor like this: float CalculateTessellationfactor( float3 worldPatchMidpoint ) { float cameraToPatchDistance = distance( gWorldEyePos, worldPatchMidpoint ); float scaledDistance = ( cameraToPatchDistance - gMinZ ) / ( gMaxZ - gMinZ ); scaledDistance = clamp( scaledDistance, 0.0f, 1.0f ); return pow( 2, lerp( 6.0f, 2.0f, scaledDistance ) ); } gMinZ/gMaxZ is min/far Z that is set once-per-frame in a constant buffer. When I inspect them in RenderDoc they have correct values (and it worked before), but apparently they do not when I render, but if I hardcode the values in the shader then it works. I assume they are overwritten repeatedly and garbage when I read them in the shader? --------------------------------------------------------------------- All in all I guess I am rendering too fast and overwriting resources all the time. How would I go about solving this?
  14. KaiserJohan

    Smooth normals and Tessellation

    Any pointers are much appreciated πŸ™‚
  15. KaiserJohan

    Smooth normals and Tessellation

    Hmm.. how am I changing the heights after generating the normals? It's all done in a previous shader stage? > - Calculate in the domain shader based on heightmap sampling I suppose this seems like a solid option. Will the normals be correctly interpolated in the pixel shader? Is there anything different from calculating normals in domain shader from say how you typically do it in a simple vertex shader?
  • Advertisement
Γ—

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net isΒ your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!