Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow using position and normals as tex coordinates #82

Merged
merged 4 commits into from
Nov 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 87 additions & 11 deletions src/arrays.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ POSSIBILITY OF SUCH DAMAGE.
#include <variant>

static char s_num_tex_arrays = 0;
static bool s_has_normals = false;
static uint8_t s_num_colors = 0;
static uint8_t s_tex_unit_mask = 0;

struct GxVertexFormat {
uint8_t attribute;
Expand Down Expand Up @@ -160,6 +163,11 @@ struct VertexReaderBase {
this->dup_color = dup_color;
}

void set_tex_coord_source(uint8_t source) { tex_coord_source = source; }
bool has_same_data(VertexReaderBase *other) const {
return data == other->data && stride == other->stride;
}

virtual void process_element(int index) = 0;

virtual void read_color(int index, GXColor *color) = 0;
Expand All @@ -171,6 +179,7 @@ struct VertexReaderBase {
const char *data;
uint16_t stride;
bool dup_color;
uint8_t tex_coord_source;
VboType vbo;
};

Expand Down Expand Up @@ -438,24 +447,86 @@ void _ogx_array_reader_init(OgxArrayReader *reader,
type, vertex_attribute);
}

void _ogx_array_reader_setup_draw_start()
static inline VertexReaderBase *get_reader(OgxArrayReader *reader)
{
GX_ClearVtxDesc();
s_num_tex_arrays = 0;
return reinterpret_cast<VertexReaderBase *>(reader);
}

void _ogx_array_reader_setup_draw(OgxArrayReader *reader)
void _ogx_arrays_setup_draw(bool has_normals, uint8_t num_colors,
uint8_t tex_unit_mask)
{
VertexReaderBase *r = reinterpret_cast<VertexReaderBase *>(reader);
r->setup_draw();
GX_ClearVtxDesc();
s_num_tex_arrays = 0;

VertexReaderBase *vertex_reader = get_reader(&glparamstate.vertex_array);
vertex_reader->setup_draw();

VertexReaderBase *normal_reader = nullptr;
if (has_normals) {
normal_reader = get_reader(&glparamstate.normal_array);
normal_reader->setup_draw();
}
if (num_colors > 0) {
VertexReaderBase *r = get_reader(&glparamstate.color_array);
r->enable_duplicate_color(num_colors > 1);
r->setup_draw();
}

int sent_tex_arrays = 0;
s_tex_unit_mask = 0;
if (tex_unit_mask) {
for (int i = 0; i < MAX_TEXTURE_UNITS; i++) {
if (tex_unit_mask & (1 << i)) {
VertexReaderBase *r = get_reader(&glparamstate.texcoord_array[i]);
/* See if the data array is the same as the positional or
* normal array. This is not just an optimization, it's
* actually needed because GX only supports up to two input
* coordinates for GX_VA_TEXx, but the client might provide
* three (along with an appropriate texture matrix). So, at
* least in those cases where these arrays coincide, we can
* support having three texture input coordinates. */
if (r->has_same_data(vertex_reader)) {
r->set_tex_coord_source(GX_TG_POS);
} else if (normal_reader &&
r->has_same_data(normal_reader)) {
r->set_tex_coord_source(GX_TG_NRM);
} else {
/* We could go on and check if this array has the same data
* of another texture array sent earlier in this same loop,
* but let's leave this optimisation for later. */
r->setup_draw();
r->set_tex_coord_source(GX_TG_TEX0 + sent_tex_arrays++);
s_tex_unit_mask |= (1 << i);
}
}
}
}

s_has_normals = has_normals;
s_num_colors = num_colors;
/* s_tex_unit_mask has been set in the loop above */
}

