Browse Source

[BUGFIX] Fix indirect and parallax mapping

Panagiotis Christopoulos Charitos 8 years ago
parent
commit
fabf3d4975

+ 13 - 11
programs/DeferredShading.ankiprog

@@ -53,8 +53,7 @@ layout(location = 0) out vec3 out_color;
 // Point light
 struct PointLight
 {
-	vec4 projectionParams;
-	vec4 posRadius; // xyz: Light pos in eye space. w: The -1/radius
+	vec4 posRadius; // xyz: Light pos in world space. w: The -1/radius
 	vec4 diffuseColorPad1; // xyz: diff color
 	vec4 specularColorPad1; // xyz: spec color
 };
@@ -62,8 +61,7 @@ struct PointLight
 // Spot light
 struct SpotLight
 {
-	vec4 projectionParams;
-	vec4 posRadius; // xyz: Light pos in eye space. w: The -1/radius
+	vec4 posRadius; // xyz: Light pos in world space. w: The -1/radius
 	vec4 diffuseColorOuterCos; // xyz: diff color, w: outer cosine of spot
 	vec4 specularColorInnerCos; // xyz: spec color, w: inner cosine of spot
 	vec4 lightDirPad1;
@@ -74,9 +72,11 @@ layout(ANKI_TEX_BINDING(0, 1)) uniform sampler2D u_msRt1;
 layout(ANKI_TEX_BINDING(0, 2)) uniform sampler2D u_msRt2;
 layout(ANKI_TEX_BINDING(0, 3)) uniform sampler2D u_msDepthRt;
 
-layout(ANKI_UBO_BINDING(0, 1)) uniform u1_
+layout(ANKI_UBO_BINDING(0, 1), row_major) uniform u1_
 {
 	vec4 u_inputTexUvScaleAndOffset; // Use this to get the correct face UVs
+	mat4 u_invViewProjMat;
+	vec4 u_camPosPad1;
 #if LIGHT_TYPE == POINT_LIGHT_TYPE
 	PointLight u_light;
 #elif LIGHT_TYPE == SPOT_LIGHT_TYPE
@@ -94,6 +94,8 @@ layout(ANKI_UBO_BINDING(0, 1)) uniform u1_
 #define u_lspec u_light.specularColorInnerCos.xyz
 #endif
 
+#define u_camPos u_camPosPad1.xyz
+
 void main()
 {
 	// Compute UV coordinates
@@ -107,17 +109,17 @@ void main()
 		discard;
 	}
 
+	// Decode and process gbuffer
 	GbufferInfo gbuffer;
 	readGBuffer(u_msRt0, u_msRt1, u_msRt2, uvToRead, 0.0, gbuffer);
 	float a2 = pow(gbuffer.roughness, 2.0);
 
-	// Calculate the light color
-	vec3 fragPos;
-	fragPos.z = u_light.projectionParams.z / (u_light.projectionParams.w + depth);
-	fragPos.xy = UV_TO_NDC(uv) * u_light.projectionParams.xy * fragPos.z;
+	vec4 worldPos4 = u_invViewProjMat * vec4(UV_TO_NDC(uv), depth, 1.0);
+	vec3 worldPos = worldPos4.xyz / worldPos4.w;
 
-	vec3 viewDir = normalize(-fragPos);
-	vec3 frag2Light = u_light.posRadius.xyz - fragPos;
+	// Calculate the light color
+	vec3 viewDir = normalize(u_camPos - worldPos);
+	vec3 frag2Light = u_light.posRadius.xyz - worldPos;
 	vec3 l = normalize(frag2Light);
 	float nol = max(0.0, dot(gbuffer.normal, l));
 

+ 22 - 24
programs/LightShading.ankiprog

@@ -92,20 +92,19 @@ void appendDecalColors(in Decal decal, in vec3 worldPos, inout vec3 diffuseColor
 	vec2 texCoords2 = texCoords4.xy / texCoords4.w;
 
 	// Clamp the tex coords. Expect a border in the texture atlas
-	texCoords2 = clamp(texCoords2, 0.0, 1.0);
+	texCoords2 = saturate(texCoords2);
 
-	vec2 diffUv = texCoords2 * decal.diffUv.zw + decal.diffUv.xy;
+	vec2 diffUv = mad(texCoords2, decal.diffUv.zw, decal.diffUv.xy);
 	vec4 dcol = texture(u_diffDecalTex, diffUv);
 	diffuseColor = mix(diffuseColor, dcol.rgb, dcol.a * decal.blendFactors[0]);
 
 	// Roughness
-	vec2 roughnessUv = texCoords2 * decal.normRoughnessUv.zw + decal.normRoughnessUv.xy;
+	vec2 roughnessUv = mad(texCoords2, decal.normRoughnessUv.zw, decal.normRoughnessUv.xy);
 	float r = texture(u_normalRoughnessDecalTex, roughnessUv).w;
 	roughness = mix(roughness, r, dcol.a * decal.blendFactors[1]);
 }
 
-void readIndirect(
-	in uint idxOffset, in vec3 pos, in vec3 r, in vec3 n, in float lod, out vec3 specIndirect, out vec3 diffIndirect)
+void readIndirect(uint idxOffset, vec3 pos, vec3 r, vec3 n, float lod, out vec3 specIndirect, out vec3 diffIndirect)
 {
 	specIndirect = vec3(0.0);
 	diffIndirect = vec3(0.0);
@@ -138,7 +137,7 @@ void readIndirect(
 
 		// Do the same for diffuse
 		uv = computeCubemapVecAccurate(n, R2, f);
-		vec3 id = texture(u_irradianceTex, vec4(uv, cubemapIndex)).rgb;
+		vec3 id = textureLod(u_irradianceTex, vec4(uv, cubemapIndex), 0.0).rgb;
 		diffIndirect = mix(id, diffIndirect, factor);
 	}
 }
@@ -149,11 +148,8 @@ void main()
 	vec2 ndc = UV_TO_NDC(in_uv);
 
 	// Get world position
-	vec3 worldPos;
-	{
-		vec4 worldPos4 = u_invViewProjMat * vec4(ndc, depth, 1.0);
-		worldPos = worldPos4.xyz / worldPos4.w;
-	}
+	vec4 worldPos4 = u_invViewProjMat * vec4(ndc, depth, 1.0);
+	vec3 worldPos = worldPos4.xyz / worldPos4.w;
 
 	// Decode GBuffer
 	vec3 normal;
@@ -174,10 +170,6 @@ void main()
 	subsurface = max(gbuffer.subsurface, SUBSURFACE_MIN);
 	emission = gbuffer.emission;
 
-	// Get SSAO
-	float ssao = texture(u_ssaoTex, in_uv).r;
-	diffCol *= ssao;
-
 	// Get first light index
 	uint idxOffset;
 	{
@@ -197,6 +189,10 @@ void main()
 		appendDecalColors(decal, worldPos, diffCol, roughness);
 	}
 
+	// Apply SSAO
+	float ssao = texture(u_ssaoTex, in_uv).r;
+	diffCol *= ssao;
+
 	// Ambient and emissive color
 	vec3 outC = diffCol * emission;
 
@@ -248,19 +244,21 @@ void main()
 	}
 
 	// Indirect
-	vec3 eye = -viewDir;
-	vec3 reflVec = reflect(eye, normal);
+	{
+		vec3 eye = -viewDir;
+		vec3 reflVec = reflect(eye, normal);
 
-	float reflLod = float(IR_MIPMAP_COUNT) * a2;
+		float reflLod = float(IR_MIPMAP_COUNT - 1u) * a2;
 
-	float ndotv = dot(normal, viewDir);
-	vec2 envBRDF = texture(u_integrationLut, vec2(a2, ndotv)).xy;
-	vec3 specIndirectTerm = specCol * envBRDF.x + envBRDF.y;
+		vec3 specIndirect, diffIndirect;
+		readIndirect(idxOffset, worldPos, reflVec, normal, reflLod, specIndirect, diffIndirect);
 
-	vec3 specIndirect, diffIndirect;
-	readIndirect(idxOffset, worldPos, reflVec, normal, reflLod, specIndirect, diffIndirect);
+		float ndotv = dot(normal, viewDir);
+		vec2 envBRDF = texture(u_integrationLut, vec2(a2, ndotv)).xy;
+		vec3 specIndirectTerm = specCol * envBRDF.x + envBRDF.y;
 
-	outC += specIndirect * specIndirectTerm + diffIndirect * diffCol;
+		outC += specIndirect * specIndirectTerm + diffIndirect * diffCol;
+	}
 
 	out_color = outC;
 #if 0

+ 9 - 5
shaders/Common.glsl

@@ -24,6 +24,7 @@
 #define DEFAULT_INT_PRECISION highp
 #endif
 
+// Constants
 precision DEFAULT_FLOAT_PRECISION float;
 precision DEFAULT_INT_PRECISION int;
 
@@ -34,9 +35,11 @@ const uint MAX_U32 = 0xFFFFFFFFu;
 const float PI = 3.14159265358979323846;
 const uint UBO_MAX_SIZE = 16384u;
 
+// Macros
 #define UV_TO_NDC(x_) ((x_)*2.0 - 1.0)
 #define NDC_TO_UV(x_) ((x_)*0.5 + 0.5)
 #define saturate(x_) clamp((x_), 0.0, 1.0)
+#define mad(a_, b_, c_) fma((a_), (b_), (c_))
 
 // Common locations
 #define POSITION_LOCATION 0
@@ -48,15 +51,16 @@ const uint UBO_MAX_SIZE = 16384u;
 #define SCALE_LOCATION 1
 #define ALPHA_LOCATION 2
 
+// Passes
+#define PASS_GB_FS 0
+#define PASS_SM 1
+#define PASS_EZ 2
+
+// Other
 #if !defined(ANKI_ARB_SHADER_BALLOT)
 #define readFirstInvocationARB(x_) (x_)
 #endif
 
 #define CALC_BITANGENT_IN_VERT 1
 
-// Passes
-#define PASS_GB_FS 0
-#define PASS_SM 1
-#define PASS_EZ 2
-
 #endif

+ 1 - 1
shaders/GBufferCommonFrag.glsl

@@ -20,7 +20,7 @@ layout(location = 2) in mediump vec4 in_tangent;
 layout(location = 3) in mediump vec3 in_bitangent;
 #endif
 layout(location = 4) in mediump float in_distFromTheCamera; // Parallax
-layout(location = 5) in highp vec3 in_eyeTangentSpace; // Parallax
+layout(location = 5) in mediump vec3 in_eyeTangentSpace; // Parallax
 layout(location = 6) in mediump vec3 in_normalTangentSpace; // Parallax
 #endif // PASS == PASS_GB_FS
 

+ 2 - 2
shaders/GBufferCommonVert.glsl

@@ -49,7 +49,7 @@ layout(location = 2) out mediump vec4 out_tangent;
 layout(location = 3) out mediump vec3 out_bitangent;
 #endif
 layout(location = 4) out mediump float out_distFromTheCamera; // Parallax
-layout(location = 5) out highp vec3 out_eyeTangentSpace; // Parallax
+layout(location = 5) out mediump vec3 out_eyeTangentSpace; // Parallax
 layout(location = 6) out mediump vec3 out_normalTangentSpace; // Parallax
 #endif
 
@@ -96,7 +96,7 @@ void parallax(mat4 modelViewMat)
 	mat3 invTbn = transpose(normalMat * mat3(t, b, n));
 
 	vec3 viewPos = (modelViewMat * vec4(g_position, 1.0)).xyz;
-	out_distFromTheCamera = length(viewPos);
+	out_distFromTheCamera = viewPos.z;
 
 	out_eyeTangentSpace = invTbn * viewPos;
 	out_normalTangentSpace = invTbn * n;

+ 12 - 0
src/anki/gr/Common.h

@@ -242,9 +242,21 @@ public:
 	{
 	}
 
+	Bool operator==(const TextureSubresourceInfo& b) const
+	{
+		ANKI_ASSERT(_m_padding[0] == b.m_padding[0]);
+		return memcmp(this, &b, sizeof(*this)) == 0;
+	}
+
+	Bool operator!=(const TextureSubresourceInfo& b) const
+	{
+		return !(*this == b);
+	}
+
 	U64 computeHash() const
 	{
 		static_assert(sizeof(*this) == sizeof(U32) * 4 + sizeof(U8) * 4, "Should be hashable");
+		ANKI_ASSERT(_m_padding[0] == b.m_padding[0]);
 		return anki::computeHash(this, sizeof(*this));
 	}
 };

