[Evas/evas-3d] Add shadow maps. Added two scene-API functions for enable and disable shadows on the scene. Added 6 light-API function for set and get the light projection.
Reviewers: raster, cedric, Hermet Subscribers: raster, cedric Differential Revision: https://phab.enlightenment.org/D1330
This commit is contained in:
parent
d1dd349feb
commit
0d2f4dbc11
|
@ -0,0 +1,313 @@
|
|||
/*
|
||||
* This example illustrating use of shadows in the scene.
|
||||
*
|
||||
* @see evas_3d_scene_shadows_enable_set(Eina_Bool _shadows_enabled)
|
||||
*
|
||||
* Compile with "gcc -o evas-3d-shadows evas-3d-shadows.c `pkg-config --libs --cflags evas ecore ecore-evas eo` -lm"
|
||||
*/
|
||||
|
||||
|
||||
#define EFL_EO_API_SUPPORT
|
||||
#define EFL_BETA_API_SUPPORT
|
||||
|
||||
#include <Eo.h>
|
||||
#include <Evas.h>
|
||||
#include <Ecore.h>
|
||||
#include <Ecore_Evas.h>
|
||||
#include <math.h>
|
||||
|
||||
#define WIDTH 1024
|
||||
#define HEIGHT 1024
|
||||
|
||||
Ecore_Evas *ecore_evas = NULL;
|
||||
Evas *evas = NULL;
|
||||
Eo *background = NULL;
|
||||
Eo *image = NULL;
|
||||
|
||||
Eo *scene = NULL;
|
||||
Eo *root_node = NULL;
|
||||
Eo *camera_node = NULL;
|
||||
Eo *light_node = NULL;
|
||||
Eo *camera = NULL;
|
||||
Eo *mesh_node = NULL;
|
||||
Eo *mesh_node1 = NULL;
|
||||
Eo *mesh = NULL;
|
||||
Eo *mesh1 = NULL;
|
||||
Eo *material = NULL;
|
||||
Eo *material1 = NULL;
|
||||
Eo *texture = NULL;
|
||||
Eo *light = NULL;
|
||||
Ecore_Animator *anim = NULL;
|
||||
|
||||
static Eina_Bool
|
||||
_animate_scene(void *data)
|
||||
{
|
||||
static int frame = 0;
|
||||
|
||||
eo_do((Evas_3D_Node *)data, evas_3d_node_mesh_frame_set(mesh, frame));
|
||||
|
||||
frame += 32;
|
||||
|
||||
if (frame > 256 * 50) frame = 0;
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_on_delete(Ecore_Evas *ee EINA_UNUSED)
|
||||
{
|
||||
ecore_main_loop_quit();
|
||||
}
|
||||
|
||||
static void
|
||||
_on_canvas_resize(Ecore_Evas *ee)
|
||||
{
|
||||
int w, h;
|
||||
|
||||
ecore_evas_geometry_get(ee, NULL, NULL, &w, &h);
|
||||
eo_do(background, evas_obj_size_set(w, h));
|
||||
eo_do(image, evas_obj_size_set(w, h));
|
||||
}
|
||||
|
||||
static double pi = 3.14159265359;
|
||||
typedef struct _vec3
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
} vec3;
|
||||
|
||||
typedef struct _vec4
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float w;
|
||||
} vec4;
|
||||
|
||||
static void
|
||||
_set_ball(Eo *mesh, double r, double x, double y, double z, int p, Evas_3D_Material *material)
|
||||
{
|
||||
int vcount, icount, vccount, i, j;
|
||||
double dtheta, dfi, sinth, costh, fi, theta, sinfi, cosfi;
|
||||
unsigned short *indices, *index;
|
||||
|
||||
icount = p * p * 6;
|
||||
vccount = p + 1;
|
||||
vcount = vccount * vccount;
|
||||
|
||||
dtheta = pi / p;
|
||||
dfi = 2 * pi / p;
|
||||
|
||||
vec3 *vertices = malloc(sizeof(vec3) * vcount);
|
||||
vec3 *normals = malloc(sizeof(vec3) * vcount);
|
||||
|
||||
for (j = 0; j < vccount; j++)
|
||||
{
|
||||
theta = j * dtheta;
|
||||
sinth = sin(theta);
|
||||
costh = cos(theta);
|
||||
for (i = 0; i < vccount; i++)
|
||||
{
|
||||
fi = i * dfi;
|
||||
sinfi = sin(fi);
|
||||
cosfi = cos(fi);
|
||||
vertices[i + j * vccount].x = r * sinth * cosfi + x;
|
||||
vertices[i + j * vccount].y = r * sinth * sinfi + y;
|
||||
vertices[i + j * vccount].z = r * costh + z;
|
||||
|
||||
normals[i + j * vccount].x = sinth * cosfi;
|
||||
normals[i + j * vccount].y = sinth * sinfi;
|
||||
normals[i + j * vccount].z = costh;
|
||||
}
|
||||
}
|
||||
|
||||
indices = malloc(sizeof(short) * icount);
|
||||
index = &indices[0];
|
||||
|
||||
for(j = 0; j < p; j++)
|
||||
for(i = 0; i < p; i++)
|
||||
{
|
||||
*index++ = (unsigned short)(i + vccount * j);
|
||||
*index++ = i + vccount * (j + 1);
|
||||
*index++ = i + 1 + vccount * (j + 1);
|
||||
|
||||
*index++ = i + vccount * j;
|
||||
*index++ = i + 1 + vccount * j;
|
||||
*index++ = i + vccount * (j + 1) + 1;
|
||||
}
|
||||
|
||||
eo_do(mesh, evas_3d_mesh_vertex_count_set(vcount),
|
||||
evas_3d_mesh_frame_add(0);
|
||||
evas_3d_mesh_frame_vertex_data_copy_set(0, EVAS_3D_VERTEX_POSITION,
|
||||
sizeof(vec3), &vertices[0]);
|
||||
evas_3d_mesh_frame_vertex_data_copy_set(0, EVAS_3D_VERTEX_NORMAL,
|
||||
sizeof(vec3), &normals[0]);
|
||||
evas_3d_mesh_index_data_copy_set(EVAS_3D_INDEX_FORMAT_UNSIGNED_SHORT,
|
||||
icount , &indices[0]);
|
||||
evas_3d_mesh_vertex_assembly_set(EVAS_3D_VERTEX_ASSEMBLY_TRIANGLES);
|
||||
evas_3d_mesh_shade_mode_set(EVAS_3D_SHADE_MODE_PHONG);
|
||||
evas_3d_mesh_frame_material_set(0, material));
|
||||
|
||||
free(vertices);
|
||||
free(normals);
|
||||
free(indices);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
//Unless Evas 3D supports Software renderer, we set gl backened forcely.
|
||||
setenv("ECORE_EVAS_ENGINE", "opengl_x11", 1);
|
||||
|
||||
if (!ecore_evas_init()) return 0;
|
||||
|
||||
ecore_evas = ecore_evas_new(NULL, 10, 10, WIDTH, HEIGHT, NULL);
|
||||
|
||||
if (!ecore_evas) return 0;
|
||||
|
||||
ecore_evas_callback_delete_request_set(ecore_evas, _on_delete);
|
||||
ecore_evas_callback_resize_set(ecore_evas, _on_canvas_resize);
|
||||
ecore_evas_show(ecore_evas);
|
||||
|
||||
evas = ecore_evas_get(ecore_evas);
|
||||
|
||||
/* Add a scene object .*/
|
||||
scene = eo_add(EVAS_3D_SCENE_CLASS, evas);
|
||||
|
||||
/* Add the root node for the scene. */
|
||||
root_node = eo_add_custom(EVAS_3D_NODE_CLASS, evas,
|
||||
evas_3d_node_constructor(EVAS_3D_NODE_TYPE_NODE));
|
||||
|
||||
/* Add the camera. */
|
||||
camera = eo_add(EVAS_3D_CAMERA_CLASS, evas);
|
||||
eo_do(camera,
|
||||
evas_3d_camera_projection_perspective_set(60.0, 1.0, 1.0, 1000.0));
|
||||
|
||||
camera_node =
|
||||
eo_add_custom(EVAS_3D_NODE_CLASS, evas,
|
||||
evas_3d_node_constructor(EVAS_3D_NODE_TYPE_CAMERA));
|
||||
eo_do(camera_node,
|
||||
evas_3d_node_camera_set(camera));
|
||||
eo_do(root_node,
|
||||
evas_3d_node_member_add(camera_node));
|
||||
eo_do(camera_node,
|
||||
evas_3d_node_position_set(100.0, 0.0, 20.0),
|
||||
evas_3d_node_look_at_set(EVAS_3D_SPACE_PARENT, 0.0, 0.0, 20.0,
|
||||
EVAS_3D_SPACE_PARENT, 0.0, 0.0, 1.0));
|
||||
/* Add the light. */
|
||||
light = eo_add(EVAS_3D_LIGHT_CLASS, evas);
|
||||
eo_do(light,
|
||||
evas_3d_light_ambient_set(0.2, 0.2, 0.2, 1.0),
|
||||
evas_3d_light_diffuse_set(1.0, 1.0, 1.0, 1.0),
|
||||
evas_3d_light_specular_set(1.0, 1.0, 1.0, 1.0),
|
||||
evas_3d_light_projection_perspective_set(45.0, 1.0, 2.0, 1000.0));
|
||||
|
||||
light_node =
|
||||
eo_add_custom(EVAS_3D_NODE_CLASS, evas,
|
||||
evas_3d_node_constructor(EVAS_3D_NODE_TYPE_LIGHT));
|
||||
eo_do(light_node,
|
||||
evas_3d_node_light_set(light),
|
||||
evas_3d_node_position_set(100.0, 30.0, 20.0),
|
||||
evas_3d_node_look_at_set(EVAS_3D_SPACE_PARENT, 0.0, 0.0, 20.0,
|
||||
EVAS_3D_SPACE_PARENT, 0.0, 0.0, 1.0));
|
||||
eo_do(root_node,
|
||||
evas_3d_node_member_add(light_node));
|
||||
|
||||
/* Add the mesh. */
|
||||
mesh = eo_add(EVAS_3D_MESH_CLASS, evas);
|
||||
material = eo_add(EVAS_3D_MATERIAL_CLASS, evas);
|
||||
|
||||
eo_do(mesh,
|
||||
evas_3d_mesh_file_set(EVAS_3D_MESH_FILE_TYPE_MD2, "sonic.md2", NULL),
|
||||
evas_3d_mesh_frame_material_set(0, material),
|
||||
evas_3d_mesh_shade_mode_set(EVAS_3D_SHADE_MODE_PHONG));
|
||||
|
||||
texture = eo_add(EVAS_3D_TEXTURE_CLASS, evas);
|
||||
eo_do(texture,
|
||||
evas_3d_texture_file_set("sonic.png", NULL),
|
||||
evas_3d_texture_filter_set(EVAS_3D_TEXTURE_FILTER_NEAREST,
|
||||
EVAS_3D_TEXTURE_FILTER_NEAREST),
|
||||
evas_3d_texture_wrap_set(EVAS_3D_WRAP_MODE_REPEAT,
|
||||
EVAS_3D_WRAP_MODE_REPEAT));
|
||||
|
||||
eo_do(material,
|
||||
evas_3d_material_texture_set(EVAS_3D_MATERIAL_DIFFUSE, texture),
|
||||
evas_3d_material_texture_set(EVAS_3D_MATERIAL_AMBIENT, texture),
|
||||
evas_3d_material_enable_set(EVAS_3D_MATERIAL_AMBIENT, EINA_TRUE),
|
||||
evas_3d_material_enable_set(EVAS_3D_MATERIAL_DIFFUSE, EINA_TRUE),
|
||||
evas_3d_material_enable_set(EVAS_3D_MATERIAL_SPECULAR, EINA_TRUE),
|
||||
evas_3d_material_enable_set(EVAS_3D_MATERIAL_NORMAL, EINA_TRUE),
|
||||
evas_3d_material_color_set(EVAS_3D_MATERIAL_AMBIENT,
|
||||
1.0, 1.0, 1.0, 1.0),
|
||||
evas_3d_material_color_set(EVAS_3D_MATERIAL_DIFFUSE,
|
||||
1.0, 1.0, 1.0, 1.0),
|
||||
evas_3d_material_color_set(EVAS_3D_MATERIAL_SPECULAR,
|
||||
1.0, 1.0, 1.0, 1.0),
|
||||
evas_3d_material_shininess_set(50.0));
|
||||
|
||||
mesh_node = eo_add_custom(EVAS_3D_NODE_CLASS, evas,
|
||||
evas_3d_node_constructor(EVAS_3D_NODE_TYPE_MESH));
|
||||
eo_do(root_node,
|
||||
evas_3d_node_member_add(mesh_node));
|
||||
eo_do(mesh_node,
|
||||
evas_3d_node_mesh_add(mesh));
|
||||
|
||||
material1 = eo_add(EVAS_3D_MATERIAL_CLASS, evas);
|
||||
|
||||
eo_do(material1,
|
||||
evas_3d_material_enable_set(EVAS_3D_MATERIAL_AMBIENT, EINA_TRUE),
|
||||
evas_3d_material_enable_set(EVAS_3D_MATERIAL_DIFFUSE, EINA_TRUE),
|
||||
evas_3d_material_enable_set(EVAS_3D_MATERIAL_SPECULAR, EINA_TRUE),
|
||||
|
||||
evas_3d_material_color_set(EVAS_3D_MATERIAL_AMBIENT, 1.0, 1.0, 1.0, 1.0),
|
||||
evas_3d_material_color_set(EVAS_3D_MATERIAL_DIFFUSE, 0.8, 0.8, 0.8, 1.0),
|
||||
evas_3d_material_color_set(EVAS_3D_MATERIAL_SPECULAR, 1.0, 1.0, 1.0, 1.0),
|
||||
evas_3d_material_shininess_set(100.0));
|
||||
|
||||
mesh1 = eo_add(EVAS_3D_MESH_CLASS, evas);
|
||||
_set_ball(mesh1, 100, -200, 0, 0, 100, material1);
|
||||
|
||||
|
||||
mesh_node1 =
|
||||
eo_add_custom(EVAS_3D_NODE_CLASS, evas,
|
||||
evas_3d_node_constructor(EVAS_3D_NODE_TYPE_MESH));
|
||||
eo_do(root_node, evas_3d_node_member_add(mesh_node1));
|
||||
eo_do(mesh_node1, evas_3d_node_mesh_add(mesh1));
|
||||
|
||||
/* Set up scene. */
|
||||
eo_do(scene,
|
||||
evas_3d_scene_root_node_set(root_node),
|
||||
evas_3d_scene_camera_node_set(camera_node),
|
||||
evas_3d_scene_size_set(WIDTH, HEIGHT),
|
||||
evas_3d_scene_shadows_enable_set(EINA_TRUE));
|
||||
|
||||
/* Add a background rectangle objects. */
|
||||
background = eo_add(EVAS_RECTANGLE_CLASS, evas);
|
||||
eo_unref(background);
|
||||
eo_do(background,
|
||||
evas_obj_color_set(0, 0, 0, 255),
|
||||
evas_obj_size_set(WIDTH, HEIGHT),
|
||||
evas_obj_visibility_set(EINA_TRUE));
|
||||
|
||||
/* Add an image object for 3D scene rendering. */
|
||||
image = evas_object_image_filled_add(evas);
|
||||
eo_do(image,
|
||||
evas_obj_size_set(WIDTH, HEIGHT),
|
||||
evas_obj_visibility_set(EINA_TRUE));
|
||||
|
||||
/* Set the image object as render target for 3D scene. */
|
||||
eo_do(image, evas_obj_image_scene_set(scene));
|
||||
|
||||
/* Add animator. */
|
||||
ecore_animator_frametime_set(0.008);
|
||||
anim = ecore_animator_add(_animate_scene, mesh_node);
|
||||
|
||||
/* Enter main loop. */
|
||||
ecore_main_loop_begin();
|
||||
|
||||
ecore_evas_free(ecore_evas);
|
||||
ecore_evas_shutdown();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -465,6 +465,7 @@ typedef enum _Evas_3D_State
|
|||
EVAS_3D_STATE_SCENE_CAMERA_NODE,
|
||||
EVAS_3D_STATE_SCENE_BACKGROUND_COLOR,
|
||||
EVAS_3D_STATE_SCENE_SIZE,
|
||||
EVAS_3D_STATE_SCENE_SHADOWS_ENABLED,
|
||||
|
||||
EVAS_3D_STATE_TEXTURE_DATA = 1,
|
||||
EVAS_3D_STATE_TEXTURE_WRAP,
|
||||
|
@ -493,6 +494,7 @@ typedef enum _Evas_3D_State
|
|||
EVAS_3D_STATE_LIGHT_SPOT_EXP,
|
||||
EVAS_3D_STATE_LIGHT_SPOT_CUTOFF,
|
||||
EVAS_3D_STATE_LIGHT_ATTENUATION,
|
||||
EVAS_3D_STATE_LIGHT_PROJECTION,
|
||||
|
||||
EVAS_3D_STATE_NODE_TRANSFORM = 1,
|
||||
EVAS_3D_STATE_NODE_MESH_GEOMETRY,
|
||||
|
@ -681,7 +683,10 @@ typedef enum _Evas_3D_Shade_Mode
|
|||
/**< Per-pixel phong shading */
|
||||
EVAS_3D_SHADE_MODE_PHONG,
|
||||
/**< Per-pixel normal map shading */
|
||||
EVAS_3D_SHADE_MODE_NORMAL_MAP
|
||||
EVAS_3D_SHADE_MODE_NORMAL_MAP,
|
||||
/**< fragment color is defined by its z-coord*/
|
||||
EVAS_3D_SHADE_MODE_SHADOW_MAP_RENDER,
|
||||
|
||||
} Evas_3D_Shade_Mode;
|
||||
|
||||
/**
|
||||
|
|
|
@ -239,4 +239,56 @@ _evas_3d_light_attenuation_enable_get(Eo *obj EINA_UNUSED, Evas_3D_Light_Data *p
|
|||
return pd->enable_attenuation;
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_evas_3d_light_projection_matrix_set(Eo *obj, Evas_3D_Light_Data *pd,
|
||||
const Evas_Real *matrix)
|
||||
{
|
||||
evas_mat4_array_set(&pd->projection, matrix);
|
||||
eo_do(obj, evas_3d_object_change(EVAS_3D_STATE_LIGHT_PROJECTION, NULL));
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_evas_3d_light_projection_matrix_get(Eo *obj EINA_UNUSED,
|
||||
Evas_3D_Light_Data *pd,
|
||||
Evas_Real *matrix)
|
||||
{
|
||||
memcpy(matrix, &pd->projection.m[0], sizeof(Evas_Real) * 16);
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_evas_3d_light_projection_perspective_set(Eo *obj, Evas_3D_Light_Data *pd,
|
||||
Evas_Real fovy, Evas_Real aspect,
|
||||
Evas_Real dnear, Evas_Real dfar)
|
||||
{
|
||||
Evas_Real xmax;
|
||||
Evas_Real ymax;
|
||||
|
||||
ymax = dnear * (Evas_Real)tan((double)fovy * M_PI / 360.0);
|
||||
xmax = ymax * aspect;
|
||||
|
||||
evas_mat4_frustum_set(&pd->projection, -xmax, xmax, -ymax, ymax, dnear, dfar);
|
||||
eo_do(obj, evas_3d_object_change(EVAS_3D_STATE_LIGHT_PROJECTION, NULL));
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_evas_3d_light_projection_frustum_set(Eo *obj, Evas_3D_Light_Data *pd,
|
||||
Evas_Real left, Evas_Real right,
|
||||
Evas_Real bottom, Evas_Real top,
|
||||
Evas_Real dnear, Evas_Real dfar)
|
||||
{
|
||||
evas_mat4_frustum_set(&pd->projection, left, right, bottom, top, dnear, dfar);
|
||||
eo_do(obj, evas_3d_object_change(EVAS_3D_STATE_LIGHT_PROJECTION, NULL));
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_evas_3d_light_projection_ortho_set(Eo *obj, Evas_3D_Light_Data *pd,
|
||||
Evas_Real left, Evas_Real right,
|
||||
Evas_Real bottom, Evas_Real top,
|
||||
Evas_Real dnear, Evas_Real dfar)
|
||||
{
|
||||
evas_mat4_ortho_set(&pd->projection, left, right, bottom, top, dnear, dfar);
|
||||
eo_do(obj, evas_3d_object_change(EVAS_3D_STATE_LIGHT_PROJECTION, NULL));
|
||||
}
|
||||
|
||||
|
||||
#include "canvas/evas_3d_light.eo.c"
|
||||
|
|
|
@ -249,6 +249,100 @@ class Evas_3D_Light (Evas_3D_Object, Evas.Common_Interface)
|
|||
@out Evas_Real quadratic; /*@ Quadratic attenuation term..*/
|
||||
}
|
||||
}
|
||||
|
||||
projection_matrix_set {
|
||||
/*@
|
||||
Set the projection matrix of the given light source.
|
||||
|
||||
@param light The given light source.
|
||||
@param matrix Pointer to the array of 16 Evas_Real values in column major order.
|
||||
|
||||
Default projection matrix is identity matrix.
|
||||
|
||||
@see evas_3d_light_projection_perspective_set()
|
||||
@see evas_3d_light_projection_ortho_set()
|
||||
@see evas_3d_light_projection_frustum_set()
|
||||
|
||||
@ingroup Evas_3D_Light
|
||||
*/
|
||||
params {
|
||||
@in const(Evas_Real) *matrix; /*@ Projection Matrix */
|
||||
}
|
||||
}
|
||||
|
||||
projection_matrix_get @const {
|
||||
/*@
|
||||
Get the projection matrix of the given light source.
|
||||
|
||||
@param light The given light source.
|
||||
@param matrix Pointer to receive the 16 Evas_Real values in column major order.
|
||||
|
||||
@see evas_3d_light_projection_matrix_set()
|
||||
|
||||
@ingroup Evas_3D_Light
|
||||
*/
|
||||
params {
|
||||
@out Evas_Real matrix; /*@ Projection Matrix */
|
||||
}
|
||||
}
|
||||
|
||||
projection_perspective_set {
|
||||
/*@
|
||||
Set the projection matrix of the given light source with perspective projection.
|
||||
|
||||
@param light The given light source.
|
||||
@param fovy Field of view angle in Y direction.
|
||||
@param aspect Aspect ratio.
|
||||
@param dnear Distance to near clipping plane.
|
||||
@param dfar Distance to far clipping plane.
|
||||
|
||||
@see evas_3d_light_projection_matrix_set()
|
||||
|
||||
@ingroup Evas_3D_Light
|
||||
*/
|
||||
|
||||
params {
|
||||
Evas_Real fovy; /*@ Field of view angle in Y direction. */
|
||||
Evas_Real aspect; /*@ Aspect ratio.*/
|
||||
Evas_Real dnear; /*@ Distance to near clipping plane. */
|
||||
Evas_Real dfar; /*@ Distance to far clipping plane. */
|
||||
}
|
||||
}
|
||||
|
||||
projection_frustum_set {
|
||||
/*@
|
||||
Set the projection matrix of the given light source with frustum projection.
|
||||
|
||||
@see evas_3d_Light_projection_matrix_set()
|
||||
|
||||
@ingroup Evas_3D_Light
|
||||
*/
|
||||
params {
|
||||
Evas_Real left; /*@ Left X coordinate of the near clipping plane. */
|
||||
Evas_Real right; /*@ Right X coordinate of the near clipping plane..*/
|
||||
Evas_Real bottom; /*@ Bottom Y coordinate of the near clipping plane. */
|
||||
Evas_Real top; /*@ Top Y coordinate of the near clipping plane */
|
||||
Evas_Real dnear; /*@ Distance to near clipping plane. */
|
||||
Evas_Real dfar; /*@ Distance to far clipping plane. */
|
||||
}
|
||||
}
|
||||
projection_ortho_set {
|
||||
/*@
|
||||
Set the projection matrix of the given light source with orthogonal projection.
|
||||
|
||||
@see evas_3d_light_projection_matrix_set()
|
||||
|
||||
@ingroup Evas_3D_Light
|
||||
*/
|
||||
params {
|
||||
Evas_Real left; /*@ Left X coordinate of the near clipping plane. */
|
||||
Evas_Real right; /*@ Right X coordinate of the near clipping plane..*/
|
||||
Evas_Real bottom; /*@ Bottom Y coordinate of the near clipping plane. */
|
||||
Evas_Real top; /*@ Top Y coordinate of the near clipping plane */
|
||||
Evas_Real dnear; /*@ Distance to near clipping plane. */
|
||||
Evas_Real dfar; /*@ Distance to far clipping plane. */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
implements {
|
||||
|
|
|
@ -65,6 +65,7 @@ _evas_3d_scene_eo_base_constructor(Eo *obj, Evas_3D_Scene_Data *pd)
|
|||
eo_do_super(obj, MY_CLASS, eo_constructor());
|
||||
eo_do(obj, evas_3d_object_type_set(EVAS_3D_OBJECT_TYPE_SCENE));
|
||||
evas_color_set(&pd->bg_color, 0.0, 0.0, 0.0, 0.0);
|
||||
pd->shadows_enabled = EINA_FALSE;
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
|
@ -710,4 +711,17 @@ _evas_3d_scene_pick_member_list_get(Eo *obj, Evas_3D_Scene_Data *pd, Evas_Real x
|
|||
return picked_nodes;
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Bool
|
||||
_evas_3d_scene_shadows_enable_get(Eo *obj EINA_UNUSED, Evas_3D_Scene_Data *pd)
|
||||
{
|
||||
return pd->shadows_enabled;
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_evas_3d_scene_shadows_enable_set(Eo *obj EINA_UNUSED, Evas_3D_Scene_Data *pd, Eina_Bool _shadows_enabled)
|
||||
{
|
||||
pd->shadows_enabled = _shadows_enabled;
|
||||
eo_do(obj, evas_3d_object_change(EVAS_3D_STATE_SCENE_SHADOWS_ENABLED, NULL));
|
||||
}
|
||||
|
||||
#include "canvas/evas_3d_scene.eo.c"
|
||||
|
|
|
@ -111,6 +111,31 @@ class Evas_3D_Scene (Evas_3D_Object, Evas.Common_Interface)
|
|||
@in Evas_Real y; /*@ Y coordinate of the picking position. */
|
||||
}
|
||||
}
|
||||
shadows_enable_set {
|
||||
/*
|
||||
Enable or disable shadows on given scene
|
||||
|
||||
If shadows_enabled @c EINA_TRUE, the objects in the scene can throw shadow to another objects located behind them.
|
||||
The depth map used for shading. Directed and projective light sources are supported.
|
||||
|
||||
@ingroup Evas_3D_Scene
|
||||
*/
|
||||
params {
|
||||
@in Eina_Bool shadows_enabled; /*@ shadows enabled status. */
|
||||
}
|
||||
}
|
||||
|
||||
shadows_enable_get @const {
|
||||
/*
|
||||
Get shadows enabled status for given scene.
|
||||
@return The shadows enabled status.
|
||||
|
||||
@ingroup Evas_3D_Scene
|
||||
*/
|
||||
return: Eina_Bool;
|
||||
params {
|
||||
}
|
||||
}
|
||||
}
|
||||
properties {
|
||||
|
||||
|
|
|
@ -2582,6 +2582,7 @@ _3d_render(Evas *eo_e, Evas_Object *eo_obj EINA_UNUSED,
|
|||
evas_3d_scene_data_init(&scene_data);
|
||||
|
||||
scene_data.bg_color = pd_scene->bg_color;
|
||||
scene_data.shadows_enabled = pd_scene->shadows_enabled;
|
||||
scene_data.camera_node = pd_scene->camera_node;
|
||||
|
||||
/* Phase 1 - Update scene graph tree. */
|
||||
|
|
|
@ -108,11 +108,12 @@ struct _Evas_3D_Scene
|
|||
{
|
||||
Evas_3D_Node *root_node;
|
||||
Evas_3D_Node *camera_node;
|
||||
Evas_Color bg_color;
|
||||
Evas_Color bg_color;
|
||||
|
||||
void *surface;
|
||||
int w, h;
|
||||
Eina_List *images;
|
||||
Eina_Bool shadows_enabled :1;
|
||||
};
|
||||
|
||||
struct _Evas_3D_Node_Mesh
|
||||
|
@ -191,6 +192,7 @@ struct _Evas_3D_Light
|
|||
Evas_Real atten_const;
|
||||
Evas_Real atten_linear;
|
||||
Evas_Real atten_quad;
|
||||
Evas_Mat4 projection;
|
||||
|
||||
Eina_Hash *nodes;
|
||||
};
|
||||
|
@ -247,6 +249,7 @@ struct _Evas_3D_Mesh
|
|||
Evas_3D_Vertex_Assembly assembly;
|
||||
|
||||
Eina_Hash *nodes;
|
||||
Eina_Bool shadowed;
|
||||
|
||||
Evas_Color fog_color;
|
||||
Eina_Bool fog_enabled :1;
|
||||
|
@ -285,6 +288,7 @@ struct _Evas_3D_Scene_Public_Data
|
|||
Evas_3D_Node *camera_node;
|
||||
Eina_List *light_nodes;
|
||||
Eina_List *mesh_nodes;
|
||||
Eina_Bool shadows_enabled :1;
|
||||
};
|
||||
|
||||
struct _Evas_3D_Pick_Data
|
||||
|
|
|
@ -407,7 +407,7 @@ E3D_Drawable *
|
|||
e3d_drawable_new(int w, int h, int alpha, GLenum depth_format, GLenum stencil_format)
|
||||
{
|
||||
E3D_Drawable *drawable = NULL;
|
||||
GLuint tex, fbo;
|
||||
GLuint tex, fbo, texDepth;
|
||||
GLuint depth_stencil_buf = 0;
|
||||
GLuint depth_buf = 0;
|
||||
GLuint stencil_buf = 0;
|
||||
|
@ -425,6 +425,14 @@ e3d_drawable_new(int w, int h, int alpha, GLenum depth_format, GLenum stencil_fo
|
|||
else
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
||||
|
||||
glGenTextures(1, &texDepth);
|
||||
glBindTexture(GL_TEXTURE_2D, texDepth);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16, w, h, 0, GL_RGB, GL_UNSIGNED_SHORT, 0);
|
||||
|
||||
glGenFramebuffers(1, &fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
|
||||
|
@ -503,6 +511,7 @@ e3d_drawable_new(int w, int h, int alpha, GLenum depth_format, GLenum stencil_fo
|
|||
drawable->depth_stencil_buf = depth_stencil_buf;
|
||||
drawable->depth_buf = depth_buf;
|
||||
drawable->stencil_buf = stencil_buf;
|
||||
drawable->texDepth = texDepth;
|
||||
|
||||
return drawable;
|
||||
|
||||
|
@ -1076,6 +1085,7 @@ _mesh_draw_data_build(E3D_Draw_Data *data,
|
|||
const Evas_Mat4 *matrix_eye,
|
||||
const Evas_Mat4 *matrix_mv,
|
||||
const Evas_Mat4 *matrix_mvp,
|
||||
const Evas_Mat4 *matrix_light,
|
||||
const Evas_3D_Node *light)
|
||||
{
|
||||
Eina_List *l, *r;
|
||||
|
@ -1089,6 +1099,10 @@ _mesh_draw_data_build(E3D_Draw_Data *data,
|
|||
data->flags |= E3D_SHADER_FLAG_FOG_ENABLED;
|
||||
data->fog_color = pdmesh->fog_color;
|
||||
}
|
||||
|
||||
if (pdmesh->shadowed)
|
||||
data->flags |= E3D_SHADER_FLAG_SHADOWED;
|
||||
|
||||
data->mode = pdmesh->shade_mode;
|
||||
data->assembly = pdmesh->assembly;
|
||||
data->vertex_count = pdmesh->vertex_count;
|
||||
|
@ -1098,6 +1112,8 @@ _mesh_draw_data_build(E3D_Draw_Data *data,
|
|||
|
||||
evas_mat4_copy(&data->matrix_mvp, matrix_mvp);
|
||||
evas_mat4_copy(&data->matrix_mv, matrix_mv);
|
||||
if (matrix_light != NULL)
|
||||
evas_mat4_copy(&data->matrix_light, matrix_light);
|
||||
|
||||
_mesh_frame_find(mesh, frame, &l, &r);
|
||||
|
||||
|
@ -1116,6 +1132,10 @@ _mesh_draw_data_build(E3D_Draw_Data *data,
|
|||
BUILD(vertex_attrib, VERTEX_POSITION, EINA_TRUE);
|
||||
BUILD(vertex_attrib, VERTEX_COLOR, EINA_TRUE);
|
||||
}
|
||||
else if (pdmesh->shade_mode == EVAS_3D_SHADE_MODE_SHADOW_MAP_RENDER)
|
||||
{
|
||||
BUILD(vertex_attrib, VERTEX_POSITION, EINA_TRUE);
|
||||
}
|
||||
else if (pdmesh->shade_mode == EVAS_3D_SHADE_MODE_DIFFUSE)
|
||||
{
|
||||
BUILD(vertex_attrib, VERTEX_POSITION, EINA_TRUE);
|
||||
|
@ -1189,21 +1209,72 @@ _mesh_draw_data_build(E3D_Draw_Data *data,
|
|||
evas_normal_matrix_get(&data->matrix_normal, matrix_mv);
|
||||
}
|
||||
|
||||
// TODO Add correct numbering
|
||||
int num;
|
||||
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &num);
|
||||
data->smap_sampler = num - 1;
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_mesh_draw(E3D_Renderer *renderer, Evas_3D_Mesh *mesh, int frame, Evas_3D_Node *light,
|
||||
const Evas_Mat4 *matrix_eye, const Evas_Mat4 *matrix_mv, const Evas_Mat4 *matrix_mvp)
|
||||
const Evas_Mat4 *matrix_eye, const Evas_Mat4 *matrix_mv, const Evas_Mat4 *matrix_mvp, const Evas_Mat4 *matrix_light)
|
||||
{
|
||||
E3D_Draw_Data data;
|
||||
|
||||
memset(&data, 0x00, sizeof(E3D_Draw_Data));
|
||||
|
||||
if (_mesh_draw_data_build(&data, mesh, frame, matrix_eye, matrix_mv, matrix_mvp, light))
|
||||
if (_mesh_draw_data_build(&data, mesh, frame, matrix_eye, matrix_mv, matrix_mvp, matrix_light, light))
|
||||
e3d_renderer_draw(renderer, &data);
|
||||
}
|
||||
|
||||
void _shadowmap_render(E3D_Drawable *drawable, E3D_Renderer *renderer, Evas_3D_Scene_Public_Data *data, Evas_Mat4 *matrix_light_eye, Evas_3D_Node *light)
|
||||
{
|
||||
Eina_List *l;
|
||||
Evas_3D_Node *n;
|
||||
Evas_3D_Shade_Mode shade_mode;
|
||||
Evas_Color c = {1.0, 1.0, 1.0};
|
||||
|
||||
glEnable(GL_POLYGON_OFFSET_FILL);
|
||||
glPolygonOffset(4.0, 10000.0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, drawable->texDepth, 0);
|
||||
e3d_renderer_target_set(renderer, drawable);
|
||||
e3d_renderer_clear(renderer, &c);
|
||||
|
||||
Evas_3D_Node_Data *pd_light_node = eo_data_scope_get(light, EVAS_3D_NODE_CLASS);
|
||||
Evas_3D_Light_Data *pd = eo_data_scope_get(pd_light_node->data.light.light, EVAS_3D_LIGHT_CLASS);
|
||||
|
||||
EINA_LIST_FOREACH(data->mesh_nodes, l, n)
|
||||
{
|
||||
Evas_Mat4 matrix_mv;
|
||||
Evas_Mat4 matrix_mvp;
|
||||
Eina_Iterator *it;
|
||||
void *ptr;
|
||||
|
||||
Evas_3D_Node_Data *pd_mesh_node = eo_data_scope_get(n, EVAS_3D_NODE_CLASS);
|
||||
evas_mat4_multiply(&matrix_mv, matrix_light_eye, &pd_mesh_node->data.mesh.matrix_local_to_world);
|
||||
evas_mat4_multiply(&matrix_mvp, &pd->projection,
|
||||
&matrix_mv);
|
||||
|
||||
it = eina_hash_iterator_data_new(pd_mesh_node->data.mesh.node_meshes);
|
||||
|
||||
while (eina_iterator_next(it, &ptr))
|
||||
{
|
||||
Evas_3D_Node_Mesh *nm = (Evas_3D_Node_Mesh *)ptr;
|
||||
Evas_3D_Mesh_Data *pdmesh = eo_data_scope_get(nm->mesh, EVAS_3D_MESH_CLASS);
|
||||
shade_mode = pdmesh->shade_mode;
|
||||
pdmesh->shade_mode = EVAS_3D_SHADE_MODE_SHADOW_MAP_RENDER;
|
||||
_mesh_draw(renderer, nm->mesh, nm->frame, light, matrix_light_eye, &matrix_mv, &matrix_mvp, &matrix_mvp);
|
||||
pdmesh->shade_mode = shade_mode;
|
||||
}
|
||||
|
||||
eina_iterator_free(it);
|
||||
}
|
||||
|
||||
glDisable(GL_POLYGON_OFFSET_FILL);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, drawable->tex, 0);
|
||||
}
|
||||
|
||||
void
|
||||
e3d_drawable_scene_render(E3D_Drawable *drawable, E3D_Renderer *renderer, Evas_3D_Scene_Public_Data *data)
|
||||
{
|
||||
|
@ -1211,10 +1282,9 @@ e3d_drawable_scene_render(E3D_Drawable *drawable, E3D_Renderer *renderer, Evas_3
|
|||
Evas_3D_Node *n;
|
||||
const Evas_Mat4 *matrix_eye;
|
||||
Evas_3D_Node *light;
|
||||
|
||||
/* Set up render target. */
|
||||
e3d_renderer_target_set(renderer, drawable);
|
||||
e3d_renderer_clear(renderer, &data->bg_color);
|
||||
Evas_Mat4 matrix_light_eye;
|
||||
Evas_3D_Light_Data *ld;
|
||||
Evas_3D_Node_Data *pd_light_node;
|
||||
|
||||
/* Get eye matrix. */
|
||||
Evas_3D_Node_Data *pd_camera_node = eo_data_scope_get(data->camera_node, EVAS_3D_NODE_CLASS);
|
||||
|
@ -1222,27 +1292,54 @@ e3d_drawable_scene_render(E3D_Drawable *drawable, E3D_Renderer *renderer, Evas_3
|
|||
|
||||
Evas_3D_Camera_Data *pd = eo_data_scope_get(pd_camera_node->data.camera.camera, EVAS_3D_CAMERA_CLASS);
|
||||
|
||||
light = eina_list_data_get(data->light_nodes);
|
||||
|
||||
if (data->shadows_enabled)
|
||||
{
|
||||
pd_light_node = eo_data_scope_get(light, EVAS_3D_NODE_CLASS);
|
||||
evas_mat4_inverse_build(&matrix_light_eye,
|
||||
&pd_light_node->position_world, &pd_light_node ->orientation_world, &pd_light_node->scale_world);
|
||||
ld = eo_data_scope_get(pd_light_node->data.light.light, EVAS_3D_LIGHT_CLASS);
|
||||
_shadowmap_render(drawable, renderer, data, &matrix_light_eye, light);
|
||||
}
|
||||
|
||||
/* Set up render target. */
|
||||
e3d_renderer_target_set(renderer, drawable);
|
||||
e3d_renderer_clear(renderer, &data->bg_color);
|
||||
EINA_LIST_FOREACH(data->mesh_nodes, l, n)
|
||||
{
|
||||
Evas_Mat4 matrix_mv;
|
||||
Evas_Mat4 matrix_light;
|
||||
Evas_Mat4 matrix_mvp;
|
||||
Eina_Iterator *it;
|
||||
void *ptr;
|
||||
Evas_3D_Node_Data *pd_mesh_node = eo_data_scope_get(n, EVAS_3D_NODE_CLASS);
|
||||
|
||||
if (data->shadows_enabled)
|
||||
{
|
||||
evas_mat4_multiply(&matrix_mv, &matrix_light_eye,
|
||||
&pd_mesh_node->data.mesh.matrix_local_to_world);
|
||||
evas_mat4_multiply(&matrix_light, &ld->projection,
|
||||
&matrix_mv);
|
||||
}
|
||||
|
||||
evas_mat4_multiply(&matrix_mv, matrix_eye, &pd_mesh_node->data.mesh.matrix_local_to_world);
|
||||
evas_mat4_multiply(&matrix_mvp, matrix_eye, &matrix_mv);
|
||||
evas_mat4_multiply(&matrix_mvp, &pd->projection,
|
||||
&matrix_mv);
|
||||
|
||||
/* TODO: Get most effective light node. */
|
||||
light = eina_list_data_get(data->light_nodes);
|
||||
|
||||
it = eina_hash_iterator_data_new(pd_mesh_node->data.mesh.node_meshes);
|
||||
|
||||
while (eina_iterator_next(it, &ptr))
|
||||
{
|
||||
Evas_3D_Node_Mesh *nm = (Evas_3D_Node_Mesh *)ptr;
|
||||
_mesh_draw(renderer, nm->mesh, nm->frame, light, matrix_eye, &matrix_mv, &matrix_mvp);
|
||||
Evas_3D_Mesh_Data *pdmesh = eo_data_scope_get(nm->mesh, EVAS_3D_MESH_CLASS);
|
||||
if (data->shadows_enabled)
|
||||
{
|
||||
pdmesh->shadowed = EINA_TRUE;
|
||||
_mesh_draw(renderer, nm->mesh, nm->frame, light, matrix_eye, &matrix_mv, &matrix_mvp, &matrix_light);
|
||||
pdmesh->shadowed = EINA_FALSE;
|
||||
}
|
||||
else _mesh_draw(renderer, nm->mesh, nm->frame, light, matrix_eye, &matrix_mv, &matrix_mvp, NULL);
|
||||
}
|
||||
|
||||
eina_iterator_free(it);
|
||||
|
|
|
@ -36,6 +36,8 @@ typedef unsigned long E3D_Shader_Flag;
|
|||
#define E3D_SHADER_FLAG_EMISSION_TEXTURE_BLEND (1 << 27)
|
||||
#define E3D_SHADER_FLAG_NORMAL_TEXTURE_BLEND (1 << 28)
|
||||
#define E3D_SHADER_FLAG_FOG_ENABLED (1 << 29)
|
||||
#define E3D_SHADER_FLAG_SHADOWED (1 << 30)
|
||||
|
||||
|
||||
static inline Eina_Bool
|
||||
_flags_need_tex_coord(E3D_Shader_Flag flags)
|
||||
|
@ -55,6 +57,7 @@ struct _E3D_Draw_Data
|
|||
Evas_Mat4 matrix_mvp;
|
||||
Evas_Mat4 matrix_mv;
|
||||
Evas_Mat3 matrix_normal;
|
||||
Evas_Mat4 matrix_light;
|
||||
|
||||
struct {
|
||||
Evas_3D_Vertex_Buffer vertex0;
|
||||
|
@ -81,6 +84,8 @@ struct _E3D_Draw_Data
|
|||
|
||||
Evas_Real shininess;
|
||||
|
||||
GLint smap_sampler;
|
||||
|
||||
struct {
|
||||
Evas_Vec4 position;
|
||||
Evas_Vec3 spot_dir;
|
||||
|
@ -124,6 +129,7 @@ struct _E3D_Drawable
|
|||
GLuint depth_stencil_buf;
|
||||
GLuint depth_buf;
|
||||
GLuint stencil_buf;
|
||||
GLuint texDepth;
|
||||
};
|
||||
|
||||
/* Texture internal functions. */
|
||||
|
|
|
@ -14,6 +14,7 @@ struct _E3D_Renderer
|
|||
|
||||
Eina_Bool vertex_attrib_enable[E3D_MAX_VERTEX_ATTRIB_COUNT];
|
||||
Eina_Bool depth_test_enable;
|
||||
GLuint texDepth;
|
||||
};
|
||||
|
||||
static inline GLenum
|
||||
|
@ -132,6 +133,8 @@ _renderer_texture_bind(E3D_Renderer *renderer, E3D_Draw_Data *data)
|
|||
}
|
||||
}
|
||||
}
|
||||
glActiveTexture(GL_TEXTURE0 + data->smap_sampler);
|
||||
glBindTexture(GL_TEXTURE_2D, renderer->texDepth);
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
@ -192,6 +195,7 @@ e3d_renderer_target_set(E3D_Renderer *renderer, E3D_Drawable *target)
|
|||
glBindFramebuffer(GL_FRAMEBUFFER, target->fbo);
|
||||
glViewport(0, 0, target->w, target->h);
|
||||
renderer->fbo = target->fbo;
|
||||
renderer->texDepth = target->texDepth;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -235,6 +239,7 @@ e3d_renderer_draw(E3D_Renderer *renderer, E3D_Draw_Data *data)
|
|||
|
||||
_renderer_program_use(renderer, program);
|
||||
e3d_program_uniform_upload(program, data);
|
||||
if (data->mode != EVAS_3D_SHADE_MODE_SHADOW_MAP_RENDER)
|
||||
_renderer_texture_bind(renderer, data);
|
||||
|
||||
/* Set up vertex attrib pointers. */
|
||||
|
|
|
@ -5,6 +5,7 @@ typedef enum _E3D_Uniform
|
|||
E3D_UNIFORM_MATRIX_MVP,
|
||||
E3D_UNIFORM_MATRIX_MV,
|
||||
E3D_UNIFORM_MATRIX_NORMAL,
|
||||
E3D_UNIFORM_MATRIX_LIGHT,
|
||||
|
||||
E3D_UNIFORM_POSITION_WEIGHT,
|
||||
E3D_UNIFORM_NORMAL_WEIGHT,
|
||||
|
@ -30,6 +31,8 @@ typedef enum _E3D_Uniform
|
|||
E3D_UNIFORM_TEXTURE_EMISSION1,
|
||||
E3D_UNIFORM_TEXTURE_NORMAL1,
|
||||
|
||||
E3D_UNIFORM_SHADOWMAP,
|
||||
|
||||
E3D_UNIFORM_LIGHT_POSITION,
|
||||
E3D_UNIFORM_LIGHT_SPOT_DIR,
|
||||
E3D_UNIFORM_LIGHT_SPOT_EXP,
|
||||
|
@ -121,6 +124,12 @@ _vertex_shader_string_variable_add(E3D_Shader_String *shader,
|
|||
{
|
||||
ADD_LINE("uniform mat4 uMatrixMvp;");
|
||||
|
||||
if (flags & E3D_SHADER_FLAG_SHADOWED)
|
||||
{
|
||||
ADD_LINE("uniform mat4 uMatrixLight;");
|
||||
ADD_LINE("varying vec4 lpos;");
|
||||
}
|
||||
|
||||
/* Vertex attributes. */
|
||||
if (flags & E3D_SHADER_FLAG_VERTEX_POSITION)
|
||||
ADD_LINE("attribute vec4 aPosition0;");
|
||||
|
@ -131,6 +140,8 @@ _vertex_shader_string_variable_add(E3D_Shader_String *shader,
|
|||
ADD_LINE("uniform float uPositionWeight;");
|
||||
}
|
||||
|
||||
else if (mode == EVAS_3D_SHADE_MODE_SHADOW_MAP_RENDER) return;
|
||||
|
||||
if (flags & E3D_SHADER_FLAG_VERTEX_NORMAL)
|
||||
ADD_LINE("attribute vec4 aNormal0;");
|
||||
|
||||
|
@ -488,6 +499,11 @@ _vertex_shader_string_get(E3D_Shader_String *shader,
|
|||
ADD_LINE("vertexNormalMap(position, normal);");
|
||||
}
|
||||
|
||||
if (flags & E3D_SHADER_FLAG_SHADOWED)
|
||||
{
|
||||
ADD_LINE("lpos = uMatrixLight * vec4(aPosition0.xyz, 1.0);");
|
||||
}
|
||||
|
||||
ADD_LINE("}");
|
||||
}
|
||||
|
||||
|
@ -504,6 +520,11 @@ _fragment_shader_string_variable_add(E3D_Shader_String *shader,
|
|||
ADD_LINE("uniform float uFogFactor;");
|
||||
ADD_LINE("uniform vec4 uFogColor;");
|
||||
}
|
||||
if (flags & E3D_SHADER_FLAG_SHADOWED)
|
||||
{
|
||||
ADD_LINE("varying vec4 lpos;");
|
||||
ADD_LINE("uniform sampler2D uShadowMap;");
|
||||
}
|
||||
|
||||
/* Materials. */
|
||||
if (flags & E3D_SHADER_FLAG_DIFFUSE)
|
||||
|
@ -689,6 +710,11 @@ _fragment_shader_string_func_flat_add(E3D_Shader_String *shader,
|
|||
ADD_LINE("gl_FragColor += uLightSpecular * color * vFactor.y;");
|
||||
}
|
||||
|
||||
if (flags & E3D_SHADER_FLAG_SHADOWED)
|
||||
{
|
||||
ADD_LINE("gl_FragColor *= shadow;");
|
||||
}
|
||||
|
||||
if (flags & E3D_SHADER_FLAG_AMBIENT)
|
||||
{
|
||||
if (flags & E3D_SHADER_FLAG_AMBIENT_TEXTURE_BLEND)
|
||||
|
@ -807,6 +833,11 @@ _fragment_shader_string_func_phong_add(E3D_Shader_String *shader,
|
|||
ADD_LINE("gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);");
|
||||
ADD_LINE("}");
|
||||
|
||||
if (flags & E3D_SHADER_FLAG_SHADOWED)
|
||||
{
|
||||
ADD_LINE("gl_FragColor *= shadow;");
|
||||
}
|
||||
|
||||
/* Ambient term. */
|
||||
if (flags & E3D_SHADER_FLAG_AMBIENT)
|
||||
{
|
||||
|
@ -971,6 +1002,11 @@ _fragment_shader_string_func_normal_map_add(E3D_Shader_String *shader,
|
|||
ADD_LINE("}");
|
||||
}
|
||||
|
||||
if (flags & E3D_SHADER_FLAG_SHADOWED)
|
||||
{
|
||||
ADD_LINE("gl_FragColor *= shadow;");
|
||||
}
|
||||
|
||||
ADD_LINE("} else {");
|
||||
ADD_LINE("gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);");
|
||||
ADD_LINE("}");
|
||||
|
@ -1023,13 +1059,35 @@ _fragment_shader_string_func_normal_map_add(E3D_Shader_String *shader,
|
|||
ADD_LINE("}");
|
||||
}
|
||||
|
||||
static void
|
||||
_fragment_shader_string_pcf_even_func_add(E3D_Shader_String *shader,
|
||||
Evas_3D_Shade_Mode mode EINA_UNUSED,
|
||||
E3D_Shader_Flag flags EINA_UNUSED)
|
||||
{
|
||||
ADD_LINE("float pcf(vec4 lpos, float size)");
|
||||
ADD_LINE("{");
|
||||
ADD_LINE("vec3 smcoord = lpos.xyz / lpos.w * 0.5 + 0.5;");
|
||||
ADD_LINE("float i, j, randx, randy, shadow;");
|
||||
ADD_LINE("shadow = 0.0;");
|
||||
ADD_LINE("for (i = -4.0; i < 4.0; i++)");
|
||||
ADD_LINE("for (j = -4.0; j < 4.0; j++)");
|
||||
ADD_LINE("{");
|
||||
ADD_LINE("shadow += float(smcoord.z <= texture2D(uShadowMap, smcoord.xy +vec2(i / 8.0, j / 8.0)*size).x);");
|
||||
ADD_LINE("}");
|
||||
ADD_LINE("return shadow / 64.0;");
|
||||
ADD_LINE("}");
|
||||
}
|
||||
|
||||
static void
|
||||
_fragment_shader_string_get(E3D_Shader_String *shader,
|
||||
Evas_3D_Shade_Mode mode, E3D_Shader_Flag flags)
|
||||
{
|
||||
/* Add variables - vertex attributes. */
|
||||
_fragment_shader_string_variable_add(shader, mode, flags);
|
||||
|
||||
if (flags & E3D_SHADER_FLAG_SHADOWED)
|
||||
{
|
||||
ADD_LINE("float shadow;");
|
||||
}
|
||||
/* Add functions. */
|
||||
if (mode == EVAS_3D_SHADE_MODE_FLAT)
|
||||
_fragment_shader_string_func_flat_add(shader, mode, flags);
|
||||
|
@ -1038,8 +1096,16 @@ _fragment_shader_string_get(E3D_Shader_String *shader,
|
|||
else if (mode == EVAS_3D_SHADE_MODE_NORMAL_MAP)
|
||||
_fragment_shader_string_func_normal_map_add(shader, mode, flags);
|
||||
|
||||
// TODO Add flexible bluring algorithm of shadows boundaries.
|
||||
if (flags & E3D_SHADER_FLAG_SHADOWED)
|
||||
_fragment_shader_string_pcf_even_func_add(shader, mode, flags);
|
||||
|
||||
/* Add main function. */
|
||||
ADD_LINE("void main() {");
|
||||
if (flags & E3D_SHADER_FLAG_SHADOWED)
|
||||
{
|
||||
ADD_LINE("shadow = pcf(lpos, 1.0 / 200.0);");
|
||||
}
|
||||
|
||||
if (mode == EVAS_3D_SHADE_MODE_VERTEX_COLOR)
|
||||
{
|
||||
|
@ -1062,6 +1128,10 @@ _fragment_shader_string_get(E3D_Shader_String *shader,
|
|||
ADD_LINE("gl_FragColor = uMaterialDiffuse;");
|
||||
}
|
||||
}
|
||||
else if(mode == EVAS_3D_SHADE_MODE_SHADOW_MAP_RENDER)
|
||||
{
|
||||
ADD_LINE("gl_FragColor = vec4(gl_FragCoord.z);");
|
||||
}
|
||||
else if (mode == EVAS_3D_SHADE_MODE_FLAT)
|
||||
{
|
||||
ADD_LINE("fragmentFlat();");
|
||||
|
@ -1217,6 +1287,7 @@ static const char *uniform_names[] =
|
|||
"uMatrixMvp",
|
||||
"uMatrixModelview",
|
||||
"uMatrixNormal",
|
||||
"uMatrixLight",
|
||||
"uPositionWeight",
|
||||
"uNormalWeight",
|
||||
"uTangentWeight",
|
||||
|
@ -1237,6 +1308,7 @@ static const char *uniform_names[] =
|
|||
"uTextureSpecular1",
|
||||
"uTextureEmission1",
|
||||
"uTextureNormal1",
|
||||
"uShadowMap",
|
||||
"uLightPosition",
|
||||
"uLightSpotDir",
|
||||
"uLightSpotExp",
|
||||
|
@ -1290,6 +1362,13 @@ _uniform_upload(E3D_Uniform u, GLint loc, const E3D_Draw_Data *data)
|
|||
glUniformMatrix3fv(loc, 1, EINA_FALSE, &m[0]);
|
||||
break;
|
||||
}
|
||||
case E3D_UNIFORM_MATRIX_LIGHT: {
|
||||
float m[16];
|
||||
for(int i = 0 ; i <16 ; i++)
|
||||
m[i] = data->matrix_light.m[i];
|
||||
glUniformMatrix4fv(loc, 1, EINA_FALSE, &m[0]);
|
||||
break;
|
||||
}
|
||||
case E3D_UNIFORM_POSITION_WEIGHT:
|
||||
glUniform1f(loc, data->vertices[EVAS_3D_VERTEX_POSITION].weight);
|
||||
break;
|
||||
|
@ -1350,6 +1429,9 @@ _uniform_upload(E3D_Uniform u, GLint loc, const E3D_Draw_Data *data)
|
|||
case E3D_UNIFORM_TEXTURE_NORMAL1:
|
||||
glUniform1i(loc, data->materials[EVAS_3D_MATERIAL_NORMAL].sampler1);
|
||||
break;
|
||||
case E3D_UNIFORM_SHADOWMAP:
|
||||
glUniform1i(loc, data->smap_sampler);
|
||||
break;
|
||||
case E3D_UNIFORM_LIGHT_POSITION:
|
||||
glUniform4f(loc, data->light.position.x, data->light.position.y,
|
||||
data->light.position.z, data->light.position.w);
|
||||
|
|
Loading…
Reference in New Issue