   Occlusion Query
  I am picking my work back up trying to convert this XNA sample to DX10.I've gotten as far as the occlusion query, got it rendered, and even worked out how to actually make it get occluded by scene geometry while playing with the Z used to draw it.The sample is just too simple, they only have a terrain and the lensflare. I don't even think it would get occluded by scene geometry if there was any.But anywho...It seems my occlusion query only gets drawn every other frame. I understand I am returning if the GetData fails, but I don't really understand when the query takes place and for how long. If it was simply between query->Begin() and query->End() then it should never fail to get the data.My concern is that once I draw the glow part on top of the query, that the query will be occluded by the glow. Am I missing something? I understand I am going to turn off writes to the depth buffer, which I guess is going to make anything drawn after, get drawn on top. That's why I am confused as to when the query actually takes place. If it is immediately between the begin and end calls, then that would make sense. If it takes longer than it wouldn't.So, questions:1) Why does the query get drawn every other frame.2) Did I code up the query incorrectly opposed to somehow getting it every frame.3) Does it indeed only occur between the query->begin() and query->end(), but take some time to actually give me back the data?4) Won't my drawing the glow actually occlude the query?#include "LensFlare.h"// Common Lib Includes#include "StringUtil.h"#include "BaseException.h"// Standard Includes#include <algorithm>using namespace common_lib_cpisz;//---------------------------------------------------------------------------LensFlare::LensFlare(ID3D10Device & device,  InputLayoutManager & inputLayoutManager,  TextureManager & textureManager, EffectManager & effectManager, Position lightPosition, const std::string & glowTextureFilePath, const std::string & flare1TextureFilePath, const std::string & flare2TextureFilePath, const std::string & flare3TextureFilePath)   :   m_querySize(100.0f),   m_glowSize(400.0f),   m_device(device),   m_inputLayoutManager(inputLayoutManager),   m_textureManager(textureManager),   m_effectManager(effectManager),   m_lightPosition(lightPosition),   m_occlusionQuery(NULL),   m_occlusionQueryActive(false){   // SNIP long exception string   // Load the textures   std::string glowTextureName;   std::string flare1TextureName;   std::string flare2TextureName;   std::string flare3TextureName;   RemoveExtFromFilename(glowTextureFilePath, glowTextureName);   RemoveExtFromFilename(flare1TextureFilePath, flare1TextureName);   RemoveExtFromFilename(flare2TextureFilePath, flare2TextureName);   RemoveExtFromFilename(flare3TextureFilePath, flare3TextureName);   m_textureManager.CreateTextureFromFile(glowTextureName, glowTextureFilePath);   m_textureManager.CreateTextureFromFile(flare1TextureName, flare1TextureFilePath);   m_textureManager.CreateTextureFromFile(flare2TextureName, flare2TextureFilePath);   m_textureManager.CreateTextureFromFile(flare3TextureName, flare3TextureFilePath);   // Create the effects   Technique * occlusionTechnique = NULL; try   { m_effect = &(m_effectManager.CreateChildEffect("LensFlare", "LensFlare.fx")); occlusionTechnique = &(m_effect->GetTechnique("OcclusionQuery")); m_occlusionPass    = &(occlusionTechnique->GetPass(0));   }   catch(BaseException & e)   { throw e;   }   // Create materials   try   { m_occlusionMaterial = m_effect->CreateMaterial(); m_occlusionMaterial->SetBool("diffuseMapped", true); m_occlusionMaterial->SetFloat4("diffuseColor", static_cast<D3DXVECTOR4>(D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f)));   }   catch(BaseException & e)   { throw e;   }   // Create a occlusion query rectangle shape   //   // NOTE - vertices are defined in counter clockwise order, instead of clockwise,   //   because the projection into 2D screen space flips the quad in the Y   //   direction and it would get culled as a backface if defined normally   std::vector<Position> occlusionPositions;   occlusionPositions.push_back(Position( -0.5f, -0.5f, 0.0f));   occlusionPositions.push_back(Position(  0.5f, -0.5f, 0.0f));   occlusionPositions.push_back(Position( -0.5f,  0.5f, 0.0f));   occlusionPositions.push_back(Position(  0.5f,  0.5f, 0.0f)); m_occlusionBuffer = Buffer::SharedPtr(new Buffer(m_device, POSITION, occlusionPositions, false));   // Create a input layouts   std::vector<InputElementDescription> inputElementDescs;   std::vector<InputElementDescription> thisElementDesc;   InputElementDescription::GetInputElementDesc(thisElementDesc,   m_occlusionBuffer->GetContentType(),    0,   0,   m_occlusionBuffer->IsPerInstance());   inputElementDescs.insert(inputElementDescs.end(), thisElementDesc.begin(), thisElementDesc.end());   m_occlusionInputLayout = m_inputLayoutManager.GetInputLayout(inputElementDescs, *m_occlusionPass);   // Create the occlusion query   D3D10_QUERY_DESC  queryDesc;   queryDesc.MiscFlags = 0;   queryDesc.Query= D3D10_QUERY_OCCLUSION;   if( FAILED(m_device.CreateQuery(&queryDesc, &m_occlusionQuery)) )   { exception.m_msg = "Could not create occlusion query"; throw exception;   }   // Init the flare circle datas   m_flares.push_back(Flare(-0.5f, 0.7f, D3DXCOLOR( 50,  25,  50, 255), "flare1"));   m_flares.push_back(Flare( 0.3f, 0.4f, D3DXCOLOR(100, 255, 200, 255), "flare1"));   m_flares.push_back(Flare( 1.2f, 1.0f, D3DXCOLOR(100,  50,  50, 255), "flare1"));   m_flares.push_back(Flare( 1.5f, 1.5f, D3DXCOLOR( 50, 100,  50, 255), "flare1"));   m_flares.push_back(Flare(-0.3f, 0.7f, D3DXCOLOR(200,  50,  50, 255), "flare2"));   m_flares.push_back(Flare( 0.6f, 0.9f, D3DXCOLOR( 50, 100,  50, 255), "flare2"));   m_flares.push_back(Flare( 0.7f, 0.4f, D3DXCOLOR( 50, 200, 200, 255), "flare2"));   m_flares.push_back(Flare(-0.7f, 0.7f, D3DXCOLOR( 50, 100,  25, 255), "flare3"));   m_flares.push_back(Flare( 0.0f, 0.6f, D3DXCOLOR( 25,  25,  25, 255), "flare3"));   m_flares.push_back(Flare( 2.0f, 1.4f, D3DXCOLOR( 25,  50, 100, 255), "flare3"));}//---------------------------------------------------------------------------LensFlare::~LensFlare(){   // Release the occlusion query   if( m_occlusionQuery )   { m_occlusionQuery->Release();   }}//---------------------------------------------------------------------------void LensFlare::Render(){   // Get the original matrices   D3DXMATRIX origProjection;   D3DXMATRIX origView;   m_effectManager.GetViewMatrix(origView);   m_effectManager.GetProjectionMatrix(origProjection);   // Get the viewport   UINT   numViewports = 1;   D3D10_VIEWPORT   viewport;   m_device.RSGetViewports(&numViewports, &viewport);   // Create new view matrix with the camera at the origin for projection of the position into the background   D3DXMATRIX newView = origView;   newView._41 = newView._42 = newView._43 = 0.0f;   newView._44 = 1.0f;   // Project the light position into 2D screen space   D3DXMATRIX identity;   D3DXMatrixIdentity(&identity);   D3DXVECTOR3 projectedPosition;   D3DXVec3Project(&projectedPosition, &m_lightPosition, &viewport, &origProjection, &newView, &identity);   // Don't draw any flares if the light is behind the camera   if( (projectedPosition.z < 0.0f) || (projectedPosition.z > 1.0f) )   { return;   }   D3DXVECTOR3 lightPosition(projectedPosition.x, projectedPosition.y, projectedPosition.z);   // Set up matrices to render in screen space   D3DXMatrixIdentity(&newView);   m_effectManager.SetViewMatrix(newView);   D3DXMATRIX newProjection;   D3DXMatrixOrthoOffCenterLH(&newProjection,0.0f,static_cast<float>(viewport.Width),static_cast<float>(viewport.Height),0.0f,0.0f,1.0f);   m_effectManager.SetProjectionMatrix(newProjection);   // Check whether the light is occluded by the scene   UpdateOcclusion(lightPosition);   // If it is visible, draw the flare   if( m_occlusionAlpha > 0 )   { RenderGlow(D3DXVECTOR2(lightPosition.x, lightPosition.y)); RenderFlares(D3DXVECTOR2(lightPosition.x, lightPosition.y));   }   // Restore Matrices   m_effectManager.SetViewMatrix(origView);   m_effectManager.SetProjectionMatrix(origProjection);}//---------------------------------------------------------------------------void LensFlare::UpdateOcclusion(D3DXVECTOR3 lightPosition){   if( m_occlusionQueryActive )   { // If the previous query has not yet completed, wait until it does UINT64 queryData; if( S_OK != m_occlusionQuery->GetData(&queryData, sizeof(UINT64), 0) ) {    return; } // Use the occlusion query pixel count to work out what percentage of the sun is visible const float queryArea = m_querySize * m_querySize; m_occlusionAlpha = std::min<float>(static_cast<float>(queryData) / queryArea, 1.0f);   }   // Set the world matrix and material   D3DXMATRIX matScale;   D3DXMATRIX matTranslation;   D3DXMATRIX world;   D3DXMatrixScaling(&matScale, m_querySize, m_querySize, 1.0f);   D3DXMatrixTranslation(&matTranslation, lightPosition.x, lightPosition.y, lightPosition.z);   D3DXMatrixMultiply(&world, &matScale, &matTranslation); try   { m_effect->SetWorldMatrix(world); m_effect->SetMaterial(*m_occlusionMaterial);   }   catch(BaseException & e)   { throw e;   }   // Bind the input layout   m_device.IASetInputLayout(m_occlusionInputLayout);   m_device.IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);   // Bind the vertex buffers   ID3D10Buffer * buffer = m_occlusionBuffer->GetD3DBuffer();   UINT stride = GetStride(m_occlusionBuffer->GetContentType());   UINT offset = 0; m_device.IASetVertexBuffers(0, 1, &buffer,  &stride,  &offset);   // Apply the pass   m_occlusionPass->Apply();   // Issue the occlusion query   m_occlusionQuery->Begin();   m_device.Draw(4, 0);   m_occlusionQuery->End();   // Flag the occlusion query as active   m_occlusionQueryActive = true;/*   // Set renderstates for drawing the occlusion query geometry. We want depth   // tests enabled, but depth writes disabled, and we set ColorWriteChannels   // to None to prevent this query polygon actually showing up on the screen.   RenderState renderState = GraphicsDevice.RenderState;   renderState.DepthBufferEnable = true;   renderState.DepthBufferWriteEnable = false;   renderState.AlphaTestEnable = false;   renderState.ColorWriteChannels = ColorWriteChannels.None;   // Reset renderstates.   renderState.ColorWriteChannels = ColorWriteChannels.All;   renderState.DepthBufferWriteEnable = true;*/}//---------------------------------------------------------------------------void LensFlare::RenderFlares(D3DXVECTOR2 lightPosition){/*   Viewport viewport = GraphicsDevice.Viewport;   // Lensflare sprites are positioned at intervals along a line that   // runs from the 2D light position toward the center of the screen.   Vector2 screenCenter = new Vector2(viewport.Width, viewport.Height) / 2; Vector2 flareVector = screenCenter - lightPosition;   // Draw the flare sprites using additive blending.   spriteBatch.Begin(SpriteBlendMode.Additive);   foreach (Flare flare in flares)   {  // Compute the position of this flare sprite.  Vector2 flarePosition = lightPosition + flareVector * flare.Position;  // Set the flare alpha based on the previous occlusion query result.  Vector4 flareColor = flare.Color.ToVector4();  flareColor.W *= occlusionAlpha;  // Center the sprite texture.  Vector2 flareOrigin = new Vector2(flare.Texture.Width, flare.Texture.Height) / 2;  // Draw the flare.  spriteBatch.Draw(flare.Texture, flarePosition, null,    new Color(flareColor), 1, flareOrigin,    flare.Scale, SpriteEffects.None, 0);   }   spriteBatch.End();*/}//---------------------------------------------------------------------------void LensFlare::RenderGlow(D3DXVECTOR2 lightPosition){/*   Vector4 color  = new Vector4(1, 1, 1, occlusionAlpha);   Vector2 origin = new Vector2(glowSprite.Width, glowSprite.Height) / 2;   float   scale  = glowSize * 2 / glowSprite.Width;   spriteBatch.Begin(SpriteBlendMode.AlphaBlend);   spriteBatch.Draw(glowSprite, lightPosition, null, new Color(color), 0,origin, scale, SpriteEffects.None, 0);   spriteBatch.End();   */}//---------------------------------------------------------------------------LensFlare::Flare::Flare(float position, float scale, const D3DXCOLOR & color, const std::string & textureName)   :m_position(position),m_scale(scale),m_color(color),m_textureName(textureName){    }