• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.

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

    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

    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

      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

    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

      Ohhhhhh !!! how did i miss that ?! Ok i'll try right now :-)   Thanks !
  10. DX11

    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

    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.   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. 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.   Hummm interesting, i'll try this when i get home then, thanks !