void _ogx_array_reader_setup_draw_color(OgxArrayReader *reader,
bool dup_color)
void _ogx_arrays_process_element(int index)
{
VertexReaderBase *r = reinterpret_cast<VertexReaderBase *>(reader);
r->enable_duplicate_color(dup_color);
r->setup_draw();
get_reader(&glparamstate.vertex_array)->process_element(index);

if (s_has_normals) {
get_reader(&glparamstate.normal_array)->process_element(index);
}

if (s_num_colors) {
get_reader(&glparamstate.color_array)->process_element(index);
}

if (s_tex_unit_mask) {
for (int i = 0; i < MAX_TEXTURE_UNITS; i++) {
if (s_tex_unit_mask & (1 << i)) {
get_reader(&glparamstate.texcoord_array[i])->
process_element(index);
}
}
}
}

void _ogx_array_reader_enable_dup_color(OgxArrayReader *reader,
Expand All @@ -471,6 +542,11 @@ void _ogx_array_reader_process_element(OgxArrayReader *reader, int index)
r->process_element(index);
}

uint8_t _ogx_array_reader_get_tex_coord_source(OgxArrayReader *reader)
{
return get_reader(reader)->tex_coord_source;
}

void _ogx_array_reader_read_pos3f(OgxArrayReader *reader,
int index, float *pos)
{
Expand Down
8 changes: 4 additions & 4 deletions src/arrays.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,13 @@ void _ogx_array_reader_init(OgxArrayReader *reader,
uint8_t vertex_attribute,
const void *data,
int num_components, GLenum type, int stride);
void _ogx_array_reader_setup_draw_start();
void _ogx_array_reader_setup_draw(OgxArrayReader *reader);
void _ogx_array_reader_setup_draw_color(OgxArrayReader *reader,
bool dup_color);
void _ogx_arrays_setup_draw(bool has_normals, uint8_t num_colors,
uint8_t tex_unit_mask);
void _ogx_arrays_process_element(int index);
void _ogx_array_reader_enable_dup_color(OgxArrayReader *reader,
bool dup_color);
void _ogx_array_reader_process_element(OgxArrayReader *reader, int index);
uint8_t _ogx_array_reader_get_tex_coord_source(OgxArrayReader *reader);

void _ogx_array_reader_read_pos3f(OgxArrayReader *reader,
int index, float *pos);
Expand Down
22 changes: 7 additions & 15 deletions src/call_lists.c
Original file line number Diff line number Diff line change
Expand Up @@ -229,20 +229,17 @@ static void execute_draw_geometry_list(struct DrawGeometry *dg)
}
}

_ogx_array_reader_setup_draw_start();
_ogx_array_reader_setup_draw(&glparamstate.vertex_array);
if (dg->cs.normal_enabled) {
_ogx_array_reader_setup_draw(&glparamstate.normal_array);
} else {
_ogx_arrays_setup_draw(dg->cs.normal_enabled,
dg->cs.color_enabled ? 2 : 0,
dg->cs.texcoord_enabled);
if (!dg->cs.normal_enabled) {
GX_SetVtxDesc(GX_VA_NRM, GX_INDEX8);
GX_SetArray(GX_VA_NRM, s_current_normal, 12);
floatcpy(s_current_normal, glparamstate.imm_mode.current_normal, 3);
/* Not needed on Dolphin, but it is on a Wii */
DCStoreRange(s_current_normal, 12);
}
if (dg->cs.color_enabled) {
_ogx_array_reader_setup_draw_color(&glparamstate.color_array, true);
} else {
if (!dg->cs.color_enabled) {
GX_SetVtxDesc(GX_VA_CLR0, GX_INDEX8);
GX_SetVtxDesc(GX_VA_CLR1, GX_INDEX8);
s_current_color = current_color;
Expand All @@ -251,13 +248,8 @@ static void execute_draw_geometry_list(struct DrawGeometry *dg)
DCStoreRange(&s_current_color, 4);
}

for (int i = 0; i < MAX_TEXTURE_UNITS; i++) {
/* It makes no sense to use a fixed texture coordinates for all vertices,
* so we won't add them unless they are enabled. */
if (dg->cs.texcoord_enabled & (1 << i)) {
_ogx_array_reader_setup_draw(&glparamstate.texcoord_array[i]);
}
}
/* It makes no sense to use a fixed texture coordinates for all vertices,
* so we won't add them unless they are enabled. */

GX_InvVtxCache();

Expand Down
Loading