// // PERFORM LIGHTING ON AN ARRAY OF VERTICES // void DxLight::Manager::Light(VertexL *dstV, Plane *srcP, Vector *srcV, Vector *srcN, Color *srcC, UVPair *srcUV, U32 &countV, U16 *dstI, U16 *srcI, U32 &countI) { ASSERT(srcV); ASSERT(dstV); ASSERT(countV < MAXVERTS); // set up the material values SetMaterialValues(); ASSERT(countV > 0 && (material_diffuse.r + material_diffuse.g + material_diffuse.b + material_diffuse.a) > 0.0f); // if the polygons are two-sided... if (BucketMan::GetPrimitiveFlags() & RS_2SIDED) { // combine the components without back-face culling Combine(dstV, srcP, srcV, srcN, srcC, srcUV, countV, dstI, srcI, countI); } else { // combine the components with back-face culling BackCull(dstV, srcP, srcV, srcN, srcC, srcUV, countV, dstI, srcI, countI); } // if there are any vertices left... if (countV) { // calculate lighting for the vertices CalculateLighting(dstV, countV); // apply lighting to the vertices ApplyLighting(dstV, countV); } }
void SimpleStaticLighter::ShineLights (iMeshWrapper* mesh, iEngine* engine, int maxlights, ShadowType shadow_type) { iMovable* movable = mesh->GetMovable (); if (!movable->InSector ()) return; // No movable, do nothing. const csBox3& world_box = mesh->GetWorldBoundingBox (); CS_ALLOC_STACK_ARRAY (iLight*, lights, maxlights); size_t num = engine->GetNearbyLights (movable->GetSectors ()->Get (0), world_box, lights, maxlights); if (num == 0) { ConstantColor (mesh, csColor4 (0, 0, 0, 0)); return; } if (num == 1) { ShineLight (mesh, lights[0], shadow_type); return; } iMeshFactoryWrapper* meshfact = mesh->GetFactory (); if (!meshfact) return; csRef<iGeneralFactoryState> fact_state = scfQueryInterface< iGeneralFactoryState> (meshfact->GetMeshObjectFactory ()); if (!fact_state) return; // Not a mesh we recognize. size_t count = fact_state->GetVertexCount (); csRef<iRenderBuffer> rbuf = csRenderBuffer::CreateRenderBuffer ( count, CS_BUF_STATIC, CS_BUFCOMP_FLOAT, 4); CS_ALLOC_STACK_ARRAY (csColor4, colors, count); size_t l; for (l = 0 ; l < num ; l++) { iLight* light = lights[l]; CalculateLighting (mesh, fact_state, light, shadow_type, colors, l == 0); } rbuf->CopyInto (colors, count); csRef<iGeneralMeshState> state = scfQueryInterface<iGeneralMeshState> (mesh->GetMeshObject ()); state->AddRenderBuffer ("static color", rbuf); mesh->GetFlags().Set (CS_ENTITY_STATICLIT); }
void SimpleStaticLighter::ShineLight (iMeshWrapper* mesh, iLight* light, ShadowType shadow_type) { iMeshFactoryWrapper* meshfact = mesh->GetFactory (); if (!meshfact) return; csRef<iGeneralFactoryState> fact_state = scfQueryInterface< iGeneralFactoryState> (meshfact->GetMeshObjectFactory ()); if (!fact_state) return; // Not a mesh we recognize. size_t count = fact_state->GetVertexCount (); csRef<iRenderBuffer> rbuf = csRenderBuffer::CreateRenderBuffer ( count, CS_BUF_STATIC, CS_BUFCOMP_FLOAT, 4); CS_ALLOC_STACK_ARRAY (csColor4, colors, count); CalculateLighting (mesh, fact_state, light, shadow_type, colors, true); rbuf->CopyInto (colors, count); csRef<iGeneralMeshState> state = scfQueryInterface<iGeneralMeshState> (mesh->GetMeshObject ()); state->AddRenderBuffer ("static color", rbuf); mesh->GetFlags().Set (CS_ENTITY_STATICLIT); }
Colour RayTracer::TraceScene(Scene* pScene, Ray& ray, Colour incolour, int tracelevel, bool shadowray) { RayHitResult result; Colour outcolour = incolour; Colour reflectColour; Colour refractColour; std::vector<Light*>* light_list = pScene->GetLightList(); if (tracelevel <= 0) // reach the MAX depth of the recursion. { return outcolour; } result = pScene->IntersectByRay(ray, shadowray); if (result.data) //the ray has hit something { Vector3 start = ray.GetRayStart(); if (!shadowray) { outcolour = CalculateLighting(light_list,&start, &result); } else { return outcolour * 0.3f; } if(m_traceflag & TRACE_REFLECTION) { //Only consider reflection for spheres and boxes if (((Primitive*)result.data)->m_primtype == Primitive::PRIMTYPE_Sphere || ((Primitive*)result.data)->m_primtype == Primitive::PRIMTYPE_Box) { //TODO: Calculate reflection ray based on the current intersection result //Recursively call TraceScene with the reflection ray //Combine the returned colour with the current surface colour // DONE m_isReflecting = true; ray.SetRay(result.point, ray.GetRay().Reflect(result.normal)); outcolour *= TraceScene(pScene, ray, outcolour, --tracelevel, shadowray); } } if (m_traceflag & TRACE_REFRACTION) { //Only consider refraction for spheres and boxes if (((Primitive*)result.data)->m_primtype == Primitive::PRIMTYPE_Sphere || ((Primitive*)result.data)->m_primtype == Primitive::PRIMTYPE_Box) { //TODO: Calculate refraction ray based on the current intersection result //Recursively call TraceScene with the reflection ray //Combine the returned colour with the current surface colour // DONE double refractionIndex = 1; // Better refraction that using a constant if (m_isRefracting) { refractionIndex = ((Primitive*)result.data)->GetMaterial()->GetRefractiveIndex() / AIR_REFRACTIVE_INDEX; } else { refractionIndex = AIR_REFRACTIVE_INDEX / ((Primitive*)result.data)->GetMaterial()->GetRefractiveIndex(); } m_isRefracting = true; ray.SetRay(result.point + (result.normal * -0.0001), ray.GetRay().Refract((result.normal), 1)); outcolour += TraceScene(pScene, ray, outcolour, --tracelevel, shadowray) * ((Primitive*)result.data)->GetMaterial()->GetTransparency(); } } //Check if this is in shadow if ( m_traceflag & TRACE_SHADOW ) { std::vector<Light*>::iterator lit_iter = light_list->begin(); while (lit_iter != light_list->end()) { //TODO: Calculate the shadow ray using the current intersection result and the light position //Recursively call TraceScene with the shadow ray // DONE Vector3 l_normal = ((*lit_iter)->GetLightPosition() - result.point).Normalise(); Vector3 l = result.point + (l_normal * 0.0001); ray.SetRay(l, l_normal); outcolour = TraceScene(pScene, ray, outcolour, --tracelevel, true); lit_iter++; } } } return outcolour; }
void dx103DFluidRenderer::Draw(const dx103DFluidData &FluidData) { // We don't need ZB anyway RCache.set_ZB(0); const dx103DFluidData::Settings &VolumeSettings = FluidData.GetSettings(); const bool bRenderFire = (VolumeSettings.m_SimulationType == dx103DFluidData::ST_FIRE); FogLighting LightData; CalculateLighting(FluidData, LightData); const Fmatrix &transform = FluidData.GetTransform(); RCache.set_xform_world( transform ); //pColorTexVar->SetResource(pSourceTexSRV); // Set shader element to set up all necessary constants to constant buffer // If you change constant buffer layout make sure this hack works ok. RCache.set_Element(m_RendererTechnique[RS_CompRayData_Back]); // Set some variables required by the shaders: //========================================================================= // The near and far planes are used to unproject the scene's z-buffer values //pZNearVar->SetFloat(g_zNear); RCache.set_c(strZNear, VIEWPORT_NEAR); //pZFarVar->SetFloat(g_zFar); RCache.set_c(strZFar, g_pGamePersistent->Environment().CurrentEnv->far_plane); //D3DXMATRIX worldView = g_gridWorld * g_View; D3DXMATRIX gridWorld; //D3DXMatrixTranspose(&gridWorld, (D3DXMATRIX*)&transform); gridWorld = *(D3DXMATRIX*)&transform; D3DXMATRIX View; //D3DXMatrixTranspose(&View, (D3DXMATRIX*)&RCache.xforms.m_v); View = *(D3DXMATRIX*)&RCache.xforms.m_v; D3DXMATRIX WorldView = gridWorld * View; // Modified later //Fmatrix WorldView = RCache.xforms.m_wv; //RCache.set_xform_world( transform ); // The length of one of the axis of the worldView matrix is the length of longest side of the box // in view space. This is used to convert the length of a ray from view space to grid space. //D3DXVECTOR3 worldXaxis = D3DXVECTOR3(worldView._11, worldView._12, worldView._13); D3DXVECTOR3 worldXaxis = D3DXVECTOR3(WorldView._11, WorldView._12, WorldView._13); float worldScale = D3DXVec3Length(&worldXaxis); //pGridScaleFactorVar->SetFloat( worldScale ); RCache.set_c(strGridScaleFactor, worldScale); // We prepend the current world matrix with this other matrix which adds an offset (-0.5, -0.5, -0.5) // and scale factors to account for unequal number of voxels on different sides of the volume box. // This is because we want to preserve the aspect ratio of the original simulation grid when // raytracing through it. //worldView = m_gridMatrix * worldView; WorldView = m_gridMatrix * WorldView; //WorldView.mulB_44(m_gridMatrix); // Fmatrix temp; // temp = transform; // temp.mulB_44(m_gridMatrix); // RCache.set_xform_world( temp ); // return; // worldViewProjection is used to transform the volume box to screen space //D3DXMATRIX WorldViewProjection; D3DXMATRIX WorldViewProjection; //Fmatrix WorldViewProjection; //worldViewProjection = worldView * g_Projection; D3DXMATRIX Projection; //D3DXMatrixTranspose(&Projection, (D3DXMATRIX*)&RCache.xforms.m_p); Projection = *(D3DXMATRIX*)&RCache.xforms.m_p; WorldViewProjection = WorldView * Projection; //WorldViewProjection.mul(RCache.xforms.m_p, WorldView); //pWorldViewProjectionVar->SetMatrix( (float*)&worldViewProjection ); // NVidia used different matrix orientation //WorldViewProjection.transpose(); //RCache.set_c(strWorldViewProjection, WorldViewProjection); RCache.set_c(strWorldViewProjection, *(Fmatrix*)&WorldViewProjection); //WorldViewProjection.transpose(); // invWorldViewProjection is used to transform positions in the "near" plane into grid space //D3DXMATRIX invWorldViewProjection; D3DXMATRIX InvWorldViewProjection; //Fmatrix InvWorldViewProjection; //WorldViewProjection.transpose(); D3DXMatrixInverse((D3DXMATRIX*)&InvWorldViewProjection, NULL, (D3DXMATRIX*)&WorldViewProjection); //WorldViewProjection.transpose(); //pInvWorldViewProjectionVar->SetMatrix((float*)&invWorldViewProjection); //InvWorldViewProjection.transpose(); //RCache.set_c(strInvWorldViewProjection, InvWorldViewProjection); RCache.set_c(strInvWorldViewProjection, *(Fmatrix*)&InvWorldViewProjection); //InvWorldViewProjection.transpose(); // Compute the inverse of the worldView matrix //D3DXMATRIX worldViewInv; D3DXMATRIX WorldViewInv; //Fmatrix WorldViewInv; D3DXMatrixInverse((D3DXMATRIX*)&WorldViewInv, NULL, (D3DXMATRIX*)&WorldView); // Compute the eye's position in "grid space" (the 0-1 texture coordinate cube) //D3DXVECTOR4 eyeInGridSpace; //D3DXVECTOR3 origin(0,0,0); D3DXVECTOR4 EyeInGridSpace; D3DXVECTOR3 Origin(0,0,0); //Fvector4 EyeInGridSpace; //Fvector3 Origin = Fvector3().set(0,0,0); //WorldViewInv.transpose(); D3DXVec3Transform((D3DXVECTOR4*)&EyeInGridSpace, (D3DXVECTOR3*)&Origin, (D3DXMATRIX*)&WorldViewInv); //WorldViewInv.transpose(); //pEyeOnGridVar->SetFloatVector((float*)&eyeInGridSpace); RCache.set_c(strEyeOnGrid, *(Fvector4*)&EyeInGridSpace); float color[4] = {0, 0, 0, 0 }; // Ray cast and render to a temporary buffer //========================================================================= // Partial init of viewport struct used below //D3D10_VIEWPORT rtViewport; //rtViewport.TopLeftX = 0; //rtViewport.TopLeftY = 0; //rtViewport.MinDepth = 0; //rtViewport.MaxDepth = 1; // Compute the ray data required by the raycasting pass below. // This function will render to a buffer of float4 vectors, where // xyz is starting position of the ray in grid space // w is the length of the ray in view space ComputeRayData(); // Do edge detection on this image to find any // problematic areas where we need to raycast at higher resolution ComputeEdgeTexture(); // Raycast into the temporary render target: // raycasting is done at the smaller resolution, using a fullscreen quad //m_pD3DDevice->ClearRenderTargetView( pRayCastRTV, color ); HW.pDevice->ClearRenderTargetView( RT[RRT_RayCastTex]->pRT, color ); //m_pD3DDevice->OMSetRenderTargets( 1, &pRayCastRTV , NULL ); CRenderTarget* pTarget = RImplementation.Target; pTarget->u_setrt(RT[RRT_RayCastTex],0,0,0); // LDR RT //rtViewport.Width = renderTextureWidth; //rtViewport.Height = renderTextureHeight; //m_pD3DDevice->RSSetViewports(1,&rtViewport); RImplementation.rmNormal(); //pTechnique->GetPassByName("QuadRaycast")->Apply(0); if (bRenderFire) RCache.set_Element(m_RendererTechnique[RS_QuadRaycastFire]); else RCache.set_Element(m_RendererTechnique[RS_QuadRaycastFog]); //pRTWidthVar->SetFloat((float)renderTextureWidth); RCache.set_c(strRTWidth, (float)m_iRenderTextureWidth); //pRTHeightVar->SetFloat((float)renderTextureHeight); RCache.set_c(strRTHeight, (float)m_iRenderTextureHeight); //pRayDataSmallVar->SetResource(pRayDataSmallSRV); DrawScreenQuad(); // Render to the back buffer sampling from the raycast texture that we just created // If and edge was detected at the current pixel we will raycast again to avoid // smoke aliasing artifacts at scene edges //ID3D10RenderTargetView* pRTV = DXUTGetD3D10RenderTargetView(); //ID3D10DepthStencilView* pDSV = DXUTGetD3D10DepthStencilView(); //m_pD3DDevice->OMSetRenderTargets( 1, &pRTV , pDSV ); // Restore render state if( !RImplementation.o.dx10_msaa ) pTarget->u_setrt( pTarget->rt_Generic_0,0,0,HW.pBaseZB); // LDR RT else pTarget->u_setrt( pTarget->rt_Generic_0,0,0,pTarget->rt_MSAADepth->pZRT); // LDR RT if (bRenderFire) RCache.set_Element(m_RendererTechnique[RS_QuadRaycastCopyFire]); else RCache.set_Element(m_RendererTechnique[RS_QuadRaycastCopyFog]); //rtViewport.Width = g_Width; //rtViewport.Height = g_Height; //m_pD3DDevice->RSSetViewports(1,&rtViewport); RImplementation.rmNormal(); //pRTWidthVar->SetFloat((float)g_Width); RCache.set_c(strRTWidth, (float)Device.dwWidth); //pRTHeightVar->SetFloat((float)g_Height); RCache.set_c(strRTHeight, (float)Device.dwHeight); RCache.set_c(strDiffuseLight, LightData.m_vLightIntencity.x, LightData.m_vLightIntencity.y, LightData.m_vLightIntencity.z, 1.0f); //pRayCastVar->SetResource(pRayCastSRV); //pEdgeVar->SetResource(pEdgeSRV); //pTechnique->GetPassByName("QuadRaycastCopy")->Apply(0); DrawScreenQuad(); }