batファイルでプリプロセッサを実行してglslをhlslに変換

環境

VisualStudio2019Community

概要

VSに付属しているcl.exeを使用してプリプロセッサを実行します。

シェーダのdefineは貧弱だったりするので、先にclを実行して前処理を済ませたりします。

後は独自のスクリプト言語を作った時の前処理に使用するでしょうか。

今回はblenderのshaderのglslをhlslに変換したかったのでバッチファイルを作成してみました。



cl.exeが実行できるように環境変数にパスを通しておく必要があります。 自分の環境だと以下に存在します。

C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29333\bin\Hostx64\x64

以下のコードの場合、Testフォルダにglslのコードを入れます。

Outputフォルダにhlslが出力されます。

Intermediateはコンバート時に必要な中間ファイルが出力されるフォルダです。

mat型のオーバーロードに対応していません。vec型と同じようにして追加すればできるようになると思います。

コード

GlslToHlslDefs.h

#if PPMODE==0
#define vec2(...) vec2_overload_tuple((__VA_ARGS__,vec2_2,vec2_1))(__VA_ARGS__)
#define vec2_overload_tuple(tuple) vec2_overload tuple
#define vec2_overload(e1,e2,n,...) n
#define vec2_1(x) float2(x,x)
#define vec2_2(x,y) float2(x,y)

#define vec3(...) vec3_overload_tuple((__VA_ARGS__,vec3_3,vec3_2,vec3_1))(__VA_ARGS__)
#define vec3_overload_tuple(tuple) vec3_overload tuple
#define vec3_overload(e1,e2,e3,n,...) n
#define vec3_1(x) float3(x,x,x)
#define vec3_2(x, y) float3(x,y)
#define vec3_3(x, y, z) float3(x,y,z)

#define vec4(...) vec4_overload_tuple((__VA_ARGS__,vec4_4,vec4_3,vec4_2,vec4_1))(__VA_ARGS__)
#define vec4_overload_tuple(tuple) vec4_overload tuple
#define vec4_overload(e1,e2,e3,e4,n,...) n
#define vec4_1(x) float4(x,x,x,x)
#define vec4_2(x, y) float4(x,y)
#define vec4_3(x, y, z) float4(x,y,z)
#define vec4_4(x, y, z,w) float4(x,y,z,w)

#elif PPMODE==1

#define vec2 float2
#define vec3 float3
#define vec4 float4
#define mat2 float2x2
#define mat3 float3x3
#define mat4 float4x4
#define fract frac

#if 1
#define mod(x,y) ((x) - (y) * floor((x) / (y)))
#else
#define mod fmod
#endif

#define mix lerp
#define atan atan2
#define textureLod(tex, uv, lod) tex2Dlod(tex, float4(uv, 0, lod))
#define iTime _Time.y
#define iChannel0 _MainTex
#define iResolution float2(_MainTex_TexelSize.zw)
#define iMouse float3(0,0,0)
#define MUL_MAT(v0, v1) mul(v1, v0)
#define floatBitsToUint asuint
#define vector vecValue
#endif

GlslToHlsl.bat

@echo off
setlocal enabledelayedexpansion

set curDir=%~dp0
set srcDir=%curDir%\Test
set intermediateDir=%curDir%\Intermediate
set outputDir=%curDir%\Output
set headerPath=%curDir%\GlslToHlslDefs.h
rem echo %headerPath%

cd %srcDir%
for /r %%f in (*.glsl) do (
    set filePath=%%f
    set baseFile=%%~nf
    set extension=%%~xf
    set fileName=!baseFile!!extension!
    set tmpPath0=%intermediateDir%\!baseFile!.i0
    set tmpPath1=%intermediateDir%\!baseFile!.i1
    set tmpPath2=%intermediateDir%\!baseFile!.i2
    set outputPath=%outputDir%\!baseFile!.hlsl
    rem echo !tmpFile0!
    rem 
    copy %headerPath% !tmpPath0!
    type !filePath! >> !tmpPath0!
    call cl.exe /EP /P /C /D PPMODE=0 /Fi!tmpPath1! !tmpPath0!
    rem 
    copy %headerPath% !tmpPath2!
    type !tmpPath1! >> !tmpPath2!
    call cl.exe /EP /P /C /D PPMODE=1 /Fi!outputPath! !tmpPath2!
)
endlocal
pause

参考

[備忘録]マクロの引数の数でオーバーロード - Qiita

余談 C++ Design: g++とvc++の可変引数マクロの挙動の違い

GitHub - Unity-Technologies/HLSLcc: DirectX shader bytecode cross compiler

Shader Playground

NagaにしてOutputFormatをHLSLにする