Commit 987589be authored by Sylvain Thery's avatar Sylvain Thery

add environment mapping shader (cube mapping)

parent 249d9999
//ShaderEnvMap::fragmentShaderText
PRECISON;
VARYING_FRAG vec3 EyeVector, Normal, LightDir,refl;
#ifdef WITH_COLOR
VARYING_FRAG vec3 Color;
#endif
uniform vec4 materialDiffuse;
uniform vec4 materialAmbient;
uniform samplerCube EnvMap;
uniform float blendCoef;
FRAG_OUT_DEF;
void main()
{
vec3 N = normalize (Normal);
vec3 L = normalize (LightDir);
float lambertTerm = dot(N,L);
vec4 finalColor = materialAmbient;
#ifdef DOUBLE_SIDED
if (lambertTerm < 0.0)
{
N = -1.0*N;
lambertTerm = -1.0*lambertTerm;
#else
if (lambertTerm > 0.0)
{
#endif
#ifndef WITH_COLOR
vec4 col = materialDiffuse;
#else
vec4 col = vec4(Color,0.0) ;
#endif
vec3 R = reflect(-EyeVector,N);
finalColor += mix(col,texture(EnvMap,R),blendCoef) * lambertTerm;
}
gl_FragColor=finalColor;
}
/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps *
* version 0.1 *
* Copyright (C) 2009-2012, IGG Team, LSIIT, University of Strasbourg *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, or (at your *
* option) any later version. *
* *
* This library is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this library; if not, write to the Free Software Foundation, *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
* *
* Web site: http://cgogn.unistra.fr/ *
* Contact information: cgogn@unistra.fr *
* *
*******************************************************************************/
#ifndef __CGOGN_SHADER_PHONG__
#define __CGOGN_SHADER_PHONG__
#include "Utils/GLSLShader.h"
#include "Utils/clippingShader.h"
#include "Geometry/vector_gen.h"
#include <string>
#ifdef WITH_QT
#include <QImage>
#endif
namespace CGoGN
{
namespace Utils
{
class ShaderEnvMap : public ClippingShader
{
protected:
// flag color per vertex or not
bool m_with_color;
// flag color per vertex or not
bool m_with_eyepos;
// shader sources OGL3
static std::string vertexShaderText;
static std::string fragmentShaderText;
// uniform locations
CGoGNGLuint m_unif_ambiant;
CGoGNGLuint m_unif_diffuse;
CGoGNGLuint m_unif_blend;
CGoGNGLuint m_unif_lightPos;
CGoGNGLuint m_unif_eyePos;
CGoGNGLuint m_unif_envMap;
//values
Geom::Vec4f m_ambiant;
Geom::Vec4f m_diffuse;
float m_blend;
Geom::Vec3f m_lightPos;
Geom::Vec3f m_eyePos;
CGoGNGLuint m_texId;
VBO* m_vboPos;
VBO* m_vboNormal;
VBO* m_vboColor;
void getLocations();
void sendParams();
void restoreUniformsAttribs();
public:
ShaderEnvMap(bool doubleSided = false, bool withEyePosition=false);
// inviduals parameter setting functions
void setAmbiant(const Geom::Vec4f& ambiant);
void setDiffuse(const Geom::Vec4f& diffuse);
void setSpecular(const Geom::Vec4f& specular);
void setBlendCoef(float blend);
void setLightPosition(const Geom::Vec3f& lp);
/// set eye position for VR environement
void setEyePosition(const Geom::Vec3f& ep);
const Geom::Vec4f& getAmbiant() const { return m_ambiant; }
const Geom::Vec4f& getDiffuse() const { return m_diffuse; }
float getBlendCoef() const { return m_blend; }
const Geom::Vec3f& getLightPosition() const { return m_lightPos; }
/**
* set all parameter in on call (one bind also)
*/
void setParams(const Geom::Vec4f& ambiant, const Geom::Vec4f& diffuse, float blend, const Geom::Vec3f& lightPos);
// attributes
unsigned int setAttributePosition(VBO* vbo);
unsigned int setAttributeNormal(VBO* vbo);
// optional attributes
unsigned int setAttributeColor(VBO* vbo);
void unsetAttributeColor();
void setCubeMap(unsigned int sz, unsigned char* Xpos, unsigned char* Ypos, unsigned char* Zpos, unsigned char* Xneg, unsigned char* Yneg, unsigned char* Zneg);
/**
* set envmap texture image
* image looks likre:
* Y
* XZXZ
* Y
* @parameter sz size of edge of cube in pixel
* @parameter ptr pointer on image data (RGB RGB RGB ....)
*/
bool setCubeMapImg(unsigned int sz, unsigned char *ptr);
/**
* set colored plane for testing
*/
bool setCubeMapPipo();
#ifdef WITH_QT
bool setCubeMap(const std::string& filename);
#endif
void predraw();
void postdraw();
};
} // namespace Utils
} // namespace CGoGN
#endif
//ShaderEnvMap::vertexShaderText
ATTRIBUTE vec3 VertexPosition, VertexNormal;
#ifdef WITH_COLOR
ATTRIBUTE vec3 VertexColor;
#endif
uniform mat4 ModelViewProjectionMatrix;
uniform mat4 ModelViewMatrix;
uniform mat4 NormalMatrix;
uniform vec3 lightPosition;
VARYING_VERT vec3 EyeVector, Normal, LightDir;
#ifdef WITH_COLOR
VARYING_VERT vec3 Color;
#endif
#ifdef WITH_EYEPOSITION
uniform vec3 eyePosition;
#endif
INVARIANT_POS;
void main ()
{
Normal = vec3 (NormalMatrix * vec4 (VertexNormal, 0.0));
vec3 Position = vec3 (ModelViewMatrix * vec4 (VertexPosition, 1.0));
LightDir = Position - lightPosition;
#ifdef WITH_EYEPOSITION
EyeVector = eyePosition-Position;
#else
EyeVector = -Position;
#endif
#ifdef WITH_COLOR
Color = VertexColor;
#endif
gl_Position = ModelViewProjectionMatrix * vec4 (VertexPosition, 1.0);
}
/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps *
* version 0.1 *
* Copyright (C) 2009-2012, IGG Team, LSIIT, University of Strasbourg *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, or (at your *
* option) any later version. *
* *
* This library is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this library; if not, write to the Free Software Foundation, *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
* *
* Web site: http://cgogn.unistra.fr/ *
* Contact information: cgogn@unistra.fr *
* *
*******************************************************************************/
#include <GL/glew.h>
#include "Utils/Shaders/shaderEnvMap.h"
#include <string.h>
namespace CGoGN
{
namespace Utils
{
#include "shaderEnvMap.vert"
#include "shaderEnvMap.frag"
ShaderEnvMap::ShaderEnvMap(bool doubleSided, bool withEyePosition):
m_with_color(false),
m_with_eyepos(withEyePosition),
m_ambiant(Geom::Vec4f(0.05f,0.05f,0.1f,0.0f)),
m_diffuse(Geom::Vec4f(0.1f,1.0f,0.1f,0.0f)),
m_blend(0.5f),
m_lightPos(Geom::Vec3f(10.0f,10.0f,1000.0f)),
m_vboPos(NULL),
m_vboNormal(NULL),
m_vboColor(NULL)
{
m_nameVS = "ShaderEnvMap_vs";
m_nameFS = "ShaderEnvMap_fs";
// get choose GL defines (2 or 3)
// ans compile shaders
std::string glxvert(*GLSLShader::DEFINES_GL);
if (m_with_eyepos)
glxvert.append("#define WITH_EYEPOSITION");
glxvert.append(vertexShaderText);
std::string glxfrag(*GLSLShader::DEFINES_GL);
// Use double sided lighting if set
if (doubleSided)
glxfrag.append("#define DOUBLE_SIDED\n");
glxfrag.append(fragmentShaderText);
loadShadersFromMemory(glxvert.c_str(), glxfrag.c_str());
// and get and fill uniforms
bind();
getLocations();
sendParams();
std::cout << "init texture" << std::endl;
glEnable(GL_TEXTURE_CUBE_MAP);
glGenTextures(1, &(*m_texId));
glBindTexture(GL_TEXTURE_CUBE_MAP, *m_texId);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_REPEAT);
glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
}
void ShaderEnvMap::getLocations()
{
*m_unif_ambiant = glGetUniformLocation(this->program_handler(), "materialAmbient");
*m_unif_diffuse = glGetUniformLocation(this->program_handler(), "materialDiffuse");
*m_unif_blend = glGetUniformLocation(this->program_handler(), "blendCoef");
*m_unif_lightPos = glGetUniformLocation(this->program_handler(), "lightPosition");
if (m_with_eyepos)
*m_unif_eyePos= glGetUniformLocation(this->program_handler(), "eyePosition");
*m_unif_envMap = glGetUniformLocation(this->program_handler(), "EnvMap");
}
void ShaderEnvMap::sendParams()
{
glUniform4fv(*m_unif_ambiant, 1, m_ambiant.data());
glUniform4fv(*m_unif_diffuse, 1, m_diffuse.data());
glUniform1f(*m_unif_blend, m_blend);
glUniform3fv(*m_unif_lightPos, 1, m_lightPos.data());
if (m_with_eyepos)
glUniform3fv(*m_unif_eyePos, 1, m_eyePos.data());
// we use texture engine 0
glUniform1iARB(*m_unif_envMap,0);
}
void ShaderEnvMap::setAmbiant(const Geom::Vec4f& ambiant)
{
this->bind();
glUniform4fv(*m_unif_ambiant,1, ambiant.data());
m_ambiant = ambiant;
}
void ShaderEnvMap::setDiffuse(const Geom::Vec4f& diffuse)
{
this->bind();
glUniform4fv(*m_unif_diffuse,1, diffuse.data());
m_diffuse = diffuse;
}
void ShaderEnvMap::setBlendCoef(float blend)
{
this->bind();
glUniform1f (*m_unif_blend, blend);
m_blend = blend;
}
void ShaderEnvMap::setLightPosition(const Geom::Vec3f& lightPos)
{
this->bind();
glUniform3fv(*m_unif_lightPos,1,lightPos.data());
m_lightPos = lightPos;
}
void ShaderEnvMap::setEyePosition(const Geom::Vec3f& eyePos)
{
if (m_with_eyepos)
{
this->bind();
glUniform3fv(*m_unif_eyePos,1,eyePos.data());
m_eyePos = eyePos;
}
}
void ShaderEnvMap::setParams(const Geom::Vec4f& ambiant, const Geom::Vec4f& diffuse, float blend, const Geom::Vec3f& lightPos)
{
m_ambiant = ambiant;
m_diffuse = diffuse;
m_blend = blend;
m_lightPos = lightPos;
bind();
sendParams();
}
unsigned int ShaderEnvMap::setAttributeColor(VBO* vbo)
{
m_vboColor = vbo;
if (!m_with_color)
{
m_with_color=true;
// set the define and recompile shader
std::string gl3vert(*GLSLShader::DEFINES_GL);
gl3vert.append("#define WITH_COLOR 1\n");
gl3vert.append(vertexShaderText);
std::string gl3frag(*GLSLShader::DEFINES_GL);
gl3frag.append("#define WITH_COLOR 1\n");
gl3frag.append(fragmentShaderText);
loadShadersFromMemory(gl3vert.c_str(), gl3frag.c_str());
// and treat uniforms
bind();
getLocations();
sendParams();
}
// bind th VA with WBO
return bindVA_VBO("VertexColor", vbo);
}
void ShaderEnvMap::unsetAttributeColor()
{
m_vboColor = NULL;
if (m_with_color)
{
m_with_color=false;
// unbind the VA
unbindVA("VertexColor");
// recompile shader
std::string gl3vert(*GLSLShader::DEFINES_GL);
gl3vert.append(vertexShaderText);
std::string gl3frag(*GLSLShader::DEFINES_GL);
gl3frag.append(fragmentShaderText);
loadShadersFromMemory(gl3vert.c_str(), gl3frag.c_str());
// and treat uniforms
bind();
getLocations();
sendParams();
}
}
void ShaderEnvMap::restoreUniformsAttribs()
{
getLocations();
bind();
sendParams();
bindVA_VBO("VertexPosition", m_vboPos);
bindVA_VBO("VertexNormal", m_vboNormal);
if (m_vboColor)
bindVA_VBO("VertexColor", m_vboColor);
unbind();
}
unsigned int ShaderEnvMap::setAttributePosition(VBO* vbo)
{
m_vboPos = vbo;
return bindVA_VBO("VertexPosition", vbo);
}
unsigned int ShaderEnvMap::setAttributeNormal(VBO* vbo)
{
m_vboNormal = vbo;
return bindVA_VBO("VertexNormal", vbo);
}
void ShaderEnvMap::setCubeMap(unsigned int sz,
unsigned char* Xpos, unsigned char* Ypos, unsigned char* Zpos,
unsigned char* Xneg, unsigned char* Yneg, unsigned char* Zneg)
{
glEnable(GL_TEXTURE_CUBE_MAP);
glBindTexture(GL_TEXTURE_CUBE_MAP, *m_texId);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, sz, sz, 0, GL_RGB, GL_UNSIGNED_BYTE, Xpos);
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, sz, sz, 0, GL_RGB, GL_UNSIGNED_BYTE, Xneg);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, sz, sz, 0, GL_RGB, GL_UNSIGNED_BYTE, Ypos);
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, sz, sz, 0, GL_RGB, GL_UNSIGNED_BYTE, Yneg);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, sz, sz, 0, GL_RGB, GL_UNSIGNED_BYTE, Zpos);
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, sz, sz, 0, GL_RGB, GL_UNSIGNED_BYTE, Zneg);
}
bool ShaderEnvMap::setCubeMapImg(unsigned int sz, unsigned char *img)
{
std::cout << "setCubeMapImg: "<< sz << std::endl;
glEnable(GL_TEXTURE_CUBE_MAP);
glBindTexture(GL_TEXTURE_CUBE_MAP, *m_texId);
unsigned char* texture = new unsigned char[3*sz*sz];
// Y+
unsigned char* ptrD = texture;
unsigned char* ptrS = img + 3*sz;
for (unsigned int i=0; i<sz; ++i)
{
memcpy(ptrD, ptrS, 3*sz);
ptrD += 3*sz;
ptrS += 12*sz;
}
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, sz, sz, 0, GL_RGB, GL_UNSIGNED_BYTE, texture);
//
// // Y-
ptrD = texture;
ptrS = img + 24*sz*sz + 3*sz ;
for (unsigned int i=0; i<sz; ++i)
{
memcpy(ptrD, ptrS, 3*sz);
ptrD += 3*sz;
ptrS += 12*sz;
}
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, sz, sz, 0, GL_RGB, GL_UNSIGNED_BYTE, texture);
// X-
ptrD = texture;
ptrS = img + 12*sz*sz;
for (unsigned int i=0; i<sz; ++i)
{
memcpy(ptrD, ptrS, 3*sz);
ptrD += 3*sz;
ptrS += 12*sz;
}
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, sz, sz, 0, GL_RGB, GL_UNSIGNED_BYTE, texture);
// X+
ptrD = texture;
ptrS = img + 12*sz*sz+ 6*sz ;
for (unsigned int i=0; i<sz; ++i)
{
memcpy(ptrD, ptrS, 3*sz);
ptrD += 3*sz;
ptrS += 12*sz;
}
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, sz, sz, 0, GL_RGB, GL_UNSIGNED_BYTE, texture);
// Z-
ptrD = texture;
ptrS = img + 12*sz*sz+ 3*sz ;
for (unsigned int i=0; i<sz; ++i)
{
memcpy(ptrD, ptrS, 3*sz);
ptrD += 3*sz;
ptrS += 12*sz;
}
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, sz, sz, 0, GL_RGB, GL_UNSIGNED_BYTE, texture);
// Z+
ptrD = texture;
ptrS = img + 12*sz*sz+ 9*sz ;
for (unsigned int i=0; i<sz; ++i)
{
memcpy(ptrD, ptrS, 3*sz);
ptrD += 3*sz;
ptrS += 12*sz;
}
//// for (unsigned int i = 0; i< sz*sz; ++i)
//// {
//// if (texture[3*i+2] != 0)
//// std::cout << "PIX= "<< int(texture[3*i]) << " / "<< int(texture[3*i+1]) << " / "<< int(texture[3*i+2]) << std::endl;
//// }
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, sz, sz, 0, GL_RGB, GL_UNSIGNED_BYTE, texture);
delete[] texture;
return true;
}
bool ShaderEnvMap::setCubeMapPipo()
{
std::cout << "setCubeMapPipo" << std::endl;
glEnable(GL_TEXTURE_CUBE_MAP);
glBindTexture(GL_TEXTURE_CUBE_MAP, *m_texId);
unsigned int sz = 256;
unsigned char* texture = new unsigned char[3*sz*sz];
for (unsigned int i = 0; i< sz*sz; ++i)
{
texture[i*3] = 255;
texture[i*3+1] = 0;
texture[i*3+2] = 0;
}
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, sz, sz, 0, GL_RGB, GL_UNSIGNED_BYTE, texture);
for (unsigned int i = 0; i< sz*sz; ++i)
{
texture[i*3] = 128;
texture[i*3+1] = 0;
texture[i*3+2] = 0;
}
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, sz, sz, 0, GL_RGB, GL_UNSIGNED_BYTE, texture);
for (unsigned int i = 0; i< sz*sz; ++i)
{
texture[i*3] = 0;
texture[i*3+1] = 255;
texture[i*3+2] = 0;
}
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, sz, sz, 0, GL_RGB, GL_UNSIGNED_BYTE, texture);
for (unsigned int i = 0; i< sz*sz; ++i)
{
texture[i*3] = 0;
texture[i*3+1] = 128;
texture[i*3+2] = 0;
}
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, sz, sz, 0, GL_RGB, GL_UNSIGNED_BYTE, texture);
for (unsigned int i = 0; i< sz*sz; ++i)
{
texture[i*3] = 0;
texture[i*3+1] = 0;
texture[i*3+2] = 255;
}
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, sz, sz, 0, GL_RGB, GL_UNSIGNED_BYTE, texture);
for (unsigned int i = 0; i< sz*sz; ++i)
{
texture[i*3] = 0;
texture[i*3+1] = 0;
texture[i*3+2] = 128;
}
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, sz, sz, 0, GL_RGB, GL_UNSIGNED_BYTE, texture);
delete[] texture;
return true;
}
#ifdef WITH_QT
bool ShaderEnvMap::setCubeMap(const std::string& filename)
{
QImage* ptr = new QImage(filename.c_str());
if (ptr == NULL)
{