NOTE: I've updated this code now to the working form and provided everything I attempted in an answer. Hopefully it helps somebody else with the same problem.
My texture is being shown as black (that is, no texture). I've gone through several other questions here with the same problem, but could not find a solution. I'm sure I'm missing something quite simple (likely ordering), but can't figure it out.
I setup my texture like this (GLProgram.checkError checks for GL errors and logs them -- I get no errors anywhere):
/*Bitmap*/ bitmap = BitmapFactory.decodeResource( context.getResources(),
R.drawable.gears );
int textures[] = new int[1];
GLES20.glGenTextures( 1, textures, 0 );
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
GLProgram.checkError( "texImage2D" );
texture = textures[0];
To draw a square which should be textured I do this:
GLES20.glVertexAttribPointer(glProgram.hATex, 2, GLES20.GL_FLOAT, false,
2*SIZEOF_FLOAT, texBuffer.under);
GLProgram.checkError( "hATex" );
GLES20.glActiveTexture(GLES20.GL_TEXTURE0 );
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture);
GLES20.glUniform1i(glProgram.hUTex, 0);
GLProgram.checkError( "Uniform" );
GLES20.glVertexAttribPointer( glProgram.hAttribPosition, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertexStride, vertexBuffer.under );
GLProgram.checkError( "Vertex" );
GLES20.glDrawArrays( GLES20.GL_TRIANGLE_FAN, 0, vertexBuffer.size/COORDS_PER_VERTEX );
GLProgram.checkError( "draw" );
My vertex shader is:
precision mediump float;
attribute vec4 vPosition;
uniform mat4 mTransform;
attribute vec2 aTex;
varying mediump vec2 vTex;
void main() {
gl_Position = mTransform * vPosition;
vTex = aTex;
}
My fragment shader is:
precision mediump float;
uniform vec4 vColor;
uniform sampler2D uTex;
varying mediump vec2 vTex;
void main(void)
{
//gl_FragColor = vColor;
//testing vTex, and it is fine
//gl_FragColor = vec4( vTex[0], vTex[1], 0, 1.0 );
//so it must be uTex which is program
gl_FragColor = texture2D(uTex,vTex);
}
I left in the commented bits to show what I checked. My vTex parameter is correct, since that bit produces the expected red/green color sweep. So I assume it must be the texture itself.
Also, uTex, aTex are located via:
hATex = GLES20.glGetAttribLocation( hProgram, "aTex" );
checkError( "aTex" );
hUTex = GLES20.glGetUniformLocation( hProgram, "uTex" );
checkError( "uTex" );
My texture comes a JPG and is 64x64 in size. I checked just after loading and it has the correct size and does appear to have pixel colors (dumping a few at random were non-zero).
The code, as presented, now works. I modified it as I tried things and for the comments. I can't be sure at which step it actually started working, since it didn't work before. Here are some of the things I checked/double-checked in the process -- I presume it has to be a combination of these somehow:
Verify source image is square and a power of two in size
non-square works so long as power of 2 in both dimensions
non-power 2 works so long as TEXTURE_WRAP is set to CLAMP_TO_EDGE
Set Min/Mag to nearest
Call bindTexture during setup and in each draw
These are things I tried, and tried again now, and appear to make no different (that is, it works either way):
use bitmap options.inScaled = false (using default options works fine)
put texImage2d before/after the glTexParameter functions
add/remove mediump from vTex (mismatched works fine, probably because default)
not calling glEnableVertexAttribArray (this results in a white box, so it wasn't my problem)
changing order of vertices and texture coords (all orders work once other things are correct -- texture may be skewed, but it does appear)
changing resource format (JPG/PNG) (RGB/Grayscale)
changing object transform matrix
TEXTURE_WRAP settings (not needed in this case, works without)
In the case when it wasn't working the error was silent: calls to glGetError returned okay and glGetProgramInfoLog was empty.
Related
I am trying to create image filters like Instagram for my Android application. I am new to image processing and have just stumbled upon this term called color mapping. After many research, I tried to create my own filter using OpenGL using a lookup table (LUT). But upon adding the filter to a camera, Here is the result:
You can see that there is this weird blueish color at the edge of my thumb. It only happens on overexposed areas of the image.
Here is the fragment shader code:
#extension GL_OES_EGL_image_external : require
precision lowp float;
varying highp vec2 vTextureCoord;
uniform samplerExternalOES inputImage;
uniform sampler2D lookup;
void main() {
vec2 tiles = vec2(8.0);
vec2 tileSize = vec2(64.0);
vec4 texel = texture2D(inputImage, vTextureCoord);
float index = texel.b * (tiles.x * tiles.y - 1.0);
float index_min = min(62.0, floor(index));
float index_max = index_min + 1.0;
vec2 tileIndex_min;
tileIndex_min.y = floor(index_min / tiles.x);
tileIndex_min.x = floor(index_min - tileIndex_min.y * tiles.x);
vec2 tileIndex_max;
tileIndex_max.y = floor(index_max / tiles.x);
tileIndex_max.x = floor(index_max - tileIndex_max.y * tiles.x);
vec2 tileUV = mix(0.5/tileSize, (tileSize-0.5)/tileSize, texel.rg);
vec2 tableUV_1 = tileIndex_min / tiles + tileUV / tiles;
vec2 tableUV_2 = tileIndex_max / tiles + tileUV / tiles;
vec3 lookUpColor_1 = texture2D(lookup, tableUV_1).rgb;
vec3 lookUpColor_2 = texture2D(lookup, tableUV_2).rgb;
vec3 lookUpColor = mix(lookUpColor_1, lookUpColor_2, index-index_min);
gl_FragColor = vec4(lookUpColor, 1.0);
}
Here is the lookup table. This is a base lookup table. I tried editing the lookup tables and applying the filter but the result is same, irrespective of the table.
What is causing this issue? Can anyone show me how to create a simple fragment shader that maps color from lookup table to the current texture? Any help would be appreciated. Regards.
Here is the code for loading the textures:
public static int loadTexture(final Bitmap img) {
int[] textures = new int[1];
GLES20.glGenTextures(1, textures, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, img, 0);
return textures[0];
}
Not sure what color space or gamma your external sampler is using, but it looks like you are getting input values outside of the zero-to-one range, so the over exposed areas are jumping a LUT tile boundary.
As a diagnostic, clamp your inputs between zero and one, but this is rarely the right "proper fix" as the clipping in the colors will be obvious.
Something like this:
vec4 texel = texture2D(inputImage, vTextureCoord);
texel = min(texel, 1.0);
I am creating a simple traingle strip to cover the whole viewport with a single rectangle. Then I am applying a 100x100 texture to this surface which changes with every frame.
I set up viewPort and initialise my vertexBuffer etc. in the onSurfaceChanged method of my GLSurfaceView class, then call my rendering function from onDrawFrame.
This setup works as it should, but at random occasions only the right lower quarter of my rectangle gets rendered, the other 3/4th of the canvas is filled with background color! It doesn't happen every time, and the anomaly disappears after rotating the device back and forth (I guess because everything gets a reset in onSurfaceChanged)
I have tried to re-upload all vertices at every frame update with GLES20.glBufferData, which seems to get rid of this bug, although it might be that I just wasn't patient enough to observe it happening (as it is quite unpredictible). It's a very simple triangle strip, so I don't think that it consumes a lot of time, but it just feels bad practice to upload a data 60/sec which isn't changing at all!
//called from onSurfaceChanged
private fun initGL (side:Int) {
/*======== Defining and storing the geometry ===========*/
//vertices for TRIANGLE STRIP
val verticesData = floatArrayOf(
-1.0f,1.0f,//LU
-1.0f,-1.0f,//LL
1.0f,1.0f,//RU
1.0f,-1.0f//RL
)
//float : 32 bit -> 4 bytes
val vertexBuffer : FloatBuffer = ByteBuffer.allocateDirect(verticesData.size * 4)
.order(ByteOrder.nativeOrder()).asFloatBuffer()
vertexBuffer.put(verticesData).position(0)
val buffers = IntArray(1)
GLES20.glGenBuffers(1, buffers, 0)
vertexBufferId = buffers[0]
//upload vertices to GPU
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vertexBufferId)
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER,
vertexBuffer.capacity() * 4, // 4 = bytes per float
vertexBuffer,
GLES20.GL_STATIC_DRAW)
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0)
/*================ Shaders ====================*/
// Vertex shader source code
val vertCode =
"""
attribute vec4 aPosition;
void main(void) {
gl_Position = aPosition;
}
"""
val fragCode =
"""
precision mediump float;
varying vec2 vCoord;
uniform sampler2D u_tex;
void main(void) {
//1-Y, because we need to flip the Y-axis!!
vec4 color = texture2D(u_tex, vec2(gl_FragCoord.x/$side.0, 1.0-(gl_FragCoord.y/$side.0)));
gl_FragColor = color;
}
"""
// Create a shader program object to store
// the combined shader program
val shaderProgram = createProgram(vertCode, fragCode)
// Use the combined shader program object
GLES20.glUseProgram(shaderProgram)
val vertexCoordLocation = GLES20.glGetAttribLocation(shaderProgram, "aPosition")
GLES20.glVertexAttribPointer(vertexCoordLocation, 2, GLES20.GL_FLOAT, false, 0, vertexBuffer)
GLES20.glEnableVertexAttribArray(vertexCoordLocation)
//set ClearColor
GLES20.glClearColor(1f,0.5f,0.5f,0.9f)
//setup a texture buffer array
val texArray = IntArray(1)
GLES20.glGenTextures(1,texArray,0)
textureId = texArray[0]
if (texArray[0]==0) Log.e(TAG, "Error with Texture!")
else Log.e(TAG, "Texture id $textureId created!")
GLES20.glActiveTexture(GLES20.GL_TEXTURE0)
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId)
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE)
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE)
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST)
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST)
GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT,1)
}
//called from onDrawFrame
private fun updateGLCanvas (matrix : ByteArray, side : Int) {
//create ByteBuffer from updated texture matrix
val textureImageBuffer : ByteBuffer = ByteBuffer.allocateDirect(matrix.size * 1)//Byte = 1 Byte
.order(ByteOrder.nativeOrder())//.asFloatBuffer()
textureImageBuffer.put(matrix).position(0)
//do I need to bind the texture in every frame?? I am desperate XD
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId)
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0,GLES20.GL_RGB, side, side, 0, GLES20.GL_RGB, GLES20.GL_UNSIGNED_BYTE, textureImageBuffer)
//bind vertex buffer
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vertexBufferId)
// Clear the color buffer bit
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT)
//draw from vertex buffer
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP,0,4)
//unbind vertex buffer
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0)
}
There are no error messages and most of the time the code is behaving as it should ... which makes this a bit difficult to track ...
If you want to use a vertex buffer, then the buffer object has to be the currently bound to the target GLES20.GL_ARRAY_BUFFER, when the array of generic vertex attribute data is specified by glVertexAttribPointer. The vertex attribute specification refers to this buffer.
In this case the last parameter of glVertexAttribPointer is treated as a byte offset into the buffer object's data store.
In your case this means the last parameter has to be 0.
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vertexBufferId)
GLES20.glVertexAttribPointer(vertexCoordLocation, 2, GLES20.GL_FLOAT, false, 0, 0)
Note, if no named buffer buffer object is bound (zero), then the last parameter is a pointer to the buffer memory. Every time when a draw call is performed, this buffer is read.
In your implementation, the data which was uploaded to the GPU is never used, because it isn't referenced by the vertex array specification.
See also Vertex Specification.
To preface this: Yes, I have looked at the large amount of "Android OpenGL ES 2.0 black textures" questions asked previously on this site. No, none of them were helpful to my situation. No, I'm not sure if I can phrase the title any better in an appropriate amount of characters.
I followed a number of tutorials and was able to set up a very simple renderer class that properly loaded and rendered textures (project A). I then tried implementing this very simple rendering system in a game engine (project B). Everything works the exact same, except texture2D() returns black for some reason. I have tried much debugging and much googling all to no avail. And so I ask for assistance.
My vertex and fragment shaders. They worked just fine in project A, so I don't think this is the source of the problem, just including for the sake of completeness.
private static final String VERTEX_SHADER_SOURCE =
...
"attribute vec2 a_TexCoord;" +
"varying vec2 v_TexCoord;" +
"void main() {" +
" v_TexCoord = a_TexCoord;" +
...
"}";
private static final String FRAGMENT_SHADER_SOURCE =
"precision mediump float;" +
"uniform sampler2D u_Texture;" +
"varying vec2 v_TexCoord;" +
"void main() {" +
" gl_FragColor = texture2D(u_Texture, v_TexCoord);" +
"}";
I create, compile, and attach these shaders to the program without error. After this, I set my handles accordingly - I also set u_Texture to point to texture unit 0 because this does not change:
...
sTexUniformHandle = GLES20.glGetUniformLocation(sProgramHandle, "u_Texture");
sMVPHandle = GLES20.glGetUniformLocation(sProgramHandle, "u_MVPMatrix");
sPositionHandle = GLES20.glGetAttribLocation(sProgramHandle, "a_Position");
sTexCoordHandle = GLES20.glGetAttribLocation(sProgramHandle, "a_TexCoord");
GLES20.glUseProgram(sProgramHandle);
GLES20.glUniform1i(sTexUniformHandle, 0);
GLES20.glUseProgram(0);
...
I then load my texture:
...
int[] texData = Utils.createTexture(context, resId);
mTexDataHandle = texData[0];
...
public static int[] createTexture(Context context, int resId) { // returns {textureHandle, width, height}
int width = -1;
int height = -1;
int[] texHandle = new int[1];
GLES20.glGenTextures(1, texHandle, 0);
if (texHandle[0] != 0) {
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inScaled = false;
final Bitmap bm = BitmapFactory.decodeResource(context.getResources(), resId, opts);
width = bm.getWidth();
height = bm.getHeight();
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texHandle[0]);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bm, 0);
bm.recycle();
}
if (texHandle[0] == 0) {
throw new RuntimeException("texture load error");
}
return new int[]{texHandle[0], width, height};
}
I did not need to set texture wrapping in project A even though my texture is 32 x 19. I changed my texture to 32 x 32 and set texture wrapping to clamp just as a precautionary measure and so no one would try to tell me that was my error. The bitmap is loading - I wrote width, height, and a few select pixels to debug and they were spot on.
In my draw method, I enable the a_TexCoord attribute and point it to the data:
...
GLES20.glEnableVertexAttribArray(sTexCoordHandle);
...
GLES20.glVertexAttribPointer(sTexCoordHandle, mTexCoordDataSize, GLES20.GL_FLOAT, false, 0, mTexCoordBuffer);
...
I wrote the whole mTexCoordBuffer out to a debug message and it's correctly loaded with the texture coordinate data.
Finally, I set the active texture unit to 0, bind my texture data to it, and draw:
...
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTexDataHandle);
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
...
I'm very new to the whole graphics library thing, but I've done my best to come to terms with what's actually going on here. I thought I understood it all, however that's obviously not the case. From what I can tell, the shaders are working properly - the black rectangle appears exactly where it should (and did in project A). The texture coordinate data that I'm passing in is the exact same as in project A and I changed nothing with how that is loaded. This leaves the actual texture data as the primary suspect, however I tried to set it up just like I did in project A and it seems correct. I would very much appreciate if someone more experienced than I could point out my mistake.
Alas, I knew it would be something worthy of a facedesk. Though I suppose I should be happy that I found the error as soon as I did and that I did, in fact, understand the GLES code I was using. On the other hand, I apparently do not understand the basics of java.
Anyways, it turns out that I was doing a whole bunch of stuff in the constructors of my Renderer and GameState classes that I shouldn't have been doing at that point in time. I made an allocateGameState() method in GameState and called it in the onSurfaceCreated() of my Renderer; problem solved.
The part that I'm still confused about is: I found out that this was my error by going back to project A and altering code until it emulated project B. At the very end, I got lucky and made the same mistake of misusing the Renderer's constructor to instantiate texture/shader/program data. This time, however, I was barraged with the following error: "call to OpenGl ES API with no current context". I quickly fixed this and applied the same fix to project B, but it makes me wonder why I wasn't getting the same error in project B..
I'm very new to Android, Eclipse, and OpenGL ES 2.0 (and object oriented programming in general), but I got a program (basically, based on a few examples I found on the Internet) working to show a cube with each face displaying a different 512 x 512 bitmap image (a PNG image loaded and converted once during the initialization phase) a few days ago.
My system is a 32-bit Vista PC, and I've been using Bluestacks as my emulator (version 0.8.11, released June 22, 2014, Android version 4.0.4). I believe its API level is 15. I have no physical Android devices to test my programs on at this time.
I now want to try a technique to use a dynamic texture.
I've looked for complete Android app examples using a dynamic texture (in Java), but I found only one and when I run it, it doesn't work on my Bluestacks.
Here's the page that has a link to the complete project containing the program:
http://blog.shayanjaved.com/2011/05/13/android-opengl-es-2-0-render-to-texture/
When I run it on my Bluestacks, all I see is a black screen.
One thing I noticed is that the texture size is huge. I changed the size to 512 x 512 (which I know works because my cube program uses 512 x 512 textures), but I still see only a black screen.
(It would be nice if somebody could try to run this program on his/her physical Android device/s and/or Bluestacks and post the result.)
The following is the method in which a dynamic texture is created and prepared for its use:
/**
* Sets up the framebuffer and renderbuffer to render to texture
*/
private void setupRenderToTexture() {
fb = new int[1];
depthRb = new int[1];
renderTex = new int[1];
// generate
GLES20.glGenFramebuffers(1, fb, 0);
GLES20.glGenRenderbuffers(1, depthRb, 0);
GLES20.glGenTextures(1, renderTex, 0);
// generate color texture
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, renderTex[0]);
// parameters
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,
GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,
GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,
GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,
GLES20.GL_LINEAR);
// create it
// create an empty intbuffer first?
int[] buf = new int[texW * texH];
texBuffer = ByteBuffer.allocateDirect(buf.length
* FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asIntBuffer();;
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGB, texW, texH, 0, GLES20.GL_RGB, GLES20.GL_UNSIGNED_SHORT_5_6_5, texBuffer);
// create render buffer and bind 16-bit depth buffer
GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, depthRb[0]);
GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER, GLES20.GL_DEPTH_COMPONENT16, texW, texH);
/*** PART BELOW SHOULD BE DONE IN onDrawFrame ***/
// bind framebuffer
/*GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fb[0]);
// specify texture as color attachment
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, renderTex[0], 0);
// attach render buffer as depth buffer
GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_DEPTH_ATTACHMENT, GLES20.GL_RENDERBUFFER, depthRb[0]);
// check status
int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER);*/
}
Does the above piece of code seem sound?
Oh, one more thing:
I've been using the following as my vertex and fragment shaders. They've been working fine to show a cube with static textures. (Normal's data are read but I'm not using any lights now.)
private final String vertexShaderCode =
// This matrix member variable provides a hook to manipulate
// the coordinates of the objects that use this vertex shader
"uniform mat4 uMVPMatrix;" +
"attribute vec4 a_Position;" +
"attribute vec4 a_Color;" +
"attribute vec3 a_Normal;" +
"attribute vec2 a_TexCoordinate;" + // Per-vertex texture coordinate information we will pass in.
"varying vec4 v_Color;" +
"varying vec2 v_TexCoordinate;" + // This will be passed into the fragment shader.
"void main() {" +
// The matrix must be included as a modifier of gl_Position.
// Note that the uMVPMatrix factor *must be first* in order
// for the matrix multiplication product to be correct.
" gl_Position = uMVPMatrix * a_Position;" +
" v_Color = a_Color;" +
" vec3 difuse = a_Normal;" +
" v_TexCoordinate = a_TexCoordinate;" + // pass through
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"uniform sampler2D u_Texture;" + // The input texture.
"varying vec4 v_Color;" +
"varying vec2 v_TexCoordinate;" + // Interpolated texture coordinate per fragment.
"void main() {" +
" gl_FragColor = (v_Color * texture2D(u_Texture, v_TexCoordinate));" +
"}";
Should they work when I render to a texture? Or do I have to have separate vertex and fragment shaders when I'm rendering to a texture?
Thank you.
I have a one big Sprite on the Scene - for example 200x200 and in the app i have an array[200][200] in which i store 0 or 1 for each pixel in big sprite.
I want to draw one more textured sprite (for example 10x10) above existing one, but i want to calculate for eache pixel in new sprite if it needs to draw it on this scene depends on provided array (if in corresponding position of the pixel in new sprite in array is '1' - i need to draw this pixel, if '0' - i don't want to draw it (maybe set alpha = 0)).
I think i can use fragment shader for each of new sprites, but i can't understand how to provide array data to the shader to calculate color for each pixel.
I think also can use fragment shader for the whole scene (if render to texture).
I am quite new in opengl and can't figure out in what way to move.
When i create resources for the scene - i try to create my mask:
mask = new float[512*512*4];
for (int i = 0; i < mask.length; i++)
{
mask[i] = 2f;
}
GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 1029384756);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 1, GLES20.GL_RGBA, 512, 512, 0, GLES20.GL_RGBA, GLES20.GL_FLOAT, FloatBuffer.wrap(mask));
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
Then when i draw new item on scene i use shader:
setShaderProgram(ShaderProgram.getInstance());
GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
GLES20.glUniform1i(RadialBlurExample.RadialBlurShaderProgram.sUniformMask, GLES20.GL_TEXTURE1);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 1029384756);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
But i can't see new item on scene (maskVal is <0.5).
I try to find working way to pass array as a texture but i can't find it.
Upload your array as a second texture with the same dimensions as the sprite, and then when you draw the sprite, sample the second texture at the same texcoord.
If the second texture doesn't meet the mask criteria, discard the fragment
uniform sampler2d sprite;
uniform sampler2d mask;
in vec2 uv;
main() {
float maskVal = texture2D(mask, uv).r;
if(maskVal > 0.5) {
gl_FragColor = texture2D(sprite,uv);
} else {
discard;
}
}