add texture projection material

This commit is contained in:
Nick Fisher
2025-03-08 13:25:15 +08:00
parent 7ed7ff48b9
commit 7d87d229d0

View File

@@ -4,23 +4,43 @@ material {
{ {
type : sampler2d, type : sampler2d,
name : color, name : color,
precision: medium precision: high
},
{
type : bool,
name : flipUVs
} }
], ],
variables : [ variables : [
{ {
name : screenPos, name : screenPos,
precision : medium precision : high
} }
], ],
requires : [ position, uv0 ], requires : [ position, uv0 ],
shadingModel : unlit, shadingModel : unlit,
doubleSided : false, doubleSided : false,
blending: transparent,
depthWrite : true, depthWrite : true,
depthCulling : false, depthCulling : false,
culling: none,
vertexDomain: device 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 { vertex {
void materialVertex(inout MaterialVertexInputs material) { void materialVertex(inout MaterialVertexInputs material) {
mat4 transform = getWorldFromModelMatrix(); mat4 transform = getWorldFromModelMatrix();
@@ -28,21 +48,22 @@ vertex {
vec4 worldPosition = mulMat4x4Float3(transform, position); vec4 worldPosition = mulMat4x4Float3(transform, position);
vec4 clipSpace = getClipFromWorldMatrix() * worldPosition; vec4 clipSpace = getClipFromWorldMatrix() * worldPosition;
// calculate NDC coordinates for vertex material.screenPos = clipSpace;
material.screenPos.xy = (clipSpace.xy / clipSpace.w) * 0.5 + 0.5;
// Get UV coordinates from mesh highp float2 uv = material.uv0;
vec2 uv = material.uv0; if(materialParams.flipUVs) {
uv = uvToRenderTargetUV(uv);
}
// Transform UVs to clip space (-1 to 1 range) // 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) // UV (0,0) maps to (-1,-1) and UV (1,1) maps to (1,1)
vec2 clipPosition = uv * 2.0 - 1.0; vec2 clipPosition = uv * 2.0 - 1.0;
material.clipSpaceTransform = mat4( 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(0.0, 0.0, 0.0, 0.0),
vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 0.0),
vec4(clipPosition, 0.0, 1.0) vec4(clipPosition.x, clipPosition.y, 0.0, 1.0)
); );
} }
} }
@@ -50,8 +71,15 @@ vertex {
fragment { fragment {
void material(inout MaterialInputs material) { void material(inout MaterialInputs material) {
prepareMaterial(material); prepareMaterial(material);
vec4 sp = clamp(variable_screenPos, 0.0, 1.0);
vec4 color = textureLod(materialParams_color, uvToRenderTargetUV(sp.xy), 0.0f); vec2 texCoords = variable_screenPos.xy / variable_screenPos.w;
material.baseColor = vec4(color.xyz, 1.0); texCoords = texCoords * 0.5 + 0.5;
vec2 texSize = vec2(textureSize(materialParams_color, 0));
//float textureAspectRatio = texSize.x / texSize.y;
//texCoords.x *= textureAspectRatio;
vec4 color = textureLod(materialParams_color, uvToRenderTargetUV(texCoords.xy), 0.0f);
material.baseColor = color;
} }
} }