Sampling values in fragment shader from a R16_UINT-3D texture in Vulkan - c++

I am using the texture tutorial from Sascha Willems and it works without any problems. Then I change the texture from a 2D texture to a 3D texture unsigned 16 bits.
I set the correct depth and then change these values:
VK_FORMAT_BC3_UNORM_BLOCK -> VK_FORMAT_R16_UINT
VK_IMAGE_TYPE_2D -> VK_IMAGE_TYPE_3D
and just one component -> view.components = { VK_COMPONENT_SWIZZLE_R };
In the shader:
sampler2D -> sampler3D
But all the values I get from texture(volumeTexture, textPos).r are now zero.
What I want to do is to upload a UINT16 image but sample it as float from the fragment shader.
If I open RenderDoc the texture looks good.
pastie.org/private/i7dqw7pm0snkbf40eyywg
This is what I did in opengl:
const auto& glType = GL_SHORT;
const auto& glFormat = GL_LUMINANCE;
const auto& glInternalFormat = GL_LUMINANCE16F_ARB;
const auto& glClampMode = GL_CLAMP_TO_EDGE;

This is what I did in opengl:
OpenGL's pixel transfer functionality is required to accept unpleasant or slow things. Vulkan's does not.
What you did in OpenGL was force the driver to convert every pixel from a 16-bit unsigned, normalized fixed-point value to a 16-bit IEEE-754 floating-point value. Almost certainly, this conversion was done on the CPU.
Vulkan doesn't have training wheels, and Vulkan drivers don't do your work for you. Vulkan has formats, and the specification states exactly what they mean. If your data does not match the format you eventually want to use, then its on you to do the conversion.

Can you please add some more info? By "read from texture" do you mean sampling in a fragment shader? Do you get any errors from the validation layers? Does your implementation support sampling from R16_UINT?
If RenderDoc displays your texture but it's not "visible" in your application you also may miss a proper image layout transition, at least on hardware that requires them. This also includes the correct subresourcerange.
And please take a look at the table provided at https://www.khronos.org/registry/vulkan/specs/1.0/xhtml/vkspec.html#resources-image-views
And make sure that your image and view parameters fit for 3D textures.

Related

Editable Texture with OpenGL

I'm trying to take advantage of a gpu's parallelism to make an image proccessing application. I'm having a shader, which takes two textures, and based on some uniform variables, computes an output texture. But instead of transparency alpha value, each texture pixel needs an extra metadata byte, mandatory in computation:
So I consider running the shader twice each frame, once to compute the Dynamic Metadata as a single byte texture, and once to calculate the resulting Paint Texture, which I need to be 3 bytes (to limit memory usage, as there might be quite some such textures loaded at once).
I find the above problem a bit complicated, I've used opengl to paint to
the screen, but I need to paint to two different textures this time,
which I do not know how to do. Besides, gl_FragColor built-in variable's
type is vec4, but I need different output values.
So, to sum it up a little, is it possible for the fragment shader to output
anything other than a vec4?
Is it possible to save to two different textures with a single call?
Is it possible to make an editable texture to store changes, until the editing ends and the data have to be passed back to the cpu?
What openGL calls would be most usefull for the above?
Paint texture should also be able to be retrieved to be shown on the screen.
The above could very easily be done via blitting textures on the cpu.
I could keep all the relevant data on the cpu, do all the work 60 times/sec,
and update the relevant texture by passing the data from the cpu to the gpu.
For changing relatively small regions of a texture each frame
(about ~20% of the total scale of about 512x512 size textures), would you consider the above approach worth the trouble?
It depends on which version of OpenGL you use.
The latest OpenGL 4+ does not have a gl_FragColor variable, and instead lets you write any number (up to supported maximum) of output colors from the fragment shader, each sent to the corresponding framebuffer color attachment:
layout(location = 0) out vec4 OUT0;
layout(location = 1) out float OUT1;
That will write OUT0 to GL_COLOR_ATTACHMENT0 and OUT1 to GL_COLOR_ATTACHEMENT1 of the currently bound framebuffer.
However, considering that you use gl_FragColor, you use some old version of OpenGL. I'm not proficient in the legacy older OpenGL versions, but you can check out whether your implementation supports the GL_ARB_draw_buffers extension and/or gl_FragData[] output variable.
Also, as stated, it's unclear why can't you use a single RGBA texture and use its alpha channel for that metadata.

Webgl: alternative to writing to gl_FragDepth

