首页 > 解决方案 > 如何在表面着色器中获取纹理坐标?

问题描述

我被要求使用表面着色器在两个给定点之间画一条线。该点以纹理坐标(0 到 1 之间)给出,并直接进入 Unity 中的表面着色器。我想通过计算像素位置并查看它是否在那条线上来做到这一点。所以我要么尝试将纹理坐标转换为世界位置,要么我得到像素相对于该纹理坐标的位置。

但我只在统一着色器手册中找到了 worldPos 和 screenPos。有什么方法可以让我获得纹理坐标中的位置(或者至少获得世界 pos 中纹理对象的大小?)

标签: unity3dshader

解决方案


这是一个简单的例子:

Shader "Line" {
    Properties {
        // Easiest way to get access of UVs in surface shaders is to define a texture
        _MainTex("Texture", 2D) = "white"{}
        // We can pack both points into one vector
        _Line("Start Pos (xy), End Pos (zw)", Vector) = (0, 0, 1, 1) 

    }

    SubShader {

        Tags { "RenderType" = "Opaque" }
        CGPROGRAM
        #pragma surface surf Lambert
        sampler2D _MainTex;
        float4 _Line;

        struct Input {
            // This UV value will now represent the pixel coordinate in UV space
            float2 uv_MainTex;
        };
        void surf (Input IN, inout SurfaceOutput o) {
            float2 start = _Line.xy;
            float2 end = _Line.zw;
            float2 pos = IN.uv_MainTex.xy;

            // Do some calculations

            return fixed4(1, 1, 1, 1);
        }
        ENDCG
    }
}

这是一篇关于如何计算一个点是否在一条线上的好帖子:

如何检查一个点是否位于另外两个点之间的线上

假设您使用以下签名定义了一个函数:

inline bool IsPointOnLine(float2 p, float2 l1, float2 l2)

然后对于返回值,你可以这样写:

return IsPointOnLine(pos, start, end) ? _LineColor : _BackgroundColor

如果您想要不使用纹理的 UV 坐标,我建议改为制作顶点片段着色器并float2 uv : TEXCOORD0在 appdata/VertexInput 结构内定义。然后,您可以将其传递给顶点函数内的片段着色器。


推荐阅读