簡體   English   中英

是否可以測試着色器是否可以修改任意像素?

[英]Is it possible to test if an arbitrary pixel is modifiable by the shader?

我正在 godot 中編寫空間着色器來像素化對象。

以前,我嘗試在對象之外編寫,但這只能在 CanvasItem 着色器中進行,現在我要回到 3D 着色器由於渲染煩惱(我無法在不使用剔除蒙版的情況下選擇性地隱藏項目,這僅限於20 層不是可擴展的解決方案。)

我天真的方法:

  1. 定義像素“單元”分辨率(即 3x3 真實像素)
  2. 對於每個片段:
    • 如果真實像素的整個“單元”在模型繪制范圍內,則根據左下角為當前像素着色(其中像素的坐標是單元分辨率的倍數)。

    • 如果當前“單元格”的任何像素超出繪制邊界,請將 alpha 設置為 1 以擦除整個單元格。

用於要求我正在尋找的可能不存在的功能的代碼的人的偽代碼:

int cell_size = 3;

fragment {
  // check within a cell to see if all pixels are part of the object being drawn to

  for (int y = 0; y < cell_size; y++) {
    for (int x = 0; x < cell_size; x++) {
      int erase_pixel = 0;

      if ( uv_in_model(vec2(FRAGCOORD.x - (FRAGCOORD.x % x), FRAGCOORD.y - (FRAGCOORD.y % y))) == false) {
        int erase_pixel = 1;
      }

    }
  }

  albedo.a = erase_pixel
}

tl; dr,是否有可能知道片段函數是否會調用任何給定點?

在對象的材質上應該有一個名為 Next Pass 的屬性。 在這部分添加一個新的空間材質,打開標志並檢查透明和無陰影,然后右鍵單擊它以顯示將其轉換為着色器材質的選項。

現在,打開新的 Shader Material 的 Shader。 最后一個過程應該已經創建了一個使用 fragment() 函數格式化的着色器,該函數包含行vec4 albedo_tex = texture(texture_albedo, base_uv);

在這一行中,您可以將“texture_albedo”替換為“SCREEN_TEXTURE”,將“base_uv”替換為“SCREEN_UV”。 這應該使新着色器看起來沒有任何變化,因為下一個 pass 材質只是從最后一個 pass 對屏幕進行采樣。

在此之上,按照“pixelated”的方式創建一個名為 something 的變量並將其設置為以下表達式: vec2 pixelated = floor(SCREEN_UV * scale) / scale; 其中 scale 是包含像素大小的浮點數或 vec2。 最后將 albedo_tex 定義中的 SCREEN_UV 替換為像素化。

在此之后,你可以有一個浮點深度,它像這樣對 DEPTH_TEXTURE 進行像素化采樣: float depth = texture(DEPTH_TEXTURE, pixelated).r; 對於只是嘗試將背景渲染到對象上的像素,此深度值將非常大。 所以,添加一個條件語句: if (depth > 100000.0f) { ALPHA = 0.0f; } if (depth > 100000.0f) { ALPHA = 0.0f; }

只要這個新的 next pass 着色器上的標志設置正確(透明和無陰影),您就應該有一個快速而骯臟的像素器。 我這樣說是因為它的邊緣有一些小瑕疵,但是您可以將 scale 設為一個統一變量並從編輯器和腳本中設置它,所以我認為它工作得很好。

在您的情況下,“測試像素是否可修改”意味着測試對象是否應該以該深度條件渲染它。

這是我從評論中修改的完整着色器

// NOTE: Shader automatically converted from Godot Engine 3.4.stable's SpatialMaterial.

shader_type spatial;
render_mode blend_mix,depth_draw_opaque,cull_back,unshaded;

//the size of pixelated blocks on the screen relative to pixels
uniform int scale;

void vertex() {
}

//vec2 representation of one used for calculation
const vec2 one = vec2(1.0f, 1.0f);

void fragment() {
    //scale SCREEN_UV up to the size of the viewport over the pixelation scale
    //assure scale is a multiple of 2 to avoid artefacts
    vec2 pixel_scale = VIEWPORT_SIZE / float(scale * 2);
    vec2 pixelated = SCREEN_UV * pixel_scale;
    //truncate the decimal place from the pixelated uvs and then shift them over by half a pixel
    pixelated = pixelated - mod(pixelated, one) + one / 2.0f;
    //scale the pixelated uvs back down to the screen
    pixelated /= pixel_scale;
    
    vec4 albedo_tex = texture(SCREEN_TEXTURE,pixelated);
    ALBEDO = albedo_tex.rgb;
    ALPHA = 1.0f;
    float depth = texture(DEPTH_TEXTURE, pixelated).r;
    if (depth > 10000.0f)
    {
        ALPHA = 0.0f;
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM