Features of the OpenGL Shading Language1.1 Example Shader Pair1.2 Data Types1.2.1 Scalars1.2.2 Vectors1.2.3 Matrices1.2.4 Samplers1.2.5 Structures1.2.6 Arrays1. Before the array is referenced, it is declared again with a size, with the same type as the fi...2. All indices that statically reference the array are compile-time constants. In this case, the ...1.2.7 Void1.2.8 Declarations and Scope1.2.9 Type Matching and Promotion1.3 Initializers and Constructors1.4 Type Conversions1.5 Qualifiers and Interface to a Shader1.5.1 Attribute Qualifiers1.5.2 Uniform Qualifiers1.5.3 Varying Qualifiers1.5.4 Constant Qualifiers1.5.5 Absent Qualifier1.6 Flow Control1.6.1 Functions1.6.2 Calling Conventions1.6.3 Built-in Functions1.7 OperationsTable 1.1 Operators, in order of precedenceOperatorDescription1.7.1 Indexing1.7.2 Swizzling1.7.3 Component-wise Operation1.8 PreprocessorTable 1.2 Permitted values for the behavior expression in the #extension directiveValue of behaviorEffect1.9 Preprocessor ExpressionsTable 1.3 Preprocessor operatorsOperatorDescription1.10 Error Handling1.11 Summary0.Features of the OpenGL Shading Languageby John Kessenich3Dlabs Inc. Ltd.03-May-2005Copyright © 2003-2005 John KessenichIn this white paper, we present the language features of the OpenGL Shading Language. We start with a simple example of a working pair of vertex and fragment shaders to show their basic structure and interfaces. Each aspect of the language will then be discussed in turn.The OpenGL Shading Language syntax comes from the C family of programming languages. Tokens, identifiers, semicolons, nesting with curly braces, control-flow, and many keywords look like C. Both comment styles // ... and /* ... */ are accepted. Much is also different though, and all important differences from C will be discussed.Each shader example is presented as it might appear in a file or onscreen. However, as explained in the OpenGL 2.0 specification, the OpenGL API passes shaders as strings, not files, as OpenGL does not consider shaders file based.1.1 Example Shader PairA program will typically contain two shaders: one vertex shader and one fragment shader. More than one shader of each type can be present, but there must be exactly one function main between all the fragment shaders and exactly one function main between all the vertex shaders. Frequently, it’s easiest to just have one shader of each type.The following is a simple pair of vertex and fragment shaders that can smoothly express a surface’s temperature with color. The range of temperatures and their colors are parameterized. First, we’ll show the vertex shader. It will be executed once for each vertex.// uniform qualified variables are changed at most once per primitiveuniform float CoolestTemp;uniform float TempRange;// attribute qualified variables are typically changed per vertexattribute float VertexTemp;// varying qualified variables communicate from the vertex shader to// the fragment shadervarying float Temperature;void main(){ // compute a temperature to be interpolated per fragment, // in the range [0.0, 1.0] Temperature = (VertexTemp - CoolestTemp) / TempRange; /* The vertex position written in the application using glVertex() can be read from the built-in variable1-2 gl_Vertex. Use this value and the current model view transformation matrix to tell the rasterizer where this vertex is. */ gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;}That’s it for the vertex shader. Primitive assembly will follow the preceding vertex processing, providing the rasterizer with enough information to create fragments. The rasterizer interpolates the Temperature values written per vertex to create values per fragment. Each fragment is then delivered to a single execution of the fragment shader, as follows:// uniform qualified variables are changed at most once per primitive// by the application, and vec3 declares a vector of three// floating-point numbersuniform vec3 CoolestColor;uniform vec3 HottestColor; // Temperature contains the now interpolated per-fragment// value of temperature set by the vertex shadervarying float Temperature;void main(){ // get a color between coolest and hottest colors, using // the mix() built-in function vec3 color = mix(CoolestColor, HottestColor, Temperature); // make a vector of 4 floating-point numbers by appending an // alpha of 1.0, and set this fragment’s color gl_FragColor = vec4(color, 1.0);}Both shaders receive user-defined state from the application through the declared uniform qualified variables. The vertex shader gets information associated with each vertex through the attribute qualified variable. Information is passed from the vertex shader to the fragment shader through varying qualified variables, whose declarations must match between the vertex and fragment shaders. The fixed functionality located between the vertex and fragment processors will interpolate the per-vertex values written to this varying variable. When the fragment shader reads this same varying variable, it reads the value interpolated for the location of the fragment being processed.Shaders interact with the fixed functionality OpenGL pipeline by writing built-in variables. OpenGL prefixes built-in variables with “gl_”. In the preceding examples, writing to gl_Position tells the OpenGL pipeline where the trans-formed vertices are located, and writing to gl_FragColor tells the OpenGL pipeline what color to attach to a fragment.Execution of the preceding shaders occurs multiple times to process a single primitive, once per vertex for the vertex shader and once per fragment for the fragment shader. Many such executions of the same shader can happen in parallel. In general, there is no direct tie or ordering between shader executions. Information can be communicated neither from vertex to vertex, nor from fragment to fragment.1.2 Data TypesWe saw vectors of floating-point numbers in the example in the previous section. Many other built-in data types are available to ease the expression of graphical operations. Booleans, integers, matrices, vectors of other types, structures, and arrays are all included. Each is discussed in the following sections. Notably missing are string and character types, as there is little use for them in processing vertex and fragment data.1-31.2.1 ScalarsThe scalar types available arefloat declares a single floating-point numberint
View Full Document