Export blend4web glsl shader to HiFi


#1

Hello guys, I’m starting to get into shaders and I want to know if this is possible. I was playing with blend4web animating a the uv cordinates and found this around the web, is a addon that allows you to export materials to glsl as a .frag or .vec.
https://blenderartists.org/forum/showthread.php?233186-Export-Materials-to-GLSL-Code

And here the direc link to the addon: https://developer.blender.org/F151259 (Press the Download file on the right side column).


#2

Support for fragment shaders (.fs) yes, support for vertex shaders no.


#3

Also, it is currently possible to use shaders upon default Entities only. No custom models. Only skyboxes, spheres, and cubes can use custom shaders.

cc: @sam & @Jherico


#4

As part of a (not so) quick test I was able to coerce an exported shader into becoming a V2 procedural function – but it only “sorta” rendered things similarly between Blender and HiFi:

At first blush the generated Vertex shader seems unnecessary:.

Vertex shader
varying vec3 varposition;
varying vec3 varnormal;
void main()
{
 vec4 position = gl_Vertex;
 vec3 normal = gl_Normal;
 vec4 co = gl_ModelViewMatrix * position;
 varposition = co.xyz;
 varnormal = normalize(gl_NormalMatrix * normal);
 gl_Position = gl_ProjectionMatrix * co;
 gl_ClipVertex = co;
}

And the generated Fragment shader is a monolithic machine-generated beast (with lots of placeholder uniform values left empty):

exampleX932l32b
[...]
uniform vec3 unf1;
varying vec3 varnormal;
varying vec3 varposition;
uniform float unf7;
uniform vec3 unf12;
uniform float unf16;
uniform float unf26;
uniform float unf28;
uniform vec3 unf29;
const float cons34 = float(1.000000);
const vec4 cons38 = vec4(1.000000, 1.000000, 1.000000, 0.005000);
uniform float unf49;
uniform float unf52;
uniform vec3 unf58;
const float cons68 = float(0.720000);
uniform vec4 unf69;
const float cons75 = float(1.000000);
uniform float unf78;
uniform float unf79;
uniform float unf80;
uniform float unf81;
uniform float unf82;
uniform vec4 unf86;
uniform vec3 unf88;

Apparently it contains its own full pipeline (specular, fog, alpha, lighting, etc.):

Fragment shader snippet
void main(void)
{
	vec3 facingnormal = (gl_FrontFacing)? varnormal: -varnormal;
	vec3 tmp2;
	vec3 tmp4;
        // [...]
	vec4 tmp92;
	vec4 tmp94;

	set_rgb(unf1, tmp2);
	shade_norm(facingnormal, tmp4);
	shade_view(varposition, tmp6);
	shade_mul_value(unf7, vec4(tmp2, 1.0), tmp9);
	set_rgb_zero(tmp10);
	lamp_visibility_other(varposition, unf12, tmp13, tmp14, tmp15);
	lamp_falloff_invsquare(unf16, tmp14, tmp18);
	lamp_visibility_clamp(tmp18, tmp20);
	shade_inp(tmp4, tmp13, tmp23);
	shade_visifac(tmp23, tmp20, unf26, tmp27);
	shade_mul_value_v3(unf28, unf29, tmp30);
	shade_mul_value(tmp27, vec4(tmp30, 1.0), tmp33);
	mtex_value_invert(cons34, tmp35);
	mix_mult(tmp35, tmp33, cons38, tmp39);
	mtex_value_invert(tmp35, tmp41);
	shade_madd(tmp9, tmp39, vec4(tmp2, 1.0), tmp45);
	shade_cooktorr_spec(tmp4, tmp13, tmp6, unf49, tmp50);
	shade_spec_t(tmp41, unf52, tmp20, tmp50, tmp55);
	shade_add_spec(tmp55, tmp30, unf58, tmp59);
	shade_add_clamped(vec4(tmp10, 1.0), vec4(tmp59, 1.0), tmp62);
	shade_clamp_positive(tmp62, tmp64);
	shade_clamp_positive(tmp45, tmp66);
	shade_maddf(tmp66, cons68, unf69, tmp70);
	shade_add(tmp70, tmp64, tmp73);
	mtex_alpha_to_col(tmp73, cons75, tmp76);
	shade_mist_factor(varposition, unf78, unf79, unf80, unf81, unf82, tmp83);
	mix_blend(tmp83, tmp76, unf86, tmp87);
	shade_world_mix(unf88, tmp87, tmp90);
	shade_alpha_opaque(tmp90, tmp92);
	linearrgb_to_srgb(tmp92, tmp94);

	gl_FragColor = tmp94;
}

The good news is that a boilerplate strategy is possible using #define magic to avoid touching the generated void main(void) block (or any of the inline GLSL functions Blender adds to the mix). Basically:

header.frag + (exported .frag) + footer.frag

Except there was a catch: not even things like diffuse color are currently exported by the Blender Addon…

However, the uniform values do seem to be available from the low-level Blender API export function, so for the test I extracted them manually into a JSON format and then inserted/replaced by hand into the assembled shader.

I’ve uploaded everything into a gist for reference:


  • example.js – a Client script for pulling everything together with some procedural Shape Entities.

#5

For simpler testing I made a new Addon – hifi_export_material.py – that abandons the monolithic Blender shader and instead attempts to generate ready-to-go 1:1 procedural shaders using:

  • Diffuse Color, Diffuse Intensity
  • Specular Color, Specular Intensity, Hardness
  • Shading Emit

Regrettably, even with just those material properties, a 1:1 translation does not yet seem possible given the overloaded interpretations happening within HiFi shading internals. For example, changing emit from 0.0 to anything else results in a radical shift in rendering behavior (including with how specular values get interpreted). So for now I’m abandoning this approach.

It is good for making blue balls (and other primitives) shinier though:


(client script for above)


#6

#7

Nice, the link to the addon is broken. Those blue primitives look like car materials.


#8

Hmm… not sure. Are you able to see this github.com repo view of hifi_export_material.py?

(if so the “Raw” button goes to the same place as original link)


#9

@Judas SpongeBob… CubePants!!!

Also if curious about what’s happening, I took a stab at bootstrapping a ProceduralShaders page on the Wiki.