*/}}
Quellcode durchsuchen

Use straight alpha for legacy

YimingWu vor 4 Tagen
Ursprung
Commit
6542c33ac5
3 geänderte Dateien mit 100 neuen und 58 gelöschten Zeilen
  1. 68 44
      ouroperations.c
  2. 5 3
      ourpaint.h
  3. 27 11
      ourshader.cpp

+ 68 - 44
ouroperations.c

@@ -317,18 +317,22 @@ void ourui_LayersPanel(laUiList *uil, laPropPack *This, laPropPack *DetachedProp
         laUiItem* b3=laOnConditionThat(uil,c,laPropExpression(&pigui->PP,""));{
 
         }laElse(uil,b3);{
-            b=laBeginRow(uil,c,1,0);
-            laShowLabel(uil,c,"Color:",0,0);
-            laShowItemFull(uil,c,0,"our.canvas.background_color",LA_WIDGET_FLOAT_COLOR,0,0,0);
-            laEndRow(uil,b);
-            b=laBeginRow(uil,c,1,0);
-            laShowLabel(uil,c,"Pattern:",0,0);
-            laShowItemFull(uil,c,0,"our.canvas.background_type",0,0,0,0)->Flags|=LA_UI_FLAGS_EXPAND|LA_UI_FLAGS_NO_CONFIRM;
-            laEndRow(uil,b);
-            b=laBeginRow(uil,c,1,0);
-            laShowItemFull(uil,c,0,"our.canvas.background_random",0,0,0,0);
-            laShowItemFull(uil,c,0,"our.canvas.background_factor",0,0,0,0);
+            laShowLabel(uil,cl,"Color:",0,0)->Flags|=LA_TEXT_ALIGN_RIGHT;
+            laShowItemFull(uil,cr,0,"our.canvas.background_color",LA_WIDGET_FLOAT_COLOR,0,0,0);
+            
+            laShowLabel(uil,cl,"Pattern:",0,0)->Flags|=LA_TEXT_ALIGN_RIGHT;
+            b=laBeginRow(uil,cr,0,0);
+            laUiItem* sel=laShowItemFull(uil,cr,0,"our.canvas.background_type",0,0,0,0);
+                sel->Flags|=LA_UI_FLAGS_NO_CONFIRM; sel->Expand=1;
+            laShowItemFull(uil,cr,0,"our.canvas.background_factor",0,0,0,0)->Flags|=LA_UI_FLAGS_KNOB;
             laEndRow(uil,b);
+            
+            laShowItemFull(uil,cr,0,"our.canvas.background_random",0,0,0,0);
+            
+            laShowSeparator(uil,c);
+
+            laShowLabel(uil,cl,"Alpha Mode:",0,0)->Flags|=LA_TEXT_ALIGN_RIGHT;
+            laShowItem(uil,cr,0,"our.canvas.alpha_mode")->Flags|=LA_UI_FLAGS_NO_CONFIRM;
         }laEndCondition(uil,b3);
     }laEndCondition(uil,b2);
 }
@@ -382,7 +386,7 @@ void ourui_PigmentDetails(laUiList *uil, laPropPack *This, laPropPack *DetachedP
     laShowItem(uil,cr,This,"pigment.absorption")->Flags|=LA_UI_FLAGS_TRANSPOSE;
     laShowItem(uil,cr,This,"pigment.absorption_density");
 }
