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)
namespace oglplus {
class VolLightExample : public Example
{
private:
Context gl;
const GLuint samples;
public:
VolLightExample(void)
, volume_prog(ObjectDesc("Volume"))
, plane_prog(ObjectDesc("Plane"))
, samples(150)
{
volume_vs.Source(
"#version 330\n"
"in vec4 Position;"
"out float vertZOffs;"
"uniform int SampleCount;"
"uniform mat4 CameraMatrix;"
"uniform vec3 ViewZ;"
"uniform float Size;"
"void main(void)"
"{"
" float hp = (SampleCount-1) * 0.5;"
" vertZOffs = (gl_InstanceID - hp)/hp;"
" gl_Position = vec4("
" Position.xyz +"
" ViewZ*vertZOffs*Size*0.5,"
" 1.0"
" );"
"}"
);
volume_vs.Compile();
volume_gs.Source(
"#version 330\n"
"layout(points) in;"
"layout(triangle_strip, max_vertices = 4) out;"
"uniform mat4 CameraMatrix, ProjectionMatrix;"
"uniform mat4 TexProjectionMatrix;"
"uniform vec3 ViewX, ViewY;"
"uniform float Size;"
"in float vertZOffs[];"
"out vec4 geomTexCoord;"
"void main(void)"
"{"
" float zo = vertZOffs[0];"
" float yo[2] = float[2](-1.0, 1.0);"
" float xo[2] = float[2](-1.0, 1.0);"
" for(int j=0;j!=2;++j)"
" for(int i=0;i!=2;++i)"
" {"
" vec4 v = vec4("
" gl_in[0].gl_Position.xyz+"
" ViewX * xo[i] * Size+"
" ViewY * yo[j] * Size,"
" 1.0"
" );"
" geomTexCoord = "
" TexProjectionMatrix *"
" v;"
" gl_Position = "
" ProjectionMatrix *"
" CameraMatrix * v;"
" EmitVertex();"
" }"
" EndPrimitive();"
"}"
);
volume_gs.Compile();
volume_fs.Source(
"#version 330\n"
"uniform sampler2D LightTex;"
"uniform int SampleCount;"
"in vec4 geomTexCoord;"
"out vec4 fragColor;"
"void main(void)"
"{"
" vec2 coord = geomTexCoord.st/geomTexCoord.q;"
" float depth = geomTexCoord.z;"
" if(depth < 0.0) discard;"
" vec4 t = texture(LightTex, coord*0.5 + 0.5);"
" if(t.a == 0.0) discard;"
" float alpha = 10.0*(1.0-t.a)/SampleCount;"
" alpha *= (t.r+t.g+t.b)*0.3333;"
" alpha /= sqrt(depth);"
" fragColor = vec4(t.rgb, alpha);"
"}"
);
volume_fs.Compile();
volume_prog.AttachShader(volume_vs);
volume_prog.AttachShader(volume_gs);
volume_prog.AttachShader(volume_fs);
volume_prog.Link();
volume_prog.Use();
volume.Bind();
volume_pos.Bind(Buffer::Target::Array);
{
GLfloat position[3] = {0.0, 0.0, 0.0};
Buffer::Data(Buffer::Target::Array, 3, position);
VertexArrayAttrib attr(volume_prog, "Position");
attr.Enable();
}
Vec3f lightPos(2.0f, 4.0f, -3.0f);
auto texProjMat =
Uniform<GLint>(volume_prog,
"SampleCount").
Set(samples);
Uniform<GLfloat>(volume_prog,
"Size").
Set(Length(lightPos));
Uniform<Mat4f>(volume_prog,
"TexProjectionMatrix").
Set(texProjMat);
plane_vs.Source(
"#version 330\n"
"in vec4 Position;"
"uniform mat4 CameraMatrix, ProjectionMatrix;"
"uniform mat4 TexProjectionMatrix;"
"out vec2 vertChecker;"
"out vec4 vertTexCoord;"
"void main(void)"
"{"
" gl_Position = "
" ProjectionMatrix *"
" CameraMatrix *"
" Position;"
" vertTexCoord = "
" TexProjectionMatrix *"
" Position;"
" vertChecker = Position.xz;"
"}"
);
plane_vs.Compile();
plane_fs.Source(
"#version 330\n"
"uniform sampler2D LightTex;"
"in vec4 vertTexCoord;"
"in vec2 vertChecker;"
"out vec4 fragColor;"
"void main(void)"
"{"
" vec2 coord = vertTexCoord.st/vertTexCoord.q;"
" vec4 t = texture(LightTex, coord*0.5 + 0.5);"
" float i = ("
" 1 +"
" int(vertChecker.x+10) % 2+"
" int(vertChecker.y+10) % 2"
" ) % 2;"
" vec3 color = vec3(0.1, 0.1, 0.1);"
" color += t.rgb * (1.0 - t.a);"
" color *= mix("
" vec3(0.9, 0.9, 1.0), "
" vec3(0.4, 0.4, 0.9), "
" i"
" );"
" fragColor = vec4(color, 1.0);"
"}"
);
plane_fs.Compile();
plane_prog.AttachShader(plane_vs);
plane_prog.AttachShader(plane_fs);
plane_prog.Link();
plane_prog.Use();
Uniform<Mat4f>(plane_prog,
"TexProjectionMatrix").
Set(texProjMat);
plane.Bind();
plane_pos.Bind(Buffer::Target::Array);
{
GLfloat data[4*3] = {
-9.0f, -4.0f, 9.0f,
-9.0f, -4.0f, -9.0f,
9.0f, -4.0f, 9.0f,
9.0f, -4.0f, -9.0f
};
Buffer::Data(Buffer::Target::Array, 4*3, data);
plane_prog.Use();
VertexArrayAttrib attr(plane_prog, "Position");
attr.Enable();
}
Texture::Active(0);
ProgramUniformSampler(volume_prog, "LightTex").Set(0);
light_tex
<< Texture::Target::_2D
<<
Vec4f(0.0f, 0.0f, 0.0f, 0.0f)
<< TextureMipmap();
gl.ClearColor(0.0f, 0.05f, 0.1f, 0.0f);
gl.ClearDepth(1.0f);
}
void Reshape(GLuint width, GLuint height)
{
gl.Viewport(width, height);
Degrees(60),
double(width)/height,
1, 40
);
ProgramUniform<Mat4f>(
plane_prog,
"ProjectionMatrix"
ProgramUniform<Mat4f>(
volume_prog,
"ProjectionMatrix"
}
{
gl.Clear().ColorBuffer().DepthBuffer();
8.0f,
);
plane.Bind();
plane_prog.Use();
Uniform<Mat4f>(plane_prog,
"CameraMatrix").
Set(cameraMatrix);
volume.Bind();
volume_prog.Use();
Uniform<Mat4f>(volume_prog,
"CameraMatrix").
Set(cameraMatrix);
Uniform<Vec3f>(volume_prog,
"ViewX").
Set(
cameraMatrix.Row(0).xyz()
);
Uniform<Vec3f>(volume_prog,
"ViewY").
Set(
cameraMatrix.Row(1).xyz()
);
Uniform<Vec3f>(volume_prog,
"ViewZ").
Set(
cameraMatrix.Row(2).xyz()
);
gl.DrawArraysInstanced(
0, 1,
samples
);
}
{
return time < 60.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 VolLightExample);
}
}