========== 内部函数 ========== 除了常见的 HLSL 函数外,DSHL 还支持特殊的**内在**函数,这些函数由着色器编译器处理。 .. note:: 这些函数将在运行时由 stcode 系统进行评估(除非在编译时已知),因此不能在 :ref:`preshader` 部分之外使用。 -------------------------------------------- float time_phase(float period, float offset) -------------------------------------------- 计算指定周期和偏移量的全局时间相位(范围 ``[0, 1)`` 中的数字)。 返回 ``frac((shadersGlobalTime + offset) / period)`` 或 ``period == 0`` 时的 ``shadersGlobalTime``,其中 ``shadersGlobalTime`` 是游戏开始时的时间(以秒为单位)。 .. code-block:: c (ps) { current_time@f1 = time_phase(0, 0); } ------------------ float sin(float x) ------------------ 计算 ``sin`` 函数。 .. code-block:: c (ps) { foo@f1 = sin(3.14); } ------------------ float cos(float x) ------------------ 计算 ``cos`` 函数。 .. code-block:: c (ps) { foo@f1 = cos(3.14); } --------------------------- float pow(float x, float y) --------------------------- 将 ``x`` 提高到 ``y`` 的幂。 .. code-block:: c (ps) { foo@f1 = pow(1.2, 3.4); } -------------------------------- float4 vecpow(float4 v, float a) -------------------------------- 将向量 ``v`` 的每个分量提升为 ``a`` 的幂。 .. code-block:: c local float4 v = (1, 2, 3, 4); local float a = 3.33; (ps) { foo@f1 = vecpow(v, a); } ------------------- float sqrt(float x) ------------------- 计算 ``x`` 的平方根。 .. code-block:: c (ps) { foo@f1 = sqrt(1.3); } --------------------------- float min(float x, float y) --------------------------- 查找两个值的最小值。 .. code-block:: c (ps) { foo@f1 = min(-1, 1); } --------------------------- float max(float x, float y) --------------------------- 求两个值的最大值。 .. code-block:: c (ps) { foo@f1 = max(-1, 1); } ------------------------------------- float fsel(float a, float b, float c) ------------------------------------- 返回 ``(a >= 0.0f) ? b : c`` .. code-block:: c (ps) { foo@f1 = fsel(1, 2, 3); } ------------------------- float4 sRGBread(float4 v) ------------------------- 将 ``v`` 的 RGB 分量提高到 ``2.2`` 的幂。 返回 ``float4(pow(v.r, 2.2f), pow(v.g, 2.2f), pow(v.b, 2.2f), v.a)`` .. code-block:: c (ps) { srgb_color@f3 = sRGBread(some_color); } // 在转换为 float3 时将舍弃 alpha ----------------------------------------- float4 get_dimensions(texture t, int mip) ----------------------------------------- 获取 ``mip`` 层的纹理 ``t`` 信息。 返回 ``float4(width, height, depth_or_array_slices, mip_levels)``。 对于体积纹理, ``depth_or_array_slices`` 存储深度;对于纹理数组,``depth_or_array_slices`` 存储数组切片数。 对于立方体纹理,``depth_or_array_slices = 1``。 .. code-block:: c texture ssao_tex; (ps) { ssao_size@f4 = get_dimensions(ssao_tex, 0); } ------------------------ float get_size(buffer b) ------------------------ 以元素为单位获取缓冲区 ``b`` 的大小。 返回 ``float(buffer_size_in_elements)``。 .. code-block:: c buffer some_buf; (ps) { buf_size@f1 = get_size(some_buf); } .. warning:: ``(RW)ByteAddressBuffer``的 ``get_size`` 将返回缓冲区中 DWORD(4 字节块)的个数。 这与 ``(RW)ByteAddressBuffer::GetDimensions`` 纯 HLSL 函数相反,后者返回的是字节数。 --------------------- float4 get_viewport() --------------------- 获取视口信息。 返回 ``float4(top_left_x, top_left_y, width, height)``。 .. code-block:: c (ps) { viewport@f4 = get_viewport(); } ------------------------- int exists_tex(texture t) ------------------------- 运行时,检查纹理 ``t`` 是否存在(从 C++ 端绑定到着色器)。 可以将其视为运行时的 ``t != NULL`` 预着色器检查。 返回值可以保存到变量中,并用于统一的 HLSL 分支。 使用方法 .. code-block:: c texture example_texture; (ps) { example_texture@tex2d = example_texture; example_texture_exists@i1 = exists_tex(example_texture); } hlsl(ps) { if (example_texture_exists) { /* ... */ } } 如果存在纹理,则返回 ``1``,否则返回 ``0``。 ------------------------ int exists_buf(buffer b) ------------------------ 类似于 ``exists_tex``。 在运行时,检查缓冲区 ``b`` 是否存在(从 C++ 端绑定到着色器)。 你可以把它看作是运行时的 ``b != NULL`` 着色器前检查。 返回值可以保存到变量中,并用于统一的 HLSL 分支。 使用方法 .. code-block:: c buffer example_buffer; (ps) { example_buffer@buf = example_buffer hlsl { StructuredBuffer example_buffer@buf; }; example_buffer_exists@i1 = exists_buf(example_buffer); } hlsl(ps) { if (example_buffer_exists) { /* ... */ } } 如果缓冲区存在,则返回 ``1``,否则返回 ``0``。