-void ourUI_PIGMENT_PREVIEWsPanel(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
+void ourui_PigmentsPreviewPanel(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
     laColumn* c=laFirstColumn(uil); laColumn* cl,*cr; laSplitColumn(uil,c,0.3); cl=laLeftColumn(c,0);cr=laRightColumn(c,0);
     laUiItem* gu; laUiList* guil; laColumn* gc;
     laShowColumnAdjuster(uil,c);
@@ -863,7 +867,7 @@ void our_CanvasSaveOffscreen(tnsOffscreen* off1,tnsOffscreen* off2){
     tnsDrawToOffscreenOnlyBind(off1);
 }
 void our_CanvasDrawTextures(tnsOffscreen* off1,tnsOffscreen* off2){
-    real MultiplyColor[4];
+    real MultiplyColor[4]; int premult=(Our->CanvasVersion<50)?1:(Our->AlphaMode==0);
 
     for(OurLayer* l=Our->Layers.pLast;l;l=l->Item.pPrev){
         if(l->Hide || l->Transparency==1) continue; real a=1-l->Transparency;
@@ -881,18 +885,18 @@ void our_CanvasDrawTextures(tnsOffscreen* off1,tnsOffscreen* off2){
                 if(!l->TexTiles[row][col] || !l->TexTiles[row][col]->Texture) continue;
                 int sx=l->TexTiles[row][col]->l,sy=l->TexTiles[row][col]->b;
                 real pad=(real)OUR_TILE_SEAM/OUR_TILE_W; int seam=OUR_TILE_SEAM;
-                tnsUseTexture2(off2->pColor[0],mixmode);    
+                tnsUseTexture2(off2->pColor[0],mixmode,premult);    
                 tnsDraw2DTextureArg(l->TexTiles[row][col]->Texture,sx+seam,sy+OUR_TILE_W-seam,OUR_TILE_W-seam*2,-OUR_TILE_W+seam*2,MultiplyColor,pad,pad,pad,pad);
                 any=1;
             }
         }
         if(any) tnsFlush();
     }
-    tnsUseTexture2(0,0);
+    tnsUseTexture2(0,0,0);
 }
 void our_CanvasDrawTiles(){
     OurLayer* l=Our->CurrentLayer; if(!l) return;
-    tnsUseImmShader; tnsEnableShaderv(T->immShader); tnsUniformUseTexture(T->immShader,0,0,0,0); tnsUseNoTexture();
+    tnsUseImmShader; tnsEnableShaderv(T->immShader); tnsUniformUseTexture(T->immShader,0,0,0,0,0); tnsUseNoTexture();
     int any=0;
     for(int row=0;row<OUR_TILES_PER_ROW;row++){
         if(!l->TexTiles[row]) continue;
@@ -912,7 +916,7 @@ void our_CanvasDrawTiles(){
     if(any) tnsFlush();
 }
 void our_CanvasDrawCropping(OurCanvasDraw* ocd){
-    tnsUseImmShader(); tnsEnableShaderv(T->immShader); tnsUniformUseTexture(T->immShader,0,0,0,0); tnsUseNoTexture();
+    tnsUseImmShader(); tnsEnableShaderv(T->immShader); tnsUniformUseTexture(T->immShader,0,0,0,0,0); tnsUseNoTexture();
     if(Our->BorderFadeWidth > 1e-6){
         real _H=Our->H,_W=Our->W,_X=Our->X,_Y=Our->Y-Our->H;
         real color[72]={0}; for(int i=1;i<18;i++){ color[i*4+3]=Our->BorderAlpha; }
@@ -1000,7 +1004,7 @@ void our_CanvasDrawReferenceBlock(OurCanvasDraw* ocd){
     real LP=Our->RefPaddings[0]*dpc,RP=LP,TP=Our->RefPaddings[1]*dpc,BP=TP;
     real MM=Our->RefMargins[2]*dpc;
 
-    tnsUseImmShader; tnsEnableShaderv(T->immShader); tnsUniformUseTexture(T->immShader,0,0,0,0); tnsUseNoTexture();
+    tnsUseImmShader; tnsEnableShaderv(T->immShader); tnsUniformUseTexture(T->immShader,0,0,0,0,0); tnsUseNoTexture();
     tnsColor4d(0,0,0,Our->RefAlpha); tnsLineWidth(3.0);
     tnsVertex2d(-W2,H2); tnsVertex2d(W2,H2); tnsVertex2d(W2,-H2); tnsVertex2d(-W2,-H2); tnsPackAs(GL_LINE_LOOP);
     if(Our->ShowRef==2){
@@ -1544,7 +1548,6 @@ void our_RemoveLayer(OurLayer* l, int cleanup){
 int our_MergeLayer(OurLayer* l){
     OurLayer* ol=l->Item.pNext; if(!ol) return 0; int xmin=INT_MAX,xmax=-INT_MAX,ymin=INT_MAX,ymax=-INT_MAX; int seam=OUR_TILE_SEAM;
     if(Our->PigmentMode){
-
         Our->u=&Our->uPigment;
     }else{
         glUseProgram(Our->CompositionProgram);
@@ -2444,7 +2447,12 @@ void our_PaintDoDabsWithSmudgeSegments(OurLayer* l,int tl, int tr, int tu, int t
         glUseProgram(Our->CanvasPigmentProgram);
         Our->u=&Our->uPigment; subroutine_count=1;
     }else{
-        glUseProgram(Our->CanvasProgram);
+        int premult=(Our->CanvasVersion<50)?1:(Our->AlphaMode==0);
+        if(premult){
+            glUseProgram(Our->CanvasProgram);
+        }else{
+            glUseProgram(Our->CanvasStraightProgram);
+        }
         Our->u=&Our->uRGBA; subroutine_count=2;
     }
 
@@ -3812,12 +3820,16 @@ void ourget_PigmentInfo(OurPigmentData* pd,char* buf, char** copy){
     real sum=xyz[0]+xyz[1]+xyz[2]; for(int i=0;i<3;i++){ xyz[i]/=sum; }
     sprintf(buf, "xyz:  %0.4lf %0.4lf %0.4lf\nsRGB: %0.4lf %0.4lf %0.4lf", LA_COLOR3(xyz), LA_COLOR3(rgb));
 }
+void ourset_AlphaMode(void* unused, int a){
+    Our->AlphaMode=a;
+}
 
 int ourget_CanvasVersion(void* unused){
     return OUR_VERSION_MAJOR*100+OUR_VERSION_MINOR*10+OUR_VERSION_SUB;
 }
 void ourpost_Canvas(void* unused){
     if(Our->CanvasVersion<20){ Our->BackgroundFactor=0; Our->BackgroundType=0; }
+    if(Our->CanvasVersion<50){ Our->AlphaMode=0; }
     LA_ACQUIRE_GLES_CONTEXT;
     laMarkMemClean(Our->CanvasSaverDummyList.pFirst);
 }
@@ -4138,7 +4150,7 @@ void ourRegisterEverything(){
     laRegisterUiTemplate("panel_tools", "Tools", ourui_ToolsPanel, 0, 0,0, 0,10,20);
     laRegisterUiTemplate("panel_brushes", "Brushes", ourui_BrushesPanel, 0, 0,0, 0,10,15);
     laRegisterUiTemplate("panel_color", "Color", ourui_ColorPanel, 0, 0,0, GL_RGBA16F,0,0);
-    laRegisterUiTemplate("panel_pigments", "Pigments", ourUI_PIGMENT_PREVIEWsPanel, 0, 0,0, GL_RGBA16F,0,0);
+    laRegisterUiTemplate("panel_pigments", "Pigments", ourui_PigmentsPreviewPanel, 0, 0,0, GL_RGBA16F,0,0);
     laRegisterUiTemplate("panel_pallettes", "Pallettes", ourui_PallettesPanel, 0, 0,0, GL_RGBA16F,0,0);
     laRegisterUiTemplate("panel_brush_nodes", "Brush Nodes", ourui_BrushPage, 0, 0,0, 0,25,30);
     laRegisterUiTemplate("panel_notes", "Notes", ourui_NotesPanel, 0, 0,0, 0,15,15);
@@ -4246,7 +4258,7 @@ void ourRegisterEverything(){
     laAddEnumItemAs(p,"TILT","Tilt","Brush direction line follows tilt direction",1,0);
     laAddEnumItemAs(p,"TWIST","Twist","Brush direction line follows twist direction",2,0);
     laAddEnumItemAs(p,"AUTO","Auto","Brush direction line determines automatically whether to show tilt or twist",3,0);
-
+    
     pc=laAddPropertyContainer("our_tools","Our Tools","OurPaint tools",0,0,sizeof(OurPaint),0,0,1);
     laPropContainerExtraFunctions(pc,0,0,0,ourpropagate_Tools,0);
     sp=laAddSubGroup(pc,"brushes","Brushes","Brushes","our_brush",0,0,ourui_Brush,offsetof(OurPaint,CurrentBrush),0,0,0,ourset_CurrentBrush,ourgetstate_H2Modified,0,offsetof(OurPaint,Brushes),0);
@@ -4375,7 +4387,7 @@ void ourRegisterEverything(){
     laAddEnumItemAs(p,"CANVAS","Canvas","Background mimics canvas texture",1,0);
     laAddEnumItemAs(p,"PAPER","Paper","Background mimics paper texture",2,0);
     laAddIntProperty(pc,"background_random","Random","Background random pattern value",0,0,0,0,0,0,0,0,offsetof(OurPaint,BackgroundRandom),0,0,0,0,0,0,0,0,0,0,0);
-    laAddFloatProperty(pc,"background_factor","Factor","Background effect factor",0,0,0,1,0,0,0,0,offsetof(OurPaint,BackgroundFactor),0,0,0,0,0,0,0,0,0,0,0);
+    laAddFloatProperty(pc,"background_factor","Factor","Background effect factor",0,0,0,1,0,0.1,0,0,offsetof(OurPaint,BackgroundFactor),0,0,0,0,0,0,0,0,0,0,0);
     laAddFloatProperty(pc,"border_alpha","Border Alpha","Alpha of the border region around the canvas",0,0,0,1,0,0.05,0.5,0,offsetof(OurPaint,BorderAlpha),0,ourset_BorderAlpha,0,0,0,0,0,0,0,0,0);
     laAddFloatProperty(pc,"border_fade_width","Fade Width","Fading of the border",0,0,0,1,0,0.05,0,0,offsetof(OurPaint,BorderFadeWidth),0,ourset_BorderFadeWidth,0,0,0,0,0,0,0,0,0);
     p=laAddEnumProperty(pc,"show_border","Show Border","Whether to show border on the canvas",0,0,0,0,0,offsetof(OurPaint,ShowBorder),0,ourset_ShowBorder,0,0,0,0,0,0,0,0);
@@ -4419,6 +4431,9 @@ void ourRegisterEverything(){
     laAddEnumItemAs(p,"RGBA","RGBA","Canvas stores regular RGBA data",0,0);
     laAddEnumItemAs(p,"PIGMENT","Pigment","Canvas stores pigment data",1,0);
     laAddSubGroup(pc,"use_pigments","Use Pigments","Pigments that are referenced in this canvas for color picker","our_use_pigment",0,0,0,-1,0,0,0,0,0,0,offsetof(OurPaint,UsePigments),0);
+    p=laAddEnumProperty(pc,"alpha_mode","Alpha Mode","How to associate alpha channel with color in RGBA canvas",0,0,0,0,0,offsetof(OurPaint,AlphaMode),0,ourset_AlphaMode,0,0,0,0,0,0,0,0);
+    laAddEnumItemAs(p,"PREMULT","Premultiplied","Color values on canvas are pre-multiplied with alpha channel",0,0);
+    laAddEnumItemAs(p,"STRAIGHT","Straight","Color values are not associative with alpha values on canvas",1,0);
 
     pc=laAddPropertyContainer("our_layer","Our Layer","OurPaint layer",0,0,sizeof(OurLayer),0,0,1);
     laPropContainerExtraFunctions(pc,ourbeforefree_Layer,ourbeforefree_Layer,0,0,0);
@@ -4639,33 +4654,38 @@ int ourInit(){
 
     Our->SmudgeTexture=tnsCreate2DTexture(OUR_CANVAS_GL_PIX,512,2,0);
 
-    Our->CanvasShader = glCreateShader(GL_COMPUTE_SHADER);
-    Our->CanvasPigmentShader = glCreateShader(GL_COMPUTE_SHADER);
-    const GLchar* source1 = strSub(OUR_CANVAS_SHADER,"#with OUR_SHADER_COMMON",OUR_SHADER_COMMON);
-    const GLchar* source1a = strSub(source1,"#with OUR_PIGMENT_COMMON",OUR_PIGMENT_COMMON);
-    char* UseContent=tnsEnsureShaderCommoms(source1a,0,0); if(source1){free(source1);}  if(source1a){free(source1a);}
+    Our->CanvasShader =         glCreateShader(GL_COMPUTE_SHADER);
+    Our->CanvasStraightShader = glCreateShader(GL_COMPUTE_SHADER);
+    Our->CanvasPigmentShader =  glCreateShader(GL_COMPUTE_SHADER);
+    char* rep[]={"#with OUR_SHADER_COMMON",OUR_SHADER_COMMON,
+                 "#with OUR_PIGMENT_COMMON",OUR_PIGMENT_COMMON,0,0};
+    const GLchar* source1=tnsRegexReplace(OUR_CANVAS_SHADER, rep);
 #ifdef LA_USE_GLES
     const GLchar* versionstr=OUR_SHADER_VERSION_320ES;
 #else
     const GLchar* versionstr=OUR_SHADER_VERSION_430;
 #endif
-    const GLchar* sources1rgb[]={versionstr, "\n#define OUR_CANVAS_MODE_RGB\n", UseContent};
-    const GLchar* sources1pigment[]={versionstr, "\n#define OUR_CANVAS_MODE_PIGMENT\n", UseContent};
-    glShaderSource(Our->CanvasShader, 3, sources1rgb, NULL); glCompileShader(Our->CanvasShader);
-    glShaderSource(Our->CanvasPigmentShader, 3, sources1pigment, NULL); glCompileShader(Our->CanvasPigmentShader);
-    if(!tnsCheckShaderCompileStatus(Our->CanvasShader,"Canvas RGB")) exit(0);
-    if(!tnsCheckShaderCompileStatus(Our->CanvasPigmentShader,"Canvas Pigment")) exit(0);
-    if(UseContent){ free(UseContent); }
-
-    Our->CanvasProgram = glCreateProgram();
-    glAttachShader(Our->CanvasProgram, Our->CanvasShader); glLinkProgram(Our->CanvasProgram);
-    glGetProgramiv(Our->CanvasProgram, GL_LINK_STATUS, &status);
+    const GLchar* sources1rgb[]=        {versionstr, "\n#define OUR_CANVAS_MODE_RGB\n", source1};
+    const GLchar* sources1rgbstraight[]={versionstr, "\n#define OUR_CANVAS_MODE_RGB\n#define OUR_STRAIGHT_ALPHA", source1};
+    const GLchar* sources1pigment[]=    {versionstr, "\n#define OUR_CANVAS_MODE_PIGMENT\n", source1};
+    glShaderSource(Our->CanvasShader, 3, sources1rgb, NULL);                 glCompileShader(Our->CanvasShader);
+    glShaderSource(Our->CanvasStraightShader, 3, sources1rgbstraight, NULL); glCompileShader(Our->CanvasStraightShader);
+    glShaderSource(Our->CanvasPigmentShader, 3, sources1pigment, NULL);      glCompileShader(Our->CanvasPigmentShader);
+    if(!tnsCheckShaderCompileStatus(Our->CanvasShader,"Canvas RGB"))                  exit(0);
+    if(!tnsCheckShaderCompileStatus(Our->CanvasStraightShader,"Canvas RGB Straight")) exit(0);
+    if(!tnsCheckShaderCompileStatus(Our->CanvasPigmentShader,"Canvas Pigment"))       exit(0);
+    if(source1){free(source1);}
+
+    Our->CanvasProgram =         glCreateProgram();
+    Our->CanvasStraightProgram = glCreateProgram();
+    Our->CanvasPigmentProgram =  glCreateProgram();
+    glAttachShader(Our->CanvasProgram, Our->CanvasShader);                 glLinkProgram(Our->CanvasProgram);
+    glAttachShader(Our->CanvasStraightProgram, Our->CanvasStraightShader); glLinkProgram(Our->CanvasStraightProgram);
+    glAttachShader(Our->CanvasPigmentProgram, Our->CanvasPigmentShader);   glLinkProgram(Our->CanvasPigmentProgram);
     tnsCheckProgramLinkStatus(Our->CanvasProgram,"Canvas");
-
-    Our->CanvasPigmentProgram = glCreateProgram();
-    glAttachShader(Our->CanvasPigmentProgram, Our->CanvasPigmentShader); glLinkProgram(Our->CanvasPigmentProgram);
-    glGetProgramiv(Our->CanvasPigmentProgram, GL_LINK_STATUS, &status);
+    tnsCheckProgramLinkStatus(Our->CanvasStraightProgram,"Canvas Straight");
     tnsCheckProgramLinkStatus(Our->CanvasPigmentProgram,"Canvas Pigment");
+
     Our->uboBrushPigmentLocation=glGetUniformBlockIndex(Our->CanvasPigmentProgram, "BrushPigmentBlock");
     glUniformBlockBinding(Our->CanvasPigmentProgram, Our->uboBrushPigmentLocation, 0);
 
@@ -4714,8 +4734,10 @@ int ourInit(){
 
     Our->u = &Our->uRGBA;
     ourGetUniforms(Our->CanvasProgram,Our->CompositionProgram);
+    Our->u = &Our->uRGBStraightA;
+    ourGetUniforms(Our->CanvasStraightProgram,Our->CompositionProgram);
     Our->u = &Our->uPigment;
-    ourGetUniforms(Our->CanvasPigmentProgram,Our->CompositionProgram); // XXXXX
+    ourGetUniforms(Our->CanvasPigmentProgram,Our->PigmentCompositionProgramT->glProgramID); // XXXXX  (?)
 
     Our->X=-2800/2; Our->W=2800;
     Our->Y=2400/2;  Our->H=2400;
@@ -4766,6 +4788,8 @@ int ourInit(){
     Our->FileRegistered = our_FileAssociationsRegistered();
 
     Our->SegmentedWrite = 1;
+    Our->CanvasVersion=ourget_CanvasVersion(0);
+    Our->AlphaMode=1;
 
 #ifdef LAGUI_ANDROID
     android_ensure_asset_to_public_dir("default_brushes.udf");

+ 5 - 3
ourpaint.h

@@ -59,10 +59,10 @@ extern const char OUR_PIGMENT_COMMON[];
 #define OUR_AT_CROP_BR 8
 
 #define OUR_VERSION_MAJOR 0
-#define OUR_VERSION_MINOR 4
+#define OUR_VERSION_MINOR 5
 #define OUR_VERSION_SUB 0
 
-#define OUR_PAINT_NAME_STRING "Our Paint v0.4"
+#define OUR_PAINT_NAME_STRING "Our Paint v0.5"
 
 #define OUR_SIGNAL_PICK 1
 #define OUR_SIGNAL_MOVE 2
@@ -522,6 +522,7 @@ STRUCTURE(OurPaint){
 
     tnsTexture* SmudgeTexture;
     GLuint CanvasShader;         GLuint CanvasProgram;
+    GLuint CanvasStraightShader; GLuint CanvasStraightProgram;
     GLuint CanvasPigmentShader;  GLuint CanvasPigmentProgram;
     GLuint CompositionShader;    GLuint CompositionProgram;
     GLuint LayerShader;          GLuint LayerProgram;
@@ -532,7 +533,8 @@ STRUCTURE(OurPaint){
     GLint uboBrushPigment,uboBrushPigmentLocation;
     GLint uboCanvasPigment,uboCanvasPigmentLocation;
 
-    BrushUniforms *u,uRGBA,uPigment;
+    BrushUniforms *u,uRGBA,uRGBStraightA,uPigment;
+    int AlphaMode;
 
     OurCanvasSurface CanvasSurface;
     OurLight         CanvasLight;

+ 27 - 11
ourshader.cpp

@@ -248,14 +248,21 @@ subroutine uniform MixRoutines uMixRoutineSelection;
 vec4 spectral_mix(vec4 a, vec4 b, float fac_a){
     return uMixRoutineSelection(a,b,fac_a);
 }
-vec4 spectral_mix_unpre(vec4 colora, vec4 colorb, float fac){
+vec4 spectral_mix_always(vec4 colora, vec4 colorb, float fac){
+#ifndef OUR_STRAIGHT_ALPHA
     vec4 ca=(colora.a==0.0f)?colora:vec4(colora.rgb/colora.a,colora.a);
     vec4 cb=(colorb.a==0.0f)?colorb:vec4(colorb.rgb/colorb.a,colorb.a);
+#else
+    vec4 ca=colora; vec4 cb=colorb;
+#endif
     float af=colora.a*(1.0f-fac);
     float aa=af/(af+fac*colorb.a+0.000001);
     vec4 result=spectral_mix(ca,cb,aa);
     result.a=mix(colora.a,colorb.a,fac);
-    return vec4(result.rgb*result.a,result.a);
+#ifndef OUR_STRAIGHT_ALPHA
+    result = vec4(result.rgb*result.a,result.a);
+#endif
+    return result;
 }
 float atan2(in float y, in float x){
     bool s = (abs(x) > abs(y)); return mix(3.1415926535/2.0 - atan(x,y), atan(y,x), s);
@@ -268,29 +275,38 @@ float brightness(vec4 color) {
     return color.r*0.2126+color.b*0.7152+color.g*0.0722;
 }
 vec4 mix_over(vec4 colora, vec4 colorb){
+#ifndef OUR_STRAIGHT_ALPHA
     vec4 a=(colora.a==0.0f)?colora:vec4(colora.rgb/colora.a,colora.a);
     vec4 b=(colorb.a==0.0f)?colorb:vec4(colorb.rgb/colorb.a,colorb.a);
+#else
+    vec4 a=colora; vec4 b=colorb;
+#endif
     vec4 m=vec4(0,0,0,0); float aa=colora.a/(colora.a+(1.0f-colora.a)*colorb.a+OUR_FLT_EPS);
     m=spectral_mix(a,b,aa);
     m.a=colora.a+colorb.a*(1.0f-colora.a);
+#ifndef OUR_STRAIGHT_ALPHA
     m=vec4(m.rgb*m.a,m.a);
+#endif
     return m;
 }
 int dab(float d, vec2 fpx, vec4 color, float size, float hardness, float smudge, vec4 smudge_color, vec4 last_color, out vec4 final){
     vec4 cc=color;
     float fac=1.0f-pow(d/size,1.0f+1.0f/(1.0f-hardness+OUR_FLT_EPS));
     float canvas=SampleCanvas(fpx,uBrushDirection,fac,uBrushForce,uBrushGunkyness);
-    cc.a=color.a*canvas*(1.0f-smudge); cc.rgb=cc.rgb*cc.a;
+    cc.a=color.a*canvas*(1.0f-smudge);
+#ifndef OUR_STRAIGHT_ALPHA
+    cc.rgb=cc.rgb*cc.a;
+#endif
     float erasing=float(uBrushErasing);
     cc=cc*(1.0f-erasing);
 
     // this looks better than the one commented out below
-    vec4 c2=spectral_mix_unpre(last_color,smudge_color,smudge*fac*color.a*canvas);
+    vec4 c2=spectral_mix_always(last_color,smudge_color,smudge*fac*color.a*canvas);
     c2=mix_over(cc,c2);
     //vec4 c2=mix_over(cc,last_color);
-    //c2=spectral_mix_unpre(c2,smudge_color,smudge*fac*color.a*canvas);
+    //c2=spectral_mix_always(c2,smudge_color,smudge*fac*color.a*canvas);
 
-    c2=spectral_mix_unpre(c2,c2*(1.0f-fac*color.a),erasing*canvas);
+    c2=spectral_mix_always(c2,c2*(1.0f-fac*color.a),erasing*canvas);
     final=c2;
     return 1;
 }
@@ -350,7 +366,7 @@ void DoDabs(){
     fpx.x=uBrushCenter.x+(fpx.x-uBrushCenter.x)*(1.+uBrushSlender);
     float dd=distance(fpx,uBrushCenter); if(dd>uBrushSize) return;
     vec4 dabc=OurImageLoad(img, px);
-    vec4 smudgec=pow(spectral_mix_unpre(pow(OurImageLoad(smudge_buckets,ivec2(1,0)),p1_22),pow(OurImageLoad(smudge_buckets,ivec2(0,0)),p1_22),uBrushRecentness),p22);
+    vec4 smudgec=pow(spectral_mix_always(pow(OurImageLoad(smudge_buckets,ivec2(1,0)),p1_22),pow(OurImageLoad(smudge_buckets,ivec2(0,0)),p1_22),uBrushRecentness),p22);
     vec4 final_color;
     dab(dd,origfpx,uBrushColor,uBrushSize,uBrushHardness,uBrushSmudge,smudgec,dabc,final_color);
     if(final_color.a>0.){
@@ -380,7 +396,7 @@ void DoSample(){
     memoryBarrier();barrier(); if(DoSample==0) return;
     if(uBrushErasing==0 || p.x!=0) return;
     color=vec4(0.,0.,0.,0.); for(int i=0;i<WORKGROUP_SIZE;i++){ color=color+OurImageLoad(smudge_buckets, ivec2(i+128,0)); }
-    color=spectral_mix_unpre(color/vec4(WORKGROUP_SIZE),OurImageLoad(smudge_buckets, ivec2(128+WORKGROUP_SIZE,0)),0.6*(1.0f-uBrushColor.a)); vec4 oldcolor=OurImageLoad(smudge_buckets, ivec2(0,0));
+    color=spectral_mix_always(color/vec4(WORKGROUP_SIZE),OurImageLoad(smudge_buckets, ivec2(128+WORKGROUP_SIZE,0)),0.6*(1.0f-uBrushColor.a)); vec4 oldcolor=OurImageLoad(smudge_buckets, ivec2(0,0));
     OurImageStore(smudge_buckets,ivec2(1,0),uBrushErasing==2?color:oldcolor);
     OurImageStore(smudge_buckets,ivec2(0,0),color);
 }
@@ -699,9 +715,9 @@ vec3 to_log_srgb(vec3 color){
 }
 
 float PigmentCMF[3][14]=float[3][14](
-float[14](0.0312392895238095,0.206838056190476,0.331771961904762,0.2294144,0.0603565122857143,0.0115536425238095,0.142399409047619,0.409927923809524,0.757860147619048,1.08086195714286,1.06489606190476,0.671900195238095,0.279014533333333,0.0811807252380952),
-float[14](0.003291837,0.0216550814285714,0.0526897938095238,0.100688807142857,0.203943585714286,0.437220023809524,0.797736085714286,0.977969833333333,0.972346723809524,0.814787419047619,0.558064080952381,0.290953433333333,0.111183708095238,0.0313402304761905),
-float[14](0.155952732857143,1.07818551904762,1.8438429047619,1.44867880952381,0.630120847619048,0.180786707619048,0.0385669957142857,0.00592827266666667,0.000780832180952381,0.000108133873809524,1.5619930952381E-05,0.,0.,0.)
+float[14](0.0343533436363636,0.220925140909091,0.328355822727273,0.2018815,0.0360974655,0.0285879281818182,0.215876535454545,0.525338609090909,0.906198259090909,1.13085586363636,0.895278031818182,0.435115186363636,0.138809882272727,0.0324976972727273),
+float[14](0.00359930259090909,0.0236005122727273,0.0565472954545455,0.114833071818182,0.236568031818182,0.535090640909091,0.876579286363636,0.992233536363636,0.923666477272727,0.708120895454545,0.419073681818182,0.178679336363636,0.0541232845454545,0.0124627878181818),
+float[14](0.171746535909091,1.15671911363636,1.84186645454545,1.32759531363636,0.488183445454546,0.12631411,0.0225265765,0.00293351760909091,0.000351412640909091,4.70501886363636E-05,3.51041136363636E-06,0.,0.,0.)
 );
 const float PigmentCMFNormalize=5.13517814086364; 
 vec3 Spectral2XYZ(float spec[OUR_SPECTRAL_SLICES]){