Cập nhật bộ nhớ kết cấu thông qua shader?


8

Tiêu đề nói gì. Có thể cập nhật một kết cấu thông qua trình tạo bóng glsl không? Cái gì đó như :

//Read
vec4 Pixel = texture2D(TextureID,gl_TexCoord[TextureIndex].st);

//Write to texture memory ?
vec4 NewPixel = Pixel + vec4(0.0,0.0,0.0,AlphaPatch);

// ?? How to write back to texture memory ??
texture2D(TextureID,gl_TexCoord[TextureIndex].st) = NewPixel; 

??

Câu trả lời:


6

Những gì bạn muốn là liên kết một kết cấu với một shader và sau đó kết xuất với kết cấu đó. Tôi có thể nhổ qua dặm của đặc tả tài liệu của OpenGL, nhưng tôi sẽ cung cấp cho cảm giác ruột của tôi mang lại cho tôi:

Tôi không nghĩ điều đó là có thể.

Tuy nhiên, điều tôi biết là có thể là bạn tạo Đối tượng Bộ đệm Khung (FBO) và kết xuất với điều đó. Đầu tiên, bạn phải tạo một FBO và đính kèm một kết cấu cho nó với cùng kích thước với kích thước bạn muốn cập nhật.

GLuint fbo_handle, fbo_texture_handle;

GLuint texture_width = GetTextureWidth();
GLuint texture_height = GetTextureWidth();

// generate texture

glGenTextures(1, &fbo_texture_handle);
glBindTexture(GL_TEXTURE_2D, fbo_texture_handle);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, texture_width, texture_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);

// generate framebuffer

glGenFrameBuffers(1, &fbo_handle);
glBindFrameBuffer(GL_FRAMEBUFFER, fbo_handle);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo_texture_handle, 0);

GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE)
{
    LOG_ERROR("Could not validate framebuffer);
}

glBindFramebuffer(GL_FRAMEBUFFER, 0);

Khi bạn muốn cập nhật kết cấu của mình, bạn phải thực hiện các bước sau.

Đầu tiên, bạn đính kèm FBO:

glBindFramebuffer(GL_FRAMEBUFFER, fbo_handle);

glPushAttrib(GL_VIEWPORT_BIT);
glViewport(0, 0, texture_width, texture_height);

Bây giờ bạn có thể kết xuất một quad toàn màn hình với một shader tạo ra màu được cập nhật:

vec4 frag_texture = texture2D(TextureID, gl_TexCoord[TextureIndex].st);

vec4 frag_updated = frag_texture + vec4(0.0, 0.0, 0.0, AlphaPatch);

gl_FragData[0] = frag_updated;

Và sau đó bạn phải sao chép bộ đệm khung kết quả vào kết cấu ban đầu.

glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_handle);
glBindTexture(GL_TEXTURE_2D, original_texture_handle);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texture_width, texture_height);

glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);

glPopAttrib();

Tuy nhiên, bạn nên xem xét những điều sau:

  • Bạn có thường xuyên cập nhật kết cấu này không?
  • Nếu bạn không phải cập nhật mọi khung hình, phương pháp này có đáng bị phạt tốc độ không?
  • Bạn có thể tạo nhiều phiên bản của kết cấu này và chu kỳ giữa chúng không?
  • Có cách nào khác để đạt được hiệu quả tương tự?

Wow cảm ơn bạn rất nhiều vì sự giúp đỡ! Và để trả lời câu hỏi của bạn: 1.Tôi có một kết cấu đặc biệt cho anh hùng của tôi mà tôi phải cập nhật mỗi khi xảy ra va chạm (với các chấm máu và những thứ khác). 2. Do tính chất của trò chơi, bạn luôn bị va chạm hoặc chạm vào những thứ đầy bụi bẩn, vì vậy tôi phải cập nhật kết cấu đó rất thường xuyên ... 3. Đó là cách tôi làm ngay bây giờ và tôi không hài lòng với nó (tôi cần vá kết cấu động) 4.Không biết: o
user1010005

4
Aha! Vâng, điều đó giúp trong việc điều chỉnh câu trả lời của tôi. Những gì bạn có thể đang tìm kiếm là đa kết cấu. Bạn có một kết cấu cho nhân vật trò chơi của bạn và bạn có một kết cấu cho thấy bụi bẩn và máu và không có gì. Trong một shader, bạn có thể kết hợp chúng để tạo hiệu ứng bạn muốn. Điều này rẻ hơn nhiều so với việc liên tục kết xuất vào một đối tượng bộ đệm khung và sao chép kết quả vào một kết cấu.
hiệp sĩ666

Cảm ơn bạn một lần nữa. Tôi không chắc ý của bạn với đa kết cấu nhưng tôi sẽ cố gắng tìm kiếm trên stackexchange :))
user1010005

4

Nếu phần cứng của bạn hỗ trợ nó, tiện ích mở rộng GL_ARB_shader_image_load_store cho phép bạn ghi vào kết cấu.


1
Tôi có thể nói với bạn ngay bây giờ rằng NVIDIA GeForce GTS 250 của tôi hỗ trợ OpenGL 3.3.0, nhưng không GL_EXT_shader_image_load_store. Điều đó có nghĩa là câu trả lời của bạn có thể đúng, nhưng chưa thực tế trong lĩnh vực này. Sucks. :(
hiệp sĩ666

1
Đúng, có vẻ như bạn cần một loạt GeForce 400 hoặc cao hơn để được hỗ trợ (đó là tính năng GL4 / DX11).
elFarto

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.