Ver código fonte

Tiler compute

Panagiotis Christopoulos Charitos 12 anos atrás
pai
commit
03a5b8c89e

+ 37 - 0
shaders/IsBinLightTemplate.glsl

@@ -0,0 +1,37 @@
+// Template function that is used to bin lights to a tile
+
+#if !defined(LIGHT_TYPE) || !defined(PLANE_TEST_FUNC) || !defined(COUNTER)
+#	error See file
+#endif
+
+#define FUNC_NAME bin ## LIGHT_TYPE ## COUNTER
+
+void FUNC_NAME(uint lightIndex)
+{
+	LIGHT_TYPE light = lights.
+
+	uvec2 from = uvec2(0, 0);
+	uvec2 to = uvec2(TILES_X_COUNT, TILES_Y_COUNT);
+
+	while(1)
+	{
+		uvec2 m = (to - from) / uvec2(2);
+
+		// Handle final
+		if(m.x == 0 || m.y == 0)
+		{
+			if(PLANE_TEST_FUNC(light, tilegrid.planesFar[tileY][tileX])
+				&& PLANE_TEST_FUNC(light, tilegrid.planesNear[tileY][tileX]))
+			{
+				// It's inside tile
+				uint pos = atomicCounterIncrement(COUNTER);
+			}
+		}
+	}
+}
+
+// Undef everything
+#undef LIGHT_TYPE
+#undef PLANE_TEST_FUNC
+#undef COUNTER
+#undef FUNC_NAME

+ 53 - 0
shaders/IsCommon.glsl

@@ -0,0 +1,53 @@
+// Contains common structures for IS
+
+struct Plane
+{
+	vec4 normalOffset;
+};
+
+struct Tilegrid
+{
+	Plane planesX[TILES_X_COUNT - 1];
+	Plane planesY[TILES_Y_COUNT - 1];
+	Plane planesNear[TILES_Y_COUNT][TILES_X_COUNT];
+	Plane planesFar[TILES_Y_COUNT][TILES_X_COUNT];
+};
+
+struct Tile
+{
+	uvec4 lightsCount;
+#if __VERSION__ == 430
+	uint pointLightIndices[MAX_POINT_LIGHTS_PER_TILE];
+	uint spotLightIndices[MAX_SPOT_LIGHTS_PER_TILE];
+	uint spotLightTexIndices[MAX_SPOT_LIGHTS_TEX_PER_TILE];
+#else
+	uvec4 pointLightIndices[MAX_POINT_LIGHTS_PER_TILE / 4];
+	uvec4 spotLightIndices[MAX_SPOT_LIGHTS_PER_TILE / 4];
+	uvec4 spotLightTexIndices[MAX_SPOT_LIGHTS_TEX_PER_TILE / 4];
+#endif
+};
+
+struct Light
+{
+	vec4 posRadius; // xyz: Light pos in eye space. w: The radius
+	vec4 diffuseColorShadowmapId;
+	vec4 specularColorTexId;
+};
+
+#define PointLight Light
+
+struct SpotLight
+{
+	Light light;
+	vec4 lightDirection;
+	vec4 outerCosInnerCos;
+	mat4 texProjectionMat;
+	vec4 extendPoints[4];
+};
+
+struct Lights
+{
+	uvec4 count;
+	PointLight pointLights[MAX_POINT_LIGHTS];
+	SpotLight spotLights[MAX_SPOT_LIGHTS];
+};

+ 137 - 0
shaders/IsUpdateTilegrid.glsl

