Clay Engine: More Lamp drawing work

This commit is contained in:
Clément Foucault 2017-03-05 05:22:40 +01:00
parent 45b42d3fb7
commit 747ac66800
9 changed files with 506 additions and 4 deletions

View File

@ -44,6 +44,7 @@ static struct DRWShapeCache {
Batch *drw_single_arrow;
Batch *drw_cube;
Batch *drw_circle;
Batch *drw_square;
Batch *drw_line;
Batch *drw_line_endpoints;
Batch *drw_empty_sphere;
@ -52,6 +53,10 @@ static struct DRWShapeCache {
Batch *drw_axis_names;
Batch *drw_lamp;
Batch *drw_lamp_sunrays;
Batch *drw_lamp_area;
Batch *drw_lamp_hemi;
Batch *drw_lamp_spot;
Batch *drw_lamp_spot_square;
Batch *drw_speaker;
Batch *drw_bone_octahedral;
Batch *drw_bone_octahedral_wire;
@ -77,6 +82,8 @@ void DRW_shape_cache_free(void)
Batch_discard_all(SHC.drw_cube);
if (SHC.drw_circle)
Batch_discard_all(SHC.drw_circle);
if (SHC.drw_square)
Batch_discard_all(SHC.drw_square);
if (SHC.drw_line)
Batch_discard_all(SHC.drw_line);
if (SHC.drw_line_endpoints)
@ -93,6 +100,14 @@ void DRW_shape_cache_free(void)
Batch_discard_all(SHC.drw_lamp);
if (SHC.drw_lamp_sunrays)
Batch_discard_all(SHC.drw_lamp_sunrays);
if (SHC.drw_lamp_area)
Batch_discard_all(SHC.drw_lamp_area);
if (SHC.drw_lamp_hemi)
Batch_discard_all(SHC.drw_lamp_hemi);
if (SHC.drw_lamp_spot)
Batch_discard_all(SHC.drw_lamp_spot);
if (SHC.drw_lamp_spot_square)
Batch_discard_all(SHC.drw_lamp_spot_square);
if (SHC.drw_speaker)
Batch_discard_all(SHC.drw_speaker);
if (SHC.drw_bone_octahedral)
@ -335,6 +350,34 @@ Batch *DRW_cache_circle_get(void)
#undef CIRCLE_RESOL
}
Batch *DRW_cache_square_get(void)
{
if (!SHC.drw_square) {
float p[4][3] = {{ 1.0f, 0.0f, 1.0f},
{ 1.0f, 0.0f, -1.0f},
{-1.0f, 0.0f, -1.0f},
{-1.0f, 0.0f, 1.0f}};
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned pos_id;
if (format.attrib_ct == 0) {
pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
}
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, 8);
for (int i = 0; i < 4; i++) {
setAttrib(vbo, pos_id, i * 2, p[i % 4]);
setAttrib(vbo, pos_id, i * 2 + 1, p[(i+1) % 4]);
}
SHC.drw_square = Batch_create(GL_LINES, vbo, NULL);
}
return SHC.drw_square;
}
Batch *DRW_cache_single_line_get(void)
{
/* Z axis line */
@ -652,6 +695,208 @@ Batch *DRW_cache_lamp_sunrays_get(void)
return SHC.drw_lamp_sunrays;
}
Batch *DRW_cache_lamp_area_get(void)
{
if (!SHC.drw_lamp_area) {
float v1[3] = {0.0f, 0.0f, 0.0f};
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned pos_id;
if (format.attrib_ct == 0) {
pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
}
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, 8);
v1[0] = v1[1] = 0.5f;
setAttrib(vbo, pos_id, 0, v1);
v1[0] = -0.5f;
setAttrib(vbo, pos_id, 1, v1);
setAttrib(vbo, pos_id, 2, v1);
v1[1] = -0.5f;
setAttrib(vbo, pos_id, 3, v1);
setAttrib(vbo, pos_id, 4, v1);
v1[0] = 0.5f;
setAttrib(vbo, pos_id, 5, v1);
setAttrib(vbo, pos_id, 6, v1);
v1[1] = 0.5f;
setAttrib(vbo, pos_id, 7, v1);
SHC.drw_lamp_area = Batch_create(GL_LINES, vbo, NULL);
}
return SHC.drw_lamp_area;
}
Batch *DRW_cache_lamp_hemi_get(void)
{
#define CIRCLE_RESOL 32
if (!SHC.drw_lamp_hemi) {
float v[3];
int vidx = 0;
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned pos_id;
if (format.attrib_ct == 0) {
pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
}
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, CIRCLE_RESOL * 2 * 2 - 6 * 2 * 2);
/* XZ plane */
for (int a = 3; a < CIRCLE_RESOL / 2 - 3; a++) {
v[0] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL) - M_PI / 2);
v[2] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL) - M_PI / 2) - 1.0f;
v[1] = 0.0f;
setAttrib(vbo, pos_id, vidx++, v);
v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL) - M_PI / 2);
v[2] = cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL) - M_PI / 2) - 1.0f;
v[1] = 0.0f;
setAttrib(vbo, pos_id, vidx++, v);
}
/* XY plane */
for (int a = 3; a < CIRCLE_RESOL / 2 - 3; a++) {
v[2] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)) - 1.0f;
v[1] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
v[0] = 0.0f;
setAttrib(vbo, pos_id, vidx++, v);
v[2] = sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL)) - 1.0f;
v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
v[0] = 0.0f;
setAttrib(vbo, pos_id, vidx++, v);
}
/* YZ plane full circle */
/* lease v[2] as it is */
const float rad = cosf((2.0f * M_PI * 3) / ((float)CIRCLE_RESOL));
for (int a = 0; a < CIRCLE_RESOL; a++) {
v[1] = rad * sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
v[0] = rad * cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
setAttrib(vbo, pos_id, vidx++, v);
v[1] = rad * sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
v[0] = rad * cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
setAttrib(vbo, pos_id, vidx++, v);
}
SHC.drw_lamp_hemi = Batch_create(GL_LINES, vbo, NULL);
}
return SHC.drw_lamp_hemi;
#undef CIRCLE_RESOL
}
Batch *DRW_cache_lamp_spot_get(void)
{
#define NSEGMENTS 32
if (!SHC.drw_lamp_spot) {
/* a single ring of vertices */
float p[NSEGMENTS][2];
float n[NSEGMENTS][3];
float neg[NSEGMENTS][3];
float half_angle = 2 * M_PI / ((float)NSEGMENTS * 2);
for (int i = 0; i < NSEGMENTS; ++i) {
float angle = 2 * M_PI * ((float)i / (float)NSEGMENTS);
p[i][0] = cosf(angle);
p[i][1] = sinf(angle);
n[i][0] = cosf(angle - half_angle);
n[i][1] = sinf(angle - half_angle);
n[i][2] = cosf(M_PI / 16.0f); /* slope of the cone */
normalize_v3(n[i]); /* necessary ? */
negate_v3_v3(neg[i], n[i]);
}
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned int pos_id, n1_id, n2_id;
if (format.attrib_ct == 0) {
pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
n1_id = add_attrib(&format, "N1", GL_FLOAT, 3, KEEP_FLOAT);
n2_id = add_attrib(&format, "N2", GL_FLOAT, 3, KEEP_FLOAT);
}
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, NSEGMENTS * 4);
for (int i = 0; i < NSEGMENTS; ++i) {
float cv[2], v[3];
cv[0] = p[i % NSEGMENTS][0];
cv[1] = p[i % NSEGMENTS][1];
/* cone sides */
v[0] = cv[0], v[1] = cv[1], v[2] = -1.0f;
setAttrib(vbo, pos_id, i * 4, v);
v[0] = 0.0f, v[1] = 0.0f, v[2] = 0.0f;
setAttrib(vbo, pos_id, i * 4 + 1, v);
setAttrib(vbo, n1_id, i * 4, n[(i) % NSEGMENTS]);
setAttrib(vbo, n1_id, i * 4 + 1, n[(i) % NSEGMENTS]);
setAttrib(vbo, n2_id, i * 4, n[(i+1) % NSEGMENTS]);
setAttrib(vbo, n2_id, i * 4 + 1, n[(i+1) % NSEGMENTS]);
/* end ring */
v[0] = cv[0], v[1] = cv[1], v[2] = -1.0f;
setAttrib(vbo, pos_id, i * 4 + 2, v);
cv[0] = p[(i + 1) % NSEGMENTS][0];
cv[1] = p[(i + 1) % NSEGMENTS][1];
v[0] = cv[0], v[1] = cv[1], v[2] = -1.0f;
setAttrib(vbo, pos_id, i * 4 + 3, v);
setAttrib(vbo, n1_id, i * 4 + 2, n[(i) % NSEGMENTS]);
setAttrib(vbo, n1_id, i * 4 + 3, n[(i) % NSEGMENTS]);
setAttrib(vbo, n2_id, i * 4 + 2, neg[(i) % NSEGMENTS]);
setAttrib(vbo, n2_id, i * 4 + 3, neg[(i) % NSEGMENTS]);
}
SHC.drw_lamp_spot = Batch_create(GL_LINES, vbo, NULL);
}
return SHC.drw_lamp_spot;
#undef NSEGMENTS
}
Batch *DRW_cache_lamp_spot_square_get(void)
{
if (!SHC.drw_lamp_spot_square) {
float p[5][3] = {{ 0.0f, 0.0f, 0.0f},
{ 1.0f, 1.0f, -1.0f},
{ 1.0f, -1.0f, -1.0f},
{-1.0f, -1.0f, -1.0f},
{-1.0f, 1.0f, -1.0f}};
unsigned int v_idx = 0;
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned int pos_id;
if (format.attrib_ct == 0) {
pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
}
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(vbo, 16);
/* piramid sides */
for (int i = 1; i <= 4; ++i) {
setAttrib(vbo, pos_id, v_idx++, p[0]);
setAttrib(vbo, pos_id, v_idx++, p[i]);
setAttrib(vbo, pos_id, v_idx++, p[(i % 4)+1]);
setAttrib(vbo, pos_id, v_idx++, p[((i+1) % 4)+1]);
}
SHC.drw_lamp_spot_square = Batch_create(GL_LINES, vbo, NULL);
}
return SHC.drw_lamp_spot_square;
}
/* Speaker */
Batch *DRW_cache_speaker_get(void)
{

View File

@ -42,6 +42,7 @@ struct Batch *DRW_cache_plain_axes_get(void);
struct Batch *DRW_cache_single_arrow_get(void);
struct Batch *DRW_cache_cube_get(void);
struct Batch *DRW_cache_circle_get(void);
struct Batch *DRW_cache_square_get(void);
struct Batch *DRW_cache_empty_sphere_get(void);
struct Batch *DRW_cache_empty_cone_get(void);
struct Batch *DRW_cache_arrows_get(void);
@ -50,6 +51,10 @@ struct Batch *DRW_cache_axis_names_get(void);
/* Lamps */
struct Batch *DRW_cache_lamp_get(void);
struct Batch *DRW_cache_lamp_sunrays_get(void);
struct Batch *DRW_cache_lamp_area_get(void);
struct Batch *DRW_cache_lamp_hemi_get(void);
struct Batch *DRW_cache_lamp_spot_get(void);
struct Batch *DRW_cache_lamp_spot_square_get(void);
/* Camera */
struct Batch *DRW_cache_camera_get(void);

View File

@ -65,6 +65,15 @@ static DRWShadingGroup *lamp_groundline;
static DRWShadingGroup *lamp_circle;
static DRWShadingGroup *lamp_circle_shadow;
static DRWShadingGroup *lamp_sunrays;
static DRWShadingGroup *lamp_distance;
static DRWShadingGroup *lamp_buflimit;
static DRWShadingGroup *lamp_buflimit_points;
static DRWShadingGroup *lamp_area;
static DRWShadingGroup *lamp_hemi;
static DRWShadingGroup *lamp_spot_cone;
static DRWShadingGroup *lamp_spot_blend;
static DRWShadingGroup *lamp_spot_pyramid;
static DRWShadingGroup *lamp_spot_blend_rect;
/* Helpers */
static DRWShadingGroup *relationship_lines;
@ -271,7 +280,6 @@ static DRWShadingGroup *shgroup_camera_instance(DRWPass *pass, struct Batch *geo
return grp;
}
static DRWShadingGroup *shgroup_distance_lines_instance(DRWPass *pass, struct Batch *geom)
{
GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_DISTANCE_LINES);
@ -287,6 +295,22 @@ static DRWShadingGroup *shgroup_distance_lines_instance(DRWPass *pass, struct Ba
return grp;
}
static DRWShadingGroup *shgroup_spot_instance(DRWPass *pass, struct Batch *geom)
{
GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR);
static bool True = true;
static bool False = false;
DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom);
DRW_shgroup_attrib_float(grp, "color", 3);
DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16);
DRW_shgroup_uniform_bool(grp, "drawFront", &False, 1);
DRW_shgroup_uniform_bool(grp, "drawBack", &False, 1);
DRW_shgroup_uniform_bool(grp, "drawSilhouette", &True, 1);
return grp;
}
/* This Function setup the passes needed for the mode rendering.
* The passes are populated by the rendering engines using the DRW_shgroup_* functions.
* If a pass is not needed use NULL instead of the pass pointer */
@ -392,8 +416,13 @@ void DRW_mode_passes_setup(DRWPass **psl_wire_overlay,
/* Lamps */
/* TODO
* for now we create 3 times the same VBO with only lamp center coordinates
* for now we create multiple times the same VBO with only lamp center coordinates
* but ideally we would only create it once */
/* start with buflimit because we don't want stipples */
geom = DRW_cache_single_line_get();
lamp_buflimit = shgroup_distance_lines_instance(*psl_non_meshes, geom);
lamp_center = shgroup_dynpoints_uniform_color(*psl_non_meshes, ts.colorLampNoAlpha, &ts.sizeLampCenter);
lamp_center_group = shgroup_dynpoints_uniform_color(*psl_non_meshes, ts.colorGroup, &ts.sizeLampCenter);
@ -407,6 +436,30 @@ void DRW_mode_passes_setup(DRWPass **psl_wire_overlay,
lamp_groundline = shgroup_groundlines_uniform_color(*psl_non_meshes, ts.colorLamp);
lamp_groundpoint = shgroup_groundpoints_uniform_color(*psl_non_meshes, ts.colorLamp);
geom = DRW_cache_lamp_area_get();
lamp_area = shgroup_instance(*psl_non_meshes, geom);
geom = DRW_cache_lamp_hemi_get();
lamp_hemi = shgroup_instance(*psl_non_meshes, geom);
geom = DRW_cache_single_line_get();
lamp_distance = shgroup_distance_lines_instance(*psl_non_meshes, geom);
geom = DRW_cache_single_line_endpoints_get();
lamp_buflimit_points = shgroup_distance_lines_instance(*psl_non_meshes, geom);
geom = DRW_cache_lamp_spot_get();
lamp_spot_cone = shgroup_spot_instance(*psl_non_meshes, geom);
geom = DRW_cache_circle_get();
lamp_spot_blend = shgroup_instance(*psl_non_meshes, geom);
geom = DRW_cache_lamp_spot_square_get();
lamp_spot_pyramid = shgroup_instance(*psl_non_meshes, geom);
geom = DRW_cache_square_get();
lamp_spot_blend_rect = shgroup_instance(*psl_non_meshes, geom);
/* Relationship Lines */
relationship_lines = shgroup_dynlines_uniform_color(*psl_non_meshes, ts.colorWire);
DRW_shgroup_state_set(relationship_lines, DRW_STATE_STIPPLE_3);
@ -591,6 +644,7 @@ void DRW_shgroup_lamp(Object *ob)
Lamp *la = ob->data;
float *color;
int theme_id = draw_object_wire_theme(ob, &color);
static float zero = 0.0f;
/* Don't draw the center if it's selected or active */
if (theme_id == TH_GROUP)
@ -603,13 +657,78 @@ void DRW_shgroup_lamp(Object *ob)
/* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */
if (la->type != LA_HEMI) {
DRW_shgroup_dynamic_call_add(lamp_circle_shadow, ob->obmat[3], color);
if ((la->mode & LA_SHAD_RAY) || ((la->mode & LA_SHAD_BUF) && (la->type == LA_SPOT))) {
DRW_shgroup_dynamic_call_add(lamp_circle_shadow, ob->obmat[3], color);
}
}
/* Sunrays */
/* Distance */
if (ELEM(la->type, LA_HEMI, LA_SUN, LA_AREA)) {
DRW_shgroup_dynamic_call_add(lamp_distance, color, &zero, &la->dist, ob->obmat);
}
copy_m4_m4(la->shapemat, ob->obmat);
if (la->type == LA_SUN) {
DRW_shgroup_dynamic_call_add(lamp_sunrays, ob->obmat[3], color);
}
else if (la->type == LA_SPOT) {
float size[3], sizemat[4][4];
static float one = 1.0f;
float blend = 1.0f - pow2f(la->spotblend);
size[0] = size[1] = sinf(la->spotsize * 0.5f) * la->dist;
size[2] = cosf(la->spotsize * 0.5f) * la->dist;
size_to_mat4(sizemat, size);
mul_m4_m4m4(la->spotconemat, ob->obmat, sizemat);
size[0] = size[1] = blend; size[2] = 1.0f;
size_to_mat4(sizemat, size);
translate_m4(sizemat, 0.0f, 0.0f, -1.0f);
rotate_m4(sizemat, 'X', M_PI / 2.0f);
mul_m4_m4m4(la->spotblendmat, la->spotconemat, sizemat);
if (la->mode & LA_SQUARE) {
DRW_shgroup_dynamic_call_add(lamp_spot_pyramid, color, &one, la->spotconemat);
/* hide line if it is zero size or overlaps with outer border,
* previously it adjusted to always to show it but that seems
* confusing because it doesn't show the actual blend size */
if (blend != 0.0f && blend != 1.0f) {
DRW_shgroup_dynamic_call_add(lamp_spot_blend_rect, color, &one, la->spotblendmat);
}
}
else {
DRW_shgroup_dynamic_call_add(lamp_spot_cone, color, la->spotconemat);
/* hide line if it is zero size or overlaps with outer border,
* previously it adjusted to always to show it but that seems
* confusing because it doesn't show the actual blend size */
if (blend != 0.0f && blend != 1.0f) {
DRW_shgroup_dynamic_call_add(lamp_spot_blend, color, &one, la->spotblendmat);
}
}
normalize_m4(la->shapemat);
DRW_shgroup_dynamic_call_add(lamp_buflimit, color, &la->clipsta, &la->clipend, ob->obmat);
DRW_shgroup_dynamic_call_add(lamp_buflimit_points, color, &la->clipsta, &la->clipend, ob->obmat);
}
else if (la->type == LA_HEMI) {
static float hemisize = 2.0f;
DRW_shgroup_dynamic_call_add(lamp_hemi, color, &hemisize, la->shapemat);
}
else if (la->type == LA_AREA) {
float size[3] = {1.0f, 1.0f, 1.0f}, sizemat[4][4];
if (la->area_shape == LA_AREA_RECT) {
size[1] = la->area_sizey / la->area_size;
size_to_mat4(sizemat, size);
mul_m4_m4m4(la->shapemat, la->shapemat, sizemat);
}
DRW_shgroup_dynamic_call_add(lamp_area, color, &la->area_size, la->shapemat);
}
/* Line and point going to the ground */
DRW_shgroup_dynamic_call_add(lamp_groundline, ob->obmat[3]);

View File

@ -170,6 +170,8 @@ data_to_c_simple(shaders/gpu_shader_instance_screenspace_variying_color_vert.gls
data_to_c_simple(shaders/gpu_shader_instance_screen_aligned_axis_name_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_instance_camera_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_instance_distance_line_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_instance_edges_variying_color_geom.glsl SRC)
data_to_c_simple(shaders/gpu_shader_instance_edges_variying_color_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_groundline_geom.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_groundpoint_vert.glsl SRC)

View File

@ -158,6 +158,7 @@ typedef enum GPUBuiltinShader {
/* instance */
GPU_SHADER_INSTANCE_UNIFORM_COLOR,
GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE,
GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR,
GPU_NUM_BUILTIN_SHADERS /* (not an actual shader) */
} GPUBuiltinShader;

View File

@ -81,6 +81,8 @@ extern char datatoc_gpu_shader_instance_screenspace_variying_color_vert_glsl[];
extern char datatoc_gpu_shader_instance_screen_aligned_axis_name_vert_glsl[];
extern char datatoc_gpu_shader_instance_camera_vert_glsl[];
extern char datatoc_gpu_shader_instance_distance_line_vert_glsl[];
extern char datatoc_gpu_shader_instance_edges_variying_color_geom_glsl[];
extern char datatoc_gpu_shader_instance_edges_variying_color_vert_glsl[];
extern char datatoc_gpu_shader_3D_groundpoint_vert_glsl[];
extern char datatoc_gpu_shader_3D_groundline_geom_glsl[];
@ -772,6 +774,9 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
[GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE] =
{ datatoc_gpu_shader_instance_variying_size_variying_color_vert_glsl,
datatoc_gpu_shader_flat_color_frag_glsl },
[GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR] = { datatoc_gpu_shader_instance_edges_variying_color_vert_glsl,
datatoc_gpu_shader_flat_color_frag_glsl,
datatoc_gpu_shader_instance_edges_variying_color_geom_glsl},
};
if (builtin_shaders[shader] == NULL) {

View File

@ -0,0 +1,57 @@
// Draw "fancy" wireframe, displaying front-facing, back-facing and
// silhouette lines differently.
// Mike Erwin, April 2015
// After working with this shader a while, convinced we should make
// separate shaders for perpective & ortho. (Oct 2016)
// Due to perspective, the line segment's endpoints might disagree on
// whether the adjacent faces are front facing. This geometry shader
// decides which edge type to use if endpoints disagree.
uniform mat4 ProjectionMatrix;
uniform bool drawFront = true;
uniform bool drawBack = true;
uniform bool drawSilhouette = true;
layout(lines) in;
layout(line_strip, max_vertices = 2) out;
in vec4 MV_pos[];
in float edgeClass[];
in vec3 fCol[];
flat out vec4 finalColor;
void emitLine(vec4 color)
{
gl_Position = ProjectionMatrix * MV_pos[0];
EmitVertex();
gl_Position = ProjectionMatrix * MV_pos[1];
finalColor = color;
EmitVertex();
EndPrimitive();
}
void main()
{
float finalEdgeClass = max(edgeClass[0], edgeClass[1]);
if (finalEdgeClass > 0.0f) {
// front-facing edge
if (drawFront)
emitLine(vec4(fCol[0], 0.75));
}
else if (finalEdgeClass < 0.0f) {
// back-facing edge
if (drawBack)
emitLine(vec4(fCol[0], 0.5));
}
else {
// exactly one face is front-facing, silhouette edge
if (drawSilhouette)
emitLine(vec4(fCol[0], 1.0));
}
}

View File

@ -0,0 +1,64 @@
// Draw "fancy" wireframe, displaying front-facing, back-facing and
// silhouette lines differently.
// Mike Erwin, April 2015
// After working with this shader a while, convinced we should make
// separate shaders for perpective & ortho. (Oct 2016)
// Due to perspective, the line segment's endpoints might disagree on
// whether the adjacent faces are front facing. We use a geometry
// shader to resolve this properly.
uniform mat4 ViewMatrix;
in vec3 pos;
in vec3 N1, N2; // normals of faces this edge joins (object coords)
/* instance attrib */
in vec3 color;
in mat4 InstanceModelMatrix;
out vec4 MV_pos;
out float edgeClass;
out vec3 fCol;
// TODO: in float angle; // [-pi .. +pi], + peak, 0 flat, - valley
mat3 NormalMatrix;
bool front(vec3 N, vec3 eye)
{
return dot(NormalMatrix * N, eye) > 0.0;
}
void main()
{
vec3 eye;
mat4 ModelViewMatrix = ViewMatrix * InstanceModelMatrix;
MV_pos = ModelViewMatrix * vec4(pos, 1.0);
NormalMatrix = transpose(inverse(mat3(ModelViewMatrix)));
/* if persp */
if (ViewMatrix[3][3] == 0.0) {
eye = normalize(-MV_pos.xyz);
}
else {
eye = vec3(0.0, 0.0, 1.0);
}
bool face_1_front = front(N1, eye);
bool face_2_front = front(N2, eye);
if (face_1_front && face_2_front)
edgeClass = 1.0; // front-facing edge
else if (face_1_front || face_2_front)
edgeClass = 0.0; // exactly one face is front-facing, silhouette edge
else
edgeClass = -1.0; // back-facing edge
fCol = color;
}

View File

@ -106,6 +106,10 @@ typedef struct Lamp {
short pr_texture, use_nodes;
char pad6[4];
float shapemat[4][4]; /* runtime, for display only */
float spotconemat[4][4]; /* runtime, for display only */
float spotblendmat[4][4]; /* runtime, for display only */
/* preview */
struct PreviewImage *preview;