premultiplied alpha support

This commit is contained in:
Sean Barrett 2015-03-17 02:10:58 -07:00
parent f49c90c03d
commit ba49d37e6a
2 changed files with 130 additions and 18 deletions

View File

@ -1,7 +1,6 @@
// @TODO
//
// - API for texture rotation on side faces (& top&bottom ?)
// - premultiplied alpha
// - edge clamp
// - better culling of vheight faces with vheight neighbors
// - better culling of non-vheight faces with fheight neighbors
@ -280,6 +279,7 @@ STBVXDEC void stbvox_set_input_stride(stbvox_mesh_maker *mm, int x_stride_in_byt
STBVXDEC stbvox_input_description *stbvox_get_input_description(stbvox_mesh_maker *mm);
STBVXDEC char *stbvox_get_vertex_shader(void);
STBVXDEC char *stbvox_get_fragment_shader(void);
STBVXDEC char *stbvox_get_fragment_shader_alpha_only(void);
STBVXDEC void stbvox_set_default_mesh(stbvox_mesh_maker *mm, int mesh);
STBVXDEC int stbvox_get_quad_count(stbvox_mesh_maker *mm, int mesh);
STBVXDEC void stbvox_get_transform(stbvox_mesh_maker *mm, float transform[3][3]);
@ -754,7 +754,7 @@ static char *stbvox_vertex_encoderogram =
// fragment output data
"flat out uvec4 facedata;\n"
" out vec3 objectspace_pos;\n"
" out vec3 voxelspace_pos;\n"
" out vec3 vnormal;\n"
" out float texlerp;\n"
" out float amb_occ;\n"
@ -778,8 +778,8 @@ static char *stbvox_vertex_encoderogram =
" texlerp = float( (attr_vertex >> 29u) ) / 7.0;\n" // a[29..31]
" vnormal = normal_table[(facedata.w>>2) & 31u];\n"
" objectspace_pos = offset * transform[0];\n" // object-to-world scale
" vec3 position = objectspace_pos + transform[1];\n" // object-to-world translate
" voxelspace_pos = offset * transform[0];\n" // mesh-to-object scale
" vec3 position = voxelspace_pos + transform[1];\n" // mesh-to-object translate
#ifdef STBVOX_DEBUG_TEST_NORMALS
" if ((facedata.w & 28u) == 16u || (facedata.w & 28u) == 24u)\n"
@ -812,7 +812,7 @@ static char *stbvox_fragment_program =
// vertex-shader output data
"flat in uvec4 facedata;\n"
" in vec3 objectspace_pos;\n"
" in vec3 voxelspace_pos;\n"
" in vec3 vnormal;\n"
" in float texlerp;\n"
" in float amb_occ;\n"
@ -847,7 +847,7 @@ static char *stbvox_fragment_program =
"vec3 compute_lighting(vec3 pos, vec3 norm, vec3 albedo, vec3 ambient);\n"
#endif
#if defined(STBVOX_CONFIG_FOG) || defined(STBVOX_CONFIG_FOG_SMOOTHSTEP)
"vec3 compute_fog(vec3 color, vec3 relative_pos);\n"
"vec3 compute_fog(vec3 color, vec3 relative_pos, float fragment_alpha);\n"
#endif
"void main()\n"
@ -878,7 +878,7 @@ static char *stbvox_fragment_program =
" vec4 color = texelFetch(color_table, int(color_id & 63u));\n"
#endif
" vec2 texcoord;\n"
" vec3 texturespace_pos = objectspace_pos + transform[2].xyz;\n"
" vec3 texturespace_pos = voxelspace_pos + transform[2].xyz;\n"
" texcoord.s = dot(texturespace_pos, texgen_s);\n"
" texcoord.t = dot(texturespace_pos, texgen_t);\n"
@ -893,13 +893,24 @@ static char *stbvox_fragment_program =
" if ((color_id & 64u) != 0u) tex1.xyz *= color.xyz;\n"
" if ((color_id & 128u) != 0u) tex2.xyz *= color.xyz;\n"
#ifdef STBVOX_CONFIG_PREMULTIPLIED_ALPHA
" tex2.rgba *= texlerp;\n"
#else
" tex2.a *= texlerp;\n"
#endif
// @TODO: could use a separate lookup table keyed on tex2 to determine this
" if (texblend_mode)\n"
" albedo = tex2.xyz * rlerp(tex2.a, 2.0*tex1.xyz, vec3(1.0,1.0,1.0));\n"
" else\n"
" albedo = rlerp(tex2.a, tex1.xyz, tex2.xyz);\n" // @TODO premultiplied alpha
" else {\n"
#ifdef STBVOX_CONFIG_PREMULTIPLIED_ALPHA
" albedo = (1.0-tex2.a)*tex1.xyz + tex2.xyz;\n"
" fragment_alpha = tex1.a;\n"
#else
" albedo = rlerp(tex2.a, tex1.xyz, tex2.xyz);\n"
" fragment_alpha = tex1.a*(1-tex2.a)+tex2.a;\n"
#endif
" }\n"
" fragment_alpha = tex1.a;\n"
#else // UNTEXTURED
@ -926,7 +937,7 @@ static char *stbvox_fragment_program =
" vec3 lit_color;\n"
" if (!emissive)\n"
#if defined(STBVOX_ICONFIG_LIGHTING) || defined(STBVOX_CONFIG_LIGHTING_SIMPLE)
" lit_color = compute_lighting(objectspace_pos + transform[1], normal, albedo, ambient_color);\n"
" lit_color = compute_lighting(voxelspace_pos + transform[1], normal, albedo, ambient_color);\n"
#else
" lit_color = albedo * ambient_color ;\n"
#endif
@ -934,11 +945,15 @@ static char *stbvox_fragment_program =
" lit_color = albedo;\n"
#if defined(STBVOX_ICONFIG_FOG) || defined(STBVOX_CONFIG_FOG_SMOOTHSTEP)
" vec3 dist = objectspace_pos + (transform[1] - camera_pos.xyz);\n"
" lit_color = compute_fog(lit_color, dist);\n"
" vec3 dist = voxelspace_pos + (transform[1] - camera_pos.xyz);\n"
" lit_color = compute_fog(lit_color, dist, fragment_alpha);\n"
#endif
#ifdef STBVOX_CONFIG_UNPREMULTIPLY
" vec4 final_color = vec4(lit_color/fragment_alpha, fragment_alpha);\n"
#else
" vec4 final_color = vec4(lit_color, fragment_alpha);\n"
#endif
" outcolor = final_color;\n"
"}\n"
@ -956,17 +971,106 @@ static char *stbvox_fragment_program =
#ifdef STBVOX_CONFIG_FOG_SMOOTHSTEP
"\n"
"vec3 compute_fog(vec3 color, vec3 relative_pos)\n"
"vec3 compute_fog(vec3 color, vec3 relative_pos, float fragment_alpha)\n"
"{\n"
" float f = sqrt(dot(relative_pos,relative_pos))/1320.0;\n"
" f = clamp(f, 0.0, 1.0);\n"
" f = 3.0*f*f - 2.0*f*f*f;\n" // smoothstep
" f = f*f;\n" // fade in more smoothly
#ifdef STBVOX_CONFIG_PREMULTIPLIED_ALPHA
" return rlerp(f, color.xyz, ambient[3]*fragment_alpha);\n"
#else
" return rlerp(f, color.xyz, ambient[3]);\n"
#endif
"}\n"
#endif
};
static char *stbvox_fragment_program_alpha_only =
{
STBVOX_SHADER_VERSION
// vertex-shader output data
"flat in uvec4 facedata;\n"
" in vec3 voxelspace_pos;\n"
" in float texlerp;\n"
// per-buffer data
"uniform vec3 transform[3];\n"
#ifndef STBVOX_ICONFIG_UNTEXTURED
// generally constant data
"uniform sampler2DArray tex_array[2];\n"
#ifdef STBVOX_CONFIG_PREFER_TEXBUFFER
"uniform samplerBuffer texscale;\n"
"uniform samplerBuffer texgen;\n"
#else
"uniform vec2 texscale[64];\n" // instead of 128, to avoid running out of uniforms
"uniform vec3 texgen[64];\n"
#endif
#endif
"out vec4 outcolor;\n"
"void main()\n"
"{\n"
" vec3 albedo;\n"
" float fragment_alpha;\n"
#ifndef STBVOX_ICONFIG_UNTEXTURED
// unpack the values
" uint tex1_id = facedata.x;\n"
" uint tex2_id = facedata.y;\n"
" uint texprojid = facedata.w & 31u;\n"
" bool texblend_mode = ((facedata.w & 128u) != 0u);\n"
#ifndef STBVOX_CONFIG_PREFER_TEXBUFFER
// load from uniforms / texture buffers
" vec3 texgen_s = texgen[texprojid];\n"
" vec3 texgen_t = texgen[texprojid+32u];\n"
" float tex1_scale = texscale[tex1_id & 63u].x;\n"
" float tex2_scale = texscale[tex2_id & 63u].y;\n"
#else
" vec3 texgen_s = texelFetch(texgen, int(texprojid)).xyz;\n"
" vec3 texgen_t = texelFetch(texgen, int(texprojid+32u)).xyz;\n"
" float tex1_scale = texelFetch(texscale, int(tex1_id & 127u)).x;\n"
" float tex2_scale = texelFetch(texscale, int(tex2_id & 127u)).y;\n"
#endif
" vec2 texcoord;\n"
" vec3 texturespace_pos = voxelspace_pos + transform[2].xyz;\n"
" texcoord.s = dot(texturespace_pos, texgen_s);\n"
" texcoord.t = dot(texturespace_pos, texgen_t);\n"
// @TODO: use 2 bits of facedata.w to enable animation of facedata.x & y?
" vec4 tex1 = texture(tex_array[0], vec3(tex1_scale * texcoord, float(tex1_id)));\n"
" vec4 tex2 = texture(tex_array[1], vec3(tex2_scale * texcoord, float(tex2_id)));\n"
" tex2.a *= texlerp;\n"
// @TODO: could use a separate lookup table keyed on tex2 to determine this
" if (texblend_mode)\n"
" ;\n"
" else {\n"
#ifdef STBVOX_CONFIG_PREMULTIPLIED_ALPHA
" fragment_alpha = tex1.a;\n"
#else
" fragment_alpha = tex1.a*(1-tex2.a)+tex2.a;\n"
#endif
" }\n"
#else // UNTEXTURED
" vec4 color;"
" fragment_alpha = 1.0;\n"
#endif
" outcolor = vec4(0.0, 0.0, 0.0, fragment_alpha);\n"
"}\n"
};
STBVXDEC char *stbvox_get_vertex_shader(void)
{
return stbvox_vertex_encoderogram;
@ -977,6 +1081,11 @@ STBVXDEC char *stbvox_get_fragment_shader(void)
return stbvox_fragment_program;
}
STBVXDEC char *stbvox_get_fragment_shader_alpha_only(void)
{
return stbvox_fragment_program_alpha_only;
}
static float stbvox_dummy_transform[3][3];
#ifdef STBVOX_CONFIG_PREFER_TEXBUFFER

