void FaceInstance::addLight(const Matrix4& localToWorld, const RendererLight& light) { const Plane3& facePlane = getFace().plane3(); Plane3 tmp = Plane3(facePlane.normal(), -facePlane.dist()) .transformed(localToWorld); if (!tmp.testPoint(light.worldOrigin()) || !tmp.testPoint(light.getLightOrigin())) { m_lights.addLight(light); } }
void StandardDeferred::renderLight(LightType lightType, const RendererLight& light, const RendererView& view, const GBufferTextures& gBufferInput, const SPtr<Texture>& lightOcclusion) { const auto& viewProps = view.getProperties(); bool isMSAA = view.getProperties().numSamples > 1; SPtr<GpuParamBlockBuffer> perViewBuffer = view.getPerViewBuffer(); light.getParameters(mPerLightBuffer); if (lightType == LightType::Directional) { DeferredDirectionalLightMat* material = DeferredDirectionalLightMat::getVariation(isMSAA, true); material->bind(gBufferInput, lightOcclusion, perViewBuffer, mPerLightBuffer); gRendererUtility().drawScreenQuad(); // Draw pixels requiring per-sample evaluation if(isMSAA) { DeferredDirectionalLightMat* msaaMaterial = DeferredDirectionalLightMat::getVariation(true, false); msaaMaterial->bind(gBufferInput, lightOcclusion, perViewBuffer, mPerLightBuffer); gRendererUtility().drawScreenQuad(); } } else // Radial or spot { // Check if viewer is inside the light volume float distSqrd = (light.internal->getBounds().getCenter() - viewProps.viewOrigin).squaredLength(); // Extend the bounds slighty to cover the case when the viewer is outside, but the near plane is intersecting // the light bounds. We need to be conservative since the material for rendering outside will not properly // render the inside of the light volume. float boundRadius = light.internal->getBounds().getRadius() + viewProps.nearPlane * 3.0f; bool isInside = distSqrd < (boundRadius * boundRadius); SPtr<Mesh> stencilMesh; if(lightType == LightType::Radial) stencilMesh = RendererUtility::instance().getSphereStencil(); else // Spot stencilMesh = RendererUtility::instance().getSpotLightStencil(); DeferredPointLightMat* material = DeferredPointLightMat::getVariation(isInside, isMSAA, true); material->bind(gBufferInput, lightOcclusion, perViewBuffer, mPerLightBuffer); // Note: If MSAA is enabled this will be rendered multisampled (on polygon edges), see if this can be avoided gRendererUtility().draw(stencilMesh); // Draw pixels requiring per-sample evaluation if(isMSAA) { DeferredPointLightMat* msaaMaterial = DeferredPointLightMat::getVariation(isInside, true, false); msaaMaterial->bind(gBufferInput, lightOcclusion, perViewBuffer, mPerLightBuffer); gRendererUtility().draw(stencilMesh); } } }
// Local helper inline void Surface_addLight(const MD5Surface& surface, VectorLightList& lights, const Matrix4& localToWorld, const RendererLight& light) { if (light.testAABB(aabb_for_oriented_aabb(surface.localAABB(), localToWorld))) { lights.addLight(light); } }
// Add a light to this model instance void PicoModelNode::insertLight(const RendererLight& light) { // Calculate transform from the superclass const Matrix4& l2w = localToWorld(); // If the light's AABB intersects the oriented AABB of this model instance, // add the light to our light list if (light.intersectsAABB(AABB::createFromOrientedAABB(_picoModel->localAABB(), l2w))) { _lights.addLight(light); } }
// Local helper inline void Surface_addLight(const MD5Surface& surface, render::lib::VectorLightList& lights, const Matrix4& localToWorld, const RendererLight& light) { if (light.intersectsAABB( AABB::createFromOrientedAABB(surface.localAABB(), localToWorld) ) ) { lights.addLight(light); } }
bool MD5ModelNode::intersectsLight(const RendererLight& light) const { return light.intersectsAABB(worldAABB()); }
bool MD5ModelNode::testLight(const RendererLight& light) const { return light.testAABB(worldAABB()); }