mirror of
https://github.com/nunuhara/xsystem4.git
synced 2026-09-22 23:18:01 +03:00
Merge pull request #66 from kichikuou/shadow
ReignEngine: Implement shadow mapping
This commit is contained in:
@@ -73,6 +73,7 @@ void gfx_update_screen_scale(void);
|
||||
void gfx_set_wait_vsync(bool wait);
|
||||
|
||||
void gfx_load_shader(struct shader *dst, const char *vertex_shader_path, const char *fragment_shader_path);
|
||||
GLuint gfx_load_shader_file(const char *path, GLenum type);
|
||||
|
||||
// rendering
|
||||
void gfx_set_clear_color(int r, int g, int b, int a);
|
||||
|
||||
@@ -74,6 +74,9 @@ struct RE_plugin {
|
||||
|
||||
struct RE_back_cg back_cg[RE_NR_BACK_CGS];
|
||||
|
||||
vec3 shadow_map_light_dir;
|
||||
float shadow_bias;
|
||||
|
||||
// Settings.
|
||||
int render_mode;
|
||||
int shadow_mode;
|
||||
@@ -109,6 +112,9 @@ struct RE_instance {
|
||||
vec3 scale;
|
||||
float alpha;
|
||||
bool draw;
|
||||
bool draw_shadow;
|
||||
bool make_shadow;
|
||||
float shadow_volume_bone_radius;
|
||||
bool draw_bump;
|
||||
float fps;
|
||||
bool motion_blend;
|
||||
|
||||
@@ -25,6 +25,7 @@ struct dir_light {
|
||||
uniform sampler2D tex;
|
||||
uniform sampler2D specular_texture;
|
||||
uniform sampler2D light_texture;
|
||||
uniform sampler2D shadow_texture;
|
||||
uniform float alpha_mod;
|
||||
|
||||
uniform bool use_normal_map;
|
||||
@@ -38,10 +39,13 @@ uniform bool use_specular_map;
|
||||
uniform float rim_exponent;
|
||||
uniform vec3 rim_color;
|
||||
uniform bool use_light_map;
|
||||
uniform bool use_shadow_map;
|
||||
uniform float shadow_bias;
|
||||
|
||||
in vec2 tex_coord;
|
||||
in vec2 light_tex_coord;
|
||||
in vec3 frag_pos;
|
||||
in vec4 shadow_frag_pos;
|
||||
in vec3 eye;
|
||||
in vec3 normal;
|
||||
in vec3 light_dir[NR_DIR_LIGHTS];
|
||||
@@ -88,5 +92,22 @@ void main() {
|
||||
frag_rgb += pow(1.0 - max(dot(normalize(normal), view_dir), 0.0), rim_exponent) * rim_color;
|
||||
}
|
||||
|
||||
// Shadow mapping
|
||||
if (use_shadow_map) {
|
||||
vec3 shadow_coords = shadow_frag_pos.xyz / shadow_frag_pos.w * 0.5 + 0.5;
|
||||
shadow_coords.z = min(1.0, shadow_coords.z - shadow_bias);
|
||||
// PCF with 9 samples.
|
||||
float shadow_factor = 1.0;
|
||||
vec2 texel_size = 1.0 / vec2(textureSize(shadow_texture, 0));
|
||||
for (int x = -1; x <= 1; ++x) {
|
||||
for (int y = -1; y <= 1; ++y) {
|
||||
float depth = texture(shadow_texture, shadow_coords.xy + vec2(x, y) * texel_size).r;
|
||||
if (depth < shadow_coords.z)
|
||||
shadow_factor -= 0.05;
|
||||
}
|
||||
}
|
||||
frag_rgb *= shadow_factor;
|
||||
}
|
||||
|
||||
frag_color = vec4(frag_rgb, texel.a * alpha_mod);
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ uniform bool use_normal_map;
|
||||
uniform vec3 view_pos;
|
||||
uniform dir_light dir_lights[NR_DIR_LIGHTS];
|
||||
uniform vec3 specular_light_dir;
|
||||
uniform mat4 shadow_transform;
|
||||
|
||||
in vec3 vertex_pos;
|
||||
in vec3 vertex_normal;
|
||||
@@ -49,6 +50,7 @@ in vec4 vertex_bone_weight;
|
||||
out vec2 tex_coord;
|
||||
out vec2 light_tex_coord;
|
||||
out vec3 frag_pos;
|
||||
out vec4 shadow_frag_pos;
|
||||
out vec3 eye;
|
||||
out vec3 normal;
|
||||
out vec3 light_dir[NR_DIR_LIGHTS];
|
||||
@@ -86,6 +88,8 @@ void main() {
|
||||
tex_coord = vertex_uv;
|
||||
light_tex_coord = vertex_light_uv;
|
||||
|
||||
shadow_frag_pos = shadow_transform * world_pos;
|
||||
|
||||
// These are in tangent-space if use_normal_map is true, in world-space
|
||||
// otherwise.
|
||||
frag_pos = TBN * vec3(world_pos);
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
/* Copyright (C) 2022 kichikuou <KichikuouChrome@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
void main() {
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/* Copyright (C) 2022 kichikuou <KichikuouChrome@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
uniform mat4 world_transform;
|
||||
uniform mat4 view_transform;
|
||||
|
||||
const int MAX_BONES = 211; // see 3d_internal.h
|
||||
const int NR_WEIGHTS = 4;
|
||||
uniform bool has_bones;
|
||||
uniform mat4 bone_matrices[MAX_BONES];
|
||||
|
||||
in vec3 vertex_pos;
|
||||
in ivec4 vertex_bone_index;
|
||||
in vec4 vertex_bone_weight;
|
||||
|
||||
void main() {
|
||||
mat4 world_bone_transform = world_transform;
|
||||
if (has_bones) {
|
||||
mat4 bone_transform = mat4(0.f);
|
||||
for (int i = 0; i < NR_WEIGHTS; i++) {
|
||||
if (vertex_bone_index[i] >= 0) {
|
||||
bone_transform += bone_matrices[vertex_bone_index[i]] * vertex_bone_weight[i];
|
||||
}
|
||||
}
|
||||
world_bone_transform *= bone_transform;
|
||||
}
|
||||
|
||||
gl_Position = view_transform * world_bone_transform * vec4(vertex_pos, 1.0);
|
||||
}
|
||||
+31
-5
@@ -36,6 +36,7 @@ struct model {
|
||||
int nr_bones;
|
||||
struct bone *bones;
|
||||
struct hash_table *bone_map; // bone id in POL/MOT -> struct bone *
|
||||
vec3 aabb[2]; // axis-aligned bounding box
|
||||
};
|
||||
|
||||
struct mesh {
|
||||
@@ -73,11 +74,33 @@ struct motion {
|
||||
float loop_frame_begin, loop_frame_end;
|
||||
};
|
||||
|
||||
struct RE_renderer {
|
||||
struct shader shader;
|
||||
GLuint depth_buffer;
|
||||
enum RE_attribute_location {
|
||||
ATTR_VERTEX_POS = 0,
|
||||
ATTR_BONE_INDEX,
|
||||
ATTR_BONE_WEIGHT,
|
||||
};
|
||||
|
||||
struct shadow_renderer {
|
||||
GLuint program;
|
||||
GLuint fbo;
|
||||
GLuint texture;
|
||||
|
||||
// Uniform variable locations
|
||||
GLint world_transform;
|
||||
GLint view_transform;
|
||||
GLint has_bones;
|
||||
GLint bone_matrices;
|
||||
};
|
||||
|
||||
struct RE_renderer {
|
||||
GLuint program;
|
||||
GLuint depth_buffer;
|
||||
struct shadow_renderer shadow;
|
||||
|
||||
// Uniform variable locations
|
||||
GLint world_transform;
|
||||
GLint view_transform;
|
||||
GLint texture;
|
||||
GLint local_transform;
|
||||
GLint proj_transform;
|
||||
GLint normal_transform;
|
||||
@@ -103,14 +126,16 @@ struct RE_renderer {
|
||||
GLint light_texture;
|
||||
GLint use_normal_map;
|
||||
GLint normal_texture;
|
||||
GLint use_shadow_map;
|
||||
GLint shadow_transform;
|
||||
GLint shadow_texture;
|
||||
GLint shadow_bias;
|
||||
|
||||
// Attribute variable locations
|
||||
GLint vertex_normal;
|
||||
GLint vertex_uv;
|
||||
GLint vertex_light_uv;
|
||||
GLint vertex_tangent;
|
||||
GLint vertex_bone_index;
|
||||
GLint vertex_bone_weight;
|
||||
|
||||
GLuint billboard_vao;
|
||||
GLuint billboard_attr_buffer;
|
||||
@@ -251,6 +276,7 @@ enum amt_field_index {
|
||||
|
||||
struct pol *pol_parse(uint8_t *data, size_t size);
|
||||
void pol_free(struct pol *pol);
|
||||
void pol_compute_aabb(struct pol *model, vec3 dest[2]);
|
||||
struct pol_bone *pol_find_bone(struct pol *pol, uint32_t id);
|
||||
|
||||
struct mot *mot_parse(uint8_t *data, size_t size);
|
||||
|
||||
+12
-10
@@ -271,8 +271,8 @@ static void add_mesh(struct model *model, struct pol_mesh *m, int material_index
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mesh->attr_buffer);
|
||||
|
||||
const uint8_t *base = (const uint8_t *)0;
|
||||
glEnableVertexAttribArray(r->shader.vertex);
|
||||
glVertexAttribPointer(r->shader.vertex, 3, GL_FLOAT, GL_FALSE, stride, base + offsetof(struct vertex_common, pos));
|
||||
glEnableVertexAttribArray(ATTR_VERTEX_POS);
|
||||
glVertexAttribPointer(ATTR_VERTEX_POS, 3, GL_FLOAT, GL_FALSE, stride, base + offsetof(struct vertex_common, pos));
|
||||
glEnableVertexAttribArray(r->vertex_normal);
|
||||
glVertexAttribPointer(r->vertex_normal, 3, GL_FLOAT, GL_FALSE, stride, base + offsetof(struct vertex_common, normal));
|
||||
glEnableVertexAttribArray(r->vertex_uv);
|
||||
@@ -295,16 +295,16 @@ static void add_mesh(struct model *model, struct pol_mesh *m, int material_index
|
||||
glVertexAttrib3f(r->vertex_tangent, 1.0, 0.0, 0.0);
|
||||
}
|
||||
if (has_bones) {
|
||||
glEnableVertexAttribArray(r->vertex_bone_index);
|
||||
glVertexAttribIPointer(r->vertex_bone_index, NR_WEIGHTS, GL_INT, stride, base + offsetof(struct vertex_bones, bone_id));
|
||||
glEnableVertexAttribArray(r->vertex_bone_weight);
|
||||
glVertexAttribPointer(r->vertex_bone_weight, NR_WEIGHTS, GL_FLOAT, GL_FALSE, stride, base + offsetof(struct vertex_bones, bone_weight));
|
||||
glEnableVertexAttribArray(ATTR_BONE_INDEX);
|
||||
glVertexAttribIPointer(ATTR_BONE_INDEX, NR_WEIGHTS, GL_INT, stride, base + offsetof(struct vertex_bones, bone_id));
|
||||
glEnableVertexAttribArray(ATTR_BONE_WEIGHT);
|
||||
glVertexAttribPointer(ATTR_BONE_WEIGHT, NR_WEIGHTS, GL_FLOAT, GL_FALSE, stride, base + offsetof(struct vertex_bones, bone_weight));
|
||||
base += sizeof(struct vertex_bones);
|
||||
} else {
|
||||
glDisableVertexAttribArray(r->vertex_bone_index);
|
||||
glVertexAttribI4i(r->vertex_bone_index, 0, 0, 0, 0);
|
||||
glDisableVertexAttribArray(r->vertex_bone_weight);
|
||||
glVertexAttrib4f(r->vertex_bone_weight, 0.0, 0.0, 0.0, 0.0);
|
||||
glDisableVertexAttribArray(ATTR_BONE_INDEX);
|
||||
glVertexAttribI4i(ATTR_BONE_INDEX, 0, 0, 0, 0);
|
||||
glDisableVertexAttribArray(ATTR_BONE_WEIGHT);
|
||||
glVertexAttrib4f(ATTR_BONE_WEIGHT, 0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
assert((intptr_t)base == stride);
|
||||
|
||||
@@ -440,6 +440,8 @@ struct model *model_load(struct archive *aar, const char *path, struct RE_render
|
||||
}
|
||||
}
|
||||
|
||||
pol_compute_aabb(pol, model->aabb);
|
||||
|
||||
free(material_offsets);
|
||||
if (amt)
|
||||
amt_free(amt);
|
||||
|
||||
@@ -295,6 +295,23 @@ void pol_free(struct pol *pol)
|
||||
free(pol);
|
||||
}
|
||||
|
||||
void pol_compute_aabb(struct pol *pol, vec3 dest[2])
|
||||
{
|
||||
vec3 aabb[2];
|
||||
glm_aabb_invalidate(aabb);
|
||||
for (uint32_t i = 0; i < pol->nr_meshes; i++) {
|
||||
struct pol_mesh *mesh = pol->meshes[i];
|
||||
if (!mesh)
|
||||
continue;
|
||||
for (uint32_t j = 0; j < mesh->nr_vertices; j++) {
|
||||
glm_vec3_minv(mesh->vertices[j].pos, aabb[0], aabb[0]);
|
||||
glm_vec3_maxv(mesh->vertices[j].pos, aabb[1], aabb[1]);
|
||||
}
|
||||
}
|
||||
glm_vec3_copy(aabb[0], dest[0]);
|
||||
glm_vec3_copy(aabb[1], dest[1]);
|
||||
}
|
||||
|
||||
struct pol_bone *pol_find_bone(struct pol *pol, uint32_t id)
|
||||
{
|
||||
for (uint32_t i = 0; i < pol->nr_bones; i++) {
|
||||
|
||||
+238
-42
@@ -25,13 +25,81 @@
|
||||
#include "reign.h"
|
||||
#include "sact.h"
|
||||
|
||||
// TODO: Respect RE_plugin.shadow_map_resolution_level
|
||||
#define SHADOW_WIDTH 1024
|
||||
#define SHADOW_HEIGHT 1024
|
||||
|
||||
enum {
|
||||
COLOR_TEXTURE_UNIT,
|
||||
SPECULAR_TEXTURE_UNIT,
|
||||
LIGHT_TEXTURE_UNIT,
|
||||
NORMAL_TEXTURE_UNIT,
|
||||
SHADOW_TEXTURE_UNIT,
|
||||
};
|
||||
|
||||
static GLuint load_shader(const char *vertex_shader_path, const char *fragment_shader_path)
|
||||
{
|
||||
GLuint program = glCreateProgram();
|
||||
GLuint vertex_shader = gfx_load_shader_file(vertex_shader_path, GL_VERTEX_SHADER);
|
||||
GLuint fragment_shader = gfx_load_shader_file(fragment_shader_path, GL_FRAGMENT_SHADER);
|
||||
|
||||
glAttachShader(program, vertex_shader);
|
||||
glAttachShader(program, fragment_shader);
|
||||
|
||||
// Bind some attributes to fixed locations, so that common VAO can be used
|
||||
// by multiple programs.
|
||||
glBindAttribLocation(program, ATTR_VERTEX_POS, "vertex_pos");
|
||||
glBindAttribLocation(program, ATTR_BONE_INDEX, "vertex_bone_index");
|
||||
glBindAttribLocation(program, ATTR_BONE_WEIGHT, "vertex_bone_weight");
|
||||
|
||||
glLinkProgram(program);
|
||||
|
||||
GLint link_success;
|
||||
glGetProgramiv(program, GL_LINK_STATUS, &link_success);
|
||||
if (!link_success) {
|
||||
GLint len;
|
||||
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &len);
|
||||
char *infolog = xmalloc(len + 1);
|
||||
glGetProgramInfoLog(program, len, NULL, infolog);
|
||||
ERROR("Failed to link shader %s, %s: %s", vertex_shader_path, fragment_shader_path, infolog);
|
||||
}
|
||||
return program;
|
||||
}
|
||||
|
||||
static void init_shadow_renderer(struct shadow_renderer *sr)
|
||||
{
|
||||
GLint orig_fbo;
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &orig_fbo);
|
||||
|
||||
sr->program = load_shader("shaders/reign_shadow.v.glsl", "shaders/reign_shadow.f.glsl");
|
||||
sr->world_transform = glGetUniformLocation(sr->program, "world_transform");
|
||||
sr->view_transform = glGetUniformLocation(sr->program, "view_transform");
|
||||
sr->has_bones = glGetUniformLocation(sr->program, "has_bones");
|
||||
sr->bone_matrices = glGetUniformLocation(sr->program, "bone_matrices");
|
||||
|
||||
glGenFramebuffers(1, &sr->fbo);
|
||||
glGenTextures(1, &sr->texture);
|
||||
glBindTexture(GL_TEXTURE_2D, sr->texture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, SHADOW_WIDTH, SHADOW_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, sr->fbo);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, sr->texture, 0);
|
||||
glDrawBuffers(0, NULL);
|
||||
glReadBuffer(GL_NONE);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, orig_fbo);
|
||||
}
|
||||
|
||||
static void destroy_shadow_renderer(struct shadow_renderer *sr)
|
||||
{
|
||||
glDeleteTextures(1, &sr->texture);
|
||||
glDeleteFramebuffers(1, &sr->fbo);
|
||||
glDeleteProgram(sr->program);
|
||||
}
|
||||
|
||||
static void init_billboard_mesh(struct RE_renderer *r)
|
||||
{
|
||||
static const GLfloat vertices[] = {
|
||||
@@ -46,8 +114,8 @@ static void init_billboard_mesh(struct RE_renderer *r)
|
||||
glGenBuffers(1, &r->billboard_attr_buffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, r->billboard_attr_buffer);
|
||||
|
||||
glEnableVertexAttribArray(r->shader.vertex);
|
||||
glVertexAttribPointer(r->shader.vertex, 3, GL_FLOAT, GL_FALSE, 20, (const void *)0);
|
||||
glEnableVertexAttribArray(ATTR_VERTEX_POS);
|
||||
glVertexAttribPointer(ATTR_VERTEX_POS, 3, GL_FLOAT, GL_FALSE, 20, (const void *)0);
|
||||
glEnableVertexAttribArray(r->vertex_uv);
|
||||
glVertexAttribPointer(r->vertex_uv, 2, GL_FLOAT, GL_FALSE, 20, (const void *)12);
|
||||
glDisableVertexAttribArray(r->vertex_light_uv);
|
||||
@@ -56,10 +124,10 @@ static void init_billboard_mesh(struct RE_renderer *r)
|
||||
glVertexAttrib3f(r->vertex_normal, 0.0, 0.0, 1.0);
|
||||
glDisableVertexAttribArray(r->vertex_tangent);
|
||||
glVertexAttrib3f(r->vertex_tangent, 1.0, 0.0, 0.0);
|
||||
glDisableVertexAttribArray(r->vertex_bone_index);
|
||||
glVertexAttribI4i(r->vertex_bone_index, 0, 0, 0, 0);
|
||||
glDisableVertexAttribArray(r->vertex_bone_weight);
|
||||
glVertexAttrib4f(r->vertex_bone_weight, 0.0, 0.0, 0.0, 0.0);
|
||||
glDisableVertexAttribArray(ATTR_BONE_INDEX);
|
||||
glVertexAttribI4i(ATTR_BONE_INDEX, 0, 0, 0, 0);
|
||||
glDisableVertexAttribArray(ATTR_BONE_WEIGHT);
|
||||
glVertexAttrib4f(ATTR_BONE_WEIGHT, 0.0, 0.0, 0.0, 0.0);
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||
|
||||
@@ -67,51 +135,63 @@ static void init_billboard_mesh(struct RE_renderer *r)
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
static void destroy_billboard_mesh(struct RE_renderer *r)
|
||||
{
|
||||
glDeleteVertexArrays(1, &r->billboard_vao);
|
||||
glDeleteBuffers(1, &r->billboard_attr_buffer);
|
||||
}
|
||||
|
||||
struct RE_renderer *RE_renderer_new(struct texture *texture)
|
||||
{
|
||||
struct RE_renderer *r = xcalloc(1, sizeof(struct RE_renderer));
|
||||
|
||||
gfx_load_shader(&r->shader, "shaders/reign.v.glsl", "shaders/reign.f.glsl");
|
||||
r->local_transform = glGetUniformLocation(r->shader.program, "local_transform");
|
||||
r->proj_transform = glGetUniformLocation(r->shader.program, "proj_transform");
|
||||
r->normal_transform = glGetUniformLocation(r->shader.program, "normal_transform");
|
||||
r->alpha_mod = glGetUniformLocation(r->shader.program, "alpha_mod");
|
||||
r->has_bones = glGetUniformLocation(r->shader.program, "has_bones");
|
||||
r->bone_matrices = glGetUniformLocation(r->shader.program, "bone_matrices");
|
||||
r->ambient = glGetUniformLocation(r->shader.program, "ambient");
|
||||
r->program = load_shader("shaders/reign.v.glsl", "shaders/reign.f.glsl");
|
||||
r->world_transform = glGetUniformLocation(r->program, "world_transform");
|
||||
r->view_transform = glGetUniformLocation(r->program, "view_transform");
|
||||
r->texture = glGetUniformLocation(r->program, "tex");
|
||||
r->local_transform = glGetUniformLocation(r->program, "local_transform");
|
||||
r->proj_transform = glGetUniformLocation(r->program, "proj_transform");
|
||||
r->normal_transform = glGetUniformLocation(r->program, "normal_transform");
|
||||
r->alpha_mod = glGetUniformLocation(r->program, "alpha_mod");
|
||||
r->has_bones = glGetUniformLocation(r->program, "has_bones");
|
||||
r->bone_matrices = glGetUniformLocation(r->program, "bone_matrices");
|
||||
r->ambient = glGetUniformLocation(r->program, "ambient");
|
||||
for (int i = 0; i < NR_DIR_LIGHTS; i++) {
|
||||
char buf[64];
|
||||
sprintf(buf, "dir_lights[%d].dir", i);
|
||||
r->dir_lights[i].dir = glGetUniformLocation(r->shader.program, buf);
|
||||
r->dir_lights[i].dir = glGetUniformLocation(r->program, buf);
|
||||
sprintf(buf, "dir_lights[%d].diffuse", i);
|
||||
r->dir_lights[i].diffuse = glGetUniformLocation(r->shader.program, buf);
|
||||
r->dir_lights[i].diffuse = glGetUniformLocation(r->program, buf);
|
||||
sprintf(buf, "dir_lights[%d].globe_diffuse", i);
|
||||
r->dir_lights[i].globe_diffuse = glGetUniformLocation(r->shader.program, buf);
|
||||
r->dir_lights[i].globe_diffuse = glGetUniformLocation(r->program, buf);
|
||||
}
|
||||
r->specular_light_dir = glGetUniformLocation(r->shader.program, "specular_light_dir");
|
||||
r->specular_strength = glGetUniformLocation(r->shader.program, "specular_strength");
|
||||
r->specular_shininess = glGetUniformLocation(r->shader.program, "specular_shininess");
|
||||
r->use_specular_map = glGetUniformLocation(r->shader.program, "use_specular_map");
|
||||
r->specular_texture = glGetUniformLocation(r->shader.program, "specular_texture");
|
||||
r->rim_exponent = glGetUniformLocation(r->shader.program, "rim_exponent");
|
||||
r->rim_color = glGetUniformLocation(r->shader.program, "rim_color");
|
||||
r->view_pos = glGetUniformLocation(r->shader.program, "view_pos");
|
||||
r->use_light_map = glGetUniformLocation(r->shader.program, "use_light_map");
|
||||
r->light_texture = glGetUniformLocation(r->shader.program, "light_texture");
|
||||
r->use_normal_map = glGetUniformLocation(r->shader.program, "use_normal_map");
|
||||
r->normal_texture = glGetUniformLocation(r->shader.program, "normal_texture");
|
||||
r->vertex_normal = glGetAttribLocation(r->shader.program, "vertex_normal");
|
||||
r->vertex_uv = glGetAttribLocation(r->shader.program, "vertex_uv");
|
||||
r->vertex_light_uv = glGetAttribLocation(r->shader.program, "vertex_light_uv");
|
||||
r->vertex_tangent = glGetAttribLocation(r->shader.program, "vertex_tangent");
|
||||
r->vertex_bone_index = glGetAttribLocation(r->shader.program, "vertex_bone_index");
|
||||
r->vertex_bone_weight = glGetAttribLocation(r->shader.program, "vertex_bone_weight");
|
||||
r->specular_light_dir = glGetUniformLocation(r->program, "specular_light_dir");
|
||||
r->specular_strength = glGetUniformLocation(r->program, "specular_strength");
|
||||
r->specular_shininess = glGetUniformLocation(r->program, "specular_shininess");
|
||||
r->use_specular_map = glGetUniformLocation(r->program, "use_specular_map");
|
||||
r->specular_texture = glGetUniformLocation(r->program, "specular_texture");
|
||||
r->rim_exponent = glGetUniformLocation(r->program, "rim_exponent");
|
||||
r->rim_color = glGetUniformLocation(r->program, "rim_color");
|
||||
r->view_pos = glGetUniformLocation(r->program, "view_pos");
|
||||
r->use_light_map = glGetUniformLocation(r->program, "use_light_map");
|
||||
r->light_texture = glGetUniformLocation(r->program, "light_texture");
|
||||
r->use_normal_map = glGetUniformLocation(r->program, "use_normal_map");
|
||||
r->normal_texture = glGetUniformLocation(r->program, "normal_texture");
|
||||
r->use_shadow_map = glGetUniformLocation(r->program, "use_shadow_map");
|
||||
r->shadow_transform = glGetUniformLocation(r->program, "shadow_transform");
|
||||
r->shadow_texture = glGetUniformLocation(r->program, "shadow_texture");
|
||||
r->shadow_bias = glGetUniformLocation(r->program, "shadow_bias");
|
||||
r->vertex_normal = glGetAttribLocation(r->program, "vertex_normal");
|
||||
r->vertex_uv = glGetAttribLocation(r->program, "vertex_uv");
|
||||
r->vertex_light_uv = glGetAttribLocation(r->program, "vertex_light_uv");
|
||||
r->vertex_tangent = glGetAttribLocation(r->program, "vertex_tangent");
|
||||
|
||||
glGenRenderbuffers(1, &r->depth_buffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, r->depth_buffer);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, texture->w, texture->h);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
|
||||
init_shadow_renderer(&r->shadow);
|
||||
init_billboard_mesh(r);
|
||||
r->billboard_textures = ht_create(256);
|
||||
return r;
|
||||
@@ -151,12 +231,12 @@ static void free_billboard_texture(void *value)
|
||||
|
||||
void RE_renderer_free(struct RE_renderer *r)
|
||||
{
|
||||
glDeleteProgram(r->shader.program);
|
||||
glDeleteProgram(r->program);
|
||||
glDeleteRenderbuffers(1, &r->depth_buffer);
|
||||
ht_foreach_value(r->billboard_textures, free_billboard_texture);
|
||||
ht_free_int(r->billboard_textures);
|
||||
glDeleteVertexArrays(1, &r->billboard_vao);
|
||||
glDeleteBuffers(1, &r->billboard_attr_buffer);
|
||||
destroy_billboard_mesh(r);
|
||||
destroy_shadow_renderer(&r->shadow);
|
||||
free(r);
|
||||
}
|
||||
|
||||
@@ -191,6 +271,15 @@ static void render_model(struct RE_instance *inst, struct RE_renderer *r)
|
||||
glm_vec3_add(inst->plugin->global_ambient, inst->ambient, ambient);
|
||||
glUniform3fv(r->ambient, 1, ambient);
|
||||
|
||||
if (inst->draw_shadow && inst->plugin->shadow_mode) {
|
||||
glUniform1i(r->use_shadow_map, GL_TRUE);
|
||||
glActiveTexture(GL_TEXTURE0 + SHADOW_TEXTURE_UNIT);
|
||||
glBindTexture(GL_TEXTURE_2D, r->shadow.texture);
|
||||
glUniform1i(r->shadow_texture, SHADOW_TEXTURE_UNIT);
|
||||
} else {
|
||||
glUniform1i(r->use_shadow_map, GL_FALSE);
|
||||
}
|
||||
|
||||
for (int i = 0; i < model->nr_meshes; i++) {
|
||||
struct mesh *mesh = &model->meshes[i];
|
||||
struct material *material = &model->materials[mesh->material];
|
||||
@@ -216,7 +305,7 @@ static void render_model(struct RE_instance *inst, struct RE_renderer *r)
|
||||
|
||||
glActiveTexture(GL_TEXTURE0 + COLOR_TEXTURE_UNIT);
|
||||
glBindTexture(GL_TEXTURE_2D, material->color_map);
|
||||
glUniform1i(r->shader.texture, COLOR_TEXTURE_UNIT);
|
||||
glUniform1i(r->texture, COLOR_TEXTURE_UNIT);
|
||||
|
||||
if (material->light_map && inst->plugin->light_map_mode) {
|
||||
glUniform1i(r->use_light_map, GL_TRUE);
|
||||
@@ -298,7 +387,7 @@ static void render_billboard(struct RE_instance *inst, struct RE_renderer *r, ma
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, bt->texture);
|
||||
glUniform1i(r->shader.texture, 0);
|
||||
glUniform1i(r->texture, 0);
|
||||
glBindVertexArray(r->billboard_vao);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
@@ -307,6 +396,105 @@ static void render_billboard(struct RE_instance *inst, struct RE_renderer *r, ma
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
static bool calc_shadow_light_transform(struct RE_plugin *plugin, mat4 dest)
|
||||
{
|
||||
// Compute AABB of shadow casters.
|
||||
vec3 aabb[2];
|
||||
glm_aabb_invalidate(aabb);
|
||||
for (int i = 0; i < plugin->nr_instances; i++) {
|
||||
struct RE_instance *inst = plugin->instances[i];
|
||||
if (!inst || !inst->make_shadow || !inst->model)
|
||||
continue;
|
||||
// Start with the model's AABB, inflated with shadow_volume_bone_radius.
|
||||
vec3 inst_aabb[2];
|
||||
glm_vec3_subs(inst->model->aabb[0], inst->shadow_volume_bone_radius, inst_aabb[0]);
|
||||
glm_vec3_adds(inst->model->aabb[1], inst->shadow_volume_bone_radius, inst_aabb[1]);
|
||||
// To save CPU cycles, consider only the translation components of bone transforms.
|
||||
vec3 bone_translation_aabb[2];
|
||||
glm_aabb_invalidate(bone_translation_aabb);
|
||||
for (int j = 0; j < inst->model->nr_bones; j++) {
|
||||
glm_vec3_minv(inst->bone_transforms[j][3], bone_translation_aabb[0], bone_translation_aabb[0]);
|
||||
glm_vec3_maxv(inst->bone_transforms[j][3], bone_translation_aabb[1], bone_translation_aabb[1]);
|
||||
}
|
||||
if (glm_aabb_isvalid(bone_translation_aabb)) {
|
||||
glm_vec3_add(inst_aabb[0], bone_translation_aabb[0], inst_aabb[0]);
|
||||
glm_vec3_add(inst_aabb[1], bone_translation_aabb[1], inst_aabb[1]);
|
||||
}
|
||||
// Apply local transform.
|
||||
if (inst->local_transform_needs_update)
|
||||
RE_instance_update_local_transform(inst);
|
||||
glm_aabb_transform(inst_aabb, inst->local_transform, inst_aabb);
|
||||
|
||||
glm_aabb_merge(inst_aabb, aabb, aabb);
|
||||
}
|
||||
if (!glm_aabb_isvalid(aabb))
|
||||
return false;
|
||||
|
||||
// Create a orthographic frustum that contains the AABB.
|
||||
vec3 center;
|
||||
glm_aabb_center(aabb, center);
|
||||
vec3 light_pos;
|
||||
glm_vec3_scale(plugin->shadow_map_light_dir, -glm_aabb_radius(aabb), light_pos);
|
||||
glm_vec3_add(light_pos, center, light_pos);
|
||||
mat4 view_matrix;
|
||||
vec3 up = {0.0, 1.0, 0.0};
|
||||
glm_lookat(light_pos, center, up, view_matrix);
|
||||
|
||||
mat4 proj_matrix;
|
||||
glm_aabb_transform(aabb, view_matrix, aabb);
|
||||
glm_ortho_aabb(aabb, proj_matrix);
|
||||
|
||||
glm_mat4_mul(proj_matrix, view_matrix, dest);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void render_shadow_map(struct RE_plugin *plugin, mat4 light_space_transform)
|
||||
{
|
||||
if (!calc_shadow_light_transform(plugin, light_space_transform)) {
|
||||
// No shadow casters, but proceed anyway to clear the shadow texture.
|
||||
glm_mat4_identity(light_space_transform);
|
||||
}
|
||||
|
||||
struct RE_renderer *r = plugin->renderer;
|
||||
GLint orig_fbo, orig_viewport[4];
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &orig_fbo);
|
||||
glGetIntegerv(GL_VIEWPORT, orig_viewport);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, r->shadow.fbo);
|
||||
glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT);
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
glUseProgram(r->shadow.program);
|
||||
|
||||
glUniformMatrix4fv(r->shadow.view_transform, 1, GL_FALSE, light_space_transform[0]);
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
// Render the shadow casters.
|
||||
for (int i = 0; i < plugin->nr_instances; i++) {
|
||||
struct RE_instance *inst = plugin->instances[i];
|
||||
if (!inst || !inst->make_shadow || !inst->model)
|
||||
continue;
|
||||
struct model *model = inst->model;
|
||||
if (model->nr_bones > 0) {
|
||||
glUniform1i(r->shadow.has_bones, GL_TRUE);
|
||||
glUniformMatrix4fv(r->shadow.bone_matrices, model->nr_bones, GL_FALSE, inst->bone_transforms[0][0]);
|
||||
} else {
|
||||
glUniform1i(r->shadow.has_bones, GL_FALSE);
|
||||
}
|
||||
glUniformMatrix4fv(r->shadow.world_transform, 1, GL_FALSE, inst->local_transform[0]);
|
||||
for (int j = 0; j < model->nr_meshes; j++) {
|
||||
struct mesh *mesh = &model->meshes[j];
|
||||
glBindVertexArray(mesh->vao);
|
||||
glDrawArrays(GL_TRIANGLES, 0, mesh->nr_vertices);
|
||||
}
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, orig_fbo);
|
||||
glViewport(orig_viewport[0], orig_viewport[1], orig_viewport[2], orig_viewport[3]);
|
||||
}
|
||||
|
||||
static void render_back_cg(struct texture *dst, struct RE_back_cg *bcg, struct RE_renderer *r)
|
||||
{
|
||||
if (!bcg->texture.handle)
|
||||
@@ -360,6 +548,12 @@ void RE_render(struct sact_sprite *sp)
|
||||
sprite_dirty(sp);
|
||||
struct texture *texture = sprite_get_texture(sp);
|
||||
|
||||
mat4 shadow_transform;
|
||||
if (plugin->shadow_mode)
|
||||
render_shadow_map(plugin, shadow_transform);
|
||||
else
|
||||
glm_mat4_identity(shadow_transform);
|
||||
|
||||
GLuint fbo = gfx_set_framebuffer(GL_DRAW_FRAMEBUFFER, texture, 0, 0, texture->w, texture->h);
|
||||
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, r->depth_buffer);
|
||||
if (glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||
@@ -388,9 +582,11 @@ void RE_render(struct sact_sprite *sp)
|
||||
plugin->proj_transform[1][1] *= -1;
|
||||
glFrontFace(GL_CW);
|
||||
|
||||
glUseProgram(r->shader.program);
|
||||
glUniformMatrix4fv(r->shader.view_transform, 1, GL_FALSE, view_transform[0]);
|
||||
glUseProgram(r->program);
|
||||
glUniformMatrix4fv(r->view_transform, 1, GL_FALSE, view_transform[0]);
|
||||
glUniformMatrix4fv(r->proj_transform, 1, GL_FALSE, plugin->proj_transform[0]);
|
||||
glUniformMatrix4fv(r->shadow_transform, 1, GL_FALSE, shadow_transform[0]);
|
||||
glUniform1f(r->shadow_bias, plugin->shadow_bias);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
+102
-15
@@ -285,9 +285,35 @@ static bool ReignEngine_SetInstanceDraw(int plugin, int instance, bool flag)
|
||||
return true;
|
||||
}
|
||||
|
||||
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, SetInstanceDrawShadow, int plugin, int instance, bool flag);
|
||||
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, SetInstanceDrawBackShadow, int plugin, int instance, bool flag);
|
||||
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, SetInstanceDrawMakeShadow, int plugin, int instance, bool flag);
|
||||
static bool ReignEngine_SetInstanceDrawShadow(int plugin, int instance, bool flag)
|
||||
{
|
||||
struct RE_instance *ri = get_instance(plugin, instance);
|
||||
if (!ri)
|
||||
return false;
|
||||
ri->draw_shadow = flag;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ReignEngine_SetInstanceDrawBackShadow(int plugin, int instance, bool flag)
|
||||
{
|
||||
struct RE_instance *ri = get_instance(plugin, instance);
|
||||
if (!ri)
|
||||
return false;
|
||||
if (flag) {
|
||||
WARNING("DrawBackShaodw is not supported");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ReignEngine_SetInstanceDrawMakeShadow(int plugin, int instance, bool flag)
|
||||
{
|
||||
struct RE_instance *ri = get_instance(plugin, instance);
|
||||
if (!ri)
|
||||
return false;
|
||||
ri->make_shadow = flag;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ReignEngine_SetInstanceDrawBump(int plugin, int instance, bool flag)
|
||||
{
|
||||
@@ -306,9 +332,23 @@ static bool ReignEngine_GetInstanceDraw(int plugin, int instance)
|
||||
return ri->draw;
|
||||
}
|
||||
|
||||
//bool ReignEngine_GetInstanceDrawShadow(int plugin, int instance);
|
||||
static bool ReignEngine_GetInstanceDrawShadow(int plugin, int instance)
|
||||
{
|
||||
struct RE_instance *ri = get_instance(plugin, instance);
|
||||
if (!ri)
|
||||
return false;
|
||||
return ri->draw_shadow;
|
||||
}
|
||||
|
||||
//bool ReignEngine_GetInstanceDrawBackShadow(int plugin, int instance);
|
||||
//bool ReignEngine_GetInstanceDrawMakeShadow(int plugin, int instance);
|
||||
|
||||
static bool ReignEngine_GetInstanceDrawMakeShadow(int plugin, int instance)
|
||||
{
|
||||
struct RE_instance *ri = get_instance(plugin, instance);
|
||||
if (!ri)
|
||||
return false;
|
||||
return ri->make_shadow;
|
||||
}
|
||||
|
||||
static bool ReignEngine_GetInstanceDrawBump(int plugin, int instance)
|
||||
{
|
||||
@@ -486,8 +526,22 @@ static bool ReignEngine_TransInstanceLocalPosToWorldPosByBone(int plugin, int in
|
||||
HLL_WARN_UNIMPLEMENTED(0.0, float, ReignEngine, CalcInstanceHeightDetection, int plugin, int instance, float x, float z);
|
||||
//float ReignEngine_GetInstanceSoftFogEdgeLength(int plugin, int instance);
|
||||
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, SetInstanceSoftFogEdgeLength, int plugin, int instance, float length);
|
||||
//float ReignEngine_GetInstanceShadowVolumeBoneRadius(int plugin, int instance);
|
||||
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, SetInstanceShadowVolumeBoneRadius, int plugin, int instance, float radius);
|
||||
|
||||
static float ReignEngine_GetInstanceShadowVolumeBoneRadius(int plugin, int instance)
|
||||
{
|
||||
struct RE_instance *ri = get_instance(plugin, instance);
|
||||
return ri ? ri->shadow_volume_bone_radius : 0.0;
|
||||
}
|
||||
|
||||
static bool ReignEngine_SetInstanceShadowVolumeBoneRadius(int plugin, int instance, float radius)
|
||||
{
|
||||
struct RE_instance *ri = get_instance(plugin, instance);
|
||||
if (!ri)
|
||||
return false;
|
||||
ri->shadow_volume_bone_radius = radius;
|
||||
return true;
|
||||
}
|
||||
|
||||
//bool ReignEngine_GetInstanceDebugDrawShadowVolume(int plugin, int instance);
|
||||
//bool ReignEngine_SetInstanceDebugDrawShadowVolume(int plugin, int instance, bool flag);
|
||||
//bool ReignEngine_SaveEffect(int plugin, int instance);
|
||||
@@ -662,11 +716,44 @@ static int ReignEngine_GetShadowMapResolutionLevel(int plugin)
|
||||
}
|
||||
|
||||
//float ReignEngine_GetShadowSplitDepth(int plugin, int num);
|
||||
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, SetShadowMapType, int plugin, int type);
|
||||
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, SetShadowMapLightLookPos, int plugin, float x, float y, float z);
|
||||
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, SetShadowMapLightDir, int plugin, float x, float y, float z);
|
||||
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, SetShadowBox, int plugin, float x, float y, float z, float size_x, float size_y, float size_z);
|
||||
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, SetShadowBias, int plugin, int num, float shadow_bias);
|
||||
|
||||
static bool ReignEngine_SetShadowMapType(int plugin, int type)
|
||||
{
|
||||
// Toushin Toshi 3 uses only type 0.
|
||||
if (type != 0)
|
||||
WARNING("non-zero shadow map type is not supported");
|
||||
return true;
|
||||
}
|
||||
|
||||
HLL_QUIET_UNIMPLEMENTED(true, bool, ReignEngine, SetShadowMapLightLookPos, int plugin, float x, float y, float z); // no-op in shadow map type 0?
|
||||
|
||||
static bool ReignEngine_SetShadowMapLightDir(int plugin, float x, float y, float z)
|
||||
{
|
||||
struct RE_plugin *p = get_plugin(plugin);
|
||||
if (!p)
|
||||
return false;
|
||||
p->shadow_map_light_dir[0] = x;
|
||||
p->shadow_map_light_dir[1] = y;
|
||||
p->shadow_map_light_dir[2] = -z;
|
||||
glm_vec3_normalize(p->shadow_map_light_dir);
|
||||
return true;
|
||||
}
|
||||
|
||||
HLL_QUIET_UNIMPLEMENTED(true, bool, ReignEngine, SetShadowBox, int plugin, float x, float y, float z, float size_x, float size_y, float size_z); // no-op in shadow map type 0?
|
||||
|
||||
static bool ReignEngine_SetShadowBias(int plugin, int num, float shadow_bias)
|
||||
{
|
||||
struct RE_plugin *p = get_plugin(plugin);
|
||||
if (!p)
|
||||
return false;
|
||||
if (num != 0) {
|
||||
WARNING("SetShadowBias(num=%d): not supported", num);
|
||||
return false;
|
||||
}
|
||||
p->shadow_bias = shadow_bias;
|
||||
return true;
|
||||
}
|
||||
|
||||
//bool ReignEngine_SetShadowSlopeBias(int plugin, float fShadowSlopeBias);
|
||||
//bool ReignEngine_SetShadowFilterMag(int plugin, float fShadowFilterMag);
|
||||
//bool ReignEngine_SetShadowTargetDistance(int plugin, int num, float fDistance);
|
||||
@@ -1194,9 +1281,9 @@ HLL_LIBRARY(ReignEngine,
|
||||
HLL_EXPORT(SetInstanceDrawMakeShadow, ReignEngine_SetInstanceDrawMakeShadow),
|
||||
HLL_EXPORT(SetInstanceDrawBump, ReignEngine_SetInstanceDrawBump),
|
||||
HLL_EXPORT(GetInstanceDraw, ReignEngine_GetInstanceDraw),
|
||||
HLL_TODO_EXPORT(GetInstanceDrawShadow, ReignEngine_GetInstanceDrawShadow),
|
||||
HLL_EXPORT(GetInstanceDrawShadow, ReignEngine_GetInstanceDrawShadow),
|
||||
HLL_TODO_EXPORT(GetInstanceDrawBackShadow, ReignEngine_GetInstanceDrawBackShadow),
|
||||
HLL_TODO_EXPORT(GetInstanceDrawMakeShadow, ReignEngine_GetInstanceDrawMakeShadow),
|
||||
HLL_EXPORT(GetInstanceDrawMakeShadow, ReignEngine_GetInstanceDrawMakeShadow),
|
||||
HLL_EXPORT(GetInstanceDrawBump, ReignEngine_GetInstanceDrawBump),
|
||||
HLL_TODO_EXPORT(GetInstanceDrawType, ReignEngine_GetInstanceDrawType),
|
||||
HLL_EXPORT(SetInstanceDrawType, ReignEngine_SetInstanceDrawType),
|
||||
@@ -1253,7 +1340,7 @@ HLL_LIBRARY(ReignEngine,
|
||||
HLL_EXPORT(CalcInstanceHeightDetection, ReignEngine_CalcInstanceHeightDetection),
|
||||
HLL_TODO_EXPORT(GetInstanceSoftFogEdgeLength, ReignEngine_GetInstanceSoftFogEdgeLength),
|
||||
HLL_EXPORT(SetInstanceSoftFogEdgeLength, ReignEngine_SetInstanceSoftFogEdgeLength),
|
||||
HLL_TODO_EXPORT(GetInstanceShadowVolumeBoneRadius, ReignEngine_GetInstanceShadowVolumeBoneRadius),
|
||||
HLL_EXPORT(GetInstanceShadowVolumeBoneRadius, ReignEngine_GetInstanceShadowVolumeBoneRadius),
|
||||
HLL_EXPORT(SetInstanceShadowVolumeBoneRadius, ReignEngine_SetInstanceShadowVolumeBoneRadius),
|
||||
HLL_TODO_EXPORT(GetInstanceDebugDrawShadowVolume, ReignEngine_GetInstanceDebugDrawShadowVolume),
|
||||
HLL_TODO_EXPORT(SetInstanceDebugDrawShadowVolume, ReignEngine_SetInstanceDebugDrawShadowVolume),
|
||||
|
||||
+3
-8
@@ -89,7 +89,7 @@ static GLchar *read_shader_file(const char *path)
|
||||
return source;
|
||||
}
|
||||
|
||||
static GLuint load_shader_file(const char *path, GLenum type)
|
||||
GLuint gfx_load_shader_file(const char *path, GLenum type)
|
||||
{
|
||||
GLint shader_compiled;
|
||||
GLuint shader;
|
||||
@@ -115,16 +115,11 @@ static GLuint load_shader_file(const char *path, GLenum type)
|
||||
void gfx_load_shader(struct shader *dst, const char *vertex_shader_path, const char *fragment_shader_path)
|
||||
{
|
||||
GLuint program = glCreateProgram();
|
||||
GLuint vertex_shader = load_shader_file(vertex_shader_path, GL_VERTEX_SHADER);
|
||||
GLuint fragment_shader = load_shader_file(fragment_shader_path, GL_FRAGMENT_SHADER);
|
||||
GLuint vertex_shader = gfx_load_shader_file(vertex_shader_path, GL_VERTEX_SHADER);
|
||||
GLuint fragment_shader = gfx_load_shader_file(fragment_shader_path, GL_FRAGMENT_SHADER);
|
||||
|
||||
glAttachShader(program, vertex_shader);
|
||||
glAttachShader(program, fragment_shader);
|
||||
|
||||
// In OpenGL < 3.2, Attribute location 0 is special. Make sure it's assigned
|
||||
// to the vertex position.
|
||||
glBindAttribLocation(program, 0, "vertex_pos");
|
||||
|
||||
glLinkProgram(program);
|
||||
|
||||
GLint link_success;
|
||||
|
||||
Reference in New Issue
Block a user