mirror of
https://github.com/lubosz/overte.git
synced 2025-04-27 07:15:30 +02:00
Include the "sky from space" shaders, too, and use them when the camera is
outside the atmosphere's outer radius.
This commit is contained in:
parent
310c0288c7
commit
82f16e7f34
4 changed files with 246 additions and 47 deletions
interface
48
interface/resources/shaders/SkyFromSpace.frag
Normal file
48
interface/resources/shaders/SkyFromSpace.frag
Normal file
|
@ -0,0 +1,48 @@
|
|||
//
|
||||
// For licensing information, see http://http.developer.nvidia.com/GPUGems/gpugems_app01.html:
|
||||
//
|
||||
// NVIDIA Statement on the Software
|
||||
//
|
||||
// The source code provided is freely distributable, so long as the NVIDIA header remains unaltered and user modifications are
|
||||
// detailed.
|
||||
//
|
||||
// No Warranty
|
||||
//
|
||||
// THE SOFTWARE AND ANY OTHER MATERIALS PROVIDED BY NVIDIA ON THE ENCLOSED CD-ROM ARE PROVIDED "AS IS." NVIDIA DISCLAIMS ALL
|
||||
// WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
//
|
||||
// Limitation of Liability
|
||||
//
|
||||
// NVIDIA SHALL NOT BE LIABLE TO ANY USER, DEVELOPER, DEVELOPER'S CUSTOMERS, OR ANY OTHER PERSON OR ENTITY CLAIMING THROUGH OR
|
||||
// UNDER DEVELOPER FOR ANY LOSS OF PROFITS, INCOME, SAVINGS, OR ANY OTHER CONSEQUENTIAL, INCIDENTAL, SPECIAL, PUNITIVE, DIRECT
|
||||
// OR INDIRECT DAMAGES (WHETHER IN AN ACTION IN CONTRACT, TORT OR BASED ON A WARRANTY), EVEN IF NVIDIA HAS BEEN ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF THE ESSENTIAL PURPOSE OF ANY
|
||||
// LIMITED REMEDY. IN NO EVENT SHALL NVIDIA'S AGGREGATE LIABILITY TO DEVELOPER OR ANY OTHER PERSON OR ENTITY CLAIMING THROUGH
|
||||
// OR UNDER DEVELOPER EXCEED THE AMOUNT OF MONEY ACTUALLY PAID BY DEVELOPER TO NVIDIA FOR THE SOFTWARE OR ANY OTHER MATERIALS.
|
||||
//
|
||||
|
||||
//
|
||||
// Atmospheric scattering fragment shader
|
||||
//
|
||||
// Author: Sean O'Neil
|
||||
//
|
||||
// Copyright (c) 2004 Sean O'Neil
|
||||
//
|
||||
|
||||
#version 120
|
||||
|
||||
uniform vec3 v3LightPos;
|
||||
uniform float g;
|
||||
uniform float g2;
|
||||
|
||||
varying vec3 v3Direction;
|
||||
|
||||
|
||||
void main (void)
|
||||
{
|
||||
float fCos = dot(v3LightPos, v3Direction) / length(v3Direction);
|
||||
float fMiePhase = 1.5 * ((1.0 - g2) / (2.0 + g2)) * (1.0 + fCos*fCos) / pow(1.0 + g2 - 2.0*g*fCos, 1.5);
|
||||
gl_FragColor = gl_Color + fMiePhase * gl_SecondaryColor;
|
||||
gl_FragColor.a = 1.0; // gl_FragColor.b;
|
||||
}
|
109
interface/resources/shaders/SkyFromSpace.vert
Normal file
109
interface/resources/shaders/SkyFromSpace.vert
Normal file
|
@ -0,0 +1,109 @@
|
|||
//
|
||||
// For licensing information, see http://http.developer.nvidia.com/GPUGems/gpugems_app01.html:
|
||||
//
|
||||
// NVIDIA Statement on the Software
|
||||
//
|
||||
// The source code provided is freely distributable, so long as the NVIDIA header remains unaltered and user modifications are
|
||||
// detailed.
|
||||
//
|
||||
// No Warranty
|
||||
//
|
||||
// THE SOFTWARE AND ANY OTHER MATERIALS PROVIDED BY NVIDIA ON THE ENCLOSED CD-ROM ARE PROVIDED "AS IS." NVIDIA DISCLAIMS ALL
|
||||
// WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
//
|
||||
// Limitation of Liability
|
||||
//
|
||||
// NVIDIA SHALL NOT BE LIABLE TO ANY USER, DEVELOPER, DEVELOPER'S CUSTOMERS, OR ANY OTHER PERSON OR ENTITY CLAIMING THROUGH OR
|
||||
// UNDER DEVELOPER FOR ANY LOSS OF PROFITS, INCOME, SAVINGS, OR ANY OTHER CONSEQUENTIAL, INCIDENTAL, SPECIAL, PUNITIVE, DIRECT
|
||||
// OR INDIRECT DAMAGES (WHETHER IN AN ACTION IN CONTRACT, TORT OR BASED ON A WARRANTY), EVEN IF NVIDIA HAS BEEN ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF THE ESSENTIAL PURPOSE OF ANY
|
||||
// LIMITED REMEDY. IN NO EVENT SHALL NVIDIA'S AGGREGATE LIABILITY TO DEVELOPER OR ANY OTHER PERSON OR ENTITY CLAIMING THROUGH
|
||||
// OR UNDER DEVELOPER EXCEED THE AMOUNT OF MONEY ACTUALLY PAID BY DEVELOPER TO NVIDIA FOR THE SOFTWARE OR ANY OTHER MATERIALS.
|
||||
//
|
||||
|
||||
//
|
||||
// Atmospheric scattering vertex shader
|
||||
//
|
||||
// Author: Sean O'Neil
|
||||
//
|
||||
// Copyright (c) 2004 Sean O'Neil
|
||||
//
|
||||
|
||||
#version 120
|
||||
|
||||
uniform vec3 v3CameraPos; // The camera's current position
|
||||
uniform vec3 v3LightPos; // The direction vector to the light source
|
||||
uniform vec3 v3InvWavelength; // 1 / pow(wavelength, 4) for the red, green, and blue channels
|
||||
uniform float fCameraHeight2; // fCameraHeight^2
|
||||
uniform float fOuterRadius; // The outer (atmosphere) radius
|
||||
uniform float fOuterRadius2; // fOuterRadius^2
|
||||
uniform float fInnerRadius; // The inner (planetary) radius
|
||||
uniform float fKrESun; // Kr * ESun
|
||||
uniform float fKmESun; // Km * ESun
|
||||
uniform float fKr4PI; // Kr * 4 * PI
|
||||
uniform float fKm4PI; // Km * 4 * PI
|
||||
uniform float fScale; // 1 / (fOuterRadius - fInnerRadius)
|
||||
uniform float fScaleDepth; // The scale depth (i.e. the altitude at which the atmosphere's average density is found)
|
||||
uniform float fScaleOverScaleDepth; // fScale / fScaleDepth
|
||||
|
||||
const int nSamples = 2;
|
||||
const float fSamples = 2.0;
|
||||
|
||||
varying vec3 v3Direction;
|
||||
|
||||
|
||||
float scale(float fCos)
|
||||
{
|
||||
float x = 1.0 - fCos;
|
||||
return fScaleDepth * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25))));
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
// Get the ray from the camera to the vertex and its length (which is the far point of the ray passing through the atmosphere)
|
||||
vec3 v3Pos = gl_Vertex.xyz;
|
||||
vec3 v3Ray = v3Pos - v3CameraPos;
|
||||
float fFar = length(v3Ray);
|
||||
v3Ray /= fFar;
|
||||
|
||||
// Calculate the closest intersection of the ray with the outer atmosphere (which is the near point of the ray passing through the atmosphere)
|
||||
float B = 2.0 * dot(v3CameraPos, v3Ray);
|
||||
float C = fCameraHeight2 - fOuterRadius2;
|
||||
float fDet = max(0.0, B*B - 4.0 * C);
|
||||
float fNear = 0.5 * (-B - sqrt(fDet));
|
||||
|
||||
// Calculate the ray's starting position, then calculate its scattering offset
|
||||
vec3 v3Start = v3CameraPos + v3Ray * fNear;
|
||||
fFar -= fNear;
|
||||
float fStartAngle = dot(v3Ray, v3Start) / fOuterRadius;
|
||||
float fStartDepth = exp(-1.0 / fScaleDepth);
|
||||
float fStartOffset = fStartDepth * scale(fStartAngle);
|
||||
|
||||
// Initialize the scattering loop variables
|
||||
//gl_FrontColor = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
float fSampleLength = fFar / fSamples;
|
||||
float fScaledLength = fSampleLength * fScale;
|
||||
vec3 v3SampleRay = v3Ray * fSampleLength;
|
||||
vec3 v3SamplePoint = v3Start + v3SampleRay * 0.5;
|
||||
|
||||
// Now loop through the sample rays
|
||||
vec3 v3FrontColor = vec3(0.0, 0.0, 0.0);
|
||||
for(int i=0; i<nSamples; i++)
|
||||
{
|
||||
float fHeight = length(v3SamplePoint);
|
||||
float fDepth = exp(fScaleOverScaleDepth * (fInnerRadius - fHeight));
|
||||
float fLightAngle = dot(v3LightPos, v3SamplePoint) / fHeight;
|
||||
float fCameraAngle = dot(v3Ray, v3SamplePoint) / fHeight;
|
||||
float fScatter = (fStartOffset + fDepth * (scale(fLightAngle) - scale(fCameraAngle)));
|
||||
vec3 v3Attenuate = exp(-fScatter * (v3InvWavelength * fKr4PI + fKm4PI));
|
||||
v3FrontColor += v3Attenuate * (fDepth * fScaledLength);
|
||||
v3SamplePoint += v3SampleRay;
|
||||
}
|
||||
|
||||
// Finally, scale the Mie and Rayleigh colors and set up the varying variables for the pixel shader
|
||||
gl_FrontSecondaryColor.rgb = v3FrontColor * fKmESun;
|
||||
gl_FrontColor.rgb = v3FrontColor * (v3InvWavelength * fKrESun);
|
||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||
v3Direction = v3CameraPos - v3Pos;
|
||||
}
|
|
@ -5,6 +5,8 @@
|
|||
// Created by Andrzej Kapolka on 5/6/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
|
||||
#include <QByteArray>
|
||||
|
||||
#include "Camera.h"
|
||||
#include "Environment.h"
|
||||
#include "renderer/ProgramObject.h"
|
||||
|
@ -12,24 +14,8 @@
|
|||
#include "world.h"
|
||||
|
||||
void Environment::init() {
|
||||
_skyFromAtmosphereProgram = new ProgramObject();
|
||||
_skyFromAtmosphereProgram->attachFromSourceFile(GL_VERTEX_SHADER_ARB, "resources/shaders/SkyFromAtmosphere.vert");
|
||||
_skyFromAtmosphereProgram->attachFromSourceFile(GL_FRAGMENT_SHADER_ARB, "resources/shaders/SkyFromAtmosphere.frag");
|
||||
_skyFromAtmosphereProgram->link();
|
||||
|
||||
_cameraPosLocation = _skyFromAtmosphereProgram->getUniformLocation("v3CameraPos");
|
||||
_lightPosLocation = _skyFromAtmosphereProgram->getUniformLocation("v3LightPos");
|
||||
_invWavelengthLocation = _skyFromAtmosphereProgram->getUniformLocation("v3InvWavelength");
|
||||
_innerRadiusLocation = _skyFromAtmosphereProgram->getUniformLocation("fInnerRadius");
|
||||
_krESunLocation = _skyFromAtmosphereProgram->getUniformLocation("fKrESun");
|
||||
_kmESunLocation = _skyFromAtmosphereProgram->getUniformLocation("fKmESun");
|
||||
_kr4PiLocation = _skyFromAtmosphereProgram->getUniformLocation("fKr4PI");
|
||||
_km4PiLocation = _skyFromAtmosphereProgram->getUniformLocation("fKm4PI");
|
||||
_scaleLocation = _skyFromAtmosphereProgram->getUniformLocation("fScale");
|
||||
_scaleDepthLocation = _skyFromAtmosphereProgram->getUniformLocation("fScaleDepth");
|
||||
_scaleOverScaleDepthLocation = _skyFromAtmosphereProgram->getUniformLocation("fScaleOverScaleDepth");
|
||||
_gLocation = _skyFromAtmosphereProgram->getUniformLocation("g");
|
||||
_g2Location = _skyFromAtmosphereProgram->getUniformLocation("g2");
|
||||
_skyFromAtmosphereProgram = createSkyProgram("Atmosphere", _skyFromAtmosphereUniformLocations);
|
||||
_skyFromSpaceProgram = createSkyProgram("Space", _skyFromSpaceUniformLocations);
|
||||
}
|
||||
|
||||
void Environment::renderAtmosphere(Camera& camera) {
|
||||
|
@ -44,32 +30,48 @@ void Environment::renderAtmosphere(Camera& camera) {
|
|||
float projection[16];
|
||||
glGetFloatv(GL_PROJECTION_MATRIX, projection);
|
||||
glm::vec3 relativeCameraPos = camera.getPosition() - getAtmosphereCenter();
|
||||
float near = camera.getNearClip(), far = glm::length(relativeCameraPos) + getAtmosphereOuterRadius();
|
||||
float height = glm::length(relativeCameraPos);
|
||||
float near = camera.getNearClip(), far = height + getAtmosphereOuterRadius();
|
||||
projection[10] = (far + near) / (near - far);
|
||||
projection[14] = (2.0f * far * near) / (near - far);
|
||||
glLoadMatrixf(projection);
|
||||
|
||||
// use the appropriate shader depending on whether we're inside or outside
|
||||
ProgramObject* program;
|
||||
int* locations;
|
||||
if (height < getAtmosphereOuterRadius()) {
|
||||
program = _skyFromAtmosphereProgram;
|
||||
locations = _skyFromAtmosphereUniformLocations;
|
||||
|
||||
} else {
|
||||
program = _skyFromSpaceProgram;
|
||||
locations = _skyFromSpaceUniformLocations;
|
||||
}
|
||||
|
||||
// the constants here are from Sean O'Neil's GPU Gems entry
|
||||
// (http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter16.html), GameEngine.cpp
|
||||
_skyFromAtmosphereProgram->bind();
|
||||
_skyFromAtmosphereProgram->setUniform(_cameraPosLocation, relativeCameraPos);
|
||||
program->bind();
|
||||
program->setUniform(locations[CAMERA_POS_LOCATION], relativeCameraPos);
|
||||
glm::vec3 lightDirection = glm::normalize(getSunLocation());
|
||||
_skyFromAtmosphereProgram->setUniform(_lightPosLocation, lightDirection);
|
||||
_skyFromAtmosphereProgram->setUniform(_invWavelengthLocation,
|
||||
program->setUniform(locations[LIGHT_POS_LOCATION], lightDirection);
|
||||
program->setUniform(locations[INV_WAVELENGTH_LOCATION],
|
||||
1 / powf(getScatteringWavelengths().r, 4.0f),
|
||||
1 / powf(getScatteringWavelengths().g, 4.0f),
|
||||
1 / powf(getScatteringWavelengths().b, 4.0f));
|
||||
_skyFromAtmosphereProgram->setUniform(_innerRadiusLocation, getAtmosphereInnerRadius());
|
||||
_skyFromAtmosphereProgram->setUniform(_krESunLocation, getRayleighScattering() * getSunBrightness());
|
||||
_skyFromAtmosphereProgram->setUniform(_kmESunLocation, getMieScattering() * getSunBrightness());
|
||||
_skyFromAtmosphereProgram->setUniform(_kr4PiLocation, getRayleighScattering() * 4.0f * PIf);
|
||||
_skyFromAtmosphereProgram->setUniform(_km4PiLocation, getMieScattering() * 4.0f * PIf);
|
||||
_skyFromAtmosphereProgram->setUniform(_scaleLocation, 1.0f / (getAtmosphereOuterRadius() - getAtmosphereInnerRadius()));
|
||||
_skyFromAtmosphereProgram->setUniform(_scaleDepthLocation, 0.25f);
|
||||
_skyFromAtmosphereProgram->setUniform(_scaleOverScaleDepthLocation,
|
||||
program->setUniform(locations[CAMERA_HEIGHT2_LOCATION], height * height);
|
||||
program->setUniform(locations[OUTER_RADIUS_LOCATION], getAtmosphereOuterRadius());
|
||||
program->setUniform(locations[OUTER_RADIUS2_LOCATION], getAtmosphereOuterRadius() * getAtmosphereOuterRadius());
|
||||
program->setUniform(locations[INNER_RADIUS_LOCATION], getAtmosphereInnerRadius());
|
||||
program->setUniform(locations[KR_ESUN_LOCATION], getRayleighScattering() * getSunBrightness());
|
||||
program->setUniform(locations[KM_ESUN_LOCATION], getMieScattering() * getSunBrightness());
|
||||
program->setUniform(locations[KR_4PI_LOCATION], getRayleighScattering() * 4.0f * PIf);
|
||||
program->setUniform(locations[KM_4PI_LOCATION], getMieScattering() * 4.0f * PIf);
|
||||
program->setUniform(locations[SCALE_LOCATION], 1.0f / (getAtmosphereOuterRadius() - getAtmosphereInnerRadius()));
|
||||
program->setUniform(locations[SCALE_DEPTH_LOCATION], 0.25f);
|
||||
program->setUniform(locations[SCALE_OVER_SCALE_DEPTH_LOCATION],
|
||||
(1.0f / (getAtmosphereOuterRadius() - getAtmosphereInnerRadius())) / 0.25f);
|
||||
_skyFromAtmosphereProgram->setUniform(_gLocation, -0.990f);
|
||||
_skyFromAtmosphereProgram->setUniform(_g2Location, -0.990f * -0.990f);
|
||||
program->setUniform(locations[G_LOCATION], -0.990f);
|
||||
program->setUniform(locations[G2_LOCATION], -0.990f * -0.990f);
|
||||
|
||||
glFrontFace(GL_CW);
|
||||
glDepthMask(GL_FALSE);
|
||||
|
@ -78,10 +80,37 @@ void Environment::renderAtmosphere(Camera& camera) {
|
|||
glDepthMask(GL_TRUE);
|
||||
glFrontFace(GL_CCW);
|
||||
|
||||
_skyFromAtmosphereProgram->release();
|
||||
program->release();
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
ProgramObject* Environment::createSkyProgram(const char* from, int* locations) {
|
||||
ProgramObject* program = new ProgramObject();
|
||||
QByteArray prefix = QByteArray("resources/shaders/SkyFrom") + from;
|
||||
program->attachFromSourceFile(GL_VERTEX_SHADER_ARB, prefix + ".vert");
|
||||
program->attachFromSourceFile(GL_FRAGMENT_SHADER_ARB, prefix + ".frag");
|
||||
program->link();
|
||||
|
||||
locations[CAMERA_POS_LOCATION] = program->getUniformLocation("v3CameraPos");
|
||||
locations[LIGHT_POS_LOCATION] = program->getUniformLocation("v3LightPos");
|
||||
locations[INV_WAVELENGTH_LOCATION] = program->getUniformLocation("v3InvWavelength");
|
||||
locations[CAMERA_HEIGHT2_LOCATION] = program->getUniformLocation("fCameraHeight2");
|
||||
locations[OUTER_RADIUS_LOCATION] = program->getUniformLocation("fOuterRadius");
|
||||
locations[OUTER_RADIUS2_LOCATION] = program->getUniformLocation("fOuterRadius2");
|
||||
locations[INNER_RADIUS_LOCATION] = program->getUniformLocation("fInnerRadius");
|
||||
locations[KR_ESUN_LOCATION] = program->getUniformLocation("fKrESun");
|
||||
locations[KM_ESUN_LOCATION] = program->getUniformLocation("fKmESun");
|
||||
locations[KR_4PI_LOCATION] = program->getUniformLocation("fKr4PI");
|
||||
locations[KM_4PI_LOCATION] = program->getUniformLocation("fKm4PI");
|
||||
locations[SCALE_LOCATION] = program->getUniformLocation("fScale");
|
||||
locations[SCALE_DEPTH_LOCATION] = program->getUniformLocation("fScaleDepth");
|
||||
locations[SCALE_OVER_SCALE_DEPTH_LOCATION] = program->getUniformLocation("fScaleOverScaleDepth");
|
||||
locations[G_LOCATION] = program->getUniformLocation("g");
|
||||
locations[G2_LOCATION] = program->getUniformLocation("g2");
|
||||
|
||||
return program;
|
||||
}
|
||||
|
|
|
@ -23,20 +23,33 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
ProgramObject* createSkyProgram(const char* from, int* locations);
|
||||
|
||||
ProgramObject* _skyFromAtmosphereProgram;
|
||||
int _cameraPosLocation;
|
||||
int _lightPosLocation;
|
||||
int _invWavelengthLocation;
|
||||
int _innerRadiusLocation;
|
||||
int _krESunLocation;
|
||||
int _kmESunLocation;
|
||||
int _kr4PiLocation;
|
||||
int _km4PiLocation;
|
||||
int _scaleLocation;
|
||||
int _scaleDepthLocation;
|
||||
int _scaleOverScaleDepthLocation;
|
||||
int _gLocation;
|
||||
int _g2Location;
|
||||
ProgramObject* _skyFromSpaceProgram;
|
||||
|
||||
enum {
|
||||
CAMERA_POS_LOCATION,
|
||||
LIGHT_POS_LOCATION,
|
||||
INV_WAVELENGTH_LOCATION,
|
||||
CAMERA_HEIGHT2_LOCATION,
|
||||
OUTER_RADIUS_LOCATION,
|
||||
OUTER_RADIUS2_LOCATION,
|
||||
INNER_RADIUS_LOCATION,
|
||||
KR_ESUN_LOCATION,
|
||||
KM_ESUN_LOCATION,
|
||||
KR_4PI_LOCATION,
|
||||
KM_4PI_LOCATION,
|
||||
SCALE_LOCATION,
|
||||
SCALE_DEPTH_LOCATION,
|
||||
SCALE_OVER_SCALE_DEPTH_LOCATION,
|
||||
G_LOCATION,
|
||||
G2_LOCATION,
|
||||
LOCATION_COUNT
|
||||
};
|
||||
|
||||
int _skyFromAtmosphereUniformLocations[LOCATION_COUNT];
|
||||
int _skyFromSpaceUniformLocations[LOCATION_COUNT];
|
||||
};
|
||||
|
||||
#endif /* defined(__interface__Environment__) */
|
||||
|
|
Loading…
Reference in a new issue