⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 atmosphericscatteringcomputer.java

📁 world wind java sdk 源码
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
                if (bCameraAbove)
                {
                    float fSampleAngle = (float)vRay.getNegative3().dot3(vPos) / fHeight;
                    interpolate(fSampleDepth, fAltitude, 0.5f - fSampleAngle * 0.5f);
                    fRayleighDepth += fSampleDepth[1] - fCameraDepth[1];
                    fMieDepth += fSampleDepth[3] - fCameraDepth[3];
                }
                else
                {
                    float fSampleAngle = (float)vRay.dot3(vPos) / fHeight;
                    interpolate(fSampleDepth, fAltitude, 0.5f - fSampleAngle * 0.5f);
                    fRayleighDepth += fCameraDepth[1] - fSampleDepth[1];
                    fMieDepth += fCameraDepth[3] - fSampleDepth[3];
                }

                // Now multiply the optical depth by the attenuation factor for the sample ray
                fRayleighDepth *= Kr4PI;
                fMieDepth *= Km4PI;

                // Calculate the attenuation factor for the sample ray
                fAttenuation[0] = (float)Math.exp(-fRayleighDepth / fWavelength4[0] - fMieDepth);
                fAttenuation[1] = (float)Math.exp(-fRayleighDepth / fWavelength4[1] - fMieDepth);
                fAttenuation[2] = (float)Math.exp(-fRayleighDepth / fWavelength4[2] - fMieDepth);

                fRayleighSum[0] += fRayleighDensity * fAttenuation[0];
                fRayleighSum[1] += fRayleighDensity * fAttenuation[1];
                fRayleighSum[2] += fRayleighDensity * fAttenuation[2];

                fMieSum[0] += fMieDensity * fAttenuation[0];
                fMieSum[1] += fMieDensity * fAttenuation[1];
                fMieSum[2] += fMieDensity * fAttenuation[2];
            }
            // Move the position to the center of the next sample ray
            vPos = vPos.add3(vSampleRay);
        }

        // Calculate the angle and phase values (this block of code could be handled by a small 1D lookup table,
        // or a 1D texture lookup in a pixel shader)
        float fAngle = (float)vRay.getNegative3().dot3(vLightDirection);
        float[] fPhase = new float[2];
        float fAngle2 = fAngle * fAngle;
        float g2 = g * g;
        fPhase[0] = 0.75f * (1.0f + fAngle2);
        fPhase[1] = 1.5f * ((1 - g2) / (2 + g2)) * (1.0f + fAngle2) / (float)Math.pow(1 + g2 - 2 * g * fAngle, 1.5f);
        fPhase[0] *= Kr * ESun;
        fPhase[1] *= Km * ESun;
        // Calculate the in-scattering color and clamp it to the max color value
        float[] fColor = new float[] { 0, 0, 0 };
        fColor[0] = fRayleighSum[0] * fPhase[0] / fWavelength4[0] + fMieSum[0] * fPhase[1];
        fColor[1] = fRayleighSum[1] * fPhase[0] / fWavelength4[1] + fMieSum[1] * fPhase[1];
        fColor[2] = fRayleighSum[2] * fPhase[0] / fWavelength4[2] + fMieSum[2] * fPhase[1];
        fColor[0] = Math.min(fColor[0], 1.0f);
        fColor[1] = Math.min(fColor[1], 1.0f);
        fColor[2] = Math.min(fColor[2], 1.0f);

        // Compute alpha transparency (PM 2006-11-19)
        float alpha = (fColor[0] + fColor[1] + fColor[2]) / 3;  // Average luminosity
        alpha = (float)Math.min(alpha + 0.50, 1f);			  // increase opacity

        // Last but not least, return the color
        return  new Color(fColor[0], fColor[1], fColor[2], alpha);
    }

    private void interpolate(float[] p, float x, float y)
    {
        float fX = x * (nBufferWidth - 1);
        float fY = y * (nBufferHeight - 1);
        int nX = Math.min(nBufferWidth - 2, Math.max(0, (int)fX));
        int nY = Math.min(nBufferHeight - 2, Math.max(0, (int)fY));
        float fRatioX = fX - nX;
        float fRatioY = fY - nY;

        int pValueOffset = (nBufferWidth * nY + nX) * 4;

        for (int i = 0; i < nChannels; i++)
        {
            p[i] = opticalDepthBuffer[pValueOffset] * (1 - fRatioX) * (1 - fRatioY) +
                opticalDepthBuffer[pValueOffset + nChannels] * (fRatioX) * (1 - fRatioY) +
                opticalDepthBuffer[pValueOffset + nChannels * nBufferWidth] * (1 - fRatioX) * (fRatioY) +
                opticalDepthBuffer[pValueOffset + nChannels * (nBufferWidth + 1)] * (fRatioX) * (fRatioY);
            pValueOffset++;
        }
    }

    private void computeOpticalDepthBuffer()
    {
        int nSize = 128;
        int nBufferSamples = 50;

        if (opticalDepthBuffer == null)
            opticalDepthBuffer = new float[nSize * nSize * 4];

        int nIndex = 0;
        for (int nAngle = 0; nAngle < nSize; nAngle++)
        {
            // angle goes from 0 to 180 degrees
            float fCos = 1.0f - (nAngle + nAngle) / (float)nSize;
            float fAngle = (float)Math.acos(fCos);

            Vec4 vRay = new Vec4((float)Math.sin(fAngle), (float)Math.cos(fAngle), 0);	// Ray pointing to the viewpoint
            for (int nHeight = 0; nHeight < nSize; nHeight++)
            {
                // from the bottom of the atmosphere to the top
                float fHeight = DELTA + fInnerRadius + ((fOuterRadius - fInnerRadius) * nHeight) / nSize;
                Vec4 vPos = new Vec4(0, fHeight, 0);				// The position of the camera

                // If the ray from vPos heading in the vRay direction intersects the inner radius (i.e. the planet),
                // then this spot is not visible from the viewpoint
                float B = 2.0f * (float)vPos.dot3(vRay);
                float Bsq = B * B;
                float Cpart = (float)vPos.dotSelf3();
                float C = Cpart - fInnerRadius * fInnerRadius;
                float fDet = Bsq - 4.0f * C;
                boolean bVisible = (fDet < 0 ||
                    (0.5f * (-B - (float)Math.sqrt(fDet)) <= 0) && (0.5f * (-B + (float)Math.sqrt(fDet)) <= 0));
                float fRayleighDensityRatio;
                float fMieDensityRatio;
                if (bVisible)
                {
                    fRayleighDensityRatio = (float)Math.exp(-(fHeight - fInnerRadius) * fScale / fRayleighScaleDepth);
                    fMieDensityRatio = (float)Math.exp(-(fHeight - fInnerRadius) * fScale / fMieScaleDepth);
                }
                else
                {
                    // Smooth the transition from light to shadow
                    fRayleighDensityRatio = opticalDepthBuffer[nIndex - nSize * nChannels] * 0.75f;
                    fMieDensityRatio = opticalDepthBuffer[nIndex + 2 - nSize * nChannels] * 0.75f;

                }

                // Determine where the ray intersects the outer radius (the top of the atmosphere)
                // This is the end of our ray for determining the optical depth (vPos is the start)
                C = Cpart - fOuterRadius * fOuterRadius;
                fDet = Bsq - 4.0f * C;
                float fFar = 0.5f * (-B + (float)Math.sqrt(fDet));

                // Next determine the length of each sample, scale the sample ray, and make sure position
                // checks are at the center of a sample ray
                float fSampleLength = fFar / nBufferSamples;
                float fScaledLength = fSampleLength * fScale;
                Vec4 vSampleRay = vRay.multiply3(fSampleLength);
                vPos = vPos.add3(vSampleRay.multiply3(0.5f));

                // Iterate through the samples to sum up the optical depth for the distance the ray travels
                // through the atmosphere
                float fRayleighDepth = 0;
                float fMieDepth = 0;
                for (int i = 0; i < nBufferSamples; i++)
                {
                    fHeight = (float)vPos.getLength3();
                    float fAltitude = (fHeight - fInnerRadius) * fScale;
                    fAltitude = Math.max(fAltitude, 0.0f);
                    fRayleighDepth += (float)Math.exp(-fAltitude / fRayleighScaleDepth);
                    fMieDepth += (float)Math.exp(-fAltitude / fMieScaleDepth);
                    vPos = vPos.add3(vSampleRay);
                }

                // Multiply the sums by the length the ray traveled
                fRayleighDepth *= fScaledLength;
                fMieDepth *= fScaledLength;

                // Store the results for Rayleigh to the light source, Rayleigh to the camera, Mie to the
                // light source, and Mie to the camera
                opticalDepthBuffer[nIndex++] = fRayleighDensityRatio;
                opticalDepthBuffer[nIndex++] = fRayleighDepth;
                opticalDepthBuffer[nIndex++] = fMieDensityRatio;
                opticalDepthBuffer[nIndex++] = fMieDepth;

            } // height

        } // angle
    }

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -