How does sampler2DArrayShadow in glsl works - opengl-es

I am not able understand how to use sampler2DAprrayShadows and how it works. Got some part of it that we need to use depth texture values (GL_DEPTH_COMPONENT) to get the compare result with ref depth.
But then how to use the return float value to get the texel.
Got reference from :
http://www.khronos.org/opengles/sdk/docs/manglsl/xhtml/texture.xml
I have written a small code to test it as below:
My fragment shader as:
in highp vec2 texcoord;
in highp vec4 basecolor;
out highp vec4 myFragColor;
uniform highp sampler2DArrayShadow basetexture;
void main(void)
{
highp vec3 coords = (vec3(texcoord, 0.0) + vec3(1.0, 1.0, 1.0)) / 2.0;
highp float depth = texture(basetexture, vec4(coords.x, coords.y, coords.z, -0.5));
myFragColor = vec4(depth * basecolor);
}
Created 3D texture (texdata), and binding it as :
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH_COMPONENT16, TEX_SIZE, TEX_SIZE, TEX_SIZE, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, texdata);

maybe this could help you:
depth cubemap make tutorial
And to be frank, you're supposed to make a frame buffer object which binds a 2D depth texture instead of a Cubemap one. If you want to use sampler: sampler2DArrayShadow, then you just need to overload the glsl function texture, which is texture( Sampler2DArrayShadow gSampler, Vec4 P, [float bias]) .P.z is the number of the 2D tex, and P.w is the reference depth value. The default bias is 0, you can ignore it if don't need one.

Related

Jittering vertices

I'm trying to get rid of spatial jitter. To be more precise, I'm trying to replicate Three.js behavior concerning matrix manipulation.
My current rendering pipeline (WebGL with m4.js)
There is a scene object, a camera and a mesh. The mesh has its position (mesh.position) set to position and the camera is floating somewhere near it.
Vertices have positions relative to mesh.position:
new Float32Array([
-5, 0, -5,
5, 0, -5,
0, 0, 5
])
Important part of render loop:
const position = {x: 6428439.8443510765, y: 0, z: 4039717.5286310893}; // mesh is located there
camera.updateMatrixWorld();
camera.updateMatrixWorldInverse();
let modelViewMatrix = m4.multiply(camera.matrixWorldInverse, mesh.matrixWorld);
material.uniforms.projectionMatrix = {type: 'Matrix4fv', value: camera.projectionMatrix};
material.uniforms.modelViewMatrix = {type: 'Matrix4fv', value: modelViewMatrix};
material.use();
mesh.draw(material);
Vertex shader:
#version 300 es
precision highp float;
in vec3 position;
in vec3 color;
out vec3 vColor;
uniform mat4 projectionMatrix;
uniform mat4 modelViewMatrix;
void main() {
vColor = color;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
Fragment shader:
#version 300 es
precision highp float;
out vec4 FragColor;
in vec3 vColor;
uniform float uSample;
void main() {
FragColor = vec4(vColor * uSample, 1);
}
Result:
When moving or rotating the camera around the mesh spatial jitter effect is observed, which is not the expected behavior.
I've implemented the same scene using Three.js, and as expected you can see no jitter while moving vertices or camera: Codepen link. Three.js must work exactly the same as my implemetation, but obviously I'm missing something.
It turns out that m4.js which is a part of webgl-3d-math library used on webgl2fundamentals.org utilizes Float32Array objects for storing matrices. Maybe this approach positively affects performance, but it also causes some confusion as JavaScript's Number uses 64-bit floats.

Using GL_TEXTURE_EXTERNAL_OES in OpenGLES 3.x for ArCore

I try to render the ArFrame into a render target using OpenGLES 3.2. The ArCore example shows the usage of GLES2 but inside GLES3 the extension is not available. Now I have found the extension GL_OES_EGL_image_external_essl3 to use samplerExternalOES. Therefore I have included gl3.h and the gl2ext.h.
The creation of the texture is similar to the ArCore example:
glGenTextures(1, &g_TextureID);
glBindTexture(GL_TEXTURE_EXTERNAL_OES, g_TextureID);
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
ArSession_setCameraTextureName(m_pARSession, g_TextureID);
Inside the rendering loop:
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_EXTERNAL_OES, g_TextureID);
My shaders look like this:
constexpr char kVertexShader[] = R"(
#version 320 es
layout(location = 0) in vec2 in_UV;
layout(location = 0) out vec2 out_UV;
void main()
{
vec2 Vertices[4];
Vertices[0] = vec2(-1.0f, -1.0f);
Vertices[1] = vec2( 1.0f, -1.0f);
Vertices[2] = vec2(-1.0f, 1.0f);
Vertices[3] = vec2( 1.0f, 1.0f);
out_UV = in_UV;
gl_Position = vec4(Vertices[gl_VertexID], 0.0f, 1.0f);
}
)";
constexpr char kFragmentShader[] = R"(
#version 320 es
#extension GL_OES_EGL_image_external_essl3 : require
precision mediump float;
layout(location = 0) uniform samplerExternalOES in_ExtOESTexture;
layout(location = 0) in vec2 in_UV;
layout(location = 0) out vec4 out_Output;
void main()
{
out_Output = texture(in_ExtOESTexture, in_UV); //vec4(in_UV, 0, 1);
}
)";
Rendering only the in_UV with out_Output = vec4(in_UV, 0, 1);, the result is a perfectly looking UV texture on the screen.
But using the texture, everything is black. The size of the the texture (using textureSize(in_ExtOESTexture, 0)) is zero for both dimensions.
Any idea how to solve this problem?
The problem was that no "arcore-preview2.apk" was installed on the device. So, no error is raised if this APK is not installed. The screen remains just black. Moreover, the google examples on GitHub are working without this APK. I have created a new issue on GitHub because of this unexpected behavior.

