Properly handle vertex color color space for Cycles GLSL
A bit tricky, need to pass additional information about what the attribute is and how to deal with it. BI path stays unchanged, just to make things simplier for now. Fixes T48555: Cycles GLSL- Incorrect Vertex Color results from Attribute node
This commit is contained in:
parent
19cfc84328
commit
e9c8917e10
Notes:
blender-bot
2023-02-14 10:21:10 +01:00
Referenced by issue #48555, Cycles GLSL- Incorrect Vertex Color results from Attribute node.
|
@ -757,22 +757,22 @@ void DM_update_weight_mcol(
|
|||
typedef struct DMVertexAttribs {
|
||||
struct {
|
||||
struct MLoopUV *array;
|
||||
int em_offset, gl_index, gl_texco;
|
||||
int em_offset, gl_index, gl_texco, gl_info_index;
|
||||
} tface[MAX_MTFACE];
|
||||
|
||||
struct {
|
||||
struct MLoopCol *array;
|
||||
int em_offset, gl_index;
|
||||
int em_offset, gl_index, gl_info_index;
|
||||
} mcol[MAX_MCOL];
|
||||
|
||||
struct {
|
||||
float (*array)[4];
|
||||
int em_offset, gl_index;
|
||||
int em_offset, gl_index, gl_info_index;
|
||||
} tang[MAX_MTFACE];
|
||||
|
||||
struct {
|
||||
float (*array)[3];
|
||||
int em_offset, gl_index, gl_texco;
|
||||
int em_offset, gl_index, gl_texco, gl_info_index;
|
||||
} orco;
|
||||
|
||||
int tottface, totmcol, tottang, totorco;
|
||||
|
|
|
@ -3673,6 +3673,7 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs,
|
|||
}
|
||||
|
||||
attribs->tface[a].gl_index = gattribs->layer[b].glindex;
|
||||
attribs->tface[a].gl_info_index = gattribs->layer[b].glinfoindoex;
|
||||
attribs->tface[a].gl_texco = gattribs->layer[b].gltexco;
|
||||
}
|
||||
else if (type == CD_MCOL) {
|
||||
|
@ -3696,6 +3697,7 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs,
|
|||
}
|
||||
|
||||
attribs->mcol[a].gl_index = gattribs->layer[b].glindex;
|
||||
attribs->mcol[a].gl_info_index = gattribs->layer[b].glinfoindoex;
|
||||
}
|
||||
else if (type == CD_TANGENT) {
|
||||
/* note, even with 'is_editmesh' this uses the derived-meshes loop data */
|
||||
|
@ -3718,6 +3720,7 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs,
|
|||
}
|
||||
|
||||
attribs->tang[a].gl_index = gattribs->layer[b].glindex;
|
||||
attribs->tang[a].gl_info_index = gattribs->layer[b].glinfoindoex;
|
||||
}
|
||||
else if (type == CD_ORCO) {
|
||||
/* original coordinates */
|
||||
|
@ -3737,6 +3740,7 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs,
|
|||
|
||||
attribs->orco.gl_index = gattribs->layer[b].glindex;
|
||||
attribs->orco.gl_texco = gattribs->layer[b].gltexco;
|
||||
attribs->orco.gl_info_index = gattribs->layer[b].glinfoindoex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3765,6 +3769,7 @@ void DM_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert,
|
|||
glTexCoord3fv(orco);
|
||||
else
|
||||
glVertexAttrib3fv(attribs->orco.gl_index, orco);
|
||||
glUniform1i(attribs->orco.gl_info_index, 0);
|
||||
}
|
||||
|
||||
/* uv texture coordinates */
|
||||
|
@ -3783,6 +3788,7 @@ void DM_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert,
|
|||
glTexCoord2fv(uv);
|
||||
else
|
||||
glVertexAttrib2fv(attribs->tface[b].gl_index, uv);
|
||||
glUniform1i(attribs->tface[b].gl_info_index, 0);
|
||||
}
|
||||
|
||||
/* vertex colors */
|
||||
|
@ -3798,6 +3804,7 @@ void DM_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert,
|
|||
}
|
||||
|
||||
glVertexAttrib4fv(attribs->mcol[b].gl_index, col);
|
||||
glUniform1i(attribs->mcol[b].gl_info_index, GPU_ATTR_INFO_SRGB);
|
||||
}
|
||||
|
||||
/* tangent for normal mapping */
|
||||
|
@ -3807,6 +3814,7 @@ void DM_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert,
|
|||
const float *tang = (array) ? array[a * 4 + vert] : zero;
|
||||
glVertexAttrib4fv(attribs->tang[b].gl_index, tang);
|
||||
}
|
||||
glUniform1i(attribs->tang[b].gl_info_index, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1032,6 +1032,7 @@ static void cdDM_drawMappedFacesGLSL(
|
|||
|
||||
if (matconv[a].attribs.totorco && matconv[a].attribs.orco.array) {
|
||||
matconv[a].datatypes[numdata].index = matconv[a].attribs.orco.gl_index;
|
||||
matconv[a].datatypes[numdata].info_index = matconv[a].attribs.orco.gl_info_index;
|
||||
matconv[a].datatypes[numdata].size = 3;
|
||||
matconv[a].datatypes[numdata].type = GL_FLOAT;
|
||||
numdata++;
|
||||
|
@ -1039,6 +1040,7 @@ static void cdDM_drawMappedFacesGLSL(
|
|||
for (b = 0; b < matconv[a].attribs.tottface; b++) {
|
||||
if (matconv[a].attribs.tface[b].array) {
|
||||
matconv[a].datatypes[numdata].index = matconv[a].attribs.tface[b].gl_index;
|
||||
matconv[a].datatypes[numdata].info_index = matconv[a].attribs.tface[b].gl_info_index;
|
||||
matconv[a].datatypes[numdata].size = 2;
|
||||
matconv[a].datatypes[numdata].type = GL_FLOAT;
|
||||
numdata++;
|
||||
|
@ -1047,6 +1049,7 @@ static void cdDM_drawMappedFacesGLSL(
|
|||
for (b = 0; b < matconv[a].attribs.totmcol; b++) {
|
||||
if (matconv[a].attribs.mcol[b].array) {
|
||||
matconv[a].datatypes[numdata].index = matconv[a].attribs.mcol[b].gl_index;
|
||||
matconv[a].datatypes[numdata].info_index = matconv[a].attribs.mcol[b].gl_info_index;
|
||||
matconv[a].datatypes[numdata].size = 4;
|
||||
matconv[a].datatypes[numdata].type = GL_UNSIGNED_BYTE;
|
||||
numdata++;
|
||||
|
@ -1055,6 +1058,7 @@ static void cdDM_drawMappedFacesGLSL(
|
|||
for (b = 0; b < matconv[a].attribs.tottang; b++) {
|
||||
if (matconv[a].attribs.tang[b].array) {
|
||||
matconv[a].datatypes[numdata].index = matconv[a].attribs.tang[b].gl_index;
|
||||
matconv[a].datatypes[numdata].info_index = matconv[a].attribs.tang[b].gl_info_index;
|
||||
matconv[a].datatypes[numdata].size = 4;
|
||||
matconv[a].datatypes[numdata].type = GL_FLOAT;
|
||||
numdata++;
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "GPU_glew.h"
|
||||
#include "GPU_buffers.h"
|
||||
#include "GPU_shader.h"
|
||||
#include "GPU_basic_shader.h"
|
||||
|
||||
|
@ -1431,6 +1432,7 @@ static void emdm_pass_attrib_vertex_glsl(const DMVertexAttribs *attribs, const B
|
|||
glTexCoord3fv(orco);
|
||||
else
|
||||
glVertexAttrib3fv(attribs->orco.gl_index, orco);
|
||||
glUniform1i(attribs->orco.gl_info_index, 0);
|
||||
}
|
||||
for (i = 0; i < attribs->tottface; i++) {
|
||||
const float *uv;
|
||||
|
@ -1447,6 +1449,7 @@ static void emdm_pass_attrib_vertex_glsl(const DMVertexAttribs *attribs, const B
|
|||
glTexCoord2fv(uv);
|
||||
else
|
||||
glVertexAttrib2fv(attribs->tface[i].gl_index, uv);
|
||||
glUniform1i(attribs->tface[i].gl_info_index, 0);
|
||||
}
|
||||
for (i = 0; i < attribs->totmcol; i++) {
|
||||
GLubyte col[4];
|
||||
|
@ -1458,6 +1461,7 @@ static void emdm_pass_attrib_vertex_glsl(const DMVertexAttribs *attribs, const B
|
|||
col[0] = 0; col[1] = 0; col[2] = 0; col[3] = 0;
|
||||
}
|
||||
glVertexAttrib4ubv(attribs->mcol[i].gl_index, col);
|
||||
glUniform1i(attribs->mcol[i].gl_info_index, GPU_ATTR_INFO_SRGB);
|
||||
}
|
||||
|
||||
for (i = 0; i < attribs->tottang; i++) {
|
||||
|
@ -1469,6 +1473,7 @@ static void emdm_pass_attrib_vertex_glsl(const DMVertexAttribs *attribs, const B
|
|||
tang = zero;
|
||||
}
|
||||
glVertexAttrib4fv(attribs->tang[i].gl_index, tang);
|
||||
glUniform1i(attribs->tang[i].gl_info_index, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2996,6 +2996,7 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm,
|
|||
|
||||
if (matconv[a].attribs.totorco && matconv[a].attribs.orco.array) {
|
||||
matconv[a].datatypes[numdata].index = matconv[a].attribs.orco.gl_index;
|
||||
matconv[a].datatypes[numdata].info_index = matconv[a].attribs.orco.gl_info_index;
|
||||
matconv[a].datatypes[numdata].size = 3;
|
||||
matconv[a].datatypes[numdata].type = GL_FLOAT;
|
||||
numdata++;
|
||||
|
@ -3003,6 +3004,7 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm,
|
|||
for (b = 0; b < matconv[a].attribs.tottface; b++) {
|
||||
if (matconv[a].attribs.tface[b].array) {
|
||||
matconv[a].datatypes[numdata].index = matconv[a].attribs.tface[b].gl_index;
|
||||
matconv[a].datatypes[numdata].info_index = matconv[a].attribs.tface[b].gl_info_index;
|
||||
matconv[a].datatypes[numdata].size = 2;
|
||||
matconv[a].datatypes[numdata].type = GL_FLOAT;
|
||||
numdata++;
|
||||
|
@ -3011,6 +3013,7 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm,
|
|||
for (b = 0; b < matconv[a].attribs.totmcol; b++) {
|
||||
if (matconv[a].attribs.mcol[b].array) {
|
||||
matconv[a].datatypes[numdata].index = matconv[a].attribs.mcol[b].gl_index;
|
||||
matconv[a].datatypes[numdata].info_index = matconv[a].attribs.mcol[b].gl_info_index;
|
||||
matconv[a].datatypes[numdata].size = 4;
|
||||
matconv[a].datatypes[numdata].type = GL_UNSIGNED_BYTE;
|
||||
numdata++;
|
||||
|
@ -3019,6 +3022,7 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm,
|
|||
for (b = 0; b < matconv[a].attribs.tottang; b++) {
|
||||
if (matconv[a].attribs.tottang && matconv[a].attribs.tang[b].array) {
|
||||
matconv[a].datatypes[numdata].index = matconv[a].attribs.tang[b].gl_index;
|
||||
matconv[a].datatypes[numdata].info_index = matconv[a].attribs.tang[b].gl_info_index;
|
||||
matconv[a].datatypes[numdata].size = 4;
|
||||
matconv[a].datatypes[numdata].type = GL_FLOAT;
|
||||
numdata++;
|
||||
|
|
|
@ -147,6 +147,7 @@ typedef struct GPUVertPointLink {
|
|||
/* used for GLSL materials */
|
||||
typedef struct GPUAttrib {
|
||||
int index;
|
||||
int info_index;
|
||||
int size;
|
||||
int type;
|
||||
} GPUAttrib;
|
||||
|
@ -179,6 +180,10 @@ typedef enum {
|
|||
GPU_BINDING_INDEX = 1,
|
||||
} GPUBindingType;
|
||||
|
||||
typedef enum {
|
||||
GPU_ATTR_INFO_SRGB = (1 << 0),
|
||||
} GPUAttrInfo;
|
||||
|
||||
/* called before drawing */
|
||||
void GPU_vertex_setup(struct DerivedMesh *dm);
|
||||
void GPU_normal_setup(struct DerivedMesh *dm);
|
||||
|
|
|
@ -104,6 +104,7 @@ typedef struct GPUVertexAttribs {
|
|||
struct {
|
||||
int type;
|
||||
int glindex;
|
||||
int glinfoindoex;
|
||||
int gltexco;
|
||||
int attribid;
|
||||
char name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */
|
||||
|
|
|
@ -822,6 +822,12 @@ void GPU_interleaved_attrib_setup(GPUBuffer *buffer, GPUAttrib data[], int numda
|
|||
|
||||
for (i = 0; i < numdata; i++) {
|
||||
glEnableVertexAttribArray(data[i].index);
|
||||
int info = 0;
|
||||
if (data[i].type == GL_UNSIGNED_BYTE) {
|
||||
info |= GPU_ATTR_INFO_SRGB;
|
||||
}
|
||||
glUniform1i(data[i].info_index, info);
|
||||
|
||||
glVertexAttribPointer(data[i].index, data[i].size, data[i].type,
|
||||
GL_TRUE, elementsize, BUFFER_OFFSET(offset));
|
||||
offset += data[i].size * GPU_typesize(data[i].type);
|
||||
|
|
|
@ -749,6 +749,7 @@ static char *code_generate_vertex(ListBase *nodes, const GPUMatType type)
|
|||
BLI_dynstr_appendf(ds, "%s %s att%d;\n",
|
||||
GLEW_VERSION_3_0 ? "in" : "attribute",
|
||||
GPU_DATATYPE_STR[input->type], input->attribid);
|
||||
BLI_dynstr_appendf(ds, "uniform int att%d_info;\n", input->attribid);
|
||||
BLI_dynstr_appendf(ds, "%s %s var%d;\n",
|
||||
GLEW_VERSION_3_0 ? "out" : "varying",
|
||||
GPU_DATATYPE_STR[input->type], input->attribid);
|
||||
|
@ -801,7 +802,8 @@ static char *code_generate_vertex(ListBase *nodes, const GPUMatType type)
|
|||
BLI_dynstr_appendf(ds, "#ifndef USE_OPENSUBDIV\n");
|
||||
}
|
||||
#endif
|
||||
BLI_dynstr_appendf(ds, "\tvar%d = att%d;\n", input->attribid, input->attribid);
|
||||
BLI_dynstr_appendf(ds, "\tset_var_from_attr(att%d, att%d_info, var%d);\n",
|
||||
input->attribid, input->attribid, input->attribid);
|
||||
#ifdef WITH_OPENSUBDIV
|
||||
if (is_mtface) {
|
||||
BLI_dynstr_appendf(ds, "#endif\n");
|
||||
|
|
|
@ -212,6 +212,9 @@ static void gpu_material_set_attrib_id(GPUMaterial *material)
|
|||
BLI_snprintf(name, sizeof(name), "att%d", attribs->layer[a].attribid);
|
||||
attribs->layer[a].glindex = GPU_shader_get_attribute(shader, name);
|
||||
|
||||
BLI_snprintf(name, sizeof(name), "att%d_info", attribs->layer[a].attribid);
|
||||
attribs->layer[a].glinfoindoex = GPU_shader_get_uniform(shader, name);
|
||||
|
||||
if (attribs->layer[a].glindex >= 0) {
|
||||
attribs->layer[b] = attribs->layer[a];
|
||||
b++;
|
||||
|
|
|
@ -2668,9 +2668,6 @@ void node_gamma(vec4 col, float gamma, out vec4 outcol)
|
|||
|
||||
void node_attribute(vec3 attr, out vec4 outcol, out vec3 outvec, out float outf)
|
||||
{
|
||||
/* TODO(sergey): This needs linearization for vertex color.
|
||||
* But how to detect cases when input is linear and when it's srgb?
|
||||
*/
|
||||
outcol = vec4(attr, 1.0);
|
||||
outvec = attr;
|
||||
outf = (attr.x + attr.y + attr.z) / 3.0;
|
||||
|
|
|
@ -14,6 +14,58 @@ varying vec3 varnormal;
|
|||
varying float gl_ClipDistance[6];
|
||||
#endif
|
||||
|
||||
float srgb_to_linearrgb(float c)
|
||||
{
|
||||
if (c < 0.04045)
|
||||
return (c < 0.0) ? 0.0 : c * (1.0 / 12.92);
|
||||
else
|
||||
return pow((c + 0.055) * (1.0 / 1.055), 2.4);
|
||||
}
|
||||
|
||||
void srgb_to_linearrgb(vec3 col_from, out vec3 col_to)
|
||||
{
|
||||
col_to.r = srgb_to_linearrgb(col_from.r);
|
||||
col_to.g = srgb_to_linearrgb(col_from.g);
|
||||
col_to.b = srgb_to_linearrgb(col_from.b);
|
||||
}
|
||||
|
||||
void srgb_to_linearrgb(vec4 col_from, out vec4 col_to)
|
||||
{
|
||||
col_to.r = srgb_to_linearrgb(col_from.r);
|
||||
col_to.g = srgb_to_linearrgb(col_from.g);
|
||||
col_to.b = srgb_to_linearrgb(col_from.b);
|
||||
col_to.a = col_from.a;
|
||||
}
|
||||
|
||||
bool is_srgb(int info)
|
||||
{
|
||||
#ifdef USE_NEW_SHADING
|
||||
return (info == 1)? true: false;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void set_var_from_attr(vec3 attr, int info, out vec3 var)
|
||||
{
|
||||
if (is_srgb(info)) {
|
||||
srgb_to_linearrgb(attr, var);
|
||||
}
|
||||
else {
|
||||
var = attr;
|
||||
}
|
||||
}
|
||||
|
||||
void set_var_from_attr(vec4 attr, int info, out vec4 var)
|
||||
{
|
||||
if (is_srgb(info)) {
|
||||
srgb_to_linearrgb(attr, var);
|
||||
}
|
||||
else {
|
||||
var = attr;
|
||||
}
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
#ifndef USE_OPENSUBDIV
|
||||
|
|
Loading…
Reference in New Issue