Exemplo n.º 1
0
	void setupScene()
	{
		m_window->getViewports().front()->setRenderQueueIdMask(~RenderQueueId_OffscreenTransparentObjects);

		LightPtr light(new Light);
		light->setDirection(glm::normalize(glm::vec3(1.5, -1, -0.5)));
		light->setPosition(glm::vec3(0, 0.5, 0) + light->getDirection() * -10.0f);
		m_visSystem->addLight(light);

		// Volume
		std::vector<std::string> gridNames;
		gridNames.push_back(m_config.densityGridName);

		if (!m_config.temperatureGridName.empty())
		{
			gridNames.push_back(m_config.temperatureGridName);
		}

		std::vector<openvdb::GridBase::Ptr> baseGrids = loadGridsFromFile(m_config.vdbVilename, gridNames);

		openvdb::FloatGrid::Ptr densityGrid = openvdb::gridPtrCast<openvdb::FloatGrid>(baseGrids[0]);

		openvdb::FloatGrid::Ptr temperatureGrid;
		if (!m_config.temperatureGridName.empty())
		{
			temperatureGrid = openvdb::gridPtrCast<openvdb::FloatGrid>(baseGrids[1]);

			// Rescale temperature field to between 0 and 1
			{
				float minValue = 99999999999999;
				float maxValue = -99999999999999;
				for (openvdb::FloatGrid::ValueOnCIter iter = temperatureGrid->cbeginValueOn(); iter.test(); ++iter) {
					float value = *iter;
					minValue = std::min(minValue, value);
					maxValue = std::max(maxValue, value);
				}

				float scale = 1.0 / (maxValue - minValue);

				for (openvdb::FloatGrid::ValueOnIter iter = temperatureGrid->beginValueOn(); iter.test(); ++iter) {
					float value = *iter;
					value = (value - minValue) * scale;
					iter.setValue(value);
				}
			}

			// Ensure both grids have the same hierarchy
			{
				openvdb::FloatGrid::Ptr resultGrid = openvdb::FloatGrid::create();
				resultGrid->tree().combine2(densityGrid->tree(), temperatureGrid->tree(), CopyBIntoA());
				temperatureGrid->tree().combine(densityGrid->tree(), CopyBIntoA());

				densityGrid = resultGrid; 
			}
		}

		std::vector<GridPtr> grids;
		GridTextureRolesMap gridTextureRoles;

		grids.push_back(GridPtr(new VdbGrid<openvdb::FloatGrid>(densityGrid, 1)));
		gridTextureRoles[GridTextureRole_Diffuse] = grids.back();

		if (m_config.generateNormals)
		{
			Vec3UByteGrid::Ptr normalGrid = createNormalGrid(*densityGrid);
			grids.push_back(GridPtr(new VdbGrid<Vec3UByteGrid>(normalGrid, 3)));
			gridTextureRoles[GridTextureRole_Normal] = grids.back();
		}

		if (temperatureGrid)
		{
			grids.push_back(GridPtr(new VdbGrid<openvdb::FloatGrid>(temperatureGrid, 1)));
			gridTextureRoles[GridTextureRole_Temperature] = grids.back();
		}

		openvdb::CoordBBox bbox;
		densityGrid->constTree().evalLeafBoundingBox(bbox);

		float scale = 1.0f / (float)bbox.extents().asVec3s().length();

		glm::vec3 center = toVec3(bbox.getCenter() * scale);
		std::ostringstream ss;
		ss << "Grid extents: " << bbox.extents().x() << ", " << bbox.extents().y() << ", " << bbox.extents().z();
		defaultLogger()->logLine(ss.str());

		int renderQueueId;
		if (m_config.renderToLowResTarget)
		{
			renderQueueId = RenderQueueId_OffscreenTransparentObjects;
		}
		else
		{
			renderQueueId = getDefaultRenderQueueId();
		}

		RenderableVolumeConfig config;
		config.grids = grids;
		config.materialFactory.reset(new SparseVolumeMaterialFactoryI(gridTextureRoles, m_config.transparent, m_config.opacityMultiplier));
		config.scale = scale;
		config.batchBoxes = !m_config.transparent; // don't batch if we have transparency so we can sort

		RenderableVolumePtr volume = RenderableVolumeFactory::createRenderableVolume(config);
		BOOST_FOREACH(const GVis::RenderableNodePtr& node, volume->nodes)
		{
			node->translate(-center);
			m_visSystem->addRenderableNode(node, renderQueueId);
		}

		if (m_config.transparent)
		{
			RenderQueuePtr renderQueue = m_visSystem->getRenderQueue(renderQueueId);
			if (renderQueue)
				renderQueue->setSortingMode(RenderSortingMode_BackToFront);
		}

		if (m_config.renderToLowResTarget)
		{
			int volumeTargetWidth = m_window->getWidth() / 2;
			int volumeTargetHeight = m_window->getHeight() / 2;

			TexturePtr offscreenTransparentObjectsTexture;
			// Create offscreen transparent objects target
			{
				ImageTextureConfig config = ImageTextureConfig::createDefault();
				config.width = volumeTargetWidth;
				config.height = volumeTargetHeight;
				config.textureAddressMode = TextureAddressMode_Clamp;
				offscreenTransparentObjectsTexture.reset(new Texture(config));

				{
					RenderTextureTargetConfig config;
					config.texture = offscreenTransparentObjectsTexture;
					config.attachment = FrameBufferAttachment_Color;
					RenderTextureTargetPtr target(new RenderTextureTarget(config));

					{
						ViewportPtr viewport = target->addDefaultViewport(m_camera);
						viewport->setRenderQueueIdMask(RenderQueueId_OffscreenTransparentObjects);
						viewport->setBackgroundColor(glm::vec4(0,0,0,0));
					}

					m_window->addRenderTarget(target);
				}
			}

			// Composite offscreen particles
			{
				TextureUnit textureUnit(offscreenTransparentObjectsTexture, "albedoSampler");

				ShaderProgramPtr shader = ShaderProgram::createShaderProgram(ShaderProgramConfig("Shaders/Common/ScreenQuad.vert", "Shaders/Common/SimpleTextured.frag"));
				TechniquePtr technique(new Technique(shader));
				technique->addTextureUnit(textureUnit);
				technique->setAlphaBlendingMode(AlphaBlendingMode_PreMultiplied);
				MaterialPtr material(new Material);
				material->setTechnique(technique);

				{
					RectangleConfig config = RectangleConfig::defaultWithSize(glm::vec2(2, 2));
					MeshPtr mesh = RectangleMeshFactory::createMesh(config);
					GeoPtr geo(new Geo(mesh, material));
					
					RenderableNodePtr renderableNode = RenderableNode::createWithSingleGeo(geo);
					m_visSystem->addRenderableNode(renderableNode, RenderQueueId_CompositeOffscreenTransparentObjects);
				}
			}
		}

		if (m_config.orbitCam)
		{
			centerNode.reset(new SceneNode);
			centerNode->addChild(m_camera);
			m_cameraInputEnabled = false;
		}
		m_camera->setPosition_parentSpace(glm::vec3(0,0,1.4));
	}
