mirror of
https://github.com/korenkonder/ReDIVA.git
synced 2026-10-05 21:28:13 +03:00
1157 lines
46 KiB
C++
1157 lines
46 KiB
C++
/*
|
|
by korenkonder
|
|
GitHub/GitLab: korenkonder
|
|
*/
|
|
|
|
#include "draw_object.hpp"
|
|
#include "../light_param/light.hpp"
|
|
#include "../shader_ft.hpp"
|
|
#include "../static_var.hpp"
|
|
#include "../texture.hpp"
|
|
|
|
static bool draw_object_blend_set(render_data_context& rend_data_ctx,
|
|
const mdl::ObjSubMeshArgs* args, obj_material_shader_lighting_type lighting_type);
|
|
static bool draw_object_blend_set_check_use_default_blend(int32_t index);
|
|
static void draw_object_chara_color_fog_set(render_data_context& rend_data_ctx,
|
|
const mdl::ObjSubMeshArgs* args, bool disable_fog);
|
|
static void draw_object_material_reset_default(
|
|
render_data_context& rend_data_ctx, const obj_material_data* mat_data);
|
|
static void draw_object_material_reset_reflect(render_data_context& rend_data_ctx);
|
|
static void draw_object_material_set_default(render_data_context& rend_data_ctx,
|
|
const mdl::ObjSubMeshArgs* args, bool use_shader);
|
|
static void draw_object_material_set_parameter(
|
|
render_data_context& rend_data_ctx, const obj_material_data* mat_data);
|
|
static void draw_object_material_set_reflect(
|
|
render_data_context& rend_data_ctx, const mdl::ObjSubMeshArgs* args);
|
|
static void draw_object_material_set_uniform(render_data_context& rend_data_ctx,
|
|
const obj_material_data* mat_data, bool disable_color_l);
|
|
static void draw_object_vertex_attrib_reset_default(
|
|
render_data_context& rend_data_ctx, const mdl::ObjSubMeshArgs* args);
|
|
static void draw_object_vertex_attrib_reset_reflect(
|
|
render_data_context& rend_data_ctx, const mdl::ObjSubMeshArgs* args);
|
|
static void draw_object_vertex_attrib_set_default(
|
|
render_data_context& rend_data_ctx, const mdl::ObjSubMeshArgs* args);
|
|
static void draw_object_vertex_attrib_set_reflect(
|
|
render_data_context& rend_data_ctx, const mdl::ObjSubMeshArgs* args);
|
|
|
|
extern render_context* rctx_ptr;
|
|
|
|
namespace mdl {
|
|
void draw(render_data_context& rend_data_ctx, obj_primitive_type primitive_type, uint32_t count,
|
|
uint16_t start, uint16_t end, obj_index_format index_format, size_t indices) {
|
|
GLenum mesh_draw_mode[] = {
|
|
GL_ZERO, //GL_POINTS,
|
|
GL_LINES,
|
|
GL_LINE_STRIP,
|
|
GL_LINE_LOOP,
|
|
GL_TRIANGLES,
|
|
GL_TRIANGLE_STRIP,
|
|
GL_TRIANGLE_FAN,
|
|
GL_ZERO, //GL_QUADS,
|
|
GL_ZERO, //GL_QUAD_STRIP,
|
|
GL_ZERO, //GL_POLYGON,
|
|
};
|
|
|
|
GLenum mesh_indices_type[] = {
|
|
GL_ZERO,
|
|
GL_UNSIGNED_SHORT,
|
|
GL_UNSIGNED_INT,
|
|
};
|
|
|
|
rend_data_ctx.set_render_data_state();
|
|
|
|
if (primitive_type == OBJ_PRIMITIVE_TRIANGLE_STRIP && index_format == OBJ_INDEX_U16)
|
|
rend_data_ctx.state.draw_range_elements(GL_TRIANGLE_STRIP,
|
|
start, end, count, GL_UNSIGNED_SHORT, (void*)indices);
|
|
else
|
|
rend_data_ctx.state.draw_elements(mesh_draw_mode[primitive_type],
|
|
count, mesh_indices_type[index_format], (void*)indices);
|
|
|
|
draw_state_stats& stats = rctx_ptr->draw_state->rend_data[rend_data_ctx.index].stats;
|
|
stats.draw_count += count;
|
|
if (primitive_type == OBJ_PRIMITIVE_TRIANGLES)
|
|
stats.draw_triangle_count += count / 3;
|
|
else if (primitive_type == OBJ_PRIMITIVE_TRIANGLE_STRIP)
|
|
stats.draw_triangle_count += count - 2;
|
|
}
|
|
|
|
void draw_etc_obj(render_data_context& rend_data_ctx, const mdl::EtcObj* etc, const mat4* mat) {
|
|
switch (etc->type) {
|
|
case mdl::ETC_OBJ_TEAPOT:
|
|
case mdl::ETC_OBJ_GRID:
|
|
case mdl::ETC_OBJ_CUBE:
|
|
case mdl::ETC_OBJ_SPHERE:
|
|
case mdl::ETC_OBJ_PLANE:
|
|
case mdl::ETC_OBJ_CONE:
|
|
case mdl::ETC_OBJ_LINE:
|
|
case mdl::ETC_OBJ_CROSS:
|
|
case mdl::ETC_OBJ_CAPSULE: // Added
|
|
case mdl::ETC_OBJ_CYLINDER: // Added
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
if (!etc->count)
|
|
return;
|
|
|
|
GLuint vao = rctx_ptr->disp_manager->get_vertex_array(etc);
|
|
if (!vao)
|
|
return;
|
|
|
|
rend_data_ctx.set_batch_worlds(*mat);
|
|
|
|
const vec4 color = etc->color;
|
|
|
|
if (etc->constant) {
|
|
vec4 diffuse = color;
|
|
vec4 ambient = color * 0.5f;
|
|
ambient.w = color.w;
|
|
vec4 emission = etc->constant ? 1.0f : vec4(0.0f, 0.0f, 0.0f, 1.0f);
|
|
vec4 specular = { 0.0f, 0.0f, 0.0f, 1.0f };
|
|
|
|
rend_data_ctx.set_batch_material_color(diffuse, ambient, emission,
|
|
0.0f, specular, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
|
|
rend_data_ctx.set_batch_blend_color_offset_color(1.0f, 0.0f);
|
|
}
|
|
else
|
|
rend_data_ctx.set_batch_blend_color_offset_color(color, 0.0f);
|
|
|
|
rend_data_ctx.state.bind_vertex_array(vao);
|
|
//rend_data_ctx.set_shader(SHADER_FT_SIMPLE);
|
|
rend_data_ctx.set_shader(etc->constant ? SHADER_FT_CONSTANT : SHADER_FT_SIMPLE);
|
|
rend_data_ctx.set_render_data_state();
|
|
switch (etc->type) {
|
|
case mdl::ETC_OBJ_TEAPOT:
|
|
rend_data_ctx.state.draw_elements(GL_TRIANGLES, etc->count, GL_UNSIGNED_INT, 0);
|
|
break;
|
|
case mdl::ETC_OBJ_GRID:
|
|
rend_data_ctx.state.set_line_width(0.2f);
|
|
rend_data_ctx.state.draw_arrays(GL_LINES, 0, etc->count);
|
|
rend_data_ctx.state.set_line_width(2.0f);
|
|
rend_data_ctx.state.draw_arrays(GL_LINES, (GLint)etc->count, 4);
|
|
rend_data_ctx.state.set_line_width(1.0f);
|
|
break;
|
|
case mdl::ETC_OBJ_CUBE:
|
|
if (etc->data.sphere.wire)
|
|
rend_data_ctx.state.draw_elements(GL_LINES, etc->count, GL_UNSIGNED_INT, (void*)etc->offset);
|
|
else
|
|
rend_data_ctx.state.draw_elements(GL_TRIANGLES, etc->count, GL_UNSIGNED_INT, (void*)etc->offset);
|
|
break;
|
|
case mdl::ETC_OBJ_SPHERE:
|
|
if (etc->data.sphere.wire)
|
|
rend_data_ctx.state.draw_elements(GL_LINES, etc->count, GL_UNSIGNED_INT, (void*)etc->offset);
|
|
else
|
|
rend_data_ctx.state.draw_elements(GL_TRIANGLES, etc->count, GL_UNSIGNED_INT, (void*)etc->offset);
|
|
break;
|
|
case mdl::ETC_OBJ_PLANE:
|
|
rend_data_ctx.state.draw_arrays(GL_TRIANGLE_STRIP, 0, etc->count);
|
|
break;
|
|
case mdl::ETC_OBJ_CONE:
|
|
if (etc->data.cone.wire)
|
|
rend_data_ctx.state.draw_elements(GL_LINES, etc->count, GL_UNSIGNED_INT, (void*)etc->offset);
|
|
else
|
|
rend_data_ctx.state.draw_elements(GL_TRIANGLES, etc->count, GL_UNSIGNED_INT, (void*)etc->offset);
|
|
break;
|
|
case mdl::ETC_OBJ_LINE:
|
|
rend_data_ctx.state.draw_arrays(GL_LINES, 0, etc->count);
|
|
break;
|
|
case mdl::ETC_OBJ_CROSS:
|
|
rend_data_ctx.state.draw_arrays(GL_LINES, 0, etc->count);
|
|
break;
|
|
case mdl::ETC_OBJ_CAPSULE: // Added
|
|
if (etc->data.capsule.wire)
|
|
rend_data_ctx.state.draw_elements(GL_LINES, etc->count, GL_UNSIGNED_INT, (void*)etc->offset);
|
|
else
|
|
rend_data_ctx.state.draw_elements(GL_TRIANGLES, etc->count, GL_UNSIGNED_INT, (void*)etc->offset);
|
|
break;
|
|
case mdl::ETC_OBJ_CYLINDER: // Added
|
|
if (etc->data.cylinder.wire)
|
|
rend_data_ctx.state.draw_elements(GL_LINES, etc->count, GL_UNSIGNED_INT, (void*)etc->offset);
|
|
else
|
|
rend_data_ctx.state.draw_elements(GL_TRIANGLES, etc->count, GL_UNSIGNED_INT, (void*)etc->offset);
|
|
break;
|
|
}
|
|
shader::unbind(rend_data_ctx.state);
|
|
rend_data_ctx.reset_shader_flags();
|
|
|
|
rend_data_ctx.set_batch_blend_color_offset_color(1.0f, 0.0f);
|
|
}
|
|
|
|
void draw_sub_mesh(render_data_context& rend_data_ctx, const ObjSubMeshArgs* args,
|
|
const mat4* mat, void(*func)(render_data_context& rend_data_ctx,
|
|
const ObjSubMeshArgs* args, const cam_data& cam, const mat4* mat), const cam_data& cam) {
|
|
GLuint vao = rctx_ptr->disp_manager->get_vertex_array(args);
|
|
if (!vao)
|
|
return;
|
|
|
|
if (args->mats) {
|
|
rend_data_ctx.set_skinning_data(rend_data_ctx.state, args->mats, args->mat_count);
|
|
|
|
rend_data_ctx.shader_flags.arr[U_SKINNING] = 1;
|
|
rend_data_ctx.state.bind_vertex_array(vao);
|
|
rend_data_ctx.set_batch_worlds(*mat);
|
|
func(rend_data_ctx, args, cam, mat);
|
|
rend_data_ctx.shader_flags.arr[U_SKINNING] = 0;
|
|
}
|
|
else {
|
|
mat4 _mat;
|
|
if (args->mesh->attrib.m.billboard)
|
|
model_mat_face_camera_view(cam, mat, &_mat);
|
|
else if (args->mesh->attrib.m.billboard_y_axis)
|
|
model_mat_face_camera_position(cam, mat, &_mat);
|
|
else
|
|
_mat = *mat;
|
|
|
|
rend_data_ctx.shader_flags.arr[U_SKINNING] = 0;
|
|
rend_data_ctx.state.bind_vertex_array(vao);
|
|
if (func != draw_sub_mesh_default || !args->instances_count) {
|
|
rend_data_ctx.set_batch_worlds(_mat);
|
|
func(rend_data_ctx, args, cam, mat);
|
|
}
|
|
else
|
|
draw_sub_mesh_default_instanced(rend_data_ctx, args, cam, &_mat);
|
|
rend_data_ctx.shader_flags.arr[U_SKINNING] = 0;
|
|
}
|
|
}
|
|
|
|
void draw_sub_mesh_default(render_data_context& rend_data_ctx,
|
|
const ObjSubMeshArgs* args, const cam_data& cam, const mat4* mat) {
|
|
if (args->set_blend_color)
|
|
rend_data_ctx.set_batch_blend_color_offset_color(args->blend_color, 0.0f);
|
|
|
|
if (!args->func)
|
|
draw_object_vertex_attrib_set_default(rend_data_ctx, args);
|
|
|
|
draw_object_material_set_default(rend_data_ctx, args, rctx_ptr->draw_state->shader);
|
|
|
|
const obj_sub_mesh* sub_mesh = args->sub_mesh;
|
|
draw(rend_data_ctx,
|
|
sub_mesh->primitive_type,
|
|
sub_mesh->num_index,
|
|
sub_mesh->first_index,
|
|
sub_mesh->last_index,
|
|
sub_mesh->index_format,
|
|
sub_mesh->index_offset);
|
|
|
|
draw_object_material_reset_default(rend_data_ctx, args->material);
|
|
if (!args->func)
|
|
draw_object_vertex_attrib_reset_default(rend_data_ctx, args);
|
|
|
|
if (args->set_blend_color)
|
|
rend_data_ctx.set_batch_blend_color_offset_color(1.0f, 0.0f);
|
|
|
|
rctx_ptr->draw_state->rend_data[rend_data_ctx.index].stats.object_draw_count++;
|
|
}
|
|
|
|
void draw_sub_mesh_default_instanced(render_data_context& rend_data_ctx,
|
|
const ObjSubMeshArgs* args, const cam_data& cam, const mat4* mat) {
|
|
if (args->set_blend_color)
|
|
rend_data_ctx.set_batch_blend_color_offset_color(args->blend_color, 0.0f);
|
|
|
|
if (!args->func)
|
|
draw_object_vertex_attrib_set_default(rend_data_ctx, args);
|
|
|
|
draw_object_material_set_default(rend_data_ctx, args, rctx_ptr->draw_state->shader);
|
|
|
|
const obj_sub_mesh* sub_mesh = args->sub_mesh;
|
|
const mat4* instances_mat = args->instances_mat;
|
|
mat4 _mat;
|
|
for (int32_t i = args->instances_count; i >= 0; i--, instances_mat++) {
|
|
mat4_mul(instances_mat, mat, &_mat);
|
|
rend_data_ctx.set_batch_worlds(_mat);
|
|
draw(rend_data_ctx,
|
|
sub_mesh->primitive_type,
|
|
sub_mesh->num_index,
|
|
sub_mesh->first_index,
|
|
sub_mesh->last_index,
|
|
sub_mesh->index_format,
|
|
sub_mesh->index_offset);
|
|
}
|
|
|
|
draw_object_material_reset_default(rend_data_ctx, args->material);
|
|
if (!args->func)
|
|
draw_object_vertex_attrib_reset_default(rend_data_ctx, args);
|
|
|
|
if (args->set_blend_color)
|
|
rend_data_ctx.set_batch_blend_color_offset_color(1.0f, 0.0f);
|
|
|
|
rctx_ptr->draw_state->rend_data[rend_data_ctx.index].stats.object_draw_count++;
|
|
}
|
|
|
|
void draw_sub_mesh_sss(render_data_context& rend_data_ctx,
|
|
const ObjSubMeshArgs* args, const cam_data& cam, const mat4* mat) {
|
|
obj_material_attrib_member attrib = args->material->material.attrib.m;
|
|
rend_data_ctx.shader_flags.arr[U_ALPHA_TEST] = (!attrib.flag_28 && (args->blend_color.w < 1.0f
|
|
|| (attrib.alpha_texture || attrib.alpha_material) && !attrib.punch_through
|
|
|| args->sub_mesh->attrib.m.translucent)
|
|
|| attrib.punch_through) ? 1 : 0;
|
|
|
|
rend_data_ctx.shader_flags.arr[U_NPR_NORMAL] = 1;
|
|
bool chara = false;
|
|
const obj_material_data* material = args->material;
|
|
switch (material->material.shader.index) {
|
|
case SHADER_FT_CLOTH:
|
|
if (!rctx_ptr->render_manager->npr_param && material->material.color.ambient.w < 1.0f
|
|
&& material->material.shader_info.m.aniso_direction == OBJ_MATERIAL_ANISO_DIRECTION_NORMAL)
|
|
chara = true;
|
|
break;
|
|
case SHADER_FT_TIGHTS:
|
|
if (!rctx_ptr->render_manager->npr_param)
|
|
chara = true;
|
|
break;
|
|
case SHADER_FT_GLASEYE:
|
|
rend_data_ctx.shader_flags.arr[U_NPR_NORMAL] = 0;
|
|
chara = true;
|
|
break;
|
|
case SHADER_FT_SKIN:
|
|
chara = true;
|
|
break;
|
|
}
|
|
|
|
if (chara) {
|
|
rend_data_ctx.set_batch_sss_param({ 0.0f, 0.0f, 0.0f, 0.5f });
|
|
rend_data_ctx.shader_flags.arr[U_SSS_CHARA] = 1;
|
|
}
|
|
else {
|
|
const vec4& sss_param = rctx_ptr->sss_data->param;
|
|
rend_data_ctx.set_batch_sss_param({ sss_param.x, sss_param.y, sss_param.z, 0.5f });
|
|
rend_data_ctx.shader_flags.arr[U_SSS_CHARA] = 0;
|
|
}
|
|
draw_sub_mesh_default(rend_data_ctx, args, cam, mat);
|
|
}
|
|
|
|
void draw_sub_mesh_reflect(render_data_context& rend_data_ctx,
|
|
const ObjSubMeshArgs* args, const cam_data& cam, const mat4* mat) {
|
|
const obj_material_data* material = args->material;
|
|
draw_object_vertex_attrib_set_reflect(rend_data_ctx, args);
|
|
obj_material_shader_lighting_type lighting_type
|
|
= material->material.shader_info.get_lighting_type();
|
|
bool disable_fog = draw_object_blend_set(rend_data_ctx, args, lighting_type);
|
|
draw_object_chara_color_fog_set(rend_data_ctx, args, disable_fog);
|
|
draw_object_material_set_reflect(rend_data_ctx, args);
|
|
|
|
const obj_sub_mesh* sub_mesh = args->sub_mesh;
|
|
if (sub_mesh->index_format != OBJ_INDEX_U8)
|
|
draw(rend_data_ctx,
|
|
sub_mesh->primitive_type,
|
|
sub_mesh->num_index,
|
|
sub_mesh->first_index,
|
|
sub_mesh->last_index,
|
|
sub_mesh->index_format,
|
|
sub_mesh->index_offset);
|
|
|
|
draw_object_material_reset_reflect(rend_data_ctx);
|
|
draw_object_vertex_attrib_reset_reflect(rend_data_ctx, args);
|
|
rend_data_ctx.reset_shader_flags();
|
|
|
|
rctx_ptr->draw_state->rend_data[rend_data_ctx.index].stats.object_reflect_draw_count++;
|
|
}
|
|
|
|
void draw_sub_mesh_reflect_reflect_map(render_data_context& rend_data_ctx,
|
|
const ObjSubMeshArgs* args, const cam_data& cam, const mat4* mat) {
|
|
draw_object_vertex_attrib_set_reflect(rend_data_ctx, args);
|
|
draw_object_material_set_reflect(rend_data_ctx, args);
|
|
|
|
const obj_sub_mesh* sub_mesh = args->sub_mesh;
|
|
if (sub_mesh->index_format != OBJ_INDEX_U8)
|
|
draw(rend_data_ctx,
|
|
sub_mesh->primitive_type,
|
|
sub_mesh->num_index,
|
|
sub_mesh->first_index,
|
|
sub_mesh->last_index,
|
|
sub_mesh->index_format,
|
|
sub_mesh->index_offset);
|
|
|
|
draw_object_material_reset_reflect(rend_data_ctx);
|
|
draw_object_vertex_attrib_reset_reflect(rend_data_ctx, args);
|
|
|
|
rctx_ptr->draw_state->rend_data[rend_data_ctx.index].stats.object_reflect_draw_count++;
|
|
}
|
|
|
|
void draw_sub_mesh_shadow(render_data_context& rend_data_ctx,
|
|
const ObjSubMeshArgs* args, const cam_data& cam, const mat4* mat) {
|
|
obj_material_attrib_member attrib = args->material->material.attrib.m;
|
|
if (!attrib.flag_28 && (args->blend_color.w < 1.0f
|
|
|| (attrib.alpha_texture || attrib.alpha_material) && !attrib.punch_through
|
|
|| args->sub_mesh->attrib.m.translucent)
|
|
|| attrib.punch_through) {
|
|
rend_data_ctx.shader_flags.arr[U_ALPHA_TEST] = 1;
|
|
rend_data_ctx.set_batch_alpha_threshold(0.5f);
|
|
draw_sub_mesh_translucent(rend_data_ctx, args, cam, mat);
|
|
rend_data_ctx.shader_flags.arr[U_ALPHA_TEST] = 0;
|
|
rend_data_ctx.set_batch_alpha_threshold(0.0f);
|
|
}
|
|
else
|
|
draw_sub_mesh_translucent(rend_data_ctx, args, cam, mat);
|
|
}
|
|
|
|
void draw_sub_mesh_translucent(render_data_context& rend_data_ctx,
|
|
const ObjSubMeshArgs* args, const cam_data& cam, const mat4* mat) {
|
|
const obj_material_data* material = args->material;
|
|
const std::vector<GLuint>* textures = args->textures;
|
|
if (rctx_ptr->draw_state->rend_data[rend_data_ctx.index].shader_index != -1) {
|
|
rend_data_ctx.set_batch_material_color_emission(args->emission);
|
|
draw_object_material_set_uniform(rend_data_ctx, material, false);
|
|
if (material->material.attrib.m.alpha_texture)
|
|
rend_data_ctx.shader_flags.arr[U_TEXTURE_COUNT] = 0;
|
|
rend_data_ctx.set_shader(rctx_ptr->draw_state->rend_data[rend_data_ctx.index].shader_index);
|
|
}
|
|
|
|
draw_object_vertex_attrib_set_default(rend_data_ctx, args);
|
|
if (args->material->material.attrib.m.double_sided)
|
|
rend_data_ctx.state.disable_cull_face();
|
|
|
|
GLuint tex_id = -1;
|
|
int32_t tex_index = 0;
|
|
if (material->material.attrib.m.alpha_texture) {
|
|
const obj_material_texture_data* texdata = material->material.texdata;
|
|
uint32_t texture_id = -1;
|
|
if (!material->material.shader_compo.m.transparency) {
|
|
for (int32_t i = 0; i < 8; i++, texdata++)
|
|
if (texdata->shader_info.m.tex_type == OBJ_MATERIAL_TEXTURE_COLOR) {
|
|
texture_id = texdata->tex_index;
|
|
break;
|
|
}
|
|
tex_index = 0;
|
|
}
|
|
else {
|
|
for (int32_t i = 0; i < 8; i++, texdata++)
|
|
if (texdata->shader_info.m.tex_type == OBJ_MATERIAL_TEXTURE_TRANSPARENCY) {
|
|
if (texdata->attrib.m.flag_29) {
|
|
texture_id = texdata->tex_index;
|
|
}
|
|
break;
|
|
}
|
|
tex_index = 3;
|
|
}
|
|
|
|
if (texture_id != -1) {
|
|
for (int32_t j = 0; j < args->texture_pattern_count; j++)
|
|
if (args->texture_pattern_array[j].src == ::texture_id(0x00, texture_id)) {
|
|
texture* tex = texture_manager_get_texture(args->texture_pattern_array[j].dst);
|
|
if (tex)
|
|
tex_id = tex->glid;
|
|
break;
|
|
}
|
|
|
|
if (tex_id == -1)
|
|
tex_id = (*textures)[texdata->texture_index];
|
|
|
|
if (tex_id == -1)
|
|
tex_id = rctx_ptr->empty_texture_2d->glid;
|
|
|
|
rend_data_ctx.state.active_bind_texture_2d(tex_index, tex_id);
|
|
|
|
int32_t wrap_s;
|
|
if (texdata->attrib.m.mirror_u)
|
|
wrap_s = 2;
|
|
else if (texdata->attrib.m.repeat_u)
|
|
wrap_s = 1;
|
|
else
|
|
wrap_s = 0;
|
|
|
|
int32_t wrap_t;
|
|
if (texdata->attrib.m.mirror_v)
|
|
wrap_t = 2;
|
|
else if (texdata->attrib.m.repeat_v)
|
|
wrap_t = 1;
|
|
else
|
|
wrap_t = 0;
|
|
|
|
texture* tex = texture_manager_get_texture(::texture_id(0x00, texture_id));
|
|
rend_data_ctx.state.bind_sampler(tex_index, rctx_ptr->samplers[(wrap_t * 3 + wrap_s) * 2
|
|
+ (!tex || tex->max_mipmap_level > 0 ? 1 : 0)]);
|
|
}
|
|
}
|
|
|
|
const obj_sub_mesh* sub_mesh = args->sub_mesh;
|
|
if (sub_mesh->index_format != OBJ_INDEX_U8)
|
|
draw(rend_data_ctx,
|
|
sub_mesh->primitive_type,
|
|
sub_mesh->num_index,
|
|
sub_mesh->first_index,
|
|
sub_mesh->last_index,
|
|
sub_mesh->index_format,
|
|
sub_mesh->index_offset);
|
|
|
|
if (tex_id != -1)
|
|
rend_data_ctx.state.active_bind_texture_2d(tex_index, rctx_ptr->empty_texture_2d->glid);
|
|
|
|
rend_data_ctx.state.enable_cull_face();
|
|
draw_object_vertex_attrib_reset_default(rend_data_ctx, args);
|
|
|
|
if (rctx_ptr->draw_state->rend_data[rend_data_ctx.index].shader_index != -1)
|
|
rend_data_ctx.reset_shader_flags();
|
|
|
|
rctx_ptr->draw_state->rend_data[rend_data_ctx.index].stats.object_translucent_draw_count++;
|
|
}
|
|
}
|
|
|
|
inline void model_mat_face_camera_position(const cam_data& cam, const mat4* src, mat4* dst) {
|
|
mat4 mat;
|
|
mat4_invert_fast(&cam.get_view_mat(), &mat);
|
|
|
|
vec3 dir = vec3::normalize(*(vec3*)&mat.row3 - *(vec3*)&src->row3);
|
|
|
|
vec3 x_rot;
|
|
vec3 y_rot;
|
|
vec3 z_rot;
|
|
|
|
y_rot = *(vec3*)&src->row1;
|
|
x_rot = vec3::normalize(vec3::cross(y_rot, dir));
|
|
z_rot = vec3::cross(x_rot, y_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(const cam_data& cam, const mat4* src, mat4* dst) {
|
|
mat3 mat;
|
|
mat4_to_mat3(&cam.get_view_mat(), &mat);
|
|
mat3_invert(&mat, &mat);
|
|
mat4_from_mat3(&mat, dst);
|
|
mat4_mul(dst, src, dst);
|
|
}
|
|
|
|
static bool draw_object_blend_set(render_data_context& rend_data_ctx,
|
|
const mdl::ObjSubMeshArgs* args, obj_material_shader_lighting_type lighting_type) {
|
|
static const GLenum blend_factor_table[] = {
|
|
GL_ZERO,
|
|
GL_ONE,
|
|
GL_SRC_COLOR,
|
|
GL_ONE_MINUS_SRC_COLOR,
|
|
GL_SRC_ALPHA,
|
|
GL_ONE_MINUS_SRC_ALPHA,
|
|
GL_DST_ALPHA,
|
|
GL_ONE_MINUS_DST_ALPHA,
|
|
GL_DST_COLOR,
|
|
GL_ONE_MINUS_DST_COLOR,
|
|
GL_SRC_ALPHA_SATURATE,
|
|
GL_ZERO,
|
|
GL_ZERO,
|
|
GL_ZERO,
|
|
GL_ZERO,
|
|
GL_ZERO,
|
|
};
|
|
|
|
const obj_material_data* material = args->material;
|
|
obj_material_attrib_member attrib = material->material.attrib.m;
|
|
if ((!attrib.alpha_texture && !attrib.alpha_material) || attrib.punch_through)
|
|
return false;
|
|
|
|
GLenum src_blend_factor = blend_factor_table[attrib.src_blend_factor];
|
|
GLenum dst_blend_factor = blend_factor_table[attrib.dst_blend_factor];
|
|
if (args->chara_color) {
|
|
light_set* set = &rctx_ptr->light_set[LIGHT_SET_MAIN];
|
|
light_data* chara_color = &set->lights[LIGHT_CHARA_COLOR];
|
|
vec4 specular;
|
|
chara_color->get_specular(specular);
|
|
if (specular.w >= 4.0f && chara_color->get_type() == LIGHT_PARALLEL
|
|
&& (src_blend_factor != GL_ONE || dst_blend_factor)) {
|
|
int32_t shader_index = rctx_ptr->draw_state->rend_data[rend_data_ctx.index].shader_index;
|
|
if (shader_index == -1) {
|
|
shader_index = material->material.shader.index;
|
|
if (shader_index == SHADER_FT_BLINN) {
|
|
if (lighting_type == OBJ_MATERIAL_SHADER_LIGHTING_CONSTANT)
|
|
shader_index = SHADER_FT_CONSTANT;
|
|
if (lighting_type == OBJ_MATERIAL_SHADER_LIGHTING_LAMBERT)
|
|
shader_index = SHADER_FT_LAMBERT;
|
|
}
|
|
}
|
|
|
|
if (draw_object_blend_set_check_use_default_blend(shader_index)) {
|
|
src_blend_factor = GL_SRC_ALPHA;
|
|
dst_blend_factor = GL_ONE_MINUS_SRC_ALPHA;
|
|
}
|
|
}
|
|
}
|
|
rend_data_ctx.state.set_blend_func(src_blend_factor, dst_blend_factor);
|
|
return dst_blend_factor == GL_ONE;
|
|
}
|
|
|
|
static bool draw_object_blend_set_check_use_default_blend(int32_t index) {
|
|
bool use_default_blend[] = {
|
|
false, false, true, false, true, false, false, true, true, true, false, false,
|
|
false, false, false, false, false, false, false, false, false, false, false, false,
|
|
false, false, false, false, false, false, false, false, false, false, false, false,
|
|
false, false, false, false, false, false, false, false, false, false, false, false,
|
|
false, false,
|
|
};
|
|
|
|
if (index >= 0 && index < SHADER_FT_MAX)
|
|
return use_default_blend[index];
|
|
return false;
|
|
}
|
|
|
|
static void draw_object_chara_color_fog_set(render_data_context& rend_data_ctx,
|
|
const mdl::ObjSubMeshArgs* args, bool disable_fog) {
|
|
rend_data_ctx.shader_flags.arr[U_CHARA_COLOR] = 0;
|
|
if (args->chara_color) {
|
|
light_set* set = &rctx_ptr->light_set[LIGHT_SET_MAIN];
|
|
light_data* chara_color = &set->lights[LIGHT_CHARA_COLOR];
|
|
vec4 specular;
|
|
chara_color->get_specular(specular);
|
|
if (specular.w > 0.0f && chara_color->get_type() == LIGHT_PARALLEL)
|
|
rend_data_ctx.shader_flags.arr[U_CHARA_COLOR] = 1;
|
|
}
|
|
|
|
obj_material_attrib_member attrib = args->material->material.attrib.m;
|
|
if (!attrib.no_fog && !disable_fog) {
|
|
rend_data_ctx.shader_flags.arr[U_FOG_STAGE] = attrib.has_fog_height ? (attrib.fog_height ? 3 : 2) : 1;
|
|
rend_data_ctx.shader_flags.arr[U_FOG_CHARA] = rctx_ptr->draw_state->fog_height ? 2 : 1;
|
|
}
|
|
}
|
|
|
|
static void draw_object_material_reset_default(
|
|
render_data_context& rend_data_ctx, const obj_material_data* mat_data) {
|
|
if (mat_data) {
|
|
rend_data_ctx.state.enable_cull_face();
|
|
obj_material_attrib_member attrib = mat_data->material.attrib.m;
|
|
if ((attrib.alpha_texture || attrib.alpha_material) && !attrib.punch_through)
|
|
rend_data_ctx.state.set_blend_func(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
}
|
|
rend_data_ctx.reset_shader_flags();
|
|
}
|
|
|
|
static void draw_object_material_reset_reflect(render_data_context& rend_data_ctx) {
|
|
rend_data_ctx.state.active_bind_texture_2d(0, rctx_ptr->empty_texture_2d->glid);
|
|
rend_data_ctx.state.enable_cull_face();
|
|
rend_data_ctx.reset_shader_flags();
|
|
}
|
|
|
|
static void draw_object_material_set_default(render_data_context& rend_data_ctx,
|
|
const mdl::ObjSubMeshArgs* args, bool use_shader) {
|
|
const std::vector<GLuint>* textures = args->textures;
|
|
const obj_material_data* material = args->material;
|
|
obj_material_shader_lighting_type lighting_type =
|
|
material->material.shader_info.get_lighting_type();
|
|
bool disable_fog = draw_object_blend_set(rend_data_ctx, args, lighting_type);
|
|
draw_object_material_set_uniform(rend_data_ctx, material, false);
|
|
if (!rctx_ptr->draw_state->rend_data[rend_data_ctx.index].shadow)
|
|
rend_data_ctx.shader_flags.arr[U_STAGE_SHADOW] = 0;
|
|
else if (!args->self_shadow)
|
|
rend_data_ctx.shader_flags.arr[U_STAGE_SHADOW] = args->sub_mesh->attrib.m.recieve_shadow ? 1 : 0;
|
|
else if (args->self_shadow != 1)
|
|
rend_data_ctx.shader_flags.arr[U_STAGE_SHADOW] = 0;
|
|
else
|
|
rend_data_ctx.shader_flags.arr[U_STAGE_SHADOW] = 1;
|
|
|
|
rend_data_ctx.shader_flags.arr[U_CHARA_SHADOW2] = args->shadow > SHADOW_CHARA ? 1 : 0;
|
|
rend_data_ctx.shader_flags.arr[U_CHARA_SHADOW] = rctx_ptr->draw_state->rend_data[rend_data_ctx.index].self_shadow ? 1 : 0;
|
|
|
|
const obj_material_texture_data* texdata = material->material.texdata;
|
|
for (int32_t i = 0, j = 0; i < 8; i++, texdata++) {
|
|
if (texdata->tex_index == -1)
|
|
continue;
|
|
|
|
GLuint tex_id = -1;
|
|
uint32_t texture_id = texdata->tex_index;
|
|
for (int32_t j = 0; j < args->texture_pattern_count; j++)
|
|
if (args->texture_pattern_array[j].src == ::texture_id(0x00, texture_id)) {
|
|
texture* tex = texture_manager_get_texture(args->texture_pattern_array[j].dst);
|
|
if (tex)
|
|
tex_id = tex->glid;
|
|
break;
|
|
}
|
|
|
|
if (tex_id == -1)
|
|
tex_id = (*textures)[texdata->texture_index];
|
|
|
|
if (tex_id == -1)
|
|
continue;
|
|
|
|
int32_t tex_index = obj_material_texture_type_get_texture_index(texdata->shader_info.m.tex_type, j);
|
|
if (tex_index < 0)
|
|
continue;
|
|
|
|
obj_material_texture_type tex_type = texdata->shader_info.m.tex_type;
|
|
if (tex_type == OBJ_MATERIAL_TEXTURE_COLOR)
|
|
j++;
|
|
|
|
if (texdata->attrib.m.flag_29) {
|
|
switch (tex_type) {
|
|
case OBJ_MATERIAL_TEXTURE_NORMAL:
|
|
rend_data_ctx.shader_flags.arr[U_NORMAL] = 0;
|
|
break;
|
|
case OBJ_MATERIAL_TEXTURE_SPECULAR:
|
|
rend_data_ctx.shader_flags.arr[U_SPECULAR] = 0;
|
|
break;
|
|
case OBJ_MATERIAL_TEXTURE_TRANSLUCENCY:
|
|
rend_data_ctx.shader_flags.arr[U_TRANSLUCENCY] = 0;
|
|
break;
|
|
case OBJ_MATERIAL_TEXTURE_TRANSPARENCY:
|
|
rend_data_ctx.shader_flags.arr[U_TRANSPARENCY] = 0;
|
|
break;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if (tex_type == OBJ_MATERIAL_TEXTURE_ENVIRONMENT_CUBE) {
|
|
rend_data_ctx.state.active_bind_texture_cube_map(tex_index, tex_id);
|
|
rend_data_ctx.state.bind_sampler(tex_index, 0);
|
|
}
|
|
else {
|
|
rend_data_ctx.state.active_bind_texture_2d(tex_index, tex_id);
|
|
|
|
int32_t wrap_s;
|
|
if (texdata->attrib.m.mirror_u)
|
|
wrap_s = 2;
|
|
else if (texdata->attrib.m.repeat_u)
|
|
wrap_s = 1;
|
|
else
|
|
wrap_s = 0;
|
|
|
|
int32_t wrap_t;
|
|
if (texdata->attrib.m.mirror_v)
|
|
wrap_t = 2;
|
|
else if (texdata->attrib.m.repeat_v)
|
|
wrap_t = 1;
|
|
else
|
|
wrap_t = 0;
|
|
|
|
texture* tex = texture_manager_get_texture(texture_id);
|
|
rend_data_ctx.state.bind_sampler(tex_index, rctx_ptr->samplers[(wrap_t * 3 + wrap_s) * 2
|
|
+ (!tex || tex->max_mipmap_level > 0 ? 1 : 0)]);
|
|
}
|
|
|
|
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_manager_get_texture(texdata->tex_index);
|
|
if (!tex)
|
|
rend_data_ctx.shader_flags.arr[uni_type] = 1;
|
|
else if (tex->internal_format == GL_COMPRESSED_RED_RGTC1_EXT)
|
|
rend_data_ctx.shader_flags.arr[uni_type] = 3;
|
|
else if (tex->internal_format == GL_COMPRESSED_RED_GREEN_RGTC2_EXT)
|
|
rend_data_ctx.shader_flags.arr[uni_type] = 2;
|
|
else
|
|
rend_data_ctx.shader_flags.arr[uni_type] = 1;
|
|
}
|
|
|
|
if (tex_index >= 0 && tex_index <= 1)
|
|
rend_data_ctx.shader_flags.arr[U_TEXTURE_BLEND] = texdata->attrib.get_blend();
|
|
}
|
|
|
|
if (material->material.attrib.m.double_sided) {
|
|
rend_data_ctx.state.disable_cull_face();
|
|
if (!material->material.attrib.m.normal_dir_light)
|
|
rend_data_ctx.shader_flags.arr[U0B] = 1;
|
|
}
|
|
|
|
draw_object_chara_color_fog_set(rend_data_ctx, args, disable_fog);
|
|
|
|
vec4 ambient = material->material.color.ambient;
|
|
if (!rctx_ptr->sss_data->enable)
|
|
ambient.w = 1.0f;
|
|
vec4 diffuse = material->material.color.diffuse;
|
|
vec4 emission = args->emission;
|
|
vec4 specular = { 0.0f, 0.0f, 0.0f, 1.0f };
|
|
|
|
float_t line_light;
|
|
if (lighting_type == OBJ_MATERIAL_SHADER_LIGHTING_PHONG) {
|
|
specular = material->material.color.specular;
|
|
|
|
float_t luma = vec3::dot(*(vec3*)&specular, { 0.30f, 0.59f, 0.11f });
|
|
if (luma >= 0.01f || args->texture_color_coefficients.w >= 0.1f)
|
|
rend_data_ctx.shader_flags.arr[U_SPECULAR_IBL] = 1;
|
|
else
|
|
rend_data_ctx.shader_flags.arr[U_SPECULAR_IBL] = 0;
|
|
|
|
if (!material->material.shader_info.m.fresnel_type)
|
|
rend_data_ctx.shader_flags.arr[U_TRANSLUCENCY] = 0;
|
|
|
|
line_light = (float_t)material->material.shader_info.m.line_light * (float_t)(1.0 / 9.0);
|
|
}
|
|
else
|
|
line_light = 0.0f;
|
|
|
|
float_t material_shininess = 0.0f;
|
|
vec4 fresnel_coefficients;
|
|
float_t shininess = 0.0f;
|
|
vec4 texture_color_coefficients;
|
|
vec4 texture_color_offset;
|
|
vec4 texture_specular_coefficients;
|
|
vec4 texture_specular_offset;
|
|
if (lighting_type != OBJ_MATERIAL_SHADER_LIGHTING_CONSTANT) {
|
|
if (material->material.shader.index == SHADER_FT_GLASEYE)
|
|
material_shininess = 10.0f;
|
|
else {
|
|
material_shininess = (material->material.color.shininess - 16.0f) * (float_t)(1.0 / 112.0);
|
|
material_shininess = max_def(material_shininess, 0.0f);
|
|
}
|
|
|
|
float_t fresnel = (float_t)material->material.shader_info.m.fresnel_type;
|
|
if (fresnel > 9.0f)
|
|
fresnel = 9.0f;
|
|
else if (fresnel == 0.0f)
|
|
fresnel = rctx_ptr->draw_state->fresnel;
|
|
fresnel = (fresnel - 1.0f) * 0.12f * 0.82f;
|
|
|
|
fresnel_coefficients = { fresnel, 0.18f, line_light, 0.0f };
|
|
|
|
shininess = max_def(material->material.color.shininess, 1.0f);
|
|
|
|
switch (material->material.shader.index) {
|
|
case SHADER_FT_SKIN: {
|
|
texture_color_coefficients = args->texture_color_coefficients;
|
|
texture_color_offset = args->texture_color_offset;
|
|
texture_specular_coefficients = args->texture_specular_coefficients;
|
|
texture_specular_offset = args->texture_specular_offset;
|
|
|
|
texture_color_coefficients.w *= 0.015f;
|
|
texture_specular_coefficients.w *= 0.015f;
|
|
} break;
|
|
case SHADER_FT_HAIR:
|
|
case SHADER_FT_CLOTH:
|
|
case SHADER_FT_TIGHTS:
|
|
texture_color_coefficients = {
|
|
1.0f - args->texture_color_coefficients.w * 0.4f,
|
|
0.0f, 0.0f, args->texture_color_coefficients.w * 0.02f };
|
|
break;
|
|
}
|
|
}
|
|
|
|
rend_data_ctx.set_batch_material_color(diffuse, ambient, emission, material_shininess,
|
|
specular, fresnel_coefficients, texture_color_coefficients, texture_color_offset,
|
|
texture_specular_coefficients, texture_specular_offset, shininess);
|
|
|
|
if (!use_shader)
|
|
rend_data_ctx.set_shader(SHADER_FT_SIMPLE);
|
|
else if (rctx_ptr->draw_state->rend_data[rend_data_ctx.index].shader_index != -1)
|
|
rend_data_ctx.set_shader(rctx_ptr->draw_state->rend_data[rend_data_ctx.index].shader_index);
|
|
else if (material->material.shader.index != -1) {
|
|
if (material->material.shader.index != SHADER_FT_BLINN)
|
|
rend_data_ctx.set_shader(material->material.shader.index);
|
|
else if (lighting_type == OBJ_MATERIAL_SHADER_LIGHTING_LAMBERT)
|
|
rend_data_ctx.set_shader(SHADER_FT_LAMBERT);
|
|
else if (lighting_type == OBJ_MATERIAL_SHADER_LIGHTING_PHONG)
|
|
rend_data_ctx.set_shader(SHADER_FT_BLINN);
|
|
else
|
|
rend_data_ctx.set_shader(SHADER_FT_CONSTANT);
|
|
}
|
|
else
|
|
rend_data_ctx.set_shader(SHADER_FT_CONSTANT);
|
|
|
|
draw_object_material_set_parameter(rend_data_ctx, material);
|
|
}
|
|
|
|
static void draw_object_material_set_parameter(
|
|
render_data_context& rend_data_ctx, const obj_material_data* mat_data) {
|
|
vec4 specular;
|
|
float_t bump_depth;
|
|
float_t intensity;
|
|
float_t reflect_uv_scale;
|
|
float_t refract_uv_scale;
|
|
float_t inv_bump_depth;
|
|
bool has_specular;
|
|
if (rctx_ptr->draw_state->use_global_material) {
|
|
bump_depth = rctx_ptr->draw_state->global_material.bump_depth;
|
|
intensity = rctx_ptr->draw_state->global_material.intensity;
|
|
reflect_uv_scale = rctx_ptr->draw_state->global_material.reflect_uv_scale;
|
|
refract_uv_scale = rctx_ptr->draw_state->global_material.refract_uv_scale;
|
|
inv_bump_depth = (1.0f - rctx_ptr->draw_state->global_material.bump_depth) * 64.0f + 1.0f;
|
|
|
|
specular = mat_data->material.color.specular;
|
|
specular.w = rctx_ptr->draw_state->global_material.reflectivity;
|
|
has_specular = true;
|
|
}
|
|
else {
|
|
bump_depth = mat_data->material.bump_depth;
|
|
intensity = mat_data->material.color.intensity;
|
|
reflect_uv_scale = 0.1f;
|
|
refract_uv_scale = 0.1f;
|
|
inv_bump_depth = (1.0f - bump_depth) * 256.0f + 1.0f;
|
|
has_specular = false;
|
|
}
|
|
|
|
rend_data_ctx.set_batch_material_parameter(has_specular ? &specular : 0,
|
|
{ inv_bump_depth, bump_depth, 0.0f, 0.0f },
|
|
{ intensity, max_def(intensity, 1.0f), intensity * 25.5f, 1.0f },
|
|
reflect_uv_scale, refract_uv_scale);
|
|
}
|
|
|
|
static void draw_object_material_set_reflect(
|
|
render_data_context& rend_data_ctx, const mdl::ObjSubMeshArgs* args) {
|
|
const obj_material_data* material = args->material;
|
|
const std::vector<GLuint>* textures = args->textures;
|
|
if (material->material.attrib.m.double_sided)
|
|
rend_data_ctx.state.disable_cull_face();
|
|
|
|
const obj_material_texture_data* texdata = material->material.texdata;
|
|
for (int32_t i = 0; i < 1; i++, texdata++) {
|
|
uint32_t texture_id = texdata->tex_index;
|
|
if (texdata->tex_index == -1)
|
|
break;
|
|
|
|
GLuint tex_id = -1;
|
|
for (int32_t j = 0; j < args->texture_pattern_count; j++)
|
|
if (args->texture_pattern_array[j].src == ::texture_id(0x00, texture_id)) {
|
|
texture* tex = texture_manager_get_texture(args->texture_pattern_array[j].dst);
|
|
if (tex)
|
|
tex_id = tex->glid;
|
|
break;
|
|
}
|
|
|
|
if (tex_id == -1)
|
|
tex_id = (*textures)[texdata->texture_index];
|
|
|
|
if (tex_id == -1)
|
|
tex_id = rctx_ptr->empty_texture_2d->glid;
|
|
|
|
rend_data_ctx.state.active_bind_texture_2d(i, tex_id);
|
|
|
|
int32_t wrap_s;
|
|
if (texdata->attrib.m.mirror_u)
|
|
wrap_s = 2;
|
|
else if (texdata->attrib.m.repeat_u)
|
|
wrap_s = 1;
|
|
else
|
|
wrap_s = 0;
|
|
|
|
int32_t wrap_t;
|
|
if (texdata->attrib.m.mirror_v)
|
|
wrap_t = 2;
|
|
else if (texdata->attrib.m.repeat_v)
|
|
wrap_t = 1;
|
|
else
|
|
wrap_t = 0;
|
|
|
|
texture* tex = texture_manager_get_texture(texture_id);
|
|
rend_data_ctx.state.bind_sampler(i, rctx_ptr->samplers[(wrap_t * 3 + wrap_s) * 2
|
|
+ (!tex || tex->max_mipmap_level > 0 ? 1 : 0)]);
|
|
}
|
|
|
|
vec4 ambient;
|
|
vec4 diffuse;
|
|
vec4 emission;
|
|
vec4 specular;
|
|
if (material->material.shader.index == -1) {
|
|
ambient = 1.0f;
|
|
diffuse = material->material.color.diffuse;
|
|
emission = 1.0f;
|
|
specular = material->material.color.specular;
|
|
}
|
|
else {
|
|
ambient = material->material.color.ambient;
|
|
diffuse = material->material.color.diffuse;
|
|
emission = args->emission;
|
|
specular = material->material.color.specular;
|
|
}
|
|
|
|
draw_object_material_set_uniform(rend_data_ctx, material, true);
|
|
rend_data_ctx.set_shader(rctx_ptr->draw_state->rend_data[rend_data_ctx.index].shader_index);
|
|
rend_data_ctx.set_batch_material_color(diffuse, ambient, emission,
|
|
0.0f, specular, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
|
|
draw_object_material_set_parameter(rend_data_ctx, args->material);
|
|
}
|
|
|
|
static void draw_object_material_set_uniform(render_data_context& rend_data_ctx,
|
|
const obj_material_data* mat_data, bool disable_color_l) {
|
|
obj_shader_compo_member shader_compo = mat_data->material.shader_compo.m;
|
|
obj_material_shader_attrib_member shader_info = mat_data->material.shader_info.m;
|
|
|
|
if (disable_color_l) {
|
|
if (shader_compo.color)
|
|
shader_compo.color_l1 = 0;
|
|
shader_compo.color_l2 = 0;
|
|
}
|
|
|
|
int32_t v4 = 0;
|
|
if (shader_compo.color) {
|
|
if (!shader_compo.color_l2)
|
|
if (shader_compo.color_l1) {
|
|
rend_data_ctx.shader_flags.arr[U_TEXTURE_COUNT] = 2;
|
|
v4 = 3;
|
|
}
|
|
else {
|
|
rend_data_ctx.shader_flags.arr[U_TEXTURE_COUNT] = 1;
|
|
v4 = 1;
|
|
}
|
|
}
|
|
else if (shader_compo.color_l1 && !shader_compo.color_l2) {
|
|
rend_data_ctx.shader_flags.arr[U_TEXTURE_COUNT] = 1;
|
|
v4 = 1;
|
|
}
|
|
else
|
|
rend_data_ctx.shader_flags.arr[U_TEXTURE_COUNT] = 0;
|
|
|
|
if (shader_compo.normal_01)
|
|
rend_data_ctx.shader_flags.arr[U_NORMAL] = 1;
|
|
if (shader_compo.specular)
|
|
rend_data_ctx.shader_flags.arr[U_SPECULAR] = 1;
|
|
if (shader_compo.transparency) {
|
|
rend_data_ctx.shader_flags.arr[U_TRANSPARENCY] = 1;
|
|
v4 |= 2;
|
|
}
|
|
if (shader_compo.translucency) {
|
|
rend_data_ctx.shader_flags.arr[U_TRANSLUCENCY] = 1;
|
|
v4 |= 2;
|
|
}
|
|
if (shader_compo.override_ibl)
|
|
rend_data_ctx.shader_flags.arr[U_ENV_MAP] = 1;
|
|
|
|
if (shader_info.aniso_direction != OBJ_MATERIAL_ANISO_DIRECTION_NORMAL)
|
|
rend_data_ctx.shader_flags.arr[U_ANISO] = shader_info.aniso_direction;
|
|
|
|
if (v4 == 1)
|
|
rend_data_ctx.shader_flags.arr[U45] = 0;
|
|
else if (v4 == 2 || v4 == 3)
|
|
rend_data_ctx.shader_flags.arr[U45] = 1;
|
|
}
|
|
|
|
static void draw_object_vertex_attrib_reset_default(
|
|
render_data_context& rend_data_ctx, const mdl::ObjSubMeshArgs* args) {
|
|
const obj_mesh* mesh = args->mesh;
|
|
obj_vertex_format vertex_format = mesh->vertex_format;
|
|
|
|
if (vertex_format & OBJ_VERTEX_BONE_DATA)
|
|
rend_data_ctx.shader_flags.arr[U_SKINNING] = 0;
|
|
|
|
if (args->morph_vertex_buffer) {
|
|
rend_data_ctx.shader_flags.arr[U_MORPH] = 0;
|
|
rend_data_ctx.shader_flags.arr[U_MORPH_COLOR] = 0;
|
|
}
|
|
|
|
/*if (args->instances_count)
|
|
rend_data_ctx.shader_flags.arr[U_INSTANCE] = 0;*/
|
|
|
|
rend_data_ctx.state.active_texture(0);
|
|
}
|
|
|
|
static void draw_object_vertex_attrib_reset_reflect(
|
|
render_data_context& rend_data_ctx, const mdl::ObjSubMeshArgs* args) {
|
|
const obj_mesh* mesh = args->mesh;
|
|
obj_vertex_format vertex_format = mesh->vertex_format;
|
|
|
|
if (vertex_format & OBJ_VERTEX_BONE_DATA)
|
|
rend_data_ctx.shader_flags.arr[U_SKINNING] = 0;
|
|
|
|
if (args->morph_vertex_buffer) {
|
|
rend_data_ctx.shader_flags.arr[U_MORPH] = 0;
|
|
rend_data_ctx.shader_flags.arr[U_MORPH_COLOR] = 0;
|
|
}
|
|
|
|
rend_data_ctx.state.active_texture(0);
|
|
}
|
|
|
|
static void draw_object_vertex_attrib_set_default(
|
|
render_data_context& rend_data_ctx, const mdl::ObjSubMeshArgs* args) {
|
|
const obj_mesh* mesh = args->mesh;
|
|
obj_vertex_format vertex_format = mesh->vertex_format;
|
|
|
|
mat4 mats[2];
|
|
mats[0] = mat4_identity;
|
|
mats[1] = mat4_identity;
|
|
bool texcoord_mat_set[4] = { false };
|
|
const obj_material_data* material = args->material;
|
|
const obj_material_texture_data* texdata = material->material.texdata;
|
|
for (int32_t i = 0, j = 0, l = 0; i < 4; i++, texdata++) {
|
|
if (texdata->tex_index == -1)
|
|
continue;
|
|
|
|
int32_t texcoord_index = obj_material_texture_type_get_texcoord_index(
|
|
texdata->shader_info.m.tex_type, j);
|
|
if (texcoord_index < 0)
|
|
continue;
|
|
|
|
if (texdata->shader_info.m.tex_type == OBJ_MATERIAL_TEXTURE_COLOR)
|
|
j++;
|
|
|
|
l++;
|
|
|
|
if (texcoord_mat_set[texcoord_index])
|
|
continue;
|
|
|
|
uint32_t texture_id = texdata->tex_index;
|
|
|
|
mats[texcoord_index] = texdata->tex_coord_mat;
|
|
if (texdata->shader_info.m.tex_type == OBJ_MATERIAL_TEXTURE_COLOR)
|
|
for (int32_t k = 0; k < args->texture_transform_count; k++)
|
|
if (args->texture_transform_array[k].id == texture_id) {
|
|
mats[texcoord_index] = args->texture_transform_array[k].mat;
|
|
texcoord_mat_set[texcoord_index] = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
rend_data_ctx.set_batch_texcoord_transforms(mats);
|
|
|
|
if (vertex_format & OBJ_VERTEX_BONE_DATA)
|
|
rend_data_ctx.shader_flags.arr[U_SKINNING] = 1;
|
|
else
|
|
rend_data_ctx.shader_flags.arr[U_SKINNING] = 0;
|
|
|
|
if (args->morph_vertex_buffer) {
|
|
rend_data_ctx.shader_flags.arr[U_MORPH] = 1;
|
|
|
|
if (vertex_format & OBJ_VERTEX_COLOR0)
|
|
rend_data_ctx.shader_flags.arr[U_MORPH_COLOR] = 1;
|
|
else
|
|
rend_data_ctx.shader_flags.arr[U_MORPH_COLOR] = 0;
|
|
|
|
rend_data_ctx.set_batch_morph_weight(args->morph_weight);
|
|
}
|
|
else {
|
|
rend_data_ctx.shader_flags.arr[U_MORPH] = 0;
|
|
rend_data_ctx.shader_flags.arr[U_MORPH_COLOR] = 0;
|
|
}
|
|
|
|
/*if (args->instances_count)
|
|
rend_data_ctx.shader_flags.arr[U_INSTANCE] = 1;
|
|
else
|
|
rend_data_ctx.shader_flags.arr[U_INSTANCE] = 0;*/
|
|
}
|
|
|
|
static void draw_object_vertex_attrib_set_reflect(
|
|
render_data_context& rend_data_ctx, const mdl::ObjSubMeshArgs* args) {
|
|
const obj_mesh* mesh = args->mesh;
|
|
obj_vertex_format vertex_format = mesh->vertex_format;
|
|
|
|
mat4 mats[2];
|
|
mats[0] = mat4_identity;
|
|
mats[1] = mat4_identity;
|
|
const obj_material_data* material = args->material;
|
|
if (material->material.texdata[0].tex_index != -1) {
|
|
uint32_t tex_index = material->material.texdata[0].tex_index;
|
|
|
|
mats[0] = material->material.texdata[0].tex_coord_mat;
|
|
if (material->material.texdata[0].shader_info.m.tex_type == OBJ_MATERIAL_TEXTURE_COLOR)
|
|
for (int32_t j = 0; j < args->texture_transform_count; j++)
|
|
if (args->texture_transform_array[j].id == tex_index) {
|
|
mats[0] = args->texture_transform_array[j].mat;
|
|
break;
|
|
}
|
|
}
|
|
|
|
rend_data_ctx.set_batch_texcoord_transforms(mats);
|
|
|
|
if (vertex_format & OBJ_VERTEX_BONE_DATA)
|
|
rend_data_ctx.shader_flags.arr[U_SKINNING] = 1;
|
|
else
|
|
rend_data_ctx.shader_flags.arr[U_SKINNING] = 0;
|
|
|
|
if (args->morph_vertex_buffer) {
|
|
rend_data_ctx.shader_flags.arr[U_MORPH] = 1;
|
|
|
|
if (vertex_format & OBJ_VERTEX_COLOR0)
|
|
rend_data_ctx.shader_flags.arr[U_MORPH_COLOR] = 1;
|
|
else
|
|
rend_data_ctx.shader_flags.arr[U_MORPH_COLOR] = 0;
|
|
|
|
rend_data_ctx.set_batch_morph_weight(args->morph_weight);
|
|
}
|
|
else {
|
|
rend_data_ctx.shader_flags.arr[U_MORPH] = 0;
|
|
rend_data_ctx.shader_flags.arr[U_MORPH_COLOR] = 0;
|
|
}
|
|
}
|