TensorFlowJS之Shader的生成

本文深入探讨了Shader如何根据用户输入的Tensor和输出的Tensor自动生成的过程。详细解析了makeShader函数如何遍历inputsInfo,为每个InputInfo生成相应的采样器和位置信息,并介绍了UV坐标在顶点着色器中的作用及输出变量的Shader生成方式。

Shader是根据用户输入的Tensor和输出的Tensor自动生成的。生成的函数是makeShader。

输入变量的Shader

输入包括采样器和UV坐标。
如果定义了两个Tensor,这段代码运行的结果是生成两个采样器:

uniform sampler2D A;
uniform int offsetA;
uniform sampler2D B;
uniform int offsetB;

makeShader会遍历inputsInfo,对每个InputInfo生成相应的采样器和位置信息(offset*是针对某些输入会被slice的情形):

export function makeShader(
    inputsInfo: InputInfo[], outputShape: ShapeInfo, userCode: string,
    usesPackedTextures: boolean): string {
  const prefixSnippets: string[] = [];
  inputsInfo.forEach(x => {
    const size = util.sizeFromShape(x.shapeInfo.logicalShape);
    // Snippet when we decided to upload the values as uniform.
    if (x.shapeInfo.isUniform) {
      prefixSnippets.push(
          `uniform float ${x.name}${size > 1 ? `[${size}]` : ''};`);
    } else {
      prefixSnippets.push(`uniform sampler2D ${x.name};`);
      prefixSnippets.push(`uniform int offset${x.name};`);
    }
  });
  const inputPrefixSnippet = prefixSnippets.join('\n');

  const inputSamplingSnippet =
      inputsInfo
          .map(x => getInputSamplingSnippet(x, outputShape, usesPackedTextures))
          .join('\n');

UV坐标的生成(其实UV坐标是来自顶点着色器的,这里对顶点着色器传递过来的UV坐标进行了加工):

function getOutputSamplingSnippet(
    outShape: number[], outTexShape: [number, number]): string {
  switch (outShape.length) {
    case 0:
      return getOutputScalarCoords();
    case 1:
      return getOutput1DCoords(outShape as [number], outTexShape);
    case 2:
      return getOutput2DCoords(outShape as [number, number], outTexShape);
    case 3:
      return getOutput3DCoords(
          outShape as [number, number, number], outTexShape);
    case 4:
      return getOutput4DCoords(
          outShape as [number, number, number, number], outTexShape);
    case 5:
      return getOutput5DCoords(
          outShape as [number, number, number, number, number], outTexShape);
    case 6:
      return getOutput6DCoords(
          outShape as [number, number, number, number, number, number],
          outTexShape);
    default:
      throw new Error(
          `${outShape.length}-D output sampling is not yet supported`);
  }
}

输出变量的Shader

通常只定义一个输出。

function getFloatTextureSetRSnippet(glsl: GLSL): string {
  return `
    void setOutput(float val) {
      ${glsl.output} = vec4(val, 0, 0, 0);
    }
  `;
}

对于一种情况,输出是:

void setOutput(float val) {
   outputColor = vec4(val, 0, 0, 0);
}

JavaScript-结构体的map-join

TFJS里面很常见这个map-join模式。

function updateItem(x) {
	return x.name+":"+x.value;
}
var array = [];
array.push({ name: 1, value: "a" });
array.push({ name: 2, value: "b" });
const map1 = array.map(x => updateItem(x));

function logMapElements(value, key, map) {
  console.log(`m[${key}] = ${value}`);
}

map1.forEach(logMapElements);

输出结果:

> "m[0] = 1:a"
> "m[1] = 2:b"
> "1:a,2:b"
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值