mirror of
https://github.com/nunuhara/xsystem4.git
synced 2026-09-22 23:18:01 +03:00
Merge pull request #375 from kichikuou/bb-3d
3D fixes for Busou Shoujotai Blade Briders
This commit is contained in:
@@ -28,6 +28,7 @@
|
||||
|
||||
typedef struct cJSON cJSON;
|
||||
struct hash_table;
|
||||
struct billboard_texture;
|
||||
|
||||
enum RE_plugin_version {
|
||||
RE_REIGN_PLUGIN, // Toushin Toshi 3
|
||||
@@ -89,6 +90,7 @@ enum RE_draw_type {
|
||||
|
||||
enum RE_draw_options {
|
||||
RE_DRAW_OPTION_EDGE = 0,
|
||||
RE_DRAW_OPTION_LIGHTING = 1,
|
||||
RE_DRAW_OPTION_MAX
|
||||
};
|
||||
|
||||
@@ -179,6 +181,7 @@ struct RE_plugin {
|
||||
int mag_speed;
|
||||
float light_params[RE_NR_LIGHT_PARAMS];
|
||||
float edge_length;
|
||||
float edge_reduction_rate;
|
||||
vec3 edge_color;
|
||||
};
|
||||
|
||||
@@ -197,6 +200,7 @@ struct RE_instance {
|
||||
float pitch, roll, yaw; // in degrees
|
||||
vec3 scale;
|
||||
float alpha;
|
||||
float grayscale_rate;
|
||||
bool draw;
|
||||
bool draw_edge;
|
||||
bool draw_shadow;
|
||||
@@ -216,6 +220,10 @@ struct RE_instance {
|
||||
|
||||
// Billboards
|
||||
enum RE_draw_type draw_type;
|
||||
vec3 vertex_pos[4];
|
||||
vec2 vertex_uv[4];
|
||||
struct billboard_texture **billboard_frames;
|
||||
int nr_billboard_frames;
|
||||
|
||||
// Lights
|
||||
vec3 vec;
|
||||
@@ -259,6 +267,7 @@ bool RE_instance_load_next_motion(struct RE_instance *instance, const char *name
|
||||
bool RE_instance_free_next_motion(struct RE_instance *instance);
|
||||
bool RE_instance_set_mesh_show(struct RE_instance *instance, const char *mesh_name, bool show);
|
||||
bool RE_instance_set_vertex_pos(struct RE_instance *instance, int index, float x, float y, float z);
|
||||
bool RE_instance_set_vertex_uv(struct RE_instance *instance, int index, float u, float v);
|
||||
int RE_instance_get_bone_index(struct RE_instance *instance, const char *name);
|
||||
bool RE_instance_trans_local_pos_to_world_pos_by_bone(struct RE_instance *instance, int bone, vec3 offset, vec3 out);
|
||||
float RE_instance_calc_height(struct RE_instance *instance, float x, float z);
|
||||
|
||||
@@ -108,6 +108,7 @@ in vec3 specular_dir;
|
||||
uniform vec4 tonemap_param; // (ExposureBias, WhitePoint, A, B)
|
||||
uniform vec4 tonemap_param2; // (C, D, E, F)
|
||||
uniform bool nolighting;
|
||||
uniform float grayscale_rate;
|
||||
|
||||
vec3 hable(vec3 v)
|
||||
{
|
||||
@@ -239,6 +240,9 @@ void main() {
|
||||
#if ENGINE == SEAL_ENGINE
|
||||
if (!nolighting)
|
||||
frag_rgb = tone_map(frag_rgb);
|
||||
|
||||
if (grayscale_rate != 0.0)
|
||||
frag_rgb = mix(frag_rgb, vec3(dot(frag_rgb, vec3(0.299, 0.587, 0.114))), grayscale_rate);
|
||||
#endif
|
||||
|
||||
// Alpha mapping
|
||||
|
||||
@@ -42,6 +42,8 @@ uniform vec2 uv_scroll;
|
||||
|
||||
#endif // ENGINE == REIGN_ENGINE
|
||||
|
||||
uniform vec4 uv_tiling;
|
||||
|
||||
#if ENABLE_LIGHT_SCATTERING
|
||||
uniform int fog_type;
|
||||
uniform vec4 ls_params; // (beta_r, beta_m, g, distance)
|
||||
@@ -128,11 +130,11 @@ void main() {
|
||||
vec4 view_pos = view_transform * world_pos;
|
||||
gl_Position = proj_transform * view_pos;
|
||||
|
||||
tex_coord = vertex_uv + uv_scroll;
|
||||
tex_coord = (vertex_uv + uv_scroll) * uv_tiling.xy;
|
||||
light_tex_coord = vertex_light_uv + uv_scroll;
|
||||
color_mod = vertex_color;
|
||||
blend_weight = vertex_blend_weight;
|
||||
blend_tex_coord = vertex_blend_uv + uv_scroll;
|
||||
blend_tex_coord = (vertex_blend_uv + uv_scroll) * uv_tiling.zw;
|
||||
dist = -view_pos.z;
|
||||
shadow_frag_pos = shadow_transform * world_pos;
|
||||
|
||||
|
||||
+13
-4
@@ -70,6 +70,8 @@ struct mesh {
|
||||
struct material {
|
||||
uint32_t flags;
|
||||
bool is_transparent;
|
||||
vec2 uv_tiling;
|
||||
vec2 blend_uv_tiling;
|
||||
int nr_color_maps;
|
||||
GLuint *color_maps;
|
||||
GLuint specular_map;
|
||||
@@ -195,15 +197,20 @@ struct RE_renderer {
|
||||
GLint tonemap_param;
|
||||
GLint tonemap_param2;
|
||||
GLint nolighting;
|
||||
GLint grayscale_rate;
|
||||
GLint alpha_mode;
|
||||
GLint alpha_texture;
|
||||
GLint uv_scroll;
|
||||
GLint uv_tiling;
|
||||
GLint blend_tex;
|
||||
GLint use_blend_texture;
|
||||
|
||||
GLuint billboard_vao;
|
||||
GLuint billboard_attr_buffer;
|
||||
struct hash_table *billboard_textures; // cg_no -> struct billboard_texture*
|
||||
GLuint billboard_particle_vao;
|
||||
GLuint billboard_particle_attr_buffer;
|
||||
GLuint billboard_instance_vao;
|
||||
GLuint billboard_instance_attr_buffer;
|
||||
struct hash_table *billboard_textures_by_no; // cg_no -> struct billboard_texture*
|
||||
struct hash_table *billboard_textures_by_path; // path -> struct billboard_texture*
|
||||
|
||||
uint32_t last_frame_timestamp;
|
||||
};
|
||||
@@ -235,7 +242,8 @@ struct archive_data *RE_get_aar_entry(struct archive *aar, const char *dir, cons
|
||||
struct RE_renderer *RE_renderer_new(void);
|
||||
void RE_renderer_free(struct RE_renderer *r);
|
||||
void RE_renderer_set_viewport_size(struct RE_renderer *r, int width, int height);
|
||||
bool RE_renderer_load_billboard_texture(struct RE_renderer *r, int cg_no);
|
||||
bool RE_renderer_load_billboard_texture_by_no(struct RE_renderer *r, int cg_no);
|
||||
struct billboard_texture *RE_renderer_load_billboard_texture_by_path(struct RE_renderer *r, struct archive *aar, const char *path);
|
||||
struct height_detector *RE_renderer_create_height_detector(struct RE_renderer *r, struct model *model);
|
||||
void RE_renderer_free_height_detector(struct height_detector *hd);
|
||||
bool RE_renderer_detect_height(struct height_detector *hd, float x, float z, float *y_out);
|
||||
@@ -653,6 +661,7 @@ struct pol_material {
|
||||
char *name;
|
||||
uint32_t flags;
|
||||
char *textures[MAX_TEXTURE_TYPE];
|
||||
vec2 uv_tiling;
|
||||
};
|
||||
|
||||
struct pol_material_group {
|
||||
|
||||
+7
-1
@@ -143,9 +143,11 @@ static GLuint *load_texture_list(struct archive *aar, const char *path, const ch
|
||||
return textures;
|
||||
}
|
||||
|
||||
static bool init_material(struct material *material, const struct pol_material *m, struct amt *amt, struct archive *aar, const char *path)
|
||||
static bool init_material(struct material *material, struct pol_material *m, struct amt *amt, struct archive *aar, const char *path)
|
||||
{
|
||||
material->flags = m->flags;
|
||||
glm_vec2_copy(m->uv_tiling, material->uv_tiling);
|
||||
glm_vec2_one(material->blend_uv_tiling);
|
||||
if (!m->textures[COLOR_MAP]) {
|
||||
WARNING("No color texture");
|
||||
return false;
|
||||
@@ -575,6 +577,8 @@ struct model *model_load(struct archive *aar, const char *path)
|
||||
if (child->children[1].m.textures[COLOR_MAP]) {
|
||||
model->materials[material_offsets[i] + j].blend_texture =
|
||||
load_texture(aar, path, child->children[1].m.textures[COLOR_MAP], NULL);
|
||||
glm_vec2_copy(child->children[1].m.uv_tiling,
|
||||
model->materials[material_offsets[i] + j].blend_uv_tiling);
|
||||
}
|
||||
} else {
|
||||
init_material(&model->materials[material_offsets[i] + j],
|
||||
@@ -735,6 +739,8 @@ struct model *model_create_sphere(int r, int g, int b, int a)
|
||||
model->materials = xcalloc(1, sizeof(struct material));
|
||||
struct material *material = &model->materials[0];
|
||||
material->is_transparent = true;
|
||||
glm_vec2_one(material->uv_tiling);
|
||||
glm_vec2_one(material->blend_uv_tiling);
|
||||
material->color_maps = xmalloc(sizeof(GLuint));
|
||||
material->nr_color_maps = 1;
|
||||
glGenTextures(1, material->color_maps);
|
||||
|
||||
+8
-2
@@ -72,14 +72,20 @@ static uint32_t parse_material_attributes(const char *name)
|
||||
|
||||
static void parse_textures(struct buffer *r, int pol_version, struct pol_material *m)
|
||||
{
|
||||
glm_vec2_one(m->uv_tiling);
|
||||
int nr_textures = buffer_read_int32(r);
|
||||
for (int i = 0; i < nr_textures; i++) {
|
||||
char *filename = read_cstring(r);
|
||||
int type = buffer_read_int32(r);
|
||||
if (pol_version >= 3)
|
||||
buffer_skip(r, 8); // 2 unknown float params
|
||||
vec2 uv_tiling = { 1.0f, 1.0f };
|
||||
if (pol_version >= 3) {
|
||||
uv_tiling[0] = buffer_read_float(r);
|
||||
uv_tiling[1] = buffer_read_float(r);
|
||||
}
|
||||
if ((unsigned)type < MAX_TEXTURE_TYPE) {
|
||||
m->textures[type] = filename;
|
||||
if (type == COLOR_MAP)
|
||||
glm_vec2_copy(uv_tiling, m->uv_tiling);
|
||||
} else {
|
||||
WARNING("invalid texture type %d", type);
|
||||
free(filename);
|
||||
|
||||
+75
-13
@@ -53,6 +53,14 @@ static struct RE_instance *create_instance(struct RE_plugin *plugin)
|
||||
instance->use_mag_speed = true;
|
||||
instance->column_height = 1.0f;
|
||||
instance->column_radius = 1.0f;
|
||||
glm_vec3_copy((vec3){-1.0f, 2.0f, 0.0f}, instance->vertex_pos[0]);
|
||||
glm_vec3_copy((vec3){-1.0f, 0.0f, 0.0f}, instance->vertex_pos[1]);
|
||||
glm_vec3_copy((vec3){ 1.0f, 2.0f, 0.0f}, instance->vertex_pos[2]);
|
||||
glm_vec3_copy((vec3){ 1.0f, 0.0f, 0.0f}, instance->vertex_pos[3]);
|
||||
glm_vec2_copy((vec2){0.0f, 0.0f}, instance->vertex_uv[0]);
|
||||
glm_vec2_copy((vec2){0.0f, 1.0f}, instance->vertex_uv[1]);
|
||||
glm_vec2_copy((vec2){1.0f, 0.0f}, instance->vertex_uv[2]);
|
||||
glm_vec2_copy((vec2){1.0f, 1.0f}, instance->vertex_uv[3]);
|
||||
glm_mat4_identity(instance->local_transform);
|
||||
glm_mat3_identity(instance->normal_transform);
|
||||
return instance;
|
||||
@@ -62,7 +70,9 @@ static void free_instance(struct RE_instance *instance);
|
||||
|
||||
static void unload_instance(struct RE_instance *instance)
|
||||
{
|
||||
if (instance->motion) {
|
||||
// A billboard's motion holds frame animation state that the game can set
|
||||
// before loading the instance data, so it must survive unloads.
|
||||
if (instance->motion && instance->type != RE_ITYPE_BILLBOARD) {
|
||||
motion_free(instance->motion);
|
||||
instance->motion = NULL;
|
||||
}
|
||||
@@ -87,6 +97,12 @@ static void unload_instance(struct RE_instance *instance)
|
||||
free(instance->bone_transforms);
|
||||
instance->bone_transforms = NULL;
|
||||
}
|
||||
if (instance->billboard_frames) {
|
||||
// No need to free the textures, they are owned by the renderer.
|
||||
free(instance->billboard_frames);
|
||||
instance->billboard_frames = NULL;
|
||||
instance->nr_billboard_frames = 0;
|
||||
}
|
||||
if (instance->height_detector) {
|
||||
RE_renderer_free_height_detector(instance->height_detector);
|
||||
instance->height_detector = NULL;
|
||||
@@ -100,6 +116,8 @@ static void unload_instance(struct RE_instance *instance)
|
||||
static void free_instance(struct RE_instance *instance)
|
||||
{
|
||||
unload_instance(instance);
|
||||
if (instance->motion)
|
||||
motion_free(instance->motion);
|
||||
free(instance->light_params);
|
||||
xfree_aligned(instance);
|
||||
}
|
||||
@@ -252,6 +270,7 @@ struct RE_plugin *RE_plugin_new(enum RE_plugin_version version)
|
||||
plugin->mag_speed = 1;
|
||||
if (version == RE_TAPIR_PLUGIN)
|
||||
plugin->draw_options[RE_DRAW_OPTION_EDGE] = 1;
|
||||
plugin->draw_options[RE_DRAW_OPTION_LIGHTING] = 1;
|
||||
plugin->edge_length = 0.02f;
|
||||
plugin->fog_type = RE_FOG_NONE;
|
||||
plugin->fog_near = 1.0f;
|
||||
@@ -483,6 +502,37 @@ bool RE_instance_data_exists(struct RE_instance *instance, const char *name)
|
||||
return exists;
|
||||
}
|
||||
|
||||
// Loads the frame images of a billboard instance. They are stored in the
|
||||
// archive as "<name>\<basename>.png", "<name>\<basename>[1].png", ...
|
||||
static bool load_billboard_frames(struct RE_instance *instance, const char *name)
|
||||
{
|
||||
const char *basename = strrchr(name, '\\');
|
||||
basename = basename ? basename + 1 : name;
|
||||
char *path = xmalloc(strlen(name) + strlen(basename) + 22);
|
||||
|
||||
int capacity = 8;
|
||||
instance->billboard_frames = xcalloc(capacity, sizeof(struct billboard_texture *));
|
||||
for (int i = 0;; i++) {
|
||||
if (i == 0)
|
||||
sprintf(path, "%s\\%s.png", name, basename);
|
||||
else
|
||||
sprintf(path, "%s\\%s[%d].png", name, basename, i);
|
||||
struct billboard_texture *bt = RE_renderer_load_billboard_texture_by_path(
|
||||
instance->plugin->renderer, instance->plugin->aar, path);
|
||||
if (!bt)
|
||||
break;
|
||||
if (i == capacity) {
|
||||
instance->billboard_frames = xrealloc_array(
|
||||
instance->billboard_frames, capacity, capacity * 2, sizeof(struct billboard_texture *));
|
||||
capacity *= 2;
|
||||
}
|
||||
instance->billboard_frames[i] = bt;
|
||||
instance->nr_billboard_frames = i + 1;
|
||||
}
|
||||
free(path);
|
||||
return instance->nr_billboard_frames > 0;
|
||||
}
|
||||
|
||||
bool RE_instance_load(struct RE_instance *instance, const char *name)
|
||||
{
|
||||
if (!instance)
|
||||
@@ -539,6 +589,9 @@ bool RE_instance_load(struct RE_instance *instance, const char *name)
|
||||
}
|
||||
}
|
||||
return true;
|
||||
case RE_ITYPE_BILLBOARD:
|
||||
if (re_plugin_version >= RE_SEAL_PLUGIN)
|
||||
return load_billboard_frames(instance, name);
|
||||
case RE_ITYPE_DIRECTIONAL_LIGHT:
|
||||
if (re_plugin_version >= RE_SEAL_PLUGIN) {
|
||||
struct archive_data *dfile = archive_get_by_name(instance->plugin->aar, name);
|
||||
@@ -610,19 +663,28 @@ bool RE_instance_set_mesh_show(struct RE_instance *instance, const char *mesh_na
|
||||
return false;
|
||||
}
|
||||
|
||||
// Converts from the (top-left, top-right, bottom-left, bottom-right) order used
|
||||
// by the API to the vertex order of the billboard mesh.
|
||||
static const int billboard_vertex_index[4] = {0, 2, 1, 3};
|
||||
|
||||
bool RE_instance_set_vertex_pos(struct RE_instance *instance, int index, float x, float y, float z)
|
||||
{
|
||||
if (!instance)
|
||||
if (!instance || (unsigned)index >= 4)
|
||||
return false;
|
||||
if (instance->type != RE_ITYPE_BILLBOARD)
|
||||
ERROR("not implemented");
|
||||
// Hack: This works because SetInstanceVertexPos is only used to scale
|
||||
// billboards, and SetInstanceScale is not used for billboards.
|
||||
if (index == 1) {
|
||||
instance->scale[0] = x;
|
||||
instance->scale[1] = y / 2.0;
|
||||
}
|
||||
return false;
|
||||
glm_vec3_copy((vec3){x, y, z}, instance->vertex_pos[billboard_vertex_index[index]]);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RE_instance_set_vertex_uv(struct RE_instance *instance, int index, float u, float v)
|
||||
{
|
||||
if (!instance || (unsigned)index >= 4)
|
||||
return false;
|
||||
if (instance->type != RE_ITYPE_BILLBOARD)
|
||||
ERROR("not implemented");
|
||||
glm_vec2_copy((vec2){u, v}, instance->vertex_uv[billboard_vertex_index[index]]);
|
||||
return true;
|
||||
}
|
||||
|
||||
int RE_instance_get_bone_index(struct RE_instance *instance, const char *name)
|
||||
@@ -907,9 +969,9 @@ bool RE_motion_set_frame_range(struct motion *motion, float begin, float end)
|
||||
return false;
|
||||
motion->frame_begin = begin;
|
||||
motion->frame_end = end;
|
||||
if (motion->instance->type == RE_ITYPE_BILLBOARD) {
|
||||
if (motion->instance->type == RE_ITYPE_BILLBOARD && re_plugin_version < RE_SEAL_PLUGIN) {
|
||||
for (int i = begin; i < end; i++) {
|
||||
if (!RE_renderer_load_billboard_texture(motion->instance->plugin->renderer, i))
|
||||
if (!RE_renderer_load_billboard_texture_by_no(motion->instance->plugin->renderer, i))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -922,9 +984,9 @@ bool RE_motion_set_loop_frame_range(struct motion *motion, float begin, float en
|
||||
return false;
|
||||
motion->loop_frame_begin = begin;
|
||||
motion->loop_frame_end = end;
|
||||
if (motion->instance->type == RE_ITYPE_BILLBOARD) {
|
||||
if (motion->instance->type == RE_ITYPE_BILLBOARD && re_plugin_version < RE_SEAL_PLUGIN) {
|
||||
for (int i = begin; i < end; i++) {
|
||||
if (!RE_renderer_load_billboard_texture(motion->instance->plugin->renderer, i))
|
||||
if (!RE_renderer_load_billboard_texture_by_no(motion->instance->plugin->renderer, i))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+139
-50
@@ -166,24 +166,8 @@ static void destroy_outline_renderer(struct outline_renderer *or)
|
||||
glDeleteProgram(or->program);
|
||||
}
|
||||
|
||||
static void init_billboard_mesh(struct RE_renderer *r)
|
||||
static void init_billboard_unused_vertex_attrs(void)
|
||||
{
|
||||
static const GLfloat vertices[] = {
|
||||
// x, y, z, u, v
|
||||
-1.0, 1.0, 0.0, 0.0, 0.0,
|
||||
-1.0, -1.0, 0.0, 0.0, 1.0,
|
||||
1.0, 1.0, 0.0, 1.0, 0.0,
|
||||
1.0, -1.0, 0.0, 1.0, 1.0,
|
||||
};
|
||||
glGenVertexArrays(1, &r->billboard_vao);
|
||||
glBindVertexArray(r->billboard_vao);
|
||||
glGenBuffers(1, &r->billboard_attr_buffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, r->billboard_attr_buffer);
|
||||
|
||||
glEnableVertexAttribArray(VATTR_POS);
|
||||
glVertexAttribPointer(VATTR_POS, 3, GL_FLOAT, GL_FALSE, 20, (const void *)0);
|
||||
glEnableVertexAttribArray(VATTR_UV);
|
||||
glVertexAttribPointer(VATTR_UV, 2, GL_FLOAT, GL_FALSE, 20, (const void *)12);
|
||||
glDisableVertexAttribArray(VATTR_LIGHT_UV);
|
||||
glVertexAttrib2f(VATTR_LIGHT_UV, 0.0, 0.0);
|
||||
glDisableVertexAttribArray(VATTR_COLOR);
|
||||
@@ -196,8 +180,39 @@ static void init_billboard_mesh(struct RE_renderer *r)
|
||||
glVertexAttribI4i(VATTR_BONE_INDEX, 0, 0, 0, 0);
|
||||
glDisableVertexAttribArray(VATTR_BONE_WEIGHT);
|
||||
glVertexAttrib4f(VATTR_BONE_WEIGHT, 0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
static void init_billboard_mesh(struct RE_renderer *r)
|
||||
{
|
||||
static const GLfloat vertices[] = {
|
||||
// x, y, z, u, v
|
||||
-1.0, 1.0, 0.0, 0.0, 0.0,
|
||||
-1.0, -1.0, 0.0, 0.0, 1.0,
|
||||
1.0, 1.0, 0.0, 1.0, 0.0,
|
||||
1.0, -1.0, 0.0, 1.0, 1.0,
|
||||
};
|
||||
glGenBuffers(1, &r->billboard_particle_attr_buffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, r->billboard_particle_attr_buffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||
glGenBuffers(1, &r->billboard_instance_attr_buffer);
|
||||
|
||||
glGenVertexArrays(1, &r->billboard_particle_vao);
|
||||
glBindVertexArray(r->billboard_particle_vao);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, r->billboard_particle_attr_buffer);
|
||||
glEnableVertexAttribArray(VATTR_POS);
|
||||
glVertexAttribPointer(VATTR_POS, 3, GL_FLOAT, GL_FALSE, 20, (const void *)0);
|
||||
glEnableVertexAttribArray(VATTR_UV);
|
||||
glVertexAttribPointer(VATTR_UV, 2, GL_FLOAT, GL_FALSE, 20, (const void *)12);
|
||||
init_billboard_unused_vertex_attrs();
|
||||
|
||||
glGenVertexArrays(1, &r->billboard_instance_vao);
|
||||
glBindVertexArray(r->billboard_instance_vao);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, r->billboard_instance_attr_buffer);
|
||||
glEnableVertexAttribArray(VATTR_POS);
|
||||
glVertexAttribPointer(VATTR_POS, 3, GL_FLOAT, GL_FALSE, 20, (const void *)0);
|
||||
glEnableVertexAttribArray(VATTR_UV);
|
||||
glVertexAttribPointer(VATTR_UV, 2, GL_FLOAT, GL_FALSE, 20, (const void *)12);
|
||||
init_billboard_unused_vertex_attrs();
|
||||
|
||||
glBindVertexArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
@@ -205,8 +220,10 @@ static void init_billboard_mesh(struct RE_renderer *r)
|
||||
|
||||
static void destroy_billboard_mesh(struct RE_renderer *r)
|
||||
{
|
||||
glDeleteVertexArrays(1, &r->billboard_vao);
|
||||
glDeleteBuffers(1, &r->billboard_attr_buffer);
|
||||
glDeleteVertexArrays(1, &r->billboard_particle_vao);
|
||||
glDeleteVertexArrays(1, &r->billboard_instance_vao);
|
||||
glDeleteBuffers(1, &r->billboard_particle_attr_buffer);
|
||||
glDeleteBuffers(1, &r->billboard_instance_attr_buffer);
|
||||
}
|
||||
|
||||
struct RE_renderer *RE_renderer_new(void)
|
||||
@@ -266,9 +283,11 @@ struct RE_renderer *RE_renderer_new(void)
|
||||
r->tonemap_param = glGetUniformLocation(r->program, "tonemap_param");
|
||||
r->tonemap_param2 = glGetUniformLocation(r->program, "tonemap_param2");
|
||||
r->nolighting = glGetUniformLocation(r->program, "nolighting");
|
||||
r->grayscale_rate = glGetUniformLocation(r->program, "grayscale_rate");
|
||||
r->alpha_mode = glGetUniformLocation(r->program, "alpha_mode");
|
||||
r->alpha_texture = glGetUniformLocation(r->program, "alpha_texture");
|
||||
r->uv_scroll = glGetUniformLocation(r->program, "uv_scroll");
|
||||
r->uv_tiling = glGetUniformLocation(r->program, "uv_tiling");
|
||||
r->blend_tex = glGetUniformLocation(r->program, "blend_tex");
|
||||
r->use_blend_texture = glGetUniformLocation(r->program, "use_blend_texture");
|
||||
|
||||
@@ -277,7 +296,8 @@ struct RE_renderer *RE_renderer_new(void)
|
||||
init_shadow_renderer(&r->shadow);
|
||||
init_outline_renderer(&r->outline);
|
||||
init_billboard_mesh(r);
|
||||
r->billboard_textures = ht_create(256);
|
||||
r->billboard_textures_by_no = ht_create(256);
|
||||
r->billboard_textures_by_path = ht_create(256);
|
||||
r->last_frame_timestamp = SDL_GetTicks();
|
||||
return r;
|
||||
}
|
||||
@@ -291,15 +311,8 @@ void RE_renderer_set_viewport_size(struct RE_renderer *r, int width, int height)
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
}
|
||||
|
||||
bool RE_renderer_load_billboard_texture(struct RE_renderer *r, int cg_no)
|
||||
static struct billboard_texture *create_billboard_texture(struct cg *cg)
|
||||
{
|
||||
if (ht_get_int(r->billboard_textures, cg_no, NULL))
|
||||
return true;
|
||||
|
||||
struct cg *cg = asset_cg_load(cg_no);
|
||||
if (!cg)
|
||||
return false;
|
||||
|
||||
struct billboard_texture *bt = xcalloc(1, sizeof(struct billboard_texture));
|
||||
glGenTextures(1, &bt->texture);
|
||||
glBindTexture(GL_TEXTURE_2D, bt->texture);
|
||||
@@ -311,12 +324,45 @@ bool RE_renderer_load_billboard_texture(struct RE_renderer *r, int cg_no)
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
bt->has_alpha = cg->metrics.has_alpha;
|
||||
return bt;
|
||||
}
|
||||
|
||||
bool RE_renderer_load_billboard_texture_by_no(struct RE_renderer *r, int cg_no)
|
||||
{
|
||||
if (ht_get_int(r->billboard_textures_by_no, cg_no, NULL))
|
||||
return true;
|
||||
|
||||
struct cg *cg = asset_cg_load(cg_no);
|
||||
if (!cg)
|
||||
return false;
|
||||
|
||||
ht_put_int(r->billboard_textures_by_no, cg_no, create_billboard_texture(cg));
|
||||
cg_free(cg);
|
||||
ht_put_int(r->billboard_textures, cg_no, bt);
|
||||
return true;
|
||||
}
|
||||
|
||||
struct billboard_texture *RE_renderer_load_billboard_texture_by_path(struct RE_renderer *r, struct archive *aar, const char *path)
|
||||
{
|
||||
struct billboard_texture *bt = ht_get(r->billboard_textures_by_path, path, NULL);
|
||||
if (bt)
|
||||
return bt;
|
||||
|
||||
struct archive_data *dfile = archive_get_by_name(aar, path);
|
||||
if (!dfile)
|
||||
return NULL;
|
||||
struct cg *cg = cg_load_data(dfile);
|
||||
archive_free_data(dfile);
|
||||
if (!cg) {
|
||||
WARNING("cg_load_data failed: %s", path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bt = create_billboard_texture(cg);
|
||||
cg_free(cg);
|
||||
ht_put(r->billboard_textures_by_path, path, bt);
|
||||
return bt;
|
||||
}
|
||||
|
||||
static void free_billboard_texture(void *value)
|
||||
{
|
||||
struct billboard_texture *bt = value;
|
||||
@@ -328,8 +374,10 @@ void RE_renderer_free(struct RE_renderer *r)
|
||||
{
|
||||
glDeleteProgram(r->program);
|
||||
glDeleteRenderbuffers(1, &r->depth_buffer);
|
||||
ht_foreach_value(r->billboard_textures, free_billboard_texture);
|
||||
ht_free_int(r->billboard_textures);
|
||||
ht_foreach_value(r->billboard_textures_by_no, free_billboard_texture);
|
||||
ht_free_int(r->billboard_textures_by_no);
|
||||
ht_foreach_value(r->billboard_textures_by_path, free_billboard_texture);
|
||||
ht_free(r->billboard_textures_by_path);
|
||||
destroy_billboard_mesh(r);
|
||||
destroy_shadow_renderer(&r->shadow);
|
||||
destroy_outline_renderer(&r->outline);
|
||||
@@ -371,6 +419,16 @@ static bool should_draw_shadow(struct mesh *mesh, struct material *material)
|
||||
&& !(material->flags & (MATERIAL_ALPHA | MATERIAL_SPRITE));
|
||||
}
|
||||
|
||||
static bool lighting_disabled(struct RE_plugin *plugin)
|
||||
{
|
||||
return plugin->draw_options[RE_DRAW_OPTION_LIGHTING] <= 0;
|
||||
}
|
||||
|
||||
static bool is_nolighting(struct RE_plugin *plugin, struct mesh *mesh)
|
||||
{
|
||||
return lighting_disabled(plugin) || (mesh->flags & MESH_NOLIGHTING);
|
||||
}
|
||||
|
||||
static void render_model(struct RE_instance *inst, struct RE_renderer *r, enum draw_phase phase)
|
||||
{
|
||||
struct model *model = inst->model;
|
||||
@@ -431,16 +489,17 @@ static void render_model(struct RE_instance *inst, struct RE_renderer *r, enum d
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
|
||||
}
|
||||
|
||||
bool nolighting = is_nolighting(inst->plugin, mesh);
|
||||
int fog_type = inst->plugin->fog_type;
|
||||
if (!inst->plugin->fog_mode || (re_plugin_version == RE_REIGN_PLUGIN && (mesh->flags & MESH_NOLIGHTING))) {
|
||||
if (!inst->plugin->fog_mode || (re_plugin_version == RE_REIGN_PLUGIN && nolighting)) {
|
||||
fog_type = RE_FOG_NONE;
|
||||
}
|
||||
glUniform1i(r->fog_type, fog_type);
|
||||
glUniform1i(r->nolighting, !!(mesh->flags & MESH_NOLIGHTING));
|
||||
glUniform1i(r->nolighting, nolighting);
|
||||
|
||||
GLboolean use_specular_map = GL_FALSE;
|
||||
float shininess = (mesh->flags & MESH_HAS_SPECULAR_POWER) ? mesh->specular_power : material->specular_shininess;
|
||||
if (inst->plugin->specular_mode && !(mesh->flags & MESH_NOLIGHTING) && shininess > 0.0f) {
|
||||
if (inst->plugin->specular_mode && !nolighting && shininess > 0.0f) {
|
||||
if (mesh->flags & MESH_HAS_SPECULAR_COLOR) {
|
||||
glUniform3fv(r->specular_color, 1, mesh->specular_color);
|
||||
} else {
|
||||
@@ -475,7 +534,7 @@ static void render_model(struct RE_instance *inst, struct RE_renderer *r, enum d
|
||||
|
||||
if (mesh->flags & MESH_ENVMAP) {
|
||||
glUniform1i(r->diffuse_type, DIFFUSE_ENV_MAP);
|
||||
} else if (mesh->flags & MESH_NOLIGHTING) {
|
||||
} else if (nolighting) {
|
||||
glUniform1i(r->diffuse_type, DIFFUSE_EMISSIVE);
|
||||
} else if (material->light_map && mesh->flags & MESH_HAS_LIGHT_UV && inst->plugin->light_map_mode) {
|
||||
glUniform1i(r->diffuse_type, DIFFUSE_LIGHT_MAP);
|
||||
@@ -516,6 +575,9 @@ static void render_model(struct RE_instance *inst, struct RE_renderer *r, enum d
|
||||
vec2 uv_scroll;
|
||||
glm_vec2_scale(mesh->uv_scroll, r->last_frame_timestamp / 1000.f, uv_scroll);
|
||||
glUniform2fv(r->uv_scroll, 1, uv_scroll);
|
||||
glUniform4f(r->uv_tiling,
|
||||
material->uv_tiling[0], material->uv_tiling[1],
|
||||
material->blend_uv_tiling[0], material->blend_uv_tiling[1]);
|
||||
|
||||
glBindVertexArray(mesh->vao);
|
||||
|
||||
@@ -566,11 +628,13 @@ static void render_skinned_model(struct RE_instance *inst, struct RE_renderer *r
|
||||
render_static_model(inst->shadow_volume_instance, r, phase);
|
||||
}
|
||||
|
||||
static void reset_draw_uniforms(struct RE_renderer *r)
|
||||
static void reset_draw_uniforms(struct RE_renderer *r, struct RE_plugin *plugin)
|
||||
{
|
||||
bool nolighting = lighting_disabled(plugin);
|
||||
glUniform1f(r->alpha_mod, 1.0f);
|
||||
glUniform3f(r->diffuse_mod, 1.0f, 1.0f, 1.0f);
|
||||
glUniform2f(r->uv_scroll, 0.0f, 0.0f);
|
||||
glUniform4f(r->uv_tiling, 1.0f, 1.0f, 1.0f, 1.0f);
|
||||
glUniform1i(r->has_bones, GL_FALSE);
|
||||
glUniform3f(r->specular_color, 0.0f, 0.0f, 0.0f);
|
||||
glUniform1f(r->specular_shininess, 0.0f);
|
||||
@@ -582,15 +646,23 @@ static void reset_draw_uniforms(struct RE_renderer *r)
|
||||
glUniform1f(r->shadow_darkness, 0.0f);
|
||||
glUniform1i(r->alpha_mode, ALPHA_BLEND);
|
||||
glUniform1i(r->fog_type, 0);
|
||||
glUniform1i(r->diffuse_type, DIFFUSE_NORMAL);
|
||||
glUniform1i(r->nolighting, nolighting);
|
||||
glUniform1i(r->diffuse_type, nolighting ? DIFFUSE_EMISSIVE : DIFFUSE_NORMAL);
|
||||
}
|
||||
|
||||
static void render_billboard(struct RE_instance *inst, struct RE_renderer *r, mat4 view_mat, enum draw_phase phase)
|
||||
{
|
||||
if (!inst->draw)
|
||||
return;
|
||||
int cg_no = inst->motion->current_frame;
|
||||
struct billboard_texture *bt = ht_get_int(r->billboard_textures, cg_no, NULL);
|
||||
int frame = inst->motion->current_frame;
|
||||
struct billboard_texture *bt;
|
||||
if (inst->nr_billboard_frames > 0) {
|
||||
if (frame < 0 || frame >= inst->nr_billboard_frames)
|
||||
return;
|
||||
bt = inst->billboard_frames[frame];
|
||||
} else {
|
||||
bt = ht_get_int(r->billboard_textures_by_no, frame, NULL);
|
||||
}
|
||||
if (!bt)
|
||||
return;
|
||||
bool is_transparent = bt->has_alpha || inst->alpha < 1.0f;
|
||||
@@ -603,8 +675,6 @@ static void render_billboard(struct RE_instance *inst, struct RE_renderer *r, ma
|
||||
glm_mat4_pick3t(view_mat, rot);
|
||||
glm_mat4_ins3(rot, local_transform);
|
||||
glm_scale(local_transform, inst->scale);
|
||||
// Billboard instances are bottomed at y=0.
|
||||
glm_translate_y(local_transform, 1.0);
|
||||
mat3 normal_transform;
|
||||
// This should be safe because billboards do not have non-uniform scaling.
|
||||
glm_mat4_pick3(local_transform, normal_transform);
|
||||
@@ -613,7 +683,7 @@ static void render_billboard(struct RE_instance *inst, struct RE_renderer *r, ma
|
||||
glUniformMatrix4fv(r->local_transform, 1, GL_FALSE, local_transform[0]);
|
||||
glUniformMatrix3fv(r->normal_transform, 1, GL_FALSE, normal_transform[0]);
|
||||
|
||||
reset_draw_uniforms(r);
|
||||
reset_draw_uniforms(r, inst->plugin);
|
||||
glUniform1f(r->alpha_mod, inst->alpha);
|
||||
glUniform1i(r->fog_type, inst->plugin->fog_mode ? inst->plugin->fog_type : 0);
|
||||
switch (inst->draw_type) {
|
||||
@@ -629,7 +699,15 @@ static void render_billboard(struct RE_instance *inst, struct RE_renderer *r, ma
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, bt->texture);
|
||||
glUniform1i(r->texture, 0);
|
||||
glBindVertexArray(r->billboard_vao);
|
||||
GLfloat vertices[4][5];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
glm_vec3_copy(inst->vertex_pos[i], vertices[i]);
|
||||
glm_vec2_copy(inst->vertex_uv[i], vertices[i] + 3);
|
||||
}
|
||||
glBindVertexArray(r->billboard_instance_vao);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, r->billboard_instance_attr_buffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STREAM_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
@@ -649,7 +727,7 @@ static void render_billboard_particles(struct RE_renderer *r, struct RE_instance
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glUniform1i(r->texture, 0);
|
||||
glBindVertexArray(r->billboard_vao);
|
||||
glBindVertexArray(r->billboard_particle_vao);
|
||||
|
||||
for (int index = 0; index < pae_obj->nr_particles; index++) {
|
||||
struct particle_instance *pi = &po->instances[index];
|
||||
@@ -686,7 +764,8 @@ static void render_polygon_particles(struct RE_renderer *r, struct RE_instance *
|
||||
if (!model)
|
||||
return;
|
||||
|
||||
glUniform1i(r->diffuse_type, DIFFUSE_NORMAL);
|
||||
glUniform1i(r->diffuse_type,
|
||||
lighting_disabled(inst->plugin) ? DIFFUSE_EMISSIVE : DIFFUSE_NORMAL);
|
||||
glUniform1i(r->fog_type, inst->plugin->fog_mode ? inst->plugin->fog_type : 0);
|
||||
|
||||
for (int index = 0; index < pae_obj->nr_particles; index++) {
|
||||
@@ -705,6 +784,9 @@ static void render_polygon_particles(struct RE_renderer *r, struct RE_instance *
|
||||
for (int i = 0; i < model->nr_meshes; i++) {
|
||||
struct mesh *mesh = &model->meshes[i];
|
||||
struct material *material = &model->materials[mesh->material];
|
||||
glUniform4f(r->uv_tiling,
|
||||
material->uv_tiling[0], material->uv_tiling[1],
|
||||
material->blend_uv_tiling[0], material->blend_uv_tiling[1]);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, material->color_maps[0]);
|
||||
@@ -742,7 +824,7 @@ static void render_s3de_billboard_particles(struct RE_renderer *r, struct RE_ins
|
||||
}
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glUniform1i(r->texture, 0);
|
||||
glBindVertexArray(r->billboard_vao);
|
||||
glBindVertexArray(r->billboard_particle_vao);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glBindTexture(GL_TEXTURE_2D, bt->texture);
|
||||
|
||||
@@ -780,7 +862,8 @@ static void render_s3de_polygon_particles(struct RE_renderer *r, struct RE_insta
|
||||
if (phase == DRAW_OPAQUE && st->emitter_alpha < 1.0f)
|
||||
return;
|
||||
|
||||
glUniform1i(r->diffuse_type, DIFFUSE_NORMAL);
|
||||
glUniform1i(r->diffuse_type,
|
||||
lighting_disabled(inst->plugin) ? DIFFUSE_EMISSIVE : DIFFUSE_NORMAL);
|
||||
// The .3de blend_type is ignored for polygon objects. Per-mesh additive
|
||||
// blend modes are not yet handled.
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
|
||||
@@ -807,6 +890,9 @@ static void render_s3de_polygon_particles(struct RE_renderer *r, struct RE_insta
|
||||
if (phase != (is_transparent ? DRAW_TRANSPARENT : DRAW_OPAQUE))
|
||||
continue;
|
||||
struct material *material = &model->materials[mesh->material];
|
||||
glUniform4f(r->uv_tiling,
|
||||
material->uv_tiling[0], material->uv_tiling[1],
|
||||
material->blend_uv_tiling[0], material->blend_uv_tiling[1]);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, material->color_maps[0]);
|
||||
@@ -850,7 +936,7 @@ static void render_s3de_effect(struct RE_instance *inst, struct RE_renderer *r,
|
||||
RE_instance_update_local_transform(inst);
|
||||
|
||||
glUniform3fv(r->instance_ambient, 1, inst->ambient);
|
||||
reset_draw_uniforms(r);
|
||||
reset_draw_uniforms(r, inst->plugin);
|
||||
|
||||
if (phase == DRAW_TRANSPARENT)
|
||||
glDepthMask(GL_FALSE);
|
||||
@@ -920,7 +1006,7 @@ static void render_particle_effect(struct RE_instance *inst, struct RE_renderer
|
||||
return;
|
||||
|
||||
glUniform3fv(r->instance_ambient, 1, inst->ambient);
|
||||
reset_draw_uniforms(r);
|
||||
reset_draw_uniforms(r, inst->plugin);
|
||||
|
||||
glDepthMask(GL_FALSE);
|
||||
|
||||
@@ -953,6 +1039,8 @@ static void render_particle_effect(struct RE_instance *inst, struct RE_renderer
|
||||
|
||||
static void render_instance(struct RE_instance *inst, struct RE_renderer *r, mat4 view_mat, enum draw_phase phase)
|
||||
{
|
||||
glUniform1f(r->grayscale_rate, inst->grayscale_rate);
|
||||
|
||||
switch (inst->type) {
|
||||
case RE_ITYPE_STATIC:
|
||||
render_static_model(inst, r, phase);
|
||||
@@ -1086,7 +1174,8 @@ static void render_outlines(struct RE_plugin *plugin, mat4 view_transform)
|
||||
bool seal_edge = re_plugin_version >= RE_SEAL_PLUGIN;
|
||||
if (seal_edge) {
|
||||
glUniform3fv(or->outline_color, 1, plugin->edge_color);
|
||||
glUniform1f(or->outline_thickness, plugin->edge_length);
|
||||
float thickness = plugin->edge_length * (1.f - plugin->edge_reduction_rate);
|
||||
glUniform1f(or->outline_thickness, thickness);
|
||||
}
|
||||
|
||||
glCullFace(GL_FRONT);
|
||||
|
||||
+41
-10
@@ -2405,7 +2405,11 @@ static bool SealEngine_GetInstanceAngleB(int plugin, int instance, float *angle_
|
||||
return true;
|
||||
}
|
||||
|
||||
//bool SealEngine_SetInstanceVertexUV(int PluginNumber, int InstanceNumber, int Index, float U, float V);
|
||||
static bool SealEngine_SetInstanceVertexUV(int plugin, int instance, int index, float u, float v)
|
||||
{
|
||||
return RE_instance_set_vertex_uv(get_instance(plugin, instance), index, u, v);
|
||||
}
|
||||
|
||||
//bool SealEngine_GetInstanceDiffuse(int PluginNumber, int InstanceNumber, float *pR, float *pG, float *pB);
|
||||
//bool SealEngine_GetInstanceAmbient(int PluginNumber, int InstanceNumber, float *pR, float *pG, float *pB);
|
||||
|
||||
@@ -2418,8 +2422,23 @@ static bool SealEngine_GetInstanceAlpha(int plugin, int instance, float *alpha)
|
||||
return true;
|
||||
}
|
||||
|
||||
//bool SealEngine_SetInstanceGrayscaleRate(int PluginNumber, int InstanceNumber, float GrayscaleRate);
|
||||
//bool SealEngine_GetInstanceGrayscaleRate(int PluginNumber, int InstanceNumber, float *GrayscaleRate);
|
||||
static bool SealEngine_SetInstanceGrayscaleRate(int plugin, int instance, float rate)
|
||||
{
|
||||
struct RE_instance *ri = get_instance(plugin, instance);
|
||||
if (!ri)
|
||||
return false;
|
||||
ri->grayscale_rate = rate;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool SealEngine_GetInstanceGrayscaleRate(int plugin, int instance, float *rate)
|
||||
{
|
||||
struct RE_instance *ri = get_instance(plugin, instance);
|
||||
if (!ri)
|
||||
return false;
|
||||
*rate = ri->grayscale_rate;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool SealEngine_IsExistInstanceMotion(int plugin, int instance, struct string *motion_name)
|
||||
{
|
||||
@@ -2550,8 +2569,20 @@ static float SealEngine_GetEdgeLength(int PluginNumber)
|
||||
return p ? p->edge_length : 0.0;
|
||||
}
|
||||
|
||||
//bool SealEngine_SetEdgeReductionRate(int PluginNumber, float EdgeReductionRate);
|
||||
//float SealEngine_GetEdgeReductionRate(int PluginNumber);
|
||||
static bool SealEngine_SetEdgeReductionRate(int plugin, float rate)
|
||||
{
|
||||
struct RE_plugin *p = RE_get_plugin(plugin);
|
||||
if (!p)
|
||||
return false;
|
||||
p->edge_reduction_rate = rate;
|
||||
return true;
|
||||
}
|
||||
|
||||
static float SealEngine_GetEdgeReductionRate(int plugin)
|
||||
{
|
||||
struct RE_plugin *p = RE_get_plugin(plugin);
|
||||
return p ? p->edge_reduction_rate : 0.0;
|
||||
}
|
||||
|
||||
static bool SealEngine_SetEdgeColor(int PluginNumber, float ColorR, float ColorG, float ColorB)
|
||||
{
|
||||
@@ -2624,12 +2655,12 @@ HLL_QUIET_UNIMPLEMENTED(false, bool, SealEngine, IsThreadLoadingMode, int Plugin
|
||||
HLL_EXPORT(GetInstanceAngle, SealEngine_GetInstanceAngle), \
|
||||
HLL_EXPORT(GetInstanceAngleP, SealEngine_GetInstanceAngleP), \
|
||||
HLL_EXPORT(GetInstanceAngleB, SealEngine_GetInstanceAngleB), \
|
||||
HLL_TODO_EXPORT(SetInstanceVertexUV, SealEngine_SetInstanceVertexUV), \
|
||||
HLL_EXPORT(SetInstanceVertexUV, SealEngine_SetInstanceVertexUV), \
|
||||
HLL_TODO_EXPORT(GetInstanceDiffuse, SealEngine_GetInstanceDiffuse), \
|
||||
HLL_TODO_EXPORT(GetInstanceAmbient, SealEngine_GetInstanceAmbient), \
|
||||
HLL_EXPORT(GetInstanceAlpha, SealEngine_GetInstanceAlpha), \
|
||||
HLL_TODO_EXPORT(SetInstanceGrayscaleRate, SealEngine_SetInstanceGrayscaleRate), \
|
||||
HLL_TODO_EXPORT(GetInstanceGrayscaleRate, SealEngine_GetInstanceGrayscaleRate), \
|
||||
HLL_EXPORT(SetInstanceGrayscaleRate, SealEngine_SetInstanceGrayscaleRate), \
|
||||
HLL_EXPORT(GetInstanceGrayscaleRate, SealEngine_GetInstanceGrayscaleRate), \
|
||||
HLL_EXPORT(IsExistInstanceMotion, SealEngine_IsExistInstanceMotion), \
|
||||
HLL_TODO_EXPORT(GetInstanceNumofBone, SealEngine_GetInstanceNumofBone), \
|
||||
HLL_TODO_EXPORT(GetInstanceBoneName, SealEngine_GetInstanceBoneName), \
|
||||
@@ -2702,8 +2733,8 @@ HLL_QUIET_UNIMPLEMENTED(false, bool, SealEngine, IsThreadLoadingMode, int Plugin
|
||||
HLL_TODO_EXPORT(GetSoftFogEdgeLength, SealEngine_GetSoftFogEdgeLength), \
|
||||
HLL_EXPORT(SetEdgeLength, SealEngine_SetEdgeLength), \
|
||||
HLL_EXPORT(GetEdgeLength, SealEngine_GetEdgeLength), \
|
||||
HLL_TODO_EXPORT(SetEdgeReductionRate, SealEngine_SetEdgeReductionRate), \
|
||||
HLL_TODO_EXPORT(GetEdgeReductionRate, SealEngine_GetEdgeReductionRate), \
|
||||
HLL_EXPORT(SetEdgeReductionRate, SealEngine_SetEdgeReductionRate), \
|
||||
HLL_EXPORT(GetEdgeReductionRate, SealEngine_GetEdgeReductionRate), \
|
||||
HLL_EXPORT(SetEdgeColor, SealEngine_SetEdgeColor), \
|
||||
HLL_EXPORT(GetEdgeColor, SealEngine_GetEdgeColor), \
|
||||
HLL_TODO_EXPORT(Calc2DDetectionHeight, SealEngine_Calc2DDetectionHeight), \
|
||||
|
||||
Reference in New Issue
Block a user