Texture is all black

As far as I can tell, my first attempt to draw a texture on a triangle is being setup correctly, but it shows up as all black.
I am sending the image to OpenGL as such:
GLuint gridTexture;
glGenTextures(1, &gridTexture);
glBindTexture(GL_TEXTURE_2D, gridTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.x,
size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
While I'm not sure how to test that "pixels" holds what I'd expect, I do know that the size.x and size.y variables are logging correctly for the PNG I'm using so I assume the pixels is working well also since they are both extracted together in my resource loader
My shaders are simple:
attribute vec4 Position;
attribute vec4 SourceColor;
attribute vec2 TextureCoordinate;
varying vec4 DestinationColor;
varying vec2 TextureCoordOut;
uniform mat4 Projection;
uniform mat4 Modelview;
void main(void)
{
DestinationColor = SourceColor;
gl_Position=Projection*Modelview*Position;
TextureCoordOut = TextureCoordinate;
}
fragment:
varying lowp vec4 DestinationColor;
varying mediump vec2 TextureCoordOut;
uniform sampler2D Sampler;
void main(void)
{
gl_FragColor = texture2D(Sampler, TextureCoordOut) * DestinationColor;
// gl_FragColor = DestinationColor; //this works and I see varied colors fine
}
I send texture coordinates from client memory like this:
glEnableVertexAttribArray(textCoordAttribute));
glVertexAttribPointer(textCoordAttribute, 2, GL_FLOAT, GL_FALSE, sizeof(vec2),&texs[0]);
The triangle and its vertices with texture coordinates are like this; I know the coordinates aren't polished, I just want to see something on the screen:
//omitting structures that I use to hold my vertex data, but you can at least see the vertices and the coordinates I am associating with them. The triangle draws fine, and if I disable the texture2D() function in the frag shader I can see the colors of the vertices so everything appears to be working except the texture itself.
top.Color=vec4(1,0,0,1);
top.Position=vec3(0,300,0);
texs.push_back(vec2(0,1));
right.Color=vec4(0,1,0,1);
right.Position=vec3(300,0,0);
texs.push_back(vec2(1,0));
left.Color=vec4(0,0,1,1);
left.Position=vec3(-300,0,0);
texs.push_back(vec2(0,0));
verts.push_back(top);
verts.push_back(right);
verts.push_back(left);
For good measure I tried binding the texture again with glBindTexture before drawing to make it was "active" but that made no difference.
I think there is probably a very simple step I am not doing somewhere but I can't find it anywhere.
For people suffering from textures showing up black, another reason I found was if you don't set up these simple parameters when creating the texture (before glTexImage2D), the texture shows up black
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
The issue is resolved by making my texture dimensions a power of 2 in length and width.
you must have a bound data to the texture before setting the filter. You must call glTexImage2D first
GLuint gridTexture;
glGenTextures(1, &gridTexture);
glBindTexture(GL_TEXTURE_2D, gridTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.x,
size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

Texture mapping of non-rectangle textures - how to get the color of a specific texel

I'm trying to convert a shader wich is written using GLSL version 120 into OpenGl ES 2.0 and I came to a problem on how to map this shader correctly.
On the original shader, I'm using texture2DRect and this is not supported on OpenGL ES ( at least not on the target hardware I'm aming for).
The shader has two textures. One is a texture mapped to a quad, the other one is simply a kind of lookup I use to multiply the texel. The lookup is a 128x128 bitmap.
The original shader looks like this:
float xx = mod(gl_FragCoord.x, 5.0);
float yy = mod(gl_FragCoord.y, 15.0);
vec4 color = texture2DRect(tex0, coord0);
vec4 lookup1 = texture2DRect(tex1, vec2(xx, yy));
gl_FragColor = color * lookup1;
I've changed it to:
float xx = mod(gl_FragCoord.x, 5.0) * (1.0/textsize.x);
float yy = mod(gl_FragCoord.y, 15.0) * (1.0/textsize.y);
vec4 color = texture2D(tex0, coord0);
vec4 lookup1 = texture2D(tex1, vec2(xx, yy));
gl_FragColor = color * lookup1;
Where textsize is a vec2 containing the lookup texture size (128x128)
I need the exact value of the texel at let's say 50,127 on the lookup. I imagined that this should be (50/128, 127/128). This is however not working as I've expected. What am I missing here?
Additional Information:
Texture parameters:
glTexParameterf(GL_TEXTURE_2D,
GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D,
GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
GL_CLAMP_TO_EDGE)
Texture declarations:
uniform samplerExternalOES tex0;
uniform sampler2D tex1;
update 2013.03.13:
I've implemented now the following function:
vec4 texelFetch(sampler2D texsampler, vec2 coord) {
vec2 mult=(2.0*coord + 1.0)/(2.0* texWidth); // 128.0
vec4 texel = texture2D(texsampler,mult);
return texel;
}
And changed the code to:
float xx = mod(gl_FragCoord.x, 5.0);
float yy = mod(gl_FragCoord.y, 15.0);
vec4 lookup1 = texelFetch(tex1, vec2(xx, yy));
Still, it does not seems to be working.

