From 660d9237e6e77fbefa8d4845132fc01e3b65eba8 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Sat, 28 Feb 2015 13:07:16 -0800 Subject: [PATCH 1/8] First version of the Shader and the magical shader program --- libraries/gpu/src/gpu/Context.h | 20 +- libraries/gpu/src/gpu/GLBackend.h | 11 + libraries/gpu/src/gpu/GLBackendShader.cpp | 275 ++++++++++++++++++ libraries/gpu/src/gpu/Resource.h | 3 +- libraries/gpu/src/gpu/Shader.cpp | 67 +++++ libraries/gpu/src/gpu/Shader.h | 126 ++++++++ libraries/gpu/src/gpu/Texture.h | 4 +- .../model/src/model/SkyFromAtmosphere.slf | 108 +++++++ .../model/src/model/SkyFromAtmosphere.slv | 68 +++++ libraries/model/src/model/SkyFromSpace.slf | 114 ++++++++ libraries/model/src/model/SkyFromSpace.slv | 43 +++ libraries/model/src/model/Stage.cpp | 10 + libraries/model/src/model/Stage.h | 4 + 13 files changed, 845 insertions(+), 8 deletions(-) create mode 100755 libraries/gpu/src/gpu/GLBackendShader.cpp create mode 100755 libraries/gpu/src/gpu/Shader.cpp create mode 100755 libraries/gpu/src/gpu/Shader.h create mode 100755 libraries/model/src/model/SkyFromAtmosphere.slf create mode 100755 libraries/model/src/model/SkyFromAtmosphere.slv create mode 100755 libraries/model/src/model/SkyFromSpace.slf create mode 100755 libraries/model/src/model/SkyFromSpace.slv 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; From cb737d64d3a858f45e6a2a58978e9ddd4e0fff07 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Sun, 1 Mar 2015 15:20:32 -0800 Subject: [PATCH 2/8] Testing the gpu::Shader compilation and building steps, ready to be used for real --- libraries/gpu/src/gpu/GLBackend.cpp | 14 ++- libraries/gpu/src/gpu/GLBackend.h | 4 +- libraries/gpu/src/gpu/GLBackendShader.cpp | 120 ++++++++++----------- libraries/gpu/src/gpu/GLBackendTexture.cpp | 11 +- libraries/model/src/model/Stage.cpp | 4 + 5 files changed, 78 insertions(+), 75 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index fd91e0df0c..64bcb006a5 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -1015,11 +1015,11 @@ GLBackend::GLBuffer::~GLBuffer() { } } -void GLBackend::syncGPUObject(const Buffer& buffer) { +GLBackend::GLBuffer* GLBackend::syncGPUObject(const Buffer& buffer) { GLBuffer* object = Backend::getGPUObject(buffer); if (object && (object->_stamp == buffer.getSysmem().getStamp())) { - return; + return object; } // need to have a gpu object? @@ -1040,12 +1040,18 @@ void GLBackend::syncGPUObject(const Buffer& buffer) { object->_size = buffer.getSysmem().getSize(); //} CHECK_GL_ERROR(); + + return object; } GLuint GLBackend::getBufferID(const Buffer& buffer) { - GLBackend::syncGPUObject(buffer); - return Backend::getGPUObject(buffer)->_buffer; + GLBuffer* bo = GLBackend::syncGPUObject(buffer); + if (bo) { + return bo->_buffer; + } else { + return 0; + } } diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 161ce1dad6..81271851bb 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -44,7 +44,7 @@ public: GLBuffer(); ~GLBuffer(); }; - static void syncGPUObject(const Buffer& buffer); + static GLBuffer* syncGPUObject(const Buffer& buffer); static GLuint getBufferID(const Buffer& buffer); class GLTexture : public GPUObject { @@ -57,7 +57,7 @@ public: GLTexture(); ~GLTexture(); }; - static void syncGPUObject(const Texture& texture); + static GLTexture* syncGPUObject(const Texture& texture); static GLuint getTextureID(const TexturePointer& texture); class GLShader : public GPUObject { diff --git a/libraries/gpu/src/gpu/GLBackendShader.cpp b/libraries/gpu/src/gpu/GLBackendShader.cpp index e37643e2f2..4d84d33a5f 100755 --- a/libraries/gpu/src/gpu/GLBackendShader.cpp +++ b/libraries/gpu/src/gpu/GLBackendShader.cpp @@ -25,12 +25,12 @@ GLBackend::GLShader::~GLShader() { } } -bool compileShader(const Shader& shader, GLBackend::GLShader& object) { +GLBackend::GLShader* compileShader(const Shader& shader) { // 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; + return nullptr; } // Shader domain @@ -40,8 +40,8 @@ bool compileShader(const Shader& shader, GLBackend::GLShader& object) { // Create the shader object GLuint glshader = glCreateShader(shaderDomain); if (!glshader) { - qDebug() << "GLShader::compileShader - failed to create the gl shader & gl program object"; - return false; + qDebug() << "GLShader::compileShader - failed to create the gl shader object"; + return nullptr; } // Assign the source @@ -56,13 +56,11 @@ bool compileShader(const Shader& shader, GLBackend::GLShader& object) { glGetShaderiv(glshader, GL_COMPILE_STATUS, &compiled); // if compilation fails - if (!compiled) - { + 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.open("debugshader.glsl"); + if (filestream.is_open()) { filestream << shaderSource->source; filestream.close(); } @@ -72,30 +70,31 @@ bool compileShader(const Shader& shader, GLBackend::GLShader& object) { glGetShaderiv(glshader, GL_INFO_LOG_LENGTH, &infoLength); char* temp = new char[infoLength] ; - glGetShaderInfoLog( glshader, infoLength, NULL, temp); + 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.open("debugshader.glsl.info.txt"); + if (filestream.is_open()) { + filestream << std::string(temp); filestream.close(); } */ delete[] temp; - glDeleteShader( glshader); - return false; + glDeleteShader(glshader); + return nullptr; } + GLuint glprogram = 0; +#ifdef SEPARATE_PROGRAM // 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; + return nullptr; } glProgramParameteri(glprogram, GL_PROGRAM_SEPARABLE, GL_TRUE); @@ -105,53 +104,52 @@ bool compileShader(const Shader& shader, GLBackend::GLShader& object) { GLint linked = 0; glGetProgramiv(glprogram, GL_LINK_STATUS, &linked); - if (!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.open("debugshader.glsl"); + if (filestream.is_open()) { filestream << shaderSource->source; filestream.close(); } */ GLint infoLength = 0; - glGetProgramiv( glprogram, GL_INFO_LOG_LENGTH, &infoLength ); + glGetProgramiv(glprogram, GL_INFO_LOG_LENGTH, &infoLength); char* temp = new char[infoLength] ; - glGetProgramInfoLog( glprogram, infoLength, NULL, temp); + 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.open("debugshader.glsl.info.txt"); + if (filestream.is_open()) { + filestream << String(temp); filestream.close(); } */ delete[] temp; - glDeleteShader( glshader); - glDeleteProgram( glprogram); - return false; + glDeleteShader(glshader); + glDeleteProgram(glprogram); + return nullptr; } +#endif // So far so good, the shader is created successfully - object._shader = glshader; - object._program = glprogram; + GLBackend::GLShader* object = new GLBackend::GLShader(); + object->_shader = glshader; + object->_program = glprogram; - return true; + return object; } -bool compileProgram(const Shader& program, GLBackend::GLShader& object) { +GLBackend::GLShader* compileProgram(const Shader& program) { if(!program.isProgram()) { - return false; + return nullptr; } // Let's go through every shaders and make sure they are ready to go @@ -160,7 +158,7 @@ bool compileProgram(const Shader& program, GLBackend::GLShader& object) { GLuint so = GLBackend::getShaderID(subShader); if (!so) { qDebug() << "GLShader::compileProgram - One of the shaders of the program is not compiled?"; - return false; + return nullptr; } shaderObjects.push_back(so); } @@ -169,7 +167,7 @@ bool compileProgram(const Shader& program, GLBackend::GLShader& object) { GLuint glprogram = glCreateProgram(); if (!glprogram) { qDebug() << "GLShader::compileProgram - failed to create the gl program object"; - return false; + return nullptr; } // glProgramParameteri(glprogram, GL_PROGRAM_, GL_TRUE); @@ -184,47 +182,45 @@ bool compileProgram(const Shader& program, GLBackend::GLShader& object) { GLint linked = 0; glGetProgramiv(glprogram, GL_LINK_STATUS, &linked); - if (!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.open("debugshader.glsl"); + if (filestream.is_open()) { filestream << shaderSource->source; filestream.close(); } */ GLint infoLength = 0; - glGetProgramiv( glprogram, GL_INFO_LOG_LENGTH, &infoLength ); + glGetProgramiv(glprogram, GL_INFO_LOG_LENGTH, &infoLength); char* temp = new char[infoLength] ; - glGetProgramInfoLog( glprogram, infoLength, NULL, temp); + 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.open("debugshader.glsl.info.txt"); + if (filestream.is_open()) { + filestream << std::string(temp); filestream.close(); } */ delete[] temp; - glDeleteProgram( glprogram); - return false; + glDeleteProgram(glprogram); + return nullptr; } // So far so good, the program is created successfully - object._shader = 0; - object._program = glprogram; + GLBackend::GLShader* object = new GLBackend::GLShader(); + object->_shader = 0; + object->_program = glprogram; - return true; + return object; } GLBackend::GLShader* GLBackend::syncGPUObject(const Shader& shader) { @@ -234,20 +230,17 @@ GLBackend::GLShader* GLBackend::syncGPUObject(const Shader& shader) { 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); + GLShader* tempObject = compileProgram(shader); + if (tempObject) { + object = tempObject; Backend::setGPUObject(shader, object); } } else if (shader.isDomain()) { - GLShader tempObject; - if (compileShader(shader, tempObject)) { - object = new GLShader(tempObject); + GLShader* tempObject = compileShader(shader); + if (tempObject) { + object = tempObject; Backend::setGPUObject(shader, object); } } @@ -256,7 +249,6 @@ GLBackend::GLShader* GLBackend::syncGPUObject(const Shader& shader) { } - GLuint GLBackend::getShaderID(const ShaderPointer& shader) { if (!shader) { return 0; diff --git a/libraries/gpu/src/gpu/GLBackendTexture.cpp b/libraries/gpu/src/gpu/GLBackendTexture.cpp index 0b2dffd6f7..6875abbc33 100755 --- a/libraries/gpu/src/gpu/GLBackendTexture.cpp +++ b/libraries/gpu/src/gpu/GLBackendTexture.cpp @@ -223,7 +223,7 @@ public: }; -void GLBackend::syncGPUObject(const Texture& texture) { +GLBackend::GLTexture* GLBackend::syncGPUObject(const Texture& texture) { GLTexture* object = Backend::getGPUObject(texture); // If GPU object already created and in sync @@ -232,14 +232,14 @@ void GLBackend::syncGPUObject(const Texture& texture) { // If gpu object info is in sync with sysmem version if (object->_contentStamp >= texture.getDataStamp()) { // Then all good, GPU object is ready to be used - return; + return object; } else { // Need to update the content of the GPU object from the source sysmem of the texture needUpdate = true; } } else if (!texture.isDefined()) { // NO texture definition yet so let's avoid thinking - return; + return nullptr; } // need to have a gpu object? @@ -320,6 +320,8 @@ void GLBackend::syncGPUObject(const Texture& texture) { qDebug() << "GLBackend::syncGPUObject(const Texture&) case for Texture Type " << texture.getType() << " not supported"; } CHECK_GL_ERROR(); + + return object; } @@ -328,8 +330,7 @@ GLuint GLBackend::getTextureID(const TexturePointer& texture) { if (!texture) { return 0; } - GLBackend::syncGPUObject(*texture); - GLTexture* object = Backend::getGPUObject(*texture); + GLTexture* object = GLBackend::syncGPUObject(*texture); if (object) { return object->_texture; } else { diff --git a/libraries/model/src/model/Stage.cpp b/libraries/model/src/model/Stage.cpp index 10dea9ab3f..9a68779caf 100644 --- a/libraries/model/src/model/Stage.cpp +++ b/libraries/model/src/model/Stage.cpp @@ -15,6 +15,7 @@ #include "SkyFromAtmosphere_vert.h" #include "SkyFromAtmosphere_frag.h" +#include "gpu/GLBackend.h" using namespace model; @@ -215,5 +216,8 @@ void SunSkyStage::updateGraphicsObject() const { double originAlt = _earthSunModel.getAltitude(); _sunLight->setPosition(Vec3(0.0f, originAlt, 0.0f)); + GLuint program = gpu::GLBackend::getShaderID(_skyShader); + + } From c097c6aad2e4c19ef4ec586d5dde7c9fa7077b08 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 6 Mar 2015 10:41:53 -0800 Subject: [PATCH 3/8] Adding the self introspection of shaders --- libraries/gpu/src/gpu/Format.h | 28 +- libraries/gpu/src/gpu/GLBackend.h | 4 + libraries/gpu/src/gpu/GLBackendShader.cpp | 331 ++++++++++++++++++++++ libraries/gpu/src/gpu/Shader.cpp | 21 +- libraries/gpu/src/gpu/Shader.h | 72 +++-- libraries/model/src/model/Stage.cpp | 7 +- libraries/render-utils/src/Model.cpp | 9 + 7 files changed, 428 insertions(+), 44 deletions(-) diff --git a/libraries/gpu/src/gpu/Format.h b/libraries/gpu/src/gpu/Format.h index cbf90384ce..73c3c92c0a 100644 --- a/libraries/gpu/src/gpu/Format.h +++ b/libraries/gpu/src/gpu/Format.h @@ -53,6 +53,8 @@ enum Type { NUINT8, NUM_TYPES, + + BOOL = UINT8, }; // Array providing the size in bytes for a given scalar type static const int TYPE_SIZE[NUM_TYPES] = { @@ -81,9 +83,9 @@ enum Dimension { VEC2, VEC3, VEC4, + MAT2, MAT3, MAT4, - NUM_DIMENSIONS, }; // Count (of scalars) in an Element for a given Dimension @@ -92,8 +94,9 @@ static const int DIMENSION_COUNT[NUM_DIMENSIONS] = { 2, 3, 4, + 4, 9, - 16 + 16, }; // Semantic of an Element @@ -118,6 +121,27 @@ enum Semantic { SRGBA, SBGRA, + UNIFORM, + + TEXTURE, + BUFFER, + + SAMPLER_1D, + SAMPLER_2D, + SAMPLER_2D_MS, + SAMPLER_3D, + SAMPLER_CUBE, + SAMPLER_1D_ARRAY, + SAMPLER_2D_ARRAY, + SAMPLER_2D_MS_ARRAY, + SAMPLER_3D_ARRAY, + SAMPLER_CUBE_ARRAY, + SAMPLER_2D_SHADOW, + SAMPLER_2D_SHADOW_ARRAY, + SAMPLER_CUBE_SHADOW, + SAMPLER_CUBE_SHADOW_ARRAY, + + NUM_SEMANTICS, }; diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 81271851bb..535d7a3e1f 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -33,6 +33,7 @@ public: static void checkGLError(); + static bool makeShader(Shader& shader); class GLBuffer : public GPUObject { @@ -65,6 +66,9 @@ public: GLuint _shader; GLuint _program; + GLuint _transformCameraSlot = -1; + GLuint _transformObjectSlot = -1; + GLShader(); ~GLShader(); }; diff --git a/libraries/gpu/src/gpu/GLBackendShader.cpp b/libraries/gpu/src/gpu/GLBackendShader.cpp index 4d84d33a5f..724f1ad019 100755 --- a/libraries/gpu/src/gpu/GLBackendShader.cpp +++ b/libraries/gpu/src/gpu/GLBackendShader.cpp @@ -10,6 +10,9 @@ // #include "GLBackendShared.h" +#include "Format.h" + +using namespace gpu; GLBackend::GLShader::GLShader() : _shader(0), @@ -25,6 +28,78 @@ GLBackend::GLShader::~GLShader() { } } + +void makeBindings(GLBackend::GLShader* shader) { + if(!shader || !shader->_program) { + return; + } + GLuint glprogram = shader->_program; + GLint loc = -1; + + //Check for gpu specific attribute bindings + loc = glGetAttribLocation(glprogram, "position"); + if (loc >= 0) { + glBindAttribLocation(glprogram, gpu::Stream::POSITION, "position"); + } + + loc = glGetAttribLocation(glprogram, "normal"); + if (loc >= 0) { + glBindAttribLocation(glprogram, gpu::Stream::NORMAL, "normal"); + } + + loc = glGetAttribLocation(glprogram, "color"); + if (loc >= 0) { + glBindAttribLocation(glprogram, gpu::Stream::COLOR, "color"); + } + + loc = glGetAttribLocation(glprogram, "texcoord"); + if (loc >= 0) { + glBindAttribLocation(glprogram, gpu::Stream::TEXCOORD, "texcoord"); + } + + loc = glGetAttribLocation(glprogram, "tangent"); + if (loc >= 0) { + glBindAttribLocation(glprogram, gpu::Stream::TANGENT, "tangent"); + } + + loc = glGetAttribLocation(glprogram, "texcoord1"); + if (loc >= 0) { + glBindAttribLocation(glprogram, gpu::Stream::TEXCOORD1, "texcoord1"); + } + + loc = glGetAttribLocation(glprogram, "clusterIndices"); + if (loc >= 0) { + glBindAttribLocation(glprogram, gpu::Stream::SKIN_CLUSTER_INDEX, "clusterIndices"); + } + + loc = glGetAttribLocation(glprogram, "clusterWeights"); + if (loc >= 0) { + glBindAttribLocation(glprogram, gpu::Stream::SKIN_CLUSTER_WEIGHT, "clusterWeights"); + } + + //Check for gpu specific uniform bindings + loc = glGetUniformBlockIndex(glprogram, "transformObjectBuffer"); + if (loc >= 0) { + glUniformBlockBinding(glprogram, loc, gpu::TRANSFORM_OBJECT_SLOT); + shader->_transformObjectSlot = gpu::TRANSFORM_OBJECT_SLOT; + } + + loc = glGetUniformBlockIndex(glprogram, "transformCameraBuffer"); + if (loc >= 0) { + glUniformBlockBinding(glprogram, loc, gpu::TRANSFORM_CAMERA_SLOT); + shader->_transformCameraSlot = gpu::TRANSFORM_OBJECT_SLOT; + } + + // Link again + glLinkProgram(glprogram); + + GLint linked = 0; + glGetProgramiv(glprogram, GL_LINK_STATUS, &linked); + if (!linked) { + qDebug() << "GLShader::makeBindings - failed to link after assigning bindings?"; + } +} + GLBackend::GLShader* compileShader(const Shader& shader) { // Any GLSLprogram ? normally yes... const std::string& shaderSource = shader.getSource().getCode(); @@ -144,6 +219,8 @@ GLBackend::GLShader* compileShader(const Shader& shader) { object->_shader = glshader; object->_program = glprogram; + makeBindings(object); + return object; } @@ -220,6 +297,8 @@ GLBackend::GLShader* compileProgram(const Shader& program) { object->_shader = 0; object->_program = glprogram; + makeBindings(object); + return object; } @@ -265,3 +344,255 @@ GLuint GLBackend::getShaderID(const ShaderPointer& shader) { } } +Element getFormatFromGLUniform(GLenum gltype) { + switch (gltype) { + case GL_FLOAT: return Element(SCALAR, gpu::FLOAT, UNIFORM); + case GL_FLOAT_VEC2: return Element(VEC2, gpu::FLOAT, UNIFORM); + case GL_FLOAT_VEC3: return Element(VEC3, gpu::FLOAT, UNIFORM); + case GL_FLOAT_VEC4: return Element(VEC4, gpu::FLOAT, UNIFORM); + + case GL_DOUBLE: return Element(SCALAR, gpu::FLOAT, UNIFORM); + case GL_DOUBLE_VEC2: return Element(VEC2, gpu::FLOAT, UNIFORM); + case GL_DOUBLE_VEC3: return Element(VEC3, gpu::FLOAT, UNIFORM); + case GL_DOUBLE_VEC4: return Element(VEC4, gpu::FLOAT, UNIFORM); + + case GL_INT: return Element(SCALAR, gpu::INT32, UNIFORM); + case GL_INT_VEC2: return Element(VEC2, gpu::INT32, UNIFORM); + case GL_INT_VEC3: return Element(VEC3, gpu::INT32, UNIFORM); + case GL_INT_VEC4: return Element(VEC4, gpu::INT32, UNIFORM); + + case GL_UNSIGNED_INT: return Element(SCALAR, gpu::UINT32, UNIFORM); + case GL_UNSIGNED_INT_VEC2: return Element(VEC2, gpu::UINT32, UNIFORM); + case GL_UNSIGNED_INT_VEC3: return Element(VEC3, gpu::UINT32, UNIFORM); + case GL_UNSIGNED_INT_VEC4: return Element(VEC4, gpu::UINT32, UNIFORM); + + case GL_BOOL: return Element(SCALAR, gpu::BOOL, UNIFORM); + case GL_BOOL_VEC2: return Element(VEC2, gpu::BOOL, UNIFORM); + case GL_BOOL_VEC3: return Element(VEC3, gpu::BOOL, UNIFORM); + case GL_BOOL_VEC4: return Element(VEC4, gpu::BOOL, UNIFORM); + + + case GL_FLOAT_MAT2: return Element(gpu::MAT2, gpu::FLOAT, UNIFORM); + case GL_FLOAT_MAT3: return Element(MAT3, gpu::FLOAT, UNIFORM); + case GL_FLOAT_MAT4: return Element(MAT4, gpu::FLOAT, UNIFORM); + +/* {GL_FLOAT_MAT2x3 mat2x3}, + {GL_FLOAT_MAT2x4 mat2x4}, + {GL_FLOAT_MAT3x2 mat3x2}, + {GL_FLOAT_MAT3x4 mat3x4}, + {GL_FLOAT_MAT4x2 mat4x2}, + {GL_FLOAT_MAT4x3 mat4x3}, + {GL_DOUBLE_MAT2 dmat2}, + {GL_DOUBLE_MAT3 dmat3}, + {GL_DOUBLE_MAT4 dmat4}, + {GL_DOUBLE_MAT2x3 dmat2x3}, + {GL_DOUBLE_MAT2x4 dmat2x4}, + {GL_DOUBLE_MAT3x2 dmat3x2}, + {GL_DOUBLE_MAT3x4 dmat3x4}, + {GL_DOUBLE_MAT4x2 dmat4x2}, + {GL_DOUBLE_MAT4x3 dmat4x3}, + */ + + case GL_SAMPLER_1D: return Element(SCALAR, gpu::FLOAT, SAMPLER_1D); + case GL_SAMPLER_2D: return Element(SCALAR, gpu::FLOAT, SAMPLER_2D); + case GL_SAMPLER_2D_MULTISAMPLE: return Element(SCALAR, gpu::FLOAT, SAMPLER_2D_MS); + case GL_SAMPLER_3D: return Element(SCALAR, gpu::FLOAT, SAMPLER_3D); + case GL_SAMPLER_CUBE: return Element(SCALAR, gpu::FLOAT, SAMPLER_CUBE); + + case GL_SAMPLER_1D_ARRAY: return Element(SCALAR, gpu::FLOAT, SAMPLER_1D_ARRAY); + case GL_SAMPLER_2D_ARRAY: return Element(SCALAR, gpu::FLOAT, SAMPLER_2D_ARRAY); + case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: return Element(SCALAR, gpu::FLOAT, SAMPLER_2D_MS_ARRAY); + + case GL_SAMPLER_2D_SHADOW: return Element(SCALAR, gpu::FLOAT, SAMPLER_2D_SHADOW); + case GL_SAMPLER_CUBE_SHADOW: return Element(SCALAR, gpu::FLOAT, SAMPLER_CUBE_SHADOW); + + case GL_SAMPLER_2D_ARRAY_SHADOW: return Element(SCALAR, gpu::FLOAT, SAMPLER_2D_SHADOW_ARRAY); + +// {GL_SAMPLER_1D_SHADOW sampler1DShadow}, + // {GL_SAMPLER_1D_ARRAY_SHADOW sampler1DArrayShadow}, + +// {GL_SAMPLER_BUFFER samplerBuffer}, +// {GL_SAMPLER_2D_RECT sampler2DRect}, + // {GL_SAMPLER_2D_RECT_SHADOW sampler2DRectShadow}, + + case GL_INT_SAMPLER_1D: return Element(SCALAR, gpu::INT32, SAMPLER_1D); + case GL_INT_SAMPLER_2D: return Element(SCALAR, gpu::INT32, SAMPLER_2D); + case GL_INT_SAMPLER_2D_MULTISAMPLE: return Element(SCALAR, gpu::INT32, SAMPLER_2D_MS); + case GL_INT_SAMPLER_3D: return Element(SCALAR, gpu::INT32, SAMPLER_3D); + case GL_INT_SAMPLER_CUBE: return Element(SCALAR, gpu::INT32, SAMPLER_CUBE); + + case GL_INT_SAMPLER_1D_ARRAY: return Element(SCALAR, gpu::INT32, SAMPLER_1D_ARRAY); + case GL_INT_SAMPLER_2D_ARRAY: return Element(SCALAR, gpu::INT32, SAMPLER_2D_ARRAY); + case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: return Element(SCALAR, gpu::INT32, SAMPLER_2D_MS_ARRAY); + + // {GL_INT_SAMPLER_BUFFER isamplerBuffer}, + // {GL_INT_SAMPLER_2D_RECT isampler2DRect}, + + case GL_UNSIGNED_INT_SAMPLER_1D: return Element(SCALAR, gpu::UINT32, SAMPLER_1D); + case GL_UNSIGNED_INT_SAMPLER_2D: return Element(SCALAR, gpu::UINT32, SAMPLER_2D); + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: return Element(SCALAR, gpu::UINT32, SAMPLER_2D_MS); + case GL_UNSIGNED_INT_SAMPLER_3D: return Element(SCALAR, gpu::UINT32, SAMPLER_3D); + case GL_UNSIGNED_INT_SAMPLER_CUBE: return Element(SCALAR, gpu::UINT32, SAMPLER_CUBE); + + case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY: return Element(SCALAR, gpu::UINT32, SAMPLER_1D_ARRAY); + case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: return Element(SCALAR, gpu::UINT32, SAMPLER_2D_ARRAY); + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: return Element(SCALAR, gpu::UINT32, SAMPLER_2D_MS_ARRAY); + +// {GL_UNSIGNED_INT_SAMPLER_BUFFER usamplerBuffer}, +// {GL_UNSIGNED_INT_SAMPLER_2D_RECT usampler2DRect}, +/* + {GL_IMAGE_1D image1D}, + {GL_IMAGE_2D image2D}, + {GL_IMAGE_3D image3D}, + {GL_IMAGE_2D_RECT image2DRect}, + {GL_IMAGE_CUBE imageCube}, + {GL_IMAGE_BUFFER imageBuffer}, + {GL_IMAGE_1D_ARRAY image1DArray}, + {GL_IMAGE_2D_ARRAY image2DArray}, + {GL_IMAGE_2D_MULTISAMPLE image2DMS}, + {GL_IMAGE_2D_MULTISAMPLE_ARRAY image2DMSArray}, + {GL_INT_IMAGE_1D iimage1D}, + {GL_INT_IMAGE_2D iimage2D}, + {GL_INT_IMAGE_3D iimage3D}, + {GL_INT_IMAGE_2D_RECT iimage2DRect}, + {GL_INT_IMAGE_CUBE iimageCube}, + {GL_INT_IMAGE_BUFFER iimageBuffer}, + {GL_INT_IMAGE_1D_ARRAY iimage1DArray}, + {GL_INT_IMAGE_2D_ARRAY iimage2DArray}, + {GL_INT_IMAGE_2D_MULTISAMPLE iimage2DMS}, + {GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY iimage2DMSArray}, + {GL_UNSIGNED_INT_IMAGE_1D uimage1D}, + {GL_UNSIGNED_INT_IMAGE_2D uimage2D}, + {GL_UNSIGNED_INT_IMAGE_3D uimage3D}, + {GL_UNSIGNED_INT_IMAGE_2D_RECT uimage2DRect}, + {GL_UNSIGNED_INT_IMAGE_CUBE uimageCube},+ [0] {_name="fInnerRadius" _location=0 _element={_semantic=15 '\xf' _dimension=0 '\0' _type=0 '\0' } } gpu::Shader::Slot + + {GL_UNSIGNED_INT_IMAGE_BUFFER uimageBuffer}, + {GL_UNSIGNED_INT_IMAGE_1D_ARRAY uimage1DArray}, + {GL_UNSIGNED_INT_IMAGE_2D_ARRAY uimage2DArray}, + {GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE uimage2DMS}, + {GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY uimage2DMSArray}, + {GL_UNSIGNED_INT_ATOMIC_COUNTER atomic_uint} +*/ + default: + return Element(); + } + +}; + + +int makeUniformSlots(GLuint glprogram, Shader::SlotSet& uniforms, Shader::SlotSet& textures, Shader::SlotSet& samplers) { + GLint uniformsCount = 0; + + glGetProgramiv(glprogram, GL_ACTIVE_UNIFORMS, &uniformsCount); + + for (int i = 0; i < uniformsCount; i++) { + const GLint NAME_LENGTH = 256; + GLchar name[NAME_LENGTH]; + GLint length = 0; + GLint size = 0; + GLenum type = 0; + glGetActiveUniform(glprogram, i, NAME_LENGTH, &length, &size, &type, name); + + auto element = getFormatFromGLUniform(type); + uniforms.insert(Shader::Slot(name, i, element)); + } + + return uniformsCount; +} + +int makeUniformBlockSlots(GLuint glprogram, Shader::SlotSet& buffers) { + GLint buffersCount = 0; + + glGetProgramiv(glprogram, GL_ACTIVE_UNIFORM_BLOCKS, &buffersCount); + + for (int i = 0; i < buffersCount; i++) { + const GLint NAME_LENGTH = 256; + GLchar name[NAME_LENGTH]; + GLint length = 0; + GLint size = 0; + GLenum type = 0; + GLint binding = -1; + glGetActiveUniformBlockiv(glprogram, i, GL_UNIFORM_BLOCK_BINDING, &binding); + glGetActiveUniformBlockiv(glprogram, i, GL_UNIFORM_BLOCK_DATA_SIZE, &size); + glGetActiveUniformBlockiv(glprogram, i, GL_UNIFORM_BLOCK_NAME_LENGTH, &length); + glGetActiveUniformBlockName(glprogram, i, NAME_LENGTH, &length, name); + + Element element(SCALAR, gpu::FLOAT, BUFFER); + buffers.insert(Shader::Slot(name, binding, element)); + } + + return buffersCount; +} + +int makeInputSlots(GLuint glprogram, Shader::SlotSet& inputs) { + GLint inputsCount = 0; + + glGetProgramiv(glprogram, GL_ACTIVE_ATTRIBUTES, &inputsCount); + + for (int i = 0; i < inputsCount; i++) { + const GLint NAME_LENGTH = 256; + GLchar name[NAME_LENGTH]; + GLint length = 0; + GLint size = 0; + GLenum type = 0; + glGetActiveAttrib(glprogram, i, NAME_LENGTH, &length, &size, &type, name); + + auto element = getFormatFromGLUniform(type); + inputs.insert(Shader::Slot(name, i, element)); + } + + return inputsCount; +} + +int makeOutputSlots(GLuint glprogram, Shader::SlotSet& outputs) { + /* GLint outputsCount = 0; + + glGetProgramiv(glprogram, GL_ACTIVE_, &outputsCount); + + for (int i = 0; i < inputsCount; i++) { + const GLint NAME_LENGTH = 256; + GLchar name[NAME_LENGTH]; + GLint length = 0; + GLint size = 0; + GLenum type = 0; + glGetActiveAttrib(glprogram, i, NAME_LENGTH, &length, &size, &type, name); + + auto element = getFormatFromGLUniform(type); + outputs.insert(Shader::Slot(name, i, element)); + } + */ + return 0; //inputsCount; +} + +bool GLBackend::makeShader(Shader& shader) { + + // First make sure the SHader has been compiled + GLShader* object = GLBackend::syncGPUObject(shader); + if (!object) { + return false; + } + + if (object->_program) { + Shader::SlotSet uniforms; + Shader::SlotSet textures; + Shader::SlotSet samplers; + makeUniformSlots(object->_program, uniforms, textures, samplers); + + Shader::SlotSet buffers; + makeUniformBlockSlots(object->_program, buffers); + + Shader::SlotSet inputs; + makeInputSlots(object->_program, inputs); + + Shader::SlotSet outputs; + makeOutputSlots(object->_program, outputs); + + shader.defineSlots(uniforms, buffers, textures, samplers, inputs, outputs); + + } else if (object->_shader) { + + } + + return true; +} diff --git a/libraries/gpu/src/gpu/Shader.cpp b/libraries/gpu/src/gpu/Shader.cpp index 87365e245e..164778b0e2 100755 --- a/libraries/gpu/src/gpu/Shader.cpp +++ b/libraries/gpu/src/gpu/Shader.cpp @@ -33,18 +33,6 @@ Shader::Shader(Type type, Pointer& vertex, Pointer& pixel): Shader::~Shader() { } - -/* -Program::Program(): - _storage(), - _type(GRAPHICS) -{ -} - -Program::~Program() -{ -} -*/ Shader* Shader::createVertex(const Source& source) { Shader* shader = new Shader(VERTEX, source); @@ -65,3 +53,12 @@ Shader* Shader::createProgram(Pointer& vertexShader, Pointer& pixelShader) { } return nullptr; } + +void Shader::defineSlots(const SlotSet& uniforms, const SlotSet& buffers, const SlotSet& textures, const SlotSet& samplers, const SlotSet& inputs, const SlotSet& outputs) { + _uniforms = uniforms; + _buffers = buffers; + _textures = textures; + _samplers = samplers; + _inputs = inputs; + _outputs = outputs; +} diff --git a/libraries/gpu/src/gpu/Shader.h b/libraries/gpu/src/gpu/Shader.h index 57177639ae..3a374d91c8 100755 --- a/libraries/gpu/src/gpu/Shader.h +++ b/libraries/gpu/src/gpu/Shader.h @@ -13,6 +13,7 @@ #include "Resource.h" #include +#include namespace gpu { @@ -40,6 +41,24 @@ public: Language _lang = GLSL; }; + class Slot { + public: + + std::string _name; + uint16 _location; + Element _element; + + Slot(const std::string& name, uint16 location, const Element& element) : _name(name), _location(location), _element(element) {} + + + class Less { + public: + bool operator() (const Slot& x, const Slot& y) const { return x._name < y._name; } + }; + }; + typedef std::set SlotSet; + + enum Type { VERTEX = 0, PIXEL, @@ -65,6 +84,22 @@ public: const Shaders& getShaders() const { return _shaders; } + // Access the exposed uniform, input and output slot + const SlotSet& getUniforms() const { return _uniforms; } + const SlotSet& getBuffers() const { return _buffers; } + const SlotSet& getTextures() const { return _textures; } + const SlotSet& getSamplers() const { return _samplers; } + const SlotSet& getInputs() const { return _inputs; } + const SlotSet& getOutputs() const { return _outputs; } + + // Define the list of uniforms, inputs and outputs for the shader + // This call is intendend to build the list of exposed slots in order + // to correctly bind resource to the shader. + // These can be build "manually" from knowledge of the atual shader code + // or automatically by calling "Context::makeShader()", this is the preferred way + void defineSlots(const SlotSet& uniforms, const SlotSet& buffers, const SlotSet& textures, const SlotSet& samplers, const SlotSet& inputs, const SlotSet& outputs); + + protected: Shader(Type type, const Source& source); Shader(Type type, Pointer& vertex, Pointer& pixel); @@ -78,6 +113,14 @@ protected: // if shader is composed of sub shaders, here they are Shaders _shaders; + // List of exposed uniform, input and output slots + SlotSet _uniforms; + SlotSet _buffers; + SlotSet _textures; + SlotSet _samplers; + SlotSet _inputs; + SlotSet _outputs; + // The type of the shader, the master key Type _type; @@ -91,35 +134,6 @@ protected: 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; -*/ }; diff --git a/libraries/model/src/model/Stage.cpp b/libraries/model/src/model/Stage.cpp index 9a68779caf..1ebb2e6ece 100644 --- a/libraries/model/src/model/Stage.cpp +++ b/libraries/model/src/model/Stage.cpp @@ -216,8 +216,13 @@ void SunSkyStage::updateGraphicsObject() const { double originAlt = _earthSunModel.getAltitude(); _sunLight->setPosition(Vec3(0.0f, originAlt, 0.0f)); - GLuint program = gpu::GLBackend::getShaderID(_skyShader); + GLuint program = gpu::GLBackend::getShaderID(_skyShader); + static int firstTime = 0; + if (firstTime == 0) { + firstTime++; + gpu::GLBackend::makeShader(*_skyShader); + } } diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index c7e5b71b22..3fcf181812 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -299,6 +299,15 @@ void Model::init() { _program.addShaderFromSourceCode(QGLShader::Fragment, model_frag); initProgram(_program, _locations); + + auto defaultShader = gpu::ShaderPointer( + gpu::Shader::createProgram( + gpu::ShaderPointer(gpu::Shader::createVertex(std::string(model_vert))), + gpu::ShaderPointer(gpu::Shader::createPixel(std::string(model_frag))) + ) + ); + gpu::GLBackend::makeShader(*defaultShader); + _normalMapProgram.addShaderFromSourceCode(QGLShader::Vertex, model_normal_map_vert); _normalMapProgram.addShaderFromSourceCode(QGLShader::Fragment, model_normal_map_frag); initProgram(_normalMapProgram, _normalMapLocations); From 23a6326aa175e696e1b8f611dcd99e9e66a11499 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Sun, 8 Mar 2015 10:53:29 -0700 Subject: [PATCH 4/8] testing the shader features in Model and refining the shader making workflow --- libraries/gpu/src/gpu/Context.cpp | 11 + libraries/gpu/src/gpu/Context.h | 9 + libraries/gpu/src/gpu/Format.h | 22 +- libraries/gpu/src/gpu/GLBackend.h | 2 +- libraries/gpu/src/gpu/GLBackendShader.cpp | 244 ++++++++++++++-------- libraries/gpu/src/gpu/Resource.h | 12 ++ libraries/gpu/src/gpu/Shader.cpp | 9 + libraries/gpu/src/gpu/Shader.h | 43 +++- libraries/model/src/model/Stage.cpp | 3 +- libraries/render-utils/src/Model.cpp | 91 +++++++- libraries/render-utils/src/Model.h | 1 + 11 files changed, 326 insertions(+), 121 deletions(-) diff --git a/libraries/gpu/src/gpu/Context.cpp b/libraries/gpu/src/gpu/Context.cpp index 85227e0557..54387e8f71 100644 --- a/libraries/gpu/src/gpu/Context.cpp +++ b/libraries/gpu/src/gpu/Context.cpp @@ -10,3 +10,14 @@ // #include "Context.h" +// this include should disappear! as soon as the gpu::Context is in place +#include "GLBackend.h" + +using namespace gpu; + +bool Context::makeProgram(Shader& shader, const Shader::BindingSet& bindings) { + if (shader.isProgram()) { + return GLBackend::makeProgram(shader, bindings); + } + return false; +} \ No newline at end of file diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index 632c5f96de..ecff65fd8d 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -92,8 +92,17 @@ public: void enqueueBatch(Batch& batch); + + protected: + // This function can only be called by "static Shader::makeProgram()" + // makeProgramShader(...) make a program shader ready to be used in a Batch. + // It compiles the sub shaders, link them and defines the Slots and their bindings. + // If the shader passed is not a program, nothing happens. + static bool makeProgram(Shader& shader, const Shader::BindingSet& bindings = Shader::BindingSet()); + + friend class Shader; }; diff --git a/libraries/gpu/src/gpu/Format.h b/libraries/gpu/src/gpu/Format.h index 73c3c92c0a..8a754bb564 100644 --- a/libraries/gpu/src/gpu/Format.h +++ b/libraries/gpu/src/gpu/Format.h @@ -122,24 +122,10 @@ enum Semantic { SBGRA, UNIFORM, - - TEXTURE, - BUFFER, - - SAMPLER_1D, - SAMPLER_2D, - SAMPLER_2D_MS, - SAMPLER_3D, - SAMPLER_CUBE, - SAMPLER_1D_ARRAY, - SAMPLER_2D_ARRAY, - SAMPLER_2D_MS_ARRAY, - SAMPLER_3D_ARRAY, - SAMPLER_CUBE_ARRAY, - SAMPLER_2D_SHADOW, - SAMPLER_2D_SHADOW_ARRAY, - SAMPLER_CUBE_SHADOW, - SAMPLER_CUBE_SHADOW_ARRAY, + UNIFORM_BUFFER, + SAMPLER, + SAMPLER_MULTISAMPLE, + SAMPLER_SHADOW, NUM_SEMANTICS, diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 535d7a3e1f..974bb6fb8b 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -33,7 +33,7 @@ public: static void checkGLError(); - static bool makeShader(Shader& shader); + static bool makeProgram(Shader& shader, const Shader::BindingSet& bindings = Shader::BindingSet()); class GLBuffer : public GPUObject { diff --git a/libraries/gpu/src/gpu/GLBackendShader.cpp b/libraries/gpu/src/gpu/GLBackendShader.cpp index 724f1ad019..5136461f5c 100755 --- a/libraries/gpu/src/gpu/GLBackendShader.cpp +++ b/libraries/gpu/src/gpu/GLBackendShader.cpp @@ -28,7 +28,6 @@ GLBackend::GLShader::~GLShader() { } } - void makeBindings(GLBackend::GLShader* shader) { if(!shader || !shader->_program) { return; @@ -36,7 +35,7 @@ void makeBindings(GLBackend::GLShader* shader) { GLuint glprogram = shader->_program; GLint loc = -1; - //Check for gpu specific attribute bindings + //Check for gpu specific attribute slotBindings loc = glGetAttribLocation(glprogram, "position"); if (loc >= 0) { glBindAttribLocation(glprogram, gpu::Stream::POSITION, "position"); @@ -77,7 +76,18 @@ void makeBindings(GLBackend::GLShader* shader) { glBindAttribLocation(glprogram, gpu::Stream::SKIN_CLUSTER_WEIGHT, "clusterWeights"); } - //Check for gpu specific uniform bindings + // Link again to take into account the assigned attrib location + glLinkProgram(glprogram); + + GLint linked = 0; + glGetProgramiv(glprogram, GL_LINK_STATUS, &linked); + if (!linked) { + qDebug() << "GLShader::makeBindings - failed to link after assigning slotBindings?"; + } + + // now assign the ubo binding, then DON't relink! + + //Check for gpu specific uniform slotBindings loc = glGetUniformBlockIndex(glprogram, "transformObjectBuffer"); if (loc >= 0) { glUniformBlockBinding(glprogram, loc, gpu::TRANSFORM_OBJECT_SLOT); @@ -90,14 +100,6 @@ void makeBindings(GLBackend::GLShader* shader) { shader->_transformCameraSlot = gpu::TRANSFORM_OBJECT_SLOT; } - // Link again - glLinkProgram(glprogram); - - GLint linked = 0; - glGetProgramiv(glprogram, GL_LINK_STATUS, &linked); - if (!linked) { - qDebug() << "GLShader::makeBindings - failed to link after assigning bindings?"; - } } GLBackend::GLShader* compileShader(const Shader& shader) { @@ -344,37 +346,45 @@ GLuint GLBackend::getShaderID(const ShaderPointer& shader) { } } -Element getFormatFromGLUniform(GLenum gltype) { +class ElementResource { +public: + gpu::Element _element; + uint16 _resource; + + ElementResource(Element&& elem, uint16 resource) : _element(elem), _resource(resource) {} +}; + +ElementResource getFormatFromGLUniform(GLenum gltype) { switch (gltype) { - case GL_FLOAT: return Element(SCALAR, gpu::FLOAT, UNIFORM); - case GL_FLOAT_VEC2: return Element(VEC2, gpu::FLOAT, UNIFORM); - case GL_FLOAT_VEC3: return Element(VEC3, gpu::FLOAT, UNIFORM); - case GL_FLOAT_VEC4: return Element(VEC4, gpu::FLOAT, UNIFORM); + case GL_FLOAT: return ElementResource(Element(SCALAR, gpu::FLOAT, UNIFORM), Resource::BUFFER); + case GL_FLOAT_VEC2: return ElementResource(Element(VEC2, gpu::FLOAT, UNIFORM), Resource::BUFFER); + case GL_FLOAT_VEC3: return ElementResource(Element(VEC3, gpu::FLOAT, UNIFORM), Resource::BUFFER); + case GL_FLOAT_VEC4: return ElementResource(Element(VEC4, gpu::FLOAT, UNIFORM), Resource::BUFFER); - case GL_DOUBLE: return Element(SCALAR, gpu::FLOAT, UNIFORM); - case GL_DOUBLE_VEC2: return Element(VEC2, gpu::FLOAT, UNIFORM); - case GL_DOUBLE_VEC3: return Element(VEC3, gpu::FLOAT, UNIFORM); - case GL_DOUBLE_VEC4: return Element(VEC4, gpu::FLOAT, UNIFORM); + case GL_DOUBLE: return ElementResource(Element(SCALAR, gpu::FLOAT, UNIFORM), Resource::BUFFER); + case GL_DOUBLE_VEC2: return ElementResource(Element(VEC2, gpu::FLOAT, UNIFORM), Resource::BUFFER); + case GL_DOUBLE_VEC3: return ElementResource(Element(VEC3, gpu::FLOAT, UNIFORM), Resource::BUFFER); + case GL_DOUBLE_VEC4: return ElementResource(Element(VEC4, gpu::FLOAT, UNIFORM), Resource::BUFFER); - case GL_INT: return Element(SCALAR, gpu::INT32, UNIFORM); - case GL_INT_VEC2: return Element(VEC2, gpu::INT32, UNIFORM); - case GL_INT_VEC3: return Element(VEC3, gpu::INT32, UNIFORM); - case GL_INT_VEC4: return Element(VEC4, gpu::INT32, UNIFORM); + case GL_INT: return ElementResource(Element(SCALAR, gpu::INT32, UNIFORM), Resource::BUFFER); + case GL_INT_VEC2: return ElementResource(Element(VEC2, gpu::INT32, UNIFORM), Resource::BUFFER); + case GL_INT_VEC3: return ElementResource(Element(VEC3, gpu::INT32, UNIFORM), Resource::BUFFER); + case GL_INT_VEC4: return ElementResource(Element(VEC4, gpu::INT32, UNIFORM), Resource::BUFFER); - case GL_UNSIGNED_INT: return Element(SCALAR, gpu::UINT32, UNIFORM); - case GL_UNSIGNED_INT_VEC2: return Element(VEC2, gpu::UINT32, UNIFORM); - case GL_UNSIGNED_INT_VEC3: return Element(VEC3, gpu::UINT32, UNIFORM); - case GL_UNSIGNED_INT_VEC4: return Element(VEC4, gpu::UINT32, UNIFORM); + case GL_UNSIGNED_INT: return ElementResource(Element(SCALAR, gpu::UINT32, UNIFORM), Resource::BUFFER); + case GL_UNSIGNED_INT_VEC2: return ElementResource(Element(VEC2, gpu::UINT32, UNIFORM), Resource::BUFFER); + case GL_UNSIGNED_INT_VEC3: return ElementResource(Element(VEC3, gpu::UINT32, UNIFORM), Resource::BUFFER); + case GL_UNSIGNED_INT_VEC4: return ElementResource(Element(VEC4, gpu::UINT32, UNIFORM), Resource::BUFFER); - case GL_BOOL: return Element(SCALAR, gpu::BOOL, UNIFORM); - case GL_BOOL_VEC2: return Element(VEC2, gpu::BOOL, UNIFORM); - case GL_BOOL_VEC3: return Element(VEC3, gpu::BOOL, UNIFORM); - case GL_BOOL_VEC4: return Element(VEC4, gpu::BOOL, UNIFORM); + case GL_BOOL: return ElementResource(Element(SCALAR, gpu::BOOL, UNIFORM), Resource::BUFFER); + case GL_BOOL_VEC2: return ElementResource(Element(VEC2, gpu::BOOL, UNIFORM), Resource::BUFFER); + case GL_BOOL_VEC3: return ElementResource(Element(VEC3, gpu::BOOL, UNIFORM), Resource::BUFFER); + case GL_BOOL_VEC4: return ElementResource(Element(VEC4, gpu::BOOL, UNIFORM), Resource::BUFFER); - case GL_FLOAT_MAT2: return Element(gpu::MAT2, gpu::FLOAT, UNIFORM); - case GL_FLOAT_MAT3: return Element(MAT3, gpu::FLOAT, UNIFORM); - case GL_FLOAT_MAT4: return Element(MAT4, gpu::FLOAT, UNIFORM); + case GL_FLOAT_MAT2: return ElementResource(Element(gpu::MAT2, gpu::FLOAT, UNIFORM), Resource::BUFFER); + case GL_FLOAT_MAT3: return ElementResource(Element(MAT3, gpu::FLOAT, UNIFORM), Resource::BUFFER); + case GL_FLOAT_MAT4: return ElementResource(Element(MAT4, gpu::FLOAT, UNIFORM), Resource::BUFFER); /* {GL_FLOAT_MAT2x3 mat2x3}, {GL_FLOAT_MAT2x4 mat2x4}, @@ -393,20 +403,20 @@ Element getFormatFromGLUniform(GLenum gltype) { {GL_DOUBLE_MAT4x3 dmat4x3}, */ - case GL_SAMPLER_1D: return Element(SCALAR, gpu::FLOAT, SAMPLER_1D); - case GL_SAMPLER_2D: return Element(SCALAR, gpu::FLOAT, SAMPLER_2D); - case GL_SAMPLER_2D_MULTISAMPLE: return Element(SCALAR, gpu::FLOAT, SAMPLER_2D_MS); - case GL_SAMPLER_3D: return Element(SCALAR, gpu::FLOAT, SAMPLER_3D); - case GL_SAMPLER_CUBE: return Element(SCALAR, gpu::FLOAT, SAMPLER_CUBE); + case GL_SAMPLER_1D: return ElementResource(Element(SCALAR, gpu::FLOAT, SAMPLER), Resource::TEXTURE_1D); + case GL_SAMPLER_2D: return ElementResource(Element(SCALAR, gpu::FLOAT, SAMPLER), Resource::TEXTURE_2D); + case GL_SAMPLER_2D_MULTISAMPLE: return ElementResource(Element(SCALAR, gpu::FLOAT, SAMPLER_MULTISAMPLE), Resource::TEXTURE_2D); + case GL_SAMPLER_3D: return ElementResource(Element(SCALAR, gpu::FLOAT, SAMPLER), Resource::TEXTURE_3D); + case GL_SAMPLER_CUBE: return ElementResource(Element(SCALAR, gpu::FLOAT, SAMPLER), Resource::TEXTURE_CUBE); - case GL_SAMPLER_1D_ARRAY: return Element(SCALAR, gpu::FLOAT, SAMPLER_1D_ARRAY); - case GL_SAMPLER_2D_ARRAY: return Element(SCALAR, gpu::FLOAT, SAMPLER_2D_ARRAY); - case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: return Element(SCALAR, gpu::FLOAT, SAMPLER_2D_MS_ARRAY); + case GL_SAMPLER_1D_ARRAY: return ElementResource(Element(SCALAR, gpu::FLOAT, SAMPLER), Resource::TEXTURE_1D_ARRAY); + case GL_SAMPLER_2D_ARRAY: return ElementResource(Element(SCALAR, gpu::FLOAT, SAMPLER), Resource::TEXTURE_2D_ARRAY); + case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: return ElementResource(Element(SCALAR, gpu::FLOAT, SAMPLER_MULTISAMPLE), Resource::TEXTURE_2D_ARRAY); - case GL_SAMPLER_2D_SHADOW: return Element(SCALAR, gpu::FLOAT, SAMPLER_2D_SHADOW); - case GL_SAMPLER_CUBE_SHADOW: return Element(SCALAR, gpu::FLOAT, SAMPLER_CUBE_SHADOW); + case GL_SAMPLER_2D_SHADOW: return ElementResource(Element(SCALAR, gpu::FLOAT, SAMPLER_SHADOW), Resource::TEXTURE_2D); + case GL_SAMPLER_CUBE_SHADOW: return ElementResource(Element(SCALAR, gpu::FLOAT, SAMPLER_SHADOW), Resource::TEXTURE_CUBE); - case GL_SAMPLER_2D_ARRAY_SHADOW: return Element(SCALAR, gpu::FLOAT, SAMPLER_2D_SHADOW_ARRAY); + case GL_SAMPLER_2D_ARRAY_SHADOW: return ElementResource(Element(SCALAR, gpu::FLOAT, SAMPLER_SHADOW), Resource::TEXTURE_2D_ARRAY); // {GL_SAMPLER_1D_SHADOW sampler1DShadow}, // {GL_SAMPLER_1D_ARRAY_SHADOW sampler1DArrayShadow}, @@ -415,28 +425,28 @@ Element getFormatFromGLUniform(GLenum gltype) { // {GL_SAMPLER_2D_RECT sampler2DRect}, // {GL_SAMPLER_2D_RECT_SHADOW sampler2DRectShadow}, - case GL_INT_SAMPLER_1D: return Element(SCALAR, gpu::INT32, SAMPLER_1D); - case GL_INT_SAMPLER_2D: return Element(SCALAR, gpu::INT32, SAMPLER_2D); - case GL_INT_SAMPLER_2D_MULTISAMPLE: return Element(SCALAR, gpu::INT32, SAMPLER_2D_MS); - case GL_INT_SAMPLER_3D: return Element(SCALAR, gpu::INT32, SAMPLER_3D); - case GL_INT_SAMPLER_CUBE: return Element(SCALAR, gpu::INT32, SAMPLER_CUBE); + case GL_INT_SAMPLER_1D: return ElementResource(Element(SCALAR, gpu::INT32, SAMPLER), Resource::TEXTURE_1D); + case GL_INT_SAMPLER_2D: return ElementResource(Element(SCALAR, gpu::INT32, SAMPLER), Resource::TEXTURE_2D); + case GL_INT_SAMPLER_2D_MULTISAMPLE: return ElementResource(Element(SCALAR, gpu::INT32, SAMPLER_MULTISAMPLE), Resource::TEXTURE_2D); + case GL_INT_SAMPLER_3D: return ElementResource(Element(SCALAR, gpu::INT32, SAMPLER), Resource::TEXTURE_3D); + case GL_INT_SAMPLER_CUBE: return ElementResource(Element(SCALAR, gpu::INT32, SAMPLER), Resource::TEXTURE_CUBE); - case GL_INT_SAMPLER_1D_ARRAY: return Element(SCALAR, gpu::INT32, SAMPLER_1D_ARRAY); - case GL_INT_SAMPLER_2D_ARRAY: return Element(SCALAR, gpu::INT32, SAMPLER_2D_ARRAY); - case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: return Element(SCALAR, gpu::INT32, SAMPLER_2D_MS_ARRAY); + case GL_INT_SAMPLER_1D_ARRAY: return ElementResource(Element(SCALAR, gpu::INT32, SAMPLER), Resource::TEXTURE_1D_ARRAY); + case GL_INT_SAMPLER_2D_ARRAY: return ElementResource(Element(SCALAR, gpu::INT32, SAMPLER), Resource::TEXTURE_2D_ARRAY); + case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: return ElementResource(Element(SCALAR, gpu::INT32, SAMPLER_MULTISAMPLE), Resource::TEXTURE_2D_ARRAY); // {GL_INT_SAMPLER_BUFFER isamplerBuffer}, // {GL_INT_SAMPLER_2D_RECT isampler2DRect}, - case GL_UNSIGNED_INT_SAMPLER_1D: return Element(SCALAR, gpu::UINT32, SAMPLER_1D); - case GL_UNSIGNED_INT_SAMPLER_2D: return Element(SCALAR, gpu::UINT32, SAMPLER_2D); - case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: return Element(SCALAR, gpu::UINT32, SAMPLER_2D_MS); - case GL_UNSIGNED_INT_SAMPLER_3D: return Element(SCALAR, gpu::UINT32, SAMPLER_3D); - case GL_UNSIGNED_INT_SAMPLER_CUBE: return Element(SCALAR, gpu::UINT32, SAMPLER_CUBE); + case GL_UNSIGNED_INT_SAMPLER_1D: return ElementResource(Element(SCALAR, gpu::UINT32, SAMPLER), Resource::TEXTURE_1D); + case GL_UNSIGNED_INT_SAMPLER_2D: return ElementResource(Element(SCALAR, gpu::UINT32, SAMPLER), Resource::TEXTURE_2D); + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: return ElementResource(Element(SCALAR, gpu::UINT32, SAMPLER_MULTISAMPLE), Resource::TEXTURE_2D); + case GL_UNSIGNED_INT_SAMPLER_3D: return ElementResource(Element(SCALAR, gpu::UINT32, SAMPLER), Resource::TEXTURE_3D); + case GL_UNSIGNED_INT_SAMPLER_CUBE: return ElementResource(Element(SCALAR, gpu::UINT32, SAMPLER), Resource::TEXTURE_CUBE); - case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY: return Element(SCALAR, gpu::UINT32, SAMPLER_1D_ARRAY); - case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: return Element(SCALAR, gpu::UINT32, SAMPLER_2D_ARRAY); - case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: return Element(SCALAR, gpu::UINT32, SAMPLER_2D_MS_ARRAY); + case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY: return ElementResource(Element(SCALAR, gpu::UINT32, SAMPLER), Resource::TEXTURE_1D_ARRAY); + case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: return ElementResource(Element(SCALAR, gpu::UINT32, SAMPLER), Resource::TEXTURE_2D_ARRAY); + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: return ElementResource(Element(SCALAR, gpu::UINT32, SAMPLER_MULTISAMPLE), Resource::TEXTURE_2D_ARRAY); // {GL_UNSIGNED_INT_SAMPLER_BUFFER usamplerBuffer}, // {GL_UNSIGNED_INT_SAMPLER_2D_RECT usampler2DRect}, @@ -475,13 +485,13 @@ Element getFormatFromGLUniform(GLenum gltype) { {GL_UNSIGNED_INT_ATOMIC_COUNTER atomic_uint} */ default: - return Element(); + return ElementResource(Element(), Resource::BUFFER); } }; -int makeUniformSlots(GLuint glprogram, Shader::SlotSet& uniforms, Shader::SlotSet& textures, Shader::SlotSet& samplers) { +int makeUniformSlots(GLuint glprogram, const Shader::BindingSet& slotBindings, Shader::SlotSet& uniforms, Shader::SlotSet& textures, Shader::SlotSet& samplers) { GLint uniformsCount = 0; glGetProgramiv(glprogram, GL_ACTIVE_UNIFORMS, &uniformsCount); @@ -493,19 +503,56 @@ int makeUniformSlots(GLuint glprogram, Shader::SlotSet& uniforms, Shader::SlotSe GLint size = 0; GLenum type = 0; glGetActiveUniform(glprogram, i, NAME_LENGTH, &length, &size, &type, name); + GLint location = glGetUniformLocation(glprogram, name); + const GLint INVALID_UNIFORM_LOCATION = -1; - auto element = getFormatFromGLUniform(type); - uniforms.insert(Shader::Slot(name, i, element)); + // Try to make sense of the gltype + auto elementResource = getFormatFromGLUniform(type); + + // The uniform as a standard var type + if (location != INVALID_UNIFORM_LOCATION) { + if (elementResource._resource == Resource::BUFFER) { + uniforms.insert(Shader::Slot(name, location, elementResource._element, elementResource._resource)); + } else { + // For texture/Sampler, the location is the actual binding value + GLint binding = -1; + glGetUniformiv(glprogram, location, &binding); + + auto requestedBinding = slotBindings.find(std::string(name)); + if (requestedBinding != slotBindings.end()) { + if (binding != (*requestedBinding)._location) { + binding = (*requestedBinding)._location; + glUniform1i(location, binding); + } + } + + textures.insert(Shader::Slot(name, binding, elementResource._element, elementResource._resource)); + samplers.insert(Shader::Slot(name, binding, elementResource._element, elementResource._resource)); + } + } } return uniformsCount; } -int makeUniformBlockSlots(GLuint glprogram, Shader::SlotSet& buffers) { - GLint buffersCount = 0; +const GLint UNUSED_SLOT = -1; +bool isUnusedSlot(GLint binding) { + return (binding == UNUSED_SLOT); +} +int makeUniformBlockSlots(GLuint glprogram, const Shader::BindingSet& slotBindings, Shader::SlotSet& buffers) { + GLint buffersCount = 0; glGetProgramiv(glprogram, GL_ACTIVE_UNIFORM_BLOCKS, &buffersCount); + // fast exit + if (buffersCount == 0) { + return 0; + } + + GLint maxNumUniformBufferSlots = 0; + glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &maxNumUniformBufferSlots); + std::vector uniformBufferSlotMap(maxNumUniformBufferSlots, -1); + for (int i = 0; i < buffersCount; i++) { const GLint NAME_LENGTH = 256; GLchar name[NAME_LENGTH]; @@ -513,19 +560,46 @@ int makeUniformBlockSlots(GLuint glprogram, Shader::SlotSet& buffers) { GLint size = 0; GLenum type = 0; GLint binding = -1; - glGetActiveUniformBlockiv(glprogram, i, GL_UNIFORM_BLOCK_BINDING, &binding); - glGetActiveUniformBlockiv(glprogram, i, GL_UNIFORM_BLOCK_DATA_SIZE, &size); + glGetActiveUniformBlockiv(glprogram, i, GL_UNIFORM_BLOCK_NAME_LENGTH, &length); glGetActiveUniformBlockName(glprogram, i, NAME_LENGTH, &length, name); + glGetActiveUniformBlockiv(glprogram, i, GL_UNIFORM_BLOCK_BINDING, &binding); + glGetActiveUniformBlockiv(glprogram, i, GL_UNIFORM_BLOCK_DATA_SIZE, &size); + + GLuint blockIndex = glGetUniformBlockIndex(glprogram, name); - Element element(SCALAR, gpu::FLOAT, BUFFER); - buffers.insert(Shader::Slot(name, binding, element)); + // CHeck if there is a requested binding for this block + auto requestedBinding = slotBindings.find(std::string(name)); + if (requestedBinding != slotBindings.end()) { + // If yes force it + if (binding != (*requestedBinding)._location) { + binding = (*requestedBinding)._location; + glUniformBlockBinding(glprogram, blockIndex, binding); + } + } else if (binding == 0) { + // If no binding was assigned then just do it finding a free slot + auto slotIt = std::find_if(uniformBufferSlotMap.begin(), uniformBufferSlotMap.end(), isUnusedSlot); + if (slotIt != uniformBufferSlotMap.end()) { + binding = slotIt - uniformBufferSlotMap.begin(); + glUniformBlockBinding(glprogram, blockIndex, binding); + } else { + // This should neve happen, an active ubo cannot find an available slot among the max available?! + binding = -1; + } + } + // If binding is valid record it + if (binding >= 0) { + uniformBufferSlotMap[binding] = blockIndex; + } + + Element element(SCALAR, gpu::UINT32, gpu::UNIFORM_BUFFER); + buffers.insert(Shader::Slot(name, binding, element, Resource::BUFFER)); } return buffersCount; } -int makeInputSlots(GLuint glprogram, Shader::SlotSet& inputs) { +int makeInputSlots(GLuint glprogram, const Shader::BindingSet& slotBindings, Shader::SlotSet& inputs) { GLint inputsCount = 0; glGetProgramiv(glprogram, GL_ACTIVE_ATTRIBUTES, &inputsCount); @@ -538,14 +612,16 @@ int makeInputSlots(GLuint glprogram, Shader::SlotSet& inputs) { GLenum type = 0; glGetActiveAttrib(glprogram, i, NAME_LENGTH, &length, &size, &type, name); - auto element = getFormatFromGLUniform(type); - inputs.insert(Shader::Slot(name, i, element)); + GLint binding = glGetAttribLocation(glprogram, name); + + auto elementResource = getFormatFromGLUniform(type); + inputs.insert(Shader::Slot(name, binding, elementResource._element, -1)); } return inputsCount; } -int makeOutputSlots(GLuint glprogram, Shader::SlotSet& outputs) { +int makeOutputSlots(GLuint glprogram, const Shader::BindingSet& slotBindings, Shader::SlotSet& outputs) { /* GLint outputsCount = 0; glGetProgramiv(glprogram, GL_ACTIVE_, &outputsCount); @@ -565,28 +641,28 @@ int makeOutputSlots(GLuint glprogram, Shader::SlotSet& outputs) { return 0; //inputsCount; } -bool GLBackend::makeShader(Shader& shader) { +bool GLBackend::makeProgram(Shader& shader, const Shader::BindingSet& slotBindings) { - // First make sure the SHader has been compiled + // First make sure the Shader has been compiled GLShader* object = GLBackend::syncGPUObject(shader); if (!object) { return false; } if (object->_program) { + Shader::SlotSet buffers; + makeUniformBlockSlots(object->_program, slotBindings, buffers); + Shader::SlotSet uniforms; Shader::SlotSet textures; Shader::SlotSet samplers; - makeUniformSlots(object->_program, uniforms, textures, samplers); - - Shader::SlotSet buffers; - makeUniformBlockSlots(object->_program, buffers); + makeUniformSlots(object->_program, slotBindings, uniforms, textures, samplers); Shader::SlotSet inputs; - makeInputSlots(object->_program, inputs); + makeInputSlots(object->_program, slotBindings, inputs); Shader::SlotSet outputs; - makeOutputSlots(object->_program, outputs); + makeOutputSlots(object->_program, slotBindings, outputs); shader.defineSlots(uniforms, buffers, textures, samplers, inputs, outputs); diff --git a/libraries/gpu/src/gpu/Resource.h b/libraries/gpu/src/gpu/Resource.h index 225e3fd927..3da25ae78f 100644 --- a/libraries/gpu/src/gpu/Resource.h +++ b/libraries/gpu/src/gpu/Resource.h @@ -38,6 +38,18 @@ public: // The size in bytes of data stored in the resource virtual Size getSize() const = 0; + enum Type { + BUFFER = 0, + TEXTURE_1D, + TEXTURE_2D, + TEXTURE_3D, + TEXTURE_CUBE, + TEXTURE_1D_ARRAY, + TEXTURE_2D_ARRAY, + TEXTURE_3D_ARRAY, + TEXTURE_CUBE_ARRAY, + }; + protected: Resource() {} diff --git a/libraries/gpu/src/gpu/Shader.cpp b/libraries/gpu/src/gpu/Shader.cpp index 164778b0e2..59838fae9c 100755 --- a/libraries/gpu/src/gpu/Shader.cpp +++ b/libraries/gpu/src/gpu/Shader.cpp @@ -13,6 +13,8 @@ #include #include +#include "Context.h" + using namespace gpu; Shader::Shader(Type type, const Source& source): @@ -62,3 +64,10 @@ void Shader::defineSlots(const SlotSet& uniforms, const SlotSet& buffers, const _inputs = inputs; _outputs = outputs; } + +bool Shader::makeProgram(Shader& shader, const Shader::BindingSet& bindings) { + if (shader.isProgram()) { + return Context::makeProgram(shader, bindings); + } + return false; +} diff --git a/libraries/gpu/src/gpu/Shader.h b/libraries/gpu/src/gpu/Shader.h index 3a374d91c8..9a5bec313b 100755 --- a/libraries/gpu/src/gpu/Shader.h +++ b/libraries/gpu/src/gpu/Shader.h @@ -45,18 +45,28 @@ public: public: std::string _name; - uint16 _location; + uint32 _location; Element _element; + uint16 _resourceType; - Slot(const std::string& name, uint16 location, const Element& element) : _name(name), _location(location), _element(element) {} + Slot(const std::string& name, uint16 location, const Element& element, uint16 resourceType = Resource::BUFFER) : + _name(name), _location(location), _element(element), _resourceType(resourceType) {} - - class Less { - public: - bool operator() (const Slot& x, const Slot& y) const { return x._name < y._name; } - }; }; - typedef std::set SlotSet; + + class Binding { + public: + std::string _name; + uint32 _location; + Binding(const std::string&& name, uint32 loc = 0) : _name(name), _location(loc) {} + }; + + template class Less { + public: + bool operator() (const T& x, const T& y) const { return x._name < y._name; } + }; + typedef std::set> SlotSet; + typedef std::set> BindingSet; enum Type { @@ -89,6 +99,7 @@ public: const SlotSet& getBuffers() const { return _buffers; } const SlotSet& getTextures() const { return _textures; } const SlotSet& getSamplers() const { return _samplers; } + const SlotSet& getInputs() const { return _inputs; } const SlotSet& getOutputs() const { return _outputs; } @@ -96,9 +107,23 @@ public: // This call is intendend to build the list of exposed slots in order // to correctly bind resource to the shader. // These can be build "manually" from knowledge of the atual shader code - // or automatically by calling "Context::makeShader()", this is the preferred way + // or automatically by calling "makeShader()", this is the preferred way void defineSlots(const SlotSet& uniforms, const SlotSet& buffers, const SlotSet& textures, const SlotSet& samplers, const SlotSet& inputs, const SlotSet& outputs); + // makeProgram(...) make a program shader ready to be used in a Batch. + // It compiles the sub shaders, link them and defines the Slots and their bindings. + // If the shader passed is not a program, nothing happens. + // + // It is possible to provide a set of slot bindings (from the name of the slot to a unit number) allowing + // to make sure slots with the same semantics can be always bound on the same location from shader to shader. + // For example, the "diffuseMap" can always be bound to texture unit #1 for different shaders by specifying a Binding("diffuseMap", 1) + // + // As of now (03/2015), the call to makeProgram is in fact calling gpu::Context::makeProgram and does rely + // on the underneath gpu::Context::Backend available. Since we only support glsl, this means that it relies + // on a glContext and the driver to compile the glsl shader. + // Hoppefully in a few years the shader compilation will be completely abstracted in a separate shader compiler library + // independant of the graphics api in use underneath (looking at you opengl & vulkan). + static bool makeProgram(Shader& shader, const Shader::BindingSet& bindings = Shader::BindingSet()); protected: Shader(Type type, const Source& source); diff --git a/libraries/model/src/model/Stage.cpp b/libraries/model/src/model/Stage.cpp index 1ebb2e6ece..d470d841bc 100644 --- a/libraries/model/src/model/Stage.cpp +++ b/libraries/model/src/model/Stage.cpp @@ -15,6 +15,7 @@ #include "SkyFromAtmosphere_vert.h" #include "SkyFromAtmosphere_frag.h" +#include "gpu/Context.h" #include "gpu/GLBackend.h" using namespace model; @@ -221,7 +222,7 @@ void SunSkyStage::updateGraphicsObject() const { static int firstTime = 0; if (firstTime == 0) { firstTime++; - gpu::GLBackend::makeShader(*_skyShader); + gpu::Shader::makeProgram(*_skyShader); } } diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 50ae3fd882..8f8f19c72a 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -299,18 +299,93 @@ void Model::initJointTransforms() { void Model::init() { if (!_program.isLinked()) { +/* + gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding(std::string("materialBuffer"), 1)); + slotBindings.insert(gpu::Shader::Binding(std::string("diffuseMap"), 0)); + slotBindings.insert(gpu::Shader::Binding(std::string("normalMap"), 1)); + slotBindings.insert(gpu::Shader::Binding(std::string("specularMap"), 2)); + slotBindings.insert(gpu::Shader::Binding(std::string("emissiveMap"), 3)); + + // Vertex shaders + auto modelVertex = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(model_vert))); + auto modelNormalMapVertex = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(model_normal_map_vert))); + auto modelLightmapVertex = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(model_lightmap_vert))); + auto modelLightmapNormalMapVertex = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(model_lightmap_normal_map_vert))); + auto modelShadowVertex = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(model_shadow_vert))); + auto skinModelVertex = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(skin_model_vert))); + auto skinModelNormalMapVertex = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(skin_model_normal_map_vert))); + auto skinModelShadowVertex = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(skin_model_shadow_vert))); + + // Pixel shaders + auto modelPixel = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(model_frag))); + auto modelNormalMapPixel = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(model_normal_map_frag))); + auto modelSpecularMapPixel = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(model_specular_map_frag))); + auto modelNormalSpecularMapPixel = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(model_normal_specular_map_frag))); + auto modelTranslucentPixel = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(model_translucent_frag))); + auto modelShadowPixel = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(model_shadow_frag))); + auto modelLightmapPixel = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(model_lightmap_frag))); + auto modelLightmapNormalMapPixel = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(model_lightmap_normal_map_frag))); + auto modelLightmapSpecularMapPixel = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(model_lightmap_specular_map_frag))); + auto modelLightmapNormalSpecularMapPixel = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(model_lightmap_normal_specular_map_frag))); + + + bool makeResult = false; + + // Programs + auto program = gpu::ShaderPointer(gpu::Shader::createProgram(modelVertex, modelPixel)); + makeResult = gpu::Shader::makeProgram(*program, slotBindings); + + auto normalMapProgram = gpu::ShaderPointer(gpu::Shader::createProgram(modelNormalMapVertex, modelNormalMapPixel)); + makeResult = gpu::Shader::makeProgram(*normalMapProgram, slotBindings); + + auto specularMapProgram = gpu::ShaderPointer(gpu::Shader::createProgram(modelVertex, modelSpecularMapPixel)); + makeResult = gpu::Shader::makeProgram(*specularMapProgram, slotBindings); + + auto normalSpecularMapProgram = gpu::ShaderPointer(gpu::Shader::createProgram(modelNormalMapVertex, modelNormalSpecularMapPixel)); + makeResult = gpu::Shader::makeProgram(*normalSpecularMapProgram, slotBindings); + + auto translucentProgram = gpu::ShaderPointer(gpu::Shader::createProgram(modelVertex, modelTranslucentPixel)); + makeResult = gpu::Shader::makeProgram(*translucentProgram, slotBindings); + + auto shadowProgram = gpu::ShaderPointer(gpu::Shader::createProgram(modelShadowVertex, modelShadowPixel)); + makeResult = gpu::Shader::makeProgram(*shadowProgram, slotBindings); + + auto lightmapProgram = gpu::ShaderPointer(gpu::Shader::createProgram(modelLightmapVertex, modelLightmapPixel)); + makeResult = gpu::Shader::makeProgram(*lightmapProgram, slotBindings); + + auto lightmapNormalMapProgram = gpu::ShaderPointer(gpu::Shader::createProgram(modelLightmapNormalMapVertex, modelLightmapNormalMapPixel)); + makeResult = gpu::Shader::makeProgram(*lightmapNormalMapProgram, slotBindings); + + auto lightmapSpecularMapProgram = gpu::ShaderPointer(gpu::Shader::createProgram(modelLightmapVertex, modelLightmapSpecularMapPixel)); + makeResult = gpu::Shader::makeProgram(*lightmapSpecularMapProgram, slotBindings); + + auto lightmapNormalSpecularMapProgram = gpu::ShaderPointer(gpu::Shader::createProgram(modelLightmapNormalMapVertex, modelLightmapNormalSpecularMapPixel)); + makeResult = gpu::Shader::makeProgram(*lightmapNormalSpecularMapProgram, slotBindings); + + auto skinProgram = gpu::ShaderPointer(gpu::Shader::createProgram(skinModelVertex, modelPixel)); + makeResult = gpu::Shader::makeProgram(*skinProgram, slotBindings); + + auto skinNormalMapProgram = gpu::ShaderPointer(gpu::Shader::createProgram(skinModelNormalMapVertex, modelNormalMapPixel)); + makeResult = gpu::Shader::makeProgram(*skinNormalMapProgram, slotBindings); + + auto skinSpecularMapProgram = gpu::ShaderPointer(gpu::Shader::createProgram(skinModelVertex, modelSpecularMapPixel)); + makeResult = gpu::Shader::makeProgram(*skinSpecularMapProgram, slotBindings); + + auto skinNormalSpecularMapProgram = gpu::ShaderPointer(gpu::Shader::createProgram(skinModelNormalMapVertex, modelNormalSpecularMapPixel)); + makeResult = gpu::Shader::makeProgram(*skinNormalSpecularMapProgram, slotBindings); + + auto skinShadowProgram = gpu::ShaderPointer(gpu::Shader::createProgram(skinModelShadowVertex, modelShadowPixel)); + makeResult = gpu::Shader::makeProgram(*skinShadowProgram, slotBindings); + + auto skinTranslucentProgram = gpu::ShaderPointer(gpu::Shader::createProgram(skinModelVertex, modelTranslucentPixel)); + makeResult = gpu::Shader::makeProgram(*skinTranslucentProgram, slotBindings); +*/ + _program.addShaderFromSourceCode(QGLShader::Vertex, model_vert); _program.addShaderFromSourceCode(QGLShader::Fragment, model_frag); initProgram(_program, _locations); - - auto defaultShader = gpu::ShaderPointer( - gpu::Shader::createProgram( - gpu::ShaderPointer(gpu::Shader::createVertex(std::string(model_vert))), - gpu::ShaderPointer(gpu::Shader::createPixel(std::string(model_frag))) - ) - ); - gpu::GLBackend::makeShader(*defaultShader); _normalMapProgram.addShaderFromSourceCode(QGLShader::Vertex, model_normal_map_vert); _normalMapProgram.addShaderFromSourceCode(QGLShader::Fragment, model_normal_map_frag); diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 303fa770ad..453d721962 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -309,6 +309,7 @@ private: int _blendNumber; int _appliedBlendNumber; + static ProgramObject _program; static ProgramObject _normalMapProgram; static ProgramObject _specularMapProgram; From cc85f468d6268cff98cd2741670bde7696b82f1e Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 9 Mar 2015 11:14:42 -0700 Subject: [PATCH 5/8] splitting the code of GLBackend into separate .cpp, adding the PIpeline,adn the state to gpu --- libraries/gpu/src/gpu/Batch.cpp | 10 +- libraries/gpu/src/gpu/Batch.h | 9 +- libraries/gpu/src/gpu/Context.h | 20 +- libraries/gpu/src/gpu/GLBackend.cpp | 447 +------------------ libraries/gpu/src/gpu/GLBackend.h | 28 +- libraries/gpu/src/gpu/GLBackendBuffer.cpp | 66 +++ libraries/gpu/src/gpu/GLBackendInput.cpp | 223 +++++++++ libraries/gpu/src/gpu/GLBackendPipeline.cpp | 95 ++++ libraries/gpu/src/gpu/GLBackendShader.cpp | 1 + libraries/gpu/src/gpu/GLBackendTransform.cpp | 156 +++++++ libraries/gpu/src/gpu/Pipeline.cpp | 34 ++ libraries/gpu/src/gpu/Pipeline.h | 53 +++ libraries/gpu/src/gpu/State.cpp | 20 + libraries/gpu/src/gpu/State.h | 88 ++++ libraries/model/src/model/Stage.cpp | 11 +- libraries/model/src/model/Stage.h | 4 +- libraries/render-utils/src/Model.cpp | 2 +- 17 files changed, 803 insertions(+), 464 deletions(-) create mode 100755 libraries/gpu/src/gpu/GLBackendBuffer.cpp create mode 100755 libraries/gpu/src/gpu/GLBackendInput.cpp create mode 100755 libraries/gpu/src/gpu/GLBackendPipeline.cpp create mode 100755 libraries/gpu/src/gpu/GLBackendTransform.cpp create mode 100755 libraries/gpu/src/gpu/Pipeline.cpp create mode 100755 libraries/gpu/src/gpu/Pipeline.h create mode 100755 libraries/gpu/src/gpu/State.cpp create mode 100755 libraries/gpu/src/gpu/State.h diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index ddbc76fce6..9ca0eeaebf 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -25,7 +25,8 @@ Batch::Batch() : _buffers(), _textures(), _streamFormats(), - _transforms() + _transforms(), + _pipelines() { } @@ -42,6 +43,7 @@ void Batch::clear() { _textures.clear(); _streamFormats.clear(); _transforms.clear(); + _pipelines.clear(); } uint32 Batch::cacheResource(Resource* res) { @@ -159,6 +161,12 @@ void Batch::setProjectionTransform(const Mat4& proj) { _params.push_back(cacheData(sizeof(Mat4), &proj)); } +void Batch::setPipeline(const PipelinePointer& pipeline) { + ADD_COMMAND(setPipeline); + + _params.push_back(_pipelines.cache(pipeline)); +} + void Batch::setUniformBuffer(uint32 slot, const BufferPointer& buffer, Offset offset, Offset size) { ADD_COMMAND(setUniformBuffer); diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index 310cd9fe16..54a6339ae3 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -21,6 +21,8 @@ #include "Stream.h" #include "Texture.h" +#include "Pipeline.h" + #if defined(NSIGHT_FOUND) #include "nvToolsExt.h" class ProfileRange { @@ -96,7 +98,9 @@ public: void setViewTransform(const Transform& view); void setProjectionTransform(const Mat4& proj); - // Shader Stage + // Pipeline Stage + void setPipeline(const PipelinePointer& pipeline); + void setUniformBuffer(uint32 slot, const BufferPointer& buffer, Offset offset, Offset size); void setUniformBuffer(uint32 slot, const BufferView& view); // not a command, just a shortcut from a BufferView @@ -164,6 +168,7 @@ public: COMMAND_setViewTransform, COMMAND_setProjectionTransform, + COMMAND_setPipeline, COMMAND_setUniformBuffer, COMMAND_setUniformTexture, @@ -281,6 +286,7 @@ public: typedef Cache::Vector TextureCaches; typedef Cache::Vector StreamFormatCaches; typedef Cache::Vector TransformCaches; + typedef Cache::Vector PipelineCaches; typedef unsigned char Byte; typedef std::vector Bytes; @@ -320,6 +326,7 @@ public: TextureCaches _textures; StreamFormatCaches _streamFormats; TransformCaches _transforms; + PipelineCaches _pipelines; protected: }; diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index ecff65fd8d..1e239f0c56 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -16,6 +16,7 @@ #include "Resource.h" #include "Texture.h" #include "Shader.h" +#include "Pipeline.h" namespace gpu { @@ -47,7 +48,6 @@ public: template< typename T > static void setGPUObject(const Buffer& buffer, T* bo) { - // buffer.setGPUObject(reinterpret_cast(bo)); buffer.setGPUObject(bo); } template< typename T > @@ -55,30 +55,32 @@ public: return reinterpret_cast(buffer.getGPUObject()); } - //void syncGPUObject(const Buffer& buffer); - template< typename T > static void setGPUObject(const Texture& texture, T* to) { - texture.setGPUObject(reinterpret_cast(to)); + texture.setGPUObject(to); } template< typename T > static T* getGPUObject(const Texture& texture) { return reinterpret_cast(texture.getGPUObject()); } - - //void syncGPUObject(const Texture& texture); - template< typename T > static void setGPUObject(const Shader& shader, T* so) { - shader.setGPUObject(reinterpret_cast(so)); + shader.setGPUObject(so); } template< typename T > static T* getGPUObject(const Shader& shader) { return reinterpret_cast(shader.getGPUObject()); } - // void syncGPUObject(const Shader& shader); + template< typename T > + static void setGPUObject(const Pipeline& pipeline, T* po) { + pipeline.setGPUObject(po); + } + template< typename T > + static T* getGPUObject(const Pipeline& pipeline) { + return reinterpret_cast(pipeline.getGPUObject()); + } protected: diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 6314d179ed..4831ecdd4c 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -25,6 +25,7 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::GLBackend::do_setViewTransform), (&::gpu::GLBackend::do_setProjectionTransform), + (&::gpu::GLBackend::do_setPipeline), (&::gpu::GLBackend::do_setUniformBuffer), (&::gpu::GLBackend::do_setUniformTexture), @@ -71,7 +72,8 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = GLBackend::GLBackend() : _input(), - _transform() + _transform(), + _pipeline() { initTransform(); } @@ -134,6 +136,7 @@ void GLBackend::checkGLError() { void GLBackend::do_draw(Batch& batch, uint32 paramOffset) { updateInput(); updateTransform(); + updatePipeline(); Primitive primitiveType = (Primitive)batch._params[paramOffset + 2]._uint; GLenum mode = _primitiveToGLmode[primitiveType]; @@ -147,6 +150,7 @@ void GLBackend::do_draw(Batch& batch, uint32 paramOffset) { void GLBackend::do_drawIndexed(Batch& batch, uint32 paramOffset) { updateInput(); updateTransform(); + updatePipeline(); Primitive primitiveType = (Primitive)batch._params[paramOffset + 2]._uint; GLenum mode = _primitiveToGLmode[primitiveType]; @@ -167,389 +171,6 @@ void GLBackend::do_drawIndexedInstanced(Batch& batch, uint32 paramOffset) { CHECK_GL_ERROR(); } -void GLBackend::do_setInputFormat(Batch& batch, uint32 paramOffset) { - Stream::FormatPointer format = batch._streamFormats.get(batch._params[paramOffset]._uint); - - if (format != _input._format) { - _input._format = format; - _input._invalidFormat = true; - } -} - -void GLBackend::do_setInputBuffer(Batch& batch, uint32 paramOffset) { - Offset stride = batch._params[paramOffset + 0]._uint; - Offset offset = batch._params[paramOffset + 1]._uint; - BufferPointer buffer = batch._buffers.get(batch._params[paramOffset + 2]._uint); - uint32 channel = batch._params[paramOffset + 3]._uint; - - if (channel < getNumInputBuffers()) { - _input._buffers[channel] = buffer; - _input._bufferOffsets[channel] = offset; - _input._bufferStrides[channel] = stride; - _input._buffersState.set(channel); - } -} - -#define SUPPORT_LEGACY_OPENGL -#if defined(SUPPORT_LEGACY_OPENGL) -static const int NUM_CLASSIC_ATTRIBS = Stream::TANGENT; -static const GLenum attributeSlotToClassicAttribName[NUM_CLASSIC_ATTRIBS] = { - GL_VERTEX_ARRAY, - GL_NORMAL_ARRAY, - GL_COLOR_ARRAY, - GL_TEXTURE_COORD_ARRAY -}; -#endif - -void GLBackend::updateInput() { - if (_input._invalidFormat || _input._buffersState.any()) { - - if (_input._invalidFormat) { - InputStageState::ActivationCache newActivation; - - // Check expected activation - if (_input._format) { - const Stream::Format::AttributeMap& attributes = _input._format->getAttributes(); - for (Stream::Format::AttributeMap::const_iterator it = attributes.begin(); it != attributes.end(); it++) { - const Stream::Attribute& attrib = (*it).second; - newActivation.set(attrib._slot); - } - } - - // Manage Activation what was and what is expected now - for (unsigned int i = 0; i < newActivation.size(); i++) { - bool newState = newActivation[i]; - if (newState != _input._attributeActivation[i]) { -#if defined(SUPPORT_LEGACY_OPENGL) - if (i < NUM_CLASSIC_ATTRIBS) { - if (newState) { - glEnableClientState(attributeSlotToClassicAttribName[i]); - } - else { - glDisableClientState(attributeSlotToClassicAttribName[i]); - } - } else { -#else - { -#endif - if (newState) { - glEnableVertexAttribArray(i); - } else { - glDisableVertexAttribArray(i); - } - } - CHECK_GL_ERROR(); - - _input._attributeActivation.flip(i); - } - } - } - - // now we need to bind the buffers and assign the attrib pointers - if (_input._format) { - const Buffers& buffers = _input._buffers; - const Offsets& offsets = _input._bufferOffsets; - const Offsets& strides = _input._bufferStrides; - - const Stream::Format::AttributeMap& attributes = _input._format->getAttributes(); - - for (Stream::Format::ChannelMap::const_iterator channelIt = _input._format->getChannels().begin(); - channelIt != _input._format->getChannels().end(); - channelIt++) { - const Stream::Format::ChannelMap::value_type::second_type& channel = (*channelIt).second; - if ((*channelIt).first < buffers.size()) { - int bufferNum = (*channelIt).first; - - if (_input._buffersState.test(bufferNum) || _input._invalidFormat) { - GLuint vbo = gpu::GLBackend::getBufferID((*buffers[bufferNum])); - glBindBuffer(GL_ARRAY_BUFFER, vbo); - CHECK_GL_ERROR(); - _input._buffersState[bufferNum] = false; - - for (unsigned int i = 0; i < channel._slots.size(); i++) { - const Stream::Attribute& attrib = attributes.at(channel._slots[i]); - GLuint slot = attrib._slot; - GLuint count = attrib._element.getDimensionCount(); - GLenum type = _elementTypeToGLType[attrib._element.getType()]; - GLuint stride = strides[bufferNum]; - GLuint pointer = attrib._offset + offsets[bufferNum]; - #if defined(SUPPORT_LEGACY_OPENGL) - if (slot < NUM_CLASSIC_ATTRIBS) { - switch (slot) { - case Stream::POSITION: - glVertexPointer(count, type, stride, reinterpret_cast(pointer)); - break; - case Stream::NORMAL: - glNormalPointer(type, stride, reinterpret_cast(pointer)); - break; - case Stream::COLOR: - glColorPointer(count, type, stride, reinterpret_cast(pointer)); - break; - case Stream::TEXCOORD: - glTexCoordPointer(count, type, stride, reinterpret_cast(pointer)); - break; - }; - } else { - #else - { - #endif - GLboolean isNormalized = attrib._element.isNormalized(); - glVertexAttribPointer(slot, count, type, isNormalized, stride, - reinterpret_cast(pointer)); - } - CHECK_GL_ERROR(); - } - } - } - } - } - // everything format related should be in sync now - _input._invalidFormat = false; - } - -/* TODO: Fancy version GL4.4 - if (_needInputFormatUpdate) { - - InputActivationCache newActivation; - - // Assign the vertex format required - if (_inputFormat) { - const StreamFormat::AttributeMap& attributes = _inputFormat->getAttributes(); - for (StreamFormat::AttributeMap::const_iterator it = attributes.begin(); it != attributes.end(); it++) { - const StreamFormat::Attribute& attrib = (*it).second; - newActivation.set(attrib._slot); - glVertexAttribFormat( - attrib._slot, - attrib._element.getDimensionCount(), - _elementTypeToGLType[attrib._element.getType()], - attrib._element.isNormalized(), - attrib._stride); - } - CHECK_GL_ERROR(); - } - - // Manage Activation what was and what is expected now - for (int i = 0; i < newActivation.size(); i++) { - bool newState = newActivation[i]; - if (newState != _inputAttributeActivation[i]) { - if (newState) { - glEnableVertexAttribArray(i); - } else { - glDisableVertexAttribArray(i); - } - _inputAttributeActivation.flip(i); - } - } - CHECK_GL_ERROR(); - - _needInputFormatUpdate = false; - } - - if (_needInputStreamUpdate) { - if (_inputStream) { - const Stream::Buffers& buffers = _inputStream->getBuffers(); - const Stream::Offsets& offsets = _inputStream->getOffsets(); - const Stream::Strides& strides = _inputStream->getStrides(); - - for (int i = 0; i < buffers.size(); i++) { - GLuint vbo = gpu::GLBackend::getBufferID((*buffers[i])); - glBindVertexBuffer(i, vbo, offsets[i], strides[i]); - } - - CHECK_GL_ERROR(); - } - _needInputStreamUpdate = false; - } -*/ -} - - -void GLBackend::do_setIndexBuffer(Batch& batch, uint32 paramOffset) { - _input._indexBufferType = (Type) batch._params[paramOffset + 2]._uint; - BufferPointer indexBuffer = batch._buffers.get(batch._params[paramOffset + 1]._uint); - _input._indexBufferOffset = batch._params[paramOffset + 0]._uint; - _input._indexBuffer = indexBuffer; - if (indexBuffer) { - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, getBufferID(*indexBuffer)); - } else { - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - } - CHECK_GL_ERROR(); -} - -// Transform Stage - -void GLBackend::do_setModelTransform(Batch& batch, uint32 paramOffset) { - _transform._model = batch._transforms.get(batch._params[paramOffset]._uint); - _transform._invalidModel = true; -} - -void GLBackend::do_setViewTransform(Batch& batch, uint32 paramOffset) { - _transform._view = batch._transforms.get(batch._params[paramOffset]._uint); - _transform._invalidView = true; -} - -void GLBackend::do_setProjectionTransform(Batch& batch, uint32 paramOffset) { - memcpy(&_transform._projection, batch.editData(batch._params[paramOffset]._uint), sizeof(Mat4)); - _transform._invalidProj = true; -} - -void GLBackend::initTransform() { -#if defined(Q_OS_WIN) - glGenBuffers(1, &_transform._transformObjectBuffer); - glGenBuffers(1, &_transform._transformCameraBuffer); - - glBindBuffer(GL_UNIFORM_BUFFER, _transform._transformObjectBuffer); - glBufferData(GL_UNIFORM_BUFFER, sizeof(_transform._transformObject), (const void*) &_transform._transformObject, GL_DYNAMIC_DRAW); - - glBindBuffer(GL_UNIFORM_BUFFER, _transform._transformCameraBuffer); - glBufferData(GL_UNIFORM_BUFFER, sizeof(_transform._transformCamera), (const void*) &_transform._transformCamera, GL_DYNAMIC_DRAW); - - - glBindBuffer(GL_UNIFORM_BUFFER, 0); -#else -#endif -} - -void GLBackend::killTransform() { -#if defined(Q_OS_WIN) - glDeleteBuffers(1, &_transform._transformObjectBuffer); - glDeleteBuffers(1, &_transform._transformCameraBuffer); -#else -#endif -} -void GLBackend::updateTransform() { - // Check all the dirty flags and update the state accordingly - if (_transform._invalidProj) { - _transform._transformCamera._projection = _transform._projection; - } - - if (_transform._invalidView) { - _transform._view.getInverseMatrix(_transform._transformCamera._view); - _transform._view.getMatrix(_transform._transformCamera._viewInverse); - } - - if (_transform._invalidModel) { - _transform._model.getMatrix(_transform._transformObject._model); - _transform._model.getInverseMatrix(_transform._transformObject._modelInverse); - } - - if (_transform._invalidView || _transform._invalidProj) { - Mat4 viewUntranslated = _transform._transformCamera._view; - viewUntranslated[3] = Vec4(0.0f, 0.0f, 0.0f, 1.0f); - _transform._transformCamera._projectionViewUntranslated = _transform._transformCamera._projection * viewUntranslated; - } - - if (_transform._invalidView || _transform._invalidProj) { -#if defined(Q_OS_WIN) - glBindBufferBase(GL_UNIFORM_BUFFER, TRANSFORM_CAMERA_SLOT, 0); - glBindBuffer(GL_ARRAY_BUFFER, _transform._transformCameraBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(_transform._transformCamera), (const void*) &_transform._transformCamera, GL_DYNAMIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); - CHECK_GL_ERROR(); -#endif - } - - if (_transform._invalidModel) { -#if defined(Q_OS_WIN) - glBindBufferBase(GL_UNIFORM_BUFFER, TRANSFORM_OBJECT_SLOT, 0); - glBindBuffer(GL_ARRAY_BUFFER, _transform._transformObjectBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(_transform._transformObject), (const void*) &_transform._transformObject, GL_DYNAMIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); - CHECK_GL_ERROR(); -#endif - } - -#if defined(Q_OS_WIN) - glBindBufferBase(GL_UNIFORM_BUFFER, TRANSFORM_OBJECT_SLOT, _transform._transformObjectBuffer); - glBindBufferBase(GL_UNIFORM_BUFFER, TRANSFORM_CAMERA_SLOT, _transform._transformCameraBuffer); - CHECK_GL_ERROR(); -#endif - - -#if defined(Q_OS_MAC) || defined(Q_OS_LINUX) - // Do it again for fixed pipeline until we can get rid of it - if (_transform._invalidProj) { - if (_transform._lastMode != GL_PROJECTION) { - glMatrixMode(GL_PROJECTION); - _transform._lastMode = GL_PROJECTION; - } - glLoadMatrixf(reinterpret_cast< const GLfloat* >(&_transform._projection)); - - CHECK_GL_ERROR(); - } - - if (_transform._invalidModel || _transform._invalidView) { - if (!_transform._model.isIdentity()) { - if (_transform._lastMode != GL_MODELVIEW) { - glMatrixMode(GL_MODELVIEW); - _transform._lastMode = GL_MODELVIEW; - } - Transform::Mat4 modelView; - if (!_transform._view.isIdentity()) { - Transform mvx; - Transform::inverseMult(mvx, _transform._view, _transform._model); - mvx.getMatrix(modelView); - } else { - _transform._model.getMatrix(modelView); - } - glLoadMatrixf(reinterpret_cast< const GLfloat* >(&modelView)); - } else { - if (!_transform._view.isIdentity()) { - if (_transform._lastMode != GL_MODELVIEW) { - glMatrixMode(GL_MODELVIEW); - _transform._lastMode = GL_MODELVIEW; - } - Transform::Mat4 modelView; - _transform._view.getInverseMatrix(modelView); - glLoadMatrixf(reinterpret_cast< const GLfloat* >(&modelView)); - } else { - // TODO: eventually do something about the matrix when neither view nor model is specified? - // glLoadIdentity(); - } - } - CHECK_GL_ERROR(); - } -#endif - - // Flags are clean - _transform._invalidView = _transform._invalidProj = _transform._invalidModel = false; -} - -void GLBackend::do_setUniformBuffer(Batch& batch, uint32 paramOffset) { - GLuint slot = batch._params[paramOffset + 3]._uint; - BufferPointer uniformBuffer = batch._buffers.get(batch._params[paramOffset + 2]._uint); - GLintptr rangeStart = batch._params[paramOffset + 1]._uint; - GLsizeiptr rangeSize = batch._params[paramOffset + 0]._uint; -#if defined(Q_OS_MAC) - GLfloat* data = (GLfloat*) (uniformBuffer->getData() + rangeStart); - glUniform4fv(slot, rangeSize / sizeof(GLfloat[4]), data); - - // NOT working so we ll stick to the uniform float array until we move to core profile - // GLuint bo = getBufferID(*uniformBuffer); - //glUniformBufferEXT(_shader._program, slot, bo); -#elif defined(Q_OS_WIN) - GLuint bo = getBufferID(*uniformBuffer); - glBindBufferRange(GL_UNIFORM_BUFFER, slot, bo, rangeStart, rangeSize); -#else - GLfloat* data = (GLfloat*) (uniformBuffer->getData() + rangeStart); - glUniform4fv(slot, rangeSize / sizeof(GLfloat[4]), data); -#endif - CHECK_GL_ERROR(); -} - -void GLBackend::do_setUniformTexture(Batch& batch, uint32 paramOffset) { - GLuint slot = batch._params[paramOffset + 1]._uint; - TexturePointer uniformTexture = batch._textures.get(batch._params[paramOffset + 0]._uint); - - GLuint to = getTextureID(uniformTexture); - glActiveTexture(GL_TEXTURE0 + slot); - glBindTexture(GL_TEXTURE_2D, to); - - CHECK_GL_ERROR(); -} - - // TODO: As long as we have gl calls explicitely issued from interface // code, we need to be able to record and batch these calls. THe long // term strategy is to get rid of any GL calls in favor of the HIFI GPU API @@ -740,8 +361,10 @@ void Batch::_glUseProgram(GLuint program) { } void GLBackend::do_glUseProgram(Batch& batch, uint32 paramOffset) { - _shader._program = batch._params[paramOffset]._uint; - glUseProgram(_shader._program); + _pipeline._program = batch._params[paramOffset]._uint; + // for this call we still want to execute the glUseProgram in the order of the glCOmmand to avoid any issue + _pipeline._invalidProgram = false; + glUseProgram(_pipeline._program); CHECK_GL_ERROR(); } @@ -998,55 +621,3 @@ void GLBackend::do_glColor4f(Batch& batch, uint32 paramOffset) { CHECK_GL_ERROR(); } -GLBackend::GLBuffer::GLBuffer() : - _stamp(0), - _buffer(0), - _size(0) -{} - -GLBackend::GLBuffer::~GLBuffer() { - if (_buffer != 0) { - glDeleteBuffers(1, &_buffer); - } -} - -GLBackend::GLBuffer* GLBackend::syncGPUObject(const Buffer& buffer) { - GLBuffer* object = Backend::getGPUObject(buffer); - - if (object && (object->_stamp == buffer.getSysmem().getStamp())) { - return object; - } - - // need to have a gpu object? - if (!object) { - object = new GLBuffer(); - glGenBuffers(1, &object->_buffer); - CHECK_GL_ERROR(); - Backend::setGPUObject(buffer, object); - } - - // Now let's update the content of the bo with the sysmem version - // TODO: in the future, be smarter about when to actually upload the glBO version based on the data that did change - //if () { - glBindBuffer(GL_ARRAY_BUFFER, object->_buffer); - glBufferData(GL_ARRAY_BUFFER, buffer.getSysmem().getSize(), buffer.getSysmem().readData(), GL_DYNAMIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); - object->_stamp = buffer.getSysmem().getStamp(); - object->_size = buffer.getSysmem().getSize(); - //} - CHECK_GL_ERROR(); - - return object; -} - - - -GLuint GLBackend::getBufferID(const Buffer& buffer) { - GLBuffer* bo = GLBackend::syncGPUObject(buffer); - if (bo) { - return bo->_buffer; - } else { - return 0; - } -} - diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 974bb6fb8b..2fd27862f9 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -75,6 +75,16 @@ public: static GLShader* syncGPUObject(const Shader& shader); static GLuint getShaderID(const ShaderPointer& shader); + + class GLPipeline : public GPUObject { + public: + GLShader* _program; + + GLPipeline(); + ~GLPipeline(); + }; + static GLPipeline* syncGPUObject(const Pipeline& pipeline); + static const int MAX_NUM_ATTRIBUTES = Stream::NUM_INPUT_SLOTS; static const int MAX_NUM_INPUT_BUFFERS = 16; @@ -160,18 +170,24 @@ protected: _lastMode(GL_TEXTURE) {} } _transform; - // Shader Stage + // Pipeline Stage + void do_setPipeline(Batch& batch, uint32 paramOffset); void do_setUniformBuffer(Batch& batch, uint32 paramOffset); void do_setUniformTexture(Batch& batch, uint32 paramOffset); - void updateShader(); - struct ShaderStageState { + void updatePipeline(); + struct PipelineStageState { + PipelinePointer _pipeline; GLuint _program; + bool _invalidProgram; - ShaderStageState() : - _program(0) {} - } _shader; + PipelineStageState() : + _pipeline(), + _program(0), + _invalidProgram(false) + {} + } _pipeline; // TODO: As long as we have gl calls explicitely issued from interface diff --git a/libraries/gpu/src/gpu/GLBackendBuffer.cpp b/libraries/gpu/src/gpu/GLBackendBuffer.cpp new file mode 100755 index 0000000000..12eab21686 --- /dev/null +++ b/libraries/gpu/src/gpu/GLBackendBuffer.cpp @@ -0,0 +1,66 @@ +// +// GLBackendBuffer.cpp +// libraries/gpu/src/gpu +// +// Created by Sam Gateau on 3/8/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" + +using namespace gpu; + +GLBackend::GLBuffer::GLBuffer() : + _stamp(0), + _buffer(0), + _size(0) +{} + +GLBackend::GLBuffer::~GLBuffer() { + if (_buffer != 0) { + glDeleteBuffers(1, &_buffer); + } +} + +GLBackend::GLBuffer* GLBackend::syncGPUObject(const Buffer& buffer) { + GLBuffer* object = Backend::getGPUObject(buffer); + + if (object && (object->_stamp == buffer.getSysmem().getStamp())) { + return object; + } + + // need to have a gpu object? + if (!object) { + object = new GLBuffer(); + glGenBuffers(1, &object->_buffer); + CHECK_GL_ERROR(); + Backend::setGPUObject(buffer, object); + } + + // Now let's update the content of the bo with the sysmem version + // TODO: in the future, be smarter about when to actually upload the glBO version based on the data that did change + //if () { + glBindBuffer(GL_ARRAY_BUFFER, object->_buffer); + glBufferData(GL_ARRAY_BUFFER, buffer.getSysmem().getSize(), buffer.getSysmem().readData(), GL_DYNAMIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + object->_stamp = buffer.getSysmem().getStamp(); + object->_size = buffer.getSysmem().getSize(); + //} + CHECK_GL_ERROR(); + + return object; +} + + + +GLuint GLBackend::getBufferID(const Buffer& buffer) { + GLBuffer* bo = GLBackend::syncGPUObject(buffer); + if (bo) { + return bo->_buffer; + } else { + return 0; + } +} + diff --git a/libraries/gpu/src/gpu/GLBackendInput.cpp b/libraries/gpu/src/gpu/GLBackendInput.cpp new file mode 100755 index 0000000000..982d2656a0 --- /dev/null +++ b/libraries/gpu/src/gpu/GLBackendInput.cpp @@ -0,0 +1,223 @@ +// +// GLBackendInput.cpp +// libraries/gpu/src/gpu +// +// Created by Sam Gateau on 3/8/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" + +using namespace gpu; + +void GLBackend::do_setInputFormat(Batch& batch, uint32 paramOffset) { + Stream::FormatPointer format = batch._streamFormats.get(batch._params[paramOffset]._uint); + + if (format != _input._format) { + _input._format = format; + _input._invalidFormat = true; + } +} + +void GLBackend::do_setInputBuffer(Batch& batch, uint32 paramOffset) { + Offset stride = batch._params[paramOffset + 0]._uint; + Offset offset = batch._params[paramOffset + 1]._uint; + BufferPointer buffer = batch._buffers.get(batch._params[paramOffset + 2]._uint); + uint32 channel = batch._params[paramOffset + 3]._uint; + + if (channel < getNumInputBuffers()) { + _input._buffers[channel] = buffer; + _input._bufferOffsets[channel] = offset; + _input._bufferStrides[channel] = stride; + _input._buffersState.set(channel); + } +} + +#define SUPPORT_LEGACY_OPENGL +#if defined(SUPPORT_LEGACY_OPENGL) +static const int NUM_CLASSIC_ATTRIBS = Stream::TANGENT; +static const GLenum attributeSlotToClassicAttribName[NUM_CLASSIC_ATTRIBS] = { + GL_VERTEX_ARRAY, + GL_NORMAL_ARRAY, + GL_COLOR_ARRAY, + GL_TEXTURE_COORD_ARRAY +}; +#endif + +void GLBackend::updateInput() { + if (_input._invalidFormat || _input._buffersState.any()) { + + if (_input._invalidFormat) { + InputStageState::ActivationCache newActivation; + + // Check expected activation + if (_input._format) { + const Stream::Format::AttributeMap& attributes = _input._format->getAttributes(); + for (Stream::Format::AttributeMap::const_iterator it = attributes.begin(); it != attributes.end(); it++) { + const Stream::Attribute& attrib = (*it).second; + newActivation.set(attrib._slot); + } + } + + // Manage Activation what was and what is expected now + for (unsigned int i = 0; i < newActivation.size(); i++) { + bool newState = newActivation[i]; + if (newState != _input._attributeActivation[i]) { +#if defined(SUPPORT_LEGACY_OPENGL) + if (i < NUM_CLASSIC_ATTRIBS) { + if (newState) { + glEnableClientState(attributeSlotToClassicAttribName[i]); + } + else { + glDisableClientState(attributeSlotToClassicAttribName[i]); + } + } else { +#else + { +#endif + if (newState) { + glEnableVertexAttribArray(i); + } else { + glDisableVertexAttribArray(i); + } + } + CHECK_GL_ERROR(); + + _input._attributeActivation.flip(i); + } + } + } + + // now we need to bind the buffers and assign the attrib pointers + if (_input._format) { + const Buffers& buffers = _input._buffers; + const Offsets& offsets = _input._bufferOffsets; + const Offsets& strides = _input._bufferStrides; + + const Stream::Format::AttributeMap& attributes = _input._format->getAttributes(); + + for (Stream::Format::ChannelMap::const_iterator channelIt = _input._format->getChannels().begin(); + channelIt != _input._format->getChannels().end(); + channelIt++) { + const Stream::Format::ChannelMap::value_type::second_type& channel = (*channelIt).second; + if ((*channelIt).first < buffers.size()) { + int bufferNum = (*channelIt).first; + + if (_input._buffersState.test(bufferNum) || _input._invalidFormat) { + GLuint vbo = gpu::GLBackend::getBufferID((*buffers[bufferNum])); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + CHECK_GL_ERROR(); + _input._buffersState[bufferNum] = false; + + for (unsigned int i = 0; i < channel._slots.size(); i++) { + const Stream::Attribute& attrib = attributes.at(channel._slots[i]); + GLuint slot = attrib._slot; + GLuint count = attrib._element.getDimensionCount(); + GLenum type = _elementTypeToGLType[attrib._element.getType()]; + GLuint stride = strides[bufferNum]; + GLuint pointer = attrib._offset + offsets[bufferNum]; + #if defined(SUPPORT_LEGACY_OPENGL) + if (slot < NUM_CLASSIC_ATTRIBS) { + switch (slot) { + case Stream::POSITION: + glVertexPointer(count, type, stride, reinterpret_cast(pointer)); + break; + case Stream::NORMAL: + glNormalPointer(type, stride, reinterpret_cast(pointer)); + break; + case Stream::COLOR: + glColorPointer(count, type, stride, reinterpret_cast(pointer)); + break; + case Stream::TEXCOORD: + glTexCoordPointer(count, type, stride, reinterpret_cast(pointer)); + break; + }; + } else { + #else + { + #endif + GLboolean isNormalized = attrib._element.isNormalized(); + glVertexAttribPointer(slot, count, type, isNormalized, stride, + reinterpret_cast(pointer)); + } + CHECK_GL_ERROR(); + } + } + } + } + } + // everything format related should be in sync now + _input._invalidFormat = false; + } + +/* TODO: Fancy version GL4.4 + if (_needInputFormatUpdate) { + + InputActivationCache newActivation; + + // Assign the vertex format required + if (_inputFormat) { + const StreamFormat::AttributeMap& attributes = _inputFormat->getAttributes(); + for (StreamFormat::AttributeMap::const_iterator it = attributes.begin(); it != attributes.end(); it++) { + const StreamFormat::Attribute& attrib = (*it).second; + newActivation.set(attrib._slot); + glVertexAttribFormat( + attrib._slot, + attrib._element.getDimensionCount(), + _elementTypeToGLType[attrib._element.getType()], + attrib._element.isNormalized(), + attrib._stride); + } + CHECK_GL_ERROR(); + } + + // Manage Activation what was and what is expected now + for (int i = 0; i < newActivation.size(); i++) { + bool newState = newActivation[i]; + if (newState != _inputAttributeActivation[i]) { + if (newState) { + glEnableVertexAttribArray(i); + } else { + glDisableVertexAttribArray(i); + } + _inputAttributeActivation.flip(i); + } + } + CHECK_GL_ERROR(); + + _needInputFormatUpdate = false; + } + + if (_needInputStreamUpdate) { + if (_inputStream) { + const Stream::Buffers& buffers = _inputStream->getBuffers(); + const Stream::Offsets& offsets = _inputStream->getOffsets(); + const Stream::Strides& strides = _inputStream->getStrides(); + + for (int i = 0; i < buffers.size(); i++) { + GLuint vbo = gpu::GLBackend::getBufferID((*buffers[i])); + glBindVertexBuffer(i, vbo, offsets[i], strides[i]); + } + + CHECK_GL_ERROR(); + } + _needInputStreamUpdate = false; + } +*/ +} + + +void GLBackend::do_setIndexBuffer(Batch& batch, uint32 paramOffset) { + _input._indexBufferType = (Type) batch._params[paramOffset + 2]._uint; + BufferPointer indexBuffer = batch._buffers.get(batch._params[paramOffset + 1]._uint); + _input._indexBufferOffset = batch._params[paramOffset + 0]._uint; + _input._indexBuffer = indexBuffer; + if (indexBuffer) { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, getBufferID(*indexBuffer)); + } else { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + } + CHECK_GL_ERROR(); +} diff --git a/libraries/gpu/src/gpu/GLBackendPipeline.cpp b/libraries/gpu/src/gpu/GLBackendPipeline.cpp new file mode 100755 index 0000000000..eba904ae4f --- /dev/null +++ b/libraries/gpu/src/gpu/GLBackendPipeline.cpp @@ -0,0 +1,95 @@ +// +// GLBackendPipeline.cpp +// libraries/gpu/src/gpu +// +// Created by Sam Gateau on 3/8/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" + +#include "Format.h" + +using namespace gpu; + +GLBackend::GLPipeline::GLPipeline() : + _program(nullptr) +{} + +GLBackend::GLPipeline::~GLPipeline() { + _program = nullptr; +} + +GLBackend::GLPipeline* GLBackend::syncGPUObject(const Pipeline& pipeline) { + GLPipeline* object = Backend::getGPUObject(pipeline); + + // If GPU object already created then good + if (object) { + return object; + } + + return nullptr; +} + +void GLBackend::do_setPipeline(Batch& batch, uint32 paramOffset) { + PipelinePointer pipeline = batch._pipelines.get(batch._params[paramOffset + 0]._uint); + + if (pipeline == _pipeline._pipeline) { + return; + } + + auto pipelineObject = syncGPUObject((*pipeline)); + if (!pipelineObject) { + return; + } + + _pipeline._pipeline = pipeline; + _pipeline._program = pipelineObject->_program->_program; + _pipeline._invalidProgram = true; +} + +void GLBackend::do_setUniformBuffer(Batch& batch, uint32 paramOffset) { + GLuint slot = batch._params[paramOffset + 3]._uint; + BufferPointer uniformBuffer = batch._buffers.get(batch._params[paramOffset + 2]._uint); + GLintptr rangeStart = batch._params[paramOffset + 1]._uint; + GLsizeiptr rangeSize = batch._params[paramOffset + 0]._uint; +#if defined(Q_OS_MAC) + GLfloat* data = (GLfloat*) (uniformBuffer->getData() + rangeStart); + glUniform4fv(slot, rangeSize / sizeof(GLfloat[4]), data); + + // NOT working so we ll stick to the uniform float array until we move to core profile + // GLuint bo = getBufferID(*uniformBuffer); + //glUniformBufferEXT(_shader._program, slot, bo); +#elif defined(Q_OS_WIN) + GLuint bo = getBufferID(*uniformBuffer); + glBindBufferRange(GL_UNIFORM_BUFFER, slot, bo, rangeStart, rangeSize); +#else + GLfloat* data = (GLfloat*) (uniformBuffer->getData() + rangeStart); + glUniform4fv(slot, rangeSize / sizeof(GLfloat[4]), data); +#endif + CHECK_GL_ERROR(); +} + +void GLBackend::do_setUniformTexture(Batch& batch, uint32 paramOffset) { + GLuint slot = batch._params[paramOffset + 1]._uint; + TexturePointer uniformTexture = batch._textures.get(batch._params[paramOffset + 0]._uint); + + GLuint to = getTextureID(uniformTexture); + glActiveTexture(GL_TEXTURE0 + slot); + glBindTexture(GL_TEXTURE_2D, to); + + CHECK_GL_ERROR(); +} + + +void GLBackend::updatePipeline() { + if (_pipeline._invalidProgram) { + glUseProgram(_pipeline._program); + CHECK_GL_ERROR(); + + _pipeline._invalidProgram = true; + } +} + diff --git a/libraries/gpu/src/gpu/GLBackendShader.cpp b/libraries/gpu/src/gpu/GLBackendShader.cpp index 5136461f5c..8adce580a5 100755 --- a/libraries/gpu/src/gpu/GLBackendShader.cpp +++ b/libraries/gpu/src/gpu/GLBackendShader.cpp @@ -672,3 +672,4 @@ bool GLBackend::makeProgram(Shader& shader, const Shader::BindingSet& slotBindin return true; } + diff --git a/libraries/gpu/src/gpu/GLBackendTransform.cpp b/libraries/gpu/src/gpu/GLBackendTransform.cpp new file mode 100755 index 0000000000..6e928bcf09 --- /dev/null +++ b/libraries/gpu/src/gpu/GLBackendTransform.cpp @@ -0,0 +1,156 @@ +// +// GLBackendTransform.cpp +// libraries/gpu/src/gpu +// +// Created by Sam Gateau on 3/8/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" + +#include "Format.h" + +using namespace gpu; + +// Transform Stage + +void GLBackend::do_setModelTransform(Batch& batch, uint32 paramOffset) { + _transform._model = batch._transforms.get(batch._params[paramOffset]._uint); + _transform._invalidModel = true; +} + +void GLBackend::do_setViewTransform(Batch& batch, uint32 paramOffset) { + _transform._view = batch._transforms.get(batch._params[paramOffset]._uint); + _transform._invalidView = true; +} + +void GLBackend::do_setProjectionTransform(Batch& batch, uint32 paramOffset) { + memcpy(&_transform._projection, batch.editData(batch._params[paramOffset]._uint), sizeof(Mat4)); + _transform._invalidProj = true; +} + +void GLBackend::initTransform() { +#if defined(Q_OS_WIN) + glGenBuffers(1, &_transform._transformObjectBuffer); + glGenBuffers(1, &_transform._transformCameraBuffer); + + glBindBuffer(GL_UNIFORM_BUFFER, _transform._transformObjectBuffer); + glBufferData(GL_UNIFORM_BUFFER, sizeof(_transform._transformObject), (const void*) &_transform._transformObject, GL_DYNAMIC_DRAW); + + glBindBuffer(GL_UNIFORM_BUFFER, _transform._transformCameraBuffer); + glBufferData(GL_UNIFORM_BUFFER, sizeof(_transform._transformCamera), (const void*) &_transform._transformCamera, GL_DYNAMIC_DRAW); + + + glBindBuffer(GL_UNIFORM_BUFFER, 0); +#else +#endif +} + +void GLBackend::killTransform() { +#if defined(Q_OS_WIN) + glDeleteBuffers(1, &_transform._transformObjectBuffer); + glDeleteBuffers(1, &_transform._transformCameraBuffer); +#else +#endif +} +void GLBackend::updateTransform() { + // Check all the dirty flags and update the state accordingly + if (_transform._invalidProj) { + _transform._transformCamera._projection = _transform._projection; + } + + if (_transform._invalidView) { + _transform._view.getInverseMatrix(_transform._transformCamera._view); + _transform._view.getMatrix(_transform._transformCamera._viewInverse); + } + + if (_transform._invalidModel) { + _transform._model.getMatrix(_transform._transformObject._model); + _transform._model.getInverseMatrix(_transform._transformObject._modelInverse); + } + + if (_transform._invalidView || _transform._invalidProj) { + Mat4 viewUntranslated = _transform._transformCamera._view; + viewUntranslated[3] = Vec4(0.0f, 0.0f, 0.0f, 1.0f); + _transform._transformCamera._projectionViewUntranslated = _transform._transformCamera._projection * viewUntranslated; + } + + if (_transform._invalidView || _transform._invalidProj) { +#if defined(Q_OS_WIN) + glBindBufferBase(GL_UNIFORM_BUFFER, TRANSFORM_CAMERA_SLOT, 0); + glBindBuffer(GL_ARRAY_BUFFER, _transform._transformCameraBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(_transform._transformCamera), (const void*) &_transform._transformCamera, GL_DYNAMIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + CHECK_GL_ERROR(); +#endif + } + + if (_transform._invalidModel) { +#if defined(Q_OS_WIN) + glBindBufferBase(GL_UNIFORM_BUFFER, TRANSFORM_OBJECT_SLOT, 0); + glBindBuffer(GL_ARRAY_BUFFER, _transform._transformObjectBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(_transform._transformObject), (const void*) &_transform._transformObject, GL_DYNAMIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + CHECK_GL_ERROR(); +#endif + } + +#if defined(Q_OS_WIN) + glBindBufferBase(GL_UNIFORM_BUFFER, TRANSFORM_OBJECT_SLOT, _transform._transformObjectBuffer); + glBindBufferBase(GL_UNIFORM_BUFFER, TRANSFORM_CAMERA_SLOT, _transform._transformCameraBuffer); + CHECK_GL_ERROR(); +#endif + + +#if defined(Q_OS_MAC) || defined(Q_OS_LINUX) + // Do it again for fixed pipeline until we can get rid of it + if (_transform._invalidProj) { + if (_transform._lastMode != GL_PROJECTION) { + glMatrixMode(GL_PROJECTION); + _transform._lastMode = GL_PROJECTION; + } + glLoadMatrixf(reinterpret_cast< const GLfloat* >(&_transform._projection)); + + CHECK_GL_ERROR(); + } + + if (_transform._invalidModel || _transform._invalidView) { + if (!_transform._model.isIdentity()) { + if (_transform._lastMode != GL_MODELVIEW) { + glMatrixMode(GL_MODELVIEW); + _transform._lastMode = GL_MODELVIEW; + } + Transform::Mat4 modelView; + if (!_transform._view.isIdentity()) { + Transform mvx; + Transform::inverseMult(mvx, _transform._view, _transform._model); + mvx.getMatrix(modelView); + } else { + _transform._model.getMatrix(modelView); + } + glLoadMatrixf(reinterpret_cast< const GLfloat* >(&modelView)); + } else { + if (!_transform._view.isIdentity()) { + if (_transform._lastMode != GL_MODELVIEW) { + glMatrixMode(GL_MODELVIEW); + _transform._lastMode = GL_MODELVIEW; + } + Transform::Mat4 modelView; + _transform._view.getInverseMatrix(modelView); + glLoadMatrixf(reinterpret_cast< const GLfloat* >(&modelView)); + } else { + // TODO: eventually do something about the matrix when neither view nor model is specified? + // glLoadIdentity(); + } + } + CHECK_GL_ERROR(); + } +#endif + + // Flags are clean + _transform._invalidView = _transform._invalidProj = _transform._invalidModel = false; +} + + diff --git a/libraries/gpu/src/gpu/Pipeline.cpp b/libraries/gpu/src/gpu/Pipeline.cpp new file mode 100755 index 0000000000..931d330c2b --- /dev/null +++ b/libraries/gpu/src/gpu/Pipeline.cpp @@ -0,0 +1,34 @@ +// +// Pipeline.cpp +// libraries/gpu/src/gpu +// +// Created by Sam Gateau on 3/8/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 "Pipeline.h" +#include +#include + +using namespace gpu; + +Pipeline::Pipeline(): + _program(), + _states() +{ +} + +Pipeline::~Pipeline() +{ +} + +Pipeline* Pipeline::create(const ShaderPointer& program, const States& states) { + Pipeline* pipeline = new Pipeline(); + pipeline->_program = program; + pipeline->_states = states; + + return pipeline; +} diff --git a/libraries/gpu/src/gpu/Pipeline.h b/libraries/gpu/src/gpu/Pipeline.h new file mode 100755 index 0000000000..c2fc944bb7 --- /dev/null +++ b/libraries/gpu/src/gpu/Pipeline.h @@ -0,0 +1,53 @@ +// +// Pipeline.h +// libraries/gpu/src/gpu +// +// Created by Sam Gateau on 3/8/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_Pipeline_h +#define hifi_gpu_Pipeline_h + +#include "Resource.h" +#include +#include + +#include "Shader.h" +#include "State.h" + +namespace gpu { + +class Pipeline { +public: + static Pipeline* create(const ShaderPointer& program, const States& states); + ~Pipeline(); + + const ShaderPointer& getProgram() const { return _program; } + + const States& getStates() const { return _states; } + +protected: + ShaderPointer _program; + States _states; + + Pipeline(); + Pipeline(const Pipeline& pipeline); // deep copy of the sysmem shader + Pipeline& operator=(const Pipeline& pipeline); // deep copy of the sysmem texture + + // 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< Pipeline > PipelinePointer; +typedef std::vector< PipelinePointer > Pipelines; + +}; + + +#endif diff --git a/libraries/gpu/src/gpu/State.cpp b/libraries/gpu/src/gpu/State.cpp new file mode 100755 index 0000000000..0b8edb7cd2 --- /dev/null +++ b/libraries/gpu/src/gpu/State.cpp @@ -0,0 +1,20 @@ +// +// State.cpp +// libraries/gpu/src/gpu +// +// Created by Sam Gateau on 3/8/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 "State.h" +#include + +using namespace gpu; + + +State::~State() +{ +} diff --git a/libraries/gpu/src/gpu/State.h b/libraries/gpu/src/gpu/State.h new file mode 100755 index 0000000000..92ef4c1c8d --- /dev/null +++ b/libraries/gpu/src/gpu/State.h @@ -0,0 +1,88 @@ +// +// Pipeline.h +// libraries/gpu/src/gpu +// +// Created by Sam Gateau on 3/8/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_State_h +#define hifi_gpu_State_h + +#include "Format.h" +#include +#include + + +namespace gpu { + +class GPUObject; + +class State { +public: + State() {} + virtual ~State(); + + // Work in progress, not used + /* + enum Field { + FILL_MODE, + CULL_MODE, + DEPTH_BIAS, + DEPTH_BIAS_CLAMP, + DEPTH_BIASSLOPE_SCALE, + + FRONT_CLOCKWISE, + DEPTH_CLIP_ENABLE, + SCISSR_ENABLE, + MULTISAMPLE_ENABLE, + ANTIALISED_LINE_ENABLE, + + DEPTH_ENABLE, + DEPTH_WRITE_MASK, + DEPTH_FUNCTION, + + STENCIL_ENABLE, + STENCIL_READ_MASK, + STENCIL_WRITE_MASK, + STENCIL_FUNCTION_FRONT, + STENCIL_FUNCTION_BACK, + STENCIL_REFERENCE, + + BLEND_INDEPENDANT_ENABLE, + BLEND_ENABLE, + BLEND_SOURCE, + BLEND_DESTINATION, + BLEND_OPERATION, + BLEND_SOURCE_ALPHA, + BLEND_DESTINATION_ALPHA, + BLEND_OPERATION_ALPHA, + BLEND_WRITE_MASK, + BLEND_FACTOR, + + SAMPLE_MASK, + + ALPHA_TO_COVERAGE_ENABLE, + }; + */ + +protected: + State(const State& state); + State& operator=(const State& state); + + // 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< State > StatePointer; +typedef std::vector< StatePointer > States; + +}; + + +#endif diff --git a/libraries/model/src/model/Stage.cpp b/libraries/model/src/model/Stage.cpp index d470d841bc..e4786df792 100644 --- a/libraries/model/src/model/Stage.cpp +++ b/libraries/model/src/model/Stage.cpp @@ -15,8 +15,6 @@ #include "SkyFromAtmosphere_vert.h" #include "SkyFromAtmosphere_frag.h" -#include "gpu/Context.h" -#include "gpu/GLBackend.h" using namespace model; @@ -156,12 +154,14 @@ SunSkyStage::SunSkyStage() : // Begining of march setYearTime(60.0f); - _skyShader = gpu::ShaderPointer( + auto skyShader = gpu::ShaderPointer( gpu::Shader::createProgram( gpu::ShaderPointer(gpu::Shader::createVertex(std::string(SkyFromAtmosphere_vert))), gpu::ShaderPointer(gpu::Shader::createPixel(std::string(SkyFromAtmosphere_frag))) ) ); + _skyPipeline = gpu::PipelinePointer(gpu::Pipeline::create(skyShader, gpu::States())); + } SunSkyStage::~SunSkyStage() { @@ -217,12 +217,11 @@ void SunSkyStage::updateGraphicsObject() const { double originAlt = _earthSunModel.getAltitude(); _sunLight->setPosition(Vec3(0.0f, originAlt, 0.0f)); - - GLuint program = gpu::GLBackend::getShaderID(_skyShader); static int firstTime = 0; if (firstTime == 0) { firstTime++; - gpu::Shader::makeProgram(*_skyShader); + bool result = gpu::Shader::makeProgram(*(_skyPipeline->getProgram())); + } } diff --git a/libraries/model/src/model/Stage.h b/libraries/model/src/model/Stage.h index 4de0edb96b..61914b5a6b 100644 --- a/libraries/model/src/model/Stage.h +++ b/libraries/model/src/model/Stage.h @@ -11,7 +11,7 @@ #ifndef hifi_model_Stage_h #define hifi_model_Stage_h -#include "gpu/Shader.h" +#include "gpu/Pipeline.h" #include "Light.h" @@ -145,7 +145,7 @@ public: protected: LightPointer _sunLight; - gpu::ShaderPointer _skyShader; + gpu::PipelinePointer _skyPipeline; float _dayTime; int _yearTime; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 8f8f19c72a..80781c3522 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -299,7 +299,7 @@ void Model::initJointTransforms() { void Model::init() { if (!_program.isLinked()) { -/* +/* //Work in progress not used yet gpu::Shader::BindingSet slotBindings; slotBindings.insert(gpu::Shader::Binding(std::string("materialBuffer"), 1)); slotBindings.insert(gpu::Shader::Binding(std::string("diffuseMap"), 0)); From ee5409b0a8c4a9e8e6d4d7b89872ed6a90ddec6a Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 9 Mar 2015 14:25:59 -0700 Subject: [PATCH 6/8] fixing compilation on macosx --- libraries/gpu/src/gpu/GLBackendShader.cpp | 616 +++++++++++----------- libraries/model/src/model/Stage.cpp | 9 +- 2 files changed, 316 insertions(+), 309 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackendShader.cpp b/libraries/gpu/src/gpu/GLBackendShader.cpp index 8adce580a5..9bcc278d8e 100755 --- a/libraries/gpu/src/gpu/GLBackendShader.cpp +++ b/libraries/gpu/src/gpu/GLBackendShader.cpp @@ -29,13 +29,13 @@ GLBackend::GLShader::~GLShader() { } void makeBindings(GLBackend::GLShader* shader) { - if(!shader || !shader->_program) { - return; - } - GLuint glprogram = shader->_program; - GLint loc = -1; - - //Check for gpu specific attribute slotBindings + if(!shader || !shader->_program) { + return; + } + GLuint glprogram = shader->_program; + GLint loc = -1; + + //Check for gpu specific attribute slotBindings loc = glGetAttribLocation(glprogram, "position"); if (loc >= 0) { glBindAttribLocation(glprogram, gpu::Stream::POSITION, "position"); @@ -74,234 +74,235 @@ void makeBindings(GLBackend::GLShader* shader) { loc = glGetAttribLocation(glprogram, "clusterWeights"); if (loc >= 0) { glBindAttribLocation(glprogram, gpu::Stream::SKIN_CLUSTER_WEIGHT, "clusterWeights"); - } - - // Link again to take into account the assigned attrib location - glLinkProgram(glprogram); - - GLint linked = 0; - glGetProgramiv(glprogram, GL_LINK_STATUS, &linked); - if (!linked) { - qDebug() << "GLShader::makeBindings - failed to link after assigning slotBindings?"; - } - - // now assign the ubo binding, then DON't relink! - - //Check for gpu specific uniform slotBindings - loc = glGetUniformBlockIndex(glprogram, "transformObjectBuffer"); - if (loc >= 0) { - glUniformBlockBinding(glprogram, loc, gpu::TRANSFORM_OBJECT_SLOT); - shader->_transformObjectSlot = gpu::TRANSFORM_OBJECT_SLOT; - } - - loc = glGetUniformBlockIndex(glprogram, "transformCameraBuffer"); - if (loc >= 0) { - glUniformBlockBinding(glprogram, loc, gpu::TRANSFORM_CAMERA_SLOT); - shader->_transformCameraSlot = gpu::TRANSFORM_OBJECT_SLOT; } + // Link again to take into account the assigned attrib location + glLinkProgram(glprogram); + + GLint linked = 0; + glGetProgramiv(glprogram, GL_LINK_STATUS, &linked); + if (!linked) { + qDebug() << "GLShader::makeBindings - failed to link after assigning slotBindings?"; + } + + // now assign the ubo binding, then DON't relink! + + //Check for gpu specific uniform slotBindings +#if defined(Q_OS_WIN) + loc = glGetUniformBlockIndex(glprogram, "transformObjectBuffer"); + if (loc >= 0) { + glUniformBlockBinding(glprogram, loc, gpu::TRANSFORM_OBJECT_SLOT); + shader->_transformObjectSlot = gpu::TRANSFORM_OBJECT_SLOT; + } + + loc = glGetUniformBlockIndex(glprogram, "transformCameraBuffer"); + if (loc >= 0) { + glUniformBlockBinding(glprogram, loc, gpu::TRANSFORM_CAMERA_SLOT); + shader->_transformCameraSlot = gpu::TRANSFORM_OBJECT_SLOT; + } +#endif } GLBackend::GLShader* compileShader(const Shader& shader) { - // 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 nullptr; - } - - // 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 object"; - return nullptr; - } - - // 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 << std::string(temp); - filestream.close(); - } - */ - delete[] temp; - - glDeleteShader(glshader); - return nullptr; - } - - GLuint glprogram = 0; -#ifdef SEPARATE_PROGRAM - // 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 nullptr; - } - - 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 nullptr; - } -#endif - - // So far so good, the shader is created successfully - GLBackend::GLShader* object = new GLBackend::GLShader(); - object->_shader = glshader; - object->_program = glprogram; - - makeBindings(object); - - return 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 nullptr; + } + + // 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 object"; + return nullptr; + } + + // 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 << std::string(temp); + filestream.close(); + } + */ + delete[] temp; + + glDeleteShader(glshader); + return nullptr; + } + + GLuint glprogram = 0; +#ifdef SEPARATE_PROGRAM + // 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 nullptr; + } + + 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 nullptr; + } +#endif + + // So far so good, the shader is created successfully + GLBackend::GLShader* object = new GLBackend::GLShader(); + object->_shader = glshader; + object->_program = glprogram; + + makeBindings(object); + + return object; } GLBackend::GLShader* compileProgram(const Shader& program) { - if(!program.isProgram()) { - return nullptr; - } - - // 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 nullptr; - } - 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 nullptr; - } - - // 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 << std::string(temp); - filestream.close(); - } - */ - delete[] temp; - - glDeleteProgram(glprogram); - return nullptr; - } - - // So far so good, the program is created successfully - GLBackend::GLShader* object = new GLBackend::GLShader(); - object->_shader = 0; - object->_program = glprogram; - - makeBindings(object); - - return object; + if(!program.isProgram()) { + return nullptr; + } + + // 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 nullptr; + } + 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 nullptr; + } + + // 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 << std::string(temp); + filestream.close(); + } + */ + delete[] temp; + + glDeleteProgram(glprogram); + return nullptr; + } + + // So far so good, the program is created successfully + GLBackend::GLShader* object = new GLBackend::GLShader(); + object->_shader = 0; + object->_program = glprogram; + + makeBindings(object); + + return object; } GLBackend::GLShader* GLBackend::syncGPUObject(const Shader& shader) { @@ -360,127 +361,135 @@ ElementResource getFormatFromGLUniform(GLenum gltype) { case GL_FLOAT_VEC2: return ElementResource(Element(VEC2, gpu::FLOAT, UNIFORM), Resource::BUFFER); case GL_FLOAT_VEC3: return ElementResource(Element(VEC3, gpu::FLOAT, UNIFORM), Resource::BUFFER); case GL_FLOAT_VEC4: return ElementResource(Element(VEC4, gpu::FLOAT, UNIFORM), Resource::BUFFER); - +/* case GL_DOUBLE: return ElementResource(Element(SCALAR, gpu::FLOAT, UNIFORM), Resource::BUFFER); case GL_DOUBLE_VEC2: return ElementResource(Element(VEC2, gpu::FLOAT, UNIFORM), Resource::BUFFER); case GL_DOUBLE_VEC3: return ElementResource(Element(VEC3, gpu::FLOAT, UNIFORM), Resource::BUFFER); case GL_DOUBLE_VEC4: return ElementResource(Element(VEC4, gpu::FLOAT, UNIFORM), Resource::BUFFER); - +*/ case GL_INT: return ElementResource(Element(SCALAR, gpu::INT32, UNIFORM), Resource::BUFFER); case GL_INT_VEC2: return ElementResource(Element(VEC2, gpu::INT32, UNIFORM), Resource::BUFFER); case GL_INT_VEC3: return ElementResource(Element(VEC3, gpu::INT32, UNIFORM), Resource::BUFFER); case GL_INT_VEC4: return ElementResource(Element(VEC4, gpu::INT32, UNIFORM), Resource::BUFFER); - + case GL_UNSIGNED_INT: return ElementResource(Element(SCALAR, gpu::UINT32, UNIFORM), Resource::BUFFER); +#if defined(Q_OS_WIN) case GL_UNSIGNED_INT_VEC2: return ElementResource(Element(VEC2, gpu::UINT32, UNIFORM), Resource::BUFFER); case GL_UNSIGNED_INT_VEC3: return ElementResource(Element(VEC3, gpu::UINT32, UNIFORM), Resource::BUFFER); case GL_UNSIGNED_INT_VEC4: return ElementResource(Element(VEC4, gpu::UINT32, UNIFORM), Resource::BUFFER); - +#endif + case GL_BOOL: return ElementResource(Element(SCALAR, gpu::BOOL, UNIFORM), Resource::BUFFER); case GL_BOOL_VEC2: return ElementResource(Element(VEC2, gpu::BOOL, UNIFORM), Resource::BUFFER); case GL_BOOL_VEC3: return ElementResource(Element(VEC3, gpu::BOOL, UNIFORM), Resource::BUFFER); case GL_BOOL_VEC4: return ElementResource(Element(VEC4, gpu::BOOL, UNIFORM), Resource::BUFFER); - - + + case GL_FLOAT_MAT2: return ElementResource(Element(gpu::MAT2, gpu::FLOAT, UNIFORM), Resource::BUFFER); case GL_FLOAT_MAT3: return ElementResource(Element(MAT3, gpu::FLOAT, UNIFORM), Resource::BUFFER); case GL_FLOAT_MAT4: return ElementResource(Element(MAT4, gpu::FLOAT, UNIFORM), Resource::BUFFER); - -/* {GL_FLOAT_MAT2x3 mat2x3}, - {GL_FLOAT_MAT2x4 mat2x4}, - {GL_FLOAT_MAT3x2 mat3x2}, - {GL_FLOAT_MAT3x4 mat3x4}, - {GL_FLOAT_MAT4x2 mat4x2}, - {GL_FLOAT_MAT4x3 mat4x3}, - {GL_DOUBLE_MAT2 dmat2}, - {GL_DOUBLE_MAT3 dmat3}, - {GL_DOUBLE_MAT4 dmat4}, - {GL_DOUBLE_MAT2x3 dmat2x3}, - {GL_DOUBLE_MAT2x4 dmat2x4}, - {GL_DOUBLE_MAT3x2 dmat3x2}, - {GL_DOUBLE_MAT3x4 dmat3x4}, - {GL_DOUBLE_MAT4x2 dmat4x2}, - {GL_DOUBLE_MAT4x3 dmat4x3}, - */ - + +/* {GL_FLOAT_MAT2x3 mat2x3}, + {GL_FLOAT_MAT2x4 mat2x4}, + {GL_FLOAT_MAT3x2 mat3x2}, + {GL_FLOAT_MAT3x4 mat3x4}, + {GL_FLOAT_MAT4x2 mat4x2}, + {GL_FLOAT_MAT4x3 mat4x3}, + {GL_DOUBLE_MAT2 dmat2}, + {GL_DOUBLE_MAT3 dmat3}, + {GL_DOUBLE_MAT4 dmat4}, + {GL_DOUBLE_MAT2x3 dmat2x3}, + {GL_DOUBLE_MAT2x4 dmat2x4}, + {GL_DOUBLE_MAT3x2 dmat3x2}, + {GL_DOUBLE_MAT3x4 dmat3x4}, + {GL_DOUBLE_MAT4x2 dmat4x2}, + {GL_DOUBLE_MAT4x3 dmat4x3}, + */ + case GL_SAMPLER_1D: return ElementResource(Element(SCALAR, gpu::FLOAT, SAMPLER), Resource::TEXTURE_1D); case GL_SAMPLER_2D: return ElementResource(Element(SCALAR, gpu::FLOAT, SAMPLER), Resource::TEXTURE_2D); - case GL_SAMPLER_2D_MULTISAMPLE: return ElementResource(Element(SCALAR, gpu::FLOAT, SAMPLER_MULTISAMPLE), Resource::TEXTURE_2D); + case GL_SAMPLER_3D: return ElementResource(Element(SCALAR, gpu::FLOAT, SAMPLER), Resource::TEXTURE_3D); case GL_SAMPLER_CUBE: return ElementResource(Element(SCALAR, gpu::FLOAT, SAMPLER), Resource::TEXTURE_CUBE); - + +#if defined(Q_OS_WIN) + case GL_SAMPLER_2D_MULTISAMPLE: return ElementResource(Element(SCALAR, gpu::FLOAT, SAMPLER_MULTISAMPLE), Resource::TEXTURE_2D); case GL_SAMPLER_1D_ARRAY: return ElementResource(Element(SCALAR, gpu::FLOAT, SAMPLER), Resource::TEXTURE_1D_ARRAY); case GL_SAMPLER_2D_ARRAY: return ElementResource(Element(SCALAR, gpu::FLOAT, SAMPLER), Resource::TEXTURE_2D_ARRAY); case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: return ElementResource(Element(SCALAR, gpu::FLOAT, SAMPLER_MULTISAMPLE), Resource::TEXTURE_2D_ARRAY); - +#endif + case GL_SAMPLER_2D_SHADOW: return ElementResource(Element(SCALAR, gpu::FLOAT, SAMPLER_SHADOW), Resource::TEXTURE_2D); +#if defined(Q_OS_WIN) case GL_SAMPLER_CUBE_SHADOW: return ElementResource(Element(SCALAR, gpu::FLOAT, SAMPLER_SHADOW), Resource::TEXTURE_CUBE); case GL_SAMPLER_2D_ARRAY_SHADOW: return ElementResource(Element(SCALAR, gpu::FLOAT, SAMPLER_SHADOW), Resource::TEXTURE_2D_ARRAY); - -// {GL_SAMPLER_1D_SHADOW sampler1DShadow}, - // {GL_SAMPLER_1D_ARRAY_SHADOW sampler1DArrayShadow}, - -// {GL_SAMPLER_BUFFER samplerBuffer}, -// {GL_SAMPLER_2D_RECT sampler2DRect}, - // {GL_SAMPLER_2D_RECT_SHADOW sampler2DRectShadow}, - +#endif + +// {GL_SAMPLER_1D_SHADOW sampler1DShadow}, + // {GL_SAMPLER_1D_ARRAY_SHADOW sampler1DArrayShadow}, + +// {GL_SAMPLER_BUFFER samplerBuffer}, +// {GL_SAMPLER_2D_RECT sampler2DRect}, + // {GL_SAMPLER_2D_RECT_SHADOW sampler2DRectShadow}, + +#if defined(Q_OS_WIN) case GL_INT_SAMPLER_1D: return ElementResource(Element(SCALAR, gpu::INT32, SAMPLER), Resource::TEXTURE_1D); case GL_INT_SAMPLER_2D: return ElementResource(Element(SCALAR, gpu::INT32, SAMPLER), Resource::TEXTURE_2D); case GL_INT_SAMPLER_2D_MULTISAMPLE: return ElementResource(Element(SCALAR, gpu::INT32, SAMPLER_MULTISAMPLE), Resource::TEXTURE_2D); case GL_INT_SAMPLER_3D: return ElementResource(Element(SCALAR, gpu::INT32, SAMPLER), Resource::TEXTURE_3D); case GL_INT_SAMPLER_CUBE: return ElementResource(Element(SCALAR, gpu::INT32, SAMPLER), Resource::TEXTURE_CUBE); - + case GL_INT_SAMPLER_1D_ARRAY: return ElementResource(Element(SCALAR, gpu::INT32, SAMPLER), Resource::TEXTURE_1D_ARRAY); case GL_INT_SAMPLER_2D_ARRAY: return ElementResource(Element(SCALAR, gpu::INT32, SAMPLER), Resource::TEXTURE_2D_ARRAY); case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: return ElementResource(Element(SCALAR, gpu::INT32, SAMPLER_MULTISAMPLE), Resource::TEXTURE_2D_ARRAY); - - // {GL_INT_SAMPLER_BUFFER isamplerBuffer}, - // {GL_INT_SAMPLER_2D_RECT isampler2DRect}, - + + // {GL_INT_SAMPLER_BUFFER isamplerBuffer}, + // {GL_INT_SAMPLER_2D_RECT isampler2DRect}, + case GL_UNSIGNED_INT_SAMPLER_1D: return ElementResource(Element(SCALAR, gpu::UINT32, SAMPLER), Resource::TEXTURE_1D); case GL_UNSIGNED_INT_SAMPLER_2D: return ElementResource(Element(SCALAR, gpu::UINT32, SAMPLER), Resource::TEXTURE_2D); case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: return ElementResource(Element(SCALAR, gpu::UINT32, SAMPLER_MULTISAMPLE), Resource::TEXTURE_2D); case GL_UNSIGNED_INT_SAMPLER_3D: return ElementResource(Element(SCALAR, gpu::UINT32, SAMPLER), Resource::TEXTURE_3D); case GL_UNSIGNED_INT_SAMPLER_CUBE: return ElementResource(Element(SCALAR, gpu::UINT32, SAMPLER), Resource::TEXTURE_CUBE); - + case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY: return ElementResource(Element(SCALAR, gpu::UINT32, SAMPLER), Resource::TEXTURE_1D_ARRAY); case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: return ElementResource(Element(SCALAR, gpu::UINT32, SAMPLER), Resource::TEXTURE_2D_ARRAY); case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: return ElementResource(Element(SCALAR, gpu::UINT32, SAMPLER_MULTISAMPLE), Resource::TEXTURE_2D_ARRAY); - -// {GL_UNSIGNED_INT_SAMPLER_BUFFER usamplerBuffer}, -// {GL_UNSIGNED_INT_SAMPLER_2D_RECT usampler2DRect}, -/* - {GL_IMAGE_1D image1D}, - {GL_IMAGE_2D image2D}, - {GL_IMAGE_3D image3D}, - {GL_IMAGE_2D_RECT image2DRect}, - {GL_IMAGE_CUBE imageCube}, - {GL_IMAGE_BUFFER imageBuffer}, - {GL_IMAGE_1D_ARRAY image1DArray}, - {GL_IMAGE_2D_ARRAY image2DArray}, - {GL_IMAGE_2D_MULTISAMPLE image2DMS}, - {GL_IMAGE_2D_MULTISAMPLE_ARRAY image2DMSArray}, - {GL_INT_IMAGE_1D iimage1D}, - {GL_INT_IMAGE_2D iimage2D}, - {GL_INT_IMAGE_3D iimage3D}, - {GL_INT_IMAGE_2D_RECT iimage2DRect}, - {GL_INT_IMAGE_CUBE iimageCube}, - {GL_INT_IMAGE_BUFFER iimageBuffer}, - {GL_INT_IMAGE_1D_ARRAY iimage1DArray}, - {GL_INT_IMAGE_2D_ARRAY iimage2DArray}, - {GL_INT_IMAGE_2D_MULTISAMPLE iimage2DMS}, - {GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY iimage2DMSArray}, - {GL_UNSIGNED_INT_IMAGE_1D uimage1D}, - {GL_UNSIGNED_INT_IMAGE_2D uimage2D}, - {GL_UNSIGNED_INT_IMAGE_3D uimage3D}, - {GL_UNSIGNED_INT_IMAGE_2D_RECT uimage2DRect}, - {GL_UNSIGNED_INT_IMAGE_CUBE uimageCube},+ [0] {_name="fInnerRadius" _location=0 _element={_semantic=15 '\xf' _dimension=0 '\0' _type=0 '\0' } } gpu::Shader::Slot - - {GL_UNSIGNED_INT_IMAGE_BUFFER uimageBuffer}, - {GL_UNSIGNED_INT_IMAGE_1D_ARRAY uimage1DArray}, - {GL_UNSIGNED_INT_IMAGE_2D_ARRAY uimage2DArray}, - {GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE uimage2DMS}, +#endif +// {GL_UNSIGNED_INT_SAMPLER_BUFFER usamplerBuffer}, +// {GL_UNSIGNED_INT_SAMPLER_2D_RECT usampler2DRect}, +/* + {GL_IMAGE_1D image1D}, + {GL_IMAGE_2D image2D}, + {GL_IMAGE_3D image3D}, + {GL_IMAGE_2D_RECT image2DRect}, + {GL_IMAGE_CUBE imageCube}, + {GL_IMAGE_BUFFER imageBuffer}, + {GL_IMAGE_1D_ARRAY image1DArray}, + {GL_IMAGE_2D_ARRAY image2DArray}, + {GL_IMAGE_2D_MULTISAMPLE image2DMS}, + {GL_IMAGE_2D_MULTISAMPLE_ARRAY image2DMSArray}, + {GL_INT_IMAGE_1D iimage1D}, + {GL_INT_IMAGE_2D iimage2D}, + {GL_INT_IMAGE_3D iimage3D}, + {GL_INT_IMAGE_2D_RECT iimage2DRect}, + {GL_INT_IMAGE_CUBE iimageCube}, + {GL_INT_IMAGE_BUFFER iimageBuffer}, + {GL_INT_IMAGE_1D_ARRAY iimage1DArray}, + {GL_INT_IMAGE_2D_ARRAY iimage2DArray}, + {GL_INT_IMAGE_2D_MULTISAMPLE iimage2DMS}, + {GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY iimage2DMSArray}, + {GL_UNSIGNED_INT_IMAGE_1D uimage1D}, + {GL_UNSIGNED_INT_IMAGE_2D uimage2D}, + {GL_UNSIGNED_INT_IMAGE_3D uimage3D}, + {GL_UNSIGNED_INT_IMAGE_2D_RECT uimage2DRect}, + {GL_UNSIGNED_INT_IMAGE_CUBE uimageCube},+ [0] {_name="fInnerRadius" _location=0 _element={_semantic=15 '\xf' _dimension=0 '\0' _type=0 '\0' } } gpu::Shader::Slot + + {GL_UNSIGNED_INT_IMAGE_BUFFER uimageBuffer}, + {GL_UNSIGNED_INT_IMAGE_1D_ARRAY uimage1DArray}, + {GL_UNSIGNED_INT_IMAGE_2D_ARRAY uimage2DArray}, + {GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE uimage2DMS}, {GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY uimage2DMSArray}, {GL_UNSIGNED_INT_ATOMIC_COUNTER atomic_uint} */ @@ -542,6 +551,7 @@ bool isUnusedSlot(GLint binding) { int makeUniformBlockSlots(GLuint glprogram, const Shader::BindingSet& slotBindings, Shader::SlotSet& buffers) { GLint buffersCount = 0; +#if defined(Q_OS_WIN) glGetProgramiv(glprogram, GL_ACTIVE_UNIFORM_BLOCKS, &buffersCount); // fast exit @@ -595,7 +605,7 @@ int makeUniformBlockSlots(GLuint glprogram, const Shader::BindingSet& slotBindin Element element(SCALAR, gpu::UINT32, gpu::UNIFORM_BUFFER); buffers.insert(Shader::Slot(name, binding, element, Resource::BUFFER)); } - +#endif return buffersCount; } diff --git a/libraries/model/src/model/Stage.cpp b/libraries/model/src/model/Stage.cpp index e4786df792..473d3c7613 100644 --- a/libraries/model/src/model/Stage.cpp +++ b/libraries/model/src/model/Stage.cpp @@ -154,12 +154,9 @@ SunSkyStage::SunSkyStage() : // Begining of march setYearTime(60.0f); - auto skyShader = gpu::ShaderPointer( - gpu::Shader::createProgram( - gpu::ShaderPointer(gpu::Shader::createVertex(std::string(SkyFromAtmosphere_vert))), - gpu::ShaderPointer(gpu::Shader::createPixel(std::string(SkyFromAtmosphere_frag))) - ) - ); + auto skyFromAtmosphereVertex = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(SkyFromAtmosphere_vert))); + auto skyFromAtmosphereFragment = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(SkyFromAtmosphere_frag))); + auto skyShader = gpu::ShaderPointer(gpu::Shader::createProgram(skyFromAtmosphereVertex, skyFromAtmosphereFragment)); _skyPipeline = gpu::PipelinePointer(gpu::Pipeline::create(skyShader, gpu::States())); } From d9c071a2a9a6ed4c471a0efa498330b942724baf Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 10 Mar 2015 00:47:27 -0700 Subject: [PATCH 7/8] trying to put the atmospheric effect in a shader header and use it on the directional lighting pass --- libraries/gpu/src/gpu/Pipeline.h | 2 +- libraries/model/src/model/Atmosphere.slh | 244 ++++++++++++++++++ libraries/model/src/model/Stage.cpp | 50 ++++ libraries/model/src/model/Stage.h | 56 ++++ .../render-utils/src/DeferredGlobalLight.slh | 10 + .../src/DeferredLightingEffect.cpp | 31 +++ .../render-utils/src/DeferredLightingEffect.h | 4 + tools/scribe/src/main.cpp | 12 +- 8 files changed, 406 insertions(+), 3 deletions(-) create mode 100755 libraries/model/src/model/Atmosphere.slh diff --git a/libraries/gpu/src/gpu/Pipeline.h b/libraries/gpu/src/gpu/Pipeline.h index c2fc944bb7..faa671c30f 100755 --- a/libraries/gpu/src/gpu/Pipeline.h +++ b/libraries/gpu/src/gpu/Pipeline.h @@ -44,7 +44,7 @@ protected: friend class Backend; }; -typedef QSharedPointer< Pipeline > PipelinePointer; +typedef std::shared_ptr< Pipeline > PipelinePointer; typedef std::vector< PipelinePointer > Pipelines; }; diff --git a/libraries/model/src/model/Atmosphere.slh b/libraries/model/src/model/Atmosphere.slh new file mode 100755 index 0000000000..11b64dde70 --- /dev/null +++ b/libraries/model/src/model/Atmosphere.slh @@ -0,0 +1,244 @@ + +<@if not MODEL_ATMOSPHERE_SLH@> +<@def MODEL_ATMOSPHERE_SLH@> + + + +struct Atmosphere { + vec4 _invWaveLength; + vec4 _radiuses; + vec4 _scales; + vec4 _scatterings; + vec4 _control; +}; + +const int numSamples = 2; + +vec3 getAtmosphereInvWaveLength(Atmosphere a) { return a._invWaveLength.xyz; } // 1 / pow(wavelength, 4) for the red, green, and blue channels + +float getAtmosphereInnerRadius(Atmosphere a) { return a._radiuses.x; } // The inner (planetary) radius +float getAtmosphereOuterRadius(Atmosphere a) { return a._radiuses.y; } // The outer (atmosphere) radius + +float getAtmosphereScale(Atmosphere a) { return a._scales.x; } // 1 / (outerRadius - innerRadius) +float getAtmosphereScaleDepth(Atmosphere a) { return a._scales.y; } // The scale depth (i.e. the altitude at which the atmosphere's average density is found) +float getAtmosphereScaleOverScaleDepth(Atmosphere a) { return a._scales.z; } // scale / scaleDepth + +vec4 getAtmosphereScattering(Atmosphere a) { return a._scatterings; } // The full Mie and Rayleigh scattering coefficients +float getAtmosphereKrESun(Atmosphere a) { return a._scatterings.x; } // Kr * ESun +float getAtmosphereKmESun(Atmosphere a) { return a._scatterings.y; } // Km * ESun +float getAtmosphereKr4PI(Atmosphere a) { return a._scatterings.z; } // Kr * 4 * PI +float getAtmosphereKm4PI(Atmosphere a) { return a._scatterings.w; } // Km * 4 * PI + +float getAtmosphereNumSamples(Atmosphere a) { return a._control.x; } // numSamples +vec2 getAtmosphereGAndG2(Atmosphere a) { return a._control.yz; } // g and g2 + +float atmosphereScale(float scaleDepth, float fCos) +{ + float x = 1.0 - fCos; + return scaleDepth * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25)))); +} + +vec4 evalAtmosphereContribution(Atmosphere atmospheric, vec3 position, vec3 cameraPos, vec3 lightPos) { + float fInnerRadius = getAtmosphereInnerRadius(atmospheric); + float fSamples = getAtmosphereNumSamples(atmospheric); + + vec3 v3InvWavelength = getAtmosphereInvWaveLength(atmospheric); + vec4 scatteringCoefs = getAtmosphereScattering(atmospheric); + float fKrESun = scatteringCoefs.x; + float fKmESun = scatteringCoefs.y; + float fKr4PI = scatteringCoefs.z; + float fKm4PI = scatteringCoefs.w; + + vec2 gAndg2 = getAtmosphereGAndG2(atmospheric); + float g = gAndg2.x; + float g2 = gAndg2.y; + + float fScale = getAtmosphereScale(atmospheric); + float fScaleDepth = getAtmosphereScaleDepth(atmospheric); + float fScaleOverScaleDepth = getAtmosphereScaleOverScaleDepth(atmospheric); + + // 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 - cameraPos; + float fFar = length(v3Ray); + v3Ray /= fFar; + + // Calculate the ray's starting position, then calculate its scattering offset + vec3 v3Start = cameraPos; + float fHeight = length(v3Start); + float fDepthStart = exp(fScaleOverScaleDepth * (fInnerRadius - fHeight)); + float fStartAngle = dot(v3Ray, v3Start) / fHeight; + float fStartOffset = fDepthStart * atmosphereScale(fScaleDepth, 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); + int nSamples = numSamples; + // int nSamples = int(fSamples); + for(int i=0; i +uniform atmosphereBuffer { + Atmosphere _atmosphere; +}; +Atmosphere getAtmosphere() { + return _atmosphere; +} +<@else@> +uniform vec4 atmosphereBuffer[9]; +Atmosphere getAtmosphere() { + Atmosphere atmosphere; + atmosphere._invWaveLength = atmosphereBuffer[0]; + atmosphere._radiuses = atmosphereBuffer[1]; + atmosphere._scales = atmosphereBuffer[2]; + atmosphere._scatterings = atmosphereBuffer[3]; + atmosphere._control = atmosphereBuffer[4]; + + return atmosphere; +} +<@endif@> + + + +<@endif@> diff --git a/libraries/model/src/model/Stage.cpp b/libraries/model/src/model/Stage.cpp index 473d3c7613..970539a908 100644 --- a/libraries/model/src/model/Stage.cpp +++ b/libraries/model/src/model/Stage.cpp @@ -134,6 +134,56 @@ void EarthSunModel::setSunLongitude(float lon) { _sunLongitude = validateLongitude(lon); invalidate(); } + +Atmosphere::Atmosphere() { + // only if created from nothing shall we create the Buffer to store the properties + Data data; + _dataBuffer = gpu::BufferView(new gpu::Buffer(sizeof(Data), (const gpu::Buffer::Byte*) &data)); + + setScatteringWavelength(_scatteringWavelength); + setRayleighScattering(_rayleighScattering); + setInnerOuterRadiuses(getInnerRadius(), getOuterRadius()); +} + +void Atmosphere::setScatteringWavelength(Vec3 wavelength) { + _scatteringWavelength = wavelength; + Data& data = editData(); + data._invWaveLength = Vec4(1.0f / powf(wavelength.x, 4.0f), 1.0f / powf(wavelength.y, 4.0f), 1.0f / powf(wavelength.z, 4.0f), 0.0f); +} + +void Atmosphere::setRayleighScattering(float scattering) { + _rayleighScattering = scattering; + updateScattering(); +} + +void Atmosphere::setMieScattering(float scattering) { + _mieScattering = scattering; + updateScattering(); +} + +void Atmosphere::setSunBrightness(float brightness) { + _sunBrightness = brightness; + updateScattering(); +} + +void Atmosphere::updateScattering() { + Data& data = editData(); + + data._scatterings.x = getRayleighScattering() * getSunBrightness(); + data._scatterings.y = getMieScattering() * getSunBrightness(); + + data._scatterings.z = getRayleighScattering() * 4.0f * glm::pi(); + data._scatterings.w = getMieScattering() * 4.0f * glm::pi(); +} + +void Atmosphere::setInnerOuterRadiuses(float inner, float outer) { + Data& data = editData(); + data._radiuses.x = inner; + data._radiuses.y = outer; + data._scales.x = 1.0f / (outer - inner); + data._scales.z = data._scales.x / data._scales.y; +} + const int NUM_DAYS_PER_YEAR = 365; const float NUM_HOURS_PER_DAY = 24.0f; diff --git a/libraries/model/src/model/Stage.h b/libraries/model/src/model/Stage.h index 61914b5a6b..3cc8b4a6e9 100644 --- a/libraries/model/src/model/Stage.h +++ b/libraries/model/src/model/Stage.h @@ -106,6 +106,60 @@ protected: static Mat4d evalWorldToGeoLocationMat(double longitude, double latitude, double altitude, double scale); }; + +class Atmosphere { +public: + + Atmosphere(); + Atmosphere(const Atmosphere& atmosphere); + Atmosphere& operator= (const Atmosphere& atmosphere); + virtual ~Atmosphere() {}; + + + void setScatteringWavelength(Vec3 wavelength); + const Vec3& getScatteringWavelength() const { return _scatteringWavelength; } + + void setRayleighScattering(float scattering); + float getRayleighScattering() const { return _rayleighScattering; } + + void setMieScattering(float scattering); + float getMieScattering() const { return _mieScattering; } + + void setSunBrightness(float brightness); + float getSunBrightness() const { return _sunBrightness; } + + void setInnerOuterRadiuses(float inner, float outer); + float getInnerRadius() const { return getData()._radiuses.x; } + float getOuterRadius() const { return getData()._radiuses.y; } + + // Data to access the attribute values of the atmosphere + class Data { + public: + Vec4 _invWaveLength = Vec4(0.0f); + Vec4 _radiuses = Vec4(6000.0f, 6025.0f, 0.0f, 0.0f); + Vec4 _scales = Vec4(0.0f, 0.25f, 0.0f, 0.0f); + Vec4 _scatterings = Vec4(0.0f); + Vec4 _control = Vec4(2.0f, -0.990f, -0.990f*-0.990f, 0.f); + + Data() {} + }; + + const UniformBufferView& getDataBuffer() const { return _dataBuffer; } + +protected: + UniformBufferView _dataBuffer; + Vec3 _scatteringWavelength = Vec3(0.650f, 0.570f, 0.475f); + float _rayleighScattering = 0.0025f; + float _mieScattering = 0.0010f; + float _sunBrightness = 20.0f; + + const Data& getData() const { return _dataBuffer.get(); } + Data& editData() { return _dataBuffer.edit(); } + + void updateScattering(); +}; +typedef QSharedPointer< Atmosphere > AtmospherePointer; + // Sun sky stage generates the rendering primitives to display a scene realistically // at the specified location and time around earth class SunSkyStage { @@ -141,9 +195,11 @@ public: float getSunIntensity() const { return getSunLight()->getIntensity(); } LightPointer getSunLight() const { valid(); return _sunLight; } + AtmospherePointer getAtmosphere() const { valid(); return _atmosphere; } protected: LightPointer _sunLight; + AtmospherePointer _atmosphere; gpu::PipelinePointer _skyPipeline; diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh index 3039c92d67..b48b61fd9f 100755 --- a/libraries/render-utils/src/DeferredGlobalLight.slh +++ b/libraries/render-utils/src/DeferredGlobalLight.slh @@ -13,6 +13,7 @@ <@include DeferredLighting.slh@> + struct SphericalHarmonics { vec4 L00; vec4 L1m1; @@ -50,6 +51,7 @@ uniform SphericalHarmonics ambientSphere; // Everything about light <@include model/Light.slh@> +<@include model/Atmosphere.slh@> // The view Matrix uniform mat4 invViewMat; @@ -89,6 +91,14 @@ vec3 evalAmbienSphereGlobalColor(float shadowAttenuation, vec3 position, vec3 no color += vec3(diffuse + shading.rgb) * shading.w * shadowAttenuation * getLightColor(light) * getLightIntensity(light); + + vec3 fragPos = vec3(invViewMat * vec4(position, 1.0)); + vec3 cameraPos = invViewMat[3].xyz; + vec3 lightPos = 10000.0 * getLightDirection(light); + + Atmosphere atmo = getAtmosphere(); + vec4 atmoColor = evalAtmosphereContribution(atmo, fragPos, cameraPos, lightPos); + return color; } diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index c8ad3711d3..96ab790cd6 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -270,6 +270,12 @@ void DeferredLightingEffect::render() { batch.setUniformBuffer(locations->lightBufferUnit, globalLight->getSchemaBuffer()); gpu::GLBackend::renderBatch(batch); } + + if (_atmosphere && (locations->atmosphereBufferUnit >= 0)) { + gpu::Batch batch; + batch.setUniformBuffer(locations->atmosphereBufferUnit, _atmosphere->getDataBuffer()); + gpu::GLBackend::renderBatch(batch); + } glUniformMatrix4fv(locations->invViewMat, 1, false, reinterpret_cast< const GLfloat* >(&invViewMat)); } @@ -511,6 +517,31 @@ void DeferredLightingEffect::loadLightProgram(const char* fragSource, bool limit locations.lightBufferUnit = -1; } #endif + +#if defined(Q_OS_MAC) + loc = program.uniformLocation("atmosphereBufferUnit"); + if (loc >= 0) { + locations.atmosphereBufferUnit = loc; + } else { + locations.atmosphereBufferUnit = -1; + } +#elif defined(Q_OS_WIN) + loc = glGetUniformBlockIndex(program.programId(), "atmosphereBufferUnit"); + if (loc >= 0) { + glUniformBlockBinding(program.programId(), loc, 1); + locations.atmosphereBufferUnit = 1; + } else { + locations.atmosphereBufferUnit = -1; + } +#else + loc = program.uniformLocation("atmosphereBufferUnit"); + if (loc >= 0) { + locations.atmosphereBufferUnit = loc; + } else { + locations.atmosphereBufferUnit = -1; + } +#endif + program.release(); } diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index 951c36f038..900c5243cb 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -20,6 +20,7 @@ #include "ProgramObject.h" #include "model/Light.h" +#include "model/Stage.h" class AbstractViewStateInterface; class PostLightingRenderable; @@ -73,6 +74,7 @@ public: // update global lighting void setAmbientLightMode(int preset); void setGlobalLight(const glm::vec3& direction, const glm::vec3& diffuse, float intensity); + void setGlobalAtmosphere(const model::AtmospherePointer& atmosphere) { _atmosphere = atmosphere; } private: DeferredLightingEffect() {} @@ -89,6 +91,7 @@ private: int radius; int ambientSphere; int lightBufferUnit; + int atmosphereBufferUnit; int invViewMat; }; @@ -146,6 +149,7 @@ private: AbstractViewStateInterface* _viewState; int _ambientLightMode = 0; + model::AtmospherePointer _atmosphere; }; /// Simple interface for objects that require something to be rendered after deferred lighting. diff --git a/tools/scribe/src/main.cpp b/tools/scribe/src/main.cpp index f68272c0ab..10f0a026ca 100755 --- a/tools/scribe/src/main.cpp +++ b/tools/scribe/src/main.cpp @@ -192,9 +192,17 @@ int main (int argc, char** argv) { targetStringStream << "#ifndef scribe_" << targetName << "_h" << std::endl; targetStringStream << "#define scribe_" << targetName << "_h" << std::endl << std::endl; - targetStringStream << "const char " << targetName << "[] = R\"XXXX(" << destStringStream.str() << ")XXXX\";"; + // targetStringStream << "const char " << targetName << "[] = R\"XXXX(" << destStringStream.str() << ")XXXX\";"; + std::istringstream destStringStreamAgain(destStringStream.str()); + targetStringStream << "const char " << targetName << "[] = \n"; + while (!destStringStreamAgain.eof()) { + std::string lineToken; + std::getline(destStringStreamAgain, lineToken); + // targetStringStream << "\"" << lineToken << "\"\n"; + targetStringStream << "R\"X(" << lineToken << ")X\"\"\\n\"\n"; + } - targetStringStream << std::endl << std::endl; + targetStringStream << ";\n" << std::endl << std::endl; targetStringStream << "#endif" << std::endl; } else { targetStringStream << destStringStream.str(); From da16baf0ca2d9e409600d481f8f15351c1dd7c2f Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 10 Mar 2015 10:24:16 -0700 Subject: [PATCH 8/8] removing the atmosphere effect from the directional lighting --- libraries/render-utils/src/DeferredGlobalLight.slh | 9 --------- 1 file changed, 9 deletions(-) diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh index b48b61fd9f..556e7421af 100755 --- a/libraries/render-utils/src/DeferredGlobalLight.slh +++ b/libraries/render-utils/src/DeferredGlobalLight.slh @@ -51,7 +51,6 @@ uniform SphericalHarmonics ambientSphere; // Everything about light <@include model/Light.slh@> -<@include model/Atmosphere.slh@> // The view Matrix uniform mat4 invViewMat; @@ -91,14 +90,6 @@ vec3 evalAmbienSphereGlobalColor(float shadowAttenuation, vec3 position, vec3 no color += vec3(diffuse + shading.rgb) * shading.w * shadowAttenuation * getLightColor(light) * getLightIntensity(light); - - vec3 fragPos = vec3(invViewMat * vec4(position, 1.0)); - vec3 cameraPos = invViewMat[3].xyz; - vec3 lightPos = 10000.0 * getLightDirection(light); - - Atmosphere atmo = getAtmosphere(); - vec4 atmoColor = evalAtmosphereContribution(atmo, fragPos, cameraPos, lightPos); - return color; }