%
% TeX file for quick technical notes; mostly conforms to dissertation
% formatting requirements
%
% Relies on mysettings.tex
%
% Uses LaTeX2e, and various packages
%
%
%
\documentclass[10pt]{article}

%
% Customizations of article class for quick notes
% Bill Mark
%
% Use postscript fonts (std=times, sans-serif=helvetica, \tt=courier)
% Note that math is still in computer modern (giving a warning), and this
% doesn't quite match the times font.
\usepackage{times}
% Extra math fonts
%\usepackage{amsfonts}
% Extra math capabilities
\usepackage{amsmath}
% Allow inclusion of encapsulated postscript figures
\usepackage{epsfig}
% Nicer tables (even when using tabular environment)
\usepackage{array}
% Better verbatim environments, plus 'boxedverbatim'
\usepackage{moreverb}
% Define ifthenelse command
\usepackage{ifthen}
% Multi-page tables ('supertabular' environment)
\usepackage{supertabular}

% Define ``et al.'' symbol
\newcommand{\etal}{{\it et al.} }

%
% Set Margins -- see ``The LaTeX Companion'', pg. 84
%
%  Note: Right justified text is optional
%
%  Full-width figures imported from elsewhere should be 6'' max width,
%  8.5'' max height.
%
\setlength{\topmargin}{-0.5in}     % Top=1.0in (1.0in+\topmar+\headht+\headsep)
\setlength{\headheight}{0.25in}
\setlength{\headsep}{0.25in}
\setlength{\textheight}{8.9in}      % Bottom= 1.1in (11.0-\topmargin-\textht.)
% Inside Margin = 1.35in, Outside Margin = 1.0 in, Text Width = 6.15
\setlength{\evensidemargin}{0.0in} % Outside = 1.0in (1.0in+\evensidemargin)
\setlength{\oddsidemargin}{0.35in} % Inside  = 1.35in (1.0in+\oddsidemargin)
\setlength{\textwidth}{6.15in}     % 8.5 = 6.15 + 1.0 + 1.35
% Bottom of footer (containing pg number) is 0.5in from bottom of page
\setlength{\footskip}{0.5in}       % Pg->Btm = Bottom-\footskip
%
% Indentation for first-line of paragraphs
%
\parindent=0.4in

%
% Define font-size command for chapter headings, ``TABLE OF CONTENTS'', etc.
% This is my own definition -- I use it in several places
%
\newcommand{\mychheadfont}{\Large}
%
% Define ``myextraspacing'' command, which controls
% the ``1.5'' or ``2.0'' spaced portions of the document.
% For 10pt text, a value of 1.25 is 1.5spacing, and 1.67 is 2x spacing;
% see The LaTeX companion, pg. 53 for other font sizes and for an explanation.
% I use a compromise value of 1.5, which is inbetween 1.5x and 2x spacing
\newcommand{\myextraspacing}{%
\renewcommand{\baselinestretch}{1.5}\small\normalsize}% Set extra spacing
% Return to single spacing
\newcommand{\mysinglespacing}{%
\renewcommand{\baselinestretch}{1.0}\small\normalsize}% Set single spacing

%
% Redefine section commands, to use different size text
% Originals are in report.cls
%
\makeatletter
\renewcommand{\section}{\@startsection{section}{1}{\z@}%
                                   {-3.5ex \@plus -1ex \@minus -.2ex}%
                                   {2.3ex \@plus.2ex}%
                                   {\reset@font\Large\bfseries}}% no chg
\renewcommand{\subsection}{\@startsection{subsection}{2}{\z@}%
                            {-3.25ex\@plus -1ex \@minus -.2ex}%
                            {1.5ex \@plus .2ex}%
                            {\reset@font\large\it\bfseries}}% Italic
\renewcommand{\subsubsection}{\@startsection{subsubsection}{3}{\z@}%
                                     {-3.25ex\@plus -1ex \@minus -.2ex}%
                                     {1.5ex \@plus .2ex}%
                                     {\reset@font\normalsize\bfseries}}% no chg
%
% Redefine figure and table captions; the following are copied from
% report.cls and modified.
%
% "Figure N" in bold
\renewcommand{\figurename}{\bf Figure}
\renewcommand{\thefigure}{\thechapter.\@arabic\c@figure}
\def\fnum@figure{\figurename~\thefigure}
\renewenvironment{figure}
                 {\@float{figure}}
                 {\end@float}
