Yann ALET

Members
  • Content count

    44
  • Joined

  • Last visited

Community Reputation

258 Neutral

About Yann ALET

  • Rank
    Member
  1.     Hehe, thanks, i already read (most of) Frank's book, that's where i started. I already made all those things you mentioned, and that's how i came to this odd conclusion :-)
  2. Gotcha ... I guess i'll use both :-)   I can see how important it is to have strong fondations, but sometimes it helps to see the end results and all the required inputs to know why you'll have to build this input in your engine.
  3. Why is that so?       Well, i think it takes a massive part out of the equation, and allow you to focus on one thing because you know the rest if working properly.   It's like, if I wanted to wanted to create heads up display for cars, should i start by building the actual car, research how a combustion engine works, aerodynamics, etc... and once the car is kind of working, start working on the actual dashboard hopping the electronic i setup won't fail me and send me wrong inputs & metrics ?   I remember at some point i wanted to have a proper sky, and i found this guy making a good one in GLSL : http://devlog-martinsh.blogspot.ca/2013/11/waterunderwater-sky-shader-update-03.html I only studied HLSL, so i needed to port it. The original shader was quite complex and i was having a hard time implementing it. I wasn't sure the problem came from my HLSL code, or actual engine feeding wrong values to the shader. So i decided to port it in 3DSMax first, and it worked wonders. I had immediate feedback and lot more tools to experiment (sliders for shader constants and such). This allowed me to have a better understanding of the shader, and i easily implemented it in my engine afterward. I didn't have to worry about things like properly computing normals as Max was doing it for me (i had to at some point in my engine, but i knew my shader code was correct at that point).   Now i want to study effects like DOF, chromatic aberration, and film grains. I can't help to think it will be a lot easier to implement this in a shader graph node editor, and once it works, try to break it down in actual HLSL.
  4. Hi there,   If you want to learn rendering programming. Is it really a smart move to start with working on your own engine ?   The more i think about it, the more i think it should be the opposite.   What do you guys think ?
  5. DX11 Can't fix shadow acne with bias

    Hi L. Spiro,   Thanks for your help, greatly appreciated, i am learning a lot. It seems the front culling approach just doesn't work well in my test case. The result is simply the same as my original code :       Normal offset just for reference :     I can see how internal faces of a cube would cast shadow over the next one and cause this artifact in the process. I guess i would need to eliminates these useless faces and the issue would naturally disappear, but doing so might be tricky because everything here is based on instancing. I assume i would need something like a geometry shader to remove internal faces right before creating my shadow map, but i am not familiar with those yet (not even sure that's the proper name for such operation, or even if it's a the good approach).   Anyway, i'll stick with the normal offset trick for now until i get better to implement fancier techniques :-)
  6. DX11 Can't fix shadow acne with bias

    Hi there, So i tried the front culling approach and it did not work :(       It also shows that my cubes are not perfectly connected as we can see a very thin line of light at the base of the cube casting shadow. I tried this quickly during a lunch break though, so i try harder tonight when i get home.   Thanks :-)
  7. DX11 Can't fix shadow acne with bias

      Humm i did not notice that artefact until you mentioned it. I removed the fix to see if it was introduced by the normal offset, and it looks like it is.     I guess i'll have to find a way to compensate 
  8. DX11 Can't fix shadow acne with bias

    Omg it works, thank you all so much !!!   // Generate projective tex-coords to project shadow map onto scene. float4x4 worldShadowTransform = mul(world, gShadowTransform); vout.ShadowPosH = mul(float4(vin.PosL + (vin.NormalL*0.1f), 1.0f), worldShadowTransform);
  9. DX11 Can't fix shadow acne with bias

      Ohhhhhh !!! how did i miss that ?! Ok i'll try right now :-)   Thanks !
  10. DX11 Can't fix shadow acne with bias

    Thanks for all your suggestions !   I'll try Aardvajk's approach 1st. I tried to implement your method, but it doesn't give me the expected result. The shader i build the shadow map with, is actually a very simple vertex shader where i just draw the scene on the deph buffer :   VertexOut VS(VertexIn vin) { VertexOut vout; float4x4 world = GetIdentity(); world[3][0] =  vin.World.x; world[3][1] =  vin.World.y; world[3][2] =  vin.World.z; float4x4 worldViewProj = mul(world, gViewProj); vout.PosH = mul(float4(vin.PosL, 1.0f), worldViewProj); vout.Tex  = mul(float4(vin.Tex, 0.0f, 1.0f), gTexTransform).xy; return vout; } My first attempt was to slightly "push" vertices away from their position in the direction of their normal vector :   VertexOut VS(VertexIn vin) { VertexOut vout; float4x4 world = GetIdentity(); world[3][0] =  vin.World.x; world[3][1] =  vin.World.y; world[3][2] =  vin.World.z; float4x4 worldViewProj = mul(world, gViewProj); vout.PosH = mul(float4(vin.PosL + vin.NormalL * 0.2f, 1.0f), worldViewProj); vout.Tex  = mul(float4(vin.Tex, 0.0f, 1.0f), gTexTransform).xy; return vout; } This made things worse :     I think i probably did this wrong, but i am not exactly sure what i missed here. Just to be sure, i increased the factor by 2 : VertexOut VS(VertexIn vin) { VertexOut vout; float4x4 world = GetIdentity(); world[3][0] =  vin.World.x; world[3][1] =  vin.World.y; world[3][2] =  vin.World.z; float4x4 worldViewProj = mul(world, gViewProj); vout.PosH = mul(float4(vin.PosL + vin.NormalL * 2.0f, 1.0f), worldViewProj); vout.Tex  = mul(float4(vin.Tex, 0.0f, 1.0f), gTexTransform).xy; return vout; }   We can see on the depth buffer faces of cubes going away from each others in the direction of normals, i i think that's the point of this technique.   Then i tried a similar approach by trying to scale the scene up by 5% just for the shadow map, and this was also a failure :  VertexOut VS(VertexIn vin) { VertexOut vout; float4x4 world = GetIdentity(); world[3][0] =  vin.World.x; world[3][1] =  vin.World.y; world[3][2] =  vin.World.z; float4x4 worldViewProj = mul(world, gViewProj); vout.PosH = mul(float4(vin.PosL * 1.05f, 1.0f), worldViewProj); vout.Tex  = mul(float4(vin.Tex, 0.0f, 1.0f), gTexTransform).xy; return vout; }   I'll keep experimenting though :-)
  11. DX11 Can't fix shadow acne with bias

    Hummm normal offset shadow ? Never heard of that (still very new to rendering). Any article, tutorial to suggest ?
  12. Hi there,   Lately i decided to dig up an old project of mine i stopped working on because shadows was giving me a hard time. Well, my shadow issue is still there, and i need help to figure this thing out.   My problem :   I have shadow acne :   http://youtu.be/K2CyKoAf-sI   I am learning D3D programming with Franck Luna's book which comes with code sample i used in my engine. The book says that acne is a common issue when working with shadow mapping, and is usually fixed by increasing the bias. I did, and predictably the acne was gone, but then i had the "peter pan" issue where the shadow would look detached from it's source :   http://youtu.be/W05WJKRwrv4   According to the book, you have to make lots of experiment with your scene to find the sweet spot (perfect bias i presume). Well i tried a lot of different values, but instead of finding the perfect bias, i ended up having both peter pan AND acne.   When i start digging on the internet how to fix shadows, i often find articles about PCF filtering which and other advanced techniques which, if i am not mistaken, will not help me fix my acne issue but improve shadow edges quality.   Implementation :   I tried to implement Frank Luna's shadow mapping sample the best i could in my engine:   Main draw call :   void LightGame::DrawScene() { mGameComponents[GameComponent::Id::Land]->BuildShadowMap(); ResetRenderTarget(); mGameComponents[GameComponent::Id::Land]->Draw(); // ... HR(mSwapChain->Present(0, 0)); }   1- I first build the Land's shadow map by rendering the land on the depth buffer only. 2- Then i reset the render target back to the backbuffer. 3- Then render the land normaly now that it has the shadow map.   This is how i build the shadow map. Note that the "Chunk" class represents the "Land" component.   void Chunk::BuildShadowMap() { // Prepare drawing on depth buffer only. GetShadowMap()->SetRenderTargetToDepthBuffer(); // I build the transform matrix i'll use to transform the shadow map from light, to player perspective. // I also initialize mLightView, and mLightProj in there. BuildShadowTransform(); // Draw the land from the light perspective. XMMATRIX view     = XMLoadFloat4x4(&mLightView); XMMATRIX proj     = XMLoadFloat4x4(&mLightProj); XMMATRIX viewProj = XMMatrixMultiply(view, proj); mBuildShadowMapFX->SetViewProj(viewProj); ID3DX11EffectTechnique* tessSmapTech = mBuildShadowMapFX->BuildShadowMapTech; ID3D11DeviceContext* deviceContext = Graphics::GetInstance().GetImmediateContext(); deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); deviceContext->IASetInputLayout(mBuildShadowMapFX->GetInputLayout()); UINT stride[] = {sizeof(Vertex::Basic32), sizeof(InstanceData)}; UINT offset[] = {0, 0}; ID3D11Buffer* bufferPointers[2] = {mVB, mInstanceBuffer};     D3DX11_TECHNIQUE_DESC techDesc; tessSmapTech->GetDesc( &techDesc );     deviceContext->IASetVertexBuffers(0, 2, bufferPointers, stride, offset); deviceContext->IASetIndexBuffer(mIB, DXGI_FORMAT_R32_UINT, 0); for(UINT p = 0; p < techDesc.Passes; ++p)     { mBuildShadowMapFX->SetViewProj(viewProj); mBuildShadowMapFX->SetTexTransform(XMMatrixScaling(2.0f, 1.0f, 1.0f)); tessSmapTech->GetPassByIndex(p)->Apply(0, deviceContext); deviceContext->DrawIndexedInstanced(36, mNumberOfActiveCubes, 0, 0, 0);     } } This is how i build the transform matrix for the shadow map. void Chunk::BuildShadowTransform(void) { DirectionalLight* sunLight = World::GetInstance().GetSunlight(); XMFLOAT3 lightPosFloat3; XMVECTOR lightDir = XMLoadFloat3(&sunLight->Direction); XMVECTOR lightPos = mBoundingSphere->Radius*(lightDir * -1.0f) * 2; XMStoreFloat3(&lightPosFloat3, lightPos); lightPosFloat3.x += mBoundingSphere->Center.x; lightPosFloat3.z += mBoundingSphere->Center.z; lightPos = XMLoadFloat3(&lightPosFloat3); XMVECTOR targetPos = XMLoadFloat3(&mBoundingSphere->Center); XMVECTOR up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f); XMMATRIX V = XMMatrixLookAtLH(lightPos, targetPos, up); // Transform bounding sphere to light space. XMFLOAT3 sphereCenterLS; XMStoreFloat3(&sphereCenterLS, XMVector3TransformCoord(targetPos, V)); // Ortho frustum in light space encloses scene. float l = sphereCenterLS.x - mBoundingSphere->Radius; float b = sphereCenterLS.y - mBoundingSphere->Radius; float n = sphereCenterLS.z - mBoundingSphere->Radius; float r = sphereCenterLS.x + mBoundingSphere->Radius; float t = sphereCenterLS.y + mBoundingSphere->Radius; float f = sphereCenterLS.z + mBoundingSphere->Radius; XMMATRIX P = XMMatrixOrthographicOffCenterLH(l, r, b, t, n, f); // Transform NDC space [-1,+1]^2 to texture space [0,1]^2 XMMATRIX T( 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.5f, 0.5f, 0.0f, 1.0f); XMMATRIX S = V*P*T; XMStoreFloat4x4(&mLightView, V); XMStoreFloat4x4(&mLightProj, P); XMStoreFloat4x4(&mShadowTransform, S); }   mBuildShadowMapFX shader :   #include "utility.fx" cbuffer cbPerObject { float4x4 gViewProj; float4x4 gTexTransform; };  struct VertexIn { float3 PosL     : POSITION0; float3 NormalL  : NORMAL; float2 Tex      : TEXCOORD; float2 IsSelected : TEXCOORD1; float3 World    : POSITION1; }; struct VertexOut { float4 PosH : SV_POSITION; float2 Tex  : TEXCOORD; }; VertexOut VS(VertexIn vin) { VertexOut vout; float4x4 world = GetIdentity(); world[3][0] =  vin.World.x; world[3][1] =  vin.World.y; world[3][2] =  vin.World.z; float4x4 worldViewProj = mul(world, gViewProj); vout.PosH = mul(float4(vin.PosL, 1.0f), worldViewProj); vout.Tex  = mul(float4(vin.Tex, 0.0f, 1.0f), gTexTransform).xy; return vout; } RasterizerState Depth { DepthBias = 1000; // <- This is where i play with the bias !!!     DepthBiasClamp = 0.0f; SlopeScaledDepthBias = 1.0f; }; technique11 BuildShadowMapTech {     pass P0     { SetVertexShader( CompileShader( vs_5_0, VS() ) );         SetGeometryShader( NULL );         SetPixelShader( NULL ); SetRasterizerState(Depth);     } }   And now the main shader rendering the land using the shadow map :   #include "light.fx" #include "utility.fx" float oneThird = 0.3334f; float twoThird = 0.6667f; float borderYThickness = 0.007f; float borderXThickness = 0.007f / 3.0f; float4 borderColor = float4(0.1f, 0.1f, 0.1f, 1.0f); struct VertexIn { float3 PosL    : POSITION0; float3 NormalL : NORMAL; float2 Tex     : TEXCOORD0; float2 IsSelected : TEXCOORD1; float3 World    : POSITION1; float2 CubeType : TEXCOORD2; }; struct VertexOut { float4 PosH    : SV_POSITION;     float3 PosW    : POSITION; float3 PosVS   : POSITION1; float3 ViewRay   : POSITION2;     float3 NormalW : NORMAL; float2 Tex     : TEXCOORD; float IsSelected : DEPTH; float4 ShadowPosH : TEXCOORD1; float CubeType : DEPTH1; }; cbuffer cbPerObject { float4x4 gWorld; float4x4 gView; float4x4 gWorldInvTranspose; float4x4 gViewProj; float4x4 gProjInvTranspose; float4x4 gTexTransform; float4x4 gShadowTransform; Material gMaterial; }; cbuffer cbPerFrame { DirectionalLight gDirLight; float3 gEyePosW; }; // Nonnumeric values cannot be added to a cbuffer. Texture2DArray gBlockMapArray; SamplerState Aniso { Filter = ANISOTROPIC; MaxAnisotropy = 4; AddressU = WRAP; AddressV = WRAP; }; SamplerComparisonState samShadow { Filter   = COMPARISON_MIN_MAG_LINEAR_MIP_POINT; AddressU = BORDER; AddressV = BORDER; AddressW = BORDER; BorderColor = float4(0.0f, 0.0f, 0.0f, 0.0f);     ComparisonFunc = LESS_EQUAL; }; RasterizerState DisableCulling { CullMode = BACK; }; SamplerState samLinear { Filter = MIN_MAG_MIP_LINEAR; AddressU = Wrap; AddressV = Wrap; }; Texture2D gShadowMap; VertexOut VS(VertexIn vin) { VertexOut vout; float4x4 world = GetIdentity(); world[3][0] =  vin.World.x; world[3][1] =  vin.World.y; world[3][2] =  vin.World.z; float4x4 WorldViewMatrix = mul(world, gView); // Transform to world space. vout.PosW    = mul(float4(vin.PosL, 1.0f), world).xyz; // Find transformed normals. vout.NormalW = mul(vin.NormalL, (float3x3)world); // Transform to homogeneous clip space. vout.PosH = mul(float4(vout.PosW, 1.0f), gViewProj);     vout.Tex = mul(float4(vin.Tex, 0.0f, 1.0f), gTexTransform).xy; vout.IsSelected = vin.IsSelected.x; // Generate projective tex-coords to project shadow map onto scene. float4x4 worldShadowTransform = mul(world, gShadowTransform); vout.ShadowPosH = mul(float4(vin.PosL, 1.0f), worldShadowTransform); float3 positionVS = mul(vin.PosL, gProjInvTranspose); vout.ViewRay = float3(positionVS.xy / positionVS.z, 1.0f); vout.PosVS = mul(float4(vin.PosL, 1.0f), WorldViewMatrix); vout.CubeType = vin.CubeType.x;          return vout; } float GetPercentLit(SamplerComparisonState samShadow, Texture2D shadowMap, float4 shadowPosH) { // Complete projection by doing division by w. shadowPosH.xyz /= shadowPosH.w; // Depth in NDC space (from light source). float depth = shadowPosH.z; return shadowMap.SampleCmpLevelZero(samShadow, shadowPosH.xy, depth).r; } float4 PS(VertexOut pin) : SV_Target { // Highlighting edges of the block if it's selected. if(pin.IsSelected == 1.0f) { if(pin.Tex.x  > oneThird && pin.Tex.x  < oneThird + borderXThickness) { return borderColor; } if(pin.Tex.x  > twoThird - borderXThickness && pin.Tex.x  < twoThird) { return borderColor; } if(pin.Tex.y  > 0.0 && pin.Tex.y  < borderYThickness) { return borderColor; } if(pin.Tex.y  > 1.0 - borderYThickness) { return borderColor; } }     // Interpolating normal can unnormalize it, so normalize it.     pin.NormalW = normalize(pin.NormalW); // Start with a sum of zero.  float4 ambient = float4(0.0f, 0.0f, 0.0f, 0.0f); float4 diffuse = float4(0.0f, 0.0f, 0.0f, 0.0f); float3 uvw = float3(pin.Tex, pin.CubeType); float4 texColor = gBlockMapArray.Sample(Aniso, uvw); ambient = gMaterial.Ambient * gDirLight.Ambient; // The light vector aims opposite the direction the light rays travel. float3 lightVec = -gDirLight.Direction; // Add diffuse and specular term, provided the surface is in  // the line of site of the light. float diffuseFactor = dot(lightVec, pin.NormalW); // Flatten to avoid dynamic branching. [flatten] if( diffuseFactor > 0.0f ) { diffuse = diffuseFactor * gMaterial.Diffuse * gDirLight.Diffuse; } float percentLit = GetPercentLit(samShadow, gShadowMap, pin.ShadowPosH); diffuse = diffuse * percentLit; float4 litColor = texColor * (diffuse + ambient); // Common to take alpha from diffuse material. litColor.a = gMaterial.Diffuse.a; return litColor; } technique11 BlockTech {     pass P0     {         SetVertexShader( CompileShader( vs_5_0, VS() ) ); SetGeometryShader( NULL );         SetPixelShader( CompileShader( ps_5_0, PS() ) ); SetRasterizerState(DisableCulling);     } }     I think this is it. I tried all kind of things, but i still do not understand where the issue is. Any help or suggestion would be greatly appreciated :-)   BTW, the full source is available here if you're interested : https://www.dropbox.com/s/0rmiln0bua3pshk/source.zip?dl=0 I have a dependency on Effect11.lib i compiled with VS2013, so you might need to rebuild it if you have and older version of VS.
  13. Poor STL threads performance

      Not sure what you mean, but i tried multiple approaches. The one i wrote above, and this one too :   for(int m_prime = 0; i < N; i++) {      threads.push_back(std::thread(&Ocean::DoFFT, this, 1, m_prime * N));      if(threads.size() == 4)      {            //.. join all 4 threads before moving to the next batch.      } }   But like Hogman mentioned, i am spawning 64 threads even with this approach, i'll just create some kind of threadpool of 4 permanent threads instead.   Side question though, assuming i make this thing work properly with expected fps boost, would i get better performance with OpenMP (so code still executed on CPU), or should i jump directly to a OpenCL implementation ?   Thanks for your help !
  14. Poor STL threads performance

    I don't think a statement about speed is at all viable when talking about MSVC's Debug builds. Debug builds are for finding bugs, not testing the speed of anything.   Sure, but as my reference fps was also in debug, i figured i could compare apples to apples. I'll keep that in mind though :-)
  15. Poor STL threads performance

      Hummm interesting, i'll try this when i get home then, thanks !