material { name : TextureProjection, parameters : [ { type : sampler2d, name : color, precision: high }, { type : sampler2d, format : float, name : depth, }, { type : bool, name : flipUVs }, { type : bool, name : useDepth } ], variables : [ { name : screenPos, precision : high }, { name: sampledDepth, precision : high } ], requires : [ position, uv0 ], shadingModel : unlit, doubleSided : false, blending: opaque, depthWrite : true, depthCulling : true, culling: none, vertexDomain: device } // // This material projects a rendered color buffer texture onto a mesh. // // This allows you to texture the mesh by retrieving the output of this shader pass. // // We do this by: // 1) calculating the screenspace position of each vertex (VS) // 2) transforming each vertex to its UV coordinate (VS) // 3) at each UV coordinate, sampling from the input buffer at the screenspace position (FS). // // In a vertex shader, Filament sets gl_Position after materialVertex(..) is called, meaning we cannot change the vertex positions ourselves. // To achieve the same effect, we set the vertexDomain to device and set clipSpaceTransform. // vertex { void materialVertex(inout MaterialVertexInputs material) { mat4 transform = getWorldFromModelMatrix(); vec3 position = getPosition().xyz; vec4 worldPosition = mulMat4x4Float3(transform, position); vec4 clipSpace = getClipFromWorldMatrix() * worldPosition; material.screenPos = clipSpace; highp float2 uv = material.uv0; // Transform UVs (0 to 1) to clip space (-1 to 1 range) // UV (0,0) maps to (-1,-1) and UV (1,1) maps to (1,1) vec2 clipPosition = uv * 2.0 - 1.0; material.clipSpaceTransform = mat4( vec4(0.0, 0.0, 0.0, 0.0), vec4(0.0, 0.0, 0.0, 0.0), vec4(0.0, 0.0, 0.0, 0.0), vec4(clipPosition.x, clipPosition.y, 0.0, 1.0) ); } } fragment { void material(inout MaterialInputs material) { prepareMaterial(material); // calculate position in clip space vec3 clipSpace = variable_screenPos.xyz / variable_screenPos.w; // convert to [0,1] vec3 deviceCoords = clipSpace * 0.5 + 0.5; // flip depth coords to [1,0] float vertexDepth = clipSpace.z; vec2 uv = deviceCoords.xy; if(materialParams.flipUVs) { uv = uvToRenderTargetUV(uv); } vec4 sampledDepth = textureLod(materialParams_depth, uv, 0.0); //material.baseColor = vec4(sampledDepth.r, 0.0, 0.0, 1.0); //material.baseColor = vec4(vertexDepth, 0.0, 0.0, 1.0); if(materialParams.useDepth && (sampledDepth.r < 0.0001 || abs(vertexDepth - sampledDepth.r) > 0.001)) { material.baseColor = vec4(0.0, 0.0, 0.0, 0.0); } else { vec2 texSize = vec2(textureSize(materialParams_color, 0)); vec4 color = textureLod(materialParams_color, uvToRenderTargetUV(deviceCoords.xy), 0.0f); material.baseColor = color; } } }