\renewenvironment{figure*}
                 {\@dblfloat{figure}}
                 {\end@dblfloat}
% Text of caption in italic, turn off bold at beginning, single-spaced
\long\def\@makecaption#1#2{%
  \vskip\abovecaptionskip\mysinglespacing
  \sbox\@tempboxa{#1: \rm\it#2\rm}%
  \ifdim \wd\@tempboxa >\hsize
    #1: \rm\it#2\rm\par
  \else
    \global \@minipagefalse
    \hbox to\hsize{\hfil\box\@tempboxa\hfil}%
  \fi
  \vskip\belowcaptionskip\myextraspacing}

% "Table N" in bold
\renewcommand{\tablename}{\bf Table}
\renewcommand{\thetable}{\thechapter.\@arabic\c@table}
\def\fnum@table{\tablename~\thetable}
\renewenvironment{table}
               {\@float{table}}
               {\end@float}
\renewenvironment{table*}
               {\@dblfloat{table}}
               {\end@dblfloat}

%
% Change spacing between figures/tables & text, etc.
%
% Between text and float at bottom or top of page
\setlength{\textfloatsep}{20pt plus 2pt minus 4pt}     % default 20pt +2-4
% Between text and float (top and bottom) for float in middle of page
\setlength{\intextsep}{20pt plus 2pt minus 4pt}
% Inter-float sep for multiple floats at bottom or top
\setlength{\floatsep}{20pt plus 2pt minus 4pt}
% Skip between figure/table and caption
\setlength{\abovecaptionskip}{0 pt plus 2pt minus 0pt}

\makeatother

%
% Define a command that, if the 'twoside' option was specified, will
% do a /cleardoublepage (insures that next page is a right-hand one)
%
\makeatletter
\def\cleardoubleiftwoside{\if@twoside\cleardoublepage\else\clearpage\fi}
\makeatother

%
% Default hyphenation settings produce too many hyphens.  Increase them.
% See TeXbook, pg. 97-98
%
\hyphenpenalty=8000    % Default is 50
\exhyphenpenalty=8000  % Default is 50
\doublehyphendemerits=10000 % Completely disallow
\finalhyphendemerits=10000  % Completely disallow
%
% Also allow greater stretching of a line
%
\tolerance=8000 % Default is much smaller (200?)
%
% Increase widow and club penalties
%
\widowpenalty=10000         % Default is 150
\displaywidowpenalty=10000  % Default is 50
\clubpenalty=10000          % Default is 150

% format a command
\def\glcommand#1{\medskip\noindent{\tt #1}\smallskip\nobreak}

%*************************
% How to do a figure
% NOTE: Full-width figures imported from elsewhere should be 6'' max width.
%*************************
%\begin{figure}[htb] \begin{center} \leavevmode
%  \epsfig{file=FIGURE.EPS}
%  \end{center}
%  \caption{The caption}
%  \label{fig:name}
%\end{figure}
%
%Then \ref{fig:name}


%******************
% Page head
%******************
%\makeatletter
%\renewcommand{\@oddhead}{\hfil Shading Language Immediate Mode --- %
%\number\month/\number\day/\number\year \hfil}%
%\renewcommand{\@evenhead}{\@oddhead}
%\makeatother

%**********************
% Suppress Page Numbers
%**********************
\makeatletter
\gdef\thepage{}
\makeatother

%
% *********************
% **  Title & Author **
% *********************
%
\title{Shading System Immediate-Mode API v2.2}
\author{William R. Mark and C. Philipp Schloter}

%
\begin{document}
% Set style for citations
%\bibliographystyle{apalike} % This does Blah and Blah2, YYYY
%\bibliographystyle{alpha} % This does BlaYY
\bibliographystyle{/u/billmark/misc/latex/alpha_full} % This does lastnameYY
%********************************
%* Control of Figure Printing
%********************************
% Draft vs. Normal mode for large figures
%\newcommand{\mygopsdraft}{\psdraft}
\newcommand{\mygopsdraft}{\psfull}

% Title
\maketitle

\myextraspacing % Set extra spacing

