2016-09-08 20 views
6

bạn có thể bỏ qua đến TL; DR ở dưới cùng để kết luận. Tôi muốn cung cấp càng nhiều thông tin càng tốt, để giúp thu hẹp thêm câu hỏi.Hiệu ứng sương mù/biến dạng nhiệt trong OpenGL (GLSL) và cách đạt được

Tôi đã gặp sự cố với hiệu ứng khói mù nhiệt mà tôi đang nghiên cứu. Đây là loại hiệu ứng mà tôi đang nghĩ đến nhưng vì đây là một hệ thống khá tổng quát, nó sẽ áp dụng cho bất kỳ sự khúc xạ không gian màn hình nào được gọi là: Overwatch ((C) 2016) heat haze on bike Hiệu ứng sương mù không phải là vấn đề của tôi. tọa độ, đúng hơn là với những gì được lấy mẫu. Cách tiếp cận đầu tiên của tôi là tạo ra các biến dạng cho mục tiêu render khác. Phương pháp này khá thành công nhưng có một sự sụp đổ lớn rất dễ thấy trước nếu bạn đã xử lý các kết cấu không gian màn hình trước đây. vấn đề là do bù đắp cho tọa độ lấy mẫu, nếu một đối tượng ở phía trước của khúc xạ, các cạnh của nó sẽ được đưa vào phép tính khúc xạ. looks fine như bạn có thể thấy có vẻ ổn khi tất cả hình học là môi trường (không có kiểm tra độ sâu) hoặc hình học ngược. looks bad và ở đây có hình lập phương gần hơn khúc xạ. Như bạn có thể thấy nó, có hiệu ứng này tôi sẽ gọi chảy máu của hình học gần hơn.

đang đổ bóng có liên quan để tham khảo:

/* transparency.frag */ 
layout (location = 0) out vec4 out_color; // frag color 
layout (location = 1) out vec4 bright; // used for bloom effect 
layout (location = 2) out vec4 deform; // deform buffer 
[...] 
void main(void) { 
    [...] 
    vec2 n = __sample_noise_texture_with_time__{}; 
    deform = vec4(n * .1, 0, 1); 
    out_color = vec4(0, 0, 0, .0); 
    bright = vec4(0.0, 0.0, 0.0, .9); 
} 

/* post_process.frag */ 
in vec2 texel; 

uniform sampler2D screen_t; 
uniform sampler2D depth_t; 
uniform sampler2D bright_t; 
uniform sampler2D deform_t; 
[...] 
void main(void) { 
    [...] 
    vec3 noise_sample = texture(deform_t, texel).xyz; 
    vec2 texel_c = texel + noise_sample.xy; 
    [sample screen and bloom with texel_c, gama corect, output to color buffer] 
} 

Để cố gắng chống lại điều này, tôi đã cố gắng một kỹ thuật mà liên quan đến việc so sánh các thành phần sâu. để làm điều này, tôi đã làm cho các đối tượng trong suốt viết frag_depth nó tp thành phần z của bộ đệm biến dạng của tôi như vậy

/* transparency.frag */ 
[...] 
deform = vec4(n * .1, gl_FragCoord.z, 1); 
[...] 

và sau đó để xác định những gì đang ở phía trước của những gì một kiểm tra nhanh chóng trong shader bài chế biến.

[...] 
float dist = texture(depth_t, texel_c).x; 
float dist1 = noise_sample.z; // what i wrote to the deform buffer z 
if (dist + .01 < dist1) { /* do something liek draw debug */ } 
[...] 

hoạt động này phần nào nhưng bị hỏng khi tôi chuyển đi, thậm chí tôi đã tuyến tính hóa giá trị độ sâu và so sánh khoảng cách. color keyed debug EDIT 3: thêm ảnh chụp màn hình tốt hơn cho giai đoạn thử nghiệm sâu better color keyed debug (Trong màu vàng mà nó lấy mẫu một cái gì đó ở phía trước, có thể không bị làm phiền để làm cho nó làm cho đa giác cũng vì vậy tôi đã thu hút chúng vào) failing from further away (và ở đây chứng minh nó một phần thất bại trong việc kiểm tra so sánh chiều sâu từ xa)

