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:
Alexander Romanov 2017-04-14 18:13:44 +03:00 committed by Clément Foucault
parent 8fdd568343
commit 76425feed8
Notes: blender-bot 2023-06-26 11:58:59 +02:00
Referenced by commit bc6a75b405, Revert "Object Info node support for GLSL mode and the internal render"
20 changed files with 181 additions and 26 deletions

View File

@ -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);

View File

@ -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=[

View File

@ -64,6 +64,7 @@
#include "DEG_depsgraph.h"
#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;
}

View 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__

View File

@ -97,6 +97,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 {
@ -212,6 +213,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 */
@ -228,7 +230,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);
@ -325,6 +327,7 @@ struct GPUParticleInfo
float location[3];
float velocity[3];
float angular_velocity[3];
int random_id;
};
#ifdef WITH_OPENSUBDIV

View File

@ -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 "";
}

View File

@ -43,6 +43,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"
@ -1880,6 +1881,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;
@ -1939,21 +1955,27 @@ 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;
GPUMaterial *gpumat = GPU_material_from_blender(GMS.gscene, mat, GMS.is_opensubdiv);
GPU_material_vertex_attributes(gpumat, gattribs);
if (GMS.dob)
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

View File

@ -124,6 +124,8 @@ struct GPUMaterial {
int partvel;
int partangvel;
int objectinfoloc;
ListBase lamps;
bool bound;
@ -226,6 +228,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 {
@ -346,9 +350,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);
@ -397,6 +406,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);
}
}
}

View File

@ -39,6 +39,7 @@
#include "GPU_uniformbuffer.h"
#include "GPU_texture.h"
#include "GPU_matrix.h"
#include "GPU_material.h"
#include "gpu_shader_private.h"

View File

@ -3578,12 +3578,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)

View File

@ -342,6 +342,8 @@ typedef struct DupliObject {
/* particle this dupli was generated from */
struct ParticleSystem *particle_system;
unsigned int random_id;
unsigned int pad;
} DupliObject;
/* **************** OBJECT ********************* */

View File

@ -2889,6 +2889,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_legacy(BlenderRNA *brna)

View File

@ -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);
}

View File

@ -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);

View File

@ -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,

View File

@ -382,6 +382,8 @@ typedef struct ObjectInstanceRen {
float part_co[3];
float part_vel[3];
float part_avel[3];
unsigned int random_id;
} ObjectInstanceRen;
/* ------------------------------------------------------------------------- */

View File

@ -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) {

View File

@ -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) {

View File

@ -278,6 +278,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

View File

@ -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);
}