Files
korenkonder_ReDIVA/src/CRE/draw_object.c
T

1717 lines
62 KiB
C

/*
by korenkonder
GitHub/GitLab: korenkonder
*/
#include "draw_object.h"
#include "light_param/light.h"
#include "shader_ft.h"
#include "static_var.h"
#include "texture.h"
#define enable_vertex_attrib_array(index) \
glEnableVertexAttribArray(index); \
draw->vertex_attrib_array[index] = true
static bool draw_object_blend_set(render_context* rctx,
draw_object* draw, object_material_shader_lighting_type lighting_type);
static void draw_object_chara_color_fog_set(render_context* rctx,
draw_object* draw, bool disable_fog);
static void draw_object_material_reset_default(object_material_data* mat_data);
static void draw_object_material_reset_reflect();
static void draw_object_material_set_default(render_context* rctx,
draw_object* draw, bool use_shader);
static void draw_object_material_set_parameter(render_context* rctx,
object_material_data* mat_data);
static void draw_object_material_set_reflect(render_context* rctx, draw_object* draw);
static void draw_object_material_set_uniform(render_context* rctx,
object_material_data* mat_data, bool disable_color_l);
static void draw_object_vertex_attrib_reset_default(draw_object* draw);
static void draw_object_vertex_attrib_reset_default_compressed(draw_object* draw);
static void draw_object_vertex_attrib_reset_reflect(draw_object* draw);
static void draw_object_vertex_attrib_reset_reflect_compressed(draw_object* draw);
static void draw_object_vertex_attrib_set_default(draw_object* draw);
static void draw_object_vertex_attrib_set_default_compressed(draw_object* draw);
static void draw_object_vertex_attrib_set_reflect(draw_object* draw);
static void draw_object_vertex_attrib_set_reflect_compressed(draw_object* draw);
void draw_object_draw(render_context* rctx, draw_object* draw, mat4* model,
void(*draw_object_func)(render_context* rctx, draw_object* draw), int32_t show_vector) {
if (draw->mats) {
mat4u* mats = draw->mats;
mat4 mat;
for (int32_t i = 0; i < draw->mat_count; i++, mats++) {
mat4u_to_mat4_transpose(mats, &mat);
shader_buffer_set_ptr_array(&shaders_ft, (size_t)i * 3, 3, (vec4*)&mat);
}
uniform_value[U_BONE_MAT] = 1;
}
else {
for (int32_t i = 0; i < SHADER_MAX_PROGRAM_BUFFER_PARAMETERS / 3; i++)
shader_buffer_set_ptr_array(&shaders_ft, (size_t)i * 3, 3, (vec4*)&mat4_identity);
uniform_value[U_BONE_MAT] = 0;
}
mat4 mat;
if (draw->mesh->flags & OBJECT_MESH_BILLBOARD)
model_mat_face_camera_view(&rctx->camera->inv_view_rot, model, &mat);
else if (draw->mesh->flags & OBJECT_MESH_BILLBOARD_Y_AXIS)
model_mat_face_camera_position(&rctx->camera->view, model, &mat);
else
mat = *model;
draw_object_model_mat_load(rctx, &mat);
if (!show_vector)
draw_object_func(rctx, draw);
uniform_value[U_BONE_MAT] = 0;
}
void draw_object_draw_default(render_context* rctx, draw_object* draw) {
if (draw->set_blend_color) {
vec4 blend_color;
vec4u_to_vec4(draw->blend_color, blend_color);
shader_env_vert_set_ptr(&shaders_ft, 3, &blend_color);
shader_env_vert_set_ptr(&shaders_ft, 4, (vec4*)&vec4_null);
}
if (!draw->draw_object_func)
draw_object_vertex_attrib_set_default(draw);
draw_object_material_set_default(rctx, draw, rctx->draw_state.shader);
if (!draw->instances_count)
object_sub_mesh_draw(rctx,
draw->sub_mesh->primitive_type,
draw->sub_mesh->indices_count,
draw->sub_mesh->first_index,
draw->sub_mesh->last_index,
draw->sub_mesh->index_format,
draw->sub_mesh->indices_offset);
else
for (int32_t i = 0; i < draw->instances_count; i++) {
mat4 mat;
mat4_transpose(&draw->instances_mat[i], &mat);
glVertexAttrib4fv(12, (const GLfloat*)&mat.row0);
glVertexAttrib4fv(13, (const GLfloat*)&mat.row1);
glVertexAttrib4fv(14, (const GLfloat*)&mat.row2);
glVertexAttrib4fv(15, (const GLfloat*)&mat.row3);
object_sub_mesh_draw(rctx,
draw->sub_mesh->primitive_type,
draw->sub_mesh->indices_count,
draw->sub_mesh->first_index,
draw->sub_mesh->last_index,
draw->sub_mesh->index_format,
draw->sub_mesh->indices_offset);
}
draw_object_material_reset_default(draw->material);
if (!draw->draw_object_func)
draw_object_vertex_attrib_reset_default(draw);
if (draw->set_blend_color) {
shader_env_vert_set_ptr(&shaders_ft, 3, (vec4*)&vec4_identity);
shader_env_vert_set_ptr(&shaders_ft, 4, (vec4*)&vec4_null);
}
rctx->draw_state.stats.object_draw_count++;
}
void draw_object_draw_sss(render_context* rctx, draw_object* draw) {
object_material_blend_flags blend_flags = draw->material->material.blend_flags;
uniform_value[U_ALPHA_TEST] = (!blend_flags.flag_28 && (draw->blend_color.w < 1.0f
|| (blend_flags.alpha_texture || blend_flags.alpha_material) && !blend_flags.punch_through
|| draw->sub_mesh->flags & OBJECT_SUB_MESH_TRANSPARENT)
|| blend_flags.punch_through) ? 1 : 0;
uniform_value[U26] = 1;
bool aniso = false;
object_material_data* material = draw->material;
switch (material->material.shader_index) {
case SHADER_FT_CLOTH:
if (!rctx->draw_pass.npr_param && material->material.ambient.w < 1.0f
&& (material->material.shader_flags.aniso_direction & 0x03) == OBJECT_MATERIAL_ANISO_DIRECTION_NORMAL)
aniso = true;
break;
case SHADER_FT_TIGHTS:
if (!rctx->draw_pass.npr_param)
aniso = true;
break;
case SHADER_FT_EYEBALL:
uniform_value[U26] = 0;
aniso = true;
break;
case SHADER_FT_SKIN:
aniso = true;
break;
}
if (aniso) {
shader_env_frag_set(&shaders_ft, 25, 0.0f, 0.0f, 0.0f, 0.5f);
uniform_value[U37] = 1;
}
else {
vec4 sss_param = rctx->draw_pass.sss_data.param;
shader_env_frag_set(&shaders_ft, 25, sss_param.x, sss_param.y, sss_param.z, 0.5f);
uniform_value[U37] = 0;
}
draw_object_draw_default(rctx, draw);
}
void draw_object_draw_reflect(render_context* rctx, draw_object* draw) {
object_material_data* material = draw->material;
draw_object_vertex_attrib_set_reflect(draw);
object_material_shader_lighting_type lighting_type =
object_material_shader_get_lighting_type(&material->material.shader_flags);
bool disable_fog = draw_object_blend_set(rctx, draw, lighting_type);
draw_object_chara_color_fog_set(rctx, draw, disable_fog);
draw_object_material_set_reflect(rctx, draw);
object_sub_mesh* sub_mesh = draw->sub_mesh;
if (sub_mesh->index_format != OBJECT_INDEX_U8)
object_sub_mesh_draw(rctx,
sub_mesh->primitive_type,
sub_mesh->indices_count,
sub_mesh->first_index,
sub_mesh->last_index,
sub_mesh->index_format,
sub_mesh->indices_offset);
draw_object_material_reset_reflect();
draw_object_vertex_attrib_reset_reflect(draw);
uniform_value_reset();
rctx->draw_state.stats.object_reflect_draw_count++;
}
void draw_object_draw_reflect_type_2(render_context* rctx, draw_object* draw) {
draw_object_vertex_attrib_set_reflect(draw);
draw_object_material_set_reflect(rctx, draw);
object_sub_mesh* sub_mesh = draw->sub_mesh;
if (sub_mesh->index_format != OBJECT_INDEX_U8)
object_sub_mesh_draw(rctx,
sub_mesh->primitive_type,
sub_mesh->indices_count,
sub_mesh->first_index,
sub_mesh->last_index,
sub_mesh->index_format,
sub_mesh->indices_offset);
draw_object_material_reset_reflect();
draw_object_vertex_attrib_reset_reflect(draw);
rctx->draw_state.stats.object_reflect_draw_count++;
}
void draw_object_draw_shadow(render_context* rctx, draw_object* draw) {
object_material_blend_flags blend_flags = draw->material->material.blend_flags;
if (!blend_flags.flag_28 && (draw->blend_color.w < 1.0f
|| (blend_flags.alpha_texture || blend_flags.alpha_material) && !blend_flags.punch_through
|| draw->sub_mesh->flags & OBJECT_SUB_MESH_TRANSPARENT)
|| blend_flags.punch_through) {
uniform_value[U_ALPHA_TEST] = 1;
draw_object_draw_translucent(rctx, draw);
}
else {
uniform_value[U_ALPHA_TEST] = 0;
draw_object_draw_translucent(rctx, draw);
}
}
void draw_object_draw_translucent(render_context* rctx, draw_object* draw) {
object_material_data* material = draw->material;
GLuint* textures = draw->textures;
if (rctx->draw_state.shader_index != -1) {
vec4 emission;
vec4u_to_vec4(material->material.emission, emission);
shader_state_material_set_emission_ptr(&shaders_ft, false, &emission);
draw_object_material_set_uniform(rctx, material, 0);
if (material->material.blend_flags.alpha_texture)
uniform_value[U_TEXTURE_COUNT] = 0;
shader_set(&shaders_ft, rctx->draw_state.shader_index);
}
draw_object_vertex_attrib_set_default(draw);
if (draw->material->material.blend_flags.double_sided)
gl_state_disable_cull_face();
GLuint tex_id = -1;
int32_t tex_index = 0;
if (material->material.blend_flags.alpha_texture) {
object_material_texture* mat_tex = material->material.textures;
uint32_t texture_id = -1;
uint32_t texture_index = -1;
if (~material->material.flags & OBJECT_MATERIAL_TRANSPARENCY) {
for (int32_t i = 0; i < 8; i++, mat_tex++)
if (mat_tex->texture_flags.type == OBJECT_MATERIAL_TEXTURE_COLOR) {
texture_id = mat_tex->texture_id;
texture_index = mat_tex->texture_index;
break;
}
tex_index = 0;
}
else {
for (int32_t i = 0; i < 8; i++, mat_tex++)
if (mat_tex->texture_flags.type == OBJECT_MATERIAL_TEXTURE_TRANSPARENCY) {
if (mat_tex->sampler_flags.flag_29) {
texture_id = mat_tex->texture_id;
texture_index = mat_tex->texture_index;
}
break;
}
tex_index = 4;
}
if (texture_id != -1) {
for (int32_t j = 0; j < draw->texture_pattern_count; j++)
if (draw->texture_pattern_array[j].src == texture_id) {
texture* tex = texture_storage_get_texture(draw->texture_pattern_array[j].dst);
if (tex)
tex_id = tex->texture;
break;
}
if (tex_id == -1)
tex_id = textures[mat_tex->texture_index];
if (tex_id == -1)
tex_id = 0;
gl_state_active_bind_texture_2d(tex_index, tex_id);
}
}
object_sub_mesh* sub_mesh = draw->sub_mesh;
if (sub_mesh->index_format != OBJECT_INDEX_U8)
object_sub_mesh_draw(rctx,
sub_mesh->primitive_type,
sub_mesh->indices_count,
sub_mesh->first_index,
sub_mesh->last_index,
sub_mesh->index_format,
sub_mesh->indices_offset);
if (tex_id != -1)
gl_state_active_bind_texture_2d(tex_index, 0);
gl_state_enable_cull_face();
draw_object_vertex_attrib_reset_default(draw);
if (rctx->draw_state.shader_index != -1)
uniform_value_reset();
rctx->draw_state.stats.object_translucent_draw_count++;
}
inline void draw_object_model_mat_load(render_context* rctx, mat4* mat) {
shader_state_matrix_set_modelview_separate(&shaders_ft, 0, mat, &rctx->view_mat, true);
shader_state_matrix_set_program(&shaders_ft, 6, mat);
}
inline void model_mat_face_camera_position(mat4* view, mat4* src, mat4* dst) {
vec3 trans;
mat4_mult_vec3_inv_trans(view, (vec3*)&view->row3, &trans);
vec3_negate(trans, trans);
vec3 dir;
vec3_sub(trans, *(vec3*)&src->row3, dir);
vec3_normalize(dir, dir);
vec3 x_rot;
vec3 y_rot;
vec3 z_rot;
y_rot = *(vec3*)&src->row1;
vec3_cross(y_rot, dir, x_rot);
vec3_normalize(x_rot, x_rot);
vec3_cross(x_rot, y_rot, z_rot);
*(vec3*)&dst->row0 = x_rot;
*(vec3*)&dst->row1 = y_rot;
*(vec3*)&dst->row2 = z_rot;
*(vec3*)&dst->row3 = *(vec3*)&src->row3;
dst->row0.w = 0.0f;
dst->row1.w = 0.0f;
dst->row2.w = 0.0f;
dst->row3.w = 1.0f;
}
inline void model_mat_face_camera_view(mat4* inv_view_rot, mat4* src, mat4* dst) {
mat4_mult(inv_view_rot, src, dst);
}
void object_sub_mesh_draw(render_context* rctx, object_primitive_type primitive_type,
uint32_t count, uint16_t start, uint16_t end, object_index_format index_format, size_t indices) {
GLenum mesh_draw_mode[] = {
[OBJECT_PRIMITIVE_POINTS ] = GL_ZERO, //GL_POINTS,
[OBJECT_PRIMITIVE_LINES ] = GL_LINES,
[OBJECT_PRIMITIVE_LINE_STRIP ] = GL_LINE_STRIP,
[OBJECT_PRIMITIVE_LINE_LOOP ] = GL_LINE_LOOP,
[OBJECT_PRIMITIVE_TRIANGLES ] = GL_TRIANGLES,
[OBJECT_PRIMITIVE_TRIANGLE_STRIP] = GL_TRIANGLE_STRIP,
[OBJECT_PRIMITIVE_TRIANGLE_FAN ] = GL_TRIANGLE_FAN,
[OBJECT_PRIMITIVE_QUADS ] = GL_ZERO, //GL_QUADS,
[OBJECT_PRIMITIVE_QUAD_STRIP ] = GL_ZERO, //GL_QUAD_STRIP,
[OBJECT_PRIMITIVE_POLYGON ] = GL_ZERO, //GL_POLYGON,
};
GLenum mesh_indices_type[] = {
[OBJECT_INDEX_U8 ] = GL_ZERO,
[OBJECT_INDEX_U16] = GL_UNSIGNED_SHORT,
[OBJECT_INDEX_U32] = GL_UNSIGNED_INT,
};
if (primitive_type == OBJECT_PRIMITIVE_TRIANGLE_STRIP && index_format == OBJECT_INDEX_U16) {
gl_state_enable_primitive_restart();
glPrimitiveRestartIndex(0xFFFF);
shader_draw_range_elements(&shaders_ft, GL_TRIANGLE_STRIP,
start, end, count, GL_UNSIGNED_SHORT, (void*)indices);
gl_state_disable_primitive_restart();
}
else
shader_draw_elements(&shaders_ft, mesh_draw_mode[primitive_type],
count, mesh_indices_type[index_format], (void*)indices);
rctx->draw_state.stats.draw_count += count;
if (primitive_type == OBJECT_PRIMITIVE_TRIANGLES)
rctx->draw_state.stats.draw_triangle_count += count / 3;
else if (primitive_type == OBJECT_PRIMITIVE_TRIANGLE_STRIP)
rctx->draw_state.stats.draw_triangle_count += count - 2;
}
static bool draw_object_blend_set(render_context* rctx, draw_object* draw, object_material_shader_lighting_type lighting_type) {
GLenum blend_factor_table[] = {
[OBJECT_MATERIAL_BLEND_ZERO] = GL_ZERO,
[OBJECT_MATERIAL_BLEND_ONE] = GL_ONE,
[OBJECT_MATERIAL_BLEND_SRC_COLOR] = GL_SRC_COLOR,
[OBJECT_MATERIAL_BLEND_INVERSE_SRC_COLOR] = GL_ONE_MINUS_SRC_COLOR,
[OBJECT_MATERIAL_BLEND_SRC_ALPHA] = GL_SRC_ALPHA,
[OBJECT_MATERIAL_BLEND_INVERSE_SRC_ALPHA] = GL_ONE_MINUS_SRC_ALPHA,
[OBJECT_MATERIAL_BLEND_DST_ALPHA] = GL_DST_ALPHA,
[OBJECT_MATERIAL_BLEND_INVERSE_DST_ALPHA] = GL_ONE_MINUS_DST_ALPHA,
[OBJECT_MATERIAL_BLEND_DST_COLOR] = GL_DST_COLOR,
[OBJECT_MATERIAL_BLEND_INVERSE_DST_COLOR] = GL_ONE_MINUS_DST_COLOR,
[OBJECT_MATERIAL_BLEND_ALPHA_SATURATE] = GL_SRC_ALPHA_SATURATE,
[11] = GL_ZERO,
[12] = GL_ZERO,
[13] = GL_ZERO,
[14] = GL_ZERO,
[15] = GL_ZERO,
};
object_material_data* material = draw->material;
object_material_blend_flags blend_flags = material->material.blend_flags;
if ((!blend_flags.alpha_texture && !blend_flags.alpha_material) || blend_flags.punch_through)
return false;
GLenum src_blend_factor = blend_factor_table[blend_flags.src_blend_factor & 0xF];
GLenum dst_blend_factor = blend_factor_table[blend_flags.dst_blend_factor & 0xF];
if (draw->chara_color) {
light_set* set = &rctx->light_set_data[LIGHT_SET_MAIN];
light_data* chara_color = &set->lights[LIGHT_CHARA_COLOR];
vec4 specular;
light_get_specular(chara_color, &specular);
if (specular.w >= 4.0f && light_get_type(chara_color) == LIGHT_PARALLEL
&& (src_blend_factor != GL_ONE || dst_blend_factor)) {
int32_t shader_index = rctx->draw_state.shader_index;
if (rctx->draw_state.shader_index == -1) {
shader_index = material->material.shader_index;
if (shader_index == SHADER_FT_BLINN) {
if (lighting_type == OBJECT_MATERIAL_SHADER_LIGHTING_CONSTANT)
shader_index = SHADER_FT_CONSTANT;
if (lighting_type == OBJECT_MATERIAL_SHADER_LIGHTING_LAMBERT)
shader_index = SHADER_FT_LAMBERT;
}
}
switch (shader_index) {
case SHADER_FT_ITEM:
case SHADER_FT_SKIN:
case SHADER_FT_HAIR:
case SHADER_FT_CLOTH:
case SHADER_FT_TIGHTS:
case SHADER_FT_GLASEYE:
src_blend_factor = GL_SRC_ALPHA;
dst_blend_factor = GL_ONE_MINUS_SRC_ALPHA;
break;
}
}
}
gl_state_set_blend_func(src_blend_factor, dst_blend_factor);
return dst_blend_factor == GL_ONE;
}
static void draw_object_chara_color_fog_set(render_context* rctx, draw_object* draw, bool disable_fog) {
uniform_value[U_CHARA_COLOR] = 0;
if (draw->chara_color) {
light_set* set = &rctx->light_set_data[LIGHT_SET_MAIN];
light_data* chara_color = &set->lights[LIGHT_CHARA_COLOR];
vec4 specular;
light_get_specular(chara_color, &specular);
if (specular.w > 0.0f && light_get_type(chara_color) == LIGHT_PARALLEL)
uniform_value[U_CHARA_COLOR] = 1;
}
object_material_blend_flags blend_flags = draw->material->material.blend_flags;
if (!blend_flags.no_fog && !disable_fog) {
if (blend_flags.has_fog_height)
uniform_value[U_FOG_HEIGHT] = 2 + blend_flags.fog_height;
else
uniform_value[U_FOG_HEIGHT] = 1;
uniform_value[U_FOG] = rctx->draw_state.fog_height ? 2 : 1;
}
}
static void draw_object_material_reset_default(object_material_data* mat_data) {
if (mat_data) {
gl_state_enable_cull_face();
object_material_blend_flags blend_flags = mat_data->material.blend_flags;
if ((blend_flags.alpha_texture || blend_flags.alpha_material) && !blend_flags.punch_through)
gl_state_set_blend_func(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
uniform_value_reset();
}
static void draw_object_material_reset_reflect() {
gl_state_active_bind_texture_2d(0, 0);
gl_state_enable_cull_face();
uniform_value_reset();
}
static void draw_object_material_set_default(render_context* rctx, draw_object* draw, bool use_shader) {
GLuint* textures = draw->textures;
object_material_data* material = draw->material;
object_material_shader_lighting_type lighting_type =
object_material_shader_get_lighting_type(&material->material.shader_flags);
bool disable_fog = draw_object_blend_set(rctx, draw, lighting_type);
draw_object_material_set_uniform(rctx, material, false);
if (!rctx->draw_state.light)
uniform_value[U_LIGHT_0] = 0;
else if (draw->self_shadow)
uniform_value[U_LIGHT_0] = draw->self_shadow ? 1 : 1;
else
uniform_value[U_LIGHT_0] = draw->sub_mesh->flags & OBJECT_SUB_MESH_RECIEVE_SHADOW ? 1 : 0;
uniform_value[U_SHADOW] = 0;
uniform_value[U_SELF_SHADOW] = rctx->draw_state.self_shadow ? 1 : 0;
object_material_texture* mat_tex = material->material.textures;
uniform_value[U_SHADOW] = draw->shadow > SHADOW_CHARA;
for (int32_t i = 0, j = 0; i < 8; i++, mat_tex++) {
if (mat_tex->texture_id == -1)
continue;
GLuint tex_id = -1;
uint32_t texture_id = mat_tex->texture_id;
for (int32_t j = 0; j < draw->texture_pattern_count; j++)
if (draw->texture_pattern_array[j].src == texture_id) {
texture* tex = texture_storage_get_texture(draw->texture_pattern_array[j].dst);
if (tex)
tex_id = tex->texture;
break;
}
if (tex_id == -1)
tex_id = textures[mat_tex->texture_index];
if (tex_id == -1)
continue;
int32_t tex_index = object_material_texture_type_get_texture_index(mat_tex->texture_flags.type, j);
if (tex_index < 0)
continue;
object_material_texture_type tex_type = mat_tex->texture_flags.type;
if (tex_type == OBJECT_MATERIAL_TEXTURE_COLOR)
j++;
if (mat_tex->sampler_flags.flag_29) {
switch (tex_type) {
case OBJECT_MATERIAL_TEXTURE_NORMAL:
uniform_value[U_NORMAL] = 0;
break;
case OBJECT_MATERIAL_TEXTURE_SPECULAR:
uniform_value[U_SPECULAR] = 0;
break;
case OBJECT_MATERIAL_TEXTURE_TRANSLUCENCY:
uniform_value[U_TRANSLUCENCY] = 0;
break;
case OBJECT_MATERIAL_TEXTURE_TRANSPARENCY:
uniform_value[U_TRANSPARENCY] = 0;
break;
}
continue;
}
if (tex_type == OBJECT_MATERIAL_TEXTURE_ENVIRONMENT_CUBE)
gl_state_active_bind_texture_cube_map(tex_index, tex_id);
else {
gl_state_active_bind_texture_2d(tex_index, tex_id);
GLenum wrap_s = 0;
if (mat_tex->sampler_flags.mirror_u)
wrap_s = GL_MIRRORED_REPEAT;
else if (mat_tex->sampler_flags.repeat_u)
wrap_s = GL_REPEAT;
GLenum wrap_t = 0;
if (mat_tex->sampler_flags.mirror_v)
wrap_t = GL_MIRRORED_REPEAT;
else if (mat_tex->sampler_flags.repeat_v)
wrap_t = GL_REPEAT;
if (wrap_s)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s);
if (wrap_t)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t);
}
if (material->material.shader_index == SHADER_FT_SKY) {
uniform_name uni_type = U_TEX_0_TYPE;
if (tex_index == 1)
uni_type = U_TEX_1_TYPE;
texture* tex = texture_storage_get_texture(mat_tex->texture_id);
if (!tex)
uniform_value[uni_type] = 1;
else if (tex->internal_format == GL_COMPRESSED_RED_RGTC1_EXT)
uniform_value[uni_type] = 3;
else if (tex->internal_format == GL_COMPRESSED_RED_GREEN_RGTC2_EXT)
uniform_value[uni_type] = 2;
else
uniform_value[uni_type] = 1;
}
int32_t texture_blend = object_material_texture_get_blend(mat_tex);
if (tex_index == 0 || tex_index == 1)
uniform_value[U_TEXTURE_BLEND] = texture_blend;
}
if (material->material.blend_flags.double_sided) {
gl_state_disable_cull_face();
if (!material->material.blend_flags.normal_direction_light)
uniform_value[U0B] = 1;
}
vec4 ambient;
*(vec3*)&ambient = *(vec3*)&material->material.ambient;
if (rctx->draw_pass.sss_data.enable)
ambient.w = material->material.ambient.w;
else
ambient.w = 1.0f;
vec4 diffuse;
vec4 emission;
vec4u_to_vec4(material->material.diffuse, diffuse);
vec4u_to_vec4(material->material.emission, emission);
draw_object_chara_color_fog_set(rctx, draw, disable_fog);
shader_state_material_set_ambient_ptr(&shaders_ft, false, &ambient);
shader_state_material_set_diffuse_ptr(&shaders_ft, false, &diffuse);
shader_state_material_set_emission_ptr(&shaders_ft, false, &emission);
float_t line_light;
if (lighting_type == OBJECT_MATERIAL_SHADER_LIGHTING_PHONG) {
vec4 specular;
vec4u_to_vec4(material->material.specular, specular);
shader_state_material_set_specular_ptr(&shaders_ft, false, &specular);
float_t luma;
vec3_dot(*(vec3*)&specular, ((vec3) {0.30f, 0.59f, 0.11f }), luma);
if (luma >= 0.0099999998f || draw->texture_color_coeff.w >= 0.1f)
uniform_value[U_SPECULAR_IBL] = 1;
else
uniform_value[U_SPECULAR_IBL] = 0;
if (!material->material.shader_flags.fresnel)
uniform_value[U_TRANSLUCENCY] = 0;
line_light = (float_t)material->material.shader_flags.line_light * (float_t)(1.0 / 9.0);
}
else
line_light = 0.0;
if (!use_shader)
shader_set(&shaders_ft, SHADER_FT_SIMPLE);
else if (rctx->draw_state.shader_index != -1)
shader_set(&shaders_ft, rctx->draw_state.shader_index);
else if (material->material.shader_index != -1) {
if (material->material.shader_index != SHADER_FT_BLINN)
shader_set(&shaders_ft, material->material.shader_index);
else if (lighting_type == OBJECT_MATERIAL_SHADER_LIGHTING_LAMBERT)
shader_set(&shaders_ft, SHADER_FT_LAMBERT);
else if (lighting_type == OBJECT_MATERIAL_SHADER_LIGHTING_PHONG)
shader_set(&shaders_ft, SHADER_FT_BLINN);
else
shader_set(&shaders_ft, SHADER_FT_CONSTANT);
}
else
shader_set(&shaders_ft, SHADER_FT_CONSTANT);
if (lighting_type != OBJECT_MATERIAL_SHADER_LIGHTING_CONSTANT) {
float_t shininess;
if (material->material.shader_index == SHADER_FT_EYEBALL)
shininess = 10.0f;
else {
shininess = (material->material.shininess - 16.0f) * (float_t)(1.0 / 112.0);
shininess = max(shininess, 0.0f);
}
shader_state_material_set_shininess(&shaders_ft, false, shininess, 0.0f, 0.0f, 1.0f);
float_t fresnel = (float_t)material->material.shader_flags.fresnel;
if (fresnel > 9.0)
fresnel = 9.0;
else if (fresnel == 0.0f)
fresnel = rctx->draw_state.fresnel;
fresnel = (fresnel - 1.0f) * (0.12f * 0.82f);
shader_local_vert_set(&shaders_ft, 0, fresnel, 0.18f, line_light, 0.0f);
shader_local_frag_set(&shaders_ft, 9, fresnel, 0.18f, line_light, 0.0f);
shininess = max(material->material.shininess, 1.0f);
shader_local_vert_set(&shaders_ft, 1, shininess, 0.0f, 0.0f, 0.0f);
shader_local_frag_set(&shaders_ft, 3, shininess, 0.0f, 0.0f, 0.0f);
switch (material->material.shader_index) {
case SHADER_FT_SKIN: {
vec4 texture_color_coeff;
vec4 texture_color_offset;
vec4 texture_specular_coeff;
vec4 texture_specular_offset;
vec4u_to_vec4(draw->texture_color_coeff, texture_color_coeff);
vec4u_to_vec4(draw->texture_color_offset, texture_color_offset);
vec4u_to_vec4(draw->texture_specular_coeff, texture_specular_coeff);
vec4u_to_vec4(draw->texture_specular_offset, texture_specular_offset);
texture_color_coeff.w *= 0.015f;
texture_specular_coeff.w *= 0.015f;
shader_local_frag_set_ptr(&shaders_ft, 5, &texture_color_coeff);
shader_local_frag_set_ptr(&shaders_ft, 6, &texture_color_offset);
shader_local_frag_set_ptr(&shaders_ft, 7, &texture_specular_coeff);
shader_local_frag_set_ptr(&shaders_ft, 8, &texture_specular_offset);
} break;
case SHADER_FT_HAIR:
case SHADER_FT_CLOTH:
case SHADER_FT_TIGHTS:
shader_local_frag_set(&shaders_ft, 5, 1.0f - draw->texture_color_coeff.w * 0.4f,
0.0f, 0.0f, draw->texture_color_coeff.w * 0.02f);
break;
}
}
draw_object_material_set_parameter(rctx, material);
}
static void draw_object_material_set_parameter(render_context* rctx, object_material_data* mat_data) {
float_t bump_depth;
float_t intensity;
float_t reflect_uv_scale;
float_t refract_uv_scale;
float_t inv_bump_depth;
if (rctx->draw_state.use_global_material) {
bump_depth = rctx->draw_state.bump_depth;
intensity = rctx->draw_state.intensity;
reflect_uv_scale = rctx->draw_state.reflect_uv_scale;
refract_uv_scale = rctx->draw_state.refract_uv_scale;
inv_bump_depth = (1.0f - rctx->draw_state.bump_depth) * 64.0f + 1.0f;
vec4 specular;
vec4_to_vec4u(mat_data->material.specular, specular);
specular.w = rctx->draw_state.specular_alpha;
shader_state_material_set_specular_ptr(&shaders_ft, false, &specular);
}
else {
bump_depth = mat_data->material.bump_depth;
reflect_uv_scale = 0.1f;
intensity = mat_data->material.intensity;
refract_uv_scale = 0.1f;
inv_bump_depth = (1.0f - bump_depth) * 256.0f + 1.0f;
}
intensity = max(intensity, 1.0f);
shader_local_vert_set(&shaders_ft, 2, inv_bump_depth, bump_depth, 0.0f, 0.0f);
shader_local_frag_set(&shaders_ft, 0, inv_bump_depth, bump_depth, 0.0f, 0.0f);
shader_local_frag_set(&shaders_ft, 1, intensity, intensity, intensity * 25.5f, 1.0f);
shader_local_frag_set(&shaders_ft, 2,
reflect_uv_scale, reflect_uv_scale, refract_uv_scale, refract_uv_scale);
vec4 specular;
shader_env_vert_get_ptr(&shaders_ft, 17, &specular);
vec3_mult(*(vec3*)&specular, *(vec3*)&mat_data->material.specular, *(vec3*)&specular);
shader_env_vert_set_ptr(&shaders_ft, 18, &specular);
}
static void draw_object_material_set_reflect(render_context* rctx, draw_object* draw) {
object_material_data* material = draw->material;
GLuint* textures = draw->textures;
if (material->material.blend_flags.double_sided)
gl_state_disable_cull_face();
object_material_texture* mat_tex = material->material.textures;
for (int32_t i = 0; i < 1; i++, mat_tex++) {
uint32_t texture_id = mat_tex->texture_id;
if (mat_tex->texture_id == -1)
break;
GLuint tex_id = -1;
for (int32_t j = 0; j < draw->texture_pattern_count; j++)
if (draw->texture_pattern_array[j].src == texture_id) {
texture* tex = texture_storage_get_texture(draw->texture_pattern_array[j].dst);
if (tex)
tex_id = tex->texture;
break;
}
if (tex_id == -1)
tex_id = textures[mat_tex->texture_index];
if (tex_id == -1)
tex_id = 0;
gl_state_active_bind_texture_2d(i, tex_id);
GLenum wrap_s = 0;
if (mat_tex->sampler_flags.mirror_u)
wrap_s = GL_MIRRORED_REPEAT;
else if (mat_tex->sampler_flags.repeat_u)
wrap_s = GL_REPEAT;
GLenum wrap_t = 0;
if (mat_tex->sampler_flags.mirror_v)
wrap_t = GL_MIRRORED_REPEAT;
else if (mat_tex->sampler_flags.repeat_v)
wrap_t = GL_REPEAT;
if (wrap_s)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s);
if (wrap_t)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t);
}
vec4 ambient;
vec4 diffuse;
vec4 emission;
vec4 specular;
if (material->material.shader_index == -1) {
ambient = vec4_identity;
vec4u_to_vec4(material->material.diffuse, diffuse);
emission = vec4_identity;
vec4u_to_vec4(material->material.specular, specular);
}
else {
vec4u_to_vec4(material->material.ambient, ambient);
vec4u_to_vec4(material->material.diffuse, diffuse);
vec4u_to_vec4(material->material.emission, emission);
vec4u_to_vec4(material->material.specular, specular);
}
draw_object_material_set_uniform(rctx, material, true);
shader_set(&shaders_ft, rctx->draw_state.shader_index);
shader_state_material_set_ambient_ptr(&shaders_ft, false, &ambient);
shader_state_material_set_diffuse_ptr(&shaders_ft, false, &diffuse);
shader_state_material_set_emission_ptr(&shaders_ft, false, &emission);
shader_state_material_set_specular_ptr(&shaders_ft, false, &specular);
draw_object_material_set_parameter(rctx, draw->material);
}
static void draw_object_material_set_uniform(render_context* rctx, object_material_data* mat_data, bool disable_color_l) {
object_material_flags flags = mat_data->material.flags;
object_material_shader_flags shader_flags = mat_data->material.shader_flags;
if (disable_color_l) {
if (flags & OBJECT_MATERIAL_COLOR)
flags &= ~OBJECT_MATERIAL_COLOR_L1;
flags &= ~OBJECT_MATERIAL_COLOR_L2;
}
int32_t v4 = 0;
if (flags & OBJECT_MATERIAL_COLOR) {
if (~flags & OBJECT_MATERIAL_COLOR_L2)
if (flags & OBJECT_MATERIAL_COLOR_L1) {
uniform_value[U_TEXTURE_COUNT] = 2;
v4 = 3;
}
else {
uniform_value[U_TEXTURE_COUNT] = 1;
v4 = 1;
}
}
else if (flags & OBJECT_MATERIAL_COLOR_L1 && ~flags & OBJECT_MATERIAL_COLOR_L2) {
uniform_value[U_TEXTURE_COUNT] = 1;
v4 = 1;
}
else
uniform_value[U_TEXTURE_COUNT] = 0;
if (flags & OBJECT_MATERIAL_NORMAL)
uniform_value[U_NORMAL] = 1;
if (flags & OBJECT_MATERIAL_SPECULAR)
uniform_value[U_SPECULAR] = 1;
if (flags & OBJECT_MATERIAL_TRANSPARENCY) {
uniform_value[U_TRANSPARENCY] = 1;
v4 |= 2;
}
if (flags & OBJECT_MATERIAL_TRANSLUCENCY) {
uniform_value[U_TRANSLUCENCY] = 1;
v4 |= 2;
}
if (flags & OBJECT_MATERIAL_OVERRIDE_IBL)
uniform_value[U_ENV_MAP] = 1;
if ((shader_flags.aniso_direction & 0x03) != OBJECT_MATERIAL_ANISO_DIRECTION_NORMAL)
uniform_value[U_ANISO] = shader_flags.aniso_direction & 0x03;
if (v4 == 1)
uniform_value[U45] = 0;
else if (v4 == 2 || v4 == 3)
uniform_value[U45] = 1;
}
static void draw_object_vertex_attrib_reset_default(draw_object* draw) {
object_mesh* mesh = draw->mesh;
object_vertex_flags vertex_flags = mesh->vertex_flags;
if (mesh->compressed) {
draw_object_vertex_attrib_reset_default_compressed(draw);
return;
}
for (int32_t i = 0; i < 16; i++) {
if (draw->vertex_attrib_array[i])
glDisableVertexAttribArray(i);
draw->vertex_attrib_array[i] = false;
}
if (vertex_flags & OBJECT_VERTEX_BONE_DATA)
uniform_value[U_BONE_MAT] = 0;
if (draw->morph_array_buffer) {
uniform_value[U_MORPH] = 0;
uniform_value[U_MORPH_COLOR] = 0;
}
uniform_value[U_INSTANCE] = 0;
gl_state_bind_element_array_buffer(0);
shader_state_matrix_set_texture(&shaders_ft, 0, (mat4*)&mat4_identity);
shader_state_matrix_set_texture(&shaders_ft, 1, (mat4*)&mat4_identity);
gl_state_active_texture(0);
}
static void draw_object_vertex_attrib_reset_default_compressed(draw_object* draw) {
object_mesh* mesh = draw->mesh;
object_vertex_flags vertex_flags = mesh->vertex_flags;
for (int32_t i = 0; i < 16; i++) {
if (draw->vertex_attrib_array[i])
glDisableVertexAttribArray(i);
draw->vertex_attrib_array[i] = false;
}
if (vertex_flags & OBJECT_VERTEX_BONE_DATA)
uniform_value[U_BONE_MAT] = 0;
if (draw->morph_array_buffer) {
uniform_value[U_MORPH] = 0;
uniform_value[U_MORPH_COLOR] = 0;
}
uniform_value[U_INSTANCE] = 0;
gl_state_bind_element_array_buffer(0);
shader_state_matrix_set_texture(&shaders_ft, 0, (mat4*)&mat4_identity);
shader_state_matrix_set_texture(&shaders_ft, 1, (mat4*)&mat4_identity);
gl_state_active_texture(0);
}
static void draw_object_vertex_attrib_reset_reflect(draw_object* draw) {
object_mesh* mesh = draw->mesh;
object_vertex_flags vertex_flags = mesh->vertex_flags;
if (mesh->compressed) {
draw_object_vertex_attrib_reset_reflect_compressed(draw);
return;
}
for (int32_t i = 0; i < 16; i++) {
if (draw->vertex_attrib_array[i])
glDisableVertexAttribArray(i);
draw->vertex_attrib_array[i] = false;
}
if (vertex_flags & OBJECT_VERTEX_BONE_DATA)
uniform_value[U_BONE_MAT] = 0;
if (draw->morph_array_buffer) {
uniform_value[U_MORPH] = 0;
uniform_value[U_MORPH_COLOR] = 0;
}
gl_state_bind_element_array_buffer(0);
shader_state_matrix_set_texture(&shaders_ft, 0, (mat4*)&mat4_identity);
gl_state_active_texture(0);
}
inline static void draw_object_vertex_attrib_reset_reflect_compressed(draw_object* draw) {
object_mesh* mesh = draw->mesh;
object_vertex_flags vertex_flags = mesh->vertex_flags;
for (int32_t i = 0; i < 16; i++) {
if (draw->vertex_attrib_array[i])
glDisableVertexAttribArray(i);
draw->vertex_attrib_array[i] = false;
}
if (vertex_flags & OBJECT_VERTEX_BONE_DATA)
uniform_value[U_BONE_MAT] = 0;
if (draw->morph_array_buffer) {
uniform_value[U_MORPH] = 0;
uniform_value[U_MORPH_COLOR] = 0;
}
gl_state_bind_element_array_buffer(0);
shader_state_matrix_set_texture(&shaders_ft, 0, (mat4*)&mat4_identity);
gl_state_active_texture(0);
}
static void draw_object_vertex_attrib_set_default(draw_object* draw) {
object_mesh* mesh = draw->mesh;
object_sub_mesh* sub_mesh = draw->sub_mesh;
GLsizei vertex_size = (GLsizei)mesh->vertex_size;
object_vertex_flags vertex_flags = mesh->vertex_flags;
if (mesh->compressed) {
draw_object_vertex_attrib_set_default_compressed(draw);
return;
}
gl_state_bind_array_buffer(draw->array_buffer);
size_t offset = 0;
if (vertex_flags & OBJECT_VERTEX_POSITION) {
enable_vertex_attrib_array(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset);
offset += 12;
}
else
glVertexAttrib4f(0, 0.0f, 0.0f, 0.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_NORMAL) {
enable_vertex_attrib_array(2);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset);
offset += 12;
}
else
glVertexAttrib4f(2, 0.0f, 0.0f, 0.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_TANGENT) {
enable_vertex_attrib_array(6);
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset);
offset += 16;
}
else
glVertexAttrib4f(5, 0.0f, 0.0f, 0.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_BINORMAL)
offset += 12;
bool texcoord_mat_set[4] = { false };
object_material_data* material = draw->material;
for (int32_t i = 0, j = 0, l = 0; i < 4; i++) {
if (material->material.textures[i].texture_id == -1)
continue;
int32_t texcoord_index = object_material_texture_type_get_texcoord_index(
material->material.textures[i].texture_flags.type, j);
if (texcoord_index < 0)
continue;
if (material->material.textures[i].texture_flags.type == OBJECT_MATERIAL_TEXTURE_COLOR)
j++;
if (vertex_flags & (OBJECT_VERTEX_TEXCOORD0 << sub_mesh->texcoord_indices[l])) {
enable_vertex_attrib_array(8 + texcoord_index);
glVertexAttribPointer(8 + texcoord_index, 2, GL_FLOAT, GL_FALSE,
vertex_size, (void*)(offset + 8ULL * sub_mesh->texcoord_indices[l]));
}
l++;
if (texcoord_mat_set[texcoord_index])
continue;
int32_t texture_id = material->material.textures[i].texture_id;
mat4 mat;
mat4u_to_mat4(&material->material.textures[i].tex_coord_mat, &mat);
shader_state_matrix_set_texture(&shaders_ft, texcoord_index, &mat);
if (material->material.textures[i].texture_flags.type == OBJECT_MATERIAL_TEXTURE_COLOR)
for (int32_t k = 0; k < draw->texture_transform_count; k++)
if (draw->texture_transform_array[k].id == texture_id) {
mat4u_to_mat4(&draw->texture_transform_array[k].mat, &mat);
shader_state_matrix_set_texture(&shaders_ft, texcoord_index, &mat);
texcoord_mat_set[texcoord_index] = true;
break;
}
}
for (int32_t i = 0; i < 4; i++)
if (!draw->vertex_attrib_array[8 + i])
glVertexAttrib4f(8 + i, 0.0f, 0.0f, 0.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_TEXCOORD0)
offset += 8;
if (vertex_flags & OBJECT_VERTEX_TEXCOORD1)
offset += 8;
if (vertex_flags & OBJECT_VERTEX_TEXCOORD2)
offset += 8;
if (vertex_flags & OBJECT_VERTEX_TEXCOORD3)
offset += 8;
if (vertex_flags & OBJECT_VERTEX_COLOR0) {
enable_vertex_attrib_array(3);
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset);
offset += 16;
}
else
glVertexAttrib4f(3, 1.0f, 1.0f, 1.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_COLOR1)
offset += 16;
if (vertex_flags & OBJECT_VERTEX_BONE_DATA) {
uniform_value[U_BONE_MAT] = 1;
enable_vertex_attrib_array(1);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset);
offset += 16;
enable_vertex_attrib_array(15);
glVertexAttribPointer(15, 4, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset);
offset += 16;
}
else {
glVertexAttrib4f(1, 0.0f, 0.0f, 0.0f, 1.0f);
glVertexAttrib4f(15, 0.0f, 0.0f, 0.0f, 1.0f);
}
if (vertex_flags & OBJECT_VERTEX_UNKNOWN) {
enable_vertex_attrib_array(7);
glVertexAttribPointer(7, 4, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset);
offset += 16;
}
else
glVertexAttrib4f(7, 0.0f, 0.0f, 0.0f, 1.0f);
if (draw->morph_array_buffer) {
uniform_value[U_MORPH] = 1;
gl_state_bind_array_buffer(draw->morph_array_buffer);
offset = 0;
if (vertex_flags & OBJECT_VERTEX_POSITION) {
enable_vertex_attrib_array(10);
glVertexAttribPointer(10, 3, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset);
offset += 12;
}
else
glVertexAttrib4f(10, 0.0f, 0.0f, 0.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_NORMAL) {
enable_vertex_attrib_array(11);
glVertexAttribPointer(11, 3, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset);
offset += 12;
}
else
glVertexAttrib4f(11, 0.0f, 0.0f, 0.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_TANGENT) {
enable_vertex_attrib_array(12);
glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset);
offset += 16;
}
else
glVertexAttrib4f(12, 0.0f, 0.0f, 0.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_BINORMAL)
offset += 12;
if (vertex_flags & OBJECT_VERTEX_TEXCOORD0) {
enable_vertex_attrib_array(13);
glVertexAttribPointer(13, 2, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset);
offset += 8;
}
else
glVertexAttrib4f(13, 0.0f, 0.0f, 0.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_TEXCOORD1) {
enable_vertex_attrib_array(14);
glVertexAttribPointer(14, 2, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset);
offset += 8;
}
else
glVertexAttrib4f(14, 0.0f, 0.0f, 0.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_TEXCOORD2)
offset += 8;
if (vertex_flags & OBJECT_VERTEX_TEXCOORD3)
offset += 8;
if (vertex_flags & OBJECT_VERTEX_COLOR0) {
uniform_value[U_MORPH_COLOR] = 1;
enable_vertex_attrib_array(5);
glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset);
offset += 16;
}
else
glVertexAttrib4f(5, 1.0f, 1.0f, 1.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_COLOR1)
offset += 16;
if (vertex_flags & OBJECT_VERTEX_BONE_DATA)
offset += 32;
if (vertex_flags & OBJECT_VERTEX_UNKNOWN)
offset += 16;
shader_env_vert_set(&shaders_ft, 13, draw->morph_value, 1.0f - draw->morph_value, 0.0f, 0.0f);
}
gl_state_bind_array_buffer(0);
gl_state_bind_element_array_buffer(draw->element_array_buffer);
if (draw->instances_count)
uniform_value[U_INSTANCE] = 1;
}
inline static void draw_object_vertex_attrib_set_default_compressed(draw_object* draw) {
object_mesh* mesh = draw->mesh;
object_sub_mesh* sub_mesh = draw->sub_mesh;
GLsizei vertex_size = (GLsizei)mesh->vertex_size;
object_vertex_flags vertex_flags = mesh->vertex_flags;
gl_state_bind_array_buffer(draw->array_buffer);
size_t offset = 0;
if (vertex_flags & OBJECT_VERTEX_POSITION) {
enable_vertex_attrib_array(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset);
offset += 12;
}
else
glVertexAttrib4f(0, 0.0f, 0.0f, 0.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_NORMAL) {
enable_vertex_attrib_array(2);
glVertexAttribPointer(2, 3, GL_SHORT, GL_TRUE, vertex_size, (void*)offset);
offset += 8;
}
else
glVertexAttrib4f(2, 0.0f, 0.0f, 0.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_TANGENT) {
enable_vertex_attrib_array(6);
glVertexAttribPointer(6, 4, GL_SHORT, GL_TRUE, vertex_size, (void*)offset);
offset += 8;
}
else
glVertexAttrib4f(6, 0.0f, 0.0f, 0.0f, 1.0f);
bool texcoord_mat_set[4] = { false };
object_material_data* material = draw->material;
for (int32_t i = 0, j = 0, l = 0; i < 4; i++) {
if (material->material.textures[i].texture_id == -1)
continue;
int32_t texcoord_index = object_material_texture_type_get_texcoord_index(
material->material.textures[i].texture_flags.type, j);
if (texcoord_index < 0)
continue;
if (material->material.textures[i].texture_flags.type == OBJECT_MATERIAL_TEXTURE_COLOR)
j++;
if (!strcmp(mesh->name, "body_MZ"))
printf("");
if (!strcmp(mesh->name, "kao_MZ"))
printf("");
if (!strcmp(mesh->name, "MZ_ami1") && !strcmp(material->material.name, "test_YZ_frame_2s"))
printf("");
if (vertex_flags & (OBJECT_VERTEX_TEXCOORD0 << sub_mesh->texcoord_indices[l])) {
enable_vertex_attrib_array(8 + texcoord_index);
glVertexAttribPointer(8 + texcoord_index, 2, GL_HALF_FLOAT, GL_FALSE,
vertex_size, (void*)(offset + 4ULL * sub_mesh->texcoord_indices[l]));
}
l++;
if (texcoord_mat_set[texcoord_index])
continue;
int32_t texture_id = material->material.textures[i].texture_id;
mat4 mat;
mat4u_to_mat4(&material->material.textures[i].tex_coord_mat, &mat);
shader_state_matrix_set_texture(&shaders_ft, texcoord_index, &mat);
if (material->material.textures[i].texture_flags.type == OBJECT_MATERIAL_TEXTURE_COLOR)
for (int32_t k = 0; k < draw->texture_transform_count; k++)
if (draw->texture_transform_array[k].id == texture_id) {
mat4u_to_mat4(&draw->texture_transform_array[k].mat, &mat);
shader_state_matrix_set_texture(&shaders_ft, texcoord_index, &mat);
texcoord_mat_set[texcoord_index] = true;
break;
}
}
for (int32_t i = 0; i < 4; i++)
if (!draw->vertex_attrib_array[8 + i])
glVertexAttrib4f(8 + i, 0.0f, 0.0f, 0.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_TEXCOORD0)
offset += 4;
if (vertex_flags & OBJECT_VERTEX_TEXCOORD1)
offset += 4;
if (vertex_flags & OBJECT_VERTEX_TEXCOORD2)
offset += 4;
if (vertex_flags & OBJECT_VERTEX_TEXCOORD3)
offset += 4;
if (vertex_flags & OBJECT_VERTEX_COLOR0) {
enable_vertex_attrib_array(3);
glVertexAttribPointer(3, 4, GL_HALF_FLOAT, GL_FALSE, vertex_size, (void*)offset);
offset += 8;
}
else
glVertexAttrib4f(3, 1.0f, 1.0f, 1.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_BONE_DATA) {
uniform_value[U_BONE_MAT] = 1;
enable_vertex_attrib_array(1);
glVertexAttribPointer(1, 4, GL_UNSIGNED_SHORT, GL_TRUE, vertex_size, (void*)offset);
offset += 8;
enable_vertex_attrib_array(15);
glVertexAttribPointer(15, 4, GL_UNSIGNED_SHORT, GL_FALSE, vertex_size, (void*)offset);
offset += 8;
}
else {
glVertexAttrib4f(1, 0.0f, 0.0f, 0.0f, 1.0f);
glVertexAttrib4f(15, 0.0f, 0.0f, 0.0f, 1.0f);
}
if (draw->morph_array_buffer) {
uniform_value[U_MORPH] = 1;
gl_state_bind_array_buffer(draw->morph_array_buffer);
offset = 0;
if (vertex_flags & OBJECT_VERTEX_POSITION) {
enable_vertex_attrib_array(10);
glVertexAttribPointer(10, 3, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset);
offset += 12;
}
else
glVertexAttrib4f(10, 0.0f, 0.0f, 0.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_NORMAL) {
enable_vertex_attrib_array(11);
glVertexAttribPointer(11, 3, GL_SHORT, GL_TRUE, vertex_size, (void*)offset);
offset += 8;
}
else
glVertexAttrib4f(11, 0.0f, 0.0f, 0.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_TANGENT) {
enable_vertex_attrib_array(12);
glVertexAttribPointer(12, 4, GL_SHORT, GL_TRUE, vertex_size, (void*)offset);
offset += 8;
}
else
glVertexAttrib4f(12, 0.0f, 0.0f, 0.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_TEXCOORD0) {
enable_vertex_attrib_array(13);
glVertexAttribPointer(13, 2, GL_HALF_FLOAT, GL_FALSE, vertex_size, (void*)offset);
offset += 4;
}
else
glVertexAttrib4f(13, 0.0f, 0.0f, 0.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_TEXCOORD1) {
enable_vertex_attrib_array(14);
glVertexAttribPointer(14, 2, GL_HALF_FLOAT, GL_FALSE, vertex_size, (void*)offset);
offset += 4;
}
else
glVertexAttrib4f(14, 0.0f, 0.0f, 0.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_TEXCOORD2)
offset += 4;
if (vertex_flags & OBJECT_VERTEX_TEXCOORD3)
offset += 4;
if (vertex_flags & OBJECT_VERTEX_COLOR0) {
uniform_value[U_MORPH_COLOR] = 1;
enable_vertex_attrib_array(5);
glVertexAttribPointer(5, 4, GL_HALF_FLOAT, GL_FALSE, vertex_size, (void*)offset);
offset += 8;
}
else
glVertexAttrib4f(5, 1.0f, 1.0f, 1.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_BONE_DATA)
offset += 16;
shader_env_vert_set(&shaders_ft, 13, draw->morph_value, 1.0f - draw->morph_value, 0.0f, 0.0f);
}
gl_state_bind_array_buffer(0);
gl_state_bind_element_array_buffer(draw->element_array_buffer);
if (draw->instances_count)
uniform_value[U_INSTANCE] = 1;
}
static void draw_object_vertex_attrib_set_reflect(draw_object* draw) {
object_mesh* mesh = draw->mesh;
object_sub_mesh* sub_mesh = draw->sub_mesh;
GLsizei vertex_size = (GLsizei)mesh->vertex_size;
object_vertex_flags vertex_flags = mesh->vertex_flags;
if (mesh->compressed) {
draw_object_vertex_attrib_set_reflect_compressed(draw);
return;
}
gl_state_bind_array_buffer(draw->array_buffer);
size_t offset = 0;
if (vertex_flags & OBJECT_VERTEX_POSITION) {
enable_vertex_attrib_array(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset);
offset += 12;
}
else
glVertexAttrib4f(0, 0.0f, 0.0f, 0.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_NORMAL) {
enable_vertex_attrib_array(2);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset);
offset += 12;
}
else
glVertexAttrib4f(2, 0.0f, 0.0f, 0.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_TANGENT)
offset += 16;
if (vertex_flags & OBJECT_VERTEX_BINORMAL)
offset += 12;
object_material_data* material = draw->material;
if (material->material.textures[0].texture_id != -1) {
if (vertex_flags & OBJECT_VERTEX_TEXCOORD0) {
enable_vertex_attrib_array(8);
glVertexAttribPointer(8, 2, GL_FLOAT, GL_FALSE,
vertex_size, (void*)(offset + 8ULL * sub_mesh->texcoord_indices[0]));
}
else
glVertexAttrib4f(8, 0.0f, 0.0f, 0.0f, 1.0f);
int32_t texture_id = material->material.textures[0].texture_id;
mat4 mat;
mat4u_to_mat4(&material->material.textures[0].tex_coord_mat, &mat);
shader_state_matrix_set_texture(&shaders_ft, 0, &mat);
if (material->material.textures[0].texture_flags.type == OBJECT_MATERIAL_TEXTURE_COLOR)
for (int32_t j = 0; j < draw->texture_transform_count; j++)
if (draw->texture_transform_array[j].id == texture_id) {
mat4u_to_mat4(&draw->texture_transform_array[j].mat, &mat);
shader_state_matrix_set_texture(&shaders_ft, 0, &mat);
break;
}
}
for (int32_t i = 1; i < 4; i++)
glVertexAttrib4f(8 + i, 0.0f, 0.0f, 0.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_TEXCOORD0)
offset += 8;
if (vertex_flags & OBJECT_VERTEX_TEXCOORD1)
offset += 8;
if (vertex_flags & OBJECT_VERTEX_TEXCOORD2)
offset += 8;
if (vertex_flags & OBJECT_VERTEX_TEXCOORD3)
offset += 8;
if (vertex_flags & OBJECT_VERTEX_COLOR0) {
enable_vertex_attrib_array(3);
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset);
offset += 16;
}
else
glVertexAttrib4f(3, 1.0f, 1.0f, 1.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_COLOR1)
offset += 16;
if (vertex_flags & OBJECT_VERTEX_BONE_DATA) {
uniform_value[U_BONE_MAT] = 1;
enable_vertex_attrib_array(1);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset);
offset += 16;
enable_vertex_attrib_array(15);
glVertexAttribPointer(15, 4, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset);
offset += 16;
}
else {
glVertexAttrib4f(1, 0.0f, 0.0f, 0.0f, 1.0f);
glVertexAttrib4f(15, 0.0f, 0.0f, 0.0f, 1.0f);
}
if (vertex_flags & OBJECT_VERTEX_UNKNOWN)
offset += 16;
if (draw->morph_array_buffer) {
uniform_value[U_MORPH] = 1;
gl_state_bind_array_buffer(draw->morph_array_buffer);
offset = 0;
if (vertex_flags & OBJECT_VERTEX_POSITION) {
enable_vertex_attrib_array(10);
glVertexAttribPointer(10, 3, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset);
offset += 12;
}
else
glVertexAttrib4f(10, 0.0f, 0.0f, 0.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_NORMAL) {
enable_vertex_attrib_array(11);
glVertexAttribPointer(11, 3, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset);
offset += 12;
}
else
glVertexAttrib4f(11, 0.0f, 0.0f, 0.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_TANGENT) {
enable_vertex_attrib_array(12);
glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset);
offset += 16;
}
else
glVertexAttrib4f(12, 0.0f, 0.0f, 0.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_BINORMAL)
offset += 12;
if (vertex_flags & OBJECT_VERTEX_TEXCOORD0) {
enable_vertex_attrib_array(13);
glVertexAttribPointer(13, 2, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset);
offset += 8;
}
else
glVertexAttrib4f(13, 0.0f, 0.0f, 0.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_TEXCOORD1) {
enable_vertex_attrib_array(14);
glVertexAttribPointer(14, 2, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset);
offset += 8;
}
else
glVertexAttrib4f(14, 0.0f, 0.0f, 0.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_TEXCOORD2)
offset += 8;
if (vertex_flags & OBJECT_VERTEX_TEXCOORD3)
offset += 8;
if (vertex_flags & OBJECT_VERTEX_COLOR0) {
uniform_value[U_MORPH_COLOR] = 1;
enable_vertex_attrib_array(5);
glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset);
offset += 16;
}
else
glVertexAttrib4f(5, 1.0f, 1.0f, 1.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_COLOR1)
offset += 16;
if (vertex_flags & OBJECT_VERTEX_BONE_DATA)
offset += 32;
if (vertex_flags & OBJECT_VERTEX_UNKNOWN)
offset += 16;
shader_env_vert_set(&shaders_ft, 13, draw->morph_value, 1.0f - draw->morph_value, 0.0f, 0.0f);
}
gl_state_bind_array_buffer(0);
gl_state_bind_element_array_buffer(draw->element_array_buffer);
}
inline static void draw_object_vertex_attrib_set_reflect_compressed(draw_object* draw) {
object_mesh* mesh = draw->mesh;
object_sub_mesh* sub_mesh = draw->sub_mesh;
GLsizei vertex_size = (GLsizei)mesh->vertex_size;
object_vertex_flags vertex_flags = mesh->vertex_flags;
gl_state_bind_array_buffer(draw->array_buffer);
size_t offset = 0;
if (vertex_flags & OBJECT_VERTEX_POSITION) {
enable_vertex_attrib_array(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset);
offset += 12;
}
else
glVertexAttrib4f(0, 0.0f, 0.0f, 0.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_NORMAL) {
enable_vertex_attrib_array(2);
glVertexAttribPointer(2, 3, GL_SHORT, GL_TRUE, vertex_size, (void*)offset);
offset += 8;
}
else
glVertexAttrib4f(2, 0.0f, 0.0f, 0.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_TANGENT)
offset += 8;
object_material_data* material = draw->material;
if (material->material.textures[0].texture_id != -1) {
if (vertex_flags & OBJECT_VERTEX_TEXCOORD0) {
enable_vertex_attrib_array(8);
glVertexAttribPointer(8, 2, GL_HALF_FLOAT, GL_FALSE,
vertex_size, (void*)(offset + 4ULL * sub_mesh->texcoord_indices[0]));
}
else
glVertexAttrib4f(8, 0.0f, 0.0f, 0.0f, 1.0f);
int32_t texture_id = material->material.textures[0].texture_id;
mat4 mat;
mat4u_to_mat4(&material->material.textures[0].tex_coord_mat, &mat);
shader_state_matrix_set_texture(&shaders_ft, 0, &mat);
if (material->material.textures[0].texture_flags.type == OBJECT_MATERIAL_TEXTURE_COLOR)
for (int32_t j = 0; j < draw->texture_transform_count; j++)
if (draw->texture_transform_array[j].id == texture_id) {
mat4u_to_mat4(&draw->texture_transform_array[j].mat, &mat);
shader_state_matrix_set_texture(&shaders_ft, 0, &mat);
break;
}
}
for (int32_t i = 1; i < 4; i++)
glVertexAttrib4f(8 + i, 0.0f, 0.0f, 0.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_TEXCOORD0)
offset += 4;
if (vertex_flags & OBJECT_VERTEX_TEXCOORD1)
offset += 4;
if (vertex_flags & OBJECT_VERTEX_TEXCOORD2)
offset += 4;
if (vertex_flags & OBJECT_VERTEX_TEXCOORD3)
offset += 4;
if (vertex_flags & OBJECT_VERTEX_COLOR0) {
enable_vertex_attrib_array(3);
glVertexAttribPointer(3, 4, GL_HALF_FLOAT, GL_FALSE, vertex_size, (void*)offset);
offset += 8;
}
else
glVertexAttrib4f(3, 1.0f, 1.0f, 1.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_BONE_DATA) {
uniform_value[U_BONE_MAT] = 1;
enable_vertex_attrib_array(1);
glVertexAttribPointer(1, 4, GL_UNSIGNED_SHORT, GL_TRUE, vertex_size, (void*)offset);
offset += 8;
enable_vertex_attrib_array(15);
glVertexAttribPointer(15, 4, GL_UNSIGNED_SHORT, GL_FALSE, vertex_size, (void*)offset);
offset += 8;
}
else {
glVertexAttrib4f(1, 0.0f, 0.0f, 0.0f, 1.0f);
glVertexAttrib4f(15, 0.0f, 0.0f, 0.0f, 1.0f);
}
if (draw->morph_array_buffer) {
uniform_value[U_MORPH] = 1;
gl_state_bind_array_buffer(draw->morph_array_buffer);
offset = 0;
if (vertex_flags & OBJECT_VERTEX_POSITION) {
enable_vertex_attrib_array(10);
glVertexAttribPointer(10, 3, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset);
offset += 12;
}
else
glVertexAttrib4f(10, 0.0f, 0.0f, 0.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_NORMAL) {
enable_vertex_attrib_array(11);
glVertexAttribPointer(11, 3, GL_SHORT, GL_TRUE, vertex_size, (void*)offset);
offset += 8;
}
else
glVertexAttrib4f(11, 0.0f, 0.0f, 0.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_TANGENT) {
enable_vertex_attrib_array(12);
glVertexAttribPointer(12, 4, GL_SHORT, GL_TRUE, vertex_size, (void*)offset);
offset += 8;
}
else
glVertexAttrib4f(12, 0.0f, 0.0f, 0.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_TEXCOORD0) {
enable_vertex_attrib_array(13);
glVertexAttribPointer(13, 2, GL_HALF_FLOAT, GL_FALSE, vertex_size, (void*)offset);
offset += 4;
}
else
glVertexAttrib4f(13, 0.0f, 0.0f, 0.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_TEXCOORD1) {
enable_vertex_attrib_array(14);
glVertexAttribPointer(14, 2, GL_HALF_FLOAT, GL_FALSE, vertex_size, (void*)offset);
offset += 4;
}
else
glVertexAttrib4f(14, 0.0f, 0.0f, 0.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_TEXCOORD2)
offset += 4;
if (vertex_flags & OBJECT_VERTEX_TEXCOORD3)
offset += 4;
if (vertex_flags & OBJECT_VERTEX_COLOR0) {
uniform_value[U_MORPH_COLOR] = 1;
enable_vertex_attrib_array(5);
glVertexAttribPointer(5, 4, GL_HALF_FLOAT, GL_FALSE, vertex_size, (void*)offset);
offset += 8;
}
else
glVertexAttrib4f(5, 0.0f, 0.0f, 0.0f, 1.0f);
if (vertex_flags & OBJECT_VERTEX_BONE_DATA)
offset += 16;
shader_env_vert_set(&shaders_ft, 13, draw->morph_value, 1.0f - draw->morph_value, 0.0f, 0.0f);
}
gl_state_bind_array_buffer(0);
gl_state_bind_element_array_buffer(draw->element_array_buffer);
}