Tôi cũng đã có một số 'vui vẻ' với một kỹ thuật khác mà tôi đã chuyển bộ đệm màu trực tiếp đến bóng đổ trong suốt và cho nó xuất mẫu. . Về lý thuyết nếu cảnh Z được sắp xếp, điều này sẽ tạo ra kết quả mong muốn. tôi sẽ cho bạn là thẩm phán về điều đó. enter image description here (Tôi có một vài dự đoán về những gì các mẫu mà nổi lên là vì chúng là tương tự như các mẫu rasterisation GPU tuy nhiên đó không phải là sin liên quan nhất mà 'giải pháp' là chi tiết của một nỗ lực tuyệt vọng hơn bất cứ điều gì)

TL, DR và ​​Câu hỏi chính thức: Tôi đã có một vài kỹ thuật dựa trên kiến ​​thức của tôi và không thể tìm thấy nhiều tài liệu về chủ đề này. Vì vậy, câu hỏi của tôi là: Làm thế nào để bạn nhận ra hiệu ứng sch như nhiệt khói/biến dạng (mà không bao gồm toàn bộ màn hình tôi có thể thêm) và có tài liệu về chủ đề này. Để tham khảo những gì loại hiệu ứng tôi sẽ được xem xét, xem ảnh chụp màn hình Overwatch của tôi và tất cả các hiệu ứng tương tự khác trong trò chơi.

Nghĩ rằng tôi cũng sẽ đề cập đến chỉ vì đầy đủ vì tôi đang chạy OpenGL 4.5 (trên cửa sổ) với hầu hết các trình tạo bóng là phiên bản 4.00 và đang làm việc với một công cụ tùy chỉnh.

EDIT: Nếu bạn muốn thông tin về phần phần mềm của động cơ, hãy hỏi. Tôi đã không bao gồm bất kỳ vì nó tôi không coi nó có liên quan tuy nhiên tôi muốn được vui để cung cấp thông số kỹ thuật và đoạn mã cũng như nhiều shaders theo yêu cầu. EDIT 2: Tôi nghĩ tôi cũng đề cập rằng điều này có thể đạt được bằng cách sử dụng một render render thứ hai và một máy bay clipping tuy nhiên, đó sẽ là tốn kém và cảm thấy không cần thiết vì quan điểm là như nhau. Có thể đó là giải pháp duy nhất nhưng tôi không tin như vậy.

Cảm ơn câu trả lời của bạn trước!

+0

Có thể độ phân giải độ sâu bạn viết không tốt? bạn đang sử dụng kết cấu nào để lưu trữ độ sâu trung gian? GL_LUMINANCE16? Tôi hy vọng bạn không đổ chiều sâu vào kênh 8 bit và so sánh điều này sau. – Harish

+0

@ Thật không may là không phải là nó, tôi đang sử dụng một định dạng GL_DEPTH_COMPONENT32 cho tất cả các bộ đệm sâu của tôi, và giải quyết tất cả các vấn đề chiến đấu z tôi đã có trong quá khứ. – claudehenry

Trả lời

1

Tôi nghĩ vấn đề là bạn đang cố bóp méo thứ gì đó đằng sau một đối tượng bị tắc và thông tin đó không còn nữa, vì đối tượng ở phía trước đã ghi đè giá trị màu ở đó. Vì vậy, bạn không thể bóp méo thông tin từ một bộ đệm màu không tồn tại nữa.

Bạn đang cố gắng giải quyết nó bằng cách kiểm tra độ sâu và bỏ qua các điểm ảnh thuộc đối tượng gần camera hơn đối tượng nhiệt trong suốt của bạn, nhưng điều này làm cho cạnh bị rò rỉ vào méo. Ngay cả khi bạn có được cạnh bỏ qua, nếu có một đối tượng ngay phía sau đối tượng trong suốt, bị tắc bởi khối lập phương ở phía trước, nó sẽ không biến dạng bởi vì thông tin màu sắc không có sẵn.

bổ sung Render đèo

  1. Như bạn đề cập thêm đường chuyền vẽ với một chiếc máy bay cắt chắc chắn là một trong những giải pháp cho vấn đề này.

mục tiêu Nhiều làm

  1. Một giải pháp tương tự để mà có thể sử dụng nhiều làm cho các mục tiêu, làm cho độ sâu của các đối tượng trong suốt trước mặt, kiểm tra cho các mảnh nằm phía sau nó và đưa chúng vào một bộ đệm màu khác. Sau đó sử dụng bộ đệm này để biến dạng thay vì bộ đệm màu đầy đủ. Bạn cũng có thể xem xét tô bóng mờ.

Đây là đoạn mã về cách bạn sẽ thiết lập nhiều mục tiêu hiển thị.

//create your fbo 
GLuint fboID; 
glGenFramebuffers(1, &fboID); 
glBindFramebuffer(GL_FRAMEBUFFER, fboID); 

//create the rbo for depth 
GLuint rboID; 
glGenRenderbuffers(1, &rboID); 
glBindRenderbuffer(GL_RENDERBUFFER, &rboID); 
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT32, width, height); 
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboID); 

//create two color textures (one for distort) 
Gluint colorTexture, distortcolorTexture; 
glGenTextures(1, &colorTexture); 
glGenTextures(1, &distortcolorTexture); 
glBindTexture(GL_TEXTURE_2D, colorTexture); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); 
glBindTexture(GL_TEXTURE_2D, distortcolorTexture); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); 

//attach both textures 
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorTexture, 0); 
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, distortcolorTexture, 0); 
//specify both the draw buffers 
GLenum drawBuffers[2] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1}; 
glDrawBuffers(2, DrawBuffers); 

Đầu tiên vẽ chiều sâu của obj trong suốt. Sau đó, trong trình đổ bóng phân đoạn của bạn cho các đối tượng khác

//compute color with your lighting... 
//write color to colortexture 
gl_FragData[0] = color; 
//check if fragment behind your transparent object 
if(depth >= tObjDepth) 
{ 
//write color to distortcolortexture 
gl_FragData[1] = color; 
} 

cuối cùng sử dụng distortcolortexture cho trình đổ bóng của bạn.

Kiểm tra độ sâu cho ma trận pixel thay vì pixel đơn.

  1. Tôi nghĩ cạnh là bị rò rỉ bởi vì có thể bạn không chỉ đơn giản là bóp méo một pixel nhưng nhiều hơn một ma trận điểm ảnh, có lẽ bạn cũng có thể thử kiểm tra độ sâu tối đa cho ma trận (ví dụ: 3x3 pixel tập trung vào pixel hiện tại) và loại bỏ nó nếu nó không kiểm tra độ sâu. (lưu ý: điều này vẫn không làm méo mó các đối tượng đằng sau đối tượng bị tắc mà bạn có thể muốn méo mó).
+0

vâng, tôi đã giải quyết vấn đề này trong các chỉnh sửa của tôi, nhưng bạn hoàn toàn chính xác. Tôi chỉ có thể làm thêm một render render, nhưng tôi đã tìm kiếm nhiều hơn cho một kỹ thuật rẻ tiền do đó tại sao tất cả các công cụ không gian màn hình tôi đã làm. Nếu bạn có thể giải thích cách tôi có thể sử dụng thêm một mục tiêu render để chọn lọc các đối tượng có độ sâu nhất định. Tôi xem xét cắt máy bay nhưng những người sẽ chỉ làm việc cho một vượt qua render. (Tôi hơi mệt một chút nhưng tôi chỉ muốn thừa nhận bạn đang trả lời, cảm ơn). – claudehenry

+0

@claudehenry Tôi đã xây dựng nhiều mục tiêu hiển thị một phần câu trả lời của tôi bằng một số mã. Hy vọng nó giúp. – Harish

Các vấn đề liên quan