Panagiotis Christopoulos Charitos 13 years ago
parent
commit
00a531b23c
3 changed files with 137 additions and 54 deletions
  1. 90 1
      shaders/IsLpGeneric.glsl
  2. 0 8
      src/collision/Frustum.cpp
  3. 47 45
      src/renderer/Is.cpp

+ 90 - 1
shaders/IsLpGeneric.glsl

@@ -79,7 +79,96 @@ flat in uint vInstanceId;
 out vec3 fColor;
 out vec3 fColor;
 /// @}
 /// @}
 
 
+//==============================================================================
+/// @return frag pos in view space
+vec3 getFragPosVSpace()
+{
+	float depth = texture(msDepthFai, vTexCoords).r;
+
+#if DISCARD
+	if(depth == 1.0)
+	{
+		discard;
+	}
+#endif
+
+	vec3 fragPosVspace;
+	fragPosVspace.z = -planes.y / (planes.x + depth);
+
+	fragPosVspace.xy = (vTexCoords * limitsOfNearPlane2) - limitsOfNearPlane;
+
+	float sc = -fragPosVspace.z / zNear;
+	fragPosVspace.xy *= sc;
+
+	return fragPosVspace;
+}
+
+//==============================================================================
+/// Performs phong lighting using the MS FAIs and a few other things
+/// @param fragPosVspace The fragment position in view space
+/// @return The final color
+vec3 doPhong(in vec3 fragPosVspace, in vec3 normal, in vec3 diffuse, 
+	in vec2 specularAll, in Light light)
+{
+	// get the vector from the frag to the light
+	vec3 frag2LightVec = light.posAndRadius.xyz - fragPosVspace;
+
+	// Instead of using normalize(frag2LightVec) we brake the operation 
+	// because we want fragLightDist for the calc of the attenuation
+	float fragLightDistSqrt = sqrt(dot(frag2LightVec, frag2LightVec));
+	vec3 lightDir = frag2LightVec / fragLightDistSqrt;
+
+	// Lambert term
+	float lambertTerm = dot(normal, lightDir);
+
+#if DISCARD
+	if(lambertTerm < 0.0)
+	{
+		discard;
+	}
+#else
+	lambertTerm = max(0.0, lambertTerm);
+#endif
+
+	// Attenuation
+	float attenuation = 1.0 - fragLightDistSqrt / light.posAndRadius.w;
+
+	// Diffuse
+	vec3 difCol = diffuse * light.diffuseColor.rgb;
+
+	// Specular
+	vec3 eyeVec = normalize(-fragPosVspace);
+	vec3 h = normalize(lightDir + eyeVec);
+	float specIntensity = pow(max(0.0, dot(normal, h)), specularAll.g);
+	vec3 specCol = light.specularColor.rgb * (specIntensity * specularAll.r);
+	
+	// end
+	return (difCol + specCol) * (attenuation * lambertTerm);
+}
+
+//==============================================================================
 void main()
 void main()
 {
 {
-	fColor = vec3(0.0, float(tiles[vInstanceId].lightsCount), 0.0);
+	// Read texture first. Optimize for future out of order HW
+	uvec2 msAll = texture(msFai0, vTexCoords).rg;
+
+	// get frag pos in view space
+	vec3 fragPosVspace = getFragPosVSpace();
+
+	// Decode MS
+	vec3 normal = unpackNormal(unpackHalf2x16(msAll[1]));
+	vec4 diffuseAndSpec = unpackUnorm4x8(msAll[0]);
+	vec2 specularAll = unpackSpecular(diffuseAndSpec.a);
+
+	// Lighting
+	uint lightsCount = tiles[vInstanceId].lightsCount;
+
+	fColor = vec3(0.0);
+	for(uint i = 0; i < lightsCount; ++i)
+	{
+		uint lightId = tiles[vInstanceId].lightIndices[i / 4][i % 4];
+
+		fColor += doPhong(fragPosVspace, normal, diffuseAndSpec.rgb, 
+			specularAll, lights[lightId]);
+	}
 }
 }

+ 0 - 8
src/collision/Frustum.cpp

@@ -123,19 +123,11 @@ void PerspectiveFrustum::recalculate()
 	// left
 	// left
 	planes[FP_LEFT] = Plane(Vec3(-c, 0.0, s), 0.0);
 	planes[FP_LEFT] = Plane(Vec3(-c, 0.0, s), 0.0);
 
 
-#if 0
-	Math::sinCos((3.0 * Math::PI - fovY) * 0.5, s, c);
-	// top
-	planes[FP_TOP] = Plane(Vec3(0.0, s, c), 0.0);
-	// bottom
-	planes[FP_BOTTOM] = Plane(Vec3(0.0, -s, c), 0.0);
-#else
 	Math::sinCos((Math::PI + fovY) * 0.5, s, c);
 	Math::sinCos((Math::PI + fovY) * 0.5, s, c);
 	// bottom
 	// bottom
 	planes[FP_BOTTOM] = Plane(Vec3(0.0, s, c), 0.0);
 	planes[FP_BOTTOM] = Plane(Vec3(0.0, s, c), 0.0);
 	// top
 	// top
 	planes[FP_TOP] = Plane(Vec3(0.0, -s, c), 0.0);
 	planes[FP_TOP] = Plane(Vec3(0.0, -s, c), 0.0);
-#endif
 
 
 	// near
 	// near
 	planes[FP_NEAR] = Plane(Vec3(0.0, 0.0, -1.0), near);
 	planes[FP_NEAR] = Plane(Vec3(0.0, 0.0, -1.0), near);

+ 47 - 45
src/renderer/Is.cpp

@@ -354,51 +354,46 @@ void Is::pointLightsPass()
 	Camera& cam = r->getScene().getActiveCamera();
 	Camera& cam = r->getScene().getActiveCamera();
 	VisibilityInfo& vi = cam.getFrustumable()->getVisibilityInfo();
 	VisibilityInfo& vi = cam.getFrustumable()->getVisibilityInfo();
 
 
+	Array<PointLight*, MAX_LIGHTS> visibleLights;
+	U visibleLightsCount = 0;
+
 	//
 	//
 	// Write the lightsUbo
 	// Write the lightsUbo
 	//
 	//
 
 
-	// Quickly count the point lights
-	U pointLightsCount = 0;
+	// Quickly get the point lights
 	for(auto it = vi.getLightsBegin(); it != vi.getLightsEnd(); ++it)
 	for(auto it = vi.getLightsBegin(); it != vi.getLightsEnd(); ++it)
 	{
 	{
-		const Light& light = *(*it);
-		if(light.getLightType() == Light::LT_POINT)
+		Light* light = (*it);
+		if(light->getLightType() == Light::LT_POINT)
 		{
 		{
-			++pointLightsCount;		
+			// Use % to avoid overflows
+			visibleLights[visibleLightsCount % MAX_LIGHTS] = 
+				static_cast<PointLight*>(light);
+			++visibleLightsCount;
 		}
 		}
 	}
 	}
 
 
