void TexturingWindow::CreateScene() { // Create a vertex buffer for a two-triangles square. The PNG is stored // in left-handed coordinates. The texture coordinates are chosen to // reflect the texture in the y-direction. struct Vertex { Vector3<float> position; Vector2<float> tcoord; }; VertexFormat vformat; vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0); vformat.Bind(VA_TEXCOORD, DF_R32G32_FLOAT, 0); std::shared_ptr<VertexBuffer> vbuffer(new VertexBuffer(vformat, 4)); Vertex* vertex = vbuffer->Get<Vertex>(); vertex[0].position = { 0.0f, 0.0f, 0.0f }; vertex[0].tcoord = { 0.0f, 1.0f }; vertex[1].position = { 1.0f, 0.0f, 0.0f }; vertex[1].tcoord = { 1.0f, 1.0f }; vertex[2].position = { 0.0f, 1.0f, 0.0f }; vertex[2].tcoord = { 0.0f, 0.0f }; vertex[3].position = { 1.0f, 1.0f, 0.0f }; vertex[3].tcoord = { 1.0f, 0.0f }; // Create an indexless buffer for a triangle mesh with two triangles. std::shared_ptr<IndexBuffer> ibuffer(new IndexBuffer(IP_TRISTRIP, 2)); // Create an effect for the vertex and pixel shaders. The texture is // bilinearly filtered and the texture coordinates are clamped to [0,1]^2. std::shared_ptr<Texture2> myTexture(WICFileIO::Load( mEnvironment.GetPath("StoneWall.png"), false)); std::shared_ptr<Texture2Effect> effect = std::make_shared<Texture2Effect>(mProgramFactory, myTexture, SamplerState::MIN_L_MAG_L_MIP_P, SamplerState::CLAMP, SamplerState::CLAMP); // Create the geometric object for drawing. Translate it so that its // center of mass is at the origin. This supports virtual trackball // motion about the object "center". mSquare = std::make_shared<Visual>(vbuffer, ibuffer, effect); mSquare->localTransform.SetTranslation(-0.5f, -0.5f, 0.0f); // Enable automatic updates of pvw-matrices and w-matrices. mCameraRig.Subscribe(mSquare->worldTransform, effect->GetPVWMatrixConstant()); #if defined(SAVE_RENDERING_TO_DISK) mTarget = std::make_shared<DrawTarget>(1, DF_R8G8B8A8_UNORM, mXSize, mYSize); mTarget->GetRTTexture(0)->SetCopyType(Resource::COPY_STAGING_TO_CPU); #endif mTrackball.Attach(mSquare); mTrackball.Update(); }
void BlendedAnimationsWindow::CreateScene() { mWireState = std::make_shared<RasterizerState>(); mWireState->fillMode = RasterizerState::FILL_WIREFRAME; mScene = std::make_shared<Node>(); mScene->AttachChild(mManager->GetRoot()); // Create a floor to walk on. VertexFormat vformat; vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0); vformat.Bind(VA_NORMAL, DF_R32G32B32_FLOAT, 0); vformat.Bind(VA_TEXCOORD, DF_R32G32_FLOAT, 0); MeshFactory mf; mf.SetVertexFormat(vformat); mFloor = mf.CreateRectangle(2, 2, 1024.0f, 2048.0f); mFloor->name = "Floor"; mScene->AttachChild(mFloor); std::shared_ptr<VertexBuffer> vbuffer = mFloor->GetVertexBuffer(); vbuffer->SetUsage(Resource::DYNAMIC_UPDATE); unsigned int numVertices = vbuffer->GetNumElements(); Vertex* vertex = vbuffer->Get<Vertex>(); for (unsigned int i = 0; i < numVertices; ++i) { vertex[i].tcoord[0] *= 64.0f; vertex[i].tcoord[1] *= 256.0f; } std::string textureName = mEnvironment.GetPath("Grating.png"); std::shared_ptr<Texture2> texture(WICFileIO::Load(textureName, true)); texture->AutogenerateMipmaps(); std::shared_ptr<Texture2Effect> effect = std::make_shared<Texture2Effect>( mProgramFactory, texture, SamplerState::MIN_L_MAG_L_MIP_L, SamplerState::WRAP, SamplerState::WRAP); mFloor->SetEffect(effect); mCameraRig.Subscribe(mFloor->worldTransform, effect->GetPVWMatrixConstant()); for (auto const& subscriber : mManager->GetSubscribers()) { mCameraRig.Subscribe(subscriber.first->worldTransform, subscriber.second); } GetMeshes(mScene); mTrackball.Attach(mScene); mTrackball.Update(mApplicationTime); }
bool Fluids3DWindow::CreateNestedBoxes() { std::string path = mEnvironment.GetPath("VolumeRender.hlsl"); std::shared_ptr<VisualProgram> program = mProgramFactory.CreateFromFiles(path, path, ""); if (!program) { return false; } mPVWMatrixBuffer = std::make_shared<ConstantBuffer>( sizeof(Matrix4x4<float>), true); *mPVWMatrixBuffer->Get<Matrix4x4<float>>() = Matrix4x4<float>::Identity(); mTrilinearClampSampler = std::make_shared<SamplerState>(); mTrilinearClampSampler->filter = SamplerState::MIN_L_MAG_L_MIP_P; mTrilinearClampSampler->mode[0] = SamplerState::CLAMP; mTrilinearClampSampler->mode[1] = SamplerState::CLAMP; mTrilinearClampSampler->mode[2] = SamplerState::CLAMP; program->GetVShader()->Set("PVWMatrix", mPVWMatrixBuffer); program->GetPShader()->Set("volumeTexture", mFluid.GetState()); program->GetPShader()->Set("trilinearClampSampler", mTrilinearClampSampler); std::shared_ptr<VisualEffect> effect = std::make_shared<VisualEffect>(program); struct Vertex { Vector3<float> position, tcoord; }; VertexFormat vformat; vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0); vformat.Bind(VA_TEXCOORD, DF_R32G32B32_FLOAT, 0); MeshFactory mf; mf.SetVertexFormat(vformat); int const numBoxes = 128; for (int i = 1; i <= numBoxes; ++i) { float extent = 0.5f*i/(numBoxes - 1.0f); std::shared_ptr<Visual> visual(mf.CreateBox(extent, extent, extent)); VertexBuffer* vbuffer = visual->GetVertexBuffer().get(); Vertex* vertex = vbuffer->Get<Vertex>(); for (unsigned int j = 0; j < vbuffer->GetNumElements(); ++j, ++vertex) { Vector3<float>& tcd = vertex->tcoord; Vector3<float> pos = vertex->position; Vector4<float> tmp{ pos[0] + 0.5f, pos[1] + 0.5f, pos[2] + 0.5f, 0.0f }; for (int k = 0; k < 3; ++k) { tcd[k] = 0.5f*(tmp[k] + 1.0f); } } visual->SetEffect(effect); mVisible.push_back(visual); } return true; }
void Delaunay3DWindow::CreateTetra(int index) { std::vector<int> const& dindices = mDelaunay.GetIndices(); VertexFormat vformat; vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0); vformat.Bind(VA_COLOR, DF_R32G32B32A32_FLOAT, 0); std::shared_ptr<VertexBuffer> vbuffer(new VertexBuffer(vformat, static_cast<unsigned int>(mVertices.size()))); vbuffer->SetUsage(Resource::DYNAMIC_UPDATE); Vertex* vertex = vbuffer->Get<Vertex>(); for (int j = 0; j < 4; ++j) { vertex[j].position = mVertices[dindices[4 * index + j]]; vertex[j].color = mLightGray; } std::shared_ptr<IndexBuffer> ibuffer(new IndexBuffer(IP_TRIMESH, 4, sizeof(unsigned int))); unsigned int* indices = ibuffer->Get<unsigned int>(); indices[0] = 0; indices[1] = 1; indices[2] = 2; indices[3] = 0; indices[4] = 3; indices[5] = 1; indices[6] = 0; indices[7] = 2; indices[8] = 3; indices[9] = 3; indices[10] = 2; indices[11] = 1; mWireTetra[index] = std::make_shared<Visual>(vbuffer, ibuffer, mVCEffect); mScene->AttachChild(mWireTetra[index]); }
//---------------------------------------------------------------------------- void PerformanceAMDWindow::CreateScene() { struct Vertex { Vector3<float> position; Vector2<float> tcoord; }; VertexFormat vformat; vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0); vformat.Bind(VA_TEXCOORD, DF_R32G32_FLOAT, 0); unsigned int const numTriangles = 1024; unsigned int const numVertices = 3 * numTriangles; std::shared_ptr<VertexBuffer> vbuffer(new VertexBuffer(vformat, numVertices)); // Randomly generate positions and texture coordinates. std::mt19937 mte; std::uniform_real_distribution<float> unirnd(0.0f, 1.0f); std::uniform_real_distribution<float> symrnd(-1.0f, 1.0f); Vertex* vertex = vbuffer->Get<Vertex>(); for (unsigned int i = 0; i < numVertices; ++i) { for (int j = 0; j < 3; ++j) { vertex[i].position[j] = symrnd(mte); } for (int j = 0; j < 2; ++j) { vertex[i].tcoord[j] = unirnd(mte); } } // The vertices are not indexed. Each consecutive triple is a triangle. std::shared_ptr<IndexBuffer> ibuffer(new IndexBuffer(IP_TRIMESH, numTriangles)); // Use a standard texture effect. std::shared_ptr<Texture2Effect> effect(new Texture2Effect( mProgramFactory, mBlurredTexture, SamplerState::MIN_L_MAG_L_MIP_P, SamplerState::CLAMP, SamplerState::CLAMP)); mPVWMatrix = effect->GetPVWMatrixConstant(); mTriangles.reset(new Visual(vbuffer, ibuffer, effect)); SubscribeCW(mTriangles, mPVWMatrix); EnableObjectMotion(); }
void MinimumVolumeSphere3DWindow::CreateScene() { // Create the points. std::mt19937 mte; std::uniform_real_distribution<float> rnd(-1.0f, 1.0f); for (auto& v : mVertices) { v = { rnd(mte), rnd(mte), rnd(mte) }; } VertexFormat vformat; vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0); MeshFactory mf; mf.SetVertexFormat(vformat); std::shared_ptr<ConstantColorEffect> effect; for (int i = 0; i < NUM_POINTS; ++i) { mPoints[i] = mf.CreateSphere(6, 6, 0.01f); effect = std::make_shared<ConstantColorEffect>(mProgramFactory, Vector4<float>({ 0.5f, 0.5f, 0.5f, 1.0f })); mPoints[i]->SetEffect(effect); mCameraRig.Subscribe(mPoints[i]->worldTransform, effect->GetPVWMatrixConstant()); std::shared_ptr<VertexBuffer> vbuffer = mPoints[i]->GetVertexBuffer(); Vector3<float>* vertex = vbuffer->Get<Vector3<float>>(); Vector3<float> offset = mVertices[i]; for (unsigned int j = 0; j < vbuffer->GetNumElements(); ++j) { vertex[j] += offset; } } // Create the segments. std::shared_ptr<VertexBuffer> vbuffer(new VertexBuffer(vformat, 12)); vbuffer->SetUsage(Resource::DYNAMIC_UPDATE); std::shared_ptr<IndexBuffer> ibuffer(new IndexBuffer( IP_POLYSEGMENT_DISJOINT, 6)); effect = std::make_shared<ConstantColorEffect>(mProgramFactory, Vector4<float>({ 0.5f, 0.0f, 0.0f, 1.0f })); mSegments = std::make_shared<Visual>(vbuffer, ibuffer, effect); mCameraRig.Subscribe(mSegments->worldTransform, effect->GetPVWMatrixConstant()); mSegments->Update(); // Create the sphere. mSphere = mf.CreateSphere(16, 16, 1.0f); effect = std::make_shared<ConstantColorEffect>(mProgramFactory, Vector4<float>({ 0.0f, 0.0f, 0.5f, 1.0f })); mSphere->SetEffect(effect); mCameraRig.Subscribe(mSphere->worldTransform, effect->GetPVWMatrixConstant()); }
void Delaunay3DWindow::CreateSphere() { VertexFormat vformat; vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0); vformat.Bind(VA_COLOR, DF_R32G32B32_FLOAT, 0); MeshFactory mf; mf.SetVertexFormat(vformat); mSphere = mf.CreateSphere(8, 8, 0.025f); std::shared_ptr<VertexColorEffect> effect = std::make_shared<VertexColorEffect>(mProgramFactory); mSphere->SetEffect(effect); // Move the sphere offscreen initially. mSphere->localTransform.SetTranslation(0.0f, 0.0f, -1000.0f); mSphere->Update(); mCameraRig.Subscribe(mSphere->worldTransform, effect->GetPVWMatrixConstant()); mScene->AttachChild(mSphere); }
//---------------------------------------------------------------------------- bool WireMeshWindow::CreateScene() { std::string path = mEnvironment.GetPath("WireMesh.hlsl"); std::shared_ptr<VertexShader> vshader(ShaderFactory::CreateVertex(path)); if (!vshader) { return false; } std::shared_ptr<GeometryShader> gshader(ShaderFactory::CreateGeometry( path)); if (!gshader) { return false; } std::shared_ptr<PixelShader> pshader(ShaderFactory::CreatePixel(path)); if (!pshader) { return false; } std::shared_ptr<ConstantBuffer> parameters( new ConstantBuffer(3 * sizeof(Vector4<float>), false)); Vector4<float>* data = parameters->Get<Vector4<float>>(); data[0] = Vector4<float>(0.0f, 0.0f, 1.0f, 1.0f); // mesh color data[1] = Vector4<float>(0.0f, 0.0f, 0.0f, 1.0f); // edge color data[2] = Vector4<float>((float)mXSize, (float)mYSize, 0.0f, 0.0f); vshader->Set("WireParameters", parameters); gshader->Set("WireParameters", parameters); pshader->Set("WireParameters", parameters); std::shared_ptr<ConstantBuffer> cbuffer( new ConstantBuffer(sizeof(Matrix4x4<float>), true)); vshader->Set("PVWMatrix", cbuffer); std::shared_ptr<VisualEffect> effect(new VisualEffect(vshader, pshader, gshader)); VertexFormat vformat; vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0); MeshFactory mf; mf.SetVertexFormat(vformat); mMesh = mf.CreateSphere(16, 16, 1.0f); mMesh->SetEffect(effect); mMesh->Update(); SubscribeCW(mMesh, cbuffer); return true; }
void OverlayEffect::Initialize(int windowWidth, int windowHeight, int textureWidth, int textureHeight) { if (windowWidth <= 0 || windowHeight <= 0 || textureWidth <= 0 || textureHeight <= 0) { LogError("Invalid input rectangle."); // Use dummy sizes. windowWidth = 1; windowHeight = 1; textureWidth = 1; textureHeight = 1; } mInvTextureWidth = 1.0f/static_cast<float>(textureWidth); mInvTextureHeight = 1.0f/static_cast<float>(textureHeight); mOverlayRectangle[0] = 0; mOverlayRectangle[1] = 0; mOverlayRectangle[2] = windowWidth; mOverlayRectangle[3] = windowHeight; mTextureRectangle[0] = 0; mTextureRectangle[1] = 0; mTextureRectangle[2] = textureWidth; mTextureRectangle[3] = textureHeight; // Create the vertex buffer. VertexFormat vformat; vformat.Bind(VA_POSITION, DF_R32G32_FLOAT, 0); vformat.Bind(VA_TEXCOORD, DF_R32G32_FLOAT, 0); mVBuffer = std::make_shared<VertexBuffer>(vformat, 4); mVBuffer->SetUsage(Resource::DYNAMIC_UPDATE); UpdateVertexBuffer(); // Create the index buffer. mIBuffer = std::make_shared<IndexBuffer>(IP_TRIMESH, 2, sizeof(unsigned int)); unsigned int* indices = mIBuffer->Get<unsigned int>(); indices[0] = 0; indices[1] = 2; indices[2] = 3; indices[3] = 0; indices[4] = 3; indices[5] = 1; }
//---------------------------------------------------------------------------- bool PlaneMeshIntersectionWindow::CreateScene() { std::string path = mEnvironment.GetPath("PlaneMeshIntersection.hlsl"); std::shared_ptr<VertexShader> vshader(ShaderFactory::CreateVertex(path)); if (!vshader) { return false; } std::shared_ptr<PixelShader> pshader(ShaderFactory::CreatePixel(path)); if (!pshader) { return false; } path = mEnvironment.GetPath("DrawIntersections.hlsl"); mDrawIntersections.reset(ShaderFactory::CreateCompute(path)); float planeDelta = 0.125f; mPMIParameters.reset(new ConstantBuffer(sizeof(PMIParameters), true)); PMIParameters& p = *mPMIParameters->Get<PMIParameters>(); p.pvMatrix = mCamera.GetProjectionViewMatrix(); p.wMatrix = Matrix4x4<float>::Identity(); p.planeVector0 = Vector4<float>(1.0f, 0.0f, 0.0f, 0.0f) / planeDelta; p.planeVector1 = Vector4<float>(0.0f, 1.0f, 0.0f, 0.0f) / planeDelta; vshader->Set("PMIParameters", mPMIParameters); std::shared_ptr<VisualEffect> effect(new VisualEffect(vshader, pshader)); VertexFormat vformat; vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0); MeshFactory mf; mf.SetVertexFormat(vformat); mMesh = mf.CreateSphere(16, 16, 1.0f); mMesh->SetEffect(effect); mMesh->Update(); return true; }
//---------------------------------------------------------------------------- bool StructuredBuffersWindow::CreateScene() { // Create the shaders and associated resources HLSLDefiner definer; definer.SetInt("WINDOW_WIDTH", mXSize); std::shared_ptr<VertexShader> vshader(ShaderFactory::CreateVertex( mEnvironment.GetPath("StructuredBuffers.hlsl"), definer)); if (!vshader) { return false; } std::shared_ptr<PixelShader> pshader(ShaderFactory::CreatePixel( mEnvironment.GetPath("StructuredBuffers.hlsl"), definer)); if (!pshader) { return false; } std::shared_ptr<ConstantBuffer> cbuffer(new ConstantBuffer( sizeof(Matrix4x4<float>), true)); vshader->Set("PVWMatrix", cbuffer); // Create the pixel shader and associated resources. std::string path = mEnvironment.GetPath("StoneWall.png"); std::shared_ptr<Texture2> baseTexture(WICFileIO::Load(path, false)); pshader->Set("baseTexture", baseTexture); std::shared_ptr<SamplerState> baseSampler(new SamplerState()); baseSampler->filter = SamplerState::MIN_L_MAG_L_MIP_P; baseSampler->mode[0] = SamplerState::CLAMP; baseSampler->mode[1] = SamplerState::CLAMP; pshader->Set("baseSampler", baseSampler); mDrawnPixels.reset(new StructuredBuffer(mXSize*mYSize, sizeof(Vector4<float>))); mDrawnPixels->SetUsage(Resource::SHADER_OUTPUT); mDrawnPixels->SetCopyType(Resource::COPY_BIDIRECTIONAL); memset(mDrawnPixels->GetData(), 0, mDrawnPixels->GetNumBytes()); pshader->Set("drawnPixels", mDrawnPixels); // Create the visual effect for the square. std::shared_ptr<VisualEffect> effect(new VisualEffect(vshader, pshader)); // Create a vertex buffer for a single triangle. The PNG is stored in // left-handed coordinates. The texture coordinates are chosen to reflect // the texture in the y-direction. struct Vertex { Vector3<float> position; Vector2<float> tcoord; }; VertexFormat vformat; vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0); vformat.Bind(VA_TEXCOORD, DF_R32G32_FLOAT, 0); std::shared_ptr<VertexBuffer> vbuffer(new VertexBuffer(vformat, 4)); Vertex* vertex = vbuffer->Get<Vertex>(); vertex[0].position = Vector3<float>(0.0f, 0.0f, 0.0f); vertex[0].tcoord = Vector2<float>(0.0f, 1.0f); vertex[1].position = Vector3<float>(1.0f, 0.0f, 0.0f); vertex[1].tcoord = Vector2<float>(1.0f, 1.0f); vertex[2].position = Vector3<float>(0.0f, 1.0f, 0.0f); vertex[2].tcoord = Vector2<float>(0.0f, 0.0f); vertex[3].position = Vector3<float>(1.0f, 1.0f, 0.0f); vertex[3].tcoord = Vector2<float>(1.0f, 0.0f); // Create an indexless buffer for a triangle mesh with two triangles. std::shared_ptr<IndexBuffer> ibuffer(new IndexBuffer(IP_TRISTRIP, 2)); // Create the geometric object for drawing. Translate it so that its // center of mass is at the origin. This supports virtual trackball // motion about the object "center". mSquare.reset(new Visual(vbuffer, ibuffer, effect)); mSquare->localTransform.SetTranslation(-0.5f, -0.5f, 0.0f); mSquare->Update(); // Enable automatic updates of pvw-matrices and w-matrices. SubscribeCW(mSquare, cbuffer); // The structured buffer is written in the pixel shader. This texture // will receive a copy of it so that we can write the results to disk // as a PNG file. mDrawnPixelsTexture = new Texture2(DF_R8G8B8A8_UNORM, mXSize, mYSize); return true; }
bool TextureArraysWindow::CreateScene() { // Create the shaders and associated resources. std::string filename = mEnvironment.GetPath("TextureArrays.hlsl"); std::shared_ptr<VisualProgram> program = mProgramFactory.CreateFromFiles(filename, filename, ""); if (!program) { return false; } // Create a vertex buffer for a single triangle. The PNG is stored in // left-handed coordinates. The texture coordinates are chosen to reflect // the texture in the y-direction. struct Vertex { Vector3<float> position; Vector2<float> tcoord; }; VertexFormat vformat; vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0); vformat.Bind(VA_TEXCOORD, DF_R32G32_FLOAT, 0); std::shared_ptr<VertexBuffer> vbuffer(new VertexBuffer(vformat, 4)); Vertex* vertex = vbuffer->Get<Vertex>(); vertex[0].position = { 0.0f, 0.0f, 0.0f }; vertex[0].tcoord = { 0.0f, 1.0f }; vertex[1].position = { 1.0f, 0.0f, 0.0f }; vertex[1].tcoord = { 1.0f, 1.0f }; vertex[2].position = { 0.0f, 1.0f, 0.0f }; vertex[2].tcoord = { 0.0f, 0.0f }; vertex[3].position = { 1.0f, 1.0f, 0.0f }; vertex[3].tcoord = { 1.0f, 0.0f }; // Create an indexless buffer for a triangle mesh with two triangles. std::shared_ptr<IndexBuffer> ibuffer(new IndexBuffer(IP_TRISTRIP, 2)); // Create an effect for the vertex and pixel shaders. The texture is // bilinearly filtered and the texture coordinates are clamped to [0,1]^2. std::shared_ptr<ConstantBuffer> cbuffer(new ConstantBuffer( sizeof(Matrix4x4<float>), true)); program->GetVShader()->Set("PVWMatrix", cbuffer); std::shared_ptr<PixelShader> pshader = program->GetPShader(); std::shared_ptr<Texture1Array> t1array(new Texture1Array(2, DF_R8G8B8A8_UNORM, 2)); unsigned int* t1data = t1array->Get<unsigned int>(); t1data[0] = 0xFF000000; t1data[1] = 0xFFFFFFFF; pshader->Set("myTexture1", t1array); Texture2* stoneTexture = WICFileIO::Load( mEnvironment.GetPath("StoneWall.png"), false); std::shared_ptr<Texture2Array> t2array(new Texture2Array(2, DF_R8G8B8A8_UNORM, 256, 256)); unsigned char* t2data = t2array->Get<unsigned char>(); size_t const numBytes = stoneTexture->GetNumBytes(); Memcpy(t2data, stoneTexture->GetData(), numBytes); t2data += numBytes; delete stoneTexture; for (size_t i = 0; i < numBytes; ++i) { *t2data++ = static_cast<unsigned char>(rand() % 256); } pshader->Set("myTexture2", t2array); std::shared_ptr<SamplerState> samplerState(new SamplerState()); samplerState->filter = SamplerState::MIN_L_MAG_L_MIP_P; samplerState->mode[0] = SamplerState::CLAMP; samplerState->mode[1] = SamplerState::CLAMP; pshader->Set("mySampler", samplerState); std::shared_ptr<VisualEffect> effect = std::make_shared<VisualEffect>(program); // Create the geometric object for drawing. Translate it so that its // center of mass is at the origin. This supports virtual trackball // motion about the object "center". mSquare = std::make_shared<Visual>(vbuffer, ibuffer, effect); mSquare->localTransform.SetTranslation(-0.5f, -0.5f, 0.0f); // Enable automatic updates of pvw-matrices and w-matrices. mCameraRig.Subscribe(mSquare->worldTransform, cbuffer); mTrackball.Attach(mSquare); mTrackball.Update(); return true; }
bool MultipleRenderTargetsWindow::CreateScene() { // Create a visual effect that populates the draw target. std::string filename = mEnvironment.GetPath("MultipleRenderTargets.hlsl"); std::shared_ptr<VisualProgram> program = mProgramFactory.CreateFromFiles(filename, filename, ""); if (!program) { return false; } std::shared_ptr<ConstantBuffer> cbuffer(new ConstantBuffer( sizeof(Matrix4x4<float>), true)); program->GetVShader()->Set("PVWMatrix", cbuffer); std::shared_ptr<PixelShader> pshader = program->GetPShader(); std::shared_ptr<ConstantBuffer> farNearRatio(new ConstantBuffer( sizeof(float), false)); pshader->Set("FarNearRatio", farNearRatio); farNearRatio->SetMember("farNearRatio", mCamera->GetDMax() / mCamera->GetDMin()); std::string path = mEnvironment.GetPath("StoneWall.png"); std::shared_ptr<Texture2> baseTexture(WICFileIO::Load(path, true)); baseTexture->AutogenerateMipmaps(); pshader->Set("baseTexture", baseTexture); std::shared_ptr<SamplerState> baseSampler(new SamplerState()); baseSampler->filter = SamplerState::MIN_L_MAG_L_MIP_L; baseSampler->mode[0] = SamplerState::CLAMP; baseSampler->mode[1] = SamplerState::CLAMP; pshader->Set("baseSampler", baseSampler); std::shared_ptr<VisualEffect> effect = std::make_shared<VisualEffect>(program); // Create a vertex buffer for a two-triangle square. The PNG is stored // in left-handed coordinates. The texture coordinates are chosen to // reflect the texture in the y-direction. struct Vertex { Vector3<float> position; Vector2<float> tcoord; }; VertexFormat vformat; vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0); vformat.Bind(VA_TEXCOORD, DF_R32G32_FLOAT, 0); std::shared_ptr<VertexBuffer> vbuffer(new VertexBuffer(vformat, 4)); Vertex* vertex = vbuffer->Get<Vertex>(); vertex[0].position = { -1.0f, -1.0f, 0.0f }; vertex[0].tcoord = { 0.0f, 1.0f }; vertex[1].position = { 1.0f, -1.0f, 0.0f }; vertex[1].tcoord = { 1.0f, 1.0f }; vertex[2].position = { -1.0f, 1.0f, 0.0f }; vertex[2].tcoord = { 0.0f, 0.0f }; vertex[3].position = { 1.0f, 1.0f, 0.0f }; vertex[3].tcoord = { 1.0f, 0.0f }; // Create an indexless buffer for a triangle mesh with two triangles. std::shared_ptr<IndexBuffer> ibuffer(new IndexBuffer(IP_TRISTRIP, 2)); // Create the geometric object for drawing and enable automatic updates // of pvw-matrices and w-matrices. mSquare = std::make_shared<Visual>(vbuffer, ibuffer, effect); mTrackball.Attach(mSquare); mTrackball.Update(); mCameraRig.Subscribe(mSquare->worldTransform, cbuffer); return true; }
bool GeometryShadersWindow::CreateScene() { std::string filename; #if defined(USE_DRAW_DIRECT) filename = mEnvironment.GetPath("RandomSquares.hlsl"); #else filename = mEnvironment.GetPath("RandomSquaresIndirect.hlsl"); #endif std::shared_ptr<VisualProgram> program = mProgramFactory.CreateFromFiles(filename, filename, filename); if (!program) { return false; } // Create particles used by direct and indirect drawing. struct Vertex { Vector3<float> position; Vector3<float> color; float size; }; // Use a Mersenne twister engine for random numbers. std::mt19937 mte; std::uniform_real_distribution<float> symr(-1.0f, 1.0f); std::uniform_real_distribution<float> unir(0.0f, 1.0f); std::uniform_real_distribution<float> posr(0.01f, 0.1f); int const numParticles = 128; std::vector<Vertex> particles(numParticles); for (auto& particle : particles) { particle.position = { symr(mte), symr(mte), symr(mte) }; particle.color = { unir(mte), unir(mte), unir(mte) }; particle.size = posr(mte); } // Create the constant buffer used by direct and indirect drawing. mMatrices = std::make_shared<ConstantBuffer>( 2 * sizeof(Matrix4x4<float>), true); program->GetGShader()->Set("Matrices", mMatrices); #if defined(USE_DRAW_DIRECT) // Create a mesh for direct drawing. VertexFormat vformat; vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0); vformat.Bind(VA_COLOR, DF_R32G32B32_FLOAT, 0); vformat.Bind(VA_TEXCOORD, DF_R32_FLOAT, 0); std::shared_ptr<VertexBuffer> vbuffer(new VertexBuffer(vformat, numParticles)); Memcpy(vbuffer->GetData(), &particles[0], numParticles*sizeof(Vertex)); #else // Create a mesh for indirect drawing. std::shared_ptr<VertexBuffer> vbuffer(new VertexBuffer(numParticles)); mParticles = std::make_shared<StructuredBuffer>(numParticles, sizeof(Vertex)); Memcpy(mParticles->GetData(), &particles[0], numParticles*sizeof(Vertex)); gshader->Set("particles", mParticles); #endif std::shared_ptr<IndexBuffer> ibuffer(new IndexBuffer(IP_POLYPOINT, numParticles)); std::shared_ptr<VisualEffect> effect = std::make_shared<VisualEffect>(program); mMesh = std::make_shared<Visual>(vbuffer, ibuffer, effect); return true; }
void MinimumVolumeBox3DWindow::CreateScene() { mScene = std::make_shared<Node>(); std::mt19937 mte; std::uniform_real_distribution<float> rnd(-1.0f, 1.0f); Vector3<float> center{ 0.0f, 0.0f, 0.0f }; Vector3<float> extent{ 1.0f, 0.25f, 0.125f }; Vector3<float> axis[3] = { { 1.0f, 1.0f, 0.0f }, { -1.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, 1.0f } }; Normalize(axis[0]); Normalize(axis[1]); Normalize(axis[2]); for (auto& v : mVertices) { float theta = rnd(mte) * (float)GTE_C_TWO_PI; float phi = rnd(mte) * (float)GTE_C_PI; float radius = 0.5f * (rnd(mte) + 1.0f); float x = extent[0] * cos(theta) * sin(phi); float y = extent[1] * sin(theta) * sin(phi); float z = extent[2] * cos(phi); v = center + radius * (x * axis[0] + y * axis[1] + z * axis[2]); } struct Vertex { Vector3<float> position; Vector4<float> color; }; VertexFormat vformat; vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0); vformat.Bind(VA_COLOR, DF_R32G32B32A32_FLOAT, 0); std::shared_ptr<VertexBuffer> vbuffer(new VertexBuffer(vformat, NUM_POINTS)); Vertex* vertex = vbuffer->Get<Vertex>(); for (int i = 0; i < NUM_POINTS; ++i) { vertex[i].position[0] = (float)mVertices[i][0]; vertex[i].position[1] = (float)mVertices[i][1]; vertex[i].position[2] = (float)mVertices[i][2]; vertex[i].color[0] = 0.5f * (rnd(mte) + 1.0f); vertex[i].color[1] = 0.5f * (rnd(mte) + 1.0f); vertex[i].color[2] = 0.5f * (rnd(mte) + 1.0f); vertex[i].color[3] = 1.0f; } std::shared_ptr<IndexBuffer> ibuffer(new IndexBuffer(IP_POLYPOINT, NUM_POINTS)); std::shared_ptr<VertexColorEffect> effect = std::make_shared<VertexColorEffect>(mProgramFactory); mPoints = std::make_shared<Visual>(vbuffer, ibuffer, effect); mCameraRig.Subscribe(mPoints->worldTransform, effect->GetPVWMatrixConstant()); mScene->AttachChild(mPoints); // Choose the number of threads to use. The default constructor for // MinimumVolumeBox3 uses a default of 1, in which case all computations // are on the main thread. The timings below are for a 64-bit release // build (no debugger attached) on Intel Core i7-3930K CPUs running at // 3.20 GHz. unsigned int numThreads = 1; #if 0 // Compute the convex hull internally using arbitrary precision // arithmetic. This is slower than computing the hull explicitly using // the maximum fixed precision; see the other conditional block of code. Timer timer; typedef BSRational<UIntegerAP32> MVBRational; MinimumVolumeBox3<float, MVBRational> mvb3(numThreads); OrientedBox3<float> minBox = mvb3(NUM_POINTS, &mVertices[0]); std::cout << "mvb3 seconds = " << timer.GetSeconds() << std::endl; // numThreads = 1, seconds = 7.09 // numThreads = 2, seconds = 6.22 #else // If mVertices were to use 'double', you would need the template type // UIntegerFP32<167> to compute the convex hull. Timer timer; typedef BSNumber<UIntegerFP32<27>> CHRational; ConvexHull3<float, CHRational> ch3(numThreads); ch3(NUM_POINTS, &mVertices[0], 0.0f); std::vector<TriangleKey<true>> const& triangles = ch3.GetHullUnordered(); int const numIndices = static_cast<int>(3 * triangles.size()); int const* indices = static_cast<int const*>(&triangles[0].V[0]); typedef BSRational<UIntegerAP32> MVBRational; MinimumVolumeBox3<float, MVBRational> mvb3(numThreads); OrientedBox3<float> minBox = mvb3(NUM_POINTS, &mVertices[0], numIndices, indices); std::cout << "mvb3 seconds = " << timer.GetSeconds() << std::endl; // numThreads = 1, seconds = 2.69 // numThreads = 2, seconds = 2.01 #endif std::vector<int> const& hull = mvb3.GetHull(); ibuffer = std::make_shared<IndexBuffer>(IP_TRIMESH, static_cast<int>(hull.size() / 3), sizeof(int)); Memcpy(ibuffer->GetData(), &hull[0], ibuffer->GetNumBytes()); mPolytope = std::make_shared<Visual>(vbuffer, ibuffer, effect); mScene->AttachChild(mPolytope); MeshFactory mf; mf.SetVertexFormat(vformat); mBoxMesh = mf.CreateBox(1.0f, 1.0f, 1.0f); vbuffer = mBoxMesh->GetVertexBuffer(); vertex = vbuffer->Get<Vertex>(); std::array<Vector3<float>, 8> corner; minBox.GetVertices(corner); for (int i = 0; i < 8; ++i) { vertex[i].position[0] = corner[i][0]; vertex[i].position[1] = corner[i][1]; vertex[i].position[2] = corner[i][2]; vertex[i].color[0] = 0.5f * (rnd(mte) + 1.0f); vertex[i].color[1] = 0.5f * (rnd(mte) + 1.0f); vertex[i].color[2] = 0.5f * (rnd(mte) + 1.0f); vertex[i].color[3] = 1.0f; } mBoxMesh->SetEffect(effect); mScene->AttachChild(mBoxMesh); mTrackball.Attach(mScene); mTrackball.Update(); }
BipedManager::BipedManager(std::string const& rootPath, std::string const& bname, ProgramFactory& programFactory, SkinController::Updater const& postUpdate) { // Vertex format shared by the two skins. VertexFormat vformat; vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0); vformat.Bind(VA_NORMAL, DF_R32G32B32_FLOAT, 0); vformat.Bind(VA_TEXCOORD, DF_R32G32_FLOAT, 0); // Create the texture effects for the two skins. std::shared_ptr<Texture2> texture[2]; std::shared_ptr<Texture2Effect> effect[2]; for (int i = 0; i < 2; ++i) { std::string name = rootPath + "Skins/Skins" + std::to_string(i) + ".texture.png"; texture[i].reset(WICFileIO::Load(name, true)); texture[i]->AutogenerateMipmaps(); effect[i] = std::make_shared<Texture2Effect>(programFactory, texture[i], SamplerState::MIN_L_MAG_L_MIP_L, SamplerState::WRAP, SamplerState::WRAP); } PreSpatialArray preSpatialArray; PreSkinArray preSkinArray; SpatialMap spatialMap; std::string filename = rootPath + bname + ".txt"; std::ifstream inFile(filename); while (!inFile.eof()) { std::string line; getline(inFile, line); if (line == "") { // The file contains no blank lines, except for the very last one. break; } // Strip off initial white space. std::string::size_type begin = line.find_first_not_of(" "); if (begin > 0) { line = line.substr(begin); } std::string::size_type end; std::string name; if (line.find("Node") == 0) { // Load the node. begin = line.find("<"); end = line.find(">"); name = line.substr(begin + 1, end - 1 - begin); if (name.back() == 'X') { // TODO: These nodes are not necessary. Remove them from the // data sets. continue; } PreSpatial* preSpatial = LoadNode(rootPath, name); preSpatialArray.push_back(preSpatial); Node* node = reinterpret_cast<Node*>(preSpatial->Associate); spatialMap[name] = node; // Load the transform controllers. NodeCtrl nc; nc.first = node; nc.second.reset(LoadTransformController(rootPath, name, "Idle")); mIdleArray.push_back(nc); nc.second.reset(LoadTransformController(rootPath, name, "Walk")); mWalkArray.push_back(nc); nc.second.reset(LoadTransformController(rootPath, name, "Run")); mRunArray.push_back(nc); } else if (line.find("TriMesh") == 0) { // Load the mesh. begin = line.find("<"); end = line.find(">"); name = line.substr(begin + 1, end - 1 - begin); int suffix = name[name.length() - 1] - '0'; PreSpatial* preSpatial = LoadMesh(rootPath, name, vformat, effect[suffix]); preSpatialArray.push_back(preSpatial); spatialMap[name] = preSpatial->Associate; // Load the skin controller. PreSkin* preSkin = LoadSkinController(rootPath, name, postUpdate); preSkinArray.push_back(preSkin); // Attach the skin controller to the mesh. preSpatial->Associate->AttachController(preSkin->Associate); } } // Resolve the bone links. for (auto preSkin : preSkinArray) { SkinController* ctrl = preSkin->Associate; Node** bones = ctrl->GetBones(); int i = 0; for (auto const& boneName : preSkin->BoneNames) { auto iter = spatialMap.find(boneName); bones[i] = reinterpret_cast<Node*>(iter->second); ++i; } } // Assemble the biped hierarchy. for (auto preSpatial : preSpatialArray) { Node* node = dynamic_cast<Node*>(preSpatial->Associate); if (node) { for (auto const& childName : preSpatial->ChildNames) { if (childName.back() == 'X') { // TODO: These nodes are not necessary. Remove them from // the data sets. continue; } auto iter = spatialMap.find(childName); Visual* mesh = dynamic_cast<Visual*>(iter->second); if (mesh) { std::shared_ptr<Visual> visual(mesh); node->AttachChild(visual); if (visual->GetEffect().get() == effect[0].get()) { mSubscribers[0].first = visual; mSubscribers[0].second = effect[0]->GetPVWMatrixConstant(); } else { mSubscribers[1].first = visual; mSubscribers[1].second = effect[1]->GetPVWMatrixConstant(); } } else { node->AttachChild(std::shared_ptr<Spatial>(iter->second)); } } } } mRoot.reset(reinterpret_cast<Node*>(preSpatialArray[0]->Associate)); for (auto preSpatial : preSpatialArray) { delete preSpatial; } for (auto preSkin : preSkinArray) { delete preSkin; } // Create the blend controllers. int const numControllers = static_cast<int>(mIdleArray.size()); mIdleWalkArray.resize(numControllers); mWalkRunArray.resize(numControllers); for (int i = 0; i < numControllers; ++i) { NodeCtrl const& nc0 = mIdleArray[i]; NodeCtrl const& nc1 = mWalkArray[i]; NodeCtrl const& nc2 = mRunArray[i]; mIdleWalkArray[i].first = nc0.first; mIdleWalkArray[i].second = std::make_shared<BlendTransformController>( nc0.second, nc1.second, true, false); mWalkRunArray[i].first = nc0.first; mWalkRunArray[i].second = std::make_shared<BlendTransformController>( nc1.second, nc2.second, true, false); } }
void BSplineSurfaceFitterWindow::CreateScene() { // Begin with a flat 64x64 height field. int const numSamples = 64; float const extent = 8.0f; VertexFormat hfformat; hfformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0); hfformat.Bind(VA_TEXCOORD, DF_R32G32_FLOAT, 0); MeshFactory mf; mf.SetVertexFormat(hfformat); mHeightField = mf.CreateRectangle(numSamples, numSamples, extent, extent); int numVertices = numSamples * numSamples; VertexPT* hfvertices = mHeightField->GetVertexBuffer()->Get<VertexPT>(); // Set the heights based on a precomputed height field. Also create a // texture image to go with the height field. std::string path = mEnvironment.GetPath("BTHeightField.png"); std::shared_ptr<Texture2> texture(WICFileIO::Load(path, false)); std::shared_ptr<Texture2Effect> txeffect = std::make_shared<Texture2Effect>(mProgramFactory, texture, SamplerState::MIN_L_MAG_L_MIP_P, SamplerState::CLAMP, SamplerState::CLAMP); mHeightField->SetEffect(txeffect); std::mt19937 mte; std::uniform_real_distribution<float> symmr(-0.05f, 0.05f); std::uniform_real_distribution<float> intvr(32.0f, 64.0f); unsigned char* data = (unsigned char*)texture->Get<unsigned char>(); std::vector<Vector3<float>> samplePoints(numVertices); for (int i = 0; i < numVertices; ++i) { unsigned char value = *data; float height = 3.0f*((float)value) / 255.0f + symmr(mte); *data++ = (unsigned char)intvr(mte); *data++ = 3 * (128 - value / 2) / 4; *data++ = 0; data++; hfvertices[i].position[2] = height; samplePoints[i] = hfvertices[i].position; } // Compute a B-Spline surface with NxN control points, where N < 64. // This surface will be sampled to 64x64 and displayed together with the // original height field for comparison. int const numControls = 32; int const degree = 3; BSplineSurfaceFit<float> fitter(degree, numControls, numSamples, degree, numControls, numSamples, &samplePoints[0]); VertexFormat ffformat; ffformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0); ffformat.Bind(VA_COLOR, DF_R32G32B32A32_FLOAT, 0); mf.SetVertexFormat(ffformat); mFittedField = mf.CreateRectangle(numSamples, numSamples, extent, extent); VertexPC* ffvertices = mFittedField->GetVertexBuffer()->Get<VertexPC>(); Vector4<float> translucent{ 1.0f, 1.0f, 1.0f, 0.5f }; for (int i = 0; i < numVertices; ++i) { float u = 0.5f*(ffvertices[i].position[0] / extent + 1.0f); float v = 0.5f*(ffvertices[i].position[1] / extent + 1.0f); ffvertices[i].position = fitter.GetPosition(u, v); ffvertices[i].color = translucent; } std::shared_ptr<VertexColorEffect> vceffect = std::make_shared<VertexColorEffect>(mProgramFactory); mFittedField->SetEffect(vceffect); mCameraRig.Subscribe(mHeightField->worldTransform, txeffect->GetPVWMatrixConstant()); mCameraRig.Subscribe(mFittedField->worldTransform, vceffect->GetPVWMatrixConstant()); mTrackball.Attach(mHeightField); mTrackball.Attach(mFittedField); mTrackball.Update(); }
bool ConvexHull3DWindow::LoadData() { std::string filename = "data"; if (mCurrentFile < 10) { filename += "0"; } filename += std::to_string(mCurrentFile) + ".txt"; std::string path = mEnvironment.GetPath(filename); if (path == "") { return false; } std::ifstream input(path); if (!input) { return false; } Vector3<float> center{ 0.0f, 0.0f, 0.0f }; unsigned int numVertices; input >> numVertices; std::vector<Vector3<float>> vertices(numVertices); for (auto& v : vertices) { for (int j = 0; j < 3; ++j) { input >> v[j]; } center += v; } input.close(); center /= static_cast<float>(numVertices); float radius = 0.0f; for (auto const& v : vertices) { Vector3<float> diff = v - center; float length = Length(diff); if (length > radius) { radius = length; } } // The worst-case number of words for UIntegerFP32<N> for 'float' input // to ConvexHull3 is N = 27. For 'double', it is 'N = 197'. ConvexHull3<float, BSNumber<UIntegerFP32<27>>> ch; if (numVertices < 4 || !ch(numVertices, &vertices[0], 0.0f)) { if (mMesh) { mTrackball.Detach(mMesh); mTrackball.Update(); mCameraRig.Unsubscribe(mMesh->worldTransform); mMesh = nullptr; } mMessage = "File = " + std::to_string(mCurrentFile) + " has intrinsic dimension " + std::to_string(ch.GetDimension()); return false; } #if defined(GTE_COLLECT_BSNUMBER_STATISTICS) std::cout << "max size = " << gte::gBSNumberMaxSize << std::endl; #endif std::vector<TriangleKey<true>> const& triangles = ch.GetHullUnordered(); std::mt19937 mte; std::uniform_real_distribution<float> rnd(0.0f, 1.0f); struct Vertex { Vector3<float> position; Vector4<float> color; }; VertexFormat vformat; vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0); vformat.Bind(VA_COLOR, DF_R32G32B32A32_FLOAT, 0); std::shared_ptr<VertexBuffer> vbuffer(new VertexBuffer(vformat, numVertices)); Vertex* vertex = vbuffer->Get<Vertex>(); for (unsigned int i = 0; i < numVertices; ++i) { vertex[i].position = vertices[i]; vertex[i].color[0] = rnd(mte); vertex[i].color[1] = rnd(mte); vertex[i].color[2] = rnd(mte); vertex[i].color[3] = 1.0f; } unsigned int numPrimitives = static_cast<unsigned int>(triangles.size()); std::shared_ptr<IndexBuffer> ibuffer(new IndexBuffer(IP_TRIMESH, numPrimitives, sizeof(unsigned int))); Memcpy(ibuffer->GetData(), &triangles[0], ibuffer->GetNumBytes()); // Update all information associated with the mesh transforms. if (mMesh) { mTrackball.Detach(mMesh); mTrackball.Update(); mCameraRig.Unsubscribe(mMesh->worldTransform); } mMesh = std::make_shared<Visual>(vbuffer, ibuffer, mEffect); mMesh->localTransform.SetTranslation(-center); mMesh->worldTransform = mMesh->localTransform; mCameraRig.Subscribe(mMesh->worldTransform, mEffect->GetPVWMatrixConstant()); // Move the camera for a centered view of the mesh. Vector4<float> camPosition = Vector4<float>{0.0f, 0.0f, 0.0f, 1.0f} - 2.5f*radius*mCamera->GetDVector(); mCamera->SetPosition(camPosition); // Update the message for display. mMessage = "File = " + std::to_string(mCurrentFile) + " , " + "Vertices = " + std::to_string(numVertices) + " , " + "Triangles =" + std::to_string(numPrimitives); mTrackball.Attach(mMesh); mTrackball.Update(); mCameraRig.UpdatePVWMatrices(); return true; }
void MassSprings3DWindow::CreateBoxFaces() { // The vertex buffer will use the mass-spring position array for its // CPU data. int const numVertices = mDimension[0] * mDimension[1] * mDimension[2]; #if defined(DO_CPU_MASS_SPRING) VertexFormat vformat; vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0); mVBuffer = std::make_shared<VertexBuffer>(vformat, numVertices, false); mVBuffer->SetUsage(Resource::DYNAMIC_UPDATE); #else mVBuffer = std::make_shared<VertexBuffer>(numVertices); #endif size_t const idxsize = sizeof(unsigned int); std::shared_ptr<IndexBuffer> ibuffer; int numTriangles, t, x, y, z, v0, v1, v2, v3; // box face z = 1 numTriangles = 2 * (mDimension[0] - 1) * (mDimension[1] - 1); ibuffer = std::make_shared<IndexBuffer>(IP_TRIMESH, numTriangles, idxsize); for (y = 1, t = 0; y < mDimension[1] - 2; ++y) { for (x = 1; x < mDimension[0] - 2; ++x) { v0 = GetIndex(x, y, 1); v1 = GetIndex(x + 1, y, 1); v2 = GetIndex(x, y + 1, 1); v3 = GetIndex(x + 1, y + 1, 1); ibuffer->SetTriangle(t++, v0, v2, v3); ibuffer->SetTriangle(t++, v0, v3, v1); } } mBoxFace[0] = std::make_shared<Visual>(mVBuffer, ibuffer); // box face z = dim2 - 2 numTriangles = 2 * (mDimension[0] - 1) * (mDimension[1] - 1); ibuffer = std::make_shared<IndexBuffer>(IP_TRIMESH, numTriangles, idxsize); for (y = 1, t = 0; y < mDimension[1] - 2; ++y) { for (x = 1; x < mDimension[0] - 2; ++x) { v0 = GetIndex(x, y, mDimension[2] - 2); v1 = GetIndex(x + 1, y, mDimension[2] - 2); v2 = GetIndex(x, y + 1, mDimension[2] - 2); v3 = GetIndex(x + 1, y + 1, mDimension[2] - 2); ibuffer->SetTriangle(t++, v0, v3, v2); ibuffer->SetTriangle(t++, v0, v1, v3); } } mBoxFace[1] = std::make_shared<Visual>(mVBuffer, ibuffer); // box face y = 1 numTriangles = 2 * (mDimension[0] - 1) * (mDimension[2] - 1); ibuffer = std::make_shared<IndexBuffer>(IP_TRIMESH, numTriangles, idxsize); for (z = 1, t = 0; z < mDimension[2] - 2; ++z) { for (x = 1; x < mDimension[0] - 2; ++x) { v0 = GetIndex(x, 1, z); v1 = GetIndex(x + 1, 1, z); v2 = GetIndex(x, 1, z + 1); v3 = GetIndex(x + 1, 1, z + 1); ibuffer->SetTriangle(t++, v0, v3, v2); ibuffer->SetTriangle(t++, v0, v1, v3); } } mBoxFace[2] = std::make_shared<Visual>(mVBuffer, ibuffer); // box face y = dim1 - 2 numTriangles = 2 * (mDimension[0] - 1) * (mDimension[2] - 1); ibuffer = std::make_shared<IndexBuffer>(IP_TRIMESH, numTriangles, idxsize); for (z = 1, t = 0; z < mDimension[2] - 2; ++z) { for (x = 1; x < mDimension[0] - 2; ++x) { v0 = GetIndex(x, mDimension[1] - 2, z); v1 = GetIndex(x + 1, mDimension[1] - 2, z); v2 = GetIndex(x, mDimension[1] - 2, z + 1); v3 = GetIndex(x + 1, mDimension[1] - 2, z + 1); ibuffer->SetTriangle(t++, v0, v2, v3); ibuffer->SetTriangle(t++, v0, v3, v1); } } mBoxFace[3] = std::make_shared<Visual>(mVBuffer, ibuffer); // box face x = 1 numTriangles = 2 * (mDimension[1] - 1) * (mDimension[2] - 1); ibuffer = std::make_shared<IndexBuffer>(IP_TRIMESH, numTriangles, idxsize); for (z = 1, t = 0; z < mDimension[2] - 2; ++z) { for (y = 1; y < mDimension[1] - 2; ++y) { v0 = GetIndex(1, y, z); v1 = GetIndex(1, y + 1, z); v2 = GetIndex(1, y, z + 1); v3 = GetIndex(1, y + 1, z + 1); ibuffer->SetTriangle(t++, v0, v2, v3); ibuffer->SetTriangle(t++, v0, v3, v1); } } mBoxFace[4] = std::make_shared<Visual>(mVBuffer, ibuffer); // box face x = dim0 - 2 numTriangles = 2 * (mDimension[1] - 1) * (mDimension[2] - 1); ibuffer = std::make_shared<IndexBuffer>(IP_TRIMESH, numTriangles, idxsize); for (z = 1, t = 0; z < mDimension[2] - 2; ++z) { for (y = 1; y < mDimension[1] - 2; ++y) { v0 = GetIndex(mDimension[0] - 2, y, z); v1 = GetIndex(mDimension[0] - 2, y + 1, z); v2 = GetIndex(mDimension[0] - 2, y, z + 1); v3 = GetIndex(mDimension[0] - 2, y + 1, z + 1); ibuffer->SetTriangle(t++, v0, v3, v2); ibuffer->SetTriangle(t++, v0, v1, v3); } } mBoxFace[5] = std::make_shared<Visual>(mVBuffer, ibuffer); Vector4<float> const color[6] = { { 1.0f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f }, { 1.0f, 0.0f, 1.0f, 1.0f }, { 1.0f, 1.0f, 0.0f, 1.0f } }; #if defined(DO_CPU_MASS_SPRING) for (int i = 0; i < 6; ++i) { mEffect[i] = std::make_shared<ConstantColorEffect>(color[i]); mBoxFace[i]->SetEffect(mEffect[i]); } #else std::string path = mEnvironment.GetPath("DrawUsingVertexID.hlsl"); std::shared_ptr<ConstantBuffer> pvwMatrixBuffer; std::shared_ptr<ConstantBuffer> colorBuffer; std::shared_ptr<VisualProgram> program; std::shared_ptr<VertexShader> vshader; std::shared_ptr<PixelShader> pshader; for (int i = 0; i < 6; ++i) { pvwMatrixBuffer = std::make_shared<ConstantBuffer>( sizeof(Matrix4x4<float>), true); colorBuffer = std::make_shared<ConstantBuffer>( sizeof(Vector4<float>), false); *colorBuffer->Get<Vector4<float>>() = color[i]; // TODO: Need to terminate application if 'program' is null. program = mProgramFactory.CreateFromFiles(path, path, ""); vshader = program->GetVShader(); vshader->Set("PVWMatrix", pvwMatrixBuffer); vshader->Set("ConstantColor", colorBuffer); vshader->Set("position", mMassSprings->GetPosition()); mEffect[i] = std::make_shared<VisualEffect>(program); mBoxFace[i]->SetEffect(mEffect[i]); } #endif }
void LightsWindow::CreateScene() { // Copper color for the planes. Vector4<float> planeAmbient{ 0.2295f, 0.08825f, 0.0275f, 1.0f }; Vector4<float> planeDiffuse{ 0.5508f, 0.2118f, 0.066f, 1.0f }; Vector4<float> planeSpecular{ 0.580594f, 0.223257f, 0.0695701f, 51.2f }; // Gold color for the spheres. Vector4<float> sphereAmbient{ 0.24725f, 0.2245f, 0.0645f, 1.0f }; Vector4<float> sphereDiffuse{ 0.34615f, 0.3143f, 0.0903f, 1.0f }; Vector4<float> sphereSpecular{ 0.797357f, 0.723991f, 0.208006f, 83.2f }; // Various parameters shared by the lighting constants. The geometric // parameters are dynamic, modified by UpdateConstants() whenever the // camera or scene moves. These include camera model position, light // model position, light model direction, and model-to-world matrix. Vector4<float> darkGray{ 0.1f, 0.1f, 0.1f, 1.0f }; Vector4<float> lightGray{ 0.75f, 0.75f, 0.75f, 1.0f }; float angle = 0.125f*(float)GTE_C_PI; Vector4<float> lightSpotCutoff{ angle, cos(angle), sin(angle), 1.0f }; mLightWorldPosition[SVTX] = { 4.0f, 4.0f - 8.0f, 8.0f, 1.0f }; mLightWorldPosition[SPXL] = { 4.0f, 4.0f + 8.0f, 8.0f, 1.0f }; mLightWorldDirection = { -1.0f, -1.0f, -1.0f, 0.0f }; Normalize(mLightWorldDirection); std::shared_ptr<Material> material[LNUM][GNUM]; std::shared_ptr<Lighting> lighting[LNUM][GNUM]; std::shared_ptr<LightCameraGeometry> geometry[LNUM][GNUM]; for (int lt = 0; lt < LNUM; ++lt) { for (int gt = 0; gt < GNUM; ++gt) { material[lt][gt] = std::make_shared<Material>(); lighting[lt][gt] = std::make_shared<Lighting>(); geometry[lt][gt] = std::make_shared<LightCameraGeometry>(); } } // Initialize the directional lighting constants. material[LDIR][GPLN]->ambient = planeAmbient; material[LDIR][GPLN]->diffuse = planeDiffuse; material[LDIR][GPLN]->specular = planeSpecular; lighting[LDIR][GPLN]->ambient = lightGray; material[LDIR][GSPH]->ambient = sphereAmbient; material[LDIR][GSPH]->diffuse = sphereDiffuse; material[LDIR][GSPH]->specular = sphereSpecular; lighting[LDIR][GSPH]->ambient = lightGray; // Initialize the point lighting constants. material[LPNT][GPLN]->ambient = planeAmbient; material[LPNT][GPLN]->diffuse = planeDiffuse; material[LPNT][GPLN]->specular = planeSpecular; lighting[LPNT][GPLN]->ambient = darkGray; material[LPNT][GSPH]->ambient = sphereAmbient; material[LPNT][GSPH]->diffuse = sphereDiffuse; material[LPNT][GSPH]->specular = sphereSpecular; lighting[LPNT][GSPH]->ambient = darkGray; // Initialize the spot lighting constants. material[LSPT][GPLN]->ambient = planeAmbient; material[LSPT][GPLN]->diffuse = planeDiffuse; material[LSPT][GPLN]->specular = planeSpecular; lighting[LSPT][GPLN]->ambient = darkGray; lighting[LSPT][GPLN]->spotCutoff = lightSpotCutoff; material[LSPT][GSPH]->ambient = sphereAmbient; material[LSPT][GSPH]->diffuse = sphereDiffuse; material[LSPT][GSPH]->specular = sphereSpecular; lighting[LSPT][GSPH]->ambient = darkGray; lighting[LSPT][GSPH]->spotCutoff = lightSpotCutoff; // Create the effects. for (int gt = 0; gt < GNUM; ++gt) { for (int st = 0; st < SNUM; ++st) { mEffect[LDIR][gt][st] = std::make_shared<DirectionalLightEffect>( mProgramFactory, mUpdater, st, material[LDIR][gt], lighting[LDIR][gt], geometry[LDIR][gt]); mEffect[LPNT][gt][st] = std::make_shared<PointLightEffect>( mProgramFactory, mUpdater, st, material[LPNT][gt], lighting[LPNT][gt], geometry[LPNT][gt]); mEffect[LSPT][gt][st] = std::make_shared<SpotLightEffect>( mProgramFactory, mUpdater, st, material[LSPT][gt], lighting[LSPT][gt], geometry[LSPT][gt]); } } // Create the planes and spheres. VertexFormat vformat; vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0); vformat.Bind(VA_NORMAL, DF_R32G32B32_FLOAT, 0); MeshFactory mf; mf.SetVertexFormat(vformat); mPlane[SVTX] = mf.CreateRectangle(128, 128, 8.0f, 8.0f); mPlane[SVTX]->localTransform.SetTranslation(0.0f, -8.0f, 0.0f); mTrackball.Attach(mPlane[SVTX]); mPlane[SPXL] = mf.CreateRectangle(128, 128, 8.0f, 8.0f); mPlane[SPXL]->localTransform.SetTranslation(0.0f, +8.0f, 0.0f); mTrackball.Attach(mPlane[SPXL]); mSphere[SVTX] = mf.CreateSphere(64, 64, 2.0f); mSphere[SVTX]->localTransform.SetTranslation(0.0f, -8.0f, 2.0f); mTrackball.Attach(mSphere[SVTX]); mSphere[SPXL] = mf.CreateSphere(64, 64, 2.0f); mSphere[SPXL]->localTransform.SetTranslation(0.0f, +8.0f, 2.0f); mTrackball.Attach(mSphere[SPXL]); mTrackball.Update(); mCaption[LDIR] = "Directional Light (left per vertex, right per pixel)"; mCaption[LPNT] = "Point Light (left per vertex, right per pixel)"; mCaption[LSPT] = "Spot Light (left per vertex, right per pixel)"; UseLightType(LDIR); }