%*****************
%* Introduction
%*****************
\section{Introduction}

This document describes modifications to the OpenGL API to support the
immediate-mode use of the Stanford real-time shading language.  We
collectively refer to these extensions as the shading-language
immediate-mode API.  These extensions are implemented as a layer on
top of regular OpenGL.

The immediate-mode API supports the following major operations:
\begin{enumerate}
\item Loading the source code for a light shader or surface shader from a file.
\item Associating one or more light shader(s) with a surface shader to
      create a combined surface/light shader.
\item Compiling a combined surface/light shader for the current
      graphics hardware.
\item Selecting a compiled surface/light shader to use as the current
      shader for rendering.
\item Setting values of shader parameters.
\end{enumerate}

When a shader is active, many OpenGL commands are no longer allowed,
because their functionality is provided through the shading language.
The disallowed commands fall into four major categories:
\begin{enumerate}
\item Fragment-processing commands (e.g. fog, texturing modes)
\item Texture-coordinate generation and transformation commands
\item Lighting commands.
\item Material-property commands.
\end{enumerate}

When using our ``lburg'' multi-pass fragment backend, commands that
configure framebuffer blending modes are also forbidden (instead, use
the {\tt Cprev} builtin variable within a shader).  However, these
commands are allowed with our ``nv'' fragment backend.

Using a forbidden OpenGL command while a programmable-shader is active
will result in undefined behavior.

%****************************
%* Initialization
%****************************
\pagebreak
\section{Initialization}

\glcommand{sglInit()}

The application must initialize the programmable shading system by
calling {\tt sglInit()} once, before calling any other {\tt sgl*}
routines.

%*****************************
%* Loading shader source code
%*****************************
\section{Loading shader source code}

\glcommand{int sglShaderFile(GLuint shaderSourceID, char *shaderName, char *filename)}

Loads the source code for the shader named {\tt shaderName} from file
{\tt filename}, and assigns it the identifier {\tt shaderCodeID}.  Any
other shaders that are specified in the file are ignored.  The loaded
shader source code becomes the active shader source code.  The
specified shader may be either a light shader or a surface shader.
{\tt shaderCodeID} must be unused when this routine is called.  The
return code is 0 if there were no errors, 1 if there was an error.

%*****************************
%* Compiling shaders
%*****************************
\section{Compiling and activating shaders}

After the source code for a shader is loaded, but before it is used,
the shader must be compiled.  Our system treats shader source code and
compiled shaders as largely separate entities.

\glcommand{sglCompileShader(GLuint shaderID)}

Compiles the current shader source code.  The compiled shader is
assigned the user-specified identifier {\tt shaderID}.  If the shader
is a surface shader, it incorporates any currently associated light
shaders (discussed in the next section).

The newly created shader becomes the 'active' shader, as if
sglBindShader() had been called.  If the shader is a light shader, it
is only active in the sense that subsequent {\tt sglParameterHandle()}
calls will apply to it.  A light shader can only be activated for
rendering purposes by associating it with a surface shader using {\tt
sglUseLight()}.

The current shader source code remains unchanged by this call.

Note that {\tt shaderID} may not be -1, because this value is reserved
for {\tt SGL\_STD\_OPENGL}, the standard OpenGL lighting/shading model.

\glcommand{sglBindShader(GLuint shaderID)}

Changes the currently active shader to that specified by {\tt shaderID}.
Note that it is illegal to render geometry when a light shader is
bound.

Specifying {\tt SGL\_STD\_OPENGL} reverts to the standard OpenGL
lighting/shading model.

%***************************
%* Associating lights with a surface
%***************************
\section{Associating lights with a surface}

For efficiency reasons, the shading system must know which light shaders
will be used with a surface shader before the surface shader is compiled.

\glcommand{sglUseLight(GLuint lightShaderID)}

This command binds a ``compiled'' light shader to the current
surface-shader source code.  {\tt lightShaderID} indicates the light
that is to be associated with the surface.

More than one light can be associated with a surface, by calling
{\tt sglUseLight()} multiple times.

However, the same (compiled) light shader may not be used more than
once with a single surface.  If two identical lights are required,
compile the light shader twice.  Our system imposes this requirement
because the {\it lightShaderID} is used to specify how light
parameters are modified.  ``Identical'' lights will usually have
different parameter values (e.g. position).

