1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
|
//
// TODO:
// - implement texture1D, texture2D, texture3D, textureCube,
// - implement shadow1D, shadow2D,
// - implement dFdx, dFdy,
//
//
// From Shader Spec, ver. 1.051
//
// The output of the fragment shader goes on to be processed by the fixed function operations at
// the back end of the OpenGL pipeline. Fragment shaders interface with the back end of the OpenGL
// pipeline using the built-in variables gl_FragColor and gl_FragDepth, or by executing the discard
// keyword.
//
// These variables may be written more than once within a fragment shader. If so, the last value
// assigned is the one used in the subsequent fixed function pipeline. The values written to these
// variables may be read back after writing them. Reading from these variables before writing them
// results in an undefined value. The fixed functionality computed depth for a fragment may be
// obtained by reading gl_FragCoord.z, described below.
//
// Writing to gl_FragColor specifies the fragment color that will be used by the subsequent fixed
// functionality pipeline. If subsequent fixed functionality consumes fragment color and an
// execution of a fragment shader does not write a value to gl_FragColor then the fragment color
// consumed is undefined.
//
// If the frame buffer is configured as a color index buffer then behavior is undefined when using
// a fragment shader.
//
// Writing to gl_FragDepth will establish the depth value for the fragment being processed. If
// depth buffering is enabled, and a shader does not write gl_FragDepth, then the fixed function
// value for depth will be used as the fragment’s depth value. If a shader statically assigns
// a value to gl_FragDepth, and there is an execution path through the shader that does not set
// gl_FragDepth, then the value of the fragment’s depth may be undefined for some executions of
// the shader. That is, if a shader statically writes gl_FragDepth, then it is responsible for
// always writing it. There is also no guarantee that a shader can compute the same depth value
// as the fixed function value; an implementation will provide invariant results within shaders
// computing depth with the same source-level expression, but invariance is not provided between
// shaders and fixed functionality.
//
// Writes to gl_FragColor and gl_FragDepth need not be clamped within a shader. The fixed
// functionality pipeline following the fragment shader will clamp these values.
//
// If a shader executes the discard keyword, the fragment is discarded, and the values of
// gl_FragDepth and gl_FragColor become irrelevant.
//
// The variable gl_FragCoord is available as a read-only variable from within fragment shaders
// and it holds the window relative coordinates x, y, z, and 1/w values for the fragment. This
// value is the result of the fixed functionality that interpolates primitives after vertex
// processing to generate fragments. The z component is the depth value that would be used for
// the fragment’s depth if a shader contained no writes to gl_FragDepth. This is useful for
// invariance if a shader conditionally computes gl_FragDepth but otherwise wants the fixed
// functionality fragment depth.
//
// The fragment shader has access to the read-only built-in variable gl_FrontFacing whose value
// is true if the fragment belongs to a front-facing primitive. One use of this is to emulate
// two-sided lighting by selecting one of two colors calculated by the vertex shader.
//
// The built-in variables that are accessible from a fragment shader are intrinsically given types
// as follows:
//
vec4 gl_FragCoord;
bool gl_FrontFacing;
vec4 gl_FragColor;
float gl_FragDepth;
//
// However, they do not behave like variables with no qualifier; their behavior is as described
// above. These built-in variables have global scope.
//
//
// Unlike user-defined varying variables, the built-in varying variables don’t have a strict
// one-to-one correspondence between the vertex language and the fragment language. Two sets are
// provided, one for each language. Their relationship is described below.
//
// The following varying variables are available to read from in a fragment shader. The gl_Color
// and gl_SecondaryColor names are the same names as attributes passed to the vertex shader.
// However, there is no name conflict, because attributes are visible only in vertex shaders
// and the following are only visible in a fragment shader.
//
varying vec4 gl_Color;
varying vec4 gl_SecondaryColor;
varying vec4 gl_TexCoord[]; // at most will be gl_MaxTextureCoordsARB
varying float gl_FogFragCoord;
//
// The values in gl_Color and gl_SecondaryColor will be derived automatically by the system from
// gl_FrontColor, gl_BackColor, gl_FrontSecondaryColor, and gl_BackSecondaryColor based on which
// face is visible. If fixed functionality is used for vertex processing, then gl_FogFragCoord will
// either be the z-coordinate of the fragment in eye space, or the interpolation of the fog
// coordinate, as described in section 3.10 of the OpenGL 1.4 Specification. The gl_TexCoord[]
// values are the interpolated gl_TexCoord[] values from a vertex shader or the texture coordinates
// of any fixed pipeline based vertex functionality.
//
// Indices to the fragment shader gl_TexCoord array are as described above in the vertex shader
// text.
//
//
// The OpenGL Shading Language defines an assortment of built-in convenience functions for scalar
// and vector operations. Many of these built-in functions can be used in more than one type
// of shader, but some are intended to provide a direct mapping to hardware and so are available
// only for a specific type of shader.
//
// The built-in functions basically fall into three categories:
//
// • They expose some necessary hardware functionality in a convenient way such as accessing
// a texture map. There is no way in the language for these functions to be emulated by a shader.
//
// • They represent a trivial operation (clamp, mix, etc.) that is very simple for the user
// to write, but they are very common and may have direct hardware support. It is a very hard
// problem for the compiler to map expressions to complex assembler instructions.
//
// • They represent an operation graphics hardware is likely to accelerate at some point. The
// trigonometry functions fall into this category.
//
// Many of the functions are similar to the same named ones in common C libraries, but they support
// vector input as well as the more traditional scalar input.
//
// Applications should be encouraged to use the built-in functions rather than do the equivalent
// computations in their own shader code since the built-in functions are assumed to be optimal
// (e.g., perhaps supported directly in hardware).
//
// User code can replace built-in functions with their own if they choose, by simply re-declaring
// and defining the same name and argument list.
//
//
// Texture Lookup Functions
//
// Texture lookup functions are available to both vertex and fragment shaders. However, level
// of detail is not computed by fixed functionality for vertex shaders, so there are some
// differences in operation between vertex and fragment texture lookups. The functions in the table
// below provide access to textures through samplers, as set up through the OpenGL API. Texture
// properties such as size, pixel format, number of dimensions, filtering method, number of mip-map
// levels, depth comparison, and so on are also defined by OpenGL API calls. Such properties are
// taken into account as the texture is accessed via the built-in functions defined below.
//
// If a non-shadow texture call is made to a sampler whose texture has depth comparisons enabled,
// then results are undefined. If a shadow texture call is made to a sampler whose texture does not
// have depth comparisions enabled, the results are also undefined.
//
// In all functions below, the bias parameter is optional for fragment shaders. The bias parameter
// is not accepted in a vertex shader. For a fragment shader, if bias is present, it is added to
// the calculated level of detail prior to performing the texture access operation. If the bias
// parameter is not provided, then the implementation automatically selects level of detail:
// For a texture that is not mip-mapped, the texture is used directly. If it is mip-mapped and
// running in a fragment shader, the LOD computed by the implementation is used to do the texture
// lookup. If it is mip-mapped and running on the vertex shader, then the base texture is used.
//
// The built-ins suffixed with “Lod” are allowed only in a vertex shader. For the “Lod” functions,
// lod is directly used as the level of detail.
//
//
// Use the texture coordinate coord to do a texture lookup in the 1D texture currently bound
// to sampler. For the projective (“Proj”) versions, the texture coordinate coord.s is divided by
// the last component of coord.
//
// XXX
vec4 texture1D (sampler1D sampler, float coord, float bias) {
return vec4 (0.0);
}
vec4 texture1DProj (sampler1D sampler, vec2 coord, float bias) {
return texture1D (sampler, coord.s / coord.t, bias);
}
vec4 texture1DProj (sampler1D sampler, vec4 coord, float bias) {
return texture1D (sampler, coord.s / coord.q, bias);
}
//
// Use the texture coordinate coord to do a texture lookup in the 2D texture currently bound
// to sampler. For the projective (“Proj”) versions, the texture coordinate (coord.s, coord.t) is
// divided by the last component of coord. The third component of coord is ignored for the vec4
// coord variant.
//
// XXX
vec4 texture2D (sampler2D sampler, vec2 coord, float bias) {
return vec4 (0.0);
}
vec4 texture2DProj (sampler2D sampler, vec3 coord, float bias) {
return texture2D (sampler, vec2 (coord.s / coord.p, coord.t / coord.p), bias);
}
vec4 texture2DProj (sampler2D sampler, vec4 coord, float bias) {
return texture2D (sampler, vec2 (coord.s / coord.q, coord.s / coord.q), bias);
}
//
// Use the texture coordinate coord to do a texture lookup in the 3D texture currently bound
// to sampler. For the projective (“Proj”) versions, the texture coordinate is divided by coord.q.
//
// XXX
vec4 texture3D (sampler3D sampler, vec3 coord, float bias) {
return vec4 (0.0);
}
vec4 texture3DProj (sampler3D sampler, vec4 coord, float bias) {
return texture3DProj (sampler, vec3 (coord.s / coord.q, coord.t / coord.q, coord.p / coord.q),
bias);
}
//
// Use the texture coordinate coord to do a texture lookup in the cube map texture currently bound
// to sampler. The direction of coord is used to select which face to do a 2-dimensional texture
// lookup in, as described in section 3.8.6 in version 1.4 of the OpenGL specification.
//
// XXX
vec4 textureCube (samplerCube sampler, vec3 coord, float bias) {
return vec4 (0.0);
}
//
// Use texture coordinate coord to do a depth comparison lookup on the depth texture bound
// to sampler, as described in section 3.8.14 of version 1.4 of the OpenGL specification. The 3rd
// component of coord (coord.p) is used as the R value. The texture bound to sampler must be a
// depth texture, or results are undefined. For the projective (“Proj”) version of each built-in,
// the texture coordinate is divide by coord.q, giving a depth value R of coord.p/coord.q. The
// second component of coord is ignored for the “1D” variants.
//
// XXX
vec4 shadow1D (sampler1DShadow sampler, vec3 coord, float bias) {
return vec4 (0.0);
}
// XXX
vec4 shadow2D (sampler2DShadow sampler, vec3 coord, float bias) {
return vec4 (0.0);
}
vec4 shadow1DProj (sampler1DShadow sampler, vec4 coord, float bias) {
return shadow1D (sampler, vec3 (coord.s / coord.q, 0.0, coord.p / coord.q), bias);
}
vec4 shadow2DProj (sampler2DShadow sampler, vec4 coord, float bias) {
return shadow2D (sampler, vec3 (coord.s / coord.q, coord.t / coord.q, coord.p / coord.q), bias);
}
//
// Fragment processing functions are only available in shaders intended for use on the fragment
// processor. Derivatives may be computationally expensive and/or numerically unstable. Therefore,
// an OpenGL implementation may approximate the true derivatives by using a fast but not entirely
// accurate derivative computation.
//
// The expected behavior of a derivative is specified using forward/backward differencing.
//
// Forward differencing:
//
// F(x+dx) - F(x) ~ dFdx(x) * dx 1a
// dFdx(x) ~ (F(x+dx) - F(x)) / dx 1b
//
// Backward differencing:
//
// F(x-dx) - F(x) ~ -dFdx(x) * dx 2a
// dFdx(x) ~ (F(x) - F(x-dx)) / dx 2b
//
// With single-sample rasterization, dx <= 1.0 in equations 1b and 2b. For multi-sample
// rasterization, dx < 2.0 in equations 1b and 2b.
//
// dFdy is approximated similarly, with y replacing x.
//
// A GL implementation may use the above or other methods to perform the calculation, subject
// to the following conditions:
//
// 1) The method may use piecewise linear approximations. Such linear approximations imply that
// higher order derivatives, dFdx(dFdx(x)) and above, are undefined.
//
// 2) The method may assume that the function evaluated is continuous. Therefore derivatives within
// the body of a non-uniform conditional are undefined.
//
// 3) The method may differ per fragment, subject to the constraint that the method may vary by
// window coordinates, not screen coordinates. The invariance requirement described in section
// 3.1 of the OpenGL 1.4 specification is relaxed for derivative calculations, because
// the method may be a function of fragment location.
//
// Other properties that are desirable, but not required, are:
//
// 4) Functions should be evaluated within the interior of a primitive (interpolated, not
// extrapolated).
//
// 5) Functions for dFdx should be evaluated while holding y constant. Functions for dFdy should
// be evaluated while holding x constant. However, mixed higher order derivatives, like
// dFdx(dFdy(y)) and dFdy(dFdx(x)) are undefined.
//
// In some implementations, varying degrees of derivative accuracy may be obtained by providing
// GL hints (section 5.6 of the OpenGL 1.4 specification), allowing a user to make an image
// quality versus speed tradeoff.
//
//
// Returns the derivative in x using local differencing for the input argument p.
//
// XXX
float dFdx (float p) {
return 0.0;
}
// XXX
vec2 dFdx (vec2 p) {
return vec2 (0.0);
}
// XXX
vec3 dFdx (vec3 p) {
return vec3 (0.0);
}
// XXX
vec4 dFdx (vec4 p) {
return vec4 (0.0);
}
//
// Returns the derivative in y using local differencing for the input argument p.
//
// These two functions are commonly used to estimate the filter width used to anti-alias procedural
// textures.We are assuming that the expression is being evaluated in parallel on a SIMD array so
// that at any given point in time the value of the function is known at the grid points
// represented by the SIMD array. Local differencing between SIMD array elements can therefore
// be used to derive dFdx, dFdy, etc.
//
// XXX
float dFdy (float p) {
return 0.0;
}
// XXX
vec2 dFdy (vec2 p) {
return vec2 (0.0);
}
// XXX
vec3 dFdy (vec3 p) {
return vec3 (0.0);
}
// XXX
vec4 dFdy (vec4 p) {
return vec4 (0.0);
}
//
// Returns the sum of the absolute derivative in x and y using local differencing for the input
// argument p, i.e.:
//
// return = abs (dFdx (p)) + abs (dFdy (p));
//
float fwidth (float p) {
return abs (dFdx (p)) + abs (dFdy (p));
}
vec2 fwidth (vec2 p) {
return abs (dFdx (p)) + abs (dFdy (p));
}
vec3 fwidth (vec3 p) {
return abs (dFdx (p)) + abs (dFdy (p));
}
vec4 fwidth (vec4 p) {
return abs (dFdx (p)) + abs (dFdy (p));
}
|