*/}}
Browse Source

Optimizations and layer composition blending

YimingWu 1 year ago
parent
commit
0075851416
2 changed files with 29 additions and 12 deletions
  1. BIN
      default_brushes.udf
  2. 29 12
      ouroperations.c

BIN
default_brushes.udf


+ 29 - 12
ouroperations.c

@@ -64,13 +64,14 @@ subroutine(BrushRoutines) void DoSample(){\n\
     ivec2 p=ivec2(gl_GlobalInvocationID.xy);\n\
     if(p.y!=0) return;\n\
     vec2 sp=round(vec2(sin(float(p.x)),cos(float(p.x)))*uBrushSize);\n\
-    ivec2 px=ivec2(sp)+uBrushCorner; if(px.x<0||px.y<0||px.x>1024||px.y>1024) return;\n\
+    ivec2 px=ivec2(sp)+uBrushCorner; if(px.x<0||px.y<0||px.x>=1024||px.y>=1024) return;\n\
+    ivec2 b=uBrushCorner; if(b.x>=0&&b.y>=0&&b.x<1024&&b.y<1024){ imageStore(smudge_buckets,ivec2(128+32,0),imageLoad(img, b)); }\n\
     vec4 color=imageLoad(img, px);\n\
     imageStore(smudge_buckets,ivec2(p.x+128,0),color);\n\
     memoryBarrier();barrier();\n\
     if(uBrushErasing==0 || p.x!=0) return;\n\
     color=vec4(0,0,0,0); for(int i=0;i<32;i++){ color=color+imageLoad(smudge_buckets, ivec2(i+128,0)); }\n\
-    color=color/64+imageLoad(img, uBrushCorner)/2; vec4 oldcolor=imageLoad(smudge_buckets, ivec2(0,0));\n\
+    color=mix(color/32,imageLoad(smudge_buckets, ivec2(128+32,0)),uBrushSmudge); vec4 oldcolor=imageLoad(smudge_buckets, ivec2(0,0));\n\
     imageStore(smudge_buckets,ivec2(1,0),uBrushErasing==2?color:oldcolor);\n\
     imageStore(smudge_buckets,ivec2(0,0),color);\n\
 }\n\
@@ -111,9 +112,19 @@ void our_LayerEnsureTiles(OurLayer* ol, real xmin,real xmax, real ymin,real ymax
 void our_LayerEnsureTileDirect(OurLayer* ol, int col, int row);
 void our_RecordUndo(OurLayer* ol, real xmin,real xmax, real ymin,real ymax,int Aligned,int Push);
 
-void our_CanvasAlphaMix(uint16_t* target, uint16_t* source){
-    real a_1=(real)(65535-source[3])/65535;
-    target[3]=source[3]+target[3]*a_1; target[0]=source[0]+target[0]*a_1; target[1]=source[1]+target[1]*a_1; target[2]=source[2]+target[2]*a_1;
+void our_CanvasAlphaMix(uint16_t* target, uint16_t* source, real alpha){
+    real a_1=(real)(65535-source[3])/65535*alpha;
+    target[3]=source[3]*alpha+target[3]*a_1;
+    target[0]=source[0]*alpha+target[0]*a_1;
+    target[1]=source[1]*alpha+target[1]*a_1;
+    target[2]=source[2]*alpha+target[2]*a_1;
+}
+void our_CanvasAdd(uint16_t* target, uint16_t* source, real alpha){
+    int a=(int)(source[3]+target[3])*alpha; TNS_CLAMP(a,0,65535);
+    int r=(int)(source[0]+target[0])*alpha; TNS_CLAMP(r,0,65535);
+    int g=(int)(source[1]+target[1])*alpha; TNS_CLAMP(g,0,65535);
+    int b=(int)(source[2]+target[2])*alpha; TNS_CLAMP(b,0,65535);
+    target[3]=a; target[0]=r; target[1]=g; target[2]=b;
 }
 
 void our_InitRGBProfile(int Linear,cmsCIExyYTRIPLE* primaries_pre_quantized, void** ptr, int* psize, char* copyright, char* manufacturer, char* description){
@@ -673,9 +684,9 @@ void our_LayerRefreshLocal(OurLayer* ol){
 }
 void our_LayerEnsureTileDirect(OurLayer* ol, int row, int col){
     if(!ol->TexTiles[row]){ol->TexTiles[row]=memAcquireSimple(sizeof(OurTexTile*)*OUR_TILES_PER_ROW);}
-    if(ol->TexTiles[row][col]) return;
-    ol->TexTiles[row][col]=memAcquireSimple(sizeof(OurTexTile));
+    if(!ol->TexTiles[row][col]) ol->TexTiles[row][col]=memAcquireSimple(sizeof(OurTexTile));
     OurTexTile*t=ol->TexTiles[row][col];
+    if(t->Texture) return;
     t->Texture=tnsCreate2DTexture(GL_RGBA16,OUR_TILE_W,OUR_TILE_W,0);
     int sx=((real)col-OUR_TILE_CTR-0.5)*OUR_TILE_W_USE,sy=((real)row-OUR_TILE_CTR-0.5)*OUR_TILE_W_USE;
     t->l=sx-OUR_TILE_SEAM,t->b=sy-OUR_TILE_SEAM; t->r=t->l+OUR_TILE_W; t->u=t->b+OUR_TILE_W;
@@ -693,7 +704,7 @@ void our_LayerEnsureTiles(OurLayer* ol, real xmin,real xmax, real ymin,real ymax
     }
     *tl=l; *tr=r; *tu=u; *tb=b;
 }
-void our_TileTextureToImage(OurTexTile* ot, int SX, int SY, int composite){
+void our_TileTextureToImage(OurTexTile* ot, int SX, int SY, int composite, int BlendMode, real alpha){
     if(!ot->Texture) return;
     int bufsize=sizeof(uint16_t)*OUR_TILE_W_USE*OUR_TILE_W_USE*4;
     ot->Data=malloc(bufsize); int seam=OUR_TILE_SEAM; int width=OUR_TILE_W_USE;
@@ -702,7 +713,11 @@ void our_TileTextureToImage(OurTexTile* ot, int SX, int SY, int composite){
     if(composite){
         for(int row=0;row<OUR_TILE_W_USE;row++){
             for(int col=0;col<OUR_TILE_W_USE;col++){
-                our_CanvasAlphaMix(&Our->ImageBuffer[((SY+row)*Our->ImageW+SX+col)*4], &ot->Data[(row*OUR_TILE_W_USE+col)*4]);
+                if(BlendMode==OUR_BLEND_NORMAL){
+                    our_CanvasAlphaMix(&Our->ImageBuffer[((SY+row)*Our->ImageW+SX+col)*4], &ot->Data[(row*OUR_TILE_W_USE+col)*4],alpha);
+                }elif(BlendMode==OUR_BLEND_ADD){
+                    our_CanvasAdd(&Our->ImageBuffer[((SY+row)*Our->ImageW+SX+col)*4], &ot->Data[(row*OUR_TILE_W_USE+col)*4],alpha);
+                }
             }
         }
     }else{
@@ -767,10 +782,11 @@ void our_CanvasFillImageBufferBackground(){
     }
 }
 void our_LayerToImageBuffer(OurLayer* ol, int composite){
+    if(ol->Hide || ol->Transparency==1) return;
     for(int row=0;row<OUR_TILES_PER_ROW;row++){ if(!ol->TexTiles[row]) continue;
         for(int col=0;col<OUR_TILES_PER_ROW;col++){ if(!ol->TexTiles[row][col]) continue;
             int sx=ol->TexTiles[row][col]->l+OUR_TILE_SEAM,sy=ol->TexTiles[row][col]->b+OUR_TILE_SEAM;
-            our_TileTextureToImage(ol->TexTiles[row][col], sx-Our->ImageX, sy-Our->ImageY, composite);
+            our_TileTextureToImage(ol->TexTiles[row][col], sx-Our->ImageX, sy-Our->ImageY, composite, ol->BlendMode, 1.0f-ol->Transparency);
         }
     }
 }
@@ -1422,7 +1438,7 @@ int ourmod_ExportImage(laOperator* a, laEvent* e){
                 if(!fp) return LA_FINISHED;
                 our_CanvasFillImageBufferBackground();
                 for(OurLayer* l=Our->Layers.pLast;l;l=l->Item.pPrev){
-                    our_LayerToImageBuffer(ol, 1);
+                    our_LayerToImageBuffer(l, 1);
                 }
                 our_ImageConvertForExport(ex->BitDepth, ex->ColorProfile);
                 our_ImageExportPNG(fp, 0, 0, 0, Our->ShowBorder, ex->BitDepth, ex->ColorProfile);
@@ -1698,6 +1714,7 @@ void ourPreFrame(){
     if(MAIN.Drivers->NeedRebuild){ ourRebuildBrushEval(); }
 }
 void ourPushEverything(){
+    laRecordDifferences(0,"our.canvas.layers");laRecordDifferences(0,"our.canvas.current_layer");
     laFreeOlderDifferences(0);
     for(OurLayer* ol=Our->Layers.pFirst;ol;ol=ol->Item.pNext){ our_LayerRefreshLocal(ol); }
 }
@@ -1873,7 +1890,7 @@ void ourRegisterEverything(){
     laAssignNewKey(km, 0, "LA_2d_view_zoom", LA_KM_SEL_UI_EXTRA, 0, LA_MOUSE_WHEEL_UP, 0, "direction=in");
     laAssignNewKey(km, 0, "LA_2d_view_zoom", LA_KM_SEL_UI_EXTRA, 0, LA_KEY_DOWN, ',', "direction=out");
     laAssignNewKey(km, 0, "LA_2d_view_zoom", LA_KM_SEL_UI_EXTRA, 0, LA_KEY_DOWN, '.', "direction=in");
-    laAssignNewKey(km, 0, "LA_2d_view_zoom", LA_KM_SEL_UI_EXTRA, LA_KEY_CTRL, LA_L_MOUSE_DOWN, 0, "direction=in");
+    laAssignNewKey(km, 0, "LA_2d_view_zoom", LA_KM_SEL_UI_EXTRA, LA_KEY_CTRL, LA_M_MOUSE_DOWN, 0, "mode=mouse;lock=true;");
     laAssignNewKey(km, 0, "LA_2d_view_move", LA_KM_SEL_UI_EXTRA, LA_KEY_ALT, LA_L_MOUSE_DOWN, 0, 0);
     laAssignNewKey(km, 0, "LA_2d_view_move", LA_KM_SEL_UI_EXTRA, 0, LA_M_MOUSE_DOWN, 0, 0);
     laAssignNewKey(km, 0, "OUR_action", LA_KM_SEL_UI_EXTRA, 0, LA_L_MOUSE_DOWN, 0, 0);