/*******************************************************************************
* Copyright 2014 Geoscience Australia
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package au.gov.ga.earthsci.worldwind.common.layers.atmosphere;
import gov.nasa.worldwind.geom.Vec4;
import javax.media.opengl.GL2;
import au.gov.ga.earthsci.worldwind.common.render.Shader;
/**
* Base shader for atmospheric scattering effects.
*
* @author Michael de Hoog (michael.dehoog@ga.gov.au)
*/
@SuppressWarnings("nls")
public abstract class AbstractAtmosphereShader extends Shader
{
private final String[] defines;
private int v3CameraPos = -1;
private int v3LightPos = -1;
private int v3InvWavelength = -1;
private int fCameraHeight = -1;
private int fCameraHeight2 = -1;
private int fInnerRadius = -1;
private int fInnerRadius2 = -1;
private int fOuterRadius = -1;
private int fOuterRadius2 = -1;
private int fKrESun = -1;
private int fKmESun = -1;
private int fKr4PI = -1;
private int fKm4PI = -1;
private int fScale = -1;
private int fScaleDepth = -1;
private int fScaleOverScaleDepth = -1;
private int fExposure = -1;
protected AbstractAtmosphereShader(String[] defines)
{
this.defines = defines;
}
@Override
protected String[] getDefines()
{
return defines;
}
public void use(GL2 gl, Vec4 cameraPos, Vec4 lightDir, float[] invWavelength4, float cameraHeight,
float innerRadius, float outerRadius, float rayleighScattering, float mieScattering, float sunBrightness,
float scaleDepth, float exposure)
{
if (super.use(gl))
{
if (cameraHeight < innerRadius + 1)
{
cameraHeight = innerRadius + 1;
cameraPos = cameraPos.normalize3().multiply3(cameraHeight);
}
float fScale = 1f / (outerRadius - innerRadius);
gl.glUniform3f(this.v3CameraPos, (float) cameraPos.x, (float) cameraPos.y, (float) cameraPos.z);
gl.glUniform3f(this.v3LightPos, (float) lightDir.x, (float) lightDir.y, (float) lightDir.z);
gl.glUniform3f(this.v3InvWavelength, invWavelength4[0], invWavelength4[1], invWavelength4[2]);
gl.glUniform1f(this.fCameraHeight, cameraHeight);
gl.glUniform1f(this.fCameraHeight2, cameraHeight * cameraHeight);
gl.glUniform1f(this.fInnerRadius, innerRadius);
gl.glUniform1f(this.fInnerRadius2, innerRadius * innerRadius);
gl.glUniform1f(this.fOuterRadius, outerRadius);
gl.glUniform1f(this.fOuterRadius2, outerRadius * outerRadius);
gl.glUniform1f(this.fKrESun, rayleighScattering * sunBrightness);
gl.glUniform1f(this.fKmESun, mieScattering * sunBrightness);
gl.glUniform1f(this.fKr4PI, rayleighScattering * 4f * (float) Math.PI);
gl.glUniform1f(this.fKm4PI, mieScattering * 4f * (float) Math.PI);
gl.glUniform1f(this.fScale, fScale);
gl.glUniform1f(this.fScaleDepth, scaleDepth);
gl.glUniform1f(this.fScaleOverScaleDepth, fScale / scaleDepth);
gl.glUniform1f(this.fExposure, exposure);
}
}
@Override
protected void getUniformLocations(GL2 gl)
{
this.v3CameraPos = gl.glGetUniformLocation(shaderProgram, "v3CameraPos");
this.v3LightPos = gl.glGetUniformLocation(shaderProgram, "v3LightPos");
this.v3InvWavelength = gl.glGetUniformLocation(shaderProgram, "v3InvWavelength");
this.fCameraHeight = gl.glGetUniformLocation(shaderProgram, "fCameraHeight");
this.fCameraHeight2 = gl.glGetUniformLocation(shaderProgram, "fCameraHeight2");
this.fInnerRadius = gl.glGetUniformLocation(shaderProgram, "fInnerRadius");
this.fInnerRadius2 = gl.glGetUniformLocation(shaderProgram, "fInnerRadius2");
this.fOuterRadius = gl.glGetUniformLocation(shaderProgram, "fOuterRadius");
this.fOuterRadius2 = gl.glGetUniformLocation(shaderProgram, "fOuterRadius2");
this.fKrESun = gl.glGetUniformLocation(shaderProgram, "fKrESun");
this.fKmESun = gl.glGetUniformLocation(shaderProgram, "fKmESun");
this.fKr4PI = gl.glGetUniformLocation(shaderProgram, "fKr4PI");
this.fKm4PI = gl.glGetUniformLocation(shaderProgram, "fKm4PI");
this.fScale = gl.glGetUniformLocation(shaderProgram, "fScale");
this.fScaleDepth = gl.glGetUniformLocation(shaderProgram, "fScaleDepth");
this.fScaleOverScaleDepth = gl.glGetUniformLocation(shaderProgram, "fScaleOverScaleDepth");
this.fExposure = gl.glGetUniformLocation(shaderProgram, "fExposure");
}
}