Get GL_LEGACY working again (poorly)

This commit is contained in:
MysterD 2023-05-03 13:13:33 -07:00
parent 0bb7adfd2d
commit ab2cbb2dbc
6 changed files with 285 additions and 332 deletions

View file

@ -534,17 +534,17 @@ struct PcDebug gPcDebug = {
.tags = {
0x0000000000000000,
0x000000000000FFFF,
0x440C28A5CC404F11,
0x2783114DDB90E597,
0x0EF4AF18EEC1303A,
0x5E6A9446709E7CFF,
0x914FA1C52D410003,
0xE9A402C28144FD8B,
0x83B8B87B1E6A0B78,
0xEE7B0ED661ABA0ED,
0x2D1D50FB02617949,
0x8AEB7180FAE739EB,
0x0CDB1A233CC71057,
0x53D5D9880C8B278E,
0xE8E307BE5802542E,
0x8A3ACC4FDB4FFE45,
0x09046C2BA3C5000D,
0xF027964ADE989C29,
0x076CF19655C70007,
0x9325E55A037D6511,
0x77ACD7B422D978A6,
0x440C28A5CC404F11,
0xE9A402C28144FD8B,
0x9A2269E87B26BE68,
},
.id = DEFAULT_ID,

View file

@ -4,45 +4,43 @@
#include "gfx_pc.h"
static u8 sAllowCCPrint = 1;
void gfx_cc_get_features(uint32_t shader_id, struct CCFeatures *cc_features) {
// DO NOT COMMIT: TODO - need to fix this
for (int32_t i = 0; i < 4; i++) {
cc_features->c[0][i] = (shader_id >> (i * 3)) & 7;
cc_features->c[1][i] = (shader_id >> (12 + i * 3)) & 7;
void gfx_cc_get_features(struct ColorCombiner* cc, struct CCFeatures* ccf) {
// DO NOT COMMIT: TODO - need to convert dx and regular gl
// reset ccf
memset(ccf, 0, sizeof(struct CCFeatures));
int cmd_length = cc->cm.use_2cycle ? 16 : 8;
for (int i = 0; i < cmd_length; i++) {
u8 c = cc->shader_commands[i];
if (c >= SHADER_INPUT_1 && c <= SHADER_INPUT_8) {
if (c > ccf->num_inputs) { ccf->num_inputs = c; }
}
ccf->used_textures[0] = ccf->used_textures[0] || c == SHADER_TEXEL0 || c == SHADER_TEXEL0A;
ccf->used_textures[1] = ccf->used_textures[1] || c == SHADER_TEXEL1 || c == SHADER_TEXEL1A;
}
cc_features->opt_alpha = (shader_id & SHADER_OPT_ALPHA) != 0;
cc_features->opt_fog = (shader_id & SHADER_OPT_FOG) != 0;
cc_features->opt_texture_edge = (shader_id & SHADER_OPT_TEXTURE_EDGE) != 0;
cc_features->opt_noise = (shader_id & SHADER_OPT_NOISE) != 0;
// figure out optimizations
for (int i = 0; i < 16 / 4; i++) {
u8* c = &cc->shader_commands[i * 4];
ccf->do_single[i] = (c[2] == 0);
ccf->do_multiply[i] = (c[1] == 0 && c[3] == 0);
ccf->do_mix[i] = (c[1] == c[3]);
}
cc_features->used_textures[0] = false;
cc_features->used_textures[1] = false;
cc_features->num_inputs = 0;
ccf->color_alpha_same[0] = 1;
ccf->color_alpha_same[1] = 1;
for (int32_t i = 0; i < 2; i++) {
for (int32_t j = 0; j < 4; j++) {
if (cc_features->c[i][j] >= SHADER_INPUT_1 && cc_features->c[i][j] <= SHADER_INPUT_8) {
if (cc_features->c[i][j] > cc_features->num_inputs) {
cc_features->num_inputs = cc_features->c[i][j];
}
}
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 || cc_features->c[i][j] == SHADER_TEXEL1A) {
cc_features->used_textures[1] = true;
for (int i = 0; i < 2; i++) {
u8* cmd = &cc->shader_commands[i * 8];
for (int j = 0; j < 4; j++) {
if (cmd[j] != cmd[j + 4]) {
ccf->color_alpha_same[i] = 0;
break;
}
}
}
cc_features->do_single[0] = cc_features->c[0][2] == 0;
cc_features->do_single[1] = cc_features->c[1][2] == 0;
cc_features->do_multiply[0] = cc_features->c[0][1] == 0 && cc_features->c[0][3] == 0;
cc_features->do_multiply[1] = cc_features->c[1][1] == 0 && cc_features->c[1][3] == 0;
cc_features->do_mix[0] = cc_features->c[0][1] == cc_features->c[0][3];
cc_features->do_mix[1] = cc_features->c[1][1] == cc_features->c[1][3];
cc_features->color_alpha_same = (shader_id & 0xfff) == ((shader_id >> 12) & 0xfff);
}
void gfx_cc_print(struct ColorCombiner *cc) {
@ -103,6 +101,197 @@ void gfx_cc_precomp(void) {
gfx_pc_precomp_shader(0x04060401, 0x05000000, 0x04060402, 0x05000b0b, 0x00000001); // 1d970841b086b2e6
gfx_pc_precomp_shader(0x01000000, 0x04000000, 0x02000000, 0x04000b0b, 0x00000001); // 410000008f86b2e6
sAllowCCPrint = 1;
}
}
static uint8_t color_comb_component_a(uint32_t v, uint8_t cycle) {
switch (v) {
case G_CCMUX_COMBINED: return cycle ? CC_COMBINED : CC_0;
case G_CCMUX_TEXEL0: return cycle ? CC_TEXEL1 : CC_TEXEL0;
case G_CCMUX_TEXEL1: return cycle ? CC_TEXEL0 : CC_TEXEL1;
case G_CCMUX_PRIMITIVE: return CC_PRIM;
case G_CCMUX_SHADE: return CC_SHADE;
case G_CCMUX_ENVIRONMENT: return CC_ENV;
case G_CCMUX_1: return CC_1;
//case G_CCMUX_NOISE: return CC_NOISE;
case G_CCMUX_0: return CC_0;
case G_CCMUX_COMBINED_ALPHA: return cycle ? CC_COMBINEDA : CC_0;
case G_CCMUX_TEXEL0_ALPHA: return cycle ? CC_TEXEL1A : CC_TEXEL0A;
case G_CCMUX_TEXEL1_ALPHA: return cycle ? CC_TEXEL0A : CC_TEXEL1A;
case G_CCMUX_PRIMITIVE_ALPHA: return CC_PRIMA;
case G_CCMUX_SHADE_ALPHA: return CC_SHADEA;
case G_CCMUX_ENV_ALPHA: return CC_ENVA;
default: return CC_0;
}
}
static uint8_t color_comb_component_b(uint32_t v, uint8_t cycle) {
switch (v) {
case G_CCMUX_COMBINED: return cycle ? CC_COMBINED : CC_0;
case G_CCMUX_TEXEL0: return cycle ? CC_TEXEL1 : CC_TEXEL0;
case G_CCMUX_TEXEL1: return cycle ? CC_TEXEL0 : CC_TEXEL1;
case G_CCMUX_PRIMITIVE: return CC_PRIM;
case G_CCMUX_SHADE: return CC_SHADE;
case G_CCMUX_ENVIRONMENT: return CC_ENV;
//case G_CCMUX_CENTER: return CC_CENTER; // is this correct for "Chrome Key Center"?
//case G_CCMUX_K4: return CC_K4;
case G_CCMUX_0: return CC_0;
case G_CCMUX_COMBINED_ALPHA: return cycle ? CC_COMBINEDA : CC_0;
case G_CCMUX_TEXEL0_ALPHA: return cycle ? CC_TEXEL1A : CC_TEXEL0A;
case G_CCMUX_TEXEL1_ALPHA: return cycle ? CC_TEXEL0A : CC_TEXEL1A;
case G_CCMUX_PRIMITIVE_ALPHA: return CC_PRIMA;
case G_CCMUX_SHADE_ALPHA: return CC_SHADEA;
case G_CCMUX_ENV_ALPHA: return CC_ENVA;
default: return CC_0;
}
}
static uint8_t color_comb_component_c(uint32_t v, uint8_t cycle) {
switch (v) {
case G_CCMUX_COMBINED: return cycle ? CC_COMBINED : CC_0;
case G_CCMUX_TEXEL0: return cycle ? CC_TEXEL1 : CC_TEXEL0;
case G_CCMUX_TEXEL1: return cycle ? CC_TEXEL0 : CC_TEXEL1;
case G_CCMUX_PRIMITIVE: return CC_PRIM;
case G_CCMUX_SHADE: return CC_SHADE;
case G_CCMUX_ENVIRONMENT: return CC_ENV;
//case G_CCMUX_CENTER: return CC_CENTER; // is this correct for "Chrome Key Center"?
case G_CCMUX_COMBINED_ALPHA: return cycle ? CC_COMBINEDA : CC_0;
case G_CCMUX_TEXEL0_ALPHA: return CC_TEXEL0A;
case G_CCMUX_TEXEL1_ALPHA: return CC_TEXEL1A;
case G_CCMUX_PRIMITIVE_ALPHA: return CC_PRIMA;
case G_CCMUX_SHADE_ALPHA: return CC_SHADEA;
case G_CCMUX_ENV_ALPHA: return CC_ENVA;
case G_CCMUX_LOD_FRACTION: return CC_LOD;
//case G_CCMUX_PRIM_LOD_FRAC: return CC_PRIM_LOD_FRACTION;
//case G_CCMUX_K5: return CC_K5;
case G_CCMUX_0: return CC_0;
default: return CC_0;
}
}
static uint8_t color_comb_component_d(uint32_t v, uint8_t cycle) {
switch (v) {
case G_CCMUX_COMBINED: return cycle ? CC_COMBINED : CC_0;
case G_CCMUX_TEXEL0: return cycle ? CC_TEXEL1 : CC_TEXEL0;
case G_CCMUX_TEXEL1: return cycle ? CC_TEXEL0 : CC_TEXEL1;
case G_CCMUX_PRIMITIVE: return CC_PRIM;
case G_CCMUX_SHADE: return CC_SHADE;
case G_CCMUX_ENVIRONMENT: return CC_ENV;
case G_CCMUX_1: return CC_1;
case G_CCMUX_0: return CC_0;
case G_CCMUX_TEXEL0_ALPHA: return cycle ? CC_TEXEL1A : CC_TEXEL0A;
case G_CCMUX_TEXEL1_ALPHA: return cycle ? CC_TEXEL0A : CC_TEXEL1A;
case G_CCMUX_PRIMITIVE_ALPHA: return CC_PRIMA;
case G_CCMUX_SHADE_ALPHA: return CC_SHADEA;
case G_CCMUX_ENV_ALPHA: return CC_ENVA;
default: return CC_0;
}
}
uint32_t color_comb_rgb(uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint8_t cycle) {
return color_comb_component_a(a, cycle)
| (color_comb_component_b(b, cycle) << 8)
| (color_comb_component_c(c, cycle) << 16)
| (color_comb_component_d(d, cycle) << 24);
}
static uint8_t color_comb_component_a_alpha(uint32_t v, uint8_t cycle) {
switch (v) {
case G_CCMUX_COMBINED_ALPHA: return cycle ? CC_COMBINEDA : CC_0;
case G_CCMUX_TEXEL0_ALPHA: return cycle ? CC_TEXEL1A : CC_TEXEL0A;
case G_CCMUX_TEXEL1_ALPHA: return cycle ? CC_TEXEL0A : CC_TEXEL1A;
case G_CCMUX_PRIMITIVE_ALPHA: return CC_PRIMA;
case G_CCMUX_SHADE_ALPHA: return CC_SHADEA;
case G_CCMUX_ENV_ALPHA: return CC_ENVA;
case G_CCMUX_1: return CC_1;
case G_CCMUX_0: return CC_0;
case G_CCMUX_COMBINED: return cycle ? CC_COMBINED : CC_0;
case G_CCMUX_TEXEL0: return cycle ? CC_TEXEL1 : CC_TEXEL0;
case G_CCMUX_TEXEL1: return cycle ? CC_TEXEL0 : CC_TEXEL1;
case G_CCMUX_PRIMITIVE: return CC_PRIM;
case G_CCMUX_SHADE: return CC_SHADE;
case G_CCMUX_ENVIRONMENT: return CC_ENV;
default: return CC_0;
}
}
static uint8_t color_comb_component_b_alpha(uint32_t v, uint8_t cycle) {
switch (v) {
case G_CCMUX_COMBINED_ALPHA: return cycle ? CC_COMBINEDA : CC_0;
case G_CCMUX_TEXEL0_ALPHA: return cycle ? CC_TEXEL1A : CC_TEXEL0A;
case G_CCMUX_TEXEL1_ALPHA: return cycle ? CC_TEXEL0A : CC_TEXEL1A;
case G_CCMUX_PRIMITIVE_ALPHA: return CC_PRIMA;
case G_CCMUX_SHADE_ALPHA: return CC_SHADEA;
case G_CCMUX_ENV_ALPHA: return CC_ENVA;
case G_CCMUX_1: return CC_1;
case G_CCMUX_0: return CC_0;
case G_CCMUX_COMBINED: return cycle ? CC_COMBINED : CC_0;
case G_CCMUX_TEXEL0: return cycle ? CC_TEXEL1 : CC_TEXEL0;
case G_CCMUX_TEXEL1: return cycle ? CC_TEXEL0 : CC_TEXEL1;
case G_CCMUX_PRIMITIVE: return CC_PRIM;
case G_CCMUX_SHADE: return CC_SHADE;
case G_CCMUX_ENVIRONMENT: return CC_ENV;
default: return CC_0;
}
}
static uint8_t color_comb_component_c_alpha(uint32_t v, uint8_t cycle) {
switch (v) {
case G_CCMUX_LOD_FRACTION: return CC_LOD;
case G_CCMUX_TEXEL0_ALPHA: return cycle ? CC_TEXEL1A : CC_TEXEL0A;
case G_CCMUX_TEXEL1_ALPHA: return cycle ? CC_TEXEL1A : CC_TEXEL1A;
case G_CCMUX_PRIMITIVE_ALPHA: return CC_PRIMA;
case G_CCMUX_SHADE_ALPHA: return CC_SHADEA;
case G_CCMUX_ENV_ALPHA: return CC_ENVA;
//case G_CCMUX_PRIM_LOD_FRAC: return CC_PRIM_LOD_FRACTION;
case G_CCMUX_0: return CC_0;
case G_CCMUX_TEXEL0: return cycle ? CC_TEXEL1 : CC_TEXEL0;
case G_CCMUX_TEXEL1: return cycle ? CC_TEXEL0 : CC_TEXEL1;
case G_CCMUX_PRIMITIVE: return CC_PRIM;
case G_CCMUX_SHADE: return CC_SHADE;
case G_CCMUX_ENVIRONMENT: return CC_ENV;
default: return CC_0;
}
}
static uint8_t color_comb_component_d_alpha(uint32_t v, uint8_t cycle) {
switch (v) {
case G_CCMUX_COMBINED_ALPHA: return cycle ? CC_COMBINEDA : CC_0;
case G_CCMUX_TEXEL0_ALPHA: return cycle ? CC_TEXEL1A : CC_TEXEL0A;
case G_CCMUX_TEXEL1_ALPHA: return cycle ? CC_TEXEL0A : CC_TEXEL1A;
case G_CCMUX_PRIMITIVE_ALPHA: return CC_PRIMA;
case G_CCMUX_SHADE_ALPHA: return CC_SHADEA;
case G_CCMUX_ENV_ALPHA: return CC_ENVA;
case G_CCMUX_1: return CC_1;
case G_CCMUX_0: return CC_0;
case G_CCMUX_COMBINED: return cycle ? CC_COMBINED : CC_0;
case G_CCMUX_TEXEL0: return cycle ? CC_TEXEL1 : CC_TEXEL0;
case G_CCMUX_TEXEL1: return cycle ? CC_TEXEL0 : CC_TEXEL1;
case G_CCMUX_PRIMITIVE: return CC_PRIM;
case G_CCMUX_SHADE: return CC_SHADE;
case G_CCMUX_ENVIRONMENT: return CC_ENV;
default: return CC_0;
}
}
uint32_t color_comb_alpha(uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint8_t cycle) {
return color_comb_component_a_alpha(a, cycle)
| (color_comb_component_b_alpha(b, cycle) << 8)
| (color_comb_component_c_alpha(c, cycle) << 16)
| (color_comb_component_d_alpha(d, cycle) << 24);
}

View file

@ -48,17 +48,12 @@ enum {
#define SHADER_OPT_NOISE (1 << 27)
struct CCFeatures {
uint8_t c[2][4];
bool opt_alpha;
bool opt_fog;
bool opt_texture_edge;
bool opt_noise;
bool used_textures[2];
int num_inputs;
bool do_single[2];
bool do_multiply[2];
bool do_mix[2];
bool color_alpha_same;
bool do_single[4];
bool do_multiply[4];
bool do_mix[4];
bool color_alpha_same[2];
};
#pragma pack(1)
@ -107,9 +102,11 @@ struct ColorCombiner {
extern "C" {
#endif
void gfx_cc_get_features(uint32_t shader_id, struct CCFeatures *cc_features);
void gfx_cc_get_features(struct ColorCombiner* cc, struct CCFeatures *cc_features);
void gfx_cc_print(struct ColorCombiner *cc);
void gfx_cc_precomp(void);
uint32_t color_comb_rgb(uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint8_t cycle);
uint32_t color_comb_alpha(uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint8_t cycle);
#ifdef __cplusplus
}

View file

@ -237,6 +237,9 @@ static void append_formula(char *buf, size_t *len, uint8_t* cmd, bool do_single,
}
static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorCombiner* cc) {
struct CCFeatures ccf = { 0 };
gfx_cc_get_features(cc, &ccf);
bool opt_alpha = cc->cm.use_alpha;
bool opt_fog = cc->cm.use_fog;
bool opt_texture_edge = cc->cm.texture_edge;
@ -249,40 +252,6 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorC
bool opt_noise = cc->cm.use_noise;
#endif
bool used_textures[2] = { 0 };
int num_inputs = 0;
int cmd_length = opt_2cycle ? 16 : 8;
for (int i = 0; i < cmd_length; i++) {
u8 c = cc->shader_commands[i];
if (c >= SHADER_INPUT_1 && c <= SHADER_INPUT_8) {
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;
}
// figure out optimizations
bool do_single[4] = { 0 };
bool do_multiply[4] = { 0 };
bool do_mix[4] = { 0 };
for (int i = 0; i < 16 / 4; i++) {
u8* c = &cc->shader_commands[i * 4];
do_single[i] = (c[2] == 0);
do_multiply[i] = (c[1] == 0 && c[3] == 0);
do_mix[i] = (c[1] == c[3]);
}
bool color_alpha_same[2] = { 1, 1 };
for (int i = 0; i < 2; i++) {
u8* cmd = &cc->shader_commands[i * 8];
for (int j = 0; j < 4; j++) {
if (cmd[j] != cmd[j + 4]) {
color_alpha_same[i] = 0;
break;
}
}
}
char vs_buf[1024];
char fs_buf[2048];
size_t vs_len = 0;
@ -296,7 +265,7 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorC
append_line(vs_buf, &vs_len, "#version 120");
#endif
append_line(vs_buf, &vs_len, "attribute vec4 aVtxPos;");
if (used_textures[0] || used_textures[1]) {
if (ccf.used_textures[0] || ccf.used_textures[1]) {
append_line(vs_buf, &vs_len, "attribute vec2 aTexCoord;");
append_line(vs_buf, &vs_len, "varying vec2 vTexCoord;");
num_floats += 2;
@ -311,13 +280,13 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorC
append_line(vs_buf, &vs_len, "varying vec2 vLightMap;");
num_floats += 2;
}
for (int i = 0; i < num_inputs; i++) {
for (int i = 0; i < ccf.num_inputs; i++) {
vs_len += sprintf(vs_buf + vs_len, "attribute vec%d aInput%d;\n", opt_alpha ? 4 : 3, i + 1);
vs_len += sprintf(vs_buf + vs_len, "varying vec%d vInput%d;\n", opt_alpha ? 4 : 3, i + 1);
num_floats += opt_alpha ? 4 : 3;
}
append_line(vs_buf, &vs_len, "void main() {");
if (used_textures[0] || used_textures[1]) {
if (ccf.used_textures[0] || ccf.used_textures[1]) {
append_line(vs_buf, &vs_len, "vTexCoord = aTexCoord;");
}
if (opt_fog) {
@ -326,7 +295,7 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorC
if (opt_light_map) {
append_line(vs_buf, &vs_len, "vLightMap = aLightMap;");
}
for (int i = 0; i < num_inputs; i++) {
for (int i = 0; i < ccf.num_inputs; i++) {
vs_len += sprintf(vs_buf + vs_len, "vInput%d = aInput%d;\n", i + 1, i + 1);
}
append_line(vs_buf, &vs_len, "gl_Position = aVtxPos;");
@ -340,7 +309,7 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorC
append_line(fs_buf, &fs_len, "#version 120");
#endif
if (used_textures[0] || used_textures[1]) {
if (ccf.used_textures[0] || ccf.used_textures[1]) {
append_line(fs_buf, &fs_len, "varying vec2 vTexCoord;");
}
if (opt_fog) {
@ -349,15 +318,15 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorC
if (opt_light_map) {
append_line(fs_buf, &fs_len, "varying vec2 vLightMap;");
}
for (int i = 0; i < num_inputs; i++) {
for (int i = 0; i < ccf.num_inputs; i++) {
fs_len += sprintf(fs_buf + fs_len, "varying vec%d vInput%d;\n", opt_alpha ? 4 : 3, i + 1);
}
if (used_textures[0]) {
if (ccf.used_textures[0]) {
append_line(fs_buf, &fs_len, "uniform sampler2D uTex0;");
append_line(fs_buf, &fs_len, "uniform vec2 uTex0Size;");
append_line(fs_buf, &fs_len, "uniform bool uTex0Filter;");
}
if (used_textures[1]) {
if (ccf.used_textures[1]) {
append_line(fs_buf, &fs_len, "uniform sampler2D uTex1;");
append_line(fs_buf, &fs_len, "uniform vec2 uTex1Size;");
append_line(fs_buf, &fs_len, "uniform bool uTex1Filter;");
@ -367,7 +336,7 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorC
// Original author: ArthurCarvalho
// Slightly modified GLSL implementation by twinaphex, mupen64plus-libretro project.
if (used_textures[0] || used_textures[1]) {
if (ccf.used_textures[0] || ccf.used_textures[1]) {
if (configFiltering == 2) {
append_line(fs_buf, &fs_len, "#define TEX_OFFSET(off) texture2D(tex, texCoord - (off)/texSize)");
append_line(fs_buf, &fs_len, "vec4 filter3point(in sampler2D tex, in vec2 texCoord, in vec2 texSize) {");
@ -402,10 +371,10 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorC
append_line(fs_buf, &fs_len, "void main() {");
if (used_textures[0]) {
if (ccf.used_textures[0]) {
append_line(fs_buf, &fs_len, "vec4 texVal0 = sampleTex(uTex0, vTexCoord, uTex0Size, uTex0Filter);");
}
if (used_textures[1]) {
if (ccf.used_textures[1]) {
if (cc->cm.light_map) {
append_line(fs_buf, &fs_len, "vec4 texVal1 = sampleTex(uTex1, vLightMap, uTex1Size, uTex1Filter);");
} else {
@ -416,14 +385,14 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorC
append_str(fs_buf, &fs_len, (opt_alpha) ? "vec4 texel = " : "vec3 texel = ");
for (int i = 0; i < (opt_2cycle + 1); i++) {
u8* cmd = &cc->shader_commands[i * 8];
if (!color_alpha_same[i] && opt_alpha) {
if (!ccf.color_alpha_same[i] && opt_alpha) {
append_str(fs_buf, &fs_len, "vec4(");
append_formula(fs_buf, &fs_len, cmd, do_single[i*2+0], do_multiply[i*2+0], do_mix[i*2+0], false, false, true);
append_formula(fs_buf, &fs_len, cmd, ccf.do_single[i*2+0], ccf.do_multiply[i*2+0], ccf.do_mix[i*2+0], false, false, true);
append_str(fs_buf, &fs_len, ", ");
append_formula(fs_buf, &fs_len, cmd, do_single[i*2+1], do_multiply[i*2+1], do_mix[i*2+1], true, true, true);
append_formula(fs_buf, &fs_len, cmd, ccf.do_single[i*2+1], ccf.do_multiply[i*2+1], ccf.do_mix[i*2+1], true, true, true);
append_str(fs_buf, &fs_len, ")");
} else {
append_formula(fs_buf, &fs_len, cmd, do_single[i*2+0], do_multiply[i*2+0], do_mix[i*2+0], opt_alpha, false, opt_alpha);
append_formula(fs_buf, &fs_len, cmd, ccf.do_single[i*2+0], ccf.do_multiply[i*2+0], ccf.do_mix[i*2+0], opt_alpha, false, opt_alpha);
}
append_line(fs_buf, &fs_len, ";");
@ -509,7 +478,7 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorC
prg->attrib_sizes[cnt] = 4;
++cnt;
if (used_textures[0] || used_textures[1]) {
if (ccf.used_textures[0] || ccf.used_textures[1]) {
prg->attrib_locations[cnt] = glGetAttribLocation(shader_program, "aTexCoord");
prg->attrib_sizes[cnt] = 2;
++cnt;
@ -527,7 +496,7 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorC
++cnt;
}
for (int i = 0; i < num_inputs; i++) {
for (int i = 0; i < ccf.num_inputs; i++) {
char name[16];
sprintf(name, "aInput%d", i + 1);
prg->attrib_locations[cnt] = glGetAttribLocation(shader_program, name);
@ -537,21 +506,21 @@ static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorC
prg->hash = cc->hash;
prg->opengl_program_id = shader_program;
prg->num_inputs = num_inputs;
prg->used_textures[0] = used_textures[0];
prg->used_textures[1] = used_textures[1];
prg->num_inputs = ccf.num_inputs;
prg->used_textures[0] = ccf.used_textures[0];
prg->used_textures[1] = ccf.used_textures[1];
prg->num_floats = num_floats;
prg->num_attribs = cnt;
gfx_opengl_load_shader(prg);
if (used_textures[0]) {
if (ccf.used_textures[0]) {
GLint sampler_location = glGetUniformLocation(shader_program, "uTex0");
prg->uniform_locations[0] = glGetUniformLocation(shader_program, "uTex0Size");
prg->uniform_locations[1] = glGetUniformLocation(shader_program, "uTex0Filter");
glUniform1i(sampler_location, 0);
}
if (used_textures[1]) {
if (ccf.used_textures[1]) {
GLint sampler_location = glGetUniformLocation(shader_program, "uTex1");
prg->uniform_locations[2] = glGetUniformLocation(shader_program, "uTex1Size");
prg->uniform_locations[3] = glGetUniformLocation(shader_program, "uTex1Filter");

View file

@ -49,8 +49,9 @@ enum MixType {
struct ShaderProgram {
bool enabled;
uint32_t shader_id;
struct CCFeatures cc;
uint64_t hash;
struct ColorCombiner cc;
struct CCFeatures ccf;
enum MixType mix;
bool texture_used[2];
int texture_ord[2];
@ -140,25 +141,12 @@ static inline GLenum texenv_set_texture(UNUSED struct ShaderProgram *prg) {
}
static inline GLenum texenv_set_texture_color(struct ShaderProgram *prg) {
GLenum mode;
// HACK: lord forgive me for this, but this is easier
switch (prg->shader_id) {
case 0x0000038D: // mario's eyes
case 0x01045A00: // peach letter
case 0x01200A00: // intro copyright fade in
mode = GL_DECAL;
break;
case 0x00000551: // goddard
mode = GL_BLEND;
break;
default:
mode = GL_MODULATE;
break;
if (prg->cc.cm.rgb1 == color_comb_rgb(G_CCMUX_TEXEL0, G_CCMUX_SHADE, G_CCMUX_TEXEL0_ALPHA, G_CCMUX_SHADE, 0)) {
return GL_DECAL;
} else {
return GL_MODULATE;
}
return mode;
}
static inline GLenum texenv_set_texture_texture(UNUSED struct ShaderProgram *prg) {
@ -183,7 +171,7 @@ static void gfx_opengl_apply_shader(struct ShaderProgram *prg) {
glDisable(GL_TEXTURE_2D);
}
if (prg->shader_id & SHADER_OPT_FOG) {
if (prg->cc.cm.use_fog) {
// blend it on top of normal tris later
cur_fog_ofs = ofs;
ofs += 4;
@ -195,10 +183,10 @@ static void gfx_opengl_apply_shader(struct ShaderProgram *prg) {
// HACK: if there's a texture and two colors, one of them is likely for speculars or some shit (see mario head)
// if there's two colors but no texture, the real color is likely the second one
// HACKHACK: alpha is 0 in the transition shader (0x01A00045), maybe figure out the flags instead
const int vlen = (prg->cc.opt_alpha && prg->shader_id != 0x01A00045) ? 4 : 3;
const int vlen = (prg->cc.cm.use_alpha /*&& prg->shader_id != 0x01A00045*/) ? 4 : 3;
const int hack = vlen * (prg->num_inputs > 1);
if (prg->texture_used[1] && prg->cc.do_mix[0]) {
if (prg->texture_used[1] && prg->ccf.do_mix[0]) {
// HACK: when two textures are mixed by vertex color, store the color
// it will be used later when rendering two texture passes
c_mix[0] = *(ofs + hack + 0);
@ -224,7 +212,7 @@ static void gfx_opengl_apply_shader(struct ShaderProgram *prg) {
// we only need to do this once
prg->enabled = true;
if (prg->shader_id & SHADER_OPT_TEXTURE_EDGE) {
if (prg->cc.cm.texture_edge) {
// (horrible) alpha discard
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.666f);
@ -258,14 +246,15 @@ static void gfx_opengl_load_shader(struct ShaderProgram *new_prg) {
cur_shader->enabled = false;
}
static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(uint32_t shader_id) {
struct CCFeatures ccf;
gfx_cc_get_features(shader_id, &ccf);
static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(struct ColorCombiner* cc) {
struct ShaderProgram *prg = &shader_program_pool[shader_program_pool_size++];
prg->shader_id = shader_id;
prg->cc = ccf;
struct CCFeatures ccf = { 0 };
gfx_cc_get_features(cc, &ccf);
prg->hash = cc->hash;
prg->cc = *cc;
prg->ccf = ccf;
prg->num_inputs = ccf.num_inputs;
prg->texture_used[0] = ccf.used_textures[0];
prg->texture_used[1] = ccf.used_textures[1];
@ -296,9 +285,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];
return NULL;
}

View file

@ -1407,197 +1407,6 @@ static void gfx_dp_load_tile(uint8_t tile, uint32_t uls, uint32_t ult, uint32_t
rdp.texture_tile.lrt = lrt;
}
static uint8_t color_comb_component_a(uint32_t v, uint8_t cycle) {
switch (v) {
case G_CCMUX_COMBINED: return cycle ? CC_COMBINED : CC_0;
case G_CCMUX_TEXEL0: return cycle ? CC_TEXEL1 : CC_TEXEL0;
case G_CCMUX_TEXEL1: return cycle ? CC_TEXEL0 : CC_TEXEL1;
case G_CCMUX_PRIMITIVE: return CC_PRIM;
case G_CCMUX_SHADE: return CC_SHADE;
case G_CCMUX_ENVIRONMENT: return CC_ENV;
case G_CCMUX_1: return CC_1;
//case G_CCMUX_NOISE: return CC_NOISE;
case G_CCMUX_0: return CC_0;
case G_CCMUX_COMBINED_ALPHA: return cycle ? CC_COMBINEDA : CC_0;
case G_CCMUX_TEXEL0_ALPHA: return cycle ? CC_TEXEL1A : CC_TEXEL0A;
case G_CCMUX_TEXEL1_ALPHA: return cycle ? CC_TEXEL0A : CC_TEXEL1A;
case G_CCMUX_PRIMITIVE_ALPHA: return CC_PRIMA;
case G_CCMUX_SHADE_ALPHA: return CC_SHADEA;
case G_CCMUX_ENV_ALPHA: return CC_ENVA;
default: return CC_0;
}
}
static uint8_t color_comb_component_b(uint32_t v, uint8_t cycle) {
switch (v) {
case G_CCMUX_COMBINED: return cycle ? CC_COMBINED : CC_0;
case G_CCMUX_TEXEL0: return cycle ? CC_TEXEL1 : CC_TEXEL0;
case G_CCMUX_TEXEL1: return cycle ? CC_TEXEL0 : CC_TEXEL1;
case G_CCMUX_PRIMITIVE: return CC_PRIM;
case G_CCMUX_SHADE: return CC_SHADE;
case G_CCMUX_ENVIRONMENT: return CC_ENV;
//case G_CCMUX_CENTER: return CC_CENTER; // is this correct for "Chrome Key Center"?
//case G_CCMUX_K4: return CC_K4;
case G_CCMUX_0: return CC_0;
case G_CCMUX_COMBINED_ALPHA: return cycle ? CC_COMBINEDA : CC_0;
case G_CCMUX_TEXEL0_ALPHA: return cycle ? CC_TEXEL1A : CC_TEXEL0A;
case G_CCMUX_TEXEL1_ALPHA: return cycle ? CC_TEXEL0A : CC_TEXEL1A;
case G_CCMUX_PRIMITIVE_ALPHA: return CC_PRIMA;
case G_CCMUX_SHADE_ALPHA: return CC_SHADEA;
case G_CCMUX_ENV_ALPHA: return CC_ENVA;
default: return CC_0;
}
}
static uint8_t color_comb_component_c(uint32_t v, uint8_t cycle) {
switch (v) {
case G_CCMUX_COMBINED: return cycle ? CC_COMBINED : CC_0;
case G_CCMUX_TEXEL0: return cycle ? CC_TEXEL1 : CC_TEXEL0;
case G_CCMUX_TEXEL1: return cycle ? CC_TEXEL0 : CC_TEXEL1;
case G_CCMUX_PRIMITIVE: return CC_PRIM;
case G_CCMUX_SHADE: return CC_SHADE;
case G_CCMUX_ENVIRONMENT: return CC_ENV;
//case G_CCMUX_CENTER: return CC_CENTER; // is this correct for "Chrome Key Center"?
case G_CCMUX_COMBINED_ALPHA: return cycle ? CC_COMBINEDA : CC_0;
case G_CCMUX_TEXEL0_ALPHA: return CC_TEXEL0A;
case G_CCMUX_TEXEL1_ALPHA: return CC_TEXEL1A;
case G_CCMUX_PRIMITIVE_ALPHA: return CC_PRIMA;
case G_CCMUX_SHADE_ALPHA: return CC_SHADEA;
case G_CCMUX_ENV_ALPHA: return CC_ENVA;
case G_CCMUX_LOD_FRACTION: return CC_LOD;
//case G_CCMUX_PRIM_LOD_FRAC: return CC_PRIM_LOD_FRACTION;
//case G_CCMUX_K5: return CC_K5;
case G_CCMUX_0: return CC_0;
default: return CC_0;
}
}
static uint8_t color_comb_component_d(uint32_t v, uint8_t cycle) {
switch (v) {
case G_CCMUX_COMBINED: return cycle ? CC_COMBINED : CC_0;
case G_CCMUX_TEXEL0: return cycle ? CC_TEXEL1 : CC_TEXEL0;
case G_CCMUX_TEXEL1: return cycle ? CC_TEXEL0 : CC_TEXEL1;
case G_CCMUX_PRIMITIVE: return CC_PRIM;
case G_CCMUX_SHADE: return CC_SHADE;
case G_CCMUX_ENVIRONMENT: return CC_ENV;
case G_CCMUX_1: return CC_1;
case G_CCMUX_0: return CC_0;
case G_CCMUX_TEXEL0_ALPHA: return cycle ? CC_TEXEL1A : CC_TEXEL0A;
case G_CCMUX_TEXEL1_ALPHA: return cycle ? CC_TEXEL0A : CC_TEXEL1A;
case G_CCMUX_PRIMITIVE_ALPHA: return CC_PRIMA;
case G_CCMUX_SHADE_ALPHA: return CC_SHADEA;
case G_CCMUX_ENV_ALPHA: return CC_ENVA;
default: return CC_0;
}
}
static inline uint32_t color_comb_rgb(uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint8_t cycle) {
return color_comb_component_a(a, cycle)
| (color_comb_component_b(b, cycle) << 8)
| (color_comb_component_c(c, cycle) << 16)
| (color_comb_component_d(d, cycle) << 24);
}
static uint8_t color_comb_component_a_alpha(uint32_t v, uint8_t cycle) {
switch (v) {
case G_CCMUX_COMBINED_ALPHA: return cycle ? CC_COMBINEDA : CC_0;
case G_CCMUX_TEXEL0_ALPHA: return cycle ? CC_TEXEL1A : CC_TEXEL0A;
case G_CCMUX_TEXEL1_ALPHA: return cycle ? CC_TEXEL0A : CC_TEXEL1A;
case G_CCMUX_PRIMITIVE_ALPHA: return CC_PRIMA;
case G_CCMUX_SHADE_ALPHA: return CC_SHADEA;
case G_CCMUX_ENV_ALPHA: return CC_ENVA;
case G_CCMUX_1: return CC_1;
case G_CCMUX_0: return CC_0;
case G_CCMUX_COMBINED: return cycle ? CC_COMBINED : CC_0;
case G_CCMUX_TEXEL0: return cycle ? CC_TEXEL1 : CC_TEXEL0;
case G_CCMUX_TEXEL1: return cycle ? CC_TEXEL0 : CC_TEXEL1;
case G_CCMUX_PRIMITIVE: return CC_PRIM;
case G_CCMUX_SHADE: return CC_SHADE;
case G_CCMUX_ENVIRONMENT: return CC_ENV;
default: return CC_0;
}
}
static uint8_t color_comb_component_b_alpha(uint32_t v, uint8_t cycle) {
switch (v) {
case G_CCMUX_COMBINED_ALPHA: return cycle ? CC_COMBINEDA : CC_0;
case G_CCMUX_TEXEL0_ALPHA: return cycle ? CC_TEXEL1A : CC_TEXEL0A;
case G_CCMUX_TEXEL1_ALPHA: return cycle ? CC_TEXEL0A : CC_TEXEL1A;
case G_CCMUX_PRIMITIVE_ALPHA: return CC_PRIMA;
case G_CCMUX_SHADE_ALPHA: return CC_SHADEA;
case G_CCMUX_ENV_ALPHA: return CC_ENVA;
case G_CCMUX_1: return CC_1;
case G_CCMUX_0: return CC_0;
case G_CCMUX_COMBINED: return cycle ? CC_COMBINED : CC_0;
case G_CCMUX_TEXEL0: return cycle ? CC_TEXEL1 : CC_TEXEL0;
case G_CCMUX_TEXEL1: return cycle ? CC_TEXEL0 : CC_TEXEL1;
case G_CCMUX_PRIMITIVE: return CC_PRIM;
case G_CCMUX_SHADE: return CC_SHADE;
case G_CCMUX_ENVIRONMENT: return CC_ENV;
default: return CC_0;
}
}
static uint8_t color_comb_component_c_alpha(uint32_t v, uint8_t cycle) {
switch (v) {
case G_CCMUX_LOD_FRACTION: return CC_LOD;
case G_CCMUX_TEXEL0_ALPHA: return cycle ? CC_TEXEL1A : CC_TEXEL0A;
case G_CCMUX_TEXEL1_ALPHA: return cycle ? CC_TEXEL1A : CC_TEXEL1A;
case G_CCMUX_PRIMITIVE_ALPHA: return CC_PRIMA;
case G_CCMUX_SHADE_ALPHA: return CC_SHADEA;
case G_CCMUX_ENV_ALPHA: return CC_ENVA;
//case G_CCMUX_PRIM_LOD_FRAC: return CC_PRIM_LOD_FRACTION;
case G_CCMUX_0: return CC_0;
case G_CCMUX_TEXEL0: return cycle ? CC_TEXEL1 : CC_TEXEL0;
case G_CCMUX_TEXEL1: return cycle ? CC_TEXEL0 : CC_TEXEL1;
case G_CCMUX_PRIMITIVE: return CC_PRIM;
case G_CCMUX_SHADE: return CC_SHADE;
case G_CCMUX_ENVIRONMENT: return CC_ENV;
default: return CC_0;
}
}
static uint8_t color_comb_component_d_alpha(uint32_t v, uint8_t cycle) {
switch (v) {
case G_CCMUX_COMBINED_ALPHA: return cycle ? CC_COMBINEDA : CC_0;
case G_CCMUX_TEXEL0_ALPHA: return cycle ? CC_TEXEL1A : CC_TEXEL0A;
case G_CCMUX_TEXEL1_ALPHA: return cycle ? CC_TEXEL0A : CC_TEXEL1A;
case G_CCMUX_PRIMITIVE_ALPHA: return CC_PRIMA;
case G_CCMUX_SHADE_ALPHA: return CC_SHADEA;
case G_CCMUX_ENV_ALPHA: return CC_ENVA;
case G_CCMUX_1: return CC_1;
case G_CCMUX_0: return CC_0;
case G_CCMUX_COMBINED: return cycle ? CC_COMBINED : CC_0;
case G_CCMUX_TEXEL0: return cycle ? CC_TEXEL1 : CC_TEXEL0;
case G_CCMUX_TEXEL1: return cycle ? CC_TEXEL0 : CC_TEXEL1;
case G_CCMUX_PRIMITIVE: return CC_PRIM;
case G_CCMUX_SHADE: return CC_SHADE;
case G_CCMUX_ENVIRONMENT: return CC_ENV;
default: return CC_0;
}
}
static inline uint32_t color_comb_alpha(uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint8_t cycle) {
return color_comb_component_a_alpha(a, cycle)
| (color_comb_component_b_alpha(b, cycle) << 8)
| (color_comb_component_c_alpha(c, cycle) << 16)
| (color_comb_component_d_alpha(d, cycle) << 24);
}
static void gfx_dp_set_combine_mode(uint32_t rgb1, uint32_t alpha1, uint32_t rgb2, uint32_t alpha2) {
//printf(">>> combine: %08x %08x %08x %08x\n", rgb1, alpha1, rgb2, alpha2);
memset(&rdp.combine_mode, 0, sizeof(struct CombineMode));