First version of the Shader and the magical shader program

This commit is contained in:
Sam Gateau 2015-02-28 13:07:16 -08:00
parent 5652852d1a
commit 660d9237e6
13 changed files with 845 additions and 8 deletions

View file

@ -15,6 +15,7 @@
#include "Resource.h"
#include "Texture.h"
#include "Shader.h"
namespace gpu {
@ -46,14 +47,15 @@ public:
template< typename T >
static void setGPUObject(const Buffer& buffer, T* bo) {
buffer.setGPUObject(reinterpret_cast<GPUObject*>(bo));
// buffer.setGPUObject(reinterpret_cast<GPUObject*>(bo));
buffer.setGPUObject(bo);
}
template< typename T >
static T* getGPUObject(const Buffer& buffer) {
return reinterpret_cast<T*>(buffer.getGPUObject());
}
void syncGPUObject(const Buffer& buffer);
//void syncGPUObject(const Buffer& buffer);
template< typename T >
static void setGPUObject(const Texture& texture, T* to) {
@ -64,7 +66,19 @@ public:
return reinterpret_cast<T*>(texture.getGPUObject());
}
void syncGPUObject(const Texture& texture);
//void syncGPUObject(const Texture& texture);
template< typename T >
static void setGPUObject(const Shader& shader, T* so) {
shader.setGPUObject(reinterpret_cast<GPUObject*>(so));
}
template< typename T >
static T* getGPUObject(const Shader& shader) {
return reinterpret_cast<T*>(shader.getGPUObject());
}
// void syncGPUObject(const Shader& shader);
protected:

View file

@ -60,6 +60,17 @@ public:
static void syncGPUObject(const Texture& texture);
static GLuint getTextureID(const TexturePointer& texture);
class GLShader : public GPUObject {
public:
GLuint _shader;
GLuint _program;
GLShader();
~GLShader();
};
static GLShader* syncGPUObject(const Shader& shader);
static GLuint getShaderID(const ShaderPointer& shader);
static const int MAX_NUM_ATTRIBUTES = Stream::NUM_INPUT_SLOTS;
static const int MAX_NUM_INPUT_BUFFERS = 16;

View file

@ -0,0 +1,275 @@
//
// GLBackendShader.cpp
// libraries/gpu/src/gpu
//
// Created by Sam Gateau on 2/28/2015.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "GLBackendShared.h"
GLBackend::GLShader::GLShader() :
_shader(0),
_program(0)
{}
GLBackend::GLShader::~GLShader() {
if (_shader != 0) {
glDeleteShader(_shader);
}
if (_program != 0) {
glDeleteProgram(_program);
}
}
bool compileShader(const Shader& shader, GLBackend::GLShader& object) {
// Any GLSLprogram ? normally yes...
const std::string& shaderSource = shader.getSource().getCode();
if (shaderSource.empty()) {
qDebug() << "GLShader::compileShader - no GLSL shader source code ? so failed to create";
return false;
}
// Shader domain
const GLenum SHADER_DOMAINS[2] = { GL_VERTEX_SHADER, GL_FRAGMENT_SHADER };
GLenum shaderDomain = SHADER_DOMAINS[shader.getType()];
// Create the shader object
GLuint glshader = glCreateShader(shaderDomain);
if (!glshader) {
qDebug() << "GLShader::compileShader - failed to create the gl shader & gl program object";
return false;
}
// Assign the source
const GLchar* srcstr = shaderSource.c_str();
glShaderSource(glshader, 1, &srcstr, NULL);
// Compile !
glCompileShader(glshader);
// check if shader compiled
GLint compiled = 0;
glGetShaderiv(glshader, GL_COMPILE_STATUS, &compiled);
// if compilation fails
if (!compiled)
{
// save the source code to a temp file so we can debug easily
/* std::ofstream filestream;
filestream.open( "debugshader.glsl" );
if ( filestream.is_open() )
{
filestream << shaderSource->source;
filestream.close();
}
*/
GLint infoLength = 0;
glGetShaderiv(glshader, GL_INFO_LOG_LENGTH, &infoLength);
char* temp = new char[infoLength] ;
glGetShaderInfoLog( glshader, infoLength, NULL, temp);
qDebug() << "GLShader::compileShader - failed to compile the gl shader object:";
qDebug() << temp;
/*
filestream.open( "debugshader.glsl.info.txt" );
if ( filestream.is_open() )
{
filestream << String( temp );
filestream.close();
}
*/
delete[] temp;
glDeleteShader( glshader);
return false;
}
// so far so good, program is almost done, need to link:
GLuint glprogram = glCreateProgram();
if (!glprogram) {
qDebug() << "GLShader::compileShader - failed to create the gl shader & gl program object";
return false;
}
glProgramParameteri(glprogram, GL_PROGRAM_SEPARABLE, GL_TRUE);
glAttachShader(glprogram, glshader);
glLinkProgram(glprogram);
GLint linked = 0;
glGetProgramiv(glprogram, GL_LINK_STATUS, &linked);
if (!linked)
{
/*
// save the source code to a temp file so we can debug easily
std::ofstream filestream;
filestream.open( "debugshader.glsl" );
if ( filestream.is_open() )
{
filestream << shaderSource->source;
filestream.close();
}
*/
GLint infoLength = 0;
glGetProgramiv( glprogram, GL_INFO_LOG_LENGTH, &infoLength );
char* temp = new char[infoLength] ;
glGetProgramInfoLog( glprogram, infoLength, NULL, temp);
qDebug() << "GLShader::compileShader - failed to LINK the gl program object :";
qDebug() << temp;
/*
filestream.open( "debugshader.glsl.info.txt" );
if ( filestream.is_open() )
{
filestream << String( temp );
filestream.close();
}
*/
delete[] temp;
glDeleteShader( glshader);
glDeleteProgram( glprogram);
return false;
}
// So far so good, the shader is created successfully
object._shader = glshader;
object._program = glprogram;
return true;
}
bool compileProgram(const Shader& program, GLBackend::GLShader& object) {
if(!program.isProgram()) {
return false;
}
// Let's go through every shaders and make sure they are ready to go
std::vector< GLuint > shaderObjects;
for (auto subShader : program.getShaders()) {
GLuint so = GLBackend::getShaderID(subShader);
if (!so) {
qDebug() << "GLShader::compileProgram - One of the shaders of the program is not compiled?";
return false;
}
shaderObjects.push_back(so);
}
// so far so good, program is almost done, need to link:
GLuint glprogram = glCreateProgram();
if (!glprogram) {
qDebug() << "GLShader::compileProgram - failed to create the gl program object";
return false;
}
// glProgramParameteri(glprogram, GL_PROGRAM_, GL_TRUE);
// Create the program from the sub shaders
for (auto so : shaderObjects) {
glAttachShader(glprogram, so);
}
// Link!
glLinkProgram(glprogram);
GLint linked = 0;
glGetProgramiv(glprogram, GL_LINK_STATUS, &linked);
if (!linked)
{
/*
// save the source code to a temp file so we can debug easily
std::ofstream filestream;
filestream.open( "debugshader.glsl" );
if ( filestream.is_open() )
{
filestream << shaderSource->source;
filestream.close();
}
*/
GLint infoLength = 0;
glGetProgramiv( glprogram, GL_INFO_LOG_LENGTH, &infoLength );
char* temp = new char[infoLength] ;
glGetProgramInfoLog( glprogram, infoLength, NULL, temp);
qDebug() << "GLShader::compileProgram - failed to LINK the gl program object :";
qDebug() << temp;
/*
filestream.open( "debugshader.glsl.info.txt" );
if ( filestream.is_open() )
{
filestream << String( temp );
filestream.close();
}
*/
delete[] temp;
glDeleteProgram( glprogram);
return false;
}
// So far so good, the program is created successfully
object._shader = 0;
object._program = glprogram;
return true;
}
GLBackend::GLShader* GLBackend::syncGPUObject(const Shader& shader) {
GLShader* object = Backend::getGPUObject<GLBackend::GLShader>(shader);
// If GPU object already created then good
if (object) {
return object;
}
// need to have a gpu object?
// GO through the process of allocating the correct storage and/or update the content
if (shader.isProgram()) {
GLShader tempObject;
if (compileProgram(shader, tempObject)) {
object = new GLShader(tempObject);
Backend::setGPUObject(shader, object);
}
} else if (shader.isDomain()) {
GLShader tempObject;
if (compileShader(shader, tempObject)) {
object = new GLShader(tempObject);
Backend::setGPUObject(shader, object);
}
}
return object;
}
GLuint GLBackend::getShaderID(const ShaderPointer& shader) {
if (!shader) {
return 0;
}
GLShader* object = GLBackend::syncGPUObject(*shader);
if (object) {
if (shader->isProgram()) {
return object->_program;
} else {
return object->_shader;
}
} else {
return 0;
}
}

View file

@ -140,12 +140,11 @@ protected:
Sysmem* _sysmem = NULL;
mutable GPUObject* _gpuObject = NULL;
// This shouldn't be used by anything else than the Backend class with the proper casting.
mutable GPUObject* _gpuObject = NULL;
void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; }
GPUObject* getGPUObject() const { return _gpuObject; }
friend class Backend;
};

