AppendicesSoftware and Hardware RequirementsSoftware Environment
You will need the following 3rd party libraries:
Hardware Environment
In general, Cg OpenGL requires a GPU with support for either ARB_vertex_program/ARB_fragment_program (GeForceFX (or better) or Radeon 9500 (or better) families) or NV_vertex_program/NV_texture_shader/NV_register_combiners (GeForce3 (or better) family). ExecutionTo execute the pre-compiled binaries, you need to use the following command line: C:\>Bumpmap.exe Cube.ms3d Fragment.cg The first parameter specifies the 3D Model to render on the screen, and the second parameter specifies the Cg fragment program to use in order to render the faces of the model. Once the application window appears on the screen, you can right-click anywhere in it and display a pop-up menu with four options in it:
ImplementationThe code that accompanies this article (and implements the concepts described within) has a few additional features that go beyond the scope of the article. In particular, the Cg code computes both the diffuse and the specular component for the lighting model, for which reason it is longer and slightly more complicated. The triangle mesh rendered on the screen is a cube created using Milkshape 3D [8]. The code is documented and automated documentation is produced using Doxygen [9]. Cg Setup Code#include <Cg/cg.h> #include <Cg/cgGL.h> void cgErrorCallback() { CGerror err = cgGetError(); if (err != CG_NO_ERROR) { cerr << "cgErrorCallback(): " << cgGetErrorString(err) << endl; exit(1); } } void main(int argc, char* argv[]) { cgSetErrorCallback(cgErrorCallback); CGcontext context = cgCreateContext(); CGprofile profile = cgGLGetLatestProfile(CG_GL_FRAGMENT); cgGLSetOptimalOptions(profile); CGprogram program = cgCreateProgramFromFile( context, CG_SOURCE, [file name], profile, NULL, // entry point NULL); // arguments cgGLLoadProgram(program); cgGLBindProgram(program); cgGLEnableProfile(profile); } Cg Rendering Code#include <Cg/cg.h> #include <Cg/cgGL.h> void draw() { // OpenGL lighting must be disabled since the pixel shader // program will compute the lighting value glDisable(GL_LIGHTING); // The first texture unit contains the detail texture glActiveTextureARB(GL_TEXTURE0_ARB); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, [detail texture handle]); // The second texture unit contains the normalmap texture glActiveTextureARB(GL_TEXTURE1_ARB); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, [normalmap texture handle]); // Set the (fixed) ambient color value CGparameter ambientColorParameter = cgGetNamedParameter(program, "ambientColor"); cgGLSetParameter3f(ambientColorParameter, [ambientr], [ambientg], [ambientb]); for every vertex in the triangle { // Bind the light vector to COLOR0 and interpolate // it across the edge glColor3f([lightx], [lighty], [lightz]); // Bind the texture coordinates to TEXTURE0 and // interpolate them across the edge glMultiTexCoord2fARB(GL_TEXTURE0_ARB, [texturex], [texturey]); // Bind the normalmap coordinates to TEXTURE1 and // interpolate them across the edge glMultiTexCoord2fARB(GL_TEXTURE1_ARB, [texturex], [texturey]); // Specify the vertex coordinates glVertex3fv([vertexx], [vertexy], [vertexz]); } } Cg Fragment Programfloat4 main(float2 detailCoords : TEXCOORD0, float2 bumpCoords: TEXCOORD1, float3 lightVector : COLOR0, uniform float3 ambientColor, uniform sampler2D detailTexture : TEXUNIT0, uniform sampler2D bumpTexture : TEXUNIT1): COLOR { float3 detailColor = tex2D(detailTexture, detailCoords).rgb; // Uncompress vectors ([0, 1] -> [-1, 1]) float3 lightVectorFinal = 2.0 * (lightVector.rgb - 0.5); float3 bumpNormalVectorFinal = 2.0 * (tex2D(bumpTexture, bumpCoords).rgb - 0.5); // Compute diffuse factor float diffuse = dot(bumpNormalVectorFinal, lightVectorFinal); return float4(diffuse * detailColor + ambientColor, 1.0); } References[1] nVIDIA "OpenGL SDK"
|
|