diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index 8955010f50..632c5f96de 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -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(bo)); + // buffer.setGPUObject(reinterpret_cast(bo)); + buffer.setGPUObject(bo); } template< typename T > static T* getGPUObject(const Buffer& buffer) { return reinterpret_cast(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(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(so)); + } + template< typename T > + static T* getGPUObject(const Shader& shader) { + return reinterpret_cast(shader.getGPUObject()); + } + + // void syncGPUObject(const Shader& shader); protected: diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 49d139d727..161ce1dad6 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -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; diff --git a/libraries/gpu/src/gpu/GLBackendShader.cpp b/libraries/gpu/src/gpu/GLBackendShader.cpp new file mode 100755 index 0000000000..e37643e2f2 --- /dev/null +++ b/libraries/gpu/src/gpu/GLBackendShader.cpp @@ -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(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; + } +} + diff --git a/libraries/gpu/src/gpu/Resource.h b/libraries/gpu/src/gpu/Resource.h index a75c3e8d7c..225e3fd927 100644 --- a/libraries/gpu/src/gpu/Resource.h +++ b/libraries/gpu/src/gpu/Resource.h @@ -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; }; diff --git a/libraries/gpu/src/gpu/Shader.cpp b/libraries/gpu/src/gpu/Shader.cpp new file mode 100755 index 0000000000..87365e245e --- /dev/null +++ b/libraries/gpu/src/gpu/Shader.cpp @@ -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 +#include + +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; +} diff --git a/libraries/gpu/src/gpu/Shader.h b/libraries/gpu/src/gpu/Shader.h new file mode 100755 index 0000000000..57177639ae --- /dev/null +++ b/libraries/gpu/src/gpu/Shader.h @@ -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 + +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 ShaderPointer; +*/ +}; + + +#endif diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index 61923999b9..3eed52c686 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -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; }; diff --git a/libraries/model/src/model/SkyFromAtmosphere.slf b/libraries/model/src/model/SkyFromAtmosphere.slf new file mode 100755 index 0000000000..02036d0d7c --- /dev/null +++ b/libraries/model/src/model/SkyFromAtmosphere.slf @@ -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 +<$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); +} diff --git a/libraries/model/src/model/SkyFromSpace.slf b/libraries/model/src/model/SkyFromSpace.slf new file mode 100755 index 0000000000..5f6ce80efa --- /dev/null +++ b/libraries/model/src/model/SkyFromSpace.slf @@ -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 #include +#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() { diff --git a/libraries/model/src/model/Stage.h b/libraries/model/src/model/Stage.h index 762e2d9717..4de0edb96b 100644 --- a/libraries/model/src/model/Stage.h +++ b/libraries/model/src/model/Stage.h @@ -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;