#version 460
#extension GL_GOOGLE_include_directive : enable
#include <light.h>
#include <transform.h>
#include "links-shdr-common.h"
#include "shader-common-generic-lighting.h"
layout ( binding = BIND_SPHERE_POS ) buffer spr { vec4 sphere_pos_rad[]; };
layout ( binding = BIND_SPHERE_ROT ) buffer sr { mat4 sphere_rot[]; };
layout ( binding = BIND_SPHERE_COLOR ) buffer sc { vec4 sphere_color[]; };
layout ( binding = BIND_UNI_COMMON ) uniform Common_Uniform
{
Shdr_Uni_Common com;
};
bool opt_tryout1 = bool(com.tryout.x);
bool opt_tryout2 = bool(com.tryout.y);
float opt_tryoutf = com.tryoutf.x;
float opt_hw02_curl = com.tryoutf.y;
#ifdef _VERTEX_SHADER_
layout ( location = LOC_IN_POS ) in vec4 in_vertex_o;
#ifdef LOC_IN_TCOOR
layout ( location = LOC_IN_TCOOR ) in vec2 in_tex_coor;
#endif
layout ( location = 0 ) out Data_to_GS
{
vec3 normal_e;
vec4 vertex_e;
vec2 tex_coor;
vec4 color;
vec4 vertex_c;
float sphere_radius;
};
void
vs_main_instances_sphere()
{
vec4 pos_rad = sphere_pos_rad[gl_InstanceIndex];
float rad = pos_rad.w;
mat4 rot = sphere_rot[gl_InstanceIndex];
vec4 normr = rot * in_vertex_o;
vec3 normal_o = normr.xyz;
vec4 vertex_o = vec4( pos_rad.xyz + rad * normal_o, 1 );
vertex_c = gl_ModelViewProjectionMatrix * vertex_o;
vertex_e = gl_ModelViewMatrix * vertex_o;
normal_e = normalize(gl_NormalMatrix * normal_o );
tex_coor = in_tex_coor;
color = sphere_color[gl_InstanceIndex];
sphere_radius = rad;
}
#endif
#ifdef _GEOMETRY_SHADER_
layout ( location = 0 ) in Data_to_GS
{
vec3 normal_e;
vec4 vertex_e;
vec2 tex_coor;
vec4 color;
vec4 vertex_c;
float sphere_radius;
} In[];
layout ( location = 0 ) out Data_to_FS
{
vec3 normal_e;
vec4 vertex_e;
vec2 tex_coor;
flat vec4 color;
flat int use_tex;
};
layout ( triangles ) in;
const int slices = 7;
const int max_v = 6 + 2 * slices + 2;
layout ( triangle_strip, max_vertices = max_v ) out;
void
gs_main_shrink()
{
const bool opt_normal_sphere = bool(com.tryout.z);
const bool unworn = false;
if ( unworn )
{
for ( int i=0; i<3; i++ )
{
normal_e = In[opt_normal_sphere?i:0].normal_e;
vertex_e = In[i].vertex_e;
color = In[i].color;
use_tex = 1; gl_Position = In[i].vertex_c;
tex_coor = In[i].tex_coor;
EmitVertex();
}
EndPrimitive();
return;
}
vec3 ctr_e = vec3(0), cnorm_e = vec3(0);
for ( int i=0; i<3; i++ )
{
ctr_e += In[i].vertex_e.xyz;
cnorm_e += In[i].normal_e;
}
ctr_e *= 0.333333333333f;
cnorm_e *= 0.333333333333f;
float ht = In[0].sphere_radius * 0.01;
for ( int i=0; i<3; i++ )
{
normal_e = mix( In[i].normal_e, cnorm_e, opt_hw02_curl );
vertex_e.xyz =
mix( In[i].vertex_e.xyz, ctr_e, opt_hw02_curl ) + normal_e * ht;
vertex_e.w = 1;
gl_Position = gl_ProjectionMatrix * vertex_e;
tex_coor = In[i].tex_coor;
color = In[i].color;
use_tex = 1;
EmitVertex();
}
EndPrimitive();
for ( int i=0; i<3; i++ )
{
vertex_e = In[i].vertex_e;
normal_e = In[opt_normal_sphere?i:0].normal_e;
color.rgb = 0.5 * In[i].color.rgb;
color.a = In[i].color.a;
use_tex = 0;
gl_Position = gl_ProjectionMatrix * vertex_e;
EmitVertex();
}
EndPrimitive();
}
void
gs_main_curl()
{
const bool opt_normal_sphere = bool(com.tryout.z);
const bool unworn = false;
if ( unworn )
{
for ( int i=0; i<3; i++ )
{
normal_e = In[opt_normal_sphere?i:0].normal_e;
vertex_e = In[i].vertex_e;
color = In[i].color;
gl_Position = In[i].vertex_c;
tex_coor = In[i].tex_coor;
EmitVertex();
}
EndPrimitive();
return;
}
int v1_idx = 0;
const int v0_idx[2] = { ( v1_idx + 1 ) % 3, ( v1_idx + 2 ) % 3 };
vec4 p1_e = In[v1_idx].vertex_e; vec3 n1_e = In[v1_idx].normal_e; vec2 tc1 = In[v1_idx].tex_coor;
const float p_frac = opt_hw02_curl;
const float f0 = 1 - p_frac;
float fi[] = { 0, f0, 1 };
for ( int i=0; i<3; i++ )
{
const float f = fi[i];
for ( int j=0; j<2; j++ )
{
const int idx = v0_idx[j];
normal_e = opt_normal_sphere
? mix( In[idx].normal_e, n1_e, f ) : In[0].normal_e;
vertex_e = mix( In[idx].vertex_e, p1_e, f );
use_tex = int( i < 1 );
color = i < 1 ? In[0].color : In[0].color * vec4(0.5,0.5,0.5,1);
gl_Position = gl_ProjectionMatrix * vertex_e;
tex_coor = mix(In[idx].tex_coor, tc1, f);
EmitVertex();
}
}
EndPrimitive();
const float n_rev = 0.5;
const float two_pi = 2 * 3.14159265;
const float delta_theta = n_rev * p_frac * two_pi / slices;
const float delta_f = p_frac / slices;
vec3 p00_e = In[v0_idx[0]].vertex_e.xyz;
vec3 p01_e = In[v0_idx[1]].vertex_e.xyz;
vec3 ax = normalize(p01_e - p00_e);
vec3 v001 = p1_e.xyz - p00_e;
vec3 az = normalize( cross(ax,v001) );
vec3 ay = cross(az,ax);
const float d = dot(v001,ay);
const float r = d / ( n_rev * two_pi );
vec3 ctr_e = p1_e.xyz - p_frac * d * ay + r * az;
for ( int i=0; i<=slices; i++ )
{
const float theta = 1.5f * 3.1415927f + delta_theta * i;
const float f = f0 + delta_f * i;
vec3 nc = ay * cos(theta) + az * sin(theta);
vec3 vc = r * nc;
for ( int j=0; j<2; j++ )
{
const int idx = v0_idx[j];
vec3 p_e = mix( In[idx].vertex_e.xyz, p1_e.xyz, f );
vec3 v_pc = ctr_e - p_e;
vertex_e.xyz = ctr_e + vc - dot(v_pc,ax) * ax;
vertex_e.w = 1;
normal_e = nc;
use_tex = 1;
tex_coor = mix( In[idx].tex_coor, tc1, f );
color = In[0].color;
gl_Position = gl_ProjectionMatrix * vertex_e;
EmitVertex();
}
}
EndPrimitive();
}
#endif
#ifdef _FRAGMENT_SHADER_
#ifdef BIND_TEXUNIT
layout ( binding = BIND_TEXUNIT ) uniform sampler2D tex_unit_0;
#endif
layout ( location = 0 ) in Data_to_FS
{
vec3 normal_e;
vec4 vertex_e;
vec2 tex_coor;
flat vec4 color;
flat int use_tex;
};
layout ( location = 0 ) out vec4 frag_color;
void
fs_main_common()
{
#ifdef BIND_TEXUNIT
vec4 texel = gl_FrontFacing && use_tex == 1
? texture(tex_unit_0,tex_coor) : vec4(1,1,1,1);
#else
vec4 texel = vec4(1,1,1,1);
#endif
vec4 color2 = gl_FrontFacing ? color : vec4(0.5,0,0,1);
frag_color = texel * generic_lighting(vertex_e, color2, normal_e);
}
#endif