Copyright 2008-2013 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 CheckerShaders
{
protected:
CheckerShaders(void)
: vertex_shader(
ObjectDesc("Vertex shader"),
StrLit("#version 330\n"
"uniform vec3 LightPosition;"
"uniform mat4 ProjectionMatrix, ModelMatrix, CameraMatrix;"
"in vec4 Position;"
"in vec3 Normal;"
"in vec2 TexCoord;"
"out vec3 vertNormal;"
"out vec3 vertLightDir;"
"out vec3 vertLightRefl;"
"out vec3 vertViewDir;"
"out vec2 vertTexCoord;"
"void main(void)"
"{"
" gl_Position = "
" ModelMatrix *"
" Position;"
" vertLightDir = LightPosition - gl_Position.xyz;"
" vertNormal = mat3(ModelMatrix)*Normal;"
" vertLightRefl = reflect("
" -normalize(vertLightDir),"
" normalize(vertNormal)"
" );"
" vertViewDir = ("
" vec4(0.0, 0.0, 1.0, 1.0)*"
" CameraMatrix"
" ).xyz;"
" gl_Position = "
" ProjectionMatrix *"
" CameraMatrix *"
" gl_Position;"
" vertTexCoord = TexCoord;"
"}")
), fragment_shader(
ObjectDesc("Fragment shader"),
StrLit("#version 330\n"
"uniform int SRepeat, TRepeat;"
"uniform vec3 Color1, Color2;"
"uniform float Refl1, Refl2;"
"in vec3 vertNormal;"
"in vec3 vertLightDir;"
"in vec3 vertLightRefl;"
"in vec3 vertViewDir;"
"in vec2 vertTexCoord;"
"out vec4 fragColor;"
"void main(void)"
"{"
" float l = length(vertLightDir);"
" float d = dot("
" normalize(vertNormal), "
" normalize(vertLightDir)"
" ) / l;"
" float s = dot("
" normalize(vertLightRefl),"
" normalize(vertViewDir)"
" );"
" float c = ("
" int(vertTexCoord.x*SRepeat) % 2+"
" int(vertTexCoord.y*TRepeat) % 2"
" ) % 2;"
" vec3 lt = vec3(1.0, 1.0, 1.0);"
" vec3 chkr = mix(Color1, Color2, c);"
" fragColor = vec4("
" chkr * 0.3 + "
" (lt + chkr) * 1.5 * max(d, 0.0) + "
" lt * pow(max(s, 0.0), mix(Refl1, Refl2, c)), "
" 1.0"
" );"
"}")
)
{ }
};
class CheckerProgram
: public CheckerShaders
, public QuickProgram
{
private:
Program& prog(
void) {
return *
this;}
public:
Uniform<Vec3f> light_position;
Uniform<Mat4f> projection_matrix, camera_matrix, model_matrix;
Uniform<GLint> s_repeat, t_repeat;
Uniform<Vec3f> color_1, color_2;
Uniform<GLfloat> refl_1, refl_2;
CheckerProgram(void)
: CheckerShaders()
,
QuickProgram(std::false_type(), vertex_shader, fragment_shader)
, light_position(prog(), "LightPosition")
, projection_matrix(prog(), "ProjectionMatrix")
, camera_matrix(prog(), "CameraMatrix")
, model_matrix(prog(), "ModelMatrix")
, s_repeat(prog(), "SRepeat")
, t_repeat(prog(), "TRepeat")
, color_1(prog(), "Color1")
, color_2(prog(), "Color2")
, refl_1(prog(), "Refl1")
, refl_2(prog(), "Refl2")
{ }
};
template <typename ShapeBuilder>
class CheckerShape
{
private:
Context gl;
ShapeBuilder make_shape;
shapes::DrawingInstructions shape_instr;
typename ShapeBuilder::IndexArray shape_indices;
Buffer positions, normals, tex_coords;
public:
CheckerShape(
const Program& prog,
const ShapeBuilder& builder)
: make_shape(builder)
, shape_instr(make_shape.Instructions())
, shape_indices(make_shape.Indices())
{
vao.Bind();
{
std::vector<GLfloat> data;
GLuint n_per_vertex = make_shape.Positions(data);
attr.Setup<GLfloat>(n_per_vertex);
attr.Enable();
}
{
std::vector<GLfloat> data;
GLuint n_per_vertex = make_shape.Normals(data);
attr.Setup<GLfloat>(n_per_vertex);
attr.Enable();
}
{
std::vector<GLfloat> data;
GLuint n_per_vertex = make_shape.TexCoordinates(data);
attr.Setup<GLfloat>(n_per_vertex);
attr.Enable();
}
}
{
vao.Bind();
gl.FrontFace(make_shape.FaceWinding());
shape_instr.Draw(shape_indices);
}
};
class CheckerExample : public Example
{
private:
Context gl;
CheckerProgram prog;
CheckerShape<shapes::Plane> plane;
CheckerShape<shapes::Sphere> sphere;
CheckerShape<shapes::Cube> cube;
CheckerShape<shapes::Torus> torus;
public:
CheckerExample(void)
: prog()
, plane(prog, shapes::Plane(
Vec3f(5.0, 0.0, 0.0),
Vec3f(0.0, 0.0,-5.0)))
, sphere(prog, shapes::Sphere())
, cube(prog, shapes::Cube())
, torus(prog, shapes::Torus())
{
gl.ClearColor(0.6f, 0.6f, 0.5f, 0.0f);
gl.ClearDepth(1.0f);
prog.Use();
prog.light_position.Set(
Vec3f(4.0, 10.0, 4.0));
}
void Reshape(GLuint width, GLuint height)
{
gl.Viewport(width, height);
prog.projection_matrix.Set(
Degrees(60),
double(width)/height,
1, 30
)
);
}
{
gl.Clear().ColorBuffer().DepthBuffer();
prog.camera_matrix.Set(
10.0,
Degrees(45 +
SineWave(time / 20.0) * 40)
)
);
prog.s_repeat = 24;
prog.t_repeat = 24;
prog.color_1 =
Vec3f(1.0f, 1.0f, 0.9f);
prog.color_2 =
Vec3f(1.0f, 0.9f, 0.8f);
prog.refl_1 = 64;
prog.refl_2 = 8;
plane.Draw();
prog.model_matrix.Set(
);
prog.s_repeat = 36;
prog.t_repeat = 24;
prog.color_1 =
Vec3f(0.5f, 0.6f, 1.0f);
prog.color_2 =
Vec3f(0.2f, 0.3f, 0.7f);
prog.refl_1 = 64;
prog.refl_2 = 32;
sphere.Draw();
prog.model_matrix.Set(
);
prog.color_1 =
Vec3f(0.5f, 1.0f, 0.6f);
prog.color_2 =
Vec3f(0.2f, 0.7f, 0.3f);
prog.refl_1 = 64;
prog.refl_2 = 64;
torus.Draw();
prog.model_matrix.Set(
);
prog.s_repeat = 8;
prog.t_repeat = 8;
prog.color_1 =
Vec3f(1.0f, 0.6f, 0.5f);
prog.color_2 =
Vec3f(0.7f, 0.3f, 0.2f);
prog.refl_1 = 64;
prog.refl_2 = 8;
cube.Draw();
}
{
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 CheckerExample);
}
}