void renderShadows(Storm3D_Scene &scene) { gfx::Renderer& renderer = storm.renderer; gfx::Device& device = renderer.device; gfx::ProgramManager& programManager = renderer.programManager; if (shadowDecals.empty() || !shadowMaterial) return; int renderAmount = 0; IStorm3D_Camera *camera = scene.GetCamera(); Storm3D_Camera *stormCamera = reinterpret_cast<Storm3D_Camera *> (camera); Frustum frustum = stormCamera->getFrustum(); uint32_t baseVertex = 0; Vertex_P3DUV *buffer = 0;; renderer.lockDynVtx<Vertex_P3DUV>(shadowDecals.size() * 4, &buffer, &baseVertex); float inverseRange = 1.f / fogRange; for (unsigned int i = 0; i < shadowDecals.size() && renderAmount < MAX_DECAL_AMOUNT; ++i) { const Decal &decal = shadowDecals[i]; Sphere sphere(decal.position, decal.getRadius()); if (frustum.visibility(sphere)) { float factor = decal.position.y - fogEnd; factor *= inverseRange; factor = std::max(0.0f, factor); factor = std::min(1.0f, factor); factor = 1.f - factor; COL color = decal.light; color.r += factor * (1.f - color.r); color.g += factor * (1.f - color.g); color.b += factor * (1.f - color.b); uint32_t vertexColor = color.as_u32_D3D_ARGB(decal.alpha); decal.insert(buffer, vertexColor); buffer += 4; ++renderAmount; } } renderer.unlockDynVtx(); if (renderAmount == 0) return; D3DXMATRIX tm; D3DXMatrixIdentity(&tm); programManager.setProgram( gfx::ProgramManager::DECAL_SHADOW); programManager.setWorldMatrix(tm); programManager.applyState(device); device.SetRenderState(D3DRS_ZWRITEENABLE, FALSE); device.SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); device.SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); device.SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO); device.SetRenderState(D3DRS_DESTBLEND, D3DBLEND_SRCCOLOR); if (shadowMaterial->baseTexture) shadowMaterial->baseTexture->Apply(0); renderer.setFVF(FVF_P3DUV); renderer.setDynVtxBuffer<Vertex_P3DUV>(); renderer.drawQuads(baseVertex, renderAmount); device.SetRenderState(D3DRS_ZWRITEENABLE, TRUE); device.SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); shadowDecals.clear(); }
void render(Storm3D_Scene &scene) { gfx::Renderer& renderer = storm.renderer; gfx::Device& device = renderer.device; gfx::ProgramManager& programManager = renderer.programManager; baseDecalVertex = 0; findDecals(scene); if (decals.empty()) return; Vertex_P3NDUV *buffer = 0; renderer.lockDynVtx<Vertex_P3NDUV>(decals.size() * 4, &buffer, &baseDecalVertex); for (unsigned int i = 0; i < decals.size(); ++i) { Decal& decal = *decals[i]; COL decalColor = decal.light * (decal.type == Outside ? outFactor : inFactor); decalColor.Clamp(); uint32_t vertexColor = decalColor.as_u32_D3D_ARGB(decal.alpha); decal.insert(buffer, vertexColor); buffer += 4; } renderer.unlockDynVtx(); // Render if (!decals.empty()) { device.SetRenderState(D3DRS_ZWRITEENABLE, FALSE); device.SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); device.SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); device.SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); device.SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); D3DXMATRIX tm; D3DXMatrixIdentity(&tm); programManager.setWorldMatrix(tm); programManager.setProgram(gfx::ProgramManager::DECAL_LIGHTING); renderer.setDynVtxBuffer<Vertex_P3NDUV>(); renderer.setFVF(FVF_P3NDUV); int materialIndex = 0; int startIndex = 0; int endIndex = 0; for (;;) { materialIndex = decals[startIndex]->materialIndex; if(materials[materialIndex].baseTexture) materials[materialIndex].baseTexture->Apply(0); programManager.setDiffuse(materials[materialIndex].diffuseColor); programManager.applyState(device); int decalAmount = decals.size(); for (int i = startIndex + 1; i < decalAmount; ++i) { if (decals[i]->materialIndex != materialIndex) break; endIndex = i; } int renderAmount = endIndex - startIndex + 1; renderer.drawQuads(baseDecalVertex + startIndex * 4, renderAmount); startIndex = ++endIndex; if (startIndex >= decalAmount) break; } device.SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); } }