@@ -0,0 +1,137 @@
+// This compute shader sets the planes of the tilegrid
+
+#pragma anki start computeShader
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+
+#define TILES_COUNT (TILES_X_COUNT * TILES_Y_COUNT)
+
+// The total number of planes. See the cpp code for details
+#define PLANES_COUNT (TILES_X_COUNT - 1 + TILES_Y_COUNT - 1  + TILES_COUNT)
+
+#define TILE_W (DEPTHMAP_WIDTH / TILES_X_COUNT)
+#define TILE_H (DEPTHMAP_HEIGHT / TILES_Y_COUNT)
+
+#define tileX gl_WorkGroupID.x
+#define tileY gl_WorkGroupID.y
+
+// Offsets of different plane groups in 
+#define PLANES_X_OFFSET 0
+#define PLANES_Y_OFFSET (PLANES_X_OFFSET + )
+#define PLANES_NEAR_OFFSET (PLANES_Y_OFFSET + TILES_Y_COUNT - 1)
+#define PLANES_FAR_OFFSET (PLANES_NEAR_OFFSET + TILES_COUNT)
+
+uniform highp sampler2D depthMap;
+
+struct Plane
+{
+	vec4 normalOffset;
+};
+
+struct Tilegrid
+{
+	Plane planesX[TILES_X_COUNT - 1];
+	Plane planesY[TILES_Y_COUNT - 1];
+	Plane planesNear[TILES_Y_COUNT][TILES_X_COUNT];
+	Plane planesFar[TILES_Y_COUNT][TILES_X_COUNT];
+};
+
+layout(std140, binding = 0) buffer tilegridBuffer
+{
+	Tilegrid tilegrid;
+};
+
+layout(std140, binding = 1) uniform uniformBuffer
+{
+	vec4 fovXfovYNearFar;
+	bvec4 frustumChanged_;
+}
+
+#define frustumChanged frustumChanged_.x
+
+#define fovX fovXfovYNearFar.x
+#define fovY fovXfovYNearFar.y
+#define near fovXfovYNearFar.z
+#define far fovXfovYNearFar.w
+
+void main()
+{
+	//
+	// First get the min max depth of the tile. This reads from memory so do
+	// it first
+	//
+	vec2 minMaxDepth = vec2(-10000.0, 100000.0);
+
+	uvec2 coord = uvec2(uvec2(tileX, tileY) * uvec2(TILE_W, TILE_H));
+
+	for(int x = 0; x < TILE_W; x++)
+	{
+		for(uint y = 0; y < TILE_H; i++)
+		{
+			float depth = texelFetch(depthMap, coord + uvec2(x, y)).r;
+
+			minMaxDepth.x = min(depth, minMaxDepth.x);
+			minMaxDepth.y = max(depth, minMaxDepth.y);
+		}
+	}
+
+	//
+	// Update top and right looking planes only when the fovs have changed
+	//
+	if(frustumChanged)
+	{
+		float near2 = 2.0 * near;
+		float l = near2 * tan(fovX * 0.5);
+		float l6 = l * (1.0 / float(TILES_X_COUNT));
+		float o = near2 * tan(fovY * 0.5);
+		float o6 = o * (1.0 / float(TILES_Y_COUNT));
+
+		// First the right looking planes in one working thread
+		if(tileY == 0U)
+		{
+			vec3 a, b;
+
+			a = vec3(
+				float(int(tileX + 1) - (int(TILES_X_COUNT) / 2)) * l6, 
+				0.0, 
+				-near);
+
+			b = cross(a, vec3(0.0, 1.0, 0.0));
+			normalize(b);
+
+			planesX[tileX].normalOffset = vec4(b, 0.0)
+		}
+
+		// Then the top looking planes in one working thread
+		if(tileX == 0U)
+		{
+			vec3 a, b;
+
+			a = vec3(
+				0.0, 
+				float(int(tileY + 1) - (int(TILES_Y_COUNT) / 2)) * o6, 
+				-near);
+
+			b = cross(vec3(1.0, 0.0, 0.0), a);
+			normalize(b);
+
+			planesY[tileY].normalOffset = vec4(b, 0.0);
+		}
+	}
+
+	//
+	// Update the far and near planes
+	//
+	{
+		// Calc the Z in view space
+		vec2 minMaxZ = 
+			vec2(far * near) / (minMaxDepth * vec2(near - far) + vec2(near));
+
+		// Set planes
+		planesNear[tileY][tileX].normalOffset = 
+			vec4(0.0, 0.0, -1.0, minMaxZ.x);
+
+		planesFar[tileY][tileX].normalOffset = 
+			vec4(0.0, 0.0, 1.0, minMaxZ.y);
+	}
+}

