瀏覽代碼

Renderer: Optimize omni shadows. CMake: Install the binaries to a dir

Panagiotis Christopoulos Charitos 8 年之前
父節點
當前提交
b1ae14eb24

+ 10 - 10
CMakeLists.txt

@@ -2,6 +2,16 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
 
 PROJECT(anki)
 
+################################################################################
+# Funcs                                                                        #
+################################################################################
+
+function(installExecutable exe)
+	add_custom_command(TARGET ${exe} POST_BUILD
+		COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/bin
+		COMMAND ${CMAKE_COMMAND} -E copy ${exe} ${CMAKE_BINARY_DIR}/bin)
+endfunction()
+
 ################################################################################
 # Determin the system to build for. Do that first                              #
 ################################################################################
@@ -201,15 +211,6 @@ set(CMAKE_CXX_FLAGS "${CXX_FLAGS} ${COMPILER_FLAGS}")
 set(CMAKE_C_FLAGS "${COMPILER_FLAGS}")
 set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LINKER_FLAGS}")
 
-################################################################################
-# Install                                                                      #
-################################################################################
-set(INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/src/" CACHE PATH "The subdirectory to the header prefix")
-set(LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Library install path")
-
-message("++ Include install dir: ${INCLUDE_INSTALL_DIR}")
-message("++ Lib install dir: ${LIB_INSTALL_DIR}")
-
 ################################################################################
 # Thirdparty                                                                   #
 ################################################################################
@@ -325,7 +326,6 @@ else()
 endif()
 
 configure_file("src/anki/Config.h.cmake" "${CMAKE_CURRENT_BINARY_DIR}/anki/Config.h")
-install(FILES "${CMAKE_CURRENT_BINARY_DIR}/anki/Config.h" DESTINATION "${INCLUDE_INSTALL_DIR}/anki")
 
 # Include & lib directories
 include_directories("src"

+ 3 - 3
README.md

@@ -77,11 +77,11 @@ To build the release version open `PowerShell` and type:
 3 Next steps
 ============
 
-Try to build with `samples` enabled (search for the `ANKI_BUILD_SAMPLES` option in your CMake GUI) and try running the 
-sponza executable. Then you will be able to see sponza running in AnKi. All samples must run from within their 
+Try to build with `samples` enabled (search for the `ANKI_BUILD_SAMPLES=ON` option in your CMake GUI) and try running 
+the sponza executable. Then you will be able to see sponza running in AnKi. All samples must run from within their 
 directory.
 
 	$cd path/to/anki/samples/sponza
-	$./path/to/build/samples/sponza/sponza
+	$./path/to/build/bin/sponza
 
 More samples will follow.

+ 7 - 3
programs/LightShading.ankiprog

@@ -213,10 +213,14 @@ void main()
 
 		LIGHTING_COMMON_BRDF();
 
-		if(light.cubeFaceCoordinates[0].x >= 0.0)
+		if(light.diffuseColorShadowmapId.w >= 0.0)
 		{
-			float shadow = computeShadowFactorOmni(
-				frag2Light, light.specularColorRadius.w, u_invViewRotation, light.cubeFaceCoordinates, u_shadowTex);
+			float shadow = computeShadowFactorOmni(frag2Light, 
+				light.specularColorRadius.w, 
+				u_invViewRotation, 
+				light.atlasTilesPad2.xy, 
+				light.diffuseColorShadowmapId.w,
+				u_shadowTex);
 			lambert *= shadow;
 		}
 

+ 7 - 3
programs/VolumetricFog.ankiprog

@@ -73,10 +73,14 @@ vec3 computeLightColor(vec3 fragPos, uint plightCount, uint plightIdx, uint slig
 		float factor = computeAttenuationFactor(light.posRadius.w, frag2Light);
 
 #if ENABLE_SHADOWS
-		if(light.cubeFaceCoordinates[0].x >= 0.0)
+		if(light.diffuseColorShadowmapId.w >= 0.0)
 		{
-			factor *= computeShadowFactorOmni(
-				frag2Light, -1.0 / light.posRadius.w, u_invViewRotation, light.cubeFaceCoordinates, u_shadowTex);
+			factor *= computeShadowFactorOmni(frag2Light, 
+				-1.0 / light.posRadius.w, 
+				u_invViewRotation, 
+				light.atlasTilesPad2.xy,
+				light.diffuseColorShadowmapId.w,
+				u_shadowTex);
 		}
 #endif
 

+ 10 - 1
samples/common/Framework.cpp

@@ -7,8 +7,17 @@
 
 using namespace anki;
 
-Error SampleApp::init(int argc, char** argv)
+Error SampleApp::init(int argc, char** argv, CString sampleName)
 {
+	if(!directoryExists("assets"))
+	{
+		ANKI_LOGE("Cannot find directory \"assets\". YOU ARE RUNNING THE SAMPLE FROM THE WRONG DIRECTORY. "
+				  "To run %s you have to navigate to the /path/to/anki/samples/%s and then execute it",
+			argv[0],
+			&sampleName[0]);
+		return Error::USER_DATA;
+	}
+
 	// Init the super class
 	Config config;
 	config.set("window.fullscreenDesktopResolution", true);

+ 1 - 1
samples/common/Framework.h

@@ -10,7 +10,7 @@
 class SampleApp : public anki::App
 {
 public:
-	anki::Error init(int argc, char** argv);
+	anki::Error init(int argc, char** argv, anki::CString sampleName);
 	anki::Error userMainLoop(anki::Bool& quit) override;
 
 	virtual anki::Error sampleExtraInit() = 0;

+ 2 - 0
samples/simple_scene/CMakeLists.txt

@@ -1,2 +1,4 @@
 add_executable(simple_scene Main.cpp ../common/Framework.cpp)
 target_link_libraries(simple_scene anki)
+
+installExecutable(simple_scene)

+ 2 - 4
samples/simple_scene/Main.cpp

@@ -25,7 +25,7 @@ int main(int argc, char* argv[])
 	Error err = Error::NONE;
 
 	MyApp* app = new MyApp;
-	err = app->init(argc, argv);
+	err = app->init(argc, argv, "simple_scene");
 	if(!err)
 	{
 		err = app->mainLoop();
@@ -33,9 +33,7 @@ int main(int argc, char* argv[])
 
 	if(err)
 	{
-		ANKI_LOGE("Error reported. To run %s you have to navigate to the /path/to/anki/samples/simple_scene. "
-				  "And then execute it",
-			argv[0]);
+		ANKI_LOGE("Error reported. Bye!");
 	}
 	else
 	{

+ 1 - 0
samples/sponza/CMakeLists.txt

@@ -1,2 +1,3 @@
 add_executable(sponza Main.cpp ../common/Framework.cpp)
 target_link_libraries(sponza anki)
+installExecutable(sponza)

+ 1 - 1
samples/sponza/Main.cpp

@@ -27,7 +27,7 @@ int main(int argc, char* argv[])
 	Error err = Error::NONE;
 
 	MyApp* app = new MyApp;
-	err = app->init(argc, argv);
+	err = app->init(argc, argv, "sponza");
 	if(!err)
 	{
 		err = app->mainLoop();

+ 1 - 0
sandbox/CMakeLists.txt

@@ -1,3 +1,4 @@
 add_definitions(-UANKI_BUILD)
 add_executable(sandbox Main.cpp)
 target_link_libraries(sandbox anki) 
+installExecutable(sandbox)

+ 2 - 2
shaders/ClusterLightCommon.glsl

@@ -25,9 +25,9 @@ struct LightingUniforms
 struct PointLight
 {
 	vec4 posRadius; // xyz: Light pos in view space. w: The -1/(radius^2)
-	vec4 diffuseColorShadowmapId; // xyz: diff color, w: unused
+	vec4 diffuseColorShadowmapId; // xyz: diff color, w: tile size in the shadow atlas
 	vec4 specularColorRadius; // xyz: spec color, w: radius
-	vec4 cubeFaceCoordinates[6]; // xy: uv offset, zw: uv scale
+	uvec4 atlasTilesPad2; // x: encodes 6 uints with atlas tile indices in the x dir. y: same for y dir.
 };
 
 // Spot light

+ 7 - 3
shaders/ForwardShadingCommonFrag.glsl

@@ -75,10 +75,14 @@ vec3 computeLightColor(vec3 diffCol)
 		const float shadow = 1.0;
 #else
 		float shadow = 1.0;
-		if(light.cubeFaceCoordinates[0].x >= 0.0)
+		if(light.diffuseColorShadowmapId.w >= 0.0)
 		{
-			shadow = computeShadowFactorOmni(
-				frag2Light, light.specularColorRadius.w, u_invViewRotation, light.cubeFaceCoordinates, u_shadowTex);
+			shadow = computeShadowFactorOmni(frag2Light,
+				light.specularColorRadius.w,
+				u_invViewRotation,
+				light.atlasTilesPad2.xy,
+				light.diffuseColorShadowmapId.w,
+				u_shadowTex);
 		}
 #endif
 

+ 29 - 0
shaders/Functions.glsl

@@ -214,6 +214,35 @@ vec2 convertCubeUvs(vec3 v, out float faceIndex)
 	return 0.5 / mag * uv + 0.5;
 }
 
+// Same as convertCubeUvs but it returns the faceIndex as unsigned int.
+vec2 convertCubeUvsu(vec3 v, out uint faceIndex)
+{
+	vec3 absV = abs(v);
+	float mag;
+	vec2 uv;
+
+	if(all(greaterThanEqual(absV.zz, absV.xy)))
+	{
+		faceIndex = (v.z < 0.0) ? 5u : 4u;
+		uv = vec2((v.z < 0.0) ? -v.x : v.x, -v.y);
+		mag = absV.z;
+	}
+	else if(absV.y >= absV.x)
+	{
+		faceIndex = (v.y < 0.0) ? 3u : 2u;
+		uv = vec2(v.x, (v.y < 0.0) ? -v.z : v.z);
+		mag = absV.y;
+	}
+	else
+	{
+		faceIndex = (v.x < 0.0) ? 1u : 0u;
+		uv = vec2((v.x < 0.0) ? v.z : -v.z, -v.y);
+		mag = absV.x;
+	}
+
+	return 0.5 / mag * uv + 0.5;
+}
+
 vec3 grayScale(vec3 col)
 {
 	float grey = (col.r + col.g + col.b) * (1.0 / 3.0);

+ 13 - 4
shaders/LightFunctions.glsl

@@ -104,7 +104,7 @@ float computeShadowFactorSpot(mat4 lightProjectionMat, vec3 fragPos, float dista
 }
 
 float computeShadowFactorOmni(
-	vec3 frag2Light, float radius, mat3 invViewMat, vec4 cubeFaceCoords[6], sampler2D shadowMap)
+	vec3 frag2Light, float radius, mat3 invViewMat, uvec2 atlasTiles, float tileSize, sampler2D shadowMap)
 {
 	vec3 dir = invViewMat * -frag2Light;
 	vec3 dirabs = abs(dir);
@@ -118,9 +118,18 @@ float computeShadowFactorOmni(
 	// Read tex
 	float shadowFactor;
 	{
-		float faceIdx;
-		vec2 uv = convertCubeUvs(dir, faceIdx);
-		uv = fma(uv, cubeFaceCoords[uint(faceIdx)].zw, cubeFaceCoords[uint(faceIdx)].xy);
+		// Convert cube coords
+		uint faceIdxu;
+		vec2 uv = convertCubeUvsu(dir, faceIdxu);
+
+		// Compute atlas tile
+		atlasTiles >>= uvec2(faceIdxu * 5u);
+		atlasTiles &= uvec2(31u);
+
+		// Compute UV
+		uv = (uv + vec2(atlasTiles)) * tileSize;
+
+		// Sample
 		shadowFactor = textureLod(shadowMap, uv, 0.0).r;
 	}
 

+ 11 - 13
src/anki/renderer/LightBin.cpp

@@ -25,23 +25,21 @@ public:
 	U32 m_firstIdx;
 };
 
-class ShaderLight
+class ShaderPointLight
 {
 public:
 	Vec4 m_posRadius;
-	Vec4 m_diffuseColorShadowmapId;
+	Vec4 m_diffuseColorTileSize;
 	Vec4 m_specularColorRadius;
+	UVec4 m_atlasTilesPad2;
 };
 
-class ShaderPointLight : public ShaderLight
-{
-public:
-	Array<Vec4, 6> m_cubeFaceCoordinates;
-};
-
-class ShaderSpotLight : public ShaderLight
+class ShaderSpotLight
 {
 public:
+	Vec4 m_posRadius;
+	Vec4 m_diffuseColorShadowmapId;
+	Vec4 m_specularColorRadius;
 	Vec4 m_lightDir;
 	Vec4 m_outerCosInnerCos;
 	Mat4 m_texProjectionMat; ///< Texture projection matrix
@@ -669,16 +667,16 @@ void LightBin::writeAndBinPointLight(
 	Vec4 pos = ctx.m_viewMat * lightEl.m_worldPosition.xyz1();
 
 	slight.m_posRadius = Vec4(pos.xyz(), 1.0f / (lightEl.m_radius * lightEl.m_radius));
-	slight.m_diffuseColorShadowmapId = lightEl.m_diffuseColor.xyz0();
+	slight.m_diffuseColorTileSize = lightEl.m_diffuseColor.xyz0();
 
 	if(lightEl.m_shadowRenderQueues[0] == nullptr || !ctx.m_shadowsEnabled)
 	{
-		slight.m_cubeFaceCoordinates[0].x() = INVALID_TEXTURE_INDEX;
+		slight.m_diffuseColorTileSize.w() = INVALID_TEXTURE_INDEX;
 	}
 	else
 	{
-		memcpy(
-			&slight.m_cubeFaceCoordinates[0][0], &lightEl.m_textureAtlasUvs[0][0], sizeof(lightEl.m_textureAtlasUvs));
+		slight.m_diffuseColorTileSize.w() = lightEl.m_atlasTileSize;
+		slight.m_atlasTilesPad2 = UVec4(lightEl.m_atlasTiles.x(), lightEl.m_atlasTiles.y(), 0, 0);
 	}
 
 	slight.m_specularColorRadius = Vec4(lightEl.m_specularColor, lightEl.m_radius);

+ 2 - 1
src/anki/renderer/RenderQueue.h

@@ -63,7 +63,8 @@ public:
 	const void* m_userData;
 	RenderQueueDrawCallback m_drawCallback;
 
-	Array<Vec4, 6> m_textureAtlasUvs; ///< Renderer internal.
+	UVec2 m_atlasTiles; ///< Renderer internal.
+	F32 m_atlasTileSize; ///< Renderer internal.
 
 	Bool hasShadow() const
 	{

+ 11 - 2
src/anki/renderer/ShadowMapping.cpp

@@ -357,6 +357,9 @@ void ShadowMapping::prepareBuildCommandBuffers(RenderingContext& ctx)
 		{
 			// All good, update the lights
 
+			light->m_atlasTiles = UVec2(0u);
+			light->m_atlasTileSize = 1.0f / m_tileCountPerRowOrColumn;
+
 			numOfFacesThatHaveDrawcalls = 0;
 			for(U face = 0; face < 6; ++face)
 			{
@@ -364,7 +367,12 @@ void ShadowMapping::prepareBuildCommandBuffers(RenderingContext& ctx)
 				{
 					// Has drawcalls, asigned it to a tile
 
-					light->m_textureAtlasUvs[face] = m_tiles[tiles[numOfFacesThatHaveDrawcalls]].m_uv;
+					const U32 tileIdx = tiles[numOfFacesThatHaveDrawcalls];
+					const U32 tileIdxX = tileIdx % m_tileCountPerRowOrColumn;
+					const U32 tileIdxY = tileIdx / m_tileCountPerRowOrColumn;
+					ANKI_ASSERT(tileIdxX <= 31u && tileIdxY <= 31u);
+					light->m_atlasTiles.x() |= tileIdxX << (5u * face);
+					light->m_atlasTiles.y() |= tileIdxY << (5u * face);
 
 					if(scratchTiles[numOfFacesThatHaveDrawcalls] != MAX_U32)
 					{
@@ -381,7 +389,8 @@ void ShadowMapping::prepareBuildCommandBuffers(RenderingContext& ctx)
 				else
 				{
 					// Doesn't have renderables, point the face to the 1st tile (that is pinned)
-					light->m_textureAtlasUvs[face] = m_tiles[0].m_uv;
+					light->m_atlasTiles.x() |= 0u << (5u * face);
+					light->m_atlasTiles.y() |= 0u << (5u * face);
 				}
 			}
 		}

+ 14 - 3
src/anki/resource/ResourceFilesystem.cpp

@@ -219,7 +219,6 @@ Error ResourceFilesystem::init(const ConfigSet& config, const CString& cacheDir)
 	for(auto& path : paths)
 	{
 		ANKI_CHECK(addNewPath(path.toCString()));
-		ANKI_RESOURCE_LOGI("Adding new data path \"%s\"", &path[0]);
 	}
 
 	addCachePath(cacheDir);
@@ -238,6 +237,7 @@ void ResourceFilesystem::addCachePath(const CString& path)
 
 Error ResourceFilesystem::addNewPath(const CString& path)
 {
+	U fileCount = 0;
 	static const CString extension(".ankizip");
 
 	auto pos = path.find(extension);
@@ -281,6 +281,7 @@ Error ResourceFilesystem::addNewPath(const CString& path)
 			if(info.uncompressed_size > 0)
 			{
 				p.m_files.pushBackSprintf(m_alloc, "%s", &filename[0]);
+				++fileCount;
 			}
 		} while(unzGoToNextFile(zfile) == UNZ_OK);
 
@@ -296,16 +297,25 @@ Error ResourceFilesystem::addNewPath(const CString& path)
 		p.m_path.sprintf(m_alloc, "%s", &path[0]);
 		p.m_isArchive = false;
 
-		ANKI_CHECK(walkDirectoryTree(path, this, [](const CString& fname, void* ud, Bool isDir) -> Error {
+		struct UserData
+		{
+			ResourceFilesystem* m_sys;
+			U* m_fileCount;
+		} ud{this, &fileCount};
+
+		ANKI_CHECK(walkDirectoryTree(path, &ud, [](const CString& fname, void* ud, Bool isDir) -> Error {
 			if(isDir)
 			{
 				return Error::NONE;
 			}
 
-			ResourceFilesystem* self = static_cast<ResourceFilesystem*>(ud);
+			UserData* udd = static_cast<UserData*>(ud);
+			ResourceFilesystem* self = udd->m_sys;
 
 			Path& p = self->m_paths.getFront();
 			p.m_files.pushBackSprintf(self->m_alloc, "%s", &fname[0]);
+
+			++(*udd->m_fileCount);
 			return Error::NONE;
 		}));
 
@@ -316,6 +326,7 @@ Error ResourceFilesystem::addNewPath(const CString& path)
 		}
 	}
 
+	ANKI_RESOURCE_LOGI("Added new data path \"%s\" that contains %u files", &path[0], fileCount);
 	return Error::NONE;
 }
 

+ 0 - 1
src/anki/scene/Visibility.cpp

@@ -393,7 +393,6 @@ void VisibilityTestTask::test(ThreadHive& hive)
 			{
 				PointLightQueueElement* el = m_result.m_pointLights.newElement(alloc);
 				lc->setupPointLightQueueElement(*el);
-				zeroMemory(el->m_textureAtlasUvs);
 
 				if(lc->getShadowEnabled())
 				{

+ 7 - 6
tests/CMakeLists.txt

@@ -1,9 +1,10 @@
-FILE(GLOB_RECURSE TESTS_SOURCES *.cpp)
-FILE(GLOB_RECURSE TESTS_HEADERS *.h)
+file(GLOB_RECURSE TESTS_SOURCES *.cpp)
+file(GLOB_RECURSE TESTS_HEADERS *.h)
 
-INCLUDE_DIRECTORIES("..")
+include_directories("..")
 
-ADD_EXECUTABLE(anki_tests ${TESTS_SOURCES} ${TESTS_HEADERS})
-TARGET_LINK_LIBRARIES(anki_tests anki)
+add_executable(anki_tests ${TESTS_SOURCES} ${TESTS_HEADERS})
+target_link_libraries(anki_tests anki)
 
-INSTALL(TARGETS anki_tests DESTINATION "${CMAKE_INSTALL_PREFIX}/tests")
+installExecutable(anki_tests)
+install(TARGETS anki_tests DESTINATION "${CMAKE_INSTALL_PREFIX}/tests")