简体   繁体   English

如何在片段着色器中保存值以便以后使用它?

[英]How to save a value inside a fragment shader to use it later?

I want to save a calculated value from fragment shader in some variable ,so that I would be able to use it next time. 我想在一些变量中保存片段着色器中的计算值,以便下次我可以使用它。

Currently, I am preparing a image using a huge algorithm and I want to save it to some vec4 and , once requested again , I want to just get that vec4 and should say 目前,我正在使用一个巨大的算法准备一个图像,我想将它保存到一些vec4,再次请求,我想得到那个vec4,应该说

gl_FragColor = vec4(previously saved variable)

This question is related to another question here which is also asked by me , but I feel that if this question has a answer then I can easily crack the other one. 这个问题与我在这里提出的另一个问题有关,但我觉得如果这个问题有答案,那么我可以很容易地破解另一个问题。

Any suggestions ? 有什么建议 ?

Fragment shaders in WebGL write to 1 of 2 things. WebGL中的片段着色器写入2件事中的1件。 Either (1) the canvas to (2) the attachments of a framebuffer. (1)画布到(2)帧缓冲的附件。 The attachments of a framebuffer can be textures. 帧缓冲的附件可以是纹理。 Textures can be used as inputs to a shader. 纹理可以用作着色器的输入。 Therefore you can write to a texture and use that texture in your next draw. 因此,您可以写入纹理并在下一次绘制中使用该纹理。

Here's an example 这是一个例子

 var vs = ` attribute vec4 position; void main() { gl_Position = position; } `; var fs = ` precision mediump float; uniform sampler2D u_texture; void main() { // just grab the middle pixel(s) from the texture // but swizzle the colors g->r, b->g, r->b gl_FragColor = texture2D(u_texture, vec2(.5)).gbra; }`; var canvas = document.querySelector("canvas"); var gl = canvas.getContext("webgl"); var program = twgl.createProgramFromSources(gl, [vs, fs]); var positionLocation = gl.getAttribLocation(program, "position"); // we don't need to look up the texture's uniform location because // we're only using 1 texture. Since the uniforms default to 0 // it will use texture 0. // put in a clipspace quad var buffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, buffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1, ]), gl.STATIC_DRAW); gl.enableVertexAttribArray(positionLocation); gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0); // make 2 1x1 pixel textures and put a red pixel the first one var tex1 = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, tex1); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([255, 0, 0, 255])); var tex2 = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, tex2); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); // make a framebuffer for tex1 var fb1 = gl.createFramebuffer(); gl.bindFramebuffer(gl.FRAMEBUFFER, fb1); // attach tex1 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex1, 0); // check this will actually work if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) !== gl.FRAMEBUFFER_COMPLETE) { alert("this combination of attachments not supported"); } // make a framebuffer for tex2 var fb2 = gl.createFramebuffer(); gl.bindFramebuffer(gl.FRAMEBUFFER, fb2); // attach tex2 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex2, 0); // check this will actually work if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) !== gl.FRAMEBUFFER_COMPLETE) { alert("this combination of attachments not supported"); } function render() { gl.useProgram(program); // render tex1 to the tex2 // input to fragment shader gl.bindTexture(gl.TEXTURE_2D, tex1); // output from fragment shader gl.bindFramebuffer(gl.FRAMEBUFFER, fb2); gl.viewport(0, 0, 1, 1); gl.drawArrays(gl.TRIANGLES, 0, 6); // render to canvas so we can see it gl.bindFramebuffer(gl.FRAMEBUFFER, null); gl.viewport(0, 0, gl.canvas.width, gl.canvas.height); // input to fragment shader, the texture we just rendered to gl.bindTexture(gl.TEXTURE_2D, tex2); gl.drawArrays(gl.TRIANGLES, 0, 6); // swap which texture we are rendering from and to var t = tex1; tex1 = tex2; tex2 = t; var f = fb1; fb1 = fb2; fb2 = f; requestAnimationFrame(render); } requestAnimationFrame(render); 
 <script src="https://twgljs.org/dist/twgl-full.min.js"></script> <canvas></canvas> 

The sample above puts red in a texture. 上面的示例将红色放在纹理中。 It then renders that texture by swizzling the color. 然后它通过调色来渲染纹理。 Green goes to the red channel, Blue goes to the green channel, Red goes to the Blue channel. 绿色进入红色通道,蓝色进入绿色通道,红色进入蓝色通道。

I makes 2 textures and attaches them to 2 framebuffers. 我制作2个纹理并将它们附加到2个帧缓冲区。

First iteration 第一次迭代

tex1 = red
tex2 = 0,0,0,0
render to fb2
tex2 is now blue (because red was copied to blue)
render tex2 to canvas (canvas is now green because blue is copied to green)
switch which textures we're rendering to

Second iteration 第二次迭代

tex1 = blue (was tex2 last time) 
tex2 = red  (was tex1 last time)
render to fb2 (was fb1 last time)
tex2 = green (because blue is copied to green)
render tex2 to canvas (canvas is now red because green is copied to red)
switch which textures we're rendering to

Fragment shader executes per fragment(pixel).And as any other shader it cannot store values by default, as you would expect in regular programming language. 片段着色器按片段(像素)执行。与任何其他着色器一样,默认情况下它不能存储值,正如您在常规编程语言中所期望的那样。 There are several ways to do what you want: You can use imageLoad/Store ,which allows you to read and write data from shader into image. 有几种方法可以做你想要的:你可以使用imageLoad / Store ,它允许你从着色器读取数据到图像。 Image uses GL textures as memory storage.What is good about it is that you can store and load numeric data without losing precision when using images because texture filtering is disabled when accessing texture data via image. 图像使用GL纹理作为内存存储。它的优点在于,您可以在使用图像时存储和加载数字数据而不会丢失精度,因为在通过图像访问纹理数据时禁用纹理过滤。

Another way to store and read data in shaders is using buffers.Uniform buffers,or since GL4.3 Shader storage buffers. 在着色器中存储和读取数据的另一种方法是使用buffers.Uniform缓冲区,或者从GL4.3 Shader存储缓冲区开始。 . SSBO allows to read and write huge amount of data.It is really up to you to decide which of those to use for storing and retrieving your data in the shaders.Some people say texture memory access is faster on some hardware.From my experience,using SSBO vs image load store,I haven't found significant difference in performance on Nvidia GPUs. SSBO允许读取和写入大量数据。您可以自行决定在着色器中使用哪些数据来存储和检索数据。有些人说某些硬件上的纹理内存访问速度更快。根据我的经验,使用SSBO与图像加载存储,我没有发现Nvidia GPU的性能有显着差异。

In your scenario I would probably go with Image Load/Store.Because you can use the same UV indexing into image data as you do into sampled texture. 在您的场景中,我可能会使用图像加载/存储。因为您可以像对采样纹理一样使用与图像数据相同的UV索引。

Also,I don't really know what version of OpenGL you are using ,but to use these extensions you must use GL4.2 and GL4.3. 另外,我真的不知道您使用的OpenGL版本,但要使用这些扩展,您必须使用GL4.2和GL4.3。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 反应:如何从异步 function 中保存价值并稍后使用 - React: How to save value from async function and use later 如何将 mongodb findone 值保存到 javascript 变量以便稍后在 nodejs 上使用 - How to save mongodb findone value to a javascript variable to use it later on nodejs 有什么办法可以在片段着色器中使用先前渲染的结果? - Is there any way to use results of a previous rendering inside a fragment shader? 如何在WebGL上的着色器中保存变量,以及如何从JavaScript程序中读取其值? - How to save a variable inside a shader on WebGL, and how to read its value from the JavaScript program? 如何保存页面对象以备后用? - How to save the page object for later use? 如何保存HTML事件供以后使用? - How to save an HTML event for later use? 如何从glslsandbox.com使用片段着色器 - How to use fragment shader from glslsandbox.com 如何在每个循环中保存变量的值,以便以后可以使用这些值 - How do I save the value of a variable on each loop so I can use those values later jQuery ajax只想将1个值保存到变量中以使用以后的Javascript - Jquery ajax only want to save 1 value to a variable to use later Javascript Busboy 保存流以备后用 - Busboy Save Stream For Use Later
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM