| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653 |
- type node_shader_t = {
- context?: node_shader_context_t;
- shader_type?: string;
- ins?: string[];
- outs?: string[];
- shared_samplers?: string[];
- uniforms?: string[];
- functions?: map_t<string, string>;
- main?: string;
- main_end?: string;
- main_normal?: string;
- main_attribs?: string;
- write_normal?: i32;
- // References
- bposition?: bool;
- wposition?: bool;
- mposition?: bool;
- vposition?: bool;
- wvpposition?: bool;
- ndcpos?: bool;
- wtangent?: bool;
- vvec?: bool;
- vvec_cam?: bool;
- n?: bool;
- nattr?: bool;
- dotnv?: bool;
- };
- function node_shader_create(context: node_shader_context_t, shader_type: string): node_shader_t {
- let raw: node_shader_t = {};
- raw.context = context;
- raw.shader_type = shader_type;
- raw.ins = [];
- raw.outs = [];
- raw.shared_samplers = [];
- raw.uniforms = [];
- raw.functions = map_create();
- raw.main = "";
- raw.main_end = "";
- raw.main_normal = "";
- raw.main_attribs = "";
- raw.write_normal = 0;
- return raw;
- }
- function node_shader_add_in(raw: node_shader_t, s: string) {
- array_push(raw.ins, s);
- }
- function node_shader_add_out(raw: node_shader_t, s: string) {
- array_push(raw.outs, s);
- }
- function node_shader_add_uniform(raw: node_shader_t, s: string, link: string = null) {
- let ar: string[] = string_split(s, " ");
- // layout(RGBA8) image3D voxels
- let utype: string = ar[ar.length - 2];
- let uname: string = ar[ar.length - 1];
- if (starts_with(utype, "sampler") || starts_with(utype, "image") || starts_with(utype, "uimage")) {
- let is_image: bool = (starts_with(utype, "image") || starts_with(utype, "uimage")) ? true : false;
- node_shader_context_add_texture_unit(raw.context, utype, uname, link, is_image);
- }
- else {
- // Prefer vec4[] for d3d to avoid padding
- if (ar[0] == "float" && string_index_of(ar[1], "[") >= 0) {
- ar[0] = "floats";
- ar[1] = string_split(ar[1], "[")[0];
- }
- else if (ar[0] == "vec4" && string_index_of(ar[1], "[") >= 0) {
- ar[0] = "floats";
- ar[1] = string_split(ar[1], "[")[0];
- }
- node_shader_context_add_constant(raw.context, ar[0], ar[1], link);
- }
- if (array_index_of(raw.uniforms, s) == -1) {
- array_push(raw.uniforms, s);
- }
- }
- function node_shader_add_shared_sampler(raw: node_shader_t, s: string) {
- if (array_index_of(raw.shared_samplers, s) == -1) {
- array_push(raw.shared_samplers, s);
- let ar: string[] = string_split(s, " ");
- // layout(RGBA8) sampler2D tex
- let utype: string = ar[ar.length - 2];
- let uname: string = ar[ar.length - 1];
- node_shader_context_add_texture_unit(raw.context, utype, uname, null, false);
- }
- }
- function node_shader_add_function(raw: node_shader_t, s: string) {
- let fname: string = string_split(s, "(")[0];
- if (map_get(raw.functions, fname) != null) {
- return;
- }
- map_set(raw.functions, fname, s);
- }
- function node_shader_write(raw: node_shader_t, s: string) {
- if (raw.write_normal > 0) {
- raw.main_normal += s + "\n";
- }
- else {
- raw.main += s + "\n";
- }
- }
- function node_shader_write_end(raw: node_shader_t, s: string) {
- raw.main_end += s + "\n";
- }
- function node_shader_write_attrib(raw: node_shader_t, s: string) {
- raw.main_attribs += s + "\n";
- }
- function node_shader_data_size(raw: node_shader_t, data: string): string {
- if (data == "float1") {
- return "1";
- }
- else if (data == "float2" || data == "short2norm") {
- return "2";
- }
- else if (data == "float3") {
- return "3";
- }
- else { // float 4 || short4norm
- return "4";
- }
- }
- function node_shader_vstruct_to_vsin(raw: node_shader_t) {
- let vs: vertex_element_t[] = raw.context.data.vertex_elements;
- for (let i: i32 = 0; i < vs.length; ++i) {
- let e: vertex_element_t = vs[i];
- node_shader_add_in(raw, "vec" + node_shader_data_size(raw, e.data) + " " + e.name);
- }
- }
- ///if (arm_direct3d11 || arm_direct3d12)
- function node_shader_get_hlsl(raw: node_shader_t, shared_sampler: string): string {
- let s: string = "#define HLSL\n";
- s += "#define textureArg(tex) Texture2D tex,SamplerState tex ## _sampler\n";
- s += "#define texturePass(tex) tex,tex ## _sampler\n";
- s += "#define sampler2D Texture2D\n";
- s += "#define sampler3D Texture3D\n";
- s += "#define texture(tex, coord) tex.Sample(tex ## _sampler, coord)\n";
- s += "#define textureShared(tex, coord) tex.Sample(" + shared_sampler + ", coord)\n";
- s += "#define textureLod(tex, coord, lod) tex.SampleLevel(tex ## _sampler, coord, lod)\n";
- s += "#define textureLodShared(tex, coord, lod) tex.SampleLevel(" + shared_sampler + ", coord, lod)\n";
- s += "#define texelFetch(tex, coord, lod) tex.Load(float3(coord.xy, lod))\n";
- s += "uint2 _GetDimensions(Texture2D tex, uint lod) { uint x, y; tex.GetDimensions(x, y); return uint2(x, y); }\n";
- s += "#define textureSize _GetDimensions\n";
- s += "#define mod(a, b) (a % b)\n";
- s += "#define vec2 float2\n";
- s += "#define vec3 float3\n";
- s += "#define vec4 float4\n";
- s += "#define ivec2 int2\n";
- s += "#define ivec3 int3\n";
- s += "#define ivec4 int4\n";
- s += "#define mat2 float2x2\n";
- s += "#define mat3 float3x3\n";
- s += "#define mat4 float4x4\n";
- s += "#define dFdx ddx\n";
- s += "#define dFdy ddy\n";
- s += "#define inversesqrt rsqrt\n";
- s += "#define fract frac\n";
- s += "#define mix lerp\n";
- let in_ext: string = "";
- let out_ext: string = "";
- // Input structure
- let index: i32 = 0;
- if (raw.ins.length > 0) {
- s += "struct SPIRV_Cross_Input {\n";
- index = 0;
- array_sort(raw.ins, function (pa: any_ptr, pb: any_ptr): i32 {
- let stra: string = DEREFERENCE(pa);
- let strb: string = DEREFERENCE(pb);
- // Sort inputs by name
- return strcmp(substring(stra, 4, stra.length), substring(strb, 4, strb.length));
- });
- for (let i: i32 = 0; i < raw.ins.length; ++i) {
- let a: string = raw.ins[i];
- s += a + in_ext + " : TEXCOORD" + index + ";\n";
- index++;
- }
- // Built-ins
- if (raw.shader_type == "vert" && string_index_of(raw.main, "gl_VertexID") >= 0) {
- s += "uint gl_VertexID : SV_VertexID;\n";
- array_push(raw.ins, "uint gl_VertexID");
- }
- if (raw.shader_type == "vert" && string_index_of(raw.main, "gl_InstanceID") >= 0) {
- s += "uint gl_InstanceID : SV_InstanceID;\n";
- array_push(raw.ins, "uint gl_InstanceID");
- }
- s += "};\n";
- }
- // Output structure
- let num: i32 = 0;
- if (raw.outs.length > 0 || raw.shader_type == "vert") {
- s += "struct SPIRV_Cross_Output {\n";
- array_sort(raw.outs, function (pa: any_ptr, pb: any_ptr): i32 {
- let stra: string = DEREFERENCE(pa);
- let strb: string = DEREFERENCE(pb);
- // Sort outputs by name
- return strcmp(substring(stra, 4, stra.length), substring(strb, 4, strb.length));
- });
- index = 0;
- if (raw.shader_type == "vert") {
- for (let i: i32 = 0; i < raw.outs.length; ++i) {
- let a: string = raw.outs[i];
- s += a + out_ext + " : TEXCOORD" + index + ";\n";
- index++;
- }
- s += "float4 svpos : SV_POSITION;\n";
- }
- else {
- let out: string = raw.outs[0];
- // Multiple render targets
- if (char_at(out, out.length - 1) == "]") {
- num = parse_int(char_at(out, out.length - 2));
- s += "vec4 frag_color[" + num + "] : SV_TARGET0;\n";
- }
- else {
- s += "vec4 frag_color : SV_TARGET0;\n";
- }
- }
- s += "};\n";
- }
- for (let i: i32 = 0; i < raw.uniforms.length; ++i) {
- let a: string = raw.uniforms[i];
- s += "uniform " + a + ";\n";
- if (starts_with(a, "sampler")) {
- s += "SamplerState " + string_split(a, " ")[1] + "_sampler;\n";
- }
- }
- if (raw.shared_samplers.length > 0) {
- for (let i: i32 = 0; i < raw.shared_samplers.length; ++i) {
- let a: string = raw.shared_samplers[i];
- s += "uniform " + a + ";\n";
- }
- s += "SamplerState " + shared_sampler + ";\n";
- }
- let keys: string[] = map_keys(raw.functions);
- for (let i: i32 = 0; i < keys.length; ++i) {
- let f: string = map_get(raw.functions, keys[i]);
- s += f + "\n";
- }
- // Begin main
- if (raw.outs.length > 0 || raw.shader_type == "vert") {
- if (raw.ins.length > 0) {
- s += "SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input) {\n";
- }
- else {
- s += "SPIRV_Cross_Output main() {\n";
- }
- }
- else {
- if (raw.ins.length > 0) {
- s += "void main(SPIRV_Cross_Input stage_input) {\n";
- }
- else {
- s += "void main() {\n";
- }
- }
- // Declare inputs
- for (let i: i32 = 0; i < raw.ins.length; ++i) {
- let a: string = raw.ins[i];
- let b: string = substring(a, 5, a.length); // Remove type "vec4 "
- s += a + " = stage_input." + b + ";\n";
- }
- if (raw.shader_type == "vert") {
- s += "vec4 gl_Position;\n";
- for (let i: i32 = 0; i < raw.outs.length; ++i) {
- let a: string = raw.outs[i];
- s += a + ";\n";
- }
- }
- else {
- if (raw.outs.length > 0) {
- if (num > 0) {
- s += "vec4 frag_color[" + num + "];\n";
- }
- else {
- s += "vec4 frag_color;\n";
- }
- }
- }
- s += raw.main_attribs;
- s += raw.main_normal;
- s += raw.main;
- s += raw.main_end;
- // Write output structure
- if (raw.outs.length > 0 || raw.shader_type == "vert") {
- s += "SPIRV_Cross_Output stage_output;\n";
- if (raw.shader_type == "vert") {
- s += "gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n";
- s += "stage_output.svpos = gl_Position;\n";
- for (let i: i32 = 0; i < raw.outs.length; ++i) {
- let a: string = raw.outs[i];
- let b: string = substring(a, 5, a.length); // Remove type "vec4 "
- s += "stage_output." + b + " = " + b + ";\n";
- }
- }
- else {
- if (num > 0) {
- for (let i: i32 = 0; i < num; ++i) {
- s += "stage_output.frag_color[" + i + "] = frag_color[" + i + "];\n";
- }
- }
- else {
- s += "stage_output.frag_color = frag_color;\n";
- }
- }
- s += "return stage_output;\n";
- }
- s += "}\n";
- return s;
- }
- ///end
- ///if arm_metal
- function node_shader_get_msl(raw: node_shader_t, shared_sampler: string): string {
- let s: string = "#define METAL\n";
- s += "#include <metal_stdlib>\n";
- s += "#include <simd/simd.h>\n";
- s += "using namespace metal;\n";
- s += "#define textureArg(tex) texture2d<float> tex,sampler tex ## _sampler\n";
- s += "#define texturePass(tex) tex,tex ## _sampler\n";
- s += "#define sampler2D texture2d<float>\n";
- s += "#define sampler3D texture3d<float>\n";
- s += "#define texture(tex, coord) tex.sample(tex ## _sampler, coord)\n";
- s += "#define textureShared(tex, coord) tex.sample(" + shared_sampler + ", coord)\n";
- s += "#define textureLod(tex, coord, lod) tex.sample(tex ## _sampler, coord, level(lod))\n";
- s += "#define textureLodShared(tex, coord, lod) tex.sample(" + shared_sampler + ", coord, level(lod))\n";
- s += "#define texelFetch(tex, coord, lod) tex.read(uint2(coord), uint(lod))\n";
- s += "float2 _getDimensions(texture2d<float> tex, uint lod) { return float2(tex.get_width(lod), tex.get_height(lod)); }\n";
- s += "#define textureSize _getDimensions\n";
- s += "#define mod(a, b) fmod(a, b)\n";
- s += "#define vec2 float2\n";
- s += "#define vec3 float3\n";
- s += "#define vec4 float4\n";
- s += "#define ivec2 int2\n";
- s += "#define ivec3 int3\n";
- s += "#define ivec4 int4\n";
- s += "#define mat2 float2x2\n";
- s += "#define mat3 float3x3\n";
- s += "#define mat4 float4x4\n";
- s += "#define dFdx dfdx\n";
- s += "#define dFdy dfdy\n";
- s += "#define inversesqrt rsqrt\n";
- s += "#define mul(a, b) b * a\n";
- s += "#define discard discard_fragment()\n";
- // Input structure
- let index: i32 = 0;
- s += "struct main_in {\n";
- index = 0;
- array_sort(raw.ins, function (pa: any_ptr, pb: any_ptr): i32 {
- let stra: string = DEREFERENCE(pa);
- let strb: string = DEREFERENCE(pb);
- // Sort inputs by name
- return strcmp(substring(stra, 4, stra.length), substring(strb, 4, strb.length));
- });
- if (raw.shader_type == "vert") {
- for (let i: i32 = 0; i < raw.ins.length; ++i) {
- let a: string = raw.ins[i];
- s += a + " [[attribute(" + index + ")]];\n";
- index++;
- }
- }
- else {
- for (let i: i32 = 0; i < raw.ins.length; ++i) {
- let a: string = raw.ins[i];
- s += a + " [[user(locn" + index + ")]];\n";
- index++;
- }
- }
- s += "};\n";
- // Output structure
- let num: i32 = 0;
- if (raw.outs.length > 0 || raw.shader_type == "vert") {
- s += "struct main_out {\n";
- array_sort(raw.outs, function (pa: any_ptr, pb: any_ptr): i32 {
- let stra: string = DEREFERENCE(pa);
- let strb: string = DEREFERENCE(pb);
- // Sort outputs by name
- return strcmp(substring(stra, 4, stra.length), substring(strb, 4, strb.length));
- });
- index = 0;
- if (raw.shader_type == "vert") {
- for (let i: i32 = 0; i < raw.outs.length; ++i) {
- let a: string = raw.outs[i];
- s += a + " [[user(locn" + index + ")]];\n";
- index++;
- }
- s += "float4 svpos [[position]];\n";
- }
- else {
- let out: string = raw.outs[0];
- // Multiple render targets
- if (char_at(out, out.length - 1) == "]") {
- num = parse_int(char_at(out, out.length - 2));
- for (let i: i32 = 0; i < num; ++i) {
- s += "float4 frag_color_" + i + " [[color(" + i + ")]];\n";
- }
- }
- else {
- s += "float4 frag_color [[color(0)]];\n";
- }
- }
- s += "};\n";
- }
- let samplers: string[] = [];
- if (raw.uniforms.length > 0) {
- s += "struct main_uniforms {\n";
- for (let i: i32 = 0; i < raw.uniforms.length; ++i) {
- let a: string = raw.uniforms[i];
- if (starts_with(a, "sampler")) {
- array_push(samplers, a);
- }
- else {
- s += a + ";\n";
- }
- }
- s += "};\n";
- }
- let keys: string[] = map_keys(raw.functions);
- for (let i: i32 = 0; i < keys.length; ++i) {
- let f: string = map_get(raw.functions, keys[i]);
- s += f + "\n";
- }
- // Begin main declaration
- s += "#undef texture\n";
- if (raw.shader_type == "vert") {
- s += "vertex ";
- }
- else {
- s += "fragment ";
- }
- if (raw.outs.length > 0 || raw.shader_type == "vert") {
- s += "main_out ";
- }
- else {
- s += "void ";
- }
- s += "my_main(";
- s += "main_in in [[stage_in]]";
- if (raw.uniforms.length > 0) {
- let bufi: i32 = raw.shader_type == "vert" ? 1 : 0;
- s += ", constant main_uniforms& uniforms [[buffer(" + bufi + ")]]";
- }
- if (samplers.length > 0) {
- for (let i: i32 = 0; i < samplers.length; ++i) {
- s += ", " + samplers[i] + " [[texture(" + i + ")]]";
- s += ", sampler " + string_split(samplers[i], " ")[1] + "_sampler [[sampler(" + i + ")]]";
- }
- }
- if (raw.shared_samplers.length > 0) {
- for (let i: i32 = 0; i < raw.shared_samplers.length; ++i) {
- let index: i32 = samplers.length + i;
- s += ", " + raw.shared_samplers[i] + " [[texture(" + index + ")]]";
- }
- let len: i32 = samplers.length;
- s += ", sampler " + shared_sampler + " [[sampler(" + len + ")]]";
- }
- // Built-ins
- if (raw.shader_type == "vert" && string_index_of(raw.main, "gl_VertexID") >= 0) {
- s += ", uint gl_VertexID [[vertex_id]]";
- }
- if (raw.shader_type == "vert" && string_index_of(raw.main, "gl_InstanceID") >= 0) {
- s += ", uint gl_InstanceID [[instance_id]]";
- }
- // End main declaration
- s += ") {\n";
- s += "#define texture(tex, coord) tex.sample(tex ## _sampler, coord)\n";
- // Declare inputs
- for (let i: i32 = 0; i < raw.ins.length; ++i) {
- let a: string = raw.ins[i];
- let b: string = substring(a, 5, a.length); // Remove type "vec4 "
- s += a + " = in." + b + ";\n";
- }
- for (let i: i32 = 0; i < raw.uniforms.length; ++i) {
- let a: string = raw.uniforms[i];
- if (!starts_with(a, "sampler")) {
- let b: string = string_split(a, " ")[1]; // Remove type "vec4 "
- if (string_index_of(b, "[") >= 0) {
- b = substring(b, 0, string_index_of(b, "["));
- let type: string = string_split(a, " ")[0];
- s += "constant " + type + " *" + b + " = uniforms." + b + ";\n";
- }
- else {
- s += a + " = uniforms." + b + ";\n";
- }
- }
- }
- if (raw.shader_type == "vert") {
- s += "vec4 gl_Position;\n";
- for (let i: i32 = 0; i < raw.outs.length; ++i) {
- let a: string = raw.outs[i];
- s += a + ";\n";
- }
- }
- else {
- if (raw.outs.length > 0) {
- if (num > 0) {
- s += "vec4 frag_color[" + num + "];\n";
- }
- else {
- s += "vec4 frag_color;\n";
- }
- }
- }
- s += raw.main_attribs;
- s += raw.main_normal;
- s += raw.main;
- s += raw.main_end;
- // Write output structure
- if (raw.outs.length > 0 || raw.shader_type == "vert") {
- s += "main_out out = {};\n";
- if (raw.shader_type == "vert") {
- s += "gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n";
- s += "out.svpos = gl_Position;\n";
- for (let i: i32 = 0; i < raw.outs.length; ++i) {
- let a: string = raw.outs[i];
- let b: string = string_split(a, " ")[1]; // Remove type "vec4 "
- s += "out." + b + " = " + b + ";\n";
- }
- }
- else {
- if (num > 0) {
- for (let i: i32 = 0; i < num; ++i) {
- s += "out.frag_color_" + i + " = frag_color[" + i + "];\n";
- }
- }
- else {
- s += "out.frag_color = frag_color;\n";
- }
- }
- s += "return out;\n";
- }
- s += "}\n";
- return s;
- }
- ///end
- ///if (arm_opengl || arm_vulkan)
- function node_shader_get_glsl(raw: node_shader_t, shared_sampler: string, version_header: string): string {
- let s: string = version_header;
- s += "#define textureArg(tex) sampler2D tex\n";
- s += "#define texturePass(tex) tex\n";
- s += "#define mul(a, b) b * a\n";
- s += "#define textureShared texture\n";
- s += "#define textureLodShared textureLod\n";
- s += "#define atan2(x, y) atan(y, x)\n";
- let in_ext: string = "";
- let out_ext: string = "";
- for (let i: i32 = 0; i < raw.ins.length; ++i) {
- let a: string = raw.ins[i];
- s += "in " + a + in_ext + ";\n";
- }
- for (let i: i32 = 0; i < raw.outs.length; ++i) {
- let a: string = raw.outs[i];
- s += "out " + a + out_ext + ";\n";
- }
- for (let i: i32 = 0; i < raw.uniforms.length; ++i) {
- let a: string = raw.uniforms[i];
- s += "uniform " + a + ";\n";
- }
- for (let i: i32 = 0; i < raw.shared_samplers.length; ++i) {
- let a: string = raw.shared_samplers[i];
- s += "uniform " + a + ";\n";
- }
- let keys: string[] = map_keys(raw.functions);
- for (let i: i32 = 0; i < keys.length; ++i) {
- let f: string = map_get(raw.functions, keys[i]);
- s += f + "\n";
- }
- s += "void main() {\n";
- s += raw.main_attribs;
- s += raw.main_normal;
- s += raw.main;
- s += raw.main_end;
- s += "}\n";
- return s;
- }
- ///end
- function node_shader_get(raw: node_shader_t): string {
- if (raw.shader_type == "vert") {
- node_shader_vstruct_to_vsin(raw);
- }
- let shared_sampler: string = "shared_sampler";
- if (raw.shared_samplers.length > 0) {
- shared_sampler = string_split(raw.shared_samplers[0], " ")[1] + "_sampler";
- }
- ///if (arm_direct3d11 || arm_direct3d12)
- let s: string = node_shader_get_hlsl(raw, shared_sampler);
- ///elseif arm_metal
- let s: string = node_shader_get_msl(raw, shared_sampler);
- ///elseif arm_vulkan
- let version_header: string = "#version 450\n";
- let s: string = node_shader_get_glsl(raw, shared_sampler, version_header);
- ///elseif arm_android
- let version_header: string = "#version 300 es\n";
- if (raw.shader_type == "frag") {
- version_header += "precision highp float;\n";
- version_header += "precision mediump int;\n";
- }
- let s: string = node_shader_get_glsl(raw, shared_sampler, version_header);
- ///elseif arm_opengl
- let version_header: string = "#version 330\n";
- let s: string = node_shader_get_glsl(raw, shared_sampler, version_header);
- ///end
- return s;
- }
|