mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2026-04-26 12:01:43 +00:00
Started adding support for advanced materials (2cycle)
This commit is contained in:
parent
d541d626c4
commit
8840649887
6 changed files with 244 additions and 151 deletions
|
|
@ -25,7 +25,7 @@ void gfx_cc_get_features(uint32_t shader_id, struct CCFeatures *cc_features) {
|
|||
if (cc_features->c[i][j] == SHADER_TEXEL0 || cc_features->c[i][j] == SHADER_TEXEL0A) {
|
||||
cc_features->used_textures[0] = true;
|
||||
}
|
||||
if (cc_features->c[i][j] == SHADER_TEXEL1) {
|
||||
if (cc_features->c[i][j] == SHADER_TEXEL1 || cc_features->c[i][j] == SHADER_TEXEL1A) {
|
||||
cc_features->used_textures[1] = true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,12 @@ enum {
|
|||
CC_SHADE,
|
||||
CC_ENV,
|
||||
CC_TEXEL0A,
|
||||
CC_LOD
|
||||
CC_LOD,
|
||||
CC_1,
|
||||
CC_TEXEL1A,
|
||||
CC_COMBINED,
|
||||
CC_COMBINEDA,
|
||||
CC_MAX,
|
||||
};
|
||||
|
||||
enum {
|
||||
|
|
@ -23,7 +28,11 @@ enum {
|
|||
SHADER_INPUT_4,
|
||||
SHADER_TEXEL0,
|
||||
SHADER_TEXEL0A,
|
||||
SHADER_TEXEL1
|
||||
SHADER_TEXEL1,
|
||||
SHADER_TEXEL1A,
|
||||
SHADER_1,
|
||||
SHADER_COMBINED,
|
||||
SHADER_COMBINEDA,
|
||||
};
|
||||
|
||||
#define SHADER_OPT_ALPHA (1 << 24)
|
||||
|
|
@ -45,6 +54,40 @@ struct CCFeatures {
|
|||
bool color_alpha_same;
|
||||
};
|
||||
|
||||
#pragma pack(1)
|
||||
struct CombineMode {
|
||||
union {
|
||||
struct {
|
||||
uint32_t rgb1;
|
||||
uint32_t alpha1;
|
||||
uint32_t rgb2;
|
||||
uint32_t alpha2;
|
||||
};
|
||||
uint8_t all_values[16];
|
||||
};
|
||||
union {
|
||||
struct {
|
||||
uint8_t use_alpha : 1;
|
||||
uint8_t use_fog : 1;
|
||||
uint8_t texture_edge : 1;
|
||||
uint8_t use_noise : 1;
|
||||
};
|
||||
uint32_t flags;
|
||||
};
|
||||
uint64_t hash;
|
||||
};
|
||||
#pragma pack()
|
||||
|
||||
#define SHADER_CMD_LENGTH 16
|
||||
|
||||
struct ColorCombiner {
|
||||
struct CombineMode cm;
|
||||
struct ShaderProgram *prg;
|
||||
uint8_t shader_input_mapping[16];
|
||||
uint8_t shader_commands[16];
|
||||
uint64_t hash;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ void get_cc_features(uint32_t shader_id, CCFeatures *cc_features) {
|
|||
if (cc_features->c[i][j] == SHADER_TEXEL0 || cc_features->c[i][j] == SHADER_TEXEL0A) {
|
||||
cc_features->used_textures[0] = true;
|
||||
}
|
||||
if (cc_features->c[i][j] == SHADER_TEXEL1) {
|
||||
if (cc_features->c[i][j] == SHADER_TEXEL1 || cc_features->c[i][j] == SHADER_TEXEL1A) {
|
||||
cc_features->used_textures[1] = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -61,6 +61,8 @@ static const char *shader_item_to_str(int32_t item, bool with_alpha, bool only_a
|
|||
default:
|
||||
case SHADER_0:
|
||||
return with_alpha ? "float4(0.0, 0.0, 0.0, 0.0)" : "float3(0.0, 0.0, 0.0)";
|
||||
case SHADER_1:
|
||||
return with_alpha ? "float4(1.0, 1.0, 1.0, 1.0)" : "float3(1.0, 1.0, 1.0)";
|
||||
case SHADER_INPUT_1:
|
||||
return with_alpha || !inputs_have_alpha ? "input.input1" : "input.input1.rgb";
|
||||
case SHADER_INPUT_2:
|
||||
|
|
@ -75,12 +77,16 @@ static const char *shader_item_to_str(int32_t item, bool with_alpha, bool only_a
|
|||
return hint_single_element ? "texVal0.a" : (with_alpha ? "float4(texVal0.a, texVal0.a, texVal0.a, texVal0.a)" : "float3(texVal0.a, texVal0.a, texVal0.a)");
|
||||
case SHADER_TEXEL1:
|
||||
return with_alpha ? "texVal1" : "texVal1.rgb";
|
||||
case SHADER_TEXEL1A:
|
||||
return hint_single_element ? "texVal1.a" : (with_alpha ? "float4(texVal1.a, texVal1.a, texVal1.a, texVal1.a)" : "float3(texVal1.a, texVal1.a, texVal1.a)");
|
||||
}
|
||||
} else {
|
||||
switch (item) {
|
||||
default:
|
||||
case SHADER_0:
|
||||
return "0.0";
|
||||
case SHADER_1:
|
||||
return "1.0";
|
||||
case SHADER_INPUT_1:
|
||||
return "input.input1.a";
|
||||
case SHADER_INPUT_2:
|
||||
|
|
@ -95,6 +101,8 @@ static const char *shader_item_to_str(int32_t item, bool with_alpha, bool only_a
|
|||
return "texVal0.a";
|
||||
case SHADER_TEXEL1:
|
||||
return "texVal1.a";
|
||||
case SHADER_TEXEL1A:
|
||||
return "texVal1.a";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@
|
|||
#define TEX_CACHE_STEP 512
|
||||
|
||||
struct ShaderProgram {
|
||||
uint32_t shader_id;
|
||||
uint64_t hash;
|
||||
GLuint opengl_program_id;
|
||||
uint8_t num_inputs;
|
||||
bool used_textures[2];
|
||||
|
|
@ -136,6 +136,8 @@ static const char *shader_item_to_str(uint32_t item, bool with_alpha, bool only_
|
|||
switch (item) {
|
||||
case SHADER_0:
|
||||
return with_alpha ? "vec4(0.0, 0.0, 0.0, 0.0)" : "vec3(0.0, 0.0, 0.0)";
|
||||
case SHADER_1:
|
||||
return with_alpha ? "vec4(1.0, 1.0, 1.0, 1.0)" : "vec3(1.0, 1.0, 1.0)";
|
||||
case SHADER_INPUT_1:
|
||||
return with_alpha || !inputs_have_alpha ? "vInput1" : "vInput1.rgb";
|
||||
case SHADER_INPUT_2:
|
||||
|
|
@ -151,11 +153,16 @@ static const char *shader_item_to_str(uint32_t item, bool with_alpha, bool only_
|
|||
(with_alpha ? "vec4(texelVal0.a, texelVal0.a, texelVal0.a, texelVal0.a)" : "vec3(texelVal0.a, texelVal0.a, texelVal0.a)");
|
||||
case SHADER_TEXEL1:
|
||||
return with_alpha ? "texVal1" : "texVal1.rgb";
|
||||
case SHADER_TEXEL1A:
|
||||
return hint_single_element ? "texVal1.a" :
|
||||
(with_alpha ? "vec4(texelVal1.a, texelVal1.a, texelVal1.a, texelVal1.a)" : "vec3(texelVal1.a, texelVal1.a, texelVal1.a)");
|
||||
}
|
||||
} else {
|
||||
switch (item) {
|
||||
case SHADER_0:
|
||||
return "0.0";
|
||||
case SHADER_1:
|
||||
return "1.0";
|
||||
case SHADER_INPUT_1:
|
||||
return "vInput1.a";
|
||||
case SHADER_INPUT_2:
|
||||
|
|
@ -170,74 +177,66 @@ static const char *shader_item_to_str(uint32_t item, bool with_alpha, bool only_
|
|||
return "texVal0.a";
|
||||
case SHADER_TEXEL1:
|
||||
return "texVal1.a";
|
||||
case SHADER_TEXEL1A:
|
||||
return "texVal1.a";
|
||||
}
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
static void append_formula(char *buf, size_t *len, uint8_t c[2][4], bool do_single, bool do_multiply, bool do_mix, bool with_alpha, bool only_alpha, bool opt_alpha) {
|
||||
static void append_formula(char *buf, size_t *len, uint8_t* cmd, bool do_single, bool do_multiply, bool do_mix, bool with_alpha, bool only_alpha, bool opt_alpha) {
|
||||
if (do_single) {
|
||||
append_str(buf, len, shader_item_to_str(c[only_alpha][3], with_alpha, only_alpha, opt_alpha, false));
|
||||
append_str(buf, len, shader_item_to_str(cmd[only_alpha * 4 + 3], with_alpha, only_alpha, opt_alpha, false));
|
||||
} else if (do_multiply) {
|
||||
append_str(buf, len, shader_item_to_str(c[only_alpha][0], with_alpha, only_alpha, opt_alpha, false));
|
||||
append_str(buf, len, shader_item_to_str(cmd[only_alpha * 4 + 0], with_alpha, only_alpha, opt_alpha, false));
|
||||
append_str(buf, len, " * ");
|
||||
append_str(buf, len, shader_item_to_str(c[only_alpha][2], with_alpha, only_alpha, opt_alpha, true));
|
||||
append_str(buf, len, shader_item_to_str(cmd[only_alpha * 4 + 2], with_alpha, only_alpha, opt_alpha, true));
|
||||
} else if (do_mix) {
|
||||
append_str(buf, len, "mix(");
|
||||
append_str(buf, len, shader_item_to_str(c[only_alpha][1], with_alpha, only_alpha, opt_alpha, false));
|
||||
append_str(buf, len, shader_item_to_str(cmd[only_alpha * 4 + 1], with_alpha, only_alpha, opt_alpha, false));
|
||||
append_str(buf, len, ", ");
|
||||
append_str(buf, len, shader_item_to_str(c[only_alpha][0], with_alpha, only_alpha, opt_alpha, false));
|
||||
append_str(buf, len, shader_item_to_str(cmd[only_alpha * 4 + 0], with_alpha, only_alpha, opt_alpha, false));
|
||||
append_str(buf, len, ", ");
|
||||
append_str(buf, len, shader_item_to_str(c[only_alpha][2], with_alpha, only_alpha, opt_alpha, true));
|
||||
append_str(buf, len, shader_item_to_str(cmd[only_alpha * 4 + 2], with_alpha, only_alpha, opt_alpha, true));
|
||||
append_str(buf, len, ")");
|
||||
} else {
|
||||
append_str(buf, len, "(");
|
||||
append_str(buf, len, shader_item_to_str(c[only_alpha][0], with_alpha, only_alpha, opt_alpha, false));
|
||||
append_str(buf, len, shader_item_to_str(cmd[only_alpha * 4 + 0], with_alpha, only_alpha, opt_alpha, false));
|
||||
append_str(buf, len, " - ");
|
||||
append_str(buf, len, shader_item_to_str(c[only_alpha][1], with_alpha, only_alpha, opt_alpha, false));
|
||||
append_str(buf, len, shader_item_to_str(cmd[only_alpha * 4 + 1], with_alpha, only_alpha, opt_alpha, false));
|
||||
append_str(buf, len, ") * ");
|
||||
append_str(buf, len, shader_item_to_str(c[only_alpha][2], with_alpha, only_alpha, opt_alpha, true));
|
||||
append_str(buf, len, shader_item_to_str(cmd[only_alpha * 4 + 2], with_alpha, only_alpha, opt_alpha, true));
|
||||
append_str(buf, len, " + ");
|
||||
append_str(buf, len, shader_item_to_str(c[only_alpha][3], with_alpha, only_alpha, opt_alpha, false));
|
||||
append_str(buf, len, shader_item_to_str(cmd[only_alpha * 4 + 3], with_alpha, only_alpha, opt_alpha, false));
|
||||
}
|
||||
}
|
||||
|
||||
static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(uint32_t shader_id) {
|
||||
uint8_t c[2][4];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
c[0][i] = (shader_id >> (i * 3)) & 7;
|
||||
c[1][i] = (shader_id >> (12 + i * 3)) & 7;
|
||||
}
|
||||
bool opt_alpha = (shader_id & SHADER_OPT_ALPHA) != 0;
|
||||
bool opt_fog = (shader_id & SHADER_OPT_FOG) != 0;
|
||||
bool opt_texture_edge = (shader_id & SHADER_OPT_TEXTURE_EDGE) != 0;
|
||||
static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorCombiner* cc) {
|
||||
bool opt_alpha = cc->cm.use_alpha;
|
||||
bool opt_fog = cc->cm.use_fog;
|
||||
bool opt_texture_edge = cc->cm.texture_edge;
|
||||
#ifdef USE_GLES
|
||||
bool opt_noise = false;
|
||||
#else
|
||||
bool opt_noise = (shader_id & SHADER_OPT_NOISE) != 0;
|
||||
bool opt_noise = cc->cm.use_noise;
|
||||
#endif
|
||||
|
||||
bool used_textures[2] = { 0, 0 };
|
||||
u8* cmd = cc->shader_commands;
|
||||
bool used_textures[2] = { 0 };
|
||||
int num_inputs = 0;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
if (c[i][j] >= SHADER_INPUT_1 && c[i][j] <= SHADER_INPUT_4) {
|
||||
if (c[i][j] > num_inputs) {
|
||||
num_inputs = c[i][j];
|
||||
}
|
||||
}
|
||||
if (c[i][j] == SHADER_TEXEL0 || c[i][j] == SHADER_TEXEL0A) {
|
||||
used_textures[0] = true;
|
||||
}
|
||||
if (c[i][j] == SHADER_TEXEL1) {
|
||||
used_textures[1] = true;
|
||||
}
|
||||
for (int i = 0; i < SHADER_CMD_LENGTH; i++) {
|
||||
u8 c = cmd[i];
|
||||
if (c >= SHADER_INPUT_1 && c <= SHADER_INPUT_4) {
|
||||
if (c > num_inputs) { num_inputs = c; }
|
||||
}
|
||||
used_textures[0] = used_textures[0] || c == SHADER_TEXEL0 || c == SHADER_TEXEL0A;
|
||||
used_textures[1] = used_textures[1] || c == SHADER_TEXEL1 || c == SHADER_TEXEL1A;
|
||||
}
|
||||
bool do_single[2] = { c[0][2] == 0, c[1][2] == 0 };
|
||||
bool do_multiply[2] = { c[0][1] == 0 && c[0][3] == 0, c[1][1] == 0 && c[1][3] == 0 };
|
||||
bool do_mix[2] = { c[0][1] == c[0][3], c[1][1] == c[1][3] };
|
||||
bool color_alpha_same = (shader_id & 0xfff) == ((shader_id >> 12) & 0xfff);
|
||||
|
||||
bool do_single[2] = { cmd[0 * 4 + 2] == 0, cmd[1 * 4 + 2] == 0 };
|
||||
bool do_multiply[2] = { cmd[0 * 4 + 1] == 0 && cmd[0 * 4 + 3] == 0, cmd[1 * 4 + 1] == 0 && cmd[1 * 4 + 3] == 0 };
|
||||
bool do_mix[2] = { cmd[0 * 4 + 1] == cmd[0 * 4 + 3], cmd[1 * 4 + 1] == cmd[1 * 4 + 3] };
|
||||
bool color_alpha_same = false; // TODO: gotta check shader comamndssadasda
|
||||
|
||||
char vs_buf[1024];
|
||||
char fs_buf[2048];
|
||||
|
|
@ -357,12 +356,12 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(uint32_t shad
|
|||
append_str(fs_buf, &fs_len, opt_alpha ? "vec4 texel = " : "vec3 texel = ");
|
||||
if (!color_alpha_same && opt_alpha) {
|
||||
append_str(fs_buf, &fs_len, "vec4(");
|
||||
append_formula(fs_buf, &fs_len, c, do_single[0], do_multiply[0], do_mix[0], false, false, true);
|
||||
append_formula(fs_buf, &fs_len, cmd, do_single[0], do_multiply[0], do_mix[0], false, false, true);
|
||||
append_str(fs_buf, &fs_len, ", ");
|
||||
append_formula(fs_buf, &fs_len, c, do_single[1], do_multiply[1], do_mix[1], true, true, true);
|
||||
append_formula(fs_buf, &fs_len, cmd, do_single[1], do_multiply[1], do_mix[1], true, true, true);
|
||||
append_str(fs_buf, &fs_len, ")");
|
||||
} else {
|
||||
append_formula(fs_buf, &fs_len, c, do_single[0], do_multiply[0], do_mix[0], opt_alpha, false, opt_alpha);
|
||||
append_formula(fs_buf, &fs_len, cmd, do_single[0], do_multiply[0], do_mix[0], opt_alpha, false, opt_alpha);
|
||||
}
|
||||
append_line(fs_buf, &fs_len, ";");
|
||||
|
||||
|
|
@ -391,11 +390,11 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(uint32_t shad
|
|||
vs_buf[vs_len] = '\0';
|
||||
fs_buf[fs_len] = '\0';
|
||||
|
||||
/*puts("Vertex shader:");
|
||||
puts("Vertex shader:");
|
||||
puts(vs_buf);
|
||||
puts("Fragment shader:");
|
||||
puts(fs_buf);
|
||||
puts("End");*/
|
||||
puts("End");
|
||||
|
||||
const GLchar *sources[2] = { vs_buf, fs_buf };
|
||||
const GLint lengths[2] = { vs_len, fs_len };
|
||||
|
|
@ -461,7 +460,7 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(uint32_t shad
|
|||
++cnt;
|
||||
}
|
||||
|
||||
prg->shader_id = shader_id;
|
||||
prg->hash = cc->hash;
|
||||
prg->opengl_program_id = shader_program;
|
||||
prg->num_inputs = num_inputs;
|
||||
prg->used_textures[0] = used_textures[0];
|
||||
|
|
@ -494,9 +493,9 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(uint32_t shad
|
|||
return prg;
|
||||
}
|
||||
|
||||
static struct ShaderProgram *gfx_opengl_lookup_shader(uint32_t shader_id) {
|
||||
static struct ShaderProgram *gfx_opengl_lookup_shader(struct ColorCombiner* cc) {
|
||||
for (size_t i = 0; i < shader_program_pool_size; i++) {
|
||||
if (shader_program_pool[i].shader_id == shader_id) {
|
||||
if (shader_program_pool[i].hash == cc->hash) {
|
||||
return &shader_program_pool[i];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,13 +94,7 @@ static struct {
|
|||
uint32_t pool_pos;
|
||||
} gfx_texture_cache;
|
||||
|
||||
struct ColorCombiner {
|
||||
uint32_t cc_id;
|
||||
struct ShaderProgram *prg;
|
||||
uint8_t shader_input_mapping[2][4];
|
||||
};
|
||||
|
||||
static struct ColorCombiner color_combiner_pool[64];
|
||||
static struct ColorCombiner color_combiner_pool[64] = { 0 };
|
||||
static uint8_t color_combiner_pool_size;
|
||||
|
||||
static struct RSP {
|
||||
|
|
@ -148,7 +142,7 @@ static struct RDP {
|
|||
bool textures_changed[2];
|
||||
|
||||
uint32_t other_mode_l, other_mode_h;
|
||||
uint32_t combine_mode;
|
||||
struct CombineMode combine_mode;
|
||||
|
||||
struct RGBA env_color, prim_color, fog_color, fill_color;
|
||||
struct XYWidthHeight viewport, scissor;
|
||||
|
|
@ -234,77 +228,110 @@ static void gfx_flush(void) {
|
|||
}
|
||||
}
|
||||
|
||||
static struct ShaderProgram *gfx_lookup_or_create_shader_program(uint32_t shader_id) {
|
||||
struct ShaderProgram *prg = gfx_rapi->lookup_shader(shader_id);
|
||||
static void combine_mode_update_hash(struct CombineMode* mode) {
|
||||
uint64_t hash = 5381;
|
||||
|
||||
hash = (hash << 5) + hash + mode->rgb1;
|
||||
hash = (hash << 5) + hash + mode->alpha1;
|
||||
hash = (hash << 5) + hash + mode->rgb2;
|
||||
hash = (hash << 5) + hash + mode->alpha2;
|
||||
hash = (hash << 5) + hash + mode->flags;
|
||||
|
||||
mode->hash = hash;
|
||||
}
|
||||
|
||||
static void color_combiner_update_hash(struct ColorCombiner* cc) {
|
||||
uint64_t hash = cc->cm.hash;
|
||||
|
||||
for (int i = 0; i < SHADER_CMD_LENGTH; i++) {
|
||||
hash = (hash << 5) + hash + cc->shader_commands[i];
|
||||
}
|
||||
|
||||
cc->hash = hash;
|
||||
}
|
||||
|
||||
static struct ShaderProgram *gfx_lookup_or_create_shader_program(struct ColorCombiner* cc) {
|
||||
struct ShaderProgram *prg = gfx_rapi->lookup_shader(cc);
|
||||
if (prg == NULL) {
|
||||
gfx_rapi->unload_shader(rendering_state.shader_program);
|
||||
prg = gfx_rapi->create_and_load_new_shader(shader_id);
|
||||
prg = gfx_rapi->create_and_load_new_shader(cc);
|
||||
rendering_state.shader_program = prg;
|
||||
}
|
||||
return prg;
|
||||
}
|
||||
|
||||
static void gfx_generate_cc(struct ColorCombiner *comb, uint32_t cc_id) {
|
||||
uint8_t c[2][4];
|
||||
uint32_t shader_id = (cc_id >> 24) << 24;
|
||||
uint8_t shader_input_mapping[2][4] = {{0}};
|
||||
for (int32_t i = 0; i < 4; i++) {
|
||||
c[0][i] = (cc_id >> (i * 3)) & 7;
|
||||
c[1][i] = (cc_id >> (12 + i * 3)) & 7;
|
||||
}
|
||||
for (int32_t i = 0; i < 2; i++) {
|
||||
if (c[i][0] == c[i][1] || c[i][2] == CC_0) {
|
||||
c[i][0] = c[i][1] = c[i][2] = 0;
|
||||
}
|
||||
uint8_t input_number[8] = {0};
|
||||
int next_input_number = SHADER_INPUT_1;
|
||||
for (int j = 0; j < 4; j++) {
|
||||
int val = 0;
|
||||
switch (c[i][j]) {
|
||||
case CC_0:
|
||||
break;
|
||||
case CC_TEXEL0:
|
||||
val = SHADER_TEXEL0;
|
||||
break;
|
||||
case CC_TEXEL1:
|
||||
val = SHADER_TEXEL1;
|
||||
break;
|
||||
case CC_TEXEL0A:
|
||||
val = SHADER_TEXEL0A;
|
||||
break;
|
||||
case CC_PRIM:
|
||||
case CC_SHADE:
|
||||
case CC_ENV:
|
||||
case CC_LOD:
|
||||
if (input_number[c[i][j]] == 0) {
|
||||
shader_input_mapping[i][next_input_number - 1] = c[i][j];
|
||||
input_number[c[i][j]] = next_input_number++;
|
||||
}
|
||||
val = input_number[c[i][j]];
|
||||
break;
|
||||
}
|
||||
shader_id |= val << (i * 12 + j * 3);
|
||||
static void gfx_generate_cc(struct ColorCombiner *cc) {
|
||||
u8 next_input_number = 0;
|
||||
u8 input_number[CC_MAX] = { 0 };
|
||||
|
||||
for (int i = 0; i < SHADER_CMD_LENGTH; i++) {
|
||||
u8 cm_cmd = cc->cm.all_values[i];
|
||||
u8 shader_cmd = 0;
|
||||
switch (cm_cmd) {
|
||||
case CC_0:
|
||||
shader_cmd = SHADER_0;
|
||||
break;
|
||||
case CC_1:
|
||||
shader_cmd = SHADER_1;
|
||||
break;
|
||||
case CC_TEXEL0:
|
||||
shader_cmd = SHADER_TEXEL0;
|
||||
break;
|
||||
case CC_TEXEL1:
|
||||
shader_cmd = SHADER_TEXEL1;
|
||||
break;
|
||||
case CC_TEXEL0A:
|
||||
shader_cmd = SHADER_TEXEL0A;
|
||||
break;
|
||||
case CC_TEXEL1A:
|
||||
shader_cmd = SHADER_TEXEL1A;
|
||||
break;
|
||||
case CC_COMBINED:
|
||||
shader_cmd = SHADER_COMBINED;
|
||||
break;
|
||||
case CC_COMBINEDA:
|
||||
shader_cmd = SHADER_COMBINEDA;
|
||||
break;
|
||||
case CC_PRIM:
|
||||
case CC_SHADE:
|
||||
case CC_ENV:
|
||||
case CC_LOD:
|
||||
if (input_number[cm_cmd] == 0) {
|
||||
cc->shader_input_mapping[next_input_number] = cm_cmd;
|
||||
input_number[cm_cmd] = SHADER_INPUT_1 + next_input_number;
|
||||
next_input_number++;
|
||||
}
|
||||
shader_cmd = input_number[cm_cmd];
|
||||
break;
|
||||
default:
|
||||
shader_cmd = SHADER_0;
|
||||
break;
|
||||
}
|
||||
cc->shader_commands[i] = shader_cmd;
|
||||
}
|
||||
comb->cc_id = cc_id;
|
||||
comb->prg = gfx_lookup_or_create_shader_program(shader_id);
|
||||
memcpy(comb->shader_input_mapping, shader_input_mapping, sizeof(shader_input_mapping));
|
||||
|
||||
color_combiner_update_hash(cc);
|
||||
cc->prg = gfx_lookup_or_create_shader_program(cc);
|
||||
}
|
||||
|
||||
static struct ColorCombiner *gfx_lookup_or_create_color_combiner(uint32_t cc_id) {
|
||||
static struct ColorCombiner *gfx_lookup_or_create_color_combiner(struct CombineMode* cm) {
|
||||
combine_mode_update_hash(cm);
|
||||
|
||||
static struct ColorCombiner *prev_combiner;
|
||||
if (prev_combiner != NULL && prev_combiner->cc_id == cc_id) {
|
||||
if (prev_combiner != NULL && prev_combiner->cm.hash == cm->hash) {
|
||||
return prev_combiner;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < color_combiner_pool_size; i++) {
|
||||
if (color_combiner_pool[i].cc_id == cc_id) {
|
||||
if (color_combiner_pool[i].cm.hash == cm->hash) {
|
||||
return prev_combiner = &color_combiner_pool[i];
|
||||
}
|
||||
}
|
||||
gfx_flush();
|
||||
|
||||
struct ColorCombiner *comb = &color_combiner_pool[color_combiner_pool_size++];
|
||||
gfx_generate_cc(comb, cc_id);
|
||||
comb->cm = *cm;
|
||||
gfx_generate_cc(comb);
|
||||
return prev_combiner = comb;
|
||||
}
|
||||
|
||||
|
|
@ -979,27 +1006,20 @@ static void OPTIMIZE_O3 gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t
|
|||
rdp.viewport_or_scissor_changed = false;
|
||||
}
|
||||
|
||||
uint32_t cc_id = rdp.combine_mode;
|
||||
struct CombineMode* cm = &rdp.combine_mode;
|
||||
|
||||
bool use_alpha = (rdp.other_mode_l & (G_BL_A_MEM << 18)) == 0;
|
||||
bool use_fog = (rdp.other_mode_l >> 30) == G_BL_CLR_FOG;
|
||||
bool texture_edge = (rdp.other_mode_l & CVG_X_ALPHA) == CVG_X_ALPHA;
|
||||
bool use_noise = (rdp.other_mode_l & G_AC_DITHER) == G_AC_DITHER;
|
||||
cm->use_alpha = (rdp.other_mode_l & (G_BL_A_MEM << 18)) == 0;
|
||||
cm->texture_edge = (rdp.other_mode_l & CVG_X_ALPHA) == CVG_X_ALPHA;
|
||||
cm->use_noise = (rdp.other_mode_l & G_AC_DITHER) == G_AC_DITHER;
|
||||
cm->use_fog = (rdp.other_mode_l >> 30) == G_BL_CLR_FOG;
|
||||
|
||||
if (texture_edge) {
|
||||
use_alpha = true;
|
||||
if (cm->texture_edge) {
|
||||
cm->use_alpha = true;
|
||||
}
|
||||
|
||||
if (use_alpha) cc_id |= SHADER_OPT_ALPHA;
|
||||
if (use_fog) cc_id |= SHADER_OPT_FOG;
|
||||
if (texture_edge) cc_id |= SHADER_OPT_TEXTURE_EDGE;
|
||||
if (use_noise) cc_id |= SHADER_OPT_NOISE;
|
||||
struct ColorCombiner *comb = gfx_lookup_or_create_color_combiner(cm);
|
||||
cm = &comb->cm;
|
||||
|
||||
if (!use_alpha) {
|
||||
cc_id &= ~0xfff000;
|
||||
}
|
||||
|
||||
struct ColorCombiner *comb = gfx_lookup_or_create_color_combiner(cc_id);
|
||||
struct ShaderProgram *prg = comb->prg;
|
||||
if (prg != rendering_state.shader_program) {
|
||||
gfx_flush();
|
||||
|
|
@ -1007,10 +1027,10 @@ static void OPTIMIZE_O3 gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t
|
|||
gfx_rapi->load_shader(prg);
|
||||
rendering_state.shader_program = prg;
|
||||
}
|
||||
if (use_alpha != rendering_state.alpha_blend) {
|
||||
if (cm->use_alpha != rendering_state.alpha_blend) {
|
||||
gfx_flush();
|
||||
gfx_rapi->set_use_alpha(use_alpha);
|
||||
rendering_state.alpha_blend = use_alpha;
|
||||
gfx_rapi->set_use_alpha(cm->use_alpha);
|
||||
rendering_state.alpha_blend = cm->use_alpha;
|
||||
}
|
||||
uint8_t num_inputs;
|
||||
bool used_textures[2];
|
||||
|
|
@ -1065,7 +1085,7 @@ static void OPTIMIZE_O3 gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t
|
|||
buf_vbo[buf_vbo_len++] = v / tex_height;
|
||||
}
|
||||
|
||||
if (use_fog) {
|
||||
if (cm->use_fog) {
|
||||
buf_vbo[buf_vbo_len++] = rdp.fog_color.r / 255.0f;
|
||||
buf_vbo[buf_vbo_len++] = rdp.fog_color.g / 255.0f;
|
||||
buf_vbo[buf_vbo_len++] = rdp.fog_color.b / 255.0f;
|
||||
|
|
@ -1073,10 +1093,11 @@ static void OPTIMIZE_O3 gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t
|
|||
}
|
||||
|
||||
for (int j = 0; j < num_inputs; j++) {
|
||||
struct RGBA *color;
|
||||
struct RGBA tmp;
|
||||
for (int k = 0; k < 1 + (use_alpha ? 1 : 0); k++) {
|
||||
switch (comb->shader_input_mapping[k][j]) {
|
||||
struct RGBA *color = NULL;
|
||||
struct RGBA tmp = { 0 };
|
||||
for (int a = 0; a < (cm->use_alpha ? 2 : 1 ); a++) {
|
||||
u8 mapping = comb->shader_input_mapping[j];
|
||||
switch (mapping) {
|
||||
case CC_PRIM:
|
||||
color = &rdp.prim_color;
|
||||
break;
|
||||
|
|
@ -1100,12 +1121,12 @@ static void OPTIMIZE_O3 gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t
|
|||
color = &tmp;
|
||||
break;
|
||||
}
|
||||
if (k == 0) {
|
||||
if (a == 0) {
|
||||
buf_vbo[buf_vbo_len++] = color->r / 255.0f;
|
||||
buf_vbo[buf_vbo_len++] = color->g / 255.0f;
|
||||
buf_vbo[buf_vbo_len++] = color->b / 255.0f;
|
||||
} else {
|
||||
if (use_fog && color == &v_arr[i]->color) {
|
||||
if (cm->use_fog && color == &v_arr[i]->color) {
|
||||
// Shade alpha is 100% for fog
|
||||
buf_vbo[buf_vbo_len++] = 1.0f;
|
||||
} else {
|
||||
|
|
@ -1360,22 +1381,34 @@ static uint8_t color_comb_component(uint32_t v) {
|
|||
return CC_ENV;
|
||||
case G_CCMUX_TEXEL0_ALPHA:
|
||||
return CC_TEXEL0A;
|
||||
/*case G_CCMUX_TEXEL1_ALPHA:
|
||||
return CC_TEXEL1A;*/
|
||||
case G_CCMUX_LOD_FRACTION:
|
||||
return CC_LOD;
|
||||
/*case G_CCMUX_1:
|
||||
return CC_1;
|
||||
case G_CCMUX_COMBINED:
|
||||
return CC_0; // return CC_COMBINED; TODO
|
||||
case G_CCMUX_COMBINED_ALPHA:
|
||||
return CC_0; //return CC_COMBINEDA; TODO*/
|
||||
default:
|
||||
return CC_0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint32_t color_comb(uint32_t a, uint32_t b, uint32_t c, uint32_t d) {
|
||||
return color_comb_component(a) |
|
||||
(color_comb_component(b) << 3) |
|
||||
(color_comb_component(c) << 6) |
|
||||
(color_comb_component(d) << 9);
|
||||
return color_comb_component(a)
|
||||
| (color_comb_component(b) << 8)
|
||||
| (color_comb_component(c) << 16)
|
||||
| (color_comb_component(d) << 24);
|
||||
}
|
||||
|
||||
static void gfx_dp_set_combine_mode(uint32_t rgb, uint32_t alpha) {
|
||||
rdp.combine_mode = rgb | (alpha << 12);
|
||||
static void gfx_dp_set_combine_mode(uint32_t rgb1, uint32_t alpha1, uint32_t rgb2, uint32_t alpha2) {
|
||||
rdp.combine_mode.rgb1 = rgb1;
|
||||
rdp.combine_mode.alpha1 = alpha1;
|
||||
|
||||
rdp.combine_mode.rgb2 = rgb2;
|
||||
rdp.combine_mode.alpha2 = alpha2;
|
||||
}
|
||||
|
||||
static void gfx_dp_set_env_color(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
|
||||
|
|
@ -1480,14 +1513,14 @@ static void gfx_draw_rectangle(int32_t ulx, int32_t uly, int32_t lrx, int32_t lr
|
|||
}
|
||||
|
||||
static void gfx_dp_texture_rectangle(int32_t ulx, int32_t uly, int32_t lrx, int32_t lry, UNUSED uint8_t tile, int16_t uls, int16_t ult, int16_t dsdx, int16_t dtdy, bool flip) {
|
||||
uint32_t saved_combine_mode = rdp.combine_mode;
|
||||
struct CombineMode saved_combine_mode = rdp.combine_mode;
|
||||
if ((rdp.other_mode_h & (3U << G_MDSFT_CYCLETYPE)) == G_CYC_COPY) {
|
||||
// Per RDP Command Summary Set Tile's shift s and this dsdx should be set to 4 texels
|
||||
// Divide by 4 to get 1 instead
|
||||
dsdx >>= 2;
|
||||
|
||||
// Color combiner is turned off in copy mode
|
||||
gfx_dp_set_combine_mode(color_comb(0, 0, 0, G_CCMUX_TEXEL0), color_comb(0, 0, 0, G_ACMUX_TEXEL0));
|
||||
gfx_dp_set_combine_mode(color_comb(0, 0, 0, G_CCMUX_TEXEL0), color_comb(0, 0, 0, G_ACMUX_TEXEL0), color_comb(0, 0, 0, G_CCMUX_TEXEL0), color_comb(0, 0, 0, G_ACMUX_TEXEL0));
|
||||
|
||||
// Per documentation one extra pixel is added in this modes to each edge
|
||||
lrx += 1 << 2;
|
||||
|
|
@ -1528,7 +1561,10 @@ static void gfx_dp_texture_rectangle(int32_t ulx, int32_t uly, int32_t lrx, int3
|
|||
}
|
||||
|
||||
gfx_draw_rectangle(ulx, uly, lrx, lry);
|
||||
|
||||
u32 cflags = rdp.combine_mode.flags;
|
||||
rdp.combine_mode = saved_combine_mode;
|
||||
rdp.combine_mode.flags = cflags;
|
||||
}
|
||||
|
||||
static void gfx_dp_fill_rectangle(int32_t ulx, int32_t uly, int32_t lrx, int32_t lry) {
|
||||
|
|
@ -1549,10 +1585,13 @@ static void gfx_dp_fill_rectangle(int32_t ulx, int32_t uly, int32_t lrx, int32_t
|
|||
v->color = rdp.fill_color;
|
||||
}
|
||||
|
||||
uint32_t saved_combine_mode = rdp.combine_mode;
|
||||
gfx_dp_set_combine_mode(color_comb(0, 0, 0, G_CCMUX_SHADE), color_comb(0, 0, 0, G_ACMUX_SHADE));
|
||||
struct CombineMode saved_combine_mode = rdp.combine_mode;
|
||||
gfx_dp_set_combine_mode(color_comb(0, 0, 0, G_CCMUX_SHADE), color_comb(0, 0, 0, G_ACMUX_SHADE), color_comb(0, 0, 0, G_CCMUX_SHADE), color_comb(0, 0, 0, G_ACMUX_SHADE));
|
||||
gfx_draw_rectangle(ulx, uly, lrx, lry);
|
||||
|
||||
u32 cflags = rdp.combine_mode.flags;
|
||||
rdp.combine_mode = saved_combine_mode;
|
||||
rdp.combine_mode.flags = cflags;
|
||||
}
|
||||
|
||||
static void gfx_dp_set_z_image(void *z_buf_address) {
|
||||
|
|
@ -1720,9 +1759,9 @@ static void OPTIMIZE_O3 gfx_run_dl(Gfx* cmd) {
|
|||
case G_SETCOMBINE:
|
||||
gfx_dp_set_combine_mode(
|
||||
color_comb(C0(20, 4), C1(28, 4), C0(15, 5), C1(15, 3)),
|
||||
color_comb(C0(12, 3), C1(12, 3), C0(9, 3), C1(9, 3)));
|
||||
/*color_comb(C0(5, 4), C1(24, 4), C0(0, 5), C1(6, 3)),
|
||||
color_comb(C1(21, 3), C1(3, 3), C1(18, 3), C1(0, 3)));*/
|
||||
color_comb(C0(12, 3), C1(12, 3), C0(9, 3), C1(9, 3)),
|
||||
color_comb(C0(5, 4), C1(24, 4), C0(0, 5), C1(6, 3)),
|
||||
color_comb(C1(21, 3), C1(3, 3), C1(18, 3), C1(0, 3)));
|
||||
break;
|
||||
// G_SETPRIMCOLOR, G_CCMUX_PRIMITIVE, G_ACMUX_PRIMITIVE, is used by Goddard
|
||||
// G_CCMUX_TEXEL1, LOD_FRACTION is used in Bowser room 1
|
||||
|
|
@ -1808,6 +1847,8 @@ void gfx_init(struct GfxWindowManagerAPI *wapi, struct GfxRenderingAPI *rapi, co
|
|||
gfx_wapi->init(window_title);
|
||||
gfx_rapi->init();
|
||||
|
||||
// DO NOT COMMIT: must update these!
|
||||
/*
|
||||
// Used in the 120 star TAS
|
||||
static uint32_t precomp_shaders[] = {
|
||||
0x01200200,
|
||||
|
|
@ -1840,6 +1881,7 @@ void gfx_init(struct GfxWindowManagerAPI *wapi, struct GfxRenderingAPI *rapi, co
|
|||
|
||||
for (size_t i = 0; i < sizeof(precomp_shaders) / sizeof(uint32_t); i++)
|
||||
gfx_lookup_or_create_shader_program(precomp_shaders[i]);
|
||||
*/
|
||||
}
|
||||
|
||||
#ifdef EXTERNAL_DATA
|
||||
|
|
|
|||
|
|
@ -6,13 +6,14 @@
|
|||
#include <stdbool.h>
|
||||
|
||||
struct ShaderProgram;
|
||||
struct ColorCombiner;
|
||||
|
||||
struct GfxRenderingAPI {
|
||||
bool (*z_is_from_0_to_1)(void);
|
||||
void (*unload_shader)(struct ShaderProgram *old_prg);
|
||||
void (*load_shader)(struct ShaderProgram *new_prg);
|
||||
struct ShaderProgram *(*create_and_load_new_shader)(uint32_t shader_id);
|
||||
struct ShaderProgram *(*lookup_shader)(uint32_t shader_id);
|
||||
struct ShaderProgram *(*create_and_load_new_shader)(struct ColorCombiner* cc);
|
||||
struct ShaderProgram *(*lookup_shader)(struct ColorCombiner* cc);
|
||||
void (*shader_get_info)(struct ShaderProgram *prg, uint8_t *num_inputs, bool used_textures[2]);
|
||||
uint32_t (*new_texture)(void);
|
||||
void (*select_texture)(int tile, uint32_t texture_id);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue