Compare commits
92 Commits
tmp-workbe
...
GPU_data_r
Author | SHA1 | Date | |
---|---|---|---|
bcf1626934 | |||
8e08b34061 | |||
d58765ccb3 | |||
25e492edaa | |||
eb42cbf273 | |||
247a1659fa | |||
4040f0af00 | |||
95ca1ed75d | |||
b733d44f04 | |||
09076e4f99 | |||
9e8f939769 | |||
b9ac83ce9d | |||
1178265b0d | |||
4d972a5606 | |||
6f51182755 | |||
316b953e34 | |||
7cb24b52d7 | |||
1653bbc778 | |||
27fe1353ad | |||
6ccc770a95 | |||
562d6ee7c4 | |||
249a1e7f18 | |||
8e069c4f8d | |||
59593af2a7 | |||
f0caa0bbad | |||
0ea4747752 | |||
1cc677a037 | |||
1543c3f706 | |||
10f095463c | |||
61978bbf32 | |||
bcddec8a45 | |||
b138fbe4a1 | |||
805ddc7790 | |||
b91ebca68e | |||
4b88dbb06e | |||
3541f234a2 | |||
6695dd5eea | |||
33f85d0fe2 | |||
26e5c28d39 | |||
86b9bcbfb4 | |||
d77ec2153b | |||
404c9e1b7a | |||
0b2abe145a | |||
418041628a | |||
62ee03467a | |||
dea27f08eb | |||
d3bd16b208 | |||
028adae2b5 | |||
f2ef00f80e | |||
cd454ab5b7 | |||
e12432ac71 | |||
165dab3551 | |||
699d7fd732 | |||
12820473b2 | |||
0aebd1b039 | |||
8599cfde8e | |||
3eaf30d216 | |||
dc7a82e5e5 | |||
d664818c96 | |||
91cd1d98f6 | |||
f40ffb79d4 | |||
4d506c6303 | |||
77aafef4b7 | |||
995c613404 | |||
9e7c8641e7 | |||
c8d50ba9e6 | |||
24dba1cbe9 | |||
4ab3f9fb1f | |||
20ce77c93c | |||
510af625bd | |||
bc4b72eabd | |||
2398f8713a | |||
84f4c305f9 | |||
2250834b40 | |||
d119166464 | |||
fcb2b87932 | |||
cfc05b0e99 | |||
38ed5b82b3 | |||
9965160c58 | |||
7bcb4fbf73 | |||
6fc928599b | |||
5b10412103 | |||
50a511b76e | |||
49b2228c0e | |||
358732c463 | |||
ded1d86b82 | |||
022d91bcf6 | |||
49385d8b1b | |||
0703ba898e | |||
9efc674800 | |||
d67d29035a | |||
f07ca03185 |
Submodule release/datafiles/locale updated: c651e63a9a...ca3f663ff4
Submodule release/scripts/addons updated: 3fc5b82c6b...1068cf3057
Submodule release/scripts/addons_contrib updated: cf842d8bb7...24d59d37f7
@@ -182,8 +182,11 @@ def write_sysinfo(op):
|
||||
output.write("\nImplementation Dependent OpenGL Limits:\n")
|
||||
output.write(lilies)
|
||||
limit = bgl.Buffer(bgl.GL_INT, 1)
|
||||
limit_fl = bgl.Buffer(bgl.GL_FLOAT, 2)
|
||||
bgl.glGetIntegerv(bgl.GL_MAX_TEXTURE_UNITS, limit)
|
||||
output.write("Maximum Fixed Function Texture Units:\t%d\n" % limit[0])
|
||||
bgl.glGetFloatv(bgl.GL_MAX_TEXTURE_UNITS, limit_fl)
|
||||
output.write("Point Sprite Size Range:\t Max: %f Min: %f\n" % (limit_fl[0], limit_fl[1]))
|
||||
|
||||
output.write("\nGLSL:\n")
|
||||
if version[0] > '1':
|
||||
|
@@ -105,6 +105,10 @@ class NODE_HT_header(Header):
|
||||
row.prop(snode, "backdrop_channels", text="", expand=True)
|
||||
layout.prop(snode, "use_auto_render")
|
||||
|
||||
elif snode.tree_type == 'WorkflowNodeTree':
|
||||
if snode_id:
|
||||
row = layout.row()
|
||||
row.template_ID(snode_id, "node_tree", new="node.new_node_tree")
|
||||
else:
|
||||
# Custom node tree is edited as independent ID block
|
||||
layout.template_ID(snode, "node_tree", new="node.new_node_tree")
|
||||
|
@@ -451,6 +451,7 @@ class USERPREF_PT_system(Panel):
|
||||
col.label(text="Anisotropic Filtering")
|
||||
col.prop(system, "anisotropic_filter", text="")
|
||||
col.prop(system, "use_vertex_buffer_objects")
|
||||
col.prop(system, "use_viewport_new")
|
||||
|
||||
col.separator()
|
||||
|
||||
|
@@ -267,7 +267,8 @@ shader_node_categories = [
|
||||
NodeItem("ShaderNodeBlackbody"),
|
||||
]),
|
||||
ShaderNewNodeCategory("SH_NEW_SCRIPT", "Script", items=[
|
||||
NodeItem("ShaderNodeScript"),
|
||||
NodeItem("ShaderNodeScript"), # OSL
|
||||
NodeItem("ShaderNodeScriptGLSL"),
|
||||
]),
|
||||
ShaderNewNodeCategory("SH_NEW_GROUP", "Group", items=node_group_items),
|
||||
ShaderNewNodeCategory("SH_NEW_LAYOUT", "Layout", items=[
|
||||
|
@@ -96,6 +96,7 @@ struct MCol;
|
||||
struct ColorBand;
|
||||
struct GPUVertexAttribs;
|
||||
struct GPUDrawObject;
|
||||
struct GPUxBatch;
|
||||
struct BMEditMesh;
|
||||
struct PBVH;
|
||||
|
||||
@@ -184,6 +185,7 @@ struct DerivedMesh {
|
||||
int deformedOnly; /* set by modifier stack if only deformed from original */
|
||||
BVHCache bvhCache;
|
||||
struct GPUDrawObject *drawObject;
|
||||
struct GPUxBatch *gpux_batch; /* TODO: replace with list of batches */
|
||||
DerivedMeshType type;
|
||||
float auto_bump_scale;
|
||||
DMDirtyFlag dirty;
|
||||
@@ -470,6 +472,10 @@ struct DerivedMesh {
|
||||
void (*setMaterial)(void *userData, int matnr, void *attribs),
|
||||
bool (*setFace)(void *userData, int index), void *userData);
|
||||
|
||||
struct GPUDrawObject *(*gpuObjectNew)(DerivedMesh *dm);
|
||||
void (*copy_gpu_data)(DerivedMesh *dm, int type, float *varray, int *index,
|
||||
int *mat_orig_to_new, void *user_data);
|
||||
|
||||
/** Release reference to the DerivedMesh. This function decides internally
|
||||
* if the DerivedMesh will be freed, or cached for later use. */
|
||||
void (*release)(DerivedMesh *dm);
|
||||
|
@@ -71,7 +71,7 @@ void id_clear_lib_data(struct Main *bmain, struct ID *id);
|
||||
|
||||
struct ListBase *which_libbase(struct Main *mainlib, short type);
|
||||
|
||||
#define MAX_LIBARRAY 35
|
||||
#define MAX_LIBARRAY 36
|
||||
int set_listbasepointers(struct Main *main, struct ListBase *lb[MAX_LIBARRAY]);
|
||||
|
||||
void BKE_libblock_free(struct Main *bmain, void *idv);
|
||||
|
@@ -94,6 +94,7 @@ typedef struct Main {
|
||||
ListBase movieclip;
|
||||
ListBase mask;
|
||||
ListBase linestyle;
|
||||
ListBase gpuworkflows;
|
||||
|
||||
char id_tag_update[256];
|
||||
|
||||
|
@@ -231,8 +231,8 @@ void BKE_mesh_normals_loop_custom_from_vertices_set(
|
||||
short (*r_clnors_data)[2]);
|
||||
|
||||
void BKE_mesh_calc_poly_normal(
|
||||
struct MPoly *mpoly, struct MLoop *loopstart,
|
||||
struct MVert *mvarray, float no[3]);
|
||||
const struct MPoly *mpoly, const struct MLoop *loopstart,
|
||||
const struct MVert *mvarray, float no[3]);
|
||||
void BKE_mesh_calc_poly_normal_coords(
|
||||
struct MPoly *mpoly, struct MLoop *loopstart,
|
||||
const float (*vertex_coords)[3], float no[3]);
|
||||
|
@@ -45,6 +45,7 @@
|
||||
#include "DNA_texture_types.h"
|
||||
#include "DNA_world_types.h"
|
||||
#include "DNA_linestyle_types.h"
|
||||
#include "DNA_view3d_types.h"
|
||||
|
||||
#include "RNA_types.h"
|
||||
|
||||
@@ -258,8 +259,9 @@ typedef struct bNodeType {
|
||||
#define NODE_CLASS_LAYOUT 100
|
||||
|
||||
/* nodetype->compatibility */
|
||||
#define NODE_OLD_SHADING 1
|
||||
#define NODE_NEW_SHADING 2
|
||||
#define NODE_OLD_SHADING 1
|
||||
#define NODE_NEW_SHADING 2
|
||||
#define NODE_WORKFLOW_SHADING 3
|
||||
|
||||
/* node resize directions */
|
||||
#define NODE_RESIZE_TOP 1
|
||||
@@ -663,6 +665,7 @@ struct NodeTreeIterStore {
|
||||
Lamp *lamp;
|
||||
World *world;
|
||||
FreestyleLineStyle *linestyle;
|
||||
GPUWorkflowShader *wfshader;
|
||||
};
|
||||
|
||||
void BKE_node_tree_iter_init(struct NodeTreeIterStore *ntreeiter, struct Main *bmain);
|
||||
@@ -782,6 +785,7 @@ struct ShadeResult;
|
||||
#define SH_NODE_COMBXYZ 189
|
||||
#define SH_NODE_OUTPUT_LINESTYLE 190
|
||||
#define SH_NODE_UVALONGSTROKE 191
|
||||
#define SH_NODE_SCRIPT_GLSL 192
|
||||
|
||||
/* custom defines options for Material node */
|
||||
#define SH_NODE_MAT_DIFF 1
|
||||
|
43
source/blender/blenkernel/BKE_workflow_shaders.h
Normal file
43
source/blender/blenkernel/BKE_workflow_shaders.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): Antony Riakiotakis.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
#ifndef BKE_WORKFLOW_SHADERS_H
|
||||
#define BKE_WORKFLOW_SHADERS_H
|
||||
|
||||
/** \file BKE_workflow_shaders.h
|
||||
* \ingroup bke
|
||||
* \since March 2015
|
||||
* \author psy-fi
|
||||
*/
|
||||
|
||||
struct GPUWorkflowShader;
|
||||
struct Main;
|
||||
|
||||
void BKE_workflow_shader_free(struct GPUWorkflowShader *shader);
|
||||
struct GPUWorkflowShader *BKE_workflow_shader_add(struct Main *bmain, const char *name);
|
||||
|
||||
|
||||
#endif // BKE_WORKFLOW_SHADERS_H
|
@@ -174,6 +174,7 @@ set(SRC
|
||||
intern/tracking_stabilize.c
|
||||
intern/tracking_util.c
|
||||
intern/unit.c
|
||||
intern/workflow_shaders.c
|
||||
intern/world.c
|
||||
intern/writeavi.c
|
||||
intern/writeframeserver.c
|
||||
@@ -274,6 +275,7 @@ set(SRC
|
||||
BKE_tracking.h
|
||||
BKE_unit.h
|
||||
BKE_utildefines.h
|
||||
BKE_workflow_shaders.h
|
||||
BKE_world.h
|
||||
BKE_writeavi.h
|
||||
BKE_writeframeserver.h
|
||||
|
@@ -75,6 +75,7 @@ static DerivedMesh *navmesh_dm_createNavMeshForVisualization(DerivedMesh *dm);
|
||||
#include "GPU_buffers.h"
|
||||
#include "GPU_extensions.h"
|
||||
#include "GPU_glew.h"
|
||||
#include "GPUx_draw.h"
|
||||
|
||||
/* very slow! enable for testing only! */
|
||||
//#define USE_MODIFIER_VALIDATE
|
||||
@@ -337,6 +338,12 @@ int DM_release(DerivedMesh *dm)
|
||||
if (dm->needsFree) {
|
||||
bvhcache_free(&dm->bvhCache);
|
||||
GPU_drawobject_free(dm);
|
||||
|
||||
if (dm->gpux_batch) {
|
||||
GPUx_batch_discard(dm->gpux_batch);
|
||||
dm->gpux_batch = NULL;
|
||||
}
|
||||
|
||||
CustomData_free(&dm->vertData, dm->numVertData);
|
||||
CustomData_free(&dm->edgeData, dm->numEdgeData);
|
||||
CustomData_free(&dm->faceData, dm->numTessFaceData);
|
||||
|
@@ -553,6 +553,10 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int
|
||||
NodeShaderScript *nss = (NodeShaderScript *)node->storage;
|
||||
rewrite_path_fixed(nss->filepath, visit_cb, absbase, bpath_user_data);
|
||||
}
|
||||
else if (node->type == SH_NODE_SCRIPT_GLSL) {
|
||||
NodeShaderScriptGLSL *nss = (NodeShaderScriptGLSL *)node->storage;
|
||||
rewrite_path_fixed(nss->filepath, visit_cb, absbase, bpath_user_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -562,7 +566,7 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int
|
||||
bNodeTree *ntree = (bNodeTree *)id;
|
||||
bNode *node;
|
||||
|
||||
if (ntree->type == NTREE_SHADER) {
|
||||
if (ELEM(ntree->type, NTREE_SHADER, NTREE_WORKFLOW)) {
|
||||
/* same as lines above */
|
||||
for (node = ntree->nodes.first; node; node = node->next) {
|
||||
if (node->type == SH_NODE_SCRIPT) {
|
||||
|
@@ -395,7 +395,7 @@ static void cdDM_drawEdges(DerivedMesh *dm, bool drawLooseEdges, bool drawAllEdg
|
||||
MEdge *medge = cddm->medge;
|
||||
int i;
|
||||
int prevstart = 0;
|
||||
int prevdraw = 1;
|
||||
bool prevdraw = true;
|
||||
bool draw = true;
|
||||
|
||||
if (cddm->pbvh && cddm->pbvh_draw &&
|
||||
@@ -417,14 +417,14 @@ static void cdDM_drawEdges(DerivedMesh *dm, bool drawLooseEdges, bool drawAllEdg
|
||||
draw = false;
|
||||
}
|
||||
if (prevdraw != draw) {
|
||||
if (prevdraw > 0 && (i - prevstart) > 0) {
|
||||
if (prevdraw && (i - prevstart) > 0) {
|
||||
GPU_buffer_draw_elements(dm->drawObject->edges, GL_LINES, prevstart * 2, (i - prevstart) * 2);
|
||||
}
|
||||
prevstart = i;
|
||||
}
|
||||
prevdraw = draw;
|
||||
}
|
||||
if (prevdraw > 0 && (i - prevstart) > 0) {
|
||||
if (prevdraw && (i - prevstart) > 0) {
|
||||
GPU_buffer_draw_elements(dm->drawObject->edges, GL_LINES, prevstart * 2, (i - prevstart) * 2);
|
||||
}
|
||||
GPU_buffer_unbind();
|
||||
@@ -1351,6 +1351,488 @@ static void cdDM_drawMappedEdges(DerivedMesh *dm, DMSetDrawOptions setDrawOption
|
||||
glEnd();
|
||||
}
|
||||
|
||||
static void cdDM_buffer_copy_vertex(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *UNUSED(user))
|
||||
{
|
||||
MVert *mvert;
|
||||
MFace *f;
|
||||
int i, j, start, totface;
|
||||
|
||||
mvert = dm->getVertArray(dm);
|
||||
f = dm->getTessFaceArray(dm);
|
||||
|
||||
totface = dm->getNumTessFaces(dm);
|
||||
for (i = 0; i < totface; i++, f++) {
|
||||
start = index[mat_orig_to_new[f->mat_nr]];
|
||||
|
||||
/* v1 v2 v3 */
|
||||
copy_v3_v3(&varray[start], mvert[f->v1].co);
|
||||
copy_v3_v3(&varray[start + 3], mvert[f->v2].co);
|
||||
copy_v3_v3(&varray[start + 6], mvert[f->v3].co);
|
||||
index[mat_orig_to_new[f->mat_nr]] += 9;
|
||||
|
||||
if (f->v4) {
|
||||
/* v3 v4 v1 */
|
||||
copy_v3_v3(&varray[start + 9], mvert[f->v3].co);
|
||||
copy_v3_v3(&varray[start + 12], mvert[f->v4].co);
|
||||
copy_v3_v3(&varray[start + 15], mvert[f->v1].co);
|
||||
index[mat_orig_to_new[f->mat_nr]] += 9;
|
||||
}
|
||||
}
|
||||
|
||||
/* copy loose points */
|
||||
j = dm->drawObject->tot_triangle_point * 3;
|
||||
for (i = 0; i < dm->drawObject->totvert; i++) {
|
||||
if (dm->drawObject->vert_points[i].point_index >= dm->drawObject->tot_triangle_point) {
|
||||
copy_v3_v3(&varray[j], mvert[i].co);
|
||||
j += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void cdDM_buffer_copy_normal(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *UNUSED(user))
|
||||
{
|
||||
int i, totface;
|
||||
int start;
|
||||
float f_no[3];
|
||||
|
||||
const float *nors = dm->getTessFaceDataArray(dm, CD_NORMAL);
|
||||
short (*tlnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
|
||||
MVert *mvert = dm->getVertArray(dm);
|
||||
MFace *f = dm->getTessFaceArray(dm);
|
||||
|
||||
totface = dm->getNumTessFaces(dm);
|
||||
for (i = 0; i < totface; i++, f++) {
|
||||
const int smoothnormal = (f->flag & ME_SMOOTH);
|
||||
|
||||
start = index[mat_orig_to_new[f->mat_nr]];
|
||||
index[mat_orig_to_new[f->mat_nr]] += f->v4 ? 18 : 9;
|
||||
|
||||
if (tlnors) {
|
||||
short (*tlnor)[3] = tlnors[i];
|
||||
/* Copy loop normals */
|
||||
normal_short_to_float_v3(&varray[start], tlnor[0]);
|
||||
normal_short_to_float_v3(&varray[start + 3], tlnor[1]);
|
||||
normal_short_to_float_v3(&varray[start + 6], tlnor[2]);
|
||||
|
||||
if (f->v4) {
|
||||
normal_short_to_float_v3(&varray[start + 9], tlnor[2]);
|
||||
normal_short_to_float_v3(&varray[start + 12], tlnor[3]);
|
||||
normal_short_to_float_v3(&varray[start + 15], tlnor[0]);
|
||||
}
|
||||
}
|
||||
else if (smoothnormal) {
|
||||
/* copy vertex normal */
|
||||
normal_short_to_float_v3(&varray[start], mvert[f->v1].no);
|
||||
normal_short_to_float_v3(&varray[start + 3], mvert[f->v2].no);
|
||||
normal_short_to_float_v3(&varray[start + 6], mvert[f->v3].no);
|
||||
|
||||
if (f->v4) {
|
||||
normal_short_to_float_v3(&varray[start + 9], mvert[f->v3].no);
|
||||
normal_short_to_float_v3(&varray[start + 12], mvert[f->v4].no);
|
||||
normal_short_to_float_v3(&varray[start + 15], mvert[f->v1].no);
|
||||
}
|
||||
}
|
||||
else if (nors) {
|
||||
/* copy cached face normal */
|
||||
copy_v3_v3(&varray[start], &nors[i * 3]);
|
||||
copy_v3_v3(&varray[start + 3], &nors[i * 3]);
|
||||
copy_v3_v3(&varray[start + 6], &nors[i * 3]);
|
||||
|
||||
if (f->v4) {
|
||||
copy_v3_v3(&varray[start + 9], &nors[i * 3]);
|
||||
copy_v3_v3(&varray[start + 12], &nors[i * 3]);
|
||||
copy_v3_v3(&varray[start + 15], &nors[i * 3]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* calculate face normal */
|
||||
if (f->v4)
|
||||
normal_quad_v3(f_no, mvert[f->v1].co, mvert[f->v2].co, mvert[f->v3].co, mvert[f->v4].co);
|
||||
else
|
||||
normal_tri_v3(f_no, mvert[f->v1].co, mvert[f->v2].co, mvert[f->v3].co);
|
||||
|
||||
copy_v3_v3(&varray[start], f_no);
|
||||
copy_v3_v3(&varray[start + 3], f_no);
|
||||
copy_v3_v3(&varray[start + 6], f_no);
|
||||
|
||||
if (f->v4) {
|
||||
copy_v3_v3(&varray[start + 9], f_no);
|
||||
copy_v3_v3(&varray[start + 12], f_no);
|
||||
copy_v3_v3(&varray[start + 15], f_no);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void cdDM_buffer_copy_uv(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *UNUSED(user))
|
||||
{
|
||||
int start;
|
||||
int i, totface;
|
||||
|
||||
MTFace *mtface;
|
||||
MFace *f;
|
||||
|
||||
if (!(mtface = DM_get_tessface_data_layer(dm, CD_MTFACE)))
|
||||
return;
|
||||
f = dm->getTessFaceArray(dm);
|
||||
|
||||
totface = dm->getNumTessFaces(dm);
|
||||
for (i = 0; i < totface; i++, f++) {
|
||||
start = index[mat_orig_to_new[f->mat_nr]];
|
||||
|
||||
/* v1 v2 v3 */
|
||||
copy_v2_v2(&varray[start], mtface[i].uv[0]);
|
||||
copy_v2_v2(&varray[start + 2], mtface[i].uv[1]);
|
||||
copy_v2_v2(&varray[start + 4], mtface[i].uv[2]);
|
||||
index[mat_orig_to_new[f->mat_nr]] += 6;
|
||||
|
||||
if (f->v4) {
|
||||
/* v3 v4 v1 */
|
||||
copy_v2_v2(&varray[start + 6], mtface[i].uv[2]);
|
||||
copy_v2_v2(&varray[start + 8], mtface[i].uv[3]);
|
||||
copy_v2_v2(&varray[start + 10], mtface[i].uv[0]);
|
||||
index[mat_orig_to_new[f->mat_nr]] += 6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void cdDM_buffer_copy_uv_texpaint(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *UNUSED(user))
|
||||
{
|
||||
int start;
|
||||
int i, totface;
|
||||
|
||||
int totmaterial = dm->totmat;
|
||||
MTFace **mtface_base;
|
||||
MTFace *stencil_base;
|
||||
int stencil;
|
||||
MFace *mf;
|
||||
|
||||
/* should have been checked for before, reassert */
|
||||
BLI_assert(DM_get_tessface_data_layer(dm, CD_MTFACE));
|
||||
mf = dm->getTessFaceArray(dm);
|
||||
mtface_base = MEM_mallocN(totmaterial * sizeof(*mtface_base), "texslots");
|
||||
|
||||
for (i = 0; i < totmaterial; i++) {
|
||||
mtface_base[i] = DM_paint_uvlayer_active_get(dm, i);
|
||||
}
|
||||
|
||||
stencil = CustomData_get_stencil_layer(&dm->faceData, CD_MTFACE);
|
||||
stencil_base = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, stencil);
|
||||
|
||||
totface = dm->getNumTessFaces(dm);
|
||||
|
||||
for (i = 0; i < totface; i++, mf++) {
|
||||
int mat_i = mf->mat_nr;
|
||||
start = index[mat_orig_to_new[mat_i]];
|
||||
|
||||
/* v1 v2 v3 */
|
||||
copy_v2_v2(&varray[start], mtface_base[mat_i][i].uv[0]);
|
||||
copy_v2_v2(&varray[start + 2], stencil_base[i].uv[0]);
|
||||
copy_v2_v2(&varray[start + 4], mtface_base[mat_i][i].uv[1]);
|
||||
copy_v2_v2(&varray[start + 6], stencil_base[i].uv[1]);
|
||||
copy_v2_v2(&varray[start + 8], mtface_base[mat_i][i].uv[2]);
|
||||
copy_v2_v2(&varray[start + 10], stencil_base[i].uv[2]);
|
||||
index[mat_orig_to_new[mat_i]] += 12;
|
||||
|
||||
if (mf->v4) {
|
||||
/* v3 v4 v1 */
|
||||
copy_v2_v2(&varray[start + 12], mtface_base[mat_i][i].uv[2]);
|
||||
copy_v2_v2(&varray[start + 14], stencil_base[i].uv[2]);
|
||||
copy_v2_v2(&varray[start + 16], mtface_base[mat_i][i].uv[3]);
|
||||
copy_v2_v2(&varray[start + 18], stencil_base[i].uv[3]);
|
||||
copy_v2_v2(&varray[start + 20], mtface_base[mat_i][i].uv[0]);
|
||||
copy_v2_v2(&varray[start + 22], stencil_base[i].uv[0]);
|
||||
index[mat_orig_to_new[mat_i]] += 12;
|
||||
}
|
||||
}
|
||||
|
||||
MEM_freeN(mtface_base);
|
||||
}
|
||||
|
||||
|
||||
static void copy_mcol_uc3(unsigned char *v, unsigned char *col)
|
||||
{
|
||||
v[0] = col[3];
|
||||
v[1] = col[2];
|
||||
v[2] = col[1];
|
||||
}
|
||||
|
||||
/* treat varray_ as an array of MCol, four MCol's per face */
|
||||
static void cdDM_buffer_copy_mcol(DerivedMesh *dm, float *varray_, int *index, int *mat_orig_to_new, void *user)
|
||||
{
|
||||
int i, totface;
|
||||
unsigned char *varray = (unsigned char *)varray_;
|
||||
unsigned char *mcol = (unsigned char *)user;
|
||||
MFace *f = dm->getTessFaceArray(dm);
|
||||
|
||||
totface = dm->getNumTessFaces(dm);
|
||||
for (i = 0; i < totface; i++, f++) {
|
||||
int start = index[mat_orig_to_new[f->mat_nr]];
|
||||
|
||||
/* v1 v2 v3 */
|
||||
copy_mcol_uc3(&varray[start], &mcol[i * 16]);
|
||||
copy_mcol_uc3(&varray[start + 3], &mcol[i * 16 + 4]);
|
||||
copy_mcol_uc3(&varray[start + 6], &mcol[i * 16 + 8]);
|
||||
index[mat_orig_to_new[f->mat_nr]] += 9;
|
||||
|
||||
if (f->v4) {
|
||||
/* v3 v4 v1 */
|
||||
copy_mcol_uc3(&varray[start + 9], &mcol[i * 16 + 8]);
|
||||
copy_mcol_uc3(&varray[start + 12], &mcol[i * 16 + 12]);
|
||||
copy_mcol_uc3(&varray[start + 15], &mcol[i * 16]);
|
||||
index[mat_orig_to_new[f->mat_nr]] += 9;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void cdDM_buffer_copy_edge(DerivedMesh *dm, float *varray_, int *UNUSED(index), int *UNUSED(mat_orig_to_new), void *UNUSED(user))
|
||||
{
|
||||
MEdge *medge;
|
||||
unsigned int *varray = (unsigned int *)varray_;
|
||||
int i, totedge;
|
||||
|
||||
medge = dm->getEdgeArray(dm);
|
||||
totedge = dm->getNumEdges(dm);
|
||||
|
||||
for (i = 0; i < totedge; i++, medge++) {
|
||||
varray[i * 2] = dm->drawObject->vert_points[medge->v1].point_index;
|
||||
varray[i * 2 + 1] = dm->drawObject->vert_points[medge->v2].point_index;
|
||||
}
|
||||
}
|
||||
|
||||
static void cdDM_buffer_copy_uvedge(DerivedMesh *dm, float *varray, int *UNUSED(index), int *UNUSED(mat_orig_to_new), void *UNUSED(user))
|
||||
{
|
||||
MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
|
||||
int i, j = 0;
|
||||
|
||||
if (!tf)
|
||||
return;
|
||||
|
||||
for (i = 0; i < dm->numTessFaceData; i++, tf++) {
|
||||
MFace mf;
|
||||
dm->getTessFace(dm, i, &mf);
|
||||
|
||||
copy_v2_v2(&varray[j], tf->uv[0]);
|
||||
copy_v2_v2(&varray[j + 2], tf->uv[1]);
|
||||
|
||||
copy_v2_v2(&varray[j + 4], tf->uv[1]);
|
||||
copy_v2_v2(&varray[j + 6], tf->uv[2]);
|
||||
|
||||
if (!mf.v4) {
|
||||
copy_v2_v2(&varray[j + 8], tf->uv[2]);
|
||||
copy_v2_v2(&varray[j + 10], tf->uv[0]);
|
||||
j += 12;
|
||||
}
|
||||
else {
|
||||
copy_v2_v2(&varray[j + 8], tf->uv[2]);
|
||||
copy_v2_v2(&varray[j + 10], tf->uv[3]);
|
||||
|
||||
copy_v2_v2(&varray[j + 12], tf->uv[3]);
|
||||
copy_v2_v2(&varray[j + 14], tf->uv[0]);
|
||||
j += 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void cdDM_copy_gpu_data(DerivedMesh *dm, int type, float *varray, int *index,
|
||||
int *mat_orig_to_new, void *user_data)
|
||||
{
|
||||
switch(type) {
|
||||
case GPU_BUFFER_VERTEX:
|
||||
cdDM_buffer_copy_vertex(dm, varray, index, mat_orig_to_new, user_data);
|
||||
break;
|
||||
case GPU_BUFFER_NORMAL:
|
||||
cdDM_buffer_copy_normal(dm, varray, index, mat_orig_to_new, user_data);
|
||||
break;
|
||||
case GPU_BUFFER_COLOR:
|
||||
cdDM_buffer_copy_mcol(dm, varray, index, mat_orig_to_new, user_data);
|
||||
break;
|
||||
case GPU_BUFFER_UV:
|
||||
cdDM_buffer_copy_uv(dm, varray, index, mat_orig_to_new, user_data);
|
||||
break;
|
||||
case GPU_BUFFER_UV_TEXPAINT:
|
||||
cdDM_buffer_copy_uv_texpaint(dm, varray, index, mat_orig_to_new, user_data);
|
||||
break;
|
||||
case GPU_BUFFER_EDGE:
|
||||
cdDM_buffer_copy_edge(dm, varray, index, mat_orig_to_new, user_data);
|
||||
break;
|
||||
case GPU_BUFFER_UVEDGE:
|
||||
cdDM_buffer_copy_uvedge(dm, varray, index, mat_orig_to_new, user_data);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* add a new point to the list of points related to a particular
|
||||
* vertex */
|
||||
#ifdef USE_GPU_POINT_LINK
|
||||
|
||||
static void cdDM_drawobject_add_vert_point(GPUDrawObject *gdo, int vert_index, int point_index)
|
||||
{
|
||||
GPUVertPointLink *lnk;
|
||||
|
||||
lnk = &gdo->vert_points[vert_index];
|
||||
|
||||
/* if first link is in use, add a new link at the end */
|
||||
if (lnk->point_index != -1) {
|
||||
/* get last link */
|
||||
for (; lnk->next; lnk = lnk->next) ;
|
||||
|
||||
/* add a new link from the pool */
|
||||
lnk = lnk->next = &gdo->vert_points_mem[gdo->vert_points_usage];
|
||||
gdo->vert_points_usage++;
|
||||
}
|
||||
|
||||
lnk->point_index = point_index;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void cdDM_drawobject_add_vert_point(GPUDrawObject *gdo, int vert_index, int point_index)
|
||||
{
|
||||
GPUVertPointLink *lnk;
|
||||
lnk = &gdo->vert_points[vert_index];
|
||||
if (lnk->point_index == -1) {
|
||||
lnk->point_index = point_index;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* USE_GPU_POINT_LINK */
|
||||
|
||||
/* update the vert_points and triangle_to_mface fields with a new
|
||||
* triangle */
|
||||
static void cdDM_drawobject_add_triangle(GPUDrawObject *gdo,
|
||||
int base_point_index,
|
||||
int face_index,
|
||||
int v1, int v2, int v3)
|
||||
{
|
||||
int i, v[3] = {v1, v2, v3};
|
||||
for (i = 0; i < 3; i++)
|
||||
cdDM_drawobject_add_vert_point(gdo, v[i], base_point_index + i);
|
||||
gdo->triangle_to_mface[base_point_index / 3] = face_index;
|
||||
}
|
||||
|
||||
/* for each vertex, build a list of points related to it; these lists
|
||||
* are stored in an array sized to the number of vertices */
|
||||
static void cdDM_drawobject_init_vert_points(GPUDrawObject *gdo, MFace *f, int totface, int totmat)
|
||||
{
|
||||
GPUBufferMaterial *mat;
|
||||
int i, *mat_orig_to_new;
|
||||
|
||||
mat_orig_to_new = MEM_callocN(sizeof(*mat_orig_to_new) * totmat,
|
||||
"GPUDrawObject.mat_orig_to_new");
|
||||
/* allocate the array and space for links */
|
||||
gdo->vert_points = MEM_mallocN(sizeof(GPUVertPointLink) * gdo->totvert,
|
||||
"GPUDrawObject.vert_points");
|
||||
#ifdef USE_GPU_POINT_LINK
|
||||
gdo->vert_points_mem = MEM_callocN(sizeof(GPUVertPointLink) * gdo->tot_triangle_point,
|
||||
"GPUDrawObject.vert_points_mem");
|
||||
gdo->vert_points_usage = 0;
|
||||
#endif
|
||||
|
||||
/* build a map from the original material indices to the new
|
||||
* GPUBufferMaterial indices */
|
||||
for (i = 0; i < gdo->totmaterial; i++)
|
||||
mat_orig_to_new[gdo->materials[i].mat_nr] = i;
|
||||
|
||||
/* -1 indicates the link is not yet used */
|
||||
for (i = 0; i < gdo->totvert; i++) {
|
||||
#ifdef USE_GPU_POINT_LINK
|
||||
gdo->vert_points[i].link = NULL;
|
||||
#endif
|
||||
gdo->vert_points[i].point_index = -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < totface; i++, f++) {
|
||||
mat = &gdo->materials[mat_orig_to_new[f->mat_nr]];
|
||||
|
||||
/* add triangle */
|
||||
cdDM_drawobject_add_triangle(gdo, mat->start + mat->totpoint,
|
||||
i, f->v1, f->v2, f->v3);
|
||||
mat->totpoint += 3;
|
||||
|
||||
/* add second triangle for quads */
|
||||
if (f->v4) {
|
||||
cdDM_drawobject_add_triangle(gdo, mat->start + mat->totpoint,
|
||||
i, f->v3, f->v4, f->v1);
|
||||
mat->totpoint += 3;
|
||||
}
|
||||
}
|
||||
|
||||
/* map any unused vertices to loose points */
|
||||
for (i = 0; i < gdo->totvert; i++) {
|
||||
if (gdo->vert_points[i].point_index == -1) {
|
||||
gdo->vert_points[i].point_index = gdo->tot_triangle_point + gdo->tot_loose_point;
|
||||
gdo->tot_loose_point++;
|
||||
}
|
||||
}
|
||||
|
||||
MEM_freeN(mat_orig_to_new);
|
||||
}
|
||||
|
||||
/* see GPUDrawObject's structure definition for a description of the
|
||||
* data being initialized here */
|
||||
static GPUDrawObject *cdDM_GPUobject_new(DerivedMesh *dm)
|
||||
{
|
||||
GPUDrawObject *gdo;
|
||||
MFace *mface;
|
||||
int totmat = dm->totmat;
|
||||
int *points_per_mat;
|
||||
int i, curmat, curpoint, totface;
|
||||
|
||||
/* object contains at least one material (default included) so zero means uninitialized dm */
|
||||
BLI_assert(totmat != 0);
|
||||
|
||||
mface = dm->getTessFaceArray(dm);
|
||||
totface = dm->getNumTessFaces(dm);
|
||||
|
||||
/* get the number of points used by each material, treating
|
||||
* each quad as two triangles */
|
||||
points_per_mat = MEM_callocN(sizeof(*points_per_mat) * totmat, "GPU_drawobject_new.mat_orig_to_new");
|
||||
for (i = 0; i < totface; i++)
|
||||
points_per_mat[mface[i].mat_nr] += mface[i].v4 ? 6 : 3;
|
||||
|
||||
/* create the GPUDrawObject */
|
||||
gdo = MEM_callocN(sizeof(GPUDrawObject), "GPUDrawObject");
|
||||
gdo->totvert = dm->getNumVerts(dm);
|
||||
gdo->totedge = dm->getNumEdges(dm);
|
||||
|
||||
/* count the number of materials used by this DerivedMesh */
|
||||
for (i = 0; i < totmat; i++) {
|
||||
if (points_per_mat[i] > 0)
|
||||
gdo->totmaterial++;
|
||||
}
|
||||
|
||||
/* allocate an array of materials used by this DerivedMesh */
|
||||
gdo->materials = MEM_mallocN(sizeof(GPUBufferMaterial) * gdo->totmaterial,
|
||||
"GPUDrawObject.materials");
|
||||
|
||||
/* initialize the materials array */
|
||||
for (i = 0, curmat = 0, curpoint = 0; i < totmat; i++) {
|
||||
if (points_per_mat[i] > 0) {
|
||||
gdo->materials[curmat].start = curpoint;
|
||||
gdo->materials[curmat].totpoint = 0;
|
||||
gdo->materials[curmat].mat_nr = i;
|
||||
|
||||
curpoint += points_per_mat[i];
|
||||
curmat++;
|
||||
}
|
||||
}
|
||||
|
||||
/* store total number of points used for triangles */
|
||||
gdo->tot_triangle_point = curpoint;
|
||||
|
||||
gdo->triangle_to_mface = MEM_mallocN(sizeof(int) * (gdo->tot_triangle_point / 3),
|
||||
"GPUDrawObject.triangle_to_mface");
|
||||
|
||||
cdDM_drawobject_init_vert_points(gdo, mface, totface, totmat);
|
||||
MEM_freeN(points_per_mat);
|
||||
|
||||
return gdo;
|
||||
}
|
||||
|
||||
static void cdDM_foreachMappedVert(
|
||||
DerivedMesh *dm,
|
||||
void (*func)(void *userData, int index, const float co[3], const float no_f[3], const short no_s[3]),
|
||||
@@ -1565,6 +2047,8 @@ static CDDerivedMesh *cdDM_create(const char *desc)
|
||||
dm->drawMappedFacesTex = cdDM_drawMappedFacesTex;
|
||||
dm->drawMappedFacesGLSL = cdDM_drawMappedFacesGLSL;
|
||||
dm->drawMappedFacesMat = cdDM_drawMappedFacesMat;
|
||||
dm->copy_gpu_data = cdDM_copy_gpu_data;
|
||||
dm->gpuObjectNew = cdDM_GPUobject_new;
|
||||
|
||||
dm->foreachMappedVert = cdDM_foreachMappedVert;
|
||||
dm->foreachMappedEdge = cdDM_foreachMappedEdge;
|
||||
|
@@ -83,6 +83,7 @@ static IDType idtypes[] = {
|
||||
{ ID_TE, "Texture", "textures", IDTYPE_FLAGS_ISLINKABLE },
|
||||
{ ID_TXT, "Text", "texts", IDTYPE_FLAGS_ISLINKABLE },
|
||||
{ ID_VF, "VFont", "fonts", IDTYPE_FLAGS_ISLINKABLE },
|
||||
{ ID_GPUWS, "GPUWorkflowShader","workflowshaders", IDTYPE_FLAGS_ISLINKABLE },
|
||||
{ ID_WO, "World", "worlds", IDTYPE_FLAGS_ISLINKABLE },
|
||||
{ ID_WM, "WindowManager", "window_managers", 0 },
|
||||
};
|
||||
|
@@ -67,6 +67,7 @@
|
||||
#include "DNA_vfont_types.h"
|
||||
#include "DNA_windowmanager_types.h"
|
||||
#include "DNA_world_types.h"
|
||||
#include "DNA_view3d_types.h"
|
||||
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_utildefines.h"
|
||||
@@ -113,6 +114,7 @@
|
||||
#include "BKE_scene.h"
|
||||
#include "BKE_text.h"
|
||||
#include "BKE_texture.h"
|
||||
#include "BKE_workflow_shaders.h"
|
||||
#include "BKE_world.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
@@ -521,6 +523,8 @@ ListBase *which_libbase(Main *mainlib, short type)
|
||||
return &(mainlib->palettes);
|
||||
case ID_PC:
|
||||
return &(mainlib->paintcurves);
|
||||
case ID_GPUWS:
|
||||
return &(mainlib->gpuworkflows);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -618,6 +622,7 @@ int set_listbasepointers(Main *main, ListBase **lb)
|
||||
lb[a++] = &(main->library);
|
||||
lb[a++] = &(main->wm);
|
||||
lb[a++] = &(main->mask);
|
||||
lb[a++] = &(main->gpuworkflows);
|
||||
|
||||
lb[a] = NULL;
|
||||
|
||||
@@ -747,6 +752,9 @@ static ID *alloc_libblock_notest(short type)
|
||||
case ID_PC:
|
||||
id = MEM_callocN(sizeof(PaintCurve), "Paint Curve");
|
||||
break;
|
||||
case ID_GPUWS:
|
||||
id = MEM_callocN(sizeof(GPUWorkflowShader), "Workflow Shader");
|
||||
break;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
@@ -1035,6 +1043,9 @@ void BKE_libblock_free_ex(Main *bmain, void *idv, bool do_id_user)
|
||||
case ID_PC:
|
||||
BKE_paint_curve_free((PaintCurve *)id);
|
||||
break;
|
||||
case ID_GPUWS:
|
||||
BKE_workflow_shader_free((GPUWorkflowShader *)id);
|
||||
break;
|
||||
}
|
||||
|
||||
/* avoid notifying on removed data */
|
||||
|
@@ -1629,8 +1629,8 @@ void BKE_mesh_loop_tangents(Mesh *mesh, const char *uvmap, float (*r_looptangent
|
||||
* computing newell normal.
|
||||
*
|
||||
*/
|
||||
static void mesh_calc_ngon_normal(MPoly *mpoly, MLoop *loopstart,
|
||||
MVert *mvert, float normal[3])
|
||||
static void mesh_calc_ngon_normal(const MPoly *mpoly, const MLoop *loopstart,
|
||||
const MVert *mvert, float normal[3])
|
||||
{
|
||||
const int nverts = mpoly->totloop;
|
||||
const float *v_prev = mvert[loopstart[nverts - 1].v].co;
|
||||
@@ -1651,8 +1651,8 @@ static void mesh_calc_ngon_normal(MPoly *mpoly, MLoop *loopstart,
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_mesh_calc_poly_normal(MPoly *mpoly, MLoop *loopstart,
|
||||
MVert *mvarray, float no[3])
|
||||
void BKE_mesh_calc_poly_normal(const MPoly *mpoly, const MLoop *loopstart,
|
||||
const MVert *mvarray, float no[3])
|
||||
{
|
||||
if (mpoly->totloop > 4) {
|
||||
mesh_calc_ngon_normal(mpoly, loopstart, mvarray, no);
|
||||
|
@@ -1718,6 +1718,7 @@ void ntreeFreeTree_ex(bNodeTree *ntree, const bool do_id_user)
|
||||
if (ntree->execdata) {
|
||||
switch (ntree->type) {
|
||||
case NTREE_SHADER:
|
||||
case NTREE_WORKFLOW:
|
||||
ntreeShaderEndExecTree(ntree->execdata);
|
||||
break;
|
||||
case NTREE_TEXTURE:
|
||||
@@ -3579,7 +3580,6 @@ static void registerTextureNodes(void)
|
||||
{
|
||||
register_node_type_tex_group();
|
||||
|
||||
|
||||
register_node_type_tex_math();
|
||||
register_node_type_tex_mix_rgb();
|
||||
register_node_type_tex_valtorgb();
|
||||
@@ -3597,6 +3597,7 @@ static void registerTextureNodes(void)
|
||||
register_node_type_tex_output();
|
||||
register_node_type_tex_viewer();
|
||||
register_node_type_sh_script();
|
||||
register_node_type_sh_script_glsl();
|
||||
register_node_type_sh_tangent();
|
||||
register_node_type_sh_normal_map();
|
||||
register_node_type_sh_hair_info();
|
||||
@@ -3637,6 +3638,7 @@ void init_nodesystem(void)
|
||||
|
||||
register_node_tree_type_cmp();
|
||||
register_node_tree_type_sh();
|
||||
register_node_tree_type_workflow();
|
||||
register_node_tree_type_tex();
|
||||
|
||||
register_node_type_frame();
|
||||
@@ -3701,6 +3703,7 @@ void BKE_node_tree_iter_init(struct NodeTreeIterStore *ntreeiter, struct Main *b
|
||||
ntreeiter->lamp = bmain->lamp.first;
|
||||
ntreeiter->world = bmain->world.first;
|
||||
ntreeiter->linestyle = bmain->linestyle.first;
|
||||
ntreeiter->wfshader = bmain->gpuworkflows.first;
|
||||
}
|
||||
bool BKE_node_tree_iter_step(struct NodeTreeIterStore *ntreeiter,
|
||||
bNodeTree **r_nodetree, struct ID **r_id)
|
||||
@@ -3740,6 +3743,11 @@ bool BKE_node_tree_iter_step(struct NodeTreeIterStore *ntreeiter,
|
||||
*r_id = (ID *)ntreeiter->linestyle;
|
||||
ntreeiter->linestyle = ntreeiter->linestyle->id.next;
|
||||
}
|
||||
else if (ntreeiter->wfshader) {
|
||||
*r_nodetree = ntreeiter->wfshader->nodetree;
|
||||
*r_id = (ID *)ntreeiter->wfshader;
|
||||
ntreeiter->wfshader = ntreeiter->wfshader->id.next;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
|
@@ -72,6 +72,7 @@
|
||||
#include "GPU_draw.h"
|
||||
#include "GPU_extensions.h"
|
||||
#include "GPU_glew.h"
|
||||
#include "GPU_buffers.h"
|
||||
|
||||
#include "CCGSubSurf.h"
|
||||
|
||||
@@ -1734,12 +1735,25 @@ static void ccgDM_drawLooseEdges(DerivedMesh *dm)
|
||||
}
|
||||
}
|
||||
|
||||
static void ccgDM_NormalFast(float *a, float *b, float *c, float *d, float no[3])
|
||||
{
|
||||
float a_cX = c[0] - a[0], a_cY = c[1] - a[1], a_cZ = c[2] - a[2];
|
||||
float b_dX = d[0] - b[0], b_dY = d[1] - b[1], b_dZ = d[2] - b[2];
|
||||
|
||||
no[0] = b_dY * a_cZ - b_dZ * a_cY;
|
||||
no[1] = b_dZ * a_cX - b_dX * a_cZ;
|
||||
no[2] = b_dX * a_cY - b_dY * a_cX;
|
||||
|
||||
normalize_v3(no);
|
||||
}
|
||||
|
||||
|
||||
static void ccgDM_glNormalFast(float *a, float *b, float *c, float *d)
|
||||
{
|
||||
float a_cX = c[0] - a[0], a_cY = c[1] - a[1], a_cZ = c[2] - a[2];
|
||||
float b_dX = d[0] - b[0], b_dY = d[1] - b[1], b_dZ = d[2] - b[2];
|
||||
float no[3];
|
||||
|
||||
|
||||
no[0] = b_dY * a_cZ - b_dZ * a_cY;
|
||||
no[1] = b_dZ * a_cX - b_dX * a_cZ;
|
||||
no[2] = b_dX * a_cY - b_dY * a_cX;
|
||||
@@ -1748,9 +1762,309 @@ static void ccgDM_glNormalFast(float *a, float *b, float *c, float *d)
|
||||
glNormal3fv(no);
|
||||
}
|
||||
|
||||
/* Only used by non-editmesh types */
|
||||
static void ccgDM_prepare_normal_data(DerivedMesh *dm, float *varray, int *vindex,
|
||||
int *mat_orig_to_new, void *UNUSED(user_data))
|
||||
{
|
||||
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
||||
CCGSubSurf *ss = ccgdm->ss;
|
||||
CCGKey key;
|
||||
short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
|
||||
int gridSize = ccgSubSurf_getGridSize(ss);
|
||||
int gridFaces = gridSize - 1;
|
||||
DMFlagMat *faceFlags = ccgdm->faceFlags;
|
||||
int i, totface = ccgSubSurf_getNumFaces(ss);
|
||||
int matnr, shademodel;
|
||||
int start;
|
||||
|
||||
CCG_key_top_level(&key, ss);
|
||||
ccgdm_pbvh_update(ccgdm);
|
||||
|
||||
for (i = 0; i < totface; i++) {
|
||||
CCGFace *f = ccgdm->faceMap[i].face;
|
||||
int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
|
||||
int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
|
||||
short (*ln)[4][3] = NULL;
|
||||
|
||||
if (faceFlags) {
|
||||
shademodel = (lnors || (faceFlags[index].flag & ME_SMOOTH)) ? GL_SMOOTH : GL_FLAT;
|
||||
matnr = faceFlags[index].mat_nr;
|
||||
}
|
||||
else {
|
||||
shademodel = GL_SMOOTH;
|
||||
matnr = 0;
|
||||
}
|
||||
|
||||
if (lnors) {
|
||||
ln = lnors;
|
||||
lnors += gridFaces * gridFaces * numVerts;
|
||||
}
|
||||
|
||||
for (S = 0; S < numVerts; S++) {
|
||||
CCGElem *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
|
||||
|
||||
if (ln) {
|
||||
/* Can't use quad strips here... */
|
||||
for (y = 0; y < gridFaces; y ++) {
|
||||
for (x = 0; x < gridFaces; x ++) {
|
||||
start = vindex[mat_orig_to_new[matnr]];
|
||||
|
||||
normal_short_to_float_v3(&varray[start], ln[0][1]);
|
||||
normal_short_to_float_v3(&varray[start + 3], ln[0][2]);
|
||||
normal_short_to_float_v3(&varray[start + 6], ln[0][3]);
|
||||
|
||||
normal_short_to_float_v3(&varray[start + 9], ln[0][3]);
|
||||
normal_short_to_float_v3(&varray[start + 12], ln[0][1]);
|
||||
normal_short_to_float_v3(&varray[start + 15], ln[0][0]);
|
||||
|
||||
vindex[mat_orig_to_new[matnr]] += 18;
|
||||
|
||||
ln ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (shademodel == GL_SMOOTH) {
|
||||
for (y = 0; y < gridFaces; y ++) {
|
||||
for (x = 0; x < gridFaces; x ++) {
|
||||
float *a = CCG_grid_elem_no(&key, faceGridData, x, y );
|
||||
float *b = CCG_grid_elem_no(&key, faceGridData, x + 1, y);
|
||||
float *c = CCG_grid_elem_no(&key, faceGridData, x + 1, y + 1);
|
||||
float *d = CCG_grid_elem_no(&key, faceGridData, x, y + 1);
|
||||
|
||||
start = vindex[mat_orig_to_new[matnr]];
|
||||
|
||||
copy_v3_v3(&varray[start], d);
|
||||
copy_v3_v3(&varray[start + 3], c);
|
||||
copy_v3_v3(&varray[start + 6], b);
|
||||
|
||||
copy_v3_v3(&varray[start + 9], d);
|
||||
copy_v3_v3(&varray[start + 12], b);
|
||||
copy_v3_v3(&varray[start + 15], a);
|
||||
|
||||
vindex[mat_orig_to_new[matnr]] += 18;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (y = 0; y < gridFaces; y ++) {
|
||||
for (x = 0; x < gridFaces; x ++) {
|
||||
float no[3];
|
||||
float *a = CCG_grid_elem_co(&key, faceGridData, x, y );
|
||||
float *b = CCG_grid_elem_co(&key, faceGridData, x + 1, y );
|
||||
float *c = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1);
|
||||
float *d = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
|
||||
|
||||
ccgDM_NormalFast(a, b, c, d, no);
|
||||
|
||||
start = vindex[mat_orig_to_new[matnr]];
|
||||
|
||||
copy_v3_v3(&varray[start], no);
|
||||
copy_v3_v3(&varray[start + 3], no);
|
||||
copy_v3_v3(&varray[start + 6], no);
|
||||
|
||||
copy_v3_v3(&varray[start + 9], no);
|
||||
copy_v3_v3(&varray[start + 12], no);
|
||||
copy_v3_v3(&varray[start + 15], no);
|
||||
|
||||
vindex[mat_orig_to_new[matnr]] += 18;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Only used by non-editmesh types */
|
||||
static void ccgDM_prepare_vertex_data(DerivedMesh *dm, float *varray, int *vindex,
|
||||
int *mat_orig_to_new, void *UNUSED(user_data))
|
||||
{
|
||||
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
||||
CCGSubSurf *ss = ccgdm->ss;
|
||||
CCGKey key;
|
||||
int gridSize = ccgSubSurf_getGridSize(ss);
|
||||
int gridFaces = gridSize - 1;
|
||||
DMFlagMat *faceFlags = ccgdm->faceFlags;
|
||||
int i, totface = ccgSubSurf_getNumFaces(ss);
|
||||
int matnr = -1, start;
|
||||
|
||||
CCG_key_top_level(&key, ss);
|
||||
ccgdm_pbvh_update(ccgdm);
|
||||
|
||||
for (i = 0; i < totface; i++) {
|
||||
CCGFace *f = ccgdm->faceMap[i].face;
|
||||
int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
|
||||
int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
|
||||
|
||||
if (faceFlags) {
|
||||
matnr = faceFlags[index].mat_nr;
|
||||
}
|
||||
else {
|
||||
matnr = 0;
|
||||
}
|
||||
|
||||
for (S = 0; S < numVerts; S++) {
|
||||
CCGElem *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
|
||||
for (y = 0; y < gridFaces; y++) {
|
||||
for (x = 0; x < gridFaces; x++) {
|
||||
float *a = CCG_grid_elem_co(&key, faceGridData, x, y);
|
||||
float *b = CCG_grid_elem_co(&key, faceGridData, x + 1, y);
|
||||
float *c = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1);
|
||||
float *d = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
|
||||
|
||||
start = vindex[mat_orig_to_new[matnr]];
|
||||
|
||||
copy_v3_v3(&varray[start], d);
|
||||
copy_v3_v3(&varray[start + 3], c);
|
||||
copy_v3_v3(&varray[start + 6], b);
|
||||
|
||||
copy_v3_v3(&varray[start + 9], d);
|
||||
copy_v3_v3(&varray[start + 12], b);
|
||||
copy_v3_v3(&varray[start + 15], a);
|
||||
|
||||
vindex[mat_orig_to_new[matnr]] += 18;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ccgDM_copy_gpu_data(DerivedMesh *dm, int type, float *varray, int *index,
|
||||
int *mat_orig_to_new, void *UNUSED(user_data))
|
||||
{
|
||||
switch(type) {
|
||||
case GPU_BUFFER_VERTEX:
|
||||
ccgDM_prepare_vertex_data(dm, varray, index, mat_orig_to_new, NULL);
|
||||
break;
|
||||
case GPU_BUFFER_NORMAL:
|
||||
ccgDM_prepare_normal_data(dm, varray, index, mat_orig_to_new, NULL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static GPUDrawObject *ccgDM_GPUObjectNew(DerivedMesh *dm) {
|
||||
// GPUBufferMaterial *mat;
|
||||
int *mat_orig_to_new;
|
||||
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
||||
CCGSubSurf *ss = ccgdm->ss;
|
||||
GPUDrawObject *gdo;
|
||||
DMFlagMat *faceFlags = ccgdm->faceFlags;
|
||||
int gridSize = ccgSubSurf_getGridSize(ss);
|
||||
int gridFaces = gridSize - 1;
|
||||
int totmat = (faceFlags) ? dm->totmat : 1;
|
||||
int *points_per_mat;
|
||||
int i, curmat, curpoint, totface;
|
||||
|
||||
/* object contains at least one material (default included) so zero means uninitialized dm */
|
||||
BLI_assert(totmat != 0);
|
||||
|
||||
totface = ccgSubSurf_getNumFaces(ss);
|
||||
|
||||
points_per_mat = MEM_callocN(sizeof(*points_per_mat) * totmat, "GPU_drawobject_new.mat_orig_to_new");
|
||||
|
||||
if (faceFlags) {
|
||||
for (i = 0; i < totface; i++) {
|
||||
CCGFace *f = ccgdm->faceMap[i].face;
|
||||
int numVerts = ccgSubSurf_getFaceNumVerts(f);
|
||||
int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
|
||||
int new_matnr = faceFlags[index].mat_nr;
|
||||
points_per_mat[new_matnr] += numVerts * gridFaces * gridFaces * 6;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < totface; i++) {
|
||||
points_per_mat[0] += gridFaces * gridFaces * 6;
|
||||
}
|
||||
}
|
||||
|
||||
/* create the GPUDrawObject */
|
||||
gdo = MEM_callocN(sizeof(GPUDrawObject), "GPUDrawObject");
|
||||
gdo->totvert = ccgSubSurf_getNumFinalFaces(ss) * 6;
|
||||
gdo->totedge = ccgSubSurf_getNumFinalEdges(ss) * 2;
|
||||
|
||||
/* count the number of materials used by this DerivedMesh */
|
||||
for (i = 0; i < totmat; i++) {
|
||||
if (points_per_mat[i] > 0)
|
||||
gdo->totmaterial++;
|
||||
}
|
||||
|
||||
/* allocate an array of materials used by this DerivedMesh */
|
||||
gdo->materials = MEM_mallocN(sizeof(GPUBufferMaterial) * gdo->totmaterial,
|
||||
"GPUDrawObject.materials");
|
||||
|
||||
/* initialize the materials array */
|
||||
for (i = 0, curmat = 0, curpoint = 0; i < totmat; i++) {
|
||||
if (points_per_mat[i] > 0) {
|
||||
gdo->materials[curmat].start = curpoint;
|
||||
gdo->materials[curmat].totpoint = points_per_mat[i];
|
||||
gdo->materials[curmat].mat_nr = i;
|
||||
|
||||
curpoint += points_per_mat[i];
|
||||
curmat++;
|
||||
}
|
||||
}
|
||||
|
||||
/* store total number of points used for triangles */
|
||||
gdo->tot_triangle_point = curpoint;
|
||||
|
||||
mat_orig_to_new = MEM_callocN(sizeof(*mat_orig_to_new) * totmat,
|
||||
"GPUDrawObject.mat_orig_to_new");
|
||||
|
||||
/* build a map from the original material indices to the new
|
||||
* GPUBufferMaterial indices */
|
||||
for (i = 0; i < gdo->totmaterial; i++) {
|
||||
mat_orig_to_new[gdo->materials[i].mat_nr] = i;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
for (i = 0; i < totface; i++) {
|
||||
CCGFace *f = ccgdm->faceMap[i].face;
|
||||
int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
|
||||
int new_matnr = faceFlags[index].mat_nr;
|
||||
|
||||
mat = &gdo->materials[mat_orig_to_new[new_matnr]];
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
MEM_freeN(mat_orig_to_new);
|
||||
MEM_freeN(points_per_mat);
|
||||
|
||||
return gdo;
|
||||
}
|
||||
|
||||
/* Only used by non-editmesh types */
|
||||
static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)[4], bool fast, DMSetMaterial setMaterial)
|
||||
{
|
||||
int a;
|
||||
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
||||
|
||||
if (ccgdm->pbvh && ccgdm->multires.mmd && !fast) {
|
||||
if (BKE_pbvh_has_faces(ccgdm->pbvh)) {
|
||||
BKE_pbvh_draw(ccgdm->pbvh, partial_redraw_planes, NULL,
|
||||
setMaterial, false);
|
||||
glShadeModel(GL_FLAT);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
GPU_vertex_setup(dm);
|
||||
GPU_normal_setup(dm);
|
||||
glShadeModel(GL_SMOOTH);
|
||||
for (a = 0; a < dm->drawObject->totmaterial; a++) {
|
||||
if (!setMaterial || setMaterial(dm->drawObject->materials[a].mat_nr + 1, NULL)) {
|
||||
glDrawArrays(GL_TRIANGLES, dm->drawObject->materials[a].start,
|
||||
dm->drawObject->materials[a].totpoint);
|
||||
}
|
||||
}
|
||||
GPU_buffer_unbind();
|
||||
|
||||
#if 0
|
||||
|
||||
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
|
||||
CCGSubSurf *ss = ccgdm->ss;
|
||||
CCGKey key;
|
||||
@@ -1765,15 +2079,6 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)
|
||||
CCG_key_top_level(&key, ss);
|
||||
ccgdm_pbvh_update(ccgdm);
|
||||
|
||||
if (ccgdm->pbvh && ccgdm->multires.mmd && !fast) {
|
||||
if (BKE_pbvh_has_faces(ccgdm->pbvh)) {
|
||||
BKE_pbvh_draw(ccgdm->pbvh, partial_redraw_planes, NULL,
|
||||
setMaterial, false);
|
||||
glShadeModel(GL_FLAT);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < totface; i++) {
|
||||
CCGFace *f = ccgdm->faceMap[i].face;
|
||||
@@ -1873,6 +2178,8 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Only used by non-editmesh types */
|
||||
@@ -3492,6 +3799,8 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
|
||||
|
||||
ccgdm->dm.drawMappedEdgesInterp = ccgDM_drawMappedEdgesInterp;
|
||||
ccgdm->dm.drawMappedEdges = ccgDM_drawMappedEdges;
|
||||
ccgdm->dm.gpuObjectNew = ccgDM_GPUObjectNew;
|
||||
ccgdm->dm.copy_gpu_data = ccgDM_copy_gpu_data;
|
||||
|
||||
ccgdm->dm.release = ccgDM_release;
|
||||
|
||||
|
66
source/blender/blenkernel/intern/workflow_shaders.c
Normal file
66
source/blender/blenkernel/intern/workflow_shaders.c
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): Antony Riakiotakis.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/blenkernel/intern/workflow_shaders.c
|
||||
* \ingroup bke
|
||||
*/
|
||||
|
||||
#include "DNA_view3d_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
|
||||
#include "BKE_library.h"
|
||||
#include "BKE_node.h"
|
||||
#include "BKE_workflow_shaders.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
|
||||
void BKE_workflow_shader_free(GPUWorkflowShader *shader)
|
||||
{
|
||||
/* is no lib link block, but world extension */
|
||||
if (shader->nodetree) {
|
||||
/* will be freed once this is handled properly, currently this resides in nodetree list */
|
||||
//ntreeFreeTree_ex(shader->nodetree, true);
|
||||
//MEM_freeN(shader->nodetree);
|
||||
//shader->nodetree = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
struct GPUWorkflowShader *BKE_workflow_shader_add(struct Main *bmain, const char *name)
|
||||
{
|
||||
GPUWorkflowShader *wfshader;
|
||||
|
||||
wfshader = BKE_libblock_alloc(bmain, ID_GPUWS, name);
|
||||
|
||||
/* enable fake user by default */
|
||||
wfshader->id.flag |= LIB_FAKEUSER;
|
||||
|
||||
/* initially active only for object mode */
|
||||
wfshader->objectmode |= OB_MODE_OBJECT;
|
||||
|
||||
return wfshader;
|
||||
}
|
@@ -2520,6 +2520,7 @@ static bNodeTree *nodetree_from_id(ID *id)
|
||||
case ID_LA: return ((Lamp *)id)->nodetree;
|
||||
case ID_TE: return ((Tex *)id)->nodetree;
|
||||
case ID_LS: return ((FreestyleLineStyle *)id)->nodetree;
|
||||
case ID_GPUWS: return ((GPUWorkflowShader *)id)->nodetree;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -2793,7 +2794,7 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
|
||||
|
||||
if (node->storage) {
|
||||
/* could be handlerized at some point */
|
||||
if (ntree->type==NTREE_SHADER) {
|
||||
if (ELEM(ntree->type, NTREE_SHADER, NTREE_WORKFLOW)) {
|
||||
if (node->type==SH_NODE_CURVE_VEC || node->type==SH_NODE_CURVE_RGB) {
|
||||
direct_link_curvemapping(fd, node->storage);
|
||||
}
|
||||
@@ -2801,6 +2802,10 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
|
||||
NodeShaderScript *nss = (NodeShaderScript *) node->storage;
|
||||
nss->bytecode = newdataadr(fd, nss->bytecode);
|
||||
}
|
||||
else if (node->type==SH_NODE_SCRIPT_GLSL) {
|
||||
NodeShaderScriptGLSL *nss = (NodeShaderScriptGLSL *) node->storage;
|
||||
/* TODO: whatever */
|
||||
}
|
||||
}
|
||||
else if (ntree->type==NTREE_COMPOSIT) {
|
||||
if (ELEM(node->type, CMP_NODE_TIME, CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB, CMP_NODE_HUECORRECT))
|
||||
@@ -3085,6 +3090,30 @@ static void direct_link_camera(FileData *fd, Camera *ca)
|
||||
direct_link_animdata(fd, ca->adt);
|
||||
}
|
||||
|
||||
/*************** READ WORKFLOW SHADER *****************/
|
||||
|
||||
static void lib_link_workflow_shader(FileData *fd, Main *main)
|
||||
{
|
||||
GPUWorkflowShader *wfshader;
|
||||
|
||||
/* only link ID pointers */
|
||||
for (wfshader = main->gpuworkflows.first; wfshader; wfshader = wfshader->id.next) {
|
||||
if (wfshader->id.flag & LIB_NEED_LINK) {
|
||||
wfshader->id.flag -= LIB_NEED_LINK;
|
||||
|
||||
if (wfshader->nodetree) {
|
||||
lib_link_ntree(fd, &wfshader->id, wfshader->nodetree);
|
||||
wfshader->nodetree->id.lib = wfshader->id.lib;
|
||||
wfshader->nodetree->view_center[0] = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void direct_link_workflow_shader(FileData *fd, GPUWorkflowShader *wfshader)
|
||||
{
|
||||
wfshader->nodetree = newdataadr(fd, wfshader->nodetree);
|
||||
}
|
||||
|
||||
/* ************ READ LAMP ***************** */
|
||||
|
||||
@@ -5945,6 +5974,7 @@ static void lib_link_screen(FileData *fd, Main *main)
|
||||
View3D *v3d = (View3D*) sl;
|
||||
BGpic *bgpic = NULL;
|
||||
|
||||
v3d->activeworkflow = newlibadr(fd, sc->id.lib, v3d->activeworkflow);
|
||||
v3d->camera= newlibadr(fd, sc->id.lib, v3d->camera);
|
||||
v3d->ob_centre= newlibadr(fd, sc->id.lib, v3d->ob_centre);
|
||||
|
||||
@@ -6244,6 +6274,7 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
|
||||
if (v3d->camera == NULL)
|
||||
v3d->camera = sc->scene->camera;
|
||||
v3d->ob_centre = restore_pointer_by_name(newmain, (ID *)v3d->ob_centre, USER_ONE);
|
||||
v3d->activeworkflow = restore_pointer_by_name(newmain, (ID *)v3d->activeworkflow, USER_ONE);
|
||||
|
||||
for (bgpic= v3d->bgpicbase.first; bgpic; bgpic= bgpic->next) {
|
||||
if ((bgpic->ima = restore_pointer_by_name(newmain, (ID *)bgpic->ima, USER_IGNORE))) {
|
||||
@@ -7690,6 +7721,9 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID
|
||||
case ID_PC:
|
||||
direct_link_paint_curve(fd, (PaintCurve *)id);
|
||||
break;
|
||||
case ID_GPUWS:
|
||||
direct_link_workflow_shader(fd, (GPUWorkflowShader *)id);
|
||||
break;
|
||||
}
|
||||
|
||||
oldnewmap_free_unused(fd->datamap);
|
||||
@@ -7877,6 +7911,7 @@ static void lib_link_all(FileData *fd, Main *main)
|
||||
lib_link_nodetree(fd, main); /* has to be done after scene/materials, this will verify group nodes */
|
||||
lib_link_brush(fd, main);
|
||||
lib_link_palette(fd, main);
|
||||
lib_link_workflow_shader(fd, main);
|
||||
lib_link_paint_curve(fd, main);
|
||||
lib_link_particlesettings(fd, main);
|
||||
lib_link_movieclip(fd, main);
|
||||
|
@@ -869,10 +869,11 @@ static void write_nodetree(WriteData *wd, bNodeTree *ntree)
|
||||
writestruct(wd, DATA, "bNodeLink", 1, link);
|
||||
if (node->storage) {
|
||||
/* could be handlerized at some point, now only 1 exception still */
|
||||
if (ntree->type==NTREE_SHADER && (node->type==SH_NODE_CURVE_VEC || node->type==SH_NODE_CURVE_RGB))
|
||||
if (ELEM(ntree->type, NTREE_SHADER, NTREE_WORKFLOW) && (node->type==SH_NODE_CURVE_VEC || node->type==SH_NODE_CURVE_RGB))
|
||||
write_curvemapping(wd, node->storage);
|
||||
else if (ntree->type==NTREE_SHADER && node->type==SH_NODE_SCRIPT) {
|
||||
NodeShaderScript *nss = (NodeShaderScript *)node->storage;
|
||||
/* XXX merwin: empty GLSL shader node can use the 'else' clause below */
|
||||
if (nss->bytecode)
|
||||
writedata(wd, DATA, strlen(nss->bytecode)+1, nss->bytecode);
|
||||
writestruct(wd, DATA, node->typeinfo->storagename, 1, node->storage);
|
||||
@@ -3182,6 +3183,23 @@ static void write_paintcurves(WriteData *wd, ListBase *idbase)
|
||||
}
|
||||
}
|
||||
|
||||
static void write_gpuworkflows(WriteData *wd, ListBase *idbase)
|
||||
{
|
||||
GPUWorkflowShader *wfshader;
|
||||
|
||||
for (wfshader = idbase->first; wfshader; wfshader = wfshader->id.next) {
|
||||
if (wfshader->id.us > 0 || wd->current) {
|
||||
writestruct(wd, ID_GPUWS, "GPUWorkflowShader", 1, wfshader);
|
||||
if (wfshader->nodetree) {
|
||||
writestruct(wd, DATA, "bNodeTree", 1, wfshader->nodetree);
|
||||
write_nodetree(wd, wfshader->nodetree);
|
||||
}
|
||||
if (wfshader->id.properties) IDP_WriteProperty(wfshader->id.properties, wd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void write_scripts(WriteData *wd, ListBase *idbase)
|
||||
{
|
||||
Script *script;
|
||||
@@ -3657,6 +3675,7 @@ static int write_file_handle(
|
||||
write_brushes (wd, &mainvar->brush);
|
||||
write_palettes (wd, &mainvar->palettes);
|
||||
write_paintcurves (wd, &mainvar->paintcurves);
|
||||
write_gpuworkflows (wd, &mainvar->gpuworkflows);
|
||||
write_scripts (wd, &mainvar->script);
|
||||
write_gpencils (wd, &mainvar->gpencil);
|
||||
write_linestyles(wd, &mainvar->linestyle);
|
||||
|
@@ -2949,6 +2949,7 @@ void ED_node_init_butfuncs(void)
|
||||
ntreeType_Composite->ui_icon = ICON_RENDERLAYERS;
|
||||
ntreeType_Shader->ui_icon = ICON_MATERIAL;
|
||||
ntreeType_Texture->ui_icon = ICON_TEXTURE;
|
||||
ntreeType_Workflow->ui_icon = ICON_SMOOTH;
|
||||
}
|
||||
|
||||
void ED_init_custom_node_type(bNodeType *ntype)
|
||||
|
@@ -134,6 +134,9 @@ void ED_node_tag_update_id(ID *id)
|
||||
else if (GS(id->name) == ID_WO)
|
||||
WM_main_add_notifier(NC_WORLD | ND_WORLD, id);
|
||||
}
|
||||
else if (ntree->type == NTREE_WORKFLOW) {
|
||||
WM_main_add_notifier(NC_SCENE | ND_NODES, id);
|
||||
}
|
||||
else if (ntree->type == NTREE_COMPOSIT) {
|
||||
WM_main_add_notifier(NC_SCENE | ND_NODES, id);
|
||||
}
|
||||
|
@@ -2372,6 +2372,8 @@ void NODE_OT_tree_socket_move(wmOperatorType *ot)
|
||||
|
||||
/* ********************** Shader Script Update ******************/
|
||||
|
||||
/* TODO: similar for GLSL node --merwin */
|
||||
|
||||
static int node_shader_script_update_poll(bContext *C)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
|
@@ -423,6 +423,9 @@ static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname)
|
||||
else
|
||||
compatibility = NODE_OLD_SHADING;
|
||||
}
|
||||
else if (ntree->type == NTREE_WORKFLOW) {
|
||||
compatibility = NODE_WORKFLOW_SHADING;
|
||||
}
|
||||
|
||||
NODE_TYPES_BEGIN(ntype) {
|
||||
NodeLinkItem *items;
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -98,6 +98,7 @@
|
||||
#include "GPU_material.h"
|
||||
#include "GPU_extensions.h"
|
||||
#include "GPU_compositing.h"
|
||||
#include "GPUx_draw.h"
|
||||
|
||||
#include "view3d_intern.h" /* own include */
|
||||
|
||||
@@ -557,6 +558,170 @@ static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit, bool wr
|
||||
glDepthMask(GL_TRUE);
|
||||
}
|
||||
|
||||
static void drawfloor_new(Scene *scene, View3D *v3d, const char **grid_unit)
|
||||
{
|
||||
/* draw only if there is something to draw */
|
||||
if (v3d->gridflag & (V3D_SHOW_FLOOR | V3D_SHOW_X | V3D_SHOW_Y | V3D_SHOW_Z)) {
|
||||
/* draw how many lines?
|
||||
* trunc(v3d->gridlines / 2) * 4
|
||||
* + 2 for xy axes (possibly with special colors)
|
||||
* + 1 for z axis (the only line not in xy plane)
|
||||
* even v3d->gridlines are honored, odd rounded down */
|
||||
const int gridlines = v3d->gridlines / 2;
|
||||
const float grid_scale = ED_view3d_grid_scale(scene, v3d, grid_unit);
|
||||
const float grid = gridlines * grid_scale;
|
||||
|
||||
const bool show_floor = (v3d->gridflag & V3D_SHOW_FLOOR) && gridlines >= 1;
|
||||
|
||||
unsigned char col_grid[3], col_axis[3];
|
||||
|
||||
UI_GetThemeColor3ubv(TH_GRID, col_grid);
|
||||
|
||||
if (show_floor) {
|
||||
const unsigned vertex_ct = 2 * (gridlines * 4 + 2);
|
||||
unsigned v = 0; /* verts drawn so far */
|
||||
VertexBuffer *verts = GPUx_vertex_buffer_create(2, vertex_ct);
|
||||
const int sublines = v3d->gridsubdiv;
|
||||
int a;
|
||||
|
||||
unsigned char col_bg[3], col_grid_emphasise[3], col_grid_light[3];
|
||||
unsigned char *col_current = NULL;
|
||||
|
||||
GPUx_specify_attrib(verts, 0, GL_VERTEX_ARRAY, GL_FLOAT, 2, KEEP_FLOAT);
|
||||
GPUx_specify_attrib(verts, 1, GL_COLOR_ARRAY, GL_UNSIGNED_BYTE, 3, NORMALIZE_INT_TO_FLOAT);
|
||||
|
||||
glDepthFunc(GL_ALWAYS); /* draw lines in order given */
|
||||
|
||||
/* draw normal grid lines */
|
||||
UI_GetColorPtrShade3ubv(col_grid, col_grid_light, 10);
|
||||
col_current = col_grid_light;
|
||||
|
||||
for (a = 1; a <= gridlines; a++) {
|
||||
/* skip emphasised divider lines */
|
||||
if (a % sublines != 0) {
|
||||
const float line = a * grid_scale;
|
||||
int i;
|
||||
/* same color at each vertex */
|
||||
for (i = 0; i < 8; ++i)
|
||||
GPUx_set_attrib(verts, 1, v + i, col_current);
|
||||
|
||||
/* set positions */
|
||||
GPUx_set_attrib_2f(verts, 0, v + 0, -grid, -line);
|
||||
GPUx_set_attrib_2f(verts, 0, v + 1, +grid, -line);
|
||||
GPUx_set_attrib_2f(verts, 0, v + 2, -grid, +line);
|
||||
GPUx_set_attrib_2f(verts, 0, v + 3, +grid, +line);
|
||||
|
||||
GPUx_set_attrib_2f(verts, 0, v + 4, -line, -grid);
|
||||
GPUx_set_attrib_2f(verts, 0, v + 5, -line, +grid);
|
||||
GPUx_set_attrib_2f(verts, 0, v + 6, +line, -grid);
|
||||
GPUx_set_attrib_2f(verts, 0, v + 7, +line, +grid);
|
||||
|
||||
v += 8;
|
||||
}
|
||||
}
|
||||
|
||||
/* draw emphasised grid lines */
|
||||
UI_GetThemeColor3ubv(TH_BACK, col_bg);
|
||||
/* emphasise division lines lighter instead of darker, if background is darker than grid */
|
||||
UI_GetColorPtrShade3ubv(col_grid, col_grid_emphasise,
|
||||
(col_grid[0] + col_grid[1] + col_grid[2] + 30 >
|
||||
col_bg[0] + col_bg[1] + col_bg[2]) ? 20 : -10);
|
||||
col_current = col_grid_emphasise;
|
||||
|
||||
for (a = sublines; a <= gridlines; a += sublines) {
|
||||
const float line = a * grid_scale;
|
||||
int i;
|
||||
/* same color at each vertex */
|
||||
for (i = 0; i < 8; ++i)
|
||||
GPUx_set_attrib(verts, 1, v + i, col_current);
|
||||
|
||||
/* set positions */
|
||||
GPUx_set_attrib_2f(verts, 0, v + 0, -grid, -line);
|
||||
GPUx_set_attrib_2f(verts, 0, v + 1, +grid, -line);
|
||||
GPUx_set_attrib_2f(verts, 0, v + 2, -grid, +line);
|
||||
GPUx_set_attrib_2f(verts, 0, v + 3, +grid, +line);
|
||||
|
||||
GPUx_set_attrib_2f(verts, 0, v + 4, -line, -grid);
|
||||
GPUx_set_attrib_2f(verts, 0, v + 5, -line, +grid);
|
||||
GPUx_set_attrib_2f(verts, 0, v + 6, +line, -grid);
|
||||
GPUx_set_attrib_2f(verts, 0, v + 7, +line, +grid);
|
||||
|
||||
v += 8;
|
||||
}
|
||||
|
||||
/* draw X axis */
|
||||
if (v3d->gridflag & V3D_SHOW_X) {
|
||||
UI_make_axis_color(col_grid, col_axis, 'X');
|
||||
col_current = col_axis;
|
||||
}
|
||||
else
|
||||
col_current = col_grid_emphasise;
|
||||
|
||||
GPUx_set_attrib(verts, 1, v + 0, col_current);
|
||||
GPUx_set_attrib(verts, 1, v + 1, col_current);
|
||||
|
||||
GPUx_set_attrib_2f(verts, 0, v + 0, -grid, 0.0f);
|
||||
GPUx_set_attrib_2f(verts, 0, v + 1, +grid, 0.0f);
|
||||
|
||||
/* draw Y axis */
|
||||
if (v3d->gridflag & V3D_SHOW_Y) {
|
||||
UI_make_axis_color(col_grid, col_axis, 'Y');
|
||||
col_current = col_axis;
|
||||
}
|
||||
else
|
||||
col_current = col_grid_emphasise;
|
||||
|
||||
GPUx_set_attrib(verts, 1, v + 2, col_current);
|
||||
GPUx_set_attrib(verts, 1, v + 3, col_current);
|
||||
|
||||
GPUx_set_attrib_2f(verts, 0, v + 2, 0.0f, -grid);
|
||||
GPUx_set_attrib_2f(verts, 0, v + 3, 0.0f, +grid);
|
||||
|
||||
v += 4;
|
||||
|
||||
BLI_assert(v == vertex_ct);
|
||||
|
||||
GPUx_vertex_buffer_prime(verts);
|
||||
GPUx_draw_lines(verts, NULL, NULL, NULL);
|
||||
|
||||
GPUx_vertex_buffer_discard(verts);
|
||||
|
||||
/* done with XY plane */
|
||||
|
||||
glDepthFunc(GL_LESS); /* restore default */
|
||||
|
||||
/* maybe draw Z axis */
|
||||
if (v3d->gridflag & V3D_SHOW_Z) {
|
||||
UI_make_axis_color(col_grid, col_axis, 'Z');
|
||||
glColor3ubv(col_axis);
|
||||
|
||||
glBegin(GL_LINES);
|
||||
glVertex3f(0.0f, 0.0f, -grid);
|
||||
glVertex3f(0.0f, 0.0f, +grid);
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* draw just the axis lines */
|
||||
int axis;
|
||||
glBegin(GL_LINES);
|
||||
for (axis = 0; axis < 3; axis++) {
|
||||
if (v3d->gridflag & (V3D_SHOW_X << axis)) {
|
||||
float vert[3] = {0.0f};
|
||||
|
||||
UI_make_axis_color(col_grid, col_axis, 'X' + axis);
|
||||
glColor3ubv(col_axis);
|
||||
|
||||
vert[axis] = grid;
|
||||
glVertex3fv(vert);
|
||||
vert[axis] = -grid;
|
||||
glVertex3fv(vert);
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void drawcursor(Scene *scene, ARegion *ar, View3D *v3d)
|
||||
{
|
||||
@@ -3693,9 +3858,147 @@ static void update_lods(Scene *scene, float camera_pos[3])
|
||||
}
|
||||
#endif
|
||||
|
||||
/* uploads and caches view dependent state such as view/projection matrix */
|
||||
static void view3d_update_view_dependent_uniforms(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static void view3d_main_area_draw_viewport_new(const bContext *UNUSED(C), Scene *scene, View3D *v3d,
|
||||
ARegion *ar, const char **grid_unit)
|
||||
{
|
||||
unsigned int lay_used = 0;
|
||||
Base *base, *base_edit = NULL; /* object being edited, if any */
|
||||
bool do_compositing = false;
|
||||
RegionView3D *rv3d = ar->regiondata;
|
||||
|
||||
#if MCE_TRACE
|
||||
printf("> %s\n", __FUNCTION__);
|
||||
#endif /* MCE_TRACE */
|
||||
|
||||
view3d_main_area_clear(scene, v3d, ar);
|
||||
|
||||
/* setup view matrices */
|
||||
view3d_main_area_setup_view(scene, v3d, ar, NULL, NULL);
|
||||
|
||||
view3d_update_view_dependent_uniforms();
|
||||
|
||||
/* framebuffer fx needed, we need to draw offscreen first */
|
||||
if (v3d->fx_settings.fx_flag) {
|
||||
GPUFXSettings fx_settings;
|
||||
BKE_screen_gpu_fx_validate(&v3d->fx_settings);
|
||||
fx_settings = v3d->fx_settings;
|
||||
if (!rv3d->compositor)
|
||||
rv3d->compositor = GPU_fx_compositor_create();
|
||||
|
||||
if (rv3d->persp == RV3D_CAMOB && v3d->camera)
|
||||
BKE_camera_to_gpu_dof(v3d->camera, &fx_settings);
|
||||
else {
|
||||
fx_settings.dof = NULL;
|
||||
}
|
||||
|
||||
if (v3d->drawtype < OB_SOLID)
|
||||
fx_settings.ssao = NULL;
|
||||
|
||||
do_compositing = GPU_fx_compositor_initialize_passes(rv3d->compositor, &ar->winrct, &ar->drawrct, &fx_settings);
|
||||
}
|
||||
|
||||
/* clear the background */
|
||||
view3d_main_area_clear(scene, v3d, ar);
|
||||
|
||||
GPUx_reset_draw_state(); /* for code below which uses GPUx_state */
|
||||
|
||||
drawfloor_new(scene, v3d, grid_unit);
|
||||
|
||||
/* yanked verbatim from view3d_draw_objects
|
||||
* not perfect but it does let us see objects positioned in space
|
||||
* TODO: draw objects prettier/better/faster/stronger
|
||||
*/
|
||||
|
||||
/* XXX merwin
|
||||
*
|
||||
* Instead of drawing all objects in list order, draw all meshes together
|
||||
* using new methods, then other types using new methods, then remaining
|
||||
* types using existing methods.
|
||||
*
|
||||
* Hand-crafted logic here is tricky; will simplify later.
|
||||
*/
|
||||
|
||||
v3d->zbuf = true;
|
||||
|
||||
/* draw meshes (and cameras) not being edited (selected or not) */
|
||||
for (base = scene->base.first; base; base = base->next) {
|
||||
lay_used |= base->lay;
|
||||
|
||||
if (base->object == scene->obedit) {
|
||||
base_edit = base; /* remember for later */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (v3d->lay & base->lay) {
|
||||
if (base->object->type == OB_MESH || base->object->type == OB_CAMERA) {
|
||||
draw_object_new(scene, ar, v3d, base, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GPUx_reset_draw_state(); /* for code below which does NOT use GPUx_state */
|
||||
|
||||
/* draw non-meshes not being edited nor selected */
|
||||
for (base = scene->base.first; base; base = base->next) {
|
||||
if (base == base_edit)
|
||||
continue;
|
||||
|
||||
if (v3d->lay & base->lay) {
|
||||
if (base->object->type != OB_MESH && base->object->type != OB_CAMERA && (base->flag & SELECT) == 0) {
|
||||
draw_object(scene, ar, v3d, base, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* mask out localview */
|
||||
v3d->lay_used = lay_used & ((1 << 20) - 1);
|
||||
|
||||
/* draw selected non-meshes */
|
||||
for (base = scene->base.first; base; base = base->next) {
|
||||
if (base == base_edit)
|
||||
continue;
|
||||
|
||||
if (v3d->lay & base->lay) {
|
||||
if (base->object->type != OB_MESH && base->object->type != OB_CAMERA && (base->flag & SELECT)) {
|
||||
draw_object(scene, ar, v3d, base, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* draw editmode */
|
||||
/* TODO: verify scene->obedit is always 1) selected and 2) in a visible layer */
|
||||
if (base_edit && (v3d->lay & base_edit->lay)) {
|
||||
draw_object(scene, ar, v3d, base_edit, 0);
|
||||
}
|
||||
|
||||
/* post process */
|
||||
if (do_compositing) {
|
||||
GPU_fx_do_composite_pass(rv3d->compositor, rv3d->winmat, rv3d->is_persp, scene, NULL);
|
||||
}
|
||||
|
||||
|
||||
/* play nice with UI drawing code outside view3d */
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
#if MCE_TRACE
|
||||
printf("< %s\n\n", __FUNCTION__);
|
||||
#endif /* MCE_TRACE */
|
||||
}
|
||||
|
||||
|
||||
static void view3d_main_area_draw_objects(const bContext *C, Scene *scene, View3D *v3d,
|
||||
ARegion *ar, const char **grid_unit)
|
||||
{
|
||||
#if MCE_TRACE
|
||||
printf("> %s\n", __FUNCTION__);
|
||||
#endif /* MCE_TRACE */
|
||||
|
||||
RegionView3D *rv3d = ar->regiondata;
|
||||
unsigned int lay_used = v3d->lay_used;
|
||||
|
||||
@@ -3781,6 +4084,9 @@ static void view3d_main_area_draw_objects(const bContext *C, Scene *scene, View3
|
||||
/* TODO: draw something else (but not this) during fly mode */
|
||||
draw_rotation_guide(rv3d);
|
||||
|
||||
#if MCE_TRACE
|
||||
printf("< %s\n\n", __FUNCTION__);
|
||||
#endif /* MCE_TRACE */
|
||||
}
|
||||
|
||||
static bool is_cursor_visible(Scene *scene)
|
||||
@@ -3906,8 +4212,11 @@ void view3d_main_area_draw(const bContext *C, ARegion *ar)
|
||||
|
||||
/* draw viewport using opengl */
|
||||
if (v3d->drawtype != OB_RENDER || !view3d_main_area_do_render_draw(scene) || clip_border) {
|
||||
view3d_main_area_draw_objects(C, scene, v3d, ar, &grid_unit);
|
||||
|
||||
if (U.gameflags & USER_VIEWPORT_2)
|
||||
view3d_main_area_draw_viewport_new(C, scene, v3d, ar, &grid_unit);
|
||||
else {
|
||||
view3d_main_area_draw_objects(C, scene, v3d, ar, &grid_unit);
|
||||
}
|
||||
#ifdef DEBUG_DRAW
|
||||
bl_debug_draw();
|
||||
#endif
|
||||
|
@@ -44,6 +44,7 @@
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_camera.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_font.h"
|
||||
@@ -55,7 +56,7 @@
|
||||
#include "BKE_screen.h"
|
||||
#include "BKE_action.h"
|
||||
#include "BKE_depsgraph.h" /* for ED_view3d_camera_lock_sync */
|
||||
|
||||
#include "BKE_workflow_shaders.h"
|
||||
|
||||
#include "BIF_gl.h"
|
||||
#include "BIF_glutil.h"
|
||||
@@ -5124,3 +5125,32 @@ void ED_view3D_lock_clear(View3D *v3d)
|
||||
v3d->ob_centre_cursor = false;
|
||||
v3d->flag2 &= ~V3D_LOCK_CAMERA;
|
||||
}
|
||||
|
||||
|
||||
/**** Workflow Shaders ******************/
|
||||
|
||||
static int view3d_workflow_new_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
View3D *v3d = CTX_wm_view3d(C);
|
||||
GPUWorkflowShader *wfshader = BKE_workflow_shader_add(bmain, "Workflow Shader");
|
||||
if (v3d)
|
||||
v3d->activeworkflow = wfshader;
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
|
||||
void VIEW3D_OT_workflow_new(struct wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "New Workflow Shader";
|
||||
ot->description = "Creates a new workflow shader";
|
||||
ot->idname = "VIEW3D_OT_workflow_new";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = view3d_workflow_new_exec;
|
||||
|
||||
/* flags */
|
||||
ot->flag = 0;
|
||||
}
|
||||
|
||||
|
@@ -330,7 +330,11 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C)
|
||||
}
|
||||
|
||||
/* Draw type */
|
||||
uiItemR(layout, &v3dptr, "viewport_shade", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
|
||||
if (U.gameflags & USER_VIEWPORT_2)
|
||||
/* TODO add something for unlinking */
|
||||
uiTemplateID(layout, C, &v3dptr, "activeworkflow", "VIEW3D_OT_workflow_new", NULL, NULL);
|
||||
else
|
||||
uiItemR(layout, &v3dptr, "viewport_shade", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
|
||||
|
||||
if (obedit == NULL && is_paint) {
|
||||
if (ob->mode & OB_MODE_ALL_PAINT) {
|
||||
|
@@ -51,6 +51,10 @@ struct wmOperatorType;
|
||||
struct wmWindowManager;
|
||||
struct wmKeyConfig;
|
||||
|
||||
/* temporary function call tracing */
|
||||
#define MCE_TRACE false
|
||||
/* TODO: remove --^ */
|
||||
|
||||
/* drawing flags: */
|
||||
enum {
|
||||
DRAW_PICKING = (1 << 0),
|
||||
@@ -103,6 +107,7 @@ void VIEW3D_OT_enable_manipulator(struct wmOperatorType *ot);
|
||||
void VIEW3D_OT_render_border(struct wmOperatorType *ot);
|
||||
void VIEW3D_OT_clear_render_border(struct wmOperatorType *ot);
|
||||
void VIEW3D_OT_zoom_border(struct wmOperatorType *ot);
|
||||
void VIEW3D_OT_workflow_new(struct wmOperatorType *ot);
|
||||
|
||||
void view3d_boxview_copy(ScrArea *sa, ARegion *ar);
|
||||
|
||||
@@ -133,6 +138,7 @@ void draw_motion_paths_cleanup(View3D *v3d);
|
||||
|
||||
/* drawobject.c */
|
||||
void draw_object(Scene *scene, struct ARegion *ar, View3D *v3d, Base *base, const short dflag);
|
||||
void draw_object_new(Scene *scene, struct ARegion *ar, View3D *v3d, Base *base, const short dflag);
|
||||
bool draw_glsl_material(Scene *scene, struct Object *ob, View3D *v3d, const char dt);
|
||||
void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, struct Object *ob, const char dt, int outline);
|
||||
void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, struct Object *ob);
|
||||
|
@@ -161,6 +161,7 @@ void view3d_operatortypes(void)
|
||||
WM_operatortype_append(VIEW3D_OT_view_center_pick);
|
||||
WM_operatortype_append(VIEW3D_OT_view_center_camera);
|
||||
WM_operatortype_append(VIEW3D_OT_view_center_lock);
|
||||
WM_operatortype_append(VIEW3D_OT_workflow_new);
|
||||
WM_operatortype_append(VIEW3D_OT_select);
|
||||
WM_operatortype_append(VIEW3D_OT_select_border);
|
||||
WM_operatortype_append(VIEW3D_OT_clip_border);
|
||||
|
@@ -56,6 +56,10 @@ set(SRC
|
||||
intern/gpu_select.c
|
||||
intern/gpu_compositing.c
|
||||
intern/gpu_debug.c
|
||||
intern/gpux_element.c
|
||||
intern/gpux_draw.c
|
||||
intern/gpux_vbo.c
|
||||
intern/gpux_state.c
|
||||
|
||||
shaders/gpu_program_smoke_frag.glsl
|
||||
shaders/gpu_program_smoke_color_frag.glsl
|
||||
@@ -88,8 +92,13 @@ set(SRC
|
||||
GPU_simple_shader.h
|
||||
GPU_select.h
|
||||
GPU_compositing.h
|
||||
GPUx_vbo.h
|
||||
GPUx_draw.h
|
||||
GPUx_element.h
|
||||
GPUx_state.h
|
||||
intern/gpu_codegen.h
|
||||
intern/gpu_private.h
|
||||
intern/gpux_element_private.h
|
||||
)
|
||||
|
||||
data_to_c_simple(shaders/gpu_program_smoke_frag.glsl SRC)
|
||||
|
@@ -48,6 +48,9 @@ struct GSet;
|
||||
struct GPUVertPointLink;
|
||||
struct PBVH;
|
||||
|
||||
typedef void (*GPUBufferCopyFunc)(DerivedMesh *dm, float *varray, int *index,
|
||||
int *mat_orig_to_new, void *user_data);
|
||||
|
||||
typedef struct GPUBuffer {
|
||||
int size; /* in bytes */
|
||||
void *pointer; /* used with vertex arrays */
|
||||
@@ -115,6 +118,18 @@ typedef struct GPUDrawObject {
|
||||
int totedge;
|
||||
} GPUDrawObject;
|
||||
|
||||
/* currently unused */
|
||||
// #define USE_GPU_POINT_LINK
|
||||
|
||||
typedef struct GPUVertPointLink {
|
||||
#ifdef USE_GPU_POINT_LINK
|
||||
struct GPUVertPointLink *next;
|
||||
#endif
|
||||
/* -1 means uninitialized */
|
||||
int point_index;
|
||||
} GPUVertPointLink;
|
||||
|
||||
|
||||
/* used for GLSL materials */
|
||||
typedef struct GPUAttrib {
|
||||
int index;
|
||||
@@ -128,9 +143,20 @@ void GPU_global_buffer_pool_free_unused(void);
|
||||
GPUBuffer *GPU_buffer_alloc(int size, bool force_vertex_arrays);
|
||||
void GPU_buffer_free(GPUBuffer *buffer);
|
||||
|
||||
GPUDrawObject *GPU_drawobject_new(struct DerivedMesh *dm);
|
||||
void GPU_drawobject_free(struct DerivedMesh *dm);
|
||||
|
||||
/* flag that controls data type to fill buffer with, a modifier will prepare. */
|
||||
typedef enum {
|
||||
GPU_BUFFER_VERTEX = 0,
|
||||
GPU_BUFFER_NORMAL,
|
||||
GPU_BUFFER_COLOR,
|
||||
GPU_BUFFER_UV,
|
||||
GPU_BUFFER_UV_TEXPAINT,
|
||||
GPU_BUFFER_EDGE,
|
||||
GPU_BUFFER_UVEDGE,
|
||||
} GPUBufferType;
|
||||
|
||||
|
||||
/* called before drawing */
|
||||
void GPU_vertex_setup(struct DerivedMesh *dm);
|
||||
void GPU_normal_setup(struct DerivedMesh *dm);
|
||||
|
@@ -62,6 +62,8 @@ void GPU_extensions_disable(void);
|
||||
bool GPU_glsl_support(void);
|
||||
bool GPU_non_power_of_two_support(void);
|
||||
bool GPU_vertex_buffer_support(void);
|
||||
bool GPU_vertex_array_object_support(void);
|
||||
bool GPU_shader4_support(void);
|
||||
bool GPU_display_list_support(void);
|
||||
bool GPU_bicubic_bump_support(void);
|
||||
bool GPU_geometry_shader_support(void);
|
||||
|
@@ -34,4 +34,39 @@
|
||||
|
||||
#include "glew-mx.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
/* Vertex Array Objects are part of OpenGL 3.0, or these extensions:
|
||||
*
|
||||
* GL_APPLE_vertex_array_object
|
||||
* ^-- universally supported on Mac, widely supported on Linux (Mesa)
|
||||
* GL_ARB_vertex_array_object
|
||||
* ^-- widely supported on Windows & vendors' Linux drivers
|
||||
*
|
||||
* The ARB extension differs from the APPLE one in that client
|
||||
* memory cannot be accessed through a non-zero vertex array object. It also
|
||||
* differs in that vertex array objects are explicitly not sharable between
|
||||
* contexts.
|
||||
* (in other words, the ARB version of VAOs *must* use VBOs for vertex data)
|
||||
*
|
||||
* Called and used the exact same way, so alias to unify our VAO code.
|
||||
*
|
||||
* Not needed for GL >= 3.0
|
||||
*/
|
||||
|
||||
# undef glIsVertexArray
|
||||
# define glIsVertexArray glIsVertexArrayAPPLE
|
||||
|
||||
# undef glBindVertexArray
|
||||
# define glBindVertexArray glBindVertexArrayAPPLE
|
||||
|
||||
# undef glGenVertexArrays
|
||||
# define glGenVertexArrays glGenVertexArraysAPPLE
|
||||
|
||||
# undef glDeleteVertexArrays
|
||||
# define glDeleteVertexArrays glDeleteVertexArraysAPPLE
|
||||
|
||||
/* TODO: a better workaround? */
|
||||
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
#endif /* __GPU_GLEW_H__ */
|
||||
|
44
source/blender/gpu/GPUx_draw.h
Normal file
44
source/blender/gpu/GPUx_draw.h
Normal file
@@ -0,0 +1,44 @@
|
||||
#ifndef BLENDER_GL_DRAW_PRIMITIVES
|
||||
#define BLENDER_GL_DRAW_PRIMITIVES
|
||||
|
||||
/* Stateless draw functions for lists of primitives.
|
||||
* Mike Erwin, Dec 2014 */
|
||||
|
||||
#include "GPUx_state.h"
|
||||
#include "GPUx_vbo.h"
|
||||
#include "GPUx_element.h"
|
||||
|
||||
/* pass ElementList = NULL to draw all vertices from VertexBuffer in order
|
||||
* pass NULL to either state arg to use defaults */
|
||||
void GPUx_draw_points(const VertexBuffer*, const ElementList*, const PointDrawState*, const CommonDrawState*);
|
||||
void GPUx_draw_lines(const VertexBuffer*, const ElementList*, const LineDrawState*, const CommonDrawState*);
|
||||
void GPUx_draw_triangles(const VertexBuffer*, const ElementList*, const PolygonDrawState*, const CommonDrawState*);
|
||||
|
||||
/* generic version uses ElementList's primitive type */
|
||||
void GPUx_draw_primitives(const VertexBuffer*, const ElementList*, const void *primitive_state, const CommonDrawState*);
|
||||
|
||||
/* handle normals/shading in various ways */
|
||||
typedef enum {
|
||||
NORMAL_DRAW_NONE, /* draw uniform surface (unlit, uncolored) for depth/picking */
|
||||
NORMAL_DRAW_SMOOTH, /* use vertex normals for smooth appearance */
|
||||
NORMAL_DRAW_FLAT, /* use poly normals for faceted appearance */
|
||||
NORMAL_DRAW_LOOP, /* use loop normals for most faithful rendering */
|
||||
} NormalDrawMode;
|
||||
|
||||
typedef struct GPUxBatch {
|
||||
GLenum prim_type; /* GL_POINTS, GL_LINES, GL_TRIANGLES (must match elem->prim_type) */
|
||||
int draw_type; /* OB_WIRE, OB_SOLID, OB_MATERIAL */
|
||||
NormalDrawMode normal_draw_mode;
|
||||
DrawState state;
|
||||
VertexBuffer *buff; /* TODO: rename "verts" */
|
||||
ElementList *elem;
|
||||
} GPUxBatch;
|
||||
|
||||
GPUxBatch *GPUx_batch_create(void);
|
||||
void GPUx_batch_discard(GPUxBatch*);
|
||||
|
||||
unsigned GPUx_batch_size(const GPUxBatch*); /* total, in bytes */
|
||||
|
||||
void GPUx_draw_batch(const GPUxBatch*);
|
||||
|
||||
#endif /* BLENDER_GL_DRAW_PRIMITIVES */
|
32
source/blender/gpu/GPUx_element.h
Normal file
32
source/blender/gpu/GPUx_element.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef BLENDER_GL_ELEMENT_LIST
|
||||
#define BLENDER_GL_ELEMENT_LIST
|
||||
|
||||
/* Element lists specify which vertices to use when drawing point,
|
||||
* line, or triangle primitives. They don't care how the per-vertex
|
||||
* data (attributes) are laid out, only *which* vertices are used.
|
||||
* Mike Erwin, Dec 2014 */
|
||||
|
||||
#include "GPU_glew.h"
|
||||
/* ^-- for GLenum (and if you're including this file, you're probably calling OpenGL anyway) */
|
||||
|
||||
struct ElementList; /* forward declaration */
|
||||
typedef struct ElementList ElementList;
|
||||
|
||||
ElementList *GPUx_element_list_create(GLenum prim_type, unsigned prim_ct, unsigned max_index);
|
||||
void GPUx_element_list_discard(ElementList*);
|
||||
|
||||
unsigned GPUx_element_list_size(const ElementList*);
|
||||
|
||||
void GPUx_set_point_vertex(ElementList*, unsigned prim_idx, unsigned v1);
|
||||
void GPUx_set_line_vertices(ElementList*, unsigned prim_idx, unsigned v1, unsigned v2);
|
||||
void GPUx_set_triangle_vertices(ElementList*, unsigned prim_idx, unsigned v1, unsigned v2, unsigned v3);
|
||||
|
||||
void GPUx_optimize(ElementList*); /* optionally call this after setting all vertex indices */
|
||||
|
||||
/* prime does all the setup (create VBO, send to GPU, etc.) */
|
||||
void GPUx_element_list_prime(ElementList*);
|
||||
|
||||
void GPUx_element_list_use(const ElementList*);
|
||||
void GPUx_element_list_done_using(const ElementList*);
|
||||
|
||||
#endif /* BLENDER_GL_ELEMENT_LIST */
|
63
source/blender/gpu/GPUx_state.h
Normal file
63
source/blender/gpu/GPUx_state.h
Normal file
@@ -0,0 +1,63 @@
|
||||
#ifndef BLENDER_GL_STATE
|
||||
#define BLENDER_GL_STATE
|
||||
|
||||
/* Two goals:
|
||||
* -- batch draws by state so we don't have to "switch gears" as often
|
||||
* -- track current draw state internally so we don't have to bother the GL as often
|
||||
* Mike Erwin, Dec 2014 */
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct {
|
||||
bool blend; /* plus src & dst of glBlendFunc? */
|
||||
bool depth_test;
|
||||
bool depth_write;
|
||||
bool lighting;
|
||||
bool interpolate; /* affects lines & polygons, not points */
|
||||
/* TODO: interpolation qualifier per attrib (flat/smooth/noperspective) instead of here */
|
||||
/* requires GLSL 1.3 (OpenGL 3.0) or EXT_gpu_shader4 */
|
||||
} CommonDrawState;
|
||||
|
||||
typedef struct {
|
||||
bool smooth; /* implies blend / transparency. Disable depth write! (p179 of AGPUO) */
|
||||
float size;
|
||||
} PointDrawState;
|
||||
|
||||
typedef struct {
|
||||
bool smooth; /* implies blend / transparency. Disable depth write! (p179 of AGPUO) */
|
||||
float width;
|
||||
int stipple; /* = 0 for don't */
|
||||
} LineDrawState;
|
||||
|
||||
typedef struct {
|
||||
bool draw_front;
|
||||
bool draw_back;
|
||||
int material_id;
|
||||
int stipple; /* = 0 for don't */
|
||||
} PolygonDrawState;
|
||||
|
||||
#define MATERIAL_NONE -1
|
||||
|
||||
typedef struct {
|
||||
CommonDrawState common;
|
||||
PointDrawState point;
|
||||
LineDrawState line;
|
||||
PolygonDrawState polygon;
|
||||
} DrawState;
|
||||
|
||||
extern const DrawState default_state;
|
||||
|
||||
|
||||
void GPUx_reset_draw_state(void); /* to defaults */
|
||||
/* ^-- call this before using set_*_state functions below */
|
||||
|
||||
/* incrementally update current GL state */
|
||||
void GPUx_set_common_state(const CommonDrawState*);
|
||||
void GPUx_set_point_state(const PointDrawState*);
|
||||
void GPUx_set_line_state(const LineDrawState*);
|
||||
void GPUx_set_polygon_state(const PolygonDrawState*);
|
||||
|
||||
/* update everything regardless of current GL state */
|
||||
void GPUx_force_state_update(void);
|
||||
|
||||
#endif /* BLENDER_GL_STATE */
|
74
source/blender/gpu/GPUx_vbo.h
Normal file
74
source/blender/gpu/GPUx_vbo.h
Normal file
@@ -0,0 +1,74 @@
|
||||
#ifndef BLENDER_GL_VERTEX_BUFFER
|
||||
#define BLENDER_GL_VERTEX_BUFFER
|
||||
|
||||
/* vertex buffer support
|
||||
* Mike Erwin, Nov 2014 */
|
||||
|
||||
#include "GPU_glew.h"
|
||||
/* ^-- for GLenum (and if you're including this file, you're probably calling OpenGL anyway) */
|
||||
#include <stdbool.h>
|
||||
|
||||
//#define GENERIC_ATTRIB
|
||||
#define TRUST_NO_ONE
|
||||
//#define PRINT
|
||||
|
||||
struct VertexBuffer; /* forward declaration */
|
||||
typedef struct VertexBuffer VertexBuffer;
|
||||
|
||||
typedef enum {
|
||||
KEEP_FLOAT,
|
||||
KEEP_INT, /* requires EXT_gpu_shader4 */
|
||||
NORMALIZE_INT_TO_FLOAT, /* 127 (ubyte) -> 0.5 (and so on for other int types) */
|
||||
CONVERT_INT_TO_FLOAT /* 127 (any int type) -> 127.0 */
|
||||
} VertexFetchMode;
|
||||
|
||||
VertexBuffer* GPUx_vertex_buffer_create(unsigned attrib_ct, unsigned GPUx_vertex_ct);
|
||||
void GPUx_vertex_buffer_discard(VertexBuffer*);
|
||||
|
||||
unsigned GPUx_vertex_ct(const VertexBuffer*);
|
||||
unsigned GPUx_vertex_buffer_size(const VertexBuffer*); /* of all vertex attrib data, in bytes */
|
||||
|
||||
#ifdef PRINT
|
||||
void GPUx_attrib_print(const VertexBuffer*, unsigned attrib_num);
|
||||
#endif /* PRINT */
|
||||
|
||||
void GPUx_specify_attrib(VertexBuffer*, unsigned attrib_num,
|
||||
#ifdef GENERIC_ATTRIB
|
||||
const char *name, /* use any legal GLSL identifier */
|
||||
#else
|
||||
GLenum attrib_array, /* use GL_VERTEX_ARRAY, GL_NORMAL_ARRAY, etc. */
|
||||
#endif
|
||||
GLenum comp_type, unsigned comp_ct, VertexFetchMode);
|
||||
|
||||
#ifdef GENERIC_ATTRIB
|
||||
/* binds all our named attributes to internally-used GL indices
|
||||
* call this before linking the program */
|
||||
void GPUx_bind_attrib_locations(const VertexBuffer*, GLuint program);
|
||||
#endif
|
||||
|
||||
/* set value of single attribute of single vertex
|
||||
* incoming data must be of same type & size for this attribute */
|
||||
void GPUx_set_attrib(VertexBuffer*, unsigned attrib_num, unsigned vertex_num, const void *data);
|
||||
/* convenience functions for specific type and size
|
||||
* can add more like this if it's useful */
|
||||
void GPUx_set_attrib_2f(VertexBuffer*, unsigned attrib_num, unsigned vertex_num, float x, float y);
|
||||
void GPUx_set_attrib_3f(VertexBuffer*, unsigned attrib_num, unsigned vertex_num, float x, float y, float z);
|
||||
|
||||
/* bulk attribute filling routines (all vertices)
|
||||
* incoming data must be of same type & size for this attribute
|
||||
* must be tightly packed in memory, no padding */
|
||||
void GPUx_fill_attrib(VertexBuffer*, unsigned attrib_num, const void *data);
|
||||
/* this version can have padding between attributes */
|
||||
void GPUx_fill_attrib_stride(VertexBuffer*, unsigned attrib_num, const void *data, unsigned stride);
|
||||
|
||||
/* call before drawing to make this vertex buffer part of current OpenGL state */
|
||||
void GPUx_vertex_buffer_use(const VertexBuffer*);
|
||||
/* call after drawing */
|
||||
void GPUx_vertex_buffer_done_using(const VertexBuffer*);
|
||||
|
||||
/* prime does all the setup (create VBOs, send to GPU, etc.)
|
||||
* call sequence: prime, use {draw} done_using, use {draw} done_using ...
|
||||
* TODO: wiki page about this */
|
||||
void GPUx_vertex_buffer_prime(VertexBuffer*);
|
||||
|
||||
#endif /* BLENDER_GL_VERTEX_BUFFER */
|
@@ -69,6 +69,25 @@ typedef enum {
|
||||
GPU_BUFFER_ELEMENT_STATE = (1 << 5),
|
||||
} GPUBufferState;
|
||||
|
||||
typedef struct {
|
||||
GLenum gl_buffer_type;
|
||||
int vector_size;
|
||||
} GPUBufferTypeSettings;
|
||||
|
||||
|
||||
static int gpu_buffer_size_from_type(DerivedMesh *dm, GPUBufferType type);
|
||||
|
||||
const GPUBufferTypeSettings gpu_buffer_type_settings[] = {
|
||||
{GL_ARRAY_BUFFER_ARB, 3}, /* vertex */
|
||||
{GL_ARRAY_BUFFER_ARB, 3}, /* normal */
|
||||
{GL_ARRAY_BUFFER_ARB, 3}, /* mcol */
|
||||
{GL_ARRAY_BUFFER_ARB, 2}, /* uv */
|
||||
{GL_ARRAY_BUFFER_ARB, 4}, /* uv for texpaint */
|
||||
{GL_ELEMENT_ARRAY_BUFFER_ARB, 2}, /* edge */
|
||||
{GL_ELEMENT_ARRAY_BUFFER_ARB, 4}, /* uv edge */
|
||||
};
|
||||
|
||||
|
||||
#define MAX_GPU_ATTRIB_DATA 32
|
||||
|
||||
#define BUFFER_OFFSET(n) ((GLubyte *)NULL + (n))
|
||||
@@ -383,186 +402,6 @@ void GPU_buffer_free(GPUBuffer *buffer)
|
||||
BLI_mutex_unlock(&buffer_mutex);
|
||||
}
|
||||
|
||||
#if 0 /* currently unused */
|
||||
# define USE_GPU_POINT_LINK
|
||||
#endif
|
||||
|
||||
typedef struct GPUVertPointLink {
|
||||
#ifdef USE_GPU_POINT_LINK
|
||||
struct GPUVertPointLink *next;
|
||||
#endif
|
||||
/* -1 means uninitialized */
|
||||
int point_index;
|
||||
} GPUVertPointLink;
|
||||
|
||||
|
||||
/* add a new point to the list of points related to a particular
|
||||
* vertex */
|
||||
#ifdef USE_GPU_POINT_LINK
|
||||
|
||||
static void gpu_drawobject_add_vert_point(GPUDrawObject *gdo, int vert_index, int point_index)
|
||||
{
|
||||
GPUVertPointLink *lnk;
|
||||
|
||||
lnk = &gdo->vert_points[vert_index];
|
||||
|
||||
/* if first link is in use, add a new link at the end */
|
||||
if (lnk->point_index != -1) {
|
||||
/* get last link */
|
||||
for (; lnk->next; lnk = lnk->next) ;
|
||||
|
||||
/* add a new link from the pool */
|
||||
lnk = lnk->next = &gdo->vert_points_mem[gdo->vert_points_usage];
|
||||
gdo->vert_points_usage++;
|
||||
}
|
||||
|
||||
lnk->point_index = point_index;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void gpu_drawobject_add_vert_point(GPUDrawObject *gdo, int vert_index, int point_index)
|
||||
{
|
||||
GPUVertPointLink *lnk;
|
||||
lnk = &gdo->vert_points[vert_index];
|
||||
if (lnk->point_index == -1) {
|
||||
lnk->point_index = point_index;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* USE_GPU_POINT_LINK */
|
||||
|
||||
/* update the vert_points and triangle_to_mface fields with a new
|
||||
* triangle */
|
||||
static void gpu_drawobject_add_triangle(GPUDrawObject *gdo,
|
||||
int base_point_index,
|
||||
int face_index,
|
||||
int v1, int v2, int v3)
|
||||
{
|
||||
int i, v[3] = {v1, v2, v3};
|
||||
for (i = 0; i < 3; i++)
|
||||
gpu_drawobject_add_vert_point(gdo, v[i], base_point_index + i);
|
||||
gdo->triangle_to_mface[base_point_index / 3] = face_index;
|
||||
}
|
||||
|
||||
/* for each vertex, build a list of points related to it; these lists
|
||||
* are stored in an array sized to the number of vertices */
|
||||
static void gpu_drawobject_init_vert_points(GPUDrawObject *gdo, MFace *f, int totface, int totmat)
|
||||
{
|
||||
GPUBufferMaterial *mat;
|
||||
int i, *mat_orig_to_new;
|
||||
|
||||
mat_orig_to_new = MEM_callocN(sizeof(*mat_orig_to_new) * totmat,
|
||||
"GPUDrawObject.mat_orig_to_new");
|
||||
/* allocate the array and space for links */
|
||||
gdo->vert_points = MEM_mallocN(sizeof(GPUVertPointLink) * gdo->totvert,
|
||||
"GPUDrawObject.vert_points");
|
||||
#ifdef USE_GPU_POINT_LINK
|
||||
gdo->vert_points_mem = MEM_callocN(sizeof(GPUVertPointLink) * gdo->tot_triangle_point,
|
||||
"GPUDrawObject.vert_points_mem");
|
||||
gdo->vert_points_usage = 0;
|
||||
#endif
|
||||
|
||||
/* build a map from the original material indices to the new
|
||||
* GPUBufferMaterial indices */
|
||||
for (i = 0; i < gdo->totmaterial; i++)
|
||||
mat_orig_to_new[gdo->materials[i].mat_nr] = i;
|
||||
|
||||
/* -1 indicates the link is not yet used */
|
||||
for (i = 0; i < gdo->totvert; i++) {
|
||||
#ifdef USE_GPU_POINT_LINK
|
||||
gdo->vert_points[i].link = NULL;
|
||||
#endif
|
||||
gdo->vert_points[i].point_index = -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < totface; i++, f++) {
|
||||
mat = &gdo->materials[mat_orig_to_new[f->mat_nr]];
|
||||
|
||||
/* add triangle */
|
||||
gpu_drawobject_add_triangle(gdo, mat->start + mat->totpoint,
|
||||
i, f->v1, f->v2, f->v3);
|
||||
mat->totpoint += 3;
|
||||
|
||||
/* add second triangle for quads */
|
||||
if (f->v4) {
|
||||
gpu_drawobject_add_triangle(gdo, mat->start + mat->totpoint,
|
||||
i, f->v3, f->v4, f->v1);
|
||||
mat->totpoint += 3;
|
||||
}
|
||||
}
|
||||
|
||||
/* map any unused vertices to loose points */
|
||||
for (i = 0; i < gdo->totvert; i++) {
|
||||
if (gdo->vert_points[i].point_index == -1) {
|
||||
gdo->vert_points[i].point_index = gdo->tot_triangle_point + gdo->tot_loose_point;
|
||||
gdo->tot_loose_point++;
|
||||
}
|
||||
}
|
||||
|
||||
MEM_freeN(mat_orig_to_new);
|
||||
}
|
||||
|
||||
/* see GPUDrawObject's structure definition for a description of the
|
||||
* data being initialized here */
|
||||
GPUDrawObject *GPU_drawobject_new(DerivedMesh *dm)
|
||||
{
|
||||
GPUDrawObject *gdo;
|
||||
MFace *mface;
|
||||
int totmat = dm->totmat;
|
||||
int *points_per_mat;
|
||||
int i, curmat, curpoint, totface;
|
||||
|
||||
/* object contains at least one material (default included) so zero means uninitialized dm */
|
||||
BLI_assert(totmat != 0);
|
||||
|
||||
mface = dm->getTessFaceArray(dm);
|
||||
totface = dm->getNumTessFaces(dm);
|
||||
|
||||
/* get the number of points used by each material, treating
|
||||
* each quad as two triangles */
|
||||
points_per_mat = MEM_callocN(sizeof(*points_per_mat) * totmat, "GPU_drawobject_new.mat_orig_to_new");
|
||||
for (i = 0; i < totface; i++)
|
||||
points_per_mat[mface[i].mat_nr] += mface[i].v4 ? 6 : 3;
|
||||
|
||||
/* create the GPUDrawObject */
|
||||
gdo = MEM_callocN(sizeof(GPUDrawObject), "GPUDrawObject");
|
||||
gdo->totvert = dm->getNumVerts(dm);
|
||||
gdo->totedge = dm->getNumEdges(dm);
|
||||
|
||||
/* count the number of materials used by this DerivedMesh */
|
||||
for (i = 0; i < totmat; i++) {
|
||||
if (points_per_mat[i] > 0)
|
||||
gdo->totmaterial++;
|
||||
}
|
||||
|
||||
/* allocate an array of materials used by this DerivedMesh */
|
||||
gdo->materials = MEM_mallocN(sizeof(GPUBufferMaterial) * gdo->totmaterial,
|
||||
"GPUDrawObject.materials");
|
||||
|
||||
/* initialize the materials array */
|
||||
for (i = 0, curmat = 0, curpoint = 0; i < totmat; i++) {
|
||||
if (points_per_mat[i] > 0) {
|
||||
gdo->materials[curmat].start = curpoint;
|
||||
gdo->materials[curmat].totpoint = 0;
|
||||
gdo->materials[curmat].mat_nr = i;
|
||||
|
||||
curpoint += points_per_mat[i];
|
||||
curmat++;
|
||||
}
|
||||
}
|
||||
|
||||
/* store total number of points used for triangles */
|
||||
gdo->tot_triangle_point = curpoint;
|
||||
|
||||
gdo->triangle_to_mface = MEM_mallocN(sizeof(int) * (gdo->tot_triangle_point / 3),
|
||||
"GPUDrawObject.triangle_to_mface");
|
||||
|
||||
gpu_drawobject_init_vert_points(gdo, mface, totface, totmat);
|
||||
MEM_freeN(points_per_mat);
|
||||
|
||||
return gdo;
|
||||
}
|
||||
|
||||
void GPU_drawobject_free(DerivedMesh *dm)
|
||||
{
|
||||
@@ -572,8 +411,10 @@ void GPU_drawobject_free(DerivedMesh *dm)
|
||||
return;
|
||||
|
||||
MEM_freeN(gdo->materials);
|
||||
MEM_freeN(gdo->triangle_to_mface);
|
||||
MEM_freeN(gdo->vert_points);
|
||||
if (gdo->triangle_to_mface)
|
||||
MEM_freeN(gdo->triangle_to_mface);
|
||||
if (gdo->vert_points)
|
||||
MEM_freeN(gdo->vert_points);
|
||||
#ifdef USE_GPU_POINT_LINK
|
||||
MEM_freeN(gdo->vert_points_mem);
|
||||
#endif
|
||||
@@ -605,12 +446,8 @@ static GPUBuffer *gpu_try_realloc(GPUBufferPool *pool, GPUBuffer *buffer, int si
|
||||
return buffer;
|
||||
}
|
||||
|
||||
typedef void (*GPUBufferCopyFunc)(DerivedMesh *dm, float *varray, int *index,
|
||||
int *mat_orig_to_new, void *user_data);
|
||||
|
||||
static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
|
||||
int vector_size, int size, GLenum target,
|
||||
void *user, GPUBufferCopyFunc copy_f)
|
||||
int type, void *user)
|
||||
{
|
||||
GPUBufferPool *pool;
|
||||
GPUBuffer *buffer;
|
||||
@@ -618,6 +455,10 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
|
||||
int *mat_orig_to_new;
|
||||
int *cur_index_per_mat;
|
||||
int i;
|
||||
const GPUBufferTypeSettings *ts = &gpu_buffer_type_settings[type];
|
||||
GLenum target = ts->gl_buffer_type;
|
||||
int vector_size = ts->vector_size;
|
||||
int size = gpu_buffer_size_from_type(dm, type);
|
||||
bool use_VBOs = (GLEW_ARB_vertex_buffer_object) && !(U.gameflags & USER_DISABLE_VBO);
|
||||
GLboolean uploaded;
|
||||
|
||||
@@ -674,7 +515,8 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
|
||||
uploaded = GL_FALSE;
|
||||
/* attempt to upload the data to the VBO */
|
||||
while (uploaded == GL_FALSE) {
|
||||
(*copy_f)(dm, varray, cur_index_per_mat, mat_orig_to_new, user);
|
||||
if (dm->copy_gpu_data)
|
||||
dm->copy_gpu_data(dm, type, varray, cur_index_per_mat, mat_orig_to_new, user);
|
||||
/* glUnmapBuffer returns GL_FALSE if
|
||||
* the data store is corrupted; retry
|
||||
* in that case */
|
||||
@@ -691,7 +533,8 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
|
||||
|
||||
if (buffer) {
|
||||
varray = buffer->pointer;
|
||||
(*copy_f)(dm, varray, cur_index_per_mat, mat_orig_to_new, user);
|
||||
if (dm->copy_gpu_data)
|
||||
dm->copy_gpu_data(dm, type, varray, cur_index_per_mat, mat_orig_to_new, user);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -703,315 +546,7 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static void GPU_buffer_copy_vertex(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *UNUSED(user))
|
||||
{
|
||||
MVert *mvert;
|
||||
MFace *f;
|
||||
int i, j, start, totface;
|
||||
|
||||
mvert = dm->getVertArray(dm);
|
||||
f = dm->getTessFaceArray(dm);
|
||||
|
||||
totface = dm->getNumTessFaces(dm);
|
||||
for (i = 0; i < totface; i++, f++) {
|
||||
start = index[mat_orig_to_new[f->mat_nr]];
|
||||
|
||||
/* v1 v2 v3 */
|
||||
copy_v3_v3(&varray[start], mvert[f->v1].co);
|
||||
copy_v3_v3(&varray[start + 3], mvert[f->v2].co);
|
||||
copy_v3_v3(&varray[start + 6], mvert[f->v3].co);
|
||||
index[mat_orig_to_new[f->mat_nr]] += 9;
|
||||
|
||||
if (f->v4) {
|
||||
/* v3 v4 v1 */
|
||||
copy_v3_v3(&varray[start + 9], mvert[f->v3].co);
|
||||
copy_v3_v3(&varray[start + 12], mvert[f->v4].co);
|
||||
copy_v3_v3(&varray[start + 15], mvert[f->v1].co);
|
||||
index[mat_orig_to_new[f->mat_nr]] += 9;
|
||||
}
|
||||
}
|
||||
|
||||
/* copy loose points */
|
||||
j = dm->drawObject->tot_triangle_point * 3;
|
||||
for (i = 0; i < dm->drawObject->totvert; i++) {
|
||||
if (dm->drawObject->vert_points[i].point_index >= dm->drawObject->tot_triangle_point) {
|
||||
copy_v3_v3(&varray[j], mvert[i].co);
|
||||
j += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void GPU_buffer_copy_normal(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *UNUSED(user))
|
||||
{
|
||||
int i, totface;
|
||||
int start;
|
||||
float f_no[3];
|
||||
|
||||
const float *nors = dm->getTessFaceDataArray(dm, CD_NORMAL);
|
||||
short (*tlnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
|
||||
MVert *mvert = dm->getVertArray(dm);
|
||||
MFace *f = dm->getTessFaceArray(dm);
|
||||
|
||||
totface = dm->getNumTessFaces(dm);
|
||||
for (i = 0; i < totface; i++, f++) {
|
||||
const int smoothnormal = (f->flag & ME_SMOOTH);
|
||||
|
||||
start = index[mat_orig_to_new[f->mat_nr]];
|
||||
index[mat_orig_to_new[f->mat_nr]] += f->v4 ? 18 : 9;
|
||||
|
||||
if (tlnors) {
|
||||
short (*tlnor)[3] = tlnors[i];
|
||||
/* Copy loop normals */
|
||||
normal_short_to_float_v3(&varray[start], tlnor[0]);
|
||||
normal_short_to_float_v3(&varray[start + 3], tlnor[1]);
|
||||
normal_short_to_float_v3(&varray[start + 6], tlnor[2]);
|
||||
|
||||
if (f->v4) {
|
||||
normal_short_to_float_v3(&varray[start + 9], tlnor[2]);
|
||||
normal_short_to_float_v3(&varray[start + 12], tlnor[3]);
|
||||
normal_short_to_float_v3(&varray[start + 15], tlnor[0]);
|
||||
}
|
||||
}
|
||||
else if (smoothnormal) {
|
||||
/* copy vertex normal */
|
||||
normal_short_to_float_v3(&varray[start], mvert[f->v1].no);
|
||||
normal_short_to_float_v3(&varray[start + 3], mvert[f->v2].no);
|
||||
normal_short_to_float_v3(&varray[start + 6], mvert[f->v3].no);
|
||||
|
||||
if (f->v4) {
|
||||
normal_short_to_float_v3(&varray[start + 9], mvert[f->v3].no);
|
||||
normal_short_to_float_v3(&varray[start + 12], mvert[f->v4].no);
|
||||
normal_short_to_float_v3(&varray[start + 15], mvert[f->v1].no);
|
||||
}
|
||||
}
|
||||
else if (nors) {
|
||||
/* copy cached face normal */
|
||||
copy_v3_v3(&varray[start], &nors[i * 3]);
|
||||
copy_v3_v3(&varray[start + 3], &nors[i * 3]);
|
||||
copy_v3_v3(&varray[start + 6], &nors[i * 3]);
|
||||
|
||||
if (f->v4) {
|
||||
copy_v3_v3(&varray[start + 9], &nors[i * 3]);
|
||||
copy_v3_v3(&varray[start + 12], &nors[i * 3]);
|
||||
copy_v3_v3(&varray[start + 15], &nors[i * 3]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* calculate face normal */
|
||||
if (f->v4)
|
||||
normal_quad_v3(f_no, mvert[f->v1].co, mvert[f->v2].co, mvert[f->v3].co, mvert[f->v4].co);
|
||||
else
|
||||
normal_tri_v3(f_no, mvert[f->v1].co, mvert[f->v2].co, mvert[f->v3].co);
|
||||
|
||||
copy_v3_v3(&varray[start], f_no);
|
||||
copy_v3_v3(&varray[start + 3], f_no);
|
||||
copy_v3_v3(&varray[start + 6], f_no);
|
||||
|
||||
if (f->v4) {
|
||||
copy_v3_v3(&varray[start + 9], f_no);
|
||||
copy_v3_v3(&varray[start + 12], f_no);
|
||||
copy_v3_v3(&varray[start + 15], f_no);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void GPU_buffer_copy_uv(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *UNUSED(user))
|
||||
{
|
||||
int start;
|
||||
int i, totface;
|
||||
|
||||
MTFace *mtface;
|
||||
MFace *f;
|
||||
|
||||
if (!(mtface = DM_get_tessface_data_layer(dm, CD_MTFACE)))
|
||||
return;
|
||||
f = dm->getTessFaceArray(dm);
|
||||
|
||||
totface = dm->getNumTessFaces(dm);
|
||||
for (i = 0; i < totface; i++, f++) {
|
||||
start = index[mat_orig_to_new[f->mat_nr]];
|
||||
|
||||
/* v1 v2 v3 */
|
||||
copy_v2_v2(&varray[start], mtface[i].uv[0]);
|
||||
copy_v2_v2(&varray[start + 2], mtface[i].uv[1]);
|
||||
copy_v2_v2(&varray[start + 4], mtface[i].uv[2]);
|
||||
index[mat_orig_to_new[f->mat_nr]] += 6;
|
||||
|
||||
if (f->v4) {
|
||||
/* v3 v4 v1 */
|
||||
copy_v2_v2(&varray[start + 6], mtface[i].uv[2]);
|
||||
copy_v2_v2(&varray[start + 8], mtface[i].uv[3]);
|
||||
copy_v2_v2(&varray[start + 10], mtface[i].uv[0]);
|
||||
index[mat_orig_to_new[f->mat_nr]] += 6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void GPU_buffer_copy_uv_texpaint(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *UNUSED(user))
|
||||
{
|
||||
int start;
|
||||
int i, totface;
|
||||
|
||||
int totmaterial = dm->totmat;
|
||||
MTFace **mtface_base;
|
||||
MTFace *stencil_base;
|
||||
int stencil;
|
||||
MFace *mf;
|
||||
|
||||
/* should have been checked for before, reassert */
|
||||
BLI_assert(DM_get_tessface_data_layer(dm, CD_MTFACE));
|
||||
mf = dm->getTessFaceArray(dm);
|
||||
mtface_base = MEM_mallocN(totmaterial * sizeof(*mtface_base), "texslots");
|
||||
|
||||
for (i = 0; i < totmaterial; i++) {
|
||||
mtface_base[i] = DM_paint_uvlayer_active_get(dm, i);
|
||||
}
|
||||
|
||||
stencil = CustomData_get_stencil_layer(&dm->faceData, CD_MTFACE);
|
||||
stencil_base = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, stencil);
|
||||
|
||||
totface = dm->getNumTessFaces(dm);
|
||||
|
||||
for (i = 0; i < totface; i++, mf++) {
|
||||
int mat_i = mf->mat_nr;
|
||||
start = index[mat_orig_to_new[mat_i]];
|
||||
|
||||
/* v1 v2 v3 */
|
||||
copy_v2_v2(&varray[start], mtface_base[mat_i][i].uv[0]);
|
||||
copy_v2_v2(&varray[start + 2], stencil_base[i].uv[0]);
|
||||
copy_v2_v2(&varray[start + 4], mtface_base[mat_i][i].uv[1]);
|
||||
copy_v2_v2(&varray[start + 6], stencil_base[i].uv[1]);
|
||||
copy_v2_v2(&varray[start + 8], mtface_base[mat_i][i].uv[2]);
|
||||
copy_v2_v2(&varray[start + 10], stencil_base[i].uv[2]);
|
||||
index[mat_orig_to_new[mat_i]] += 12;
|
||||
|
||||
if (mf->v4) {
|
||||
/* v3 v4 v1 */
|
||||
copy_v2_v2(&varray[start + 12], mtface_base[mat_i][i].uv[2]);
|
||||
copy_v2_v2(&varray[start + 14], stencil_base[i].uv[2]);
|
||||
copy_v2_v2(&varray[start + 16], mtface_base[mat_i][i].uv[3]);
|
||||
copy_v2_v2(&varray[start + 18], stencil_base[i].uv[3]);
|
||||
copy_v2_v2(&varray[start + 20], mtface_base[mat_i][i].uv[0]);
|
||||
copy_v2_v2(&varray[start + 22], stencil_base[i].uv[0]);
|
||||
index[mat_orig_to_new[mat_i]] += 12;
|
||||
}
|
||||
}
|
||||
|
||||
MEM_freeN(mtface_base);
|
||||
}
|
||||
|
||||
|
||||
static void copy_mcol_uc3(unsigned char *v, unsigned char *col)
|
||||
{
|
||||
v[0] = col[3];
|
||||
v[1] = col[2];
|
||||
v[2] = col[1];
|
||||
}
|
||||
|
||||
/* treat varray_ as an array of MCol, four MCol's per face */
|
||||
static void GPU_buffer_copy_mcol(DerivedMesh *dm, float *varray_, int *index, int *mat_orig_to_new, void *user)
|
||||
{
|
||||
int i, totface;
|
||||
unsigned char *varray = (unsigned char *)varray_;
|
||||
unsigned char *mcol = (unsigned char *)user;
|
||||
MFace *f = dm->getTessFaceArray(dm);
|
||||
|
||||
totface = dm->getNumTessFaces(dm);
|
||||
for (i = 0; i < totface; i++, f++) {
|
||||
int start = index[mat_orig_to_new[f->mat_nr]];
|
||||
|
||||
/* v1 v2 v3 */
|
||||
copy_mcol_uc3(&varray[start], &mcol[i * 16]);
|
||||
copy_mcol_uc3(&varray[start + 3], &mcol[i * 16 + 4]);
|
||||
copy_mcol_uc3(&varray[start + 6], &mcol[i * 16 + 8]);
|
||||
index[mat_orig_to_new[f->mat_nr]] += 9;
|
||||
|
||||
if (f->v4) {
|
||||
/* v3 v4 v1 */
|
||||
copy_mcol_uc3(&varray[start + 9], &mcol[i * 16 + 8]);
|
||||
copy_mcol_uc3(&varray[start + 12], &mcol[i * 16 + 12]);
|
||||
copy_mcol_uc3(&varray[start + 15], &mcol[i * 16]);
|
||||
index[mat_orig_to_new[f->mat_nr]] += 9;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void GPU_buffer_copy_edge(DerivedMesh *dm, float *varray_, int *UNUSED(index), int *UNUSED(mat_orig_to_new), void *UNUSED(user))
|
||||
{
|
||||
MEdge *medge;
|
||||
unsigned int *varray = (unsigned int *)varray_;
|
||||
int i, totedge;
|
||||
|
||||
medge = dm->getEdgeArray(dm);
|
||||
totedge = dm->getNumEdges(dm);
|
||||
|
||||
for (i = 0; i < totedge; i++, medge++) {
|
||||
varray[i * 2] = dm->drawObject->vert_points[medge->v1].point_index;
|
||||
varray[i * 2 + 1] = dm->drawObject->vert_points[medge->v2].point_index;
|
||||
}
|
||||
}
|
||||
|
||||
static void GPU_buffer_copy_uvedge(DerivedMesh *dm, float *varray, int *UNUSED(index), int *UNUSED(mat_orig_to_new), void *UNUSED(user))
|
||||
{
|
||||
MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
|
||||
int i, j = 0;
|
||||
|
||||
if (!tf)
|
||||
return;
|
||||
|
||||
for (i = 0; i < dm->numTessFaceData; i++, tf++) {
|
||||
MFace mf;
|
||||
dm->getTessFace(dm, i, &mf);
|
||||
|
||||
copy_v2_v2(&varray[j], tf->uv[0]);
|
||||
copy_v2_v2(&varray[j + 2], tf->uv[1]);
|
||||
|
||||
copy_v2_v2(&varray[j + 4], tf->uv[1]);
|
||||
copy_v2_v2(&varray[j + 6], tf->uv[2]);
|
||||
|
||||
if (!mf.v4) {
|
||||
copy_v2_v2(&varray[j + 8], tf->uv[2]);
|
||||
copy_v2_v2(&varray[j + 10], tf->uv[0]);
|
||||
j += 12;
|
||||
}
|
||||
else {
|
||||
copy_v2_v2(&varray[j + 8], tf->uv[2]);
|
||||
copy_v2_v2(&varray[j + 10], tf->uv[3]);
|
||||
|
||||
copy_v2_v2(&varray[j + 12], tf->uv[3]);
|
||||
copy_v2_v2(&varray[j + 14], tf->uv[0]);
|
||||
j += 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
GPU_BUFFER_VERTEX = 0,
|
||||
GPU_BUFFER_NORMAL,
|
||||
GPU_BUFFER_COLOR,
|
||||
GPU_BUFFER_UV,
|
||||
GPU_BUFFER_UV_TEXPAINT,
|
||||
GPU_BUFFER_EDGE,
|
||||
GPU_BUFFER_UVEDGE,
|
||||
} GPUBufferType;
|
||||
|
||||
typedef struct {
|
||||
GPUBufferCopyFunc copy;
|
||||
GLenum gl_buffer_type;
|
||||
int vector_size;
|
||||
} GPUBufferTypeSettings;
|
||||
|
||||
const GPUBufferTypeSettings gpu_buffer_type_settings[] = {
|
||||
{GPU_buffer_copy_vertex, GL_ARRAY_BUFFER_ARB, 3},
|
||||
{GPU_buffer_copy_normal, GL_ARRAY_BUFFER_ARB, 3},
|
||||
{GPU_buffer_copy_mcol, GL_ARRAY_BUFFER_ARB, 3},
|
||||
{GPU_buffer_copy_uv, GL_ARRAY_BUFFER_ARB, 2},
|
||||
{GPU_buffer_copy_uv_texpaint, GL_ARRAY_BUFFER_ARB, 4},
|
||||
{GPU_buffer_copy_edge, GL_ELEMENT_ARRAY_BUFFER_ARB, 2},
|
||||
{GPU_buffer_copy_uvedge, GL_ELEMENT_ARRAY_BUFFER_ARB, 4}
|
||||
};
|
||||
|
||||
/* get the GPUDrawObject buffer associated with a type */
|
||||
static GPUBuffer **gpu_drawobject_buffer_from_type(GPUDrawObject *gdo, GPUBufferType type)
|
||||
@@ -1067,12 +602,9 @@ static int gpu_buffer_size_from_type(DerivedMesh *dm, GPUBufferType type)
|
||||
/* call gpu_buffer_setup with settings for a particular type of buffer */
|
||||
static GPUBuffer *gpu_buffer_setup_type(DerivedMesh *dm, GPUBufferType type)
|
||||
{
|
||||
const GPUBufferTypeSettings *ts;
|
||||
void *user_data = NULL;
|
||||
GPUBuffer *buf;
|
||||
|
||||
ts = &gpu_buffer_type_settings[type];
|
||||
|
||||
/* special handling for MCol and UV buffers */
|
||||
if (type == GPU_BUFFER_COLOR) {
|
||||
if (!(user_data = DM_get_tessface_data_layer(dm, dm->drawObject->colType)))
|
||||
@@ -1083,9 +615,7 @@ static GPUBuffer *gpu_buffer_setup_type(DerivedMesh *dm, GPUBufferType type)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buf = gpu_buffer_setup(dm, dm->drawObject, ts->vector_size,
|
||||
gpu_buffer_size_from_type(dm, type),
|
||||
ts->gl_buffer_type, user_data, ts->copy);
|
||||
buf = gpu_buffer_setup(dm, dm->drawObject, type, user_data);
|
||||
|
||||
return buf;
|
||||
}
|
||||
@@ -1096,9 +626,13 @@ static GPUBuffer *gpu_buffer_setup_common(DerivedMesh *dm, GPUBufferType type)
|
||||
{
|
||||
GPUBuffer **buf;
|
||||
|
||||
if (!dm->drawObject)
|
||||
dm->drawObject = GPU_drawobject_new(dm);
|
||||
|
||||
if (!dm->drawObject) {
|
||||
if (dm->gpuObjectNew)
|
||||
dm->drawObject = dm->gpuObjectNew(dm);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buf = gpu_drawobject_buffer_from_type(dm->drawObject, type);
|
||||
if (!(*buf))
|
||||
*buf = gpu_buffer_setup_type(dm, type);
|
||||
@@ -1188,7 +722,7 @@ void GPU_color_setup(DerivedMesh *dm, int colType)
|
||||
if (!dm->drawObject) {
|
||||
/* XXX Not really nice, but we need a valid gpu draw object to set the colType...
|
||||
* Else we would have to add a new param to gpu_buffer_setup_common. */
|
||||
dm->drawObject = GPU_drawobject_new(dm);
|
||||
dm->drawObject = dm->gpuObjectNew(dm);
|
||||
dm->dirty &= ~DM_DIRTY_MCOL_UPDATE_DRAW;
|
||||
dm->drawObject->colType = colType;
|
||||
}
|
||||
|
@@ -303,6 +303,22 @@ bool GPU_vertex_buffer_support(void)
|
||||
return GLEW_ARB_vertex_buffer_object || GLEW_VERSION_1_5;
|
||||
}
|
||||
|
||||
bool GPU_vertex_array_object_support(void)
|
||||
{
|
||||
return GLEW_VERSION_3_0 || GLEW_ARB_vertex_array_object || GLEW_APPLE_vertex_array_object;
|
||||
}
|
||||
|
||||
bool GPU_shader4_support(void)
|
||||
{
|
||||
/* includes a number of GLSL enhancements:
|
||||
* - full integer support
|
||||
* - interpolation qualifiers (flat, smooth, noperspective)
|
||||
* - gl_VertexID, gl_PrimitiveID
|
||||
* - custom fragment shader outputs, for MRT
|
||||
*/
|
||||
return GLEW_VERSION_3_0 || GLEW_EXT_gpu_shader4;
|
||||
}
|
||||
|
||||
bool GPU_display_list_support(void)
|
||||
{
|
||||
return !GG.dlistsdisabled;
|
||||
|
95
source/blender/gpu/intern/gpux_buffer_id.c
Normal file
95
source/blender/gpu/intern/gpux_buffer_id.c
Normal file
@@ -0,0 +1,95 @@
|
||||
#include "gpux_buffer_id.h"
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_threads.h"
|
||||
|
||||
//#define ORPHAN_DEBUG
|
||||
|
||||
#ifdef ORPHAN_DEBUG
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#define ORPHANED_BUFFER_MAX 48
|
||||
static GLuint orphaned_buffer_ids[ORPHANED_BUFFER_MAX];
|
||||
static unsigned orphaned_buffer_ct = 0;
|
||||
|
||||
#define ORPHANED_VAO_MAX 16
|
||||
static GLuint orphaned_vao_ids[ORPHANED_VAO_MAX];
|
||||
static unsigned orphaned_vao_ct = 0;
|
||||
|
||||
static ThreadMutex orphan_mutex = BLI_MUTEX_INITIALIZER;
|
||||
|
||||
GLuint buffer_id_alloc()
|
||||
{
|
||||
GLuint new_buffer_id;
|
||||
|
||||
BLI_assert(BLI_thread_is_main());
|
||||
|
||||
/* delete orphaned IDs */
|
||||
BLI_mutex_lock(&orphan_mutex);
|
||||
if (orphaned_buffer_ct) {
|
||||
#ifdef ORPHAN_DEBUG
|
||||
printf("deleting %d orphaned VBO%s\n", orphaned_buffer_ct, orphaned_buffer_ct == 1 ? "" : "s");
|
||||
#endif
|
||||
glDeleteBuffers(orphaned_buffer_ct, orphaned_buffer_ids);
|
||||
orphaned_buffer_ct = 0;
|
||||
}
|
||||
BLI_mutex_unlock(&orphan_mutex);
|
||||
|
||||
glGenBuffers(1, &new_buffer_id);
|
||||
return new_buffer_id;
|
||||
}
|
||||
|
||||
void buffer_id_free(GLuint buffer_id)
|
||||
{
|
||||
if (BLI_thread_is_main()) {
|
||||
glDeleteBuffers(1, &buffer_id);
|
||||
}
|
||||
else {
|
||||
/* add this ID to the orphaned list */
|
||||
BLI_mutex_lock(&orphan_mutex);
|
||||
BLI_assert(orphaned_buffer_ct < ORPHANED_BUFFER_MAX); /* increase MAX if needed */
|
||||
#ifdef ORPHAN_DEBUG
|
||||
printf("orphaning VBO %d\n", buffer_id);
|
||||
#endif
|
||||
orphaned_buffer_ids[orphaned_buffer_ct++] = buffer_id;
|
||||
BLI_mutex_unlock(&orphan_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
GLuint vao_id_alloc()
|
||||
{
|
||||
GLuint new_vao_id;
|
||||
|
||||
BLI_assert(BLI_thread_is_main());
|
||||
|
||||
/* delete orphaned IDs */
|
||||
BLI_mutex_lock(&orphan_mutex);
|
||||
if (orphaned_vao_ct) {
|
||||
#ifdef ORPHAN_DEBUG
|
||||
printf("deleting %d orphaned VAO%s\n", orphaned_vao_ct, orphaned_vao_ct == 1 ? "" : "s");
|
||||
#endif
|
||||
glDeleteVertexArrays(orphaned_vao_ct, orphaned_vao_ids);
|
||||
orphaned_vao_ct = 0;
|
||||
}
|
||||
BLI_mutex_unlock(&orphan_mutex);
|
||||
|
||||
glGenVertexArrays(1, &new_vao_id);
|
||||
return new_vao_id;
|
||||
}
|
||||
|
||||
void vao_id_free(GLuint vao_id)
|
||||
{
|
||||
if (BLI_thread_is_main()) {
|
||||
glDeleteVertexArrays(1, &vao_id);
|
||||
}
|
||||
else {
|
||||
/* add this ID to the orphaned list */
|
||||
BLI_mutex_lock(&orphan_mutex);
|
||||
BLI_assert(orphaned_vao_ct < ORPHANED_VAO_MAX); /* increase MAX if needed */
|
||||
#ifdef ORPHAN_DEBUG
|
||||
printf("orphaning VAO %d\n", vao_id);
|
||||
#endif
|
||||
orphaned_vao_ids[orphaned_vao_ct++] = vao_id;
|
||||
BLI_mutex_unlock(&orphan_mutex);
|
||||
}
|
||||
}
|
19
source/blender/gpu/intern/gpux_buffer_id.h
Normal file
19
source/blender/gpu/intern/gpux_buffer_id.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef BLENDER_GL_BUFFER_ID
|
||||
#define BLENDER_GL_BUFFER_ID
|
||||
|
||||
/* Manage GL buffer IDs in a thread-safe way
|
||||
* Use these instead of glGenBuffers & its friends
|
||||
* - alloc must be called from main thread
|
||||
* - free can be called from any thread
|
||||
* private for now since GPUx uses this internally
|
||||
* Mike Erwin, April 2015 */
|
||||
|
||||
#include "GPU_glew.h"
|
||||
|
||||
GLuint buffer_id_alloc(void);
|
||||
void buffer_id_free(GLuint buffer_id);
|
||||
|
||||
GLuint vao_id_alloc(void);
|
||||
void vao_id_free(GLuint vao_id);
|
||||
|
||||
#endif /* BLENDER_GL_BUFFER_ID */
|
213
source/blender/gpu/intern/gpux_draw.c
Normal file
213
source/blender/gpu/intern/gpux_draw.c
Normal file
@@ -0,0 +1,213 @@
|
||||
|
||||
#include "GPUx_draw.h"
|
||||
#include "gpux_element_private.h"
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#ifdef TRUST_NO_ONE
|
||||
#include "BLI_utildefines.h"
|
||||
#endif /* TRUST_NO_ONE */
|
||||
|
||||
#define REALLY_DRAW
|
||||
|
||||
/* generally useful utility function */
|
||||
static unsigned chop_to_multiple(unsigned x, unsigned m)
|
||||
{
|
||||
return x - x % m;
|
||||
}
|
||||
|
||||
void GPUx_draw_points(const VertexBuffer *vbo, const ElementList *el, const PointDrawState *point_state, const CommonDrawState *common_state)
|
||||
{
|
||||
GPUx_set_common_state(common_state);
|
||||
GPUx_set_point_state(point_state);
|
||||
|
||||
#ifdef TRUST_NO_ONE
|
||||
if (el) {
|
||||
BLI_assert(el->prim_type == GL_POINTS);
|
||||
BLI_assert(max_index(el) < GPUx_vertex_ct(vbo));
|
||||
}
|
||||
#endif /* TRUST_NO_ONE */
|
||||
|
||||
#ifdef REALLY_DRAW
|
||||
GPUx_vertex_buffer_use(vbo);
|
||||
|
||||
if (el) {
|
||||
GPUx_element_list_use(el);
|
||||
glDrawRangeElements(GL_POINTS, min_index(el), max_index(el), el->prim_ct, el->index_type, index_ptr(el));
|
||||
GPUx_element_list_done_using(el);
|
||||
}
|
||||
else
|
||||
glDrawArrays(GL_POINTS, 0, GPUx_vertex_ct(vbo));
|
||||
|
||||
GPUx_vertex_buffer_done_using(vbo);
|
||||
#endif /* REALLY_DRAW */
|
||||
}
|
||||
|
||||
void GPUx_draw_lines(const VertexBuffer *vbo, const ElementList *el, const LineDrawState *line_state, const CommonDrawState *common_state)
|
||||
{
|
||||
GPUx_set_common_state(common_state);
|
||||
GPUx_set_line_state(line_state);
|
||||
|
||||
#ifdef TRUST_NO_ONE
|
||||
if (el) {
|
||||
BLI_assert(el->prim_type == GL_LINES);
|
||||
BLI_assert(max_index(el) < GPUx_vertex_ct(vbo));
|
||||
}
|
||||
#endif /* TRUST_NO_ONE */
|
||||
|
||||
#ifdef REALLY_DRAW
|
||||
GPUx_vertex_buffer_use(vbo);
|
||||
|
||||
if (el) {
|
||||
GPUx_element_list_use(el);
|
||||
glDrawRangeElements(GL_LINES, min_index(el), max_index(el), el->prim_ct * 2, el->index_type, index_ptr(el));
|
||||
GPUx_element_list_done_using(el);
|
||||
}
|
||||
else
|
||||
glDrawArrays(GL_LINES, 0, chop_to_multiple(GPUx_vertex_ct(vbo), 2));
|
||||
|
||||
GPUx_vertex_buffer_done_using(vbo);
|
||||
#endif /* REALLY_DRAW */
|
||||
}
|
||||
|
||||
void GPUx_draw_triangles(const VertexBuffer *vbo, const ElementList *el, const PolygonDrawState *polygon_state, const CommonDrawState *common_state)
|
||||
{
|
||||
GPUx_set_common_state(common_state);
|
||||
GPUx_set_polygon_state(polygon_state);
|
||||
|
||||
#ifdef TRUST_NO_ONE
|
||||
if (el) {
|
||||
BLI_assert(el->prim_type == GL_TRIANGLES);
|
||||
BLI_assert(max_index(el) < GPUx_vertex_ct(vbo));
|
||||
}
|
||||
#endif /* TRUST_NO_ONE */
|
||||
|
||||
#ifdef REALLY_DRAW
|
||||
GPUx_vertex_buffer_use(vbo);
|
||||
|
||||
if (el) {
|
||||
GPUx_element_list_use(el);
|
||||
glDrawRangeElements(GL_TRIANGLES, min_index(el), max_index(el), el->prim_ct * 3, el->index_type, index_ptr(el));
|
||||
GPUx_element_list_done_using(el);
|
||||
}
|
||||
else
|
||||
glDrawArrays(GL_TRIANGLES, 0, chop_to_multiple(GPUx_vertex_ct(vbo), 3));
|
||||
|
||||
GPUx_vertex_buffer_done_using(vbo);
|
||||
#endif /* REALLY_DRAW */
|
||||
}
|
||||
|
||||
void GPUx_draw_primitives(const VertexBuffer *vbo, const ElementList *el, const void *primitive_state, const CommonDrawState *common_state)
|
||||
{
|
||||
int vert_per_prim = 0;
|
||||
|
||||
#ifdef TRUST_NO_ONE
|
||||
BLI_assert(max_index(el) < GPUx_vertex_ct(vbo));
|
||||
#endif /* TRUST_NO_ONE */
|
||||
|
||||
switch (el->prim_type) {
|
||||
case GL_POINTS:
|
||||
GPUx_set_point_state((const PointDrawState*)primitive_state);
|
||||
vert_per_prim = 1;
|
||||
break;
|
||||
case GL_LINES:
|
||||
GPUx_set_line_state((const LineDrawState*)primitive_state);
|
||||
vert_per_prim = 2;
|
||||
break;
|
||||
case GL_TRIANGLES:
|
||||
GPUx_set_polygon_state((const PolygonDrawState*)primitive_state);
|
||||
vert_per_prim = 3;
|
||||
break;
|
||||
default:
|
||||
#ifdef TRUST_NO_ONE
|
||||
BLI_assert(false);
|
||||
#else
|
||||
return;
|
||||
#endif /* TRUST_NO_ONE */
|
||||
}
|
||||
|
||||
GPUx_set_common_state(common_state);
|
||||
|
||||
#ifdef REALLY_DRAW
|
||||
GPUx_vertex_buffer_use(vbo);
|
||||
GPUx_element_list_use(el);
|
||||
|
||||
glDrawRangeElements(el->prim_type, min_index(el), max_index(el), el->prim_ct * vert_per_prim, el->index_type, index_ptr(el));
|
||||
|
||||
GPUx_element_list_done_using(el);
|
||||
GPUx_vertex_buffer_done_using(vbo);
|
||||
#endif /* REALLY_DRAW */
|
||||
}
|
||||
|
||||
GPUxBatch *GPUx_batch_create()
|
||||
{
|
||||
GPUxBatch *batch = MEM_callocN(sizeof(GPUxBatch), "GPUxBatch");
|
||||
batch->prim_type = GL_NONE;
|
||||
batch->state = default_state;
|
||||
return batch;
|
||||
}
|
||||
|
||||
void GPUx_batch_discard(GPUxBatch *batch)
|
||||
{
|
||||
GPUx_vertex_buffer_discard(batch->buff);
|
||||
if (batch->elem)
|
||||
GPUx_element_list_discard(batch->elem);
|
||||
MEM_freeN(batch);
|
||||
}
|
||||
|
||||
unsigned GPUx_batch_size(const GPUxBatch *batch)
|
||||
{
|
||||
unsigned sz = GPUx_vertex_buffer_size(batch->buff);
|
||||
if (batch->elem)
|
||||
sz += GPUx_element_list_size(batch->elem);
|
||||
return sz;
|
||||
}
|
||||
|
||||
void GPUx_draw_batch(const GPUxBatch *batch)
|
||||
{
|
||||
int vert_per_prim = 0;
|
||||
|
||||
#ifdef TRUST_NO_ONE
|
||||
if (batch->elem) {
|
||||
BLI_assert(batch->elem->prim_type == batch->prim_type);
|
||||
BLI_assert(max_index(batch->elem) < GPUx_vertex_ct(batch->buff));
|
||||
}
|
||||
#endif /* TRUST_NO_ONE */
|
||||
|
||||
switch (batch->prim_type) {
|
||||
case GL_POINTS:
|
||||
GPUx_set_point_state(&batch->state.point);
|
||||
vert_per_prim = 1;
|
||||
break;
|
||||
case GL_LINES:
|
||||
GPUx_set_line_state(&batch->state.line);
|
||||
vert_per_prim = 2;
|
||||
break;
|
||||
case GL_TRIANGLES:
|
||||
GPUx_set_polygon_state(&batch->state.polygon);
|
||||
vert_per_prim = 3;
|
||||
break;
|
||||
default:
|
||||
#ifdef TRUST_NO_ONE
|
||||
BLI_assert(false);
|
||||
#else
|
||||
return;
|
||||
#endif /* TRUST_NO_ONE */
|
||||
}
|
||||
|
||||
GPUx_set_common_state(&batch->state.common);
|
||||
|
||||
#ifdef REALLY_DRAW
|
||||
GPUx_vertex_buffer_use(batch->buff);
|
||||
|
||||
if (batch->elem) {
|
||||
GPUx_element_list_use(batch->elem);
|
||||
glDrawRangeElements(batch->prim_type, min_index(batch->elem), max_index(batch->elem),
|
||||
batch->elem->prim_ct * vert_per_prim, batch->elem->index_type, index_ptr(batch->elem));
|
||||
GPUx_element_list_done_using(batch->elem);
|
||||
}
|
||||
else
|
||||
glDrawArrays(batch->prim_type, 0, chop_to_multiple(GPUx_vertex_ct(batch->buff), vert_per_prim));
|
||||
|
||||
GPUx_vertex_buffer_done_using(batch->buff);
|
||||
#endif /* REALLY_DRAW */
|
||||
}
|
290
source/blender/gpu/intern/gpux_element.c
Normal file
290
source/blender/gpu/intern/gpux_element.c
Normal file
@@ -0,0 +1,290 @@
|
||||
|
||||
#include "gpux_element_private.h"
|
||||
#include "gpux_buffer_id.h"
|
||||
#include "BLI_utildefines.h"
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#ifdef USE_ELEM_VBO
|
||||
/* keep index data in main mem or VRAM (not both) */
|
||||
#define KEEP_SINGLE_COPY
|
||||
#endif
|
||||
|
||||
/* private functions */
|
||||
|
||||
#ifdef TRACK_INDEX_RANGE
|
||||
static void track_index_range(ElementList *el, unsigned v)
|
||||
{
|
||||
if (v < el->min_observed_index)
|
||||
el->min_observed_index = v;
|
||||
if (v > el->max_observed_index) /* would say "else if" but the first time... */
|
||||
el->max_observed_index = v;
|
||||
}
|
||||
#endif /* TRACK_INDEX_RANGE */
|
||||
|
||||
unsigned min_index(const ElementList *el)
|
||||
{
|
||||
#ifdef TRACK_INDEX_RANGE
|
||||
return el->min_observed_index;
|
||||
#else
|
||||
return 0;
|
||||
#endif /* TRACK_INDEX_RANGE */
|
||||
}
|
||||
|
||||
unsigned max_index(const ElementList *el)
|
||||
{
|
||||
#ifdef TRACK_INDEX_RANGE
|
||||
return el->max_observed_index;
|
||||
#else
|
||||
return el->max_allowed_index;
|
||||
#endif /* TRACK_INDEX_RANGE */
|
||||
}
|
||||
|
||||
const void *index_ptr(const ElementList *el)
|
||||
{
|
||||
#ifdef USE_ELEM_VBO
|
||||
if (el->vbo_id) /* primed, data lives in buffer object */
|
||||
return (const void*)0;
|
||||
else /* data lives in client memory */
|
||||
return el->indices;
|
||||
#else
|
||||
return el->indices;
|
||||
#endif /* USE_ELEM_VBO */
|
||||
}
|
||||
|
||||
/* public functions */
|
||||
|
||||
ElementList *GPUx_element_list_create(GLenum prim_type, unsigned prim_ct, unsigned max_index)
|
||||
{
|
||||
ElementList *el;
|
||||
|
||||
#ifdef TRUST_NO_ONE
|
||||
BLI_assert(prim_type == GL_POINTS || prim_type == GL_LINES || prim_type == GL_TRIANGLES);
|
||||
#endif /* TRUST_NO_ONE */
|
||||
|
||||
el = MEM_callocN(sizeof(ElementList), "ElementList");
|
||||
|
||||
el->prim_type = prim_type;
|
||||
el->prim_ct = prim_ct;
|
||||
el->max_allowed_index = max_index;
|
||||
|
||||
if (max_index <= 255)
|
||||
el->index_type = GL_UNSIGNED_BYTE;
|
||||
else if (max_index <= 65535)
|
||||
el->index_type = GL_UNSIGNED_SHORT;
|
||||
else
|
||||
el->index_type = GL_UNSIGNED_INT;
|
||||
|
||||
#ifdef TRACK_INDEX_RANGE
|
||||
el->min_observed_index = max_index + 1; /* any valid index will be < this */
|
||||
el->max_observed_index = 0;
|
||||
#endif /* TRACK_INDEX_RANGE */
|
||||
|
||||
el->indices = MEM_callocN(GPUx_element_list_size(el), "ElementList.indices");
|
||||
|
||||
return el;
|
||||
}
|
||||
|
||||
void GPUx_element_list_discard(ElementList *el)
|
||||
{
|
||||
#ifdef USE_ELEM_VBO
|
||||
if (el->vbo_id)
|
||||
buffer_id_free(el->vbo_id);
|
||||
#endif /* USE_ELEM_VBO */
|
||||
|
||||
if (el->indices)
|
||||
MEM_freeN(el->indices);
|
||||
MEM_freeN(el);
|
||||
}
|
||||
|
||||
unsigned GPUx_element_list_size(const ElementList *el)
|
||||
{
|
||||
unsigned prim_vertex_ct = 0, index_size = 0;
|
||||
|
||||
if (el->prim_type == GL_POINTS)
|
||||
prim_vertex_ct = 1;
|
||||
else if (el->prim_type == GL_LINES)
|
||||
prim_vertex_ct = 2;
|
||||
else if (el->prim_type == GL_TRIANGLES)
|
||||
prim_vertex_ct = 3;
|
||||
|
||||
if (el->index_type == GL_UNSIGNED_BYTE)
|
||||
index_size = sizeof(GLubyte);
|
||||
else if (el->index_type == GL_UNSIGNED_SHORT)
|
||||
index_size = sizeof(GLushort);
|
||||
else if (el->index_type == GL_UNSIGNED_INT)
|
||||
index_size = sizeof(GLuint);
|
||||
|
||||
return prim_vertex_ct * el->prim_ct * index_size;
|
||||
}
|
||||
|
||||
void GPUx_set_point_vertex(ElementList *el, unsigned prim_idx, unsigned v1)
|
||||
{
|
||||
const unsigned offset = prim_idx;
|
||||
#ifdef TRUST_NO_ONE
|
||||
BLI_assert(el->prim_type == GL_POINTS);
|
||||
BLI_assert(prim_idx < el->prim_ct); /* prim out of range */
|
||||
BLI_assert(v1 <= el->max_allowed_index); /* index out of range */
|
||||
#endif /* TRUST_NO_ONE */
|
||||
#ifdef TRACK_INDEX_RANGE
|
||||
track_index_range(el, v1);
|
||||
#endif /* TRACK_INDEX_RANGE */
|
||||
switch (el->index_type) {
|
||||
case GL_UNSIGNED_BYTE:
|
||||
{
|
||||
GLubyte *indices = el->indices;
|
||||
indices[offset] = v1;
|
||||
break;
|
||||
}
|
||||
case GL_UNSIGNED_SHORT:
|
||||
{
|
||||
GLushort *indices = el->indices;
|
||||
indices[offset] = v1;
|
||||
break;
|
||||
}
|
||||
case GL_UNSIGNED_INT:
|
||||
{
|
||||
GLuint *indices = el->indices;
|
||||
indices[offset] = v1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GPUx_set_line_vertices(ElementList *el, unsigned prim_idx, unsigned v1, unsigned v2)
|
||||
{
|
||||
const unsigned offset = prim_idx * 2;
|
||||
#ifdef TRUST_NO_ONE
|
||||
BLI_assert(el->prim_type == GL_LINES);
|
||||
BLI_assert(prim_idx < el->prim_ct); /* prim out of range */
|
||||
BLI_assert(v1 <= el->max_allowed_index && v2 <= el->max_allowed_index); /* index out of range */
|
||||
BLI_assert(v1 != v2); /* degenerate line */
|
||||
#endif /* TRUST_NO_ONE */
|
||||
#ifdef TRACK_INDEX_RANGE
|
||||
track_index_range(el, v1);
|
||||
track_index_range(el, v2);
|
||||
#endif /* TRACK_INDEX_RANGE */
|
||||
switch (el->index_type) {
|
||||
case GL_UNSIGNED_BYTE:
|
||||
{
|
||||
GLubyte *indices = el->indices;
|
||||
indices[offset] = v1;
|
||||
indices[offset + 1] = v2;
|
||||
break;
|
||||
}
|
||||
case GL_UNSIGNED_SHORT:
|
||||
{
|
||||
GLushort *indices = el->indices;
|
||||
indices[offset] = v1;
|
||||
indices[offset + 1] = v2;
|
||||
break;
|
||||
}
|
||||
case GL_UNSIGNED_INT:
|
||||
{
|
||||
GLuint *indices = el->indices;
|
||||
indices[offset] = v1;
|
||||
indices[offset + 1] = v2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GPUx_set_triangle_vertices(ElementList *el, unsigned prim_idx, unsigned v1, unsigned v2, unsigned v3)
|
||||
{
|
||||
const unsigned offset = prim_idx * 3;
|
||||
#ifdef TRUST_NO_ONE
|
||||
BLI_assert(el->prim_type == GL_TRIANGLES);
|
||||
BLI_assert(prim_idx < el->prim_ct); /* prim out of range */
|
||||
BLI_assert(v1 <= el->max_allowed_index && v2 <= el->max_allowed_index && v3 <= el->max_allowed_index); /* index out of range */
|
||||
BLI_assert(v1 != v2 && v2 != v3 && v3 != v1); /* degenerate triangle */
|
||||
#endif /* TRUST_NO_ONE */
|
||||
#ifdef TRACK_INDEX_RANGE
|
||||
track_index_range(el, v1);
|
||||
track_index_range(el, v2);
|
||||
track_index_range(el, v3);
|
||||
#endif /* TRACK_INDEX_RANGE */
|
||||
switch (el->index_type) {
|
||||
case GL_UNSIGNED_BYTE:
|
||||
{
|
||||
GLubyte *indices = el->indices;
|
||||
indices[offset] = v1;
|
||||
indices[offset + 1] = v2;
|
||||
indices[offset + 2] = v3;
|
||||
break;
|
||||
}
|
||||
case GL_UNSIGNED_SHORT:
|
||||
{
|
||||
GLushort *indices = el->indices;
|
||||
indices[offset] = v1;
|
||||
indices[offset + 1] = v2;
|
||||
indices[offset + 2] = v3;
|
||||
break;
|
||||
}
|
||||
case GL_UNSIGNED_INT:
|
||||
{
|
||||
GLuint *indices = el->indices;
|
||||
indices[offset] = v1;
|
||||
indices[offset + 1] = v2;
|
||||
indices[offset + 2] = v3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GPUx_optimize(ElementList *el)
|
||||
{
|
||||
UNUSED_VARS(el);
|
||||
|
||||
/* TODO: apply Forsyth's vertex cache algorithm */
|
||||
|
||||
/* http://hacksoflife.blogspot.com/2010/01/to-strip-or-not-to-strip.html
|
||||
* http://home.comcast.net/~tom_forsyth/papers/fast_vert_cache_opt.html <-- excellent
|
||||
* http://home.comcast.net/%7Etom_forsyth/blog.wiki.html#%5B%5BRegular%20mesh%20vertex%20cache%20ordering%5D%5D */
|
||||
|
||||
/* Another opportunity: lines & triangles can have their verts rotated
|
||||
* could use this for de-dup and cache optimization.
|
||||
* line ab = ba
|
||||
* triangle abc = bca = cab */
|
||||
|
||||
/* TODO: (optional) rearrange vertex attrib buffer to improve mem locality */
|
||||
}
|
||||
|
||||
void GPUx_element_list_prime(ElementList *el)
|
||||
{
|
||||
#ifdef USE_ELEM_VBO
|
||||
#ifdef TRUST_NO_ONE
|
||||
BLI_assert(el->vbo_id == 0);
|
||||
#endif /* TRUST_NO_ONE */
|
||||
el->vbo_id = buffer_id_alloc();
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, el->vbo_id);
|
||||
/* fill with delicious data & send to GPU the first time only */
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, GPUx_element_list_size(el), el->indices, GL_STATIC_DRAW);
|
||||
#ifdef KEEP_SINGLE_COPY
|
||||
/* now that GL has a copy, discard original */
|
||||
MEM_freeN(el->indices);
|
||||
el->indices = NULL;
|
||||
#endif /* KEEP_SINGLE_COPY */
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
#else
|
||||
UNUSED_VARS(el);
|
||||
#endif /* USE_ELEM_VBO */
|
||||
}
|
||||
|
||||
void GPUx_element_list_use(const ElementList *el)
|
||||
{
|
||||
#ifdef USE_ELEM_VBO
|
||||
#ifdef TRUST_NO_ONE
|
||||
BLI_assert(el->vbo_id);
|
||||
#endif /* TRUST_NO_ONE */
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, el->vbo_id);
|
||||
#else
|
||||
UNUSED_VARS(el);
|
||||
#endif /* USE_ELEM_VBO */
|
||||
}
|
||||
|
||||
void GPUx_element_list_done_using(const ElementList *el)
|
||||
{
|
||||
UNUSED_VARS(el);
|
||||
#ifdef USE_ELEM_VBO
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
#endif /* USE_ELEM_VBO */
|
||||
}
|
37
source/blender/gpu/intern/gpux_element_private.h
Normal file
37
source/blender/gpu/intern/gpux_element_private.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef BLENDER_GL_ELEMENT_LIST_PRIVATE
|
||||
#define BLENDER_GL_ELEMENT_LIST_PRIVATE
|
||||
|
||||
#include "GPUx_element.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
/* track min & max observed index (for glDrawRangeElements) */
|
||||
#define TRACK_INDEX_RANGE
|
||||
|
||||
/* VBOs are guaranteed for any GL >= 1.5
|
||||
* They can be turned off here (mostly for comparison). */
|
||||
#define USE_ELEM_VBO
|
||||
|
||||
struct ElementList {
|
||||
unsigned prim_ct;
|
||||
GLenum prim_type; /* GL_POINTS, GL_LINES, GL_TRIANGLES */
|
||||
GLenum index_type; /* GL_UNSIGNED_BYTE, _SHORT (ES), also _INT (full GL) */
|
||||
unsigned max_allowed_index;
|
||||
|
||||
#ifdef TRACK_INDEX_RANGE
|
||||
unsigned min_observed_index;
|
||||
unsigned max_observed_index;
|
||||
#endif /* TRACK_INDEX_RANGE */
|
||||
|
||||
#ifdef USE_ELEM_VBO
|
||||
GLuint vbo_id;
|
||||
#endif /* USE_ELEM_VBO */
|
||||
|
||||
void *indices; /* array of index_type */
|
||||
};
|
||||
|
||||
unsigned min_index(const ElementList*);
|
||||
unsigned max_index(const ElementList*);
|
||||
|
||||
const void *index_ptr(const ElementList*); /* for glDrawElements */
|
||||
|
||||
#endif /* BLENDER_GL_ELEMENT_LIST_PRIVATE */
|
277
source/blender/gpu/intern/gpux_state.c
Normal file
277
source/blender/gpu/intern/gpux_state.c
Normal file
@@ -0,0 +1,277 @@
|
||||
|
||||
#include "GPUx_state.h"
|
||||
#include "GPUx_vbo.h"
|
||||
|
||||
#include <string.h> /* memset */
|
||||
|
||||
#ifdef TRUST_NO_ONE
|
||||
#include "BLI_utildefines.h"
|
||||
#endif /* TRUST_NO_ONE */
|
||||
|
||||
const DrawState default_state = {
|
||||
.common = {
|
||||
.blend = false,
|
||||
.depth_test = true,
|
||||
.depth_write = true,
|
||||
.lighting = false,
|
||||
.interpolate = false
|
||||
},
|
||||
.point = {
|
||||
.smooth = false,
|
||||
.size = 1.0f
|
||||
},
|
||||
.line = {
|
||||
.smooth = false,
|
||||
.width = 1.0f,
|
||||
.stipple = 0
|
||||
},
|
||||
.polygon = {
|
||||
.draw_front = true,
|
||||
.draw_back = true,
|
||||
.material_id = MATERIAL_NONE,
|
||||
.stipple = 0
|
||||
}
|
||||
};
|
||||
|
||||
static DrawState current;
|
||||
static bool polygon_stipple_pattern_set = false;
|
||||
/* TODO: these should be replicated once per GL context
|
||||
* ^-- more of a MUSTDO */
|
||||
|
||||
void GPUx_reset_draw_state()
|
||||
{
|
||||
current = default_state;
|
||||
GPUx_force_state_update();
|
||||
}
|
||||
|
||||
void GPUx_set_common_state(const CommonDrawState *state)
|
||||
{
|
||||
if (state == NULL)
|
||||
state = &default_state.common;
|
||||
|
||||
if (state->blend != current.common.blend) {
|
||||
if (state->blend)
|
||||
glEnable(GL_BLEND);
|
||||
else
|
||||
glDisable(GL_BLEND);
|
||||
current.common.blend = state->blend;
|
||||
}
|
||||
|
||||
if (state->depth_test != current.common.depth_test) {
|
||||
if (state->depth_test)
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
else
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
current.common.depth_test = state->depth_test;
|
||||
}
|
||||
|
||||
if (state->depth_write != current.common.depth_write) {
|
||||
if (state->depth_write)
|
||||
glDepthMask(1);
|
||||
else
|
||||
glDepthMask(0);
|
||||
current.common.depth_write = state->depth_write;
|
||||
}
|
||||
|
||||
if (state->lighting != current.common.lighting) {
|
||||
if (state->lighting)
|
||||
glEnable(GL_LIGHTING);
|
||||
else
|
||||
glDisable(GL_LIGHTING);
|
||||
current.common.lighting = state->lighting;
|
||||
}
|
||||
|
||||
if (state->interpolate != current.common.interpolate) {
|
||||
if (state->interpolate)
|
||||
glShadeModel(GL_SMOOTH);
|
||||
else
|
||||
glShadeModel(GL_FLAT);
|
||||
current.common.interpolate = state->interpolate;
|
||||
}
|
||||
}
|
||||
|
||||
void GPUx_set_point_state(const PointDrawState *state)
|
||||
{
|
||||
if (state == NULL)
|
||||
state = &default_state.point;
|
||||
|
||||
if (state->smooth != current.point.smooth) {
|
||||
if (state->smooth)
|
||||
glEnable(GL_POINT_SMOOTH);
|
||||
else
|
||||
glDisable(GL_POINT_SMOOTH);
|
||||
current.point.smooth = state->smooth;
|
||||
}
|
||||
|
||||
if (state->size != current.point.size) {
|
||||
glPointSize(state->size);
|
||||
current.point.size = state->size;
|
||||
}
|
||||
}
|
||||
|
||||
void GPUx_set_line_state(const LineDrawState *state)
|
||||
{
|
||||
if (state == NULL)
|
||||
state = &default_state.line;
|
||||
|
||||
if (state->smooth != current.line.smooth) {
|
||||
if (state->smooth)
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
else
|
||||
glDisable(GL_LINE_SMOOTH);
|
||||
current.line.smooth = state->smooth;
|
||||
}
|
||||
|
||||
if (state->width != current.line.width) {
|
||||
glLineWidth(state->width);
|
||||
current.line.width = state->width;
|
||||
}
|
||||
|
||||
if (state->stipple != current.line.stipple) {
|
||||
if (state->stipple) {
|
||||
const GLushort pattern = 0xAAAA;
|
||||
glEnable(GL_LINE_STIPPLE);
|
||||
/* line stipple is 16-bit pattern */
|
||||
glLineStipple(state->stipple, pattern);
|
||||
}
|
||||
else
|
||||
glDisable(GL_LINE_STIPPLE);
|
||||
current.line.stipple = state->stipple;
|
||||
}
|
||||
}
|
||||
|
||||
static GLenum faces_to_cull(const PolygonDrawState *state)
|
||||
{
|
||||
/* https://www.opengl.org/wiki/Face_Culling */
|
||||
|
||||
if (!state->draw_front && !state->draw_back)
|
||||
return GL_FRONT_AND_BACK;
|
||||
else if (!state->draw_front)
|
||||
return GL_FRONT;
|
||||
else if (!state->draw_back)
|
||||
return GL_BACK;
|
||||
else
|
||||
return GL_NONE; /* no culling */
|
||||
}
|
||||
|
||||
void GPUx_set_polygon_state(const PolygonDrawState *state)
|
||||
{
|
||||
if (state == NULL)
|
||||
state = &default_state.polygon;
|
||||
|
||||
if (state->draw_front != current.polygon.draw_front ||
|
||||
state->draw_back != current.polygon.draw_back) {
|
||||
|
||||
const GLenum cull = faces_to_cull(state);
|
||||
|
||||
if (cull == GL_NONE)
|
||||
glDisable(GL_CULL_FACE);
|
||||
else {
|
||||
const GLenum curr_cull = faces_to_cull(¤t.polygon);
|
||||
if (curr_cull == GL_NONE)
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(cull);
|
||||
}
|
||||
current.polygon.draw_front = state->draw_front;
|
||||
current.polygon.draw_back = state->draw_back;
|
||||
}
|
||||
|
||||
if (state->material_id != current.polygon.material_id) {
|
||||
/* TODO: whatever needed to make material active */
|
||||
current.polygon.material_id = state->material_id;
|
||||
}
|
||||
|
||||
if (state->stipple != current.polygon.stipple) {
|
||||
if (state->stipple) {
|
||||
glEnable(GL_POLYGON_STIPPLE);
|
||||
if (!polygon_stipple_pattern_set) {
|
||||
/* polygon stipple is 32x32-bit pattern */
|
||||
GLubyte pattern[128];
|
||||
memset(pattern, 0xAA, sizeof(pattern));
|
||||
glPolygonStipple(pattern);
|
||||
polygon_stipple_pattern_set = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
glDisable(GL_POLYGON_STIPPLE);
|
||||
current.polygon.stipple = state->stipple;
|
||||
}
|
||||
}
|
||||
|
||||
void GPUx_force_state_update()
|
||||
{
|
||||
const GLenum cull = faces_to_cull(¤t.polygon);
|
||||
/* TODO: factor some of this stuff out, share with set_*_state functions? */
|
||||
|
||||
/* common state */
|
||||
if (current.common.blend)
|
||||
glEnable(GL_BLEND);
|
||||
else
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
if (current.common.depth_test)
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
else
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
if (current.common.depth_write)
|
||||
glDepthMask(1);
|
||||
else
|
||||
glDepthMask(0);
|
||||
|
||||
if (current.common.lighting)
|
||||
glEnable(GL_LIGHTING);
|
||||
else
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
if (current.common.interpolate)
|
||||
glShadeModel(GL_SMOOTH);
|
||||
else
|
||||
glShadeModel(GL_FLAT);
|
||||
|
||||
/* point state */
|
||||
if (current.point.smooth)
|
||||
glEnable(GL_POINT_SMOOTH);
|
||||
else
|
||||
glDisable(GL_POINT_SMOOTH);
|
||||
|
||||
glPointSize(current.point.size);
|
||||
|
||||
/* line state */
|
||||
if (current.line.smooth)
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
else
|
||||
glDisable(GL_LINE_SMOOTH);
|
||||
|
||||
glLineWidth(current.line.width);
|
||||
|
||||
if (current.line.stipple) {
|
||||
const GLushort pattern = 0xAAAA;
|
||||
glEnable(GL_LINE_STIPPLE);
|
||||
/* line stipple is 16-bit pattern */
|
||||
glLineStipple(current.line.stipple, pattern);
|
||||
}
|
||||
else
|
||||
glDisable(GL_LINE_STIPPLE);
|
||||
|
||||
/* polygon state */
|
||||
if (cull == GL_NONE)
|
||||
glDisable(GL_CULL_FACE);
|
||||
else {
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(cull);
|
||||
}
|
||||
|
||||
/* TODO: whatever needed to make material active */
|
||||
|
||||
if (current.polygon.stipple) {
|
||||
GLubyte pattern[128];
|
||||
glEnable(GL_POLYGON_STIPPLE);
|
||||
/* polygon stipple is 32x32-bit pattern */
|
||||
memset(pattern, 0xAA, sizeof(pattern));
|
||||
glPolygonStipple(pattern);
|
||||
polygon_stipple_pattern_set = true;
|
||||
}
|
||||
else
|
||||
glDisable(GL_POLYGON_STIPPLE);
|
||||
}
|
550
source/blender/gpu/intern/gpux_vbo.c
Normal file
550
source/blender/gpu/intern/gpux_vbo.c
Normal file
@@ -0,0 +1,550 @@
|
||||
|
||||
#include "GPUx_vbo.h"
|
||||
#include "gpux_buffer_id.h"
|
||||
#include "GPU_extensions.h"
|
||||
#include "BLI_utildefines.h"
|
||||
#include "MEM_guardedalloc.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef PRINT
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
/* VBOs are guaranteed for any GL >= 1.5
|
||||
* They can be turned off here (mostly for comparison). */
|
||||
#define USE_VBO
|
||||
|
||||
#ifdef USE_VBO
|
||||
/* VAOs are part of GL 3.0, and optionally available in 2.1 as an extension:
|
||||
* APPLE_vertex_array_object or ARB_vertex_array_object
|
||||
* the ARB version of VAOs *must* use VBOs for vertex data
|
||||
* so we should follow that restriction on all platforms. */
|
||||
#define USE_VAO
|
||||
|
||||
/* keep vertex data in main mem or VRAM (not both) */
|
||||
#define KEEP_SINGLE_COPY
|
||||
|
||||
#ifdef __linux__
|
||||
#define MESA_WORKAROUND
|
||||
/* For padded attributes (stride > size) Mesa likes the VBO to have some extra
|
||||
* space at the end, else it drops those attributes of our final vertex.
|
||||
* noticed this on Mesa 10.4.3 */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef unsigned char byte;
|
||||
|
||||
typedef struct {
|
||||
GLenum comp_type;
|
||||
unsigned comp_ct; /* 1 to 4 */
|
||||
unsigned sz; /* size in bytes, 1 to 16 */
|
||||
unsigned stride; /* natural stride in bytes, 1 to 16 */
|
||||
VertexFetchMode fetch_mode;
|
||||
#ifdef GENERIC_ATTRIB
|
||||
char *name;
|
||||
#else
|
||||
GLenum array;
|
||||
#endif
|
||||
void *data;
|
||||
/* TODO: more storage options
|
||||
* - single VBO for all attribs (sequential)
|
||||
* - single VBO, attribs interleaved
|
||||
* - distinguish between static & dynamic attribs, w/ separate storage */
|
||||
#ifdef USE_VBO
|
||||
GLuint vbo_id;
|
||||
#endif /* USE_VBO */
|
||||
} Attrib;
|
||||
|
||||
static unsigned comp_sz(GLenum type)
|
||||
{
|
||||
const GLubyte sizes[] = {1,1,2,2,4,4,4}; /* uint32 might result in smaller code? */
|
||||
#ifdef TRUST_NO_ONE
|
||||
BLI_assert(type >= GL_BYTE && type <= GL_FLOAT);
|
||||
#endif /* TRUST_NO_ONE */
|
||||
return sizes[type - GL_BYTE];
|
||||
}
|
||||
|
||||
static unsigned attrib_sz(const Attrib *a)
|
||||
{
|
||||
return a->comp_ct * comp_sz(a->comp_type);
|
||||
}
|
||||
|
||||
static unsigned attrib_align(const Attrib *a)
|
||||
{
|
||||
const unsigned c = comp_sz(a->comp_type);
|
||||
/* AMD HW can't fetch these well, so pad it out (other vendors too?) */
|
||||
if (a->comp_ct == 3 && c <= 2)
|
||||
return 4 * c;
|
||||
else
|
||||
return a->comp_ct * c;
|
||||
}
|
||||
|
||||
struct VertexBuffer
|
||||
{
|
||||
unsigned attrib_ct; /* 1 to 16 */
|
||||
unsigned vertex_ct;
|
||||
#ifdef USE_VAO
|
||||
GLuint vao_id;
|
||||
#endif /* USE_VAO */
|
||||
Attrib attribs[]; /* flexible array */
|
||||
};
|
||||
|
||||
#ifdef PRINT
|
||||
void GPUx_attrib_print(const VertexBuffer *buff, unsigned attrib_num)
|
||||
{
|
||||
unsigned int comp_size, v;
|
||||
Attrib *a = buff->attribs + attrib_num;
|
||||
unsigned type_idx = a->comp_type - GL_BYTE;
|
||||
/* use GLSL names when they exist, or type_count for the others */
|
||||
const char *singular[] = {"byte","ubyte","short","ushort","int","uint","float"};
|
||||
const char *plural[] = {"byte_","ubyte_","short_","ushort_","ivec","uint_","vec"};
|
||||
#ifdef GENERIC_ATTRIB
|
||||
const char *var_name = a->name ? a->name : "foo";
|
||||
#else
|
||||
const char* var_name = "foo";
|
||||
switch (a->array) {
|
||||
case GL_VERTEX_ARRAY:
|
||||
var_name = "gl_Vertex";
|
||||
break;
|
||||
case GL_NORMAL_ARRAY:
|
||||
var_name = "gl_Normal";
|
||||
break;
|
||||
case GL_COLOR_ARRAY:
|
||||
var_name = "gl_Color";
|
||||
break;
|
||||
case GL_TEXTURE_COORD_ARRAY:
|
||||
var_name = "gl_MultiTexCoord0";
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
#endif
|
||||
#ifdef TRUST_NO_ONE
|
||||
BLI_assert(attrib_num < buff->attrib_ct);
|
||||
BLI_assert(a->comp_type >= GL_BYTE && a->comp_type <= GL_FLOAT);
|
||||
BLI_assert(a->data != NULL); /* attribute must be specified & in main mem */
|
||||
#endif /* TRUST_NO_ONE */
|
||||
if (a->comp_ct == 1)
|
||||
printf("attrib %s %s = {\n", singular[type_idx], var_name);
|
||||
else
|
||||
printf("attrib %s%d %s = {\n", plural[type_idx], a->comp_ct, var_name);
|
||||
|
||||
comp_size = comp_sz(a->comp_type);
|
||||
for (v = 0; v < buff->vertex_ct; ++v) {
|
||||
unsigned int offset;
|
||||
const void *data = (byte*)a->data + v * a->stride;
|
||||
for (offset = 0; offset < a->sz; ++offset) {
|
||||
if (offset % comp_size == 0)
|
||||
putchar(' ');
|
||||
printf("%02X", *(const byte*)data + offset);
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
puts("}");
|
||||
}
|
||||
#endif /* PRINT */
|
||||
|
||||
VertexBuffer *GPUx_vertex_buffer_create(unsigned a_ct, unsigned v_ct)
|
||||
{
|
||||
VertexBuffer *buff;
|
||||
#ifdef TRUST_NO_ONE
|
||||
BLI_assert(a_ct >= 1 && a_ct <= 16);
|
||||
#ifdef USE_VAO
|
||||
BLI_assert(GPU_vertex_array_object_support());
|
||||
#endif /* USE_VBO */
|
||||
#endif /* TRUST_NO_ONE */
|
||||
buff = MEM_callocN(offsetof(VertexBuffer, attribs) + a_ct * sizeof(Attrib), "VertexBuffer");
|
||||
buff->attrib_ct = a_ct;
|
||||
buff->vertex_ct = v_ct;
|
||||
return buff;
|
||||
}
|
||||
|
||||
void GPUx_vertex_buffer_discard(VertexBuffer *buff)
|
||||
{
|
||||
unsigned a_idx;
|
||||
for (a_idx = 0; a_idx < buff->attrib_ct; ++a_idx) {
|
||||
Attrib *a = buff->attribs + a_idx;
|
||||
#ifdef USE_VBO
|
||||
if (a->vbo_id)
|
||||
buffer_id_free(a->vbo_id);
|
||||
#endif /* USE_VBO */
|
||||
#ifdef GENERIC_ATTRIB
|
||||
free(a->name);
|
||||
#endif /* GENERIC_ATTRIB */
|
||||
if (a->data)
|
||||
MEM_freeN(a->data);
|
||||
}
|
||||
#ifdef USE_VAO
|
||||
if (buff->vao_id)
|
||||
vao_id_free(buff->vao_id);
|
||||
#endif /* USE_VAO */
|
||||
MEM_freeN(buff);
|
||||
}
|
||||
|
||||
static unsigned attrib_total_size(const VertexBuffer *buff, unsigned attrib_num)
|
||||
{
|
||||
const Attrib *attrib = buff->attribs + attrib_num;
|
||||
#ifdef TRUST_NO_ONE
|
||||
BLI_assert(attrib_num < buff->attrib_ct);
|
||||
#endif /* TRUST_NO_ONE */
|
||||
|
||||
#ifdef MESA_WORKAROUND
|
||||
/* an over-estimate, with padding after each vertex */
|
||||
return buff->vertex_ct * attrib->stride;
|
||||
#else
|
||||
/* just enough space for every vertex, with padding between but not after the last */
|
||||
return (buff->vertex_ct - 1) * attrib->stride + attrib->sz;
|
||||
#endif /* MESA_WORKAROUND */
|
||||
}
|
||||
|
||||
unsigned GPUx_vertex_buffer_size(const VertexBuffer *buff)
|
||||
{
|
||||
unsigned sz = 0;
|
||||
unsigned a_idx;
|
||||
for (a_idx = 0; a_idx < buff->attrib_ct; ++a_idx)
|
||||
sz += attrib_total_size(buff, a_idx);
|
||||
return sz;
|
||||
}
|
||||
|
||||
void GPUx_specify_attrib(VertexBuffer *buff, unsigned attrib_num,
|
||||
#ifdef GENERIC_ATTRIB
|
||||
const char *name,
|
||||
#else
|
||||
GLenum attrib_array,
|
||||
#endif
|
||||
GLenum comp_type, unsigned comp_ct, VertexFetchMode fetch_mode)
|
||||
{
|
||||
Attrib *attrib;
|
||||
#ifdef TRUST_NO_ONE
|
||||
BLI_assert(attrib_num < buff->attrib_ct);
|
||||
BLI_assert(comp_type >= GL_BYTE && comp_type <= GL_FLOAT);
|
||||
BLI_assert(comp_ct >= 1 && comp_ct <= 4);
|
||||
|
||||
if (comp_type == GL_FLOAT)
|
||||
BLI_assert(fetch_mode == KEEP_FLOAT);
|
||||
else {
|
||||
BLI_assert(fetch_mode != KEEP_FLOAT);
|
||||
if (fetch_mode == KEEP_INT)
|
||||
BLI_assert(GPU_shader4_support());
|
||||
}
|
||||
|
||||
#ifndef GENERIC_ATTRIB
|
||||
/* classic (non-generic) attributes each have their quirks
|
||||
* handle below */
|
||||
switch (attrib_array) {
|
||||
case GL_VERTEX_ARRAY:
|
||||
BLI_assert(comp_type == GL_FLOAT || comp_type == GL_SHORT || comp_type == GL_INT);
|
||||
if (comp_type != GL_FLOAT)
|
||||
BLI_assert(fetch_mode == CONVERT_INT_TO_FLOAT);
|
||||
BLI_assert(comp_ct >= 2);
|
||||
break;
|
||||
case GL_NORMAL_ARRAY:
|
||||
BLI_assert(comp_type == GL_FLOAT || comp_type == GL_BYTE || comp_type == GL_SHORT || comp_type == GL_INT);
|
||||
if (comp_type != GL_FLOAT)
|
||||
BLI_assert(fetch_mode == NORMALIZE_INT_TO_FLOAT);
|
||||
BLI_assert(comp_ct == 3);
|
||||
break;
|
||||
case GL_COLOR_ARRAY:
|
||||
/* any comp_type allowed */
|
||||
if (comp_type != GL_FLOAT)
|
||||
BLI_assert(fetch_mode == NORMALIZE_INT_TO_FLOAT);
|
||||
BLI_assert(comp_ct >= 3);
|
||||
break;
|
||||
case GL_TEXTURE_COORD_ARRAY:
|
||||
BLI_assert(comp_type == GL_FLOAT || comp_type == GL_SHORT || comp_type == GL_INT);
|
||||
if (comp_type != GL_FLOAT)
|
||||
BLI_assert(fetch_mode == CONVERT_INT_TO_FLOAT);
|
||||
break;
|
||||
/* not supporting these:
|
||||
* GL_INDEX_ARRAY
|
||||
* GL_SECONDARY_COLOR_ARRAY
|
||||
* GL_EDGE_FLAG_ARRAY
|
||||
* GL_FOG_COORD_ARRAY
|
||||
*/
|
||||
default:
|
||||
BLI_assert(false); /* bad or unsupported array */
|
||||
}
|
||||
BLI_assert(fetch_mode != KEEP_INT); /* glVertexPointer and friends have no int variants */
|
||||
/* TODO: allow only one of each type of array (scan other attribs) */
|
||||
#endif
|
||||
#endif /* TRUST_NO_ONE */
|
||||
attrib = buff->attribs + attrib_num;
|
||||
#ifdef GENERIC_ATTRIB
|
||||
attrib->name = strdup(name);
|
||||
#else
|
||||
attrib->array = attrib_array;
|
||||
#endif /* GENERIC_ATTRIB */
|
||||
attrib->comp_type = comp_type;
|
||||
attrib->comp_ct = comp_ct;
|
||||
attrib->sz = attrib_sz(attrib);
|
||||
attrib->stride = attrib_align(attrib);
|
||||
attrib->fetch_mode = fetch_mode;
|
||||
attrib->data = MEM_mallocN(attrib_total_size(buff, attrib_num), "Attrib.data");
|
||||
#ifdef PRINT
|
||||
GPUx_attrib_print(buff, attrib_num);
|
||||
#endif /* PRINT */
|
||||
}
|
||||
|
||||
#ifdef GENERIC_ATTRIB
|
||||
void GPUx_bind_attrib_locations(const VertexBuffer *buff, GLuint program)
|
||||
{
|
||||
unsigned a_idx;
|
||||
#ifdef TRUST_NO_ONE
|
||||
BLI_assert(glIsProgram(program));
|
||||
#endif
|
||||
for (a_idx = 0; a_idx < buff->attrib_ct; ++a_idx) {
|
||||
const Attrib *a = buff->attribs + a_idx;
|
||||
glBindAttribLocation(program, a_idx, a->name);
|
||||
}
|
||||
}
|
||||
#endif /* GENERIC_ATTRIB */
|
||||
|
||||
void GPUx_set_attrib(VertexBuffer *buff, unsigned attrib_num, unsigned vertex_num, const void *data)
|
||||
{
|
||||
Attrib *attrib = buff->attribs + attrib_num;
|
||||
#ifdef TRUST_NO_ONE
|
||||
BLI_assert(attrib_num < buff->attrib_ct);
|
||||
BLI_assert(vertex_num < buff->vertex_ct);
|
||||
BLI_assert(attrib->data != NULL); /* attribute must be specified & in main mem */
|
||||
#endif /* TRUST_NO_ONE */
|
||||
memcpy((byte*)attrib->data + vertex_num * attrib->stride, data, attrib->sz);
|
||||
}
|
||||
|
||||
void GPUx_set_attrib_2f(VertexBuffer *buff, unsigned attrib_num, unsigned vertex_num, float x, float y)
|
||||
{
|
||||
const GLfloat data[] = { x, y };
|
||||
#ifdef TRUST_NO_ONE
|
||||
Attrib *attrib = buff->attribs + attrib_num;
|
||||
BLI_assert(attrib->comp_type == GL_FLOAT);
|
||||
BLI_assert(attrib->comp_ct == 2);
|
||||
#endif /* TRUST_NO_ONE */
|
||||
GPUx_set_attrib(buff, attrib_num, vertex_num, data);
|
||||
}
|
||||
|
||||
void GPUx_set_attrib_3f(VertexBuffer *buff, unsigned attrib_num, unsigned vertex_num, float x, float y, float z)
|
||||
{
|
||||
const GLfloat data[] = { x, y, z };
|
||||
#ifdef TRUST_NO_ONE
|
||||
Attrib *attrib = buff->attribs + attrib_num;
|
||||
BLI_assert(attrib->comp_type == GL_FLOAT);
|
||||
BLI_assert(attrib->comp_ct == 3);
|
||||
#endif /* TRUST_NO_ONE */
|
||||
GPUx_set_attrib(buff, attrib_num, vertex_num, data);
|
||||
}
|
||||
|
||||
void GPUx_fill_attrib(VertexBuffer *buff, unsigned attrib_num, const void *data)
|
||||
{
|
||||
Attrib *attrib = buff->attribs + attrib_num;
|
||||
#ifdef TRUST_NO_ONE
|
||||
BLI_assert(attrib_num < buff->attrib_ct);
|
||||
BLI_assert(attrib->data != NULL); /* attribute must be specified & in main mem */
|
||||
#endif /* TRUST_NO_ONE */
|
||||
if (attrib->sz == attrib->stride) {
|
||||
/* tightly packed, so we can copy it all at once */
|
||||
memcpy(attrib->data, data, buff->vertex_ct * attrib->sz);
|
||||
}
|
||||
else {
|
||||
unsigned v;
|
||||
/* not tightly packed, so we must copy it per vertex
|
||||
* (this is begging for vector (SSE) coding) */
|
||||
for (v = 0; v < buff->vertex_ct; ++v)
|
||||
memcpy((byte*)attrib->data + v * attrib->stride, (byte*)data + v * attrib->sz, attrib->sz);
|
||||
}
|
||||
}
|
||||
|
||||
void GPUx_fill_attrib_stride(VertexBuffer *buff, unsigned attrib_num, const void *data, unsigned stride)
|
||||
{
|
||||
Attrib *attrib = buff->attribs + attrib_num;
|
||||
#ifdef TRUST_NO_ONE
|
||||
BLI_assert(attrib_num < buff->attrib_ct);
|
||||
BLI_assert(attrib->data != NULL); /* attribute must be specified & in main mem */
|
||||
BLI_assert(stride >= attrib->sz); /* no overlapping attributes (legal but weird) */
|
||||
#endif /* TRUST_NO_ONE */
|
||||
if (stride == attrib->stride) {
|
||||
/* natural stride used, so we can copy it all at once */
|
||||
memcpy(attrib->data, data, buff->vertex_ct * attrib->sz);
|
||||
}
|
||||
else {
|
||||
unsigned v;
|
||||
/* we must copy it per vertex */
|
||||
for (v = 0; v < buff->vertex_ct; ++v)
|
||||
memcpy((byte*)attrib->data + v * attrib->stride, (byte*)data + v * stride, attrib->sz);
|
||||
}
|
||||
}
|
||||
|
||||
void GPUx_vertex_buffer_prime(VertexBuffer *buff)
|
||||
{
|
||||
unsigned a_idx;
|
||||
#ifdef USE_VAO
|
||||
#ifdef TRUST_NO_ONE
|
||||
BLI_assert(buff->vao_id == 0);
|
||||
#endif /* TRUST_NO_ONE */
|
||||
|
||||
buff->vao_id = vao_id_alloc();
|
||||
glBindVertexArray(buff->vao_id);
|
||||
#endif /* USE_VAO */
|
||||
|
||||
#ifdef USE_VBO
|
||||
for (a_idx = 0; a_idx < buff->attrib_ct; ++a_idx) {
|
||||
Attrib *a = buff->attribs + a_idx;
|
||||
|
||||
#ifdef USE_VAO
|
||||
#ifdef GENERIC_ATTRIB
|
||||
glEnableVertexAttribArray(a_idx);
|
||||
#else
|
||||
glEnableClientState(a->array);
|
||||
#endif /* GENERIC_ATTRIB */
|
||||
#endif /* USE_VAO */
|
||||
|
||||
#ifdef TRUST_NO_ONE
|
||||
BLI_assert(a->vbo_id == 0);
|
||||
#endif /* TRUST_NO_ONE */
|
||||
|
||||
a->vbo_id = buffer_id_alloc();
|
||||
glBindBuffer(GL_ARRAY_BUFFER, a->vbo_id);
|
||||
/* fill with delicious data & send to GPU the first time only */
|
||||
glBufferData(GL_ARRAY_BUFFER, attrib_total_size(buff, a_idx), a->data, GL_STATIC_DRAW);
|
||||
#ifdef KEEP_SINGLE_COPY
|
||||
/* now that GL has a copy, discard original */
|
||||
MEM_freeN(a->data);
|
||||
a->data = NULL;
|
||||
#endif /* KEEP_SINGLE_COPY */
|
||||
|
||||
#ifdef USE_VAO
|
||||
#ifdef GENERIC_ATTRIB
|
||||
switch (a->fetch_mode) {
|
||||
case KEEP_FLOAT:
|
||||
case CONVERT_INT_TO_FLOAT:
|
||||
glVertexAttribPointer(a_idx, a->comp_ct, a->comp_type, GL_FALSE, a->stride, 0);
|
||||
break;
|
||||
case NORMALIZE_INT_TO_FLOAT:
|
||||
glVertexAttribPointer(a_idx, a->comp_ct, a->comp_type, GL_TRUE, a->stride, 0);
|
||||
break;
|
||||
case KEEP_INT:
|
||||
glVertexAttribIPointerEXT(a_idx, a->comp_ct, a->comp_type, a->stride, 0);
|
||||
}
|
||||
#else /* classic (non-generic) attributes */
|
||||
switch (a->array) {
|
||||
case GL_VERTEX_ARRAY:
|
||||
glVertexPointer(a->comp_ct, a->comp_type, a->stride, 0);
|
||||
break;
|
||||
case GL_NORMAL_ARRAY:
|
||||
glNormalPointer(a->comp_type, a->stride, 0);
|
||||
break;
|
||||
case GL_COLOR_ARRAY:
|
||||
glColorPointer(a->comp_ct, a->comp_type, a->stride, 0);
|
||||
break;
|
||||
case GL_TEXTURE_COORD_ARRAY:
|
||||
glTexCoordPointer(a->comp_ct, a->comp_type, a->stride, 0);
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
#endif /* GENERIC_ATTRIB */
|
||||
#endif /* USE_VAO */
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
#else
|
||||
UNUSED_VARS(a_idx, buff);
|
||||
#endif /* USE_VBO */
|
||||
|
||||
#ifdef USE_VAO
|
||||
glBindVertexArray(0);
|
||||
#endif /* USE_VAO */
|
||||
}
|
||||
|
||||
void GPUx_vertex_buffer_use(const VertexBuffer *buff)
|
||||
{
|
||||
#ifdef USE_VAO
|
||||
#ifdef TRUST_NO_ONE
|
||||
BLI_assert(buff->vao_id);
|
||||
#endif /* TRUST_NO_ONE */
|
||||
|
||||
/* simply bind & exit */
|
||||
glBindVertexArray(buff->vao_id);
|
||||
#else
|
||||
unsigned int a_idx;
|
||||
|
||||
for (a_idx = 0; a_idx < buff->attrib_ct; ++a_idx) {
|
||||
Attrib *a = buff->attribs + a_idx;
|
||||
const void *data;
|
||||
|
||||
#ifdef GENERIC_ATTRIB
|
||||
glEnableVertexAttribArray(a_idx);
|
||||
#else
|
||||
glEnableClientState(a->array);
|
||||
#endif /* GENERIC_ATTRIB */
|
||||
|
||||
#ifdef USE_VBO
|
||||
#ifdef TRUST_NO_ONE
|
||||
BLI_assert(a->vbo_id);
|
||||
#endif /* TRUST_NO_ONE */
|
||||
glBindBuffer(GL_ARRAY_BUFFER, a->vbo_id);
|
||||
|
||||
data = 0;
|
||||
#else /* client vertex array */
|
||||
data = a->data;
|
||||
#endif /* USE_VBO */
|
||||
|
||||
#ifdef GENERIC_ATTRIB
|
||||
switch (a->fetch_mode) {
|
||||
case KEEP_FLOAT:
|
||||
case CONVERT_INT_TO_FLOAT:
|
||||
glVertexAttribPointer(a_idx, a->comp_ct, a->comp_type, GL_FALSE, a->stride, data);
|
||||
break;
|
||||
case NORMALIZE_INT_TO_FLOAT:
|
||||
glVertexAttribPointer(a_idx, a->comp_ct, a->comp_type, GL_TRUE, a->stride, data);
|
||||
break;
|
||||
case KEEP_INT:
|
||||
glVertexAttribIPointerEXT(a_idx, a->comp_ct, a->comp_type, a->stride, data);
|
||||
}
|
||||
#else /* classic (non-generic) attributes */
|
||||
switch (a->array) {
|
||||
case GL_VERTEX_ARRAY:
|
||||
glVertexPointer(a->comp_ct, a->comp_type, a->stride, data);
|
||||
break;
|
||||
case GL_NORMAL_ARRAY:
|
||||
glNormalPointer(a->comp_type, a->stride, data);
|
||||
break;
|
||||
case GL_COLOR_ARRAY:
|
||||
glColorPointer(a->comp_ct, a->comp_type, a->stride, data);
|
||||
break;
|
||||
case GL_TEXTURE_COORD_ARRAY:
|
||||
glTexCoordPointer(a->comp_ct, a->comp_type, a->stride, data);
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
#endif /* GENERIC_ATTRIB */
|
||||
}
|
||||
|
||||
#ifdef USE_VBO
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
#endif /* USE_VBO */
|
||||
#endif /* USE_VAO */
|
||||
}
|
||||
|
||||
void GPUx_vertex_buffer_done_using(const VertexBuffer *buff)
|
||||
{
|
||||
#ifdef USE_VAO
|
||||
UNUSED_VARS(buff);
|
||||
glBindVertexArray(0);
|
||||
#else
|
||||
unsigned int a_idx;
|
||||
|
||||
for (a_idx = 0; a_idx < buff->attrib_ct; ++a_idx) {
|
||||
#ifdef GENERIC_ATTRIB
|
||||
glDisableVertexAttribArray(a_idx);
|
||||
#else
|
||||
glDisableClientState(buff->attribs[a_idx].array);
|
||||
#endif /* GENERIC_ATTRIB */
|
||||
}
|
||||
#endif /* USE_VAO */
|
||||
}
|
||||
|
||||
unsigned GPUx_vertex_ct(const VertexBuffer *buff)
|
||||
{
|
||||
return buff->vertex_ct;
|
||||
}
|
@@ -222,6 +222,7 @@ typedef struct PreviewImage {
|
||||
#define ID_LS MAKE_ID2('L', 'S') /* FreestyleLineStyle */
|
||||
#define ID_PAL MAKE_ID2('P', 'L') /* Palette */
|
||||
#define ID_PC MAKE_ID2('P', 'C') /* PaintCurve */
|
||||
#define ID_GPUWS MAKE_ID2('G', 'W') /* GPUWorkflowShader */
|
||||
|
||||
/* NOTE! Fake IDs, needed for g.sipo->blocktype or outliner */
|
||||
#define ID_SEQ MAKE_ID2('S', 'Q')
|
||||
|
@@ -394,6 +394,7 @@ typedef struct bNodeTree {
|
||||
#define NTREE_SHADER 0
|
||||
#define NTREE_COMPOSIT 1
|
||||
#define NTREE_TEXTURE 2
|
||||
#define NTREE_WORKFLOW 3
|
||||
|
||||
/* ntree->init, flag */
|
||||
#define NTREE_TYPE_INIT 1
|
||||
@@ -840,6 +841,18 @@ typedef struct NodeShaderScript {
|
||||
char *bytecode;
|
||||
} NodeShaderScript;
|
||||
|
||||
typedef struct NodeShaderScriptGLSL {
|
||||
/* XXX merwin: what is needed here? */
|
||||
int mode; /* ok, use same values */
|
||||
int flag; /* ok, use same flag */
|
||||
|
||||
char filepath[1024]; /* 1024 = FILE_MAX */
|
||||
|
||||
/* v-- don't need these though */
|
||||
/* char bytecode_hash[64]; */
|
||||
/* char *bytecode; */
|
||||
} NodeShaderScriptGLSL;
|
||||
|
||||
typedef struct NodeShaderTangent {
|
||||
int direction_type;
|
||||
int axis;
|
||||
|
@@ -739,6 +739,7 @@ typedef enum eOpenGL_RenderingOptions {
|
||||
USER_DISABLE_MIPMAP = (1 << 2),
|
||||
USER_DISABLE_VBO = (1 << 3),
|
||||
/* USER_DISABLE_AA = (1 << 4), */ /* DEPRECATED */
|
||||
USER_VIEWPORT_2 = (1 << 5),
|
||||
} eOpenGL_RenderingOptions;
|
||||
|
||||
/* selection method for opengl gpu_select_method */
|
||||
|
@@ -61,6 +61,8 @@ struct GPUFX;
|
||||
#include "DNA_movieclip_types.h"
|
||||
#include "DNA_gpu_types.h"
|
||||
|
||||
struct bNodeTree;
|
||||
|
||||
/* ******************************** */
|
||||
|
||||
/* The near/far thing is a Win EXCEPTION. Thus, leave near/far in the
|
||||
@@ -81,6 +83,16 @@ typedef struct BGpic {
|
||||
char pad[6];
|
||||
} BGpic;
|
||||
|
||||
|
||||
typedef struct GPUWorkflowShader {
|
||||
ID id;
|
||||
int objectmode; /* object modes for which this workflow applies */
|
||||
int use_material; /* workflow shader is overlaid over materials of the meshes */
|
||||
int datamask; /* datamask of the data that will be required for this workflow shader */
|
||||
int pad;
|
||||
struct bNodeTree *nodetree; /* node tree that describes the shader */
|
||||
} GPUWorkflowShader;
|
||||
|
||||
/* ********************************* */
|
||||
|
||||
typedef struct RegionView3D {
|
||||
@@ -229,6 +241,7 @@ typedef struct View3D {
|
||||
|
||||
/* XXX deprecated? */
|
||||
struct bGPdata *gpd DNA_DEPRECATED; /* Grease-Pencil Data (annotation layers) */
|
||||
struct GPUWorkflowShader *activeworkflow;
|
||||
|
||||
/* multiview - stereo 3d */
|
||||
short stereo3d_flag;
|
||||
|
@@ -259,6 +259,7 @@ extern StructRNA RNA_GPencilFrame;
|
||||
extern StructRNA RNA_GPencilLayer;
|
||||
extern StructRNA RNA_GPencilStroke;
|
||||
extern StructRNA RNA_GPencilStrokePoint;
|
||||
extern StructRNA RNA_GPUWorkflowShader;
|
||||
extern StructRNA RNA_GameBooleanProperty;
|
||||
extern StructRNA RNA_GameFloatProperty;
|
||||
extern StructRNA RNA_GameIntProperty;
|
||||
@@ -514,6 +515,7 @@ extern StructRNA RNA_ShaderNodeNormal;
|
||||
extern StructRNA RNA_ShaderNodeGamma;
|
||||
extern StructRNA RNA_ShaderNodeOutput;
|
||||
extern StructRNA RNA_ShaderNodeScript;
|
||||
extern StructRNA RNA_ShaderNodeScriptGLSL;
|
||||
extern StructRNA RNA_ShaderNodeRGB;
|
||||
extern StructRNA RNA_ShaderNodeRGBCurve;
|
||||
extern StructRNA RNA_ShaderNodeRGBToBW;
|
||||
@@ -675,6 +677,7 @@ extern StructRNA RNA_WindowManager;
|
||||
extern StructRNA RNA_WipeSequence;
|
||||
extern StructRNA RNA_WireframeModifier;
|
||||
extern StructRNA RNA_WoodTexture;
|
||||
extern StructRNA RNA_WorkflowNodeTree;
|
||||
extern StructRNA RNA_World;
|
||||
extern StructRNA RNA_WorldAmbientOcclusion;
|
||||
extern StructRNA RNA_WorldLighting;
|
||||
|
@@ -159,6 +159,7 @@ short RNA_type_to_ID_code(StructRNA *type)
|
||||
if (RNA_struct_is_a(type, &RNA_VectorFont)) return ID_VF;
|
||||
if (RNA_struct_is_a(type, &RNA_World)) return ID_WO;
|
||||
if (RNA_struct_is_a(type, &RNA_WindowManager)) return ID_WM;
|
||||
if (RNA_struct_is_a(type, &RNA_GPUWorkflowShader)) return ID_GPUWS;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -198,6 +199,7 @@ StructRNA *ID_code_to_RNA_type(short idcode)
|
||||
case ID_VF: return &RNA_VectorFont;
|
||||
case ID_WM: return &RNA_WindowManager;
|
||||
case ID_WO: return &RNA_World;
|
||||
case ID_GPUWS: return &RNA_GPUWorkflowShader;
|
||||
|
||||
default: return &RNA_ID;
|
||||
}
|
||||
|
@@ -2951,6 +2951,50 @@ static void rna_ShaderNodeScript_update(Main *bmain, Scene *scene, PointerRNA *p
|
||||
ED_node_tag_update_nodetree(bmain, ntree);
|
||||
}
|
||||
|
||||
static void rna_ShaderNodeScriptGLSL_mode_set(PointerRNA *ptr, int value)
|
||||
{
|
||||
bNode *node = (bNode *)ptr->data;
|
||||
NodeShaderScriptGLSL *nss = node->storage;
|
||||
|
||||
if (nss->mode != value) {
|
||||
nss->mode = value;
|
||||
nss->filepath[0] = '\0';
|
||||
nss->flag &= ~NODE_SCRIPT_AUTO_UPDATE;
|
||||
|
||||
/* replace text datablock by filepath */
|
||||
if (node->id) {
|
||||
Text *text = (Text *)node->id;
|
||||
|
||||
if (value == NODE_SCRIPT_EXTERNAL && text->name) {
|
||||
BLI_strncpy(nss->filepath, text->name, sizeof(nss->filepath));
|
||||
BLI_path_rel(nss->filepath, G.main->name);
|
||||
}
|
||||
|
||||
id_us_min(node->id);
|
||||
node->id = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void rna_ShaderNodeScriptGLSL_update(Main *bmain, Scene *scene, PointerRNA *ptr)
|
||||
{
|
||||
/* TODO: the right thing --merwin */
|
||||
#if 0
|
||||
bNodeTree *ntree = (bNodeTree *)ptr->id.data;
|
||||
bNode *node = (bNode *)ptr->data;
|
||||
RenderEngineType *engine_type = RE_engines_find(scene->r.engine);
|
||||
|
||||
if (engine_type && engine_type->update_script_node) {
|
||||
/* auto update node */
|
||||
RenderEngine *engine = RE_engine_create(engine_type);
|
||||
engine_type->update_script_node(engine, ntree, node);
|
||||
RE_engine_free(engine);
|
||||
}
|
||||
|
||||
ED_node_tag_update_nodetree(bmain, ntree);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void rna_ShaderNodeSubsurface_update(Main *bmain, Scene *scene, PointerRNA *ptr)
|
||||
{
|
||||
bNodeTree *ntree = (bNodeTree *)ptr->id.data;
|
||||
@@ -4034,6 +4078,40 @@ static void def_sh_script(StructRNA *srna)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void def_sh_script_glsl(StructRNA *srna)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
prop = RNA_def_property(srna, "script_glsl", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "id");
|
||||
RNA_def_property_struct_type(prop, "Text");
|
||||
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
|
||||
RNA_def_property_ui_text(prop, "Script", "Internal shader script to define the shader");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNodeScriptGLSL_update");
|
||||
|
||||
RNA_def_struct_sdna_from(srna, "NodeShaderScriptGLSL", "storage");
|
||||
|
||||
prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH);
|
||||
RNA_def_property_ui_text(prop, "File Path", "Shader script path");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNodeScriptGLSL_update");
|
||||
|
||||
prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_funcs(prop, NULL, "rna_ShaderNodeScriptGLSL_mode_set", NULL);
|
||||
RNA_def_property_enum_items(prop, node_script_mode_items);
|
||||
RNA_def_property_ui_text(prop, "Script Source", "");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_auto_update", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_SCRIPT_AUTO_UPDATE);
|
||||
RNA_def_property_ui_text(prop, "Auto Update",
|
||||
"Automatically update the shader when the .glsl file changes (external scripts only)");
|
||||
|
||||
/* needs to be reset to avoid bad pointer type in API functions below */
|
||||
RNA_def_struct_sdna_from(srna, "bNode", NULL);
|
||||
|
||||
/* API functions */
|
||||
}
|
||||
|
||||
/* -- Compositor Nodes ------------------------------------------------------ */
|
||||
|
||||
static void def_cmp_alpha_over(StructRNA *srna)
|
||||
@@ -7693,6 +7771,7 @@ static void rna_def_nodetree(BlenderRNA *brna)
|
||||
|
||||
static EnumPropertyItem static_type_items[] = {
|
||||
{NTREE_SHADER, "SHADER", ICON_MATERIAL, "Shader", "Shader nodes"},
|
||||
{NTREE_WORKFLOW, "WORKFLOW", ICON_SMOOTH, "Workflow", "Workflow nodes"},
|
||||
{NTREE_TEXTURE, "TEXTURE", ICON_TEXTURE, "Texture", "Texture nodes"},
|
||||
{NTREE_COMPOSIT, "COMPOSITING", ICON_RENDERLAYERS, "Compositing", "Compositing nodes"},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
@@ -7876,6 +7955,18 @@ static void rna_def_shader_nodetree(BlenderRNA *brna)
|
||||
RNA_def_struct_ui_icon(srna, ICON_MATERIAL);
|
||||
}
|
||||
|
||||
|
||||
static void rna_def_workflow_nodetree(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
|
||||
srna = RNA_def_struct(brna, "WorkflowNodeTree", "NodeTree");
|
||||
RNA_def_struct_ui_text(srna, "Workflow Node Tree",
|
||||
"Node tree consisting of linked nodes used for shader workflows");
|
||||
RNA_def_struct_sdna(srna, "bNodeTree");
|
||||
RNA_def_struct_ui_icon(srna, ICON_SMOOTH);
|
||||
}
|
||||
|
||||
static void rna_def_texture_nodetree(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
@@ -7972,6 +8063,7 @@ void RNA_def_nodetree(BlenderRNA *brna)
|
||||
|
||||
rna_def_composite_nodetree(brna);
|
||||
rna_def_shader_nodetree(brna);
|
||||
rna_def_workflow_nodetree(brna);
|
||||
rna_def_texture_nodetree(brna);
|
||||
|
||||
#define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
|
||||
@@ -7994,6 +8086,7 @@ void RNA_def_nodetree(BlenderRNA *brna)
|
||||
define_specific_node(brna, "ShaderNodeGroup", "ShaderNode", "Group", "", def_group);
|
||||
define_specific_node(brna, "CompositorNodeGroup", "CompositorNode", "Group", "", def_group);
|
||||
define_specific_node(brna, "TextureNodeGroup", "TextureNode", "Group", "", def_group);
|
||||
define_specific_node(brna, "WorkflowNodeGroup", "TextureNode", "Group", "", def_group);
|
||||
def_custom_group(brna);
|
||||
|
||||
/* special socket types */
|
||||
|
@@ -2031,6 +2031,21 @@ static void rna_def_space_outliner(BlenderRNA *brna)
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL);
|
||||
}
|
||||
|
||||
static void rna_def_workflow_shader(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
srna = RNA_def_struct(brna, "GPUWorkflowShader", "ID");
|
||||
RNA_def_struct_sdna(srna, "GPUWorkflowShader");
|
||||
RNA_def_struct_ui_text(srna, "Workflow Shader", "Drawing definition in the 3D viewport");
|
||||
|
||||
prop = RNA_def_property(srna, "node_tree", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "nodetree");
|
||||
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_CONTEXT_UPDATE);
|
||||
RNA_def_property_ui_text(prop, "Node Tree", "Node tree for node based worlds");
|
||||
}
|
||||
|
||||
static void rna_def_background_image(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
@@ -2347,6 +2362,11 @@ static void rna_def_space_view3d(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Viewport Shading", "Method to display/shade objects in the 3D View");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_SpaceView3D_viewport_shade_update");
|
||||
|
||||
prop = RNA_def_property(srna, "activeworkflow", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Shading Workflow", "Method to display/shade objects in the 3D View");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_SpaceView3D_viewport_shade_update");
|
||||
|
||||
prop = RNA_def_property(srna, "local_view", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "localvd");
|
||||
RNA_def_property_ui_text(prop, "Local View",
|
||||
@@ -4548,6 +4568,7 @@ void RNA_def_space(BlenderRNA *brna)
|
||||
rna_def_filemenu_entry(brna);
|
||||
rna_def_space_filebrowser(brna);
|
||||
rna_def_space_outliner(brna);
|
||||
rna_def_workflow_shader(brna);
|
||||
rna_def_background_image(brna);
|
||||
rna_def_space_view3d(brna);
|
||||
rna_def_space_buttons(brna);
|
||||
|
@@ -4045,6 +4045,13 @@ static void rna_def_userdef_system(BlenderRNA *brna)
|
||||
/* this isn't essential but nice to check if VBO draws any differently */
|
||||
RNA_def_property_update(prop, NC_WINDOW, "rna_userdef_vbo_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_viewport_new", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "gameflags", USER_VIEWPORT_2);
|
||||
RNA_def_property_ui_text(prop, "Viewport 2",
|
||||
"Use new viewport code in viewport");
|
||||
/* this isn't essential but nice to check if VBO draws any differently */
|
||||
RNA_def_property_update(prop, NC_WINDOW, "rna_userdef_vbo_update");
|
||||
|
||||
prop = RNA_def_property(srna, "anisotropic_filter", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "anisotropic_filter");
|
||||
RNA_def_property_enum_items(prop, anisotropic_items);
|
||||
|
@@ -174,6 +174,7 @@ set(SRC
|
||||
shader/nodes/node_shader_bump.c
|
||||
shader/nodes/node_shader_emission.c
|
||||
shader/nodes/node_shader_fresnel.c
|
||||
shader/nodes/node_shader_script_glsl.c
|
||||
shader/nodes/node_shader_geometry.c
|
||||
shader/nodes/node_shader_holdout.c
|
||||
shader/nodes/node_shader_layer_weight.c
|
||||
|
@@ -35,6 +35,7 @@
|
||||
#include "BKE_node.h"
|
||||
|
||||
extern struct bNodeTreeType *ntreeType_Shader;
|
||||
extern struct bNodeTreeType *ntreeType_Workflow;
|
||||
|
||||
|
||||
/* the type definitions array */
|
||||
@@ -42,6 +43,8 @@ extern struct bNodeTreeType *ntreeType_Shader;
|
||||
|
||||
void register_node_tree_type_sh(void);
|
||||
|
||||
void register_node_tree_type_workflow(void);
|
||||
|
||||
void register_node_type_sh_group(void);
|
||||
|
||||
void register_node_type_sh_output(void);
|
||||
@@ -90,6 +93,7 @@ void register_node_type_sh_tex_coord(void);
|
||||
void register_node_type_sh_particle_info(void);
|
||||
void register_node_type_sh_hair_info(void);
|
||||
void register_node_type_sh_script(void);
|
||||
void register_node_type_sh_script_glsl(void);
|
||||
void register_node_type_sh_normal_map(void);
|
||||
void register_node_type_sh_tangent(void);
|
||||
void register_node_type_sh_vect_transform(void);
|
||||
|
@@ -105,6 +105,7 @@ DefNode( ShaderNode, SH_NODE_BUMP, def_sh_bump, "BU
|
||||
DefNode( ShaderNode, SH_NODE_NORMAL_MAP, def_sh_normal_map, "NORMAL_MAP", NormalMap, "Normal Map", "" )
|
||||
DefNode( ShaderNode, SH_NODE_TANGENT, def_sh_tangent, "TANGENT", Tangent, "Tangent", "" )
|
||||
DefNode( ShaderNode, SH_NODE_SCRIPT, def_sh_script, "SCRIPT", Script, "Script", "" )
|
||||
DefNode( ShaderNode, SH_NODE_SCRIPT_GLSL, def_sh_script_glsl, "SCRIPT_GLSL", ScriptGLSL, "ScriptGLSL", "" )
|
||||
DefNode( ShaderNode, SH_NODE_TEX_IMAGE, def_sh_tex_image, "TEX_IMAGE", TexImage, "Image Texture", "" )
|
||||
DefNode( ShaderNode, SH_NODE_TEX_ENVIRONMENT, def_sh_tex_environment, "TEX_ENVIRONMENT", TexEnvironment, "Environment Texture","" )
|
||||
DefNode( ShaderNode, SH_NODE_TEX_SKY, def_sh_tex_sky, "TEX_SKY", TexSky, "Sky Texture", "" )
|
||||
|
@@ -36,7 +36,9 @@
|
||||
#include "DNA_material_types.h"
|
||||
#include "DNA_node_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
#include "DNA_view3d_types.h"
|
||||
#include "DNA_world_types.h"
|
||||
#include "DNA_linestyle_types.h"
|
||||
|
||||
@@ -50,6 +52,7 @@
|
||||
#include "BKE_linestyle.h"
|
||||
#include "BKE_node.h"
|
||||
#include "BKE_scene.h"
|
||||
#include "BKE_screen.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
||||
@@ -197,6 +200,71 @@ void register_node_tree_type_sh(void)
|
||||
ntreeTypeAdd(tt);
|
||||
}
|
||||
|
||||
static void workflow_get_from_context(const bContext *C, bNodeTreeType *UNUSED(treetype), bNodeTree **r_ntree, ID **r_id, ID **r_from)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
ScrArea *sa = NULL;
|
||||
ARegion *ar = NULL;
|
||||
View3D *v3d = NULL;
|
||||
bScreen *screen = CTX_wm_screen(C);
|
||||
|
||||
*r_from = NULL;
|
||||
|
||||
if (screen) {
|
||||
sa = BKE_screen_find_big_area(screen, SPACE_VIEW3D, 0);
|
||||
ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
|
||||
if (ar) {
|
||||
v3d = sa->spacedata.first;
|
||||
}
|
||||
}
|
||||
|
||||
if (v3d && v3d->activeworkflow) {
|
||||
*r_id = &v3d->activeworkflow->id;
|
||||
*r_ntree = v3d->activeworkflow->nodetree;
|
||||
}
|
||||
else if (bmain->gpuworkflows.first) {
|
||||
GPUWorkflowShader *wfshader = bmain->gpuworkflows.first;
|
||||
*r_id = &wfshader->id;
|
||||
*r_ntree = wfshader->nodetree;
|
||||
}
|
||||
else {
|
||||
*r_id = NULL;
|
||||
*r_ntree = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int workflow_tree_poll(const bContext *UNUSED(C), bNodeTreeType *UNUSED(treetype))
|
||||
{
|
||||
return (U.gameflags & USER_VIEWPORT_2) != 0;
|
||||
}
|
||||
|
||||
bNodeTreeType *ntreeType_Workflow;
|
||||
|
||||
void register_node_tree_type_workflow(void)
|
||||
{
|
||||
bNodeTreeType *tt = ntreeType_Workflow = MEM_callocN(sizeof(bNodeTreeType), "shader node tree type");
|
||||
|
||||
tt->type = NTREE_WORKFLOW;
|
||||
strcpy(tt->idname, "WorkflowNodeTree");
|
||||
strcpy(tt->ui_name, "Workflow");
|
||||
tt->ui_icon = 0; /* defined in drawnode.c */
|
||||
strcpy(tt->ui_description, "Workflow nodes");
|
||||
|
||||
tt->foreach_nodeclass = foreach_nodeclass;
|
||||
tt->localize = localize;
|
||||
tt->local_sync = local_sync;
|
||||
tt->local_merge = local_merge;
|
||||
tt->update = update;
|
||||
tt->poll = workflow_tree_poll;
|
||||
tt->get_from_context = workflow_get_from_context;
|
||||
|
||||
tt->ext.srna = &RNA_WorkflowNodeTree;
|
||||
|
||||
ntreeTypeAdd(tt);
|
||||
}
|
||||
|
||||
|
||||
/* GPU material from shader nodes */
|
||||
|
||||
void ntreeGPUMaterialNodes(bNodeTree *ntree, GPUMaterial *mat, short compatibility)
|
||||
|
76
source/blender/nodes/shader/nodes/node_shader_script_glsl.c
Normal file
76
source/blender/nodes/shader/nodes/node_shader_script_glsl.c
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* 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, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2005 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/nodes/shader/nodes/node_shader_script_glsl.c
|
||||
* \ingroup shdnodes
|
||||
*/
|
||||
|
||||
#include "node_shader_util.h"
|
||||
|
||||
/* **************** Script ******************** */
|
||||
|
||||
static void init(bNodeTree *UNUSED(ntree), bNode *node)
|
||||
{
|
||||
NodeShaderScriptGLSL *nss = MEM_callocN(sizeof(NodeShaderScriptGLSL), "GLSL shader script node");
|
||||
node->storage = nss;
|
||||
}
|
||||
|
||||
static void node_free_glsl(bNode *node)
|
||||
{
|
||||
NodeShaderScriptGLSL *nss = node->storage;
|
||||
|
||||
if (nss) {
|
||||
// if (nss->bytecode) {
|
||||
// MEM_freeN(nss->bytecode);
|
||||
// }
|
||||
|
||||
MEM_freeN(nss);
|
||||
}
|
||||
}
|
||||
|
||||
static void node_copy_glsl(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, bNode *src_node)
|
||||
{
|
||||
NodeShaderScriptGLSL *src_nss = src_node->storage;
|
||||
NodeShaderScriptGLSL *dest_nss = MEM_dupallocN(src_nss);
|
||||
|
||||
// if (src_nss->bytecode)
|
||||
// dest_nss->bytecode = MEM_dupallocN(src_nss->bytecode);
|
||||
|
||||
dest_node->storage = dest_nss;
|
||||
}
|
||||
|
||||
void register_node_type_sh_script_glsl(void)
|
||||
{
|
||||
static bNodeType ntype;
|
||||
|
||||
sh_node_type_base(&ntype, SH_NODE_SCRIPT_GLSL, "ScriptGLSL", NODE_CLASS_SCRIPT, 0);
|
||||
node_type_compatibility(&ntype, NODE_NEW_SHADING);
|
||||
node_type_init(&ntype, init);
|
||||
node_type_storage(&ntype, "NodeShaderScriptGLSL", node_free_glsl, node_copy_glsl);
|
||||
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
Reference in New Issue
Block a user