void TextureBaseOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) { TexResult texres = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL}; float textureSize[4]; float textureOffset[4]; float vec[3]; int retval; const float cx = this->getWidth() / 2; const float cy = this->getHeight() / 2; const float u = (x - cx) / this->getWidth() * 2; const float v = (y - cy) / this->getHeight() * 2; this->m_inputSize->readSampled(textureSize, x, y, sampler); this->m_inputOffset->readSampled(textureOffset, x, y, sampler); vec[0] = textureSize[0] * (u + textureOffset[0]); vec[1] = textureSize[1] * (v + textureOffset[1]); vec[2] = textureSize[2] * textureOffset[2]; retval = multitex_ext(this->m_texture, vec, NULL, NULL, 0, &texres, m_pool, m_sceneColorManage); if (texres.talpha) output[3] = texres.ta; else output[3] = texres.tin; if ((retval & TEX_RGB)) { output[0] = texres.tr; output[1] = texres.tg; output[2] = texres.tb; } else { output[0] = output[1] = output[2] = output[3]; } }
void TextureBaseOperation::executePixel(float *color, float x, float y, PixelSampler sampler) { TexResult texres = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL}; float textureSize[4]; float textureOffset[4]; float vec[3]; int retval; const float cx = this->getWidth() / 2; const float cy = this->getHeight() / 2; const float u = (cx - x) / this->getWidth() * 2; const float v = (cy - y) / this->getHeight() * 2; this->m_inputSize->read(textureSize, x, y, sampler); this->m_inputOffset->read(textureOffset, x, y, sampler); vec[0] = textureSize[0] * (u + textureOffset[0]); vec[1] = textureSize[1] * (v + textureOffset[1]); vec[2] = textureSize[2] * textureOffset[2]; retval = multitex_ext(this->m_texture, vec, NULL, NULL, 0, &texres); if (texres.talpha) color[3] = texres.ta; else color[3] = texres.tin; if ((retval & TEX_RGB)) { color[0] = texres.tr; color[1] = texres.tg; color[2] = texres.tb; } else color[0] = color[1] = color[2] = color[3]; }
void texture_evaluate(struct Tex *tex, float value[3], float color_r[3]) { TexResult texres= {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL}; multitex_ext(tex, value, NULL, NULL, 1, &texres); color_r[0] = texres.tr; color_r[1] = texres.tg; color_r[2] = texres.tb; color_r[3] = texres.tin; }
static void texture_evaluate(struct Tex *tex, float value[3], float color_r[4]) { TexResult texres = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL}; /* TODO(sergey): always use color management now. */ multitex_ext(tex, value, NULL, NULL, 1, &texres, NULL, true); color_r[0] = texres.tr; color_r[1] = texres.tg; color_r[2] = texres.tb; color_r[3] = texres.tin; }
void TextureBaseOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) { TexResult texres = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL}; float textureSize[4]; float textureOffset[4]; float vec[3]; int retval; const float cx = this->getWidth() / 2; const float cy = this->getHeight() / 2; float u = (x - cx) / this->getWidth() * 2; float v = (y - cy) / this->getHeight() * 2; /* When no interpolation/filtering happens in multitex() foce nearest interpolation. * We do it here because (a) we can't easily say multitex() that we want nearest * interpolation and (b) in such configuration multitex() sinply floor's the value * which often produces artifacts. */ if (m_texture != NULL && (m_texture->imaflag & TEX_INTERPOL) == 0) { u += 0.5f / cx; v += 0.5f / cy; } this->m_inputSize->readSampled(textureSize, x, y, sampler); this->m_inputOffset->readSampled(textureOffset, x, y, sampler); vec[0] = textureSize[0] * (u + textureOffset[0]); vec[1] = textureSize[1] * (v + textureOffset[1]); vec[2] = textureSize[2] * textureOffset[2]; const int thread_id = WorkScheduler::current_thread_id(); retval = multitex_ext( this->m_texture, vec, NULL, NULL, 0, &texres, thread_id, m_pool, m_sceneColorManage, false); if (texres.talpha) { output[3] = texres.ta; } else { output[3] = texres.tin; } if ((retval & TEX_RGB)) { output[0] = texres.tr; output[1] = texres.tg; output[2] = texres.tb; } else { output[0] = output[1] = output[2] = output[3]; } }
float paint_get_tex_pixel(Brush* br, float u, float v) { TexResult texres; float co[3]; int hasrgb; co[0] = u; co[1] = v; co[2] = 0; memset(&texres, 0, sizeof(TexResult)); hasrgb = multitex_ext(br->mtex.tex, co, NULL, NULL, 0, &texres); if (hasrgb & TEX_RGB) texres.tin = (0.35f*texres.tr + 0.45f*texres.tg + 0.2f*texres.tb)*texres.ta; return texres.tin; }
/* TODO: should probably be unified with BrushPainter stuff? */ unsigned int *brush_gen_texture_cache(Brush *br, int half_side) { unsigned int *texcache = NULL; MTex *mtex = &br->mtex; TexResult texres= {0}; int hasrgb, ix, iy; int side = half_side * 2; if(mtex->tex) { float x, y, step = 2.0 / side, co[3]; texcache = MEM_callocN(sizeof(int) * side * side, "Brush texture cache"); BKE_image_get_ibuf(mtex->tex->ima, NULL); /*do normalized cannonical view coords for texture*/ for (y=-1.0, iy=0; iy<side; iy++, y += step) { for (x=-1.0, ix=0; ix<side; ix++, x += step) { co[0]= x; co[1]= y; co[2]= 0.0f; /* This is copied from displace modifier code */ hasrgb = multitex_ext(mtex->tex, co, NULL, NULL, 0, &texres); /* if the texture gave an RGB value, we assume it didn't give a valid * intensity, so calculate one (formula from do_material_tex). * if the texture didn't give an RGB value, copy the intensity across */ if(hasrgb & TEX_RGB) texres.tin = (0.35f * texres.tr + 0.45f * texres.tg + 0.2f * texres.tb); texres.tin = texres.tin * 255.0f; ((char*)texcache)[(iy*side+ix)*4] = (char)texres.tin; ((char*)texcache)[(iy*side+ix)*4+1] = (char)texres.tin; ((char*)texcache)[(iy*side+ix)*4+2] = (char)texres.tin; ((char*)texcache)[(iy*side+ix)*4+3] = (char)texres.tin; } } } return texcache; }
/* TODO: should probably be unified with BrushPainter stuff? */ unsigned int *BKE_brush_gen_texture_cache(Brush *br, int half_side, bool use_secondary) { unsigned int *texcache = NULL; MTex *mtex = (use_secondary) ? &br->mask_mtex : &br->mtex; TexResult texres = {0}; int hasrgb, ix, iy; int side = half_side * 2; if (mtex->tex) { float x, y, step = 2.0 / side, co[3]; texcache = MEM_callocN(sizeof(int) * side * side, "Brush texture cache"); /* do normalized cannonical view coords for texture */ for (y = -1.0, iy = 0; iy < side; iy++, y += step) { for (x = -1.0, ix = 0; ix < side; ix++, x += step) { co[0] = x; co[1] = y; co[2] = 0.0f; /* This is copied from displace modifier code */ /* TODO(sergey): brush are always cacheing with CM enabled for now. */ hasrgb = multitex_ext(mtex->tex, co, NULL, NULL, 0, &texres, NULL, true); /* if the texture gave an RGB value, we assume it didn't give a valid * intensity, so calculate one (formula from do_material_tex). * if the texture didn't give an RGB value, copy the intensity across */ if (hasrgb & TEX_RGB) texres.tin = rgb_to_grayscale(&texres.tr); ((char *)texcache)[(iy * side + ix) * 4] = ((char *)texcache)[(iy * side + ix) * 4 + 1] = ((char *)texcache)[(iy * side + ix) * 4 + 2] = ((char *)texcache)[(iy * side + ix) * 4 + 3] = (char)(texres.tin * 255.0f); } } } return texcache; }
static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **in, short thread) { static float red[] = {1,0,0,1}; static float white[] = {1,1,1,1}; float *coord = p->coord; Tex *nodetex = (Tex *)node->id; if(node->custom2 || node->need_exec==0) { /* this node refers to its own texture tree! */ QUATCOPY( out, (fabs(coord[0] - coord[1]) < .01) ? white : red ); } else if(nodetex) { TexResult texres; int textype; float nor[] = {0,0,0}; float col1[4], col2[4]; tex_input_rgba(col1, in[0], p, thread); tex_input_rgba(col2, in[1], p, thread); texres.nor = nor; textype = multitex_ext(nodetex, coord, 0, 0, 0, &texres); if(textype & TEX_RGB) { QUATCOPY(out, &texres.tr); } else { QUATCOPY(out, col1); ramp_blend(MA_RAMP_BLEND, out, out+1, out+2, texres.tin, col2); } } }
static void do_texture_effector(EffectorCache *eff, EffectorData *efd, EffectedPoint *point, float *total_force) { TexResult result[4]; float tex_co[3], strength, force[3]; float nabla = eff->pd->tex_nabla; int hasrgb; short mode = eff->pd->tex_mode; bool scene_color_manage; if (!eff->pd->tex) return; result[0].nor = result[1].nor = result[2].nor = result[3].nor = NULL; strength= eff->pd->f_strength * efd->falloff; copy_v3_v3(tex_co, point->loc); if (eff->pd->flag & PFIELD_TEX_2D) { float fac=-dot_v3v3(tex_co, efd->nor); madd_v3_v3fl(tex_co, efd->nor, fac); } if (eff->pd->flag & PFIELD_TEX_OBJECT) { mul_m4_v3(eff->ob->imat, tex_co); } scene_color_manage = BKE_scene_check_color_management_enabled(eff->scene); hasrgb = multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result, NULL, scene_color_manage, false); if (hasrgb && mode==PFIELD_TEX_RGB) { force[0] = (0.5f - result->tr) * strength; force[1] = (0.5f - result->tg) * strength; force[2] = (0.5f - result->tb) * strength; } else { strength/=nabla; tex_co[0] += nabla; multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+1, NULL, scene_color_manage, false); tex_co[0] -= nabla; tex_co[1] += nabla; multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+2, NULL, scene_color_manage, false); tex_co[1] -= nabla; tex_co[2] += nabla; multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+3, NULL, scene_color_manage, false); if (mode == PFIELD_TEX_GRAD || !hasrgb) { /* if we don't have rgb fall back to grad */ /* generate intensity if texture only has rgb value */ if (hasrgb & TEX_RGB) { int i; for (i=0; i<4; i++) result[i].tin = (1.0f / 3.0f) * (result[i].tr + result[i].tg + result[i].tb); } force[0] = (result[0].tin - result[1].tin) * strength; force[1] = (result[0].tin - result[2].tin) * strength; force[2] = (result[0].tin - result[3].tin) * strength; } else { /*PFIELD_TEX_CURL*/ float dbdy, dgdz, drdz, dbdx, dgdx, drdy; dbdy = result[2].tb - result[0].tb; dgdz = result[3].tg - result[0].tg; drdz = result[3].tr - result[0].tr; dbdx = result[1].tb - result[0].tb; dgdx = result[1].tg - result[0].tg; drdy = result[2].tr - result[0].tr; force[0] = (dbdy - dgdz) * strength; force[1] = (drdz - dbdx) * strength; force[2] = (dgdx - drdy) * strength; } } if (eff->pd->flag & PFIELD_TEX_2D) { float fac = -dot_v3v3(force, efd->nor); madd_v3_v3fl(force, efd->nor, fac); } add_v3_v3(total_force, force); }
static void do_texture_effector(EffectorCache *eff, EffectorData *efd, EffectedPoint *point, float *total_force) { TexResult result[4]; float tex_co[3], strength, force[3]; float nabla = eff->pd->tex_nabla; int hasrgb; short mode = eff->pd->tex_mode; if(!eff->pd->tex) return; result[0].nor = result[1].nor = result[2].nor = result[3].nor = NULL; strength= eff->pd->f_strength * efd->falloff; copy_v3_v3(tex_co,point->loc); if(eff->pd->flag & PFIELD_TEX_2D) { float fac=-dot_v3v3(tex_co, efd->nor); VECADDFAC(tex_co, tex_co, efd->nor, fac); } if(eff->pd->flag & PFIELD_TEX_OBJECT) { mul_m4_v3(eff->ob->imat, tex_co); } hasrgb = multitex_ext(eff->pd->tex, tex_co, NULL,NULL, 0, result); if(hasrgb && mode==PFIELD_TEX_RGB) { force[0] = (0.5f - result->tr) * strength; force[1] = (0.5f - result->tg) * strength; force[2] = (0.5f - result->tb) * strength; } else { strength/=nabla; tex_co[0] += nabla; multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+1); tex_co[0] -= nabla; tex_co[1] += nabla; multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+2); tex_co[1] -= nabla; tex_co[2] += nabla; multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+3); if(mode == PFIELD_TEX_GRAD || !hasrgb) { /* if we dont have rgb fall back to grad */ force[0] = (result[0].tin - result[1].tin) * strength; force[1] = (result[0].tin - result[2].tin) * strength; force[2] = (result[0].tin - result[3].tin) * strength; } else { /*PFIELD_TEX_CURL*/ float dbdy, dgdz, drdz, dbdx, dgdx, drdy; dbdy = result[2].tb - result[0].tb; dgdz = result[3].tg - result[0].tg; drdz = result[3].tr - result[0].tr; dbdx = result[1].tb - result[0].tb; dgdx = result[1].tg - result[0].tg; drdy = result[2].tr - result[0].tr; force[0] = (dbdy - dgdz) * strength; force[1] = (drdz - dbdx) * strength; force[2] = (dgdx - drdy) * strength; } } if(eff->pd->flag & PFIELD_TEX_2D){ float fac = -dot_v3v3(force, efd->nor); VECADDFAC(force, force, efd->nor, fac); } add_v3_v3(total_force, force); }