void Render(double time) { gl.Clear().ColorBuffer().DepthBuffer(); // auto camera = CamMatrixf::Orbiting( Vec3f(), 4.5, Degrees(time * 35), Degrees(SineWave(time / 30.0) * 60) ); auto model = ModelMatrixf::RotationY(FullCircles(time * 0.25)) * ModelMatrixf::RotationX(FullCircles(time * 0.33)); camera_matrix.Set(camera); model_matrix.Set(model); transf_time.Set(time); face_pp.Bind(); gl.PolygonMode(PolygonMode::Fill); torus_instr.Draw(torus_indices); frame_pp.Bind(); gl.PolygonMode(PolygonMode::Line); torus_instr.Draw(torus_indices); }
void RenderFrameShadowMap( const Vec3f& light_position, const Mat4f& torus_matrix, const Mat4f& light_proj_matrix ) { frame_shadow_fbo.Bind(Framebuffer::Target::Draw); gl.Viewport(shadow_tex_side, shadow_tex_side); gl.ClearDepthBuffer(1.0f); gl.CullFace(Face::Back); transf_prog.camera_matrix.Set(light_proj_matrix); transf_prog.camera_position.Set(light_position); // Render the torus' frame transf_prog.model_matrix.Set(torus_matrix); shadow_pp.Bind(); gl.Enable(Capability::PolygonOffsetFill); torus.Draw( [](GLuint phase) -> bool { return (phase <= 3); } ); gl.Disable(Capability::PolygonOffsetFill); }
void RenderGlassShadowMap( const Vec3f& light_position, const Vec3f& torus_center, const Mat4f& torus_matrix, const Mat4f& light_proj_matrix ) { glass_shadow_fbo.Bind(Framebuffer::Target::Draw); gl.Viewport(shadow_tex_side, shadow_tex_side); const GLfloat clear_color[4] = {1.0f, 1.0f, 1.0f, 0.0f}; gl.ClearColorBuffer(0, clear_color); transf_prog.camera_matrix.Set(light_proj_matrix); transf_prog.camera_position.Set(light_position); transf_prog.light_proj_matrix.Set(light_proj_matrix); transf_prog.light_position.Set(light_position); // Render the torus' frame transf_prog.model_matrix.Set(torus_matrix); // setup the view clipping plane Planef clip_plane = Planef::FromPointAndNormal( torus_center, Normalized(light_position-torus_center) ); transf_prog.clip_plane.Set(clip_plane.Equation()); light_pp.Bind(); light_prog.color = Vec3f(0.6f, 0.4f, 0.1f); gl.Disable(Capability::DepthTest); gl.Enable(Functionality::ClipDistance, 0); gl.Enable(Capability::Blend); for(int c=0; c!=2; ++c) { transf_prog.clip_direction.Set((c == 0)?1:-1); for(int p=3; p>=0; --p) { if(p % 2 == 0) gl.CullFace(Face::Front); else gl.CullFace(Face::Back); torus.Draw( [&p](GLuint phase) -> bool { if(p == 0 || p == 3) { return (phase == 4); } else return (phase > 4); } ); } } gl.Disable(Capability::Blend); gl.Disable(Functionality::ClipDistance, 0); gl.Enable(Capability::DepthTest); }
TorusExample(void) : make_torus(1.0, 0.5, 18, 36) , torus_instr(make_torus.Instructions()) , torus_indices(make_torus.Indices()) , transf_prog(make_transf_prog()) , face_prog(make_face_prog()) , frame_prog(make_frame_prog()) , projection_matrix(transf_prog, "ProjectionMatrix") , camera_matrix(transf_prog, "CameraMatrix") , model_matrix(transf_prog, "ModelMatrix") , transf_time(transf_prog, "Time") { transf_prog.Use(); torus.Bind(); verts.Bind(Buffer::Target::Array); { std::vector<GLfloat> data; GLuint n_per_vertex = make_torus.Positions(data); Buffer::Data(Buffer::Target::Array, data); VertexArrayAttrib attr(transf_prog, "Position"); attr.Setup<GLfloat>(n_per_vertex); attr.Enable(); } normals.Bind(Buffer::Target::Array); { std::vector<GLfloat> data; GLuint n_per_vertex = make_torus.Normals(data); Buffer::Data(Buffer::Target::Array, data); VertexArrayAttrib attr(transf_prog, "Normal"); attr.Setup<GLfloat>(n_per_vertex); attr.Enable(); } texcoords.Bind(Buffer::Target::Array); { std::vector<GLfloat> data; GLuint n_per_vertex = make_torus.TexCoordinates(data); Buffer::Data(Buffer::Target::Array, data); VertexArrayAttrib attr(transf_prog, "TexCoord"); attr.Setup<GLfloat>(n_per_vertex); attr.Enable(); } face_pp.Bind(); face_prog.Use(); face_pp.UseStages(transf_prog).Vertex().Geometry(); face_pp.UseStages(face_prog).Fragment(); frame_pp.Bind(); frame_prog.Use(); frame_pp.UseStages(transf_prog).Vertex().Geometry(); frame_pp.UseStages(frame_prog).Fragment(); gl.Bind(NoProgramPipeline()); gl.Use(NoProgram()); gl.ClearColor(0.7f, 0.6f, 0.5f, 0.0f); gl.ClearDepth(1.0f); gl.Enable(Capability::DepthTest); gl.DepthFunc(CompareFn::Less); gl.FrontFace(make_torus.FaceWinding()); }
void RenderImage( double time, const Vec3f& torus_center, const Mat4f& torus_matrix, const Mat4f& light_proj_matrix ) { // this is going into the on-screen framebuffer DefaultFramebuffer().Bind(Framebuffer::Target::Draw); gl.ClearColor(0.6f, 0.6f, 0.5f, 0.0f); gl.Viewport(width, height); gl.Clear().ColorBuffer().DepthBuffer(); gl.CullFace(Face::Back); // transf_prog.light_proj_matrix.Set(light_proj_matrix); Mat4f perspective = CamMatrixf::PerspectiveX( Degrees(60), float(width)/height, 1, 60 ); // setup the camera Vec3f camera_target(0.0f, 0.8f, 0.0f); auto camera = CamMatrixf::Orbiting( camera_target, GLfloat(8.0 - SineWave(time / 15.0)*3.0), FullCircles(time / 24.0), Degrees(45 + SineWave(time / 20.0) * 40) ); Vec3f camera_position = camera.Position(); transf_prog.camera_matrix.Set(perspective*camera); transf_prog.camera_position.Set(camera_position); // setup the view clipping plane Planef clip_plane = Planef::FromPointAndNormal( torus_center, Normalized(camera_position-torus_center) ); metal_pp.Bind(); // Render the plane transf_prog.model_matrix = ModelMatrixf(); transf_prog.texture_matrix.Set(Mat2f(Vec2f(9.0f,0.0f), Vec2f(0.0f,9.0f))); metal_prog.color_1 = Vec3f(1.0f, 0.9f, 0.8f); metal_prog.color_2 = Vec3f(0.9f, 0.8f, 0.6f); metal_prog.with_glass_shadow = 1; plane.Draw([](GLuint) -> bool {return true;}); // Render the torus transf_prog.model_matrix.Set(torus_matrix); transf_prog.texture_matrix.Set(Mat2f(Vec2f(16.0f,0.0f), Vec2f(0.0f, 4.0f))); metal_prog.metal_tex.Set(0); metal_prog.color_1 = Vec3f(0.9f, 0.9f, 0.9f); metal_prog.color_2 = Vec3f(0.3f, 0.3f, 0.3f); metal_prog.with_glass_shadow = 0; // the metal-part torus.Draw( [](GLuint phase) -> bool { return (phase <= 3); } ); // now the glass part glass_pp.Bind(); glass_prog.color = Vec3f(0.6f, 0.4f, 0.1f); gl.Enable(Functionality::ClipDistance, 0); gl.Enable(Capability::Blend); transf_prog.clip_plane.Set(clip_plane.Equation()); for(int c=0; c!=2; ++c) { transf_prog.clip_direction.Set((c == 0)?-1:1); for(int p=0; p!=4; ++p) { if(p % 2 == 0) gl.CullFace(Face::Front); else gl.CullFace(Face::Back); torus.Draw( [&p](GLuint phase) -> bool { if(p == 0 || p == 3) return (phase == 4); else return (phase > 4); } ); } } gl.Disable(Capability::Blend); gl.Disable(Functionality::ClipDistance, 0); }
GlassAndMetalExample(void) : transf_prog() , metal_prog() , plane(transf_prog, shapes::Plane(Vec3f(9, 0, 0), Vec3f(0, 0,-9))) , torus(transf_prog, shapes::WickerTorus()) , shadow_tex_side(1024) { NoProgram().Use(); shadow_pp.Bind(); shadow_pp.UseStages(transf_prog).Vertex(); shadow_pp.UseStages(shadow_prog).Fragment(); light_pp.Bind(); light_pp.UseStages(transf_prog).Vertex(); light_pp.UseStages(light_prog).Fragment(); glass_pp.Bind(); glass_pp.UseStages(transf_prog).Vertex(); glass_pp.UseStages(glass_prog).Fragment(); metal_pp.Bind(); metal_pp.UseStages(transf_prog).Vertex(); metal_pp.UseStages(metal_prog).Fragment(); Texture::Active(0); metal_prog.metal_tex.Set(0); gl.Bound(Texture::Target::_2D, metal_texture) .MinFilter(TextureMinFilter::LinearMipmapLinear) .MagFilter(TextureMagFilter::Linear) .WrapS(TextureWrap::Repeat) .WrapT(TextureWrap::Repeat) .Image2D( images::BrushedMetalUByte( 512, 512, 5120, -3, +3, 32, 128 ) ).GenerateMipmap(); Texture::Active(1); metal_prog.frame_shadow_tex.Set(1); glass_prog.frame_shadow_tex.Set(1); gl.Bound(Texture::Target::_2D, frame_shadow_tex) .MinFilter(TextureMinFilter::Linear) .MagFilter(TextureMagFilter::Linear) .WrapS(TextureWrap::ClampToEdge) .WrapT(TextureWrap::ClampToEdge) .CompareMode(TextureCompareMode::CompareRefToTexture) .Image2D( 0, PixelDataInternalFormat::DepthComponent32, shadow_tex_side, shadow_tex_side, 0, PixelDataFormat::DepthComponent, PixelDataType::Float, nullptr ); gl.Bound(Framebuffer::Target::Draw, frame_shadow_fbo) .AttachTexture( FramebufferAttachment::Depth, frame_shadow_tex, 0 ); Texture::Active(2); metal_prog.glass_shadow_tex.Set(2); gl.Bound(Texture::Target::_2D, glass_shadow_tex) .MinFilter(TextureMinFilter::Linear) .MagFilter(TextureMagFilter::Linear) .WrapS(TextureWrap::ClampToEdge) .WrapT(TextureWrap::ClampToEdge) .Image2D( 0, PixelDataInternalFormat::RGBA, shadow_tex_side, shadow_tex_side, 0, PixelDataFormat::RGBA, PixelDataType::UnsignedByte, nullptr ); gl.Bound(Framebuffer::Target::Draw, glass_shadow_fbo) .AttachTexture( FramebufferAttachment::Color, glass_shadow_tex, 0 ); gl.ClearDepth(1.0f); gl.Enable(Capability::DepthTest); gl.Enable(Capability::CullFace); gl.BlendFunc(BlendFn::SrcAlpha, BlendFn::OneMinusSrcAlpha); gl.PolygonOffset(1.0, 1.0); }
void RenderImage( double time, const Mat4f& torus_matrix, const Mat4f& light_proj_matrix ) { // this is going into the on-screen framebuffer DefaultFramebuffer().Bind(Framebuffer::Target::Draw); gl.ClearColor(1.0f, 0.9f, 0.8f, 0.0f); gl.Viewport(width, height); gl.Clear().ColorBuffer().DepthBuffer(); gl.CullFace(Face::Back); // transf_prog.light_proj_matrix.Set(light_proj_matrix); Mat4f perspective = CamMatrixf::PerspectiveX( Degrees(60), float(width)/height, 1, 60 ); // setup the camera Vec3f camera_target(0.0f, 0.8f, 0.0f); auto camera = CamMatrixf::Orbiting( camera_target, GLfloat(7.0 - SineWave(time / 14.0)*3.0), FullCircles(time / 26.0), Degrees(45 + SineWave(time / 17.0) * 40) ); Vec3f camera_position = camera.Position(); transf_prog.camera_matrix.Set(perspective*camera); transf_prog.camera_position.Set(camera_position); // render into the depth buffer shadow_pp.Bind(); gl.Enable(Capability::PolygonOffsetFill); gl.ColorMask(false, false, false, false); transf_prog.model_matrix = ModelMatrixf(); plane.Draw(); transf_prog.model_matrix.Set(torus_matrix); torus.Draw(); gl.ColorMask(true, true, true, true); gl.Disable(Capability::PolygonOffsetFill); gl.Enable(Capability::Blend); gl.Disable(Capability::Blend); // render into the color buffer sketch_pp.Bind(); gl.Enable(Capability::Blend); transf_prog.model_matrix = ModelMatrixf(); transf_prog.texture_matrix.Set(Mat2f(Vec2f(3.0, 0.0), Vec2f(0.0, 3.0))); plane.Draw(); transf_prog.model_matrix.Set(torus_matrix); transf_prog.texture_matrix.Set(Mat2f(Vec2f(8.0, 0.0), Vec2f(0.0, 2.0))); torus.Draw([](GLuint phase) -> bool { return phase < 4; }); transf_prog.texture_matrix.Set(Mat2f(Vec2f(0.0, 2.0), Vec2f(8.0, 0.0))); torus.Draw([](GLuint phase) -> bool { return phase >= 4; }); // render the edges line_pp.Bind(); transf_prog.model_matrix = ModelMatrixf(); plane.DrawEdges(); transf_prog.model_matrix.Set(torus_matrix); torus.DrawEdges(); gl.Disable(Capability::Blend); }
SketchExample(void) : transf_prog() , sketch_prog() , plane( transf_prog, shapes::Plane( Vec3f(0, 0, 0), Vec3f(9, 0, 0), Vec3f(0, 0,-9), 9, 9 ) ), torus(transf_prog, shapes::WickerTorus()) , sketch_tex_layers(8) , shadow_tex_side(1024) { NoProgram().Use(); shadow_pp.Bind(); shadow_pp.UseStages(transf_prog).Vertex(); shadow_pp.UseStages(shadow_prog).Fragment(); sketch_pp.Bind(); sketch_pp.UseStages(transf_prog).Vertex(); sketch_pp.UseStages(sketch_prog).Fragment(); line_pp.Bind(); line_pp.UseStages(transf_prog).Vertex(); line_pp.UseStages(line_prog).Geometry().Fragment(); Texture::Active(0); sketch_prog.sketch_tex.Set(0); { auto bound_tex = gl.Bound(Texture::Target::_3D, sketch_texture); for(GLuint i=0; i<sketch_tex_layers; ++i) { auto image = images::BrushedMetalUByte( 512, 512, 64 + i*128, -(2+i*4), +(2+i*4), 64, 256-i*4 ); if(i == 0) { bound_tex.Image3D( 0, PixelDataInternalFormat::RGB, image.Width(), image.Height(), sketch_tex_layers, 0, image.Format(), image.Type(), nullptr ); } bound_tex.SubImage3D( 0, 0, 0, i, image.Width(), image.Height(), 1, image.Format(), image.Type(), image.RawData() ); } bound_tex.GenerateMipmap(); bound_tex.MinFilter(TextureMinFilter::LinearMipmapLinear); bound_tex.MagFilter(TextureMagFilter::Linear); bound_tex.WrapS(TextureWrap::Repeat); bound_tex.WrapT(TextureWrap::Repeat); bound_tex.WrapR(TextureWrap::ClampToEdge); } Texture::Active(1); sketch_prog.shadow_tex.Set(1); gl.Bound(Texture::Target::_2D, shadow_tex) .MinFilter(TextureMinFilter::Linear) .MagFilter(TextureMagFilter::Linear) .WrapS(TextureWrap::ClampToEdge) .WrapT(TextureWrap::ClampToEdge) .CompareMode(TextureCompareMode::CompareRefToTexture) .Image2D( 0, PixelDataInternalFormat::DepthComponent32, shadow_tex_side, shadow_tex_side, 0, PixelDataFormat::DepthComponent, PixelDataType::Float, nullptr ); gl.Bound(Framebuffer::Target::Draw, frame_shadow_fbo) .AttachTexture( FramebufferAttachment::Depth, shadow_tex, 0 ); gl.ClearDepth(1.0f); gl.Enable(Capability::DepthTest); gl.Enable(Capability::CullFace); gl.DepthFunc(CompareFn::LEqual); gl.BlendFunc(BlendFn::SrcAlpha, BlendFn::OneMinusSrcAlpha); gl.PolygonOffset(1.0, 1.0); gl.LineWidth(1.5); }
TorusExample(void) : make_torus(1.0, 0.5, 18, 36) , torus_instr(make_torus.Instructions()) , torus_indices(make_torus.Indices()) , vs(ObjectDesc("Vertex")) , gs(ObjectDesc("Geometry")) , face_fs(ObjectDesc("Face fragment")) , frame_fs(ObjectDesc("Frame fragment")) , transf_prog(ObjectDesc("Transformation")) , face_prog(ObjectDesc("Face")) , frame_prog(ObjectDesc("Frame")) , projection_matrix(transf_prog, "ProjectionMatrix") , camera_matrix(transf_prog, "CameraMatrix") , model_matrix(transf_prog, "ModelMatrix") , transf_time(transf_prog, "Time") { vs.Source( "#version 330\n" "uniform mat4 ModelMatrix;" "in vec4 Position;" "in vec3 Normal;" "in vec2 TexCoord;" "out gl_PerVertex {" " vec4 gl_Position;" "};" "out vec3 vertNormal;" "out vec2 vertTexCoord;" "void main(void)" "{" " gl_Position = ModelMatrix * Position;" " vertNormal = (ModelMatrix*vec4(Normal,0.0)).xyz;" " vertTexCoord = TexCoord;" "}" ); vs.Compile(); gs.Source( "#version 330\n" "layout(triangles) in;" "layout(triangle_strip, max_vertices = 15) out;" "uniform mat4 CameraMatrix, ProjectionMatrix;" "uniform vec3 LightPos;" "uniform float Time;" "in gl_PerVertex {" " vec4 gl_Position;" "} gl_in[];" "in vec3 vertNormal[];" "in vec2 vertTexCoord[];" "out gl_PerVertex {" " vec4 gl_Position;" "};" "out vec3 geomNormal;" "out vec3 geomLight;" "out float geomGlow;" "flat out int geomTop;" "void main(void)" "{" " vec3 FaceNormal = normalize(" " vertNormal[0]+" " vertNormal[1]+" " vertNormal[2] " " );" " vec2 FaceCoord = 0.33333 * (" " vertTexCoord[0]+" " vertTexCoord[1]+" " vertTexCoord[2] " " );" " float Offs = (sin((FaceCoord.s + Time/10.0)* 3.14 * 2.0 * 10)*0.5 + 0.5)*0.4;" " Offs *= cos(FaceCoord.t * 3.1415 * 2.0)*0.5 + 0.51;" " vec3 pos[3], norm[3];" " for(int i=0; i!=3; ++i)" " pos[i] = gl_in[i].gl_Position.xyz;" " for(int i=0; i!=3; ++i)" " norm[i] = cross(" " FaceNormal, " " normalize(pos[(i+1)%3] - pos[i])" " );" " vec3 pofs = FaceNormal * Offs;" " geomTop = 0;" " for(int i=0; i!=3; ++i)" " {" " geomNormal = norm[i];" " for(int j=0; j!=2; ++j)" " {" " vec3 tpos = pos[(i+j)%3];" " geomLight = LightPos-tpos;" " geomGlow = 1.0;" " gl_Position = " " ProjectionMatrix *" " CameraMatrix *" " vec4(tpos, 1.0);" " EmitVertex();" " geomGlow = 0.7;" " geomLight = LightPos-tpos+pofs;" " gl_Position = " " ProjectionMatrix *" " CameraMatrix *" " vec4(tpos + pofs, 1.0);" " EmitVertex();" " }" " EndPrimitive();" " }" " geomGlow = 0.0;" " geomTop = 1;" " for(int i=0; i!=3; ++i)" " {" " geomLight = LightPos - (pos[i]+pofs);" " geomNormal = vertNormal[i];" " gl_Position = " " ProjectionMatrix *" " CameraMatrix *" " vec4(pos[i] + pofs, 1.0);" " EmitVertex();" " }" " EndPrimitive();" "}" ); gs.Compile(); transf_prog.AttachShader(vs); transf_prog.AttachShader(gs); transf_prog.MakeSeparable(); transf_prog.Link(); transf_prog.Use(); ProgramUniform<Vec3f>(transf_prog, "LightPos").Set(4, 4, -8); torus.Bind(); verts.Bind(Buffer::Target::Array); { std::vector<GLfloat> data; GLuint n_per_vertex = make_torus.Positions(data); Buffer::Data(Buffer::Target::Array, data); VertexAttribArray attr(transf_prog, "Position"); attr.Setup(n_per_vertex, DataType::Float); attr.Enable(); } normals.Bind(Buffer::Target::Array); { std::vector<GLfloat> data; GLuint n_per_vertex = make_torus.Normals(data); Buffer::Data(Buffer::Target::Array, data); VertexAttribArray attr(transf_prog, "Normal"); attr.Setup(n_per_vertex, DataType::Float); attr.Enable(); } texcoords.Bind(Buffer::Target::Array); { std::vector<GLfloat> data; GLuint n_per_vertex = make_torus.TexCoordinates(data); Buffer::Data(Buffer::Target::Array, data); VertexAttribArray attr(transf_prog, "TexCoord"); attr.Setup(n_per_vertex, DataType::Float); attr.Enable(); } face_fs.Source( "#version 330\n" "in vec3 geomNormal;" "in vec3 geomLight;" "in float geomGlow;" "flat in int geomTop;" "uniform vec3 TopColor, SideColor;" "const vec3 LightColor = vec3(1.0, 1.0, 1.0);" "out vec4 fragColor;" "void main(void)" "{" " float d = max(dot(" " normalize(geomLight)," " normalize(geomNormal)" " ), 0.0);" " vec3 color;" " if(geomTop != 0)" " {" " color = TopColor * d +" " LightColor * pow(d, 8.0);" " }" " else" " {" " color = SideColor * geomGlow +" " LightColor *" " pow(d, 2.0) * 0.2;" " }" " fragColor = vec4(color, 1.0);" "}" ); face_fs.Compile(); face_prog.AttachShader(face_fs); face_prog.MakeSeparable(); face_prog.Link(); ProgramUniform<Vec3f>(face_prog, "TopColor").Set(0.2f, 0.2f, 0.2f); ProgramUniform<Vec3f>(face_prog, "SideColor").Set(0.9f, 0.9f, 0.2f); face_pp.Bind(); face_prog.Use(); face_pp.UseStages(transf_prog).Vertex().Geometry(); face_pp.UseStages(face_prog).Fragment(); frame_fs.Source( "#version 330\n" "out vec4 fragColor;" "void main(void)" "{" " fragColor = vec4(0.2, 0.1, 0.0, 1.0);" "}" ); frame_fs.Compile(); frame_prog.AttachShader(frame_fs); frame_prog.MakeSeparable(); frame_prog.Link(); frame_pp.Bind(); frame_prog.Use(); frame_pp.UseStages(transf_prog).Vertex().Geometry(); frame_pp.UseStages(frame_prog).Fragment(); ProgramPipeline::Unbind(); Program::UseNone(); gl.ClearColor(0.7f, 0.6f, 0.5f, 0.0f); gl.ClearDepth(1.0f); gl.Enable(Capability::DepthTest); gl.DepthFunc(CompareFn::Less); gl.FrontFace(make_torus.FaceWinding()); }