Aliassing when flipping a texture in fragment shader

I've created a multi-texture fragment shader in which I want to flip one of the textures but when doing this my texture gets all jaggy. Is there a solution to this problem?
This is my fragment shader code:
void main(void)
{
lowp vec4 camera = texture2D(texture0, destinationTexCoord);
lowp vec4 viewfinder = texture2D(texture1, vec2(destinationTexCoord.x, 1.0 - destinationTexCoord.y));
lowp vec4 result = mix(camera, viewfinder, viewfinder.a);
gl_FragColor = result;
}
Texture filtering I'm using:
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);
Some background information: I'm blending these textures in my fragment shader (blending code stripped out) so I'm not looking for a solution where I rotate a second plane and merge them down on the framebuffer. I'm wondering if it is a good idea to flip/rotate around the texture coordinates in my fragment shader.
In the end I'll pass in a uniform saying: rotate or don't, resulting in that one texture getting rotated or not.
Using mediump instead of lowp for destinationTexCoord will improve the sampling rate for
the vec2(destinationTexCoord.x, 1.0 - destinationTexCoord.y) calculation. However, my recommendation is to use two varying vec2s instead of using a dependent texture read. i.e. cameraTexCoord and viewfinderTexCoord. You can avoid a mediump calculation in the fragment shader, and take advantage of the hardware's (hopefully) optimized vert-frag interpolation.
There's really no reason to use lowp for texture coordinates, unless they are dependent, in which case lowp may be better for the fragment shader calculations. Otherwise, lowp has not resulted in any gains, in my experience (I only know PowerVR hardware on iOS though).

Resources