View file

@ -0,0 +1,67 @@
//
// Shader.cpp
// libraries/gpu/src/gpu
//
// Created by Sam Gateau on 2/27/2015.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "Shader.h"
#include <math.h>
#include <QDebug>
using namespace gpu;
Shader::Shader(Type type, const Source& source):
_source(source),
_type(type)
{
}
Shader::Shader(Type type, Pointer& vertex, Pointer& pixel):
_type(type)
{
_shaders.resize(2);
_shaders[VERTEX] = vertex;
_shaders[PIXEL] = pixel;
}
Shader::~Shader()
{
}
/*
Program::Program():
_storage(),
_type(GRAPHICS)
{
}
Program::~Program()
{
}
*/
Shader* Shader::createVertex(const Source& source) {
Shader* shader = new Shader(VERTEX, source);
return shader;
}
Shader* Shader::createPixel(const Source& source) {
Shader* shader = new Shader(PIXEL, source);
return shader;
}
Shader* Shader::createProgram(Pointer& vertexShader, Pointer& pixelShader) {
if (vertexShader && vertexShader->getType() == VERTEX) {
if (pixelShader && pixelShader->getType() == PIXEL) {
Shader* shader = new Shader(PROGRAM, vertexShader, pixelShader);
return shader;
}
}
return nullptr;
}

