OpenGL: stipple support added to basic GLSL shader
[blender.git] / source / blender / gpu / shaders / gpu_shader_basic_frag.glsl
1
2 /* Options:
3  *
4  * USE_COLOR: use glColor for diffuse colors
5  * USE_TEXTURE: use texture for diffuse colors
6  * USE_SCENE_LIGHTING: use lights (up to 8)
7  * USE_SOLID_LIGHTING: assume 3 directional lights for solid draw mode
8  * USE_TWO_SIDED: flip normal towards viewer
9  * NO_SPECULAR: use specular component
10  */
11
12 #define NUM_SOLID_LIGHTS 3
13 #define NUM_SCENE_LIGHTS 8
14
15 /* Keep these in sync with GPU_basic_shader.h */
16 #define STIPPLE_HALFTONE                               0
17 #define STIPPLE_QUARTTONE                              1
18 #define STIPPLE_CHECKER_8PX                            2
19 #define STIPPLE_HEXAGON                                3
20 #define STIPPLE_DIAG_STRIPES                           4
21 #define STIPPLE_DIAG_STRIPES_SWAP                      5
22 #define STIPPLE_S3D_INTERLACE_ROW                      6
23 #define STIPPLE_S3D_INTERLACE_ROW_SWAP                 7
24 #define STIPPLE_S3D_INTERLACE_COLUMN                   8
25 #define STIPPLE_S3D_INTERLACE_COLUMN_SWAP              9
26 #define STIPPLE_S3D_INTERLACE_CHECKERBOARD             10
27 #define STIPPLE_S3D_INTERLACE_CHECKERBOARD_SWAP        11
28
29 #if defined(USE_SOLID_LIGHTING) || defined(USE_SCENE_LIGHTING)
30 varying vec3 varying_normal;
31
32 #ifndef USE_SOLID_LIGHTING
33 varying vec3 varying_position;
34 #endif
35 #endif
36
37 #ifdef USE_COLOR
38 varying vec4 varying_vertex_color;
39 #endif
40
41 #ifdef USE_TEXTURE
42 varying vec2 varying_texture_coord;
43 uniform sampler2D texture_map;
44 #endif
45
46 #ifdef USE_STIPPLE
47 uniform int stipple_id;
48 #endif
49
50 void main()
51 {
52 #if defined(USE_STIPPLE)
53         /* We have to use mod function and integer casting.
54          * This can be optimized further with the bitwise operations
55          * when GLSL 1.3 is supported. */
56         if (stipple_id == STIPPLE_HALFTONE ||
57             stipple_id == STIPPLE_S3D_INTERLACE_CHECKERBOARD ||
58             stipple_id == STIPPLE_S3D_INTERLACE_CHECKERBOARD_SWAP)
59         {
60             int result = int(mod(gl_FragCoord.x + gl_FragCoord.y, 2));
61             bool dis = result == 0;
62             if (stipple_id == STIPPLE_S3D_INTERLACE_CHECKERBOARD_SWAP)
63                 dis = !dis;
64             if (dis)
65                 discard;
66         }
67         else if (stipple_id == STIPPLE_QUARTTONE) {
68             int mody = int(mod(gl_FragCoord.y, 4));
69             int modx = int(mod(gl_FragCoord.x, 4));
70             if (mody == 0) {
71                 if (modx != 2)
72                     discard;
73             }
74             else if (mody == 2){
75                 if (modx != 0)
76                     discard;
77             }
78             else
79                 discard;
80         }
81         else if (stipple_id == STIPPLE_CHECKER_8PX) {
82             int result = int(mod(int(gl_FragCoord.x)/8 + int(gl_FragCoord.y)/8, 2));
83             if (result != 0)
84                 discard;
85         }
86         else if (stipple_id == STIPPLE_DIAG_STRIPES) {
87             int mody = int(mod(gl_FragCoord.y, 16));
88             int modx = int(mod(gl_FragCoord.x, 16));
89             if ((16 - modx > mody && mody > 8 - modx) || mody > 24 - modx)
90                 discard;
91         }
92         else if (stipple_id == STIPPLE_DIAG_STRIPES_SWAP) {
93             int mody = int(mod(gl_FragCoord.y, 16));
94             int modx = int(mod(gl_FragCoord.x, 16));
95             if (!((16 - modx > mody && mody > 8 - modx) || mody > 24 - modx))
96                 discard;
97         }
98         else if (stipple_id == STIPPLE_S3D_INTERLACE_ROW || stipple_id == STIPPLE_S3D_INTERLACE_ROW_SWAP) {
99             int result = int(mod(gl_FragCoord.y, 2));
100             bool dis = result == 0;
101             if (stipple_id == STIPPLE_S3D_INTERLACE_ROW_SWAP)
102                 dis = !dis;
103             if (dis)
104                 discard;
105         }
106         else if (stipple_id == STIPPLE_S3D_INTERLACE_COLUMN || stipple_id == STIPPLE_S3D_INTERLACE_COLUMN_SWAP) {
107             int result = int(mod(gl_FragCoord.x, 2));
108             bool dis = result != 0;
109             if (stipple_id == STIPPLE_S3D_INTERLACE_COLUMN_SWAP)
110                 dis = !dis;
111             if (dis)
112                 discard;
113         }
114         else if (stipple_id == STIPPLE_HEXAGON) {
115             int mody = int(mod(gl_FragCoord.y, 2));
116             int modx = int(mod(gl_FragCoord.x, 4));
117             if (mody != 0) {
118                 if (modx != 1)
119                     discard;
120             }
121             else {
122                 if (modx != 3)
123                     discard;
124             }
125         }
126
127
128 #endif
129
130 #if defined(USE_SOLID_LIGHTING) || defined(USE_SCENE_LIGHTING)
131         /* compute normal */
132         vec3 N = normalize(varying_normal);
133
134 #ifdef USE_TWO_SIDED
135         if (!gl_FrontFacing)
136                 N = -N;
137 #endif
138
139         /* compute diffuse and specular lighting */
140         vec3 L_diffuse = vec3(0.0);
141 #ifndef NO_SPECULAR
142         vec3 L_specular = vec3(0.0);
143 #endif
144
145 #ifdef USE_SOLID_LIGHTING
146         /* assume 3 directional lights */
147         for (int i = 0; i < NUM_SOLID_LIGHTS; i++) {
148                 vec3 light_direction = gl_LightSource[i].position.xyz;
149
150                 /* diffuse light */
151                 vec3 light_diffuse = gl_LightSource[i].diffuse.rgb;
152                 float diffuse_bsdf = max(dot(N, light_direction), 0.0);
153                 L_diffuse += light_diffuse*diffuse_bsdf;
154
155 #ifndef NO_SPECULAR
156                 /* specular light */
157                 vec3 light_specular = gl_LightSource[i].specular.rgb;
158                 vec3 H = gl_LightSource[i].halfVector.xyz;
159
160                 float specular_bsdf = pow(max(dot(N, H), 0.0), gl_FrontMaterial.shininess);
161                 L_specular += light_specular*specular_bsdf;
162 #endif
163         }
164 #else
165         /* all 8 lights, makes no assumptions, potentially slow */
166
167 #ifndef NO_SPECULAR
168         /* view vector computation, depends on orthographics or perspective */
169         vec3 V = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(varying_position): vec3(0.0, 0.0, -1.0);
170 #endif
171
172         for (int i = 0; i < NUM_SCENE_LIGHTS; i++) {
173                 /* todo: this is a slow check for disabled lights */
174                 if (gl_LightSource[i].specular.a == 0.0)
175                         continue;
176
177                 float intensity = 1.0;
178                 vec3 light_direction;
179
180                 if (gl_LightSource[i].position.w == 0.0) {
181                         /* directional light */
182                         light_direction = gl_LightSource[i].position.xyz;
183                 }
184                 else {
185                         /* point light */
186                         vec3 d = gl_LightSource[i].position.xyz - varying_position;
187                         light_direction = normalize(d);
188
189                         /* spot light cone */
190                         if (gl_LightSource[i].spotCutoff < 90.0) {
191                                 float cosine = max(dot(light_direction, -gl_LightSource[i].spotDirection), 0.0);
192                                 intensity = pow(cosine, gl_LightSource[i].spotExponent);
193                                 intensity *= step(gl_LightSource[i].spotCosCutoff, cosine);
194                         }
195
196                         /* falloff */
197                         float distance = length(d);
198
199                         intensity /= gl_LightSource[i].constantAttenuation +
200                                 gl_LightSource[i].linearAttenuation * distance +
201                                 gl_LightSource[i].quadraticAttenuation * distance * distance;
202                 }
203
204                 /* diffuse light */
205                 vec3 light_diffuse = gl_LightSource[i].diffuse.rgb;
206                 float diffuse_bsdf = max(dot(N, light_direction), 0.0);
207                 L_diffuse += light_diffuse*diffuse_bsdf*intensity;
208
209 #ifndef NO_SPECULAR
210                 /* specular light */
211                 vec3 light_specular = gl_LightSource[i].specular.rgb;
212                 vec3 H = normalize(light_direction - V);
213
214                 float specular_bsdf = pow(max(dot(N, H), 0.0), gl_FrontMaterial.shininess);
215                 L_specular += light_specular*specular_bsdf*intensity;
216 #endif
217         }
218 #endif
219
220         /* compute diffuse color, possibly from texture or vertex colors */
221         float alpha;
222
223 #if defined(USE_TEXTURE) && defined(USE_COLOR)
224         vec4 texture_color = texture2D(texture_map, varying_texture_coord);
225
226         L_diffuse *= texture_color.rgb * varying_vertex_color.rgb;
227         alpha = texture_color.a * varying_vertex_color.a;
228 #elif defined(USE_TEXTURE)
229         vec4 texture_color = texture2D(texture_map, varying_texture_coord);
230
231         L_diffuse *= texture_color.rgb;
232         alpha = texture_color.a;
233 #elif defined(USE_COLOR)
234         L_diffuse *= varying_vertex_color.rgb;
235         alpha = varying_vertex_color.a;
236 #else
237         L_diffuse *= gl_FrontMaterial.diffuse.rgb;
238         alpha = gl_FrontMaterial.diffuse.a;
239 #endif
240
241         /* sum lighting */
242         vec3 L = gl_FrontLightModelProduct.sceneColor.rgb + L_diffuse;
243
244 #ifndef NO_SPECULAR
245         L += L_specular*gl_FrontMaterial.specular.rgb;
246 #endif
247
248         /* write out fragment color */
249         gl_FragColor = vec4(L, alpha);
250 #else
251
252         /* no lighting */
253 #if defined(USE_TEXTURE) && defined(USE_COLOR)
254         gl_FragColor = texture2D(texture_map, varying_texture_coord) * varying_vertex_color;
255 #elif defined(USE_TEXTURE)
256         gl_FragColor = texture2D(texture_map, varying_texture_coord);
257 #elif defined(USE_COLOR)
258         gl_FragColor = varying_vertex_color;
259 #else
260         gl_FragColor = gl_FrontMaterial.diffuse;
261 #endif
262
263 #endif
264 }
265