Copyright 2008-2014 Matus Chochlik. Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <cmath>
namespace oglplus {
class ReflectionExample : public Example
{
private:
shapes::TwistedTorus make_torus;
shapes::DrawingInstructions torus_instr;
Context gl;
ProgramUniform<Mat4f>
norm_projection_matrix, norm_camera_matrix, norm_model_matrix,
refl_projection_matrix, refl_camera_matrix, refl_model_matrix;
Buffer torus_verts, torus_normals;
Buffer plane_verts, plane_normals;
public:
ReflectionExample(void)
: torus_indices(make_torus.Indices())
, torus_instr(make_torus.Instructions())
, vs_norm(ObjectDesc("Vertex-Normal"))
, vs_refl(ObjectDesc("Vertex-Reflection"))
, gs_refl(ObjectDesc("Geometry-Reflection"))
, norm_projection_matrix(prog_norm)
, norm_camera_matrix(prog_norm)
, norm_model_matrix(prog_norm)
, refl_projection_matrix(prog_refl)
, refl_camera_matrix(prog_refl)
, refl_model_matrix(prog_refl)
{
namespace sv = oglplus::smart_values;
vs_norm.Source(
"#version 330\n"
"in vec4 Position;"
"in vec3 Normal;"
"out vec3 geomColor;"
"out vec3 geomNormal;"
"out vec3 geomLight;"
"uniform mat4 ProjectionMatrix, CameraMatrix, ModelMatrix;"
"uniform vec3 LightPos;"
"void main(void)"
"{"
" gl_Position = ModelMatrix * Position;"
" geomColor = Normal;"
" geomNormal = mat3(ModelMatrix)*Normal;"
" geomLight = LightPos-gl_Position.xyz;"
" gl_Position = ProjectionMatrix * CameraMatrix * gl_Position;"
"}"
);
vs_norm.Compile();
vs_refl.Source(
"#version 330\n"
"in vec4 Position;"
"in vec3 Normal;"
"out vec3 vertNormal;"
"void main(void)"
"{"
" gl_Position = Position;"
" vertNormal = Normal;"
"}"
);
vs_refl.Compile();
gs_refl.Source(
"#version 330\n"
"layout(triangles) in;"
"layout(triangle_strip, max_vertices = 6) out;"
"in vec3 vertNormal[];"
"uniform mat4 ProjectionMatrix;"
"uniform mat4 CameraMatrix;"
"uniform mat4 ModelMatrix;"
"out vec3 geomColor;"
"out vec3 geomNormal;"
"out vec3 geomLight;"
"uniform vec3 LightPos;"
"mat4 ReflectionMatrix = mat4("
" 1.0, 0.0, 0.0, 0.0,"
" 0.0,-1.0, 0.0, 0.0,"
" 0.0, 0.0, 1.0, 0.0,"
" 0.0, 0.0, 0.0, 1.0 "
");"
"void main(void)"
"{"
" for(int v=0; v!=gl_in.length(); ++v)"
" {"
" vec4 Position = gl_in[v].gl_Position;"
" gl_Position = ModelMatrix * Position;"
" geomColor = vertNormal[v];"
" geomNormal = mat3(ModelMatrix)*vertNormal[v];"
" geomLight = LightPos - gl_Position.xyz;"
" gl_Position = "
" ProjectionMatrix *"
" CameraMatrix *"
" ReflectionMatrix *"
" gl_Position;"
" EmitVertex();"
" }"
" EndPrimitive();"
"}"
);
gs_refl.Compile();
fs.Source(
"#version 330\n"
"in vec3 geomColor;"
"in vec3 geomNormal;"
"in vec3 geomLight;"
"out vec4 fragColor;"
"void main(void)"
"{"
" float l = length(geomLight);"
" float d = l > 0.0 ? dot("
" geomNormal, "
" normalize(geomLight)"
" ) / l : 0.0;"
" float i = 0.2 + max(d, 0.0) * 2.0;"
" fragColor = vec4(abs(geomNormal)*i, 1.0);"
"}"
);
fs.Compile();
prog_norm.AttachShader(vs_norm);
prog_norm.AttachShader(fs);
prog_norm.Link();
norm_projection_matrix.BindTo("ProjectionMatrix");
norm_camera_matrix.BindTo("CameraMatrix");
norm_model_matrix.BindTo("ModelMatrix");
prog_refl.AttachShader(vs_refl);
prog_refl.AttachShader(gs_refl);
prog_refl.AttachShader(fs);
prog_refl.Link();
refl_projection_matrix.BindTo("ProjectionMatrix");
refl_camera_matrix.BindTo("CameraMatrix");
refl_model_matrix.BindTo("ModelMatrix");
torus.Bind();
{
std::vector<GLfloat> data;
GLuint n_per_vertex = make_torus.Positions(data);
typedef VertexArrayAttrib VAA;
VertexAttribSlot
loc_norm = VAA::GetLocation(prog_norm, "Position"),
loc_refl = VAA::GetLocation(prog_refl, "Position");
assert(loc_norm == loc_refl);
VertexArrayAttrib attr(loc_norm);
attr.Setup<GLfloat>(n_per_vertex);
attr.Enable();
}
{
std::vector<GLfloat> data;
GLuint n_per_vertex = make_torus.Normals(data);
typedef VertexArrayAttrib VAA;
VertexAttribSlot
loc_norm = VAA::GetLocation(prog_norm, "Normal"),
loc_refl = VAA::GetLocation(prog_refl, "Normal");
assert(loc_norm == loc_refl);
VertexArrayAttrib attr(loc_norm);
attr.Setup<GLfloat>(n_per_vertex);
attr.Enable();
}
plane.Bind();
{
GLfloat data[4*3] = {
-2.0f, 0.0f, 2.0f,
-2.0f, 0.0f, -2.0f,
2.0f, 0.0f, 2.0f,
2.0f, 0.0f, -2.0f
};
prog_norm.Use();
VertexArrayAttrib attr(prog_norm, "Position");
attr.Enable();
}
{
GLfloat data[4*3] = {
-0.1f, 1.0f, 0.1f,
-0.1f, 1.0f, -0.1f,
0.1f, 1.0f, 0.1f,
0.1f, 1.0f, -0.1f
};
prog_norm.Use();
VertexArrayAttrib attr(prog_norm, "Normal");
attr.Enable();
}
Vec3f lightPos(2.0f, 2.0f, 3.0f);
prog_norm.Use();
(prog_norm/
"LightPos").
Set(lightPos);
prog_refl.Use();
(prog_refl/
"LightPos").
Set(lightPos);
gl.ClearColor(0.2f, 0.2f, 0.2f, 0.0f);
gl.ClearDepth(1.0f);
gl.ClearStencil(0);
}
void Reshape(GLuint width, GLuint height)
{
gl.Viewport(width, height);
Degrees(65),
double(width)/height,
1, 40
);
norm_projection_matrix.Set(projection);
refl_projection_matrix.Set(projection);
}
{
namespace sv = oglplus::smart_values;
gl.Clear().ColorBuffer().DepthBuffer().StencilBuffer();
6.5,
Degrees(time * 135),
Degrees(15 + (-
SineWave(0.25+time/12.5)+1.0)*0.5*75)
);
norm_camera_matrix.Set(camera);
refl_camera_matrix.Set(camera);
prog_norm.Use();
gl.ColorMask(false, false, false, false);
norm_model_matrix.Set(identity);
plane.Bind();
gl.ColorMask(true, true, true, true);
prog_refl.Use();
refl_model_matrix.Set(model);
torus.Bind();
torus_instr.Draw(torus_indices);
prog_norm.Use();
norm_model_matrix.Set(model);
torus_instr.Draw(torus_indices);
norm_model_matrix.Set(identity);
plane.Bind();
}
{
return time < 30.0;
}
};
void setupExample(ExampleParams& ){ }
std::unique_ptr<ExampleThread> makeExampleThread(
Example& ,
unsigned ,
const ExampleParams&
){ return std::unique_ptr<ExampleThread>(); }
std::unique_ptr<Example> makeExample(const ExampleParams& )
{
return std::unique_ptr<Example>(new ReflectionExample);
}
}