Linux OpenGL Practice Chapter -11-shadow

Source: Internet
Author: User

OpenGL Shadows

In a three-dimensional scenario, in order to make the scene look more realistic, you often need to add a shadow to it, OpenGL can use many techniques to achieve the shadow, and one of the very classic implementations is to use a shadow map implementation, in this section we will use a shadow map to achieve a simple scene of the shadow.

Principle

Using shadow maps to implement shading, the principle is to use OpenGL rendering to the map to render the current scene through depth test of the depth value of the slice to a depth map, and then render the object again by depth comparison to determine whether the slice is in the shadow.

Implementation steps

It consists of two steps:

1. Render the scene from the angle of the light source, this time the rendering we don't care what the scene looks like, just to get the depth value of the element and store the depth value in a depth map, which represents the maximum depth of light the light source can reach;

2. Render the scene again from the camera's point of view, while calculating the depth value of the slice in the light source coordinate when the slice is rendered, using this depth value and the depth value of the same element stored in the depth map, if it is less than or equal to the depth value in the depth map, it is not in the shadow or in the shadow.

Code

Creates a depth map, which is attached to the frame cache as a render attachment.

//Create frame Cache
Glgenframebuffers (1,&FBO);
Glbindframebuffer (GL_DRAW_FRAMEBUFFER,FBO);


     //create a depth textureGlgentextures (1,&Depthtex); Glbindtexture (Gl_texture_2d,depthtex); Glteximage2d (gl_texture_2d,0, Gl_depth_component,width,height,0, Gl_depth_component, Gl_float, NULL); Gltexparameteri (gl_texture_2d,gl_texture_min_filter,gl_linear); Gltexparameteri (gl_texture_2d,gl_texture_mag_filter,gl_linear); //Gltexparameteri (gl_texture_2d, Gl_texture_compare_mode, gl_compare_ref_to_texture); //Gltexparameteri (gl_texture_2d, gl_texture_compare_func,gl_lequal);Gltexparameteri (Gl_texture_2d,gl_texture_wrap_s,gl_clamp_to_edge); Gltexparameteri (Gl_texture_2d,gl_texture_wrap_t,gl_clamp_to_edge); //bindingGlframebuffertexture2d (Gl_draw_framebuffer,gl_depth_attachment,gl_texture_2d,depthtex,0);

The frame cache is bound to store the rendering results in the depth map.

       //Render Shadow MapsGlbindframebuffer (GL_DRAW_FRAMEBUFFER,FBO); Glviewport (0,0, Width,height); Glcleardepth (1.0); Glclear (Gl_color_buffer_bit|gl_depth_buffer_bit); //turn on polygon offset to avoid zfighting of deep dataglenable (Gl_polygon_offset_fill); Glpolygonoffset (2.0f,4.0f); //RenderingTshader->Use (); Tshader->setmatrix ("Model", Boxmodelmat.get ());       Glbindvertexarray (Boxvao); Gldrawarrays (Gl_triangles,0, $); Tshader->setmatrix ("Model", Planemodelmat.get ());       Glbindvertexarray (VAO); Gldrawarrays (Gl_triangles,0,6); Gldisable (Gl_polygon_offset_fill);

The shader used to render the shadow map is just the simplest shader, and the slice shader doesn't even do anything.

Shadow.vert

 the Core layout (location =0 in vec3 ipos;uniform mat4 model;uniform mat4 lightspace;                                     void Main () {        = lightspace * Model * VEC4 (IPos,1.0);}

Shadow.frag

The gl_fragcoord.zvoid  main ()        {;}

You can also release the code of the comment to show the depth of the set element, but it is more efficient when commented out, because the bottom layer will set the depth buffer anyway.

When you finish rendering the shadow map, render the scene again and use the shadow map.

        //back to Camera viewGlbindframebuffer (Gl_framebuffer,0); Glviewport (0,0, Width,height); Glclear (Gl_color_buffer_bit|gl_depth_buffer_bit); //draw a scenePlaneshader->Use ();        Glbindtexture (GL_TEXTURE_2D,TT); Planeshader->setmatrix ("Model", Boxmodelmat.get ());        Glbindvertexarray (Boxvao); Gldrawarrays (Gl_triangles,0, $); Planeshader-Use ();        Glbindtexture (Gl_texture_2d,depthtex); Modelshader->setmatrix ("Model", Planemodelmat.get ());        Glbindvertexarray (VAO); Gldrawarrays (Gl_triangles,0,6); Glbindtexture (gl_texture_2d,0);

Shadow map shader, note in this practice, because only the simplest box is rendered and no textures are used, the default glbindtexture is used to bind the shadow map, but when rendering a complex model, be sure to pay attention to the binding of the shadow map (using multiple textures in the shader).

Plane.vert

#version theCorelayout ( location=0)inchvec3 ipos;layout ( location=1)inchvec2 itexcoords;uniform mat4 model;uniform mat4 view;uniform mat4 proj;uniform mat4 Lightview; outvs_out {vec3 fragpos; VEC4 Fragposlightspace;} Vs_out; outvec2 texcoords;voidMain () {Vs_out.fragpos= VEC3 (Model * VEC4 (IPos,1.0)); Vs_out.fragposlightspace= Lightview * VEC4 (Vs_out.fragpos,1.0); Texcoords=itexcoords; Gl_position= proj * View * model * VEC4 (IPos,1.0);}

Plane.frag

#version theCoreinchvs_out {vec3 fragpos; VEC4 Fragposlightspace;} fs_in;inchvec2 texcoords;uniform sampler2d shadowmap; outVEC4 color;floatshadowcalculation (Vec4 fragposlightspace) {vec3 projcoords= FRAGPOSLIGHTSPACE.XYZ/FRAGPOSLIGHTSPACE.W; Projcoords= Projcoords *0.5+0.5; floatClosestdepth =Texture (Shadowmap, projcoords.xy). R; floatCurrentdepth =projcoords.z; floatShadow = currentdepth > Closestdepth?1.0:0.0; returnShadow;}voidMain () {VEC4 fragposlightspace=Fs_in.fragposlightspace; VEC3 Projcoords= FRAGPOSLIGHTSPACE.XYZ/FRAGPOSLIGHTSPACE.W; Projcoords= Projcoords *0.5+0.5; floatShadow =shadowcalculation (fs_in.fragposlightspace); VEC3 Red= VEC3 (1,0,0); VEC3 Lighting= VEC3 (0.1,0.1,0.1) +  (1-shadow) *Red; Color= VEC4 (lighting,1.0);}

Effect

Full code:

Https://github.com/xin-lover/opengl-learn/tree/master/chapter-11-shadow

Linux OpenGL Practice Chapter -11-shadow

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.