Recent from talks
Nothing was collected or created yet.
Cg (programming language)
View on Wikipedia| Cg/HLSL | |
|---|---|
A scene containing several different 2D HLSL shaders. Distortion of the statue is achieved purely physically, while the texture of the rectangular frame beside it is based on color intensity. The square in the background has been transformed and rotated. The partial transparency and reflection of the water in the foreground are added by a shader applied finally to the entire scene. | |
| Family | shading language |
| Developer | nVIDIA, Microsoft |
| Website | developer |
| Dialects | |
| Cg, HLSL, Playstation Shading Language | |
| Influenced by | |
| C, RenderMan Shading Language | |
| Influenced | |
| GLSL | |
Cg (short for C for Graphics), also known as High-Level Shader Language (HLSL), is a high-level shading language developed by Nvidia and Microsoft for programming shaders. Cg/HLSL is based on the C programming language and although they share the same core syntax, some features of C were modified and new data types were added to make Cg/HLSL more suitable for programming graphics processing units.[1][2]
Two main branches of the Cg/HLSL language exist: the Nvidia Cg compiler (cgc) which outputs DirectX or OpenGL and the Microsoft HLSL which outputs DirectX shaders in bytecode format.[3][4] Nvidia's cgc was deprecated in 2012, with no additional development or support available.[5]
HLSL shaders can enable many special effects in both 2D and 3D computer graphics. The Cg/HLSL language originally only included support for vertex shaders and pixel shaders, but other types of shaders were introduced gradually as well:
- DirectX 10 (Shader Model 4) and Cg 2.0 introduced geometry shaders.[6]
- DirectX 11 (Shader Model 5) introduced compute shaders (GPGPU) and tessellation shaders (hull and domain). The latter is present in Cg 3.1.
- DirectX 12 (Shader Model 6.3) introduced ray tracing shaders (ray generation, intersection, bit / closest hit / miss).
Background
[edit]Due to technical advances in graphics hardware, some areas of 3D graphics programming have become quite complex. To simplify the process, new features were added to graphics cards, including the ability to modify their rendering pipelines using vertex and pixel shaders.
In the beginning, vertex and pixel shaders were programmed at a very low level with only the assembly language of the graphics processing unit. Although using the assembly language gave the programmer complete control over code and flexibility, it was fairly hard to use. A portable, higher level language for programming the GPU was needed, so Cg was created to overcome these problems and make shader development easier.
Some of the benefits of using Cg over assembly are:
- High level code is easier to learn, program, read, and maintain than assembly code.
- Cg code is portable to a wide range of hardware and platforms, unlike assembly code, which usually depends on hardware and the platforms it's written for.
- The Cg compiler can optimize code and do lower level tasks automatically, which are hard to do and error prone in assembly.
Language
[edit]Data types
[edit]Cg has six basic data types. Some of them are the same as in C, while others are especially added for GPU programming. These types are:
- float - a 32bit floating point number
- half - a 16bit floating point number
- int - a 32bit integer
- fixed - a 12bit fixed point number
- bool - a Boolean variable
- sampler* - represents a texture object
Cg also features vector and matrix data types that are based on the basic data types, such as float3 and float4x4. Such data types are quite common when dealing with 3D graphics programming. Cg also has struct and array data types, which work in a similar way to their C equivalents.
Operators
[edit]Cg supports a wide range of operators, including the common arithmetic operators from C, the equivalent arithmetic operators for vector and matrix data types, and the common logical operators.
Functions and control structures
[edit]Cg shares the basic control structures with C, like if/else, while, and for. It also has a similar way of defining functions.
Semantics
[edit]Preprocessor
[edit]Cg implements many C preprocessor directives and its macro expansion system. It implements #include.[7]
HLSL features
[edit]- Namespace
- Annotation
Environment
[edit]Compilation targets
[edit]Cg programs are built for different shader profiles that stand for GPUs with different capabilities.[8] These profiles decide, among others, how many instructions can be in each shader, how many registers are available, and what kind of resources a shader can use. Even if a program is correct, it might be too complex to work on a profile.[7]
As the number of profile and shader types cropped up, Microsoft has switched to use the term "Shader Model" to group a set of profiles found in a generation of GPUs.[9] Cg supports some of the newer profiles up to Shader Model 5.0 as well as translation to glsl or hlsl.[8]
| Pixel shader version | 1.0 to 1.3[10] | 1.4[10] | 2.0[10][11] | 2.0a[10][11][12] | 2.0b[10][11][13] | 3.0[10][14] | 4.0[15] 4.1[16] 5.0[17] |
|---|---|---|---|---|---|---|---|
| Dependent texture limit | 4 | 6 | 8 | Unlimited | 8 | Unlimited | Unlimited |
| Texture instruction limit | 4 | 6*2 | 32 | Unlimited | Unlimited | Unlimited | Unlimited |
| Position register | No | No | No | No | No | Yes | Yes |
| Instruction slots | 8+4 | 8+4 | 32 + 64 | 512 | 512 | ≥ 512 | ≥ 65536 |
| Executed instructions | 8+4 | 6*2+8*2 | 32 + 64 | 512 | 512 | 65536 | Unlimited |
| Texture indirections | 4 | 4 | 4 | Unlimited | 4 | Unlimited | Unlimited |
| Interpolated registers | 2 + 4 | 2 + 6 | 2 + 8 | 2 + 8 | 2 + 8 | 10 | 32 |
| Instruction predication | No | No | No | Yes | No | Yes | No |
| Index input registers | No | No | No | No | No | Yes | Yes |
| Temp registers | 2 | 6 | 12 to 32 | 22 | 32 | 32 | 4096 |
| Constant registers | 8 | 8 | 32 | 32 | 32 | 224 | 16×4096 |
| Arbitrary swizzling | No | No | No | Yes | No | Yes | Yes |
| Gradient instructions | No | No | No | Yes | No | Yes | Yes |
| Loop count register | No | No | No | No | No | Yes | Yes |
| Face register (2-sided lighting) | No | No | No | No | Yes | Yes | Yes |
| Dynamic flow control | No | No | No | No | No | Yes (24) | Yes (64) |
| Bitwise Operators | No | No | No | No | No | No | Yes |
| Native Integers | No | No | No | No | No | No | Yes |
- PS 1.0 — Unreleased 3dfx Rampage, DirectX 8.
- PS 1.1 — GeForce 3, DirectX 8.
- PS 1.2 — 3Dlabs Wildcat VP, DirectX 8.0a.
- PS 1.3 — GeForce 4 Ti, DirectX 8.0a.
- PS 1.4 — Radeon 8500-9250, Matrox Parhelia, DirectX 8.1.
- Shader Model 2.0 — Radeon 9500-9800/X300-X600, DirectX 9.
- Shader Model 2.0a — GeForce FX/PCX-optimized model, DirectX 9.0a.
- Shader Model 2.0b — Radeon X700-X850 shader model, DirectX 9.0b.
- Shader Model 3.0 — Radeon X1000 and GeForce 6, DirectX 9.0c.
- Shader Model 4.0 — Radeon HD 2000 and GeForce 8, DirectX 10.
- Shader Model 4.1 — Radeon HD 3000 and GeForce 200, DirectX 10.1.
- Shader Model 5.0 — Radeon HD 5000 and GeForce 400, DirectX 11.
- Shader Model 5.1 — GCN 1+, Fermi+, DirectX 12 (11_0+) with WDDM 2.0.
- Shader Model 6.0 — GCN 1+, Kepler+, DirectX 12 (11_0+) with WDDM 2.1.
- Shader Model 6.1 — GCN 1+, Kepler+, DirectX 12 (11_0+) with WDDM 2.3.
- Shader Model 6.2 — GCN 1+, Kepler+, DirectX 12 (11_0+) with WDDM 2.4.
- Shader Model 6.3 — GCN 1+, Kepler+, DirectX 12 (11_0+) with WDDM 2.5.
- Shader Model 6.4 — GCN 1+, Kepler+, Skylake+, DirectX 12 (11_0+) with WDDM 2.6.
- Shader Model 6.5 — GCN 1+, Kepler+, Skylake+, DirectX 12 (11_0+) with WDDM 2.7.
"32 + 64" for Executed Instructions means "32 texture instructions and 64 arithmetic instructions."
| Vertex shader version | VS 1.1[18] | VS 2.0[11][18][19] | VS 2.0a[11][18][19] | VS 3.0[14][18] | VS 4.0[15] VS 4.1[20] VS 5.0[17] |
|---|---|---|---|---|---|
| # of instruction slots | 128 | 256 | 256 | ≥ 512 | ≥ 65536 |
| Max # of instructions executed | 128 | 1024 | 65536 | 65536 | Unlimited |
| Instruction predication | No | No | Yes | Yes | Yes |
| Temp registers | 12 | 12 | 16 | 32 | 4096 |
| # constant registers | ≥ 96 | ≥ 256 | 256 | ≥ 256 | 16×4096 |
| Static flow control | No | Yes | Yes | Yes | Yes |
| Dynamic flow control | No | No | Yes | Yes | Yes |
| Dynamic flow control depth | — | — | 24 | 24 | 64 |
| Vertex texture fetch | No | No | No | Yes | Yes |
| # of texture samplers | — | — | — | 4 | 128 |
| Geometry instancing support | No | No | No | Yes | Yes |
| Bitwise operators | No | No | No | No | Yes |
| Native integers | No | No | No | No | Yes |
The standard library
[edit]As in C, Cg/HLSL features a set of functions for common tasks in GPU programming. Some of the functions have equivalents in C, like the mathematical functions abs and sin, while others are specialized in GPU programming tasks, like the texture mapping functions tex1D and tex2D.
The Cg runtime library
[edit]Cg programs are merely vertex and pixel shaders, and they need supporting programs that handle the rest of the rendering process. Cg can be used with two graphics APIs: OpenGL or DirectX. Each has its own set of Cg functions to communicate with the Cg program, like setting the current Cg shader, passing parameters, and such tasks.
In addition to being able to compile Cg source to assembly code, the Cg runtime also has the ability to compile shaders during execution of the supporting program. This allows the runtime to compile the shader using the latest optimizations available for hardware that the program is currently executing on. However, this technique requires that the source code for the shader be available in plain text to the compiler, allowing the user of the program to access the source-code for the shader. Some developers view this as a major drawback of this technique.
To avoid exposing the source code of the shader, and still maintain some of the hardware specific optimizations, the concept of profiles was developed. Shaders can be compiled to suit different graphics hardware platforms (according to profiles). When executing the supporting program, the best/most optimized shader is loaded according to its profile. For instance there might be a profile for a graphics card that supports complex pixel shaders, and another profile for one that supports only minimal pixel shaders. By creating a pixel shader for each of these profiles a supporting program enlarges the number of supported hardware platforms without sacrificing picture quality on powerful systems.'
Compilers and dialects
[edit]The Cg dialect has only ever had one compiler, in the form of Nvidia's Cg toolkit.
Microsoft has released two compilers for HLSL. The original compiler was the closed-source FXC (Effect Compiler), supported until 2015. It was deprecated in favor of the open-source LLVM-based DXC (DirectXShaderCompiler) with support for newer HLSL features.[21] Both compilers generate bytecode: while the older FXC used DXBC, DXC now uses DXIL. DXC can also emit SPIR-V bytecode.[22]
The Khronos Group has also written a LLVM-based HLSL compiler, in the form of a frontend for glslang, their GLSL-to-SPIR_V compiler. Support for SPIR-V means that the shaders can be cross-platform, no longer limiting them to a DirectX stack.[23] This task was previously performed by source-level converters like HLSL2GLSL, but the resulting code is often bloated.[24]
Derived languages
[edit]The PlayStation Shader Language (PSSL) is based on Cg/HLSL.[25]
The ReshadeFX shading language is also based on Cg/HLSL. Shaders written in ReshadeFX are compiled to OpenGL, DX, or Vulkan and injected into games to act as post-processing filters.[26]
Applications and games that use Cg or HLSL
[edit]- 3DVIA Virtools
- Adobe Photoshop
- Maya[27]
- Battlefield 2
- Crystal Space
- Dolphinity Racer
- Earth's Special Forces - A Half-Life Mod
- Enemy Territory: Quake Wars
- Doom 3 BFG Edition
- EON Professional™/Ultra™ of EON Reality
- eyeon Fusion
- Far Cry
- Garshasp: The Monster Slayer
- GLScene
- Gun Metal
- Hitman: Blood Money
- Irrlicht Engine
- League of Legends
- Lightfeather 3D Engine
- LightWave 11.6[28]
- muvee Reveal
- OGRE
- OpenEmu
- Panda3D
- PCSX2
- PlayStation 3
- RetroArch
- R.U.S.E.
- Snes9x
- Unity game engine[29]
- Unreal Engine
See also
[edit]References
[edit]- ^ "Fusion Industries :: Cg and HLSL FAQ ::". 24 August 2012. Archived from the original on 24 August 2012.
- ^ "The Cg Tutorial - Chapter 1. Introduction". developer.download.nvidia.cn.
- ^ "Writing HLSL Shaders in Direct3D 9 (Windows)". msdn.microsoft.com. 24 May 2021.
- ^ "Cg FAQ". NVIDIA DesignWorks. 8 March 2011. Retrieved 25 May 2017.
- ^ "Cg Toolkit | NVIDIA Developer". 8 March 2011.
- ^ "Cg 2.0 Release Notes" (PDF). nvidia.com. January 2008.
- ^ a b Mark J. Kilgard, Cg in Two Pages, 2003.
- ^ a b "Cg Profile Documentation". Nvidia developer.
- ^ "Shader Models vs Shader Profiles - Win32 apps". docs.microsoft.com. 30 June 2021.
- ^ a b c d e f "Pixel Shader Differences". msdn.microsoft.com. 2011-02-08.
- ^ a b c d e Peeper, Craig (2004-03-15). "Microsoft DirectX High Level Shader Language (HLSL)" (PPT). microsoft.com. pp. 5–8, 24–25.
- ^ Shimpi, Anand Lal. "NVIDIA Introduces GeForce FX (NV30)". Archived from the original on June 10, 2013.
- ^ Wilson, Derek. "ATI Radeon X800 Pro and XT Platinum Edition: R420 Arrives". Archived from the original on September 28, 2012.
- ^ a b Shader Model 3.0, Ashu Rege, NVIDIA Developer Technology Group, 2004.
- ^ a b The Direct3D 10 System, David Blythe, Microsoft Corporation, 2006.
- ^ "Registers - ps_4_1 (Windows)". msdn.microsoft.com. 23 August 2019.
- ^ a b "Registers - ps_5_0 (Windows)". msdn.microsoft.com. 23 August 2019.
- ^ a b c d "Vertex Shader Differences". msdn.microsoft.com. 2011-02-08.
- ^ a b Shimpi, Anand Lal. "NVIDIA Introduces GeForce FX (NV30)". Archived from the original on June 10, 2013.
- ^ "Registers - vs_4_1 (Windows)". msdn.microsoft.com. 23 August 2019.
- ^ "Porting from FXC to DXC". GitHub.
- ^ "microsoft/DirectXShaderCompiler: This repo hosts the source for the DirectX Shader Compiler which is based on LLVM/Clang". Microsoft. 21 October 2020.
- ^ "glslang: Khronos-reference front end for GLSL/ESSL, partial front end for HLSL, and a SPIR-V generator". The Khronos Group. 21 October 2020.
- ^ Matt Turner. Video on YouTube.
- ^ Stenson, Richard; Ho, Chris. "PlayStation Shading Language for PS4". GDC Europe 2013.
- ^ "ReShade FX shading language". GitHub. 15 February 2022.
- ^ "Maya Cg Plug-in | NVIDIA".
- ^ "LightWave - 11.6 Features Overview".
- ^ "Unity - Manual: Writing Shaders".
Further reading
[edit]- Randima Fernando, Mark J. Kilgard, The Cg Tutorial: The Definitive Guide to Programmable Real-Time Graphics, Addison-Wesley Professional, ISBN 0-321-19496-9
- Randima Fernando, GPU Gems: Programming Techniques, Tips, and Tricks for Real-Time Graphics, Addison-Wesley Professional, ISBN 0-321-22832-4
- William R. Mark, R. Steven Glanville, Kurt Akeley, Mark J. Kilgard, Cg: A System for Programming Graphics Hardware in a C-like Language, Proceedings of SIGGRAPH 2003, doi:10.1145/1201775.882362
External links
[edit]- cgc-opensrc - Mirror for nvidia's open source compiler, 2002
- Some essential materials (e.g. the design paper) are gathered in these course notes from Siggraph 2005
- Nvidia-hosted materials:
- NeHe Cg vertex shader tutorial
- Documentation for the Cg Shader standard used by emulators
- Aras Pranckevičius, Cross Platform Shaders in 2014.
Cg (programming language)
View on GrokipediaHistory and Development
Origins and Design Goals
Cg, or C for Graphics, was developed by NVIDIA in close collaboration with Microsoft, beginning in 2001, as a high-level shading language to simplify programming for the emerging programmable GPUs in graphics hardware.[5][1] This effort aimed to address the limitations of low-level assembly-like languages that dominated early GPU programming, which required developers to manage intricate hardware details manually.[6] The language was publicly announced by NVIDIA in June 2002, coinciding with the release of DirectX 9, and formally presented at SIGGRAPH 2003. In July 2002, NVIDIA open-sourced the Cg compiler technology at SIGGRAPH 2002 to promote broader adoption.[7][8][9] The primary design goals of Cg centered on enhancing portability across diverse GPU architectures, enabling developers to write shaders that could target multiple hardware generations without extensive rewrites.[6] By adopting a C-like syntax, Cg sought to make GPU programming more accessible to non-experts, particularly graphics artists and application developers familiar with C/C++ workflows, thus reducing the barrier to entry compared to verbose assembly code.[1][6] Integration with established APIs like OpenGL and Direct3D was a core objective, allowing seamless compilation of Cg programs into vendor-specific shader code while maintaining a unified development experience.[8] Cg drew significant influence from Microsoft's High-Level Shading Language (HLSL), developed in tandem as part of the collaboration, to meet the shading needs of both DirectX and OpenGL ecosystems.[1][10] Positioned initially as a vendor-neutral alternative, Cg emphasized hardware-oriented features like support for vector mathematics and graphics primitives, such as transformations and lighting calculations, to facilitate real-time rendering on stream processors.[6][8] The key designers of Cg included William R. Mark, R. Steven Glanville, Kurt Akeley, and Mark J. Kilgard, all from NVIDIA, who focused on creating a general-purpose language that balanced expressiveness with the constraints of parallel graphics hardware.[6][8] Their work prioritized data-dependent control flow in shaders and adaptability to evolving GPU capabilities, laying the foundation for broader adoption in graphics programming.[2]Release Timeline and Key Milestones
The Cg programming language was initially released in December 2002 as part of the NVIDIA Cg Toolkit version 1.0, coinciding with the launch of the GeForce FX series graphics cards, which introduced programmable shading capabilities on consumer GPUs.[11] This toolkit bundled the Cg compiler (cgc) and runtime libraries, enabling developers to write shaders that compiled to early programmable targets such as ARB_vertex_program, ARB_fragment_program, NV_vertex_program, and DirectX 8 profiles like vs_1_1 and ps_1_1.[12] The release emphasized portability across OpenGL and DirectX APIs, supporting Windows and Linux platforms from the outset.[11] Subsequent updates in the early years expanded profile support and optimizations. Version 1.1, released in February 2003, introduced additional DirectX 9 and OpenGL targets, including vs_2_0 and ps_2_0, while version 1.4 in September 2005 added advanced vertex shader 2.0 extended profiles and improved code generation for better performance on NVIDIA hardware.[12][13] By version 1.5 in September 2007, the toolkit supported over 20 profiles and included native binaries for Windows (32-bit and 64-bit), Linux (32-bit and 64-bit), Mac OS X (versions 10.3 and 10.4), and Solaris x86.[14][15] A significant milestone came with version 2.0 in May 2008, which added compatibility for DirectX 10 profiles such as vs_4_0, gs_4_0, and ps_4_0, enabling Cg shaders to leverage geometry shaders and other features introduced in Windows Vista and DirectX 10 hardware.[16] This update also incorporated advanced optimizations, including better instruction selection and register allocation for improved runtime efficiency.[16] Follow-on releases like 2.1 (August 2008) and 2.2 (April 2009) refined these capabilities with bug fixes and enhanced GLSL output.[17] The final major releases occurred around 2010, with version 3.0 debuting in July 2010 to support emerging DirectX 11 features, including tessellation shaders (hs_5_0 and ds_5_0) and uniform buffer objects in OpenGL.[18] Version 3.1 followed in April 2012, adding GLSL 1.10/1.20 translation and fixes for geometry program runtime issues, marking the last significant update before active development ceased.[19] Throughout its lifecycle, the Cg Toolkit was distributed as a free download from the NVIDIA Developer website, providing SDKs for cross-platform development on Windows, Linux, and Mac OS X.[4]Deprecation and Legacy Status
In 2012, NVIDIA announced the deprecation of the Cg Toolkit, with the final update released in April of that year as version 3.1, citing redundancy in light of the growing standardization of High-Level Shading Language (HLSL) for DirectX and OpenGL Shading Language (GLSL) for OpenGL and Vulkan APIs.[4][20] The toolkit has received no new features or security patches since then, and NVIDIA now archives downloads on its developer site while explicitly recommending migration to HLSL or GLSL for new development.[21] Despite its deprecation, Cg maintains a legacy role in pre-2012 graphics applications, including older video games and embedded systems where shader code was authored in the language, as these systems often lack the resources for full refactoring.[4] Source code availability persists through open-source forks and mirrors, such as the Cg Toolkit repository on GitHub, which includes support for the CgFX effects format and allows limited maintenance by the community.[22] Additionally, alternatives like the nvFx library, developed by an NVIDIA engineer, provide open-source implementations for CgFX-compatible effects.[4] As of 2025, Cg adoption remains minimal in active projects, overshadowed by modern graphics APIs such as Vulkan and Apple's Metal, which favor portable intermediate representations like SPIR-V for shader deployment.[23] NVIDIA and industry standards bodies recommend migration paths, including compiling HLSL (Cg's syntactic successor) to SPIR-V via tools like the DirectX Shader Compiler for Vulkan compatibility, ensuring shaders can target contemporary hardware without proprietary dependencies.[24][25] The deprecation has amplified perceptions of vendor lock-in from Cg's early NVIDIA-centric design, complicating updates in legacy codebases tied to specific GPU profiles, while the absence of ongoing maintenance raises risks of unpatched vulnerabilities in deployed shaders.[4][26]Language Features
Syntax and Basic Semantics
Cg adopts a syntax closely modeled on the C programming language, facilitating familiarity for developers experienced in general-purpose programming. Programs are organized into entry-point functions, such as a main function for vertex or pixel shaders, which contain variable declarations, assignment statements, control flow constructs, and code blocks delimited by curly braces. These functions process input data from the graphics pipeline, perform computations, and produce outputs, with parameters annotated using specifiers likein, out, or inout to define data flow.[27][28][1]
Semantically, Cg is a statically typed, declarative language designed for compilation into GPU-specific instructions, enabling uniform evaluation across supported hardware profiles while incorporating flow control for branching and looping. Each shader invocation operates in isolation without interdependencies between threads, ensuring deterministic execution on parallel GPU architectures. Key rules mandate side-effect-free expressions, particularly for vector and matrix operations, to align with the SIMD nature of graphics processing units, where computations occur implicitly in parallel across multiple threads or fragments.[27][29][1]
In effect files with the .cgfx extension, Cg programs are encapsulated within technique and pass blocks that define rendering sequences, allowing parameters such as uniforms or textures to be bound at runtime via the Cg API for dynamic configuration. Error handling primarily occurs at compile time through the Cg compiler, which performs checks for type mismatches and semantic violations, while runtime errors are managed through API callbacks from functions like cgCompileProgram. For data types, Cg supports scalar types like float and int, alongside graphics-oriented constructs such as vectors (e.g., float4) and matrices, though full details vary by profile.[28][27][1]
Data Types and Variables
Cg provides a set of built-in scalar data types tailored for graphics programming, includingfloat for IEEE 32-bit single-precision floating-point numbers, half for 16-bit lower-precision floating-point values suitable for intermediate computations in fragment programs, fixed for signed fixed-point numbers with a range of [-2, 2) and at least 10 bits of fractional precision, int for 32-bit two's complement integers, and bool for boolean values representing true or false.[30] These scalars support precision control, where half and fixed enable optimizations for hardware constraints, such as reduced bandwidth on mobile GPUs.[31]
Cg also supports composite data types, including structs for user-defined groupings of variables (e.g., struct Input { float3 position; float2 uv; }) and arrays for collections of elements (e.g., float[10] for single-dimensional or multi-dimensional variants), which are first-class types with copy semantics and used in parameters, locals, or uniforms, subject to profile-specific limits on size and dimensions.[32]
Vector types in Cg are constructed by appending a dimension suffix (2, 3, or 4) to scalar base types, yielding predefined types like float2, float3, float4, half3, and similar variants for int and bool.[30] Vectors can be initialized using constructors, such as float4(1.0, 0.0, 0.0, 1.0), which packs the scalar arguments into components.[30] Component access and manipulation employ swizzling with selectors like .xyz, .rgba, or arbitrary combinations (e.g., pos.xyz to extract the first three components of a position vector).[30]
Matrix types follow a similar naming convention, denoted as TYPErowsXcolumns where rows and columns range from 1 to 4, such as float3x3 or float4x4.[30] Matrices employ column-major storage order, aligning with graphics APIs like OpenGL, and can be constructed by passing column vectors, for example, float3x3(col0, col1, col2) where each col is a float3.[30] Elements are accessed via zero-based indexing (e.g., matrix[0][1] for row 0, column 1) or swizzling with _m<row><col> notation (e.g., myMatrix._m01).[30]
Texture sampling in Cg utilizes specialized types including sampler1D, sampler2D, sampler3D, samplerCUBE, and samplerRECT, which serve as opaque handles to texture objects and support read-only access.[30] These samplers integrate with sampler_state blocks in CgFX effects to configure sampling behaviors, such as filtering modes (MinFilter, MagFilter, MipFilter) for texture magnification, minification, and mipmapping, as well as options like GenerateMipmap to enable automatic mipmap generation and LODBias for level-of-detail adjustments.[33]
Variables in Cg are scoped as uniforms for read-only input parameters constant across shader invocations (e.g., model-view matrices passed from the application), varyings for data transfer between shader stages like vertex to fragment programs, or local variables declared within functions for temporary computations.[30] Cg does not support dynamic memory allocation, relying instead on statically declared variables without pointers or heap operations.[30]
Type qualifiers modify variable behavior, including uniform for constant inputs, varying for inter-stage data, and const to enforce immutability after initialization.[30] Precision specifiers like half provide hints for hardware optimization, particularly on mobile GPUs where lower precision reduces power consumption without significant quality loss in graphics pipelines.[31]
Operators and Expressions
Cg provides a rich set of operators and expressions modeled after ANSI C, extended to handle graphics primitives such as vectors and matrices through component-wise operations and specialized built-in functions.[32] These operators enable efficient manipulation of scalar, vector, and matrix data in shader programs, with no support for operator overloading to maintain simplicity and portability across graphics hardware profiles.[30] Arithmetic operations in Cg include the standard binary operators addition (+), subtraction (-), multiplication (*), and division (/) for scalars, vectors, and matrices.[32] These perform component-wise computations on vectors and matrices; for instance, adding two float3 vectors results in a new float3 where each component is the sum of the corresponding inputs.[30] Unary operators include negation (-) and positive identity (+), applicable to all numeric types.[32] Scalar operands are automatically promoted and replicated to match vector or matrix dimensions during operations.[32]
For vector mathematics, Cg includes built-in functions such as dot(a, b) for computing the scalar dot product of two vectors of the same dimension and cross(a, b) for the vector cross product, limited to 3D float3 inputs yielding a perpendicular float3 output.[32] These functions are essential for lighting and geometry calculations in shaders.[30] An example usage is:
float intensity = dot(normal, lightDir); // Scalar result from two float3 vectors
float3 perpendicular = cross(vec1, vec2); // float3 result
float intensity = dot(normal, lightDir); // Scalar result from two float3 vectors
float3 perpendicular = cross(vec1, vec2); // float3 result
* operator for multiplication between a matrix and a vector (e.g., mat4 * float4 yielding a float4) or between two matrices (e.g., mat4 * mat4 yielding a mat4), following standard linear algebra rules.[32] Transposition is handled via the library function transpose(mat), which swaps rows and columns without a dedicated operator.[30] Arithmetic operators like + and - apply component-wise to matrices as well.[32]
Logical operators in Cg consist of conjunction (&&), disjunction (||), and negation (!), operating on scalar booleans or component-wise on boolean vectors without short-circuit evaluation.[30] Relational operators such as less than (<), greater than (>), equality (==), inequality (!=), less than or equal (<=), and greater than or equal (>=) compare scalars or perform component-wise comparisons on vectors and matrices, returning a boolean scalar or vector accordingly.[32] For example, float3 a = float3(1.0, 2.0, 3.0); bool3 result = a > 2.0; produces bool3(false, false, true).[30]
Type casting in Cg supports implicit promotions, such as from int to float or half to float, with potential precision loss warnings during compilation.[32] Explicit casts use C-style syntax like (float)x or constructor notation float(x) for scalars, vectors, and matrices, enabling conversions between compatible numeric types.[30]
Operator precedence adheres to standard C rules, with multiplication and division having higher precedence than addition and subtraction, and all operators respecting left-to-right associativity within the same precedence level; parentheses are used to enforce grouping.[32] Built-in functions like dot and cross are invoked with standard function-call syntax and follow the precedence of function calls.[30]
Special expressions for texture sampling include functions like tex1D(sampler, coord) for 1D textures, returning a float4 color value based on the scalar coordinate, with variants such as tex1Dlod(sampler, coord) for explicit level-of-detail (LOD) control to bias or clamp mipmapping.[32] Similar functions exist for 2D (tex2D), 3D (tex3D), and cube map (texCUBE) sampling, operating on appropriate sampler types and coordinate vectors.[30] An example is:
float4 color = tex1D(sampler1D, 0.5); // Sample at midpoint
float4 detailed = tex1Dlod(sampler1D, float4(0.5, 0.0, 0.0, 0.0)); // With [LOD](/page/Lod) 0
float4 color = tex1D(sampler1D, 0.5); // Sample at midpoint
float4 detailed = tex1Dlod(sampler1D, float4(0.5, 0.0, 0.0, 0.0)); // With [LOD](/page/Lod) 0
Control Structures and Functions
Cg supports conditional statements using theif-else construct and the ternary operator ?:, enabling selection based on boolean expressions. The if statement evaluates a condition and executes the associated block if true, with an optional else clause for the alternative path; for example, if (dot > 0.0) return 1.0; else return 0.0;. The ternary operator provides a concise alternative, such as float result = (condition) ? value1 : value2;, though side effects in both branches are always evaluated regardless of the condition in certain profiles. Dynamic branching, where execution paths diverge based on runtime data, is supported in higher profiles like vs_3_0 and fp40, but older profiles such as vp20 or arbfp1 may predicate instructions instead, evaluating both paths for efficiency on GPU hardware.[32]
Looping constructs in Cg include for, while, and do-while statements, all requiring integer indices for predictability on parallel GPU architectures. The for loop initializes, checks a condition, and increments iteratively, as in for (int i = 0; i < 10; i++) { sum += array[i]; }; fixed iteration counts are preferred for compile-time unrolling to optimize performance. The while and do-while loops evaluate conditions before or after each iteration, respectively, such as while (i < limit) { i++; } or do { process(); } while (condition);. In profiles like arbfp1 or fp30, loops must be unrollable with compile-time determinable iterations, while fp40 allows data-dependent loops up to 256 iterations and 4 nesting levels. The [unroll] attribute hints the compiler to fully unroll a loop, e.g., [unroll] for (int i = 0; i < 4; i++) {...}, aiding optimization but increasing code size. Integer-based loops ensure predictable execution, avoiding floating-point imprecision issues. Break and continue statements are available in higher profiles such as vs_3_0 and ps_3_0, but not in lower profiles like vp20 or arbfp1, to balance dynamic control with static control flow analysis.[32]
Functions in Cg are declared with a return type, name, and parameter list, mirroring C syntax but adapted for GPU execution; for instance, float4 computeLighting(float3 normal) { ... return result; }. Parameters are passed by value and qualified as in (default, read-only), out (write-only), or inout (read-write), supporting scalars, vectors, matrices, or arrays; default values are allowed for uniform in parameters. Overloading by parameter count or type is permitted, but recursion is not supported due to GPU stack limitations and shader design constraints. Entry points, such as shader mains, are identified by semantics like POSITION or TEXCOORD0 on outputs, e.g., float4 main(float2 uv : TEXCOORD0) : COLOR { ... }. User-defined functions promote modularity, though all must inline or unroll for hardware compatibility.[32]
Cg includes attributes to guide compiler optimizations for control flow. The [branch] attribute encourages dynamic branching for conditionals in supported profiles, potentially reducing redundant computations, as in [branch] if (condition) {...}. Conversely, [flatten] directs the compiler to flatten the flow, evaluating all paths without branching for cases where divergence is rare or costly. These annotations, applied to statements, help balance performance across GPU generations. Brief mention is made of built-in intrinsics like sin and cos for trigonometric computations, which integrate seamlessly into functions but are detailed in the standard library.[32]
Overall limitations emphasize GPU efficiency: dynamic features like data-dependent loops or branching are profile-specific, with lower ones favoring static, uniform execution to avoid divergence in parallel threads; integer loops and absence of early exits ensure predictable wavefront execution.[32]
Preprocessing and Extensions
Preprocessor Directives
The Cg programming language incorporates a preprocessor modeled on the ANSI C standard, enabling developers to manage code reuse, conditional compilation, and debugging information through directives processed before semantic analysis. This preprocessor supports macro definition and substitution to facilitate the creation of reusable code snippets and constants within shader programs.[32] The#define directive allows for the definition of simple constants or parameterized macros, while #undef removes previously defined macros. For instance, a simple constant can be defined as #define PI 3.14159, which substitutes PI with 3.14159 throughout the source code during preprocessing. Parameterized macros extend this functionality, such as #define MAX(a,b) ((a)>(b)?(a):(b)), which enables inline computation of the maximum value between two arguments, promoting code conciseness in graphics computations. These macros are expanded textually before compilation, adhering to ANSI C rules for token replacement and argument handling.[32][30]
Inclusion of external files is handled via the #include directive, which incorporates shared header files containing common definitions or functions, typically using syntax like #include <file.cg> or #include "file.cg". This supports modular shader development by allowing reuse of utility code across multiple programs. Conditional compilation directives such as #ifdef, #ifndef, #if, #else, and #endif further enhance this by enabling platform- or profile-specific code paths; for example, #ifdef DEBUG ... #endif includes debug statements only when the DEBUG macro is defined, often set via compiler flags like -D DEBUG. These directives evaluate macro existence or simple integer expressions at preprocessing time, excluding unsupported complex logic like file I/O operations.[32][10]
Additional directives include #line for specifying source line numbers to aid debugging output, such as #line 100 "newfile.cg" to indicate the current position in a virtual file, and #pragma for compiler hints like suppressing warnings or targeting specific profiles. The #error directive halts compilation with a custom message, e.g., #error "Unsupported profile", useful for enforcing build-time checks. While Cg profiles require support for core conditional directives and macro expansion via #define, file inclusion via #include is optional but widely implemented in NVIDIA's tools.[30][32]
Limitations of the Cg preprocessor stem from its textual, pre-semantic processing phase, prohibiting runtime-dependent features or advanced logic beyond basic arithmetic in #if conditions, and it lacks direct file I/O capabilities to maintain shader portability. Best practices recommend using these directives sparingly for defining common constants or handling platform variations, such as DirectX versus OpenGL targets, while avoiding excessive macro nesting to prevent debugging difficulties from expanded code traces. Overuse can obscure error locations, as substitutions occur before semantic checks, making it preferable to reserve them for shared headers rather than inline logic.[32][10]
HLSL Compatibility and Differences
Cg incorporates many elements from Microsoft's High-Level Shading Language (HLSL) to facilitate development for DirectX users, sharing a C-like syntax that includes scalar, vector, and matrix types, function overloading, and swizzle operators, allowing most Cg code to compile with minimal modifications using HLSL compilers.[32] Effect files in Cg, often with .cgfx or .fx extensions, mirror HLSL's .fx format by bundling shaders, passes, techniques, and state management, while semantics such as TEXCOORD0 and POSITION ensure consistent input/output mappings across both languages.[32] State annotations in CgFX files provide metadata for parameters, similar to HLSL's annotation system, enabling runtime queries and validation through APIs like cgGetNamedEffect and cgValidateTechnique.[32] Despite these similarities, Cg's profile system—such as fp20 for fragment programs or vp40 for vertex programs—differs from HLSL's shader models like ps_2_0 or vs_3_0, as profiles specify GPU hardware capabilities and API targets rather than just model versions, with Cg natively supporting OpenGL alongside DirectX through libraries like CgGL and CgD3D.[32] Cg imports HLSL-compatible data types, such as half for 16-bit floating-point precision with s10e5 encoding, but it lacks HLSL's explicit precise qualifier for controlling compiler optimizations in Shader Model 5.0 and later, relying instead on options like -strict for similar behavior.[32] The cgc compiler in the Cg toolkit can generate HLSL-like bytecode for DirectX profiles using flags such as -profile hlslv or -d3d, enabling direct interoperability; for OpenGL integration, functions like cgGLSetParameter1d or cgGLBindProgram allow parameter binding without HLSL conversion.[32] Early versions of Cg (pre-2.0) omitted support for geometry shaders, a feature introduced in HLSL with DirectX 10, though later profiles like gs_4_0 added equivalent capabilities.[32] Texture intrinsics also vary: Cg's tex2D function can omit the sampler argument in some contexts (e.g., tex2D(texture, uv)), differing from HLSL's requirement for explicit sampler binding as tex2D(sampler, uv), with additional profile-specific extensions in Cg like texCUBEARRAY for arrayed cube maps.[32] As of 2025, Cg's HLSL compatibility remains useful for porting legacy shaders to modern OpenGL or older DirectX pipelines, but it is not recommended for new DirectX 12 development, where HLSL with Shader Model 6.0+ and updated intrinsics provide better performance and feature support without Cg's deprecated runtime dependencies.[34]Compilation and Runtime Environment
Profiles and Compilation Targets
Cg employs a set of profiles to abstract the programmable capabilities of graphics hardware, enabling compilation to specific shader models for vertex and fragment processing across OpenGL and Direct3D APIs prevalent up to the 2010 era. Vertex profiles encompass vp20 and vp40 for NVIDIA OpenGL hardware, corresponding to NV_vertex_program and NV_vertex_program3 extensions, respectively, alongside ARB_vertex_program (arbvp1) for broader compatibility. Fragment profiles include fp20 and fp30 for NVIDIA OpenGL, mapping to NV_register_combiners2 and NV_fragment_program, as well as ARB_fragment_program (arbfp1). NVIDIA-specific profiles, such as vp30 for NV_vertex_program2, provide targeted support for proprietary extensions on GeForce 5 and later GPUs. Direct3D equivalents include vs_2_0/vs_3_0 for vertex shaders and ps_2_0/ps_3_0 for pixel shaders, aligning with Shader Model 2.0 and 3.0 capabilities.[35][13] The standalone Cg compiler, cgc, translates Cg programs into assembly code or bytecode tailored to these profiles, outputting formats such as NV_vertex_program2 assembly for OpenGL or DirectX shader assembly for models like vs_3_0 and ps_2_0. This process enforces hardware-specific constraints during compilation, ensuring compatibility with the targeted GPU architecture.[36][13] Each profile imposes distinct resource limits on instructions, temporaries, and constants to match underlying hardware capabilities, as summarized in the following table for key DirectX and OpenGL profiles up to the 2010 era:| Profile | Total Instructions | Temporaries | Constants (float4 registers) | Notes |
|---|---|---|---|---|
| ps_2_0 (DirectX Pixel Shader 2.0) | 96 | 32 | 32 | 64 arithmetic + 32 texture instructions; supports up to 16 samplers.[37][13] |
| vs_3_0 (DirectX Vertex Shader 3.0) | 65,536 | 32 | 256 | Supports up to 65,535 dynamic instructions; constants limited to c0-c255.[38][13] |
| fp20 (OpenGL Fragment Profile 20) | 256 | 32 | 32 | Maps to NV_fragment_program; equivalent to ps_2_x limits with restricted texture functions.[39][13] |
| vp20 (OpenGL Vertex Profile 20) | 256 | 12 | 96 | Maps to NV_vertex_program; no branching support.[39][13] |
#pragma profile(name) directive within Cg source code, such as #pragma profile(vs_2_0), or through command-line flags when invoking cgc, for example cgc -profile ps_2_0 input.cg. If no profile is specified, cgc requires one via the flag, defaulting to error rather than a generic CG fallback, though runtime APIs like cgCreateProgram allow dynamic profile loading.[13][39]
Older profiles, including vp20 and fp20, lack support for dynamic loops and branching due to fixed instruction sequences in early NVIDIA hardware like GeForce 3, restricting shaders to static flow control. While modern GPUs far exceed these constraints—offering millions of instructions and unified shader architectures—Cg's profiles extend up to Shader Model 5.0 (DirectX 11) and equivalent OpenGL 4.x extensions, but do not support later models like Shader Model 6.0 or beyond, such as those in DirectX 12 or Vulkan SPIR-V. As of 2025, Cg profiles are considered obsolete, with Vulkan's SPIR-V intermediate representation serving as the preferred target for new cross-platform shader development.[13][40][4]
Standard Library Overview
The Cg standard library provides a collection of built-in functions optimized for graphics programming on GPUs, focusing on mathematical computations, geometric operations, vector and matrix manipulations, texture sampling, and procedural noise generation. These functions are designed to be deterministic, ensuring consistent results for the same inputs across GPU executions, and exclude any input/output operations or system calls to maintain suitability for parallel shader environments. All functions support overloading based on input types, automatically adapting to scalar values or vector types such asfloat, float2, float3, float4, half, or fixed variants, where the return type matches the dimensionality of the inputs—for instance, dot(float3 a, float3 b) returns a float.[32][41]
Mathematical functions in the Cg library encompass trigonometric, exponential, and logarithmic operations essential for shading calculations. Trigonometric functions include sin, cos, and tan for standard angles, along with hyperbolic variants sinh, cosh, and tanh; inverse functions such as [asin](/page/Asin), acos, atan, and [atan2](/page/Atan2) are also available for angle computations. Exponential and logarithmic functions cover exp and exp2 for base-e and base-2 exponentials, respectively, alongside log, log10, and log2 for logarithms, enabling efficient handling of growth and decay in lighting models. Additional utilities like [pow](/page/Exponentiation) for exponentiation and sqrt for square roots support these operations, with all functions overloaded for vector inputs to process components in parallel.[42][32]
Geometric functions facilitate vector-based computations critical for spatial transformations in shaders. Core operations include length to compute the Euclidean magnitude of a vector, normalize to produce a unit-length vector, and reflect to calculate the reflection of an incident vector over a normal (limited to three-component vectors). The dot function computes the scalar dot product between vectors, returning a float, while cross generates the cross product for perpendicular vectors in 3D space. These functions adapt seamlessly to vector types, promoting concise code for tasks like normal mapping or light direction calculations.[41][32]
Vector and matrix functions extend geometric capabilities to linear algebra operations. The mul function performs matrix multiplication, supporting both matrix-matrix and matrix-vector products, such as transforming a position vector by a 4x4 transformation matrix. Matrix-specific intrinsics include inverse for computing the inverse of square matrices like float4x4, determinant for evaluating the scalar determinant, and transpose for swapping rows and columns. These operations are overloaded to handle various matrix dimensions, ensuring efficient GPU implementation without explicit loops.[42][32]
Texturing functions enable sampling from texture resources, supporting multiple dimensions and projection modes. Basic samplers include tex1D for one-dimensional textures, tex2D for two-dimensional, tex3D for volumetric, and texCUBE for cube maps, each taking a sampler and coordinate input to return a float4 color value. Projection variants like tex1Dproj, tex2Dproj, and tex3Dproj divide coordinates by the w-component for perspective-correct sampling. Additional modifiers such as tex2Dbias and tex2Dlod allow control over mip level and bias for anti-aliasing, with overloads accommodating vector coordinates.[41][32]
Procedural noise functions generate pseudo-random patterns using Perlin noise algorithms, useful for textures like clouds or terrain. The library includes noise1 for 1D input, noise2 for 2D, and noise3 for 3D, each returning a float value between 0 and 1 that is fully deterministic based on the input vector. These functions support vector overloads, allowing seamless application to higher dimensions without additional code.[32][41]
Cg Runtime API
The Cg Runtime API provides a C/C++ interface for applications to load, compile, link, and execute Cg shader programs at runtime, primarily targeting graphics pipelines in OpenGL and Direct3D environments. This API consists of core runtime functions for program management, along with specialized extensions for graphics API integration (cgGL* for OpenGL and cgD3D* for Direct3D). It enables dynamic shader handling without requiring offline compilation, facilitating runtime customization in graphics applications.[39] Core operations begin with creating a Cg context, which serves as a container for programs and parameters. The functionCGcontext cgCreateContext(void) initializes a new context and returns its handle, or NULL on failure due to memory allocation errors.[43] Programs are then loaded using CGprogram cgCreateProgramFromFile(CGcontext context, CGprofile profile, const char *filename, CGprogramtype program_type, const char *entry, const char **args), which reads shader source from a file, associates it with a specified profile (e.g., vertex or fragment), and prepares it for compilation within the given context. Compilation occurs via CGbool cgCompileProgram(CGprogram program), which targets the program's profile and returns CG_TRUE on success; the status can be verified with CGbool cgIsProgramCompiled(CGprogram program). These steps ensure shaders are validated and optimized for the target GPU before binding.[39]
Parameter handling allows applications to bind data to shader uniforms and varyings. Parameters are retrieved by name using CGparameter cgGetNamedParameter(CGprogram program, const char *name), which returns a handle or NULL if not found. For OpenGL, scalar values are set with functions like void cgGLSetParameter1f(CGparameter param, float x), while arrays are bound via void cgGLSetParameterArray1f(CGparameter param, int offset, int nelements, const float *values) or similar variants for multi-component data (e.g., cgGLSetParameterArray4f). Direct3D equivalents, such as cgD3D9SetParameter1f and cgD3D9SetParameterArray1f, follow analogous patterns but require device setup with cgD3D9SetDevice(IDirect3DDevice9 *device). Array sizes must be predefined using cgSetArraySize to avoid recompilation on changes. Effects, which encapsulate multiple techniques and passes, are managed with CGeffect cgCreateEffect(CGcontext context, const char *source, const char **args), enabling higher-level rendering control. Program binding to the graphics pipeline uses cgGLBindProgram(CGprogram program) for OpenGL or cgD3D9BindProgram(CGprogram program) for Direct3D 9, with similar functions for Direct3D 11 (e.g., cgD3D11BindProgram).[39]
Error handling is integral, with const char *cgGetLastErrorString(void) retrieving the most recent error message after operations like creation or compilation fail. This function supports context-specific queries and aids debugging without halting execution. For validation, applications check return values and error strings post-compilation or binding.[39]
Memory management requires explicit cleanup to prevent leaks. Programs are destroyed with void cgDestroyProgram(CGprogram program), and contexts with cgDestroyContext(CGcontext context), releasing associated resources. The API supports a locking policy configurable via cgSetLockingPolicy, defaulting to CG_THREAD_SAFE_POLICY for basic multithreading, though concurrent access to shared contexts demands external synchronization to avoid races.[39]
As of 2025, the Cg Runtime API remains available through the archived Cg 3.1 Toolkit, but it is unmaintained since NVIDIA's last release in 2012, with headers and libraries downloadable for legacy support. Game engines like Unity incorporated Cg API wrappers for shader management prior to 2018, when they transitioned to HLSL compatibility due to Cg's deprecation.[4]
Tools and Implementations
Official Compilers and Toolkits
The official compiler for the Cg programming language is the Cg Compiler (cgc), a standalone command-line tool developed by NVIDIA that translates Cg or GLSL source programs into assembly code or high-level shading language code compatible with OpenGL and DirectX APIs.[36] Developers invoke cgc with options such as-profile to specify target profiles (e.g., vp40 for vertex programs on certain NVIDIA GPUs) and -o to direct output to a file, as in the command cgc -profile vp40 -o output.asm input.cg.[28] This tool enables offline compilation of shaders, producing optimized assembly for deployment in graphics applications.
The Cg Toolkit encompasses a suite of components essential for Cg development, including header files like cg.h for API access, runtime libraries such as cg.lib and cggl.lib for integration with OpenGL and Direct3D, along with examples, documentation, and a user's manual.[16] A key graphical tool within the toolkit was FX Composer, an integrated development environment (IDE) for authoring, editing, previewing, and optimizing Cg and CgFX effects in real time, featuring shader performance analysis via integrated tools like ShaderPerf; however, FX Composer was discontinued after its final release, version 2.5.[44]
Debugging support in the official tools focuses on compiler-level diagnostics, with cgc providing error output for syntax and semantic issues during compilation, as well as the -debug option to enable a built-in debug function that halts shader execution and outputs diagnostic values for runtime inspection.[45] While early integration with NVIDIA's debugging environments existed for shader validation, the legacy nature of Cg limits advanced features in modern tools.
The Cg Toolkit was distributed by NVIDIA until its deprecation, with version 3.1 released in April 2012 marking the final update, after which it transitioned to legacy status with downloads available only for maintenance of existing applications.[4] It no longer receives development or support, lacks compatibility with GPUs beyond those from the early 2010s, and NVIDIA advises against its use for new projects in favor of standardized shading languages. For Linux environments seeking OpenGL shader support, third-party implementations like Mesa offer GLSL-based alternatives that can emulate some Cg functionality through compatible profiles, though direct Cg compilation requires the official toolkit.[4]