203 lines
5.7 KiB
GLSL
203 lines
5.7 KiB
GLSL
/**
|
|
* @file depthToShadowVolumeG.glsl
|
|
*
|
|
* $LicenseInfo:firstyear=2011&license=viewerlgpl$
|
|
* Second Life Viewer Source Code
|
|
* Copyright (C) 2011, Linden Research, Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation;
|
|
* version 2.1 of the License only.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*
|
|
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
|
* $/LicenseInfo$
|
|
*/
|
|
#extension GL_ARB_geometry_shader4 : enable
|
|
#extension GL_ARB_texture_rectangle : enable
|
|
|
|
/*[EXTRA_CODE_HERE]*/
|
|
|
|
layout (triangles) in;
|
|
layout (triangle_strip, max_vertices = 128) out;
|
|
|
|
uniform sampler2DRect depthMap;
|
|
uniform mat4 shadowMatrix[6];
|
|
uniform vec4 lightpos;
|
|
|
|
VARYING vec2 vary_texcoord0;
|
|
|
|
out vec3 to_vec;
|
|
|
|
void cross_products(out vec4 ns[3], int a, int b, int c)
|
|
{
|
|
ns[0] = cross(gl_PositionIn[b].xyz - gl_PositionIn[a].xyz, gl_PositionIn[c].xyz - gl_PositionIn[a].xyz);
|
|
ns[1] = cross(gl_PositionIn[c].xyz - gl_PositionIn[b].xyz, gl_PositionIn[a].xyz - gl_PositionIn[b].xyz);
|
|
ns[2] = cross(gl_PositionIn[a].xyz - gl_PositionIn[c].xyz, gl_PositionIn[b].xyz - gl_PositionIn[c].xyz);
|
|
}
|
|
|
|
vec3 getLightDirection(vec4 lightpos, vec3 pos)
|
|
{
|
|
|
|
vec3 lightdir = lightpos.xyz - lightpos.w * pos;
|
|
return lightdir;
|
|
}
|
|
|
|
void emitTri(vec4 v[3])
|
|
{
|
|
gl_Position = proj_matrix * v[0];
|
|
EmitVertex();
|
|
|
|
gl_Position = proj_matrix * v[1];
|
|
EmitVertex();
|
|
|
|
gl_Position = proj_matrix * v[2];
|
|
EmitVertex();
|
|
|
|
EndPrimitive();
|
|
}
|
|
|
|
void emitQuad(vec4 v[4]
|
|
{
|
|
// Emit a quad as a triangle strip.
|
|
gl_Position = proj_matrix*v[0];
|
|
EmitVertex();
|
|
|
|
gl_Position = proj_matrix*v[1];
|
|
EmitVertex();
|
|
|
|
gl_Position = proj_matrix*v[2];
|
|
EmitVertex();
|
|
|
|
gl_Position = proj_matrix*v[3];
|
|
EmitVertex();
|
|
|
|
EndPrimitive();
|
|
}
|
|
|
|
void emitPrimitives(int layer)
|
|
{
|
|
int i = layer;
|
|
gl_Layer = i;
|
|
|
|
vec4 depth1 = vec4(texture2DRect(depthMap, tc0).rg, texture2DRect(depthMap, tc1).rg));
|
|
vec3 depth2 = vec4(texture2DRect(depthMap, tc2).rg, texture2DRect(depthMap, tc3).rg));
|
|
vec3 depth3 = vec4(texture2DRect(depthMap, tc4).rg, texture2DRect(depthMap, tc5).rg));
|
|
vec3 depth4 = vec4(texture2DRect(depthMap, tc6).rg, texture2DRect(depthMap, tc7).rg));
|
|
|
|
depth1 = min(depth1, depth2);
|
|
depth1 = min(depth1, depth3);
|
|
depth1 = min(depth1, depth4);
|
|
|
|
vec2 depth = min(depth1.xy, depth1.zw);
|
|
|
|
int side = sqrt(gl_VerticesIn);
|
|
|
|
for (int j = 0; j < side; j++)
|
|
{
|
|
for (int k = 0; k < side; ++k)
|
|
{
|
|
vec3 pos = gl_PositionIn[(j * side) + k].xyz;
|
|
vec4 v = shadowMatrix[i] * vec4(pos, 1.0);
|
|
gl_Position = v;
|
|
to_vec = pos - light_position.xyz * depth;
|
|
EmitVertex();
|
|
}
|
|
|
|
EndPrimitive();
|
|
}
|
|
|
|
vec3 norms[3]; // Normals
|
|
vec3 lightdir3]; // Directions toward light
|
|
|
|
vec4 v[4]; // Temporary vertices
|
|
|
|
vec4 or_pos[3] =
|
|
{ // Triangle oriented toward light source
|
|
gl_PositionIn[0],
|
|
gl_PositionIn[2],
|
|
gl_PositionIn[4]
|
|
};
|
|
|
|
// Compute normal at each vertex.
|
|
cross_products(n, 0, 2, 4);
|
|
|
|
// Compute direction from vertices to light.
|
|
lightdir[0] = getLightDirection(lightpos, gl_PositionIn[0].xyz);
|
|
lightdir[1] = getLightDirection(lightpos, gl_PositionIn[2].xyz);
|
|
lightdir[2] = getLightDirection(lightpos, gl_PositionIn[4].xyz);
|
|
|
|
// Check if the main triangle faces the light.
|
|
bool faces_light = true;
|
|
if (!(dot(ns[0],d[0]) > 0
|
|
|dot(ns[1],d[1]) > 0
|
|
|dot(ns[2],d[2]) > 0))
|
|
{
|
|
// Flip vertex winding order in or_pos.
|
|
or_pos[1] = gl_PositionIn[4];
|
|
or_pos[2] = gl_PositionIn[2];
|
|
faces_light = false;
|
|
}
|
|
|
|
// Near cap: simply render triangle.
|
|
emitTri(or_pos);
|
|
|
|
// Far cap: extrude positions to infinity.
|
|
v[0] =vec4(lightpos.w * or_pos[0].xyz - lightpos.xyz,0);
|
|
v[1] =vec4(lightpos.w * or_pos[2].xyz - lightpos.xyz,0);
|
|
v[2] =vec4(lightpos.w * or_pos[1].xyz - lightpos.xyz,0);
|
|
|
|
emitTri(v);
|
|
|
|
// Loop over all edges and extrude if needed.
|
|
for ( int i=0; i<3; i++ )
|
|
{
|
|
// Compute indices of neighbor triangle.
|
|
int v0 = i*2;
|
|
int nb = (i*2+1);
|
|
int v1 = (i*2+2) % 6;
|
|
cross_products(n, v0, nb, v1);
|
|
|
|
// Compute direction to light, again as above.
|
|
d[0] =lightpos.xyz-lightpos.w*gl_PositionIn[v0].xyz;
|
|
d[1] =lightpos.xyz-lightpos.w*gl_PositionIn[nb].xyz;
|
|
d[2] =lightpos.xyz-lightpos.w*gl_PositionIn[v1].xyz;
|
|
|
|
bool is_parallel = gl_PositionIn[nb].w < 1e-5;
|
|
|
|
// Extrude the edge if it does not have a
|
|
// neighbor, or if it's a possible silhouette.
|
|
if (is_parallel ||
|
|
( faces_light != (dot(ns[0],d[0])>0 ||
|
|
dot(ns[1],d[1])>0 ||
|
|
dot(ns[2],d[2])>0) ))
|
|
{
|
|
// Make sure sides are oriented correctly.
|
|
int i0 = faces_light ? v0 : v1;
|
|
int i1 = faces_light ? v1 : v0;
|
|
|
|
v[0] = gl_PositionIn[i0];
|
|
v[1] = vec4(lightpos.w*gl_PositionIn[i0].xyz - lightpos.xyz, 0);
|
|
v[2] = gl_PositionIn[i1];
|
|
v[3] = vec4(lightpos.w*gl_PositionIn[i1].xyz - lightpos.xyz, 0);
|
|
|
|
emitQuad(v);
|
|
}
|
|
}
|
|
}
|
|
|
|
void main()
|
|
{
|
|
// Output
|
|
emitPrimitives(0);
|
|
}
|