View File

@ -21,7 +21,8 @@
#define STBVOX_CONFIG_PREFER_TEXBUFFER
//#define STBVOX_CONFIG_LIGHTING_SIMPLE
#define STBVOX_CONFIG_FOG_SMOOTHSTEP
#define STBVOX_CONFIG_PREMULTIPLIED_ALPHA // use this even though it doesn't really work for alpha test without next #define
//#define STBVOX_CONFIG_UNPREMULTIPLY // slower, makes windows & fancy leaves look better
#define STBVOX_ROTATION_IN_LIGHTING
#define STB_VOXEL_RENDER_IMPLEMENTATION
@ -33,7 +34,9 @@ extern void ods(char *fmt, ...);
#define FAST_CHUNK
#define IN_PLACE
#define SKIP_TERRAIN 0 // must be a multiple of 16; doesn't build some underground stuff
#define SKIP_TERRAIN 0 // use to avoid building underground stuff
// allows you to see what perf would be like if underground was efficiently culled,
// or if you were making a game without underground
enum
{
@ -189,7 +192,7 @@ unsigned char minecraft_info[256][7] =
{ C_empty },
{ C_solid, 54,54,54,54,54,54 },
{ C_solid, 125,125,125,125,125,125 },
{ C_solid, 124,124,124,124,124,124 },
{ C_solid, 126,126,126,126,126,126 },
{ C_empty }, // bars
{ C_trans, 49,49,49,49,49,49 }, // glass pane
{ C_solid, 136,136,136,136,137,137 }, // melon
@ -227,7 +230,7 @@ unsigned char minecraft_info[256][7] =
// 128
{ C_solid, 192,192,192,192,176,176 }, // sandstone stairs
{ C_solid, 32,32,32,32,32,32 }, // emerald ore
{ C_empty }, // ender chest
{ C_solid, 26,26,26,27,25,25 }, // ender chest
{ C_empty },
{ C_empty },
{ C_solid, 23,23,23,23,23,23 }, // emerald block