Beispiel #1
0
inline void FELighting::inlineSetPixel(int offset, LightingData& data, LightSource::PaintingData& paintingData,
                                       int lightX, int lightY, float factorX, float factorY, IntPoint& normal2DVector)
{
    m_lightSource->updatePaintingData(paintingData, lightX, lightY, static_cast<float>(data.pixels->item(offset + cAlphaChannelOffset)) * data.surfaceScale);

    float lightStrength;
    if (!normal2DVector.x() && !normal2DVector.y()) {
        // Normal vector is (0, 0, 1). This is a quite frequent case.
        if (m_lightingType == FELighting::DiffuseLighting) {
            lightStrength = m_diffuseConstant * paintingData.lightVector.z() / paintingData.lightVectorLength;
        } else {
            FloatPoint3D halfwayVector = paintingData.lightVector;
            halfwayVector.setZ(halfwayVector.z() + paintingData.lightVectorLength);
            float halfwayVectorLength = halfwayVector.length();
            if (m_specularExponent == 1)
                lightStrength = m_specularConstant * halfwayVector.z() / halfwayVectorLength;
            else
                lightStrength = m_specularConstant * powf(halfwayVector.z() / halfwayVectorLength, m_specularExponent);
        }
    } else {
        FloatPoint3D normalVector;
        normalVector.setX(factorX * static_cast<float>(normal2DVector.x()) * data.surfaceScale);
        normalVector.setY(factorY * static_cast<float>(normal2DVector.y()) * data.surfaceScale);
        normalVector.setZ(1);
        float normalVectorLength = normalVector.length();

        if (m_lightingType == FELighting::DiffuseLighting) {
            lightStrength = m_diffuseConstant * (normalVector * paintingData.lightVector) / (normalVectorLength * paintingData.lightVectorLength);
        } else {
            FloatPoint3D halfwayVector = paintingData.lightVector;
            halfwayVector.setZ(halfwayVector.z() + paintingData.lightVectorLength);
            float halfwayVectorLength = halfwayVector.length();
            if (m_specularExponent == 1)
                lightStrength = m_specularConstant * (normalVector * halfwayVector) / (normalVectorLength * halfwayVectorLength);
            else
                lightStrength = m_specularConstant * powf((normalVector * halfwayVector) / (normalVectorLength * halfwayVectorLength), m_specularExponent);
        }
    }

    if (lightStrength > 1)
        lightStrength = 1;
    if (lightStrength < 0)
        lightStrength = 0;

    data.pixels->set(offset, static_cast<unsigned char>(lightStrength * paintingData.colorVector.x()));
    data.pixels->set(offset + 1, static_cast<unsigned char>(lightStrength * paintingData.colorVector.y()));
    data.pixels->set(offset + 2, static_cast<unsigned char>(lightStrength * paintingData.colorVector.z()));
}
ALWAYS_INLINE void FELighting::setPixel(LightingData& data, LightSource::PaintingData& paintingData,
    int lightX, int lightY, float factorX, int normalX, float factorY, int normalY)
{
    m_lightSource->updatePaintingData(paintingData, lightX, lightY, static_cast<float>(data.pixels->get(data.offset + 3)) * data.surfaceScale);

    data.normalVector.setX(factorX * static_cast<float>(normalX) * data.surfaceScale);
    data.normalVector.setY(factorY * static_cast<float>(normalY) * data.surfaceScale);
    data.normalVector.setZ(1.0f);
    data.normalVector.normalize();

    if (m_lightingType == FELighting::DiffuseLighting)
        data.lightStrength = m_diffuseConstant * (data.normalVector * paintingData.lightVector);
    else {
        FloatPoint3D halfwayVector = paintingData.lightVector;
        halfwayVector.setZ(halfwayVector.z() + 1.0f);
        halfwayVector.normalize();
        if (m_specularExponent == 1.0f)
            data.lightStrength = m_specularConstant * (data.normalVector * halfwayVector);
        else
            data.lightStrength = m_specularConstant * powf(data.normalVector * halfwayVector, m_specularExponent);
    }

    if (data.lightStrength > 1.0f)
        data.lightStrength = 1.0f;
    if (data.lightStrength < 0.0f)
        data.lightStrength = 0.0f;

    data.pixels->set(data.offset, static_cast<unsigned char>(data.lightStrength * paintingData.colorVector.x()));
    data.pixels->set(data.offset + 1, static_cast<unsigned char>(data.lightStrength * paintingData.colorVector.y()));
    data.pixels->set(data.offset + 2, static_cast<unsigned char>(data.lightStrength * paintingData.colorVector.z()));
}
void LayerCompositingThread::setDrawTransform(double scale, const TransformationMatrix& matrix, const TransformationMatrix& projectionMatrix)
{
    m_drawTransform = projectionMatrix * matrix;

    FloatRect boundsRect(-origin(), bounds());

    if (sizeIsScaleInvariant())
        boundsRect.scale(1 / scale);

    m_centerW = 0;
    m_transformedBounds.clear();
    m_ws.clear();
    m_textureCoordinates.clear();
    if (matrix.hasPerspective() && !m_layerRendererSurface) {
        // Perform processing according to http://www.w3.org/TR/css3-transforms 6.2
        // If w < 0 for all four corners of the transformed box, the box is not rendered.
        // If w < 0 for one to three corners of the transformed box, the box
        // must be replaced by a polygon that has any parts with w < 0 cut out.
        // If w = 0, (x′, y′, z′) = (x ⋅ n, y ⋅ n, z ⋅ n)
        // We implement this by intersecting with the image plane, i.e. the last row of the column-major matrix.
        // To avoid problems with w close to 0, we use w = epsilon as the near plane by subtracting epsilon from matrix.m44().
        const float epsilon = 1e-3;
        Vector<FloatPoint3D, 4> quad = toVector<FloatPoint3D, 4>(boundsRect);
        Vector<FloatPoint3D, 4> polygon = intersect(quad, LayerClipPlane(FloatPoint3D(matrix.m14(), matrix.m24(), matrix.m34()), matrix.m44() - epsilon));

        // Compute the clipped texture coordinates.
        if (polygon != quad) {
            for (size_t i = 0; i < polygon.size(); ++i) {
                FloatPoint3D& p = polygon[i];
                m_textureCoordinates.append(FloatPoint(p.x() / boundsRect.width() + 0.5f, p.y() / boundsRect.height() + 0.5f));
            }
        }

        // If w > 0, (x′, y′, z′) = (x/w, y/w, z/w)
        for (size_t i = 0; i < polygon.size(); ++i) {
            float w;
            FloatPoint3D p = multVecMatrix(matrix, polygon[i], w);
            if (w != 1) {
                p.setX(p.x() / w);
                p.setY(p.y() / w);
                p.setZ(p.z() / w);
            }

            FloatPoint3D q = projectionMatrix.mapPoint(p);
            m_transformedBounds.append(FloatPoint(q.x(), q.y()));
            m_ws.append(w);
        }

        m_centerW = matrix.m44();
    } else
        m_transformedBounds = toVector<FloatPoint, 4>(m_drawTransform.mapQuad(boundsRect));

    m_boundingBox = WebCore::boundingBox(m_transformedBounds);
}