+ 14 - 0
src/anki/gr/gl/TextureImpl.cpp

@@ -368,6 +368,20 @@ U TextureImpl::computeSurfaceIdx(const TextureSurfaceInfo& surf) const
 
 MicroTextureView TextureImpl::getOrCreateView(const TextureSubresourceInfo& subresource) const
 {
+	// Quick opt: Check if the subresource refers to the whole tex
+	TextureSubresourceInfo wholeTexSubresource;
+	wholeTexSubresource.m_mipmapCount = getMipmapCount();
+	wholeTexSubresource.m_faceCount = textureTypeIsCube(getTextureType()) ? 6 : 1;
+	wholeTexSubresource.m_layerCount = getLayerCount();
+	wholeTexSubresource.m_depthStencilAspect = getDepthStencilAspect();
+
+	if(subresource == wholeTexSubresource)
+	{
+		MicroTextureView view{getGlName(), wholeTexSubresource.m_depthStencilAspect};
+		return view;
+	}
+
+	// Continue with the regular init
 	LockGuard<Mutex> lock(m_viewsMapMtx);
 	auto it = m_viewsMap.find(subresource);
 

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

@@ -23,7 +23,8 @@ struct Indirect::LightPassVertexUniforms
 struct Indirect::LightPassPointLightUniforms
 {
 	Vec4 m_inputTexUvScaleAndOffset;
-	Vec4 m_projectionParams;
+	Mat4 m_invViewProjMat;
+	Vec4 m_camPosPad1;
 	Vec4 m_posRadius;
 	Vec4 m_diffuseColorPad1;
 	Vec4 m_specularColorPad1;
@@ -32,7 +33,8 @@ struct Indirect::LightPassPointLightUniforms
 struct Indirect::LightPassSpotLightUniforms
 {
 	Vec4 m_inputTexUvScaleAndOffset;
-	Vec4 m_projectionParams;
+	Mat4 m_invViewProjMat;
+	Vec4 m_camPosPad1;
 	Vec4 m_posRadius;
 	Vec4 m_diffuseColorOuterCos;
 	Vec4 m_specularColorInnerCos;
@@ -469,7 +471,7 @@ void Indirect::runLightShading(U32 faceIdx, RenderPassWorkContext& rgraphCtx)
 		const RenderQueue& rqueue = *probe.m_renderQueues[faceIdx];
 
 		const Mat4& vpMat = rqueue.m_viewProjectionMatrix;
-		const Mat4& vMat = rqueue.m_viewMatrix;
+		const Mat4 invViewProjMat = rqueue.m_viewProjectionMatrix.getInverse();
 
 		// Do point lights
 		cmdb->bindShaderProgram(m_lightShading.m_plightGrProg);
@@ -490,11 +492,11 @@ void Indirect::runLightShading(U32 faceIdx, RenderPassWorkContext& rgraphCtx)
 			LightPassPointLightUniforms* light =
 				allocateAndBindUniforms<LightPassPointLightUniforms*>(sizeof(LightPassPointLightUniforms), cmdb, 0, 1);
 
-			Vec4 pos = vMat * plightEl->m_worldPosition.xyz1();
-
 			light->m_inputTexUvScaleAndOffset = Vec4(1.0f / 6.0f, 1.0f, faceIdx * (1.0f / 6.0f), 0.0f);
-			light->m_projectionParams = rqueue.m_projectionMatrix.extractPerspectiveUnprojectionParams();
-			light->m_posRadius = Vec4(pos.xyz(), 1.0f / (plightEl->m_radius * plightEl->m_radius));
+			light->m_invViewProjMat = invViewProjMat;
+			light->m_camPosPad1 = rqueue.m_cameraTransform.getTranslationPart();
+			light->m_posRadius =
+				Vec4(plightEl->m_worldPosition.xyz(), 1.0f / (plightEl->m_radius * plightEl->m_radius));
 			light->m_diffuseColorPad1 = plightEl->m_diffuseColor.xyz0();
 			light->m_specularColorPad1 = plightEl->m_specularColor.xyz0();
 
@@ -536,17 +538,17 @@ void Indirect::runLightShading(U32 faceIdx, RenderPassWorkContext& rgraphCtx)
 				allocateAndBindUniforms<LightPassSpotLightUniforms*>(sizeof(LightPassSpotLightUniforms), cmdb, 0, 1);
 
 			light->m_inputTexUvScaleAndOffset = Vec4(1.0f / 6.0f, 1.0f, faceIdx * (1.0f / 6.0f), 0.0f);
-			light->m_projectionParams = rqueue.m_projectionMatrix.extractPerspectiveUnprojectionParams();
+			light->m_invViewProjMat = invViewProjMat;
+			light->m_camPosPad1 = rqueue.m_cameraTransform.getTranslationPart();
 
-			Vec4 pos = vMat * splightEl->m_worldTransform.getTranslationPart().xyz1();
-			light->m_posRadius = Vec4(pos.xyz(), 1.0f / (splightEl->m_distance * splightEl->m_distance));
+			light->m_posRadius = Vec4(splightEl->m_worldTransform.getTranslationPart().xyz(),
+				1.0f / (splightEl->m_distance * splightEl->m_distance));
 
 			light->m_diffuseColorOuterCos = Vec4(splightEl->m_diffuseColor, cos(splightEl->m_outerAngle / 2.0f));
 
 			light->m_specularColorInnerCos = Vec4(splightEl->m_specularColor, cos(splightEl->m_innerAngle / 2.0f));
 
 			Vec3 lightDir = -splightEl->m_worldTransform.getZAxis().xyz();
-			lightDir = vMat.getRotationPart() * lightDir;
 			light->m_lightDirPad1 = lightDir.xyz0();
 
 			// Draw

+ 1 - 1
src/anki/renderer/LightShading.cpp

@@ -145,7 +145,7 @@ void LightShading::run(const RenderingContext& ctx, RenderPassWorkContext& rgrap
 	rgraphCtx.bindColorTextureAndSampler(1, 4, m_r->getSsao().getRt(), m_r->getLinearSampler());
 
 	rgraphCtx.bindColorTextureAndSampler(0, 0, m_r->getShadowMapping().getShadowmapRt(), m_r->getLinearSampler());
-	rgraphCtx.bindColorTextureAndSampler(0, 1, m_r->getIndirect().getReflectionRt(), m_r->getLinearSampler());
+	rgraphCtx.bindColorTextureAndSampler(0, 1, m_r->getIndirect().getReflectionRt(), m_r->getTrilinearRepeatSampler());
 	rgraphCtx.bindColorTextureAndSampler(0, 2, m_r->getIndirect().getIrradianceRt(), m_r->getLinearSampler());
 	cmdb->bindTextureAndSampler(0,
 		3,