126
libraries/gpu/src/gpu/Shader.h Executable file
View file

@ -0,0 +1,126 @@
//
// Shader.h
// libraries/gpu/src/gpu
//
// Created by Sam Gateau on 2/27/2015.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_gpu_Shader_h
#define hifi_gpu_Shader_h
#include "Resource.h"
#include <memory>
namespace gpu {
class Shader {
public:
typedef QSharedPointer< Shader > Pointer;
typedef std::vector< Pointer > Shaders;
class Source {
public:
enum Language {
GLSL = 0,
};
Source() {}
Source(const std::string& code, Language lang = GLSL) : _code(code), _lang(lang) {}
Source(const Source& source) : _code(source._code), _lang(source._lang) {}
virtual ~Source() {}
virtual const std::string& getCode() const { return _code; }
protected:
std::string _code;
Language _lang = GLSL;
};
enum Type {
VERTEX = 0,
PIXEL,
GEOMETRY,
NUM_DOMAINS,
PROGRAM,
};
static Shader* createVertex(const Source& source);
static Shader* createPixel(const Source& source);
static Shader* createProgram(Pointer& vertexShader, Pointer& pixelShader);
~Shader();
Type getType() const { return _type; }
bool isProgram() const { return getType() > NUM_DOMAINS; }
bool isDomain() const { return getType() < NUM_DOMAINS; }
const Source& getSource() const { return _source; }
const Shaders& getShaders() const { return _shaders; }
protected:
Shader(Type type, const Source& source);
Shader(Type type, Pointer& vertex, Pointer& pixel);
Shader(const Shader& shader); // deep copy of the sysmem shader
Shader& operator=(const Shader& shader); // deep copy of the sysmem texture
// Source contains the actual source code or nothing if the shader is a program
Source _source;
// if shader is composed of sub shaders, here they are
Shaders _shaders;
// The type of the shader, the master key
Type _type;
// This shouldn't be used by anything else than the Backend class with the proper casting.
mutable GPUObject* _gpuObject = NULL;
void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; }
GPUObject* getGPUObject() const { return _gpuObject; }
friend class Backend;
};
typedef Shader::Pointer ShaderPointer;
typedef std::vector< ShaderPointer > Shaders;
/*
class Program {
public:
enum Type {
GRAPHICS = 0,
NUM_TYPES,
};
Program();
Program(const Program& program); // deep copy of the sysmem shader
Program& operator=(const Program& program); // deep copy of the sysmem texture
~Program();
protected:
Shaders _shaders;
Type _type;
// This shouldn't be used by anything else than the Backend class with the proper casting.
mutable GPUObject* _gpuObject = NULL;
void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; }
GPUObject* getGPUObject() const { return _gpuObject; }
friend class Backend;
};
typedef QSharedPointer<Shader> ShaderPointer;
*/
};
#endif

View file

@ -207,12 +207,10 @@ protected:
Size resize(Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices);
mutable GPUObject* _gpuObject = NULL;
// This shouldn't be used by anything else than the Backend class with the proper casting.
mutable GPUObject* _gpuObject = NULL;
void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; }
GPUObject* getGPUObject() const { return _gpuObject; }
friend class Backend;
};

View file

@ -0,0 +1,108 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
//
// 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
//
uniform vec3 v3CameraPos; // The camera's current position
uniform vec3 v3InvWavelength; // 1 / pow(wavelength, 4) for the red, green, and blue channels
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;
uniform vec3 v3LightPos;
uniform float g;
uniform float g2;
varying vec3 position;
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 = position;
vec3 v3Ray = v3Pos - v3CameraPos;
float fFar = length(v3Ray);
v3Ray /= fFar;
// Calculate the ray's starting position, then calculate its scattering offset
vec3 v3Start = v3CameraPos;
float fHeight = length(v3Start);
float fDepth = exp(fScaleOverScaleDepth * (fInnerRadius - fHeight));
float fStartAngle = dot(v3Ray, v3Start) / fHeight;
float fStartOffset = fDepth * 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 * 0.99;
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
vec3 secondaryFrontColor = v3FrontColor * fKmESun;
vec3 frontColor = v3FrontColor * (v3InvWavelength * fKrESun);
vec3 v3Direction = v3CameraPos - v3Pos;
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.rgb = frontColor.rgb + fMiePhase * secondaryFrontColor.rgb;
gl_FragColor.a = gl_FragColor.b;
gl_FragColor.rgb = pow(gl_FragColor.rgb, vec3(1.0/2.2));
}

View file

@ -0,0 +1,68 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
//
// 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
//
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 fOuterRadius; // The outer (atmosphere) radius
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 position;
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)
position = gl_Vertex.xyz * fOuterRadius;
gl_Position = gl_ModelViewProjectionMatrix * vec4(position, 1.0);
}

View file

@ -0,0 +1,114 @@
#version 120
//
// 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
//
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
uniform float g;
uniform float g2;
const int nSamples = 2;
const float fSamples = 2.0;
varying vec3 position;
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 = position;
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 * 0.99;
float fScatter = (fStartOffset + fDepth * (scale(fLightAngle) - scale(fCameraAngle)));
vec3 v3Attenuate = exp(-fScatter * (v3InvWavelength * fKr4PI + fKm4PI));
v3FrontColor += v3Attenuate * (fDepth * fScaledLength);
v3SamplePoint += v3SampleRay;
}
vec3 v3Direction = v3CameraPos - v3Pos;
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);
vec3 color = v3FrontColor * (v3InvWavelength * fKrESun);
vec3 secondaryColor = v3FrontColor * fKmESun;
gl_FragColor.rgb = color + fMiePhase * secondaryColor;
gl_FragColor.a = gl_FragColor.b;
gl_FragColor.rgb = pow(gl_FragColor.rgb, vec3(1.0/2.2));
}

View file

@ -0,0 +1,43 @@
#version 120
//
// 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
//
uniform float fOuterRadius; // The outer (atmosphere) radius
varying vec3 position;
void main(void)
{
position = gl_Vertex.xyz * fOuterRadius;
gl_Position = gl_ModelViewProjectionMatrix * vec4(position, 1.0);
}

View file

@ -13,6 +13,9 @@
#include <glm/gtx/transform.hpp>
#include <math.h>
#include "SkyFromAtmosphere_vert.h"
#include "SkyFromAtmosphere_frag.h"
using namespace model;
@ -150,6 +153,13 @@ SunSkyStage::SunSkyStage() :
setDayTime(12.0f);
// Begining of march
setYearTime(60.0f);
_skyShader = gpu::ShaderPointer(
gpu::Shader::createProgram(
gpu::ShaderPointer(gpu::Shader::createVertex(std::string(SkyFromAtmosphere_vert))),
gpu::ShaderPointer(gpu::Shader::createPixel(std::string(SkyFromAtmosphere_frag)))
)
);
}
SunSkyStage::~SunSkyStage() {

View file

@ -11,6 +11,8 @@
#ifndef hifi_model_Stage_h
#define hifi_model_Stage_h
#include "gpu/Shader.h"
#include "Light.h"
namespace model {
@ -143,6 +145,8 @@ public:
protected:
LightPointer _sunLight;
gpu::ShaderPointer _skyShader;
float _dayTime;
int _yearTime;