In WebGL, is it possible to write to the fragment's depth value or control the fragment's depth value in some other way?
As far as I could find, gl_FragDepth is not present in webgl 1.x, but I am wondering if there is any other way (extensions, browser specific support, etc) to do it.
What I want to archive is to have a ray traced object play along with other elements drawn using the usual model, view, projection.
There is the extension EXT_frag_depth
Because it's an extension it might not be available everywhere so you need to check it exists.
var isFragDepthAvailable = gl.getExtension("EXT_frag_depth");
If isFragDepthAvailable is not falsey then you can enable it in your shaders with
#extension GL_EXT_frag_depth : enable
Otherwise you can manipulate gl_Position.z in your vertex shader though I suspect that's not really a viable solution for most needs.
Brad Larson has a clever workaround for this that he uses in Molecules (full blog post):
To work around this, I implemented my own custom depth buffer using a
frame buffer object that was bound to a texture the size of the
screen. For each frame, I first do a rendering pass where the only
value that is output is a color value corresponding to the depth at
that point. In order to handle multiple overlapping objects that might
write to the same fragment, I enable color blending and use the
GL_MIN_EXT blending equation. This means that the color components
used for that fragment (R, G, and B) are the minimum of all the
components that objects have tried to write to that fragment (in my
coordinate system, a depth of 0.0 is near the viewer, and 1.0 is far
away). In order to increase the precision of depth values written to
this texture, I encode depth to color in such a way that as depth
values increase, red fills up first, then green, and finally blue.
This gives me 768 depth levels, which works reasonably well.
EDIT: Just realized WebGL doesn't support min blending, so not very useful. Sorry.

Why does OpenGL lighten my scene when multisampling with an FBO?

I just switched my OpenGL drawing code from drawing to the display directly to using an off-screen FBO with render buffers attached. The off-screen FBO is blitted to the screen correctly when I allocate normal render buffer storage.
However, when I enable multisampling on the render buffers (via glRenderbufferStorageMultisample), every color in the scene seems like it has been brightened (thus giving different colors than the non-multisampled part).
I suspect there's some glEnable option that I need to set to maintain the same colors, but I can't seem to find any mention of this problem elsewhere.
Any ideas?
I stumbled upon the same problem, due to the lack of proper downsampling because of mismatching sample locations. What worked for me was:
A separate "single sample" FBO with identical attachments, format and dimension (with texture or renderbuffer attached) to blit into for downsampling and then draw/blit this to the window buffer
Render into a multisample window buffer with multisample texture having the same sample count as input, by passing all corresponding samples per fragment using a GLSL fragment shader. This worked with sample shading enabled and is the overkill approach for deferred shading as you can calculate light, shadow, AO, etc. per sample.
I did also rather sloppy manual downsampling to single sample framebuffers using GLSL, where I had to fetch each sample separately using texelFetch().
Things got really slow with multisampling. Although CSAA performed better than MSAA, I recommend to take a look at FXAA shaders for postprocessing as a considerable alternative, when performance is an issue or those rather new extensions required, such as ARB_texture_multisample, are not available.
Accessing samples in GLSL:
vec4 texelDownsampleAvg(sampler2DMS sampler,ivec2 texelCoord,const int sampleCount)
{
vec4 accum = texelFetch(sampler,texelCoord,0);
for(int sample = 1; sample < sampleCount; ++sample) {
accum += texelFetch(sampler,texelCoord,sample);
}
return accum / sampleCount;
}
http://developer.download.nvidia.com/opengl/specs/GL_EXT_framebuffer_multisample.txt
http://developer.download.nvidia.com/opengl/specs/GL_EXT_framebuffer_blit.txt
11) Should blits be allowed between buffers of different bit sizes?
Resolved: Yes, for color buffers only. Attempting to blit
between depth or stencil buffers of different size generates
INVALID_OPERATION.
13) How should BlitFramebuffer color space conversion be
specified? Do we allow context clamp state to affect the
blit?
Resolved: Blitting to a fixed point buffer always clamps,
blitting to a floating point buffer never clamps. The context
state is ignored.
http://www.opengl.org/registry/specs/ARB/sample_shading.txt
Blitting multisampled FBO with multiple color attachments in OpenGL
The solution that worked for me was changing the renderbuffer color format. I picked GL_RGBA32F and GL_DEPTH_COMPONENT32F (figuring that I wanted the highest precision), and the NVIDIA drivers interpret that differently (I suspect sRGB compensation, but I could be wrong).
The renderbuffer image formats I found to work are GL_RGBA8 with GL_DEPTH_COMPONENT24.

Mixing Audio Using OpenGL

I want to mix two (or more) 16bit audio streams using OpenGL and I need a bit of help
Basically what I want to do is to put the audio data into texture which I draw to a frame buffer object and then read back. This is not a problem, however drawing the data in way that gives correct results is a bit more problematic.
I have basically two questions.
In order to mix the data by drawing i need to use blending (alpha = 0.5), however the result should not have any alpha channel. So if I render to e.g. a frame buffer with the format RGB will alpha blending still work as I expect and the resulting alpha will not be written to the fbo? (I want to avoid having to read back the fbo for each render pass)
texture |sR|sG|sB|
framebuffer(before) |dR|dG|dB|
framebuffer(after)
|dR*0.5+sR*0.5|dG*0.5+sG*0.5|dB*0.5+sB*0.5|
The audio samples are signed 16bit integer values. Is it possible do signed calculations this way? Or will I need to first convert the values to unsigned on the cpu, draw them, and then make them signed again on the cpu?
EDIT:
I was a bit unclear. My hardware is restricted to OpenGL 3.3 hardware. I would prefer to not use CUDA or OpenCL, since I'm alrdy using OpenGL for other stuff.
Each audio sample will be rendered in seperate passes, which means that it has to "mix" with whats already been rendered to the frame buffer. The problem is how the output from the pixel shader is written to the framebuffer (this blending is not accessible through programmable shaders, as far as i know, and one has to use glBlendFunc).
EDIT2:
Each audio sample will be rendered in different passes, so only one audio sample will be available in the shader at a time, which means that they need to be accumulated in the FBO.
foreach(var audio_sample in audio_samples)
draw(audio_sample);
and not
for(int n = 0; n < audio_samples.size(); ++n)
{
glActiveTexture(GL_TEXTURE0 + n);
glBindTexture(audio_sample);
}
draw_everything();
Frankly, why wouldn't you just use programmable pixel shaders for that?
Do you have to use OpenGL 1 Fixed Functionality Pipeline?
I'd just go with a programmable shader operating on signed 16bit grayscale linear textures.
Edit:
foreach(var audio_sample in audio_samples)
blend FBO1 + audio_sample => FBO2
swap FBO2, FBO1
It ought to be just as fast, if not faster (thanks to streaming pipelines).
I agree with QDot. Could you however inform us a bit about the hardware restrictions you are facing? If you have reasonable modern hardware I might even suggest to go the CUDA or OpenCL route, in stead of going through OpenGL.
You should be able to do blending even if the destination buffer does not have alpha. That said, rendering to non-power-of-two sizes (rgb16 = 6bytes/pixel) usually incurs performance penalties.
Signed is not your typical render target format, but it does exist in the OpenGL 4.0 specification (Table 3.12, called RGB16_SNORM or RGB16I, depending on whether you want a normalized representation or not).
As a side note, you also have glBlendFunc(GL_CONSTANT_ALPHA,GL_ONE_MINUS_CONSTANT_ALPHA) to not even have to specify an alpha per-pixel. That may not be available on all GL implementations though.

Accessing 32-bit Depth Buffer from fragment shader?

I'm trying to do the following technique for shadowing, I read it on the NVIDIA site and it seemed like a good technique. I would prefer it to calculating shadow volumes on the cpu because it seems more 'true' and I could use this one for soft-shadowing. :
1st pass:
Fill depth buffer from perspective of LIGHT0. Copy this depth buffer for second pass. (*)
2nd pass:
Render view from EYE, and for each fragment:
Get the XY location in the depth buffer stored in (*). Get the corresponding 32-bit value.
Calculate the distance to the light.
Match this distance to the stored depth buffer value.
If it is larger, then the fragment is drawn in glDisable(LIGHT0) mode, otherwise it is drawn with the light enabled. For this purpose I use two fragment shaders and fragments blend/switch between the two according to the comparison of the distance.
Now, I'd want to do the last steps in the fragment shader, for some reasons. One of them is that I want to take the distance into account for the 'effect" of the shadowing. In my game, if the distance to the obstructing object is small, it is safe to say that the shadow will be very "strict". If it is further away, global illumination kicks in more and the shadow is slighter. This is because it's a card game, this would not be the case for more complicated 'concave' shapes.
But, I'm new to openGL and I don't understand how to do any of the following:
How to access that 1st pass depth buffer in the fragment shader without copying it to a 2d texture. I assume that is not possible?
If copying the 32-bit depth buffer to a texture that has 8-bits in each R,G,B,A component and then re-assembling that value in the fragment shader is the most efficient thing I can do?
If there are cross-platform extensions I could use for this.
Thanks if someone can help me or give me some more ideas, I'm kind of stumped right now and my lack of good hardware and free time really makes for an exhausting process to debug/try everything out.
1st way is to use FBOs with a GL_DEPTH_COMPONENT texture attached to the GL_DEPTH_ATTACHMENT attachment.
The second way is to use glCopyTexImage2D again with a GL_DEPTH_COMPONENT texture.
FBOs are cross platform and available in almost every modern OpenGL implementation, you should have them available to you.
You are right: you need to create a 2D texture from the depth buffer values in order to use those values in the 2nd pass.
Concerning the texture itself, I think that copying from 32bits depth buffer to 8 bits RGBA will not use a cast to convert data: for a mid range value of the depth buffer (say 0x80000000), you will get half tone on R, G, B and A on your rgba texture:
RGBA[0] = 0x80;
RGBA[1] = 0x80;
RGBA[2] = 0x80;
RGBA[3] = 0x80;
Where you would have expected: (cast)
RGBA[0] = 0x80;
RGBA[1] = 0;
RGBA[2] = 0;
RGBA[3] = 0;
So, for the right format, I am not sure, but I would suggest you not to modify it during the copy, since you don't want to have a conversion overhead.