Browse Source

Renderer: Optimizations

Panagiotis Christopoulos Charitos 8 years ago
parent
commit
91c472ef39

+ 7 - 16
shaders/FsCommonFrag.glsl

@@ -23,8 +23,9 @@ layout(ANKI_TEX_BINDING(1, 0)) uniform sampler2D anki_msDepthRt;
 #define anki_u_time u_lightingUniforms.rendererSizeTimePad1.z
 #define RENDERER_SIZE (u_lightingUniforms.rendererSizeTimePad1.xy * 0.5)
 
-layout(location = 0) in vec3 in_vertPosViewSpace;
-layout(location = 1) flat in float in_alpha;
+layout(location = 0) flat in float in_alpha;
+layout(location = 1) in vec2 in_uv;
+layout(location = 2) in vec3 in_posViewSpace;
 
 layout(location = 0) out vec4 out_color;
 
@@ -82,7 +83,7 @@ void particleSoftTextureAlpha(in sampler2D depthMap, in sampler2D tex, in float
 #define particleTextureAlpha_DEFINED
 void particleTextureAlpha(in sampler2D tex, vec4 mulColor, vec4 addColor, in float alpha)
 {
-	vec4 color = texture(tex, gl_PointCoord) * mulColor + addColor;
+	vec4 color = texture(tex, in_uv) * mulColor + addColor;
 	color.a *= alpha;
 
 	writeGBuffer(color);
@@ -117,17 +118,7 @@ vec3 computeLightColor(vec3 diffCol)
 	vec3 outColor = vec3(0.0);
 
 	// Compute frag pos in view space
-	vec3 fragPos;
-	{
-		float depth = gl_FragCoord.z;
-		fragPos.z = u_lightingUniforms.projectionParams.z / (u_lightingUniforms.projectionParams.w + depth);
-
-		vec2 screenSize = 1.0 / RENDERER_SIZE;
-
-		vec2 ndc = gl_FragCoord.xy * screenSize * 2.0 - 1.0;
-
-		fragPos.xy = ndc * u_lightingUniforms.projectionParams.xy * fragPos.z;
-	}
+	vec3 fragPos = in_posViewSpace;
 
 	// Find the cluster and then the light counts
 	uint clusterIdx = computeClusterIndex(gl_FragCoord.xy / RENDERER_SIZE,
@@ -209,7 +200,7 @@ vec3 computeLightColor(vec3 diffCol)
 #define particleTextureAlphaLight_DEFINED
 void particleTextureAlphaLight(in sampler2D tex, in float alpha)
 {
-	vec4 color = texture(tex, gl_PointCoord);
+	vec4 color = texture(tex, in_uv);
 	color.a *= alpha;
 
 	color.rgb = computeLightColor(color.rgb);
@@ -222,7 +213,7 @@ void particleTextureAlphaLight(in sampler2D tex, in float alpha)
 #define particleAnimatedTextureAlphaLight_DEFINED
 void particleAnimatedTextureAlphaLight(sampler2DArray tex, float alpha, float layerCount, float period)
 {
-	vec4 color = readAnimatedTextureRgba(tex, layerCount, period, gl_PointCoord, anki_u_time);
+	vec4 color = readAnimatedTextureRgba(tex, layerCount, period, in_uv, anki_u_time);
 
 	color.rgb = computeLightColor(color.rgb);
 

+ 12 - 12
shaders/FsCommonVert.glsl

@@ -25,13 +25,13 @@ layout(location = POSITION_LOCATION) in vec3 in_position;
 layout(location = SCALE_LOCATION) in float in_scale;
 layout(location = ALPHA_LOCATION) in float in_alpha;
 
-layout(location = 0) out vec3 out_vertPosViewSpace;
-layout(location = 1) flat out float out_alpha;
+layout(location = 0) flat out float out_alpha;
+layout(location = 1) out vec2 out_uv;
+layout(location = 2) out vec3 out_posViewSpace;
 
 out gl_PerVertex
 {
 	vec4 gl_Position;
-	float gl_PointSize;
 };
 
 #define setPositionVec3_DEFINED
@@ -53,11 +53,17 @@ void writePositionMvp(in mat4 mvp)
 }
 
 #define particle_DEFINED
-void particle(in mat4 mvp)
+void particle(in mat4 mvp, in mat3 camRot, in mat4 viewMat)
 {
-	ANKI_WRITE_POSITION(mvp * vec4(in_position, 1));
+	const vec2 POSITIONS[4] = vec2[](vec2(-0.5, -0.5), vec2(0.5, -0.5), vec2(-0.5, 0.5), vec2(0.5, 0.5));
+	vec3 worldPos = camRot * vec3(POSITIONS[gl_VertexID] * in_scale, 0.0) + in_position;
+	ANKI_WRITE_POSITION(mvp * vec4(worldPos, 1.0));
+
+	out_posViewSpace = (viewMat * vec4(worldPos, 1.0)).xyz;
+
 	out_alpha = in_alpha;
-	gl_PointSize = in_scale * u_lightingUniforms.rendererSizeTimePad1.x * 0.5 / gl_Position.w;
+
+	out_uv = POSITIONS[gl_VertexID] + 0.5;
 }
 
 #define writeAlpha_DEFINED
@@ -66,10 +72,4 @@ void writeAlpha(in float alpha)
 	out_alpha = alpha;
 }
 
-#define writeVertPosViewSpace_DEFINED
-void writeVertPosViewSpace(in mat4 modelViewMat)
-{
-	out_vertPosViewSpace = vec3(modelViewMat * vec4(in_position, 1.0));
-}
-
 #endif

+ 6 - 3
shaders/Volumetric.frag.glsl

@@ -95,6 +95,11 @@ void main()
 
 	vec2 ndc = in_uv * 2.0 - 1.0;
 
+	vec3 farPos;
+	farPos.xy = ndc * u_lightingUniforms.projectionParams.xy * farZ;
+	farPos.z = farZ;
+	vec3 viewDir = normalize(farPos);
+
 	uint i = uint(in_uv.x * float(CLUSTER_COUNT.x));
 	uint j = uint(in_uv.y * float(CLUSTER_COUNT.y));
 	uint ij = j * CLUSTER_COUNT.x + i;
@@ -144,9 +149,7 @@ void main()
 				break;
 			}
 
-			vec3 fragPos;
-			fragPos.z = zMedian;
-			fragPos.xy = ndc * u_lightingUniforms.projectionParams.xy * fragPos.z;
+			vec3 fragPos = viewDir * (zMedian / viewDir.z);
 
 			newCol += computeLightColor(fragPos, plightCount, plightIdx, slightCount, slightIdx);
 		}

+ 2 - 1
src/anki/gr/CommandBuffer.h

@@ -142,7 +142,8 @@ public:
 	/// @{
 
 	/// Bind vertex buffer.
-	void bindVertexBuffer(U32 binding, BufferPtr buff, PtrSize offset, PtrSize stride);
+	void bindVertexBuffer(
+		U32 binding, BufferPtr buff, PtrSize offset, PtrSize stride, VertexStepRate stepRate = VertexStepRate::VERTEX);
 
 	/// Setup a vertex attribute.
 	void setVertexAttribute(U32 location, U32 buffBinding, const PixelFormat& fmt, PtrSize relativeOffset);

+ 2 - 1
src/anki/gr/Enums.h

@@ -115,7 +115,8 @@ enum class VertexStepRate : U8
 {
 	VERTEX,
 	INSTANCE,
-	DRAW
+	DRAW,
+	COUNT
 };
 
 enum class ComponentFormat : U8

+ 8 - 4
src/anki/gr/gl/CommandBuffer.cpp

@@ -75,7 +75,8 @@ void CommandBuffer::finish()
 	getManager().getImplementation().getRenderingThread().finishCommandBuffer(CommandBufferPtr(this));
 }
 
-void CommandBuffer::bindVertexBuffer(U32 binding, BufferPtr buff, PtrSize offset, PtrSize stride)
+void CommandBuffer::bindVertexBuffer(
+	U32 binding, BufferPtr buff, PtrSize offset, PtrSize stride, VertexStepRate stepRate)
 {
 	class Cmd final : public GlCommand
 	{
@@ -84,18 +85,21 @@ void CommandBuffer::bindVertexBuffer(U32 binding, BufferPtr buff, PtrSize offset
 		U32 m_binding;
 		PtrSize m_offset;
 		PtrSize m_stride;
+		Bool8 m_instanced;
 
-		Cmd(U32 binding, BufferPtr buff, PtrSize offset, PtrSize stride)
+		Cmd(U32 binding, BufferPtr buff, PtrSize offset, PtrSize stride, Bool instanced)
 			: m_buff(buff)
 			, m_binding(binding)
 			, m_offset(offset)
 			, m_stride(stride)
+			, m_instanced(instanced)
 		{
 		}
 
 		Error operator()(GlState& state)
 		{
 			glBindVertexBuffer(m_binding, m_buff->m_impl->getGlName(), m_offset, m_stride);
+			glVertexBindingDivisor(m_binding, (m_instanced) ? 1 : 0);
 			return ErrorCode::NONE;
 		}
 	};
@@ -103,9 +107,9 @@ void CommandBuffer::bindVertexBuffer(U32 binding, BufferPtr buff, PtrSize offset
 	ANKI_ASSERT(buff);
 	ANKI_ASSERT(stride > 0);
 
-	if(m_impl->m_state.bindVertexBuffer(binding, buff, offset, stride))
+	if(m_impl->m_state.bindVertexBuffer(binding, buff, offset, stride, stepRate))
 	{
-		m_impl->pushBackNewCommand<Cmd>(binding, buff, offset, stride);
+		m_impl->pushBackNewCommand<Cmd>(binding, buff, offset, stride, stepRate == VertexStepRate::INSTANCE);
 	}
 }
 

+ 3 - 1
src/anki/gr/gl/StateTracker.h

@@ -64,16 +64,18 @@ public:
 		BufferImpl* m_buff = nullptr;
 		PtrSize m_offset = 0;
 		PtrSize m_stride = 0;
+		VertexStepRate m_stepRate = VertexStepRate::COUNT;
 	};
 
 	Array<VertexBuffer, MAX_VERTEX_ATTRIBUTES> m_vertBuffs;
 
-	Bool bindVertexBuffer(U32 binding, BufferPtr buff, PtrSize offset, PtrSize stride)
+	Bool bindVertexBuffer(U32 binding, BufferPtr buff, PtrSize offset, PtrSize stride, VertexStepRate stepRate)
 	{
 		VertexBuffer& b = m_vertBuffs[binding];
 		b.m_buff = buff->m_impl.get();
 		b.m_offset = offset;
 		b.m_stride = stride;
+		b.m_stepRate = stepRate;
 		return true;
 	}
 

+ 13 - 2
src/anki/renderer/Drawer.cpp

@@ -213,6 +213,9 @@ Error SetupRenderableVariableVisitor::visit(const TRenderableVariableTemplate& r
 		ANKI_ASSERT(cachedTrfs == 0 && "Cannot have transform");
 		uniSet(mvar, &vp, 1);
 		break;
+	case BuiltinMaterialVariableId::V_MATRIX:
+		uniSet(mvar, &v, 1);
+		break;
 	case BuiltinMaterialVariableId::NORMAL_MATRIX:
 	{
 		ANKI_ASSERT(cachedTrfs > 0);
@@ -248,6 +251,13 @@ Error SetupRenderableVariableVisitor::visit(const TRenderableVariableTemplate& r
 		uniSet(mvar, &bmvp[0], cachedTrfs);
 		break;
 	}
+	case BuiltinMaterialVariableId::CAMERA_ROT_MATRIX:
+	{
+		// Calc the billboard rotation matrix
+		Mat3 rot = v.getRotationPart().getTransposed();
+		uniSet(mvar, &rot, 1);
+		break;
+	}
 	case BuiltinMaterialVariableId::MAX_TESS_LEVEL:
 	{
 		const RenderComponentVariable& base = rvar;
@@ -377,12 +387,13 @@ Error RenderableDrawer::flushDrawcall(DrawContext& ctx, CompleteRenderingBuildIn
 		const RenderingVertexBufferBinding& binding = build.m_out.m_vertexBufferBindings[i];
 		if(binding.m_buffer)
 		{
-			cmdb->bindVertexBuffer(i, binding.m_buffer, binding.m_offset, binding.m_stride);
+			cmdb->bindVertexBuffer(i, binding.m_buffer, binding.m_offset, binding.m_stride, binding.m_stepRate);
 		}
 		else
 		{
 			ANKI_ASSERT(!!(binding.m_token));
-			cmdb->bindVertexBuffer(i, binding.m_token.m_buffer, binding.m_token.m_offset, binding.m_stride);
+			cmdb->bindVertexBuffer(
+				i, binding.m_token.m_buffer, binding.m_token.m_offset, binding.m_stride, binding.m_stepRate);
 		}
 	}
 

+ 2 - 0
src/anki/resource/Material.h

@@ -36,8 +36,10 @@ enum class BuiltinMaterialVariableId : U8
 	MVP_MATRIX,
 	MV_MATRIX,
 	VP_MATRIX,
+	V_MATRIX,
 	NORMAL_MATRIX,
 	BILLBOARD_MVP_MATRIX,
+	CAMERA_ROT_MATRIX,
 	MAX_TESS_LEVEL,
 	MS_DEPTH_MAP,
 	COUNT

+ 14 - 0
src/anki/resource/MaterialLoader.cpp

@@ -160,6 +160,10 @@ static ANKI_USE_RESULT Error computeBuiltin(const CString& name, BuiltinMaterial
 	{
 		out = BuiltinMaterialVariableId::VP_MATRIX;
 	}
+	else if(name == "anki_viewMatrix")
+	{
+		out = BuiltinMaterialVariableId::V_MATRIX;
+	}
 	else if(name == "anki_n")
 	{
 		out = BuiltinMaterialVariableId::NORMAL_MATRIX;
@@ -168,6 +172,10 @@ static ANKI_USE_RESULT Error computeBuiltin(const CString& name, BuiltinMaterial
 	{
 		out = BuiltinMaterialVariableId::BILLBOARD_MVP_MATRIX;
 	}
+	else if(name == "anki_cameraRotation")
+	{
+		out = BuiltinMaterialVariableId::CAMERA_ROT_MATRIX;
+	}
 	else if(name == "anki_tessLevel")
 	{
 		out = BuiltinMaterialVariableId::MAX_TESS_LEVEL;
@@ -204,12 +212,18 @@ static ShaderVariableDataType getBuiltinType(BuiltinMaterialVariableId in)
 	case BuiltinMaterialVariableId::VP_MATRIX:
 		out = ShaderVariableDataType::MAT4;
 		break;
+	case BuiltinMaterialVariableId::V_MATRIX:
+		out = ShaderVariableDataType::MAT4;
+		break;
 	case BuiltinMaterialVariableId::NORMAL_MATRIX:
 		out = ShaderVariableDataType::MAT3;
 		break;
 	case BuiltinMaterialVariableId::BILLBOARD_MVP_MATRIX:
 		out = ShaderVariableDataType::MAT4;
 		break;
+	case BuiltinMaterialVariableId::CAMERA_ROT_MATRIX:
+		out = ShaderVariableDataType::MAT3;
+		break;
 	case BuiltinMaterialVariableId::MAX_TESS_LEVEL:
 		out = ShaderVariableDataType::FLOAT;
 		break;

+ 1 - 2
src/anki/resource/ParticleEmitterResource.cpp

@@ -151,8 +151,7 @@ Error ParticleEmitterResource::load(const ResourceFilename& filename)
 	// sanity checks
 	//
 
-	static const char* ERROR = "Particle emmiter: "
-							   "Incorrect or missing value %s";
+	static const char* ERROR = "Particle emmiter: Incorrect or missing value %s";
 
 	if(m_particle.m_life <= 0.0)
 	{

+ 4 - 2
src/anki/scene/ParticleEmitter.cpp

@@ -284,6 +284,7 @@ Error ParticleEmitter::buildRendering(const RenderingBuildInfoIn& in, RenderingB
 	out.m_vertexBufferBindingCount = 1;
 	out.m_vertexBufferBindings[0].m_token = m_vertBuffToken;
 	out.m_vertexBufferBindings[0].m_stride = VERTEX_SIZE;
+	out.m_vertexBufferBindings[0].m_stepRate = VertexStepRate::INSTANCE;
 
 	out.m_vertexAttributeCount = 3;
 	out.m_vertexAttributes[0].m_bufferBinding = 0;
@@ -296,10 +297,11 @@ Error ParticleEmitter::buildRendering(const RenderingBuildInfoIn& in, RenderingB
 	out.m_vertexAttributes[2].m_format = PixelFormat(ComponentFormat::R32, TransformFormat::FLOAT);
 	out.m_vertexAttributes[2].m_relativeOffset = sizeof(Vec3) + sizeof(F32);
 
-	out.m_topology = PrimitiveTopology::POINTS;
+	out.m_topology = PrimitiveTopology::TRIANGLE_STRIP;
 
 	out.m_drawArrays = true;
-	out.m_drawcall.m_arrays.m_count = m_aliveParticlesCount;
+	out.m_drawcall.m_arrays.m_instanceCount = m_aliveParticlesCount;
+	out.m_drawcall.m_arrays.m_count = 4;
 
 	// The particles are already in world position but materials use the MVP
 	out.m_hasTransform = true;

+ 4 - 2
src/anki/scene/RenderComponent.h

@@ -117,16 +117,18 @@ class RenderingVertexBufferBinding : public VertexBufferBinding
 {
 public:
 	StagingGpuMemoryToken m_token;
+	VertexStepRate m_stepRate = VertexStepRate::VERTEX;
 
 	Bool operator==(const RenderingVertexBufferBinding& b) const
 	{
 		if(m_token)
 		{
-			return m_token == b.m_token;
+			return m_token == b.m_token && m_stepRate == b.m_stepRate;
 		}
 		else
 		{
-			return static_cast<const VertexBufferBinding&>(*this) == static_cast<const VertexBufferBinding&>(b);
+			return static_cast<const VertexBufferBinding&>(*this) == static_cast<const VertexBufferBinding&>(b)
+				&& m_stepRate == b.m_stepRate;
 		}
 	}