Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- void Scene3D::Render(
- float dt,
- IDirect3DDevice9* device,
- IDirect3DVertexDeclaration9* VertexDecl,
- ID3DXEffect* RenderOnlyAmbientLightEffect
- ) const {
- auto SetRenderTargetToDevice = [&] {
- std::unique_ptr<IDirect3DSurface9, COMDeleter> RenderTargetSurface;
- D3DCALL(RenderTarget->GetSurfaceLevel(0, PointerToPointer(RenderTargetSurface)));
- D3DCALL(device->SetRenderTarget(0, RenderTargetSurface.get()));
- D3DCALL(device->SetDepthStencilSurface(DepthBuffer.get()));
- };
- auto SetMeshSpecificDataToEffect = [&](ID3DXEffect* effect, const Direct3D9::Mesh* mesh) {
- auto RenData = mesh->GetRenderData();
- /*if (auto handle = effect->GetParameterByName(0, "ColourMap")) {
- effect->SetTexture(handle, RenData.Texture);
- }*/
- if (auto handle = effect->GetParameterByName(0, "AmbientMaterial")) {
- effect->SetVector(handle, reinterpret_cast<D3DXVECTOR4*>(&RenData.AmbientMaterial));
- }
- if (auto handle = effect->GetParameterByName(0, "DiffuseMaterial")) {
- effect->SetVector(handle, reinterpret_cast<D3DXVECTOR4*>(&RenData.DiffuseMaterial));
- }
- if (auto handle = effect->GetParameterByName(0, "SpecularMaterial")) {
- effect->SetVector(handle, reinterpret_cast<D3DXVECTOR4*>(&RenData.SpecularMaterial));
- }
- };
- auto SetCameraSpecificDataToEffect = [&](ID3DXEffect* effect) {
- if (auto handle = effect->GetParameterByName(0, "CameraVP")) {
- D3DXMATRIX Projection;
- D3DXMATRIX View;
- D3DXMatrixLookAtLH(
- &View,
- &D3DVector(camera.Position),
- &D3DVector(camera.LookingAt),
- &D3DVector(camera.Up)
- );
- #pragma warning(disable : 4244)
- D3DXMatrixPerspectiveLH(
- &Projection,
- GetDimensions().x,
- GetDimensions().y,
- camera.NearPlane,
- camera.FarPlane
- );
- #pragma warning(default : 4244)
- effect->SetMatrix(handle, &(View * Projection));
- }
- };
- // Define a couple variables the helpers can use
- auto SendAllVerticesToPipeline = [&, this](ID3DXEffect* effect, const std::unordered_map<const Direct3D9::Mesh*, std::unordered_set<Object*>>& ObjectsByMesh) {
- std::for_each(ObjectsByMesh.begin(), ObjectsByMesh.end(), [&, this](const decltype(*ObjectsByMesh.begin())& group) {
- // Set all per-mesh data - first to the pipeline
- auto RenData = group.first->GetRenderData();
- D3DCALL(device->SetStreamSource(
- 0,
- RenData.VertexBuffer,
- 0,
- sizeof(Render::InputMesh::Vertex)
- ));
- D3DCALL(device->SetStreamSource(
- 1,
- InstanceBuffer.get(),
- 0,
- sizeof(D3DXMATRIX)
- ));
- D3DCALL(device->SetIndices(
- RenData.IndexBuffer
- ));
- // then to the effect
- SetMeshSpecificDataToEffect(effect, group.first);
- auto handle = effect->GetTechniqueByName("PrimaryTechnique");
- D3DCALL(effect->SetTechnique(handle));
- unsigned int passes;
- D3DCALL(effect->Begin(&passes, 0));
- auto bones = group.first->GetBones();
- std::for_each(bones.begin(), bones.end(), [&](const decltype(*bones.begin())& bone) {
- std::vector<Direct3D9::Bone*> bones;
- std::for_each(group.second.begin(), group.second.end(), [&](const Wide::Direct3D9::Object* obj) {
- bones.push_back(obj->GetBoneByName(bone->Name));
- });
- D3DXMATRIXA16* matrices;
- InstanceBuffer->Lock(0, bones.size() * sizeof(D3DXMATRIXA16), reinterpret_cast<void**>(&matrices), D3DLOCK_DISCARD);
- std::for_each(bones.begin(), bones.end(), [&, this](Direct3D9::Bone* bone) {
- *matrices = bone->World;
- matrices++; // Guaranteed not to overflow because we already made the size as large as we needed it
- });
- for(unsigned int i = 0; i < passes; i++) {
- D3DCALL(effect->BeginPass(i));
- D3DCALL(device->DrawIndexedPrimitive(
- D3DPRIMITIVETYPE::D3DPT_TRIANGLESTRIP,
- bone->VertBegin,
- 0,
- bone->NumVerts,
- bone->IndexBegin,
- bone->NumIndices / 3
- ));
- D3DCALL(effect->EndPass());
- }
- });
- D3DCALL(effect->End());
- });
- };
- // Save the original back buffer and depth stencil
- std::unique_ptr<IDirect3DSurface9, COMDeleter> BackBuffer;
- std::unique_ptr<IDirect3DSurface9, COMDeleter> DepthStencil;
- D3DCALL(device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, PointerToPointer(BackBuffer)));
- D3DCALL(device->GetDepthStencilSurface(PointerToPointer(DepthStencil)));
- // Sort the objects by mesh, and compute the world matrices whilst you're at it.
- std::unordered_map<const Direct3D9::Mesh*, std::unordered_set<Object*>> ObjectsByMesh;
- std::for_each(Objects.begin(), Objects.end(), [&](Wide::Render::Object* ptr) {
- auto d3dptr = static_cast<Wide::Direct3D9::Object*>(ptr);
- d3dptr->ComputeWorldMatrices();
- ObjectsByMesh[d3dptr->GetMesh().get()].insert(d3dptr);
- });
- // Resize the buffer, if it's not big enough to hold what we're doin here.
- unsigned int maxsize = 0;
- std::for_each(ObjectsByMesh.begin(), ObjectsByMesh.end(), [&](const decltype(*ObjectsByMesh.begin())& group) {
- maxsize = std::max(maxsize, group.second.size());
- });
- if (InstanceBufferSize < maxsize) {
- InstanceBufferSize = maxsize;
- ResetInstanceBuffer(device);
- }
- // Set the mesh-independent stuff to the device
- D3DCALL(device->SetVertexDeclaration(VertexDecl));
- D3DCALL(device->SetStreamSource(1, InstanceBuffer.get(), 0, sizeof(D3DXMATRIXA16)));
- // If there is only ambient light, then just render directly to BB with no shadow mapping
- if (Lights.empty()) {
- // Render ambient only- no shadowmapping needed
- SetRenderTargetToDevice();
- SetCameraSpecificDataToEffect(RenderOnlyAmbientLightEffect);
- SendAllVerticesToPipeline(RenderOnlyAmbientLightEffect, ObjectsByMesh);
- }
- // Restore the previous backbuffer and depth stencil
- D3DCALL(device->SetRenderTarget(0, BackBuffer.get()));
- D3DCALL(device->SetDepthStencilSurface(DepthStencil.get()));
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement