World background working on cycle nodes.

This is added in the spirit of the general cycles GLSL system
which is pretty much WIP still.

This will only work on cycles at the moment but generating for blender
internal is possible too of course though it will be done in a separate
commit.

This hasn't been tested with all and every node in cycles, but
environment and regular textures with texture coordinates work.

There is some difference between the way cycles treats some coordinates,
which is in world space and the way GLSL treats them, which is in view
space.
We might want to explore and improve this further in the future.

...also </drumroll>
This commit is contained in:
2014-11-24 17:18:56 +01:00
parent 8bc84e10f5
commit 8fa55d95e4
23 changed files with 324 additions and 94 deletions

View File

@@ -757,6 +757,7 @@ if B.targets != ['cudakernels']:
data_to_c_simple("source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl")
data_to_c_simple("source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_vert.glsl")
data_to_c_simple("source/blender/gpu/shaders/gpu_shader_vertex.glsl")
data_to_c_simple("source/blender/gpu/shaders/gpu_shader_vertex_world.glsl")
data_to_c_simple("source/blender/gpu/shaders/gpu_shader_vsm_store_frag.glsl")
data_to_c_simple("source/blender/gpu/shaders/gpu_shader_vsm_store_vert.glsl")
data_to_c_simple("intern/opencolorio/gpu_shader_display_transform.glsl")

View File

@@ -116,7 +116,7 @@ void BKE_material_free_ex(Material *ma, bool do_id_user)
MEM_freeN(ma->texpaintslot);
if (ma->gpumaterial.first)
GPU_material_free(ma);
GPU_material_free(&ma->gpumaterial);
}
void init_material(Material *ma)
@@ -1724,7 +1724,7 @@ void paste_matcopybuf(Material *ma)
MEM_freeN(ma->nodetree);
}
GPU_material_free(ma);
GPU_material_free(&ma->gpumaterial);
id = (ma->id);
memcpy(ma, &matcopybuf, sizeof(Material));

View File

@@ -49,6 +49,8 @@
#include "BKE_node.h"
#include "BKE_world.h"
#include "GPU_material.h"
void BKE_world_free_ex(World *wrld, bool do_id_user)
{
MTex *mtex;
@@ -69,6 +71,9 @@ void BKE_world_free_ex(World *wrld, bool do_id_user)
MEM_freeN(wrld->nodetree);
}
if (wrld->gpumaterial.first)
GPU_material_free(&wrld->gpumaterial);
BKE_icon_delete((struct ID *)wrld);
wrld->id.icon_id = 0;
}

View File

@@ -3260,6 +3260,7 @@ static void direct_link_world(FileData *fd, World *wrld)
}
wrld->preview = direct_link_preview_image(fd, wrld->preview);
BLI_listbase_clear(&wrld->gpumaterial);
}

View File

