154
edits
Changes
→This Week
return i;
}</syntaxhighlight>
<syntaxhighlight lang="cpp">
template <class T, class I>
</syntaxhighlight>
*:: viewpoint - simulates distortion due to perspective projection - useful for clouds
*::: normal is fixed (difference between viewpoint position and camera heading)
*::: up is open to change
<syntaxhighlight lang="cpp">
case VIEWPOINT:
break;
</syntaxhighlight>
*: Object.h and Object.cpp code
* Texture Filtering
*:: 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>
* DirectX Errors
*: APIDisplay::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>
* 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>::vertexSize = 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-us/library/windows/desktop/bb172630%28v=vs.85%29.aspx D3DVERTEXELEMENT9 struct]
* The Pipeline
*: [http://en.wikipedia.org/wiki/Instruction_pipeline What is a pipeline]
}
</syntaxhighlight>
:: [http://msdn.microsoft.com/en-us/library/windows/desktop/bb172768%28v=vs.85%29.aspx D3DXCreateEffectFromFile()]
<syntaxhighlight lang="cpp">
if (errorBuffer) errorBuffer->Release();
powerHandle = effect->GetParameterByName(0, "material.power");
</syntaxhighlight>
:: [http://msdn.microsoft.com/en-us/library/windows/desktop/bb205696%28v=vs.85%29.aspx GetParameterByName()]
: APIDisplay.cpp - beginDrawFrame()
<syntaxhighlight lang="cpp">
effect->SetVector(viewPoint, (D3DXVECTOR4*)&heading);
</syntaxhighlight>
:: [http://msdn.microsoft.com/en-us/library/windows/desktop/bb205720%28v=vs.85%29.aspx SetMatrix()]
:: [http://msdn.microsoft.com/en-us/library/windows/desktop/bb205729%28v=vs.85%29.aspx SetVector()]
<syntaxhighlight lang="cpp">
Colour colour(red, green, blue);
}
</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">
}
</syntaxhighlight>
:: [http://msdn.microsoft.com/en-us/library/windows/desktop/bb205817%28v=vs.85%29.aspx BeginPass()]
: APIDisplay.cpp - endPass()
<syntaxhighlight lang="cpp">
}
</syntaxhighlight>
:: [http://msdn.microsoft.com/en-us/library/windows/desktop/bb205823%28v=vs.85%29.aspx EndPass()]
: APIDisplay.cpp - endEffect()
<syntaxhighlight lang="cpp">
}
</syntaxhighlight>
:: [http://msdn.microsoft.com/en-us/library/windows/desktop/bb205821%28v=vs.85%29.aspx End()]
: APIDisplay.cpp - setWorld()
<syntaxhighlight lang="cpp">
effect->CommitChanges();
</syntaxhighlight>
:: [http://msdn.microsoft.com/en-us/library/windows/desktop/bb205819%28v=vs.85%29.aspx CommitChanges()]
: APIDisplay.cpp - release()
<syntaxhighlight lang="cpp">
}
</syntaxhighlight>
: effects.fx - Constant Memory
<syntaxhighlight lang="cpp">
// 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 8 - 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://rbwhitaker.wikidot.com/skyboxes-1 RB Whitaker's notes on skyboxes]* [http://knol.google.com/k/3d-skybox# Koen Samyn's knol]* [http://www.gameengineer.net/samples-graphics.html Game Engineer's demo]* [http://www.planetside.co.uk/terragen Terragen Texture Tool]* DirectX Utility - DirectX Texture Tool == Week 9 - Mar 11 ===== This Week ===* [http://msdn.microsoft.com/en-us/library/bb147178%28v=VS.85%29.aspx Mathematics of Lighting]* Lighting in Vertex Shaders** Notation**: G<sub>a</sub> - global ambient color**: C<sub>a</sub> - material ambient color**: C<sub>d</sub> - material diffuse color**: C<sub>s</sub> - material specular color**: L<sub>a<sub>i</sub></sub> - ambient color of light i**: L<sub>d<sub>i</sub></sub> - diffuse color of light i**: L<sub>s<sub>i</sub></sub> - specular color of light i**: L<sub>dir<sub>i</sub></sub> - direction vector of light i**: N - normal to the surface at the vertex*** [http://msdn.microsoft.com/en-us/library/bb172279%28v=VS.85%29.aspx Attenuation and Spotlight Factors]**** Atten<sub>i</sub> - attenuation of light i***: d<sub>i</sub> - distance from light i***:: d<sub>i</sub> = |L<sub>dir<sub>i</sub></sub>|***: a<sub>0</sub> - constant attenuation factor***: a<sub>1</sub> - linear attenuation factor***: a<sub>2</sub> - quadratic attenuation factor***: Atten<sub>i</sub> = 1/(a<sub>0</sub> + a<sub>1</sub> d<sub>i</sub> + a<sub>2</sub> d<sub>i</sub><sup>2</sup>)***: Atten<sub>i</sub> = [0, 1]**** Spot<sub>i</sub> - spot factor of light i***: Spot<sub>i</sub> = {[r<sub>i</sub> - cos(phi<sub>i</sub>/2)]/[cos(theta<sub>i</sub>/2) - cos(phi<sub>i</sub>/2)]}<sup>f<sub>i</sub></sup>***: r<sub>i</sub> - cosine of angle from axis of spotlight<sub>i</sub>***:: r<sub>i</sub> = norm(- light direction in camera space) . norm(L<sub>dir<sub>i</sub></sub>)***: phi<sub>i</sub> - penumbra (exterior cone) angle of spotlight<sub>i</sub>***: theta<sub>i</sub> - umbra (interior cone) angle of spotlight<sub>i</sub>***: f<sub>i</sub> - falloff factor of spotlight<sub>i</sub>** [http://en.wikipedia.org/wiki/Blinn%E2%80%93Phong_shading_model Blinn-Phong and Phong]**: V - viewpoint vector**:: V = norm(Camera<sub>position</sub> - Vertex<sub>position</sub>)** Phong - account accurately for position of viewer**: Specular reflectance = (R<sub>i</sub> . V)<sup>p<sub>i</sub></sup>**: R<sub>i</sub> - reflection vector**:: R<sub>i</sub> = 2 * (N . L<sub>dir<sub>i</sub></sub>) N - L<sub>dir<sub>i</sub></sub>**: p<sub>i</sub> - true specular power of light i**:** Blinn-Phong - use halfway vector instead of reflection vector - adjust power to compensate**: Specular reflectance = (N . H<sub>i</sub>)<sup>p'<sub>i</sub></sup>**: H<sub>i</sub> - halfway vector**:: H<sub>i</sub> = norm(V + L<sub>dir<sub>i</sub></sub>)**:: H<sub>i</sub> = norm([0,0,1] + L<sub>dir<sub>i</sub></sub>) - less computationally intensive - assumes that camera is at infinity along z axis**: p'<sub>i</sub> - adjusted specular power of light i**:** [http://msdn.microsoft.com/en-us/library/bb172256%28v=VS.85%29.aspx Ambient]**: C<sub>a</sub> * ( G<sub>a</sub> + sum [L<sub>a<sub>i</sub></sub> * Atten<sub>i</sub> * Spot<sub>i</sub>] )** [http://msdn.microsoft.com/en-us/library/bb219656%28v=VS.85%29.aspx Diffuse]**: C<sub>d</sub> * sum [ L<sub>d<sub>i</sub></sub> * (N . L<sub>dir<sub>i</sub></sub>) * Atten<sub>i</sub> * Spot<sub>i</sub> ]** [http://msdn.microsoft.com/en-us/library/bb147399%28VS.85%29.aspx Specular]**: C<sub>s</sub> * sum [ L<sub>s<sub>i</sub></sub> * (N . H<sub>i</sub>)<sup>p'<sub>i</sub></sup> * Atten<sub>i</sub> * Spot<sub>i</sub> ] - Blinn-Phong**: C<sub>s</sub> * sum [ L<sub>s<sub>i</sub></sub> * (R<sub>i</sub> . V)<sup>p<sub>i</sub></sup> * Atten<sub>i</sub> * Spot<sub>i</sub> ] - Phong** [http://msdn.microsoft.com/en-us/library/ff471376%28v=vs.85%29.aspx HLSL Intrinsic Functions]*** [http://msdn.microsoft.com/en-us/library/bb509630%28v=vs.85%29.aspx normalize()] - normalize a vector*** [http://msdn.microsoft.com/en-us/library/bb509594%28v=vs.85%29.aspx dot(,)] - dot product of two vectors of any size*** [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 ===
=== Resources ===
== Week 10 - 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 11 - Mar 25 ==
=== This Week ===
<syntaxhighlight lang="cpp">
</syntaxhighlight>
=== To Do ===
=== Resources ===
-->
<!--
== Week 12 - Apr 1 ==
=== This Week ===
<syntaxhighlight lang="cpp">
</syntaxhighlight>
=== To Do ===
=== Resources ===
-->