Exemplo n.º 2
0
	void setupScene()
	{
		// Must create ClSystem before OpenGL textures. FIXME: this constraint should be more explicit
		m_clSystem.reset(new ClSystem);

		m_window->getViewports().front()->setRenderQueueIdMask(~RenderQueueId_OffscreenTransparentObjects);

		LightPtr light(new Light);
		light->setDirection(glm::normalize(glm::vec3(1.5, -1, -0.5)));
		light->setPosition(glm::vec3(0, 1.0, 0) + light->getDirection() * -10.0f);
		m_visSystem->addLight(light);

		{
			ShadowProjectorConfig config = ShadowProjectorConfig::createDefault();
			config.sceneHeight = config.sceneWidth = 2;
			config.shadowFormat = ShadowFormat_RGB32F;
			m_shadowProjector.reset(new ShadowProjector(config));
			m_shadowProjector->setLight(light);
			m_window->addRenderTarget(m_shadowProjector->getRenderTextureTarget());
		}

		RenderTextureTargetPtr sceneDepthTarget = createDepthTarget(m_camera, m_window->getWidth(), m_window->getHeight());
		sceneDepthTarget->getViewports().front()->setRenderQueueIdMask(~RenderQueueId_OffscreenTransparentObjects);
		TexturePtr sceneDepthTexture = sceneDepthTarget->getTexture();

		// Volume
		{
			int width = 64;
			int height = 128;
			int depth = 128;
			int size = width * height * depth * 4;
			m_imageData.reset(new unsigned char[size]);
			memset(m_imageData.get(), 0, size);

			// Density texture
			m_textureConfig = ImageTextureConfig::createDefault();
			m_textureConfig.width = width;
			m_textureConfig.height = height;
			m_textureConfig.depth = depth;
			m_textureConfig.is3d = true;
			m_textureConfig.format = PixelFormat_RGBA8;
			m_textureConfig.textureAddressMode = TextureAddressMode_Clamp;
			m_textureConfig.data = m_imageData.get();
			m_fluidStateTexture.reset(new Texture(m_textureConfig));

			// Normal texture
			{
				ImageTextureConfig normalTextureConfig = m_textureConfig;
				normalTextureConfig.width /= 2;
				normalTextureConfig.height /= 2;
				normalTextureConfig.depth /= 2;
				normalTextureConfig.data = 0;
				m_normalTexture.reset(new Texture(normalTextureConfig));
			}


			glm::vec3 boxSize(0.5, 1, 1);
			glm::vec3 volumeTextureSize(m_textureConfig.width, m_textureConfig.height, m_textureConfig.depth);

			MaterialPtr material(new Material);

			// Main technique
			{
				ShaderProgramPtr shader = ShaderProgram::createShaderProgram(ShaderProgramConfig("Shaders/Volume/RaymarchedVolume.vert", "Shaders/Volume/VolumetricSmoke.frag"));
				
				
				TechniquePtr technique(new Technique(shader));
				{
					Vec3ShaderParameterPtr boxModelSizeParameter(new Vec3ShaderParameter("volumeSize_modelSpace", boxSize));
					technique->addCustomShaderParameter(boxModelSizeParameter);

					Vec3ShaderParameterPtr oneOnVolumeTextureSizeParameter(new Vec3ShaderParameter("oneOnVolumeTextureSize", 1.0f / volumeTextureSize));
					technique->addCustomShaderParameter(oneOnVolumeTextureSizeParameter);
					technique->addCustomShaderParameter(ShaderParameterPtr(new FloatShaderParameter("opacityMultiplier", 30.0)));

					technique->setAlphaBlendingMode(AlphaBlendingMode_PreMultiplied);
					{
						TextureUnit unit(m_fluidStateTexture, "albedoSampler");
						technique->addTextureUnit(unit);
					}

					{
						TextureUnit unit(sceneDepthTexture, "sceneDepthSampler");
						technique->addTextureUnit(unit);
					}

					{
						TextureUnit unit(m_shadowProjector->getShadowTexture(), "shadowSampler");
						technique->addTextureUnit(unit);
					}

					{
						TextureUnit unit(m_normalTexture, "normalSampler");
						technique->addTextureUnit(unit);
					}
				}

				material->setTechnique(technique);
			}

			// Deep shadow caster technique
			{
				ShaderProgramPtr shader = ShaderProgram::createShaderProgram(ShaderProgramConfig("Shaders/Volume/RaymarchedVolume.vert", "Shaders/Volume/VolumeShadowCaster.frag"));

				TechniquePtr technique(new Technique(shader));
				{
					Vec3ShaderParameterPtr boxModelSizeParameter(new Vec3ShaderParameter("volumeSize_modelSpace", boxSize));
					technique->addCustomShaderParameter(boxModelSizeParameter);

					Vec3ShaderParameterPtr oneOnVolumeTextureSizeParameter(new Vec3ShaderParameter("oneOnVolumeTextureSize", 1.0f / volumeTextureSize));
					technique->addCustomShaderParameter(oneOnVolumeTextureSizeParameter);
					technique->addCustomShaderParameter(ShaderParameterPtr(new FloatShaderParameter("opacityMultiplier", 0.8)));

					{
						TextureUnit unit(m_fluidStateTexture, "albedoSampler");
						technique->addTextureUnit(unit);
					}
				}

				material->setTechnique(technique, TechniqueCategory_DepthRtt);
			}

			{
				BoxConfig config;
				config.size = boxSize;
				MeshPtr mesh = BoxMeshFactory::createMesh(config);
				GeoPtr geo(new Geo(mesh, material));

				RenderableNodePtr renderableNode(new RenderableNode);
				renderableNode->addRenderable(geo);
				renderableNode->setPosition(glm::vec3(0, 0.5, 0));
				m_visSystem->addRenderableNode(renderableNode, RenderQueueId_OffscreenTransparentObjects);
			}
		}

		// Scene geo
		{
			ShadowedMaterialFactory materialFactory(m_shadowProjector->getShadowTexture());
			// Ground plane
			{
				RectangleConfig config = RectangleConfig::defaultWithSize(glm::vec2(5, 5));
				config.orientation = glm::angleAxis(halfPi(), glm::vec3(-1, 0, 0));
				MeshPtr mesh = RectangleMeshFactory::createMesh(config);

				GeoPtr geo(new Geo(mesh, materialFactory.createMaterial(TextureRoles())));
				RenderableNodePtr renderableNode = RenderableNode::createWithSingleGeo(geo);
				m_visSystem->addRenderableNode(renderableNode);
			}
		}

		int volumeTargetWidth = m_window->getWidth() / 2;
		int volumeTargetHeight = m_window->getHeight() / 2;

		TexturePtr offscreenTransparentObjectsTexture;
		// Create offscreen transparent objects target
		{
			ImageTextureConfig config = ImageTextureConfig::createDefault();
			config.width = volumeTargetWidth;
			config.height = volumeTargetHeight;
			config.textureAddressMode = TextureAddressMode_Clamp;
			offscreenTransparentObjectsTexture.reset(new Texture(config));

			{
				RenderTextureTargetConfig config;
				config.texture = offscreenTransparentObjectsTexture;
				config.attachment = FrameBufferAttachment_Color;
				RenderTextureTargetPtr target(new RenderTextureTarget(config));

				{
					ViewportPtr viewport = target->addDefaultViewport(m_camera);
					viewport->setRenderQueueIdMask(RenderQueueId_OffscreenTransparentObjects);
					viewport->setBackgroundColor(glm::vec4(0,0,0,0));
				}

				m_window->addRenderTarget(target);
			}
		}

		// Composite offscreen particles
		{
			TextureUnit textureUnit(offscreenTransparentObjectsTexture, "albedoSampler");

			ShaderProgramPtr shader = ShaderProgram::createShaderProgram(ShaderProgramConfig("Shaders/Common/ScreenQuad.vert", "Shaders/Common/SimpleTextured.frag"));
			TechniquePtr technique(new Technique(shader));
			technique->addTextureUnit(textureUnit);
			technique->setAlphaBlendingMode(AlphaBlendingMode_PreMultiplied);
			MaterialPtr material(new Material);
			material->setTechnique(technique);

			{
				RectangleConfig config = RectangleConfig::defaultWithSize(glm::vec2(2, 2));
				MeshPtr mesh = RectangleMeshFactory::createMesh(config);
				GeoPtr geo(new Geo(mesh, material));

				RenderableNodePtr renderableNode(new RenderableNode);
				renderableNode->addRenderable(geo);
				m_visSystem->addRenderableNode(renderableNode, RenderQueueId_CompositeOffscreenTransparentObjects);
			}
		}

		int tempBufferElementCount = m_textureConfig.width * m_textureConfig.height * m_textureConfig.depth;

		std::string fluidKernelsDir = "Kernels/Fluid";

		TempBufferPoolPtr tempBufferPool(new TempBufferPool(*m_clSystem, tempBufferElementCount));
		m_solver = createFluidSolver(*m_clSystem, getGlTexture(m_fluidStateTexture), tempBufferPool, fluidKernelsDir);
		FluidSolverParamsPtr params = m_solver->getParams();
		params->temperatureBuoyancy = 15;
		params->densityWeight = 2.0;
		params->drag = 0.05;

		m_isosurfaceNormalCalculator = createIsosurfaceNormalCalculator(*m_clSystem, getGlTexture(m_normalTexture), m_solver, tempBufferPool, fluidKernelsDir);

		m_camera->setPosition(glm::vec3(2.2, 0.5, 0.7));
		m_cameraController->rotate(1.2, -0.05);
	}