-	if(pointLightsCount > MAX_LIGHTS)
+	if(visibleLightsCount > MAX_LIGHTS)
 	{
 	{
-		throw ANKI_EXCEPTION("Too many lights");
+		throw ANKI_EXCEPTION("Too many visible lights");
 	}
 	}
 
 
 	// Map
 	// Map
 	ShaderPointLights* lightsMappedBuff = (ShaderPointLights*)lightsUbo.map(
 	ShaderPointLights* lightsMappedBuff = (ShaderPointLights*)lightsUbo.map(
 		0, 
 		0, 
-		sizeof(ShaderPointLight) * pointLightsCount,
+		sizeof(ShaderPointLight) * visibleLightsCount,
 		GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
 		GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
 
 
 	// Write the buff
 	// Write the buff
-	pointLightsCount = 0;
-	for(auto it = vi.getLightsBegin(); it != vi.getLightsEnd(); ++it)
+	for(U i = 0; i < visibleLightsCount; i++)
 	{
 	{
-		const Light& light = *(*it);
-		if(light.getLightType() == Light::LT_POINT)
-		{
-			ShaderPointLight& pl = lightsMappedBuff->lights[pointLightsCount];
-			const PointLight& plight = static_cast<const PointLight&>(light);
+		ShaderPointLight& pl = lightsMappedBuff->lights[i];
+		const PointLight& plight = *visibleLights[i];
 
 
-			Vec3 pos = light.getWorldTransform().getOrigin().getTransformed(
-				cam.getViewMatrix());
-
-			pl.posAndRadius = Vec4(pos, plight.getRadius());
-			pl.diffuseColor = light.getDiffuseColor();
-			pl.specularColor = light.getSpecularColor();
-
-			++pointLightsCount;		
-		}
+		pl.posAndRadius = Vec4(pos, plight.getRadius());
+		pl.diffuseColor = plight.getDiffuseColor();
+		pl.specularColor = plight.getSpecularColor();
 	}
 	}
 
 
 	// Done
 	// Done
@@ -418,32 +413,24 @@ void Is::pointLightsPass()
 			Tile& tile = tiles[j][i];
 			Tile& tile = tiles[j][i];
 
 
 			U lightsInTileCount = 0;
 			U lightsInTileCount = 0;
-			U ids = 0;
 
 
-			for(auto it = vi.getLightsBegin(); it != vi.getLightsEnd(); ++it)
+			for(U i = 0; i < visibleLightsCount; i++)
 			{
 			{
-				const Light& light = *(*it);
-				if(light.getLightType() != Light::LT_POINT)
-				{
-					continue;
-				}
-
-				const PointLight& plight =
-					static_cast<const PointLight&>(light);
+				const PointLight& plight = *visibleLights[i];
 
 
 				if(cullLight(plight, tile))
 				if(cullLight(plight, tile))
 				{
 				{
-					tile.lightIndices[lightsInTileCount] = ids;
+					// Use % to avoid overflows
+					tile.lightIndices[lightsInTileCount 
+						% MAX_LIGHTS_PER_TILE] = i;
 					++lightsInTileCount;
 					++lightsInTileCount;
 				}
 				}
-
-				++ids;
 			}
 			}
 
 
-			/*if(lightsInTileCount > MAX_LIGHTS_PER_TILE)
+			if(lightsInTileCount > MAX_LIGHTS_PER_TILE)
 			{
 			{
 				throw ANKI_EXCEPTION("Too many lights per tile");
 				throw ANKI_EXCEPTION("Too many lights per tile");
-			}*/
+			}
 
 
 			tile.lightsCount = lightsInTileCount;
 			tile.lightsCount = lightsInTileCount;
 		}
 		}
@@ -461,16 +448,31 @@ void Is::pointLightsPass()
 		for(U i = 0; i < TILES_X_COUNT; i++)
 		for(U i = 0; i < TILES_X_COUNT; i++)
 		{
 		{
 			const Tile& tile = tiles[j][i];
 			const Tile& tile = tiles[j][i];
+
 			stiles->tiles[j][i].lightsCount = tile.lightsCount;
 			stiles->tiles[j][i].lightsCount = tile.lightsCount;
 
 
-			/*for(U k = 0; k < tile.lightsCount; k++)
-			{
-				stiles->tiles[j][i].lightIndices[k] = tile.lightIndices[k];
-			}*/
+			memcpy(
+				&(stiles->tiles[j][i].lightIndices[0]),
+				&tile.lightIndices[0],
+				sizeof(U32) * MAX_LIGHTS_PER_TILE);
 		}
 		}
 	}
 	}
 
 
 	tilesUbo.unmap();
 	tilesUbo.unmap();
+
+	//
+	// Setup shader and draw
+	//
+	
+	// shader prog
+	const ShaderProgram& shader = *lightSProgs[LST_POINT];
+	shader.bind();
+
+	shader.findUniformVariable("msFai0").set(r->getMs().getFai0());
+	shader.findUniformVariable("msDepthFai").set(
+		r->getMs().getDepthFai());
+
+	r->drawQuadInstanced(TILES_Y_COUNT * TILES_X_COUNT);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
@@ -485,8 +487,8 @@ void Is::run()
 	GlStateSingleton::get().setViewport(0, 0, r->getWidth(), r->getHeight());
 	GlStateSingleton::get().setViewport(0, 0, r->getWidth(), r->getHeight());
 
 
 	pointLightsPass();
 	pointLightsPass();
-	lightSProgs[0]->bind();
-	r->drawQuadInstanced(TILES_Y_COUNT * TILES_X_COUNT);
+	//lightSProgs[0]->bind();
+	//r->drawQuadInstanced(TILES_Y_COUNT * TILES_X_COUNT);
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki