Tôi có thể lưu trữ hình ảnh vào biến PHP không?

Tải/lưu trữ hình ảnh là khả năng của Shader ít nhiều tùy ý đọc và ghi vào hình ảnh

Tổng quan

Ý tưởng với tải/lưu trữ hình ảnh là người dùng có thể liên kết một trong các hình ảnh trong Kết cấu với một số điểm liên kết hình ảnh [tách biệt với các đơn vị hình ảnh kết cấu]. Trình tạo bóng có thể đọc thông tin từ những hình ảnh này và ghi thông tin vào chúng theo cách mà chúng không thể thực hiện được với kết cấu

Điều này có thể cho phép một số tính năng mạnh mẽ, bao gồm tính minh bạch không phụ thuộc vào đơn đặt hàng tương đối rẻ

Nếu bạn nghĩ rằng đây là một tính năng tuyệt vời, hãy nhớ rằng không có gì gọi là bữa trưa miễn phí. Chi phí sử dụng tải/lưu trữ hình ảnh là tất cả các hoạt động ghi của nó không được tự động kết hợp. Bằng cách sử dụng tải/lưu trữ hình ảnh, bạn chịu trách nhiệm quản lý những gì OpenGL thường quản lý cho bạn bằng cách đọc/ghi kết cấu thông thường

biến hình ảnh

Biến ảnh trong GLSL là biến có một trong các kiểu ảnh sau. Các loại hình ảnh dựa trên loại Kết cấu nguồn cho hình ảnh. Không phải tất cả các loại kết cấu đều có loại hình ảnh tương ứng. Các biến hình ảnh phải được khai báo với bộ định tính lưu trữ thống nhất [hoặc dưới dạng đầu vào tham số chức năng]

Giống như bộ lấy mẫu, các biến hình ảnh đại diện cho số thực dấu phẩy động, số nguyên có dấu hoặc số nguyên không dấu. Tiền tố được sử dụng cho tên biến hình ảnh biểu thị cái đó, sử dụng các quy ước GLSL tiêu chuẩn. Không có tiền tố nghĩa là dấu phẩy động, tiền tố i nghĩa là số nguyên có dấu và u nghĩa là số nguyên không dấu

Để rõ ràng, khi bạn nhìn thấy chữ g đứng trước "hình ảnh" trong tên hình ảnh, nó đại diện cho bất kỳ tiền tố nào trong 3 tiền tố có thể có. Các biến hình ảnh là

Không có biến thể "bóng tối"

Bạn sẽ nhận thấy một số mục nhập "một lớp từ" trong bảng trên. Có thể liên kết một lớp cụ thể từ các loại kết cấu nhất định với hình ảnh. Khi bạn làm như vậy, bạn phải sử dụng một biến hình ảnh khác so với loại thực tế của kết cấu nguồn, như minh họa ở trên

vòng loại bộ nhớ

Các biến hình ảnh có thể được khai báo với một số từ hạn định có ý nghĩa khác nhau về cách truy cập biến

mạch lạcThông thường, trình biên dịch tự do cho rằng lời gọi shader này là lời gọi duy nhất sửa đổi các giá trị được đọc qua biến này. Nó cũng có thể tự do cho rằng các lời gọi shader khác có thể không nhìn thấy các giá trị được ghi thông qua biến này. Việc sử dụng vòng loại này là cần thiết để cho phép các lệnh gọi shader phụ thuộc giao tiếp với nhau, vì nó thực thi tính nhất quán của các truy cập bộ nhớ. Việc sử dụng điều này yêu cầu các rào cản bộ nhớ thích hợp được thực thi để có thể đạt được khả năng hiển thị. Khi giao tiếp giữa các lời gọi trình đổ bóng cho các lệnh hiển thị khác nhau, nên sử dụng glMemoryBarrier thay vì vòng loại này. dễ bay hơiTrình biên dịch thường tự do giả định rằng các giá trị được truy cập thông qua các biến sẽ chỉ thay đổi sau các rào cản bộ nhớ hoặc đồng bộ hóa khác. Với vòng loại này, trình biên dịch giả định rằng nội dung của bộ lưu trữ được đại diện bởi biến có thể bị thay đổi bất cứ lúc nào. hạn chếThông thường, trình biên dịch phải giả định rằng bạn có thể truy cập cùng một đối tượng hình ảnh/bộ đệm thông qua các biến riêng biệt trong cùng một trình đổ bóng. Do đó, nếu bạn ghi vào một biến và đọc từ một biến thứ hai, trình biên dịch sẽ giả định rằng có thể bạn đang đọc giá trị mà bạn vừa viết. Với vòng loại này, bạn đang nói với trình biên dịch rằng biến cụ thể này là biến duy nhất có thể sửa đổi bộ nhớ hiển thị thông qua biến đó trong lời gọi trình đổ bóng này [các giai đoạn đổ bóng khác không được tính ở đây]. Điều này cho phép trình biên dịch tối ưu hóa việc đọc/ghi tốt hơn. Bạn nên sử dụng cái này bất cứ khi nào có thể. readonlyThông thường, trình biên dịch cho phép bạn đọc và ghi từ các biến theo ý muốn. Nếu bạn sử dụng biến này, biến chỉ có thể được sử dụng cho các thao tác đọc [các thao tác nguyên tử bị cấm vì chúng cũng được tính là ghi]. writeonlyThông thường, trình biên dịch cho phép bạn đọc và ghi từ các biến theo ý muốn. Nếu bạn sử dụng biến này, biến chỉ có thể được sử dụng cho các thao tác ghi [các thao tác nguyên tử bị cấm vì chúng cũng được tính là số lần đọc]

Ghi chú. chỉ ghi và chỉ đọc không loại trừ lẫn nhau. Đối với các biến được gắn thẻ với cả hai từ hạn định, vẫn có thể truy vấn thông tin về tài nguyên. Ví dụ: các biến hình ảnh đủ điều kiện vẫn có thể tra cứu kích thước của hình ảnh

Có thể sử dụng nhiều từ hạn định, nhưng chúng phải có ý nghĩa với nhau. Bạn được khuyến khích sử dụng hạn chế bất cứ khi nào có thể

hạn định định dạng

Các biến hình ảnh có thể được khai báo bằng một bộ định dạng; . Do đó, cần có bộ định dạng định dạng nếu bạn không khai báo biến với bộ nhớ chỉ ghi. Các biến chỉ ghi không thể được sử dụng như trong bất kỳ thao tác đọc nào; . Vì vậy nếu bạn muốn đọc từ một hình ảnh, bạn phải khai báo định dạng

Định dạng xác định cách trình đổ bóng diễn giải các bit dữ liệu mà nó đọc từ hình ảnh. Nó cũng xác định cách nó chuyển đổi dữ liệu được truyền cho các hoạt động ghi khi nó ghi nó vào hình ảnh. Điều này cho phép Định dạng hình ảnh thực tế của hình ảnh khác nhau giữa những gì trình đổ bóng nhìn thấy và những gì được lưu trữ trong hình ảnh, đôi khi đáng kể

Các định dạng được chia thành ba loại, đại diện cho ba loại hình biến

  • Định dạng hình ảnh bố cục dấu phẩy động
    • rgba32f
    • rgba16f
    • rg32f
    • rg16f
    • r11f_g11f_b10f
    • r32f
    • r16f
    • rgba16
    • rgb10_a2
    • rgba8
    • rg16
    • rg8
    • r16
    • r8
    • rgba16_snorm
    • rgba8_snorm
    • rg16_snorm
    • rg8_snorm
    • r16_snorm
    • r8_snorm
  • Định dạng hình ảnh bố cục số nguyên đã ký
    • rgba32i
    • rgba16i
    • rgba8i
    • rg32i
    • rg16i
    • rg8i
    • r32i
    • r16i
    • r8i
  • Định dạng hình ảnh bố cục số nguyên không dấu
    • rgba32ui
    • rgba16ui
    • rgb10_a2ui
    • rgba8ui
    • rg32ui
    • rg16ui
    • rg8ui
    • r32ui
    • r16ui
    • r8ui

Hoạt động hình ảnh

OpenGL cung cấp một số chức năng để truy cập hình ảnh thông qua các biến hình ảnh

Các hoạt động hình ảnh có "tọa độ hình ảnh", phục vụ mục đích chỉ định vị trí trong hình ảnh mà quyền truy cập sẽ diễn ra. Tọa độ ảnh khác với tọa độ kết cấu ở chỗ tọa độ ảnh luôn là số nguyên có dấu trong không gian texel

Mỗi biến hình ảnh có một kích thước cụ thể cho tọa độ hình ảnh của chúng, đại diện cho kích thước của hình ảnh bên dưới. Biến image1D lấy int làm tọa độ. image2DArray lấy ivec3;

Bản đồ khối [và mảng bản đồ khối] được truy cập rất khác so với truy cập kết cấu. Tọa độ hình ảnh cho các mảng bản đồ khối và bản đồ khối đều là ivec3. Tọa độ không phải là một hướng; . Thành phần thứ ba là chỉ mục khuôn mặt, vì điều này thường được xác định. Các biến hình ảnh xử lý hiệu quả các bản đồ khối chỉ đơn giản là một dạng kết cấu mảng;

Khi truy cập kết cấu nhiều mẫu, hàm truy cập có một tham số khác, một int xác định chỉ mục mẫu để đọc hoặc ghi vào

Chúng ta hãy gọi chung các tham số tọa độ hình ảnh là "IMAGE_COORD". Khi bạn thấy điều này trong định nghĩa hàm bên dưới, điều này có nghĩa là hàm lấy tọa độ hình ảnh, có thể bao gồm tham số chỉ mục mẫu nếu đó là hình ảnh nhiều mẫu

Kích thước ảnh

Kích thước của hình ảnh cho một biến hình ảnh có thể được truy vấn với chức năng này

 ivec imageSize[gimage image​];

Kích thước của vectơ được trả về sẽ là kích thước của tọa độ hình ảnh, ngoại trừ trường hợp bản đồ khối. Đối với bản đồ khối, kích thước sẽ là ivec2; . Các mảng bản đồ khối sẽ trả về ivec3, với thành phần thứ ba là số lượng mặt lớp

Truy cập bất kỳ texels nào nằm ngoài kích thước này sẽ dẫn đến truy cập không hợp lệ, như được định nghĩa bên dưới

tải hình ảnh

Các chức năng tải hình ảnh đọc một vị trí cụ thể từ hình ảnh vào shader

Ghi chú. Các thao tác tải từ bất kỳ texel nào nằm ngoài ranh giới của hình ảnh bị ràng buộc sẽ trả về tất cả các số không

Đọc từ một hình ảnh được thực hiện với chức năng này

 gvec4 imageLoad[gimage image​, IMAGE_COORD];

Giá trị trả về là dữ liệu từ hình ảnh, được chuyển đổi theo định dạng được chỉ định bởi bộ định dạng bố cục định dạng

kho ảnh

Hoạt động lưu trữ hình ảnh ghi một giá trị vào một vị trí cụ thể trong hình ảnh

Ghi chú. Lưu trữ các hoạt động cho bất kỳ texel nào nằm ngoài ranh giới của hình ảnh bị ràng buộc sẽ không làm gì cả

Ghi vào một hình ảnh được thực hiện với chức năng này

 void imageStore[gimage image​, IMAGE_COORD, gvec4 data​];

Giá trị trong dữ liệu​ sẽ được ghi vào hình ảnh tại tọa độ đã cho, sử dụng chuyển đổi định dạng dựa trên tham số định dạng được cung cấp cho glBindImageTexture

hoạt động nguyên tử

Các hoạt động nguyên tử thực hiện các hoạt động đọc/sửa đổi/ghi trên một vị trí trong ảnh. Các hoạt động này được đảm bảo là "nguyên tử". nếu hai shader thực hiện cùng một thao tác nguyên tử trên cùng một vị trí trong cùng một hình ảnh, một cái sẽ đi trước, theo sau là cái kia

Hãy xem xét một shader đọc từ một vị trí, thêm 1 vào vị trí đó và sau đó ghi vào vị trí đó. Về mặt lý thuyết, hai shader như vậy có thể đọc và ghi vào cùng một vị trí trong cùng một hình ảnh cùng một lúc. Do cách xử lý truy cập bộ nhớ, chuỗi sự kiện này hoàn toàn có thể hoạt động như thế này

  • Shader A đọc giá trị hình ảnh, giả sử 0
  • Shader B đọc giá trị hình ảnh, cũng 0
  • Shader B thêm 1 vào giá trị cục bộ của nó là 0, trở thành 1
  • Shader B ghi giá trị cục bộ của nó vào hình ảnh. Hình ảnh bây giờ có 1
  • Shader A thêm 1 vào giá trị cục bộ của nó là 0, trở thành 1
  • Shader A ghi giá trị cục bộ của nó vào hình ảnh. Hình ảnh bây giờ có 1

Hoạt động nguyên tử ngăn chặn khả năng này hoàn toàn. Hoạt động nguyên tử độc lập của mỗi shader sẽ hoàn thành đầy đủ trước khi hoạt động tiếp theo bắt đầu

Giá trị trả về của tất cả các hoạt động nguyên tử là giá trị ban đầu trước khi sửa đổi. Giá trị được ghi sẽ là giá trị được sửa đổi

Các thao tác nguyên tử đối với bất kỳ texel nào nằm ngoài ranh giới của hình ảnh bị ràng buộc sẽ trả về 0 và không làm gì cả

giới hạn nguyên tử

Có một số hạn chế nghiêm trọng đối với hoạt động nguyên tử hình ảnh. Đầu tiên, các nguyên tử chỉ có thể được sử dụng trên các hình ảnh số nguyên, có dấu hoặc không dấu. Thứ hai, chúng chỉ có thể được sử dụng trên hình ảnh có định dạng GL_R32I/r32i hoặc GL_R32UI/r32ui

Rất có thể sử dụng chuyển đổi định dạng để thực hiện các thao tác hình ảnh với các định dạng khác. Nhưng logic mã GLSL sẽ hoạt động trên các số nguyên 32 bit

Dưới đây, thuật ngữ "gint" có nghĩa là int hoặc uint, phù hợp với loại hình ảnh

Giá trị đặt nguyên tử

Giá trị tại vị trí trong ảnh có thể được đặt trực tiếp thông qua chức năng này

 gint imageAtomicExchange[gimage image​, IMAGE_COORDS, gint data​];

Chức năng này được gọi là "trao đổi" vì nó trao đổi dữ liệu​ với giá trị trong ảnh một cách hiệu quả. Giá trị trả về của tất cả các hàm nguyên tử là giá trị ban đầu từ hình ảnh, vì vậy nó đang trao đổi dữ liệu​ với giá trị đó

Bộ điều kiện nguyên tử

Một hoạt động rất mạnh mẽ là hoạt động sửa đổi có điều kiện. Thao tác này sẽ chỉ ghi một giá trị mới nếu giá trị hiện tại trong ảnh bằng với giá trị đã cho

 gint imageAtomicCompSwap[gimage image​, IMAGE_COORDS, gint compare​, gint data​];

Nếu giá trị hiện tại của ảnh​ tại tọa độ ảnh chính xác bằng so sánh​, thì dữ liệu​ sẽ được lưu vào ảnh tại vị trí đó. Nếu không, vị trí sẽ giữ nguyên giá trị ban đầu

Mặc dù hàm không cung cấp cách trực tiếp để biết liệu nó có thực sự viết giá trị hay không, nhưng nó luôn trả về giá trị ban đầu. Vì vậy, nếu bạn cần biết, bạn có thể tự mình kiểm tra giá trị trả về so sánh

toán nguyên tử

GLSL chỉ cung cấp một phép toán duy nhất. bổ sung

 gint imageAtomicAdd[gimage image​, IMAGE_COORDS, gint data​];

Điều này sẽ đọc giá trị từ hình ảnh, thêm dữ liệu​ vào nó, sau đó ghi nó vào hình ảnh

Rõ ràng nếu bạn cần trừ, chỉ cần phủ định dữ liệu​. Điều này sẽ chỉ hoạt động trực tiếp với các số nguyên đã ký. Tuy nhiên, vì GLSL 4. 30 bắt buộc phần bù của hai, bạn có thể nhận được hiệu ứng tương tự với các số nguyên không dấu, vì các hàm tạo chuyển đổi int[uint] và uint[int] sẽ bảo toàn mẫu bit

Vì vậy, nếu bạn cần phép trừ số nguyên không dấu, bạn có thể làm điều này

 imageAtomicAdd[..., uint[-data]];

Rõ ràng nếu điều này tạo ra một giá trị âm, thay vào đó, bạn sẽ nhận lại một giá trị rất dương, vì nó cho rằng bạn đang làm toán không dấu

nguyên tử bitwise

GLSL cung cấp 3 hoạt động bitwise nguyên tử. và, hoặc, và xor

 gint imageAtomicAnd[gimage image​, IMAGE_COORDS, gint data​];
 gint imageAtomicOr[gimage image​, IMAGE_COORDS, gint data​];
 gint imageAtomicXor[gimage image​, IMAGE_COORDS, gint data​];

Chúng đọc giá trị từ hình ảnh, thực hiện thao tác với dữ liệu đã cho và ghi kết quả trở lại hình ảnh

tối thiểu nguyên tử

GLSL cung cấp một cặp chức năng đảm bảo rằng giá trị trong hình ảnh không lớn hơn giá trị đã cho hoặc không nhỏ hơn giá trị đó

________số 8

Hàm "Min" đặt giá trị trong hình ảnh nhỏ hơn giá trị hoặc dữ liệu hiện tại của nó​. Hàm "Tối đa" đặt giá trị trong hình ảnh lớn hơn giá trị hoặc dữ liệu hiện tại của nó

Hình ảnh lưu trữ và loại bỏ

Fragment Shader có khả năng đưa ra lệnh loại bỏ. Điều này sẽ ngăn việc ghi bất kỳ giá trị đoạn nào vào bộ đệm khung. Đối với các trình đổ bóng thực thi lệnh loại bỏ, mọi lưu trữ hình ảnh hoặc nguyên tử được thực hiện trước khi thực hiện lệnh loại bỏ sẽ hoạt động bình thường. Khi lệnh hủy được thực thi, lệnh gọi trình đổ bóng sẽ bị chấm dứt và sẽ không thực hiện thêm hoạt động lưu trữ hình ảnh hoặc hoạt động nguyên tử nào

Hình ảnh trong ngữ cảnh

Cách liên kết một biến hình ảnh trong GLSL hoạt động rất giống với cách liên kết bộ lấy mẫu với kết cấu

Đối với mỗi giai đoạn đổ bóng, có một số đơn vị hình ảnh có sẵn [đừng nhầm với đơn vị hình ảnh kết cấu]. Số lượng đơn vị hình ảnh có thể được truy vấn trên mỗi giai đoạn, sử dụng GL_MAX_*_IMAGE_UNIFORMS, trong đó * được điền bằng giai đoạn đổ bóng thích hợp. Lưu ý rằng OpenGL 4. 3 chỉ yêu cầu Fragment Shader và Compute Shader phải có số đơn vị hình ảnh khác không;

Tổng số đơn vị hình ảnh có sẵn được truy vấn qua GL_MAX_IMAGE_UNITS;

Giống như với các bộ lấy mẫu, các biến hình ảnh tham chiếu các chỉ số đơn vị hình ảnh trong ngữ cảnh. Chúng thường được thiết lập với một hạn định bố cục ràng buộc, nhưng chúng cũng có thể được thiết lập với glUniform1i hoặc glProgramUniform1i

Sau khi liên kết biến hình ảnh với đơn vị hình ảnh của nó, sau đó bạn liên kết hình ảnh với ngữ cảnh. Điều này được thực hiện thông qua chức năng này

void glBindImageTexture[GLuint unit​, GLuint texture​, GLint level​, GLboolean layered​, GLint layer​, GLenum access​, GLenum format​]

Điều này liên kết một hình ảnh từ kết cấu​ với đơn vị hình ảnh nhất định, sử dụng cấp độ mipmap​ và lớp mảng đã cho

Các liên kết hình ảnh có thể được xếp lớp hoặc không xếp lớp, được xác định bởi lớp​. Nếu lớp​ là GL_TRUE, thì kết cấu​ phải là Kết cấu mảng [thuộc một số loại], Kết cấu sơ đồ khối hoặc Kết cấu 3D. Nếu một hình ảnh phân lớp đang bị ràng buộc, thì toàn bộ cấp độ mipmap được chỉ định theo cấp độ​ sẽ bị ràng buộc

Nếu hình ảnh không được xếp lớp thì người dùng phải sử dụng lớp​ để chọn lớp mảng nào sẽ bị ràng buộc. Nếu kết cấu không có các lớp mảng thì tham số này phải bằng 0. Cũng như các chức năng khác, nếu đây là kết cấu mảng sơ đồ khối, thì lớp​ là mặt lớp cần chọn

Nếu một kết cấu mảng hoặc sơ đồ khối bị ràng buộc và không được phân lớp, thì hình ảnh được liên kết không phải là một mảng hoặc hình ảnh sơ đồ khối. Vì vậy, nếu bạn liên kết một lớp mảng đơn từ kết cấu GL_TEXTURE_1D_ARRAY, thì lớp đó nên được sử dụng với loại biến hình ảnh image1D. Tương tự, các lớp từ kết cấu mảng 2D, sơ đồ khối, kết cấu 3D hoặc mảng sơ đồ khối phải là image2D và một lớp từ mảng nhiều mẫu 2D nên sử dụng image2DMS

Quyền truy cập chỉ định cách trình đổ bóng có thể truy cập hình ảnh thông qua đơn vị hình ảnh này. Đây có thể là GL_READ_ONLY, GL_WRITE_ONLY hoặc GL_READ_WRITE. Nếu trình tạo bóng vi phạm hạn chế này, thì mọi điều tồi tệ có thể xảy ra, bao gồm cả việc chấm dứt chương trình. Bạn nên sử dụng các vòng loại bộ nhớ trong chính trình đổ bóng để nắm bắt điều này tại thời điểm biên dịch trình đổ bóng

Tham số định dạng là Định dạng hình ảnh xác định định dạng sẽ được sử dụng để ghi vào hình ảnh. Nếu một định dạng hạn định được chỉ định trong shader, định dạng này phải phù hợp với nó. Định dạng phải tương thích với định dạng hình ảnh của kết cấu. Tham số định dạng chỉ có thể sử dụng các định dạng từ bảng sau

Image Unit FormatFormat QualifierImage Unit FormatFormat QualifierGL_RGBA32Frgba32fGL_RGBA32UIrgba32uiGL_RGBA16Frgba16fGL_RGBA16UIrgba16uiGL_RG32Frg32fGL_RGB10_A2UIrgb10_a2uiGL_RG16Frg16fGL_RGBA8UIrgba8uiGL_R11F_G11F_B10Fr11f_g11f_b10fGL_RG32UIrg32uiGL_R32Fr32fGL_RG16UIrg16uiGL_R16Fr16fGL_RG8UIrg8uiGL_RGBA16rgba16GL_R32UIr32uiGL_RGB10_A2rgb10_a2GL_R16UIr16uiGL_RGBA8rgba8GL_R8UIr8uiGL_RG16rg16GL_RGBA32Irgba32iGL_RG8rg8GL_RGBA16Irgba16iGL_R16r16GL_RGBA8Irgba8iGL_R8r8GL_RG32Irg32iGL_RGBA16_SNORMrgba16_snormGL_RG16Irg16iGL_RGBA8_SNORMrgba8_snormGL_RG8Irg8iGL_RG16_SNORMrg16_snormGL_R32Ir32iGL_RG8_SNORMrg8_snormGL_R16Ir16iGL_R16_SNORMr16_snormGL_R8Ir8i


Ngoài ra, lưu ý rằng đây là những định dạng hình ảnh duy nhất bạn có thể sử dụng cho hình ảnh trong các hoạt động tải/lưu trữ hình ảnh. Bạn phải sử dụng chính xác các định dạng hình ảnh này và không sử dụng các định dạng khác

uniform layout[binding=4,rgba8ui] writeonly uimage2D someImage;
void main[]
{
  ...
  imageStore[someImage,ivec2[1,1],ivec4[255,255,0,0]];
  ...
}

 gvec4 imageLoad[gimage image​, IMAGE_COORD];
0

Multibind và hình ảnh

Đối tượng MultibindCore trong phiên bản 4. 6 Core kể từ phiên bản 4. Tiện ích mở rộng ARB 4 nhânARB_multi_bind

Một loạt các đối tượng hình ảnh có thể được liên kết với một loạt các điểm liên kết hình ảnh với một lệnh gọi hàm duy nhất

đầu tiên​ là chỉ mục liên kết hình ảnh để bắt đầu liên kết mảng với. số lượng là số lượng chỉ số để ràng buộc. Do đó, các chỉ số liên kết hình ảnh sẽ được thay đổi là những chỉ số trong phạm vi nửa mở, [đầu tiên​, đầu tiên​ + số lượng​]

Nếu kết cấu​ là NULL, thì nó hoạt động giống như liên kết hình ảnh 0 với tất cả các chỉ số liên kết đã cho. Nếu không, nó sẽ liên kết từng kết cấu trong mảng với các chỉ số. kết cấu phải có các yếu tố đếm

Đối với mỗi kết cấu trong mảng, nếu kết cấu bằng 0, thì nó sẽ tương đương với việc gọi glBindImageTexture[first + i, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8]. Nếu kết cấu là một đối tượng kết cấu thực tế, nó sẽ tương đương với việc gọi glBindImageTexture[first + i, textures[i], 0, GL_TRUE, 0, GL_READ_WRITE, lookupInternalFormat[textures[i]]], trong đó lookupInternalFormat lấy Định dạng hình ảnh

Tính thiết thực

Bạn có thể nhận thấy rằng glBindImageTexture có nhiều tùy chọn tham số hơn glBindImageTexture nhiều liên kết. Nếu bạn sử dụng nhiều ràng buộc, bạn có một số hạn chế đáng kể đối với những gì bạn đang ràng buộc

Kết cấu sẽ luôn được ràng buộc dưới dạng kết cấu nhiều lớp; . Nó sẽ luôn ràng buộc mipmap cấp 0. Nó sẽ luôn ràng buộc nó để đọc và viết. Và bạn không thể thực hiện ánh xạ lại định dạng;

Có một công cụ có thể giảm thiểu hầu hết những hạn chế này. chế độ xem kết cấu. Bạn có thể tạo chế độ xem của kết cấu hiện có. Điều này cho phép bạn chọn một lớp/mặt mipmap và mảng cụ thể từ một kết cấu phía trước. Sau đó, bạn có thể liên kết nhiều chế độ xem này, chọn trước mipmap và lớp mà bạn muốn một cách hiệu quả. Hơn nữa, chế độ xem kết cấu đã có thể thực hiện cùng một loại chuyển đổi định dạng mà hình ảnh có thể thực hiện

Điều duy nhất mà kết cấu chế độ xem không thể cứu bạn khỏi ràng buộc đọc/ghi. Tuy nhiên, điều đó có thể được đặt trong shader tốt. Vì vậy, bạn không thực sự cần nó

chuyển đổi định dạng

Định dạng hình ảnh của hình ảnh có thể khác với định dạng được chỉ định cho chức năng liên kết hình ảnh và trong trình đổ bóng. Các giá trị đọc và ghi được chuyển đổi theo cách sau, giả sử rằng các định dạng tương thích

Thuật ngữ "định dạng nguồn" biểu thị định dạng hình ảnh của bất kỳ nguồn nào của hoạt động. Tương tự, "định dạng đích" là định dạng hình ảnh của bất kỳ đích nào của thao tác là. Vì vậy

  • thao tác đọc
  • thao tác ghi
    • định dạng nguồn. Định dạng được chỉ định bởi chức năng liên kết hình ảnh glBindImageTexture
    • định dạng đích. Định dạng thực tế của hình ảnh

Tất cả các hoạt động, dù là đọc hay ghi, đều hoạt động như thể chúng đang sao chép dữ liệu từ/sang hình ảnh với các định dạng đó. Bước đầu tiên của thao tác ghi sẽ lấy giá trị do trình đổ bóng cung cấp và ghi giá trị đó vào kết cấu ở định dạng hình ảnh nguồn. Sau đó, quá trình chuyển đổi định dạng diễn ra, sao chép giá trị vào đích. Tương tự, bước cuối cùng của thao tác đọc là đọc từ ảnh đích vào giá trị trong trình đổ bóng

Ghi chú. Phần tiếp theo là mô tả về cách đọc và viết hoạt động như thế nào. Rõ ràng, không có phần cứng nào làm theo cách này;

Việc chuyển đổi hoạt động dựa trên các bản sao bộ nhớ sử dụng các chức năng API hiện có. Các giá trị định dạng nguồn được đọc vào bộ nhớ như thể đang gọi glGetTexImage. Các giá trị định dạng đích được ghi vào hình ảnh của chúng như thể chúng được tải lên thông qua lệnh gọi một trong các hàm glTexSubImage

Cả hai chức năng này đều có các định dạng và loại truyền pixel. Hai cuộc gọi hiệu quả sẽ sử dụng các định dạng và loại khớp chính xác với định dạng hình ảnh nguồn/đích

Ví dụ: nếu định dạng hình ảnh nguồn là GL_RGBA8UI, thì định dạng​ và loại​ được chuyển tới glGetTexImage sẽ là GL_RGBA_INTEGER và GL_UNSIGNED_BYTE. Nếu định dạng hình ảnh đích cho một bản sao là GL_RGB10_A2 [có thể tương thích hoặc không tương thích với GL_RGBA8UI], thì các tham số sẽ là GL_RGBA và GL_UNSIGNED_INT_2_10_10_10_REV. Có thể tìm thấy toàn bộ thông số truyền pixel trong OpenGL 4. 5, Bảng 8. 27, trang 281

Các giá trị định dạng đích được ghi vào "bộ nhớ", sử dụng các giá trị được lấy từ nguồn, như thể được ghi bằng một trong các lệnh gọi glTexSubImage. Các lệnh gọi này lại sử dụng các loại và định dạng truyền pixel khớp chính xác với định dạng đích

Lưu ý rằng [sẵn sàng tương thích] chúng tôi hoàn toàn có khả năng chuyển đổi giữa các định dạng dấu phẩy động và tích phân. Tuy nhiên, việc chuyển đổi giữa GL_R32F và GL_RGBA8 không được xác định rõ, về mặt chuyển đổi cuối. Lý do là GL_R32F sẽ được đọc bằng một loại GL_FLOAT, nhưng việc viết sẽ ghi 4 byte theo thứ tự RGBA. Byte R sẽ là byte đầu tiên được đọc từ GL_FLOAT, nhưng bộ nhớ cuối của GL_FLOAT không được xác định. Vì vậy, byte đầu tiên có thể là quan trọng nhất hoặc ít quan trọng nhất

Đối với bất kỳ nền tảng cụ thể nào, bạn có thể giả định một endian cụ thể. Nhưng bản thân OpenGL không đảm bảo. Nếu bạn muốn một số đảm bảo về việc có thể chơi với các bit của kết cấu dấu phẩy động 32 bit, thay vào đó, hãy chuyển đổi nó thành GL_R32UI và thực hiện thao tác bit của bạn trong trình đổ bóng

tương thích định dạng

Ma trận tương thích định dạng hình ảnh khác nhau cho hoạt động tải/lưu trữ hình ảnh rất giống với ma trận tương thích cho chế độ xem kết cấu, mặc dù có một số khác biệt. Sự khác biệt đầu tiên là danh sách các định dạng hình ảnh có thể được sử dụng cho hình ảnh trong hoạt động tải/lưu trữ bị hạn chế hơn. chỉ các định dạng được đề cập ở trên mới có thể được sử dụng. Cụ thể, điều này có nghĩa là không thể sử dụng các định dạng hình ảnh sRGB trong các hoạt động tải/lưu trữ hình ảnh. Mặc dù bạn có thể tạo kết cấu chế độ xem từ định dạng sRGB sang định dạng không phải sRGB, bản thân chúng có thể được sử dụng trong tải/lưu trữ hình ảnh

Mỗi định dạng này có hai thuộc tính. một kích thước và một lớp học. Kích thước đại diện cho kích thước bit của mỗi texel. Ví dụ GL_R32F có size là 32; . Lớp đại diện cho số lượng thành phần và độ sâu bit của từng thành phần. Loại GL_R32F là 1x32, trong khi loại GL_RGBA8 là 4x8

Lớp dành cho các định dạng có độ sâu bit lẻ [ví dụ: GL_R11F_G11F_B10F] là sự sắp xếp của các thành phần. Vì vậy, lớp của GL_R11F_G11F_B10F là 11/11/10, trong khi lớp của GL_RGB10_A2UI là 10/10/10/2. Điều này có một lớp phù hợp với GL_RGB10_A2

Nếu kết cấu được phân bổ bởi OpenGL [OpenCL hoặc các lớp tương tác khác có thể phân bổ kết cấu], thì điều duy nhất quan trọng đối với tính tương thích là kích thước texel tổng thể. Vì vậy, việc ánh xạ hình ảnh GL_R32F sang định dạng GL_RGBA8UI và ngược lại là hoàn toàn hợp lệ, mặc dù các chuyển đổi endian một lần nữa có thể khiến điều này không sử dụng được trong mã nền tảng trung lập

Nếu một kết cấu được phân bổ từ bên ngoài OpenGL, thì khả năng tương thích được xác định như thế nào có thể không phụ thuộc vào kích thước texel; . Bạn phải sử dụng glGetTexParameter với GL_IMAGE_FORMAT_COMPATIBILITY_TYPE để phát hiện. Nó sẽ trả về GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE hoặc GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS, chỉ định cách xác định khả năng tương thích

Bạn cũng có thể phát hiện điều này ở cấp định dạng hình ảnh bằng truy vấn định dạng hình ảnh sử dụng cùng một tham số;

Để thay thế cho việc truy vấn với kết cấu nước ngoài, bạn chỉ có thể sử dụng các định dạng phù hợp với lớp. Nếu các lớp phù hợp, kích thước cũng phù hợp

Mạch lạc bộ nhớ

Viết và hoạt động nguyên tử thông qua các biến hình ảnh không tự động mạch lạc. Do đó, bạn phải làm những việc để đảm bảo rằng quá trình ghi đã diễn ra trước khi bạn có thể đọc các giá trị đó

Làm cách nào để gán một hình ảnh cho một biến trong PHP?

Use this: echo "
  • Chủ Đề