본문으로 건너뛰기

TSMPDecodeCommon.cginc

TSMPDecodeCommon.cginc는 TSMP codec decode pass용 공용 shader include입니다. Source texture uniforms, vertex input/output structs, default vertex function, block sampling helpers, YCoCg conversion helpers를 정의합니다.

TSMP source frame을 pixel 또는 block 기준으로 sample하는 codec-specific decode logic 앞에 include하세요.

Include path:

#include "Packages/com.kibalab.tsmp.core/Runtime/Codecs/Common/Shaders/cgincs/TSMPDecodeCommon.cginc"

Texture inputs​

SymbolType용도
_MainTexTexture2DSource TSMP frame texture.
sampler_MainTexSamplerState_MainTex sampler.

정확한 byte recovery가 필요하므로 decode shader는 point-like sampling을 사용해야 합니다. Helpers는 mip selection을 피하기 위해 SampleLevel(..., 0.0)을 호출합니다.

Common uniforms​

Uniform용도
_BlockSizeCodec block 하나의 pixel size.
_SampleSizeBlock 내부에서 sample할 pixel 수. 설정되지 않으면 helper가 _BlockSize에서 default를 고릅니다.
_StartBlockFirst payload block index.
_ByteCountDecoder가 요청한 valid payload bytes 수.
_ActiveWidthBlocksRow당 writable/readable block 수.
_SourceWidthSource frame width in pixels.
_SourceHeightSource frame height in pixels.
_OutputWidthByte output texture width in pixels.
_OutputHeightByte output texture height in pixels.
_FlipYNon-zero이면 source sampling을 vertically flip합니다.

이 값들은 decoder/material setup path가 할당합니다. Uniform이 제공된다면 custom codec은 texture dimensions에서 추측하지 않는 것이 좋습니다.

Vertex structs​

Include는 다음 struct를 정의합니다.

struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};

struct v2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
};

Decode pass가 position과 UV만 필요할 때 사용하세요. Custom interpolator가 필요하면 이 default shape에 의존하지 말고 별도 pass에서 직접 struct를 정의하는 편이 좋습니다.

vert(appdata v)​

v2f vert(appdata v)

Default vertex function입니다. UnityObjectToClipPos(v.vertex)로 clip-space position을 만들고 v.uv를 전달합니다.

Pixel sampling helpers​

SampleRgbAtTopLeftPixel(float2 pixel)​

주어진 source pixel의 center를 sample하고 RGB를 반환합니다.

Y coordinate는 _FlipY로 계산됩니다.

float rawY = (pixel.y + 0.5) / _SourceHeight;
float uvY = lerp(rawY, 1.0 - rawY, _FlipY);

SampleLumaAtTopLeftPixel(float2 pixel)​

Pixel RGB를 sample하고 average luma를 반환합니다.

dot(rgb, float3(0.33333334, 0.33333334, 0.33333334))

Perceptual luma가 아니라 단순 channel average입니다.

Block sampling helpers​

SampleBlockRgb(float blockX, float blockY)​

Block 중앙의 square region을 sample하고 average RGB를 반환합니다.

Sample size rule:

  • _SampleSize > 0.5이면 floor(_SampleSize)를 사용합니다.
  • 아니면 _BlockSize >= 8일 때 4, 더 작은 block에서는 3을 사용합니다.
  • Sample size는 1..min(_BlockSize, 8)로 clamp됩니다.

Loop는 8x8로 제한되어 codec sampling cost가 예측 가능합니다.

SampleBlockLuma(float blockX, float blockY)​

SampleBlockRgb와 같은 방식이지만 average luma를 반환합니다.

SampleBlockByIndex(float blockIndex)​

_ActiveWidthBlocks로 linear block index를 (blockX, blockY)로 변환한 뒤 SampleBlockRgb를 호출합니다.

SampleLumaBlockByIndex(float blockIndex)​

Linear block index를 (blockX, blockY)로 변환한 뒤 SampleBlockLuma를 호출합니다.

Payload block helper​

float PayloadBlockIndex(int symbolIndex)

다음을 반환합니다.

_StartBlock + symbolIndex

Header/payload boundary를 hard-code하지 않고 codec symbol index를 payload block index로 매핑할 때 사용하세요.

Integer helper​

int FloorDivNonNegative(int value, float divisor)

Non-negative value에 대해 floor(value / divisor)를 반환합니다. Byte index를 symbol index로 매핑할 때 사용할 수 있습니다.

Color conversion helpers​

float3 TSMP_RgbToYCoCg(float3 c)
float3 TSMP_YCoCgToRgb(float3 c)

Compatibility alias도 정의됩니다.

#define RgbToYCoCg TSMP_RgbToYCoCg
#define YCoCgToRgb TSMP_YCoCgToRgb

새 shader code에서는 macro/name conflict를 줄이기 위해 가능하면 TSMP_ 이름을 사용하세요.

Common use with TSMPDecodeByteOutput.cginc​

일반 decode shader는 TSMPDecodeCommon.cginc로 sampling helper를 받고, DecodeByte(int byteIndex)를 구현한 뒤, TSMPDecodeByteOutput.cginc를 include해서 byte output texture를 씁니다.

#include "Packages/com.kibalab.tsmp.core/Runtime/Codecs/Common/Shaders/cgincs/TSMPDecodeCommon.cginc"

int DecodeByte(int byteIndex)
{
float blockIndex = PayloadBlockIndex(byteIndex);
float luma = SampleLumaBlockByIndex(blockIndex);
return (int)round(saturate(luma) * 255.0);
}

#include "Packages/com.kibalab.tsmp.core/Runtime/Codecs/Common/Shaders/cgincs/TSMPDecodeByteOutput.cginc"

실제 codec은 보통 한 block에서 여러 bit 또는 symbol을 decode합니다. 이 예시는 include flow를 보여주기 위한 것입니다.