forked from bartvdbraak/blender
fixes scale on derivative maps
This commit is contained in:
parent
82480e9995
commit
965c287630
@ -94,6 +94,7 @@ struct DerivedMesh {
|
||||
BVHCache bvhCache;
|
||||
struct GPUDrawObject *drawObject;
|
||||
DerivedMeshType type;
|
||||
float auto_bump_scale;
|
||||
|
||||
/* Misc. Queries */
|
||||
|
||||
@ -578,6 +579,7 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm,
|
||||
struct GPUVertexAttribs *gattribs, DMVertexAttribs *attribs);
|
||||
|
||||
void DM_add_tangent_layer(DerivedMesh *dm);
|
||||
void DM_calc_auto_bump_scale(DerivedMesh *dm);
|
||||
|
||||
/* Set object's bounding box based on DerivedMesh min/max data */
|
||||
void DM_set_object_boundbox(struct Object *ob, DerivedMesh *dm);
|
||||
|
@ -184,6 +184,7 @@ void DM_init(DerivedMesh *dm, DerivedMeshType type,
|
||||
DM_init_funcs(dm);
|
||||
|
||||
dm->needsFree = 1;
|
||||
dm->auto_bump_scale = -1.0f;
|
||||
}
|
||||
|
||||
void DM_from_template(DerivedMesh *dm, DerivedMesh *source, DerivedMeshType type,
|
||||
@ -1831,6 +1832,159 @@ void DM_add_tangent_layer(DerivedMesh *dm)
|
||||
MEM_freeN(vtangents);
|
||||
}
|
||||
|
||||
void DM_calc_auto_bump_scale(DerivedMesh *dm)
|
||||
{
|
||||
int totvert= dm->getNumVerts(dm);
|
||||
int totface= dm->getNumFaces(dm);
|
||||
|
||||
MVert * mvert = dm->getVertArray(dm);
|
||||
MFace * mface = dm->getFaceArray(dm);
|
||||
MTFace * mtface = dm->getFaceDataArray(dm, CD_MTFACE);
|
||||
|
||||
if(mtface)
|
||||
{
|
||||
double dsum = 0.0;
|
||||
int nr_accumulated = 0;
|
||||
int f;
|
||||
|
||||
for ( f=0; f<totface; f++ )
|
||||
{
|
||||
{
|
||||
float * verts[4], * tex_coords[4];
|
||||
const int nr_verts = mface[f].v4!=0 ? 4 : 3;
|
||||
int i, is_degenerate;
|
||||
|
||||
verts[0]=mvert[mface[f].v1].co; verts[1]=mvert[mface[f].v2].co; verts[2]=mvert[mface[f].v3].co;
|
||||
tex_coords[0]=mtface[f].uv[0]; tex_coords[1]=mtface[f].uv[1]; tex_coords[2]=mtface[f].uv[2];
|
||||
if(nr_verts==4)
|
||||
{
|
||||
verts[3]=mvert[mface[f].v4].co;
|
||||
tex_coords[3]=mtface[f].uv[3];
|
||||
}
|
||||
|
||||
// discard degenerate faces
|
||||
is_degenerate = 0;
|
||||
if( equals_v3v3(verts[0], verts[1]) || equals_v3v3(verts[0], verts[2]) || equals_v3v3(verts[1], verts[2]) ||
|
||||
equals_v2v2(tex_coords[0], tex_coords[1]) || equals_v2v2(tex_coords[0], tex_coords[2]) || equals_v2v2(tex_coords[1], tex_coords[2]) )
|
||||
{
|
||||
is_degenerate = 1;
|
||||
}
|
||||
|
||||
// verify last vertex as well if this is a quad
|
||||
if ( is_degenerate==0 && nr_verts==4 )
|
||||
{
|
||||
if( equals_v3v3(verts[3], verts[0]) || equals_v3v3(verts[3], verts[1]) || equals_v3v3(verts[3], verts[2]) ||
|
||||
equals_v2v2(tex_coords[3], tex_coords[0]) || equals_v2v2(tex_coords[3], tex_coords[1]) || equals_v2v2(tex_coords[3], tex_coords[2]) )
|
||||
{
|
||||
is_degenerate = 1;
|
||||
}
|
||||
|
||||
// verify the winding is consistent
|
||||
if ( is_degenerate==0 )
|
||||
{
|
||||
float prev_edge[2];
|
||||
int is_signed = 0;
|
||||
sub_v2_v2v2(prev_edge, tex_coords[0], tex_coords[3]);
|
||||
|
||||
i = 0;
|
||||
while ( is_degenerate==0 && i<4 )
|
||||
{
|
||||
float cur_edge[2], signed_area;
|
||||
sub_v2_v2v2(cur_edge, tex_coords[(i+1)&0x3], tex_coords[i]);
|
||||
signed_area = prev_edge[0]*cur_edge[1] - prev_edge[1]*cur_edge[0];
|
||||
if ( i==0 ) is_signed = signed_area<0.0f ? 1 : 0;
|
||||
else if((is_signed!=0)!=(signed_area<0.0f)) is_degenerate=1;
|
||||
|
||||
if ( is_degenerate==0 )
|
||||
{
|
||||
copy_v2_v2(prev_edge, cur_edge);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// proceed if not a degenerate face
|
||||
if ( is_degenerate==0 )
|
||||
{
|
||||
int nr_tris_to_pile=0;
|
||||
// quads split at shortest diagonal
|
||||
int offs = 0; // initial triangulation is 0,1,2 and 0, 2, 3
|
||||
if ( nr_verts==4 )
|
||||
{
|
||||
float pos_len_diag0, pos_len_diag1;
|
||||
float vtmp[3];
|
||||
sub_v3_v3v3(vtmp, verts[2], verts[0]);
|
||||
pos_len_diag0 = dot_v3v3(vtmp, vtmp);
|
||||
sub_v3_v3v3(vtmp, verts[3], verts[1]);
|
||||
pos_len_diag1 = dot_v3v3(vtmp, vtmp);
|
||||
|
||||
if(pos_len_diag1<pos_len_diag0)
|
||||
offs=1; // alter split
|
||||
else if(pos_len_diag0==pos_len_diag1) // do UV check instead
|
||||
{
|
||||
float tex_len_diag0, tex_len_diag1;
|
||||
|
||||
sub_v2_v2v2(vtmp, tex_coords[2], tex_coords[0]);
|
||||
tex_len_diag0 = dot_v2v2(vtmp, vtmp);
|
||||
sub_v2_v2v2(vtmp, tex_coords[3], tex_coords[1]);
|
||||
tex_len_diag1 = dot_v2v2(vtmp, vtmp);
|
||||
|
||||
if(tex_len_diag1<tex_len_diag0)
|
||||
{
|
||||
offs=1; // alter split
|
||||
}
|
||||
}
|
||||
}
|
||||
nr_tris_to_pile = nr_verts-2 ;
|
||||
if ( nr_tris_to_pile==1 || nr_tris_to_pile==2 )
|
||||
{
|
||||
const int indices[] = {offs+0, offs+1, offs+2, offs+0, offs+2, (offs+3)&0x3 };
|
||||
int t;
|
||||
for ( t=0; t<nr_tris_to_pile; t++ )
|
||||
{
|
||||
float f2x_area_uv;
|
||||
float * p0 = verts[indices[t*3+0]];
|
||||
float * p1 = verts[indices[t*3+1]];
|
||||
float * p2 = verts[indices[t*3+2]];
|
||||
|
||||
float edge_t0[2], edge_t1[2];
|
||||
sub_v2_v2v2(edge_t0, tex_coords[indices[t*3+1]], tex_coords[indices[t*3+0]]);
|
||||
sub_v2_v2v2(edge_t1, tex_coords[indices[t*3+2]], tex_coords[indices[t*3+0]]);
|
||||
|
||||
f2x_area_uv = fabsf(edge_t0[0]*edge_t1[1] - edge_t0[1]*edge_t1[0]);
|
||||
if ( f2x_area_uv>FLT_EPSILON )
|
||||
{
|
||||
float norm[3], v0[3], v1[3], f2x_surf_area, fsurf_ratio;
|
||||
sub_v3_v3v3(v0, p1, p0);
|
||||
sub_v3_v3v3(v1, p2, p0);
|
||||
cross_v3_v3v3(norm, v0, v1);
|
||||
|
||||
f2x_surf_area = len_v3(norm);
|
||||
fsurf_ratio = f2x_surf_area/f2x_area_uv; // tri area divided by texture area
|
||||
|
||||
++nr_accumulated;
|
||||
dsum += (double)(fsurf_ratio);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// finalize
|
||||
{
|
||||
const float avg_area_ratio = (nr_accumulated>0) ? ((float)(dsum / nr_accumulated)) : 1.0f;
|
||||
const float use_as_render_bump_scale = sqrtf(avg_area_ratio); // use width of average surface ratio as your bump scale
|
||||
dm->auto_bump_scale = use_as_render_bump_scale;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dm->auto_bump_scale = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs, DMVertexAttribs *attribs)
|
||||
{
|
||||
CustomData *vdata, *fdata, *tfdata = NULL;
|
||||
@ -1851,6 +2005,10 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs,
|
||||
else
|
||||
tfdata = fdata;
|
||||
|
||||
/* calc auto bump scale if necessary */
|
||||
if(dm->auto_bump_scale<=0.0f)
|
||||
DM_calc_auto_bump_scale(dm);
|
||||
|
||||
/* add a tangent layer if necessary */
|
||||
for(b = 0; b < gattribs->totlayer; b++)
|
||||
if(gattribs->layer[b].type == CD_TANGENT)
|
||||
|
@ -83,7 +83,8 @@ typedef enum GPUBuiltin {
|
||||
GPU_INVERSE_OBJECT_MATRIX = 8,
|
||||
GPU_VIEW_POSITION = 16,
|
||||
GPU_VIEW_NORMAL = 32,
|
||||
GPU_OBCOLOR = 64
|
||||
GPU_OBCOLOR = 64,
|
||||
GPU_AUTO_BUMPSCALE = 128
|
||||
} GPUBuiltin;
|
||||
|
||||
typedef enum GPUBlendMode {
|
||||
@ -129,7 +130,7 @@ void GPU_material_free(struct Material *ma);
|
||||
void GPU_materials_free(void);
|
||||
|
||||
void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double time, int mipmap);
|
||||
void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[][4], float viewmat[][4], float viewinv[][4], float obcol[4]);
|
||||
void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[][4], float viewmat[][4], float viewinv[][4], float obcol[4], float autobumpscale);
|
||||
void GPU_material_unbind(GPUMaterial *material);
|
||||
int GPU_material_bound(GPUMaterial *material);
|
||||
|
||||
@ -162,6 +163,7 @@ typedef enum GPUDynamicType {
|
||||
GPU_DYNAMIC_OBJECT_VIEWIMAT = 3,
|
||||
GPU_DYNAMIC_OBJECT_IMAT = 4,
|
||||
GPU_DYNAMIC_OBJECT_COLOR = 5,
|
||||
GPU_DYNAMIC_OBJECT_AUTOBUMPSCALE = 15,
|
||||
GPU_DYNAMIC_LAMP_FIRST = 6,
|
||||
GPU_DYNAMIC_LAMP_DYNVEC = 6,
|
||||
GPU_DYNAMIC_LAMP_DYNCO = 7,
|
||||
|
@ -344,6 +344,8 @@ const char *GPU_builtin_name(GPUBuiltin builtin)
|
||||
return "varnormal";
|
||||
else if(builtin == GPU_OBCOLOR)
|
||||
return "unfobcolor";
|
||||
else if(builtin == GPU_AUTO_BUMPSCALE)
|
||||
return "unfobautobumpscale";
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
@ -60,6 +60,7 @@
|
||||
#include "BKE_node.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_scene.h"
|
||||
#include "BKE_DerivedMesh.h"
|
||||
|
||||
#include "BLI_threads.h"
|
||||
#include "BLI_blenlib.h"
|
||||
@ -1159,7 +1160,7 @@ int GPU_enable_material(int nr, void *attribs)
|
||||
gpumat = GPU_material_from_blender(GMS.gscene, mat);
|
||||
GPU_material_vertex_attributes(gpumat, gattribs);
|
||||
GPU_material_bind(gpumat, GMS.gob->lay, GMS.glay, 1.0, !(GMS.gob->mode & OB_MODE_TEXTURE_PAINT));
|
||||
GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, GMS.gviewmat, GMS.gviewinv, GMS.gob->col);
|
||||
GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, GMS.gviewmat, GMS.gviewinv, GMS.gob->col, GMS.gob->derivedFinal->auto_bump_scale);
|
||||
GMS.gboundmat= mat;
|
||||
|
||||
/* for glsl use alpha blend mode, unless it's set to solid and
|
||||
|
@ -94,7 +94,7 @@ struct GPUMaterial {
|
||||
/* for passing uniforms */
|
||||
int viewmatloc, invviewmatloc;
|
||||
int obmatloc, invobmatloc;
|
||||
int obcolloc;
|
||||
int obcolloc, obautobumpscaleloc;
|
||||
|
||||
ListBase lamps;
|
||||
};
|
||||
@ -212,7 +212,8 @@ static int GPU_material_construct_end(GPUMaterial *material)
|
||||
material->invobmatloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_INVERSE_OBJECT_MATRIX));
|
||||
if(material->builtins & GPU_OBCOLOR)
|
||||
material->obcolloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_OBCOLOR));
|
||||
|
||||
if(material->builtins & GPU_AUTO_BUMPSCALE)
|
||||
material->obautobumpscaleloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_AUTO_BUMPSCALE));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -273,7 +274,7 @@ void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double tim
|
||||
}
|
||||
}
|
||||
|
||||
void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[][4], float viewmat[][4], float viewinv[][4], float obcol[4])
|
||||
void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[][4], float viewmat[][4], float viewinv[][4], float obcol[4], float autobumpscale)
|
||||
{
|
||||
if(material->pass) {
|
||||
GPUShader *shader = GPU_pass_shader(material->pass);
|
||||
@ -300,7 +301,9 @@ void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[][4], float v
|
||||
CLAMP(col[3], 0.0f, 1.0f);
|
||||
GPU_shader_uniform_vector(shader, material->obcolloc, 4, 1, col);
|
||||
}
|
||||
|
||||
if(material->builtins & GPU_AUTO_BUMPSCALE) {
|
||||
GPU_shader_uniform_vector(shader, material->obautobumpscaleloc, 1, 1, &autobumpscale);
|
||||
}
|
||||
/* update lamps */
|
||||
for(nlink=material->lamps.first; nlink; nlink=nlink->next) {
|
||||
lamp= nlink->data;
|
||||
@ -1087,8 +1090,7 @@ static void do_material_tex(GPUShadeInput *shi)
|
||||
/* ntap bumpmap image */
|
||||
int iBumpSpace;
|
||||
float ima_x, ima_y;
|
||||
float hScale = 0.1f; // compatibility adjustment factor for all bumpspace types
|
||||
float hScaleTex = 13.0f; // factor for scaling texspace bumps
|
||||
float hScale;
|
||||
|
||||
float imag_tspace_dimension_x = 1024.0f; // only used for texture space variant
|
||||
float aspect = 1.0f;
|
||||
@ -1096,16 +1098,35 @@ static void do_material_tex(GPUShadeInput *shi)
|
||||
GPUNodeLink *surf_pos = GPU_builtin(GPU_VIEW_POSITION);
|
||||
GPUNodeLink *vR1, *vR2;
|
||||
GPUNodeLink *dBs, *dBt, *fDet;
|
||||
|
||||
|
||||
hScale = 0.1; // compatibility adjustment factor for all bumpspace types
|
||||
if( mtex->texflag & MTEX_BUMP_TEXTURESPACE )
|
||||
hScale = hScaleTex;
|
||||
hScale = 13.0f; // factor for scaling texspace bumps
|
||||
else if(found_deriv_map!=0)
|
||||
hScale = 1.0f;
|
||||
|
||||
// resolve texture resolution
|
||||
if( (mtex->texflag & MTEX_BUMP_TEXTURESPACE) || found_deriv_map ) {
|
||||
ImBuf *ibuf= BKE_image_get_ibuf(tex->ima, &tex->iuser);
|
||||
ima_x= 512.0f; ima_y= 512.f; // prevent calling textureSize, glsl 1.3 only
|
||||
if(ibuf) {
|
||||
ima_x= ibuf->x;
|
||||
ima_y= ibuf->y;
|
||||
aspect = ((float) ima_y) / ima_x;
|
||||
}
|
||||
}
|
||||
|
||||
// The negate on norfac is done because the
|
||||
// normal in the renderer points inward which corresponds
|
||||
// to inverting the bump map. Should this ever change
|
||||
// this negate must be removed.
|
||||
norfac = -hScale * mtex->norfac;
|
||||
if(found_deriv_map) norfac /= sqrtf(ima_x*ima_y);
|
||||
|
||||
tnorfac = GPU_uniform(&norfac);
|
||||
|
||||
if(found_deriv_map)
|
||||
GPU_link(mat, "math_multiply", tnorfac, GPU_builtin(GPU_AUTO_BUMPSCALE), &tnorfac);
|
||||
|
||||
if(GPU_link_changed(stencil))
|
||||
GPU_link(mat, "math_multiply", tnorfac, stencil, &tnorfac);
|
||||
@ -1152,17 +1173,6 @@ static void do_material_tex(GPUShadeInput *shi)
|
||||
|
||||
iBumpSpacePrev = iBumpSpace;
|
||||
}
|
||||
|
||||
// resolve texture resolution
|
||||
if( (mtex->texflag & MTEX_BUMP_TEXTURESPACE) || found_deriv_map ) {
|
||||
ImBuf *ibuf= BKE_image_get_ibuf(tex->ima, &tex->iuser);
|
||||
ima_x= 512.0f; ima_y= 512.f; // prevent calling textureSize, glsl 1.3 only
|
||||
if(ibuf) {
|
||||
ima_x= ibuf->x;
|
||||
ima_y= ibuf->y;
|
||||
aspect = ((float) ima_y) / ima_x;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(found_deriv_map) {
|
||||
@ -1703,6 +1713,7 @@ GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma)
|
||||
{ GPU_OBJECT_MATRIX, GPU_DYNAMIC_OBJECT_MAT, GPU_DATA_16F },
|
||||
{ GPU_INVERSE_OBJECT_MATRIX, GPU_DYNAMIC_OBJECT_IMAT, GPU_DATA_16F },
|
||||
{ GPU_OBCOLOR, GPU_DYNAMIC_OBJECT_COLOR, GPU_DATA_4F },
|
||||
{ GPU_AUTO_BUMPSCALE, GPU_DYNAMIC_OBJECT_AUTOBUMPSCALE, GPU_DATA_1F },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
@ -87,6 +87,7 @@ PyInit_gpu(void)
|
||||
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_VIEWIMAT);
|
||||
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_IMAT);
|
||||
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_COLOR);
|
||||
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_AUTOBUMPSCALE);
|
||||
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DYNVEC);
|
||||
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DYNCO);
|
||||
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DYNIMAT);
|
||||
|
@ -1932,11 +1932,13 @@ static int ntap_bump_compute(NTapBump *ntap_bump, ShadeInput *shi, MTex *mtex, T
|
||||
float *nvec = texres->nor;
|
||||
texres->nor = NULL;
|
||||
|
||||
if( mtex->texflag & MTEX_BUMP_TEXTURESPACE ) {
|
||||
if(tex->ima)
|
||||
Hscale *= 13.0f; // appears to be a sensible default value
|
||||
} else
|
||||
Hscale *= 0.1f; // factor 0.1 proved to look like the previous bump code
|
||||
if(found_deriv_map==0) {
|
||||
if( mtex->texflag & MTEX_BUMP_TEXTURESPACE ) {
|
||||
if(tex->ima)
|
||||
Hscale *= 13.0f; // appears to be a sensible default value
|
||||
} else
|
||||
Hscale *= 0.1f; // factor 0.1 proved to look like the previous bump code
|
||||
}
|
||||
|
||||
if( !ntap_bump->init_done ) {
|
||||
copy_v3_v3(ntap_bump->vNacc, shi->vn);
|
||||
@ -1958,15 +1960,18 @@ static int ntap_bump_compute(NTapBump *ntap_bump, ShadeInput *shi, MTex *mtex, T
|
||||
}
|
||||
|
||||
if(found_deriv_map) {
|
||||
float dBdu, dBdv;
|
||||
float dBdu, dBdv, auto_bump;
|
||||
float s = 1; // negate this if flipped texture coordinate
|
||||
texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt);
|
||||
rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, texres);
|
||||
|
||||
auto_bump = shi->obr->ob->derivedFinal->auto_bump_scale;
|
||||
auto_bump /= sqrtf((float) (dimx*dimy));
|
||||
|
||||
// this variant using a derivative map is described here
|
||||
// http://mmikkelsen3d.blogspot.com/2011/07/derivative-maps.html
|
||||
dBdu = Hscale*dimx*(2*texres->tr-1);
|
||||
dBdv = Hscale*dimy*(2*texres->tg-1);
|
||||
dBdu = auto_bump*Hscale*dimx*(2*texres->tr-1);
|
||||
dBdv = auto_bump*Hscale*dimy*(2*texres->tg-1);
|
||||
|
||||
dHdx = dBdu*dxt[0] + s * dBdv*dxt[1];
|
||||
dHdy = dBdu*dyt[0] + s * dBdv*dyt[1];
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_DerivedMesh.h"
|
||||
|
||||
#include "BL_BlenderShader.h"
|
||||
#include "BL_Material.h"
|
||||
@ -146,7 +147,7 @@ void BL_BlenderShader::Update(const RAS_MeshSlot & ms, RAS_IRasterizer* rasty )
|
||||
else
|
||||
obcol[0]= obcol[1]= obcol[2]= obcol[3]= 1.0f;
|
||||
|
||||
GPU_material_bind_uniforms(gpumat, obmat, viewmat, viewinvmat, obcol);
|
||||
GPU_material_bind_uniforms(gpumat, obmat, viewmat, viewinvmat, obcol, ms.m_pDerivedMesh->auto_bump_scale);
|
||||
|
||||
mAlphaBlend = GPU_material_alpha_blend(gpumat, obcol);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user