Motor II. Env map Spotlight Szécsi László
Letöltés /code/E/code/EggCoreSecondBase.zip Kibontani (vagy előző labor folyt.): diák: //l07-engine2.ppt
Próba Különböző színű űrhajók
Feladat: env map az egyikre 1.Effect fileba 1.Új technique: “envMapped” 2.Új sampler 3.VS marad 4.PS új 2.XML fileba 1.Új ShadedMesh 2.A "basic" roleban használjuk az "envMapped" techniqueet 3.Valamelyik Entity használja a SMt
Új sampler textureCUBE environmentCubeTexture; samplerCUBE environmentCubeSampler = sampler_state { texture = ; MipFilter = Linear; MagFilter = Linear; MinFilter = Linear; };
Új pixel shader float4 psEnvMapped(TrafoOutput input) : COLOR0 { float3 viewDir = normalize(eyePosition - input.worldPos); float3 reflectionDir = reflect(-viewDir, input.normal); return tex2D(kdMapSampler, input.tex) + texCUBE(environmentCubeSampler, reflectionDir) * 0.5; }
Új technique technique envMapped { pass ExamplePass { VertexShader = compile vs_2_0 vsTrafo(); PixelShader = compile ps_3_0 psEnvMapped(); }
Kód kiegészítés.fx fileban változó (már megvan): float3 eyePosition; EngineCore::render: effect->SetFloatArray("eyePosition", (float*)¤tCamera->second- >getEyePosition(), 3);
Új ShadedMesh
Új Entity
Feladat: környezet a háttérbe 1.Új mesh: quad.x (full viewport quad) 2.Új ShadedMesh: quad 1.Basic role: background 3.Új entity 4.Effect fileba 1.Új technique 2.VS quad rajzoló 3.PS envMap kiolvasó
Kód kiegészítés.fx fileban változó: float3 eyePosition; float4x4 rotProjMatrixInverse; EngineCore::render: rotProjMatrixInverse beállítása
Ez már megvan struct QuadInput { float4 pos: POSITION; float2 tex: TEXCOORD0; }; struct QuadOutput { float4 pos: POSITION; float2 tex: TEXCOORD0; float3 worldPosMinusEye: TEXCOORD1; }; QuadOutput vsQuad(QuadInput input) { QuadOutput output = (QuadOutput)0; output.pos = input.pos; float4 hWorldPosMinusEye = mul(input.pos, rotProjMatrixInverse); hWorldPosMinusEye /= hWorldPosMinusEye.w; output.worldPosMinusEye = hWorldPosMinusEye.xyz; output.pos.z = 1; output.tex = input.tex; return output; };
Env map háttér technique float4 psBackground(QuadOutput input) : COLOR0 { float3 viewDir = normalize(input.worldPosMinusEye); return texCUBE(environmentCubeSampler, viewDir); } technique background { pass ExamplePass { CullMode = None; ZEnable = False; VertexShader = compile vs_2_0 vsQuad(); PixelShader = compile ps_2_0 psBackground(); }
Új ShadedMesh <Mesh name="quad" xFileName="media\\quad.x" autoShadedMesh="false" />
Feladat: Bővítés fényforrásokkal betöltése.fx-be Spotlight tömb basic technique pixel shaderének kiegészítése –ciklus –fények szerinti árnyalás
XML <Spotlight name="fixed" pos.x="0" pos.y="10" pos.z="0" dir.x="0" dir.y="-1" dir.z="0" power.r="1000" power.g="1000" power.b="1000"focus="5" /> <Spotlight name="shipLight" owner="flagShip" pos.x="-16" pos.y="0" pos.z="0" dir.x="-1" dir.y="0" dir.z="0" power.r="10" power.g="1000" power.b="10"focus="5" />
Új class: Spotlight class Entity; class NodeGroup; class RenderContext; /// Light source class for point-like, directed light sources. class Spotlight { protected: /// Entity the light is moving with. Can be NULL for a fixed light. Entity* owner; /// Peak radiance of light source, emitted in main direction. D3DXVECTOR3 peakRadiance; /// Light source position, relative to owner entity. In world space, if owner is NULL. D3DXVECTOR3 position; /// Main direction, at which the light source emits its peak radiance, relative to owner entity. In world space, if owner is NULL. D3DXVECTOR3 direction; /// Exponent for radiance falloff at directions further away from main direction. double focus; public: /// Constructor. Spotlight(const D3DXVECTOR3& peakRadiance, const D3DXVECTOR3& position, const D3DXVECTOR3& direction, double focus); /// Assigns owner entity to light. void setOwner(Entity* owner); /// Returns peak radiance. const D3DXVECTOR3& getPeakRadiance(); /// Returns world space position. D3DXVECTOR3 getPosition(); /// Returns world space direction. D3DXVECTOR3 getDirection(); /// Returns falloff exponent. float getFocus(); };
Spotlight.cpp #include "DXUT.h" #include "Spotlight.h" #include "Entity.h" #include "RenderContext.h" #include "NodeGroup.h" Spotlight::Spotlight(const D3DXVECTOR3& peakRadiance, const D3DXVECTOR3& position, const D3DXVECTOR3& direction, double focus) { this->peakRadiance = peakRadiance; this->position = position; this->direction = direction; this->focus = focus; this->owner = NULL; } void Spotlight::setOwner(Entity* owner) { this->owner = owner; } const D3DXVECTOR3& Spotlight::getPeakRadiance() { return peakRadiance; } D3DXVECTOR3 Spotlight::getPosition() { if(owner == NULL) return position; D3DXMATRIX ownerModelMatrix; owner->getModelMatrix(ownerModelMatrix); D3DXVECTOR3 worldPosition; D3DXVec3TransformCoord(&worldPosition, &position, &ownerModelMatrix); return worldPosition; } D3DXVECTOR3 Spotlight::getDirection() { if(owner == NULL) return direction; D3DXMATRIX ownerModelMatrix; owner->getModelMatrix(ownerModelMatrix); D3DXVECTOR3 worldDirection; D3DXVec3TransformNormal(&worldDirection, &direction, &ownerModelMatrix); return worldDirection; } float Spotlight::getFocus() { return focus; }
Directory.h class Spotlight; typedef std::map SpotlightDirectory;
EngineCore.h SpotlightDirectory spotlightDirectory;
EngineCore.h private: void loadSpotlights(XMLNode& xMainNode);
EngineCore.cpp void EngineCore::loadLevel() { … loadSpotlights(xMainNode); }
EngineCore.cpp void EngineCore::loadSpotlights(XMLNode& xMainNode) { int iSpotlight = 0; XMLNode spotlightNode; while( !(spotlightNode = xMainNode.getChildNode(L"Spotlight", iSpotlight)).isEmpty() ) { D3DXVECTOR3 position = spotlightNode.readVector(L"pos"); D3DXVECTOR3 direction = spotlightNode.readVector(L"dir"); D3DXVECTOR3 peakRadiance = spotlightNode.readVector(L"power"); double focus = spotlightNode.readDouble(L"focus"); Spotlight* spotlight = new Spotlight(peakRadiance, position, direction, focus); const wchar_t* ownerEntityName = spotlightNode|L"owner"; if(ownerEntityName != NULL) { EntityDirectory::iterator iEntity = entityDirectory.find(ownerEntityName); if(iEntity != entityDirectory.end()) { spotlight->setOwner(iEntity->second); } const wchar_t* spotlightName = spotlightNode|L"name"; spotlightDirectory[spotlightName] = spotlight; iSpotlight++; }
EngineCore:: releaseManagedResources { SpotlightDirectory::iterator i = spotlightDirectory.begin(); while(i != spotlightDirectory.end()) { delete i->second; i++; }
EngineCore::render SpotlightDirectory::iterator i = spotlightDirectory.begin(); int ci = 0; while(i != spotlightDirectory.end()) { char varname[128]; sprintf(varname, "spotlights[%d].peakRadiance", ci); effect->SetFloatArray(varname, (float*)&i->second->getPeakRadiance(), 3); sprintf(varname, "spotlights[%d].position", ci); effect->SetFloatArray(varname, (float*)&i->second->getPosition(), 3); sprintf(varname, "spotlights[%d].direction", ci); effect->SetFloatArray(varname, (float*)&i->second->getDirection(), 3); sprintf(varname, "spotlights[%d].focus", ci); effect->SetFloat(varname, i->second->getFocus()); i++; ci++; }
standard.fx struct Spotlight { float3 peakRadiance; float3 position; float3 direction; float focus; } spotlights[2]; int nSpotlights = 2;
textured.fx, psBasic float4 psBasic(TrafoOutput input) : COLOR0 { float3 lighting = 0.5; for(int il=0; il<nSpotlights; il++) { float3 lightDiff = spotlights[il].position - input.worldPos; float3 lightDir = normalize(lightDiff); lighting += spotlights[il].peakRadiance * max(0, dot(input.normal, lightDir)) * pow( max(0, dot(-lightDir,spotlights[il].direction)), spotlights[il].focus) /dot(lightDiff, lightDiff); } return float4( lighting * tex2D(kdMapSampler, input.tex) * kdColor, 1); }
Próba Fények hatása látszik