Open main menu

CDOT Wiki β

Changes

GAM670/DPS905 Weekly Schedule 20121

96,318 bytes added, 08:00, 21 March 2012
This Week
*:: axis-aligned bounding boxes
*:: oriented bounding boxes
 
=== To Do ===
* Research the feature that you are going to add and prepare a plan of action
* Prepare a team page for your team so that repos can be ordered
* Add a section to your team page to track your project and solicit commentary
 
=== Resources ===
 
== Week 3 - Jan 23 ==
=== This Week ===
* Collision Detection (cont'd)
*: Shape
*:: Shape : Frame
*:: Shape::setRadius()
*:: Shape::getRadius()
*:: Shape::setRadius(float r);
*:: Shape::setRadius(float x, float y, float z);
*:: Shape::getRadius() const { return radius; }
*:: Shape::setPlane(Vector n, float d);
*:: Shape::setAxisAligned(Vector min, Vector max);
* Comprehensive Camerawork
*: rotation about an axis
*: order of rotation matters
*: Euler angles
*: gimble : [http://www.youtube.com/watch?v=UpSMNYTVqQI&feature=related 3-2-1 angles]*: gimbal lock*:: [http://www.youtube.com/watch?v=rrUCBOlJdt4&feature=related StephenSeefeld.net]*: complex numbers*:: solution of cubic equations 16th century*:: two-dimensional representation*:: [http://en.wikipedia.org/wiki/Complex_number#Matrix_representation_of_complex_numbers matrix representation]*: quaternions*:: extension of complex numbers*:: four-dimensional representation*:: [http://en.wikipedia.org/wiki/Quaternion#Matrix_representations matrix representation]*: geometric algebra (more abstract)<!*:: [http://staff.science.uva.nl/~leo/cinderella/line1.html Dorst's site]*:: [http://sinai.apphy.u-fukui.ac.jp/gcj/software/GAcindy-1.4/GAcindy.htm Hitzer's site]* BillboardsVisibility Determination**: definition, purpose test a point for presence within a set of a billboardplanes**: normal calculations - general rotation matrix - vector and angle** ViewFrustum**: parameter - view * projection**: 6 planes**:: near and far planes**:: left and right planes**:: top and bottom planes**: types of billboardscoding* SkyBox*:: constructor**:: definition ViewFrustum::contains()** Finite Size of a skyboxObjects**: other formsExpansion of the View Frustum
* Index Buffers
*: amount of storage needed for vertex data
*: indexing
*: indexed primitives
 
=== To Do ===
=== Resources ===
* [http://en.wikipedia.org/wiki/Complex_number Wikipedia on Complex Numbers]
* [http://en.wikipedia.org/wiki/Quaternion Wikipedia on Quaternions]
* [http://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation Wikipedia on quaternions and Spatial Rotations]
* [http://mathworld.wolfram.com/Quaternion.html Wolfram on Quaternions]
* [http://www.cprogramming.com/tutorial/3d/quaternions.html CProgramming.com on Quaternions]
* [http://www.ogre3d.org/tikiwiki/Quaternion+and+Rotation+Primer Ogre intro on Quaternions]
* collision sample
* indexBuffering sample
 
 
== Week 4 - Jan 30 ==
=== This Week ===
* Meshes
*: What is a mesh?
*:: vertex list -> vertex buffer
*:: index list -> index buffer
*:: attribute list -> subset to which primitives belong
*:: pyramid sample
*: Stock Objects
*:: Sphere
*::: slices and partitions
*:: Cylinder
*:: Torus
*:: Utah Teapot
*: Simple Mesh COM object: APIGraphic.h and .cpp code*:: What is a mesh?Custom Mesh
*:: Create a Mesh
*:: APIGraphic.h code<syntaxhighlight lang="cpp">template <class T = Vertex, class I = Index>class APICustomMesh : public iAPIGraphic, public APIBase {  unsigned nSubsets; // number of subsets unsigned nPrimitives; // number of primitives unsigned* attribute; // points to mesh's attribute list I* index; // points to mesh's array of indices unsigned iIndex; // number of indices currently saved unsigned nIndices; // number of indices in the mesh T* vertex; // points to mesh's array of vertices unsigned iVertex; // number of vertices currently saved unsigned nVertices; // number of vertices in the mesh LPD3DXMESH apiMesh; // set of vertices, indices  protected: virtual ~APICustomMesh(); void setup();  public: APICustomMesh(unsigned*, int, int, int, int); APICustomMesh(const APICustomMesh& v); APICustomMesh& operator=(const APICustomMesh& v); APICustomMesh* clone() const { return new APICustomMesh(*this); } unsigned add(const T& v); void add(unsigned); void draw(unsigned); void suspend(); void release() { suspend(); } void Delete() const { delete this; }};</syntaxhighlight>*:: APIGraphic.cpp - APIGraphic<syntaxhighlight lang="cpp">template <class T, class I>APICustomMesh<T, I>::APICustomMesh(unsigned* a, int np, int ni, int nv, int ns) : nSubsets(ns), nPrimitives(np), nIndices(ni), nVertices(nv), iIndex(0), iVertex(0) {  attribute = new unsigned[nPrimitives]; for (unsigned i = 0; i < nPrimitives; i++) attribute[i] = a[i];  index = new I[nIndices]; vertex = new T[nVertices];  apiMesh = nullptr;}</syntaxhighlight>*:: APIGraphic.cpp - add()<syntaxhighlight lang="cpp">template <class T, class I>unsigned APICustomMesh<T, I>::add(const T& v) {  unsigned i = iVertex;  if (vertex && iVertex < nVertices) vertex[iVertex++] = v;  return i;}</syntaxhighlight><syntaxhighlight lang="cpp">template <class T, class I>void APICustomMesh<T, I>::add(unsigned v) {  if (index && iIndex < nIndices) index[iIndex++] = v;}</syntaxhighlight>*:: APIGraphic.cpp - setup()<syntaxhighlight lang="cpp">template <class T, class I>void APICustomMesh<T, I>::setup() {  T *pv; I *pi; DWORD *pa; nIndices = iIndex; nVertices = iVertex;  // create an empty mesh and lock its buffers if (FAILED(D3DXCreateMesh(nPrimitives, nVertices, 0, APIVertexDeclaration<T>::format(), d3dd, &apiMesh))) { error(L"APIMesh::14 Couldn\'t create the empty mesh"); apiMesh = nullptr; } else if (FAILED(apiMesh->LockVertexBuffer(0, (void**)&pv))) { error(L"APIMesh::15 Couldn\'t lock vertex buffer"); release(); } else if (FAILED(apiMesh->LockIndexBuffer(0, (void**)&pi))) { error(L"APIMesh::16 Couldn\'t lock index buffer"); release(); } else if (FAILED(apiMesh->LockAttributeBuffer(0, &pa))) { error(L"APIMesh::17 Couldn\'t lock attribute buffer"); release(); } else { // populate the newly created Vertex Buffer for (unsigned i = 0; i < nVertices; i++) vertex[i].populate((void**)&pv); apiMesh->UnlockVertexBuffer(); // populate the newly created Index Buffer for (unsigned i = 0; i < nIndices; i++) pi[i] = index[i]; apiMesh->UnlockIndexBuffer(); // Populate the newly created Attribute Buffer for (unsigned i = 0; i < nPrimitives; i++) pa[i] = attribute[i]; apiMesh->UnlockAttributeBuffer(); }}</syntaxhighlight>*:: APIGraphic.cpp - DrawSubset()<syntaxhighlight lang="cpp">template <class T, class I>void APICustomMesh<T, I>::draw(unsigned iSubset) {  // if mesh doesn't exist, set it up first if (!apiMesh) setup();  if (apiMesh) apiMesh->DrawSubset(iSubset);}</syntaxhighlight>*::: DrawIndexedPrimitive parameters*:: FVF settingsAPIGraphic.cpp - suspend()<syntaxhighlight lang="cpp">template <class T, class I>void APICustomMesh<!T, I>::suspend() {  // release the interface to the mesh if (apiMesh) { apiMesh->Release(); apiMesh = nullptr; }}</syntaxhighlight>*:: APIGraphic.cpp -~APIGraphic<syntaxhighlight lang="cpp">template <class T, class I>APICustomMesh<T, I>::~APICustomMesh() {  release(); if (attribute) delete [] attribute; if (index) delete [] index; if (vertex) delete [] vertex;}</syntaxhighlight>*: X File* Visibility Determination:: Create Mesh from File*SkyBox*: test definition of a point for presence within skybox*:: attachment to camera*:: inverted coordinates*: skybox textures*: Graphic.cpp code*: more complicated forms - skydome* Billboards*: definition, purpose of a set billboard<syntaxhighlight lang="cpp">void Billboard::render(unsigned) {  Vector h, u, r, p = position(); Camera* camera = *(Camera**)(Camera::getCurrent()); Vector cameraPosition = camera->position(); Vector cameraHeading = ::normal(camera->orientation('z')); Vector cameraUp = ::normal(camera->orientation('y')); switch (type) { // ... see below } Matrix rot(r.x, r.y, r.z, 0, u.x, u.y, u.z, 0, h.x, h.y, h.z, 0, 0, 0, 0, 1); orient(rot);  Object::render(0);}</syntaxhighlight>*: types of planesbillboards*:: screen-aligned - useful for annotation text, lens flares*::: normal is opposite to camera heading*::: up is camera->up<syntaxhighlight lang="cpp"> case SCREEN: h = cameraHeading; // fixed u = cameraUp; // up is fixed r = cross(u, h); break;</syntaxhighlight>*:: axial - useful for cylindrical symmetry - trees (textured object does not face straight on)*::: up is fixed*::: normal calculations faces the viewer as much as possible<syntaxhighlight lang="cpp"> case AXIAL: h = ::normal(position() - cameraPosition); // heading is open to change u = Vector(0, 1, 0); // up axis is fixed r = cross(u, h); h = cross(u, r); break;</syntaxhighlight>*:: view_plane - no distortion - useful for*::: normal is fixed (opposite to camera heading)*::: up is open to change<syntaxhighlight lang="cpp"> case VIEW_PLANE: h = cameraHeading; // heading is fixed u = Vector(0, 1, 0); // up is open to change r = cross(u, h); u = cross(h, r); break;</syntaxhighlight>*:: viewpoint - simulates distortion due to perspective projection - general rotation matrix useful for clouds*::: normal is fixed (difference between viewpoint position and camera heading)*::: up is open to change<syntaxhighlight lang="cpp"> case VIEWPOINT: h = ::normal(position() - vector cameraPosition); // heading is fixed u = Vector(0, 1, 0); // up is open to change r = cross(u, h); u = cross(h, r); break;</syntaxhighlight>*: Object.h and angleObject.cpp code* Texture Filtering*: mip maps*:: multum in parvo*:: texture creation*:: APITexture::SetSamplerState()<syntaxhighlight lang="cpp"> // mipmap filtering if (flags & TEX_MIPMAP) d3dd->SetSamplerState(i, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); else d3dd->SetSamplerState(i, D3DSAMP_MIPFILTER, D3DTEXF_NONE);</syntaxhighlight>* ViewingFrustumDirectX Errors*: DirectX Utilities - Lookup Tool*: parametersAPIDisplay::restore() example<syntaxhighlight lang="cpp">bool APIDisplay::restore() {  bool rc = false;  if (d3dd) { HRESULT hr; hr = d3dd->TestCooperativeLevel(); if (hr == D3DERR_DEVICENOTRESET) // reset the APIDisplay device rc = d3dd->Reset(&d3dpp) == D3D_OK; else if (hr == S_OK) rc = true; } if (rc) { // reacquire sprite manager references to video memory if (manager) manager->OnResetDevice(); }  // complete the restoration if (rc) { setupLighting(); setupBlending(); }  return rc;}</syntaxhighlight> === To Do ====== Resources ===* meshes sample* [http://rbwhitaker.wikidot.com/skyboxes-1 Rob Whitaker on Skyboxes]* [http://web.cs.wpi.edu/~emmanuel/courses/cs563/S05/talks/suman_wk8_IBR.pdf Image Based Rendering - Suman Nadella on Billboarding and Imposters]*[http://www.digitalrune.com/Products/GameEngine/Particles.aspx DigitalRune]*[http://en.wikipedia.org/wiki/Mipmap Wikipedia on Texture Filtering]* [http: near//www.directxtutorial.com/Tutorial9/B-Direct3DBasics/dx9B7.aspx D3D 9 tutorial on modeling with an Index list] == Week 5 -clipping planeFeb 6 ===== This Week ===*Vertex Declarations*: [http://msdn.microsoft.com/en-us/library/windows/desktop/bb172559%28v=vs.85%29.aspx FVF Codes]<syntaxhighlight lang="cpp">template <class T = Vertex>class APIVertexDeclaration {  static D3DVERTEXELEMENT9 fmt[MAXD3DDECLLENGTH + 1]; static unsigned vertexSize; public: static D3DVERTEXELEMENT9* format() { return fmt; } static unsigned size() { return vertexSize; }};</syntaxhighlight><syntaxhighlight lang="cpp">template <>D3DVERTEXELEMENT9 APIVertexDeclaration<Vertex>::fmt[MAXD3DDECLLENGTH + 1] = { { 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, { 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, { 0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()}; template<>unsigned APIVertexDeclaration<Vertex>:: farvertexSize = 32;</syntaxhighlight><syntaxhighlight lang="cpp"> template <>D3DVERTEXELEMENT9 APIVertexDeclaration<LitVertex>::fmt[MAXD3DDECLLENGTH + 1] = { { 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, { 0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, D3DDECL_END()}; template <>unsigned APIVertexDeclaration<LitVertex>::vertexSize = 16;</syntaxhighlight>:: [http://msdn.microsoft.com/en-clipping planeus/library/windows/desktop/bb172630%28v=vs.85%29.aspx D3DVERTEXELEMENT9 struct]* The Pipeline*: [http://en.wikipedia.org/wiki/Instruction_pipeline What is a pipeline]*:* The GPU*: [http://en.wikipedia.org/wiki/Graphics_processing_unit What is a GPU]** nVidia**: [http://en.wikipedia.org/wiki/Geforce GeForce]**: [http://en.wikipedia.org/wiki/NVIDIA_Quadro Quadro]**: [http://en.wikipedia.org/wiki/Nvidia_Tesla Tesla]**: [http://en.wikipedia.org/wiki/Comparison_of_Nvidia_graphics_processing_units Comparison]** AMD (previously ATI)**: [http://en.wikipedia.org/wiki/Radeon_R520 Radeon 520]**: [http://en.wikipedia.org/wiki/Comparison_of_AMD_graphics_processing_units Comparison]* Shader Languages*: [http://en.wikipedia.org/wiki/Shader what is a shader]*: dedicated shaders*: [http://en.wikipedia.org/wiki/Unified_shader_model unified shaders]*: how does a shader work** Languages**:[http: field of view angle//en.wikipedia.org/wiki/HLSL HLSL - Microsoft]**:[http: aspect ratio//en.wikipedia.org/wiki/Cg_%28programming_language%29 Cg - nVidia]**: [http://en.wikipedia.org/wiki/GLSL GLSL - OpenGL (Khronos)]* Vertex Shaders* Pixel Shaders* effect of skybox and point light on frame rate === To Do === == Week 6 planes- Feb 13 ===== This Week ======= Vertex Shader Programming ====* Host: APIPlatformSettings.h - Vertex Shader Identification - select between fixed function and programmable pipelines here<syntaxhighlight lang="cpp">// shader file data#define VERTEX_SHADER_FILE L"vertexShader.hlsl"#define VERTEX_SHADER_ENTRY_POINT "vertexShader"</syntaxhighlight>: APIBase.h - pointers into the shader - APIBase is the base class for the graphics API classes<syntaxhighlight lang="cpp"> static IDirect3DVertexShader9*vertexShader; // vertex shader static ID3DXConstantTable* uniformVS; // for vertex shader</syntaxhighlight>: APIBase.cpp - initialize the shader pointers<syntaxhighlight lang="cpp">IDirect3DVertexShader9* APIBase::vertexShader = nullptr; // vertex shaderID3DXConstantTable* APIBase::uniformVS = nullptr; // for vertex shader</syntaxhighlight>: APIDisplay.h - keeps track of the current projection matrix<syntaxhighlight lang="cpp"> Matrix projection; // projection transformation</syntaxhighlight>: APIDisplay.cpp - setup() - checks the shader version<syntaxhighlight lang="cpp"> // points to compiled shader code LPD3DXBUFFER compiledCodeVS = nullptr;  // check for minimum vertex shader version required if (caps.VertexShaderVersion < D3DVS_VERSION(2,0)) error(L"APIDisplay:: near 09 Device does not support vertex shader 2_0");</syntaxhighlight>compiles the shader hlsl code, retrieves address of constant memory and far planesvertex shader<syntaxhighlight lang="cpp"> // compile the vertex shader source code else if (FAILED(D3DXCompileShaderFromFile(VERTEX_SHADER_FILE, NULL, NULL, VERTEX_SHADER_ENTRY_POINT, D3DXGetVertexShaderProfile(d3dd), D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION, &compiledCodeVS, NULL, &uniformVS))) { release(); error(L"APIDisplay::13 Unable to compile vertex shader"); } // create the vertex shader object else if (FAILED(d3dd->CreateVertexShader( (DWORD*)compiledCodeVS->GetBufferPointer(), &vertexShader))) { compiledCodeVS->Release(); release(); error(L"APIDisplay::14 Unable to create vertex shader object"); } else { compiledCodeVS->Release();</syntaxhighlight>sets the current vertex shader<syntaxhighlight lang="cpp"> d3dd->SetVertexShader(vertexShader);</syntaxhighlight>: APIDisplay.cpp - setProjection() - stores the projection matrix<syntaxhighlight lang="cpp"> this->projection = *((Matrix*)projection);</syntaxhighlight>:: left APIDisplay.cpp - beginDrawFrame() - copies the view matrix and right planesthe camera heading to constant memory<syntaxhighlight lang="cpp"> Matrix& v = *((Matrix*)view); Matrix viewProjection = v * projection; uniformVS->SetMatrix(d3dd, "viewProjection", (D3DXMATRIX*)&viewProjection); Vector heading(v.m13, v.m23, v.m33); // Required for specular lighting calculations uniformVS->SetFloatArray(d3dd, "heading", (FLOAT*)&heading, 3);</syntaxhighlight><syntaxhighlight lang="cpp"> Colour colour(red, green, blue); uniformVS->SetFloatArray(d3dd, "ambient", (FLOAT*)&colour, 4); uniformVS->SetInt(d3dd, "noLights", 4);</syntaxhighlight>: APIDisplay.cpp - set() - copies the lighting state to constant memory<syntaxhighlight lang="cpp"> uniformVS->SetBool(d3dd, "lighting", b);</syntaxhighlight>: APIDisplay.cpp - setWorld() - copies the world matrix to constant memory<syntaxhighlight lang="cpp"> uniformVS->SetMatrix(d3dd, "world", (D3DXMATRIX*)world);</syntaxhighlight>:APIDisplay.cpp - setReflectivity() - copies the reflectivity to constant memory<syntaxhighlight lang="cpp"> uniformVS->SetFloatArray(d3dd, "material.ambient", (FLOAT*)&r.ambient, 4); uniformVS->SetFloatArray(d3dd, "material.diffuse", (FLOAT*)&r.diffuse, 4); uniformVS->SetFloatArray(d3dd, "material.specular", (FLOAT*)&r.specular, 4); uniformVS->SetFloat (d3dd, "material.power", (FLOAT)r.power);</syntaxhighlight>: top APIDisplay.cpp - release() - releases constant memory and bottom planesthe vertex shader<syntaxhighlight lang="cpp"> // release the shader COM objects if (uniformVS) { uniformVS->Release(); uniformVS = nullptr; } if (vertexShader) { vertexShader->Release(); vertexShader = nullptr; }</syntaxhighlight>: APILight.cpp - setup() - copies the light properties to constant memory<syntaxhighlight lang="cpp"> // Populate the vertex shader constant table // // Light descriptors within the vertex shader char typ[] = "light[0].type"; char amb[] = "light[0].ambient"; char dif[] = "light[0].diffuse"; char spe[] = "light[0].specular"; char pos[] = "light[0].position"; char dir[] = "light[0].direction"; char spt[] = "light[0].spot"; char att[] = "light[0].attenuation"; char ran[] = "light[0].range"; // // Reset index in light descriptor typ[6] = index + '0'; amb[6] = index + '0'; dif[6] = index + '0'; spe[6] = index + '0'; pos[6] = index + '0'; dir[6] = index + '0'; spt[6] = index + '0'; att[6] = index + '0'; ran[6] = index + '0'; // Populate the vertex shader constant table Vector attenuation(attenuation0, attenuation1, attenuation2); Vector spot(cosf(phi/2), cosf(theta/2), falloff); Vector zero; uniformVS->SetInt(d3dd, typ, type); uniformVS->SetFloatArray(d3dd, amb, (FLOAT*)&ambient, 4); uniformVS->SetFloatArray(d3dd, dif, (FLOAT*)&diffuse, 4); uniformVS->SetFloatArray(d3dd, spe, (FLOAT*)&specular, 4); uniformVS->SetFloatArray(d3dd, pos, (FLOAT*)&zero, 3); uniformVS->SetFloatArray(d3dd, dir, (FLOAT*)&zero, 3); uniformVS->SetFloatArray(d3dd, att, (FLOAT*)&attenuation, 3); uniformVS->SetFloatArray(d3dd, spt, (FLOAT*)&spot, 3); uniformVS->SetFloat(d3dd, ran, range); rc = true;</syntaxhighlight>: codingAPILight.cpp - turnOn() - repositions the light and turns it on<syntaxhighlight lang="cpp"> char constantLightOn[] = "lightOn[0]"; constantLightOn[8] = index + '0'; char pos[] = "light[0].position"; char dir[] = "light[0].direction"; pos[6] = index + '0'; dir[6] = index + '0'; uniformVS->SetFloatArray(d3dd, pos, (FLOAT*)&p, 3); uniformVS->SetFloatArray(d3dd, dir, (FLOAT*)&o, 3); uniformVS->SetBool(d3dd, constantLightOn, true);</syntaxhighlight>:APILight.cpp - update() - repositions the light<syntaxhighlight lang="cpp"> char constantLightOn[] = "lightOn[0]"; constantLightOn[8] = index + '0'; char pos[] = "light[0].position"; char dir[] = "light[0].direction"; pos[6] = index + '0'; dir[6] = index + '0'; uniformVS->SetFloatArray(d3dd, pos, (FLOAT*)&p, 3); uniformVS->SetFloatArray(d3dd, dir, (FLOAT*)&o, 3); uniformVS->SetBool(d3dd, constantLightOn, true);</syntaxhighlight>: APILight.cpp - turnOff() - turns off the light<syntaxhighlight lang="cpp"> char constantLightOn[] = "lightOn[0]"; constantLightOn[8] = index + '0'; uniformVS->SetBool(d3dd, constantLightOn, false);</syntaxhighlight>: APIGraphic.h - class APIXMesh - processes an X file mesh<syntaxhighlight lang="cpp"> D3DXCOLOR* ambient; D3DXCOLOR* diffuse; D3DXCOLOR* specular; FLOAT* power;</syntaxhighlight>: APIGraphic.cpp - APIXMesh() - constructor<syntaxhighlight lang="cpp"> ambient = nullptr; diffuse = nullptr; specular = nullptr; power = nullptr;</syntaxhighlight>: APIGraphic.cpp - APIXMesh() - copy constructor<syntaxhighlight lang="cpp"> ambient = nullptr; diffuse = nullptr; specular = nullptr; power = nullptr;</syntaxhighlight>: APIGraphic.cpp - operator=() = assignment operator<syntaxhighlight lang="cpp"> if (ambient) delete [] ambient; if (diffuse) delete [] diffuse; if (specular) delete [] specular; if (power) delete [] power; ambient = new D3DXCOLOR[src.nSubsets]; diffuse = new D3DXCOLOR[src.nSubsets]; specular = new D3DXCOLOR[src.nSubsets]; power = new FLOAT[src.nSubsets];</syntaxhighlight><syntaxhighlight lang="cpp"> for (unsigned i = 0; i < nSubsets; i++) { ambient[i] = src.ambient[i]; diffuse[i] = src.diffuse[i]; specular[i] = src.specular[i]; power[i] = src.power[i]; }</syntaxhighlight>: APIGraphic.cpp - setup() -<syntaxhighlight lang="cpp"> ambient = new D3DXCOLOR[nSubsets]; diffuse = new D3DXCOLOR[nSubsets]; specular = new D3DXCOLOR[nSubsets]; power = new FLOAT[nSubsets];</syntaxhighlight><syntaxhighlight lang="cpp"> ambient[i].r = matl[i].MatD3D.Diffuse.r * 0.7f; ambient[i].g = matl[i].MatD3D.Diffuse.g * 0.7f; ambient[i].b = matl[i].MatD3D.Diffuse.b * 0.7f; ambient[i].a = matl[i].MatD3D.Diffuse.a; diffuse[i] = matl[i].MatD3D.Diffuse; // reflected from lights specular[i] = matl[i].MatD3D.Specular; // shine from lights power[i] = matl[i].MatD3D.Power; // 0 if it shouldn't be shiny</syntaxhighlight>: APIGraphic.cpp - draw()<syntaxhighlight lang="cpp"> uniformVS->SetFloatArray(d3dd, "material.ambient", (FLOAT*)&ambient[i], 4); uniformVS->SetFloatArray(d3dd, "material.diffuse", (FLOAT*)&diffuse[i], 4); uniformVS->SetFloatArray(d3dd, "material.specular", (FLOAT*)&specular[i], 4); uniformVS->SetFloat(d3dd, "material.power", (FLOAT)power[i]);</syntaxhighlight>: APIGraphic.cpp - suspend()<syntaxhighlight lang="cpp"> if (ambient) delete [] ambient; if (diffuse) delete [] diffuse; if (specular) delete [] specular; if (power) delete [] power;</syntaxhighlight>* Device: vertexShader.hlsl - Constant Memory<syntaxhighlight lang="cpp">#define MLIGHTS 4#define POINT_LIGHT 0#define SPOT_LIGHT 1#define DIRECTIONAL_LIGHT 2 // Types//// Light holds the data for a single light in world space//struct Light { int type; // POINT_LIGHT, SPOT_LIGHT, DIRECTIONAL_LIGHT float4 ambient; float4 diffuse; float4 specular; float3 direction; // in world space float3 position; // in world space float3 attenuation; // .xyz for 1.0f/ (.x + .y *d + .z *d * d) float3 spot; // .x = cos(phi/2), .y = cos(theta/2), .z = falloff float range; // where attenuation becomes 0}; // Material holds the reflectivity properties of the material//struct Material { float4 ambient; float4 diffuse; float4 specular; float power;}; // RawVertex holds the untransformed data for a single vertex//struct RawVertex {  float3 position :POSITION; // position in local space float3 normal : ViewingFrustumNORMAL; // normal in local space float2 texCoord :TEXCOORD; // texture coordinates}; // TransformedVertex holds the transformed data for a single vertex//struct TransformedVertex {  float4 position :containsPOSITION; // position in homogeneous clip space float4 colour : COLOR; // colour of the lit vertex float2 texCoord0 : TEXCOORD0; // texture coordinates - stage 0 float2 texCoord1 : TEXCOORD1; // texture coordinates - stage 1}; // Uniform Data (constant for a stream of vertices)//// Lightingfloat4 ambient; // global ambient light - always onLight light[MLIGHTS]; // static lightsbool lightOn[MLIGHTS]; // switches for static lightsMaterial material; // material reflectivity// Geometryfloat4x4 viewProjection; // view * Finite Size projection transformationfloat4x4 world; // world transformationfloat3 heading; // camera heading for specular calcs// Lit Vertexbool litVertex; // omit lighting calculations - already lit </syntaxhighlight>: vertexShader.hlsl - vertexShader()<syntaxhighlight lang="cpp">// vertexShader receives a raw vertex and returns the transformed vertex//TransformedVertex vertexShader(RawVertex raw) {  TransformedVertex transformed; float4 worldPosition; // world position of Objectsthe vertex float3 worldNormal; // vertex normal in world space  // Transform the vertex to homogeneous clip coordinates // // A more efficient algorithm would accept the world*view*projection // tranformation as one uniform matrix and avoid the 2-stage product // This will require a bit of restructuring of the application code. // worldPosition = mul(float4(raw.position, 1.0), world); // local to world transformed.position = mul(worldPosition, viewProjection); //... to clip  // not working if (litVertex) { transformed.colour.r = raw.normal.r; transformed.colour.g = raw.normal.g; transformed.colour.b = raw.normal.b; transformed.colour.a = 1.0f; } else {  // Transform the vertex normal to world space. Only the rotation-scaling // part of the world transformation is used. Since the world // transformation may contain scaling, the result of this multiplication // needs to be normalized. // worldNormal = mul(raw.normal, (float3x3)world); worldNormal = normalize(worldNormal); // Determine the colour of the vertex from each light in turn // // Use the cosine of the angle between the worldNormal and the direction // of the light to determine the amount of reflected light. The cosine // is given by the dot product, if both vectors have been normalized. If // the cosine is less than 0, the angle is greater than 90 degrees and // no light is reflected. Use saturate() to implement this condition. // // A more efficient algorithm would supply the light direction already // converted to the local space of the vertex (by using the inverse of // the world transformation). // float diffuseFactor, reflectFactor, distance; float attenuationFactor, spotFactor, rho; float3 lightDirection, camera = normalize(heading); float3 ambientLight = ambient.xyz; float3 diffuseLight = (float3)0; float3 specularLight = (float3)0; for (int i = 0; i < MLIGHTS; i++) { if (lightOn[i]) { lightDirection = - normalize((light[i].type == POINT_LIGHT)? float3(worldPosition.x, worldPosition.y, worldPosition.z) - light[i].position : Expansion light[i].direction); diffuseFactor = saturate(dot(worldNormal, lightDirection)); reflectFactor = saturate(dot(normalize(2 * diffuseFactor * worldNormal - lightDirection), camera)); attenuationFactor = 1.0f; spotFactor = 1.0f; if (light[i].type == POINT_LIGHT || light[i].type == SPOT_LIGHT) { // detail calcs for attenuationFactor and spotFactor distance = length((float3)worldPosition - light[i].position); if (distance < light[i].range) { attenuationFactor = light[i].attenuation.x + light[i].attenuation.y * distance + light[i].attenuation.z * distance * distance; attenuationFactor = 1.0f / attenuationFactor; if (light[i].type == SPOT_LIGHT) { rho = saturate(dot(normalize(light[i].position - float3(worldPosition.x, worldPosition.y, worldPosition.z)), normalize(-light[i].direction))); if (rho <= light[i].spot.x) spotFactor = 0.0f; else if (rho <= light[i].spot.y) spotFactor = pow( abs((rho - light[i].spot.x)/ (light[i].spot.y - light[i].spot.x)), light[i].spot.z); } } else attenuationFactor = 0.0f; }  // accumulate ambient, diffuse, and specular elements of light // ambientLight += attenuationFactor * spotFactor * light[i].ambient.xyz; diffuseLight += attenuationFactor * spotFactor * diffuseFactor * light[i].diffuse.xyz; specularLight += attenuationFactor * spotFactor * light[i].specular.xyz * pow(reflectFactor, material.power); } } // apply material reflectivity to each accumulated element of light // to obtain the Viewing Frustumcolour of the lit vertex // transformed.colour.xyz = saturate(material.ambient.xyz * ambientLight) + saturate(material.diffuse.xyz * diffuseLight) + saturate(material.specular.xyz * specularLight); // pass the diffuse alpha along as the alpha component // transformed.colour.w = material.diffuse.w; }  // pass the texture coordinates along unaltered // transformed.texCoord0 = raw.texCoord; transformed.texCoord1 = raw.texCoord;  return transformed;}</syntaxhighlight> ==== Fragment Shader ====* Host: APIPlatformSettings.h<syntaxhighlight lang="cpp">#define FRAGMENT_SHADER_FILE L"fragmentShader.hlsl"#define FRAGMENT_SHADER_ENTRY_POINT "fragmentShader"</syntaxhighlight>: APIBase.h<syntaxhighlight lang="cpp"> // Fragment Shader Support static IDirect3DPixelShader9* fragmentShader; // fragment shader static ID3DXConstantTable* uniformFS; // for fragment shader</syntaxhighlight>: APIBase.cpp<syntaxhighlight lang="cpp">IDirect3DPixelShader9* APIBase::fragmentShader = nullptr; // fragment shaderID3DXConstantTable* APIBase::uniformFS = nullptr; // for fragment shader</syntaxhighlight>: APIDisplay.cpp - setup()<syntaxhighlight lang="cpp"> LPD3DXBUFFER compiledCodeFS = nullptr;  // checks for minimum pixel shader version required else if (caps.PixelShaderVersion < D3DPS_VERSION(3,0)) error(L"Display::10 Device does not support pixel shader 3_0");</syntaxhighlight><syntaxhighlight lang="cpp"> // compile the fragment shader source code else if (FAILED(D3DXCompileShaderFromFile(FRAGMENT_SHADER_FILE, NULL, NULL, FRAGMENT_SHADER_ENTRY_POINT, D3DXGetPixelShaderProfile(d3dd), 0, &compiledCodeFS, NULL, &uniformFS))) { release(); error(L"APIDisplay::15 Unable to compile the fragment shader code"); } // create the pixel shader object else if (FAILED(d3dd->CreatePixelShader( (DWORD*)compiledCodeFS->GetBufferPointer(), &fragmentShader))) { compiledCodeFS->Release(); release(); error(L"APIDisplay::16 Unable to create fragment shader object"); } else { compiledCodeFS->Release();</syntaxhighlight>:: [http://msdn.microsoft.com/en-us/library/windows/desktop/bb172732%28v=vs.85%29.aspx D3DXCompileShaderFromFile()]:: [http://msdn.microsoft.com/en-us/library/windows/desktop/bb172870%28v=vs.85%29.aspx D3DXGetPixelShaderProfile()]:: [http://msdn.microsoft.com/en-us/library/windows/desktop/bb174450%28v=vs.85%29.aspx IDirect3DDevice9::CreatePixelShader()]<syntaxhighlight lang="cpp"> d3dd->SetPixelShader(fragmentShader);</syntaxhighlight>:: [http://msdn.microsoft.com/en-us/library/windows/desktop/bb174450%28v=vs.85%29.aspx IDirect3DDevice9::SetPixelShader()]: APIDisplay.cpp - beginDrawFrame()<syntaxhighlight lang="cpp"> Colour colour(red, green, blue); uniformFS->SetFloatArray(d3dd, "ambient", (FLOAT*)&colour, 4); uniformFS->SetInt(d3dd, "noLights", 4);</syntaxhighlight>:: [http://msdn.microsoft.com/en-us/library/windows/desktop/bb205775%28v=vs.85%29.aspx ID3DXConstantTable::SetFloatArray()]:: [http://msdn.microsoft.com/en-us/library/windows/desktop/bb205776%28v=vs.85%29.aspx ID3DXConstantTable::SetInt()]: APIDisplay.cpp - set()<syntaxhighlight lang="cpp"> uniformFS->SetBool(d3dd, "lighting", b);</syntaxhighlight>:: [http://msdn.microsoft.com/en-us/library/windows/desktop/bb205771%28v=vs.85%29.aspx ID3DXConstantTable::SetBool()]: APIDisplay.cpp - setReflectivity()<syntaxhighlight lang="cpp"> uniformFS->SetFloatArray(d3dd, "material.ambient", (FLOAT*)&r.ambient, 4); uniformFS->SetFloatArray(d3dd, "material.diffuse", (FLOAT*)&r.diffuse, 4); uniformFS->SetFloatArray(d3dd, "material.specular", (FLOAT*)&r.specular, 4); uniformFS->SetFloat (d3dd, "material.power", (FLOAT)r.power);</syntaxhighlight>: APIDisplay.cpp - release()<syntaxhighlight lang="cpp"> } if (uniformFS) { uniformFS->Release(); uniformFS = nullptr; } if (fragmentShader) { fragmentShader->Release(); fragmentShader = nullptr; }</syntaxhighlight>: APIGraphic.cpp - APIXMesh: Shape:draw()<syntaxhighlight lang="cpp"> uniformFS->SetFloatArray(d3dd, "material.ambient", (FLOAT*)&ambient[i], 4); uniformFS->SetFloatArray(d3dd, "material.diffuse", (FLOAT*)&diffuse[i], 4); uniformFS->SetFloatArray(d3dd, "material.specular", (FLOAT*)&specular[i], 4); uniformFS->SetFloat(d3dd, "material.power", (FLOAT)power[i]);</syntaxhighlight>:: [http://msdn.microsoft.com/en-us/library/windows/desktop/bb205774%28v=vs.85%29.aspx ID3DXConstantTable::SetFloat()]: Shape APILight.cpp - setup()<syntaxhighlight lang="cpp"> uniformFS->SetInt(d3dd, typ, type); uniformFS->SetFloatArray(d3dd, amb, (FLOAT*)&ambient, 4); uniformFS->SetFloatArray(d3dd, dif, (FLOAT*)&diffuse, 4); uniformFS->SetFloatArray(d3dd, spe, (FLOAT*)&specular, 4); uniformFS->SetFloatArray(d3dd, pos, (FLOAT*)&zero, 3); uniformFS->SetFloatArray(d3dd, dir, (FLOAT*)&zero, 3); uniformFS->SetFloatArray(d3dd, att, (FLOAT*)&attenuation, 3); uniformFS->SetFloatArray(d3dd, spt, (FLOAT*)&spot, 3); uniformFS->SetFloat(d3dd, ran, range);</syntaxhighlight>: FrameAPILight.cpp - turnOn()<syntaxhighlight lang="cpp"> uniformFS->SetFloatArray(d3dd, pos, (FLOAT*)&p, 3); uniformFS->SetFloatArray(d3dd, dir, (FLOAT*)&o, 3); uniformFS->SetBool(d3dd, constantLightOn, true);</syntaxhighlight><syntaxhighlight lang="cpp"> uniformFS->SetFloatArray(d3dd, pos, (FLOAT*)&p, 3); uniformFS->SetFloatArray(d3dd, dir, (FLOAT*)&o, 3); uniformFS->SetBool(d3dd, constantLightOn, true);</syntaxhighlight>:APILight.cpp - update()<syntaxhighlight lang="cpp"> uniformFS->SetFloatArray(d3dd, pos, (FLOAT*)&p, 3); uniformFS->SetFloatArray(d3dd, dir, (FLOAT*)&o, 3); uniformFS->SetBool(d3dd, constantLightOn, true);</syntaxhighlight>: ShapeAPILight.cpp - turnOff()<syntaxhighlight lang="cpp"> uniformFS->SetBool(d3dd, constantLightOn, false);</syntaxhighlight>:APITexture.cpp - attach()<syntaxhighlight lang="cpp"> char str[] = "texOn"; uniformFS->SetBool(d3dd, str, true);</syntaxhighlight>:setRadiusAPITexture.cpp - detach()<syntaxhighlight lang="cpp"> char str[] = "texOn"; uniformFS->SetBool(d3dd, str, false);</syntaxhighlight>*Device:vertexShader.hlsl - Constant Memory<syntaxhighlight lang="cpp">// Types//// RawVertex holds the original data for a vertex in the stream//struct RawVertex {  float3 position : ShapeePOSITION; // position in local space float3 normal :NORMAL; // normal in local space float2 texCoord :getRadiusTEXCOORD0; // texture coordinates}; // TransformedVertex holds the transformed data for the vertex//struct TransformedVertex {  float4 position : POSITION; // position in homogeneous clip space float2 texCoord : TEXCOORD; // texture coordinates float3 worldPos : TEXCOORD1; // position in world space float3 worldNor : TEXCOORD2; // lighting normal in world space float3 toViewer : TEXCOORD3; // direction to viewer in world space}; // Uniform Data (constant for the stream of vertices)//// Geometryfloat4x4 viewProjection; // view * projection transformationfloat4x4 world; // world transformationfloat3 viewPoint; // camera viewpoint for specular calcs// Lit Vertexbool litVertex; // omit lighting calculations - already lit </syntaxhighlight>: vertexShader.hlsl - vertexShader()<syntaxhighlight lang="cpp">// vertexShader receives a raw data for a vertex and transforms that data//TransformedVertex vertexShader(RawVertex raw) {  TransformedVertex transformed; // result returned by this function float4 worldPosition; // world position of the vertex float3 worldNormal; // vertex normal in world space  // Transform the vertex to homogeneous clip coordinates // // A more efficient algorithm would accept the world*view*projection // tranformation as one uniform matrix and avoid the 2-stage product // This will require a bit of restructuring of the application code. // worldPosition = mul(float4(raw.position, 1.0), world); // local to world transformed.position = mul(worldPosition, viewProjection); //... to clip transformed.worldPos = worldPosition.xyz;  // Transform the vertex normal to world space. Only the rotation-scaling // part of the world transformation is used. Since the world // transformation may contain scaling, the result of this multiplication // needs to be normalized. // worldNormal = mul(raw.normal, (float3x3)world); worldNormal = normalize(worldNormal); transformed.worldNor = worldNormal; // Determine the direction from the camera's viewpoint to this vertex for // subsequent lighting calculations // transformed.toViewer = normalize(viewPoint - worldPosition.xyz); // pass the texture coordinates along unaltered // transformed.texCoord = raw.texCoord;  return transformed;}</syntaxhighlight>: fragmentShader.hlsl - Constant Memory<syntaxhighlight lang="cpp">#define MLIGHTS 4#define MTEXTURES 2#define POINT_LIGHT 0#define SPOT_LIGHT 1#define DIRECTIONAL_LIGHT 2 // Types//// Light holds the data for a single static light in world space//struct Light { int type; // POINT_LIGHT, SPOT_LIGHT, DIRECTIONAL_LIGHT float4 ambient; float4 diffuse; float4 specular; float3 direction; // in world space float3 position; // in world space float3 attenuation; // .xyz for 1.0f/ (.x + .y * d + .z * d * d) float3 spot; // .x = cos(phi/2), .y = cos(theta/2), .z = falloff float range; // where attenuation becomes 0}; // Material holds the reflectivity properties of the material//struct Material { float4 ambient; float4 diffuse; float4 specular; float power;}; // RawPixel holds the data for a single fragment of the stream//struct RawPixel { float2 texcoord : TEXCOORD0; // texture coordinate at this fragment float3 position : TEXCOORD1; // fragment position in world space float3 normal : TEXCOORD2; // lighting normal in world space float3 toViewer : TEXCOORD3; // direction to viewer in world space}; // Uniform Data (constant for a stream of fragments)//float4 ambient; // global ambient light -always onint noLights; // no of active lightsLight light[MLIGHTS]; // static lightsbool lightOn[MLIGHTS]; // light switchMaterial material; // material reflectivitybool lighting; // lighting calculations on? bool texOn; // texture switchsampler2D tex; // set by the application </syntaxhighlight>: fragmentShader.hlsl -fragmentShader()<syntaxhighlight lang="cpp">// The fragment shader receives raw fragment data and returns a pixel colour//float4 fragmentShader(RawPixel raw) : COLOR {  float4 colour; // result returned by this function float3 normal; // normal to the fragment float3 toViewer; // from fragment to the camera float3 toLightSource; // from fragment to current light source // lighting contribution accumulators float3 ambientLight = ambient.xyz; float3 diffuseLight = (float3)0; float3 specularLight = (float3)0; // lighting calculation factors float diffuseFactor, reflectFactor, distance; float attenuationFactor, spotFactor, rho; // normalize the fragment data normal = normalize(raw.normal); toViewer = normalize(raw.toViewer); // perform calculations for each light in turn for (int i = 0; i < noLights && i < MLIGHTS; i++) { if (lightOn[i]) { float diffuseFactor, reflectFactor, factor; // diffuse and reflection factors toLightSource = normalize((light[i].type == POINT_LIGHT)? light[i].position - raw.position : - light[i].direction); diffuseFactor = saturate(dot(normal, toLightSource)); reflectFactor = saturate(dot(normalize(2 * diffuseFactor * normal - toLightSource), toViewer));  attenuationFactor = 1.0f; spotFactor = 1.0f; if (light[i].type == POINT_LIGHT || light[i].type == SPOT_LIGHT) { // detail calcs for attenuationFactor and spotFactor distance = length(raw.position - light[i].position); if (distance < light[i].range) { attenuationFactor = light[i].attenuation.x + light[i].attenuation.y * distance + light[i].attenuation.z * distance * distance; attenuationFactor = 1.0f / attenuationFactor; if (light[i].type == SPOT_LIGHT) { rho = saturate(dot(normalize(light[i].position - float3(raw.position.x, raw.position.y, raw.position.z)), normalize(-light[i].direction))); if (rho <= light[i].spot.x) spotFactor = 0.0f; else if (rho <= light[i].spot.y) spotFactor = pow(abs( (rho - light[i].spot.x)/ (light[i].spot.y - light[i].spot.x)), light[i].spot.z); } } else attenuationFactor = 0.0f; }  // accumulate ambient, diffuse, and specular elements of light // ambientLight += attenuationFactor * spotFactor * light[i].ambient.xyz; diffuseLight += attenuationFactor * spotFactor * diffuseFactor * light[i].diffuse.xyz; specularLight += attenuationFactor * spotFactor * light[i].specular.xyz * pow(reflectFactor, material.power); } // apply material reflectivity to each accumulated element of light // to obtain the colour of the lit fragment // colour.xyz = saturate(material.ambient.xyz * ambientLight) + saturate(material.diffuse.xyz * diffuseLight) + saturate(material.specular.xyz * specularLight); colour.w = material.diffuse.w; }  // apply texture // if (texOn) colour *= tex2D(tex, raw.texcoord);
return colour;
}
</syntaxhighlight>
=== To Do ===
* Form Teamsreorganize framework code so that vertex shader receives product of world, Identify Members view, and projection matrices** store viewProjection matrix as an instance variable in APIDisplay** pre-multiply viewProjection by world to obtain composite matrix to pass to vertex shader** add composite matrix to the constant table in the vertex shader* reorganize framework code to minimize duplication of heading normalization** perform normalization of heading in APIDisplay::beginDrawFrame() === Resources === == Week 7 - Feb 20 ===== This Week ===* Effects Framework** techniques*: passes* Source Code: APIBase.h<syntaxhighlight lang="cpp"> static ID3DXEffect* effect; // points to effects framework</syntaxhighlight>: APIBase.cpp<syntaxhighlight lang="cpp">ID3DXEffect* APIBase::effect = nullptr; // effects framework</syntaxhighlight>: APIDisplay.h<syntaxhighlight lang="cpp"> // Effects Framework handles D3DXHANDLE viewProjection; // view * projection D3DXHANDLE viewPoint; // camera viewpoint D3DXHANDLE ambient; // global ambient color D3DXHANDLE ambientHandle; // current ambient reflectivity D3DXHANDLE diffuseHandle; // current diffuse reflectivity D3DXHANDLE specularHandle; // current specular reflectivity D3DXHANDLE powerHandle; // current shininess coefficient D3DXHANDLE worldHandle; // current world transformation</syntaxhighlight><syntaxhighlight lang="cpp"> void beginEffect(const char*, unsigned&); void beginPass(unsigned); void endPass(); void endEffect(2);</syntaxhighlight>: APIDisplay.cpp - APIDisplay()<syntaxhighlight lang="cpp"> viewProjection = nullptr; viewPoint = nullptr; ambient = nullptr; ambientHandle = nullptr; diffuseHandle = nullptr; specularHandle = nullptr; powerHandle = nullptr; worldHandle = nullptr;</syntaxhighlight>: APIDisplay.cpp -5 memberssetup() and add your team and members <syntaxhighlight lang="cpp"> LPD3DXBUFFER errorBuffer = NULL;</syntaxhighlight><syntaxhighlight lang="cpp"> // create the effects framework else if (FAILED(D3DXCreateEffectFromFile(d3dd, EFFECT_FILE, 0, 0, D3DXSHADER_DEBUG, 0, &effect, &errorBuffer))) { release(); error(L"APIDisplay::17 Unable to create the effects framework"); }</syntaxhighlight>:: [http://msdn.microsoft.com/en-us/library/windows/desktop/bb172768%28v=vs.85%29.aspx D3DXCreateEffectFromFile()]<syntaxhighlight lang="cpp"> if (errorBuffer) errorBuffer->Release(); viewProjection = effect->GetParameterByName(0, "viewProjection"); viewPoint = effect->GetParameterByName(0, "viewPoint"); ambient = effect->GetParameterByName(0, "ambient"); worldHandle = effect->GetParameterByName(0, "world"); ambientHandle = effect->GetParameterByName(0, "material.ambient"); diffuseHandle = effect->GetParameterByName(0, "material.diffuse"); specularHandle = effect->GetParameterByName(0, "material.specular"); powerHandle = effect->GetParameterByName(0, "material.power");</syntaxhighlight>:: [GAM670http://msdn.microsoft.com/en-us/DPS905 Teams 20111 | Teams 20111library/windows/desktop/bb205696%28v=vs.85%29.aspx GetParameterByName()]: APIDisplay.cpp - beginDrawFrame()<syntaxhighlight lang="cpp"> Matrix& v = *((Matrix*)view); Matrix viewprojection = v * projection; Vector heading(v.m13, v.m23, v.m33); effect->SetMatrix(viewProjection, (D3DXMATRIX*)&viewprojection); effect->SetVector(viewPoint, (D3DXVECTOR4*)&heading);</syntaxhighlight>:: [http://msdn.microsoft.com/en-us/library/windows/desktop/bb205720%28v=vs.85%29.aspx SetMatrix()] ''' Before Thursday 20th''':: [http://msdn.microsoft.com/en-us/library/windows/desktop/bb205729%28v=vs.85%29.aspx SetVector()]<syntaxhighlight lang="cpp"> Colour colour(red, green, blue); effect->SetVector(ambient, (D3DXVECTOR4*)&colour);</syntaxhighlight>: APIDisplay.cpp - beginEffect()<syntaxhighlight lang="cpp">void APIDisplay::beginEffect(const char* Confirm your name and information at technique, unsigned& nPasses) {  D3DXHANDLE techniqueHandle = effect->GetTechniqueByName(technique); effect->SetTechnique(techniqueHandle); effect->Begin(&nPasses, 0);}</syntaxhighlight>:: [http://msdn.microsoft.com/en-us/library/windows/desktop/bb205706%28v=vs.85%29.aspx GetTechniqueByName()]:: [http://msdn.microsoft.com/en-us/library/windows/desktop/bb205834%28v=vs.85%29.aspx SetTechnique()]:: [http://msdn.microsoft.com/en-us/library/windows/desktop/bb205815%28v=vs.85%29.aspx Begin()]: APIDisplay.cpp - beginPass()<syntaxhighlight lang="cpp">void APIDisplay::beginPass(unsigned i) {  effect->BeginPass(i);}</syntaxhighlight>:: [http://msdn.microsoft.com/en-us/library/windows/desktop/bb205817%28v=vs.85%29.aspx BeginPass()]: APIDisplay.cpp - endPass()<syntaxhighlight lang="cpp">void APIDisplay::endPass() {  effect->EndPass();}</syntaxhighlight>:: [http://msdn.microsoft.com/en-us/library/windows/desktop/bb205823%28v=vs.85%29.aspx EndPass()]: APIDisplay.cpp - endEffect()<syntaxhighlight lang="cpp">void APIDisplay::endEffect() {  effect->End();}</syntaxhighlight>:: [http://msdn.microsoft.com/en-us/library/windows/desktop/bb205821%28v=vs.85%29.aspx End()]: APIDisplay.cpp - setWorld()<syntaxhighlight lang="cpp"> effect->SetMatrix(worldHandle, (D3DXMATRIX*)world);</syntaxhighlight>: APIDisplay.cpp - setReflectivity()<syntaxhighlight lang="cpp"> effect->SetVector(ambientHandle, (D3DXVECTOR4*)&r.ambient); effect->SetVector(diffuseHandle, (D3DXVECTOR4*)&r.diffuse); effect->SetVector(specularHandle, (D3DXVECTOR4*)&r.specular); effect->SetFloat(powerHandle, r.power); effect->CommitChanges();</syntaxhighlight>:: [GAM670http://msdn.microsoft.com/en-us/library/windows/desktop/DPS905Student List 20111 | Student List 20111bb205819%28v=vs.85%29.aspx CommitChanges()]: APIDisplay.cpp - release()<syntaxhighlight lang="cpp"> if (effect) { effect->Release(); effect = NULL; }</syntaxhighlight>: effects.fx - Constant Memory<syntaxhighlight lang="cpp">#define MLIGHTS 4#define POINT_LIGHT 0#define SPOT_LIGHT 1#define DIRECTIONAL_LIGHT 2 // Types//// Light holds the data for a single static light in world space//struct Light { int type; // POINT_LIGHT, SPOT_LIGHT, DIRECTIONAL_LIGHT float3 ambient; float3 diffuse; float3 specular; float3 direction; // in world space float3 position; // in world space float3 attenuation; // .xyz for 1.0f/ (.x + .y * d + .z * d * d) float3 spot; // .x = cos(phi/2), .y = cos(theta/2), .z = falloff float range; // where attenuation becomes 0}; // Material holds the reflectivity properties of the material//struct Material { float4 ambient; float4 diffuse; float4 specular; float power;}; // RawPixel holds the data for a single fragment of the stream//struct RawPixel { float2 texcoord : TEXCOORD0; // texture coordinate at this fragment float3 position : TEXCOORD1; // fragment position in world space float3 normal : TEXCOORD2; // lighting normal in world space float3 toViewer : TEXCOORD3; // direction to viewer in world space}; // Uniform Data (constant for a stream of fragments)//float4 ambient; // global ambient light - always onint noLights; // no of static lightsLight light[MLIGHTS]; // static lightsbool lightOn[MLIGHTS]; // light switchMaterial material; // material reflectivity bool texOn; // texture switchsampler2D tex; // set by the application // Types//// RawVertex holds the original data for a vertex in the stream//struct RawVertex {  float3 position : POSITION; // position in local space float3 normal : NORMAL; // normal in local space float2 texCoord : TEXCOORD0; // texture coordinates}; // TransformedVertex holds the transformed data for the vertex//struct TransformedVertex {  float4 position : POSITION; // position in homogeneous clip space float2 texCoord : TEXCOORD; // texture coordinates float3 worldPos : TEXCOORD1; // position in world space float3 worldNor : TEXCOORD2; // lighting normal in world space float3 toViewer : TEXCOORD3; // direction to viewer in world space}; // Uniform Data (constant for the stream of vertices)//// Geometryfloat4x4 viewProjection; // view * projection transformationfloat4x4 world; // world transformationfloat4 viewPoint; // camera viewpoint for specular calcs// Geometryfloat3 heading; // camera heading for specular calcs// Lit Vertexbool litVertex; // omit lighting calculations - already lit </syntaxhighlight>: effects.fx - VertexShader<syntaxhighlight lang="cpp">// vertexShader receives a raw data for a vertex and transforms that data//TransformedVertex vertexShader(RawVertex raw) {  TransformedVertex transformed; // result returned by this function float4 worldPosition; // world position of the vertex float3 worldNormal; // vertex normal in world space  // Transform the vertex to homogeneous clip coordinates // // A more efficient algorithm would accept the world*view*projection // tranformation as one uniform matrix and avoid the 2-stage product // This will require a bit of restructuring of the application code. // worldPosition = mul(float4(raw.position, 1.0), world); // local to world transformed.position = mul(worldPosition, viewProjection); //... to clip transformed.worldPos = worldPosition.xyz;  // Transform the vertex normal to world space. Only the rotation-scaling // part of the world transformation is used. Since the world // transformation may contain scaling, the result of this multiplication // needs to be normalized. // worldNormal = mul(raw.normal, (float3x3)world); worldNormal = normalize(worldNormal); transformed.worldNor = worldNormal; // Determine the direction from the camera's viewpoint to this vertex for // subsequent lighting calculations // transformed.toViewer = normalize(viewPoint - worldPosition.xyz); // pass the texture coordinates along unaltered // transformed.texCoord = raw.texCoord;  return transformed;}
</syntaxhighlight>
: effects.fx - FragmentShader
<syntaxhighlight lang="cpp">
// The fragment shader receives raw fragment data and returns a pixel colour
//
float4 fragmentShader(RawPixel raw) : COLOR {
 
float4 colour; // result returned by this function
float3 normal; // normal to the fragment
float3 toViewer; // from fragment to the camera
float3 toLightSource; // from fragment to current light source
// lighting contribution accumulators
float3 ambientLight = ambient.xyz;
float3 diffuseLight = (float3)0;
float3 specularLight = (float3)0;
// lighting calculation factors
float diffuseFactor, reflectFactor, distance;
float attenuationFactor, spotFactor, rho;
// normalize the fragment data
normal = normalize(raw.normal);
toViewer = normalize(raw.toViewer);
// perform calculations for each light in turn
for (int i = 0; i < noLights && i < MLIGHTS; i++) {
if (lightOn[i]) {
float diffuseFactor, reflectFactor, factor;
// diffuse and reflection factors
toLightSource = normalize((light[i].type == POINT_LIGHT)?
light[i].position - raw.position : - light[i].direction);
diffuseFactor = saturate(dot(normal, toLightSource));
reflectFactor = saturate(dot(normalize(2 * diffuseFactor *
normal - toLightSource), toViewer));
 
attenuationFactor = 1.0f;
spotFactor = 1.0f;
if (light[i].type == POINT_LIGHT ||
light[i].type == SPOT_LIGHT) {
// detail calcs for attenuationFactor and spotFactor
distance = length(raw.position - light[i].position);
if (distance < light[i].range) {
attenuationFactor = light[i].attenuation.x +
light[i].attenuation.y * distance +
light[i].attenuation.z * distance * distance;
attenuationFactor = 1.0f / attenuationFactor;
if (light[i].type == SPOT_LIGHT) {
rho = saturate(dot(normalize(light[i].position -
float3(raw.position.x, raw.position.y,
raw.position.z)),
normalize(-light[i].direction)));
if (rho <= light[i].spot.x)
spotFactor = 0.0f;
else if (rho <= light[i].spot.y)
spotFactor = pow(abs(
(rho - light[i].spot.x)/
(light[i].spot.y - light[i].spot.x)),
light[i].spot.z);
}
}
else
attenuationFactor = 0.0f;
}
 
// accumulate ambient, diffuse, and specular elements of light
//
ambientLight += attenuationFactor * spotFactor *
light[i].ambient.xyz;
diffuseLight += attenuationFactor * spotFactor * diffuseFactor *
light[i].diffuse.xyz;
specularLight += attenuationFactor * spotFactor *
light[i].specular.xyz * pow(reflectFactor, material.power);
}
}
// apply material reflectivity to each accumulated element of light
// to obtain the colour of the lit fragment
//
colour.xyz =
saturate(material.ambient.xyz * ambientLight) +
saturate(material.diffuse.xyz * diffuseLight) +
saturate(material.specular.xyz * specularLight);
colour.w = material.diffuse.w;
 
// apply texture
//
if (texOn)
colour *= tex2D(tex, raw.texcoord);
 
return colour;
}
</syntaxhighlight>
: effects.fx - technique opaque
<syntaxhighlight lang="cpp">
technique opaque {
pass {
VertexShader = compile vs_3_0 vertexShader();
PixelShader = compile ps_3_0 fragmentShader();
}
}
 
</syntaxhighlight>
: effects.fx - technique translucent
<syntaxhighlight lang="cpp">
technique translucent {
pass {
VertexShader = compile vs_3_0 vertexShader();
PixelShader = compile ps_3_0 fragmentShader();
}
}
</syntaxhighlight>
<syntaxhighlight lang="cpp">
</syntaxhighlight>
=== To Do ===
=== Resources ===
== Week 3 8 - Jan 23 Mar 4 ==
=== This Week ===
* Frank Luna's notes for DirectX10 (page 306)
:[http://books.google.ca/books?id=AyACb-t8E-MC&pg=PA306&lpg=PA306#v=onepage&q&f=false Environment Maps](Google books)
:[http://libcat.senecac.on.ca/vwebv/holdingsInfo?searchId=19588&recCount=50&recPointer=2&bibId=261220 Environment Maps](Seneca ELibraray)
* Design.cpp
: Design::initialize() - create the skybox object
<syntaxhighlight lang="cpp">
// initialize initializes the general display design coordinator, creates the
// primitive sets, textures, objects, lights, sounds, cameras, and text items
//
void Design::initialize() {
 
// ...
 
// create textures
iTexture* sunset = CreateCubeTexture(L"Islands.dds");
 
// ...
 
iObject* skybox = CreateSkybox();
skybox->rotatex(-1.5708f);
skybox->attach(sunset);
setSkybox(skybox);
 
// ...
}
</syntaxhighlight>
* Coordinator.cpp
: Coordinator::render() - using different techniques for different objects
<syntaxhighlight lang="cpp">
void Coordinator::render() {
 
// adjust framecount and fps
if (now - lastReset <= unitsPerSec)
framecount++;
else {
// recalculate the frame rate
fps = framecount * unitsPerSec / (now - lastReset);
framecount = 0;
lastReset = now;
if (timerText) {
wchar_t str[MAX_DESC + 1];
sprintf(str, fps, L" fps");
timerText->set(str);
}
}
// update the user input devices
userInput->update();
Coordinator::update();
// update the model
update();
// update the audio
audio->setVolume(volume);
audio->setFrequencyRatio(frequency);
audio->update(Camera::getView());
 
// start rendering
display->beginDrawFrame(Camera::getView());
display->setAmbientLight(ambient.r, ambient.g, ambient.b);
unsigned nPasses;
// render all of the opaque unlit objects
display->beginEffect("opaque", nPasses);
for (unsigned i = 0; i < nPasses; i++) {
display->beginPass(i);
render(OPAQUE_OBJECT);
display->endPass();
}
display->endEffect();
// render all of the translucent unlit objects
display->beginEffect("translucent", nPasses);
for (unsigned i = 0; i < nPasses; i++) {
display->beginPass(i);
render(TRANSLUCENT_OBJECT);
display->endPass();
}
display->endEffect();
// render all of the lit objects
display->beginEffect("litObjects", nPasses);
for (unsigned i = 0; i < nPasses; i++) {
display->beginPass(i);
render(LIT_OBJECT);
display->endPass();
}
display->endEffect();
// render the skybox
display->beginEffect("skybox", nPasses);
if (background && !skybox) {
Rectf fullScreen(0, 0, 1, 1);
display->beginDrawHUD(0);
background->render(fullScreen, true);
display->endDrawHUD();
}
else if (skybox) {
for (unsigned i = 0; i < nPasses; i++) {
display->beginPass(i);
render(SKYBOX);
display->endPass();
}
}
display->endEffect();
display->set(ALPHA_BLEND, false);
display->beginDrawHUD(HUD_ALPHA);
render(ALL_HUDS);
display->endDrawHUD();
display->endDrawFrame();
render(ALL_SOUNDS);
}
</syntaxhighlight>
: Coordinator::render(iObject*) - render a single object one subset at a time
<syntaxhighlight lang="cpp">
void Coordinator::render(iObject* object) {
 
display->setWorld(&object->world());
unsigned nSubsets = object->noSubsets();
for (unsigned i = 0; i < nSubsets; i++) {
iTexture* texture = object->getTexture(i);
if (texture) texture->attach();
display->setReflectivity(object->getReflectivity(i));
object->render(i);
if (texture) texture->detach();
}
}
</syntaxhighlight>
* Skybox class
: iObject interface - CreateSkybox declaration
<syntaxhighlight lang="cpp">
class iObject : public Shape, public Base {
public:
// initialization
virtual void attach(iTexture* t) = 0;
virtual void attach(iTexture** t) = 0;
// execution
virtual unsigned noSubsets() const = 0;
virtual void render(unsigned) = 0;
virtual void setTextureFilter(unsigned) = 0;
virtual iTexture* getTexture(unsigned) const = 0;
virtual const void* getReflectivity(unsigned) const = 0;
virtual bool belongsTo(Category category) const = 0;
};
 
iObject* CreateObject(iGraphic*, const Reflectivity* = nullptr, unsigned = 1u);
iObject* CreateBillboard(BillboardType, iGraphic*,
const Reflectivity* = nullptr);
iObject* CreateSkybox();
 
iObject* Clone(const iObject*);
</syntaxhighlight>
: Skybox class - derived from Object
<syntaxhighlight lang="cpp">
//-------------------------------- Skybox -------------------------------------
//
// A Skybox is an inverted Object that translates with the viewpoint
//
class Skybox : public Object {
 
public:
Skybox();
void render(unsigned);
};
</syntaxhighlight>
: CreateSkybox
<syntaxhighlight lang="cpp">
iObject* CreateSkybox() {
 
return new Skybox();
}
</syntaxhighlight>
: Skybox::Skybox - SKYBOX category, 2 x 2 x 2 cube
<syntaxhighlight lang="cpp">
Skybox::Skybox() : Object(SKYBOX, CreateIBox(-1, -1, -1 * MODEL_Z_AXIS, 1, 1,
1 * MODEL_Z_AXIS)) {
}
</syntaxhighlight>
: Skybox::render(unsigned) - move skybox centroid to current camera position
<syntaxhighlight lang="cpp">
void Skybox::render(unsigned) {
 
Camera* camera = *(Camera**)(Camera::getCurrent());
Vector disp = camera->position() - position();
translate(disp.x, disp.y, disp.z);
 
Object::render(0);
}
</syntaxhighlight>
* Texture class
: iTexture interface - CreateCubeTexture declaration
<syntaxhighlight lang="cpp">
class iTexture : public Base {
public:
virtual void attach() const = 0;
virtual void setFilter(unsigned) const = 0;
virtual void detach() = 0;
virtual void render(const Rectf&, bool = false) = 0;
};
 
iTexture* CreateTexture(const wchar_t* file, unsigned filter = 0);
iTexture* CreateCubeTexture(const wchar_t* file, unsigned filter = 0);
 
iTexture* Clone(const iTexture*);
</syntaxhighlight>
: Texture class - add the cube parameter to constructor
<syntaxhighlight lang="cpp">
class Texture : public iTexture {
 
iAPITexture* apiTexture; // points to the api texture
 
Texture(const Texture&);
virtual ~Texture();
 
public:
Texture(const wchar_t* file, unsigned filter = 0, bool cube = false);
Texture& operator=(const Texture&);
void* clone() const { return new Texture(*this); }
// execution
void attach() const;
void setFilter(unsigned) const;
void detach();
void render(const Rectf&, bool);
// termination
void suspend();
void release();
};</syntaxhighlight>
: CreateCubeTexture - call constructor with true flag for cube
<syntaxhighlight lang="cpp">
iTexture* CreateCubeTexture(const wchar_t* file, unsigned filter) {
 
return new Texture(file, filter, true);
}
</syntaxhighlight>
: Texture::Texture() - create APICubeTexture()
<syntaxhighlight lang="cpp">
Texture::Texture(const wchar_t* file, unsigned filter, bool cube) {
 
coordinator->add(this);
 
wchar_t* fileWithPath = nullptr;
if (file) {
// add the directory to create the relative filename
int len = strlen(file) + strlen(TEXTURE_DIRECTORY) + 1;
fileWithPath = new wchar_t[len + 1];
::nameWithDir(fileWithPath, TEXTURE_DIRECTORY, file, len);
}
 
// apiTexture on the graphics device
if (cube)
apiTexture = CreateAPICubeTexture(fileWithPath);
else
apiTexture = CreateAPITexture(fileWithPath, filter);
 
if (fileWithPath) delete [] fileWithPath;
}
</syntaxhighlight>
: iAPITexture interface - add CreateAPICubeTexture declaration
<syntaxhighlight lang="cpp">
class iAPITexture {
public:
virtual iAPITexture* clone() const = 0;
// execution
virtual void attach() = 0;
virtual void setFilter(unsigned flags) = 0;
virtual void detach() = 0;
virtual void render(const Rectf&, unsigned char, bool = false) = 0;
// termination
virtual void suspend() = 0;
virtual void release() = 0;
virtual void Delete() const = 0;
};
 
iAPITexture* CreateAPITexture(const wchar_t* file, unsigned filter);
iAPITexture* CreateAPICubeTexture(const wchar_t* file);
</syntaxhighlight>
* APITexture.h
: APICubeTexture class definition
<syntaxhighlight lang="cpp">
class APICubeTexture : public iAPITexture, public APIBase {
 
wchar_t* file; // points to file with texture image
unsigned filter; // default texture filtering flags
 
IDirect3DCubeTexture9* tex; // interface to texture COM object
 
virtual ~APICubeTexture();
 
void setup();
 
public:
APICubeTexture(const wchar_t* file);
APICubeTexture(const APICubeTexture&);
iAPITexture& operator=(const APICubeTexture&);
iAPITexture* clone() const { return new APICubeTexture(*this); }
// execution
void attach();
void setFilter(unsigned filter) {}
void detach();
void render(const Rectf&, unsigned char, bool) {}
// suspension
void suspend();
// termination
void release();
void Delete() const { delete this; }
};
</syntaxhighlight>
:: [http://msdn.microsoft.com/en-us/library/windows/desktop/bb174329%28v=vs.85%29.aspx IDirect3DCubeTexture9 interface]
: APICubeTexture class implementation
<syntaxhighlight lang="cpp">
//-------------------------------- APICubeTexture -----------------------------
//
// The APICubeTexture class implements a texture at the API level
//
iAPITexture* CreateAPICubeTexture(const wchar_t* file) {
 
return new APICubeTexture(file);
}
 
// constructor initializes the texture identifier
//
APICubeTexture::APICubeTexture(const wchar_t* file) {
 
if (file) {
int len = strlen(file);
this->file = new wchar_t[len + 1];
strcpy(this->file, file, len);
}
else
this->file = nullptr;
 
tex = nullptr;
}
 
APICubeTexture::APICubeTexture(const APICubeTexture& src) {
 
file = nullptr;
tex = nullptr;
*this = src;
}
 
iAPITexture& APICubeTexture::operator=(const APICubeTexture& src) {
 
if (this != &src) {
if (file)
delete [] file;
if (src.file) {
int len = strlen(src.file);
file = new wchar_t[len + 1];
strcpy(file, src.file, len);
}
else
file = nullptr;
suspend();
tex = nullptr;
}
 
return *this;
}
 
// setup creates the api texture from the texture file
//
void APICubeTexture::setup() {
 
// create a texture COM object from the texture file
//
HRESULT hr;
if (file && FAILED(hr = D3DXCreateCubeTextureFromFileEx(d3dd, file,
0, D3DX_DEFAULT, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, D3DX_DEFAULT,
D3DX_DEFAULT, 0, nullptr, nullptr, &tex))) {
error(L"APICubeTexture::11 Failed to create texture COM object from file");
tex = nullptr;
}
}
 
// attach attaches the api texture to sampling stage i
//
void APICubeTexture::attach() {
 
if (!tex) setup();
 
if (tex)
d3dd->SetTexture(0, tex);
}
 
// detach detaches the api texture from sampling stage 0
//
void APICubeTexture::detach() {
 
if (tex)
d3dd->SetTexture(0, nullptr);
}
 
// suspend releases the api texture
//
void APICubeTexture::suspend() {
 
// release the Interface to the texture COM object
if (tex) {
tex->Release();
tex = nullptr;
}
}
 
// releases suspends the api texture
//
void APICubeTexture::release() {
 
suspend();
}
 
// destructor releases the api texture
//
APICubeTexture::~APICubeTexture() {
 
release();
}
</syntaxhighlight>
:: [http://msdn.microsoft.com/en-us/library/windows/desktop/bb172757%28v=vs.85%29.aspx D3DXCreateCubeTextureFromFileEx]
* effects.fx
: vertex shader outpu structure
<syntaxhighlight lang="cpp">
//-------------------------------- Skybox -------------------------------------
//
struct FS_Skybox {
float4 pos : POSITION;
float3 tex : TEXCOORD0;
};
</syntaxhighlight>
: vertex shader
<syntaxhighlight lang="cpp">
FS_Skybox skyboxVertexShader(float3 pos : POSITION) {
FS_Skybox output = (FS_Skybox) 0;
output.pos = mul(float4(pos, 0), world); // Note the 0, this so the skybox rotates, but without translation
output.pos = mul(output.pos, viewProjection).xyww; // The z coordinate is replaced by w, so that the point is always projected at infinity
output.tex = pos.xzy; // Note that y and z are switched to match the texture coordinate system
return output;
}
</syntaxhighlight>
: skybox sampler state
<syntaxhighlight lang="cpp">
texture skyBox;
samplerCUBE skySampler = sampler_state {
texture = <skyBox>;
MagFilter = LINEAR;
Minfilter = LINEAR;
Mipfilter = LINEAR;
AddressU = MIRROR;
AddressV = MIRROR;
AddressW = MIRROR;
};
</syntaxhighlight>
: fragment shader
<syntaxhighlight lang="cpp">
float4 skyboxFragmentShader(FS_Skybox input) : COLOR0 {
return texCUBE(skySampler, input.tex);
}
</syntaxhighlight>
: skybox technique
<syntaxhighlight lang="cpp">
technique skybox {
 
pass {
AlphaBlendEnable = false;
ZENABLE = true;
ZWRITEENABLE = false; // By not storing the skybox's z-buffer value, it enables objects behind the skybox to be drawn, giving a realist look (e.g. an airplane in the distance)
CullMode = None;
VertexShader = compile vs_3_0 skyboxVertexShader();
PixelShader = compile ps_3_0 skyboxFragmentShader();
}
}
</syntaxhighlight>
 
=== To Do ===
=== Resources ===
* [http://wwwrbwhitaker.microsoftwikidot.com/downloadsskyboxes-1 RB Whitaker's notes on skyboxes]* [http:/en/detailsknol.aspx?FamilyID=3021d52bgoogle.com/k/3d-514eskybox# Koen Samyn's knol]* [http://www.gameengineer.net/samples-41d3graphics.html Game Engineer's demo]* [http://www.planetside.co.uk/terragen Terragen Texture Tool]* DirectX Utility -ad02-438a3ba730ba DirectX SDK June 2010]Texture Tool
 == Week 4 9 - Jan 30 Mar 11 ==
=== This Week ===
* [http://msdn.microsoft.com/en-us/library/bb147178%28v=VS.85%29.aspx Mathematics of Lighting]
* Vertex Shaders
* Lighting in Vertex Shaders
** Notation
*** [http://msdn.microsoft.com/en-us/library/bb509617%28v=vs.85%29.aspx length()] - length of a vector
*** [http://msdn.microsoft.com/en-us/library/bb509645%28v=vs.85%29.aspx saturate()] - clamp scalar, vector, or matrix to [0, 1]
* effects.fx - for unlit vertices and fragments
: Uniform data
<syntaxhighlight lang="cpp">
#define MLIGHTS 4
#define POINT_LIGHT 0
#define SPOT_LIGHT 1
#define DIRECTIONAL_LIGHT 2
 
// Types
//
// Light holds the data for a single static light in world space
//
struct Light {
int type; // POINT_LIGHT, SPOT_LIGHT, DIRECTIONAL_LIGHT
float3 ambient;
float3 diffuse;
float3 specular;
float3 direction; // in world space
float3 position; // in world space
float3 attenuation; // .xyz for 1.0f/ (.x + .y * d + .z * d * d)
float3 spot; // .x = cos(phi/2), .y = cos(theta/2), .z = falloff
float range; // where attenuation becomes 0
};
 
// Material holds the reflectivity properties of the material
//
struct Material {
float4 ambient;
float4 diffuse;
float4 specular;
float power;
};
 
// Uniform Data (constant for the stream of vertices)
//
// Geometry
float4x4 viewProjection; // view * projection transformation
float4x4 world; // world transformation
float4 viewPoint; // camera viewpoint for specular calcs
float3 heading; // camera heading for specular calcs
int noLights; // no of static lights
Light light[MLIGHTS]; // static lights
bool lightOn[MLIGHTS]; // light switch
 
// Uniform Data (constant for a stream of fragments)
//
float4 ambient; // global ambient light - always on
Material material; // material reflectivity
 
bool texOn; // texture switch
texture texMap;
sampler2D tex = sampler_state {
texture = <texMap>;
Filter = MIN_MAG_MIP_LINEAR;
AddressU = MIRROR;
AddressV = MIRROR;
};
</syntaxhighlight>
: Varying Data - simple unlit objects
<syntaxhighlight lang="cpp">
//-------------------------------- Simple Unlit Objects -----------------------
//
// UnlitInput holds the original data for a vertex in the stream
//
struct UnlitVSInput {
 
float3 position : POSITION; // position in local space
float3 normal : NORMAL; // normal in local space
float2 texCoord : TEXCOORD0; // texture coordinates
};
 
// UnlitOutput holds the transformed data for the vertex
//
struct UnlitVSOutput {
 
float4 position : POSITION; // position in homogeneous clip space
float2 texCoord : TEXCOORD; // texture coordinates
float3 normal : TEXCOORD1; // lighting normal in world space
float3 toViewer : TEXCOORD2; // direction to viewer in world space
float3 toLight[MLIGHTS] : TEXCOORD3; // light vector
};
 
// UnlitFSInput holds the input data for a single fragment of the stream
//
struct UnlitFSInput {
float2 texCoord : TEXCOORD0; // texture coordinate at this fragment
float3 normal : TEXCOORD1; // lighting normal in world space
float3 toViewer : TEXCOORD2; // direction to viewer in world space
float3 toLight[MLIGHTS] : TEXCOORD3; // direction from fragment to light i
};
</syntaxhighlight>
: Vertex Shader
<syntaxhighlight lang="cpp">
// unlitVShader transforms vertex and lighting data for simple unlit objects
//
UnlitVSOutput unlitVShader(UnlitVSInput input) {
 
UnlitVSOutput output; // result returned by this function
 
// Transform the vertex coordinates to homogeneous clip coordinates
//
// A more efficient algorithm would accept the world*view*projection
// tranformation as one uniform matrix and avoid the 2-stage product
// This will require a bit of restructuring of the application code.
//
output.position = mul(float4(input.position, 1.0), world); // local to world
output.position = mul(output.position, viewProjection); //... to clip
// Determine the vector from this vertex to the viewer
output.toViewer = viewPoint.xyz - input.position;
 
// Determine the vector from this vertex to light source i in local space
// (assumes that light position and direction are specified in local space)
for (int i = 0; i < noLights; i++)
if (light[i].type == DIRECTIONAL_LIGHT)
output.toLight[i] = - light[i].direction;
else
output.toLight[i] = light[i].position - input.position;
// pass the normal and texture coordinates along unaltered
//
output.normal = input.normal;
output.texCoord = input.texCoord;
 
return output;
}
 
</syntaxhighlight>
: Fragment Shader
<syntaxhighlight lang="cpp">
// This fragment shader processes lighting for noLights lights in object space
// and returns a pixel colour
//
float4 unlitFShader(UnlitFSInput input) : COLOR {
 
float4 output; // result returned by this function
float3 normal; // normal to the fragment
float3 toViewer; // from fragment to the camera
float3 toLightSource; // from fragment to current light source
// lighting contribution accumulators
float3 ambientLight = ambient.xyz;
float3 diffuseLight = (float3)0;
float3 specularLight = (float3)0;
// lighting calculation factors
float diffuseFactor, reflectFactor, distance, factor;
float attenuationFactor, spotFactor, rho;
// normalize the fragment input
normal = normalize(input.normal);
toViewer = normalize(input.toViewer);
// perform calculations for each light in turn
for (int i = 0; i < noLights && i < MLIGHTS; i++) {
if (lightOn[i]) {
// diffuse and reflection factors
toLightSource = normalize(input.toLight[i]);
diffuseFactor = saturate(dot(normal, toLightSource));
reflectFactor = saturate(dot(normalize(2 * diffuseFactor *
normal - toLightSource), toViewer));
 
// attenuation
if (light[i].type != DIRECTIONAL_LIGHT) {
distance = length(input.toLight[i]);
if (distance < light[i].range) {
attenuationFactor = light[i].attenuation.x +
light[i].attenuation.y * distance +
light[i].attenuation.z * distance * distance;
attenuationFactor = 1.0f / attenuationFactor;
}
else
attenuationFactor = 0.0f;
}
else
attenuationFactor = 1.0f;
 
// spot
if (light[i].type == SPOT_LIGHT) {
rho = saturate(dot(toLightSource,
normalize(-light[i].direction)));
if (rho <= light[i].spot.x)
spotFactor = 0.0f;
else if (rho <= light[i].spot.y)
spotFactor = pow(abs(
(rho - light[i].spot.x)/
(light[i].spot.y - light[i].spot.x)),
light[i].spot.z);
else
spotFactor = 1.0f;
}
else
spotFactor = 1.0;
 
factor = attenuationFactor * spotFactor;
 
// accumulate ambient, diffuse, and specular elements of light i
ambientLight += factor * light[i].ambient.xyz;
diffuseLight += factor * diffuseFactor * light[i].diffuse.xyz;
specularLight += factor * light[i].specular.xyz *
pow(reflectFactor, material.power);
}
}
// apply material reflectivity to each accumulated element of light
// to obtain the colour of the lit fragment
//
output.xyz =
saturate(material.ambient.xyz * ambientLight) +
saturate(material.diffuse.xyz * diffuseLight) +
saturate(material.specular.xyz * specularLight);
output.w = material.diffuse.w;
 
// sample the texture
//
if (texOn)
output *= tex2D(tex, input.texCoord);
 
return output;
}
</syntaxhighlight>
: techniques - opaque and translucent
<syntaxhighlight lang="cpp">
technique opaque {
pass {
AlphaBlendEnable = false;
VertexShader = compile vs_3_0 unlitVShader();
PixelShader = compile ps_3_0 unlitFShader();
}
}
</syntaxhighlight>
 
<syntaxhighlight lang="cpp">
technique translucent {
pass {
AlphaBlendEnable = true;
VertexShader = compile vs_3_0 unlitVShader();
PixelShader = compile ps_3_0 unlitFShader();
}
}
</syntaxhighlight>
 
=== To Do ===
* reorganize framework code so that vertex shader receives product of world, view, and projection matrices** store viewProjection matrix as an instance variable in Display** add viewProjection query to Display to extract product of view and projection matrices** retrieve viewProjection in *::draw() method** pre-multiply viewProjection by world to obtain composite matrix to pass to vertex shader** add composite matrix to the constant table in the vertex shader* reorganize framework code to minimize duplication of heading normalization** perform normalization of heading in Display::beginDraw()=== Resources ===
=== Resources ===
== Week 5 10 - Feb 6 Mar 18 ==
=== This Week ===
* Texturing - Identification
: connection between Design.cpp and effects.fx
** iTexture.h
:: add texture and texture state identifier
<syntaxhighlight lang="cpp">
iTexture* CreateTexture(const wchar_t* file, const char* str,
const char* isOn);
</syntaxhighlight>
** Texture.h
:
<syntaxhighlight lang="cpp">
Texture(const wchar_t*, const char*, const char*);
</syntaxhighlight>
** Texture.cpp
:
<syntaxhighlight lang="cpp">
// constructor initializes the texture identifier
//
Texture::Texture(const wchar_t* file, const char* str,
const char* isOn) : filter(0u) {
 
if (file) {
int len = strlen(file);
this->file = new wchar_t[len + 1];
strcpy(this->file, file, len);
}
else
this->file = nullptr;
 
tex = nullptr;
#if PIPELINE == FIXED_FUNCTION
#elif PIPELINE == PROGRAMMABLE
#elif PIPELINE == PROGRAMMABLE_EFFECT
textureHandle = effect->GetParameterByName(0, str);
textureonHandle = effect->GetParameterByName(0, isOn);
#endif
}
</syntaxhighlight>
:
<syntaxhighlight lang="cpp">
effect->SetTexture(textureHandle, tex);
effect->SetBool(textureonHandle, true);
</syntaxhighlight>
** iAPITexture.h
:: add texture and texture state identifier
<syntaxhighlight lang="cpp">
iAPITexture* CreateAPITexture(const wchar_t* file, const char* str,
const char* isOn);
</syntaxhighlight>
** APITexture.h
:
<syntaxhighlight lang="cpp">
D3DXHANDLE textureHandle; // points to texture
D3DXHANDLE textureonHandle; // points to texture on status
public:
APITexture(const wchar_t*, const char*, const char*);
</syntaxhighlight>
** APITexture.cpp
:
<syntaxhighlight lang="cpp">
// constructor initializes the texture identifier
//
APITexture::APITexture(const wchar_t* file, const char* str,
const char* isOn, AddressMode m) : filter(0u), mode(m) {
 
if (file) {
int len = strlen(file);
this->file = new wchar_t[len + 1];
strcpy(this->file, file, len);
}
else
this->file = nullptr;
 
tex = nullptr;
target = nullptr;
#if PIPELINE == FIXED_FUNCTION
#elif PIPELINE == PROGRAMMABLE
#elif PIPELINE == PROGRAMMABLE_EFFECT
textureHandle = effect->GetParameterByName(0, str);
textureonHandle = effect->GetParameterByName(0, isOn);
#endif
}
</syntaxhighlight>
:
<syntaxhighlight lang="cpp">
effect->SetTexture(textureHandle, tex);
effect->SetBool(textureonHandle, true);
</syntaxhighlight>
* Texturing - Tiling
: [http://msdn.microsoft.com/en-us/library/windows/desktop/bb206245%28v=vs.85%29.aspx Texture Coordinates]
** iGraphic.h
:: add u v parameters, both of which default to 1
<syntaxhighlight lang="cpp">
iGraphic* CreateBox(float, float, float, float, float, float,
float = 1, float = 1);
iGraphic* CreateIBox(float, float, float, float, float, float,
float = 1, float = 1);
iGraphic* CreateRectangleList(float, float, float, float,
float = 1, float = 1);
iGraphic* CreateIRectangleList(float, float, float, float,
float = 1, float = 1);
iGraphic* CreateMeshBox(float, float, float, float, float,
float, float = 1, float = 1);
</syntaxhighlight>
** Graphic.cpp
:: extend add functions to include u v parameters
<syntaxhighlight lang="cpp">
//-------------------------------- Graphic Structures -------------------------
//
// prototypes for add() function used by the Create...() functions
void add(VertexList<Vertex>*, const Vector&, const Vector&, const Vector&,
const Vector&, const Vector&, float = 1, float = 1);
void add(IndexedList<Vertex>*, const Vector&, const Vector&, const Vector&,
const Vector&, const Vector&, float = 1, float = 1);
void add(CustomMesh<Vertex>*, const Vector&, const Vector&, const Vector&,
const Vector&, const Vector&, float = 1, float = 1);
 
// CreateBox builds a triangle vertex list for a brick-like box from two
// extreme points one face at a time with all faces having the same attributes
//
iGraphic* CreateBox(float minx, float miny, float minz, float maxx,
float maxy, float maxz, float u, float v) {
VertexList<Vertex>* vertexList =
(VertexList<Vertex>*)CreateVertexList<Vertex>(TRIANGLE_LIST, 12);
 
float x = (minx + maxx) / 2;
float y = (miny + maxy) / 2;
float z = (minz + maxz) / 2;
minx -= x;
miny -= y;
minz -= z;
maxx -= x;
maxy -= y;
maxz -= z;
// bounding sphere
float max;
max = maxx > maxy ? maxx : maxy;
max = maxz > max ? maxz : max;
vertexList->setRadius(1.73205f * max);
// locate centroid at origin
Vector p1 = Vector(minx, miny, minz),
p2 = Vector(minx, maxy, minz),
p3 = Vector(maxx, maxy, minz),
p4 = Vector(maxx, miny, minz),
p5 = Vector(minx, miny, maxz),
p6 = Vector(minx, maxy, maxz),
p7 = Vector(maxx, maxy, maxz),
p8 = Vector(maxx, miny, maxz);
add(vertexList, p1, p2, p3, p4, Vector(0, 0, -1), u, v); // front
add(vertexList, p4, p3, p7, p8, Vector(1, 0, 0), u, v); // right
add(vertexList, p8, p7, p6, p5, Vector(0, 0, 1), u, v); // back
add(vertexList, p6, p2, p1, p5, Vector(-1, 0, 0), u, v); // left
add(vertexList, p1, p4, p8, p5, Vector(0, -1, 0), u, v); // bottom
add(vertexList, p2, p6, p7, p3, Vector(0, 1, 0), u, v); // top
 
return vertexList;
}
 
iGraphic* CreateIBox(float minx, float miny, float minz, float maxx,
float maxy, float maxz, float u, float v) {
IndexedList<Vertex>* indexedList = (IndexedList<Vertex>*)
CreateIndexedList<Vertex, unsigned short>(TRIANGLE_LIST, 12);
 
float x = (minx + maxx) / 2;
float y = (miny + maxy) / 2;
float z = (minz + maxz) / 2;
minx -= x;
miny -= y;
minz -= z;
maxx -= x;
maxy -= y;
maxz -= z;
// bounding sphere
float max;
max = maxx > maxy ? maxx : maxy;
max = maxz > max ? maxz : max;
indexedList->setRadius(1.73205f * max);
// locate centroid at origin
Vector p1 = Vector(minx, miny, minz),
p2 = Vector(minx, maxy, minz),
p3 = Vector(maxx, maxy, minz),
p4 = Vector(maxx, miny, minz),
p5 = Vector(minx, miny, maxz),
p6 = Vector(minx, maxy, maxz),
p7 = Vector(maxx, maxy, maxz),
p8 = Vector(maxx, miny, maxz);
add(indexedList, p1, p2, p3, p4, Vector(0, 0, -1), u, v); // front
add(indexedList, p4, p3, p7, p8, Vector(1, 0, 0), u, v); // right
add(indexedList, p8, p7, p6, p5, Vector(0, 0, 1), u, v); // back
add(indexedList, p6, p2, p1, p5, Vector(-1, 0, 0), u, v); // left
add(indexedList, p1, p4, p8, p5, Vector(0, -1, 0), u, v); // bottom
add(indexedList, p2, p6, p7, p3, Vector(0, 1, 0), u, v); // top
 
return indexedList;
}
 
// CreateRectangleList builds a triangle list in the x-y plane from its two
// extreme points
//
iGraphic* CreateRectangleList(float minx, float miny, float maxx, float maxy,
float u, float v) {
VertexList<Vertex>* vertexList =
(VertexList<Vertex>*)CreateVertexList<Vertex>(TRIANGLE_LIST, 2);
 
float x = (minx + maxx) / 2, y = (miny + maxy) / 2;
minx -= x;
miny -= y;
maxx -= x;
maxy -= y;
// bounding sphere
float max;
max = maxx > maxy ? maxx : maxy;
vertexList->setRadius(1.73205f * max);
// locate centroid at origin
Vector p1 = Vector(minx, miny, 0),
p2 = Vector(minx, maxy, 0),
p3 = Vector(maxx, maxy, 0),
p4 = Vector(maxx, miny, 0);
add(vertexList, p1, p2, p3, p4, Vector(0, 0, -1), u, v);
return vertexList;
}
 
// CreateIRectangleList builds an indexed triangle list in the x-y plane from
// its two extreme points
//
iGraphic* CreateIRectangleList(float minx, float miny, float maxx, float maxy,
float u, float v) {
IndexedList<Vertex>* indexedList = (IndexedList<Vertex>*)
CreateIndexedList<Vertex, unsigned short>(TRIANGLE_LIST, 2);
 
float x = (minx + maxx) / 2, y = (miny + maxy) / 2;
minx -= x;
miny -= y;
maxx -= x;
maxy -= y;
// bounding sphere
float max;
max = maxx > maxy ? maxx : maxy;
indexedList->setRadius(1.73205f * max);
// locate centroid at origin
Vector p1 = Vector(minx, miny, 0),
p2 = Vector(minx, maxy, 0),
p3 = Vector(maxx, maxy, 0),
p4 = Vector(maxx, miny, 0);
add(indexedList, p1, p2, p3, p4, Vector(0, 0, -1), u, v);
return indexedList;
}
 
// CreateIRectangleList builds an indexed triangle list in the x-y plane from
// its two extreme points
//
iGraphic* CreateBRectangleList(float minx, float miny, float maxx, float maxy,
float u, float v) {
IndexedList<BumpVertex>* indexedList = (IndexedList<BumpVertex>*)
CreateIndexedList<BumpVertex, unsigned short>(TRIANGLE_LIST, 2);
 
float x = (minx + maxx) / 2, y = (miny + maxy) / 2;
minx -= x;
miny -= y;
maxx -= x;
maxy -= y;
// bounding sphere
float max;
max = maxx > maxy ? maxx : maxy;
indexedList->setRadius(1.73205f * max);
// locate centroid at origin
Vector p1 = Vector(minx, miny, 0),
p2 = Vector(minx, maxy, 0),
p3 = Vector(maxx, maxy, 0),
p4 = Vector(maxx, miny, 0);
add(indexedList, p1, p2, p3, p4, Vector(0, 0, -1), u, v);
return indexedList;
}
 
// CreateMeshBox builds a mesh for a brick-like box from two extreme points one
// face at a time with each faces having distinct attributes
//
iGraphic* CreateMeshBox(float minx, float miny, float minz, float maxx,
float maxy, float maxz, float u, float v) {
 
unsigned attribute[] = {0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5};
 
CustomMesh<>* mesh = (CustomMesh<>*)
CreateCustomMesh<Vertex, unsigned short>(attribute, 12, 36, 24, 6);
 
float x = (minx + maxx) / 2, y = (miny + maxy) / 2, z = (minz + maxz) / 2;
minx -= x;
miny -= y;
minz -= z;
maxx -= x;
maxy -= y;
maxz -= z;
// bounding sphere
float max;
max = maxx > maxy ? maxx : maxy;
max = maxz > max ? maxz : max;
mesh->setRadius(1.73205f * max);
// one face at a time
Vector p1 = Vector(minx, miny, minz),
p2 = Vector(minx, maxy, minz),
p3 = Vector(maxx, maxy, minz),
p4 = Vector(maxx, miny, minz),
p5 = Vector(minx, miny, maxz),
p6 = Vector(minx, maxy, maxz),
p7 = Vector(maxx, maxy, maxz),
p8 = Vector(maxx, miny, maxz);
add(mesh, p1, p2, p3, p4, Vector(0, 0, -1), u, v); // front
add(mesh, p4, p3, p7, p8, Vector(1, 0, 0), u, v); // right
add(mesh, p8, p7, p6, p5, Vector(0, 0, 1), u, v); // back
add(mesh, p6, p2, p1, p5, Vector(-1, 0, 0), u, v); // left
add(mesh, p1, p4, p8, p5, Vector(0, -1, 0), u, v); // bottom
add(mesh, p2, p6, p7, p3, Vector(0, 1, 0), u, v); // top
 
return mesh;
}
 
void add(VertexList<Vertex>* vertexList, const Vector& p1, const Vector& p2,
const Vector& p3, const Vector& p4, const Vector& n, float u, float v) {
 
vertexList->add(Vertex(p1, n, 0, v));
vertexList->add(Vertex(p2, n, 0, 0));
vertexList->add(Vertex(p3, n, u, 0));
vertexList->add(Vertex(p1, n, 0, v));
vertexList->add(Vertex(p3, n, u, 0));
vertexList->add(Vertex(p4, n, u, v));
}
 
void add(IndexedList<Vertex>* indexedList, const Vector& p1, const Vector& p2,
const Vector& p3, const Vector& p4, const Vector& n, float u, float v) {
 
unsigned v1 = indexedList->add(Vertex(p1, n, 0, v));
unsigned v2 = indexedList->add(Vertex(p2, n, 0, 0));
unsigned v3 = indexedList->add(Vertex(p3, n, u, 0));
unsigned v4 = indexedList->add(Vertex(p4, n, u, v));
indexedList->add(v1);
indexedList->add(v2);
indexedList->add(v3);
indexedList->add(v1);
indexedList->add(v3);
indexedList->add(v4);
}
 
void add(CustomMesh<Vertex>* mesh, const Vector& p1, const Vector& p2,
const Vector& p3, const Vector& p4, const Vector& n, float u, float v) {
 
unsigned v1 = mesh->add(Vertex(p1, n, 0, v));
unsigned v2 = mesh->add(Vertex(p2, n, 0, 0));
unsigned v3 = mesh->add(Vertex(p3, n, u, 0));
unsigned v4 = mesh->add(Vertex(p4, n, u, v));
mesh->add(v1);
mesh->add(v2);
mesh->add(v3);
mesh->add(v1);
mesh->add(v3);
mesh->add(v4);
}
 
</syntaxhighlight>
* Texturing - Address Modes
: [http://msdn.microsoft.com/en-us/library/windows/desktop/bb206239%28v=vs.85%29.aspx Direct3D9 Addressing Modes]
** APITexture.h
:
<syntaxhighlight lang="cpp">
D3DXHANDLE textureMode; // points to texture mode
</syntaxhighlight>
** APITexture.cpp
:
<syntaxhighlight lang="cpp">
effect->SetInt(textureMode, (int)mode);
</syntaxhighlight>
** effects.fx - uniform variables
::
<syntaxhighlight lang="cpp">
// Addressing Modes
#define TEX_WRAP 0
#define TEX_CLAMP 1
#define TEX_MIRROR 2
 
//...
 
bool tex_1_On; // texture switch
int tex_mode; // addressing mode
texture tex_1;
 
sampler2D tex_1_ww = sampler_state {
texture = <tex_1>;
Filter = MIN_MAG_MIP_LINEAR;
AddressU = WRAP;
AddressV = WRAP;
};
 
sampler2D tex_1_mm = sampler_state {
texture = <tex_1>;
Filter = MIN_MAG_MIP_LINEAR;
AddressU = MIRROR;
AddressV = MIRROR;
};
 
sampler2D tex_1_cc = sampler_state {
texture = <tex_1>;
Filter = MIN_MAG_MIP_LINEAR;
AddressU = CLAMP;
AddressV = CLAMP;
};
 
</syntaxhighlight>
** effects.fx - fragment shader
:
<syntaxhighlight lang="cpp">
// sample the texture
//
if (tex_1_On) {
if (tex_mode == TEX_CLAMP)
output *= tex2D(tex_1_cc, input.texCoord);
else if (tex_mode == TEX_WRAP)
output *= tex2D(tex_1_ww, input.texCoord);
else if (tex_mode == TEX_MIRROR)
output *= tex2D(tex_1_mm, input.texCoord);
}
</syntaxhighlight>
* Texturing - Multi-Texturing
** effects.fx - uniform variables
:
<syntaxhighlight lang="cpp">
bool tex_2_On; // texture switch
texture tex_2;
 
sampler2D tex_2_ww = sampler_state {
texture = <tex_2>;
Filter = MIN_MAG_MIP_LINEAR;
AddressU = WRAP;
AddressV = WRAP;
};
 
sampler2D tex_2_mm = sampler_state {
texture = <tex_2>;
Filter = MIN_MAG_MIP_LINEAR;
AddressU = MIRROR;
AddressV = MIRROR;
};
 
sampler2D tex_2_cc = sampler_state {
texture = <tex_2>;
Filter = MIN_MAG_MIP_LINEAR;
AddressU = CLAMP;
AddressV = CLAMP;
};
 
</syntaxhighlight>
** effects.fx - fragment shader
:
<syntaxhighlight lang="cpp">
if (tex_2_On) {
if (tex_mode == TEX_CLAMP)
output *= tex2D(tex_2_cc, input.texCoord);
else if (tex_mode == TEX_WRAP)
output *= tex2D(tex_2_ww, input.texCoord);
else if (tex_mode == TEX_MIRROR)
output *= tex2D(tex_2_mm, input.texCoord);
}
</syntaxhighlight>
 
=== To Do ===
=== Resources ===
<!--== Week 6 11 - Feb 13 Mar 25 ==
=== This Week ===
 
<syntaxhighlight lang="cpp">
</syntaxhighlight>
 
=== To Do ===
=== Resources ===
-->
<!--
== Week 12 - Apr 1 ==
=== This Week ===
<syntaxhighlight lang="cpp">
</syntaxhighlight>
== Week 7 - Feb 20 ==
=== This Week ===
=== To Do ===
=== Resources ===
-->