%****************************
%* Setting parameter values
%****************************
\subsection{Setting parameter values}

For performance reasons, shader parameters are identified at
rendering-time with numeric identifiers rather than names.  For each
compiled shader, the programmer can choose the bindings from names to
numeric identifiers, within some constraints.  We refer to the numeric
parameter identifiers as {\it parameter handles}.  Each compiled
surface or light shader has its own parameter-handle space.

There is an important advantage to allowing the programmer to choose
values of parameter handles.  It facilitates the use of a single
geometry rendering routine (e.g. renderSphere) with different surface
shaders, as long as the programmer chooses a consistent mapping of
parameter handles to actual parameters for all of the relevant
shaders.

\glcommand{sglParameterHandle(char *paramName, GLuint paramHandle)}

Assigns the parameter handle {\tt paramHandle} to the current shader's
parameter {\tt paramName}.  The value of paramHandle must be between 0
and {\tt SGL\_MAX\_PARAMHANDLE}.  The value of {\tt
SGL\_MAX\_PARAMHANDLE} is guaranteed to be no less than 15.

\glcommand{sglParameter*(GLuint paramHandle, TYPE v, \ldots)}\\
\glcommand{sglParameter*v(GLuint paramHandle, TYPE *v)}

Assigns a value to the shader parameter(s) specified by {\tt
  paramHandle}.  For a per-vertex parameter, this routine may be
called at any time.  For a per-primitive parameter, this routine may
only be called outside of a begin/end pair.

Because our shading language does not explicitly identify shader
parameters as ``colors'' or ``texture coordinates'', the shading
system can not automatically assign default values in the manner that
OpenGL does.  For example, in OpenGL a {\tt glColor3f} command
automatically sets the fourth value (alpha) to the default value of
1.0.  When using our system, the user must always specify all four
components of the color value.  Likewise, the user must always specify
all four components of a texture value.  For a 2D texture, the third
and fourth values should usually be set to 0.0 and 1.0 respectively.

The {\tt sglParameter*} routine is available in {\tt sglParameter1*},
{\tt sglParameter4*}, and {\tt sglParameter16*} variants.  The {\tt
sglParameter16*} variants are used to specify matrix parameters,
using OpenGL's array format.

If the shading language specifies a parameter's type as either {\tt
clampf} or {\tt clampfv}, type conversions are performed in the same
manner as they are for the OpenGL {\tt glColor*} routines (see OpenGL
Red Book, 3rd edition, Table 4-1).\footnote{For implementation
simplicity, our system deviates from the behavior in Table 4-1 in a
minor way.  Our system treats negative and positive values
symmetrically.  For example, a signed-byte value of -127 maps to -1.0,
whereas in OpenGL the value of -128 maps to -1.0}. In summary,
integer-to-float conversions are performed such that the maximum
integer value (e.g. 255 for an unsigned byte) maps to 1.0.  This
behavior allows colors and normals to be stored in unsigned bytes in a
natural manner.

Our shading language uses textures, but the contents of the textures
are not defined using the language.  Textures are defined by the
application program, then passed to the shading-language routine as a
'texref' parameter.  Our system relies on OpenGL's texture object
facility ({\tt glBindTexture()}).  The {\tt sglParameter1i} or {\tt
sglParameter1iv} routines are used to specify 'texref' parameters.
The value of the integer parameter is the {\it textureName} created
using {\tt glBindTexture()}.

\glcommand{sglLightParameter*(GLuint lightShaderID, GLuint paramHandle, TYPE v, \ldots)}\\
\glcommand{sglLightParameter*v(GLuint lightShaderID, GLuint paramHandle, TYPE *v)}

Assigns a value to the light parameter specified by {\tt paramHandle}.
The ``compiled'' light shader is specified by {\tt lightShaderID}.
For a per-vertex parameter, this routine may be called at any time.
For a per-primitive parameter, this routine may only be called outside
of a begin/end pair.

\subsection{Light Pose}

The pose of a light (position, direction, and orientation) is set
using a routine defined for that purpose.

\glcommand{sglLightPosefv(GLuint lightShaderID, GLuint pname, GLfloat *v)}

