Пример #1
0
bool Cylinder::intersectCap(const Ray &localRay, double &t)
{
    if (localRay.direction().y() < 0.0)
        t = (0.5 * m_length - localRay.origin().y()) / localRay.direction().y();
    else if (localRay.direction().y() > 0.0)
        t = (-0.5 * m_length - localRay.origin().y()) / localRay.direction().y();
    else
        return false;

    QVector4D p = localRay.along(t);
    if (p.x() * p.x() + p.z() * p.z() < m_rSq)
        return true;

    return false;
}
Пример #2
0
QVector3D WhittedRenderer::trace(const Ray& primaryRay, int depth, const QList<Shape*>& shapes, const QList<Light*>& lights)
{
    double minDist = std::numeric_limits<double>::max();
    Shape* closestShape = nullptr;

    QVector3D shaded;
    if (m_grid->intersect(primaryRay, closestShape, minDist)) {
        auto material = closestShape->material();
        shaded = material->ambientReflectivity() * m_ambientLightColor * material->colorVector();
        QColor color = material ? material->color() : QColor(40, 40, 40);
        QVector3D diffuseColor(color.redF(), color.greenF(), color.blueF());
        QVector4D hitPoint = primaryRay.along(minDist);
        QVector4D normalVector = closestShape->surfaceNormal(hitPoint, primaryRay);
        QVector4D viewVector = -primaryRay.direction();
        foreach(Light* light, lights) {

            QVector3D emittance;
            QVector4D lightVector;
            light->sample(lightVector, emittance);
            lightVector = lightVector - hitPoint;
            float lightVectorLengthSquared = lightVector.lengthSquared();
            float lightVectorLength = sqrt(lightVectorLengthSquared);
            lightVector.normalize();

            Ray shadowRay(hitPoint, lightVector);
            double t;
            Shape* blockingShape;
            bool shadowRayHit = m_grid->intersect(shadowRay, blockingShape, t);
            if (!shadowRayHit || (shadowRayHit && (lightVectorLengthSquared < t * t))) {
                // Diffuse
                float dot = fmax(0.0f, QVector4D::dotProduct(lightVector, normalVector)) * material->diffuseReflectivity();
                emittance *= 1 / (1 + 0.2 * lightVectorLength + 0.08 * lightVectorLengthSquared);
                shaded += dot * QVector3D(emittance.x() * diffuseColor.x(),
                                          emittance.y() * diffuseColor.y(),
                                          emittance.z() * diffuseColor.z());

                // Specular
                if (material->specularReflectivity() > 0.0) {
                    QVector4D reflectedLightVector = MathUtils::reflect(-lightVector, normalVector); // lightVector and normalVector are already normalized
                    float dot = QVector4D::dotProduct(reflectedLightVector, viewVector);
                    if (dot > 0.0)
                        shaded += material->specularReflectivity() * pow(dot, material->shininess()) * emittance;
                }
            }
        }