@@ -281,7 +281,7 @@ static void material_changed(Main *bmain, Material *ma)
/* glsl */
if (ma->gpumaterial.first)
GPU_material_free(ma);
GPU_material_free(&ma->gpumaterial);
/* find node materials using this */
for (parent = bmain->mat.first; parent; parent = parent->id.next) {
@@ -295,7 +295,7 @@ static void material_changed(Main *bmain, Material *ma)
BKE_icon_changed(BKE_icon_getid(&parent->id));
if (parent->gpumaterial.first)
GPU_material_free(parent);
GPU_material_free(&parent->gpumaterial);
}
/* find if we have a scene with textured display */
@@ -341,10 +341,10 @@ static void lamp_changed(Main *bmain, Lamp *la)
for (ma = bmain->mat.first; ma; ma = ma->id.next)
if (ma->gpumaterial.first)
GPU_material_free(ma);
GPU_material_free(&ma->gpumaterial);
if (defmaterial.gpumaterial.first)
GPU_material_free(&defmaterial);
GPU_material_free(&defmaterial.gpumaterial);
}
static int material_uses_texture(Material *ma, Tex *tex)
@@ -382,7 +382,7 @@ static void texture_changed(Main *bmain, Tex *tex)
BKE_icon_changed(BKE_icon_getid(&ma->id));
if (ma->gpumaterial.first)
GPU_material_free(ma);
GPU_material_free(&ma->gpumaterial);
}
/* find lamps */
@@ -411,6 +411,9 @@ static void texture_changed(Main *bmain, Tex *tex)
}
BKE_icon_changed(BKE_icon_getid(&wo->id));
if (wo->gpumaterial.first)
GPU_material_free(&wo->gpumaterial);
}
/* find compositing nodes */
@@ -456,14 +459,17 @@ static void world_changed(Main *bmain, World *wo)
/* icons */
BKE_icon_changed(BKE_icon_getid(&wo->id));
/* glsl */
for (ma = bmain->mat.first; ma; ma = ma->id.next)
if (ma->gpumaterial.first)
GPU_material_free(ma);
GPU_material_free(&ma->gpumaterial);
if (defmaterial.gpumaterial.first)
GPU_material_free(&defmaterial);
GPU_material_free(&defmaterial.gpumaterial);
if (wo->gpumaterial.first)
GPU_material_free(&wo->gpumaterial);
}
static void image_changed(Main *bmain, Image *ima)
@@ -483,6 +489,7 @@ static void scene_changed(Main *bmain, Scene *scene)
{
Object *ob;
Material *ma;
World *wo;
/* glsl */
for (ob = bmain->object.first; ob; ob = ob->id.next) {
@@ -498,10 +505,14 @@ static void scene_changed(Main *bmain, Scene *scene)
for (ma = bmain->mat.first; ma; ma = ma->id.next)
if (ma->gpumaterial.first)
GPU_material_free(ma);
GPU_material_free(&ma->gpumaterial);
for (wo = bmain->world.first; wo; wo = wo->id.next)
if (wo->gpumaterial.first)
GPU_material_free(&wo->gpumaterial);
if (defmaterial.gpumaterial.first)
GPU_material_free(&defmaterial);
GPU_material_free(&defmaterial.gpumaterial);
}
void ED_render_id_flush_update(Main *bmain, ID *id)

View File

@@ -342,14 +342,22 @@ void snode_dag_update(bContext *C, SpaceNode *snode)
void snode_notify(bContext *C, SpaceNode *snode)
{
ID *id = snode->id;
WM_event_add_notifier(C, NC_NODE | NA_EDITED, NULL);
if (ED_node_is_shader(snode))
WM_event_add_notifier(C, NC_MATERIAL | ND_NODES, snode->id);
if (ED_node_is_shader(snode)) {
if (GS(id->name) == ID_MA)
WM_main_add_notifier(NC_MATERIAL | ND_SHADING, id);
else if (GS(id->name) == ID_LA)
WM_main_add_notifier(NC_LAMP | ND_LIGHTING, id);
else if (GS(id->name) == ID_WO)
WM_main_add_notifier(NC_WORLD | ND_WORLD, id);
}
else if (ED_node_is_compositor(snode))
WM_event_add_notifier(C, NC_SCENE | ND_NODES, snode->id);
WM_event_add_notifier(C, NC_SCENE | ND_NODES, id);
else if (ED_node_is_texture(snode))
WM_event_add_notifier(C, NC_TEXTURE | ND_NODES, snode->id);
WM_event_add_notifier(C, NC_TEXTURE | ND_NODES, id);
}
void ED_node_set_tree_type(SpaceNode *snode, bNodeTreeType *typeinfo)
@@ -662,11 +670,16 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
/* if active texture changed, free glsl materials */
if ((node->flag & NODE_ACTIVE_TEXTURE) && !was_active_texture) {
Material *ma;
World *wo;
for (ma = bmain->mat.first; ma; ma = ma->id.next)
if (ma->nodetree && ma->use_nodes && ntreeHasTree(ma->nodetree, ntree))
GPU_material_free(ma);
GPU_material_free(&ma->gpumaterial);
for (wo = bmain->world.first; wo; wo = wo->id.next)
if (wo->nodetree && wo->use_nodes && ntreeHasTree(wo->nodetree, ntree))
GPU_material_free(&wo->gpumaterial);
WM_main_add_notifier(NC_IMAGE, NULL);
}

View File

@@ -414,7 +414,7 @@ static void view3d_free(SpaceLink *sl)
/* matcap material, its preview rect gets freed via icons */
if (vd->defmaterial) {
if (vd->defmaterial->gpumaterial.first)
GPU_material_free(vd->defmaterial);
GPU_material_free(&vd->defmaterial->gpumaterial);
BKE_previewimg_free(&vd->defmaterial->preview);
MEM_freeN(vd->defmaterial);
}
@@ -1168,6 +1168,7 @@ static void space_view3d_listener(bScreen *UNUSED(sc), ScrArea *sa, struct wmNot
case NC_WORLD:
switch (wmn->data) {
case ND_WORLD_DRAW:
case ND_WORLD:
if (v3d->flag3 & V3D_SHOW_WORLD)
ED_area_tag_redraw_regiontype(sa, RGN_TYPE_WINDOW);
break;

View File

@@ -2807,10 +2807,34 @@ void ED_view3d_draw_offscreen_init(Scene *scene, View3D *v3d)
static void view3d_main_area_clear(Scene *scene, View3D *v3d, ARegion *ar, bool force)
{
/* clear background */
if (scene->world && ((v3d->flag3 & V3D_SHOW_WORLD) || force)) { /* clear with solid color */
if (scene->world && ((v3d->flag3 & V3D_SHOW_WORLD) || force)) {
float alpha = (force) ? 1.0f : 0.0;
bool glsl = GPU_glsl_support() && BKE_scene_use_new_shading_nodes(scene) && scene->world->nodetree && scene->world->use_nodes;
if (scene->world->skytype & WO_SKYBLEND) { /* blend sky */
if (glsl) {
RegionView3D *rv3d = ar->regiondata;
GPUMaterial *gpumat = GPU_material_world(scene, scene->world);
/* calculate full shader for background */
GPU_material_bind(gpumat, 1, 1, 1.0, true, rv3d->viewmat, rv3d->viewinv, (v3d->scenelock != 0));
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_ALWAYS);
glShadeModel(GL_SMOOTH);
glBegin(GL_QUADS);
glVertex3f(-1.0, -1.0, 1.0);
glVertex3f(1.0, -1.0, 1.0);
glVertex3f(1.0, 1.0, 1.0);
glVertex3f(-1.0, 1.0, 1.0);
glEnd();
glShadeModel(GL_FLAT);
GPU_material_unbind(gpumat);
glDepthFunc(GL_LEQUAL);
glDisable(GL_DEPTH_TEST);
}
else if (scene->world->skytype & WO_SKYBLEND) { /* blend sky */
int x, y;
float col_hor[3];
float col_zen[3];
@@ -3009,7 +3033,9 @@ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, int winx,
* warning! can be slow so only free animated images - campbell */
GPU_free_images_anim();
}
/* setup view matrices */
view3d_main_area_setup_view(scene, v3d, ar, viewmat, winmat);
/* clear opengl buffers */
if (do_sky) {
view3d_main_area_clear(scene, v3d, ar, true);
@@ -3019,11 +3045,6 @@ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, int winx,
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
/* setup view matrices */
view3d_main_area_setup_view(scene, v3d, ar, viewmat, winmat);
/* main drawing call */
view3d_draw_objects(NULL, scene, v3d, ar, NULL, do_bgpic, true);

View File

@@ -73,6 +73,7 @@ data_to_c_simple(shaders/gpu_shader_sep_gaussian_blur_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_simple_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_simple_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_vertex.glsl SRC)
data_to_c_simple(shaders/gpu_shader_vertex_world.glsl SRC)
data_to_c_simple(shaders/gpu_shader_vsm_store_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_vsm_store_vert.glsl SRC)

View File

@@ -58,6 +58,7 @@ struct GPUMaterial;
struct GPUTexture;
struct GPULamp;
struct PreviewImage;
struct World;
typedef struct GPUNode GPUNode;
typedef struct GPUNodeLink GPUNodeLink;
@@ -95,6 +96,12 @@ typedef enum GPUOpenGLBuiltin {
GPU_COLOR = 2,
} GPUOpenGLBuiltin;
typedef enum GPUMatType {
GPU_MATERIAL_TYPE_MESH = 1,
GPU_MATERIAL_TYPE_WORLD = 2,
} GPUMatType;
typedef enum GPUBlendMode {
GPU_BLEND_SOLID = 0,
GPU_BLEND_ADD = 1,
@@ -131,10 +138,11 @@ void GPU_material_enable_alpha(GPUMaterial *material);
GPUBlendMode GPU_material_alpha_blend(GPUMaterial *material, float obcol[4]);
/* High level functions to create and use GPU materials */
GPUMaterial *GPU_material_world(struct Scene *scene, struct World *wo);
GPUMaterial *GPU_material_from_blender(struct Scene *scene, struct Material *ma);
GPUMaterial *GPU_material_matcap(struct Scene *scene, struct Material *ma);
void GPU_material_free(struct Material *ma);
void GPU_material_free(struct ListBase *gpumaterial);
void GPU_materials_free(void);
@@ -144,6 +152,7 @@ void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[4][4], float
void GPU_material_unbind(GPUMaterial *material);
int GPU_material_bound(GPUMaterial *material);
struct Scene *GPU_material_scene(GPUMaterial *material);
GPUMatType GPU_Material_get_type(GPUMaterial *material);
void GPU_material_vertex_attributes(GPUMaterial *material,
struct GPUVertexAttribs *attrib);

View File

@@ -69,6 +69,7 @@ sources.extend((
os.path.join(env['DATA_SOURCES'], "gpu_shader_sep_gaussian_blur_frag.glsl.c"),
os.path.join(env['DATA_SOURCES'], "gpu_shader_sep_gaussian_blur_vert.glsl.c"),
os.path.join(env['DATA_SOURCES'], "gpu_shader_vertex.glsl.c"),
os.path.join(env['DATA_SOURCES'], "gpu_shader_vertex_world.glsl.c"),
os.path.join(env['DATA_SOURCES'], "gpu_shader_vsm_store_frag.glsl.c"),
os.path.join(env['DATA_SOURCES'], "gpu_shader_vsm_store_vert.glsl.c"),
))

View File

@@ -58,6 +58,7 @@
extern char datatoc_gpu_shader_material_glsl[];
extern char datatoc_gpu_shader_vertex_glsl[];
extern char datatoc_gpu_shader_vertex_world_glsl[];
static char *glsl_material_library = NULL;
@@ -252,7 +253,7 @@ void gpu_codegen_exit(void)
extern Material defmaterial; // render module abuse...
if (defmaterial.gpumaterial.first)
GPU_material_free(&defmaterial);
GPU_material_free(&defmaterial.gpumaterial);
if (FUNCTION_HASH) {
BLI_ghash_free(FUNCTION_HASH, NULL, MEM_freeN);
@@ -624,8 +625,7 @@ static char *code_generate_fragment(ListBase *nodes, GPUOutput *output, const ch
if (builtins & GPU_VIEW_NORMAL)
BLI_dynstr_append(ds, "\tvec3 facingnormal = (gl_FrontFacing)? varnormal: -varnormal;\n");
codegen_declare_tmps(ds, nodes);
codegen_call_functions(ds, nodes, output);
@@ -640,12 +640,13 @@ static char *code_generate_fragment(ListBase *nodes, GPUOutput *output, const ch
return code;
}
static char *code_generate_vertex(ListBase *nodes)
static char *code_generate_vertex(ListBase *nodes, int type)
{
DynStr *ds = BLI_dynstr_new();
GPUNode *node;
GPUInput *input;
char *code;
char *vertcode;
for (node=nodes->first; node; node=node->next) {
for (input=node->inputs.first; input; input=input->next) {
@@ -659,8 +660,21 @@ static char *code_generate_vertex(ListBase *nodes)
}
BLI_dynstr_append(ds, "\n");
BLI_dynstr_append(ds, datatoc_gpu_shader_vertex_glsl);
switch (type) {
case GPU_MATERIAL_TYPE_MESH:
vertcode = datatoc_gpu_shader_vertex_glsl;
break;
case GPU_MATERIAL_TYPE_WORLD:
vertcode = datatoc_gpu_shader_vertex_world_glsl;
break;
default:
fprintf(stderr, "invalid material type, set one after GPU_material_construct_begin\n");
break;
}
BLI_dynstr_append(ds, vertcode);
for (node=nodes->first; node; node=node->next)
for (input=node->inputs.first; input; input=input->next)
if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
@@ -1386,7 +1400,7 @@ static void gpu_nodes_prune(ListBase *nodes, GPUNodeLink *outlink)
}
}
GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUVertexAttribs *attribs, int *builtins, const char *name)
GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUVertexAttribs *attribs, int *builtins, int type, const char *name)
{
GPUShader *shader;
GPUPass *pass;
@@ -1405,7 +1419,7 @@ GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUVertexAttri
/* generate code and compile with opengl */
fragmentcode = code_generate_fragment(nodes, outlink->output, name);
vertexcode = code_generate_vertex(nodes);
vertexcode = code_generate_vertex(nodes, type);
shader = GPU_shader_create(vertexcode, fragmentcode, glsl_material_library, NULL);
/* failed? */

View File

@@ -175,7 +175,7 @@ struct GPUPass {
typedef struct GPUPass GPUPass;
GPUPass *GPU_generate_pass(ListBase *nodes, struct GPUNodeLink *outlink,
struct GPUVertexAttribs *attribs, int *builtin, const char *name);
struct GPUVertexAttribs *attribs, int *builtin, int type, const char *name);
struct GPUShader *GPU_pass_shader(GPUPass *pass);

View File

@@ -76,10 +76,15 @@ typedef enum DynMatProperty {
DYN_LAMP_PERSMAT = 8,
} DynMatProperty;
struct GPUMaterial {
Scene *scene;
Material *ma;
/* material for mesh surface, worlds or something else.
* some code generation is done differently depending on the use case */
int type;
/* for creating the material */
ListBase nodes;
GPUNodeLink *outlink;
@@ -194,7 +199,7 @@ static void gpu_material_set_attrib_id(GPUMaterial *material)
attribs->totlayer = b;
}
static int GPU_material_construct_end(GPUMaterial *material)
static int GPU_material_construct_end(GPUMaterial *material, const char *passname)
{
if (material->outlink) {
GPUNodeLink *outlink;
@@ -202,7 +207,7 @@ static int GPU_material_construct_end(GPUMaterial *material)
outlink = material->outlink;
material->pass = GPU_generate_pass(&material->nodes, outlink,
&material->attribs, &material->builtins, material->ma->id.name);
&material->attribs, &material->builtins, material->type, passname);
if (!material->pass)
return 0;
@@ -229,12 +234,12 @@ static int GPU_material_construct_end(GPUMaterial *material)
return 0;
}
void GPU_material_free(Material *ma)
void GPU_material_free(ListBase *gpumaterial)
{
LinkData *link;
LinkData *nlink, *mlink, *next;
for (link=ma->gpumaterial.first; link; link=link->next) {
for (link=gpumaterial->first; link; link=link->next) {
GPUMaterial *material = link->data;
if (material->pass)
@@ -243,19 +248,23 @@ void GPU_material_free(Material *ma)
for (nlink=material->lamps.first; nlink; nlink=nlink->next) {
GPULamp *lamp = nlink->data;
for (mlink=lamp->materials.first; mlink; mlink=next) {
next = mlink->next;
if (mlink->data == ma)
BLI_freelinkN(&lamp->materials, mlink);
if (material->ma) {
Material *ma = material->ma;
for (mlink=lamp->materials.first; mlink; mlink=next) {
next = mlink->next;
if (mlink->data == ma)
BLI_freelinkN(&lamp->materials, mlink);
}
}
}
BLI_freelistN(&material->lamps);
MEM_freeN(material);
}
BLI_freelistN(&ma->gpumaterial);
BLI_freelistN(gpumaterial);
}
bool GPU_lamp_override_visible(GPULamp *lamp, SceneRenderLayer *srl, Material *ma)
@@ -280,42 +289,44 @@ void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double tim
viewlay &= srl->lay;
/* handle layer lamps */
for (nlink=material->lamps.first; nlink; nlink=nlink->next) {
lamp= nlink->data;
if (!lamp->hide && (lamp->lay & viewlay) && (!(lamp->mode & LA_LAYER) || (lamp->lay & oblay))
&& GPU_lamp_override_visible(lamp, srl, material->ma)) {
lamp->dynenergy = lamp->energy;
copy_v3_v3(lamp->dyncol, lamp->col);
}
else {
lamp->dynenergy = 0.0f;
lamp->dyncol[0]= lamp->dyncol[1]= lamp->dyncol[2] = 0.0f;
}
if (material->dynproperty & DYN_LAMP_VEC) {
copy_v3_v3(lamp->dynvec, lamp->vec);
normalize_v3(lamp->dynvec);
negate_v3(lamp->dynvec);
mul_mat3_m4_v3(viewmat, lamp->dynvec);
}
if (material->dynproperty & DYN_LAMP_CO) {
copy_v3_v3(lamp->dynco, lamp->co);
mul_m4_v3(viewmat, lamp->dynco);
}
if (material->dynproperty & DYN_LAMP_IMAT) {
mul_m4_m4m4(lamp->dynimat, lamp->imat, viewinv);
}
if (material->dynproperty & DYN_LAMP_PERSMAT) {
if (!GPU_lamp_has_shadow_buffer(lamp)) /* The lamp matrices are already updated if we're using shadow buffers */
GPU_lamp_update_buffer_mats(lamp);
mul_m4_m4m4(lamp->dynpersmat, lamp->persmat, viewinv);
if (material->type == GPU_MATERIAL_TYPE_MESH) {
for (nlink=material->lamps.first; nlink; nlink=nlink->next) {
lamp= nlink->data;
if (!lamp->hide && (lamp->lay & viewlay) && (!(lamp->mode & LA_LAYER) || (lamp->lay & oblay))
&& GPU_lamp_override_visible(lamp, srl, material->ma)) {
lamp->dynenergy = lamp->energy;
copy_v3_v3(lamp->dyncol, lamp->col);
}
else {
lamp->dynenergy = 0.0f;
lamp->dyncol[0]= lamp->dyncol[1]= lamp->dyncol[2] = 0.0f;
}
if (material->dynproperty & DYN_LAMP_VEC) {
copy_v3_v3(lamp->dynvec, lamp->vec);
normalize_v3(lamp->dynvec);
negate_v3(lamp->dynvec);
mul_mat3_m4_v3(viewmat, lamp->dynvec);
}
if (material->dynproperty & DYN_LAMP_CO) {
copy_v3_v3(lamp->dynco, lamp->co);
mul_m4_v3(viewmat, lamp->dynco);
}
if (material->dynproperty & DYN_LAMP_IMAT) {
mul_m4_m4m4(lamp->dynimat, lamp->imat, viewinv);
}
if (material->dynproperty & DYN_LAMP_PERSMAT) {
if (!GPU_lamp_has_shadow_buffer(lamp)) /* The lamp matrices are already updated if we're using shadow buffers */
GPU_lamp_update_buffer_mats(lamp);
mul_m4_m4m4(lamp->dynpersmat, lamp->persmat, viewinv);
}
}
}
/* note material must be bound before setting uniforms */
GPU_pass_bind(material->pass, time, mipmap);
@@ -376,6 +387,12 @@ Scene *GPU_material_scene(GPUMaterial *material)
return material->scene;
}
GPUMatType GPU_Material_get_type(GPUMaterial *material)
{
return material->type;
}
void GPU_material_vertex_attributes(GPUMaterial *material, GPUVertexAttribs *attribs)
{
*attribs = material->attribs;
@@ -1589,6 +1606,7 @@ GPUMaterial *GPU_material_matcap(Scene *scene, Material *ma)
/* allocate material */
mat = GPU_material_construct_begin(ma);
mat->scene = scene;
mat->type = GPU_MATERIAL_TYPE_MESH;
if (ma->preview && ma->preview->rect[0]) {
outlink = gpu_material_preview_matcap(mat, ma);
@@ -1599,7 +1617,7 @@ GPUMaterial *GPU_material_matcap(Scene *scene, Material *ma)
GPU_material_output_link(mat, outlink);
GPU_material_construct_end(mat);
GPU_material_construct_end(mat, "matcap_pass");
/* note that even if building the shader fails in some way, we still keep
* it to avoid trying to compile again and again, and simple do not use
@@ -1612,6 +1630,45 @@ GPUMaterial *GPU_material_matcap(Scene *scene, Material *ma)
return mat;
}
GPUMaterial *GPU_material_world(struct Scene *scene, struct World *wo)
{
LinkData *link;
GPUMaterial *mat;
for (link=wo->gpumaterial.first; link; link=link->next)
if (((GPUMaterial*)link->data)->scene == scene)
return link->data;
/* allocate material */
mat = GPU_material_construct_begin(NULL);
mat->scene = scene;
mat->type = GPU_MATERIAL_TYPE_WORLD;
/* create nodes */
if (BKE_scene_use_new_shading_nodes(scene) && wo->nodetree && wo->use_nodes)
ntreeGPUMaterialNodes(wo->nodetree, mat, NODE_NEW_SHADING);
else {
/* old fixed function world */
}
if (GPU_material_do_color_management(mat))
if (mat->outlink)
GPU_link(mat, "linearrgb_to_srgb", mat->outlink, &mat->outlink);
GPU_material_construct_end(mat, wo->id.name);
/* note that even if building the shader fails in some way, we still keep
* it to avoid trying to compile again and again, and simple do not use
* the actual shader on drawing */
link = MEM_callocN(sizeof(LinkData), "GPUMaterialLink");
link->data = mat;
BLI_addtail(&wo->gpumaterial, link);
return mat;
}
GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma)
{
GPUMaterial *mat;
@@ -1625,6 +1682,7 @@ GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma)
/* allocate material */
mat = GPU_material_construct_begin(ma);
mat->scene = scene;
mat->type = GPU_MATERIAL_TYPE_MESH;
/* render pipeline option */
if (ma->mode & MA_TRANSP)
@@ -1654,7 +1712,7 @@ GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma)
if (mat->outlink)
GPU_link(mat, "linearrgb_to_srgb", mat->outlink, &mat->outlink);
GPU_material_construct_end(mat);
GPU_material_construct_end(mat, ma->id.name);
/* note that even if building the shader fails in some way, we still keep
* it to avoid trying to compile again and again, and simple do not use
@@ -1671,12 +1729,16 @@ void GPU_materials_free(void)
{
Object *ob;
Material *ma;
World *wo;
extern Material defmaterial;
for (ma=G.main->mat.first; ma; ma=ma->id.next)
GPU_material_free(ma);
GPU_material_free(&ma->gpumaterial);
GPU_material_free(&defmaterial);
for (wo=G.main->world.first; wo; wo=wo->id.next)
GPU_material_free(&ma->gpumaterial);
GPU_material_free(&defmaterial.gpumaterial);
for (ob=G.main->object.first; ob; ob=ob->id.next)
GPU_lamp_free(ob);
@@ -1945,7 +2007,7 @@ void GPU_lamp_free(Object *ob)
BLI_freelinkN(&lamp->materials, nlink);
if (ma->gpumaterial.first)
GPU_material_free(ma);
GPU_material_free(&ma->gpumaterial);
}
gpu_lamp_shadow_free(lamp);

View File

@@ -2256,6 +2256,22 @@ void node_emission(vec4 color, float strength, vec3 N, out vec4 result)
result = color*strength;
}
/* background */
void background_transform_to_world(vec3 viewvec, out vec3 worldvec)
{
vec4 v = (gl_ProjectionMatrix[3][3] == 0.0) ? vec4(viewvec, 1.0) : vec4(0.0, 0.0, 1.0, 1.0);
vec4 co_homogenous = (gl_ProjectionMatrixInverse * v);
vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0);
worldvec = (gl_ModelViewMatrixInverse * co).xyz;
}
void node_background(vec4 color, float strength, vec3 N, out vec4 result)
{
result = color*strength;
}
/* closures */
void node_mix_shader(float fac, vec4 shader1, vec4 shader2, out vec4 shader)
@@ -2364,6 +2380,30 @@ void node_tex_coord(vec3 I, vec3 N, mat4 viewinvmat, mat4 obinvmat,
reflection = (viewinvmat*vec4(view_reflection, 0.0)).xyz;
}
void node_tex_coord_background(vec3 I, vec3 N, mat4 viewinvmat, mat4 obinvmat,
vec3 attr_orco, vec3 attr_uv,
out vec3 generated, out vec3 normal, out vec3 uv, out vec3 object,
out vec3 camera, out vec3 window, out vec3 reflection)
{
vec4 v = (gl_ProjectionMatrix[3][3] == 0.0) ? vec4(I, 1.0) : vec4(0.0, 0.0, 1.0, 1.0);
vec4 co_homogenous = (gl_ProjectionMatrixInverse * v);
vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0);
co = normalize(co);
vec3 coords = (gl_ModelViewMatrixInverse * co).xyz;
generated = coords;
normal = -coords;
uv = attr_uv;
object = coords;
camera = co.xyz;
window = mtex_2d_mapping(I);
reflection = -coords;
}
/* textures */
void node_tex_gradient(vec3 co, out vec4 color, out float fac)
@@ -2525,6 +2565,11 @@ void node_output_material(vec4 surface, vec4 volume, float displacement, out vec
result = surface;
}
void node_output_world(vec4 surface, vec4 volume, out vec4 result)
{
result = surface;
}
/* ********************** matcap style render ******************** */
void material_preview_matcap(vec4 color, sampler2D ima, vec4 N, vec4 mask, out vec4 result)

View File

@@ -0,0 +1,13 @@
varying vec3 varposition;
varying vec3 varnormal;
void main()
{
/* position does not need to be transformed, we already have it */
gl_Position = gl_Vertex;
varposition = gl_Vertex.xyz;
varnormal = normalize(-varposition);

View File

@@ -128,6 +128,7 @@ typedef struct World {
/* nodes */
struct bNodeTree *nodetree;
ListBase gpumaterial; /* runtime */
} World;
/* **************** WORLD ********************* */

View File

@@ -485,7 +485,7 @@ static void rna_SpaceView3D_matcap_update(Main *UNUSED(bmain), Scene *UNUSED(sce
BKE_previewimg_free(&ma->preview);
if (ma->gpumaterial.first)
GPU_material_free(ma);
GPU_material_free(&ma->gpumaterial);
WM_main_add_notifier(NC_MATERIAL | ND_SHADING_DRAW, ma);
}

View File

@@ -89,7 +89,7 @@ static void rna_World_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerR
World *wo = ptr->id.data;
DAG_id_tag_update(&wo->id, 0);
WM_main_add_notifier(NC_WORLD, wo);
WM_main_add_notifier(NC_WORLD | ND_WORLD, wo);
}
static void rna_World_draw_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)

View File

@@ -40,6 +40,11 @@ static bNodeSocketTemplate sh_node_background_out[] = {
{ -1, 0, "" }
};
static int node_shader_gpu_background(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "node_background", in, out, GPU_builtin(GPU_VIEW_NORMAL));
}
/* node type definition */
void register_node_type_sh_background(void)
{
@@ -50,6 +55,7 @@ void register_node_type_sh_background(void)
node_type_socket_templates(&ntype, sh_node_background_in, sh_node_background_out);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
node_type_gpu(&ntype, node_shader_gpu_background);
nodeRegisterType(&ntype);
}

View File

@@ -35,6 +35,16 @@ static bNodeSocketTemplate sh_node_output_world_in[] = {
{ -1, 0, "" }
};
static int node_shader_gpu_output_world(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
GPUNodeLink *outlink;
GPU_stack_link(mat, "node_output_world", in, out, &outlink);
GPU_material_output_link(mat, outlink);
return 1;
}
/* node type definition */
void register_node_type_sh_output_world(void)
{
@@ -45,7 +55,8 @@ void register_node_type_sh_output_world(void)
node_type_socket_templates(&ntype, sh_node_output_world_in, NULL);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
node_type_gpu(&ntype, node_shader_gpu_output_world);
/* Do not allow muting output node. */
node_type_internal_links(&ntype, NULL);

View File

@@ -46,10 +46,18 @@ static int node_shader_gpu_tex_coord(GPUMaterial *mat, bNode *UNUSED(node), bNod
{
GPUNodeLink *orco = GPU_attribute(CD_ORCO, "");
GPUNodeLink *mtface = GPU_attribute(CD_MTFACE, "");
return GPU_stack_link(mat, "node_tex_coord", in, out,
GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_VIEW_NORMAL),
GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_INVERSE_OBJECT_MATRIX), orco, mtface);
GPUMatType type = GPU_Material_get_type(mat);
if (type == GPU_MATERIAL_TYPE_MESH) {
return GPU_stack_link(mat, "node_tex_coord", in, out,
GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_VIEW_NORMAL),
GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_INVERSE_OBJECT_MATRIX), orco, mtface);
}
else {
return GPU_stack_link(mat, "node_tex_coord_background", in, out,
GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_VIEW_NORMAL),
GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_INVERSE_OBJECT_MATRIX), orco, mtface);
}
}
/* node type definition */

View File

@@ -67,9 +67,15 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat, bNode *node, bNodeE
if (!ima)
return GPU_stack_link(mat, "node_tex_environment_empty", in, out);
if (!in[0].link)
in[0].link = GPU_builtin(GPU_VIEW_POSITION);
if (!in[0].link) {
GPUMatType type = GPU_Material_get_type(mat);
if (type == GPU_MATERIAL_TYPE_MESH)
in[0].link = GPU_builtin(GPU_VIEW_POSITION);
else
GPU_link(mat, "background_transform_to_world", GPU_builtin(GPU_VIEW_POSITION), &in[0].link);
}
node_shader_gpu_tex_mapping(mat, node, in, out);
if (tex->projection == SHD_PROJ_EQUIRECTANGULAR)