forked from bartvdbraak/blender
Object Info node support for GLSL mode and the internal render
Object Info node can be useful to give some variation to a single material assigned to multiple instances. This patch adds support for Viewport and BI. {F499530} Example: {F499528} Reviewers: merwin, brecht, dfelinto Reviewed By: brecht Subscribers: duarteframos, fclem, homyachetser, Evgeny_Rodygin, AlexKowel, yurikovelenov Differential Revision: https://developer.blender.org/D2425
This commit is contained in:
parent
6fc7521ade
commit
78b5d66af8
@ -379,27 +379,16 @@ Object *BlenderSync::sync_object(BL::Object& b_parent,
|
||||
}
|
||||
}
|
||||
|
||||
/* random number */
|
||||
object->random_id = hash_string(object->name.c_str());
|
||||
|
||||
if(persistent_id) {
|
||||
for(int i = 0; i < OBJECT_PERSISTENT_ID_SIZE; i++)
|
||||
object->random_id = hash_int_2d(object->random_id, persistent_id[i]);
|
||||
}
|
||||
else
|
||||
object->random_id = hash_int_2d(object->random_id, 0);
|
||||
|
||||
if(b_parent.ptr.data != b_ob.ptr.data)
|
||||
object->random_id ^= hash_int(hash_string(b_parent.name().c_str()));
|
||||
|
||||
/* dupli texture coordinates */
|
||||
/* dupli texture coordinates and random_id */
|
||||
if(b_dupli_ob) {
|
||||
object->dupli_generated = 0.5f*get_float3(b_dupli_ob.orco()) - make_float3(0.5f, 0.5f, 0.5f);
|
||||
object->dupli_uv = get_float2(b_dupli_ob.uv());
|
||||
object->random_id = b_dupli_ob.random_id();
|
||||
}
|
||||
else {
|
||||
object->dupli_generated = make_float3(0.0f, 0.0f, 0.0f);
|
||||
object->dupli_uv = make_float2(0.0f, 0.0f);
|
||||
object->random_id = hash_int_2d(hash_string(object->name.c_str()), 0);
|
||||
}
|
||||
|
||||
object->tag_update(scene);
|
||||
|
@ -157,6 +157,7 @@ shader_node_categories = [
|
||||
NodeItem("ShaderNodeGeometry"),
|
||||
NodeItem("ShaderNodeExtendedMaterial"),
|
||||
NodeItem("ShaderNodeParticleInfo"),
|
||||
NodeItem("ShaderNodeObjectInfo"),
|
||||
NodeItem("NodeGroupInput", poll=group_input_output_item_poll),
|
||||
]),
|
||||
ShaderOldNodeCategory("SH_OUTPUT", "Output", items=[
|
||||
|
@ -64,6 +64,7 @@
|
||||
|
||||
|
||||
#include "BLI_strict_flags.h"
|
||||
#include "BLI_hash.h"
|
||||
|
||||
/* Dupli-Geometry */
|
||||
|
||||
@ -180,6 +181,22 @@ static DupliObject *make_dupli(const DupliContext *ctx,
|
||||
if (ob->type == OB_MBALL)
|
||||
dob->no_draw = true;
|
||||
|
||||
/* random number */
|
||||
/* the logic here is designed to match Cycles */
|
||||
dob->random_id = BLI_hash_string(dob->ob->id.name + 2);
|
||||
|
||||
if (dob->persistent_id[0] != INT_MAX) {
|
||||
for(i = 0; i < MAX_DUPLI_RECUR*2; i++)
|
||||
dob->random_id = BLI_hash_int_2d(dob->random_id, (unsigned int)dob->persistent_id[i]);
|
||||
}
|
||||
else {
|
||||
dob->random_id = BLI_hash_int_2d(dob->random_id, 0);
|
||||
}
|
||||
|
||||
if (ctx->object != ob) {
|
||||
dob->random_id ^= BLI_hash_int(BLI_hash_string(ctx->object->id.name + 2));
|
||||
}
|
||||
|
||||
return dob;
|
||||
}
|
||||
|
||||
|
66
source/blender/blenlib/BLI_hash.h
Normal file
66
source/blender/blenlib/BLI_hash.h
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.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#ifndef __BLI_HASH_H__
|
||||
#define __BLI_HASH_H__
|
||||
|
||||
/** \file BLI_hash.h
|
||||
* \ingroup bli
|
||||
*/
|
||||
|
||||
static inline unsigned int BLI_hash_int_2d(unsigned int kx, unsigned int ky)
|
||||
{
|
||||
#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
|
||||
|
||||
unsigned int a, b, c;
|
||||
|
||||
a = b = c = 0xdeadbeef + (2 << 2) + 13;
|
||||
a += kx;
|
||||
b += ky;
|
||||
|
||||
c ^= b; c -= rot(b,14);
|
||||
a ^= c; a -= rot(c,11);
|
||||
b ^= a; b -= rot(a,25);
|
||||
c ^= b; c -= rot(b,16);
|
||||
a ^= c; a -= rot(c,4);
|
||||
b ^= a; b -= rot(a,14);
|
||||
c ^= b; c -= rot(b,24);
|
||||
|
||||
return c;
|
||||
|
||||
#undef rot
|
||||
}
|
||||
|
||||
static inline unsigned int BLI_hash_string(const char *str)
|
||||
{
|
||||
unsigned int i = 0, c;
|
||||
|
||||
while((c = *str++))
|
||||
i = i * 37 + c;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static inline unsigned int BLI_hash_int(unsigned int k)
|
||||
{
|
||||
return BLI_hash_int_2d(k, 0);
|
||||
}
|
||||
|
||||
#endif // __BLI_HASH_H__
|
@ -98,6 +98,7 @@ typedef enum GPUBuiltin {
|
||||
GPU_PARTICLE_ANG_VELOCITY = (1 << 12),
|
||||
GPU_LOC_TO_VIEW_MATRIX = (1 << 13),
|
||||
GPU_INVERSE_LOC_TO_VIEW_MATRIX = (1 << 14),
|
||||
GPU_OBJECT_INFO = (1 << 15)
|
||||
} GPUBuiltin;
|
||||
|
||||
typedef enum GPUOpenGLBuiltin {
|
||||
@ -213,6 +214,7 @@ bool GPU_stack_link(GPUMaterial *mat, const char *name, GPUNodeStack *in, GPUNod
|
||||
|
||||
void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link);
|
||||
void GPU_material_enable_alpha(GPUMaterial *material);
|
||||
GPUBuiltin GPU_get_material_builtins(GPUMaterial *material);
|
||||
GPUBlendMode GPU_material_alpha_blend(GPUMaterial *material, float obcol[4]);
|
||||
|
||||
/* High level functions to create and use GPU materials */
|
||||
@ -230,7 +232,7 @@ void GPU_material_bind(
|
||||
float viewmat[4][4], float viewinv[4][4], float cameraborder[4], bool scenelock);
|
||||
void GPU_material_bind_uniforms(
|
||||
GPUMaterial *material, float obmat[4][4], float viewmat[4][4], float obcol[4],
|
||||
float autobumpscale, GPUParticleInfo *pi);
|
||||
float autobumpscale, GPUParticleInfo *pi, float object_info[3]);
|
||||
void GPU_material_unbind(GPUMaterial *material);
|
||||
bool GPU_material_bound(GPUMaterial *material);
|
||||
struct Scene *GPU_material_scene(GPUMaterial *material);
|
||||
@ -345,6 +347,7 @@ struct GPUParticleInfo
|
||||
float location[3];
|
||||
float velocity[3];
|
||||
float angular_velocity[3];
|
||||
int random_id;
|
||||
};
|
||||
|
||||
#ifdef WITH_OPENSUBDIV
|
||||
|
@ -410,6 +410,8 @@ const char *GPU_builtin_name(GPUBuiltin builtin)
|
||||
return "unfparticlevel";
|
||||
else if (builtin == GPU_PARTICLE_ANG_VELOCITY)
|
||||
return "unfparticleangvel";
|
||||
else if (builtin == GPU_OBJECT_INFO)
|
||||
return "unfobjectinfo";
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_threads.h"
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_hash.h"
|
||||
|
||||
#include "DNA_lamp_types.h"
|
||||
#include "DNA_material_types.h"
|
||||
@ -1899,6 +1900,21 @@ static int gpu_get_particle_info(GPUParticleInfo *pi)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void GPU_get_object_info(float oi[3], Material *mat)
|
||||
{
|
||||
Object *ob = GMS.gob;
|
||||
oi[0] = ob->index;
|
||||
oi[1] = mat->index;
|
||||
unsigned int random;
|
||||
if (GMS.dob) {
|
||||
random = GMS.dob->random_id;
|
||||
}
|
||||
else {
|
||||
random = BLI_hash_int_2d(BLI_hash_string(GMS.gob->id.name + 2), 0);
|
||||
}
|
||||
oi[2] = random * (1.0f/(float)0xFFFFFFFF);
|
||||
}
|
||||
|
||||
int GPU_object_material_bind(int nr, void *attribs)
|
||||
{
|
||||
GPUVertexAttribs *gattribs = attribs;
|
||||
@ -1958,6 +1974,7 @@ int GPU_object_material_bind(int nr, void *attribs)
|
||||
/* bind glsl material and get attributes */
|
||||
Material *mat = GMS.gmatbuf[nr];
|
||||
GPUParticleInfo partile_info;
|
||||
float object_info[3] = {0};
|
||||
|
||||
float auto_bump_scale;
|
||||
|
||||
@ -1967,13 +1984,17 @@ int GPU_object_material_bind(int nr, void *attribs)
|
||||
if (GMS.dob) {
|
||||
gpu_get_particle_info(&partile_info);
|
||||
}
|
||||
|
||||
if (GPU_get_material_builtins(gpumat) & GPU_OBJECT_INFO) {
|
||||
GPU_get_object_info(object_info, mat);
|
||||
}
|
||||
|
||||
GPU_material_bind(
|
||||
gpumat, GMS.gob->lay, GMS.glay, 1.0, !(GMS.gob->mode & OB_MODE_TEXTURE_PAINT),
|
||||
GMS.gviewmat, GMS.gviewinv, GMS.gviewcamtexcofac, GMS.gscenelock);
|
||||
|
||||
auto_bump_scale = GMS.gob->derivedFinal != NULL ? GMS.gob->derivedFinal->auto_bump_scale : 1.0f;
|
||||
GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, GMS.gviewmat, GMS.gob->col, auto_bump_scale, &partile_info);
|
||||
GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, GMS.gviewmat, GMS.gob->col, auto_bump_scale, &partile_info, object_info);
|
||||
GMS.gboundmat = mat;
|
||||
|
||||
/* for glsl use alpha blend mode, unless it's set to solid and
|
||||
|
@ -122,6 +122,8 @@ struct GPUMaterial {
|
||||
int partvel;
|
||||
int partangvel;
|
||||
|
||||
int objectinfoloc;
|
||||
|
||||
ListBase lamps;
|
||||
bool bound;
|
||||
|
||||
@ -268,6 +270,8 @@ static int gpu_material_construct_end(GPUMaterial *material, const char *passnam
|
||||
material->partvel = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PARTICLE_VELOCITY));
|
||||
if (material->builtins & GPU_PARTICLE_ANG_VELOCITY)
|
||||
material->partangvel = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PARTICLE_ANG_VELOCITY));
|
||||
if (material->builtins & GPU_OBJECT_INFO)
|
||||
material->objectinfoloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_OBJECT_INFO));
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
@ -398,9 +402,14 @@ void GPU_material_bind(
|
||||
}
|
||||
}
|
||||
|
||||
GPUBuiltin GPU_get_material_builtins(GPUMaterial *material)
|
||||
{
|
||||
return material->builtins;
|
||||
}
|
||||
|
||||
void GPU_material_bind_uniforms(
|
||||
GPUMaterial *material, float obmat[4][4], float viewmat[4][4], float obcol[4],
|
||||
float autobumpscale, GPUParticleInfo *pi)
|
||||
float autobumpscale, GPUParticleInfo *pi, float object_info[3])
|
||||
{
|
||||
if (material->pass) {
|
||||
GPUShader *shader = GPU_pass_shader(material->pass);
|
||||
@ -449,6 +458,9 @@ void GPU_material_bind_uniforms(
|
||||
if (material->builtins & GPU_PARTICLE_ANG_VELOCITY) {
|
||||
GPU_shader_uniform_vector(shader, material->partangvel, 3, 1, pi->angular_velocity);
|
||||
}
|
||||
if (material->builtins & GPU_OBJECT_INFO) {
|
||||
GPU_shader_uniform_vector(shader, material->objectinfoloc, 3, 1, object_info);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "GPU_glew.h"
|
||||
#include "GPU_shader.h"
|
||||
#include "GPU_texture.h"
|
||||
#include "GPU_material.h"
|
||||
|
||||
/* TODO(sergey): Find better default values for this constants. */
|
||||
#define MAX_DEFINE_LENGTH 1024
|
||||
|
@ -3563,12 +3563,12 @@ void node_light_falloff(float strength, float tsmooth, out float quadratic, out
|
||||
constant = strength;
|
||||
}
|
||||
|
||||
void node_object_info(out vec3 location, out float object_index, out float material_index, out float random)
|
||||
void node_object_info(mat4 obmat, vec3 info, out vec3 location, out float object_index, out float material_index, out float random)
|
||||
{
|
||||
location = vec3(0.0);
|
||||
object_index = 0.0;
|
||||
material_index = 0.0;
|
||||
random = 0.0;
|
||||
location = obmat[3].xyz;
|
||||
object_index = info.x;
|
||||
material_index = info.y;
|
||||
random = info.z;
|
||||
}
|
||||
|
||||
void node_normal_map(vec4 tangent, vec3 normal, vec3 texnormal, out vec3 outnormal)
|
||||
|
@ -335,6 +335,8 @@ typedef struct DupliObject {
|
||||
|
||||
/* particle this dupli was generated from */
|
||||
struct ParticleSystem *particle_system;
|
||||
unsigned int random_id;
|
||||
unsigned int pad;
|
||||
} DupliObject;
|
||||
|
||||
/* **************** OBJECT ********************* */
|
||||
|
@ -2897,6 +2897,10 @@ static void rna_def_dupli_object(BlenderRNA *brna)
|
||||
RNA_def_property_enum_items(prop, dupli_items);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Dupli Type", "Duplicator type that generated this dupli object");
|
||||
|
||||
prop = RNA_def_property(srna, "random_id", PROP_INT, PROP_UNSIGNED);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Dupli random id", "Random id for this dupli object");
|
||||
}
|
||||
|
||||
static void rna_def_object_base(BlenderRNA *brna)
|
||||
|
@ -39,7 +39,16 @@ static bNodeSocketTemplate sh_node_object_info_out[] = {
|
||||
|
||||
static int node_shader_gpu_object_info(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
|
||||
{
|
||||
return GPU_stack_link(mat, "node_object_info", in, out);
|
||||
return GPU_stack_link(mat, "node_object_info", in, out, GPU_builtin(GPU_OBJECT_MATRIX), GPU_builtin(GPU_OBJECT_INFO));
|
||||
}
|
||||
|
||||
static void node_shader_exec_object_info(void *data, int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **UNUSED(in), bNodeStack **out)
|
||||
{
|
||||
ShaderCallData *scd = (ShaderCallData *)data;
|
||||
copy_v4_v4(out[0]->vec, RE_object_instance_get_matrix(scd->shi->obi, RE_OBJECT_INSTANCE_MATRIX_OB)[3]);
|
||||
out[1]->vec[0] = RE_object_instance_get_object_pass_index(scd->shi->obi);
|
||||
out[2]->vec[0] = scd->shi->mat->index;
|
||||
out[3]->vec[0] = RE_object_instance_get_random_id(scd->shi->obi) * (1.0f/(float)0xFFFFFFFF);;
|
||||
}
|
||||
|
||||
/* node type definition */
|
||||
@ -53,6 +62,7 @@ void register_node_type_sh_object_info(void)
|
||||
node_type_init(&ntype, NULL);
|
||||
node_type_storage(&ntype, "", NULL, NULL);
|
||||
node_type_gpu(&ntype, node_shader_gpu_object_info);
|
||||
node_type_exec(&ntype, NULL, NULL, node_shader_exec_object_info);
|
||||
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
|
@ -381,7 +381,7 @@ bool RE_allow_render_generic_object(struct Object *ob);
|
||||
/* RE_updateRenderInstances flag */
|
||||
enum {
|
||||
RE_OBJECT_INSTANCES_UPDATE_VIEW = (1 << 0),
|
||||
RE_OBJECT_INSTANCES_UPDATE_OBMAT = (1 << 1),
|
||||
RE_OBJECT_INSTANCES_UPDATE_OBMAT = (1 << 1)
|
||||
};
|
||||
void RE_updateRenderInstances(Render *re, int flag);
|
||||
|
||||
|
@ -178,6 +178,7 @@ typedef struct ShadeInput {
|
||||
|
||||
unsigned int lay;
|
||||
int layflag, passflag, combinedflag;
|
||||
short object_pass_index;
|
||||
struct Group *light_override;
|
||||
struct Material *mat_override;
|
||||
|
||||
@ -241,6 +242,9 @@ enum {
|
||||
|
||||
const float (*RE_object_instance_get_matrix(struct ObjectInstanceRen *obi, int matrix_id))[4];
|
||||
|
||||
float RE_object_instance_get_object_pass_index(struct ObjectInstanceRen *obi);
|
||||
float RE_object_instance_get_random_id(struct ObjectInstanceRen *obi);
|
||||
|
||||
enum {
|
||||
RE_VIEW_MATRIX,
|
||||
RE_VIEWINV_MATRIX,
|
||||
|
@ -382,6 +382,8 @@ typedef struct ObjectInstanceRen {
|
||||
float part_co[3];
|
||||
float part_vel[3];
|
||||
float part_avel[3];
|
||||
|
||||
unsigned int random_id;
|
||||
} ObjectInstanceRen;
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
@ -66,6 +66,7 @@
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_hash.h"
|
||||
|
||||
#include "DNA_material_types.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
@ -1458,6 +1459,14 @@ ObjectInstanceRen *RE_addRenderInstance(
|
||||
}
|
||||
}
|
||||
|
||||
/* Fill object info */
|
||||
if (dob) {
|
||||
obi->random_id = dob->random_id;
|
||||
}
|
||||
else {
|
||||
obi->random_id = BLI_hash_int_2d(BLI_hash_string(obi->ob->id.name + 2), 0);
|
||||
}
|
||||
|
||||
RE_updateRenderInstance(re, obi, RE_OBJECT_INSTANCES_UPDATE_OBMAT | RE_OBJECT_INSTANCES_UPDATE_VIEW);
|
||||
|
||||
if (mat) {
|
||||
|
@ -2141,6 +2141,16 @@ const float (*RE_object_instance_get_matrix(struct ObjectInstanceRen *obi, int m
|
||||
return NULL;
|
||||
}
|
||||
|
||||
float RE_object_instance_get_object_pass_index(struct ObjectInstanceRen *obi)
|
||||
{
|
||||
return obi->ob->index;
|
||||
}
|
||||
|
||||
float RE_object_instance_get_random_id(struct ObjectInstanceRen *obi)
|
||||
{
|
||||
return obi->random_id;
|
||||
}
|
||||
|
||||
const float (*RE_render_current_get_matrix(int matrix_id))[4]
|
||||
{
|
||||
switch (matrix_id) {
|
||||
|
@ -274,6 +274,7 @@ struct Object *RE_GetCamera(struct Render *re) RET_NULL
|
||||
float RE_lamp_get_data(struct ShadeInput *shi, struct Object *lamp_obj, float col[4], float lv[3], float *dist, float shadow[4]) RET_ZERO
|
||||
const float (*RE_object_instance_get_matrix(struct ObjectInstanceRen *obi, int matrix_id))[4] RET_NULL
|
||||
const float (*RE_render_current_get_matrix(int matrix_id))[4] RET_NULL
|
||||
const float RE_object_instance_get_object_pass_index(struct ObjectInstanceRen *obi) RET_ZERO
|
||||
|
||||
/* blenkernel */
|
||||
bool BKE_paint_proj_mesh_data_check(struct Scene *scene, struct Object *ob, bool *uvs, bool *mat, bool *tex, bool *stencil) RET_ZERO
|
||||
|
@ -169,7 +169,7 @@ void BL_BlenderShader::Update(const RAS_MeshSlot & ms, RAS_IRasterizer* rasty )
|
||||
|
||||
rasty->GetViewMatrix().getValue(&viewmat[0][0]);
|
||||
float auto_bump_scale = ms.m_pDerivedMesh!=0 ? ms.m_pDerivedMesh->auto_bump_scale : 1.0f;
|
||||
GPU_material_bind_uniforms(gpumat, obmat, viewmat, obcol, auto_bump_scale, NULL);
|
||||
GPU_material_bind_uniforms(gpumat, obmat, viewmat, obcol, auto_bump_scale, NULL, NULL);
|
||||
|
||||
mAlphaBlend = GPU_material_alpha_blend(gpumat, obcol);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user