mirror of
https://github.com/Cesarus85/ringfall-mjolnir-vr.git
synced 2026-10-17 13:00:25 +02:00
Web: meter blend in the shader
WebGL refuses blendFunc(CONSTANT_ALPHA, CONSTANT_COLOR), so the meters (ammo counters) drew with the previous blend and a GL error each frame.
This commit is contained in:
1 parent
a3277d94dc
commit
5cd65a0cb0
4 files changed
+64
-2
No files matched your search
@@ -394,6 +394,9 @@ struct program_entry
|
||||
GLint bump_matrix, bump_luminance, texture_scale;
|
||||
GLint texture_lod_bias;
|
||||
GLint screen_offset;
|
||||
/* nv2a_pixel_shader_key's source_blend's color, and what it last had */
|
||||
GLint blend_constant;
|
||||
float blend_constant_value[4];
|
||||
/* the lights of a draw lit for each pixel (XGPU_MODEL_LIGHT_COUNT), and
|
||||
constants_serial at their last upload */
|
||||
GLint model_lights;
|
||||
@@ -793,6 +796,27 @@ void xgpu_gl_texture_deleted(unsigned int texture)
|
||||
}
|
||||
}
|
||||
|
||||
/* the source blend factor the pixel shader applies (nv2a_pixel_shader_key's
|
||||
source_blend), when the draw's blend mixes a constant color factor with a
|
||||
constant alpha one, which WebGL refuses; 0 otherwise */
|
||||
static unsigned char source_blend_in_shader(void)
|
||||
{
|
||||
#ifdef HALO_WEB
|
||||
DWORD source = D3D__RenderState[D3DRS_SRCBLEND], destination = D3D__RenderState[D3DRS_DESTBLEND];
|
||||
int source_kind = source == D3DBLEND_CONSTANTCOLOR || source == D3DBLEND_INVCONSTANTCOLOR ? 1 :
|
||||
source == D3DBLEND_CONSTANTALPHA || source == D3DBLEND_INVCONSTANTALPHA ? 2 : 0;
|
||||
int destination_kind = destination == D3DBLEND_CONSTANTCOLOR || destination == D3DBLEND_INVCONSTANTCOLOR ? 1 :
|
||||
destination == D3DBLEND_CONSTANTALPHA || destination == D3DBLEND_INVCONSTANTALPHA ? 2 : 0;
|
||||
|
||||
if (D3D__RenderState[D3DRS_ALPHABLENDENABLE] && source_kind && destination_kind && source_kind != destination_kind)
|
||||
{
|
||||
return source == D3DBLEND_CONSTANTCOLOR ? 1 : source == D3DBLEND_INVCONSTANTCOLOR ? 2 :
|
||||
source == D3DBLEND_CONSTANTALPHA ? 3 : 4;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void state_enable(unsigned char *shadow, GLenum capability, BOOL enabled)
|
||||
{
|
||||
unsigned char value = enabled ? 1 : 0;
|
||||
@@ -2827,6 +2851,7 @@ static struct program_entry *program_get(GLuint vertex_shader, GLuint fragment_s
|
||||
entry->texture_scale = glGetUniformLocation(entry->program, "texture_scale");
|
||||
entry->texture_lod_bias = glGetUniformLocation(entry->program, "texture_lod_bias");
|
||||
entry->screen_offset = glGetUniformLocation(entry->program, "screen_offset");
|
||||
entry->blend_constant = glGetUniformLocation(entry->program, "blend_constant");
|
||||
entry->model_lights = glGetUniformLocation(entry->program, "model_lights");
|
||||
for (stage = 0; stage < D3DTSS_MAXSTAGES; stage++)
|
||||
{
|
||||
@@ -3485,10 +3510,13 @@ static void apply_raster_state(BOOL has_depth)
|
||||
GLenum equation = blend_equation(rs[D3DRS_BLENDOP]);
|
||||
float blend_color[4];
|
||||
|
||||
if (gl_state.blend_source != (GLenum)rs[D3DRS_SRCBLEND] ||
|
||||
/* (a constant factor the pixel shader applies: source_blend_in_shader) */
|
||||
GLenum source = source_blend_in_shader() ? GL_ONE : (GLenum)rs[D3DRS_SRCBLEND];
|
||||
|
||||
if (gl_state.blend_source != source ||
|
||||
gl_state.blend_destination != (GLenum)rs[D3DRS_DESTBLEND])
|
||||
{
|
||||
gl_state.blend_source = (GLenum)rs[D3DRS_SRCBLEND];
|
||||
gl_state.blend_source = source;
|
||||
gl_state.blend_destination = (GLenum)rs[D3DRS_DESTBLEND];
|
||||
glBlendFunc(gl_state.blend_source, gl_state.blend_destination);
|
||||
}
|
||||
@@ -3721,6 +3749,7 @@ static struct program_entry *prepare_draw(BOOL immediate)
|
||||
key.alpha_test_samples = (unsigned char)target_samples;
|
||||
#endif
|
||||
key.fog_enable = D3D__RenderState[D3DRS_FOGENABLE] != 0;
|
||||
key.source_blend = source_blend_in_shader();
|
||||
key.fog_table_mode = (unsigned char)D3D__RenderState[D3DRS_FOGTABLEMODE];
|
||||
#ifdef HALO_GLES
|
||||
key.count_samples = device.visibility_test_active && xgpu_capabilities.atomic_counters;
|
||||
@@ -3756,6 +3785,17 @@ static struct program_entry *prepare_draw(BOOL immediate)
|
||||
stats.draws++;
|
||||
draw_flush();
|
||||
state_program(entry->program);
|
||||
if (key.source_blend && entry->blend_constant >= 0)
|
||||
{
|
||||
float blend_constant[4];
|
||||
|
||||
color_to_vec4(D3D__RenderState[D3DRS_BLENDCOLOR], blend_constant);
|
||||
if (memcmp(entry->blend_constant_value, blend_constant, sizeof(blend_constant)))
|
||||
{
|
||||
memcpy(entry->blend_constant_value, blend_constant, sizeof(blend_constant));
|
||||
glUniform4fv(entry->blend_constant, 1, blend_constant);
|
||||
}
|
||||
}
|
||||
#ifdef HALO_GLES
|
||||
if (key.count_samples)
|
||||
glBindBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, device.visibility_counters,
|
||||
|
||||
@@ -620,6 +620,8 @@ char *nv2a_pixel_shader_to_glsl(const struct nv2a_pixel_shader_key *key)
|
||||
XGPU_PIXEL_UNIFORMS);
|
||||
for (stage = 0; stage < 4; stage++)
|
||||
xgpu_text_append(&text, "uniform %s tex%d;\n", sampler_declaration(key->sampler_type[stage]), stage);
|
||||
if (key->source_blend)
|
||||
xgpu_text_append(&text, "uniform vec4 blend_constant;\n");
|
||||
if (key->per_pixel_lighting)
|
||||
model_lighting(&text, key->per_pixel_lighting == 2);
|
||||
xgpu_text_append(&text,
|
||||
@@ -745,6 +747,17 @@ char *nv2a_pixel_shader_to_glsl(const struct nv2a_pixel_shader_key *key)
|
||||
if (key->count_samples)
|
||||
xgpu_text_append(&text, "\tatomicCounterIncrement(visible_samples);\n");
|
||||
#endif
|
||||
if (key->source_blend)
|
||||
{
|
||||
static const char *const factors[] =
|
||||
{
|
||||
"blend_constant", "(1.0 - blend_constant)", "vec4(blend_constant.a)", "vec4(1.0 - blend_constant.a)"
|
||||
};
|
||||
|
||||
xgpu_text_append(&text, "\tfragment_color = clamp(result, 0.0, 1.0) * %s;\n}\n",
|
||||
factors[(key->source_blend - 1) & 3]);
|
||||
return text.buffer;
|
||||
}
|
||||
xgpu_text_append(&text, "\tfragment_color = clamp(result, 0.0, 1.0);\n}\n");
|
||||
return text.buffer;
|
||||
}
|
||||
@@ -146,6 +146,11 @@ struct nv2a_pixel_shader_key
|
||||
proportion to how far alpha is past the reference, not all of the pixel
|
||||
or none of it, so that cut-out edges (foliage, grates) are smoothed too */
|
||||
unsigned char alpha_test_samples;
|
||||
/* the source's blend factor, applied here instead (1 the blend color, 2
|
||||
one less it, 3 its alpha, 4 one less that; 0 none): WebGL refuses a
|
||||
blend of a constant color factor with a constant alpha one, as the
|
||||
meters' (shader_transparent_meter) */
|
||||
unsigned char source_blend;
|
||||
};
|
||||
|
||||
char *nv2a_pixel_shader_to_glsl(const struct nv2a_pixel_shader_key *key);
|
||||
|
||||
@@ -261,6 +261,10 @@ multiply-adds). `tools/web_build.py` writes the graph.
|
||||
each attribute (`d3d8_gl.c`).
|
||||
- No feedback loops: a draw that samples the target it draws into samples
|
||||
a copy of it.
|
||||
- No blend of a constant color factor with a constant alpha one (the
|
||||
meters, as the ammo counters on the weapons): the source's factor is
|
||||
applied by the pixel shader instead (`nv2a_pixel_shader_key`'s
|
||||
`source_blend`).
|
||||
- No `glCopyImageSubData`, `glDrawElementsBaseVertex` or
|
||||
`glMemoryBarrier`: the ES renderer's blits and rebased indices. An
|
||||
index array drawn twice the same is kept rebased in a buffer of its own
|
||||
|
||||
Reference in new issue
Block a user