+ 76 - 8
shaders/IsUpdateTiles.glsl

@@ -1,21 +1,89 @@
+// Compute shader that bins lights to the tiles
+
 #pragma anki start computeShader
 
-// Set workgroup XXX
+// Set number of work items
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
 
-struct Tile
+#pragma anki include "shaders/IsCommon.glsl"
+
+//
+// Data
+//
+
+// The tilegrid input buffer
+layout(std140, binding = 0) buffer tilegridBuffer
 {
-	uvec4 lightsCount;
-	uvec4 lightIndices[MAX_LIGHTS_PER_TILE / 4];
+	Tilegrid tilegrid;
 };
 
-layout(std140, binding = 0) buffer tilesBuffer
+// The lights input buffers
+layout(std140, binding = 1) buffer lightsBuffer
 {
-	Tile tiles[TILES_X_COUNT * TILES_Y_COUNT];
+	Lights lights;
+}; 
+
+// The output buffer
+layout(std430, binding = 2) buffer tilesBuffer
+{
+	Tile tiles[TILES_Y_COUNT][TILES_X_COUNT];
 };
 
+// Buffers with atomic counters for each tile
+layout(std430, binding = 1) buffer pointLightsCountBuffer
+{
+	atomic_uint pointLightsCount[TILES_Y_COUNT][TILES_X_COUNT];
+};
+layout(std430, binding = 2) buffer spotLightsCountBuffer
+{
+	atomic_uint spotLightsCount[TILES_Y_COUNT][TILES_X_COUNT];
+};
+layout(std430, binding = 3) buffer spotLightsTexCountBuffer
+{
+	atomic_uint spotLightsTexCount[TILES_Y_COUNT][TILES_X_COUNT];
+};
+
+//
+// Functions
+//
+
+// Return true if spere is in the half space defined by the plane
+bool pointLightInsidePlane(in PointLight light, in Plane plane)
+{	
+	// Result of the plane test. Distance of 
+	float dist = dot(plane.normalOffset.xyz, light.posRadius.xyz) 
+		- plane.normalOffset.w;
+
+	return dist >= 0.0;
+}
+
+// Spot light inside plane
+bool spotLightInsidePlane(in SpotLight light, in Plane plane)
+{
+	if(pointLightInsidePlane(light.light, plane))
+	{
+		return true;
+	}
+
+	for(uint i = 0U; i < 4; i++)
+	{
+		float dist = dot(plane.normalOffset.xyz, light.extendPoints[i].xyz) 
+			- plane.normalOffset.w;
+
+		if(dist >= 0.0)
+		{
+			return true;
+		}
+	}
+	return false;
+}
+
+// main
 void main()
 {
-	tiles[gl_WorkGroupID.x * TILES_Y_COUNT + gl_WorkGroupID.y].
-		lightsCount.w = 665U;
+	// First the point lights
+	for(uint i = 0U; i < lights.count.x; i++)
+	{
+		
+	}
 }

+ 2 - 2
src/renderer/Is.cpp

@@ -631,7 +631,7 @@ void Is::lightPass()
 	tilesUbo.write(&clientBuffer);
 
 	// XXX
-	{
+	/*{
 		tilesUbo.bind(GL_SHADER_STORAGE_BUFFER);
 		tilesUbo.setBinding(0);
 
@@ -640,7 +640,7 @@ void Is::lightPass()
 		glDispatchCompute(Tiler::TILES_X_COUNT, Tiler::TILES_Y_COUNT, 1);
 
 		tilesUbo.bind(GL_UNIFORM_BUFFER);
-	}
+	}*/
 
 	//
 	// Setup shader and draw