{\tt pname} can be {\tt SGL\_POSITION}, {\tt SGL\_DIRECTION}, or {\tt
SGL\_UPAXIS}.  The light direction defines the $-Z$ axis in light space,
and the up axis defines the $Y$ axis in light space.

The vector {\tt v} should always be a four-element vector, and is
considered to be in modelview space (i.e. transformed by the modelview
matrix or its inverse transpose, as appropriate).  For {\tt
SGL\_POSITION}, the fourth element of the vector should usually be set
to 1.0.  For {\tt SGL\_DIRECTION} and {\tt SGL\_UPAXIS}, the fourth
element should usually be set to 0.0.

\subsection{Ambient Light}

\glcommand{sglAmbient*(\ldots)}

Specify the global ambient color.  This color is accessible in surface
shaders using the pre-defined {\tt Ca} variable.  If a surface shader
does not use the {\tt Ca} variable, the ambient color will be ignored.
This routine can not be called inside a Begin/End pair.

%*************************************
%* Replacements for standard OpenGL routines 
%*************************************
\section{Replacements for Standard OpenGL routines}

\subsection{Begin/End and Flush/Finish}

Use {\tt sglBegin()}, {\tt sglEnd()}, {\tt sglFlush()}, and {\tt
sglFinish()} instead of the corresponding standard OpenGL routines.
Using the standard OpenGL routines while a programmable shader is
active will result in undefined behavior.

\subsection{Vertices, Normals, Tangents, Binormals}

\glcommand{sglVertex*(TYPE v, \ldots)}\\
\glcommand{sglVertex*v(TYPE v, \ldots)}\\
\glcommand{sglNormal3*(TYPE v, \ldots)}\\
\glcommand{sglNormal3*v(TYPE v, \ldots)}\\
\glcommand{sglTangent3*(TYPE v, \ldots)}\\
\glcommand{sglTangent3*v(TYPE v, \ldots)}\\
\glcommand{sglBinormal3*(TYPE v, \ldots)}\\
\glcommand{sglBinormal3*v(TYPE v, \ldots)}\\

Vertices and local coordinate-frame vectors are passed using our
versions of the classical OpenGL routines.  The results of calling one
of the standard OpenGL routines while a programmable shader is active
are undefined.

\pagebreak

\subsection{Vertex arrays}
To attain higher frame rates when using large models, the shading
system provides {\tt sglParameterPointer}, {\tt sglEnableClientState}, {\tt sglGetClientState},
{\tt sglDisableClientState} and {\tt sglDrawArrays}. These routines differ
from the OpenGL routines in that they support not only arrays of vertices, normals, binormals or tangents,
but also of any other shader parameter. To setup vertex arrays, you have to follow a basic
three step procedure, consisting of calls to:
\begin{enumerate}
\item {\tt sglParameterPointer}
\item {\tt sglEnableClientState}
\item {\tt sglDrawArrays}.\\
\end{enumerate}

First, the pointers to the parameter arrays have to be specified by
{\tt sglParameterPointer(int handle, GLsizei size, GLenum type,  GLsizei stride, float *pointer)}.
Valid handles are {\tt SGL\_VERTEX, SGL\_NOMRAL, SGL\_BINORMAL, SGL\_TANGENT}  or any parameter
handle obtained from {\tt sglParameterHandle}.  The parameters {\tt size}, {\tt type}, {\tt stride} and {\tt pointer} follow standard OpenGL vertex-array conventions.
Please note that in the current version of the immediate-mode API:
\begin{itemize}
\item GL\_FLOAT is the only supported type.
\item Stride should always be set to 4 for {\tt SGL\_VERTEX}, and to 3 for {\tt SGL\_NORMAL}, {\tt SGL\_BINORMAL}
or {\tt SGL\_TANGENT} arrays.\\
\end{itemize}

After specifying all parameter arrays, they must be activated for rendering by calling
{\tt sglEnableClientState(int handle)}. Similar, an activated parameter array can be disabled
again by calling {\tt sglDisableClientState(int handle)}.\\

