739 lines
22 KiB
C++
739 lines
22 KiB
C++
/* This file is part of the Pangolin Project.
|
|
* http://github.com/stevenlovegrove/Pangolin
|
|
*
|
|
* Copyright (c) 2011 Steven Lovegrove
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person
|
|
* obtaining a copy of this software and associated documentation
|
|
* files (the "Software"), to deal in the Software without
|
|
* restriction, including without limitation the rights to use,
|
|
* copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following
|
|
* conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be
|
|
* included in all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
* OTHER DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <sstream>
|
|
#include <fstream>
|
|
#include <algorithm>
|
|
#include <vector>
|
|
#include <map>
|
|
#include <cctype>
|
|
|
|
#include <pangolin/gl/glplatform.h>
|
|
#include <pangolin/gl/colour.h>
|
|
#include <pangolin/utils/file_utils.h>
|
|
#include <pangolin/display/opengl_render_state.h>
|
|
|
|
#ifdef HAVE_GLES
|
|
#define GLhandleARB GLuint
|
|
#endif
|
|
|
|
#if defined(HAVE_EIGEN) && !defined(__CUDACC__) //prevent including Eigen in cuda files
|
|
#define USE_EIGEN
|
|
#endif
|
|
|
|
#ifdef USE_EIGEN
|
|
#include <Eigen/Core>
|
|
#endif // USE_EIGEN
|
|
|
|
namespace pangolin
|
|
{
|
|
|
|
////////////////////////////////////////////////
|
|
// Standard attribute locations
|
|
////////////////////////////////////////////////
|
|
|
|
const GLuint DEFAULT_LOCATION_POSITION = 0;
|
|
const GLuint DEFAULT_LOCATION_COLOUR = 1;
|
|
const GLuint DEFAULT_LOCATION_NORMAL = 2;
|
|
const GLuint DEFAULT_LOCATION_TEXCOORD = 3;
|
|
|
|
const char DEFAULT_NAME_POSITION[] = "a_position";
|
|
const char DEFAULT_NAME_COLOUR[] = "a_color";
|
|
const char DEFAULT_NAME_NORMAL[] = "a_normal";
|
|
const char DEFAULT_NAME_TEXCOORD[] = "a_texcoord";
|
|
|
|
////////////////////////////////////////////////
|
|
// Interface
|
|
////////////////////////////////////////////////
|
|
|
|
enum GlSlShaderType
|
|
{
|
|
GlSlAnnotatedShader = 0,
|
|
GlSlFragmentShader = GL_FRAGMENT_SHADER,
|
|
GlSlVertexShader = GL_VERTEX_SHADER,
|
|
GlSlGeometryShader = 0x8DD9 /*GL_GEOMETRY_SHADER*/,
|
|
GlSlComputeShader = 0x91B9 /*GL_COMPUTE_SHADER*/
|
|
};
|
|
|
|
class GlSlProgram
|
|
{
|
|
public:
|
|
GlSlProgram();
|
|
|
|
//! Move Constructor
|
|
GlSlProgram(GlSlProgram&& tex);
|
|
|
|
~GlSlProgram();
|
|
|
|
bool AddShader(
|
|
GlSlShaderType shader_type,
|
|
const std::string& source_code,
|
|
const std::map<std::string,std::string>& program_defines = std::map<std::string,std::string>(),
|
|
const std::vector<std::string>& search_path = std::vector<std::string>()
|
|
);
|
|
|
|
bool AddShaderFromFile(
|
|
GlSlShaderType shader_type,
|
|
const std::string& filename,
|
|
const std::map<std::string,std::string>& program_defines = std::map<std::string,std::string>(),
|
|
const std::vector<std::string>& search_path = std::vector<std::string>()
|
|
);
|
|
|
|
bool Link();
|
|
|
|
// Remove all shaders from this program, and reload from files.
|
|
bool ReloadShaderFiles();
|
|
|
|
GLint GetAttributeHandle(const std::string& name);
|
|
GLint GetUniformHandle(const std::string& name);
|
|
|
|
// Before setting uniforms, be sure to Bind() the GlSl program first.
|
|
void SetUniform(const std::string& name, int x);
|
|
void SetUniform(const std::string& name, int x1, int x2);
|
|
void SetUniform(const std::string& name, int x1, int x2, int x3);
|
|
void SetUniform(const std::string& name, int x1, int x2, int x3, int x4);
|
|
|
|
void SetUniform(const std::string& name, float f);
|
|
void SetUniform(const std::string& name, float f1, float f2);
|
|
void SetUniform(const std::string& name, float f1, float f2, float f3);
|
|
void SetUniform(const std::string& name, float f1, float f2, float f3, float f4);
|
|
|
|
void SetUniform(const std::string& name, Colour c);
|
|
|
|
void SetUniform(const std::string& name, const OpenGlMatrix& m);
|
|
|
|
#ifdef HAVE_EIGEN
|
|
void SetUniform(const std::string& name, const Eigen::Matrix3f& m);
|
|
void SetUniform(const std::string& name, const Eigen::Matrix4f& m);
|
|
void SetUniform(const std::string& name, const Eigen::Matrix3d& m);
|
|
void SetUniform(const std::string& name, const Eigen::Matrix4d& m);
|
|
#endif
|
|
|
|
#if GL_VERSION_4_3
|
|
GLint GetProgramResourceIndex(const std::string& name);
|
|
void SetShaderStorageBlock(const std::string& name, const int& bindingIndex);
|
|
#endif
|
|
|
|
void Bind();
|
|
void SaveBind();
|
|
void Unbind();
|
|
|
|
|
|
void BindPangolinDefaultAttribLocationsAndLink();
|
|
|
|
// Unlink all shaders from program
|
|
void ClearShaders();
|
|
|
|
GLint ProgramId() const {
|
|
return prog;
|
|
}
|
|
|
|
bool Valid() const {
|
|
return ProgramId() != 0;
|
|
}
|
|
|
|
protected:
|
|
struct ShaderFileOrCode
|
|
{
|
|
GlSlShaderType shader_type;
|
|
std::string filename;
|
|
std::string code;
|
|
std::map<std::string,std::string> program_defines;
|
|
std::vector<std::string> search_path;
|
|
};
|
|
|
|
|
|
// Convenience method to load shader description
|
|
bool AddShaderFile(const ShaderFileOrCode &shader_file);
|
|
|
|
std::string ParseIncludeFilename(
|
|
const std::string& location
|
|
);
|
|
|
|
std::string SearchIncludePath(
|
|
const std::string& filename,
|
|
const std::vector<std::string>& search_path,
|
|
const std::string& current_path
|
|
);
|
|
|
|
bool AddPreprocessedShader(
|
|
GlSlShaderType shader_type,
|
|
const std::string& source_code,
|
|
const std::string& name_for_errors
|
|
);
|
|
|
|
void PreprocessGLSL(
|
|
std::istream& input,
|
|
std::ostream& output,
|
|
const std::map<std::string,std::string>& program_defines,
|
|
const std::vector<std::string>& search_path,
|
|
const std::string& current_path
|
|
);
|
|
|
|
// Split 'code' into several code blocks per shader type
|
|
// shader blocks in 'code' must be annotated with:
|
|
// @start vertex, @start fragment, @start geometry or @start compute
|
|
static std::map<GlSlShaderType,std::string>
|
|
SplitAnnotatedShaders(const std::string& code);
|
|
|
|
bool linked;
|
|
std::vector<GLhandleARB> shaders;
|
|
GLenum prog;
|
|
GLint prev_prog;
|
|
std::vector<ShaderFileOrCode> shader_files;
|
|
};
|
|
|
|
class GlSlUtilities
|
|
{
|
|
public:
|
|
inline static GlSlProgram& OffsetAndScale(float offset, float scale) {
|
|
GlSlProgram& prog = Instance().prog_offsetscale;
|
|
prog.Bind();
|
|
prog.SetUniform("offset", offset);
|
|
prog.SetUniform("scale", scale);
|
|
return prog;
|
|
}
|
|
|
|
inline static GlSlProgram& Scale(float scale, float bias = 0.0f) {
|
|
GlSlProgram& prog = Instance().prog_scale;
|
|
prog.Bind();
|
|
prog.SetUniform("scale", scale);
|
|
prog.SetUniform("bias", bias);
|
|
return prog;
|
|
}
|
|
|
|
inline static void UseNone()
|
|
{
|
|
glUseProgram(0);
|
|
}
|
|
|
|
protected:
|
|
static GlSlUtilities& Instance() {
|
|
// TODO: BUG: The GlSLUtilities instance needs to be tied
|
|
// to the OpenGL context, not the thread, or globally.
|
|
#ifndef PANGO_NO_THREADLOCAL
|
|
thread_local
|
|
#else
|
|
static
|
|
#endif
|
|
GlSlUtilities instance;
|
|
return instance;
|
|
}
|
|
|
|
// protected constructor
|
|
GlSlUtilities() {
|
|
const char* source_scale =
|
|
"uniform float scale;"
|
|
"uniform float bias;"
|
|
"uniform sampler2D tex;"
|
|
"void main() {"
|
|
" vec2 uv = gl_TexCoord[0].st;"
|
|
" if(0.0 <= uv.x && uv.x <= 1.0 && 0.0 <= uv.y && uv.y <= 1.0) {"
|
|
" gl_FragColor = texture2D(tex,uv);"
|
|
" gl_FragColor.xyz *= scale;"
|
|
" gl_FragColor.xyz += vec3(bias,bias,bias);"
|
|
" }else{"
|
|
" float v = 0.1;"
|
|
" gl_FragColor.xyz = vec3(v,v,v);"
|
|
" }"
|
|
"}";
|
|
prog_scale.AddShader(GlSlFragmentShader, source_scale);
|
|
prog_scale.Link();
|
|
|
|
const char* source_offsetscale =
|
|
"uniform float offset;"
|
|
"uniform float scale;"
|
|
"uniform sampler2D tex;"
|
|
"void main() {"
|
|
" vec2 uv = gl_TexCoord[0].st;"
|
|
" if(0.0 <= uv.x && uv.x <= 1.0 && 0.0 <= uv.y && uv.y <= 1.0) {"
|
|
" gl_FragColor = texture2D(tex,gl_TexCoord[0].st);"
|
|
" gl_FragColor.xyz += vec3(offset,offset,offset);"
|
|
" gl_FragColor.xyz *= scale;"
|
|
" }else{"
|
|
" float v = 0.1;"
|
|
" gl_FragColor.xyz = vec3(v,v,v);"
|
|
" }"
|
|
"}";
|
|
prog_offsetscale.AddShader(GlSlFragmentShader, source_offsetscale);
|
|
prog_offsetscale.Link();
|
|
}
|
|
|
|
GlSlProgram prog_scale;
|
|
GlSlProgram prog_offsetscale;
|
|
};
|
|
|
|
|
|
////////////////////////////////////////////////
|
|
// Implementation
|
|
////////////////////////////////////////////////
|
|
|
|
inline bool IsLinkSuccessPrintLog(GLhandleARB prog)
|
|
{
|
|
GLint status;
|
|
glGetProgramiv(prog, GL_LINK_STATUS, &status);
|
|
if(status != GL_TRUE) {
|
|
pango_print_error("GLSL Program link failed: ");
|
|
const int PROGRAM_LOG_MAX_LEN = 10240;
|
|
char infolog[PROGRAM_LOG_MAX_LEN];
|
|
GLsizei len;
|
|
glGetProgramInfoLog(prog, PROGRAM_LOG_MAX_LEN, &len, infolog);
|
|
if(len) {
|
|
pango_print_error("%s\n",infolog);
|
|
}else{
|
|
pango_print_error("No details provided.\n");
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
inline bool IsCompileSuccessPrintLog(GLhandleARB shader, const std::string& name_for_errors)
|
|
{
|
|
GLint status;
|
|
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
|
|
if(status != GL_TRUE) {
|
|
pango_print_error("GLSL Shader compilation failed: ");
|
|
const int SHADER_LOG_MAX_LEN = 10240;
|
|
char infolog[SHADER_LOG_MAX_LEN];
|
|
GLsizei len;
|
|
glGetShaderInfoLog(shader, SHADER_LOG_MAX_LEN, &len, infolog);
|
|
if(len) {
|
|
pango_print_error("%s:\n%s\n",name_for_errors.c_str(), infolog);
|
|
}else{
|
|
pango_print_error("%s:\nNo details provided.\n",name_for_errors.c_str());
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
inline GlSlProgram::GlSlProgram()
|
|
: linked(false), prog(0), prev_prog(0)
|
|
{
|
|
}
|
|
|
|
//! Move Constructor
|
|
inline GlSlProgram::GlSlProgram(GlSlProgram&& o)
|
|
: linked(o.linked), shaders(o.shaders), prog(o.prog), prev_prog(o.prev_prog)
|
|
{
|
|
o.prog = 0;
|
|
}
|
|
|
|
inline GlSlProgram::~GlSlProgram()
|
|
{
|
|
if(prog) {
|
|
ClearShaders();
|
|
glDeleteProgram(prog);
|
|
}
|
|
}
|
|
|
|
inline void PrintSourceCode(const std::string& src)
|
|
{
|
|
std::stringstream ss(src);
|
|
std::string line;
|
|
|
|
for(int linenum=1; std::getline(ss,line,'\n'); ++linenum) {
|
|
std::cout << linenum << ":\t" << line << std::endl;
|
|
}
|
|
}
|
|
|
|
inline bool GlSlProgram::AddPreprocessedShader(
|
|
GlSlShaderType shader_type,
|
|
const std::string& source_code,
|
|
const std::string& name_for_errors
|
|
) {
|
|
if(!prog) {
|
|
prog = glCreateProgram();
|
|
}
|
|
|
|
// PrintSourceCode(source_code);
|
|
|
|
GLhandleARB shader = glCreateShader(shader_type);
|
|
const char* source = source_code.c_str();
|
|
glShaderSource(shader, 1, &source, NULL);
|
|
glCompileShader(shader);
|
|
bool success = IsCompileSuccessPrintLog(shader, name_for_errors);
|
|
if(success) {
|
|
glAttachShader(prog, shader);
|
|
shaders.push_back(shader);
|
|
linked = false;
|
|
}
|
|
return success;
|
|
}
|
|
|
|
inline std::string GlSlProgram::ParseIncludeFilename(const std::string& location)
|
|
{
|
|
size_t start = location.find_first_of("\"<");
|
|
if(start != std::string::npos) {
|
|
size_t end = location.find_first_of("\">", start+1);
|
|
if(end != std::string::npos) {
|
|
return location.substr(start+1, end - start - 1);
|
|
}
|
|
}
|
|
throw std::runtime_error("GLSL Parser: Unable to parse include location " + location );
|
|
}
|
|
|
|
inline std::string GlSlProgram::SearchIncludePath(
|
|
const std::string& filename,
|
|
const std::vector<std::string>& search_path,
|
|
const std::string& current_path
|
|
) {
|
|
if(FileExists(current_path + "/" + filename)) {
|
|
return current_path + "/" + filename;
|
|
}else{
|
|
for(size_t i=0; i < search_path.size(); ++i) {
|
|
const std::string hypoth = search_path[i] + "/" + filename;
|
|
if( FileExists(hypoth) ) {
|
|
return hypoth;
|
|
}
|
|
}
|
|
}
|
|
return "";
|
|
}
|
|
|
|
inline void GlSlProgram::PreprocessGLSL(
|
|
std::istream& input, std::ostream& output,
|
|
const std::map<std::string,std::string>& program_defines,
|
|
const std::vector<std::string> &search_path,
|
|
const std::string ¤t_path
|
|
) {
|
|
const size_t MAXLINESIZE = 10240;
|
|
char line[MAXLINESIZE] = "";
|
|
|
|
while(!input.eof()) {
|
|
// Take like from source
|
|
input.getline(line,MAXLINESIZE);
|
|
|
|
// Transform
|
|
if( !strncmp(line, "#include", 8 ) ) {
|
|
// C++ / G3D style include directive
|
|
const std::string import_file = ParseIncludeFilename(line+8);
|
|
const std::string resolved_file = SearchIncludePath(import_file, search_path, current_path);
|
|
|
|
std::ifstream ifs(resolved_file.c_str());
|
|
if(ifs.good()) {
|
|
const std::string file_path = pangolin::PathParent(resolved_file);
|
|
PreprocessGLSL(ifs, output, program_defines, search_path, file_path);
|
|
}else{
|
|
throw std::runtime_error("GLSL Parser: Unable to open " + import_file );
|
|
}
|
|
}else if( !strncmp(line, "#expect", 7) ) {
|
|
// G3D style 'expect' directive, annotating expected preprocessor
|
|
// definition with document string
|
|
|
|
// Consume whitespace before token
|
|
size_t token_start = 7;
|
|
while( std::isspace(line[token_start]) ) ++token_start;
|
|
|
|
// Iterate over contigous charecters until \0 or whitespace
|
|
size_t token_end = token_start;
|
|
while( line[token_end] && !std::isspace(line[token_end]) ) ++token_end;
|
|
|
|
std::string token(line+token_start, line+token_end);
|
|
std::map<std::string,std::string>::const_iterator it = program_defines.find(token);
|
|
if( it == program_defines.end() ) {
|
|
pango_print_warn("Expected define missing (defaulting to 0): '%s'\n%s\n", token.c_str(), line + token_end );
|
|
output << "#define " << token << " 0" << std::endl;
|
|
}else{
|
|
output << "#define " << token << " " << it->second << std::endl;
|
|
}
|
|
}else{
|
|
// Output directly
|
|
output << line << std::endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
inline void GlSlProgram::ClearShaders()
|
|
{
|
|
// Remove and delete each shader
|
|
for(size_t i=0; i<shaders.size(); ++i ) {
|
|
glDetachShader(prog, shaders[i]);
|
|
glDeleteShader(shaders[i]);
|
|
}
|
|
shaders.clear();
|
|
}
|
|
|
|
inline bool GlSlProgram::AddShaderFile(const ShaderFileOrCode& shader_file)
|
|
{
|
|
std::stringstream buffer;
|
|
|
|
if(shader_file.code.empty()) {
|
|
std::ifstream ifs(shader_file.filename.c_str());
|
|
if(ifs.is_open()) {
|
|
PreprocessGLSL(ifs, buffer, shader_file.program_defines, shader_file.search_path, ".");
|
|
}else{
|
|
throw std::runtime_error(FormatString("Unable to open shader file '%'", shader_file.filename));
|
|
}
|
|
}else{
|
|
std::istringstream iss(shader_file.code);
|
|
PreprocessGLSL(iss, buffer, shader_file.program_defines, shader_file.search_path, ".");
|
|
}
|
|
|
|
const std::string code = buffer.str();
|
|
const std::string input_name = !shader_file.filename.empty() ? shader_file.filename : "<string>";
|
|
|
|
if(shader_file.shader_type == GlSlAnnotatedShader) {
|
|
const std::map<GlSlShaderType,std::string> split_progs = SplitAnnotatedShaders(code);
|
|
for(const auto& type_code : split_progs) {
|
|
if(!AddPreprocessedShader(type_code.first, type_code.second, input_name )) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}else{
|
|
return AddPreprocessedShader(shader_file.shader_type, code, input_name);
|
|
}
|
|
}
|
|
|
|
inline bool GlSlProgram::AddShaderFromFile(
|
|
GlSlShaderType shader_type,
|
|
const std::string& filename,
|
|
const std::map<std::string,std::string>& program_defines,
|
|
const std::vector<std::string>& search_path
|
|
) {
|
|
ShaderFileOrCode shader_file = {
|
|
shader_type,
|
|
pangolin::PathExpand(filename),
|
|
std::string(),
|
|
program_defines,
|
|
search_path
|
|
};
|
|
shader_files.push_back(shader_file);
|
|
return AddShaderFile(shader_file);
|
|
}
|
|
|
|
inline bool GlSlProgram::AddShader(
|
|
GlSlShaderType shader_type,
|
|
const std::string& source_code,
|
|
const std::map<std::string,std::string>& program_defines,
|
|
const std::vector<std::string>& search_path
|
|
) {
|
|
ShaderFileOrCode shader_file = {
|
|
shader_type,
|
|
std::string(),
|
|
source_code,
|
|
program_defines,
|
|
search_path
|
|
};
|
|
shader_files.push_back(shader_file);
|
|
return AddShaderFile(shader_file);
|
|
}
|
|
|
|
inline bool GlSlProgram::ReloadShaderFiles()
|
|
{
|
|
ClearShaders();
|
|
|
|
for(const auto& sf : shader_files) {
|
|
if(!AddShaderFile(sf)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
Link();
|
|
return true;
|
|
}
|
|
|
|
inline std::map<GlSlShaderType,std::string>
|
|
GlSlProgram::SplitAnnotatedShaders(const std::string& code)
|
|
{
|
|
std::map<GlSlShaderType,std::string> ret;
|
|
|
|
std::stringstream input(code);
|
|
std::stringstream output;
|
|
|
|
const size_t MAXLINESIZE = 10240;
|
|
char line[MAXLINESIZE];
|
|
|
|
GlSlShaderType current_type = GlSlAnnotatedShader;
|
|
auto finish_block = [&](GlSlShaderType type){
|
|
if(current_type != GlSlAnnotatedShader) {
|
|
ret[current_type] = output.str();
|
|
}
|
|
output.str(std::string());
|
|
current_type = type;
|
|
};
|
|
|
|
while(!input.eof()) {
|
|
// Take like from source
|
|
input.getline(line,MAXLINESIZE);
|
|
|
|
// Transform
|
|
if( !strncmp(line, "@start", 6 ) ) {
|
|
const std::string str_shader_type = pangolin::Trim(std::string(line).substr(6));
|
|
if(str_shader_type == "vertex") {
|
|
finish_block(GlSlVertexShader);
|
|
}else if(str_shader_type == "fragment") {
|
|
finish_block(GlSlFragmentShader);
|
|
}else if(str_shader_type == "geometry") {
|
|
finish_block(GlSlGeometryShader);
|
|
}else if(str_shader_type == "compute") {
|
|
finish_block(GlSlComputeShader);
|
|
}
|
|
}else{
|
|
output << line << std::endl;
|
|
}
|
|
}
|
|
|
|
finish_block(GlSlAnnotatedShader);
|
|
|
|
return ret;
|
|
}
|
|
|
|
inline bool GlSlProgram::Link()
|
|
{
|
|
glLinkProgram(prog);
|
|
return IsLinkSuccessPrintLog(prog);
|
|
}
|
|
|
|
inline void GlSlProgram::Bind()
|
|
{
|
|
prev_prog = 0;
|
|
glUseProgram(prog);
|
|
}
|
|
|
|
inline void GlSlProgram::SaveBind()
|
|
{
|
|
glGetIntegerv(GL_CURRENT_PROGRAM, &prev_prog);
|
|
glUseProgram(prog);
|
|
}
|
|
|
|
inline void GlSlProgram::Unbind()
|
|
{
|
|
glUseProgram(prev_prog);
|
|
}
|
|
|
|
inline GLint GlSlProgram::GetAttributeHandle(const std::string& name)
|
|
{
|
|
return glGetAttribLocation(prog, name.c_str());
|
|
}
|
|
|
|
inline GLint GlSlProgram::GetUniformHandle(const std::string& name)
|
|
{
|
|
return glGetUniformLocation(prog, name.c_str());
|
|
}
|
|
|
|
inline void GlSlProgram::SetUniform(const std::string& name, int x)
|
|
{
|
|
glUniform1i( GetUniformHandle(name), x);
|
|
}
|
|
|
|
inline void GlSlProgram::SetUniform(const std::string& name, int x1, int x2)
|
|
{
|
|
glUniform2i( GetUniformHandle(name), x1, x2);
|
|
}
|
|
|
|
inline void GlSlProgram::SetUniform(const std::string& name, int x1, int x2, int x3)
|
|
{
|
|
glUniform3i( GetUniformHandle(name), x1, x2, x3);
|
|
}
|
|
|
|
inline void GlSlProgram::SetUniform(const std::string& name, int x1, int x2, int x3, int x4)
|
|
{
|
|
glUniform4i( GetUniformHandle(name), x1, x2, x3, x4);
|
|
}
|
|
|
|
inline void GlSlProgram::SetUniform(const std::string& name, float f)
|
|
{
|
|
glUniform1f( GetUniformHandle(name), f);
|
|
}
|
|
|
|
inline void GlSlProgram::SetUniform(const std::string& name, float f1, float f2)
|
|
{
|
|
glUniform2f( GetUniformHandle(name), f1,f2);
|
|
}
|
|
|
|
inline void GlSlProgram::SetUniform(const std::string& name, float f1, float f2, float f3)
|
|
{
|
|
glUniform3f( GetUniformHandle(name), f1,f2,f3);
|
|
}
|
|
|
|
inline void GlSlProgram::SetUniform(const std::string& name, float f1, float f2, float f3, float f4)
|
|
{
|
|
glUniform4f( GetUniformHandle(name), f1,f2,f3,f4);
|
|
}
|
|
|
|
inline void GlSlProgram::SetUniform(const std::string& name, Colour c)
|
|
{
|
|
glUniform4f( GetUniformHandle(name), c.r, c.g, c.b, c.a);
|
|
}
|
|
|
|
inline void GlSlProgram::SetUniform(const std::string& name, const OpenGlMatrix& mat)
|
|
{
|
|
// glUniformMatrix4dv seems to be crashing...
|
|
float m[16];
|
|
for (int i = 0; i < 16; ++i) {
|
|
m[i] = (float)mat.m[i];
|
|
}
|
|
glUniformMatrix4fv( GetUniformHandle(name), 1, GL_FALSE, m);
|
|
}
|
|
|
|
#ifdef HAVE_EIGEN
|
|
inline void GlSlProgram::SetUniform(const std::string& name, const Eigen::Matrix3f& m)
|
|
{
|
|
glUniformMatrix3fv( GetUniformHandle(name), 1, GL_FALSE, m.data());
|
|
}
|
|
inline void GlSlProgram::SetUniform(const std::string& name, const Eigen::Matrix4f& m)
|
|
{
|
|
glUniformMatrix4fv( GetUniformHandle(name), 1, GL_FALSE, m.data());
|
|
}
|
|
inline void GlSlProgram::SetUniform(const std::string& name, const Eigen::Matrix3d& m)
|
|
{
|
|
glUniformMatrix3dv( GetUniformHandle(name), 1, GL_FALSE, m.data());
|
|
}
|
|
inline void GlSlProgram::SetUniform(const std::string& name, const Eigen::Matrix4d& m)
|
|
{
|
|
glUniformMatrix4dv( GetUniformHandle(name), 1, GL_FALSE, m.data());
|
|
}
|
|
#endif
|
|
|
|
inline void GlSlProgram::BindPangolinDefaultAttribLocationsAndLink()
|
|
{
|
|
glBindAttribLocation(prog, DEFAULT_LOCATION_POSITION, DEFAULT_NAME_POSITION);
|
|
glBindAttribLocation(prog, DEFAULT_LOCATION_COLOUR, DEFAULT_NAME_COLOUR);
|
|
glBindAttribLocation(prog, DEFAULT_LOCATION_NORMAL, DEFAULT_NAME_NORMAL);
|
|
glBindAttribLocation(prog, DEFAULT_LOCATION_TEXCOORD, DEFAULT_NAME_TEXCOORD);
|
|
Link();
|
|
}
|
|
|
|
#if GL_VERSION_4_3
|
|
inline GLint GlSlProgram::GetProgramResourceIndex(const std::string& name)
|
|
{
|
|
return glGetProgramResourceIndex(prog, GL_SHADER_STORAGE_BLOCK, name.c_str());
|
|
}
|
|
|
|
inline void GlSlProgram::SetShaderStorageBlock(const std::string& name, const int& bindingIndex)
|
|
{
|
|
glShaderStorageBlockBinding(prog, GetProgramResourceIndex(name), bindingIndex);
|
|
}
|
|
#endif
|
|
|
|
}
|