To render the actual vertex array using all activated parameter arrays, call\\
{\tt sglDrawArrays(GLenum mode, GLint first, GLsizei count)} which again follows standard OpenGL conventions. Please note that rendering will only
occur if an SGL\_VERTEX array was both specified and activated.
All other parameter arrays are optional. {\tt SGL\_NOMRAL, SGL\_BINORMAL} and {\tt SGL\_TANGENT} are set to constant
default values if not provided.

%**************************************************
%* Advanced features 
%**************************************************
\section{Advanced features}

\subsection{Manual backend configuration}
To offer manual control over which backends the shading system should use, the immediate-mode interface provides 
{\tt sglSetBackEndType(char* perprimitivegroup, char* vertex, char* fragment)}. This routine presents a wraper
for the internal, low-level functions {\tt set\_bcodegen,} {\tt set\_vcodegen} and {\tt set\_fcodegen}.

Currently, there are two primitive-group backends (``cc'' and ``x86''), three
vertex backends (``cc'', ``x86'', and ``nv20''), and two fragment backends
(``lb'' and ``nv'').  ``lb'' is a standard-OpenGL backend; ``nv'' is a
register-combiner backend.

\subsection{Shader parameter list retrieval}
The following two routines allow a program to retrieve the lists
of parameters required by a surface shader. To retrieve the number of
parameters for the current surface shader:\\
{\tt sglGetParameterCount(int *count)} where count returns the total number of
parameters for the shader.\\

To retrieve the name and number of values for a specific parameter:\\
{\tt sglGetParameterInfo(int p, char **name, int *vcnt)}
where p defines the parameter of the current shader, ranging from 0 to (1-count),
name returns the name of the parameter and vcnt returns the number of values
for this parameter. E.g. for a float4 parameter, vcnt would return 4.\\

To retrieve the lists of parameters required by a light shader,
use the following routines:\\
{\tt sglGetLightParameterCount(int lightid, int *count)}\\
{\tt sglGetLightParameterInfo(int lightid, int p, char **name, int *vcnt)}\\
Both routines take a {\tt lightid} as parameter that specifies the light
for which information should be retrieved.

%*****************
%* Depth testing
%*****************
\section{Depth testing}

Ideally, depth testing works exactly as it does in standard OpenGL.
However, in some implementations, incorrect shading may occur if two
(potentially visible) fragments at a pixel have exactly the same
depth.  This problem only occurs if an implementation uses the
framebuffer for inter-pass temporary storage in a multi-pass shader.

\pagebreak
%****************************
%* Error Handling
%****************************
\section{Error Handling}

The shading system has a flexible method for handling errors.  Errors
are divided into two classes, minor and major.  For each class of
error, the application can choose one of four behaviors:

\begin{itemize}
\item {\tt SG\_MSG\_NONE} -- No message is printed, and program execution
      continues.  Errors can only be detected by polling for them using
      {\tt sglGetError}.
\item {\tt SGL\_MSG\_WARN\_ONCE} -- A message is printed for the first error
      that occurs, and program execution continues.  No message is
      printed for subsequent errors.
\item {\tt SGL\_MSG\_WARN} -- A message is printed for every error that
      occurs, and program execution continues.
\item {\tt SGL\_MSG\_ABORT} -- When an error occurs, a messsage is printed
      and program execution is halted.
\end{itemize}

\glcommand{sglDebugLevel(int minor, int major)}

Specify the behavior for minor and major errors.  The default is
{\tt sglDebugLevel(SGL\_MSG\_WARN\_ONCE, SGL\_MSG\_ABORT)}.

\glcommand{GLenum sglGetError(void)}

Poll for an error.  If no error has occurred, {\tt GL\_NO\_ERROR} is
returned.  If an error has occurred, the error code is returned.

\glcommand{const GLubyte* sglErrorString(GLenum errorCode)}

Returns a descriptive string corresponding to an error code.

%*******************************
%* System Tips
%*******************************
\section{System Tips}

In our current implementation, every {\tt sglBegin}/{\tt sglEnd} pair
is expensive.  If possible, group all primitives into one such pair.

Because of restrictions in current graphics hardware, if a translucent
shader is implemented using more than one hardware pass, overlapping
transparent primitives will not render correctly.  You must call {\tt
sglFlush} between each group of potentially overlapping primitives to
avoid this problem.

\end{document}

% Local Variables: 
% mode: latex
% TeX-master: "imode.tex"
% End: 
